Revision 9faa6c3c
Added by Ermal LUÇI about 15 years ago
usr/local/captiveportal/index.php | ||
---|---|---|
234 | 234 |
|
235 | 235 |
function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $ruleno = null) { |
236 | 236 |
|
237 |
global $redirurl, $g, $config, $url_redirection, $type; |
|
238 |
|
|
239 |
/* See if a ruleno is passed, if not start locking the sessions because this means there isn't one atm */ |
|
240 |
$captiveshouldunlock = false; |
|
241 |
if ($ruleno == null) { |
|
242 |
$cplock = lock('captiveportal'); |
|
243 |
$captiveshouldunlock = true; |
|
244 |
$ruleno = captiveportal_get_next_ipfw_ruleno(); |
|
245 |
} |
|
246 |
|
|
247 |
/* if the pool is empty, return appropriate message and exit */ |
|
248 |
if (is_null($ruleno)) { |
|
249 |
portal_reply_page($redirurl, "error", "System reached maximum login capacity"); |
|
250 |
log_error("WARNING! Captive portal has reached maximum login capacity"); |
|
251 |
if ($captiveshouldunlock == true) |
|
252 |
unlock($cplock); |
|
253 |
exit; |
|
254 |
} |
|
255 |
|
|
256 |
// Ensure we create an array if we are missing attributes |
|
257 |
if (!is_array($attributes)) |
|
258 |
$attributes = array(); |
|
259 |
|
|
260 |
/* read in client database */ |
|
261 |
$cpdb = captiveportal_read_db(); |
|
262 |
|
|
263 |
$radiusservers = captiveportal_get_radius_servers(); |
|
264 |
|
|
265 |
if ($attributes['voucher']) |
|
266 |
$remaining_time = $attributes['session_timeout']; |
|
267 |
|
|
268 |
/* Find an existing session */ |
|
269 |
for ($i = 0; $i < count($cpdb); $i++) { |
|
270 |
/* on the same ip */ |
|
271 |
if($cpdb[$i][2] == $clientip) { |
|
272 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - REUSING OLD SESSION"); |
|
273 |
$sessionid = $cpdb[$i][5]; |
|
274 |
break; |
|
275 |
} |
|
276 |
elseif (($attributes['voucher']) && ($username != 'unauthenticated') && ($cpdb[$i][4] == $username)) { |
|
277 |
// user logged in with an active voucher. Check for how long and calculate |
|
278 |
// how much time we can give him (voucher credit - used time) |
|
279 |
$remaining_time = $cpdb[$i][0] + $cpdb[$i][7] - time(); |
|
280 |
if ($remaining_time < 0) // just in case. |
|
281 |
$remaining_time = 0; |
|
282 |
|
|
283 |
/* This user was already logged in so we disconnect the old one */ |
|
284 |
captiveportal_disconnect($cpdb[$i],$radiusservers,13); |
|
285 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); |
|
286 |
unset($cpdb[$i]); |
|
287 |
break; |
|
288 |
} |
|
289 |
elseif ((isset($config['captiveportal']['noconcurrentlogins'])) && ($username != 'unauthenticated')) { |
|
290 |
/* on the same username */ |
|
291 |
if (strcasecmp($cpdb[$i][4], $username) == 0) { |
|
292 |
/* This user was already logged in so we disconnect the old one */ |
|
293 |
captiveportal_disconnect($cpdb[$i],$radiusservers,13); |
|
294 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); |
|
295 |
unset($cpdb[$i]); |
|
296 |
break; |
|
297 |
} |
|
298 |
} |
|
299 |
} |
|
300 |
|
|
301 |
if ($attributes['voucher'] && $remaining_time <= 0) { |
|
302 |
unlock($cplock); |
|
303 |
return 0; // voucher already used and no time left |
|
304 |
} |
|
305 |
|
|
306 |
$writecfg = false; |
|
307 |
if (!isset($sessionid)) { |
|
308 |
|
|
309 |
/* generate unique session ID */ |
|
310 |
$tod = gettimeofday(); |
|
311 |
$sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); |
|
312 |
|
|
313 |
/* Add rules for traffic shaping |
|
314 |
* We don't need to add extra rules since traffic will pass due to the following kernel option |
|
315 |
* net.inet.ip.fw.one_pass: 1 |
|
316 |
*/ |
|
317 |
$peruserbw = isset($config['captiveportal']['peruserbw']); |
|
318 |
$passthrumacadd = isset($config['captiveportal']['passthrumacadd']); |
|
319 |
|
|
320 |
$bw_up = isset($attributes['bw_up']) ? trim($attributes['bw_up']) : $config['captiveportal']['bwdefaultup']; |
|
321 |
$bw_down = isset($attributes['bw_down']) ? trim($attributes['bw_down']) : $config['captiveportal']['bwdefaultdn']; |
|
322 |
|
|
323 |
if ($passthrumacadd) { |
|
324 |
$mac = array(); |
|
325 |
$mac['mac'] = $clientmac; |
|
326 |
$mac['descr'] = "Auto added pass-through MAC for user {$username}"; |
|
327 |
if (!empty($bw_up)) |
|
328 |
$mac['bw_up'] = $bw_up; |
|
329 |
if (!empty($bw_down)) |
|
330 |
$mac['bw_down'] = $bw_down; |
|
331 |
if (!is_array($config['captiveportal']['passthrumac'])) |
|
332 |
$config['captiveportal']['passthrumac'] = array(); |
|
333 |
$config['captiveportal']['passthrumac'][] = $mac; |
|
334 |
$writecfg = true; |
|
237 |
global $redirurl, $g, $config, $url_redirection, $type; |
|
238 |
|
|
239 |
/* See if a ruleno is passed, if not start locking the sessions because this means there isn't one atm */ |
|
240 |
$captiveshouldunlock = false; |
|
241 |
if ($ruleno == null) { |
|
242 |
$cplock = lock('captiveportal'); |
|
243 |
$captiveshouldunlock = true; |
|
244 |
$ruleno = captiveportal_get_next_ipfw_ruleno(); |
|
335 | 245 |
} |
336 |
|
|
337 |
if ($peruserbw && !empty($bw_up) && is_numeric($bw_up)) { |
|
338 |
$bw_up_pipeno = $ruleno + 20000; |
|
339 |
//$bw_up /= 1000; // Scale to Kbit/s |
|
340 |
mwexec("/sbin/ipfw pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100"); |
|
341 |
|
|
342 |
if (!isset($config['captiveportal']['nomacfilter']) || $passthrumacadd) |
|
343 |
mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac} {$bw_up_pipeno}"); |
|
344 |
else |
|
345 |
mwexec("/sbin/ipfw table 1 add {$clientip} {$bw_up_pipeno}"); |
|
346 |
} else { |
|
347 |
if (!isset($config['captiveportal']['nomacfilter']) || $passthrumacadd) |
|
348 |
mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac}"); |
|
349 |
else |
|
350 |
mwexec("/sbin/ipfw table 1 add {$clientip}"); |
|
351 |
} |
|
352 |
if ($peruserbw && !empty($bw_down) && is_numeric($bw_down)) { |
|
353 |
$bw_down_pipeno = $ruleno + 20001; |
|
354 |
//$bw_down /= 1000; // Scale to Kbit/s |
|
355 |
mwexec("/sbin/ipfw pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100"); |
|
356 |
|
|
357 |
if (!isset($config['captiveportal']['nomacfilter']) || $passthrumacadd) |
|
358 |
mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac} {$bw_down_pipeno}"); |
|
359 |
else |
|
360 |
mwexec("/sbin/ipfw table 2 add {$clientip} {$bw_down_pipeno}"); |
|
361 |
} else { |
|
362 |
if (!isset($config['captiveportal']['nomacfilter']) || $passthrumacadd) |
|
363 |
mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac}"); |
|
364 |
else |
|
365 |
mwexec("/sbin/ipfw table 2 add {$clientip}"); |
|
366 |
} |
|
367 | 246 |
|
368 |
if ($attributes['voucher']) |
|
369 |
$attributes['session_timeout'] = $remaining_time; |
|
370 |
|
|
371 |
/* encode password in Base64 just in case it contains commas */ |
|
372 |
$bpassword = base64_encode($password); |
|
373 |
$cpdb[] = array(time(), $ruleno, $clientip, $clientmac, $username, $sessionid, $bpassword, |
|
374 |
$attributes['session_timeout'], |
|
375 |
$attributes['idle_timeout'], |
|
376 |
$attributes['session_terminate_time']); |
|
377 |
|
|
378 |
if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) { |
|
379 |
$acct_val = RADIUS_ACCOUNTING_START($ruleno, |
|
380 |
$username, |
|
381 |
$sessionid, |
|
382 |
$radiusservers, |
|
383 |
$clientip, |
|
384 |
$clientmac); |
|
385 |
|
|
386 |
if ($acct_val == 1) |
|
387 |
captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED"); |
|
388 |
} |
|
247 |
/* if the pool is empty, return appropriate message and exit */ |
|
248 |
if (is_null($ruleno)) { |
|
249 |
portal_reply_page($redirurl, "error", "System reached maximum login capacity"); |
|
250 |
log_error("WARNING! Captive portal has reached maximum login capacity"); |
|
251 |
if ($captiveshouldunlock == true) |
|
252 |
unlock($cplock); |
|
253 |
exit; |
|
254 |
} |
|
389 | 255 |
|
390 |
/* rewrite information to database */
|
|
391 |
captiveportal_write_db($cpdb);
|
|
392 |
}
|
|
256 |
// Ensure we create an array if we are missing attributes
|
|
257 |
if (!is_array($attributes))
|
|
258 |
$attributes = array();
|
|
393 | 259 |
|
394 |
if ($captiveshouldunlock == true)
|
|
395 |
unlock($cplock);
|
|
260 |
/* read in client database */
|
|
261 |
$cpdb = captiveportal_read_db();
|
|
396 | 262 |
|
397 |
if ($writecfg == true) { |
|
398 |
write_config(); |
|
399 |
captiveportal_passthrumac_configure(true); |
|
400 |
} |
|
263 |
$radiusservers = captiveportal_get_radius_servers(); |
|
401 | 264 |
|
402 |
/* redirect user to desired destination */ |
|
403 |
if ($url_redirection) |
|
404 |
$my_redirurl = $url_redirection; |
|
405 |
else if ($config['captiveportal']['redirurl']) |
|
406 |
$my_redirurl = $config['captiveportal']['redirurl']; |
|
407 |
else |
|
408 |
$my_redirurl = $redirurl; |
|
265 |
if ($attributes['voucher']) |
|
266 |
$remaining_time = $attributes['session_timeout']; |
|
267 |
|
|
268 |
/* Find an existing session */ |
|
269 |
for ($i = 0; $i < count($cpdb); $i++) { |
|
270 |
/* on the same ip */ |
|
271 |
if($cpdb[$i][2] == $clientip) { |
|
272 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - REUSING OLD SESSION"); |
|
273 |
$sessionid = $cpdb[$i][5]; |
|
274 |
break; |
|
275 |
} |
|
276 |
elseif (($attributes['voucher']) && ($username != 'unauthenticated') && ($cpdb[$i][4] == $username)) { |
|
277 |
// user logged in with an active voucher. Check for how long and calculate |
|
278 |
// how much time we can give him (voucher credit - used time) |
|
279 |
$remaining_time = $cpdb[$i][0] + $cpdb[$i][7] - time(); |
|
280 |
if ($remaining_time < 0) // just in case. |
|
281 |
$remaining_time = 0; |
|
282 |
|
|
283 |
/* This user was already logged in so we disconnect the old one */ |
|
284 |
captiveportal_disconnect($cpdb[$i],$radiusservers,13); |
|
285 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); |
|
286 |
unset($cpdb[$i]); |
|
287 |
break; |
|
288 |
} |
|
289 |
elseif ((isset($config['captiveportal']['noconcurrentlogins'])) && ($username != 'unauthenticated')) { |
|
290 |
/* on the same username */ |
|
291 |
if (strcasecmp($cpdb[$i][4], $username) == 0) { |
|
292 |
/* This user was already logged in so we disconnect the old one */ |
|
293 |
captiveportal_disconnect($cpdb[$i],$radiusservers,13); |
|
294 |
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); |
|
295 |
unset($cpdb[$i]); |
|
296 |
break; |
|
297 |
} |
|
298 |
} |
|
299 |
} |
|
409 | 300 |
|
410 |
if(isset($config['captiveportal']['logoutwin_enable']) && !isset($config['captiveportal']['passthrumacadd'])) { |
|
301 |
if ($attributes['voucher'] && $remaining_time <= 0) { |
|
302 |
unlock($cplock); |
|
303 |
return 0; // voucher already used and no time left |
|
304 |
} |
|
411 | 305 |
|
412 |
if (isset($config['captiveportal']['httpslogin'])) |
|
413 |
$logouturl = "https://{$config['captiveportal']['httpsname']}:8001/"; |
|
414 |
else { |
|
415 |
$ifip = portal_ip_from_client_ip($clientip); |
|
416 |
if (!$ifip) |
|
417 |
$ourhostname = $config['system']['hostname'] . ":8000"; |
|
418 |
else |
|
419 |
$ourhostname = "{$ifip}:8000"; |
|
420 |
$logouturl = "http://{$ourhostname}/"; |
|
306 |
$writecfg = false; |
|
307 |
if (!isset($sessionid)) { |
|
308 |
|
|
309 |
/* generate unique session ID */ |
|
310 |
$tod = gettimeofday(); |
|
311 |
$sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); |
|
312 |
|
|
313 |
/* Add rules for traffic shaping |
|
314 |
* We don't need to add extra rules since traffic will pass due to the following kernel option |
|
315 |
* net.inet.ip.fw.one_pass: 1 |
|
316 |
*/ |
|
317 |
$peruserbw = isset($config['captiveportal']['peruserbw']); |
|
318 |
|
|
319 |
$bw_up = isset($attributes['bw_up']) ? trim($attributes['bw_up']) : $config['captiveportal']['bwdefaultup']; |
|
320 |
$bw_down = isset($attributes['bw_down']) ? trim($attributes['bw_down']) : $config['captiveportal']['bwdefaultdn']; |
|
321 |
|
|
322 |
if ($passthrumac) { |
|
323 |
$mac = array(); |
|
324 |
$mac['mac'] = $clientmac; |
|
325 |
$mac['descr'] = "Auto added pass-through MAC for user {$username}"; |
|
326 |
if (!empty($bw_up)) |
|
327 |
$mac['bw_up'] = $bw_up; |
|
328 |
if (!empty($bw_down)) |
|
329 |
$mac['bw_down'] = $bw_down; |
|
330 |
if (!is_array($config['captiveportal']['passthrumac'])) |
|
331 |
$config['captiveportal']['passthrumac'] = array(); |
|
332 |
$config['captiveportal']['passthrumac'][] = $mac; |
|
333 |
$macrules = captiveportal_passthrumac_configure_entry($mac); |
|
334 |
file_put_contents("{$g['tmp_path']}/macentry.rules.tmp", $macrules); |
|
335 |
mwexec("/sbin/ipfw -q {$g['tmp_path']}/macentry.rules.tmp"); |
|
336 |
$writecfg = true; |
|
337 |
} else { |
|
338 |
|
|
339 |
if ($peruserbw && !empty($bw_up) && is_numeric($bw_up)) { |
|
340 |
$bw_up_pipeno = $ruleno + 20000; |
|
341 |
//$bw_up /= 1000; // Scale to Kbit/s |
|
342 |
mwexec("/sbin/ipfw pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100"); |
|
343 |
|
|
344 |
if (!isset($config['captiveportal']['nomacfilter'])) |
|
345 |
mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac} {$bw_up_pipeno}"); |
|
346 |
else |
|
347 |
mwexec("/sbin/ipfw table 1 add {$clientip} {$bw_up_pipeno}"); |
|
348 |
} else { |
|
349 |
if (!isset($config['captiveportal']['nomacfilter'])) |
|
350 |
mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac}"); |
|
351 |
else |
|
352 |
mwexec("/sbin/ipfw table 1 add {$clientip}"); |
|
353 |
} |
|
354 |
if ($peruserbw && !empty($bw_down) && is_numeric($bw_down)) { |
|
355 |
$bw_down_pipeno = $ruleno + 20001; |
|
356 |
//$bw_down /= 1000; // Scale to Kbit/s |
|
357 |
mwexec("/sbin/ipfw pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100"); |
|
358 |
|
|
359 |
if (!isset($config['captiveportal']['nomacfilter'])) |
|
360 |
mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac} {$bw_down_pipeno}"); |
|
361 |
else |
|
362 |
mwexec("/sbin/ipfw table 2 add {$clientip} {$bw_down_pipeno}"); |
|
363 |
} else { |
|
364 |
if (!isset($config['captiveportal']['nomacfilter'])) |
|
365 |
mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac}"); |
|
366 |
else |
|
367 |
mwexec("/sbin/ipfw table 2 add {$clientip}"); |
|
368 |
} |
|
369 |
|
|
370 |
if ($attributes['voucher']) |
|
371 |
$attributes['session_timeout'] = $remaining_time; |
|
372 |
|
|
373 |
/* encode password in Base64 just in case it contains commas */ |
|
374 |
$bpassword = base64_encode($password); |
|
375 |
$cpdb[] = array(time(), $ruleno, $clientip, $clientmac, $username, $sessionid, $bpassword, |
|
376 |
$attributes['session_timeout'], $attributes['idle_timeout'], $attributes['session_terminate_time']); |
|
377 |
|
|
378 |
if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) { |
|
379 |
$acct_val = RADIUS_ACCOUNTING_START($ruleno, |
|
380 |
$username, $sessionid, $radiusservers, $clientip, $clientmac); |
|
381 |
|
|
382 |
if ($acct_val == 1) |
|
383 |
captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED"); |
|
384 |
} |
|
385 |
|
|
386 |
/* rewrite information to database */ |
|
387 |
captiveportal_write_db($cpdb); |
|
388 |
} |
|
421 | 389 |
} |
422 | 390 |
|
423 |
echo <<<EOD |
|
391 |
if ($captiveshouldunlock == true) |
|
392 |
unlock($cplock); |
|
393 |
|
|
394 |
if ($writecfg == true) |
|
395 |
write_config(); |
|
396 |
|
|
397 |
/* redirect user to desired destination */ |
|
398 |
if ($url_redirection) |
|
399 |
$my_redirurl = $url_redirection; |
|
400 |
else if ($config['captiveportal']['redirurl']) |
|
401 |
$my_redirurl = $config['captiveportal']['redirurl']; |
|
402 |
else |
|
403 |
$my_redirurl = $redirurl; |
|
404 |
|
|
405 |
if(isset($config['captiveportal']['logoutwin_enable']) && !isset($config['captiveportal']['passthrumacadd'])) { |
|
406 |
|
|
407 |
if (isset($config['captiveportal']['httpslogin'])) |
|
408 |
$logouturl = "https://{$config['captiveportal']['httpsname']}:8001/"; |
|
409 |
else { |
|
410 |
$ifip = portal_ip_from_client_ip($clientip); |
|
411 |
if (!$ifip) |
|
412 |
$ourhostname = $config['system']['hostname'] . ":8000"; |
|
413 |
else |
|
414 |
$ourhostname = "{$ifip}:8000"; |
|
415 |
$logouturl = "http://{$ourhostname}/"; |
|
416 |
} |
|
417 |
|
|
418 |
echo <<<EOD |
|
424 | 419 |
<HTML> |
425 | 420 |
<HEAD><TITLE>Redirecting...</TITLE></HEAD> |
426 | 421 |
<BODY> |
... | ... | |
452 | 447 |
</HTML> |
453 | 448 |
|
454 | 449 |
EOD; |
455 |
} else { |
|
456 |
header("Location: " . $my_redirurl); |
|
457 |
return $sessionid; |
|
458 |
} |
|
450 |
} else { |
|
451 |
header("Location: " . $my_redirurl); |
|
452 |
} |
|
459 | 453 |
|
460 |
return $sessionid;
|
|
454 |
return $sessionid;
|
|
461 | 455 |
} |
462 | 456 |
|
463 | 457 |
|
Also available in: Unified diff
Improve/correct the passthrumac rules when this option is enabled.