Listing permissions
authorAdam Chlipala <adamc@hcoop.net>
Thu, 14 Dec 2006 23:05:36 +0000 (23:05 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Thu, 14 Dec 2006 23:05:36 +0000 (23:05 +0000)
src/acl.sig
src/acl.sml
src/main-admin.sml
src/main.sig
src/main.sml
src/msg.sml
src/msgTypes.sml

index d815cad..fc72ab6 100644 (file)
@@ -27,6 +27,9 @@ signature ACL = sig
     val query : acl -> bool
     (* Is this permission granted? *)
 
     val query : acl -> bool
     (* Is this permission granted? *)
 
+    val queryAll : string -> (string * string list) list
+    (* What are all of a user's permissions, by class? *)
+
     val class : {user : string, class : string} -> DataStructures.StringSet.set
     (* For what objects does the user have the permission? *)
 
     val class : {user : string, class : string} -> DataStructures.StringSet.set
     (* For what objects does the user have the permission? *)
 
index d0b41fe..0adfb4b 100644 (file)
@@ -37,6 +37,13 @@ fun query {user, class, value} =
            NONE => false
          | SOME values => SS.member (values, value)
 
            NONE => false
          | SOME values => SS.member (values, value)
 
+fun queryAll user =
+    case SM.find (!acl, user) of
+       NONE => []
+      | SOME classes => SM.foldri (fn (class, values, out) =>
+                                     (class, SS.foldr (op::) [] values) :: out)
+                                 [] classes
+
 fun class {user, class} =
     case SM.find (!acl, user) of
        NONE => SS.empty
 fun class {user, class} =
     case SM.find (!acl, user) of
        NONE => SS.empty
index b4ba422..f79d44e 100644 (file)
 
 (* Driver for server *)
 
 
 (* Driver for server *)
 
+fun requestPerms user =
+    case Main.requestListPerms user of
+       NONE => ()
+      | SOME classes =>
+       (print ("Permissions for " ^ user ^ ":\n");
+        app (fn (class, values) =>
+                (print (class ^ ":");
+                 app (fn value => print (" " ^ value)) values;
+                 print "\n")) classes)
+
 val _ =
     case CommandLine.arguments () of
        ["grant", user, class, value] => Main.requestGrant {user = user, class = class, value = value}
       | ["revoke", user, class, value] => Main.requestRevoke {user = user, class = class, value = value}
 val _ =
     case CommandLine.arguments () of
        ["grant", user, class, value] => Main.requestGrant {user = user, class = class, value = value}
       | ["revoke", user, class, value] => Main.requestRevoke {user = user, class = class, value = value}
+      | ["perms", user] => requestPerms user
+      | ["perms"] => requestPerms (Posix.SysDB.Passwd.name (Posix.SysDB.getpwuid (Posix.ProcEnv.getuid ())))
       | _ => print "Invalid command-line arguments\n"
       | _ => print "Invalid command-line arguments\n"
index ee5915a..88e0a65 100644 (file)
@@ -33,6 +33,7 @@ signature MAIN = sig
     val request : string -> unit
     val requestGrant : Acl.acl -> unit
     val requestRevoke : Acl.acl -> unit
     val request : string -> unit
     val requestGrant : Acl.acl -> unit
     val requestRevoke : Acl.acl -> unit
+    val requestListPerms : string -> (string * string list) list option
 
     val service : unit -> unit
     val slave : unit -> unit
 
     val service : unit -> unit
     val slave : unit -> unit
index 9204159..03d5877 100644 (file)
@@ -205,6 +205,24 @@ fun requestRevoke acl =
        OpenSSL.close bio
     end
 
        OpenSSL.close bio
     end
 
+fun requestListPerms user =
+    let
+       val (_, bio) = requestBio (fn () => ())
+    in
+       Msg.send (bio, MsgListPerms user);
+       (case Msg.recv bio of
+            NONE => (print "Server closed connection unexpectedly.\n";
+                     NONE)
+          | SOME m =>
+            case m of
+                MsgPerms perms => SOME perms
+              | MsgError s => (print ("Listing failed: " ^ s ^ "\n");
+                               NONE)
+              | _ => (print "Unexpected server reply.\n";
+                      NONE))
+       before OpenSSL.close bio
+    end
+
 fun service () =
     let
        val () = Acl.read Config.aclFile
 fun service () =
     let
        val () = Acl.read Config.aclFile
@@ -310,6 +328,20 @@ fun service () =
                                     handle OpenSSL.OpenSSL _ => ();
                                     loop ())
 
                                     handle OpenSSL.OpenSSL _ => ();
                                     loop ())
 
