+fun requestRmuser user =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgRmuser user);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Removal succeeded.\n"
+ | MsgError s => print ("Removal failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbUser dbtype =
+ let
+ val (_, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgCreateDbUser dbtype);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Your user has been created.\n"
+ | MsgError s => print ("Creation failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbPasswd rc =
+ let
+ val (_, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgDbPasswd rc);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Your password has been changed.\n"
+ | MsgError s => print ("Password set failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbTable p =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgCreateDb p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("Your database " ^ user ^ "_" ^ #dbname p ^ " has been created.\n")
+ | MsgError s => print ("Creation failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbDrop p =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgDropDb p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("Your database " ^ user ^ "_" ^ #dbname p ^ " has been dropped.\n")
+ | MsgError s => print ("Drop failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbGrant p =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgGrantDb p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("You've been granted all allowed privileges to database " ^ user ^ "_" ^ #dbname p ^ ".\n")
+ | MsgError s => print ("Grant failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestListMailboxes domain =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgListMailboxes domain);
+ (case Msg.recv bio of
+ NONE => Vmail.Error "Server closed connection unexpectedly."
+ | SOME m =>
+ case m of
+ MsgMailboxes users => (Msg.send (bio, MsgOk);
+ Vmail.Listing users)
+ | MsgError s => Vmail.Error ("Listing failed: " ^ s)
+ | _ => Vmail.Error "Unexpected server reply.")
+ before OpenSSL.close bio
+ end
+
+fun requestNewMailbox p =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgNewMailbox p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("A mapping for " ^ #user p ^ "@" ^ #domain p ^ " has been created.\n")
+ | MsgError s => print ("Creation failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestPasswdMailbox p =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgPasswdMailbox p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("The password for " ^ #user p ^ "@" ^ #domain p ^ " has been changed.\n")
+ | MsgError s => print ("Set failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestRmMailbox p =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgRmMailbox p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("The mapping for mailbox " ^ #user p ^ "@" ^ #domain p ^ " has been deleted.\n")
+ | MsgError s => print ("Remove failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestSaQuery addr =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgSaQuery addr);
+ (case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgSaStatus b => (print ("SpamAssassin filtering for " ^ addr ^ " is "
+ ^ (if b then "ON" else "OFF") ^ ".\n");
+ Msg.send (bio, MsgOk))
+ | MsgError s => print ("Query failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n")
+ before OpenSSL.close bio
+ end
+
+fun requestSaSet p =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgSaSet p);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("SpamAssassin filtering for " ^ #1 p ^ " is now "
+ ^ (if #2 p then "ON" else "OFF") ^ ".\n")
+ | MsgError s => print ("Set failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestSmtpLog domain =
+ let
+ val (_, bio) = requestBio (fn () => ())
+
+ val _ = Msg.send (bio, MsgSmtpLogReq domain)
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => ()
+ | MsgSmtpLogRes line => (print line;
+ loop ())
+ | MsgError s => print ("Log search failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n"
+ in
+ loop ();
+ OpenSSL.close bio
+ end
+
+fun requestMysqlFixperms () =
+ let
+ val (_, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context,
+ Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgMysqlFixperms);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Permissions granted.\n"
+ | MsgError s => print ("Failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestApt {node, pkg} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QApt pkg))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgYes => (print "Package is installed.\n";
+ OS.Process.success)
+ | MsgNo => (print "Package is not installed.\n";
+ OS.Process.failure)
+ | MsgError s => (print ("APT query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestAptExists {node, pkg} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QAptExists pkg))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgAptQuery {section,description} => (print "Package exists.\n";
+ print ("Section: " ^ section ^ "\n");
+ print ("Description: " ^ description ^ "\n");
+ OS.Process.success)
+ | MsgNo => (print "Package does not exist.\n";
+ OS.Process.failure
+ (* It might be the Wrong Thing (tm) to use MsgNo like this *))
+ | MsgError s => (print ("APT existence query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestCron {node, uname} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QCron uname))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgYes => (print "User has cron permissions.\n";
+ OS.Process.success)
+ | MsgNo => (print "User does not have cron permissions.\n";
+ OS.Process.failure)
+ | MsgError s => (print ("Cron query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestFtp {node, uname} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QFtp uname))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgYes => (print "User has FTP permissions.\n";
+ OS.Process.success)
+ | MsgNo => (print "User does not have FTP permissions.\n";
+ OS.Process.failure)
+ | MsgError s => (print ("FTP query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestTrustedPath {node, uname} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QTrustedPath uname))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgYes => (print "User has trusted path restriction.\n";
+ OS.Process.success)
+ | MsgNo => (print "User does not have trusted path restriction.\n";
+ OS.Process.failure)
+ | MsgError s => (print ("Trusted path query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestSocketPerm {node, uname} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QSocket uname))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgSocket p => (case p of
+ Any => print "Any\n"
+ | Client => print "Client\n"
+ | Server => print "Server\n"
+ | Nada => print "Nada\n";
+ OS.Process.success)
+ | MsgError s => (print ("Socket permission query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestFirewall {node, uname} =
+ let
+ val (user, context) = requestContext (fn () => ())
+ val bio = OpenSSL.connect true (context, if node = Config.dispatcherName then
+ dispatcher
+ else
+ Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort)
+
+ val _ = Msg.send (bio, MsgQuery (QFirewall {node = node, user = uname}))
+
+ fun loop () =
+ case Msg.recv bio of
+ NONE => (print "Server closed connection unexpectedly.\n";
+ OS.Process.failure)
+ | SOME m =>
+ case m of
+ MsgFirewall ls => (app (fn s => (print s; print "\n")) ls;
+ OS.Process.success)
+ | MsgError s => (print ("Firewall query failed: " ^ s ^ "\n");
+ OS.Process.failure)
+ | _ => (print "Unexpected server reply.\n";
+ OS.Process.failure)
+ in
+ loop ()
+ before OpenSSL.close bio
+ end
+
+fun requestDescribe dom =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgDescribe dom);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgDescription s => print s
+ | MsgError s => print ("Description failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestReUsers () =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgReUsers);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Callbacks run.\n"
+ | MsgError s => print ("Failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestFirewallRegen node =