Auto-generation of per-user rules from simple config file
authorAdam Chlipala <adamc@hcoop.net>
Sun, 2 Oct 2005 16:06:38 +0000 (16:06 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Sun, 2 Oct 2005 16:06:38 +0000 (16:06 +0000)
.cvsignore [new file with mode: 0644]
config.sml [new file with mode: 0644]
fwtool.cm [new file with mode: 0644]
fwtool.sig [new file with mode: 0644]
fwtool.sml [new file with mode: 0644]
main.sml [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..82beda6
--- /dev/null
@@ -0,0 +1 @@
+fwtool
diff --git a/config.sml b/config.sml
new file mode 100644 (file)
index 0000000..843281a
--- /dev/null
@@ -0,0 +1,27 @@
+(*
+Fwtool (http://hcoop.sf.net/)
+Copyright (C) 2005  Adam Chlipala
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*)
+
+(* Settings that control fwtool behavior *)
+
+structure Config = struct
+
+val fwdir = "/home/adamc_admin"
+(* Where firewall config lives *)
+
+end
diff --git a/fwtool.cm b/fwtool.cm
new file mode 100644 (file)
index 0000000..ed33a56
--- /dev/null
+++ b/fwtool.cm
@@ -0,0 +1,10 @@
+Group is
+       ../domtool/src/smlnj-lib/sources.cm
+       ../domtool/src/map.sml
+
+       config.sml
+
+       fwtool.sig
+       fwtool.sml
+
+       main.sml
\ No newline at end of file
diff --git a/fwtool.sig b/fwtool.sig
new file mode 100644 (file)
index 0000000..6a78d28
--- /dev/null
@@ -0,0 +1,22 @@
+(*
+Fwtool (http://hcoop.sf.net/)
+Copyright (C) 2005  Adam Chlipala
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*)
+
+signature FWTOOL = sig
+    val main : string * string list -> OS.Process.status
+end
diff --git a/fwtool.sml b/fwtool.sml
new file mode 100644 (file)
index 0000000..55ec010
--- /dev/null
@@ -0,0 +1,119 @@
+(*
+Fwtool (http://hcoop.sf.net/)
+Copyright (C) 2005  Adam Chlipala
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*)
+
+(* Main functionality *)
+
+structure Fwtool :> FWTOOL = struct
+
+open Config
+
+fun main _ =
+    let
+       val inf = TextIO.openIn (fwdir ^ "/users.rules")
+       val out_lines = ref StringMap.empty
+       val in_lines = ref StringMap.empty
+       val users_tcp_out_conf = TextIO.openOut (fwdir ^ "/users_tcp_out.conf")
+       val users_tcp_in_conf = TextIO.openOut (fwdir ^ "/users_tcp_in.conf")
+
+       fun confLine (f, r) (uid, uname, line) =
+           let
+               val line = String.concat ["\t", line, "\n"]
+               val lines = case StringMap.find (!r, uname) of
+                               NONE => (f (uid, uname); [])
+                             | SOME lines => lines
+           in
+               r := StringMap.insert (!r, uname, line :: lines)
+           end
+
+       val confLine_in = confLine ((fn (uid, uname) =>
+                                       TextIO.output (users_tcp_in_conf, String.concat
+                                                                              ["mod owner uid-owner ",
+                                                                               Int.toString uid,
+                                                                               " { goto user_",
+                                                                               uname,
+                                                                               "_tcp_in goto lreject; }\n"])),
+                                   in_lines)
+
+       val confLine_out = confLine ((fn (uid, uname) =>
+                                       TextIO.output (users_tcp_out_conf, String.concat
+                                                                              ["mod owner uid-owner ",
+                                                                               Int.toString uid,
+                                                                               " { goto user_",
+                                                                               uname,
+                                                                               "_tcp_out; goto lreject; }\n"])),
+                                   out_lines)
+
+       fun parsePorts ports =
+           case String.fields (fn ch => ch = #",") ports of
+               [pp] => pp
+             | pps => String.concat ["(", String.concatWith " " pps, ")"]
+
+       fun parseHosts addr hosts =
+           case hosts of
+               [] => ""
+             | [host] => String.concat [" ", addr, " ", host]
+             | _ => String.concat [" ", addr, " (", String.concatWith " " hosts, ")"]
+
+       fun loop () =
+           case TextIO.inputLine inf of
+               NONE => ()
+             | SOME line =>
+               case String.tokens Char.isSpace line of
+                   uname :: rest =>
+                   let
+                       val uid = Posix.SysDB.Passwd.uid (Posix.SysDB.getpwnam uname)
+                       val uid = SysWord.toInt (Posix.ProcEnv.uidToWord uid)
+                   in
+                       case rest of
+                           "Client" :: ports :: hosts =>
+                           confLine_out (uid, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
+                         | "Server" :: ports :: hosts =>
+                           confLine_in (uid, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
+                         | ["LocalServer", ports] =>
+                           confLine_in (uid, uname, String.concat ["saddr $WE dport ", parsePorts ports, " ACCEPT;"])
+                         | _ => print "Invalid config line\n";
+                       loop ()
+                   end
+                 | _ => loop ()
+
+       val _ = loop ()
+
+       val _ = TextIO.closeOut users_tcp_out_conf;
+       val _ = TextIO.closeOut users_tcp_in_conf;
+       val users_conf = TextIO.openOut (fwdir ^ "/users.conf")
+    in
+       StringMap.appi (fn (uname, lines) =>
+                          TextIO.output (users_conf,
+                                         String.concat ("chain users_"
+                                                        :: uname
+                                                        :: "_tcp_in proto tcp {\n"
+                                                        :: lines
+                                                        @ ["}\n\n"]))) (!in_lines);
+       StringMap.appi (fn (uname, lines) =>
+                          TextIO.output (users_conf,
+                                         String.concat ("chain users_"
+                                                        :: uname
+                                                        :: "_tcp_out proto tcp {\n"
+                                                        :: lines
+                                                        @ ["}\n\n"]))) (!out_lines);
+       TextIO.closeOut users_conf;
+       OS.Process.success
+    end
+
+end
diff --git a/main.sml b/main.sml
new file mode 100644 (file)
index 0000000..681eeb0
--- /dev/null
+++ b/main.sml
@@ -0,0 +1,20 @@
+(*
+Fwtool (http://hcoop.sf.net/)
+Copyright (C) 2005  Adam Chlipala
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*)
+
+val _ = OS.Process.exit (Fwtool.main (CommandLine.name (), CommandLine.arguments ()))