.PHONY: all mlton smlnj install
-mlton: bin/domtool-server bin/domtool-client bin/domtool-slave
+mlton: bin/domtool-server bin/domtool-client bin/domtool-slave bin/domtool-admin
smlnj: $(COMMON_DEPS) openssl/smlnj/FFI/libssl.h.cm src/domtool.cm
$(MAKE_MLB_BASE) >src/domtool-slave.mlb
echo "main-slave.sml" >>src/domtool-slave.mlb
+src/domtool-admin.mlb: Makefile src/prefix.mlb src/sources src/suffix.mlb
+ $(MAKE_MLB_BASE) >src/domtool-admin.mlb
+ echo "main-admin.sml" >>src/domtool-admin.mlb
+
openssl/smlnj/FFI/libssl.h.cm: openssl/openssl_sml.h
cd openssl/smlnj ; ml-nlffigen -d FFI -lh LibsslH.libh -include ../libssl-h.sml \
-cm libssl.h.cm -D__builtin_va_list="void*" \
bin/domtool-slave: $(COMMON_MLTON_DEPS) src/domtool-slave.mlb
mlton -output bin/domtool-slave -link-opt -ldl src/domtool-slave.mlb
+bin/domtool-admin: $(COMMON_MLTON_DEPS) src/domtool-admin.mlb
+ mlton -output bin/domtool-admin -link-opt -ldl src/domtool-admin.mlb
+
install:
cp scripts/domtool-publish /usr/local/sbin/
cp scripts/domtool-reset-global /usr/local/sbin/
cp bin/domtool-server /usr/local/sbin/
cp bin/domtool-slave /usr/local/sbin/
cp bin/domtool-client /usr/local/bin/domtool
+ cp bin/domtool-admin /usr/local/bin/
.PHONY: grab_lib
domtool-server
domtool-client
domtool-slave
+domtool-admin
domtool-server.mlb
domtool-client.mlb
domtool-slave.mlb
+domtool-admin.mlb
--- /dev/null
+(* HCoop Domtool (http://hcoop.sourceforge.net/)
+ * Copyright (c) 2006, 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.
+ *)
+
+(* Driver for server *)
+
+val _ =
+ case CommandLine.arguments () of
+ ["grant", user, class, value] => Main.requestGrant {user = user, class = class, value = value}
+ | _ => print "Invalid command-line arguments\n"
val eval : string -> unit
val request : string -> unit
+ val requestGrant : Acl.acl -> unit
+
val service : unit -> unit
val slave : unit -> unit
val dispatcher =
Config.dispatcher ^ ":" ^ Int.toString Config.dispatcherPort
-fun request fname =
+fun requestContext f =
let
val uid = Posix.ProcEnv.getuid ()
val user = Posix.SysDB.Passwd.name (Posix.SysDB.getpwuid uid)
-
+
val () = Acl.read Config.aclFile
val () = Domain.setUser user
-
- val _ = check fname
-
- val uid = Posix.ProcEnv.getuid ()
- val user = Posix.SysDB.Passwd.name (Posix.SysDB.getpwuid uid)
+
+ val () = f ()
val context = OpenSSL.context (Config.certDir ^ "/" ^ user ^ ".pem",
Config.keyDir ^ "/" ^ user ^ "/key.pem",
Config.trustStore)
+ in
+ (user, context)
+ end
- val bio = OpenSSL.connect (context, dispatcher)
+fun requestBio f =
+ let
+ val (user, context) = requestContext f
+ in
+ (user, OpenSSL.connect (context, dispatcher))
+ end
+
+fun request fname =
+ let
+ val (user, bio) = requestBio (fn () => ignore (check fname))
val inf = TextIO.openIn fname
end
handle ErrorMsg.Error => ()
+fun requestGrant acl =
+ let
+ val (user, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgGrant acl);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Grant succeeded.\n"
+ | MsgError s => print ("Grant failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
fun service () =
let
val () = Acl.read Config.aclFile
MsgError
("Error during configuration evaluation: "
^ s)));
- OS.FileSys.remove outname;
- (ignore (OpenSSL.readChar bio);
- OpenSSL.close bio)
- handle OpenSSL.OpenSSL _ => ();
- loop ()
+ OS.FileSys.remove outname;
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ()
end
+
+ | MsgGrant acl =>
+ if Acl.query {user = user, class = "group", value = "root"} then
+ ((Acl.grant acl;
+ Acl.write Config.aclFile;
+ Msg.send (bio, MsgOk))
+ handle OpenSSL.OpenSSL s =>
+ (print "OpenSSL error\n";
+ Msg.send (bio,
+ MsgError
+ ("Error during granting: "
+ ^ s)));
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ else
+ ((Msg.send (bio, MsgError "Not authorized to grant privileges");
+ ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+
| _ =>
(Msg.send (bio, MsgError "Unexpected command")
handle OpenSSL.OpenSSL _ => ();
| 2 => Modify
| _ => raise OpenSSL.OpenSSL "Bad action number to deserialize"
+fun sendAcl (bio, {user, class, value}) =
+ (OpenSSL.writeString (bio, user);
+ OpenSSL.writeString (bio, class);
+ OpenSSL.writeString (bio, value))
+
+fun recvAcl bio =
+ case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of
+ (SOME user, SOME class, SOME value) => SOME {user = user, class = class, value = value}
+ | _ => NONE
+
fun send (bio, m) =
case m of
MsgOk => OpenSSL.writeInt (bio, 1)
OpenSSL.writeString (bio, dir);
OpenSSL.writeString (bio, file))
| MsgDoFiles => OpenSSL.writeInt (bio, 5)
+ | MsgGrant acl => (OpenSSL.writeInt (bio, 6);
+ sendAcl (bio, acl))
fun checkIt v =
case v of
file = file})
| _ => NONE)
| 5 => SOME MsgDoFiles
+ | 6 => (case recvAcl bio of
+ SOME acl => SOME (MsgGrant acl)
+ | _ => NONE)
| _ => NONE)
end
(* The status of a configuration file has changed. *)
| MsgDoFiles
(* Perform the actions associated with the MsgFiles sent previously. *)
+ | MsgGrant of Acl.acl
+ (* Grant a new permission *)
end