diff options
author | Scott Ullrich <sullrich@pfsense.org> | 2005-03-07 23:12:41 +0000 |
---|---|---|
committer | Scott Ullrich <sullrich@pfsense.org> | 2005-03-07 23:12:41 +0000 |
commit | 9699028a571f1df9bd54799a8df0b97d03f6901b (patch) | |
tree | 44b7a6d30f21088895656ad7f0e9395c6f606f3a /etc | |
parent | 90b7aa76dae8c8436f968d2cb47f25a1c52ef989 (diff) | |
download | pfsense-9699028a571f1df9bd54799a8df0b97d03f6901b.zip pfsense-9699028a571f1df9bd54799a8df0b97d03f6901b.tar.gz |
Add local user manager code imported from Pascal Suter's m0n0wall developers group message.
Diffstat (limited to 'etc')
-rw-r--r-- | etc/inc/captiveportal.inc | 256 |
1 files changed, 129 insertions, 127 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc index abb8a1b..719d0d8 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -2,20 +2,20 @@ /* captiveportal.inc part of m0n0wall (http://m0n0.ch/wall) - - Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + + Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>. All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE @@ -26,35 +26,41 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + This version of captiveportal.inc has been modified by Rob Parker + <rob.parker@keycom.co.uk> to include changes for per-user bandwidth management + via returned RADIUS attributes. This page has been modified to delete any + added rules which may have been created by other per-user code (index.php, etc). + These changes are (c) 2004 Keycom PLC. +*/ + /* include all configuration functions */ require_once("functions.inc"); require_once("radius_accounting.inc") ; function captiveportal_configure() { global $config, $g; - + if (isset($config['captiveportal']['enable']) && (($config['captiveportal']['interface'] == "lan") || isset($config['interfaces'][$config['captiveportal']['interface']]['enable']))) { - + if ($g['booting']) echo "Starting captive portal... "; - + /* kill any running mini_httpd */ killbypid("{$g['varrun_path']}/mini_httpd.cp.pid"); killbypid("{$g['varrun_path']}/mini_httpd.cps.pid"); - + /* kill any running minicron */ killbypid("{$g['varrun_path']}/minicron.pid"); - + /* generate ipfw rules */ $cprules = captiveportal_rules_generate(); - + /* make sure ipfw is loaded */ mwexec("/sbin/kldload ipfw"); - + /* stop accounting on all clients */ captiveportal_radius_stop_all() ; @@ -64,7 +70,7 @@ function captiveportal_configure() { unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db"); unlink_if_exists("{$g['vardb_path']}/captiveportal_ip.db"); unlink_if_exists("{$g['vardb_path']}/captiveportal_radius.db"); - + /* write portal page */ if ($config['captiveportal']['page']['htmltext']) $htmltext = base64_decode($config['captiveportal']['page']['htmltext']); @@ -72,37 +78,16 @@ function captiveportal_configure() { /* example/template page */ $htmltext = <<<EOD <html> -<title>pfSense's captive portal</title> <head> - <STYLE type="text/css"> -.listhdrr { - background-color: #BBBBBB; - padding-right: 16px; - padding-left: 6px; - font-weight: bold; - border-right: 1px solid #999999; - border-bottom: 1px solid #999999; - font-size: 11px; - padding-top: 5px; - padding-bottom: 5px; -} - - </STYLE> +<title>m0n0wall captive portal</title> </head> -<body bgcolor="#990000"> -<center> -<font color="white" face="arial" size="+1">Welcome to pfSense's captive portal!</font> -<p> -<form method="post" action="$PORTAL_ACTION$"> -<table border="0" cellpadding="6" cellspacing="0"> -<tr><td align="right" class="listhdrr"><font color="white">Username:</td><td class="listhdrr"><input name="auth_user" type="text"></td></tr> -<tr><td align="right" class="listhdrr"><font color="white">Password:</td><td class="listhdrr"><input name="auth_pass" type="password"></td></tr> -<input name="redirurl" type="hidden" value="$PORTAL_REDIRURL$"> -</table> -<p> -<center><input name="accept" type="submit" value="Continue"> +<body> +<h2>m0n0wall captive portal</h2> +<p>This is the default captive portal page. Please upload your own custom HTML file on the <em>Services: Captive portal</em> screen in the m0n0wall webGUI.</p> +<form method="post" action="\$PORTAL_ACTION\$"> + <input name="accept" type="submit" value="Continue"> + <input name="redirurl" type="hidden" value="\$PORTAL_REDIRURL\$"> </form> -</center> </body> </html> @@ -112,9 +97,9 @@ EOD; $fd = @fopen("{$g['varetc_path']}/captiveportal.html", "w"); if ($fd) { fwrite($fd, $htmltext); - fclose($fd); + fclose($fd); } - + /* write error page */ if ($config['captiveportal']['page']['errtext']) $errtext = base64_decode($config['captiveportal']['page']['errtext']); @@ -141,14 +126,14 @@ EOD; $fd = @fopen("{$g['varetc_path']}/captiveportal-error.html", "w"); if ($fd) { fwrite($fd, $errtext); - fclose($fd); + fclose($fd); } /* load rules */ mwexec("/sbin/ipfw -f delete set 1"); mwexec("/sbin/ipfw -f delete set 2"); mwexec("/sbin/ipfw -f delete set 3"); - + /* XXX - seems like ipfw cannot accept rules directly on stdin, so we have to write them to a temporary file first */ $fd = @fopen("{$g['tmp_path']}/ipfw.cp.rules", "w"); @@ -156,30 +141,30 @@ EOD; printf("Cannot open ipfw.cp.rules in captiveportal_configure()\n"); return 1; } - + fwrite($fd, $cprules); fclose($fd); - + mwexec("/sbin/ipfw {$g['tmp_path']}/ipfw.cp.rules"); - + unlink("{$g['tmp_path']}/ipfw.cp.rules"); - + /* filter on layer2 as well so we can check MAC addresses */ mwexec("/sbin/sysctl net.link.ether.ipfw=1"); - + chdir($g['captiveportal_path']); - + /* start web server */ mwexec("/usr/local/sbin/mini_httpd -a -M 0 -u root -maxproc 16" . " -p 8000 -i {$g['varrun_path']}/mini_httpd.cp.pid"); - + /* fire up another one for HTTPS if requested */ if (isset($config['captiveportal']['httpslogin']) && $config['captiveportal']['certificate'] && $config['captiveportal']['private-key']) { - + $cert = base64_decode($config['captiveportal']['certificate']); $key = base64_decode($config['captiveportal']['private-key']); - + $fd = fopen("{$g['varetc_path']}/cert-portal.pem", "w"); if (!$fd) { printf("Error: cannot open cert-portal.pem in system_webgui_start().\n"); @@ -190,23 +175,23 @@ EOD; fwrite($fd, "\n"); fwrite($fd, $key); fclose($fd); - + mwexec("/usr/local/sbin/mini_httpd -S -a -M 0 -E {$g['varetc_path']}/cert-portal.pem" . " -u root -maxproc 16 -p 8001" . " -i {$g['varrun_path']}/mini_httpd.cps.pid"); } - + /* start pruning process (interval = 60 seconds) */ mwexec("/usr/local/bin/minicron 60 {$g['varrun_path']}/minicron.pid " . "/etc/rc.prunecaptiveportal"); - + /* generate passthru mac database */ captiveportal_passthrumac_configure() ; /* create allowed ip database and insert ipfw rules to make it so */ captiveportal_allowedip_configure() ; /* generate radius server database */ - if($config['captiveportal']['radiusip']) { + if($config['captiveportal']['radiusip'] && $config['captiveportal']['auth_method']=="radius") { $radiusip = $config['captiveportal']['radiusip'] ; if($config['captiveportal']['radiusport']) @@ -234,7 +219,7 @@ EOD; if ($g['booting']) echo "done\n"; - + } else { killbypid("{$g['varrun_path']}/mini_httpd.cp.pid"); killbypid("{$g['varrun_path']}/minicron.pid"); @@ -250,13 +235,13 @@ EOD; mwexec("/sbin/ipfw -f delete set 3"); } } - + return 0; } function captiveportal_rules_generate() { global $config, $g; - + $cpifn = $config['captiveportal']['interface']; $cpif = $config['interfaces'][$cpifn]['if']; $cpip = $config['interfaces'][$cpifn]['ipaddr']; @@ -265,7 +250,7 @@ function captiveportal_rules_generate() { clients as skipto 50000 rules to make traffic shaping work */ $cprules = ""; - + /* captive portal on LAN interface? */ if ($cpifn == "lan") { /* add anti-lockout rules */ @@ -313,7 +298,7 @@ add 1305 set 1 pass tcp from $cpip 8001 to any out EOD; } - + $cprules .= <<<EOD # ... 10000-19899: rules per authenticated client go here... @@ -338,47 +323,47 @@ EOD; /* remove clients that have been around for longer than the specified amount of time */ /* db file structure: timestamp,ipfw_rule_no,clientip,clientmac,username,sessionid */ function captiveportal_prune_old() { - + global $g, $config; - + /* check for expired entries */ if ($config['captiveportal']['timeout']) $timeout = $config['captiveportal']['timeout'] * 60; else $timeout = 0; - + if ($config['captiveportal']['idletimeout']) $idletimeout = $config['captiveportal']['idletimeout'] * 60; else $idletimeout = 0; - + if (!$timeout && !$idletimeout) return; - + captiveportal_lock(); - + /* read database */ $cpdb = captiveportal_read_db(); - + $radiusservers = captiveportal_get_radius_servers(); - + for ($i = 0; $i < count($cpdb); $i++) { - + $timedout = false; - + /* hard timeout? */ if ($timeout) { if ((time() - $cpdb[$i][0]) >= $timeout) - $timedout = true; + $timedout = true; } - + /* if an idle timeout is specified, get last activity timestamp from ipfw */ if (!$timedout && $idletimeout) { $lastact = captiveportal_get_last_activity($cpdb[$i][1]); if ($lastact && ((time() - $lastact) >= $idletimeout)) $timedout = true; } - + if ($timedout) { /* this client needs to be deleted - remove ipfw rules */ if (isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) { @@ -388,31 +373,40 @@ function captiveportal_prune_old() { $cpdb[$i][0], // start time $radiusservers[0]['ipaddr'], $radiusservers[0]['acctport'], - $radiusservers[0]['key']); + $radiusservers[0]['key'], + $cpdb[$i][2]); //clientip + syslog(LOG_INFO,"Authenticated user $cpdb[$i][4] timed out"); } + //KEYCOM: we need to delete +40500 and +45500 as well... + //these are the rule numbers we use to control traffic shaping for each logged in user via captive portal mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000)); + //we only need to remove our rules if peruserbw is turned on. + if(isset($config['captiveportal']['peruserbw'])) { + mwexec("/sbin/ipfw delete " . ($cpdb[$i][1]+40500)); + mwexec("/sbin/ipfw delete " . ($cpdb[$i][1]+45500)); + } unset($cpdb[$i]); } } - + /* write database */ captiveportal_write_db($cpdb); - + captiveportal_unlock(); } /* remove a single client by ipfw rule number */ function captiveportal_disconnect_client($id) { - + global $g, $config; - + captiveportal_lock(); - + /* read database */ $cpdb = captiveportal_read_db(); $radiusservers = captiveportal_get_radius_servers(); - - /* find entry */ + + /* find entry */ for ($i = 0; $i < count($cpdb); $i++) { if ($cpdb[$i][1] == $id) { /* this client needs to be deleted - remove ipfw rules */ @@ -423,17 +417,24 @@ function captiveportal_disconnect_client($id) { $cpdb[$i][0], // start time $radiusservers[0]['ipaddr'], $radiusservers[0]['acctport'], - $radiusservers[0]['key']); + $radiusservers[0]['key'], + $cpdb[$i][2]); //clientip + syslog(LOG_INFO,"Authenticated user $cpdb[$i][4] disconnected"); } mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000)); + //we only need to remove our rules if peruserbw is turned on. + if(isset($config['captiveportal']['peruserbw'])) { + mwexec("/sbin/ipfw delete " . ($cpdb[$i][1]+40500)); + mwexec("/sbin/ipfw delete " . ($cpdb[$i][1]+45500)); + } unset($cpdb[$i]); break; } } - + /* write database */ captiveportal_write_db($cpdb); - + captiveportal_unlock(); } @@ -443,9 +444,9 @@ function captiveportal_radius_stop_all() { captiveportal_lock() ; $cpdb = captiveportal_read_db() ; - + $radiusservers = captiveportal_get_radius_servers(); - + if (isset($radiusservers[0])) { for ($i = 0; $i < count($cpdb); $i++) { RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno @@ -454,7 +455,8 @@ function captiveportal_radius_stop_all() { $cpdb[$i][0], // start time $radiusservers[0]['ipaddr'], $radiusservers[0]['acctport'], - $radiusservers[0]['key']); + $radiusservers[0]['key'], + $cpdb[$i][2]); //clientip } } captiveportal_unlock() ; @@ -462,34 +464,34 @@ function captiveportal_radius_stop_all() { function captiveportal_passthrumac_configure() { global $config, $g; - + /* clear out passthru macs, if necessary */ if (file_exists("{$g['vardb_path']}/captiveportal_mac.db")) { unlink("{$g['vardb_path']}/captiveportal_mac.db"); } - + if (is_array($config['captiveportal']['passthrumac'])) { - + $fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db", "w"); if (!$fd) { printf("Error: cannot open passthru mac DB file in captiveportal_passthrumac_configure().\n"); - return 1; + return 1; } - + foreach ($config['captiveportal']['passthrumac'] as $macent) { /* record passthru mac so it can be recognized and let thru */ fwrite($fd, $macent['mac'] . "\n"); } - - fclose($fd); + + fclose($fd); } - + return 0; } function captiveportal_allowedip_configure() { global $config, $g; - + captiveportal_lock() ; /* clear out existing allowed ips, if necessary */ @@ -501,7 +503,7 @@ function captiveportal_allowedip_configure() { if($line) { list($ip,$rule) = explode(",",$line); mwexec("/sbin/ipfw delete $rule") ; - } + } } } fclose($fd) ; @@ -513,16 +515,16 @@ function captiveportal_allowedip_configure() { $ruleno = trim(file_get_contents("{$g['vardb_path']}/captiveportal.nextrule")); if (!$ruleno) $ruleno = 10000; /* first rule number */ - + if (is_array($config['captiveportal']['allowedip'])) { - + $fd = @fopen("{$g['vardb_path']}/captiveportal_ip.db", "w"); if (!$fd) { printf("Error: cannot open allowed ip DB file in captiveportal_allowedip_configure().\n"); captiveportal_unlock() ; - return 1; + return 1; } - + foreach ($config['captiveportal']['allowedip'] as $ipent) { /* record allowed ip so it can be recognized and removed later */ fwrite($fd, $ipent['ip'] . "," . $ruleno ."\n"); @@ -538,8 +540,8 @@ function captiveportal_allowedip_configure() { if ($ruleno > 19899) $ruleno = 10000; } - - fclose($fd); + + fclose($fd); /* write next rule number */ $fd = @fopen("{$g['vardb_path']}/captiveportal.nextrule", "w"); @@ -548,31 +550,31 @@ function captiveportal_allowedip_configure() { fclose($fd); } } - + captiveportal_unlock() ; return 0; } /* get last activity timestamp given ipfw rule number */ function captiveportal_get_last_activity($ruleno) { - + exec("/sbin/ipfw -T list {$ruleno} 2>/dev/null", $ipfwoutput); - + /* in */ if ($ipfwoutput[0]) { $ri = explode(" ", $ipfwoutput[0]); if ($ri[1]) return $ri[1]; } - + return 0; } /* read captive portal DB into array */ function captiveportal_read_db() { - + global $g; - + $cpdb = array(); $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r"); if ($fd) { @@ -580,7 +582,7 @@ function captiveportal_read_db() { $line = trim(fgets($fd)); if ($line) { $cpdb[] = explode(",", $line); - } + } } fclose($fd); } @@ -589,9 +591,9 @@ function captiveportal_read_db() { /* write captive portal DB */ function captiveportal_write_db($cpdb) { - + global $g; - + $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w"); if ($fd) { foreach ($cpdb as $cpent) { @@ -603,9 +605,9 @@ function captiveportal_write_db($cpdb) { /* read RADIUS servers into array */ function captiveportal_get_radius_servers() { - + global $g; - + if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) { $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db","r"); if ($fd) { @@ -619,22 +621,22 @@ function captiveportal_get_radius_servers() { } } fclose($fd); - + return $radiusservers; } } - + return false; } /* lock captive portal information, decide that the lock file is stale after 10 seconds */ function captiveportal_lock() { - + global $g; - + $lockfile = "{$g['varrun_path']}/captiveportal.lock"; - + $n = 0; while ($n < 10) { /* open the lock file in append mode to avoid race condition */ @@ -652,11 +654,11 @@ function captiveportal_lock() { /* unlock configuration file */ function captiveportal_unlock() { - + global $g; - + $lockfile = "{$g['varrun_path']}/captiveportal.lock"; - + if (file_exists($lockfile)) unlink($lockfile); } |