Project

General

Profile

Download (22.9 KB) Statistics
| Branch: | Tag: | Revision:
1 8c1ce6c7 Scott Ullrich
<?php
2 5b237745 Scott Ullrich
/*
3 65fbb388 Scott Ullrich
    $Id$
4
    part of m0n0wall (http://m0n0.ch/wall)
5
6 9568c1a1 Ermal Lu?i
    Copyrigth (C) 2009	    Ermal Lu?i
7 65fbb388 Scott Ullrich
    Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
8
    All rights reserved.
9
10
    Redistribution and use in source and binary forms, with or without
11
    modification, are permitted provided that the following conditions are met:
12
13
    1. Redistributions of source code must retain the above copyright notice,
14
       this list of conditions and the following disclaimer.
15
16
    2. Redistributions in binary form must reproduce the above copyright
17
       notice, this list of conditions and the following disclaimer in the
18
       documentation and/or other materials provided with the distribution.
19
20
    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
    POSSIBILITY OF SUCH DAMAGE.
30 5b237745 Scott Ullrich
*/
31 f5024891 Scott Ullrich
/*
32
	pfSense_BUILDER_BINARIES:	/sbin/ipfw	
33
	pfSense_MODULE:	captiveportal
34
*/
35 5b237745 Scott Ullrich
36 0092b3bd mgrooms
require_once("auth.inc");
37 65fbb388 Scott Ullrich
require_once("functions.inc");
38 483e6de8 Scott Ullrich
require_once("captiveportal.inc");
39 65fbb388 Scott Ullrich
40 eb15decb Ermal
$errormsg = "Invalid credentials specified.";
41
42 65fbb388 Scott Ullrich
header("Expires: 0");
43
header("Cache-Control: no-store, no-cache, must-revalidate");
44
header("Cache-Control: post-check=0, pre-check=0", false);
45
header("Pragma: no-cache");
46 232846a2 Ermal
header("Connection: close");
47 5b237745 Scott Ullrich
48
$orig_host = $_ENV['HTTP_HOST'];
49 fe383a26 Ermal
$orig_request = $_REQUEST['redirurl'];
50 6fa4bdc6 Scott Ullrich
$clientip = $_SERVER['REMOTE_ADDR'];
51 5b237745 Scott Ullrich
52
if (!$clientip) {
53 c9cb32c4 Ermal
	/* not good - bail out */
54
	log_error("Captive portal could not determine client's IP address.");
55
	$error_message = "An error occurred.  Please check the system logs for more information.";
56
	portal_reply_page($redirurl, "error", $errormsg);
57
	exit;
58 65fbb388 Scott Ullrich
}
59
60
if (isset($config['captiveportal']['httpslogin']))
61
    $ourhostname = $config['captiveportal']['httpsname'] . ":8001";
62 f8b11310 Ermal Lu?i
else {
63
    $ifip = portal_ip_from_client_ip($clientip);
64
    if (!$ifip)
65
    	$ourhostname = $config['system']['hostname'] . ":8000";
66
    else
67
    	$ourhostname = "{$ifip}:8000";
68
}
69 65fbb388 Scott Ullrich
70
if ($orig_host != $ourhostname) {
71
    /* the client thinks it's connected to the desired web server, but instead
72
       it's connected to us. Issue a redirect... */
73
74
    if (isset($config['captiveportal']['httpslogin']))
75
        header("Location: https://{$ourhostname}/index.php?redirurl=" . urlencode("http://{$orig_host}{$orig_request}"));
76
    else
77
        header("Location: http://{$ourhostname}/index.php?redirurl=" . urlencode("http://{$orig_host}{$orig_request}"));
78
79
    exit;
80 5b237745 Scott Ullrich
}
81 65fbb388 Scott Ullrich
if (preg_match("/redirurl=(.*)/", $orig_request, $matches))
82
    $redirurl = urldecode($matches[1]);
83 b6494b87 Erik Fonnesbeck
if ($_POST['redirurl'])
84
    $redirurl = $_POST['redirurl'];
85 8ebbae22 Ermal
if (!empty($config['captiveportal']['redirurl']))
86
	$redirurl = $config['captiveportal']['redirurl'];
