structure Sec :> SEC = struct open Init Util Sql structure Req = Request(struct val table = "Sec" val adminGroup = "server" fun subject _ = "Security permissions change request" val template = "sec" val descr = "change" fun body (mail, req) = (Mail.mwrite (mail, req); Mail.mwrite (mail, "\n")) end) fun findSubusers uname = let val uname_under = uname ^ "_" val inf = TextIO.openIn "/etc/passwd" fun loop subs = case TextIO.inputLine inf of NONE => ListMergeSort.sort (fn (x, y) => String.compare (x, y) = GREATER) subs | SOME line => case String.fields (fn ch => ch = #":") line of uname'::_ => if size uname' >= size uname_under andalso String.substring (uname', 0, size uname_under) = uname_under then loop (uname' :: subs) else loop subs | _ => loop subs in loop [] before TextIO.closeIn inf end datatype socket_perms = ANY | CLIENT_ONLY | SERVER_ONLY | NADA fun inGroup (uname, grp) = let val uname_under = uname ^ "_" val inf = TextIO.openIn "/etc/group" fun loop () = case TextIO.inputLine inf of NONE => false | SOME line => case String.fields (fn ch => ch = #":") line of [gname, _, _, members] => if gname = grp then mem (uname, String.fields (fn ch => ch = #",") members) else loop () | _ => loop () in loop () before TextIO.closeIn inf end fun socketPerms uname = if inGroup (uname, "no-sockets") then NADA else if inGroup (uname, "no-cli-sockets") then if inGroup (uname, "no-serv-sockets") then NADA else SERVER_ONLY else if inGroup (uname, "no-serv-sockets") then CLIENT_ONLY else ANY fun isTpe uname = inGroup (uname, "only-tpe") end