Socket permission querying
authorAdam Chlipala <adamc@hcoop.net>
Sun, 25 Feb 2007 18:43:16 +0000 (18:43 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Sun, 25 Feb 2007 18:43:16 +0000 (18:43 +0000)
src/main-admin.sml
src/main.sig
src/main.sml
src/msg.sml
src/msgTypes.sml
src/plugins/socketPerm.sig [new file with mode: 0644]
src/plugins/socketPerm.sml [new file with mode: 0644]
src/plugins/trustedPath.sml
src/slave.sig
src/slave.sml
src/sources

index e670a6e..ffda0d7 100644 (file)
@@ -52,4 +52,5 @@ val _ =
       | ["cron", node, uname] => OS.Process.exit (Main.requestCron {node = node, uname = uname})
       | ["ftp", node, uname] => OS.Process.exit (Main.requestFtp {node = node, uname = uname})
       | ["tpe", node, uname] => OS.Process.exit (Main.requestTrustedPath {node = node, uname = uname})
+      | ["sockperm", node, uname] => OS.Process.exit (Main.requestSocketPerm {node = node, uname = uname})
       | _ => print "Invalid command-line arguments\n"
index 03f361b..ce81c60 100644 (file)
@@ -73,4 +73,5 @@ signature MAIN = sig
     val requestCron : {node : string, uname : string} -> OS.Process.status
     val requestFtp : {node : string, uname : string} -> OS.Process.status
     val requestTrustedPath : {node : string, uname : string} -> OS.Process.status
+    val requestSocketPerm : {node : string, uname : string} -> OS.Process.status
 end
index 90a5e94..96c9204 100644 (file)
@@ -720,6 +720,37 @@ fun requestTrustedPath {node, uname} =
        before OpenSSL.close bio
     end
 
+fun requestSocketPerm {node, uname} =
+    let
+       val (user, context) = requestContext (fn () => ())
+       val bio = OpenSSL.connect (context, if node = Config.masterNode 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 regenerate context =
     let
        val b = basis ()
@@ -809,6 +840,7 @@ fun answerQuery q =
       | QCron user => if Cron.allowed user then MsgYes else MsgNo
       | 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)
 
 fun describeQuery q =
     case q of
@@ -816,6 +848,7 @@ fun describeQuery q =
       | QCron user => "Asked about cron permissions for user " ^ user
       | 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
 
 fun service () =
     let
index bd7b5ee..3c795b2 100644 (file)
@@ -88,6 +88,21 @@ fun recvBool bio =
       | SOME 1 => SOME true
       | _ => NONE
 
+fun sendSockPerm (bio, p) =
+    case p of
+       Any => OpenSSL.writeInt (bio, 0)
+      | Client => OpenSSL.writeInt (bio, 1)
+      | Server => OpenSSL.writeInt (bio, 2)
+      | Nada => OpenSSL.writeInt (bio, 3)
+
+fun recvSockPerm bio =
+    case OpenSSL.readInt bio of
+       SOME 0 => SOME Any
+      | SOME 1 => SOME Client
+      | SOME 2 => SOME Server
+      | SOME 3 => SOME Nada
+      | _ => NONE
+
 fun sendQuery (bio, q) =
     case q of
        QApt s => (OpenSSL.writeInt (bio, 0);
@@ -98,6 +113,8 @@ fun sendQuery (bio, q) =
                   OpenSSL.writeString (bio, s))
       | QTrustedPath s => (OpenSSL.writeInt (bio, 3);
                           OpenSSL.writeString (bio, s))
+      | QSocket s => (OpenSSL.writeInt (bio, 4);
+                     OpenSSL.writeString (bio, s))
 
 fun recvQuery bio =
     case OpenSSL.readInt bio of
@@ -107,6 +124,7 @@ fun recvQuery bio =
           | 1 => Option.map QCron (OpenSSL.readString bio)
           | 2 => Option.map QFtp (OpenSSL.readString bio)
           | 3 => Option.map QTrustedPath (OpenSSL.readString bio)
+          | 4 => Option.map QSocket (OpenSSL.readString bio)
           | _ => NONE)
       | NONE => NONE
 
@@ -196,6 +214,8 @@ fun send (bio, m) =
       | MsgNo => OpenSSL.writeInt (bio, 31)
       | MsgQuery q => (OpenSSL.writeInt (bio, 32);
                       sendQuery (bio, q))
