index.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
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");
+require_once("radius_authentication.inc");
+require_once("radius_accounting.inc");
header("Expires: 0");
header("Cache-Control: no-store, no-cache, must-revalidate");
$orig_host = $_ENV['HTTP_HOST'];
$orig_request = $_ENV['CAPTIVE_REQPATH'];
-$lockfile = "{$g['varrun_path']}/captiveportal.lock";
$clientip = $_ENV['REMOTE_ADDR'];
if (!$clientip) {
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}/?redirurl=" . urlencode("http://{$orig_host}{$orig_request}"));
+ else
+ header("Location: http://{$ourhostname}/?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']);
+
+if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
+ $radius_enable = TRUE;
+ if ($radius_enable && $macfilter && isset($config['captiveportal']['radmac_enable']))
+ $radmac_enable = TRUE;
+}
+
/* find MAC address for client */
$clientmac = arp_get_mac_by_ip($clientip);
-if (!$clientmac && !isset($config['captiveportal']['nomacfilter'])) {
+if (!$clientmac && $macfilter) {
/* unable to find MAC address - shouldn't happen! - bail out */
+ captiveportal_logportalauth("unauthenticated","noclientmac",$clientip,"ERROR");
exit;
}
-if ($clientmac && portal_mac_fixed($clientmac)) {
+if ($_POST['logout_id']) {
+ disconnect_client($_POST['logout_id']);
+ echo <<<EOD
+<HTML>
+<HEAD><TITLE>Disconnecting...</TITLE></HEAD>
+<BODY BGCOLOR="#435370">
+<SPAN STYLE="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">
+<B>You've been disconnected.</B>
+</SPAN>
+<SCRIPT LANGUAGE="JavaScript">
+<!--
+setTimeout('window.close();',5000) ;
+-->
+</SCRIPT>
+</BODY>
+</HTML>
+
+EOD;
+} else if ($clientmac && $macfilter && portal_mac_fixed($clientmac)) {
/* punch hole in ipfw for pass thru mac addresses */
portal_allow($clientip, $clientmac, "unauthenticated");
+ exit;
-} else if ($_POST['accept'] && file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
+} 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) {
- /* 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");
+ $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 {
- readfile("{$g['varetc_path']}/captiveportal-error.html");
+ captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"ERROR");
+ portal_reply_page($redirurl, "error");
}
} else if ($_POST['accept'] && $config['captiveportal']['auth_method'] == "local") {
if ($loginok){
captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"LOGIN");
- portal_allow($clientip, $clientmac,$_POST['auth_user'],0,0);
+ portal_allow($clientip, $clientmac,$_POST['auth_user']);
} else {
captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE");
- readfile("{$g['varetc_path']}/captiveportal-error.html");
+ portal_reply_page($redirurl, "error");
}
} else if ($_POST['accept'] && $clientip) {
portal_allow($clientip, $clientmac, "unauthenticated");
-} else if ($_POST['logout_id']) {
- disconnect_client($_POST['logout_id']);
- echo <<<EOD
-<HTML>
-<HEAD><TITLE>Disconnecting...</TITLE></HEAD>
-<BODY BGCOLOR="#435370">
-<SPAN STYLE="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">
-<B>You've been disconnected.</B>
-</SPAN>
-<SCRIPT LANGUAGE="JavaScript">
-<!--
-setTimeout('window.close();',5000) ;
--->
-</SCRIPT>
-</BODY>
-</HTML>
-
-EOD;
-} else if (($_ENV['SERVER_PORT'] != 8001) && isset($config['captiveportal']['httpslogin'])) {
- /* redirect to HTTPS login page */
- header("Location: https://{$config['captiveportal']['httpsname']}:8001/?redirurl=" . urlencode("http://{$orig_host}{$orig_request}"));
} else {
/* display captive portal page */
- $htmltext = file_get_contents("{$g['varetc_path']}/captiveportal.html");
-
- /* substitute variables */
+ portal_reply_page($redirurl, "login");
+}
+
+exit;
+
+function portal_reply_page($redirurl, $type = null, $message = null) {
+ global $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");
+
+ /* 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);
-
- 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);
-
+ $htmltext = str_replace("\$PORTAL_MESSAGE\$", htmlspecialchars($message), $htmltext);
+
echo $htmltext;
}
-exit;
-
function portal_mac_fixed($clientmac) {
global $g ;
return FALSE ;
}
-function portal_allow($clientip,$clientmac,$clientuser,$password = "") {
+function portal_mac_radius($clientmac,$clientip) {
+ global $config ;
- global $orig_host, $orig_request, $g, $config;
+ $radmac_secret = $config['captiveportal']['radmac_secret'];
- /* user has accepted AUP - let him in */
- portal_lock();
-
- /* 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 */
+ /* authentication against the radius server */
+ $auth_list = radius($clientmac,$radmac_secret,$clientip,$clientmac,"MACHINE LOGIN");
+ if ($auth_list['auth_val'] == 2) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+function portal_allow($clientip,$clientmac,$clientuser,$password = null, $session_timeout = null, $idle_timeout = null, $url_redirection = null, $session_terminate_time = null) {
+
+ global $redirurl, $g, $config;
+
+ if ((isset($config['captiveportal']['noconcurrentlogins'])) && ($clientuser != 'unauthenticated'))
+ kick_concurrent_logins($clientuser);
- $saved_ruleno = $ruleno;
+ captiveportal_lock();
+ $ruleno = get_next_ipfw_ruleno();
+
/* generate unique session ID */
$tod = gettimeofday();
$sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16);
}
/* 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);
- }
+ $cpdb = captiveportal_read_db();
$radiusservers = captiveportal_get_radius_servers();
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $clientip);
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3], // clientmac
+ 13); // Port Preempted
}
mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000));
unset($cpdb[$i]);
}
}
+ /* encode password in Base64 just in case it contains commas */
+ $bpassword = base64_encode($password);
+ $cpdb[] = array(time(), $ruleno, $clientip, $clientmac, $clientuser, $sessionid, $bpassword, $session_timeout, $idle_timeout, $session_terminate_time);
+
/* 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);
- }
-
+ captiveportal_write_db($cpdb);
+
/* write next rule number */
$fd = @fopen("{$g['vardb_path']}/captiveportal.nextrule", "w");
if ($fd) {
fclose($fd);
}
- portal_unlock();
+ captiveportal_unlock();
/* redirect user to desired destination */
- if ($config['captiveportal']['redirurl'])
- $redirurl = $config['captiveportal']['redirurl'];
- else if ($_POST['redirurl'])
- $redirurl = $_POST['redirurl'];
+ if ($url_redirection)
+ $my_redirurl = $url_redirection;
+ else if ($config['captiveportal']['redirurl'])
+ $my_redirurl = $config['captiveportal']['redirurl'];
else
- $redirurl = "http://{$orig_host}{$orig_request}";
+ $my_redirurl = $redirurl;
if(isset($config['captiveportal']['logoutwin_enable'])) {
<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.document.close();
}
-document.location.href="{$redirurl}";
+document.location.href="{$my_redirurl}";
-->
</SCRIPT>
</BODY>
EOD;
} else {
- header("Location: " . $redirurl);
+ header("Location: " . $my_redirurl);
}
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;
-}
+/* Ensure that only one username is used by one client at a time
+ * by Paul Taylor
+ */
+function kick_concurrent_logins($user) {
-/* 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++;
+ 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);
+ }
}
}
}
-/* unlock captive portal information file */
-function portal_unlock() {
-
- global $lockfile;
-
- if (file_exists($lockfile))
- unlink($lockfile);
-}
-
/* remove a single client by session ID
by Dinesh Nair
*/
-function disconnect_client($sessionid) {
+function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) {
global $g, $config;
- portal_lock();
+ captiveportal_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);
- }
+ $cpdb = captiveportal_read_db();
$radiusservers = captiveportal_get_radius_servers();
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $cpdb[$i][2]);
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3], // clientmac
+ $term_cause);
}
mwexec("/sbin/ipfw delete " . $cpdb[$i][1] . " " . ($cpdb[$i][1]+10000));
- captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"LOGOUT");
+ captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
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");
- }
- fclose($fd);
- }
+ captiveportal_write_db($cpdb);
- portal_unlock();
+ captiveportal_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();
+function get_next_ipfw_ruleno() {
+
+ global $g;
+
+ /* 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 */
+
+ return $ruleno;
}
?>
// - RFC2869 (Radius Extensions)
// * now sends Acct-Input-Gigawords
// * now sends Acct-Output-Gigawords
+ // * full implementation of nas-ip/nas_mac and called/calling-station ids
*/
-function RADIUS_ACCOUNTING_START($username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip) {
- $sharedsecret=$radiuskey ;
+function RADIUS_ACCOUNTING_START($ruleno,$username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip,$clientmac) {
# $debug = 1 ;
+ global $config;
exec("/bin/hostname", $nasHostname) ;
if(!$nasHostname[0])
/* set 5 second timeout on socket i/o */
stream_set_timeout($fd, 5) ;
- $nas_ip_address = get_nas_ip();
+ $nas_mac = get_interface_mac($config['interfaces']['wan']['if']); // This function is defined in radius_authentication.inc
+ $nas_port = $ruleno - 10000;
+ $ip_exp=explode(".",$clientip);
+ $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null;
+
+ switch($radiusvendor) {
- if(!isset($clientip)) {
- //if there's no client ip, we'll need to use the NAS ip
- $clientip=$nas_ip_address;
+ case 'cisco':
+ $calledstationid = $clientmac;
+ $callingstationid = $clientip;
+ break;
+
+ default:
+ $calledstationid = $nas_mac;
+ $callingstationid = $clientmac;
}
- $ip_exp=explode(".",$clientip);
if ($debug)
echo "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\n";
6+ // Acct Status Type
6+ // Acct RADIUS Authenticated
2+strlen($sessionid)+ // Acct SessionID
+ 2+strlen($calledstationid)+ //Called-Station-ID
+ 2+strlen($callingstationid)+ //Calling-Station-ID
6; // Framed-IP-Address
// v v v v v v v v v 1 v
// Line # 1 2 3 4 5 6 7 8 9 0 E
- $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCCCCC",
+ $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCCCCC",
4,$thisidentifier,$length/256,$length%256, // header
0,0,0,0, // authcode
6,6,0,0,0,1, // service type
1,2+strlen($username),$username, // username
32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier
- 5,6,0,0,0,0, // nasPort
+ 5,6,0,0,0,$nas_port, // nasPort
61,6,0,0,0,15, // nasPortType = Ethernet
40,6,0,0,0,1, // Acct Status Type = Start
45,6,0,0,0,1, // Acct RADIUS Authenticated
44,2+strlen($sessionid),$sessionid, // Acct Session ID
+ 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID
+ 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID
8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address
);
// v v v v v v v v v 1 v
// Line # 1 2 3 4 5 6 7 8 9 0 E
- $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCCCCC",
+ $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCCCCC",
4,$thisidentifier,$length/256,$length%256, // header
$RA, // authcode
6,6,0,0,0,1, // service type
1,2+strlen($username),$username, // username
32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier
- 5,6,0,0,0,0, // nasPort
+ 5,6,0,0,0,$nas_port, // nasPort
61,6,0,0,0,15, // nasPortType = Ethernet
40,6,0,0,0,1, // Acct Status Type = Start
45,6,0,0,0,1, // Acct RADIUS Authenticated
44,2+strlen($sessionid),$sessionid, // Acct Session ID
+ 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID
+ 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID
8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address
);
// See RFC2866 for this.
}
-function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip,$interimupdate=false, $radius_term_cause = 1) {
- $sharedsecret=$radiuskey ;
+function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip,$clientmac, $term_cause = 1, $interimupdate=false,$stop_time = null) {
# $debug = 1 ;
+ global $config;
+
+ $stop_time = (empty($stop_time)) ? time() : $stop_time;
exec("/bin/hostname", $nasHostname) ;
if(!$nasHostname[0])
/* set 5 second timeout on socket i/o */
stream_set_timeout($fd, 5) ;
- $nas_ip_address = get_nas_ip();
+ $nas_port = $ruleno - 10000;
+ $nas_mac = get_interface_mac($config['interfaces']['wan']['if']);
+ $ip_exp=explode(".",$clientip);
+ $session_time = $stop_time - $start_time;
+ $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null;
+
+ switch($radiusvendor) {
- if(!isset($clientip)) {
- //if there's no client ip, we'll need to use the NAS ip
- $clientip=$nas_ip_address;
+ case 'cisco':
+ $calledstationid = $clientmac;
+ $callingstationid = $clientip;
+ break;
+
+ default:
+ $calledstationid = $nas_mac;
+ $callingstationid = $clientmac;
}
- $ip_exp=explode(".",$clientip);
if ($debug)
echo "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\n";
6+ // output bytes
6+ // output packets
6+ // output gigawords
- 2+strlen($nas_ip_address)+ //Called-Station-ID
- 2+strlen($clientip)+ //Calling-Station-ID
-
+ 2+strlen($calledstationid)+ //Called-Station-ID
+ 2+strlen($callingstationid)+ //Calling-Station-ID
6; //Framed-IP-Address
if ($interimupdate)
6,6,0,0,0,1, // service type
1,2+strlen($username),$username, // username
32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier
- 5,6,0,0,0,0, // nasPort
+ 5,6,0,0,0,$nas_port, // nasPort
61,6,0,0,0,15, // nasPortType = Ethernet
40,6,0,0,0,$acctstatustype, // Acct Status Type
45,6,0,0,0,1, // Acct RADIUS Authenticated
44,2+strlen($sessionid),$sessionid, // Acct Session ID
- 49,6,$radius_term_cause, // Acct Terminate = User Request
- 46,6,time() - $start_time, // Session Time
+ 49,6,$term_cause, // Acct Terminate
+ 46,6,$session_time, // Session Time
42,6,$input_bytes, // Input Octets
47,6,$input_pkts, // Input Packets
52,6,$input_gigawords, // Input Gigawords
43,6,$output_bytes, // Output Octets
48,6,$output_pkts, // Output Packets
53,6,$output_gigawords, // Output Gigawords
- 30,2+strlen($nas_ip_address),$nas_ip_address, //Called-Station-ID
- 31,2+strlen($clientip),$clientip, //Calling-Station-ID
-
+ 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID
+ 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID
8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address
);
6,6,0,0,0,1, // service type
1,2+strlen($username),$username, // username
32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier
- 5,6,0,0,0,0, // nasPort
+ 5,6,0,0,0,$nas_port, // nasPort
61,6,0,0,0,15, // nasPortType = Ethernet
40,6,0,0,0,$acctstatustype, // Acct Status Type
45,6,0,0,0,1, // Acct RADIUS Authenticated
44,2+strlen($sessionid),$sessionid, // Acct Session ID
- 49,6,$radius_term_cause, // Acct Terminate = User Request
- 46,6,time() - $start_time, // Session Time
+ 49,6,$term_cause, // Acct Terminate = User Request
+ 46,6,$session_time, // Session Time
42,6,$input_bytes, // Input Octets
47,6,$input_pkts, // Input Packets
52,6,$input_gigawords, // Input Gigawords
43,6,$output_bytes, // Output Octets
48,6,$output_pkts, // Output Packets
53,6,$output_gigawords, // Output Gigawords
- 30,2+strlen($nas_ip_address),$nas_ip_address, //Called-Station-ID
- 31,2+strlen($clientip),$clientip, //Calling-Station-ID
-
+ 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID
+ 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID
8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address
);
// See RFC2866 for this.
}
-function get_nas_ip() {
- global $config;
-
- /* static WAN IP address */
- return $config['interfaces']['wan']['ipaddr'];
-}
-
function gigawords($bytes) {
/* We use BCMath functions since normal integers don't work with so large numbers */
<?php
- //
- // $Id: radius_authentication.inc,v 1.3 2002/01/23 23:21:20 mavetju Exp $
- //
- // radius authentication v1.0 by Edwin Groothuis (edwin@mavetju.org)
- //
- // If you didn't get this file via http://www.mavetju.org, please
- // check for the availability of newer versions.
- //
- // See LICENSE for distribution issues. If this file isn't in
- // the distribution, please inform me about it.
- //
- // If you want to use this script, fill in the configuration in
- // radius_authentication.conf and call the function
- // RADIUS_AUTHENTICATION() with the username and password
- // provided by the user. If it returns a 2, the authentication
- // was successfull!
-
- // If you want to use this, make sure that you have raw sockets
- // enabled during compile-time: "./configure --enable-sockets".
-
- // This version has been modified by Dinesh Nair <dinesh@alphaque.com>
- // for use in the m0n0wall distribution http://m0n0.ch/wall/
- //
- // Changes include moving from raw sockets to fsockopen
- // and the removal of dependency on external conf file
- // An existing bug which resulted in a malformed RADIUS packet
- // was also fixed and patches submitted to Edwin. This bug would
- // have caused authentication to fail on every access.
-
-function RADIUS_AUTHENTICATION($username,$password,$radiusip,$radiusport,$radiuskey) {
- $sharedsecret=$radiuskey ;
- # $debug = 1 ;
-
- exec("/bin/hostname", $nasHostname) ;
- if(!$nasHostname[0])
- $nasHostname[0] = "m0n0wall" ;
-
- $fd = @fsockopen("udp://$radiusip",$radiusport,$errno,$errstr,3) ;
- if(!$fd)
- return 1 ; /* error return */
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+/*
+Copyright (c) 2005, Jonathan De Graeve <jonathan.de.graeve@imelda.be>
+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.
+3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+
+This code cannot simply be copied and put under the GNU Public License or
+any other GPL-like (LGPL, GPL2) License.
+
+ This code is made possible thx to samples made by Michael Bretterklieber <michael@bretterklieber.com>
+ author of the PHP PECL Radius package
+
+ Changes made include:
+ * Support for multiple radius servers
+ * Error Message and Reply Message
+ * Called-Station-Id,Calling-Station-Id,NAS-Port,NAS-Port-Type
+ * Different Authentication Methods
+
+*/
+
+require_once("radius.inc");
+
+/*
+RADIUS AUTHENTICATION
+---------------------
+*/
+
+function RADIUS_AUTHENTICATION($username,$password,$radiusservers,$clientip,$clientmac,$ruleno) {
+ global $config;
+
+ /* Initialisation of variables - Constructor */
+ $retvalue = array();
+ $retvalue['error'] = $retvalue['reply_message'] = $retvalue['url_redirection'] = $retvalue['session_timeout'] = $retvalue['idle_timeout'] = $retvalue['session_terminate_time'] = null;
+ $nas_mac = get_interface_mac($config['interfaces']['wan']['if']);
+ $nas_port = $ruleno - 10000;
+ $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null;
+
+ exec("/bin/hostname", $nasHostname) ;
+ if(!$nasHostname[0])
+ $nasHostname[0] = "m0n0wall" ;
+
+$rauth = new Auth_RADIUS_PAP($username, $password);
+
+/*
+Add support for more then one radiusserver.
+At most 10 servers may be specified.
+When multiple servers are given, they are tried in round-robin fashion until a valid response is received
+*/
+
+foreach ($radiusservers as $radsrv) {
+
+ // Add a new server to our instance
+ $rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['key']);
- /* set 5 second timeout on socket i/o */
- stream_set_timeout($fd, 5) ;
-
- if ($debug)
- echo "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\n";
-
- $RA=pack("CCCCCCCCCCCCCCCC", // auth code
- 1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
- 1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
- 1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
- 1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255);
-
- $encryptedpassword=Encrypt($password,$sharedsecret,$RA);
-
- $length=4+ // header
- 16+ // auth code
- 6+ // service type
- 2+strlen($username)+ // username
- 2+strlen($encryptedpassword)+ // userpassword
- 2+strlen($nasHostname[0])+ // nasIdentifier
- 6+ // nasPort
- 6; // nasPortType
-
- $thisidentifier=rand()%256;
- // v v v v v v v v v
- // Line # 1 2 3 4 5 6 7 8 E
- $data=pack("CCCCa*CCCCCCCCa*CCa*CCa*CCCCCCCCCCCC",
- 1,$thisidentifier,$length/256,$length%256, // header
- $RA, // authcode
- 6,6,0,0,0,1, // service type
- 1,2+strlen($username),$username, // username
- 2,2+strlen($encryptedpassword),$encryptedpassword, // userpassword
- 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier
- 5,6,0,0,0,0, // nasPort
- 61,6,0,0,0,15 // nasPortType = Ethernet
- );
-
- if($debug) {
- echo "username is $username with len " . strlen($username) ."\n" ;
- echo "encryptedpassword is $encryptedpassword with len " . strlen($encryptedpassword) ."\n" ;
- echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ;
- }
-
- $ret = fwrite($fd,$data) ;
- if( !$ret || ($ret != $length) )
- return 1; /* error return */
-
- if ($debug)
- echo "<br>writing $length bytes<hr>\n";
-
- $readdata = fgets($fd,2) ; /* read 1 byte */
- $status = socket_get_status($fd) ;
- fclose($fd) ;
-
- if($status['timed_out'])
- $retvalue = 1 ;
- else
- $retvalue = ord($readdata) ;
-
- return $retvalue ;
+}
+
+$rauth->username = $username;
+$rauth->password = $password;
+
+
+if (!$rauth->start()) {
+ $retvalue['auth_val'] = 1;
+ $retvalue['error'] = $rauth->getError();
+ if ($debug)
+ printf("Radius start: %s<br>\n", $retvalue['error']);
+}
+else {
+
+ // 1 -> Access-Request => We will use this value as an error indicator since we can't get a 1 back from the radius
// 2 -> Access-Accept
// 3 -> Access-Reject
// See RFC2865 for this.
-}
-function Encrypt($password,$key,$RA) {
- global $debug;
+ /*
+ * We put our attributes in here
+ */
- $keyRA=$key.$RA;
+ switch($radiusvendor) {
- if ($debug)
- echo "<br>key: $key<br>password: $password<hr>\n";
+ case 'cisco':
+ $rauth->putAttribute(RADIUS_CALLED_STATION_ID, $clientmac);
+ $rauth->putAttribute(RADIUS_CALLING_STATION_ID, $clientip);
+ break;
- $md5checksum=md5($keyRA);
- $output="";
+ default:
+ $rauth->putAttribute(RADIUS_CALLED_STATION_ID, $nas_mac);
+ $rauth->putAttribute(RADIUS_CALLING_STATION_ID, $clientmac);
+ }
+
+ // Default attributes
+ $rauth->putAttribute(RADIUS_NAS_PORT, $nas_port);
+
+ // Send request
+
+ $result = $rauth->send();
+ if (PEAR::isError($result)) {
+ $retvalue['auth_val'] = 1;
+ $retvalue['error'] = $result->getMessage();
+ if ($debug)
+ printf("Radius send failed: %s<br>\n", $retvalue['error']);
+ } else if ($result === true) {
+ $retvalue['auth_val'] = 2;
+ if ($debug)
+ printf("Radius Auth succeeded<br>\n");
+ } else {
+ $retvalue['auth_val'] = 3;
+ if ($debug)
+ printf("Radius Auth rejected<br>\n");
+ }
- for ($i=0;$i<=15;$i++) {
- if (2*$i>strlen($md5checksum)) $m=0; else $m=hexdec(substr($md5checksum,2*$i,2));
- if ($i>strlen($keyRA)) $k=0; else $k=ord(substr($keyRA,$i,1));
- if ($i>strlen($password)) $p=0; else $p=ord(substr($password,$i,1));
- $c=$m^$p;
- $output.=chr($c);
+ // Get attributes, even if auth failed.
+ // We will push the results in the retvalue array
+ if (!$rauth->getAttributes()) {
+ $retvalue['error'] = $rauth->getError();
+ if ($debug)
+ printf("Radius getAttributes: No attributes<br>\n", $retvalue['error']);
+ } else {
+ $retvalue = array_merge($retvalue,$rauth->listAttributes());
+ if ($debug) {
+ if (!$rauth->listAttributes())
+ printf("No Attributes<br>\n");
+ else
+ print_r($rauth->listAttributes());
+ }
+ // We convert the session_terminate_time to unixtimestamp if its set before returning the whole array to our caller
+ if (!empty($retvalue['session_terminate_time'])) {
+ $stt = &$retvalue['session_terminate_time'];
+ $stt = strtotime(preg_replace("/\+(\d+):(\d+)$/", " +\${1}\${2}", preg_replace("/(\d+)T(\d+)/", "\${1} \${2}",$stt)));
+ }
}
- return $output;
+ }
+
+ // close OO RADIUS_AUTHENTICATION
+ $rauth->close();
+
+ return $retvalue;
+
}
+
?>
/sbin/umount -f /cf
/sbin/mount -r /cf
- echo "Done - rebooting system..."
- /sbin/reboot
+ echo "Done - rebooting system..."
+
+ # unset CGI environment variables so as not to confuse PHP
+ unset CONTENT_TYPE GATEWAY_INTERFACE REMOTE_USER REMOTE_ADDR AUTH_TYPE
+ unset HTTP_USER_AGENT CONTENT_LENGTH SCRIPT_FILENAME HTTP_HOST
+ unset SERVER_SOFTWARE HTTP_REFERER SERVER_PROTOCOL REQUEST_METHOD
+ unset SERVER_PORT SCRIPT_NAME SERVER_NAME
+
+ /etc/rc.cleanreboot
;;
esac
<!-- <earlyshellcmd></earlyshellcmd> -->
<!-- <harddiskstandby></harddiskstandby> -->
<!-- <polling/> -->
+ <!-- <notes></notes> -->
</system>
<interfaces>
<lan>
<syslocation></syslocation>
<syscontact></syscontact>
<rocommunity>public</rocommunity>
+ <!-- <bindlan/> -->
</snmpd>
<diag>
<ipv6nat>
<redirurl></redirurl>
<auth_method>none|radius|local</auth_method>
<radiusip></radiusip>
+ <radiusip2></radiusip2>
<radiusport></radiusport>
+ <radiusport2></radiusport2>
<radiuskey></radiuskey>
+ <radiuskey2></radiuskey2>
+ <radiussession_timeout></radiussession_timeout>
<nomacfilter/>
<reauthenticate/>
<reauthenticateacct>stopstart|interimupdate</reauthenticateacct>
+ <maxproc></maxproc>
+ <maxprocperip></maxprocperip>
+ <croninterval></croninterval>
<user>
<name></name>
<password></password>
<expirationdate></expirationdate>
</user>
+
+ <element>
+ <name></name>
+ <size></size>
+ <content></content>
+ </element>
</captiveportal>
-->
<nat>
captiveportal.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
/* include all configuration functions */
require_once("functions.inc");
require_once("radius_authentication.inc");
-require_once("radius_accounting.inc") ;
+require_once("radius_accounting.inc");
+
+$lockfile = "{$g['varrun_path']}/captiveportal.lock";
function captiveportal_configure() {
global $config, $g;
/* stop accounting on all clients */
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; }
+
/* remove old information */
unlink_if_exists("{$g['vardb_path']}/captiveportal.nextrule");
unlink_if_exists("{$g['vardb_path']}/captiveportal.db");
fwrite($fd, $errtext);
fclose($fd);
}
+
+ /* write elements */
+ captiveportal_write_elements();
/* load rules */
mwexec("/sbin/ipfw -f delete set 1");
chdir($g['captiveportal_path']);
+ if ($config['captiveportal']['maxproc'])
+ $maxproc = $config['captiveportal']['maxproc'];
+ else
+ $maxproc = 16;
+
+ if (isset($config['captiveportal']['maxprocperip']) &&
+ $config['captiveportal']['maxprocperip'] !== "") {
+ if ($config['captiveportal']['maxprocperip'] == 0)
+ $maxperiparg = "";
+ else
+ $maxperiparg = "-maxperip " . $config['captiveportal']['maxprocperip'];
+ } else
+ $maxperiparg = "-maxperip 4";
+
/* 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");
+ $cpip = $config['interfaces'][$config['captiveportal']['interface']]['ipaddr'];
+ mwexec("/usr/local/sbin/mini_httpd -a -M 0 -u root -maxproc $maxproc $maxperiparg" .
+ " -p 8000 -i {$g['varrun_path']}/mini_httpd.cp.pid" .
+ " -cpelement {$g['captiveportal_element_path']} $cpip:8000");
/* fire up another one for HTTPS if requested */
if (isset($config['captiveportal']['httpslogin']) &&
fwrite($fd, "\n");
fwrite($fd, $key);
fclose($fd);
-
+
+ $httpsname = ($config['captiveportal']['httpsname']) ? $config['captiveportal']['httpsname'] : $cpip;
+
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");
+ " -u root -maxproc $maxproc $maxperiparg -p 8001" .
+ " -i {$g['varrun_path']}/mini_httpd.cps.pid" .
+ " -cpelement {$g['captiveportal_element_path']} $httpsname:8001");
}
- /* start pruning process (interval = 60 seconds) */
- mwexec("/usr/local/bin/minicron 60 {$g['varrun_path']}/minicron.pid " .
+ /* start pruning process (interval defaults to 60 seconds) */
+ mwexec("/usr/local/bin/minicron $croninterval {$g['varrun_path']}/minicron.pid " .
"/etc/rc.prunecaptiveportal");
/* generate passthru mac 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
$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);
}
}
/* 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 */
+/* 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;
for ($i = 0; $i < count($cpdb); $i++) {
$timedout = false;
+ $term_cause = 1;
/* hard timeout? */
if ($timeout) {
- if ((time() - $cpdb[$i][0]) >= $timeout)
- $timedout = true;
+ if ((time() - $cpdb[$i][0]) >= $timeout) {
+ $timedout = true;
+ $term_cause = 5; // Session-Timeout
+ }
+ }
+
+ /* Session-Terminate-Time */
+ if (!$timedout && !empty($cpdb[$i][9])) {
+ if (time() >= $cpdb[$i][9]) {
+ $timedout = true;
+ $term_cause = 5; // Session-Timeout
+ }
}
+ /* 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;
/* 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))
+ if ($lastact && ((time() - $lastact) >= $idletimeout)) {
$timedout = true;
+ $term_cause = 4; // Idle-Timeout
+ $stop_time = $lastact; // Entry added to comply with WISPr
+ }
+ }
+
+ /* if radius session_timeout is enabled and the session_timeout is not null, then check if the user should be logged out */
+ if (!$timedout && isset($config['captiveportal']['radiussession_timeout']) && !empty($cpdb[$i][7])) {
+ if (time() >= ($cpdb[$i][0] + $cpdb[$i][7])) {
+ $timedout = true;
+ $term_cause = 5; // Session-Timeout
+ }
}
if ($timedout) {
- captiveportal_disconnect($cpdb[$i], $radiusservers);
+ captiveportal_disconnect($cpdb[$i], $radiusservers,$term_cause,$stop_time);
captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "TIMEOUT");
unset($cpdb[$i]);
}
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $cpdb[$i][2]); //clientip
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3], // clientmac
+ 10); // NAS Request
exec("/sbin/ipfw zero {$cpdb[$i][1]}");
- RADIUS_ACCOUNTING_START($cpdb[$i][4],
- $cpdb[$i][5],
+ RADIUS_ACCOUNTING_START($cpdb[$i][1], // ruleno
+ $cpdb[$i][4], // username
+ $cpdb[$i][5], // sessionid
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $cpdb[$i][2]);
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3]); // clientmac
} else if ($config['captiveportal']['reauthenticateacct'] == "interimupdate") {
RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
$cpdb[$i][4], // username
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $cpdb[$i][2], //clientip
- true);
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3], // clientmac
+ 10, // NAS Request
+ true); // Interim Updates
}
}
/* check this user against RADIUS again */
- $auth_val = RADIUS_AUTHENTICATION($cpdb[$i][4],
- base64_decode($cpdb[$i][6]),
- $radiusservers[0]['ipaddr'],
- $radiusservers[0]['port'],
- $radiusservers[0]['key']);
+ $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_val == 3) {
- captiveportal_disconnect($cpdb[$i], $radiusservers);
- captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT");
+ 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']);
unset($cpdb[$i]);
}
}
}
/* remove a single client according to the DB entry */
-function captiveportal_disconnect($dbent, $radiusservers) {
+function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) {
global $g, $config;
+
+ $stop_time = (empty($stop_time)) ? time() : $stop_time;
/* this client needs to be deleted - remove ipfw rules */
if (isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) {
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $dbent[2]); //clientip
+ $dbent[2], // clientip
+ $dbent[3], // clientmac
+ $term_cause, // Acct-Terminate-Cause
+ false,
+ $stop_time);
}
mwexec("/sbin/ipfw delete " . $dbent[1] . " " . ($dbent[1]+10000));
}
/* remove a single client by ipfw rule number */
-function captiveportal_disconnect_client($id) {
+function captiveportal_disconnect_client($id,$term_cause = 1) {
global $g, $config;
/* find entry */
for ($i = 0; $i < count($cpdb); $i++) {
if ($cpdb[$i][1] == $id) {
- captiveportal_disconnect($cpdb[$i], $radiusservers);
+ captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause);
captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT");
unset($cpdb[$i]);
break;
/* send RADIUS acct stop for all current clients */
function captiveportal_radius_stop_all() {
global $g, $config;
+
+ if (!isset($config['captiveportal']['radacct_enable']))
+ return;
captiveportal_lock();
$cpdb = captiveportal_read_db();
$radiusservers[0]['ipaddr'],
$radiusservers[0]['acctport'],
$radiusservers[0]['key'],
- $cpdb[$i][2]); //clientip
+ $cpdb[$i][2], // clientip
+ $cpdb[$i][3], // clientmac
+ 7); // Admin Reboot
}
}
captiveportal_unlock();
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) {
- while (!feof($fd)) {
- $line = trim(fgets($fd));
- if ($line) {
- $cpdb[] = explode(",", $line);
- }
- }
- fclose($fd);
- }
- return $cpdb;
-}
-
-/* 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) {
- fwrite($fd, join(",", $cpent) . "\n");
- }
- fclose($fd);
- }
-}
-
/* 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;
+
+ 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 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 */
- if ($fd = @fopen($lockfile, "x")) {
- /* succeeded */
- fclose($fd);
- return;
- } else {
- /* file locked, wait and try again */
- sleep(1);
- $n++;
- }
- }
+
+ 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++;
+ }
+ }
}
-/* unlock configuration file */
+/* unlock captive portal information file */
function captiveportal_unlock() {
-
- global $g;
-
- $lockfile = "{$g['varrun_path']}/captiveportal.lock";
-
- if (file_exists($lockfile))
- unlink($lockfile);
+
+ global $lockfile;
+
+ if (file_exists($lockfile))
+ unlink($lockfile);
}
/* log successful captive portal authentication to syslog */
/* part of this code from php.net */
-function captiveportal_logportalauth($user,$mac,$ip,$status) {
+function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) {
define_syslog_variables();
+ $message = trim($message);
openlog("logportalauth", LOG_PID, LOG_LOCAL4);
// Log it
+ if (!$message)
syslog(LOG_INFO, "$status: $user, $mac, $ip");
+ else
+ syslog(LOG_INFO, "$status: $user, $mac, $ip, $message");
closelog();
}
+function radius($username,$password,$clientip,$clientmac,$type) {
+ global $g, $config;
+
+ $next_ruleno = get_next_ipfw_ruleno();
+ $radiusservers = captiveportal_get_radius_servers();
+ $radacct_enable = isset($config['captiveportal']['radacct_enable']);
+
+ $auth_list = RADIUS_AUTHENTICATION($username,
+ $password,
+ $radiusservers,
+ $clientip,
+ $clientmac,
+ $next_ruleno);
+
+ if ($auth_list['auth_val'] == 2) {
+ captiveportal_logportalauth($username,$clientmac,$clientip,$type);
+ $sessionid = portal_allow($clientip,
+ $clientmac,
+ $username,
+ $password,
+ $auth_list['session_timeout'],
+ $auth_list['idle_timeout'],
+ $auth_list['url_redirection'],
+ $auth_list['session_terminate_time']);
+
+ if ($radacct_enable) {
+ $auth_list['acct_val'] = RADIUS_ACCOUNTING_START($next_ruleno,
+ $username,
+ $sessionid,
+ $radiusservers[0]['ipaddr'],
+ $radiusservers[0]['acctport'],
+ $radiusservers[0]['key'],
+ $clientip,
+ $clientmac);
+ if ($auth_list['acct_val'] == 1)
+ captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED");
+ }
+ }
+
+ return $auth_list;
+
+}
+
+/* read captive portal DB into array */
+function captiveportal_read_db() {
+
+ global $g;
+
+ $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);
+ }
+ return $cpdb;
+}
+
+/* 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) {
+ fwrite($fd, join(",", $cpent) . "\n");
+ }
+ fclose($fd);
+ }
+}
+
+function captiveportal_write_elements() {
+ global $g, $config;
+
+ /* delete any existing elements */
+ if (is_dir($g['captiveportal_element_path'])) {
+ $dh = opendir($g['captiveportal_element_path']);
+ while (($file = readdir($dh)) !== false) {
+ if ($file != "." && $file != "..")
+ unlink($g['captiveportal_element_path'] . "/" . $file);
+ }
+ closedir($dh);
+ } else {
+ mkdir($g['captiveportal_element_path']);
+ }
+
+ if (is_array($config['captiveportal']['element'])) {
+
+ foreach ($config['captiveportal']['element'] as $data) {
+ $fd = @fopen($g['captiveportal_element_path'] . '/' . $data['name'], "wb");
+ if (!$fd) {
+ printf("Error: cannot open '{$data['name']}' in captiveportal_write_elements().\n");
+ return 1;
+ }
+ $decoded = base64_decode($data['content']);
+ fwrite($fd,$decoded);
+ fclose($fd);
+ }
+ }
+
+ return 0;
+}
+
?>
config.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
if (!file_exists($conffile))
return 1;
+ if (!config_validate($conffile))
+ return 1;
+
config_lock();
conf_mount_rw();
return 0;
}
+function config_validate($conffile) {
+
+ global $g, $xmlerr;
+
+ $xml_parser = xml_parser_create();
+
+ if (!($fp = fopen($conffile, "r"))) {
+ $xmlerr = "XML error: unable to open file";
+ return false;
+ }
+
+ while ($data = fread($fp, 4096)) {
+ if (!xml_parse($xml_parser, $data, feof($fp))) {
+ $xmlerr = sprintf("%s at line %d",
+ xml_error_string(xml_get_error_code($xml_parser)),
+ xml_get_current_line_number($xml_parser));
+ return false;
+ }
+ }
+ xml_parser_free($xml_parser);
+
+ fclose($fp);
+
+ return true;
+}
+
/* lock configuration file, decide that the lock file is stale after
10 seconds */
function config_lock() {
filter.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
functions.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
*/
/* include all configuration functions */
+require_once("globals.inc");
+require_once("config.inc");
require_once("system.inc");
require_once("interfaces.inc");
require_once("services.inc");
require_once("shaper.inc");
require_once("vpn.inc");
require_once("captiveportal.inc");
+require_once("util.inc");
?>
globals.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
"cf_conf_path" => "/cf/conf",
"www_path" => "/usr/local/www",
"captiveportal_path" => "/usr/local/captiveportal",
+ "captiveportal_element_path" => "/var/db/cpelements",
+ "captiveportal_element_sizelimit" => 262144,
"xml_rootobj" => "m0n0wall",
"pppoe_interface" => "ng0",
"n_pptp_units" => 16,
interfaces.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
}
}
+function get_interface_mac($interface) {
+
+ /* build interface list with netstat */
+ exec("/usr/bin/netstat -I $interface -nW -f link", $linkinfo);
+ array_shift($linkinfo);
+ $alink = preg_split("/\s+/", $linkinfo[0]);
+ $mac = chop($alink[3]);
+ return $mac;
+}
+
?>
--- /dev/null
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PEAR, the PHP Extension and Application Repository |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 1997-2004 The PHP Group |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available through the world-wide-web at the following url: |
+// | http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +--------------------------------------------------------------------+
+// | Authors: Sterling Hughes <sterling@php.net> |
+// | Stig Bakken <ssb@php.net> |
+// | Tomas V.V.Cox <cox@idecnet.com> |
+// +--------------------------------------------------------------------+
+//
+// $Id: PEAR.php,v 1.50.2.19 2005/03/28 16:56:58 cellog Exp $
+//
+
+define('PEAR_ERROR_RETURN', 1);
+define('PEAR_ERROR_PRINT', 2);
+define('PEAR_ERROR_TRIGGER', 4);
+define('PEAR_ERROR_DIE', 8);
+define('PEAR_ERROR_CALLBACK', 16);
+/**
+ * WARNING: obsolete
+ * @deprecated
+ */
+define('PEAR_ERROR_EXCEPTION', 32);
+define('PEAR_ZE2', (function_exists('version_compare') &&
+ version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ define('OS_WINDOWS', true);
+ define('OS_UNIX', false);
+ define('PEAR_OS', 'Windows');
+} else {
+ define('OS_WINDOWS', false);
+ define('OS_UNIX', true);
+ define('PEAR_OS', 'Unix'); // blatant assumption
+}
+
+// instant backwards compatibility
+if (!defined('PATH_SEPARATOR')) {
+ if (OS_WINDOWS) {
+ define('PATH_SEPARATOR', ';');
+ } else {
+ define('PATH_SEPARATOR', ':');
+ }
+}
+
+$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs'] = array();
+$GLOBALS['_PEAR_error_handler_stack'] = array();
+
+@ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes. Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix). Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters. Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded. If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference: $obj =& new PEAR_child;
+ *
+ * @since PHP 4.0.2
+ * @author Stig Bakken <ssb@php.net>
+ * @see http://pear.php.net/manual/
+ */
+class PEAR
+{
+ // {{{ properties
+
+ /**
+ * Whether to enable internal debug messages.
+ *
+ * @var bool
+ * @access private
+ */
+ var $_debug = false;
+
+ /**
+ * Default error mode for this object.
+ *
+ * @var int
+ * @access private
+ */
+ var $_default_error_mode = null;
+
+ /**
+ * Default error options used for this object when error mode
+ * is PEAR_ERROR_TRIGGER.
+ *
+ * @var int
+ * @access private
+ */
+ var $_default_error_options = null;
+
+ /**
+ * Default error handler (callback) for this object, if error mode is
+ * PEAR_ERROR_CALLBACK.
+ *
+ * @var string
+ * @access private
+ */
+ var $_default_error_handler = '';
+
+ /**
+ * Which class to use for error objects.
+ *
+ * @var string
+ * @access private
+ */
+ var $_error_class = 'PEAR_Error';
+
+ /**
+ * An array of expected errors.
+ *
+ * @var array
+ * @access private
+ */
+ var $_expected_errors = array();
+
+ // }}}
+
+ // {{{ constructor
+
+ /**
+ * Constructor. Registers this object in
+ * $_PEAR_destructor_object_list for destructor emulation if a
+ * destructor object exists.
+ *
+ * @param string $error_class (optional) which class to use for
+ * error objects, defaults to PEAR_Error.
+ * @access public
+ * @return void
+ */
+ function PEAR($error_class = null)
+ {
+ $classname = strtolower(get_class($this));
+ if ($this->_debug) {
+ print "PEAR constructor called, class=$classname\n";
+ }
+ if ($error_class !== null) {
+ $this->_error_class = $error_class;
+ }
+ while ($classname && strcasecmp($classname, "pear")) {
+ $destructor = "_$classname";
+ if (method_exists($this, $destructor)) {
+ global $_PEAR_destructor_object_list;
+ $_PEAR_destructor_object_list[] = &$this;
+ if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+ register_shutdown_function("_PEAR_call_destructors");
+ $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+ }
+ break;
+ } else {
+ $classname = get_parent_class($classname);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ destructor
+
+ /**
+ * Destructor (the emulated type of...). Does nothing right now,
+ * but is included for forward compatibility, so subclass
+ * destructors should always call it.
+ *
+ * See the note in the class desciption about output from
+ * destructors.
+ *
+ * @access public
+ * @return void
+ */
+ function _PEAR() {
+ if ($this->_debug) {
+ printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
+ }
+ }
+
+ // }}}
+ // {{{ getStaticProperty()
+
+ /**
+ * If you have a class that's mostly/entirely static, and you need static
+ * properties, you can use this method to simulate them. Eg. in your method(s)
+ * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
+ * You MUST use a reference, or they will not persist!
+ *
+ * @access public
+ * @param string $class The calling classname, to prevent clashes
+ * @param string $var The variable to retrieve.
+ * @return mixed A reference to the variable. If not set it will be
+ * auto initialised to NULL.
+ */
+ function &getStaticProperty($class, $var)
+ {
+ static $properties;
+ return $properties[$class][$var];
+ }
+
+ // }}}
+ // {{{ registerShutdownFunc()
+
+ /**
+ * Use this function to register a shutdown method for static
+ * classes.
+ *
+ * @access public
+ * @param mixed $func The function name (or array of class/method) to call
+ * @param mixed $args The arguments to pass to the function
+ * @return void
+ */
+ function registerShutdownFunc($func, $args = array())
+ {
+ $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+ }
+
+ // }}}
+ // {{{ isError()
+
+ /**
+ * Tell whether a value is a PEAR error.
+ *
+ * @param mixed $data the value to test
+ * @param int $code if $data is an error object, return true
+ * only if $code is a string and
+ * $obj->getMessage() == $code or
+ * $code is an integer and $obj->getCode() == $code
+ * @access public
+ * @return bool true if parameter is an error
+ */
+ function isError($data, $code = null)
+ {
+ if (is_a($data, 'PEAR_Error')) {
+ if (is_null($code)) {
+ return true;
+ } elseif (is_string($code)) {
+ return $data->getMessage() == $code;
+ } else {
+ return $data->getCode() == $code;
+ }
+ }
+ return false;
+ }
+
+ // }}}
+ // {{{ setErrorHandling()
+
+ /**
+ * Sets how errors generated by this object should be handled.
+ * Can be invoked both in objects and statically. If called
+ * statically, setErrorHandling sets the default behaviour for all
+ * PEAR objects. If called in an object, setErrorHandling sets
+ * the default behaviour for that object.
+ *
+ * @param int $mode
+ * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+ * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+ * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
+ *
+ * @param mixed $options
+ * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+ * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+ *
+ * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+ * to be the callback function or method. A callback
+ * function is a string with the name of the function, a
+ * callback method is an array of two elements: the element
+ * at index 0 is the object, and the element at index 1 is
+ * the name of the method to call in the object.
+ *
+ * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+ * a printf format string used when printing the error
+ * message.
+ *
+ * @access public
+ * @return void
+ * @see PEAR_ERROR_RETURN
+ * @see PEAR_ERROR_PRINT
+ * @see PEAR_ERROR_TRIGGER
+ * @see PEAR_ERROR_DIE
+ * @see PEAR_ERROR_CALLBACK
+ * @see PEAR_ERROR_EXCEPTION
+ *
+ * @since PHP 4.0.5
+ */
+
+ function setErrorHandling($mode = null, $options = null)
+ {
+ if (isset($this) && is_a($this, 'PEAR')) {
+ $setmode = &$this->_default_error_mode;
+ $setoptions = &$this->_default_error_options;
+ } else {
+ $setmode = &$GLOBALS['_PEAR_default_error_mode'];
+ $setoptions = &$GLOBALS['_PEAR_default_error_options'];
+ }
+
+ switch ($mode) {
+ case PEAR_ERROR_EXCEPTION:
+ case PEAR_ERROR_RETURN:
+ case PEAR_ERROR_PRINT:
+ case PEAR_ERROR_TRIGGER:
+ case PEAR_ERROR_DIE:
+ case null:
+ $setmode = $mode;
+ $setoptions = $options;
+ break;
+
+ case PEAR_ERROR_CALLBACK:
+ $setmode = $mode;
+ // class/object method callback
+ if (is_callable($options)) {
+ $setoptions = $options;
+ } else {
+ trigger_error("invalid error callback", E_USER_WARNING);
+ }
+ break;
+
+ default:
+ trigger_error("invalid error mode", E_USER_WARNING);
+ break;
+ }
+ }
+
+ // }}}
+ // {{{ expectError()
+
+ /**
+ * This method is used to tell which errors you expect to get.
+ * Expected errors are always returned with error mode
+ * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
+ * and this method pushes a new element onto it. The list of
+ * expected errors are in effect until they are popped off the
+ * stack with the popExpect() method.
+ *
+ * Note that this method can not be called statically
+ *
+ * @param mixed $code a single error code or an array of error codes to expect
+ *
+ * @return int the new depth of the "expected errors" stack
+ * @access public
+ */
+ function expectError($code = '*')
+ {
+ if (is_array($code)) {
+ array_push($this->_expected_errors, $code);
+ } else {
+ array_push($this->_expected_errors, array($code));
+ }
+ return sizeof($this->_expected_errors);
+ }
+
+ // }}}
+ // {{{ popExpect()
+
+ /**
+ * This method pops one element off the expected error codes
+ * stack.
+ *
+ * @return array the list of error codes that were popped
+ */
+ function popExpect()
+ {
+ return array_pop($this->_expected_errors);
+ }
+
+ // }}}
+ // {{{ _checkDelExpect()
+
+ /**
+ * This method checks unsets an error code if available
+ *
+ * @param mixed error code
+ * @return bool true if the error code was unset, false otherwise
+ * @access private
+ * @since PHP 4.3.0
+ */
+ function _checkDelExpect($error_code)
+ {
+ $deleted = false;
+
+ foreach ($this->_expected_errors AS $key => $error_array) {
+ if (in_array($error_code, $error_array)) {
+ unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+ $deleted = true;
+ }
+
+ // clean up empty arrays
+ if (0 == count($this->_expected_errors[$key])) {
+ unset($this->_expected_errors[$key]);
+ }
+ }
+ return $deleted;
+ }
+
+ // }}}
+ // {{{ delExpect()
+
+ /**
+ * This method deletes all occurences of the specified element from
+ * the expected error codes stack.
+ *
+ * @param mixed $error_code error code that should be deleted
+ * @return mixed list of error codes that were deleted or error
+ * @access public
+ * @since PHP 4.3.0
+ */
+ function delExpect($error_code)
+ {
+ $deleted = false;
+
+ if ((is_array($error_code) && (0 != count($error_code)))) {
+ // $error_code is a non-empty array here;
+ // we walk through it trying to unset all
+ // values
+ foreach($error_code as $key => $error) {
+ if ($this->_checkDelExpect($error)) {
+ $deleted = true;
+ } else {
+ $deleted = false;
+ }
+ }
+ return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+ } elseif (!empty($error_code)) {
+ // $error_code comes alone, trying to unset it
+ if ($this->_checkDelExpect($error_code)) {
+ return true;
+ } else {
+ return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+ }
+ } else {
+ // $error_code is empty
+ return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+ }
+ }
+
+ // }}}
+ // {{{ raiseError()
+
+ /**
+ * This method is a wrapper that returns an instance of the
+ * configured error class with this object's default error
+ * handling applied. If the $mode and $options parameters are not
+ * specified, the object's defaults are used.
+ *
+ * @param mixed $message a text error message or a PEAR error object
+ *
+ * @param int $code a numeric error code (it is up to your class
+ * to define these if you want to use codes)
+ *
+ * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+ * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+ * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
+ *
+ * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+ * specifies the PHP-internal error level (one of
+ * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+ * If $mode is PEAR_ERROR_CALLBACK, this
+ * parameter specifies the callback function or
+ * method. In other error modes this parameter
+ * is ignored.
+ *
+ * @param string $userinfo If you need to pass along for example debug
+ * information, this parameter is meant for that.
+ *
+ * @param string $error_class The returned error object will be
+ * instantiated from this class, if specified.
+ *
+ * @param bool $skipmsg If true, raiseError will only pass error codes,
+ * the error message parameter will be dropped.
+ *
+ * @access public
+ * @return object a PEAR error object
+ * @see PEAR::setErrorHandling
+ * @since PHP 4.0.5
+ */
+ function raiseError($message = null,
+ $code = null,
+ $mode = null,
+ $options = null,
+ $userinfo = null,
+ $error_class = null,
+ $skipmsg = false)
+ {
+ // The error is yet a PEAR error object
+ if (is_object($message)) {
+ $code = $message->getCode();
+ $userinfo = $message->getUserInfo();
+ $error_class = $message->getType();
+ $message->error_message_prefix = '';
+ $message = $message->getMessage();
+ }
+
+ if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+ if ($exp[0] == "*" ||
+ (is_int(reset($exp)) && in_array($code, $exp)) ||
+ (is_string(reset($exp)) && in_array($message, $exp))) {
+ $mode = PEAR_ERROR_RETURN;
+ }
+ }
+ // No mode given, try global ones
+ if ($mode === null) {
+ // Class error handler
+ if (isset($this) && isset($this->_default_error_mode)) {
+ $mode = $this->_default_error_mode;
+ $options = $this->_default_error_options;
+ // Global error handler
+ } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+ $mode = $GLOBALS['_PEAR_default_error_mode'];
+ $options = $GLOBALS['_PEAR_default_error_options'];
+ }
+ }
+
+ if ($error_class !== null) {
+ $ec = $error_class;
+ } elseif (isset($this) && isset($this->_error_class)) {
+ $ec = $this->_error_class;
+ } else {
+ $ec = 'PEAR_Error';
+ }
+ if ($skipmsg) {
+ return new $ec($code, $mode, $options, $userinfo);
+ } else {
+ return new $ec($message, $code, $mode, $options, $userinfo);
+ }
+ }
+
+ // }}}
+ // {{{ throwError()
+
+ /**
+ * Simpler form of raiseError with fewer options. In most cases
+ * message, code and userinfo are enough.
+ *
+ * @param string $message
+ *
+ */
+ function throwError($message = null,
+ $code = null,
+ $userinfo = null)
+ {
+ if (isset($this) && is_a($this, 'PEAR')) {
+ return $this->raiseError($message, $code, null, null, $userinfo);
+ } else {
+ return PEAR::raiseError($message, $code, null, null, $userinfo);
+ }
+ }
+
+ // }}}
+ function staticPushErrorHandling($mode, $options = null)
+ {
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+ $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
+ $def_options = &$GLOBALS['_PEAR_default_error_options'];
+ $stack[] = array($def_mode, $def_options);
+ switch ($mode) {
+ case PEAR_ERROR_EXCEPTION:
+ case PEAR_ERROR_RETURN:
+ case PEAR_ERROR_PRINT:
+ case PEAR_ERROR_TRIGGER:
+ case PEAR_ERROR_DIE:
+ case null:
+ $def_mode = $mode;
+ $def_options = $options;
+ break;
+
+ case PEAR_ERROR_CALLBACK:
+ $def_mode = $mode;
+ // class/object method callback
+ if (is_callable($options)) {
+ $def_options = $options;
+ } else {
+ trigger_error("invalid error callback", E_USER_WARNING);
+ }
+ break;
+
+ default:
+ trigger_error("invalid error mode", E_USER_WARNING);
+ break;
+ }
+ $stack[] = array($mode, $options);
+ return true;
+ }
+
+ function staticPopErrorHandling()
+ {
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+ $setmode = &$GLOBALS['_PEAR_default_error_mode'];
+ $setoptions = &$GLOBALS['_PEAR_default_error_options'];
+ array_pop($stack);
+ list($mode, $options) = $stack[sizeof($stack) - 1];
+ array_pop($stack);
+ switch ($mode) {
+ case PEAR_ERROR_EXCEPTION:
+ case PEAR_ERROR_RETURN:
+ case PEAR_ERROR_PRINT:
+ case PEAR_ERROR_TRIGGER:
+ case PEAR_ERROR_DIE:
+ case null:
+ $setmode = $mode;
+ $setoptions = $options;
+ break;
+
+ case PEAR_ERROR_CALLBACK:
+ $setmode = $mode;
+ // class/object method callback
+ if (is_callable($options)) {
+ $setoptions = $options;
+ } else {
+ trigger_error("invalid error callback", E_USER_WARNING);
+ }
+ break;
+
+ default:
+ trigger_error("invalid error mode", E_USER_WARNING);
+ break;
+ }
+ return true;
+ }
+
+ // {{{ pushErrorHandling()
+
+ /**
+ * Push a new error handler on top of the error handler options stack. With this
+ * you can easily override the actual error handler for some code and restore
+ * it later with popErrorHandling.
+ *
+ * @param mixed $mode (same as setErrorHandling)
+ * @param mixed $options (same as setErrorHandling)
+ *
+ * @return bool Always true
+ *
+ * @see PEAR::setErrorHandling
+ */
+ function pushErrorHandling($mode, $options = null)
+ {
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+ if (isset($this) && is_a($this, 'PEAR')) {
+ $def_mode = &$this->_default_error_mode;
+ $def_options = &$this->_default_error_options;
+ } else {
+ $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
+ $def_options = &$GLOBALS['_PEAR_default_error_options'];
+ }
+ $stack[] = array($def_mode, $def_options);
+
+ if (isset($this) && is_a($this, 'PEAR')) {
+ $this->setErrorHandling($mode, $options);
+ } else {
+ PEAR::setErrorHandling($mode, $options);
+ }
+ $stack[] = array($mode, $options);
+ return true;
+ }
+
+ // }}}
+ // {{{ popErrorHandling()
+
+ /**
+ * Pop the last error handler used
+ *
+ * @return bool Always true
+ *
+ * @see PEAR::pushErrorHandling
+ */
+ function popErrorHandling()
+ {
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+ array_pop($stack);
+ list($mode, $options) = $stack[sizeof($stack) - 1];
+ array_pop($stack);
+ if (isset($this) && is_a($this, 'PEAR')) {
+ $this->setErrorHandling($mode, $options);
+ } else {
+ PEAR::setErrorHandling($mode, $options);
+ }
+ return true;
+ }
+
+ // }}}
+ // {{{ loadExtension()
+
+ /**
+ * OS independant PHP extension load. Remember to take care
+ * on the correct extension name for case sensitive OSes.
+ *
+ * @param string $ext The extension name
+ * @return bool Success or not on the dl() call
+ */
+ function loadExtension($ext)
+ {
+ if (!extension_loaded($ext)) {
+ // if either returns true dl() will produce a FATAL error, stop that
+ if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
+ return false;
+ }
+ if (OS_WINDOWS) {
+ $suffix = '.dll';
+ } elseif (PHP_OS == 'HP-UX') {
+ $suffix = '.sl';
+ } elseif (PHP_OS == 'AIX') {
+ $suffix = '.a';
+ } elseif (PHP_OS == 'OSX') {
+ $suffix = '.bundle';
+ } else {
+ $suffix = '.so';
+ }
+ return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+ }
+ return true;
+ }
+
+ // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+ global $_PEAR_destructor_object_list;
+ if (is_array($_PEAR_destructor_object_list) &&
+ sizeof($_PEAR_destructor_object_list))
+ {
+ reset($_PEAR_destructor_object_list);
+ if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) {
+ $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
+ }
+ while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+ $classname = get_class($objref);
+ while ($classname) {
+ $destructor = "_$classname";
+ if (method_exists($objref, $destructor)) {
+ $objref->$destructor();
+ break;
+ } else {
+ $classname = get_parent_class($classname);
+ }
+ }
+ }
+ // Empty the object list to ensure that destructors are
+ // not called more than once.
+ $_PEAR_destructor_object_list = array();
+ }
+
+ // Now call the shutdown functions
+ if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+ foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+ call_user_func_array($value[0], $value[1]);
+ }
+ }
+}
+
+// }}}
+
+class PEAR_Error
+{
+ // {{{ properties
+
+ var $error_message_prefix = '';
+ var $mode = PEAR_ERROR_RETURN;
+ var $level = E_USER_NOTICE;
+ var $code = -1;
+ var $message = '';
+ var $userinfo = '';
+ var $backtrace = null;
+
+ // }}}
+ // {{{ constructor
+
+ /**
+ * PEAR_Error constructor
+ *
+ * @param string $message message
+ *
+ * @param int $code (optional) error code
+ *
+ * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
+ * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
+ * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
+ *
+ * @param mixed $options (optional) error level, _OR_ in the case of
+ * PEAR_ERROR_CALLBACK, the callback function or object/method
+ * tuple.
+ *
+ * @param string $userinfo (optional) additional user/debug info
+ *
+ * @access public
+ *
+ */
+ function PEAR_Error($message = 'unknown error', $code = null,
+ $mode = null, $options = null, $userinfo = null)
+ {
+ if ($mode === null) {
+ $mode = PEAR_ERROR_RETURN;
+ }
+ $this->message = $message;
+ $this->code = $code;
+ $this->mode = $mode;
+ $this->userinfo = $userinfo;
+ if (function_exists("debug_backtrace")) {
+ if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
+ $this->backtrace = debug_backtrace();
+ }
+ }
+ if ($mode & PEAR_ERROR_CALLBACK) {
+ $this->level = E_USER_NOTICE;
+ $this->callback = $options;
+ } else {
+ if ($options === null) {
+ $options = E_USER_NOTICE;
+ }
+ $this->level = $options;
+ $this->callback = null;
+ }
+ if ($this->mode & PEAR_ERROR_PRINT) {
+ if (is_null($options) || is_int($options)) {
+ $format = "%s";
+ } else {
+ $format = $options;
+ }
+ printf($format, $this->getMessage());
+ }
+ if ($this->mode & PEAR_ERROR_TRIGGER) {
+ trigger_error($this->getMessage(), $this->level);
+ }
+ if ($this->mode & PEAR_ERROR_DIE) {
+ $msg = $this->getMessage();
+ if (is_null($options) || is_int($options)) {
+ $format = "%s";
+ if (substr($msg, -1) != "\n") {
+ $msg .= "\n";
+ }
+ } else {
+ $format = $options;
+ }
+ die(sprintf($format, $msg));
+ }
+ if ($this->mode & PEAR_ERROR_CALLBACK) {
+ if (is_callable($this->callback)) {
+ call_user_func($this->callback, $this);
+ }
+ }
+ if ($this->mode & PEAR_ERROR_EXCEPTION) {
+ trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions", E_USER_WARNING);
+ eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);');
+ }
+ }
+
+ // }}}
+ // {{{ getMode()
+
+ /**
+ * Get the error mode from an error object.
+ *
+ * @return int error mode
+ * @access public
+ */
+ function getMode() {
+ return $this->mode;
+ }
+
+ // }}}
+ // {{{ getCallback()
+
+ /**
+ * Get the callback function/method from an error object.
+ *
+ * @return mixed callback function or object/method array
+ * @access public
+ */
+ function getCallback() {
+ return $this->callback;
+ }
+
+ // }}}
+ // {{{ getMessage()
+
+
+ /**
+ * Get the error message from an error object.
+ *
+ * @return string full error message
+ * @access public
+ */
+ function getMessage()
+ {
+ return ($this->error_message_prefix . $this->message);
+ }
+
+
+ // }}}
+ // {{{ getCode()
+
+ /**
+ * Get error code from an error object
+ *
+ * @return int error code
+ * @access public
+ */
+ function getCode()
+ {
+ return $this->code;
+ }
+
+ // }}}
+ // {{{ getType()
+
+ /**
+ * Get the name of this error/exception.
+ *
+ * @return string error/exception name (type)
+ * @access public
+ */
+ function getType()
+ {
+ return get_class($this);
+ }
+
+ // }}}
+ // {{{ getUserInfo()
+
+ /**
+ * Get additional user-supplied information.
+ *
+ * @return string user-supplied information
+ * @access public
+ */
+ function getUserInfo()
+ {
+ return $this->userinfo;
+ }
+
+ // }}}
+ // {{{ getDebugInfo()
+
+ /**
+ * Get additional debug information supplied by the application.
+ *
+ * @return string debug information
+ * @access public
+ */
+ function getDebugInfo()
+ {
+ return $this->getUserInfo();
+ }
+
+ // }}}
+ // {{{ getBacktrace()
+
+ /**
+ * Get the call backtrace from where the error was generated.
+ * Supported with PHP 4.3.0 or newer.
+ *
+ * @param int $frame (optional) what frame to fetch
+ * @return array Backtrace, or NULL if not available.
+ * @access public
+ */
+ function getBacktrace($frame = null)
+ {
+ if ($frame === null) {
+ return $this->backtrace;
+ }
+ return $this->backtrace[$frame];
+ }
+
+ // }}}
+ // {{{ addUserInfo()
+
+ function addUserInfo($info)
+ {
+ if (empty($this->userinfo)) {
+ $this->userinfo = $info;
+ } else {
+ $this->userinfo .= " ** $info";
+ }
+ }
+
+ // }}}
+ // {{{ toString()
+
+ /**
+ * Make a string representation of this object.
+ *
+ * @return string a string with an object summary
+ * @access public
+ */
+ function toString() {
+ $modes = array();
+ $levels = array(E_USER_NOTICE => 'notice',
+ E_USER_WARNING => 'warning',
+ E_USER_ERROR => 'error');
+ if ($this->mode & PEAR_ERROR_CALLBACK) {
+ if (is_array($this->callback)) {
+ $callback = (is_object($this->callback[0]) ?
+ strtolower(get_class($this->callback[0])) :
+ $this->callback[0]) . '::' .
+ $this->callback[1];
+ } else {
+ $callback = $this->callback;
+ }
+ return sprintf('[%s: message="%s" code=%d mode=callback '.
+ 'callback=%s prefix="%s" info="%s"]',
+ strtolower(get_class($this)), $this->message, $this->code,
+ $callback, $this->error_message_prefix,
+ $this->userinfo);
+ }
+ if ($this->mode & PEAR_ERROR_PRINT) {
+ $modes[] = 'print';
+ }
+ if ($this->mode & PEAR_ERROR_TRIGGER) {
+ $modes[] = 'trigger';
+ }
+ if ($this->mode & PEAR_ERROR_DIE) {
+ $modes[] = 'die';
+ }
+ if ($this->mode & PEAR_ERROR_RETURN) {
+ $modes[] = 'return';
+ }
+ return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+ 'prefix="%s" info="%s"]',
+ strtolower(get_class($this)), $this->message, $this->code,
+ implode("|", $modes), $levels[$this->level],
+ $this->error_message_prefix,
+ $this->userinfo);
+ }
+
+ // }}}
+}
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
--- /dev/null
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+/*
+Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
+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.
+3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+
+This code cannot simply be copied and put under the GNU Public License or
+any other GPL-like (LGPL, GPL2) License.
+
+ $Id: RADIUS.php,v 1.5 2004/03/25 15:48:40 mbretter Exp $
+
+ This version of RADIUS.php has been modified by
+ Jonathan De Graeve <jonathan@imelda.be> to integrate with M0n0wall <http://www.m0n0.ch/wall>
+
+ $Id_jdg: 2005/12/22 14:22:42
+
+ Changes made include:
+ * StandardAttributes for M0n0wall use
+ * Removed internal Session-Id creation
+ * Adding of ReplyMessage to getAttributes()
+ * Adding of listAttributes()
+ * Adding of VENDOR Bay Networks (Nortel)
+ * Adding of VENDOR Nomadix
+ * Adding of VENDOR WISPr (Wi-Fi Alliance)
+
+*/
+
+require_once("pear.inc");
+
+/**
+* Client implementation of RADIUS. This are wrapper classes for
+* the RADIUS PECL.
+* Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
+*
+* @package Auth_RADIUS
+* @author Michael Bretterklieber <michael@bretterklieber.com>
+* @access public
+* @version $Revision: 1.5 $
+*/
+
+PEAR::loadExtension('radius');
+
+/**
+ * class Auth_RADIUS
+ *
+ * Abstract base class for RADIUS
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS extends PEAR {
+
+ /**
+ * List of RADIUS servers.
+ * @var array
+ * @see addServer(), putServer()
+ */
+ var $_servers = array();
+
+ /**
+ * Path to the configuration-file.
+ * @var string
+ * @see setConfigFile()
+ */
+ var $_configfile = null;
+
+ /**
+ * Resource.
+ * @var resource
+ * @see open(), close()
+ */
+ var $res = null;
+
+ /**
+ * Username for authentication and accounting requests.
+ * @var string
+ */
+ var $username = null;
+
+ /**
+ * Password for plaintext-authentication (PAP).
+ * @var string
+ */
+ var $password = null;
+
+ /**
+ * List of known attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $attributes = array();
+
+ /**
+ * List of raw attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $rawAttributes = array();
+
+ /**
+ * List of raw vendor specific attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $rawVendorAttributes = array();
+
+ /**
+ * Constructor
+ *
+ * Loads the RADIUS PECL/extension
+ *
+ * @return void
+ */
+ function Auth_RADIUS()
+ {
+ $this->PEAR();
+ }
+
+ /**
+ * Adds a RADIUS server to the list of servers for requests.
+ *
+ * At most 10 servers may be specified. When multiple servers
+ * are given, they are tried in round-robin fashion until a
+ * valid response is received
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @param integer $port Portnumber
+ * @param string $sharedSecret Shared secret
+ * @param integer $timeout Timeout for each request
+ * @param integer $maxtries Max. retries for each request
+ * @return void
+ */
+ function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 5, $maxtries = 3)
+ {
+ $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
+ }
+
+ /**
+ * Returns an error message, if an error occurred.
+ *
+ * @access public
+ * @return string
+ */
+ function getError()
+ {
+ return radius_strerror($this->res);
+ }
+
+ /**
+ * Sets the configuration-file.
+ *
+ * @access public
+ * @param string $file Path to the configuration file
+ * @return void
+ */
+ function setConfigfile($file)
+ {
+ $this->_configfile = $file;
+ }
+
+ /**
+ * Puts an attribute.
+ *
+ * @access public
+ * @param integer $attrib Attribute-number
+ * @param mixed $port Attribute-value
+ * @param type $type Attribute-type
+ * @return bool true on success, false on error
+ */
+ function putAttribute($attrib, $value, $type = null)
+ {
+ if ($type == null) {
+ $type = gettype($value);
+ }
+
+ switch ($type) {
+ case 'integer':
+ return radius_put_int($this->res, $attrib, $value);
+
+ case 'addr':
+ return radius_put_addr($this->res, $attrib, $value);
+
+ case 'string':
+ default:
+ return radius_put_attr($this->res, $attrib, $value);
+ }
+
+ }
+
+ /**
+ * Puts a vendor-specific attribute.
+ *
+ * @access public
+ * @param integer $vendor Vendor (MSoft, Cisco, ...)
+ * @param integer $attrib Attribute-number
+ * @param mixed $port Attribute-value
+ * @param type $type Attribute-type
+ * @return bool true on success, false on error
+ */
+ function putVendorAttribute($vendor, $attrib, $value, $type = null)
+ {
+
+ if ($type == null) {
+ $type = gettype($value);
+ }
+
+ switch ($type) {
+ case 'integer':
+ return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
+
+ case 'addr':
+ return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
+
+ case 'string':
+ default:
+ return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
+ }
+
+ }
+
+ /**
+ * Prints known attributes received from the server.
+ *
+ * @access public
+ */
+ function dumpAttributes()
+ {
+ foreach ($this->attributes as $name => $data) {
+ echo "$name:$data<br>\n";
+ }
+ }
+
+ /**
+ * Return our know attributes array received from the server.
+ *
+ * @access public
+ */
+ function listAttributes()
+ {
+ return $this->attributes;
+ }
+
+ /**
+ * Overwrite this.
+ *
+ * @access public
+ */
+ function open()
+ {
+ }
+
+ /**
+ * Overwrite this.
+ *
+ * @access public
+ */
+ function createRequest()
+ {
+ }
+
+ /**
+ * Puts standard attributes.
+ *
+ * @access public
+ */
+ function putStandardAttributes()
+ {
+ $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_ETHERNET);
+ $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_LOGIN);
+ }
+
+ /**
+ * Puts custom attributes.
+ *
+ * @access public
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ }
+
+ /**
+ * Configures the radius library.
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @param integer $port Portnumber
+ * @param string $sharedSecret Shared secret
+ * @param integer $timeout Timeout for each request
+ * @param integer $maxtries Max. retries for each request
+ * @return bool true on success, false on error
+ * @see addServer()
+ */
+ function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
+ {
+ if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Configures the radius library via external configurationfile
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @return bool true on success, false on error
+ */
+ function putConfigfile($file)
+ {
+ if (!radius_config($this->res, $file)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Initiates a RADIUS request.
+ *
+ * @access public
+ * @return bool true on success, false on errors
+ */
+ function start()
+ {
+ if (!$this->open()) {
+ return false;
+ }
+
+ foreach ($this->_servers as $s) {
+ // Servername, port, sharedsecret, timeout, retries
+ if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
+ return false;
+ }
+ }
+
+ if (!empty($this->_configfile)) {
+ if (!$this->putConfigfile($this->_configfile)) {
+ return false;
+ }
+ }
+
+ $this->createRequest();
+ $this->putStandardAttributes();
+ $this->putAuthAttributes();
+ return true;
+ }
+
+ /**
+ * Sends a prepared RADIUS request and waits for a response
+ *
+ * @access public
+ * @return mixed true on success, false on reject, PEAR_Error on error
+ */
+ function send()
+ {
+ $req = radius_send_request($this->res);
+ if (!$req) {
+ return $this->raiseError('Error sending request: ' . $this->getError());
+ }
+
+ switch($req) {
+ case RADIUS_ACCESS_ACCEPT:
+ if (is_subclass_of($this, 'auth_radius_acct')) {
+ return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
+ }
+ return true;
+
+ case RADIUS_ACCESS_REJECT:
+ return false;
+
+ case RADIUS_ACCOUNTING_RESPONSE:
+ if (is_subclass_of($this, 'auth_radius_pap')) {
+ return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
+ }
+ return true;
+
+ default:
+ return $this->raiseError("Unexpected return value: $req");
+ }
+
+ }
+
+ /**
+ * Reads all received attributes after sending the request.
+ *
+ * This methos stores know attributes in the property attributes,
+ * all attributes (including known attibutes) are stored in rawAttributes
+ * or rawVendorAttributes.
+ * NOTE: call this functio also even if the request was rejected, because the
+ * Server returns usualy an errormessage
+ *
+ * @access public
+ * @return bool true on success, false on error
+ */
+ function getAttributes()
+ {
+
+ while ($attrib = radius_get_attr($this->res)) {
+
+ if (!is_array($attrib)) {
+ return false;
+ }
+
+ $attr = $attrib['attr'];
+ $data = $attrib['data'];
+
+ $this->rawAttributes[$attr] = $data;
+
+ switch ($attr) {
+ case RADIUS_FRAMED_IP_ADDRESS:
+ $this->attributes['framed_ip'] = radius_cvt_addr($data);
+ break;
+
+ case RADIUS_FRAMED_IP_NETMASK:
+ $this->attributes['framed_mask'] = radius_cvt_addr($data);
+ break;
+
+ case RADIUS_FRAMED_MTU:
+ $this->attributes['framed_mtu'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FRAMED_COMPRESSION:
+ $this->attributes['framed_compression'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_SESSION_TIMEOUT:
+ $this->attributes['session_timeout'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_IDLE_TIMEOUT:
+ $this->attributes['idle_timeout'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_SERVICE_TYPE:
+ $this->attributes['service_type'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_CLASS:
+ $this->attributes['class'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FRAMED_PROTOCOL:
+ $this->attributes['framed_protocol'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FRAMED_ROUTING:
+ $this->attributes['framed_routing'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FILTER_ID:
+ $this->attributes['filter_id'] = radius_cvt_string($data);
+ break;
+
+ case RADIUS_REPLY_MESSAGE:
+ $this->attributes['reply_message'] = radius_cvt_string($data);
+ break;
+
+ case RADIUS_VENDOR_SPECIFIC:
+ $attribv = radius_get_vendor_attr($data);
+ if (!is_array($attribv)) {
+ return false;
+ }
+
+ $vendor = $attribv['vendor'];
+ $attrv = $attribv['attr'];
+ $datav = $attribv['data'];
+
+ $this->rawVendorAttributes[$vendor][$attrv] = $datav;
+
+ if ($vendor == RADIUS_VENDOR_MICROSOFT) {
+
+ switch ($attrv) {
+ case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
+ $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_ERROR:
+ $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
+ $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
+ $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
+ $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
+ $demangled = radius_demangle($this->res, $datav);
+ $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
+ $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
+ $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
+ $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
+ $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
+ break;
+ }
+ }
+
+ if ($vendor == RADIUS_VENDOR_BAY) {
+
+ switch ($attrv) {
+ case RADIUS_BAY_CES_GROUP:
+ $this->attributes['ces_group'] = radius_cvt_string($datav);
+ break;
+ }
+ }
+
+ if ($vendor == 3309) { /* RADIUS_VENDOR_NOMADIX */
+
+ switch ($attrv) {
+ case 1: /* RADIUS_NOMADIX_BW_UP */
+ $this->attributes['bw_up'] = radius_cvt_int($datav);
+ break;
+ case 2: /* RADIUS_NOMADIX_BW_DOWN */
+ $this->attributes['bw_down'] = radius_cvt_int($datav);
+ break;
+ case 3: /* RADIUS_NOMADIX_URL_REDIRECTION */
+ $this->attributes['url_redirection'] = radius_cvt_string($datav);
+ break;
+ case 5: /* RADIUS_NOMADIX_EXPIRATION */
+ $this->attributes['expiration'] = radius_cvt_string($datav);
+ break;
+ case 7: /* RADIUS_NOMADIX_MAXBYTESUP */
+ $this->attributes['maxbytesup'] = radius_cvt_int($datav);
+ break;
+ case 8: /* RADIUS_NOMADIX_MAXBYTESDOWN */
+ $this->attributes['maxbytesdown'] = radius_cvt_int($datav);
+ break;
+ case 10: /* RADIUS_NOMADIX_LOGOFF_URL */
+ $this->attributes['url_logoff'] = radius_cvt_string($datav);
+ break;
+ }
+ }
+
+ if ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
+
+ switch ($attrv) {
+ case 1: /* WISPr-Location-ID */
+ $this->attributes['location_id'] = radius_cvt_string($datav);
+ break;
+ case 2: /* WISPr-Location-Name */
+ $this->attributes['location_name'] = radius_cvt_string($datav);
+ break;
+ case 3: /* WISPr-Logoff-URL */
+ $this->attributes['url_logoff'] = radius_cvt_string($datav);
+ break;
+ case 4: /* WISPr-Redirection-URL */
+ $this->attributes['url_redirection'] = radius_cvt_string($datav);
+ break;
+ case 5: /* WISPr-Bandwidth-Min-Up */
+ $this->attributes['bw_minbytesup'] = radius_cvt_int($datav);
+ break;
+ case 6: /* WISPr-Bandwidth-Min-Down */
+ $this->attributes['bw_minbytesdown'] = radius_cvt_int($datav);
+ break;
+ case 7: /* WIPSr-Bandwidth-Max-Up */
+ $this->attributes['bw_maxbytesup'] = radius_cvt_int($datav);
+ break;
+ case 8: /* WISPr-Bandwidth-Max-Down */
+ $this->attributes['bw_maxbytesdown'] = radius_cvt_int($datav);
+ break;
+ case 9: /* WISPr-Session-Terminate-Time */
+ $this->attributes['session_terminate_time'] = radius_cvt_string($datav);
+ break;
+ case 10: /* WISPr-Session-Terminate-End-Of-Day */
+ $this->attributes['session_terminate_endofday'] = radius_cvt_int($datav);
+ break;
+ case 11: /* WISPr-Billing-Class-Of-Service */
+ $this->attributes['billing_class_of_service'] = radius_cvt_string($datav);
+ break;
+ }
+ }
+
+ break;
+
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ if ($this->res != null) {
+ radius_close($this->res);
+ $this->res = null;
+ }
+ $this->username = str_repeat("\0", strlen($this->username));
+ $this->password = str_repeat("\0", strlen($this->password));
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_PAP
+ *
+ * Class for authenticating using PAP (Plaintext)
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_PAP extends Auth_RADIUS
+{
+
+ /**
+ * Constructor
+ *
+ * @param string $username Username
+ * @param string $password Password
+ * @return void
+ */
+ function Auth_RADIUS_PAP($username = null, $password = null)
+ {
+ $this->Auth_RADIUS();
+ $this->username = $username;
+ $this->password = $password;
+ }
+
+ /**
+ * Creates a RADIUS resource
+ *
+ * Creates a RADIUS resource for authentication. This should be the first
+ * call before you make any other things with the library.
+ *
+ * @return bool true on success, false on error
+ */
+ function open()
+ {
+ $this->res = radius_auth_open();
+ if (!$this->res) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates an authentication request
+ *
+ * Creates an authentication request.
+ * You MUST call this method before you can put any attribute
+ *
+ * @return bool true on success, false on error
+ */
+ function createRequest()
+ {
+ if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Put authentication specific attributes
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->password)) {
+ $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
+ }
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_CHAP_MD5
+ *
+ * Class for authenticating using CHAP-MD5 see RFC1994.
+ * Instead og the plaintext password the challenge and
+ * the response are needed.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
+{
+ /**
+ * 8 Bytes binary challenge
+ * @var string
+ */
+ var $challenge = null;
+
+ /**
+ * 16 Bytes MD5 response binary
+ * @var string
+ */
+ var $response = null;
+
+ /**
+ * Id of the authentication request. Should incremented after every request.
+ * @var integer
+ */
+ var $chapid = 1;
+
+ /**
+ * Constructor
+ *
+ * @param string $username Username
+ * @param string $challenge 8 Bytes Challenge (binary)
+ * @param integer $chapid Requestnumber
+ * @return void
+ */
+ function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
+ {
+ $this->Auth_RADIUS_PAP();
+ $this->username = $username;
+ $this->challenge = $challenge;
+ $this->chapid = $chapid;
+ }
+
+ /**
+ * Put CHAP-MD5 specific attributes
+ *
+ * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
+ * and the response. The chapid is inserted in the first byte of the response.
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response)) {
+ $response = pack('C', $this->chapid) . $this->response;
+ $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
+ }
+ if (isset($this->challenge)) {
+ $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ Auth_RADIUS_PAP::close();
+ $this->challenge = str_repeat("\0", strlen($this->challenge));
+ $this->response = str_repeat("\0", strlen($this->response));
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_MSCHAPv1
+ *
+ * Class for authenticating using MS-CHAPv1 see RFC2433
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
+{
+ /**
+ * LAN-Manager-Response
+ * @var string
+ */
+ var $lmResponse = null;
+
+ /**
+ * Wether using deprecated LM-Responses or not.
+ * 0 = use LM-Response, 1 = use NT-Response
+ * @var bool
+ */
+ var $flags = 1;
+
+ /**
+ * Put MS-CHAPv1 specific attributes
+ *
+ * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
+ * and the response. The response has this structure:
+ * struct rad_mschapvalue {
+ * u_char ident;
+ * u_char flags;
+ * u_char lm_response[24];
+ * u_char response[24];
+ * };
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response) || isset($this->lmResponse)) {
+ $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
+ $ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24);
+ $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
+ }
+ if (isset($this->challenge)) {
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+}
+
+/**
+ * class Auth_RADIUS_MSCHAPv2
+ *
+ * Class for authenticating using MS-CHAPv2 see RFC2759
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
+{
+ /**
+ * 16 Bytes binary challenge
+ * @var string
+ */
+ var $challenge = null;
+
+ /**
+ * 16 Bytes binary Peer Challenge
+ * @var string
+ */
+ var $peerChallenge = null;
+
+ /**
+ * Put MS-CHAPv2 specific attributes
+ *
+ * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
+ * and the response. The response has this structure:
+ * struct rad_mschapv2value {
+ * u_char ident;
+ * u_char flags;
+ * u_char pchallenge[16];
+ * u_char reserved[8];
+ * u_char response[24];
+ * };
+ * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response) && isset($this->peerChallenge)) {
+ // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
+ $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
+ }
+ if (isset($this->challenge)) {
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ Auth_RADIUS_MSCHAPv1::close();
+ $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
+ }
+}
+
+/**
+ * class Auth_RADIUS_Acct
+ *
+ * Class for RADIUS accounting
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct extends Auth_RADIUS
+{
+ /**
+ * Defines where the Authentication was made, possible values are:
+ * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
+ * @var integer
+ */
+ var $authentic = null;
+
+ /**
+ * Defines the type of the accounting request, on of:
+ * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
+ * @var integer
+ */
+ var $status_type = null;
+
+ /**
+ * The time the user was logged in in seconds
+ * @var integer
+ */
+ var $session_time = null;
+
+ /**
+ * A uniq identifier for the session of the user, maybe the PHP-Session-Id
+ * @var string
+ */
+ var $session_id = null;
+
+ /**
+ * Constructor
+ *
+ * This function is disabled for M0n0wall since we use our own session_id
+ *
+ * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
+ * @return void
+ *
+ function Auth_RADIUS_Acct()
+ {
+ $this->Auth_RADIUS();
+
+ if (isset($_SERVER)) {
+ $var = &$_SERVER;
+ } else {
+ $var = &$GLOBALS['HTTP_SERVER_VARS'];
+ }
+
+ $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
+ }
+ */
+
+ /**
+ * Constructor
+ *
+ */
+
+ function Auth_RADIUS_Acct()
+ {
+ $this->Auth_RADIUS();
+ }
+
+ /**
+ * Creates a RADIUS resource
+ *
+ * Creates a RADIUS resource for accounting. This should be the first
+ * call before you make any other things with the library.
+ *
+ * @return bool true on success, false on error
+ */
+ function open()
+ {
+ $this->res = radius_acct_open();
+ if (!$this->res) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates an accounting request
+ *
+ * Creates an accounting request.
+ * You MUST call this method before you can put any attribute.
+ *
+ * @return bool true on success, false on error
+ */
+ function createRequest()
+ {
+ if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Put attributes for accounting.
+ *
+ * Here we put some accounting values. There many more attributes for accounting,
+ * but for web-applications only certain attributes make sense.
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
+ $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
+ if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
+ $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
+ }
+ if (isset($this->authentic)) {
+ $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
+ }
+
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_Acct_Start
+ *
+ * Class for RADIUS accounting. Its usualy used, after the user has logged in.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_START by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_START;
+}
+
+/**
+ * class Auth_RADIUS_Acct_Start
+ *
+ * Class for RADIUS accounting. Its usualy used, after the user has logged out.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_STOP by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_STOP;
+}
+
+if (!defined('RADIUS_UPDATE'))
+ define('RADIUS_UPDATE', 3);
+
+/**
+ * class Auth_RADIUS_Acct_Update
+ *
+ * Class for interim RADIUS accounting updates.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_UPDATE by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_UPDATE;
+}
+
+?>
services.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
EOD;
+ if (isset($config['snmpd']['bindlan'])) {
+ $snmpdconf .= "agentaddress udp:161@{$config['interfaces']['lan']['ipaddr']}\n";
+ }
+
fwrite($fd, $snmpdconf);
fclose($fd);
shaper.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
util.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
return mwexec("/usr/bin/killall " . escapeshellarg($procname));
}
+/* kill a process by name */
+function sigkillbyname($procname, $sig) {
+ return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname));
+}
+
/* return the subnet address given a host address and a subnet bit count */
function gen_subnet($ipaddr, $bits) {
if (!is_ipaddr($ipaddr) || !is_numeric($bits))
vpn.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
echo "Configuring IPsec VPN... ";
} else {
/* kill racoon */
- killbypid("{$g['varrun_path']}/racoon.pid");
+ killbyname("racoon");
/* wait for process to die */
sleep(2);
/* send a SIGKILL to be sure */
- sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
+ sigkillbyname("racoon", "KILL");
}
/* flush SPD and SAD */
functions to parse/dump configuration files in XML format
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
$listtags = explode(" ", "rule user key dnsserver winsserver " .
"encryption-algorithm-option hash-algorithm-option hosts tunnel onetoone " .
"staticmap route alias pipe queue shellcmd cacert earlyshellcmd mobilekey " .
- "servernat proxyarpnet passthrumac allowedip wolentry vlan domainoverrides");
+ "servernat proxyarpnet passthrumac allowedip wolentry vlan domainoverrides element");
function startElement($parser, $name, $attrs) {
global $depth, $curpath, $config, $havedata, $listtags;
die("XML error: no $rootobj object found!\n");
}
+ fclose($fp);
+
return $config[$rootobj];
}
rc.banner
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
*** This is m0n0wall, version {$version}
built on {$buildtime} for {$g['fullplatform']}
- Copyright (C) 2002-2005 by Manuel Kasper. All rights reserved.
+ Copyright (C) 2002-2006 by Manuel Kasper. All rights reserved.
Visit http://m0n0.ch/wall for updates.
rc.bootup
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
--- /dev/null
+#!/usr/local/bin/php -f
+<?php
+/*
+ rc.cleanreboot
+ 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_once("config.inc");
+require_once("functions.inc");
+
+system_reboot_sync();
+
+?>
rc.initial.defaults
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.initial.password
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.initial.ping
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.initial.reboot
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.initial.setlanip
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.initial.setports
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.newwanip
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
rc.prunecaptiveportal
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_backup.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system_reboot();
$savemsg = "The configuration has been restored. The firewall is now rebooting.";
} else {
- $input_errors[] = "The configuration could not be restored.";
+ $errstr = "The configuration could not be restored.";
+ if ($xmlerr)
+ $errstr .= " (XML error: $xmlerr)";
+ $input_errors[] = $errstr;
}
} else {
$input_errors[] = "The configuration could not be restored (file upload error).";
diag_defaults.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_ipfstat.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2005 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2005-2006 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_ipsec_sad.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_ipsec_spd.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs_dhcp.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs_filter.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs_portal.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs_settings.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_logs_vpn.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_ping.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Bob Zoller (bob@kludgebox.com) and Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Bob Zoller (bob@kludgebox.com) and Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_resetstate.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diag_traceroute.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2005 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2005-2006 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
exec_raw.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
</td></tr></table></td>
</tr>
<tr align="center" valign="top" bgcolor="#435370">
- <td colspan="2" class="cpline">m0n0wall is © 2002-2005 by Manuel Kasper.
+ <td colspan="2" class="cpline">m0n0wall is © 2002-2006 by Manuel Kasper.
All rights reserved. [<a href="/license.php" class="tblnk">view license</a>]</td>
</tr>
</table>
firewall_aliases.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_aliases_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_1to1.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_1to1_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_out.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_out_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_server.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_nat_server_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_rules.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_rules_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper_pipes.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper_pipes_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper_queues.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
firewall_shaper_queues_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
graph.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2004-2005 T. Lechat <dev@lechat.org> and Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2004-2006 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
+ and Jonathan Watt <jwatt@jwatt.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
POSSIBILITY OF SUCH DAMAGE.
*/
-// VERSION 1.0.4
+header("Content-type: image/svg+xml");
/********** HTTP GET Based Conf ***********/
-$ifnum=@$_GET["ifnum"]; //BSD / SNMP interface name / number
-$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum"; //Interface name that will be showed on top right of graph
+$ifnum=@$_GET["ifnum"]; // BSD / SNMP interface name / number
+$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum"; //Interface name that will be showed on top right of graph
/********* Other conf *******/
-$scale_type="up"; //Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas
-$nb_plot=120; //NB plot in graph
+$scale_type="up"; //Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas
+$nb_plot=120; //NB plot in graph
$time_interval=1; //Refresh time Interval
-$first_stage_time_interval=2; //First stage time Intervall
-
-$urldata=@$_SERVER["SCRIPT_NAME"];
$fetch_link = "stats.cgi?$ifnum";
-//Style
-$style['bg']="fill:white;stroke:none;stroke-width:0;opacity:1;";
-$style['axis']="fill:black;stroke:black;stroke-width:1;";
-$style['in']="fill:#435370; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
-$style['out']="fill:#8092B3; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
-$style['graph_in']="fill:none;stroke:#435370;stroke-width:1;opacity:0.8;";
-$style['graph_out']="fill:none;stroke:#8092B3;stroke-width:1;opacity:0.8;";
-$style['legend']="fill:black; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
-$style['graphname']="fill:#435370; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:8;";
-$style['grid_txt']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:6;";
-$style['grid']="stroke:gray;stroke-width:1;opacity:0.5;";
-$style['switch_unit']="fill:#435370; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
-$style['switch_scale']="fill:#435370; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
-$style['error']="fill:blue; font-family:Arial; font-size:4;";
-$style['collect_initial']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
+//SVG attributes
+$attribs['axis']='fill="black" stroke="black"';
+$attribs['in']='fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
+$attribs['out']='fill="#8092B3" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
+$attribs['graph_in']='fill="none" stroke="#435370" stroke-opacity="0.8"';
+$attribs['graph_out']='fill="none" stroke="#8092B3" stroke-opacity="0.8"';
+$attribs['legend']='fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
+$attribs['graphname']='fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="8"';
+$attribs['grid_txt']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"';
+$attribs['grid']='stroke="gray" stroke-opacity="0.5"';
+$attribs['switch_unit']='fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
+$attribs['switch_scale']='fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
+$attribs['error']='fill="blue" font-family="Arial" font-size="4"';
+$attribs['collect_initial']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
//Error text if we cannot fetch data : depends on which method is used
$error_text = "Cannot get data about interface $ifnum";
-$height=100; //SVG internal height : do not modify
-$width=200; //SVG internal width : do not modify
+$height=100; //SVG internal height : do not modify
+$width=200; //SVG internal width : do not modify
/********* Graph DATA **************/
-header("Content-type: image/svg+xml");
-print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?><svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
-<g id="graph" style="visibility:visible">
- <rect id="bg" x1="0" y1="0" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['bg']?>"/>
- <line id="axis_x" x1="0" y1="0" x2="0" y2="<?=$height?>" style="<?=$style['axis']?>"/>
- <line id="axis_y" x1="0" y1="<?=$height?>" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['axis']?>"/>
- <path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_out']?>"/>
- <path id="graph_in" d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_in']?>"/>
- <path id="grid" d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" style="<?=$style[grid]?>"/>
- <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
- <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
- <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
- <text id="graph_in_lbl" x="5" y="8" style="<?=$style['in']?>">In</text>
- <text id="graph_out_lbl" x="5" y="16" style="<?=$style['out']?> ">Out</text>
- <text id="graph_in_txt" x="20" y="8" style="<?=$style['in']?>"> </text>
- <text id="graph_out_txt" x="20" y="16" style="<?=$style['out']?> "> </text>
- <text id="ifname" x="<?=$width?>" y="8" style="<?=$style['graphname']?> text-anchor:end"><?=$ifname?></text>
- <text id="switch_unit" x="<?=$width*0.55?>" y="5" style="<?=$style['switch_unit']?>">Switch to bytes/s</text>
- <text id="switch_scale" x="<?=$width*0.55?>" y="11" style="<?=$style['switch_scale']?>">AutoScale (<?=$scale_type?>)</text>
- <text id="datetime" x="<?=$width*0.33?>" y="5" style="<?=$style['legend']?>"> </text>
- <text id="graphlast" x="<?=$width*0.55?>" y="17" style="<?=$style['legend']?>">Graph shows last <?=$time_interval*$nb_plot?> seconds</text>
- <polygon id="axis_arrow_x" style="<?=$style['axis']?>" points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
- <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>" style="visibility:hidden;<?=$style['error']?> text-anchor:middle"><?=$error_text?></text>
- <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>" style="visibility:hidden;<?=$style['collect_initial']?> text-anchor:middle">Collecting initial data, please wait...</text>
-</g>
-
-<script type="text/ecmascript"><![CDATA[
-var SVGDoc;
-var last_ifin=0;
-var last_ifout=0;
-var last_ugmt=0;
-var diff_ugmt=0;
-var diff_ifin=0;
-var diff_ifout=0;
+print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?>
+<svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
+ <g id="graph">
+ <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/>
+ <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?=$attribs['axis']?>/>
+ <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?=$attribs['axis']?>/>
+ <path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_out']?>/>
+ <path id="graph_in" d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_in']?>/>
+ <path id="grid" d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" <?=$attribs['grid']?>/>
+ <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
+ <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
+ <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
+ <text id="graph_in_lbl" x="5" y="8" <?=$attribs['in']?>>In</text>
+ <text id="graph_out_lbl" x="5" y="16" <?=$attribs['out']?>>Out</text>
+ <text id="graph_in_txt" x="20" y="8" <?=$attribs['in']?>> </text>
+ <text id="graph_out_txt" x="20" y="16" <?=$attribs['out']?>> </text>
+ <text id="ifname" x="<?=$width?>" y="8" <?=$attribs['graphname']?> text-anchor="end"><?=$ifname?></text>
+ <text id="switch_unit" x="<?=$width*0.55?>" y="5" <?=$attribs['switch_unit']?>>Switch to bytes/s</text>
+ <text id="switch_scale" x="<?=$width*0.55?>" y="11" <?=$attribs['switch_scale']?>>AutoScale (<?=$scale_type?>)</text>
+ <text id="datetime" x="<?=$width*0.33?>" y="5" <?=$attribs['legend']?>> </text>
+ <text id="graphlast" x="<?=$width*0.55?>" y="17" <?=$attribs['legend']?>>Graph shows last <?=$time_interval*$nb_plot?> seconds</text>
+ <polygon id="axis_arrow_x" <?=$attribs['axis']?> points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
+ <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>" visibility="hidden" <?=$attribs['error']?> text-anchor="middle"><?=$error_text?></text>
+ <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>" visibility="hidden" <?=$attribs['collect_initial']?> text-anchor="middle">Collecting initial data, please wait...</text>
+ </g>
+ <script type="text/ecmascript">
+ <![CDATA[
+
+/**
+ * getURL is a proprietary Adobe function, but it's simplicity has made it very
+ * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
+ */
+if (typeof getURL == 'undefined') {
+ getURL = function(url, callback) {
+ if (!url)
+ throw 'No URL for getURL';
+
+ try {
+ if (typeof callback.operationComplete == 'function')
+ callback = callback.operationComplete;
+ } catch (e) {}
+ if (typeof callback != 'function')
+ throw 'No callback function for getURL';
+
+ var http_request = null;
+ if (typeof XMLHttpRequest != 'undefined') {
+ http_request = new XMLHttpRequest();
+ }
+ else if (typeof ActiveXObject != 'undefined') {
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+ if (!http_request)
+ throw 'Both getURL and XMLHttpRequest are undefined';
+
+ http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ callback( { success : true,
+ content : http_request.responseText,
+ contentType : http_request.getResponseHeader("Content-Type") } );
+ }
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ }
+}
+
+var SVGDoc = null;
+var last_ifin = 0;
+var last_ifout = 0;
+var last_ugmt = 0;
var max = 0;
-plot_in=new Array();
-plot_out=new Array();
+var plot_in = new Array();
+var plot_out = new Array();
-var isfirst=1;
-var index_plot=0;
-var step = <?=$width?> / <?=$nb_plot?> ;
+var max_num_points = <?=$nb_plot?>; // maximum number of plot data points
+var step = <?=$width?> / max_num_points ;
var unit = 'bits';
var scale_type = '<?=$scale_type?>';
function init(evt) {
- SVGDoc = evt.getTarget().getOwnerDocument();
- SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
- SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
+ SVGDoc = evt.target.ownerDocument;
+ SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
+ SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
- go();
+ fetch_data();
}
function switch_unit(event)
{
- SVGDoc.getElementById('switch_unit').getFirstChild().setData('Switch to ' + unit + '/s');
- if(unit=='bits') unit='bytes';else unit='bits';
+ SVGDoc.getElementById('switch_unit').firstChild.data = 'Switch to ' + unit + '/s';
+ unit = (unit == 'bits') ? 'bytes' : 'bits';
}
function switch_scale(event)
{
- if(scale_type=='up') scale_type='follow';else scale_type='up';
- SVGDoc.getElementById('switch_scale').getFirstChild().setData('AutoScale (' + scale_type + ')');
+ scale_type = (scale_type == 'up') ? 'follow' : 'up';
+ SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')';
}
-function go() {
- getURL('<?=$fetch_link?>',urlcallback);
+function fetch_data() {
+ getURL('<?=$fetch_link?>', plot_data);
}
-function urlcallback(obj) {
- var error = 0;
- now = new Date();
-
- //Show datetimelegend
- var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' +
- LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
- SVGDoc.getElementById('datetime').getFirstChild().setData(datetime);
-
- //shift plot to left if nb_plot is already completed
- var i=0;
- if(index_plot > <?=$nb_plot?>)
- {
- while (i <= <?=$nb_plot?>)
- {
- var a=i+1;
- plot_in[i]=plot_in[a];
- plot_out[i]=plot_out[a];
- i=i+1;
- }
- index_plot = <?=$nb_plot?>;
- plot_in[index_plot]=0;
- plot_out[index_plot]=0;
- }
-
- //if Geturl returns something
- if (obj.success){
- var t=obj.content.split("|");
- var ugmt = parseFloat(t[0]);//ugmt is an unixtimestamp style
- var ifin = parseInt(t[1]);//ifin must be in bytes
- var ifout = parseInt(t[2]);//ifout must be in bytes
- var scale;
-
- if(!isNumber(ifin) || !isNumber(ifout)) {
- goerror();
- return;
- } else {
- SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'hidden');
- }
-
- diff_ugmt = ugmt - last_ugmt;
- diff_ifin = ifin - last_ifin;
- diff_ifout = ifout - last_ifout;
-
- if (diff_ugmt == 0)
- diff_ugmt = 1; /* avoid division by zero */
-
- last_ugmt = ugmt;
- last_ifin = ifin;
- last_ifout = ifout;
-
- if(isfirst) {
- SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'visible');
- setTimeout('go()',<?=1000*$first_stage_time_interval?>);
- isfirst=0;
- return;
- } else SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'hidden');
-
- plot_in[index_plot] = diff_ifin / diff_ugmt;
- plot_out[index_plot]= diff_ifout / diff_ugmt;
-
- SVGDoc.getElementById('graph_in_txt').getFirstChild().setData(formatSpeed(plot_in[index_plot],unit));
- SVGDoc.getElementById('graph_out_txt').getFirstChild().setData(formatSpeed(plot_out[index_plot],unit));
-
- /* determine peak for sensible scaling */
- if (scale_type == 'up') {
- if (plot_in[index_plot] > max)
- max = plot_in[index_plot];
- if (plot_out[index_plot] > max)
- max = plot_out[index_plot];
- } else if (scale_type == 'follow') {
- i = 0;
- max = 0;
- while (i <= <?=$nb_plot?>) {
- if (plot_in[i] > max)
- max = plot_in[i];
- if (plot_out[i] > max)
- max = plot_out[i];
- i++;
- }
+function plot_data(obj) {
+ // Show datetimelegend
+ var now = new Date();
+ var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' +
+ LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
+ SVGDoc.getElementById('datetime').firstChild.data = datetime;
+
+ if (!obj.success)
+ return handle_error(); // getURL failed to get data
+
+ var t = obj.content.split("|");
+ var ugmt = parseFloat(t[0]); // ugmt is an unixtimestamp style
+ var ifin = parseInt(t[1]); // number of bytes received by the interface
+ var ifout = parseInt(t[2]); // number of bytes sent by the interface
+ var scale;
+
+ if (!isNumber(ifin) || !isNumber(ifout))
+ return handle_error();
+
+ var diff_ugmt = ugmt - last_ugmt;
+ var diff_ifin = ifin - last_ifin;
+ var diff_ifout = ifout - last_ifout;
+
+ if (diff_ugmt == 0)
+ diff_ugmt = 1; /* avoid division by zero */
+
+ last_ugmt = ugmt;
+ last_ifin = ifin;
+ last_ifout = ifout;
+
+ switch (plot_in.length) {
+ case 0:
+ SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
+ plot_in[0] = diff_ifin / diff_ugmt;
+ plot_out[0] = diff_ifout / diff_ugmt;
+ setTimeout('fetch_data()',<?=1000*$time_interval?>);
+ return;
+ case 1:
+ SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
+ break;
+ case max_num_points:
+ // shift plot to left if the maximum number of plot points has been reached
+ var i = 0;
+ while (i < max_num_points) {
+ plot_in[i] = plot_in[i+1];
+ plot_out[i] = plot_out[++i];
}
-
- var rmax;
-
- if (unit == 'bits') {
- /* round up max, such that
- 100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
- rmax = 12500;
- i = 0;
- while (max > rmax) {
- i++;
- if (i && (i % 4 == 0))
- rmax *= 1.25;
- else
- rmax *= 2;
- }
- } else {
- /* round up max, such that
- 10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */
- rmax = 10240;
- i = 0;
- while (max > rmax) {
- i++;
- if (i && (i % 4 == 0))
- rmax *= 1.25;
- else
- rmax *= 2;
-
- if (i == 8)
- rmax *= 1.024;
- }
- }
-
- scale = <?=$height?> / rmax;
-
- /* change labels accordingly */
- SVGDoc.getElementById('grid_txt1').getFirstChild().setData(formatSpeed(3*rmax/4,unit));
- SVGDoc.getElementById('grid_txt2').getFirstChild().setData(formatSpeed(2*rmax/4,unit));
- SVGDoc.getElementById('grid_txt3').getFirstChild().setData(formatSpeed(rmax/4,unit));
-
- i = 0;
-
- while (i <= index_plot)
- {
- var x = step * i;
- var y_in= <?=$height?> - (plot_in[i] * scale);
- var y_out= <?=$height?> - (plot_out[i] * scale);
- if(i==0) {
- var path_in = "M" + x + " " + y_in;
- var path_out = "M" + x + " " + y_out;
- }
- else
- {
- var path_in = path_in + " L" + x + " " + y_in;
- var path_out = path_out + " L" + x + " " + y_out;
- }
- i = i + 1;
- }
-
- index_plot = index_plot+1;
- SVGDoc.getElementById('graph_in').setAttribute("d", path_in);
- SVGDoc.getElementById('graph_out').setAttribute("d", path_out);
-
- setTimeout('go()',<?=1000*$time_interval?>);
- }
- else
- { //In case of Geturl fails
- goerror();
- }
+ plot_in.length--;
+ plot_out.length--;
+ }
+
+ plot_in[plot_in.length] = diff_ifin / diff_ugmt;
+ plot_out[plot_out.length]= diff_ifout / diff_ugmt;
+ var index_plot = plot_in.length - 1;
+
+ SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
+ SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);
+
+ /* determine peak for sensible scaling */
+ if (scale_type == 'up') {
+ if (plot_in[index_plot] > max)
+ max = plot_in[index_plot];
+ if (plot_out[index_plot] > max)
+ max = plot_out[index_plot];
+ }
+ else if (scale_type == 'follow') {
+ i = 0;
+ max = 0;
+ while (i < plot_in.length) {
+ if (plot_in[i] > max)
+ max = plot_in[i];
+ if (plot_out[i] > max)
+ max = plot_out[i];
+ i++;
+ }
+ }
+
+ var rmax; // max, rounded up
+
+ if (unit == 'bits') {
+ /* round up max, such that
+ 100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
+ rmax = 12500;
+ i = 0;
+ while (max > rmax) {
+ i++;
+ if (i && (i % 4 == 0))
+ rmax *= 1.25;
+ else
+ rmax *= 2;
+ }
+ } else {
+ /* round up max, such that
+ 10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */
+ rmax = 10240;
+ i = 0;
+ while (max > rmax) {
+ i++;
+ if (i && (i % 4 == 0))
+ rmax *= 1.25;
+ else
+ rmax *= 2;
+
+ if (i == 8)
+ rmax *= 1.024;
+ }
+ }
+
+ scale = <?=$height?> / rmax;
+
+ /* change labels accordingly */
+ SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit);
+ SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit);
+ SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit);
+
+ var path_in = "M 0 " + (<?=$height?> - (plot_in[0] * scale));
+ var path_out = "M 0 " + (<?=$height?> - (plot_out[0] * scale));
+ for (i = 1; i < plot_in.length; i++)
+ {
+ var x = step * i;
+ var y_in = <?=$height?> - (plot_in[i] * scale);
+ var y_out = <?=$height?> - (plot_out[i] * scale);
+ path_in += " L" + x + " " + y_in;
+ path_out += " L" + x + " " + y_out;
+ }
+
+ SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
+ SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
+ SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);
+
+ setTimeout('fetch_data()',<?=1000*$time_interval?>);
}
-function goerror() {
- SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'visible');
- setTimeout('go()',<?=1000*$time_interval?>);
+function handle_error() {
+ SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
+ setTimeout('fetch_data()',<?=1000*$time_interval?>);
}
function isNumber(a) {
- return typeof a == 'number' && isFinite(a);
+ return typeof a == 'number' && isFinite(a);
}
-function formatSpeed(speed,unit){
- if(unit=='bits') return formatSpeedBits(speed);
- else if(unit=='bytes') return formatSpeedBytes(speed);
+function formatSpeed(speed, unit) {
+ if (unit == 'bits')
+ return formatSpeedBits(speed);
+ if (unit == 'bytes')
+ return formatSpeedBytes(speed);
}
function formatSpeedBits(speed) {
- // format speed in bits/sec, input: bytes/sec
- if (speed < 125000)
- return Math.round(speed / 125) + " Kbps";
- else if (speed < 125000000)
- return Math.round(speed / 1250)/100 + " Mbps";
- else
- return Math.round(speed / 1250000)/100 + " Gbps"; /* wow! */
+ // format speed in bits/sec, input: bytes/sec
+ if (speed < 125000)
+ return Math.round(speed / 125) + " Kbps";
+ if (speed < 125000000)
+ return Math.round(speed / 1250)/100 + " Mbps";
+ // else
+ return Math.round(speed / 1250000)/100 + " Gbps"; /* wow! */
}
+
function formatSpeedBytes(speed) {
- // format speed in bytes/sec, input: bytes/sec
- if (speed < 1048576)
- return Math.round(speed / 10.24)/100 + " KB/s";
- else if (speed < 1073741824)
- return Math.round(speed / 10485.76)/100 + " MB/s";
- else
- return Math.round(speed / 10737418.24)/100 + " GB/s"; /* wow! */
+ // format speed in bytes/sec, input: bytes/sec
+ if (speed < 1048576)
+ return Math.round(speed / 10.24)/100 + " KB/s";
+ if (speed < 1073741824)
+ return Math.round(speed / 10485.76)/100 + " MB/s";
+ // else
+ return Math.round(speed / 10737418.24)/100 + " GB/s"; /* wow! */
}
+
function LZ(x) {
- return (x < 0 || x > 9 ? "" : "0") + x
+ return (x < 0 || x > 9 ? "" : "0") + x;
}
-]]></script>
-</svg>
\ No newline at end of file
+
+ ]]>
+ </script>
+</svg>
graph_cpu.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2004-2005 T. Lechat <dev@lechat.org> and Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
+ and Jonathan Watt <jwatt@jwatt.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
POSSIBILITY OF SUCH DAMAGE.
*/
+header("Content-type: image/svg+xml");
+
/********* Other conf *******/
-$nb_plot=120; //NB plot in graph
+$nb_plot = 120; // maximum number of data points to plot in the graph
$fetch_link = "stats.cgi?cpu";
-//Style
-$style['bg']="fill:white;stroke:none;stroke-width:0;opacity:1;";
-$style['axis']="fill:black;stroke:black;stroke-width:1;";
-$style['cpu']="fill:#435370; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
-$style['graph_cpu']="fill:none;stroke:#435370;stroke-width:1;opacity:0.8;";
-$style['legend']="fill:black; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
-$style['grid_txt']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:6;";
-$style['grid']="stroke:gray;stroke-width:1;opacity:0.5;";
-$style['error']="fill:blue; font-family:Arial; font-size:4;";
-$style['collect_initial']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
+//SVG attributes
+$attribs['axis']='fill="black" stroke="black"';
+$attribs['cpu']='fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
+$attribs['graph_cpu']='fill="none" stroke="#435370" stroke-opacity="0.8"';
+$attribs['legend']='fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
+$attribs['grid_txt']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"';
+$attribs['grid']='stroke="gray" stroke-opacity="0.5"';
+$attribs['error']='fill="blue" font-family="Arial" font-size="4"';
+$attribs['collect_initial']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
-$error_text = "Cannot get CPU load";
-
-$height=100; //SVG internal height : do not modify
-$width=200; //SVG internal width : do not modify
+$height=100; // SVG internal height : do not modify
+$width=200; // SVG internal width : do not modify
/********* Graph DATA **************/
-header("Content-type: image/svg+xml");
-print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?><svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
-<g id="graph" style="visibility:visible">
- <rect id="bg" x1="0" y1="0" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['bg']?>"/>
- <line id="axis_x" x1="0" y1="0" x2="0" y2="<?=$height?>" style="<?=$style['axis']?>"/>
- <line id="axis_y" x1="0" y1="<?=$height?>" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['axis']?>"/>
- <path id="graph_cpu" d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_cpu']?>"/>
- <path id="grid" d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" style="<?=$style[grid]?>"/>
- <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" style="<?=$style['grid_txt']?> text-anchor:end">75%</text>
- <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" style="<?=$style['grid_txt']?> text-anchor:end">50%</text>
- <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" style="<?=$style['grid_txt']?> text-anchor:end">25%</text>
- <text id="graph_cpu_txt" x="4" y="8" style="<?=$style['cpu']?>"> </text>
- <polygon id="axis_arrow_x" style="<?=$style['axis']?>" points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
- <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>" style="visibility:hidden;<?=$style['error']?> text-anchor:middle"><?=$error_text?></text>
- <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>" style="visibility:hidden;<?=$style['collect_initial']?> text-anchor:middle">Collecting initial data, please wait...</text>
-</g>
-
-<script type="text/ecmascript"><![CDATA[
-var SVGDoc;
-var last_cpu_total=0;
-var last_cpu_idle=0;
-var diff_cpu_total=0;
-var diff_cpu_idle=0;
-plot_cpu = new Array();
-
-var isfirst=1;
-var index_plot=0;
-var step = <?=$width?> / <?=$nb_plot?> ;
+print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?>
+<svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt);">
+ <g id="graph">
+ <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/>
+ <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?=$attribs['axis']?>/>
+ <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?=$attribs['axis']?>/>
+ <polygon id="axis_arrow_x" <?=$attribs['axis']?> points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
+ <path id="graph_cpu" d="" <?=$attribs['graph_cpu']?>/>
+ <path id="grid" d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" <?=$attribs['grid']?>/>
+ <text id="grid_txt1" x="100%" y="25%" <?=$attribs['grid_txt']?> text-anchor="end">75%</text>
+ <text id="grid_txt2" x="100%" y="50%" <?=$attribs['grid_txt']?> text-anchor="end">50%</text>
+ <text id="grid_txt3" x="100%" y="75%" <?=$attribs['grid_txt']?> text-anchor="end">25%</text>
+ <text id="graph_cpu_txt" x="4" y="8" <?=$attribs['cpu']?>> </text>
+ <text id="error" x="50%" y="50%" visibility="hidden" <?=$attribs['error']?> text-anchor="middle">Cannot get CPU load</text>
+ <text id="collect_initial" x="50%" y="50%" visibility="hidden" <?=$attribs['collect_initial']?> text-anchor="middle">Collecting initial data, please wait...</text>
+ </g>
+ <script type="text/ecmascript">
+ <![CDATA[
+
+/**
+ * getURL is a proprietary Adobe function, but it's simplicity has made it very
+ * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
+ */
+if (typeof getURL == 'undefined') {
+ getURL = function(url, callback) {
+ if (!url)
+ throw 'No URL for getURL';
+
+ try {
+ if (typeof callback.operationComplete == 'function')
+ callback = callback.operationComplete;
+ } catch (e) {}
+ if (typeof callback != 'function')
+ throw 'No callback function for getURL';
+
+ var http_request = null;
+ if (typeof XMLHttpRequest != 'undefined') {
+ http_request = new XMLHttpRequest();
+ }
+ else if (typeof ActiveXObject != 'undefined') {
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+ if (!http_request)
+ throw 'Both getURL and XMLHttpRequest are undefined';
+
+ http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ callback( { success : true,
+ content : http_request.responseText,
+ contentType : http_request.getResponseHeader("Content-Type") } );
+ }
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ }
+}
+
+var SVGDoc = null;
+var last_cpu_total = 0;
+var last_cpu_idle = 0;
+var diff_cpu_total = 0;
+var diff_cpu_idle = 0;
+var cpu_data = new Array();
+
+var max_num_points = <?=$nb_plot?>; // maximum number of plot data points
+var step = <?=$width?> / max_num_points; // plot X division size
+var scale = <?=$height?> / 100;
function init(evt) {
- SVGDoc = evt.getTarget().getOwnerDocument();
- go();
+ SVGDoc = evt.target.ownerDocument;
+ fetch_data();
}
-function go() {
- getURL('<?=$fetch_link?>',urlcallback);
+function fetch_data() {
+ getURL('<?=$fetch_link?>', plot_cpu_data);
}
-function urlcallback(obj) {
- var error = 0;
-
- //shift plot to left if nb_plot is already completed
- var i=0;
- if(index_plot > <?=$nb_plot?>)
- {
- while (i <= <?=$nb_plot?>)
- {
- var a=i+1;
- plot_cpu[i]=plot_cpu[a];
- i=i+1;
- }
- index_plot = <?=$nb_plot?>;
- plot_cpu[index_plot]=0;
- }
-
- //if Geturl returns something
- if (obj.success){
- var cpu = parseInt(obj.content);
- var scale;
-
- if(!isNumber(cpu)) {
- goerror();
- return;
- } else {
- SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'hidden');
- }
-
- if(isfirst) {
- SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'visible');
- go();
- isfirst=0;
- return;
- } else SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'hidden');
-
- plot_cpu[index_plot] = cpu;
-
- SVGDoc.getElementById('graph_cpu_txt').getFirstChild().setData(plot_cpu[index_plot] + '%');
-
- scale = <?=$height?> / 100;
-
- i = 0;
-
- while (i <= index_plot)
- {
- var x = step * i;
- var y_cpu= <?=$height?> - (plot_cpu[i] * scale);
- if(i==0) {
- var path_cpu = "M" + x + " " + y_cpu;
- }
- else
- {
- var path_cpu = path_cpu + " L" + x + " " + y_cpu;
- }
- i = i + 1;
- }
-
- index_plot = index_plot+1;
- SVGDoc.getElementById('graph_cpu').setAttribute("d", path_cpu);
-
- go();
- }
- else
- { //In case of Geturl fails
- goerror();
- }
+function plot_cpu_data(obj) {
+ if (!obj.success)
+ return handle_error(); // getURL failed to get current CPU load data
+
+ var cpu = parseInt(obj.content);
+ if (!isNumber(cpu))
+ return handle_error();
+
+ switch (cpu_data.length) {
+ case 0:
+ SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
+ cpu_data[0] = cpu;
+ fetch_data();
+ return;
+ case 1:
+ SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
+ break;
+ case max_num_points:
+ // shift plot to left if the maximum number of plot points has been reached
+ var i = 0;
+ while (i < max_num_points) {
+ cpu_data[i] = cpu_data[++i];
+ }
+ --cpu_data.length;
+ }
+
+ cpu_data[cpu_data.length] = cpu;
+
+ var path_data = "M 0 " + (<?=$height?> - (cpu_data[0] * scale));
+ for (var i = 1; i < cpu_data.length; ++i) {
+ var x = step * i;
+ var y_cpu = <?=$height?> - (cpu_data[i] * scale);
+ path_data += " L" + x + " " + y_cpu;
+ }
+
+ SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'hidden');
+ SVGDoc.getElementById('graph_cpu_txt').firstChild.data = cpu + '%';
+ SVGDoc.getElementById('graph_cpu').setAttributeNS(null, "d", path_data);
+
+ fetch_data();
}
-function goerror() {
- SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'visible');
- go();
+function handle_error() {
+ SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
+ fetch_data();
}
function isNumber(a) {
- return typeof a == 'number' && isFinite(a);
+ return typeof a == 'number' && isFinite(a);
}
-function LZ(x) {
- return (x < 0 || x > 9 ? "" : "0") + x
-}
-]]></script>
-</svg>
\ No newline at end of file
+ ]]>
+ </script>
+</svg>
font-size: 10px;
font-weight: bold;
}
+.formbtns {
+ font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
+ font-size: 9px;
+ font-weight: bold;
+}
+textarea.notes {
+ font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+}
.vvcell {
background-color: #FFFFC6;
}
padding-top: 2px;
padding-bottom: 2px;
}
+.optsect_t2 {
+ border-right: 1px solid #999999;
+ background-color: #435370;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ font-size: 11px;
+ color: #FFFFFF;
+ font-weight: bold;
+}
.optsect_s {
font-size: 11px;
color: #FFFFFF;
guiconfig.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
usort($config['captiveportal']['allowedip'],"allowedipscmp");
}
+function cpelements_sort() {
+ global $g, $config;
+
+ function cpelementscmp($a, $b) {
+ return strcasecmp($a['name'], $b['name']);
+ }
+
+ usort($config['captiveportal']['element'],"cpelementscmp");
+}
+
function wol_sort() {
global $g, $config;
index.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
fclose($fd);
}
+if ($_POST) {
+ $config['system']['notes'] = base64_encode($_POST['notes']);
+ write_config();
+ header("Location: index.php");
+ exit;
+}
+
?>
<?php include("fbegin.inc"); ?>
+<form action="" method="POST">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr align="center" valign="top">
<td height="10" colspan="2"> </td>
?>
</td>
</tr>
+ <tr>
+ <td width="25%" class="vncellt" valign="top">Notes</td>
+ <td width="75%" class="listr">
+ <textarea name="notes" cols="75" rows="7" id="notes" class="notes"><?=htmlspecialchars(base64_decode($config['system']['notes']));?></textarea><br>
+ <input name="Submit" type="submit" class="formbtns" value="Save">
+ </td>
+ </tr>
</table>
+</form>
<?php include("fend.inc"); ?>
part of m0n0wall (http://m0n0.ch/wall)
Written by Jim McBeath based on existing m0n0wall files
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_lan.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_opt.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_vlan.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_vlan_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_wan.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
interfaces_wlan.inc
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
require("guiconfig.inc");
?>
<?php include("fbegin.inc"); ?>
- <p><strong>m0n0wall is Copyright © 2002-2005 by Manuel Kasper
+ <p><strong>m0n0wall is Copyright © 2002-2006 by Manuel Kasper
(<a href="mailto:mk@neon1.net">mk@neon1.net</a>).<br>
All rights reserved.</strong></p>
<p> Redistribution and use in source and binary forms, with or without<br>
<br>
Paul Taylor (<a href="mailto:paultaylor@winn-dixie.com">paultaylor@winn-dixie.com</a>)<br>
<em><font color="#666666">ARP table, Traceroute and Filter state pages</font></em><br>
+ <em><font color="#666666">captive portal: disable concurrent logins, file manager</font></em><br>
<br>
Jonathan De Graeve (<a href="mailto:Jonathan.De.Graeve@imelda.be">Jonathan.De.Graeve@imelda.be</a>)<br>
- <em><font color="#666666">captive portal RADIUS accounting gigawords</font></em></p>
+ <em><font color="#666666">complete captive portal RADIUS overhaul; file manager</font></em></p>
<hr size="1">
<p>m0n0wall is based upon/includes various free software packages,
listed below.<br>
This product includes software developed by Edwin Groothuis.<br>
<br>
wol (<a href="http://ahh.sourceforge.net/wol" target="_blank">http://ahh.sourceforge.net/wol</a>)<br>
- Copyright © 2000,2001,2002,2003,2004 Thomas Krennwallner <krennwallner@aon.at>
+ Copyright © 2000,2001,2002,2003,2004 Thomas Krennwallner <krennwallner@aon.at><br>
+ <br>
+ PHP RADIUS PECL package<br>
+ Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>. All rights reserved.
<?php include("fend.inc"); ?>
reboot.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_captiveportal.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
}
$pconfig['cinterface'] = $config['captiveportal']['interface'];
+$pconfig['maxproc'] = $config['captiveportal']['maxproc'];
+$pconfig['maxprocperip'] = $config['captiveportal']['maxprocperip'];
$pconfig['timeout'] = $config['captiveportal']['timeout'];
$pconfig['idletimeout'] = $config['captiveportal']['idletimeout'];
$pconfig['enable'] = isset($config['captiveportal']['enable']);
$pconfig['auth_method'] = $config['captiveportal']['auth_method'];
$pconfig['radacct_enable'] = isset($config['captiveportal']['radacct_enable']);
+$pconfig['radmac_enable'] = isset($config['captiveportal']['radmac_enable']);
+$pconfig['radmac_secret'] = $config['captiveportal']['radmac_secret'];
$pconfig['reauthenticate'] = isset($config['captiveportal']['reauthenticate']);
$pconfig['reauthenticateacct'] = $config['captiveportal']['reauthenticateacct'];
$pconfig['httpslogin_enable'] = isset($config['captiveportal']['httpslogin']);
$pconfig['key'] = base64_decode($config['captiveportal']['private-key']);
$pconfig['logoutwin_enable'] = isset($config['captiveportal']['logoutwin_enable']);
$pconfig['nomacfilter'] = isset($config['captiveportal']['nomacfilter']);
+$pconfig['noconcurrentlogins'] = isset($config['captiveportal']['noconcurrentlogins']);
$pconfig['redirurl'] = $config['captiveportal']['redirurl'];
$pconfig['radiusip'] = $config['captiveportal']['radiusip'];
+$pconfig['radiusip2'] = $config['captiveportal']['radiusip2'];
$pconfig['radiusport'] = $config['captiveportal']['radiusport'];
+$pconfig['radiusport2'] = $config['captiveportal']['radiusport2'];
$pconfig['radiusacctport'] = $config['captiveportal']['radiusacctport'];
$pconfig['radiuskey'] = $config['captiveportal']['radiuskey'];
+$pconfig['radiuskey2'] = $config['captiveportal']['radiuskey2'];
+$pconfig['radiusvendor'] = $config['captiveportal']['radiusvendor'];
+$pconfig['radiussession_timeout'] = isset($config['captiveportal']['radiussession_timeout']);
if ($_POST) {
if (($_POST['radiusip'] && !is_ipaddr($_POST['radiusip']))) {
$input_errors[] = "A valid IP address must be specified. [".$_POST['radiusip']."]";
}
+ if (($_POST['radiusip2'] && !is_ipaddr($_POST['radiusip2']))) {
+ $input_errors[] = "A valid IP address must be specified. [".$_POST['radiusip2']."]";
+ }
if (($_POST['radiusport'] && !is_port($_POST['radiusport']))) {
$input_errors[] = "A valid port number must be specified. [".$_POST['radiusport']."]";
}
+ if (($_POST['radiusport2'] && !is_port($_POST['radiusport2']))) {
+ $input_errors[] = "A valid port number must be specified. [".$_POST['radiusport2']."]";
+ }
if (($_POST['radiusacctport'] && !is_port($_POST['radiusacctport']))) {
- $input_errors[] = "A valid port number must be specified. [".$_POST['radiusport']."]";
+ $input_errors[] = "A valid port number must be specified. [".$_POST['radiusacctport']."]";
+ }
+ if ($_POST['maxproc'] && (!is_numeric($_POST['maxproc']) || ($_POST['maxproc'] < 4) || ($_POST['maxproc'] > 100))) {
+ $input_errors[] = "The total maximum number of concurrent connections must be between 4 and 100.";
+ }
+ $mymaxproc = $_POST['maxproc'] ? $_POST['maxproc'] : 16;
+ if ($_POST['maxprocperip'] && (!is_numeric($_POST['maxprocperip']) || ($_POST['maxprocperip'] > $mymaxproc))) {
+ $input_errors[] = "The maximum number of concurrent connections per client IP address may not be larger than the global maximum.";
}
if (!$input_errors) {
$config['captiveportal']['interface'] = $_POST['cinterface'];
+ $config['captiveportal']['maxproc'] = $_POST['maxproc'];
+ $config['captiveportal']['maxprocperip'] = $_POST['maxprocperip'] ? $_POST['maxprocperip'] : false;
$config['captiveportal']['timeout'] = $_POST['timeout'];
$config['captiveportal']['idletimeout'] = $_POST['idletimeout'];
$config['captiveportal']['enable'] = $_POST['enable'] ? true : false;
$config['captiveportal']['auth_method'] = $_POST['auth_method'];
$config['captiveportal']['radacct_enable'] = $_POST['radacct_enable'] ? true : false;
$config['captiveportal']['reauthenticate'] = $_POST['reauthenticate'] ? true : false;
+ $config['captiveportal']['radmac_enable'] = $_POST['radmac_enable'] ? true : false;
+ $config['captiveportal']['radmac_secret'] = $_POST['radmac_secret'] ? $_POST['radmac_secret'] : false;
$config['captiveportal']['reauthenticateacct'] = $_POST['reauthenticateacct'];
$config['captiveportal']['httpslogin'] = $_POST['httpslogin_enable'] ? true : false;
$config['captiveportal']['httpsname'] = $_POST['httpsname'];
$config['captiveportal']['private-key'] = base64_encode($_POST['key']);
$config['captiveportal']['logoutwin_enable'] = $_POST['logoutwin_enable'] ? true : false;
$config['captiveportal']['nomacfilter'] = $_POST['nomacfilter'] ? true : false;
+ $config['captiveportal']['noconcurrentlogins'] = $_POST['noconcurrentlogins'] ? true : false;
$config['captiveportal']['redirurl'] = $_POST['redirurl'];
$config['captiveportal']['radiusip'] = $_POST['radiusip'];
+ $config['captiveportal']['radiusip2'] = $_POST['radiusip2'];
$config['captiveportal']['radiusport'] = $_POST['radiusport'];
+ $config['captiveportal']['radiusport2'] = $_POST['radiusport2'];
$config['captiveportal']['radiusacctport'] = $_POST['radiusacctport'];
$config['captiveportal']['radiuskey'] = $_POST['radiuskey'];
+ $config['captiveportal']['radiuskey2'] = $_POST['radiuskey2'];
+ $config['captiveportal']['radiusvendor'] = $_POST['radiusvendor'] ? $_POST['radiusvendor'] : false;
+ $config['captiveportal']['radiussession_timeout'] = $_POST['radiussession_timeout'] ? true : false;
/* file upload? */
if (is_uploaded_file($_FILES['htmlfile']['tmp_name']))
<script language="JavaScript">
<!--
function enable_change(enable_change) {
- var endis;
+ var endis, radius_endis;
endis = !(document.iform.enable.checked || enable_change);
+ radius_endis = !((!endis && document.iform.auth_method[2].checked) || enable_change);
document.iform.cinterface.disabled = endis;
+ document.iform.maxproc.disabled = endis;
+ document.iform.maxprocperip.disabled = endis;
document.iform.idletimeout.disabled = endis;
document.iform.timeout.disabled = endis;
document.iform.redirurl.disabled = endis;
- document.iform.radiusip.disabled = endis;
- document.iform.radiusport.disabled = endis;
- document.iform.radiuskey.disabled = endis;
- document.iform.radacct_enable.disabled = endis;
- document.iform.radiusacctport.disabled = endis;
- document.iform.reauthenticate.disabled = endis;
- document.iform.reauthenticateacct.disabled = endis;
+ document.iform.radiusip.disabled = radius_endis;
+ document.iform.radiusip2.disabled = radius_endis;
+ document.iform.radiusport.disabled = radius_endis;
+ document.iform.radiusport2.disabled = radius_endis;
+ document.iform.radiuskey.disabled = radius_endis;
+ document.iform.radiuskey2.disabled = radius_endis;
+ document.iform.radacct_enable.disabled = radius_endis;
+ document.iform.reauthenticate.disabled = radius_endis;
document.iform.auth_method[0].disabled = endis;
document.iform.auth_method[1].disabled = endis;
document.iform.auth_method[2].disabled = endis;
+ document.iform.radmac_enable.disabled = radius_endis;
document.iform.httpslogin_enable.disabled = endis;
document.iform.httpsname.disabled = endis;
document.iform.cert.disabled = endis;
document.iform.key.disabled = endis;
document.iform.logoutwin_enable.disabled = endis;
document.iform.nomacfilter.disabled = endis;
+ document.iform.noconcurrentlogins.disabled = endis;
+ document.iform.radiusvendor.disabled = radius_endis;
+ document.iform.radiussession_timeout.disabled = radius_endis;
document.iform.htmlfile.disabled = endis;
document.iform.errfile.disabled = endis;
+
+ document.iform.radiusacctport.disabled = (radius_endis || !document.iform.radacct_enable.checked) && !enable_change;
+
+ document.iform.radmac_secret.disabled = (radius_endis || !document.iform.radmac_enable.checked) && !enable_change;
+
+ var reauthenticate_dis = (radius_endis || !document.iform.reauthenticate.checked) && !enable_change;
+ document.iform.reauthenticateacct[0].disabled = reauthenticate_dis;
+ document.iform.reauthenticateacct[1].disabled = reauthenticate_dis;
+ document.iform.reauthenticateacct[2].disabled = reauthenticate_dis;
}
//-->
</script>
<li class="tabinact"><a href="services_captiveportal_mac.php">Pass-through MAC</a></li>
<li class="tabinact"><a href="services_captiveportal_ip.php">Allowed IP addresses</a></li>
<li class="tabinact"><a href="services_captiveportal_users.php">Users</a></li>
+ <li class="tabinact"><a href="services_captiveportal_filemanager.php">File manager</a></li>
</ul>
</td></tr>
<tr>
</select> <br>
<span class="vexpl">Choose which interface to run the captive portal on.</span></td>
</tr>
+ <tr>
+ <td valign="top" class="vncell">Maximum concurrent connections</td>
+ <td class="vtable">
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ <td><input name="maxprocperip" type="text" class="formfld" id="maxprocperip" size="5" value="<?=htmlspecialchars($pconfig['maxprocperip']);?>"> per client IP address (0 = no limit)</td>
+ </tr>
+ <tr>
+ <td><input name="maxproc" type="text" class="formfld" id="maxproc" size="5" value="<?=htmlspecialchars($pconfig['maxproc']);?>"> total</td>
+ </tr>
+ </table>
+This setting limits the number of concurrent connections to the captive portal HTTP(S) server. This does not set how many users can be logged in
+to the captive portal, but rather how many users can load the portal page or authenticate at the same time!
+Default is 4 connections per client IP address, with a total maximum of 16 connections.</td>
+ </tr>
<tr>
<td valign="top" class="vncell">Idle timeout</td>
<td class="vtable">
to access after they've authenticated.</td>
</tr>
<tr>
+ <td valign="top" class="vncell">Concurrent user logins</td>
+ <td class="vtable">
+ <input name="noconcurrentlogins" type="checkbox" class="formfld" id="noconcurrentlogins" value="yes" <?php if ($pconfig['noconcurrentlogins']) echo "checked"; ?>>
+ <strong>Disable concurrent logins</strong><br>
+ If this option is set, only the most recent login per username will be active. Subsequent logins will cause machines previously logged in with the same username to be disconnected.</td>
+ </tr>
+ <tr>
<td valign="top" class="vncell">MAC filtering </td>
<td class="vtable">
<input name="nomacfilter" type="checkbox" class="formfld" id="nomacfilter" value="yes" <?php if ($pconfig['nomacfilter']) echo "checked"; ?>>
<strong>Disable MAC filtering</strong><br>
- If this option is set, no attempts will be made to ensure that the MAC address of clients stays the same while they're logged in. This is required when the MAC address of cannot be determined (usually because there are routers between m0n0wall and the clients).</td>
+ If this option is set, no attempts will be made to ensure that the MAC address of clients stays the same while they're logged in.
+ This is required when the MAC address of the client cannot be determined (usually because there are routers between m0n0wall and the clients).
+ If this is enabled, RADIUS MAC authentication cannot be used.</td>
</tr>
<tr>
<td width="22%" valign="top" class="vncell">Authentication</td>
<td width="78%" class="vtable">
<table cellpadding="0" cellspacing="0">
<tr>
- <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="none" <?php if($pconfig['auth_method']!="local" && $pconfig['auth_method']!="radius") echo "checked"; ?>>
+ <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="none" onClick="enable_change(false)" <?php if($pconfig['auth_method']!="local" && $pconfig['auth_method']!="radius") echo "checked"; ?>>
No authentication</td>
</tr>
<tr>
- <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="local" <?php if($pconfig['auth_method']=="local") echo "checked"; ?>>
+ <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="local" onClick="enable_change(false)" <?php if($pconfig['auth_method']=="local") echo "checked"; ?>>
Local <a href="services_captiveportal_users.php">user manager</a></td>
</tr>
<tr>
- <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="radius" <?php if($pconfig['auth_method']=="radius") echo "checked"; ?>>
+ <td colspan="2"><input name="auth_method" type="radio" id="auth_method" value="radius" onClick="enable_change(false)" <?php if($pconfig['auth_method']=="radius") echo "checked"; ?>>
RADIUS authentication</td>
</tr><tr>
<td> </td>
<td> </td>
</tr>
- <tr>
- <td>IP address:</td>
- <td><input name="radiusip" type="text" class="formfld" id="radiusip" size="20" value="<?=htmlspecialchars($pconfig['radiusip']);?>"></td>
- </tr><tr>
- <td>Port:</td>
- <td><input name="radiusport" type="text" class="formfld" id="radiusport" size="5" value="<?=htmlspecialchars($pconfig['radiusport']);?>"></td>
- </tr><tr>
- <td>Shared secret: </td>
- <td><input name="radiuskey" type="text" class="formfld" id="radiuskey" size="16" value="<?=htmlspecialchars($pconfig['radiuskey']);?>"> </td>
- </tr>
- <tr>
- <td>Accounting: </td>
- <td><input name="radacct_enable" type="checkbox" id="radacct_enable" value="yes" <?php if($pconfig['radacct_enable']) echo "checked"; ?>>
- send RADIUS accounting packets</td>
- </tr>
- <tr>
- <td>Accounting port: </td>
- <td><input name="radiusacctport" type="text" class="formfld" id="radiusacctport" size="5" value="<?=htmlspecialchars($pconfig['radiusacctport']);?>"></td>
- </tr>
- <tr>
- <td valign="top">Reauthentication: </td>
- <td><input name="reauthenticate" type="checkbox" id="reauthenticate" value="yes" <?php if($pconfig['reauthenticate']) echo "checked"; ?>>
- reauthenticate connected users every minute<br><br>
- <input name="reauthenticateacct" type="radio" value="" <?php if(!$pconfig['reauthenticateacct']) echo "checked"; ?>> no accounting updates<br>
- <input name="reauthenticateacct" type="radio" value="stopstart" <?php if($pconfig['reauthenticateacct'] == "stopstart") echo "checked"; ?>> stop/start accounting<br>
- <input name="reauthenticateacct" type="radio" value="interimupdate" <?php if($pconfig['reauthenticateacct'] == "interimupdate") echo "checked"; ?>> interim update</td>
- </tr>
</table>
- <br>
- When using RADIUS authentication, enter the IP address and port of the RADIUS server which users of the captive portal have to authenticate against. Leave port number blank to use the default port (1812). Leave the RADIUS shared secret blank to not use a RADIUS shared secret. RADIUS accounting packets will also be sent to the RADIUS server if accounting is enabled (default port is 1813).
- <br><br>If reauthentication is enabled, Access-Requests will be sent to the RADIUS server for each user that is logged in every minute. If an Access-Reject is received for a user, that user is disconnected from the captive portal immediately.
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">Primary RADIUS server</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">IP address</td>
+ <td class="vtable"><input name="radiusip" type="text" class="formfld" id="radiusip" size="20" value="<?=htmlspecialchars($pconfig['radiusip']);?>"><br>
+ Enter the IP address of the RADIUS server which users of the captive portal have to authenticate against.</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Port</td>
+ <td class="vtable"><input name="radiusport" type="text" class="formfld" id="radiusport" size="5" value="<?=htmlspecialchars($pconfig['radiusport']);?>"><br>
+ Leave this field blank to use the default port (1812).</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Shared secret </td>
+ <td class="vtable"><input name="radiuskey" type="text" class="formfld" id="radiuskey" size="16" value="<?=htmlspecialchars($pconfig['radiuskey']);?>"><br>
+ Leave this field blank to not use a RADIUS shared secret (not recommended).</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">Secondary RADIUS server</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">IP address</td>
+ <td class="vtable"><input name="radiusip2" type="text" class="formfld" id="radiusip2" size="20" value="<?=htmlspecialchars($pconfig['radiusip2']);?>"><br>
+ If you have a second RADIUS server, you can activate it by entering its IP address here.</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Port</td>
+ <td class="vtable"><input name="radiusport2" type="text" class="formfld" id="radiusport2" size="5" value="<?=htmlspecialchars($pconfig['radiusport2']);?>"></td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Shared secret </td>
+ <td class="vtable"><input name="radiuskey2" type="text" class="formfld" id="radiuskey2" size="16" value="<?=htmlspecialchars($pconfig['radiuskey2']);?>"></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">Accounting</td>
+ </tr>
+ <tr>
+ <td class="vncell"> </td>
+ <td class="vtable"><input name="radacct_enable" type="checkbox" id="radacct_enable" value="yes" onClick="enable_change(false)" <?php if($pconfig['radacct_enable']) echo "checked"; ?>>
+ <strong>send RADIUS accounting packets</strong><br>
+ If this is enabled, RADIUS accounting packets will be sent to the primary RADIUS server.</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Accounting port</td>
+ <td class="vtable"><input name="radiusacctport" type="text" class="formfld" id="radiusacctport" size="5" value="<?=htmlspecialchars($pconfig['radiusacctport']);?>"><br>
+ Leave blank to use the default port (1813).</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">Reauthentication</td>
+ </tr>
+ <tr>
+ <td class="vncell"> </td>
+ <td class="vtable"><input name="reauthenticate" type="checkbox" id="reauthenticate" value="yes" onClick="enable_change(false)" <?php if($pconfig['reauthenticate']) echo "checked"; ?>>
+ <strong>Reauthenticate connected users every minute</strong><br>
+ If reauthentication is enabled, Access-Requests will be sent to the RADIUS server for each user that is
+ logged in every minute. If an Access-Reject is received for a user, that user is disconnected from the captive portal immediately.</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Accounting updates</td>
+ <td class="vtable">
+ <input name="reauthenticateacct" type="radio" value="" <?php if(!$pconfig['reauthenticateacct']) echo "checked"; ?>> no accounting updates<br>
+ <input name="reauthenticateacct" type="radio" value="stopstart" <?php if($pconfig['reauthenticateacct'] == "stopstart") echo "checked"; ?>> stop/start accounting<br>
+ <input name="reauthenticateacct" type="radio" value="interimupdate" <?php if($pconfig['reauthenticateacct'] == "interimupdate") echo "checked"; ?>> interim update
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">RADIUS MAC authentication</td>
+ </tr>
+ <tr>
+ <td class="vncell"> </td>
+ <td class="vtable">
+ <input name="radmac_enable" type="checkbox" id="radmac_enable" value="yes" onClick="enable_change(false)" <?php if ($pconfig['radmac_enable']) echo "checked"; ?>><strong>Enable RADIUS MAC authentication</strong><br>
+ If this option is enabled, the captive portal will try to authenticate users by sending their MAC address as the username and the password
+ entered below to the RADIUS server.</td>
+ </tr>
+ <tr>
+ <td class="vncell">Shared secret</td>
+ <td class="vtable"><input name="radmac_secret" type="text" class="formfld" id="radmac_secret" size="16" value="<?=htmlspecialchars($pconfig['radmac_secret']);?>"></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="optsect_t2">RADIUS options</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Session-Timeout</td>
+ <td class="vtable"><input name="radiussession_timeout" type="checkbox" id="radiussession_timeout" value="yes" <?php if ($pconfig['radiussession_timeout']) echo "checked"; ?>><strong>Use RADIUS Session-Timeout attributes</strong><br>
+ When this is enabled, clients will be disconnected after the amount of time retrieved from the RADIUS Session-Timeout attribute.</td>
+ </tr>
+ <tr>
+ <td class="vncell" valign="top">Type</td>
+ <td class="vtable"><select name="radiusvendor" id="radiusvendor">
+ <option>default</option>
+ <?php
+ $radiusvendors = array("cisco");
+ foreach ($radiusvendors as $radiusvendor){
+ if ($pconfig['radiusvendor'] == $radiusvendor)
+ echo "<option selected value=\"$radiusvendor\">$radiusvendor</option>\n";
+ else
+ echo "<option value=\"$radiusvendor\">$radiusvendor</option>\n";
+ }
+ ?></select><br>
+ If RADIUS type is set to Cisco, in Access-Requests the value of Calling-Station-Id will be set to the client's IP address and
+ the Called-Station-Id to the client's MAC address. Default behaviour is Calling-Station-Id = client's MAC address and Called-Station-Id = m0n0wall's WAN IP address.</td>
+ </tr>
+ </table>
</tr>
<tr>
<td valign="top" class="vncell">HTTPS login</td>
<td class="vtable">
<input name="httpslogin_enable" type="checkbox" class="formfld" id="httpslogin_enable" value="yes" <?php if($pconfig['httpslogin_enable']) echo "checked"; ?>>
<strong>Enable HTTPS login</strong><br>
- If enabled, the username and password will be transmitted over an HTTPS connection to protect against eavesdroppers. This option only applies when RADIUS authentication is used. A server name, certificate and matching private key must also be specified below.</td>
+ If enabled, the username and password will be transmitted over an HTTPS connection to protect against eavesdroppers. A server name, certificate and matching private key must also be specified below.</td>
</tr>
<tr>
<td valign="top" class="vncell">HTTPS server name </td>
<br>
<?php endif; ?>
Upload an HTML file for the portal page here (leave blank to keep the current one). Make sure to include a form (POST to "$PORTAL_ACTION$")
-with a submit button (name="accept") and a hidden field with name="redirurl" and value="$PORTAL_REDIRURL$". Include the "auth_user" and "auth_pass" input elements if RADIUS authentication is enabled. If RADIUS is enabled and no "auth_user" is present, authentication will always fail. If RADIUS is not enabled, you can omit both of these input elements. Example code for the form:<br>
+with a submit button (name="accept") and a hidden field with name="redirurl" and value="$PORTAL_REDIRURL$".
+Include the "auth_user" and "auth_pass" input fields if authentication is enabled, otherwise it will always fail.
+Example code for the form:<br>
<br>
<tt><form method="post" action="$PORTAL_ACTION$"><br>
<input name="auth_user" type="text"><br>
<br>
<br>
<?php endif; ?>
-The contents of the HTML file that you upload here are displayed when a RADIUS authentication error occurs.</td>
+The contents of the HTML file that you upload here are displayed when an authentication error occurs.
+You may include "$PORTAL_MESSAGE$", which will be replaced by the error or reply messages from the RADIUS server, if any.</td>
</tr>
<tr>
<td width="22%" valign="top"> </td>
--- /dev/null
+#!/usr/local/bin/php
+<?php
+/*
+ services_captiveportal_filemanager.php
+ part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2005-2006 Jonathan De Graeve (jonathan.de.graeve@imelda.be)
+ and Paul Taylor (paultaylor@winn-dixie.com).
+ 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.
+*/
+
+$pgtitle = array("Services", "Captive portal");
+
+require_once("guiconfig.inc");
+
+if (!is_array($config['captiveportal']['element']))
+ $config['captiveportal']['element'] = array();
+
+cpelements_sort();
+$a_element = &$config['captiveportal']['element'];
+
+// Calculate total size of all files
+$total_size = 0;
+foreach ($a_element as $element) {
+ $total_size += $element['size'];
+}
+
+if ($_POST) {
+ unset($input_errors);
+
+ if (is_uploaded_file($_FILES['new']['tmp_name'])) {
+
+ $name = $_FILES['new']['name'];
+ $size = filesize($_FILES['new']['tmp_name']);
+
+ // is there already a file with that name?
+ foreach ($a_element as $element) {
+ if ($element['name'] == $name) {
+ $input_errors[] = "A file with the name '$name' already exists.";
+ break;
+ }
+ }
+
+ // check total file size
+ if (($total_size + $size) > $g['captiveportal_element_sizelimit']) {
+ $input_errors[] = "The total size of all files uploaded may not exceed " .
+ format_bytes($g['captiveportal_element_sizelimit']) . ".";
+ }
+
+ if (!$input_errors) {
+ $element = array();
+ $element['name'] = $name;
+ $element['size'] = $size;
+ $element['content'] = base64_encode(file_get_contents($_FILES['new']['tmp_name']));
+
+ $a_element[] = $element;
+
+ write_config();
+ captiveportal_write_elements();
+ header("Location: services_captiveportal_filemanager.php");
+ exit;
+ }
+ }
+} else {
+ if (($_GET['act'] == "del") && $a_element[$_GET['id']]) {
+ unset($a_element[$_GET['id']]);
+ write_config();
+ captiveportal_write_elements();
+ header("Location: services_captiveportal_filemanager.php");
+ exit;
+ }
+}
+
+?>
+<?php include("fbegin.inc"); ?>
+<form action="services_captiveportal_filemanager.php" method="post" enctype="multipart/form-data" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td class="tabnavtbl">
+ <ul id="tabnav">
+ <li class="tabinact"><a href="services_captiveportal.php">Captive portal</a></li>
+ <li class="tabinact"><a href="services_captiveportal_mac.php">Pass-through MAC</a></li>
+ <li class="tabinact"><a href="services_captiveportal_ip.php">Allowed IP addresses</a></li>
+ <li class="tabinact"><a href="services_captiveportal_users.php">Users</a></li>
+ <li class="tabact">File manager</li>
+ </ul>
+ </td></tr>
+ <tr>
+ <td class="tabcont">
+ <table width="80%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="70%" class="listhdrr">Name</td>
+ <td width="20%" class="listhdr">Size</td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php $i = 0; foreach ($a_element as $element): ?>
+ <tr>
+ <td class="listlr"><?=htmlspecialchars($element['name']);?></td>
+ <td class="listr" align="right"><?=format_bytes($element['size']);?></td>
+ <td valign="middle" nowrap class="list">
+ <a href="services_captiveportal_filemanager.php?act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this file?')"><img src="x.gif" title="delete file" width="17" height="17" border="0"></a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+
+ <?php if (count($a_element) > 0): ?>
+ <tr>
+ <td class="listlr" style="background-color: #eee"><strong>TOTAL</strong></td>
+ <td class="listr" style="background-color: #eee" align="right"><strong><?=format_bytes($total_size);?></strong></td>
+ <td valign="middle" nowrap class="list"></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if ($_GET['act'] == 'add'): ?>
+ <tr>
+ <td class="listlr" colspan="2"><input type="file" name="new" class="formfld" size="40" id="new">
+ <input name="Submit" type="submit" class="formbtn" value="Upload"></td>
+ <td valign="middle" nowrap class="list">
+ <a href="services_captiveportal_filemanager.php"><img src="x.gif" title="cancel" width="17" height="17" border="0"></a>
+ </td>
+ </tr>
+ <?php else: ?>
+ <tr>
+ <td class="list" colspan="2"></td>
+ <td class="list"> <a href="services_captiveportal_filemanager.php?act=add"><img src="plus.gif" title="add file" width="17" height="17" border="0"></a></td>
+ </tr>
+ <?php endif; ?>
+ </table>
+ <span class="vexpl"><span class="red"><strong>
+ Note:<br>
+ </strong></span>
+ Any files that you upload here will be made available in the root directory
+ of the captive portal HTTP(S) server. You may reference them directly from
+ your portal page HTML code using relative paths. Example: you've uploaded
+ an image with the name 'test.jpg' using the file manager. Then you can
+ include it in your portal page like this:<br><br>
+ <tt><img src="test.jpg" width=... height=...></tt>
+ <br><br>
+ The total size limit for all files is <?=format_bytes($g['captiveportal_element_sizelimit']);?>.</span>
+</td>
+</tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
<li class="tabinact"><a href="services_captiveportal_mac.php">Pass-through MAC</a></li>
<li class="tabact">Allowed IP addresses</li>
<li class="tabinact"><a href="services_captiveportal_users.php">Users</a></li>
+ <li class="tabinact"><a href="services_captiveportal_filemanager.php">File manager</a></li>
</ul>
</td></tr>
<tr>
<li class="tabact">Pass-through MAC</li>
<li class="tabinact"><a href="services_captiveportal_ip.php">Allowed IP addresses</a></li>
<li class="tabinact"><a href="services_captiveportal_users.php">Users</a></li>
+ <li class="tabinact"><a href="services_captiveportal_filemanager.php">File manager</a></li>
</ul>
</td></tr>
<tr>
services_captiveportal_users.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Copyright (C) 2005 Pascal Suter <d-monodev@psuter.ch>.
All rights reserved.
<li class="tabinact"><a href="services_captiveportal_mac.php">Pass-through MAC</a></li>
<li class="tabinact"><a href="services_captiveportal_ip.php">Allowed IP addresses</a></li>
<li class="tabact">Users</li>
+ <li class="tabinact"><a href="services_captiveportal_filemanager.php">File manager</a></li>
</ul>
</td></tr>
<tr>
services_captiveportal_users_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Copyright (C) 2005 Pascal Suter <d-monodev@psuter.ch>.
All rights reserved.
services_dhcp.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_dhcp_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_dnsmasq_domainoverride_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_dyndns.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_proxyarp.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_proxyarp_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_snmp.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
$pconfig['syscontact'] = $config['snmpd']['syscontact'];
$pconfig['rocommunity'] = $config['snmpd']['rocommunity'];
$pconfig['enable'] = isset($config['snmpd']['enable']);
+$pconfig['bindlan'] = isset($config['snmpd']['bindlan']);
if ($_POST) {
$config['snmpd']['syscontact'] = $_POST['syscontact'];
$config['snmpd']['rocommunity'] = $_POST['rocommunity'];
$config['snmpd']['enable'] = $_POST['enable'] ? true : false;
+ $config['snmpd']['bindlan'] = $_POST['bindlan'] ? true : false;
write_config();
document.iform.syslocation.disabled = endis;
document.iform.syscontact.disabled = endis;
document.iform.rocommunity.disabled = endis;
+ document.iform.bindlan.disabled = endis;
}
//-->
</script>
<br>
In most cases, "public" is used here</td>
</tr>
+ <tr>
+ <td width="22%" valign="top" class="vtable"></td>
+ <td width="78%" class="vtable">
+ <input name="bindlan" type="checkbox" value="yes" <?php if ($pconfig['bindlan']) echo "checked"; ?>> <strong>Bind to LAN interface only</strong>
+ <br>
+ This option can be useful when trying to access the SNMP agent
+ by the LAN interface's IP address through a VPN tunnel terminated on the WAN interface.</td>
+ </tr>
<tr>
<td width="22%" valign="top"> </td>
<td width="78%">
services_wol.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
services_wol_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
status_captiveportal.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
<?php
if ($_GET['act'] == "del") {
- captiveportal_disconnect_client($_GET['id']);
+ captiveportal_disconnect_client($_GET['id'],6);
}
flush();
status_graph.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
status_graph_cpu.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
status_interfaces.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
status_wireless.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system_advanced.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system_firmware.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system_routes.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
system_routes_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
uploadconfig.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_ca.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_ca_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_keys.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_keys_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_ipsec_mobile.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_pptp.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_pptp_users.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
vpn_pptp_users_edit.php
part of m0n0wall (http://m0n0.ch/wall)
- Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without