Project

General

Profile

« Previous | Next » 

Revision 9faa6c3c

Added by Ermal LUÇI about 15 years ago

Improve/correct the passthrumac rules when this option is enabled.

View differences:

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