From 737c68d4f3a11a344c7469085615e7a335c9a1b3 Mon Sep 17 00:00:00 2001 From: Adam Chlipala Date: Sun, 25 Feb 2007 18:43:16 +0000 Subject: [PATCH] Socket permission querying --- src/main-admin.sml | 1 + src/main.sig | 1 + src/main.sml | 33 ++++++++++++++++++++++++++++++++ src/msg.sml | 21 ++++++++++++++++++++ src/msgTypes.sml | 10 ++++++++++ src/plugins/socketPerm.sig | 26 +++++++++++++++++++++++++ src/plugins/socketPerm.sml | 38 +++++++++++++++++++++++++++++++++++++ src/plugins/trustedPath.sml | 4 +--- src/slave.sig | 3 +++ src/slave.sml | 5 +++++ src/sources | 3 +++ 11 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/plugins/socketPerm.sig create mode 100644 src/plugins/socketPerm.sml diff --git a/src/main-admin.sml b/src/main-admin.sml index e670a6e..ffda0d7 100644 --- a/src/main-admin.sml +++ b/src/main-admin.sml @@ -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" diff --git a/src/main.sig b/src/main.sig index 03f361b..ce81c60 100644 --- a/src/main.sig +++ b/src/main.sig @@ -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 diff --git a/src/main.sml b/src/main.sml index 90a5e94..96c9204 100644 --- a/src/main.sml +++ b/src/main.sml @@ -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 diff --git a/src/msg.sml b/src/msg.sml index bd7b5ee..3c795b2 100644 --- a/src/msg.sml +++ b/src/msg.sml @@ -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 diff --git a/src/msgTypes.sml b/src/msgTypes.sml index e0f4385..b91e198 100644 --- a/src/msgTypes.sml +++ b/src/msgTypes.sml @@ -20,6 +20,12 @@ 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 index 0000000..0a4815b --- /dev/null +++ b/src/plugins/socketPerm.sig @@ -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 index 0000000..cec04a7 --- /dev/null +++ b/src/plugins/socketPerm.sml @@ -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 diff --git a/src/plugins/trustedPath.sml b/src/plugins/trustedPath.sml index 092a5b5..99b449b 100644 --- a/src/plugins/trustedPath.sml +++ b/src/plugins/trustedPath.sml @@ -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 diff --git a/src/slave.sig b/src/slave.sig index a3d322f..1fed991 100644 --- a/src/slave.sig +++ b/src/slave.sig @@ -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 diff --git a/src/slave.sml b/src/slave.sml index 64613ed..af8b606 100644 --- a/src/slave.sml +++ b/src/slave.sml @@ -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 diff --git a/src/sources b/src/sources index 28feb3c..20fa877 100644 --- a/src/sources +++ b/src/sources @@ -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 -- 2.20.1