diff options
author | Seth Mos <seth.mos@dds.nl> | 2011-01-18 09:10:36 +0100 |
---|---|---|
committer | Seth Mos <seth.mos@dds.nl> | 2011-01-18 09:10:36 +0100 |
commit | 1f74cd2d101f032472a4968a10b64161652d6c1f (patch) | |
tree | d692513243aaed6003264f0b877b50cbeb69328b /etc/inc/captiveportal.inc | |
parent | c9d174dfc0a29c59ae35f43a470460f36f695b61 (diff) | |
parent | 96e889fc1e938187dd18238d80e3163e1aca3006 (diff) | |
download | pfsense-1f74cd2d101f032472a4968a10b64161652d6c1f.zip pfsense-1f74cd2d101f032472a4968a10b64161652d6c1f.tar.gz |
Merge remote branch 'upstream/master'
Conflicts:
etc/inc/interfaces.inc
etc/inc/system.inc
Diffstat (limited to 'etc/inc/captiveportal.inc')
-rw-r--r-- | etc/inc/captiveportal.inc | 274 |
1 files changed, 131 insertions, 143 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc index e36a626..84c98b2 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -206,7 +206,7 @@ EOD; function captiveportal_configure() { global $config, $g; - $captiveportallck = lock('captiveportal'); + $captiveportallck = lock('captiveportal', LOCK_EX); if (isset($config['captiveportal']['enable'])) { @@ -233,13 +233,14 @@ function captiveportal_configure() { captiveportal_init_rules(true); /* stop accounting on all clients */ - captiveportal_radius_stop_all(true); + captiveportal_radius_stop_all(); /* initialize minicron interval value */ $croninterval = $config['captiveportal']['croninterval'] ? $config['captiveportal']['croninterval'] : 60; /* double check if the $croninterval is numeric and at least 10 seconds. If not we set it to 60 to avoid problems */ - if ((!is_numeric($croninterval)) || ($croninterval < 10)) { $croninterval = 60; } + if ((!is_numeric($croninterval)) || ($croninterval < 10)) + $croninterval = 60; /* write portal page */ if ($config['captiveportal']['page']['htmltext']) @@ -414,41 +415,7 @@ EOD; "/etc/rc.prunecaptiveportal"); /* generate radius server database */ - if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) || - ($config['captiveportal']['auth_method'] == "radius"))) { - $radiusip = $config['captiveportal']['radiusip']; - $radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null; - - if ($config['captiveportal']['radiusport']) - $radiusport = $config['captiveportal']['radiusport']; - else - $radiusport = 1812; - - if ($config['captiveportal']['radiusacctport']) - $radiusacctport = $config['captiveportal']['radiusacctport']; - else - $radiusacctport = 1813; - - if ($config['captiveportal']['radiusport2']) - $radiusport2 = $config['captiveportal']['radiusport2']; - else - $radiusport2 = 1812; - - $radiuskey = $config['captiveportal']['radiuskey']; - $radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null; - - $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w"); - if (!$fd) { - printf("Error: cannot open radius DB file in captiveportal_configure().\n"); - return 1; - } else if (isset($radiusip2, $radiuskey2)) { - fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n" - . $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2); - } else { - fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey); - } - fclose($fd); - } + captiveportal_init_radius_servers(); if ($g['booting']) echo "done\n"; @@ -457,7 +424,7 @@ EOD; killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid"); killbypid("{$g['varrun_path']}/minicron.pid"); - captiveportal_radius_stop_all(true); + captiveportal_radius_stop_all(); mwexec("/sbin/sysctl net.link.ether.ipfw=0"); @@ -706,32 +673,31 @@ EOD; return $cprules; } -/* 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,password,session_timeout,idle_timeout,session_terminate_time */ - -/* (password is in Base64 and only saved when reauthentication is enabled) */ +/* 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,password,session_timeout,idle_timeout,session_terminate_time + * (password is in Base64 and only saved when reauthentication is enabled) + */ function captiveportal_prune_old() { - global $g, $config; /* check for expired entries */ - if ($config['captiveportal']['timeout']) - $timeout = $config['captiveportal']['timeout'] * 60; - else + if (empty($config['captiveportal']['timeout']) || + !is_numeric($config['captiveportal']['timeout'])) $timeout = 0; - - if ($config['captiveportal']['idletimeout']) - $idletimeout = $config['captiveportal']['idletimeout'] * 60; else + $timeout = $config['captiveportal']['timeout'] * 60; + + if (empty($config['captiveportal']['idletimeout']) || + !is_numeric($config['captiveportal']['idletimeout'])) $idletimeout = 0; + else + $idletimeout = $config['captiveportal']['idletimeout'] * 60; if (!$timeout && !$idletimeout && !isset($config['captiveportal']['reauthenticate']) && - !isset($config['captiveportal']['radiussession_timeout']) && !isset($config['voucher']['enable'])) + !isset($config['captiveportal']['radiussession_timeout']) && !isset($config['voucher']['enable'])) return; - $captiveportallck = lock('captiveportal'); - /* read database */ $cpdb = captiveportal_read_db(); @@ -766,19 +732,19 @@ function captiveportal_prune_old() { } /* check if the radius idle_timeout attribute has been set and if its set change the idletimeout to this value */ - $idletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout; + $uidletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout; /* if an idle timeout is specified, get last activity timestamp from ipfw */ - if (!$timedout && $idletimeout) { - $lastact = captiveportal_get_last_activity($cpdb[$i][2]); - /* If the user has logged on but not sent any traffic they will never be logged out. - * We "fix" this by setting lastact to the login timestamp. - */ - $lastact = $lastact ? $lastact : $cpdb[$i][0]; - if ($lastact && ((time() - $lastact) >= $idletimeout)) { - $timedout = true; - $term_cause = 4; // Idle-Timeout - $stop_time = $lastact; // Entry added to comply with WISPr - } + if (!$timedout && $uidletimeout) { + $lastact = captiveportal_get_last_activity($cpdb[$i][2]); + /* If the user has logged on but not sent any traffic they will never be logged out. + * We "fix" this by setting lastact to the login timestamp. + */ + $lastact = $lastact ? $lastact : $cpdb[$i][0]; + if ($lastact && ((time() - $lastact) >= $uidletimeout)) { + $timedout = true; + $term_cause = 4; // Idle-Timeout + $stop_time = $lastact; // Entry added to comply with WISPr + } } /* if vouchers are configured, activate session timeouts */ @@ -804,9 +770,7 @@ function captiveportal_prune_old() { } /* do periodic RADIUS reauthentication? */ - if (!$timedout && isset($config['captiveportal']['reauthenticate']) && - !empty($radiusservers)) { - + if (!$timedout && !empty($radiusservers)) { if (isset($config['captiveportal']['radacct_enable'])) { if ($config['captiveportal']['reauthenticateacct'] == "stopstart") { /* stop and restart accounting */ @@ -840,18 +804,20 @@ function captiveportal_prune_old() { } /* check this user against RADIUS again */ - $auth_list = RADIUS_AUTHENTICATION($cpdb[$i][4], // username - base64_decode($cpdb[$i][6]), // password + if (isset($config['captiveportal']['reauthenticate'])) { + $auth_list = RADIUS_AUTHENTICATION($cpdb[$i][4], // username + base64_decode($cpdb[$i][6]), // password $radiusservers, $cpdb[$i][2], // clientip $cpdb[$i][3], // clientmac $cpdb[$i][1]); // ruleno - if ($auth_list['auth_val'] == 3) { - captiveportal_disconnect($cpdb[$i], $radiusservers, 17); - captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT", $auth_list['reply_message']); - $unsetindexes[$i] = $i; - } + if ($auth_list['auth_val'] == 3) { + captiveportal_disconnect($cpdb[$i], $radiusservers, 17); + captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT", $auth_list['reply_message']); + $unsetindexes[$i] = $i; + } + } } } /* This is a kludge to overcome some php weirdness */ @@ -860,13 +826,10 @@ function captiveportal_prune_old() { /* write database */ captiveportal_write_db($cpdb); - - unlock($captiveportallck); } /* remove a single client according to the DB entry */ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) { - global $g, $config; $stop_time = (empty($stop_time)) ? time() : $stop_time; @@ -874,15 +837,15 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t /* this client needs to be deleted - remove ipfw rules */ if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) { RADIUS_ACCOUNTING_STOP($dbent[1], // ruleno - $dbent[4], // username - $dbent[5], // sessionid - $dbent[0], // start time - $radiusservers, - $dbent[2], // clientip - $dbent[3], // clientmac - $term_cause, // Acct-Terminate-Cause - false, - $stop_time); + $dbent[4], // username + $dbent[5], // sessionid + $dbent[0], // start time + $radiusservers, + $dbent[2], // clientip + $dbent[3], // clientmac + $term_cause, // Acct-Terminate-Cause + false, + $stop_time); } /* Delete client's ip entry from tables 3 and 4. */ mwexec("/sbin/ipfw table 1 delete {$dbent[2]}"); @@ -908,22 +871,17 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t /* remove a single client by ipfw rule number */ function captiveportal_disconnect_client($id,$term_cause = 1) { - global $g, $config; - $captiveportallck = lock('captiveportal'); - /* read database */ $cpdb = captiveportal_read_db(); $radiusservers = captiveportal_get_radius_servers(); /* find entry */ - $tmpindex = 0; - $cpdbcount = count($cpdb); - for ($i = 0; $i < $cpdbcount; $i++) { - if ($cpdb[$i][1] == $id) { - captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause); - captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT"); + foreach ($cpdb as $i => $cpentry) { + if ($cpentry[1] == $id) { + captiveportal_disconnect($cpentry, $radiusservers, $term_cause); + captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT"); unset($cpdb[$i]); break; } @@ -931,37 +889,29 @@ function captiveportal_disconnect_client($id,$term_cause = 1) { /* write database */ captiveportal_write_db($cpdb); - - unlock($captiveportallck); } /* send RADIUS acct stop for all current clients */ -function captiveportal_radius_stop_all($lock = false) { - global $g, $config; +function captiveportal_radius_stop_all() { + global $config; if (!isset($config['captiveportal']['radacct_enable'])) return; - if (!$lock) - $captiveportallck = lock('captiveportal'); - - $cpdb = captiveportal_read_db(); - $radiusservers = captiveportal_get_radius_servers(); if (!empty($radiusservers)) { - for ($i = 0; $i < count($cpdb); $i++) { - RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno - $cpdb[$i][4], // username - $cpdb[$i][5], // sessionid - $cpdb[$i][0], // start time - $radiusservers, - $cpdb[$i][2], // clientip - $cpdb[$i][3], // clientmac - 7); // Admin Reboot + $cpdb = captiveportal_read_db(); + foreach ($cpdb as $cpentry) { + RADIUS_ACCOUNTING_STOP($cpentry[1], // ruleno + $cpentry[4], // username + $cpentry[5], // sessionid + $cpentry[0], // start time + $radiusservers, + $cpentry[2], // clientip + $cpentry[3], // clientmac + 7); // Admin Reboot } } - if (!$lock) - unlock($captiveportallck); } function captiveportal_passthrumac_configure_entry($macent) { @@ -1123,11 +1073,51 @@ function captiveportal_get_last_activity($ip) { return 0; } +function captiveportal_init_radius_servers() { + global $config, $g; + + /* generate radius server database */ + if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) || + ($config['captiveportal']['auth_method'] == "radius"))) { + $radiusip = $config['captiveportal']['radiusip']; + $radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null; + + if ($config['captiveportal']['radiusport']) + $radiusport = $config['captiveportal']['radiusport']; + else + $radiusport = 1812; + if ($config['captiveportal']['radiusacctport']) + $radiusacctport = $config['captiveportal']['radiusacctport']; + else + $radiusacctport = 1813; + if ($config['captiveportal']['radiusport2']) + $radiusport2 = $config['captiveportal']['radiusport2']; + else + $radiusport2 = 1812; + $radiuskey = $config['captiveportal']['radiuskey']; + $radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null; + + $cprdsrvlck = lock('captiveportalradius', LOCK_EX); + $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w"); + if (!$fd) { + captiveportal_syslog("Error: cannot open radius DB file in captiveportal_configure().\n"); + unlock($cprdsrvlck); + return 1; + } else if (isset($radiusip2, $radiuskey2)) + fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n" + . $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2); + else + fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey); + fclose($fd); + unlock($cprdsrvlck); + } +} + /* read RADIUS servers into array */ function captiveportal_get_radius_servers() { - global $g; + $cprdsrvlck = lock('captiveportalradius'); if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) { $radiusservers = array(); $cpradiusdb = file("{$g['vardb_path']}/captiveportal_radius.db", @@ -1142,23 +1132,25 @@ function captiveportal_get_radius_servers() { } } + unlock($cprdsrvlck); return $radiusservers; } + unlock($cprdsrvlck); return false; } /* log successful captive portal authentication to syslog */ /* part of this code from php.net */ function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) { - $message = trim($message); // Log it if (!$message) $message = "$status: $user, $mac, $ip"; - else + else { + $message = trim($message); $message = "$status: $user, $mac, $ip, $message"; + } captiveportal_syslog($message); - closelog(); } /* log simple messages to syslog */ @@ -1174,9 +1166,6 @@ function captiveportal_syslog($message) { function radius($username,$password,$clientip,$clientmac,$type) { global $g, $config; - /* Start locking from the beginning of an authentication session */ - $captiveportallck = lock('captiveportal'); - $ruleno = captiveportal_get_next_ipfw_ruleno(); /* If the pool is empty, return appropriate message and fail authentication */ @@ -1184,16 +1173,9 @@ function radius($username,$password,$clientip,$clientmac,$type) { $auth_list = array(); $auth_list['auth_val'] = 1; $auth_list['error'] = "System reached maximum login capacity"; - unlock($captiveportallck); return $auth_list; } - /* - * Drop the lock since radius takes some time to finish. - * The implementation is reentrant so we gain speed with this. - */ - unlock($captiveportallck); - $radiusservers = captiveportal_get_radius_servers(); $auth_list = RADIUS_AUTHENTICATION($username, @@ -1203,8 +1185,6 @@ function radius($username,$password,$clientip,$clientmac,$type) { $clientmac, $ruleno); - $captiveportallck = lock('captiveportal'); - if ($auth_list['auth_val'] == 2) { captiveportal_logportalauth($username,$clientmac,$clientip,$type); $sessionid = portal_allow($clientip, @@ -1215,18 +1195,16 @@ function radius($username,$password,$clientip,$clientmac,$type) { $ruleno); } - unlock($captiveportallck); - return $auth_list; - } /* read captive portal DB into array */ function captiveportal_read_db() { - global $g; $cpdb = array(); + + $cpdblck = lock('captiveportaldb'); $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r"); if ($fd) { while (!feof($fd)) { @@ -1237,21 +1215,23 @@ function captiveportal_read_db() { } fclose($fd); } + unlock($cpdblck); return $cpdb; } /* write captive portal DB */ function captiveportal_write_db($cpdb) { - global $g; - + + $cpdblck = lock('captiveportaldb', LOCK_EX); $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w"); - if ($fd) { + if ($fd) { foreach ($cpdb as $cpent) { fwrite($fd, join(",", $cpent) . "\n"); - } + } fclose($fd); - } + } + unlock($cpdblck); } function captiveportal_write_elements() { @@ -1308,6 +1288,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang if(!isset($config['captiveportal']['enable'])) return NULL; + $cpruleslck = lock('captiveportalrules', LOCK_EX); $ruleno = 0; if (file_exists("{$g['vardb_path']}/captiveportal.rules")) { $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules")); @@ -1334,6 +1315,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang $ruleno = 2; } file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules)); + unlock($cpruleslck); return $ruleno; } @@ -1343,6 +1325,7 @@ function captiveportal_free_ipfw_ruleno($ruleno, $usedbw = false) { if(!isset($config['captiveportal']['enable'])) return NULL; + $cpruleslck = lock('captiveportalrules', LOCK_EX); if (file_exists("{$g['vardb_path']}/captiveportal.rules")) { $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules")); $rules[$ruleno] = false; @@ -1350,6 +1333,7 @@ function captiveportal_free_ipfw_ruleno($ruleno, $usedbw = false) { $rules[++$ruleno] = false; file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules)); } + unlock($cpruleslck); } function captiveportal_get_ipfw_passthru_ruleno($value) { @@ -1358,13 +1342,17 @@ function captiveportal_get_ipfw_passthru_ruleno($value) { if(!isset($config['captiveportal']['enable'])) return NULL; + $cpruleslck = lock('captiveportalrules', LOCK_EX); if (file_exists("{$g['vardb_path']}/captiveportal.rules")) { $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules")); $ruleno = intval(`/sbin/ipfw show | /usr/bin/grep {$value} | /usr/bin/grep -v grep | /usr/bin/cut -d " " -f 1 | /usr/bin/head -n 1`); - if ($rules[$ruleno]) + if ($rules[$ruleno]) { + unlock($cpruleslck); return $ruleno; + } } + unlock($cpruleslck); return NULL; } |