87 65fbb388 Scott Ullrich
88
$macfilter = !isset($config['captiveportal']['nomacfilter']);
89 0852838c Ermal
$passthrumac = isset($config['captiveportal']['passthrumacadd']);
90 65fbb388 Scott Ullrich
91 5b237745 Scott Ullrich
/* find MAC address for client */
92
$clientmac = arp_get_mac_by_ip($clientip);
93 0852838c Ermal
if (!$clientmac && ($macfilter || $passthrumac)) {
94 65fbb388 Scott Ullrich
    /* unable to find MAC address - shouldn't happen! - bail out */
95
    captiveportal_logportalauth("unauthenticated","noclientmac",$clientip,"ERROR");
96 18cbd65f Chris Buechler
    echo "An error occurred.  Please check the system logs for more information.";
97 d102e3ed Chris Buechler
    log_error("Captive portal could not determine client's MAC address.  Disable MAC address filtering in captive portal if you do not need this functionality.");
98 65fbb388 Scott Ullrich
    exit;
99 5b237745 Scott Ullrich
}
100
101 65fbb388 Scott Ullrich
/* find out if we need RADIUS + RADIUSMAC or not */
102
if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
103
    $radius_enable = TRUE;
104 f8b11310 Ermal Lu?i
    if (isset($config['captiveportal']['radmac_enable']))
105 65fbb388 Scott Ullrich
        $radmac_enable = TRUE;
106
}
107 6e865a74 Scott Ullrich
108 65fbb388 Scott Ullrich
if ($_POST['logout_id']) {
109 532cb894 Ermal
	echo <<<EOD
110 5b237745 Scott Ullrich
<HTML>
111
<HEAD><TITLE>Disconnecting...</TITLE></HEAD>
112
<BODY BGCOLOR="#435370">
113
<SPAN STYLE="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">
114 b2ce71ff Scott Ullrich
<B>You have been disconnected.</B>
115 5b237745 Scott Ullrich
</SPAN>
116
<SCRIPT LANGUAGE="JavaScript">
117
<!--
118
setTimeout('window.close();',5000) ;
119
-->
120
</SCRIPT>
121
</BODY>
122
</HTML>
123
124
EOD;
125 532cb894 Ermal
	disconnect_client($_POST['logout_id']);
126
	exit;
127 65fbb388 Scott Ullrich
} else if ($clientmac && $radmac_enable && portal_mac_radius($clientmac,$clientip)) {
128
    /* radius functions handle everything so we exit here since we're done */
129
    exit;
130
131 8015e67b Erik Fonnesbeck
} else if (portal_consume_passthrough_credit($clientmac)) {
132
    /* allow the client through if it had a pass-through credit for its MAC */
133
    captiveportal_logportalauth("unauthenticated",$clientmac,$clientip,"ACCEPT");
134
    portal_allow($clientip, $clientmac, "unauthenticated");
135
136 336e3c1c Charlie
} else if ($_POST['accept'] && $_POST['auth_voucher']) {
137
138
    $voucher = trim($_POST['auth_voucher']);
139
    $timecredit = voucher_auth($voucher);
140
    // $timecredit contains either a credit in minutes or an error message
141
    if ($timecredit > 0) {  // voucher is valid. Remaining minutes returned
142
        // if multiple vouchers given, use the first as username
143
        $a_vouchers = split("[\t\n\r ]+",$voucher);
144
        $voucher = $a_vouchers[0];
145
        $attr = array( 'voucher' => 1,
146
                'session_timeout' => $timecredit*60,
147
                'session_terminate_time' => 0);
148
        if (portal_allow($clientip, $clientmac,$voucher,null,$attr)) {
149
150
            // YES: user is good for $timecredit minutes.
151 d102e3ed Chris Buechler
            captiveportal_logportalauth($voucher,$clientmac,$clientip,"Voucher login good for $timecredit min.");
152 336e3c1c Charlie
        } else {
153 eb15decb Ermal
            portal_reply_page($redirurl, "error", $config['voucher']['msgexpired'] ? $config['voucher']['msgexpired']: $errormsg);
154 336e3c1c Charlie
        }
155
    } else if (-1 == $timecredit) {  // valid but expired
156
        captiveportal_logportalauth($voucher,$clientmac,$clientip,"FAILURE","voucher expired");
157 eb15decb Ermal
        portal_reply_page($redirurl, "error", $config['voucher']['msgexpired'] ? $config['voucher']['msgexpired']: $errormsg);
158 336e3c1c Charlie
    } else {
159
        captiveportal_logportalauth($voucher,$clientmac,$clientip,"FAILURE");
160 eb15decb Ermal
        portal_reply_page($redirurl, "error", $config['voucher']['msgnoaccess'] ? $config['voucher']['msgnoaccess'] : $errormsg);
161 336e3c1c Charlie
    }
162
163 65fbb388 Scott Ullrich
} else if ($_POST['accept'] && $radius_enable) {
164
165
    if ($_POST['auth_user'] && $_POST['auth_pass']) {
166
        $auth_list = radius($_POST['auth_user'],$_POST['auth_pass'],$clientip,$clientmac,"USER LOGIN");
167 814992f7 Ermal
	$type = "error";
168
	if (!empty($auth_list['url_redirection'])) {
169
		$redirurl = $auth_list['url_redirection'];
170
		$type = "redir";
171
	}
172 65fbb388 Scott Ullrich
173
        if ($auth_list['auth_val'] == 1) {
174
            captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"ERROR",$auth_list['error']);
175 eb15decb Ermal
 	    portal_reply_page($redirurl, $type, $auth_list['error'] ? $auth_list['error'] : $errormsg);
176 65fbb388 Scott Ullrich
        }
177
        else if ($auth_list['auth_val'] == 3) {
178
            captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE",$auth_list['reply_message']);
179 eb15decb Ermal
            portal_reply_page($redirurl, $type, $auth_list['reply_message'] ? $auth_list['reply_message'] : $errormsg);
180 65fbb388 Scott Ullrich
        }
181
    } else {
182
        captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"ERROR");
