diff options
author | Scott Ullrich <sullrich@pfsense.org> | 2006-09-05 17:01:27 +0000 |
---|---|---|
committer | Scott Ullrich <sullrich@pfsense.org> | 2006-09-05 17:01:27 +0000 |
commit | 65fbb3889680ae561f0d60c8038dbc1a737af0a2 (patch) | |
tree | 7abb23bc94a6b4ce3129f0273b06f72b8b24eaeb /usr/local/captiveportal | |
parent | cf83f490b89ba56da3f02f9f1d13873035a9daf2 (diff) | |
download | pfsense-65fbb3889680ae561f0d60c8038dbc1a737af0a2.zip pfsense-65fbb3889680ae561f0d60c8038dbc1a737af0a2.tar.gz |
Fix $VARIABLES$
Diffstat (limited to 'usr/local/captiveportal')
-rwxr-xr-x | usr/local/captiveportal/index.php | 755 |
1 files changed, 373 insertions, 382 deletions
diff --git a/usr/local/captiveportal/index.php b/usr/local/captiveportal/index.php index 788efcf..c74e593 100755 --- a/usr/local/captiveportal/index.php +++ b/usr/local/captiveportal/index.php @@ -1,135 +1,95 @@ <?php /* - index.php - part of m0n0wall (http://m0n0.ch/wall) - - 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 - AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - 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. + $Id$ + part of m0n0wall (http://m0n0.ch/wall) + + Copyright (C) 2003-2006 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 + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + 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. */ -require("globals.inc"); -require("util.inc"); -require("config.inc"); -require("radius_authentication.inc"); -require("radius_accounting.inc"); +require_once("functions.inc"); + +header("Expires: 0"); +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); $orig_host = $_ENV['HTTP_HOST']; $orig_request = $_GET['redirurl']; -$lockfile = "{$g['varrun_path']}/captiveportal.lock"; $clientip = $_SERVER['REMOTE_ADDR']; if (!$clientip) { - /* not good - bail out */ + /* not good - bail out */ echo "An error occured. Please check the system logs for more information."; log_error("Captive portal could not deterimine clients ip address."); - exit; + exit; +} + +if (isset($config['captiveportal']['httpslogin'])) + $ourhostname = $config['captiveportal']['httpsname'] . ":8001"; +else + $ourhostname = $config['interfaces'][$config['captiveportal']['interface']]['ipaddr'] . ":8000"; + +if ($orig_host != $ourhostname) { + /* the client thinks it's connected to the desired web server, but instead + it's connected to us. Issue a redirect... */ + + if (isset($config['captiveportal']['httpslogin'])) + header("Location: https://{$ourhostname}/index.php?redirurl=" . urlencode("http://{$orig_host}{$orig_request}")); + else + header("Location: http://{$ourhostname}/index.php?redirurl=" . urlencode("http://{$orig_host}{$orig_request}")); + + exit; } +if (preg_match("/redirurl=(.*)/", $orig_request, $matches)) + $redirurl = urldecode($matches[1]); +if ($_POST['redirurl']) + $redirurl = $_POST['redirurl']; + +$macfilter = !isset($config['captiveportal']['nomacfilter']); + /* find MAC address for client */ $clientmac = arp_get_mac_by_ip($clientip); -if (!$clientmac && !isset($config['captiveportal']['nomacfilter'])) { - /* unable to find MAC address - shouldn't happen! - bail out */ +if (!$clientmac && $macfilter) { + /* unable to find MAC address - shouldn't happen! - bail out */ + captiveportal_logportalauth("unauthenticated","noclientmac",$clientip,"ERROR"); echo "An error occured. Please check the system logs for more information."; log_error("Captive portal could not deterimine clients MAC address. Disable MAC address filtering in captive portal if you do not needs this functionality."); - exit; + exit; } -if ($clientmac && portal_mac_fixed($clientmac)) { - /* punch hole in ipfw for pass thru mac addresses */ - portal_allow($clientip, $clientmac, "unauthenticated"); - -} else if ($_POST['accept'] && file_exists("{$g['vardb_path']}/captiveportal_radius.db")) { - - /* authenticate against radius server */ - $radiusservers = captiveportal_get_radius_servers(); - - if ($_POST['auth_user'] && $_POST['auth_pass']) { - $auth_val = RADIUS_AUTHENTICATION($_POST['auth_user'], - $_POST['auth_pass'], - $radiusservers[0]['ipaddr'], - $radiusservers[0]['port'], - $radiusservers[0]['key']); - if ($auth_val == 2) { - captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"LOGIN"); - $sessionid = portal_allow($clientip, $clientmac, $_POST['auth_user'], $_POST['auth_pass']); - if (isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) { - $auth_val = RADIUS_ACCOUNTING_START($_POST['auth_user'], - $sessionid, - $radiusservers[0]['ipaddr'], - $radiusservers[0]['acctport'], - $radiusservers[0]['key'], - $clientip); - } - } else { - captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE"); - readfile("{$g['varetc_path']}/captiveportal-error.html"); - } - } else { - readfile("{$g['varetc_path']}/captiveportal-error.html"); - } - -} else if ($_POST['accept'] && $config['captiveportal']['auth_method'] == "local") { - - //check against local usermanager - $userdb = &$config['captiveportal']['user']; - - $loginok = false; - - //erase expired accounts - if (is_array($userdb)) { - $moddb = false; - for ($i = 0; $i < count($userdb); $i++) { - if ($userdb[$i]['expirationdate'] && (strtotime("-1 day") > strtotime($userdb[$i]['expirationdate']))) { - unset($userdb[$i]); - $moddb = true; - } - } - if ($moddb) - write_config(); - - $userdb = &$config['captiveportal']['user']; - - for ($i = 0; $i < count($userdb); $i++) { - if (($userdb[$i]['name'] == $_POST['auth_user']) && ($userdb[$i]['password'] == md5($_POST['auth_pass']))) { - $loginok = true; - break; - } - } - } +/* find out if we need RADIUS + RADIUSMAC or not */ +if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) { + $radius_enable = TRUE; + if ($radius_enable && isset($config['captiveportal']['radmac_enable'])) + $radmac_enable = TRUE; +} - if ($loginok){ - captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"LOGIN"); - portal_allow($clientip, $clientmac,$_POST['auth_user'],0,0); - } else { - captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE"); - readfile("{$g['varetc_path']}/captiveportal-error.html"); - } -} else if ($_POST['accept'] && $clientip) { - portal_allow($clientip, $clientmac, "unauthenticated"); -} else if ($_POST['logout_id']) { - disconnect_client($_POST['logout_id']); - echo <<<EOD +if ($_POST['logout_id']) { + disconnect_client($_POST['logout_id']); + echo <<<EOD <HTML> <HEAD><TITLE>Disconnecting...</TITLE></HEAD> <BODY BGCOLOR="#435370"> @@ -145,323 +105,354 @@ setTimeout('window.close();',5000) ; </HTML> EOD; -} else if (($_ENV['SERVER_PORT'] != 8001) && isset($config['captiveportal']['httpslogin'])) { - /* redirect to HTTPS login page */ - header("Location: https://{$config['captiveportal']['httpsname']}:8001/index.php?redirurl=" . urlencode("http://{$orig_host}{$orig_request}")); -} else { - - header("Expires: 0"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - - /* display captive portal page */ - $htmltext = file_get_contents("{$g['varetc_path']}/captiveportal.html"); - - /* substitute variables */ - if (isset($config['captiveportal']['httpslogin'])) - $htmltext = str_replace("\$PORTAL_ACTION\$", "https://{$config['captiveportal']['httpsname']}:8001/", $htmltext); - else - $htmltext = str_replace("\$PORTAL_ACTION\$", "http://{$config['interfaces'][$config['captiveportal']['interface']]['ipaddr']}:8000/", $htmltext); +/* The $macfilter can be removed safely since we first check if the $clientmac is present, if not we fail */ +} else if ($clientmac && portal_mac_fixed($clientmac)) { + /* punch hole in ipfw for pass thru mac addresses */ + portal_allow($clientip, $clientmac, "unauthenticated"); + exit; + +} else if ($clientmac && $radmac_enable && portal_mac_radius($clientmac,$clientip)) { + /* radius functions handle everything so we exit here since we're done */ + exit; + +} else if ($_POST['accept'] && $radius_enable) { + + if ($_POST['auth_user'] && $_POST['auth_pass']) { + $auth_list = radius($_POST['auth_user'],$_POST['auth_pass'],$clientip,$clientmac,"USER LOGIN"); + + if ($auth_list['auth_val'] == 1) { + captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"ERROR",$auth_list['error']); + portal_reply_page($redirurl, "error", $auth_list['error']); + } + else if ($auth_list['auth_val'] == 3) { + captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE",$auth_list['reply_message']); + portal_reply_page($redirurl, "error", $auth_list['reply_message']); + } + } else { + captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"ERROR"); + portal_reply_page($redirurl, "error"); + } - if (preg_match("/redirurl=(.*)/", $orig_request, $matches)) - $redirurl = urldecode($matches[1]); - else - $redirurl = "http://{$orig_host}{$orig_request}"; - $htmltext = str_replace("\$PORTAL_REDIRURL\$", htmlspecialchars($redirurl), $htmltext); +} else if ($_POST['accept'] && $config['captiveportal']['auth_method'] == "local") { - echo $htmltext; + //check against local usermanager + $userdb = &$config['captiveportal']['user']; + + $loginok = false; + + //erase expired accounts + if (is_array($userdb)) { + $moddb = false; + for ($i = 0; $i < count($userdb); $i++) { + if ($userdb[$i]['expirationdate'] && (strtotime("-1 day") > strtotime($userdb[$i]['expirationdate']))) { + unset($userdb[$i]); + $moddb = true; + } + } + if ($moddb) + write_config(); + + $userdb = &$config['captiveportal']['user']; + + for ($i = 0; $i < count($userdb); $i++) { + if (($userdb[$i]['name'] == $_POST['auth_user']) && ($userdb[$i]['password'] == md5($_POST['auth_pass']))) { + $loginok = true; + break; + } + } + } + + if ($loginok){ + captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"LOGIN"); + portal_allow($clientip, $clientmac,$_POST['auth_user']); + } else { + captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE"); + portal_reply_page($redirurl, "error"); + } +} else if ($_POST['accept'] && $clientip) { + captiveportal_logportalauth("unauthenticated",$clientmac,$clientip,"ACCEPT"); + portal_allow($clientip, $clientmac, "unauthenticated"); +} else { + /* display captive portal page */ + portal_reply_page($redirurl, "login"); } - exit; -function portal_mac_fixed($clientmac) { - global $g ; - - /* open captive portal mac db */ - if (file_exists("{$g['vardb_path']}/captiveportal_mac.db")) { - $fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db","r") ; - if (!$fd) { - return FALSE; - } - while (!feof($fd)) { - $mac = trim(fgets($fd)) ; - if(strcasecmp($clientmac, $mac) == 0) { - fclose($fd) ; - return TRUE ; - } - } - fclose($fd) ; - } - return FALSE ; -} - -function portal_allow($clientip,$clientmac,$clientuser,$password = "") { +function portal_reply_page($redirurl, $type = null, $message = null) { + global $g, $config; - global $orig_host, $orig_request, $g, $config; + /* Get captive portal layout */ + if ($type == "login") + $htmltext = file_get_contents("{$g['varetc_path']}/captiveportal.html"); + else + $htmltext = file_get_contents("{$g['varetc_path']}/captiveportal-error.html"); - /* user has accepted AUP - let him in */ - portal_lock(); + /* substitute other variables */ + if (isset($config['captiveportal']['httpslogin'])) + $htmltext = str_replace("\$PORTAL_ACTION\$", "https://{$config['captiveportal']['httpsname']}:8001/", $htmltext); + else + $htmltext = str_replace("\$PORTAL_ACTION\$", "http://{$config['interfaces'][$config['captiveportal']['interface']]['ipaddr']}:8000/", $htmltext); - /* get next ipfw rule number */ - if (file_exists("{$g['vardb_path']}/captiveportal.nextrule")) - $ruleno = trim(file_get_contents("{$g['vardb_path']}/captiveportal.nextrule")); - if (!$ruleno) - $ruleno = 10000; /* first rule number */ + $htmltext = str_replace("\$PORTAL_REDIRURL\$", htmlspecialchars($redirurl), $htmltext); + $htmltext = str_replace("\$PORTAL_MESSAGE\$", htmlspecialchars($message), $htmltext); - $saved_ruleno = $ruleno; - - /* generate unique session ID */ - $tod = gettimeofday(); - $sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); - - /* add ipfw rules for layer 3 */ - exec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from $clientip to any in"); - exec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to $clientip out"); - - /* add ipfw rules for layer 2 */ - if (!isset($config['captiveportal']['nomacfilter'])) { - $l2ruleno = $ruleno + 10000; - exec("/sbin/ipfw add $l2ruleno set 3 deny all from $clientip to any not MAC any $clientmac layer2 in"); - exec("/sbin/ipfw add $l2ruleno set 3 deny all from any to $clientip not MAC $clientmac any layer2 out"); - } - - /* read in client database */ - $cpdb = array(); - - $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r"); - if ($fd) { - while (!feof($fd)) { - $line = trim(fgets($fd)) ; - if($line) { - $cpdb[] = explode(",",$line); - } - } - fclose($fd); - } - - $radiusservers = captiveportal_get_radius_servers(); - - /* find an existing entry and delete it */ - for ($i = 0; $i < count($cpdb); $i++) { - if(!strcasecmp($cpdb[$i][2],$clientip)) { - if(isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) { - RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno - $cpdb[$i][4], // username - $cpdb[$i][5], // sessionid - $cpdb[$i][0], // start time - $radiusservers[0]['ipaddr'], - $radiusservers[0]['acctport'], - $radiusservers[0]['key'], - $clientip); - } - mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000)); - unset($cpdb[$i]); - break; - } - } - - /* rewrite information to database */ - $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w"); - if ($fd) { - foreach ($cpdb as $cpent) { - fwrite($fd, join(",", $cpent) . "\n"); - } - /* write in this new entry */ - /* encode password in Base64 just in case it contains commas */ - $bpassword = base64_encode($password); - fwrite($fd, time().",{$ruleno},{$clientip},{$clientmac},{$clientuser},{$sessionid},{$bpassword}\n") ; - fclose($fd); - } - - /* write next rule number */ - $fd = @fopen("{$g['vardb_path']}/captiveportal.nextrule", "w"); - if ($fd) { - $ruleno++; - if ($ruleno > 19899) - $ruleno = 10000; /* wrap around */ - fwrite($fd, $ruleno); - fclose($fd); - } + echo $htmltext; +} - portal_unlock(); +function portal_mac_fixed($clientmac) { + global $g ; + + /* open captive portal mac db */ + if (file_exists("{$g['vardb_path']}/captiveportal_mac.db")) { + $fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db","r") ; + if (!$fd) { + return FALSE; + } + while (!feof($fd)) { + $mac = trim(fgets($fd)) ; + if(strcasecmp($clientmac, $mac) == 0) { + fclose($fd) ; + return TRUE ; + } + } + fclose($fd) ; + } + return FALSE ; +} - /* redirect user to desired destination */ - if ($config['captiveportal']['redirurl']) - $redirurl = $config['captiveportal']['redirurl']; - else if ($_POST['redirurl']) - $redirurl = $_POST['redirurl']; - else - $redirurl = "http://{$orig_host}{$orig_request}"; +function portal_mac_radius($clientmac,$clientip) { + global $config ; - if(isset($config['captiveportal']['logoutwin_enable'])) { + $radmac_secret = $config['captiveportal']['radmac_secret']; - if (isset($config['captiveportal']['httpslogin'])) - $logouturl = "https://{$config['captiveportal']['httpsname']}:8001/"; - else - $logouturl = "http://{$config['interfaces'][$config['captiveportal']['interface']]['ipaddr']}:8000/"; + /* authentication against the radius server */ + $username = mac_format($clientmac); + $auth_list = radius($username,$radmac_secret,$clientip,$clientmac,"MACHINE LOGIN"); + if ($auth_list['auth_val'] == 2) { + return TRUE; + } + return FALSE; +} - echo <<<EOD +function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $ruleno = null) { + + global $redirurl, $g, $config; + + /* See if a ruleno is passed, if not start locking the sessions because this means there isn't one atm */ + if ($ruleno == null) { + captiveportal_lock(); + $ruleno = captiveportal_get_next_ipfw_ruleno(); + } + + /* if the pool is empty, return appropriate message and exit */ + if (is_null($ruleno)) { + portal_reply_page($redirurl, "error", "System reached maximum login capacity"); + captiveportal_unlock(); + exit; + } + + // Ensure we create an array if we are missing attributes + if (!is_array($attributes)) + $attributes = array(); + + /* read in client database */ + $cpdb = captiveportal_read_db(); + + $radiusservers = captiveportal_get_radius_servers(); + + /* Find an existing session */ + for ($i = 0; $i < count($cpdb); $i++) { + /* on the same ip */ + if($cpdb[$i][2] == $clientip) { + captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - REUSING OLD SESSION"); + $sessionid = $cpdb[$i][5]; + break; + } + elseif ((isset($config['captiveportal']['noconcurrentlogins'])) && ($username != 'unauthenticated')) { + /* on the same username */ + if ($cpdb[$i][4] == $username) { + /* This user was already logged in so we disconnect the old one */ + captiveportal_disconnect($cpdb[$i],$radiusservers,13); + captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); + unset($cpdb[$i]); + break; + } + } + } + + if (!isset($sessionid)) { + + /* generate unique session ID */ + $tod = gettimeofday(); + $sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); + + /* Add rules for traffic shaping + * We don't need to add extra l3 allow rules since traffic will pass due to the following kernel option + * net.inet.ip.fw.one_pass: 1 + */ + $peruserbw = isset($config['captiveportal']['peruserbw']); + + $bw_up = isset($attributes['bw_up']) ? trim($attributes['bw_up']) : $config['captiveportal']['bwdefaultup']; + $bw_down = isset($attributes['bw_down']) ? trim($attributes['bw_down']) : $config['captiveportal']['bwdefaultdn']; + + if ($peruserbw && !empty($bw_up) && is_numeric($bw_up)) { + $bw_up_pipeno = $ruleno + 40500; + exec("/sbin/ipfw add $ruleno set 2 pipe $bw_up_pipeno ip from $clientip to any in"); + exec("/sbin/ipfw pipe $bw_up_pipeno config bw {$bw_up}Kbit/s queue 100"); + } else { + exec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from $clientip to any in"); + } + if ($peruserbw && !empty($bw_down) && is_numeric($bw_down)) { + $bw_down_pipeno = $ruleno + 45500; + exec("/sbin/ipfw add $ruleno set 2 pipe $bw_down_pipeno ip from any to $clientip out"); + exec("/sbin/ipfw pipe $bw_down_pipeno config bw {$bw_down}Kbit/s queue 100"); + } else { + exec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to $clientip out"); + } + + /* add ipfw rules for layer 2 */ + if (!isset($config['captiveportal']['nomacfilter'])) { + $l2ruleno = $ruleno + 10000; + exec("/sbin/ipfw add $l2ruleno set 3 deny all from $clientip to any not MAC any $clientmac layer2 in"); + exec("/sbin/ipfw add $l2ruleno set 3 deny all from any to $clientip not MAC $clientmac any layer2 out"); + } + + /* encode password in Base64 just in case it contains commas */ + $bpassword = base64_encode($password); + $cpdb[] = array(time(), $ruleno, $clientip, $clientmac, $username, $sessionid, $bpassword, + $attributes['session_timeout'], + $attributes['idle_timeout'], + $attributes['session_terminate_time']); + + if (isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) { + $acct_val = RADIUS_ACCOUNTING_START($ruleno, + $username, + $sessionid, + $radiusservers[0]['ipaddr'], + $radiusservers[0]['acctport'], + $radiusservers[0]['key'], + $clientip, + $clientmac); + if ($acct_val == 1) + captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED"); + } + + + } + + /* rewrite information to database */ + captiveportal_write_db($cpdb); + + /* redirect user to desired destination */ + if ($url_redirection) + $my_redirurl = $url_redirection; + else if ($config['captiveportal']['redirurl']) + $my_redirurl = $config['captiveportal']['redirurl']; + else + $my_redirurl = $redirurl; + + if(isset($config['captiveportal']['logoutwin_enable'])) { + + if (isset($config['captiveportal']['httpslogin'])) + $logouturl = "https://{$config['captiveportal']['httpsname']}:8001/"; + else + $logouturl = "http://{$config['interfaces'][$config['captiveportal']['interface']]['ipaddr']}:8000/"; + + echo <<<EOD <HTML> <HEAD><TITLE>Redirecting...</TITLE></HEAD> <BODY> <SPAN STYLE="font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;"> -<B>Redirecting to <A HREF="{$redirurl}">{$redirurl}</A>...</B> +<B>Redirecting to <A HREF="{$my_redirurl}">{$my_redirurl}</A>...</B> </SPAN> <SCRIPT LANGUAGE="JavaScript"> <!-- LogoutWin = window.open('', 'Logout', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=256,height=64'); if (LogoutWin) { - LogoutWin.document.write('<HTML>'); - LogoutWin.document.write('<HEAD><TITLE>Logout</TITLE></HEAD>') ; - LogoutWin.document.write('<BODY BGCOLOR="#435370">'); - LogoutWin.document.write('<DIV ALIGN="center" STYLE="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">') ; - LogoutWin.document.write('<B>Click the button below to disconnect</B><P>'); - LogoutWin.document.write('<FORM METHOD="POST" ACTION="{$logouturl}">'); - LogoutWin.document.write('<INPUT NAME="logout_id" TYPE="hidden" VALUE="{$sessionid}">'); - LogoutWin.document.write('<INPUT NAME="logout" TYPE="submit" VALUE="Logout">'); - LogoutWin.document.write('</FORM>'); - LogoutWin.document.write('</DIV></BODY>'); - LogoutWin.document.write('</HTML>'); - LogoutWin.document.close(); + LogoutWin.document.write('<HTML>'); + LogoutWin.document.write('<HEAD><TITLE>Logout</TITLE></HEAD>') ; + LogoutWin.document.write('<BODY BGCOLOR="#435370">'); + LogoutWin.document.write('<DIV ALIGN="center" STYLE="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">') ; + LogoutWin.document.write('<B>Click the button below to disconnect</B><P>'); + LogoutWin.document.write('<FORM METHOD="POST" ACTION="{$logouturl}">'); + LogoutWin.document.write('<INPUT NAME="logout_id" TYPE="hidden" VALUE="{$sessionid}">'); + LogoutWin.document.write('<INPUT NAME="logout" TYPE="submit" VALUE="Logout">'); + LogoutWin.document.write('</FORM>'); + LogoutWin.document.write('</DIV></BODY>'); + LogoutWin.document.write('</HTML>'); + LogoutWin.document.close(); } -document.location.href="{$redirurl}"; +document.location.href="{$my_redirurl}"; --> </SCRIPT> </BODY> </HTML> EOD; - } else { - header("Location: " . $redirurl); - } + } else { + header("Location: " . $my_redirurl); + } - return $sessionid; + captiveportal_unlock(); + return $sessionid; } -/* 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) { - $radiusservers = array(); - while (!feof($fd)) { - $line = trim(fgets($fd)); - if ($line) { - $radsrv = array(); - list($radsrv['ipaddr'],$radsrv['port'],$radsrv['acctport'],$radsrv['key']) = explode(",",$line); - $radiusservers[] = $radsrv; - } - } - fclose($fd); - - return $radiusservers; - } - } - return false; -} -/* lock captive portal information, decide that the lock file is stale after - 10 seconds */ -function portal_lock() { - - global $lockfile; - - $n = 0; - while ($n < 10) { - /* open the lock file in append mode to avoid race condition */ - if ($fd = @fopen($lockfile, "x")) { - /* succeeded */ - fclose($fd); - return; - } else { - /* file locked, wait and try again */ - sleep(1); - $n++; - } - } -} +/* remove a single client by session ID + by Dinesh Nair + */ +function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) { -/* unlock captive portal information file */ -function portal_unlock() { + global $g, $config; - global $lockfile; + captiveportal_lock(); + /* read database */ + $cpdb = captiveportal_read_db(); - if (file_exists($lockfile)) - unlink($lockfile); + $radiusservers = captiveportal_get_radius_servers(); + + /* find entry */ + for ($i = 0; $i < count($cpdb); $i++) { + if ($cpdb[$i][5] == $sessionid) { + captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause); + captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason); + unset($cpdb[$i]); + break; + } + } + + /* write database */ + captiveportal_write_db($cpdb); + + captiveportal_unlock(); } -/* remove a single client by session ID - by Dinesh Nair +/* + * This function will calculate the lowest free firewall ruleno + * within the range specified based on the actual installed rules + * */ -function disconnect_client($sessionid) { - - global $g, $config; - - portal_lock(); - - /* read database */ - $cpdb = array() ; - $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r"); - if ($fd) { - while (!feof($fd)) { - $line = trim(fgets($fd)) ; - if($line) { - $cpdb[] = explode(",",$line); - } - } - fclose($fd); - } - $radiusservers = captiveportal_get_radius_servers(); - - /* find entry */ - for ($i = 0; $i < count($cpdb); $i++) { - if ($cpdb[$i][5] == $sessionid) { - /* this client needs to be deleted - remove ipfw rules */ - if(isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) { - RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno - $cpdb[$i][4], // username - $cpdb[$i][5], // sessionid - $cpdb[$i][0], // start time - $radiusservers[0]['ipaddr'], - $radiusservers[0]['acctport'], - $radiusservers[0]['key'], - $cpdb[$i][2]); - } - mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000)); - captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"LOGOUT"); - unset($cpdb[$i]); - break; - } - } +function captiveportal_get_next_ipfw_ruleno($rulenos_start = 10000, $rulenos_range_max = 9899) { - /* rewrite information to database */ - $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w"); - if ($fd) { - foreach ($cpdb as $cpent) { - fwrite($fd, join(",", $cpent) . "\n"); - } - fclose($fd); + exec("/sbin/ipfw show", $fwrules); + foreach ($fwrules as $fwrule) { + preg_match("/^(\d+)\s+/", $fwrule, $matches); + $rulenos_used[] = $matches[1]; } + $rulenos_used = array_unique($rulenos_used); + $rulenos_range = count($rulenos_used); + if ($rulenos_range > $rulenos_range_max) { + return NULL; + } + $rulenos_pool = range($rulenos_start, ($rulenos_start + $rulenos_range)); + $rulenos_free = array_diff($rulenos_pool, $rulenos_used); + $ruleno = array_shift($rulenos_free); - portal_unlock(); -} - -/* log successful captive portal authentication to syslog */ -/* part of this code from php.net */ -function captiveportal_logportalauth($user,$mac,$ip,$status) { - define_syslog_variables(); - openlog("logportalauth", LOG_PID, LOG_LOCAL4); - // Log it - syslog(LOG_INFO, "$status: $user, $mac, $ip"); - closelog(); + return $ruleno; } -?> +?>
\ No newline at end of file |