Bug fixes
[hcoop/zz_old/fwtool.git] / fwtool.sml
1 (*
2 Fwtool (http://hcoop.sf.net/)
3 Copyright (C) 2005 Adam Chlipala
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *)
19
20 (* Main functionality *)
21
22 structure Fwtool :> FWTOOL = struct
23
24 open Config
25
26 fun main _ =
27 let
28 val inf = TextIO.openIn (fwdir ^ "/users.rules")
29 val out_lines = ref StringMap.empty
30 val in_lines = ref StringMap.empty
31 val users_tcp_out_conf = TextIO.openOut (fwdir ^ "/users_tcp_out.conf")
32 val users_tcp_in_conf = TextIO.openOut (fwdir ^ "/users_tcp_in.conf")
33
34 fun confLine (f, r) (uid, uname, line) =
35 let
36 val line = String.concat ["\t", line, "\n"]
37 val lines = case StringMap.find (!r, uname) of
38 NONE => (f (uid, uname); [])
39 | SOME lines => lines
40 in
41 r := StringMap.insert (!r, uname, line :: lines)
42 end
43
44 val confLine_in = confLine ((fn (uid, uname) =>
45 TextIO.output (users_tcp_in_conf, String.concat
46 ["mod owner uid-owner ",
47 Int.toString uid,
48 " { goto user_",
49 uname,
50 "_tcp_in; goto lreject; }\n"])),
51 in_lines)
52
53 val confLine_out = confLine ((fn (uid, uname) =>
54 TextIO.output (users_tcp_out_conf, String.concat
55 ["mod owner uid-owner ",
56 Int.toString uid,
57 " { goto user_",
58 uname,
59 "_tcp_out; goto lreject; }\n"])),
60 out_lines)
61
62 fun parsePorts ports =
63 case String.fields (fn ch => ch = #",") ports of
64 [pp] => pp
65 | pps => String.concat ["(", String.concatWith " " pps, ")"]
66
67 fun parseHosts addr hosts =
68 case hosts of
69 [] => ""
70 | [host] => String.concat [" ", addr, " ", host]
71 | _ => String.concat [" ", addr, " (", String.concatWith " " hosts, ")"]
72
73 fun loop () =
74 case TextIO.inputLine inf of
75 NONE => ()
76 | SOME line =>
77 case String.tokens Char.isSpace line of
78 uname :: rest =>
79 let
80 val uid = Posix.SysDB.Passwd.uid (Posix.SysDB.getpwnam uname)
81 val uid = SysWord.toInt (Posix.ProcEnv.uidToWord uid)
82 in
83 case rest of
84 "Client" :: ports :: hosts =>
85 confLine_out (uid, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
86 | "Server" :: ports :: hosts =>
87 confLine_in (uid, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
88 | ["LocalServer", ports] =>
89 confLine_in (uid, uname, String.concat ["saddr $WE dport ", parsePorts ports, " ACCEPT;"])
90 | _ => print "Invalid config line\n";
91 loop ()
92 end
93 | _ => loop ()
94
95 val _ = loop ()
96
97 val _ = TextIO.closeOut users_tcp_out_conf;
98 val _ = TextIO.closeOut users_tcp_in_conf;
99 val users_conf = TextIO.openOut (fwdir ^ "/users.conf")
100 in
101 StringMap.appi (fn (uname, lines) =>
102 TextIO.output (users_conf,
103 String.concat ("chain user_"
104 :: uname
105 :: "_tcp_in proto tcp {\n"
106 :: lines
107 @ ["}\n\n"]))) (!in_lines);
108 StringMap.appi (fn (uname, lines) =>
109 TextIO.output (users_conf,
110 String.concat ("chain user_"
111 :: uname
112 :: "_tcp_out proto tcp {\n"
113 :: lines
114 @ ["}\n\n"]))) (!out_lines);
115 TextIO.closeOut users_conf;
116 OS.Process.success
117 end
118
119 end