X-Git-Url: https://git.hcoop.net/hcoop/domtool2.git/blobdiff_plain/f296c49694436583aa6194852bae5df395dacd05..4555c311c5b74225cd3de63dc88e12644262dc2a:/src/main.sml diff --git a/src/main.sml b/src/main.sml index e2df22b..3a31c34 100644 --- a/src/main.sml +++ b/src/main.sml @@ -1,5 +1,6 @@ (* HCoop Domtool (http://hcoop.sourceforge.net/) * Copyright (c) 2006-2009, Adam Chlipala + * Copyright (c) 2012,2013,2014 Clinton Ebadi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -50,11 +51,12 @@ fun check' G fname = () else Option.app (Unused.check G) (#3 prog); - Tycheck.checkFile G (Defaults.tInit prog) prog) + Tycheck.checkFile G prog) end fun basis () = let + val _ = ErrorMsg.reset () val dir = Posix.FileSys.opendir Config.libRoot fun loop files = @@ -100,7 +102,7 @@ fun check G fname = raise ErrorMsg.Error else let - val G' = Tycheck.checkFile G (Defaults.tInit prog) prog + val G' = Tycheck.checkFile G prog in if !ErrorMsg.anyErrors then raise ErrorMsg.Error @@ -116,6 +118,7 @@ fun check G fname = fun notTmp s = String.sub (s, 0) <> #"." + andalso s <> "_darcs" andalso CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"." orelse ch = #"_" orelse ch = #"-") s fun setupUser () = @@ -193,6 +196,8 @@ fun reduce G fname = (*(Defaults.eInit ())*) +val toplevel = Env.initialDynEnvVals Reduce.reduceExp + fun eval G evs fname = case reduce G fname of (G, SOME body') => @@ -200,14 +205,14 @@ fun eval G evs fname = raise ErrorMsg.Error else let - val evs' = Eval.exec' evs body' + val evs' = Eval.exec' (toplevel G, evs) body' in (G, evs') end | (G, NONE) => (G, evs) val dispatcher = - Config.dispatcher ^ ":" ^ Int.toString Config.dispatcherPort + Domain.nodeIp Config.dispatcherName ^ ":" ^ Int.toString Config.dispatcherPort val self = "localhost:" ^ Int.toString Config.slavePort @@ -537,7 +542,7 @@ fun requestDbUser dbtype = let val (_, context) = requestContext (fn () => ()) val bio = OpenSSL.connect true (context, - Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort) + Domain.nodeIp Config.Dbms.dbmsNode ^ ":" ^ Int.toString Config.slavePort) in Msg.send (bio, MsgCreateDbUser dbtype); case Msg.recv bio of @@ -664,6 +669,22 @@ fun requestPasswdMailbox p = OpenSSL.close bio end +fun requestPortalPasswdMailbox p = + let + val (_, bio) = requestBio (fn () => ()) + in + (Msg.send (bio, MsgPortalPasswdMailbox p); + case Msg.recv bio of + NONE => (print "Server closed connection unexpectedly.\n"; OS.Process.failure) + | SOME m => + case m of + MsgOk => (print ("The password for " ^ #user p ^ "@" ^ #domain p ^ " has been changed.\n"); + OS.Process.success) + | MsgError s => (print ("Set failed: " ^ s ^ "\n"); OS.Process.failure) + | _ => (print "Unexpected server reply.\n"; OS.Process.failure)) + before OpenSSL.close bio + end + fun requestRmMailbox p = let val (_, bio) = requestBio (fn () => ()) @@ -937,7 +958,7 @@ fun requestFirewall {node, uname} = else Domain.nodeIp node ^ ":" ^ Int.toString Config.slavePort) - val _ = Msg.send (bio, MsgQuery (QFirewall uname)) + val _ = Msg.send (bio, MsgQuery (QFirewall {node = node, user = uname})) fun loop () = case Msg.recv bio of @@ -1090,7 +1111,7 @@ fun regenerateEither tc checker context = val ok = ref true fun contactNode (node, ip) = - if node = Config.defaultNode then + if node = Config.dispatcherName then Domain.resetLocal () else let val bio = OpenSSL.connect true (context, @@ -1148,9 +1169,11 @@ fun regenerateEither tc checker context = ok := false) else (); - ignore (foldl checker' (basis (), Defaults.eInit ()) files) + let val basis' = basis () in + ignore (foldl checker' (basis', SM.empty) files) + end end - else if String.isSuffix "_admin" user then + else if (String.isSuffix "_admin" user) orelse (String.isSuffix ".daemon" user) then () else (print ("Couldn't access " ^ user ^ "'s ~/.domtool directory.\n"); @@ -1223,7 +1246,7 @@ fun answerQuery q = | QFtp user => if Ftp.allowed user then MsgYes else MsgNo | QTrustedPath user => if TrustedPath.query user then MsgYes else MsgNo | QSocket user => MsgSocket (SocketPerm.query user) - | QFirewall user => MsgFirewall (Firewall.query user) + | QFirewall {node, user} => MsgFirewall (Firewall.query (node, user)) fun describeQuery q = case q of @@ -1233,7 +1256,7 @@ fun describeQuery q = | QFtp user => "Asked about FTP permissions for user " ^ user | QTrustedPath user => "Asked about trusted path settings for user " ^ user | QSocket user => "Asked about socket permissions for user " ^ user - | QFirewall user => "Asked about firewall rules for user " ^ user + | QFirewall {node, user} => "Asked about firewall rules on " ^ node ^ " for user " ^ user fun doIt' loop bio f cleanup = ((case f () of @@ -1313,7 +1336,9 @@ fun service () = end in doIt (fn () => (Env.pre (); - ignore (foldl doOne (basis (), Defaults.eInit ()) codes); + let val basis' = basis () in + ignore (foldl doOne (basis', SM.empty) codes) + end; Env.post (); Msg.send (bio, MsgOk); ("Configuration complete.", NONE))) @@ -1513,6 +1538,27 @@ fun service () = SOME msg)) (fn () => ()) + | MsgPortalPasswdMailbox {domain, user = emailUser, oldpasswd, newpasswd} => + doIt (fn () => + if not (Acl.query {user = user, class = "priv", value = "vmail"}) then + ("User is not authorized to run portal vmail password", + SOME "You're not authorized to use the portal password command") + else if not (Domain.validEmailUser emailUser) then + ("Invalid e-mail username " ^ emailUser, + SOME "Invalid e-mail username") + else if not (CharVector.all Char.isGraph oldpasswd + andalso CharVector.all Char.isGraph newpasswd) then + ("Invalid password", + SOME "Invalid password; may only contain printable, non-space characters") + else + case Vmail.portalpasswd {domain = domain, user = emailUser, + oldpasswd = oldpasswd, newpasswd = newpasswd} of + NONE => ("Changed password of mailbox " ^ emailUser ^ "@" ^ domain, + NONE) + | SOME msg => ("Error changing mailbox password for " ^ emailUser ^ "@" ^ domain ^ ": " ^ msg, + SOME msg)) + (fn () => ()) + | MsgRmMailbox {domain, user = emailUser} => doIt (fn () => if not (Domain.yourDomain domain) then @@ -1545,6 +1591,7 @@ fun service () = NONE => ("User tried to set SA filtering for " ^ addr, SOME "You aren't allowed to configure SA filtering for that recipient.") | SOME addr' => (SetSA.set (addr', b); + SetSA.rebuild (); Msg.send (bio, MsgOk); ("Set SA filtering status for " ^ addr ^ " to " ^ (if b then "ON" else "OFF"), @@ -1684,6 +1731,10 @@ fun slave () = Msg.send (bio, MsgOk) else Msg.send (bio, MsgError "userdb update failed")) + | MsgSaChanged => (if Slave.shell [Config.SpamAssassin.postReload] then + Msg.send (bio, MsgOk) + else + Msg.send (bio, MsgError "Error reloading SpamAssassin addresses")) | _ => (print "Dispatcher sent unexpected command\n"; Msg.send (bio, MsgError "Unexpected command")) in