+                             | MsgListPerms user =>
+                               ((Msg.send (bio, MsgPerms (Acl.queryAll user));
+                                 print ("Sent permission list for user " ^ user ^ ".\n"))
+                                handle OpenSSL.OpenSSL s =>
+                                       (print "OpenSSL error\n";
+                                        Msg.send (bio,
+                                                  MsgError
+                                                      ("Error during permission listing: "
+                                                       ^ s)));
+                               (ignore (OpenSSL.readChar bio);
+                                OpenSSL.close bio)
+                               handle OpenSSL.OpenSSL _ => ();
+                               loop ())
+
                              | _ =>
                                (Msg.send (bio, MsgError "Unexpected command")
                                 handle OpenSSL.OpenSSL _ => ();
                              | _ =>
                                (Msg.send (bio, MsgError "Unexpected command")
                                 handle OpenSSL.OpenSSL _ => ();
index 5569355..f2c4d72 100644 (file)
@@ -59,6 +59,17 @@ fun send (bio, m) =
                         sendAcl (bio, acl))
       | MsgRevoke acl => (OpenSSL.writeInt (bio, 7);
                          sendAcl (bio, acl))
                         sendAcl (bio, acl))
       | MsgRevoke acl => (OpenSSL.writeInt (bio, 7);
                          sendAcl (bio, acl))
+      | MsgListPerms user => (OpenSSL.writeInt (bio, 8);
+                             OpenSSL.writeString (bio, user))
+      | MsgPerms classes => (OpenSSL.writeInt (bio, 9);
+                            app (fn (class, values) =>
+                                    (OpenSSL.writeInt (bio, 1);
+                                     OpenSSL.writeString (bio, class);
+                                     app (fn value =>
+                                             (OpenSSL.writeInt (bio, 1);
+                                              OpenSSL.writeString (bio, value))) values;
+                                     OpenSSL.writeInt (bio, 0))) classes;
+                            OpenSSL.writeInt (bio, 0))
 
 fun checkIt v =
     case v of
 
 fun checkIt v =
     case v of
@@ -90,6 +101,33 @@ fun recv bio =
                   | 7 => (case recvAcl bio of
                               SOME acl => SOME (MsgRevoke acl)
                             | _ => NONE)
                   | 7 => (case recvAcl bio of
                               SOME acl => SOME (MsgRevoke acl)
                             | _ => NONE)
+                  | 8 => (case OpenSSL.readString bio of
+                              SOME user => SOME (MsgListPerms user)
+                            | _ => NONE)
+                  | 9 => let
+                        fun loop classes =
+                            case OpenSSL.readInt bio of
+                                SOME 0 => SOME (MsgPerms (rev classes))
+                              | SOME 1 =>
+                                (case OpenSSL.readString bio of
+                                     SOME class =>
+                                     let
+                                         fun loop' values =
+                                             case OpenSSL.readInt bio of
+                                                 SOME 0 => loop ((class, rev values) :: classes)
+                                               | SOME 1 =>
+                                                 (case OpenSSL.readString bio of
+                                                      SOME value => loop' (value :: values)
+                                                    | NONE => NONE)
+                                               | _ => NONE
+                                     in
+                                         loop' []
+                                     end
+                                   | NONE => NONE)
+                              | _ => NONE
+                    in
+                        loop []
+                    end
                   | _ => NONE)
         
 end
                   | _ => NONE)
         
 end
index a5fe2f7..4ee4cbc 100644 (file)
@@ -35,5 +35,10 @@ datatype msg =
        (* Grant a permission *)
        | MsgRevoke of Acl.acl
        (* Revoke a permission *)
        (* Grant a permission *)
        | MsgRevoke of Acl.acl
        (* Revoke a permission *)
+       | MsgListPerms of string
+       (* List all of a user's permissions *)
+       | MsgPerms of (string * string list) list
+       (* A response to MsgListPerms, giving a permission class and all values
+       * for which the user is authorized in that class *)
 
 end
 
 end