183 eb15decb Ermal
        portal_reply_page($redirurl, "error", $errormsg);
184 65fbb388 Scott Ullrich
    }
185 8c1ce6c7 Scott Ullrich
186 65fbb388 Scott Ullrich
} else if ($_POST['accept'] && $config['captiveportal']['auth_method'] == "local") {
187 8c1ce6c7 Scott Ullrich
188 0092b3bd mgrooms
	//check against local user manager
189
	$loginok = local_backed($_POST['auth_user'], $_POST['auth_pass']);
190 65fbb388 Scott Ullrich
    if ($loginok){
191
        captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"LOGIN");
192
        portal_allow($clientip, $clientmac,$_POST['auth_user']);
193
    } else {
194
        captiveportal_logportalauth($_POST['auth_user'],$clientmac,$clientip,"FAILURE");
195 eb15decb Ermal
        portal_reply_page($redirurl, "error", $errormsg);
196 65fbb388 Scott Ullrich
    }
197 8015e67b Erik Fonnesbeck
} else if ($_POST['accept'] && $clientip) {
198 65fbb388 Scott Ullrich
    captiveportal_logportalauth("unauthenticated",$clientmac,$clientip,"ACCEPT");
199
    portal_allow($clientip, $clientmac, "unauthenticated");
200
} else {
201
    /* display captive portal page */
202 4993f81c Chris Buechler
    portal_reply_page($redirurl, "login",null,$clientmac,$clientip);
203 5b237745 Scott Ullrich
}
204
205
exit;
206
207 72b9e452 Ermal
function portal_reply_page($redirurl, $type = null, $message = null, $clientmac = null, $clientip = null, $username = null, $password = null) {
208 8ebbae22 Ermal
	global $g, $config;
209
210
	/* Get captive portal layout */
211
	if ($type == "redir") {
212
		header("Location: {$redirurl}");
213
		return;
214
	} else if ($type == "login")
215
		$htmltext = get_include_contents("{$g['varetc_path']}/captiveportal.html");
216
	else
217
		$htmltext = get_include_contents("{$g['varetc_path']}/captiveportal-error.html");
218
219 38060391 Scott Ullrich
	/* substitute the PORTAL_REDIRURL variable */
220
	if ($config['captiveportal']['preauthurl']) {
221
		$htmltext = str_replace("\$PORTAL_REDIRURL\$", "{$config['captiveportal']['preauthurl']}", $htmltext);
222
		$htmltext = str_replace("#PORTAL_REDIRURL#", "{$config['captiveportal']['preauthurl']}", $htmltext);
223
	}
224
225 8ebbae22 Ermal
	/* substitute other variables */
226
	if (isset($config['captiveportal']['httpslogin'])) {
227
		$htmltext = str_replace("\$PORTAL_ACTION\$", "https://{$config['captiveportal']['httpsname']}:8001/", $htmltext);
228
		$htmltext = str_replace("#PORTAL_ACTION#", "https://{$config['captiveportal']['httpsname']}:8001/", $htmltext);
229
	} else {
230 7a7e94a7 Scott Ullrich
		$ifip = portal_ip_from_client_ip($clientip);
231 8ebbae22 Ermal
		if (!$ifip)
232
			$ourhostname = $config['system']['hostname'] . ":8000";
233
		else
234
			$ourhostname = "{$ifip}:8000";
235
		$htmltext = str_replace("\$PORTAL_ACTION\$", "http://{$ourhostname}/", $htmltext);
236
		$htmltext = str_replace("#PORTAL_ACTION#", "http://{$ourhostname}/", $htmltext);
237
	}
238 8c1ce6c7 Scott Ullrich
239 8ebbae22 Ermal
	$htmltext = str_replace("\$PORTAL_REDIRURL\$", htmlspecialchars($redirurl), $htmltext);
240
	$htmltext = str_replace("\$PORTAL_MESSAGE\$", htmlspecialchars($message), $htmltext);
241
	$htmltext = str_replace("\$CLIENT_MAC\$", htmlspecialchars($clientmac), $htmltext);
242
	$htmltext = str_replace("\$CLIENT_IP\$", htmlspecialchars($clientip), $htmltext);
243 5b237745 Scott Ullrich
244 7a7e94a7 Scott Ullrich
	// Special handling case for captive portal master page so that it can be ran 
245
	// through the PHP interpreter using the include method above.  We convert the
246
	// $VARIABLE$ case to #VARIABLE# in /etc/inc/captiveportal.inc before writing out.
247
	$htmltext = str_replace("#PORTAL_REDIRURL#", htmlspecialchars($redirurl), $htmltext);
248
	$htmltext = str_replace("#PORTAL_MESSAGE#", htmlspecialchars($message), $htmltext);
249
	$htmltext = str_replace("#CLIENT_MAC#", htmlspecialchars($clientmac), $htmltext);
250
	$htmltext = str_replace("#CLIENT_IP#", htmlspecialchars($clientip), $htmltext);
251 72b9e452 Ermal
	$htmltext = str_replace("#USERNAME#", htmlspecialchars($username), $htmltext);
252
	$htmltext = str_replace("#PASSWORD#", htmlspecialchars($password), $htmltext);
253 7a7e94a7 Scott Ullrich
254 65fbb388 Scott Ullrich
    echo $htmltext;
255
}
256 8c1ce6c7 Scott Ullrich
257 65fbb388 Scott Ullrich
function portal_mac_radius($clientmac,$clientip) {
258
    global $config ;
259 8c1ce6c7 Scott Ullrich
260 65fbb388 Scott Ullrich
    $radmac_secret = $config['captiveportal']['radmac_secret'];
261 8c1ce6c7 Scott Ullrich
262 65fbb388 Scott Ullrich
    /* authentication against the radius server */
263
    $username = mac_format($clientmac);
264
    $auth_list = radius($username,$radmac_secret,$clientip,$clientmac,"MACHINE LOGIN");
265 814992f7 Ermal
    if ($auth_list['auth_val'] == 2)
266 65fbb388 Scott Ullrich
        return TRUE;
267 0eb9b1b4 Ermal
    if (!empty($auth_list['url_redirection']))
268 814992f7 Ermal
	portal_reply_page($auth_list['url_redirection'], "redir");
269 0eb9b1b4 Ermal
270 65fbb388 Scott Ullrich
    return FALSE;
271
}
272 8c1ce6c7 Scott Ullrich
273 65fbb388 Scott Ullrich
function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $ruleno = null)  {
274
275 72b9e452 Ermal
	global $redirurl, $g, $config, $type, $passthrumac, $_POST;
276 9faa6c3c Ermal
277 d31bc32a Ermal
	/* See if a ruleno is passed, if not start sessions because this means there isn't one atm */
278
	if ($ruleno == null)
279 9faa6c3c Ermal
		$ruleno = captiveportal_get_next_ipfw_ruleno();
280 65fbb388 Scott Ullrich
281 9faa6c3c Ermal
	/* if the pool is empty, return appropriate message and exit */
282
	if (is_null($ruleno)) {
283
		portal_reply_page($redirurl, "error", "System reached maximum login capacity");
284
		log_error("WARNING!  Captive portal has reached maximum login capacity");
285
		exit;
286
	}
287 65fbb388 Scott Ullrich
288 9faa6c3c Ermal
	// Ensure we create an array if we are missing attributes
289
	if (!is_array($attributes))
290
		$attributes = array();
291 65fbb388 Scott Ullrich
292 9faa6c3c Ermal
	/* read in client database */
293
	$cpdb = captiveportal_read_db();
294 65fbb388 Scott Ullrich
295 9faa6c3c Ermal
	$radiusservers = captiveportal_get_radius_servers();
296 6ce61a8f Ermal
297 9faa6c3c Ermal
	if ($attributes['voucher'])
298
		$remaining_time = $attributes['session_timeout'];
299
300 72b9e452 Ermal
	$writecfg = false;
301 9faa6c3c Ermal
	/* Find an existing session */
302 1c291e64 Ermal
	if ((isset($config['captiveportal']['noconcurrentlogins'])) && $passthrumac) {
303
		if (isset($config['captiveportal']['passthrumacadd'])) {
304
			$mac = captiveportal_passthrumac_findbyname($username);
305
			if (!empty($mac)) {
306 72b9e452 Ermal
				if ($_POST['replacemacpassthru']) {
307 3bf8eb93 Ermal
					foreach ($config['captiveportal']['passthrumac'] as $idx => $macent) {
308 72b9e452 Ermal
						if ($macent['mac'] == $mac['mac']) {
309 4d349ede Ermal
							$macrules = "";
310
							$ruleno = captiveportal_get_ipfw_passthru_ruleno($mac['mac']);
311
                                			if ($ruleno) {
312
								captiveportal_free_ipfw_ruleno($ruleno, true);
313 b90996c5 Ermal
                                        			$macrules .= "delete {$ruleno}\n";
314 4d349ede Ermal
								++$ruleno;
315 b90996c5 Ermal
                                        			$macrules .= "delete {$ruleno}\n";
316 4d349ede Ermal
                                			}
317 72b9e452 Ermal
							unset($config['captiveportal']['passthrumac'][$idx]);
318
							$mac['mac'] = $clientmac;
319
							$config['captiveportal']['passthrumac'][] = $mac;
320 e06b7fa2 Ermal
							$macrules .= captiveportal_passthrumac_configure_entry($mac);
321 72b9e452 Ermal
							file_put_contents("{$g['tmp_path']}/macentry.rules.tmp", $macrules);
322
							mwexec("/sbin/ipfw -q {$g['tmp_path']}/macentry.rules.tmp");
323
							$writecfg = true;
324
							$sessionid = true;
325
							break;
326
						}
327
					}
328
                                } else {
329 d83dccff Chris Buechler
					portal_reply_page($redirurl, "error", "Username: {$username} is already authenticated using another MAC address.",
330 72b9e452 Ermal
						$clientmac, $clientip, $username, $password);
331
					exit;
332
				}
333 1c291e64 Ermal
			}
334
		}
335
	}
336
337
	$nousers = count($cpdb);
338
	for ($i = 0; $i < $nousers; $i++) {
339 9faa6c3c Ermal
		/* on the same ip */
340
		if($cpdb[$i][2] == $clientip) {
341
			captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - REUSING OLD SESSION");
342
			$sessionid = $cpdb[$i][5];
343
			break;
344
		}
345
		elseif (($attributes['voucher']) && ($username != 'unauthenticated') && ($cpdb[$i][4] == $username)) {
346
			// user logged in with an active voucher. Check for how long and calculate 
347
			// how much time we can give him (voucher credit - used time)
348
			$remaining_time = $cpdb[$i][0] + $cpdb[$i][7] - time();
349
			if ($remaining_time < 0)    // just in case. 
350
				$remaining_time = 0;
351
352
			/* This user was already logged in so we disconnect the old one */
353
			captiveportal_disconnect($cpdb[$i],$radiusservers,13);
354
			captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION");
355
			unset($cpdb[$i]);
356
			break;
357
		}
358
		elseif ((isset($config['captiveportal']['noconcurrentlogins'])) && ($username != 'unauthenticated')) {
359
			/* on the same username */
360
			if (strcasecmp($cpdb[$i][4], $username) == 0) {
361
				/* This user was already logged in so we disconnect the old one */
362
				captiveportal_disconnect($cpdb[$i],$radiusservers,13);
363
				captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],"CONCURRENT LOGIN - TERMINATING OLD SESSION");
364
				unset($cpdb[$i]);
365
				break;
366
			}
367
		}
