don't complain about $user.daemon missing a domtool dir
[hcoop/domtool2.git] / src / main.sml
index cc35c62..0a241fa 100644 (file)
@@ -56,6 +56,7 @@ fun check' G fname =
 
 fun basis () =
     let
+       val _ = ErrorMsg.reset ()
        val dir = Posix.FileSys.opendir Config.libRoot
 
        fun loop files =
@@ -667,6 +668,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 () => ())
@@ -1155,7 +1172,7 @@ fun regenerateEither tc checker context =
                            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");
@@ -1520,6 +1537,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
@@ -1552,6 +1590,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"),
@@ -1691,6 +1730,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