payment: note that Stripe has instituted an additional 1% fee for non-US cards
[hcoop/portal.git] / sec.sml
CommitLineData
dfb0d0d7
AC
1structure Sec :> SEC = struct
2
3open Init Util Sql
4
3d2ed222
AC
5structure Req = RequestH(struct
6 val table = "Sec"
7 val adminGroup = "server"
8 fun subject _ = "Security permissions change request"
9 val template = "sec"
10 val descr = "change"
11 fun body {node, mail, data = req} =
12 (Mail.mwrite (mail, req);
13 Mail.mwrite (mail, "\n"))
14 end)
dfb0d0d7
AC
15
16fun findSubusers uname =
17 let
18 val uname_under = uname ^ "_"
19 val inf = TextIO.openIn "/etc/passwd"
20
21 fun loop subs =
22 case TextIO.inputLine inf of
23 NONE => ListMergeSort.sort (fn (x, y) => String.compare (x, y) = GREATER) subs
24 | SOME line =>
25 case String.fields (fn ch => ch = #":") line of
26 uname'::_ =>
27 if size uname' >= size uname_under
28 andalso String.substring (uname', 0, size uname_under) = uname_under then
29 loop (uname' :: subs)
30 else
31 loop subs
32 | _ => loop subs
33 in
34 loop []
35 before TextIO.closeIn inf
36 end
37
38datatype socket_perms =
39 ANY
40 | CLIENT_ONLY
41 | SERVER_ONLY
42 | NADA
43
3d2ed222 44fun socketPerms {node, uname} =
dfb0d0d7 45 let
3d2ed222
AC
46 val proc = Unix.execute ("/bin/sh",
47 ["-c",
811dc1e5 48 "DOMTOOL_USER=hcoop.daemon /usr/local/bin/domtool-admin sockperm "
3d2ed222
AC
49 ^ Init.nodeName node ^ " " ^ uname])
50
51 val inf = Unix.textInstreamOf proc
dfb0d0d7 52
3d2ed222
AC
53 val p = case TextIO.inputLine inf of
54 SOME "Any\n" => ANY
55 | SOME "Client\n" => CLIENT_ONLY
56 | SOME "Server\n" => SERVER_ONLY
57 | _ => NADA
dfb0d0d7 58 in
3d2ed222
AC
59 TextIO.closeIn inf;
60 if OS.Process.isSuccess (Unix.reap proc) then
61 p
dfb0d0d7 62 else
3d2ed222
AC
63 NADA
64 end
dfb0d0d7 65
3d2ed222
AC
66fun checkIt cmd {node, uname} =
67 OS.Process.isSuccess (OS.Process.system
811dc1e5 68 ("DOMTOOL_USER=hcoop.daemon /usr/local/bin/domtool-admin "
3d2ed222 69 ^ cmd ^ " " ^ Init.nodeName node ^ " " ^ uname ^ " >/dev/null 2>/dev/null"))
dfb0d0d7 70
3d2ed222
AC
71val isTpe = checkIt "tpe"
72val cronAllowed = checkIt "cron"
e510b9bd 73
3d2ed222 74fun findFirewallRules {node, uname} =
e510b9bd 75 let
3d2ed222
AC
76 val proc = Unix.execute ("/bin/sh",
77 ["-c",
811dc1e5 78 "DOMTOOL_USER=hcoop.daemon /usr/local/bin/domtool-admin firewall "
3d2ed222
AC
79 ^ Init.nodeName node ^ " " ^ uname])
80
81 val inf = Unix.textInstreamOf proc
e510b9bd 82
3d2ed222 83 fun readEm lines =
e510b9bd 84 case TextIO.inputLine inf of
3d2ed222
AC
85 SOME line => readEm (String.substring (line, 0, size line - 1) :: lines)
86 | NONE => rev lines
87
88 val lines = readEm []
e510b9bd 89 in
3d2ed222
AC
90 TextIO.closeIn inf;
91 if OS.Process.isSuccess (Unix.reap proc) then
92 lines
93 else
94 []
e510b9bd
AC
95 end
96
308f44e7
AC
97fun intFromString s =
98 if CharVector.all Char.isDigit s andalso size s > 0 then
99 Int.fromString s
100 else
101 NONE
102
103fun validPort port =
104 case intFromString port of
105 NONE => false
106 | SOME n => n > 0
107
108fun validPortPiece pp =
109 case String.fields (fn ch => ch = #":") pp of
110 [port] => validPort port
111 | [port1, port2] => validPort port1 andalso validPort port2
112
113fun validPorts ports =
114 List.all validPortPiece (String.fields (fn ch => ch = #",") ports)
115
116fun validIp s =
117 case map intFromString (String.fields (fn ch => ch = #".") s) of
118 [SOME n1, SOME n2, SOME n3, SOME n4] =>
119 n1 >= 0 andalso n1 < 256 andalso n2 >= 0 andalso n2 < 256 andalso n3 >= 0 andalso n3 < 256 andalso n4 >= 0 andalso n4 < 256
120 | _ => false
121
122fun isIdent ch = Char.isLower ch orelse Char.isDigit ch
123
124fun validHost s =
125 size s > 0 andalso size s < 20
126 andalso CharVector.all (fn ch => isIdent ch orelse ch = #"-") s
127
128fun validDomain s =
129 size s > 0 andalso size s < 100
130 andalso List.all validHost (String.fields (fn ch => ch = #".") s)
131
132val validHosts = List.all (fn x => validIp x orelse validDomain x)
133
134fun validRule rule =
135 case String.tokens Char.isSpace rule of
136 "Client" :: ports :: hosts => validPorts ports andalso validHosts hosts
137 | "Server" :: ports :: hosts => validPorts ports andalso validHosts hosts
138 | ["LocalServer", ports] => validPorts ports
f658a3d8 139 | ["ProxiedServer", ports] => validPorts ports
308f44e7
AC
140 | _ => false
141
b5001e8f
CE
142fun fulldomain (sub, dom) =
143 sub ^ (if String.size sub <> 0 then "." else "") ^ dom
144
dfb0d0d7 145end