368
	}
369 65fbb388 Scott Ullrich
370 d31bc32a Ermal
	if ($attributes['voucher'] && $remaining_time <= 0)
371 9faa6c3c Ermal
		return 0;       // voucher already used and no time left
372 65fbb388 Scott Ullrich
373 9faa6c3c Ermal
	if (!isset($sessionid)) {
374
		/* generate unique session ID */
375
		$tod = gettimeofday();
376
		$sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16);
377
378
		/* Add rules for traffic shaping
379
		 * We don't need to add extra rules since traffic will pass due to the following kernel option
380
		 * net.inet.ip.fw.one_pass: 1
381
		 */
382
		$peruserbw = isset($config['captiveportal']['peruserbw']);
383
384
		$bw_up = isset($attributes['bw_up']) ? trim($attributes['bw_up']) : $config['captiveportal']['bwdefaultup'];
385
		$bw_down = isset($attributes['bw_down']) ? trim($attributes['bw_down']) : $config['captiveportal']['bwdefaultdn'];
386
387
		if ($passthrumac) {
388
			$mac = array();
389
			$mac['mac'] = $clientmac;
390 1c291e64 Ermal
			if (isset($config['captiveportal']['passthrumacaddusername']))
391
				$mac['username'] = $username;
392 9faa6c3c Ermal
			$mac['descr'] =  "Auto added pass-through MAC for user {$username}";
393
			if (!empty($bw_up))
394
				$mac['bw_up'] = $bw_up;
395
			if (!empty($bw_down))
396
				$mac['bw_down'] = $bw_down;
397
			if (!is_array($config['captiveportal']['passthrumac']))
398
				$config['captiveportal']['passthrumac'] = array();
399
			$config['captiveportal']['passthrumac'][] = $mac;
400
			$macrules = captiveportal_passthrumac_configure_entry($mac);
401
			file_put_contents("{$g['tmp_path']}/macentry.rules.tmp", $macrules);
402
			mwexec("/sbin/ipfw -q {$g['tmp_path']}/macentry.rules.tmp");
403
			$writecfg = true;
404
		} else {
405
			if ($peruserbw && !empty($bw_up) && is_numeric($bw_up)) {
406
				$bw_up_pipeno = $ruleno + 20000;
407
				//$bw_up /= 1000; // Scale to Kbit/s
408
				mwexec("/sbin/ipfw pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100");
409
410
				if (!isset($config['captiveportal']['nomacfilter']))
411
					mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac} {$bw_up_pipeno}");
412
				else
413
					mwexec("/sbin/ipfw table 1 add {$clientip} {$bw_up_pipeno}");
414
			} else {
415
				if (!isset($config['captiveportal']['nomacfilter']))
416
					mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac}");
