1 structure Sec
:> SEC
= struct
5 structure Req
= Request(struct
7 val adminGroup
= "server"
8 fun subject _
= "Security permissions change request"
11 fun body (mail
, req
) =
12 (Mail
.mwrite (mail
, req
);
13 Mail
.mwrite (mail
, "\n"))
16 fun findSubusers uname
=
18 val uname_under
= uname ^
"_"
19 val inf
= TextIO.openIn
"/etc/passwd"
22 case TextIO.inputLine inf
of
23 NONE
=> ListMergeSort
.sort (fn (x
, y
) => String.compare (x
, y
) = GREATER
) subs
25 case String.fields (fn ch
=> ch
= #
":") line
of
27 if size uname
' >= size uname_under
28 andalso String.substring (uname
', 0, size uname_under
) = uname_under
then
35 before TextIO.closeIn inf
38 datatype socket_perms
=
44 fun inGroup (uname
, grp
) =
46 val uname_under
= uname ^
"_"
47 val inf
= TextIO.openIn
"/etc/group"
50 case TextIO.inputLine inf
of
53 case String.fields (fn ch
=> ch
= #
":") line
of
54 [gname
, _
, _
, members
] =>
56 mem (uname
, String.fields (fn ch
=> ch
= #
",") members
)
62 before TextIO.closeIn inf
65 fun socketPerms uname
=
66 if inGroup (uname
, "no-sockets") then
68 else if inGroup (uname
, "no-cli-sockets") then
69 if inGroup (uname
, "no-serv-sockets") then
73 else if inGroup (uname
, "no-serv-sockets") then
78 fun isTpe uname
= inGroup (uname
, "only-tpe")
80 fun findFirewallRules uname
=
82 val inf
= TextIO.openIn
"/etc/firewall/users.rules"
85 case TextIO.inputLine inf
of
86 NONE
=> List.rev rules
88 if String.sub (line
, 0) = #
"#" then
90 else case String.tokens
Char.isSpace line
of
92 if uname
= uname
' then
93 loop (String.concatWith
" " rest
:: rules
)
99 before TextIO.closeIn inf
102 fun somethingAllowed fname uname
=
104 val inf
= TextIO.openIn fname
105 val uname
' = uname ^
"\n"
108 case TextIO.inputLine inf
of
110 | SOME line
=> line
= uname
' orelse loop ()
113 before TextIO.closeIn inf
116 val cronAllowed
= somethingAllowed
"/etc/cron.allow"
117 val ftpAllowed
= somethingAllowed
"/etc/ftpusers"