From dfb0d0d7748a9bd707705e0a676529a771366180 Mon Sep 17 00:00:00 2001 From: Adam Chlipala Date: Sun, 2 Oct 2005 15:01:35 +0000 Subject: [PATCH] Group membership change requests --- domain.sml | 3 +- exn.mlt | 4 ++ sec.mlt | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sec.sig | 15 +++++ sec.sml | 80 +++++++++++++++++++++++ tables.sql | 11 ++++ util.sig | 2 + util.sml | 2 + 8 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 sec.mlt create mode 100644 sec.sig create mode 100644 sec.sml diff --git a/domain.sml b/domain.sml index cec1eb6..4a7cc87 100644 --- a/domain.sml +++ b/domain.sml @@ -5,7 +5,6 @@ structure Domain = Request(struct val template = "domain" val descr = "domain" fun body (mail, dom) = - (Mail.mwrite (mail, "Domain: "); - Mail.mwrite (mail, dom); + (Mail.mwrite (mail, dom); Mail.mwrite (mail, "\n")) end) diff --git a/exn.mlt b/exn.mlt index 31b13bf..8e534a4 100644 --- a/exn.mlt +++ b/exn.mlt @@ -7,6 +7,10 @@ <% switch Web.getExn () of Fail msg => %> Fail: <% Web.htmlNl msg %> +<% | OS.SysErr (name, NONE) => %> +System error: <% Web.html name %> +<% | OS.SysErr (name, SOME syserr) => %> +System error: <% Web.html name %>: <% Web.html (OS.errorName syserr) %>: <% Web.htmlNl (OS.errorMsg syserr) %> <% | Init.C.Sql msg => %> SQL: <% Web.htmlNl msg %> <% | Init.Access msg => %> diff --git a/sec.mlt b/sec.mlt new file mode 100644 index 0000000..c8bdfba --- /dev/null +++ b/sec.mlt @@ -0,0 +1,181 @@ +<% val you = Init.getUserId (); +val yourname = Init.getUserName (); + +val uname = case $"uname" of + "" => yourname + | uname => uname; + +val socks = Sec.socketPerms uname; +val tpe = Sec.isTpe uname; + +ref showNormal = true; + +@header [("title", ["Security settings"])]; + +if $"cmd" = "socks" then + showNormal := false; + val socks = $"socks"; + %>Are you sure you want to request that socket permissions for <% Web.html uname %> be changed to <% Web.html socks %>?
+ ">Yes, place the request!<% +elseif $"cmd" = "socks2" then + val id = Sec.Req.add (you, String.concat [uname, ": change socket permissions to ", $"socks"], $"msg"); + if not (Sec.Req.notifyNew id) then + %>

Error sending e-mail notification

<% + end + %>

Request added

<% + +elseif $"cmd" = "tpe" then + showNormal := false; + val tpe = iff $"tpe" = "yes" then "on" else "off"; + %>Are you sure you want to request that trusted-path-executables-only for <% Web.html uname %> be turned <% tpe %>?
+ ">Yes, place the request!<% +elseif $"cmd" = "tpe2" then + val id = Sec.Req.add (you, String.concat [uname, ": turn tpe ", $"tpe"], $"msg"); + if not (Sec.Req.notifyNew id) then + %>

Error sending e-mail notification

<% + end + %>

Request added

<% + +elseif $"cmd" = "open" then + showNormal := false; + Group.requireGroupName "server"; + %>

Open requests

+ List all requests<% + + foreach (name, req) in Sec.Req.listOpen () do %> +


+ + + + + +
By: <% name %>
Time: <% #stamp req %>
Request: <% #data req %>
Msg: <% Web.html (#msg req) %>
+ +
+[Modify] +[Delete]
+ +<% end + +elseif $"cmd" = "list" then + showNormal := false; + Group.requireGroupName "server" + %>

All requests

<% + + foreach (name, req) in Sec.Req.list () do %> +


+ + + + + +
By: <% name %>
Time: <% #stamp req %>
Request: <% #data req %>
Reason: <% Web.html (#msg req) %>
+ +
+[Modify] +[Delete] + +<% end + +elseif $"mod" <> "" then + showNormal := false; + Group.requireGroupName "server"; + val id = Web.stoi ($"mod"); + val req = Sec.Req.lookup id; + val user = Init.lookupUser (#usr req) %> +

Handle request

+ +
+ + + + + + + + +
Requestor: <% #name user %>
Time: <% #stamp req %>
Status:
Request:
Message:
+
+ +<% elseif $"save" <> "" then + showNormal := false; + Group.requireGroupName "server"; + val id = Web.stoi ($"save"); + val req = Sec.Req.lookup id; + val oldStatus = #status req; + val newStatus = Sec.Req.statusFromInt (Web.stoi ($"status")); + Sec.Req.modify {req with data = $"req", msg = $"msg", status = newStatus}; + if oldStatus <> newStatus then + if not (Sec.Req.notifyMod (oldStatus, newStatus, Init.getUserName(), id)) then + %>

Error sending e-mail notification

<% + end + end + %>

Request modified

+ Back to: open requests, all requests + +<% elseif $"del" <> "" then + showNormal := false; + Group.requireGroupName "server"; + val id = Web.stoi ($"del"); + val req = Sec.Req.lookup id; + val user = Init.lookupUser (#usr req) + %>

Are you sure you want to delete request by <% #name user %> for "<% #data req %>"?

+ Yes, I'm sure! + +<% elseif $"del2" <> "" then + showNormal := false; + Group.requireGroupName "server"; + val id = Web.stoi ($"del2"); + Sec.Req.delete id + %>

Request deleted

+ Back to: open requests, all requests + +<% end; + +if showNormal then %> + +
+Your users:
+ +

Request socket permissions change

+ +
+ + + + + + +
New permissions:
Reason:
+
+ +

Request change to your execute permissions

+ +
+ + + + + + +
Trusted path executables only?
Reason:
+
+ +<% end %> + +<% @footer[] %> \ No newline at end of file diff --git a/sec.sig b/sec.sig new file mode 100644 index 0000000..947e601 --- /dev/null +++ b/sec.sig @@ -0,0 +1,15 @@ +signature SEC = sig + structure Req : REQUEST_OUT + + val findSubusers : string -> string list + + datatype socket_perms = + ANY + | CLIENT_ONLY + | SERVER_ONLY + | NADA + + val inGroup : string * string -> bool + val socketPerms : string -> socket_perms + val isTpe : string -> bool +end diff --git a/sec.sml b/sec.sml new file mode 100644 index 0000000..5974bc2 --- /dev/null +++ b/sec.sml @@ -0,0 +1,80 @@ +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 diff --git a/tables.sql b/tables.sql index 555d81b..97a890c 100644 --- a/tables.sql +++ b/tables.sql @@ -271,3 +271,14 @@ CREATE TABLE RollCallEntry( PRIMARY KEY (rol, usr), FOREIGN KEY (rol) REFERENCES RollCall(id) ON DELETE CASCADE, FOREIGN KEY (usr) REFERENCES WebUser(id) ON DELETE CASCADE); + +CREATE TABLE Sec( + id INTEGER PRIMARY KEY, + usr INTEGER NOT NULL, + data TEXT NOT NULL, + msg TEXT NOT NULL, + status INTEGER NOT NULL, + stamp TIMESTAMP NOT NULL, + FOREIGN KEY (usr) REFERENCES WebUser(id) ON DELETE CASCADE); + +CREATE SEQUENCE SecSeq START 1; diff --git a/util.sig b/util.sig index 46a86b1..c82c869 100644 --- a/util.sig +++ b/util.sig @@ -26,4 +26,6 @@ sig val domainDir : string -> string val readFile : string -> string + + val mem : ''a * ''a list -> bool end diff --git a/util.sml b/util.sml index 9ac38d0..7da69eb 100644 --- a/util.sml +++ b/util.sml @@ -78,4 +78,6 @@ fun readFile fname = before TextIO.closeIn inf end +fun mem (x, ls) = List.exists (fn y => y = x) ls + end -- 2.20.1