417
				else
418
					mwexec("/sbin/ipfw table 1 add {$clientip}");
419
			}
420
			if ($peruserbw && !empty($bw_down) && is_numeric($bw_down)) {
421
				$bw_down_pipeno = $ruleno + 20001;
422
				//$bw_down /= 1000; // Scale to Kbit/s
423
				mwexec("/sbin/ipfw pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100");
424
425
				if (!isset($config['captiveportal']['nomacfilter']))
426
					mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac} {$bw_down_pipeno}");
427
				else
428
					mwexec("/sbin/ipfw table 2 add {$clientip} {$bw_down_pipeno}");
429
			} else {
430
				if (!isset($config['captiveportal']['nomacfilter']))
431
					mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac}");
432
				else
433
					mwexec("/sbin/ipfw table 2 add {$clientip}");
434
			}
435
436
			if ($attributes['voucher'])
437
				$attributes['session_timeout'] = $remaining_time;
438
439
			/* encode password in Base64 just in case it contains commas */
440
			$bpassword = base64_encode($password);
441
			$cpdb[] = array(time(), $ruleno, $clientip, $clientmac, $username, $sessionid, $bpassword,
442
				$attributes['session_timeout'], $attributes['idle_timeout'], $attributes['session_terminate_time']);
443
444
			if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) {
445
				$acct_val = RADIUS_ACCOUNTING_START($ruleno,
446
                                		$username, $sessionid, $radiusservers, $clientip, $clientmac);
447
				if ($acct_val == 1)
448
					captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED");
449
			}