+      | MsgSocket p => (OpenSSL.writeInt (bio, 33);
+                       sendSockPerm (bio, p))
 
 fun checkIt v =
     case v of
@@ -294,6 +314,7 @@ fun recv bio =
                   | 30 => SOME MsgYes
                   | 31 => SOME MsgNo
                   | 32 => Option.map MsgQuery (recvQuery bio)
+                  | 33 => Option.map MsgSocket (recvSockPerm bio)
                   | _ => NONE)
         
 end
index e0f4385..b91e198 100644 (file)
 
 structure MsgTypes = struct
 
+datatype socket_permission =
+        Any
+       | Client
+       | Server
+       | Nada
+
 datatype query =
         QApt of string
        (* Is this apt package installed? *)
@@ -29,6 +35,8 @@ datatype query =
        (* Is this user allowed to use FTP? *)
        | QTrustedPath of string
        (* Is this user restricted to trusted-path executables? *)
+       | QSocket of string
+       (* What socket permissions does this user have? *)
 
 datatype msg =
         MsgOk
@@ -98,5 +106,7 @@ datatype msg =
        (* Answers to boolean queries *)
        | MsgQuery of query
        (* Ask for host-specific information *)
+       | MsgSocket of socket_permission
+       (* Answer to a QSocket query *)
 
 end
diff --git a/src/plugins/socketPerm.sig b/src/plugins/socketPerm.sig
new file mode 100644 (file)
index 0000000..0a4815b
--- /dev/null
@@ -0,0 +1,26 @@
+(* HCoop Domtool (http://hcoop.sourceforge.net/)
+ * Copyright (c) 2006-2007, Adam Chlipala
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(* Socket permission settings querying *)
+
+signature SOCKET_PERM = sig
+
+    val query : string -> MsgTypes.socket_permission
+    (* What socket permissions does the named user have on this host? *)
+
+end
diff --git a/src/plugins/socketPerm.sml b/src/plugins/socketPerm.sml
new file mode 100644 (file)
index 0000000..cec04a7
--- /dev/null
@@ -0,0 +1,38 @@
+(* HCoop Domtool (http://hcoop.sourceforge.net/)
+ * Copyright (c) 2006-2007, Adam Chlipala
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(* Trusted path settings querying *)
+
+structure SocketPerm :> SOCKET_PERM = struct
+
+open MsgTypes
+
+fun query uname =
+    if Slave.inGroup {user = uname, group = "no-sockets"} then
+        Nada
+    else if Slave.inGroup {user = uname, group = "no-cli-sockets"} then
+        if Slave.inGroup {user = uname, group = "no-serv-sockets"} then
+            Nada
+        else
+            Server
+    else if Slave.inGroup {user = uname, group = "no-serv-sockets"} then
+        Client
+    else
+        Any
+
+end
index 092a5b5..99b449b 100644 (file)
@@ -20,8 +20,6 @@
 
 structure TrustedPath :> TRUSTED_PATH = struct
 
-fun query uname = List.exists (fn x => x = uname)
-                 (Posix.SysDB.Group.members (Posix.SysDB.getgrnam "only-tpe"))
-                 handle OS.SysErr _ => false
+fun query uname = Slave.inGroup {group = "only-tpe", user = uname}
 
 end
index a3d322f..1fed991 100644 (file)
@@ -64,4 +64,7 @@ signature SLAVE = sig
     val lineInFile : string -> string -> bool
     (* Is there a line in the file (first arg) that matches that given? *)
 
+    val inGroup : {user : string, group : string} -> bool
+    (* Check membership in a UNIX group. *)
+
 end
index 64613ed..af8b606 100644 (file)
@@ -195,4 +195,9 @@ fun lineInFile fname line =
        before TextIO.closeIn inf
     end handle IO.Io _ => false
 
+fun inGroup {user, group} =
+    List.exists (fn x => x = user)
+               (Posix.SysDB.Group.members (Posix.SysDB.getgrnam group))
+               handle OS.SysErr _ => false
+
 end
index 28feb3c..20fa877 100644 (file)
@@ -98,6 +98,9 @@ plugins/ftp.sml
 plugins/trustedPath.sig
 plugins/trustedPath.sml
 
+plugins/socketPerm.sig
+plugins/socketPerm.sml
+
 mail/vmail.sig
 mail/vmail.sml