(* 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 user_" :: uname :: "_tcp_in proto tcp {\n" :: lines @ ["}\n\n"]))) (!in_lines); StringMap.appi (fn (uname, lines) => TextIO.output (users_conf, String.concat ("chain user_" :: uname :: "_tcp_out proto tcp {\n" :: lines @ ["}\n\n"]))) (!out_lines); TextIO.closeOut users_conf; OS.Process.success end end