450
451
			/* rewrite information to database */
452
			captiveportal_write_db($cpdb);
453
		}
454 f8b11310 Ermal Lu?i
	}
455 65fbb388 Scott Ullrich
456 9faa6c3c Ermal
	if ($writecfg == true)
457
		write_config();
458
459
	/* redirect user to desired destination */
460 9628bd1c Ermal
	if (!empty($attributes['url_redirection']))
461
		$my_redirurl = $attributes['url_redirection'];
462 9faa6c3c Ermal
	else if ($config['captiveportal']['redirurl'])
463
		$my_redirurl = $config['captiveportal']['redirurl'];
464
	else
465
		$my_redirurl = $redirurl;
466
467 091cb5e9 Ermal
	if(isset($config['captiveportal']['logoutwin_enable']) && !$passthrumac) {
468 9faa6c3c Ermal
469
		if (isset($config['captiveportal']['httpslogin']))
470
			$logouturl = "https://{$config['captiveportal']['httpsname']}:8001/";
471
		else {
472
			$ifip = portal_ip_from_client_ip($clientip);
473
			if (!$ifip)
474
				$ourhostname = $config['system']['hostname'] . ":8000";
475
			else
476
				$ourhostname = "{$ifip}:8000";
477
			$logouturl = "http://{$ourhostname}/";
478
		}
479
480 2e12b76c jim-p
		if (isset($attributes['reply_message']))
481
			$message = $attributes['reply_message'];
482
		else
483
			$message = 0;
484
485 5b87b24e Ermal
		include("{$g['varetc_path']}/captiveportal-logout.html");
486 5b237745 Scott Ullrich
487 9faa6c3c Ermal
	} else {
488 c7cdfe20 Scott Ullrich
		header("Location: " . $my_redirurl);
489 9faa6c3c Ermal
	}
