Project

General

Profile

Download (10.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	$Id$
4
	part of m0n0wall (http://m0n0.ch/wall)
5

    
6
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
7
	Copyright (C) 2009 Ermal Luçi
8
	Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32
/*
33
	pfSense_MODULE:	captiveportal
34
*/
35

    
36
require_once("auth.inc");
37
require_once("functions.inc");
38
require_once("captiveportal.inc");
39

    
40
$errormsg = "Invalid credentials specified.";
41

    
42
header("Expires: 0");
43
header("Cache-Control: no-cache, no-store, must-revalidate");
44
header("Pragma: no-cache");
45
header("Connection: close");
46

    
47
global $cpzone, $cpzoneid;
48

    
49
$cpzone = $_REQUEST['zone'];
50
$cpcfg = $config['captiveportal'][$cpzone];
51
if (empty($cpcfg)) {
52
	log_error("Submission to captiveportal with unknown parameter zone: " . htmlspecialchars($cpzone));
53
	portal_reply_page($redirurl, "error", $errormsg);
54
	ob_flush();
55
	return;
56
}
57

    
58
$cpzoneid = $cpcfg['zoneid'];
59

    
60
$orig_host = $_SERVER['HTTP_HOST'];
61
/* NOTE: IE 8/9 is buggy and that is why this is needed */
62
$orig_request = trim($_REQUEST['redirurl'], " /");
63
$clientip = $_SERVER['REMOTE_ADDR'];
64

    
65
if (!$clientip) {
66
	/* not good - bail out */
67
	log_error("Zone: {$cpzone} - Captive portal could not determine client's IP address.");
68
	$error_message = "An error occurred.  Please check the system logs for more information.";
69
	portal_reply_page($redirurl, "error", $errormsg);
70
	ob_flush();
71
	return;
72
}
73

    
74
$cpsession = captiveportal_isip_logged($clientip);
75
$ourhostname = portal_hostname_from_client_ip($clientip);
76
/* Automatically switching to the logout page requires a custom logout page to be present. */
77
if ((!empty($cpsession)) && (! $_POST['logout_id']) && (!empty($cpcfg['page']['logouttext']))) {
78
	/* if client already logged in so show logout page */
79
	$protocol = (isset($config['captiveportal'][$cpzone]['httpslogin'])) ? 'https://' : 'http://';
80
	$logouturl = "{$protocol}{$ourhostname}/";
81

    
82
	$sessionid = $cpsession['sessionid'];
83
	$attributes = array();
84
	if (!empty($cpsession['session_timeout']))
85
		$attributes['session_timeout'] = $cpsession['session_timeout'];
86
	if (!empty($cpsession['session_terminate_time']))
87
		$attributes['session_terminate_time'] = $cpsession['session_terminate_time'];
88

    
89
	include("{$g['varetc_path']}/captiveportal-{$cpzone}-logout.html");
90
	ob_flush();
91
	return;
92
} else if ($orig_host != $ourhostname) {
93
	/* the client thinks it's connected to the desired web server, but instead
94
	   it's connected to us. Issue a redirect... */
95
	$protocol = (isset($cpcfg['httpslogin'])) ? 'https://' : 'http://';
96
	header("Location: {$protocol}{$ourhostname}/index.php?zone={$cpzone}&redirurl=" . urlencode("http://{$orig_host}/{$orig_request}"));
97

    
98
	ob_flush();
99
	return;
100
}
101

    
102
if (!empty($cpcfg['redirurl'])) {
103
	$redirurl = $cpcfg['redirurl'];
104
} else if (preg_match("/redirurl=(.*)/", $orig_request, $matches)) {
105
	$redirurl = urldecode($matches[1]);
106
} else if ($_REQUEST['redirurl']) {
107
	$redirurl = $_REQUEST['redirurl'];
108
}
109

    
110
$macfilter = !isset($cpcfg['nomacfilter']);
111
$passthrumac = isset($cpcfg['passthrumacadd']);
112

    
113
/* find MAC address for client */
114
if ($macfilter || $passthrumac) {
115
	$tmpres = pfSense_ip_to_mac($clientip);
116
	if (!is_array($tmpres)) {
117
		/* unable to find MAC address - shouldn't happen! - bail out */
118
		captiveportal_logportalauth("unauthenticated", "noclientmac", $clientip, "ERROR");
119
		echo "An error occurred.  Please check the system logs for more information.";
120
		log_error("Zone: {$cpzone} - Captive portal could not determine client's MAC address.  Disable MAC address filtering in captive portal if you do not need this functionality.");
121
		ob_flush();
122
		return;
123
	}
124
	$clientmac = $tmpres['macaddr'];
125
	unset($tmpres);
126
}
127

    
128
/* find out if we need RADIUS + RADIUSMAC or not */
129
if (file_exists("{$g['vardb_path']}/captiveportal_radius_{$cpzone}.db")) {
130
	$radius_enable = TRUE;
131
	if (isset($cpcfg['radmac_enable'])) {
132
		$radmac_enable = TRUE;
133
	}
134
}
135

    
136
/* find radius context */
137
$radiusctx = 'first';
138
if ($_POST['auth_user2']) {
139
	$radiusctx = 'second';
140
}
141

    
142
if ($_POST['logout_id']) {
143
	echo <<<EOD
144
<html>
145
<head><title>Disconnecting...</title></head>
146
<body bgcolor="#435370">
147
<span style="color: #ffffff; font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px;">
148
<b>You have been disconnected.</b>
149
</span>
150
<script type="text/javascript">
151
<!--
152
setTimeout('window.close();',5000) ;
153
-->
154
</script>
155
</body>
156
</html>
157

    
158
EOD;
159
	captiveportal_disconnect_client($_POST['logout_id']);
160

    
161
} else if ($macfilter && $clientmac && captiveportal_blocked_mac($clientmac)) {
162
	captiveportal_logportalauth($clientmac, $clientmac, $clientip, "Blocked MAC address");
163
	if (!empty($cpcfg['blockedmacsurl'])) {
164
		portal_reply_page($cpcfg['blockedmacsurl'], "redir");
165
	} else {
166
		portal_reply_page($redirurl, "error", "This MAC address has been blocked");
167
	}
168

    
169
} else if ($clientmac && $radmac_enable && portal_mac_radius($clientmac, $clientip, $radiusctx)) {
170
	/* radius functions handle everything so we exit here since we're done */
171

    
172
} else if (portal_consume_passthrough_credit($clientmac)) {
173
	/* allow the client through if it had a pass-through credit for its MAC */
174
	captiveportal_logportalauth("unauthenticated", $clientmac, $clientip, "ACCEPT");
175
	portal_allow($clientip, $clientmac, "unauthenticated");
176

    
177
} else if (isset($config['voucher'][$cpzone]['enable']) && $_POST['accept'] && $_POST['auth_voucher']) {
178
	$voucher = trim($_POST['auth_voucher']);
179
	$timecredit = voucher_auth($voucher);
180
	// $timecredit contains either a credit in minutes or an error message
181
	if ($timecredit > 0) {  // voucher is valid. Remaining minutes returned
182
		// if multiple vouchers given, use the first as username
183
		$a_vouchers = preg_split("/[\t\n\r ]+/s", $voucher);
184
		$voucher = $a_vouchers[0];
185
		$attr = array(
186
			'voucher' => 1,
187
			'session_timeout' => $timecredit*60,
188
			'session_terminate_time' => 0);
189
		if (portal_allow($clientip, $clientmac, $voucher, null, $attr)) {
190
			// YES: user is good for $timecredit minutes.
191
			captiveportal_logportalauth($voucher, $clientmac, $clientip, "Voucher login good for $timecredit min.");
192
		} else {
193
			portal_reply_page($redirurl, "error", $config['voucher'][$cpzone]['descrmsgexpired'] ? $config['voucher'][$cpzone]['descrmsgexpired']: $errormsg);
194
		}
195
	} else if (-1 == $timecredit) {  // valid but expired
196
		captiveportal_logportalauth($voucher, $clientmac, $clientip, "FAILURE", "voucher expired");
197
		portal_reply_page($redirurl, "error", $config['voucher'][$cpzone]['descrmsgexpired'] ? $config['voucher'][$cpzone]['descrmsgexpired']: $errormsg);
198
	} else {
199
		captiveportal_logportalauth($voucher, $clientmac, $clientip, "FAILURE");
200
		portal_reply_page($redirurl, "error", $config['voucher'][$cpzone]['descrmsgnoaccess'] ? $config['voucher'][$cpzone]['descrmsgnoaccess'] : $errormsg);
201
	}
202

    
203
} else if ($_POST['accept'] && $radius_enable) {
204
	if (($_POST['auth_user'] && isset($_POST['auth_pass'])) || ($_POST['auth_user2'] && isset($_POST['auth_pass2']))) {
205
		if (!empty($_POST['auth_user'])) {
206
			$user = $_POST['auth_user'];
207
			$paswd = $_POST['auth_pass'];
208
		} else if (!empty($_POST['auth_user2'])) {
209
			$user = $_POST['auth_user2'];
210
			$paswd = $_POST['auth_pass2'];
211
		}
212
		$auth_list = radius($user, $paswd, $clientip, $clientmac, "USER LOGIN", $radiusctx);
213
		$type = "error";
214
		if (!empty($auth_list['url_redirection'])) {
215
			$redirurl = $auth_list['url_redirection'];
216
			$type = "redir";
217
		}
218

    
219
		if ($auth_list['auth_val'] == 1) {
220
			captiveportal_logportalauth($user, $clientmac, $clientip, "ERROR", $auth_list['error']);
221
			portal_reply_page($redirurl, $type, $auth_list['error'] ? $auth_list['error'] : $errormsg);
222
		} else if ($auth_list['auth_val'] == 3) {
223
			captiveportal_logportalauth($user, $clientmac, $clientip, "FAILURE", $auth_list['reply_message']);
224
			portal_reply_page($redirurl, $type, $auth_list['reply_message'] ? $auth_list['reply_message'] : $errormsg);
225
		}
226
	} else {
227
		if (!empty($_POST['auth_user'])) {
228
			$user = $_POST['auth_user'];
229
		} else if (!empty($_POST['auth_user2'])) {
230
			$user = $_POST['auth_user2'];
231
		} else {
232
			$user = 'unknown';
233
		}
234
		captiveportal_logportalauth($user, $clientmac, $clientip, "ERROR");
235
		portal_reply_page($redirurl, "error", $errormsg);
236
	}
237

    
238
} else if ($_POST['accept'] && $cpcfg['auth_method'] == "local") {
239
	if ($_POST['auth_user'] && $_POST['auth_pass']) {
240
		//check against local user manager
241
		$loginok = local_backed($_POST['auth_user'], $_POST['auth_pass']);
242

    
243
		if ($loginok && isset($cpcfg['localauth_priv'])) {
244
			$loginok = userHasPrivilege(getUserEntry($_POST['auth_user']), "user-services-captiveportal-login");
245
		}
246

    
247
		if ($loginok) {
248
			captiveportal_logportalauth($_POST['auth_user'], $clientmac, $clientip, "LOGIN");
249
			portal_allow($clientip, $clientmac, $_POST['auth_user']);
250
		} else {
251
			captiveportal_logportalauth($_POST['auth_user'], $clientmac, $clientip, "FAILURE");
252
			portal_reply_page($redirurl, "error", $errormsg);
253
		}
254
	} else {
255
		portal_reply_page($redirurl, "error", $errormsg);
256
	}
257

    
258
} else if ($_POST['accept'] && $clientip && $cpcfg['auth_method'] == "none") {
259
	captiveportal_logportalauth("unauthenticated", $clientmac, $clientip, "ACCEPT");
260
	portal_allow($clientip, $clientmac, "unauthenticated");
261

    
262
} else {
263
	/* display captive portal page */
264
	portal_reply_page($redirurl, "login", null, $clientmac, $clientip);
265
}
266

    
267
ob_flush();
268

    
269
?>
(1-1/3)