From 9bc9188655c1482825fc858d63735032d88a542a Mon Sep 17 00:00:00 2001 From: jdegraeve Date: Thu, 20 Apr 2006 08:32:54 +0000 Subject: [PATCH] Rewrite locking implementation to remain the same locking file throughout an authentication session. This fixes issues with radius mac authentication with browsers based on Mozilla (Firefox, Flock...) who initiate more then 1 initial http session causing a double authentication of the CP and a locking stale. git-svn-id: https://svn.m0n0.ch/wall/trunk@131 e36fee2c-cc09-0410-a7cc-ebac5c6737de --- captiveportal/index.php | 111 +++++++++++++++++----------------- phpconf/inc/captiveportal.inc | 7 ++- 2 files changed, 63 insertions(+), 55 deletions(-) diff --git a/captiveportal/index.php b/captiveportal/index.php index 100d332..ea8fe01 100755 --- a/captiveportal/index.php +++ b/captiveportal/index.php @@ -231,20 +231,15 @@ function portal_mac_radius($clientmac,$clientip) { return FALSE; } -function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attributes = null) { +function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attributes = null, $ruleno = null) { global $redirurl, $g, $config; - // Ensure we create an array if we are missing attributes - if (!is_array($attributes)) - $attributes = array(); - - if ((isset($config['captiveportal']['noconcurrentlogins'])) && ($clientuser != 'unauthenticated')) - kick_concurrent_logins($clientuser); - - captiveportal_lock(); - - $ruleno = captiveportal_get_next_ipfw_ruleno(); + /* 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)) { @@ -253,6 +248,29 @@ function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attrib 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(); + + if ((isset($config['captiveportal']['noconcurrentlogins'])) && ($clientuser != 'unauthenticated')) { + /* Ensure that only one username is used by one client at a time + * by Paul Taylor + */ + if (isset($cpdb)) { + /* find duplicate entry */ + for ($i = 0; $i < count($cpdb); $i++) { + if ($cpdb[$i][4] == $user) { + /* This user was already logged in */ + $cpdb = disconnect_client($cpdb[$i][5],"CONCURRENT LOGIN - TERMINATING OLD SESSION",13,$cpdb); + } + } + } + } + + /* generate unique session ID */ $tod = gettimeofday(); $sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); @@ -268,12 +286,10 @@ function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attrib exec("/sbin/ipfw add $l2ruleno set 3 deny all from any to $clientip not MAC $clientmac any layer2 out"); } - /* read in client database */ - $cpdb = captiveportal_read_db(); - $radiusservers = captiveportal_get_radius_servers(); - /* find an existing entry and delete it */ + /* WHY DO WE DO THIS? WE ARE ALREADY KICKING OUT USERS WITH kick_concurrent_logins + 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])) { @@ -293,6 +309,7 @@ function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attrib break; } } + */ /* encode password in Base64 just in case it contains commas */ $bpassword = base64_encode($password); @@ -304,8 +321,6 @@ function portal_allow($clientip,$clientmac,$clientuser,$password = null, $attrib /* rewrite information to database */ captiveportal_write_db($cpdb); - captiveportal_unlock(); - /* redirect user to desired destination */ if ($url_redirection) $my_redirurl = $url_redirection; @@ -356,48 +371,31 @@ EOD; } else { header("Location: " . $my_redirurl); } - + + captiveportal_unlock(); return $sessionid; } -/* Ensure that only one username is used by one client at a time - * by Paul Taylor - */ -function kick_concurrent_logins($user) { - - captiveportal_lock(); - /* read database */ - $cpdb = captiveportal_read_db(); - - captiveportal_unlock(); - - if (isset($cpdb)) { - /* find duplicate entry */ - for ($i = 0; $i < count($cpdb); $i++) { - if ($cpdb[$i][4] == $user) { - /* This user was already logged in */ - disconnect_client($cpdb[$i][5],"CONCURRENT LOGIN - TERMINATING OLD SESSION",13); - } - } - } -} /* remove a single client by session ID by Dinesh Nair */ -function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) { - +function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1, $cpdb = null) { + global $g, $config; - - captiveportal_lock(); - - /* read database */ - $cpdb = captiveportal_read_db(); - + + /* Retrieve the user database if it isn't passed through */ + if (is_null($cpdb)) { + captiveportal_lock(); + /* read database */ + $cpdb = captiveportal_read_db(); + $cp_unlock = true; + } + $radiusservers = captiveportal_get_radius_servers(); - - /* find entry */ + + /* find entry */ for ($i = 0; $i < count($cpdb); $i++) { if ($cpdb[$i][5] == $sessionid) { /* this client needs to be deleted - remove ipfw rules */ @@ -419,11 +417,16 @@ function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1 break; } } - - /* rewrite information to database */ - captiveportal_write_db($cpdb); - - captiveportal_unlock(); + + if ($cp_unlock) { + /* rewrite information to database */ + captiveportal_write_db($cpdb); + + captiveportal_unlock(); + } + else { + return $cpdb; + } } diff --git a/phpconf/inc/captiveportal.inc b/phpconf/inc/captiveportal.inc index 858aee2..3b12fb6 100644 --- a/phpconf/inc/captiveportal.inc +++ b/phpconf/inc/captiveportal.inc @@ -775,6 +775,9 @@ function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) { function radius($username,$password,$clientip,$clientmac,$type) { global $g, $config; + /* Start locking from the beginning of an authentication session */ + captiveportal_lock(); + $ruleno = captiveportal_get_next_ipfw_ruleno(); /* if the pool is empty, return apprioriate message and fail authentication */ @@ -782,6 +785,7 @@ function radius($username,$password,$clientip,$clientmac,$type) { $auth_list = array(); $auth_list['auth_val'] = 1; $auth_list['error'] = "System reached maximum login capacity"; + captiveportal_unlock(); return $auth_list; } @@ -801,7 +805,8 @@ function radius($username,$password,$clientip,$clientmac,$type) { $clientmac, $username, $password, - $auth_list); + $auth_list, + $ruleno); if ($radacct_enable) { $auth_list['acct_val'] = RADIUS_ACCOUNTING_START($ruleno, -- 2.25.1