490 8c1ce6c7 Scott Ullrich
491 9faa6c3c Ermal
	return $sessionid;
492 5b237745 Scott Ullrich
}
493
494 8c1ce6c7 Scott Ullrich
495 5b237745 Scott Ullrich
496 65fbb388 Scott Ullrich
/* remove a single client by session ID
497 d31bc32a Ermal
 *  by Dinesh Nair
498 65fbb388 Scott Ullrich
 */
499
function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) {
500
    global $g, $config;
501 8c1ce6c7 Scott Ullrich
502 65fbb388 Scott Ullrich
    /* read database */
503
    $cpdb = captiveportal_read_db();
504 8c1ce6c7 Scott Ullrich
505 65fbb388 Scott Ullrich
    $radiusservers = captiveportal_get_radius_servers();
506
507
    /* find entry */
508 6ce61a8f Ermal
    $dbcount = count($cpdb);
509
    for ($i = 0; $i < $dbcount; $i++) {
510 65fbb388 Scott Ullrich
        if ($cpdb[$i][5] == $sessionid) {
511
            captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause);
512
            captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
513
            unset($cpdb[$i]);
514
            break;
515
        }
516
    }
517
518
    /* write database */
519
    captiveportal_write_db($cpdb);
520 5b237745 Scott Ullrich
}
521
522 03552507 Erik Fonnesbeck
/*
523 8015e67b Erik Fonnesbeck
 * Used for when pass-through credits are enabled.
524 03552507 Erik Fonnesbeck
 * Returns true when there was at least one free login to deduct for the MAC.
525
 * Expired entries are removed as they are seen.
526
 * Active entries are updated according to the configuration.
527
 */
528 8015e67b Erik Fonnesbeck
function portal_consume_passthrough_credit($clientmac) {
529 03552507 Erik Fonnesbeck
	global $config;
530
531
	if (!empty($config['captiveportal']['freelogins_count']) && is_numeric($config['captiveportal']['freelogins_count']))
532
		$freeloginscount = $config['captiveportal']['freelogins_count'];
533
	else
534
		return false;
535
536
	if (!empty($config['captiveportal']['freelogins_resettimeout']) && is_numeric($config['captiveportal']['freelogins_resettimeout']))
537
		$resettimeout = $config['captiveportal']['freelogins_resettimeout'];
538
	else
539
		return false;
540
541
	if ($freeloginscount < 1 || $resettimeout <= 0 || !clientmac)
542
		return false;
543
544
	$updatetimeouts = isset($config['captiveportal']['freelogins_updatetimeouts']);
545
546
	/*
547
	 * Read database of used MACs.  Lines are a comma-separated list
548 8015e67b Erik Fonnesbeck
	 * of the time, MAC, then the count of pass-through credits remaining.
549 03552507 Erik Fonnesbeck
	 */
550
	$usedmacs = captiveportal_read_usedmacs_db();
551
552
	$currenttime = time();
553
	$found = false;
554
	foreach ($usedmacs as $key => $usedmac) {
555
		$usedmac = explode(",", $usedmac);
556
557
		if ($usedmac[1] == $clientmac) {
558
			if ($usedmac[0] + ($resettimeout * 3600) > $currenttime) {
559
				if ($usedmac[2] < 1) {
560
					if ($updatetimeouts) {
561
						$usedmac[0] = $currenttime;
562
						unset($usedmacs[$key]);
563
						$usedmacs[] = implode(",", $usedmac);
564
						captiveportal_write_usedmacs_db($usedmacs);
565
					}
566
567
					return false;
568
				} else {
569
					$usedmac[2] -= 1;
570
					$usedmacs[$key] = implode(",", $usedmac);
571
				}
572
573
				$found = true;
574
			} else
575
				unset($usedmacs[$key]);
576
577
			break;
578
		} else if ($usedmac[0] + ($resettimeout * 3600) <= $currenttime)
579
				unset($usedmacs[$key]);
580
	}
581
582
	if (!$found) {
583
		$usedmac = array($currenttime, $clientmac, $freeloginscount - 1);
584
		$usedmacs[] = implode(",", $usedmac);
585
	}
586
587
	captiveportal_write_usedmacs_db($usedmacs);
588
	return true;
589
}
590
591
function captiveportal_read_usedmacs_db() {
592
	global $g;
593
594 d31bc32a Ermal
	$cpumaclck = lock('captiveusedmacs');
595 03552507 Erik Fonnesbeck
	if (file_exists("{$g['vardb_path']}/captiveportal_usedmacs.db")) {
596
		$usedmacs = file("{$g['vardb_path']}/captiveportal_usedmacs.db", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
597
		if (!usedmacs)
598
			$usedmacs = array();
599
	} else
600
		$usedmacs = array();
601
602 d31bc32a Ermal
	unlock($cpumaclck);
603 03552507 Erik Fonnesbeck
	return $usedmacs;
604
}
605
606
function captiveportal_write_usedmacs_db($usedmacs) {
607
	global $g;
608
609 d31bc32a Ermal
	$cpumaclck = lock('captiveusedmacs', LOCK_EX);
610
	@file_put_contents("{$g['vardb_path']}/captiveportal_usedmacs.db", implode("\n", $usedmacs));
611
	unlock($cpumaclck);
612 03552507 Erik Fonnesbeck
}
613
614 60b66b60 Ermal
?>