Project

General

Profile

Download (46.1 KB) Statistics
| Branch: | Tag: | Revision:
1 55eb9c44 --global
<?php
2 b37b4034 Phil Davis
/*
3
	auth.inc
4
*/
5 995df6c3 Stephen Beaver
/* ====================================================================
6
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
7 cb41dd63 Renato Botelho
 *	Copyright (c)  2005-2006 Bill Marquette <bill.marquette@gmail.com>
8
 *	Copyright (c)  2006 Paul Taylor <paultaylor@winn-dixie.com>
9 b37b4034 Phil Davis
 *	Copyright (c)  2003-2006 Manuel Kasper <mk@neon1.net>
10 995df6c3 Stephen Beaver
 *
11
 *	Redistribution and use in source and binary forms, with or without modification,
12
 *	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
19
 *		the documentation and/or other materials provided with the
20
 *		distribution.
21
 *
22
 *	3. All advertising materials mentioning features or use of this software
23
 *		must display the following acknowledgment:
24
 *		"This product includes software developed by the pfSense Project
25
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
26
 *
27
 *	4. The names "pfSense" and "pfSense Project" must not be used to
28
 *		 endorse or promote products derived from this software without
29
 *		 prior written permission. For written permission, please contact
30
 *		 coreteam@pfsense.org.
31
 *
32
 *	5. Products derived from this software may not be called "pfSense"
33
 *		nor may "pfSense" appear in their names without prior written
34
 *		permission of the Electric Sheep Fencing, LLC.
35
 *
36
 *	6. Redistributions of any form whatsoever must retain the following
37
 *		acknowledgment:
38
 *
39
 *	"This product includes software developed by the pfSense Project
40
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
41
 *
42
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
43
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
45
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
46
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
51
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
53
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
54
 *
55
 *	====================================================================
56
 *
57
 */
58 55eb9c44 --global
/*
59
 * NOTE : Portions of the mschapv2 support was based on the BSD licensed CHAP.php
60
 * file courtesy of Michael Retterklieber.
61
 */
62 1e0b1727 Phil Davis
if (!$do_not_include_config_gui_inc) {
63 052e65ef Scott Ullrich
	require_once("config.gui.inc");
64 1e0b1727 Phil Davis
}
65 55eb9c44 --global
66 9ae11a62 Scott Ullrich
// Will be changed to false if security checks fail
67
$security_passed = true;
68
69 1180e4f0 Sjon Hortensius
/* If this function doesn't exist, we're being called from Captive Portal or
70 0321fa1b jim-p
   another internal subsystem which does not include authgui.inc */
71 14eab6fb jim-p
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
72 0734024c Chris Buechler
	/* DNS ReBinding attack prevention.  https://redmine.pfsense.org/issues/708 */
73 0321fa1b jim-p
	$found_host = false;
74 209620ea Seth Mos
75 4cf79fdd smos
	/* Either a IPv6 address with or without a alternate port */
76 1e0b1727 Phil Davis
	if (strstr($_SERVER['HTTP_HOST'], "]")) {
77 4cf79fdd smos
		$http_host_port = explode("]", $_SERVER['HTTP_HOST']);
78 209620ea Seth Mos
		/* v6 address has more parts, drop the last part */
79 1e0b1727 Phil Davis
		if (count($http_host_port) > 1) {
80 209620ea Seth Mos
			array_pop($http_host_port);
81
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
82
		} else {
83 4cf79fdd smos
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
84 209620ea Seth Mos
		}
85 7319dc73 jim-p
	} else {
86 4fcab77b smos
		$http_host = explode(":", $_SERVER['HTTP_HOST']);
87
		$http_host = $http_host[0];
88 7319dc73 jim-p
	}
89 1e0b1727 Phil Davis
	if (is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
90 46bb8a0b Sjon Hortensius
		strcasecmp($http_host, "localhost") == 0 or $_SERVER['SERVER_ADDR'] == "::1") {
91 9ae11a62 Scott Ullrich
		$found_host = true;
92 1e0b1727 Phil Davis
	}
93
	if (strcasecmp($http_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 or
94 46bb8a0b Sjon Hortensius
		strcasecmp($http_host, $config['system']['hostname']) == 0) {
95 d7bf3178 Erik Fonnesbeck
		$found_host = true;
96 1e0b1727 Phil Davis
	}
97 9ae11a62 Scott Ullrich
98 1e0b1727 Phil Davis
	if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
99
		foreach ($config['dyndnses']['dyndns'] as $dyndns) {
100
			if (strcasecmp($dyndns['host'], $http_host) == 0) {
101 0321fa1b jim-p
				$found_host = true;
102 9ae11a62 Scott Ullrich
				break;
103
			}
104 1e0b1727 Phil Davis
		}
105
	}
106 7319dc73 jim-p
107 1e0b1727 Phil Davis
	if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
108
		foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
109
			if (strcasecmp($rfc2136['host'], $http_host) == 0) {
110 fa087612 jim-p
				$found_host = true;
111
				break;
112
			}
113 1e0b1727 Phil Davis
		}
114
	}
115 fa087612 jim-p
116 1e0b1727 Phil Davis
	if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
117 86b21903 jim-p
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
118 1e0b1727 Phil Davis
		foreach ($althosts as $ah) {
119
			if (strcasecmp($ah, $http_host) == 0 or strcasecmp($ah, $_SERVER['SERVER_ADDR']) == 0) {
120 86b21903 jim-p
				$found_host = true;
121 9ae11a62 Scott Ullrich
				break;
122
			}
123 1e0b1727 Phil Davis
		}
124 9b13f84b Scott Ullrich
	}
125 ce46b5da Scott Ullrich
126 1e0b1727 Phil Davis
	if ($found_host == false) {
127
		if (!security_checks_disabled()) {
128 8cd558b6 ayvis
			display_error_form("501", gettext("Potential DNS Rebind attack detected, see http://en.wikipedia.org/wiki/DNS_rebinding<br />Try accessing the router by IP address instead of by hostname."));
129 9ae11a62 Scott Ullrich
			exit;
130
		}
131
		$security_passed = false;
132
	}
133
}
134 ef173724 Scott Ullrich
135 9ae11a62 Scott Ullrich
// If the HTTP_REFERER is something other than ourselves then disallow.
136 1e0b1727 Phil Davis
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nohttpreferercheck'])) {
137
	if ($_SERVER['HTTP_REFERER']) {
138
		if (file_exists("{$g['tmp_path']}/setupwizard_lastreferrer")) {
139
			if ($_SERVER['HTTP_REFERER'] == file_get_contents("{$g['tmp_path']}/setupwizard_lastreferrer")) {
140 9ae11a62 Scott Ullrich
				unlink("{$g['tmp_path']}/setupwizard_lastreferrer");
141
				header("Refresh: 1; url=index.php");
142 1180e4f0 Sjon Hortensius
?>
143
<!DOCTYPE html>
144
<html lang="en">
145
<head>
146
	<link rel="stylesheet" href="/bootstrap/css/pfSense.css" />
147
	<title><?=gettext("Redirecting..."); ?></title>
148
</head>
149
<body id="error" class="no-menu">
150
	<div id="jumbotron">
151
		<div class="container">
152 c7d61071 Sander van Leeuwen
			<div class="col-sm-offset-3 col-sm-6 col-xs-12">
153
				<p><?=gettext("Redirecting to the dashboard...")?></p>
154
			</div>
155 1180e4f0 Sjon Hortensius
		</div>
156
	</div>
157
</body>
158
</html>
159
<?php
160 9ae11a62 Scott Ullrich
				exit;
161
			}
162
		}
163
		$found_host = false;
164
		$referrer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
165 e6f7e0be smos
		$referrer_host = str_replace(array("[", "]"), "", $referrer_host);
166 1e0b1727 Phil Davis
		if ($referrer_host) {
167 ae52d165 Renato Botelho
			if (strcasecmp($referrer_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 ||
168 4e322e2c Phil Davis
			    strcasecmp($referrer_host, $config['system']['hostname']) == 0) {
169 9ae11a62 Scott Ullrich
				$found_host = true;
170 1e0b1727 Phil Davis
			}
171 9f0bee02 jim-p
172 1e0b1727 Phil Davis
			if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
173 9ae11a62 Scott Ullrich
				$althosts = explode(" ", $config['system']['webgui']['althostnames']);
174
				foreach ($althosts as $ah) {
175 1e0b1727 Phil Davis
					if (strcasecmp($referrer_host, $ah) == 0) {
176 9ae11a62 Scott Ullrich
						$found_host = true;
177
						break;
178
					}
179
				}
180
			}
181 9f0bee02 jim-p
182 1e0b1727 Phil Davis
			if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
183
				foreach ($config['dyndnses']['dyndns'] as $dyndns) {
184
					if (strcasecmp($dyndns['host'], $referrer_host) == 0) {
185 9f0bee02 jim-p
						$found_host = true;
186
						break;
187
					}
188 1e0b1727 Phil Davis
				}
189
			}
190 9f0bee02 jim-p
191 1e0b1727 Phil Davis
			if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
192
				foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
193
					if (strcasecmp($rfc2136['host'], $referrer_host) == 0) {
194 9f0bee02 jim-p
						$found_host = true;
195
						break;
196
					}
197 1e0b1727 Phil Davis
				}
198
			}
199 9f0bee02 jim-p
200 1e0b1727 Phil Davis
			if (!$found_host) {
201 9ae11a62 Scott Ullrich
				$interface_list_ips = get_configured_ip_addresses();
202 1e0b1727 Phil Davis
				foreach ($interface_list_ips as $ilips) {
203
					if (strcasecmp($referrer_host, $ilips) == 0) {
204 9ae11a62 Scott Ullrich
						$found_host = true;
205
						break;
206
					}
207
				}
208 e6f7e0be smos
				$interface_list_ipv6s = get_configured_ipv6_addresses();
209 1e0b1727 Phil Davis
				foreach ($interface_list_ipv6s as $ilipv6s) {
210
					if (strcasecmp($referrer_host, $ilipv6s) == 0) {
211 e6f7e0be smos
						$found_host = true;
212
						break;
213
					}
214
				}
215 1e0b1727 Phil Davis
				if ($referrer_host == "127.0.0.1" || $referrer_host == "localhost") {
216 17dd7ff3 Chris Buechler
					// allow SSH port forwarded connections and links from localhost
217
					$found_host = true;
218
				}
219 9ae11a62 Scott Ullrich
			}
220
		}
221 1e0b1727 Phil Davis
		if ($found_host == false) {
222
			if (!security_checks_disabled()) {
223 9ae11a62 Scott Ullrich
				display_error_form("501", "An HTTP_REFERER was detected other than what is defined in System -> Advanced (" . htmlspecialchars($_SERVER['HTTP_REFERER']) . ").  You can disable this check if needed in System -> Advanced -> Admin.");
224 0f806eca Erik Fonnesbeck
				exit;
225
			}
226 9ae11a62 Scott Ullrich
			$security_passed = false;
227
		}
228 1e0b1727 Phil Davis
	} else {
229 9ae11a62 Scott Ullrich
		$security_passed = false;
230 1e0b1727 Phil Davis
	}
231 4fe9c2dc Scott Ullrich
}
232
233 1e0b1727 Phil Davis
if (function_exists("display_error_form") && $security_passed) {
234 9ae11a62 Scott Ullrich
	/* Security checks passed, so it should be OK to turn them back on */
235
	restore_security_checks();
236 1e0b1727 Phil Davis
}
237 9ae11a62 Scott Ullrich
unset($security_passed);
238
239 55eb9c44 --global
$groupindex = index_groups();
240
$userindex = index_users();
241
242
function index_groups() {
243
	global $g, $debug, $config, $groupindex;
244
245
	$groupindex = array();
246
247 6dcd80af Ermal
	if (is_array($config['system']['group'])) {
248 55eb9c44 --global
		$i = 0;
249 1e0b1727 Phil Davis
		foreach ($config['system']['group'] as $groupent) {
250 55eb9c44 --global
			$groupindex[$groupent['name']] = $i;
251
			$i++;
252
		}
253
	}
254
255
	return ($groupindex);
256
}
257
258
function index_users() {
259
	global $g, $debug, $config;
260
261 6dcd80af Ermal
	if (is_array($config['system']['user'])) {
262 55eb9c44 --global
		$i = 0;
263 1e0b1727 Phil Davis
		foreach ($config['system']['user'] as $userent) {
264 55eb9c44 --global
			$userindex[$userent['name']] = $i;
265
			$i++;
266
		}
267
	}
268
269
	return ($userindex);
270
}
271
272
function & getUserEntry($name) {
273
	global $debug, $config, $userindex;
274 1e0b1727 Phil Davis
	if (isset($userindex[$name])) {
275 55eb9c44 --global
		return $config['system']['user'][$userindex[$name]];
276 1e0b1727 Phil Davis
	}
277 55eb9c44 --global
}
278
279
function & getUserEntryByUID($uid) {
280
	global $debug, $config;
281 84924e76 Ermal
282 1e0b1727 Phil Davis
	if (is_array($config['system']['user'])) {
283
		foreach ($config['system']['user'] as & $user) {
284
			if ($user['uid'] == $uid) {
285 84924e76 Ermal
				return $user;
286 1e0b1727 Phil Davis
			}
287
		}
288
	}
289 55eb9c44 --global
290
	return false;
291
}
292
293
function & getGroupEntry($name) {
294
	global $debug, $config, $groupindex;
295 1e0b1727 Phil Davis
	if (isset($groupindex[$name])) {
296 55eb9c44 --global
		return $config['system']['group'][$groupindex[$name]];
297 1e0b1727 Phil Davis
	}
298 55eb9c44 --global
}
299
300
function & getGroupEntryByGID($gid) {
301
	global $debug, $config;
302 84924e76 Ermal
303 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
304
		foreach ($config['system']['group'] as & $group) {
305
			if ($group['gid'] == $gid) {
306 84924e76 Ermal
				return $group;
307 1e0b1727 Phil Davis
			}
308
		}
309
	}
310 55eb9c44 --global
311
	return false;
312
}
313
314 6dc88d53 Ermal Luci
function get_user_privileges(& $user) {
315
316 1e0b1727 Phil Davis
	$privs = $user['priv'];
317
	if (!is_array($privs)) {
318
		$privs = array();
319
	}
320 6dc88d53 Ermal Luci
321 1e0b1727 Phil Davis
	$names = local_user_get_groups($user, true);
322 6dc88d53 Ermal Luci
323 1e0b1727 Phil Davis
	foreach ($names as $name) {
324
		$group = getGroupEntry($name);
325
		if (is_array($group['priv'])) {
326 4de8f7ba Phil Davis
			$privs = array_merge($privs, $group['priv']);
327 1e0b1727 Phil Davis
		}
328
	}
329 6dc88d53 Ermal Luci
330 1e0b1727 Phil Davis
	return $privs;
331 6dc88d53 Ermal Luci
}
332
333
function userHasPrivilege($userent, $privid = false) {
334
335 1e0b1727 Phil Davis
	if (!$privid || !is_array($userent)) {
336
		return false;
337
	}
338 6dc88d53 Ermal Luci
339 1e0b1727 Phil Davis
	$privs = get_user_privileges($userent);
340 6dc88d53 Ermal Luci
341 1e0b1727 Phil Davis
	if (!is_array($privs)) {
342
		return false;
343
	}
344 6dc88d53 Ermal Luci
345 1e0b1727 Phil Davis
	if (!in_array($privid, $privs)) {
346
		return false;
347
	}
348 6dc88d53 Ermal Luci
349 1e0b1727 Phil Davis
	return true;
350 6dc88d53 Ermal Luci
}
351
352 55eb9c44 --global
function local_backed($username, $passwd) {
353
354
	$user = getUserEntry($username);
355 1e0b1727 Phil Davis
	if (!$user) {
356 55eb9c44 --global
		return false;
357 1e0b1727 Phil Davis
	}
358 55eb9c44 --global
359 1e0b1727 Phil Davis
	if (is_account_disabled($username) || is_account_expired($username)) {
360 a13ce628 Ermal Lu?i
		return false;
361 1e0b1727 Phil Davis
	}
362 a13ce628 Ermal Lu?i
363 1e0b1727 Phil Davis
	if ($user['password']) {
364
		if (crypt($passwd, $user['password']) == $user['password']) {
365 55eb9c44 --global
			return true;
366 1e0b1727 Phil Davis
		}
367 55eb9c44 --global
	}
368
369 1e0b1727 Phil Davis
	if ($user['md5-hash']) {
370
		if (md5($passwd) == $user['md5-hash']) {
371 55eb9c44 --global
			return true;
372 1e0b1727 Phil Davis
		}
373 55eb9c44 --global
	}
374
375
	return false;
376
}
377
378
function local_sync_accounts() {
379
	global $debug, $config;
380
	conf_mount_rw();
381
382
	/* remove local users to avoid uid conflicts */
383
	$fd = popen("/usr/sbin/pw usershow -a", "r");
384
	if ($fd) {
385
		while (!feof($fd)) {
386 4de8f7ba Phil Davis
			$line = explode(":", fgets($fd));
387 1e0b1727 Phil Davis
			if (((!strncmp($line[0], "_", 1)) || ($line[2] < 2000) || ($line[2] > 65000)) && ($line[0] != "admin")) {
388 55eb9c44 --global
				continue;
389 1e0b1727 Phil Davis
			}
390 2b41df9c Renato Botelho
			/*
391
			 * If a crontab was created to user, pw userdel will be interactive and
392
			 * can cause issues. Just remove crontab before run it when necessary
393
			 */
394
			unlink_if_exists("/var/cron/tabs/{$line[0]}");
395 0f84dee3 Renato Botelho
			$cmd = "/usr/sbin/pw userdel -n '{$line[0]}'";
396 1e0b1727 Phil Davis
			if ($debug) {
397 94021404 Carlos Eduardo Ramos
				log_error(sprintf(gettext("Running: %s"), $cmd));
398 1e0b1727 Phil Davis
			}
399 55eb9c44 --global
			mwexec($cmd);
400
		}
401
		pclose($fd);
402
	}
403
404
	/* remove local groups to avoid gid conflicts */
405
	$gids = array();
406
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
407
	if ($fd) {
408
		while (!feof($fd)) {
409 4de8f7ba Phil Davis
			$line = explode(":", fgets($fd));
410 1e0b1727 Phil Davis
			if (!strncmp($line[0], "_", 1)) {
411 55eb9c44 --global
				continue;
412 1e0b1727 Phil Davis
			}
413
			if ($line[2] < 2000) {
414 55eb9c44 --global
				continue;
415 1e0b1727 Phil Davis
			}
416
			if ($line[2] > 65000) {
417 55eb9c44 --global
				continue;
418 1e0b1727 Phil Davis
			}
419 55eb9c44 --global
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
420 1e0b1727 Phil Davis
			if ($debug) {
421 94021404 Carlos Eduardo Ramos
				log_error(sprintf(gettext("Running: %s"), $cmd));
422 1e0b1727 Phil Davis
			}
423 55eb9c44 --global
			mwexec($cmd);
424
		}
425
		pclose($fd);
426
	}
427
428
	/* make sure the all group exists */
429
	$allgrp = getGroupEntryByGID(1998);
430
	local_group_set($allgrp, true);
431
432 5af2baf7 jim-p
	/* sync all local users */
433 1e0b1727 Phil Davis
	if (is_array($config['system']['user'])) {
434
		foreach ($config['system']['user'] as $user) {
435 5af2baf7 jim-p
			local_user_set($user);
436 1e0b1727 Phil Davis
		}
437
	}
438 5af2baf7 jim-p
439 f3e0a111 jim-p
	/* sync all local groups */
440 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
441
		foreach ($config['system']['group'] as $group) {
442 f3e0a111 jim-p
			local_group_set($group);
443 1e0b1727 Phil Davis
		}
444
	}
445 f3e0a111 jim-p
446 55eb9c44 --global
	conf_mount_ro();
447
448
}
449
450
function local_user_set(& $user) {
451
	global $g, $debug;
452
453 b3c106a0 Ermal
	if (empty($user['password'])) {
454
		log_error("There is something wrong in your config because user {$user['name']} password is missing!");
455
		return;
456
	}
457
458 2bb07efc Scott Ullrich
	conf_mount_rw();
459
460 1180e4f0 Sjon Hortensius
	$home_base = "/home/";
461 55eb9c44 --global
	$user_uid = $user['uid'];
462
	$user_name = $user['name'];
463 461df7c0 jim-p
	$user_home = "{$home_base}{$user_name}";
464 55eb9c44 --global
	$user_shell = "/etc/rc.initial";
465
	$user_group = "nobody";
466
467
	// Ensure $home_base exists and is writable
468 1e0b1727 Phil Davis
	if (!is_dir($home_base)) {
469 55eb9c44 --global
		mkdir($home_base, 0755);
470 1e0b1727 Phil Davis
	}
471 55eb9c44 --global
472 df8d74de jim-p
	$lock_account = false;
473 55eb9c44 --global
	/* configure shell type */
474 3e251b12 Erik Fonnesbeck
	/* Cases here should be ordered by most privileged to least privileged. */
475 a137fedd jim-p
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
476 29293dce jim-p
		$user_shell = "/bin/tcsh";
477 1ed86bc6 jim-p
	} elseif (userHasPrivilege($user, "user-copy-files")) {
478 a137fedd jim-p
		$user_shell = "/usr/local/bin/scponly";
479 3e251b12 Erik Fonnesbeck
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
480
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
481 fbfd675a jim-p
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
482
		$user_shell = "/sbin/nologin";
483 1ed86bc6 jim-p
	} else {
484
		$user_shell = "/sbin/nologin";
485 df8d74de jim-p
		$lock_account = true;
486
	}
487
488
	/* Lock out disabled or expired users, unless it's root/admin. */
489
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
490
		$user_shell = "/sbin/nologin";
491
		$lock_account = true;
492 55eb9c44 --global
	}
493
494
	/* root user special handling */
495
	if ($user_uid == 0) {
496
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
497 1e0b1727 Phil Davis
		if ($debug) {
498 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("Running: %s"), $cmd));
499 1e0b1727 Phil Davis
		}
500 55eb9c44 --global
		$fd = popen($cmd, "w");
501
		fwrite($fd, $user['password']);
502
		pclose($fd);
503
		$user_group = "wheel";
504 2708e399 jim-p
		$user_home = "/root";
505 29293dce jim-p
		$user_shell = "/etc/rc.initial";
506 55eb9c44 --global
	}
507
508
	/* read from pw db */
509 9fd14591 jim-p
	$fd = popen("/usr/sbin/pw usershow -n {$user_name} 2>&1", "r");
510 55eb9c44 --global
	$pwread = fgets($fd);
511
	pclose($fd);
512 9fd14591 jim-p
	$userattrs = explode(":", trim($pwread));
513 55eb9c44 --global
514
	/* determine add or mod */
515 9fd14591 jim-p
	if (($userattrs[0] != $user['name']) || (!strncmp($pwread, "pw:", 3))) {
516 4b49a8a9 jim-p
		$user_op = "useradd -m -k /etc/skel -o";
517 38564fde smos
	} else {
518 55eb9c44 --global
		$user_op = "usermod";
519 38564fde smos
	}
520 55eb9c44 --global
521 1180e4f0 Sjon Hortensius
	$comment = str_replace(array(":", "!", "@"), " ", $user['descr']);
522 55eb9c44 --global
	/* add or mod pw db */
523
	$cmd = "/usr/sbin/pw {$user_op} -q -u {$user_uid} -n {$user_name}".
524 eb72845c jim-p
			" -g {$user_group} -s {$user_shell} -d {$user_home}".
525 1cb94b24 Ermal
			" -c ".escapeshellarg($comment)." -H 0 2>&1";
526 55eb9c44 --global
527 1e0b1727 Phil Davis
	if ($debug) {
528 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
529 1e0b1727 Phil Davis
	}
530 55eb9c44 --global
	$fd = popen($cmd, "w");
531
	fwrite($fd, $user['password']);
532
	pclose($fd);
533
534
	/* create user directory if required */
535
	if (!is_dir($user_home)) {
536
		mkdir($user_home, 0700);
537
	}
538 23c652cd Ermal
	@chown($user_home, $user_name);
539
	@chgrp($user_home, $user_group);
540 55eb9c44 --global
541
	/* write out ssh authorized key file */
542 1e0b1727 Phil Davis
	if ($user['authorizedkeys']) {
543 a2286360 Ermal Lu?i
		if (!is_dir("{$user_home}/.ssh")) {
544 23c652cd Ermal
			@mkdir("{$user_home}/.ssh", 0700);
545
			@chown("{$user_home}/.ssh", $user_name);
546 a2286360 Ermal Lu?i
		}
547
		$keys = base64_decode($user['authorizedkeys']);
548 23c652cd Ermal
		@file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
549
		@chown("{$user_home}/.ssh/authorized_keys", $user_name);
550 1e0b1727 Phil Davis
	} else {
551 cdab65cc Erik Fonnesbeck
		unlink_if_exists("{$user_home}/.ssh/authorized_keys");
552 1e0b1727 Phil Davis
	}
553 df8d74de jim-p
554
	$un = $lock_account ? "" : "un";
555 e4d09dca Renato Botelho
	exec("/usr/sbin/pw {$un}lock {$user_name} -q 2>/dev/null");
556 1180e4f0 Sjon Hortensius
557 2bb07efc Scott Ullrich
	conf_mount_ro();
558 55eb9c44 --global
}
559
560
function local_user_del($user) {
561
	global $debug;
562 2bb07efc Scott Ullrich
563 55eb9c44 --global
	/* remove all memberships */
564 019e6c3f jim-p
	local_user_set_groups($user);
565 55eb9c44 --global
566 a39675ec jim-p
	/* Don't remove /root */
567 1e0b1727 Phil Davis
	if ($user['uid'] != 0) {
568 a39675ec jim-p
		$rmhome = "-r";
569 1e0b1727 Phil Davis
	}
570 a39675ec jim-p
571 9fd14591 jim-p
	/* read from pw db */
572
	$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
573
	$pwread = fgets($fd);
574
	pclose($fd);
575
	$userattrs = explode(":", trim($pwread));
576
577
	if ($userattrs[0] != $user['name']) {
578
		log_error("Tried to remove user {$user['name']} but got user {$userattrs[0]} instead. Bailing.");
579
		return;
580
	}
581
582 55eb9c44 --global
	/* delete from pw db */
583 9fd14591 jim-p
	$cmd = "/usr/sbin/pw userdel -n {$user['name']} {$rmhome}";
584 55eb9c44 --global
585 1e0b1727 Phil Davis
	if ($debug) {
586 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
587 1e0b1727 Phil Davis
	}
588 0914b6bb Ermal
	mwexec($cmd);
589 2bb07efc Scott Ullrich
590 0914b6bb Ermal
	/* Delete user from groups needs a call to write_config() */
591
	local_group_del_user($user);
592 55eb9c44 --global
}
593
594 4d9801c2 Jim Thompson
function local_user_set_password(&$user, $password) {
595 55eb9c44 --global
596
	$user['password'] = crypt($password);
597
	$user['md5-hash'] = md5($password);
598
599
	// Converts ascii to unicode.
600
	$astr = (string) $password;
601
	$ustr = '';
602
	for ($i = 0; $i < strlen($astr); $i++) {
603
		$a = ord($astr{$i}) << 8;
604 4de8f7ba Phil Davis
		$ustr .= sprintf("%X", $a);
605 55eb9c44 --global
	}
606
607
}
608
609
function local_user_get_groups($user, $all = false) {
610
	global $debug, $config;
611
612
	$groups = array();
613 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
614 55eb9c44 --global
		return $groups;
615 1e0b1727 Phil Davis
	}
616 55eb9c44 --global
617 1e0b1727 Phil Davis
	foreach ($config['system']['group'] as $group) {
618 4de8f7ba Phil Davis
		if ($all || (!$all && ($group['name'] != "all"))) {
619 1e0b1727 Phil Davis
			if (is_array($group['member'])) {
620
				if (in_array($user['uid'], $group['member'])) {
621 55eb9c44 --global
					$groups[] = $group['name'];
622 1e0b1727 Phil Davis
				}
623
			}
624
		}
625
	}
626 55eb9c44 --global
627 1e0b1727 Phil Davis
	if ($all) {
628 b0c231e4 jim-p
		$groups[] = "all";
629 1e0b1727 Phil Davis
	}
630 b0c231e4 jim-p
631 55eb9c44 --global
	sort($groups);
632
633
	return $groups;
634 1180e4f0 Sjon Hortensius
635 55eb9c44 --global
}
636
637 4de8f7ba Phil Davis
function local_user_set_groups($user, $new_groups = NULL) {
638 55eb9c44 --global
	global $debug, $config, $groupindex;
639 4de8f7ba Phil Davis
640 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
641 55eb9c44 --global
		return;
642 1e0b1727 Phil Davis
	}
643 55eb9c44 --global
644 739c78ac jim-p
	$cur_groups = local_user_get_groups($user, true);
645 55eb9c44 --global
	$mod_groups = array();
646
647 1e0b1727 Phil Davis
	if (!is_array($new_groups)) {
648 55eb9c44 --global
		$new_groups = array();
649 1e0b1727 Phil Davis
	}
650 55eb9c44 --global
651 1e0b1727 Phil Davis
	if (!is_array($cur_groups)) {
652 55eb9c44 --global
		$cur_groups = array();
653 1e0b1727 Phil Davis
	}
654 55eb9c44 --global
655
	/* determine which memberships to add */
656
	foreach ($new_groups as $groupname) {
657 4de8f7ba Phil Davis
		if ($groupname == '' || in_array($groupname, $cur_groups)) {
658 55eb9c44 --global
			continue;
659 1e0b1727 Phil Davis
		}
660 55eb9c44 --global
		$group = & $config['system']['group'][$groupindex[$groupname]];
661
		$group['member'][] = $user['uid'];
662
		$mod_groups[] = $group;
663
	}
664 9ae11a62 Scott Ullrich
	unset($group);
665 55eb9c44 --global
666
	/* determine which memberships to remove */
667
	foreach ($cur_groups as $groupname) {
668 4de8f7ba Phil Davis
		if (in_array($groupname, $new_groups)) {
669 e879fc81 Ermal
			continue;
670 1e0b1727 Phil Davis
		}
671
		if (!isset($config['system']['group'][$groupindex[$groupname]])) {
672 25fec9b3 jim-p
			continue;
673 1e0b1727 Phil Davis
		}
674 55eb9c44 --global
		$group = & $config['system']['group'][$groupindex[$groupname]];
675 7b5c56ea jim-p
		if (is_array($group['member'])) {
676
			$index = array_search($user['uid'], $group['member']);
677
			array_splice($group['member'], $index, 1);
678
			$mod_groups[] = $group;
679
		}
680 55eb9c44 --global
	}
681 9ae11a62 Scott Ullrich
	unset($group);
682 55eb9c44 --global
683
	/* sync all modified groups */
684 1e0b1727 Phil Davis
	foreach ($mod_groups as $group) {
685 55eb9c44 --global
		local_group_set($group);
686 1e0b1727 Phil Davis
	}
687 55eb9c44 --global
}
688
689 0914b6bb Ermal
function local_group_del_user($user) {
690
	global $config;
691
692 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
693
		return;
694
	}
695 0914b6bb Ermal
696 1e0b1727 Phil Davis
	foreach ($config['system']['group'] as $group) {
697 0914b6bb Ermal
		if (is_array($group['member'])) {
698
			foreach ($group['member'] as $idx => $uid) {
699 1e0b1727 Phil Davis
				if ($user['uid'] == $uid) {
700 0914b6bb Ermal
					unset($config['system']['group']['member'][$idx]);
701 1e0b1727 Phil Davis
				}
702 0914b6bb Ermal
			}
703
		}
704
	}
705
}
706
707 55eb9c44 --global
function local_group_set($group, $reset = false) {
708
	global $debug;
709
710
	$group_name = $group['name'];
711
	$group_gid = $group['gid'];
712 baca968c Ermal
	$group_members = '';
713 1e0b1727 Phil Davis
	if (!$reset && !empty($group['member']) && count($group['member']) > 0) {
714 4de8f7ba Phil Davis
		$group_members = implode(",", $group['member']);
715 1e0b1727 Phil Davis
	}
716 55eb9c44 --global
717 1e0b1727 Phil Davis
	if (empty($group_name)) {
718 baca968c Ermal
		return;
719 1e0b1727 Phil Davis
	}
720 baca968c Ermal
721 55eb9c44 --global
	/* read from group db */
722
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
723
	$pwread = fgets($fd);
724
	pclose($fd);
725
726
	/* determine add or mod */
727 1e0b1727 Phil Davis
	if (!strncmp($pwread, "pw:", 3)) {
728 55eb9c44 --global
		$group_op = "groupadd";
729 1e0b1727 Phil Davis
	} else {
730 55eb9c44 --global
		$group_op = "groupmod";
731 1e0b1727 Phil Davis
	}
732 55eb9c44 --global
733
	/* add or mod group db */
734 224b4208 Renato Botelho
	$cmd = "/usr/sbin/pw {$group_op} {$group_name} -g {$group_gid} -M '{$group_members}' 2>&1";
735 55eb9c44 --global
736 1e0b1727 Phil Davis
	if ($debug) {
737 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
738 1e0b1727 Phil Davis
	}
739 0914b6bb Ermal
	mwexec($cmd);
740 55eb9c44 --global
741
}
742
743
function local_group_del($group) {
744
	global $debug;
745
746
	/* delete from group db */
747
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
748
749 1e0b1727 Phil Davis
	if ($debug) {
750 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
751 1e0b1727 Phil Davis
	}
752 0914b6bb Ermal
	mwexec($cmd);
753 55eb9c44 --global
}
754
755 6306b5dd Ermal Lu?i
function ldap_test_connection($authcfg) {
756 55eb9c44 --global
	global $debug, $config, $g;
757
758 c61e4626 Ermal Lu?i
	if ($authcfg) {
759 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
760
			$ldapproto = "ldap";
761
		} else {
762
			$ldapproto = "ldaps";
763
		}
764
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
765
		$ldapport = $authcfg['ldap_port'];
766
		if (!empty($ldapport)) {
767 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
768 1e0b1727 Phil Davis
		}
769
		$ldapbasedn = $authcfg['ldap_basedn'];
770
		$ldapbindun = $authcfg['ldap_binddn'];
771
		$ldapbindpw = $authcfg['ldap_bindpw'];
772
	} else {
773 6306b5dd Ermal Lu?i
		return false;
774 1e0b1727 Phil Davis
	}
775 55eb9c44 --global
776 1e0b1727 Phil Davis
	/* first check if there is even an LDAP server populated */
777 4de8f7ba Phil Davis
	if (!$ldapserver) {
778 1e0b1727 Phil Davis
		return false;
779
	}
780 c61e4626 Ermal Lu?i
781 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
782
	ldap_setup_caenv($authcfg);
783 fe2031ab Ermal
784 1e0b1727 Phil Davis
	/* connect and see if server is up */
785
	$error = false;
786
	if (!($ldap = ldap_connect($ldapserver))) {
787 9f27de6d jim-p
		$error = true;
788 1e0b1727 Phil Davis
	}
789 c61e4626 Ermal Lu?i
790 1e0b1727 Phil Davis
	if ($error == true) {
791
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
792
		return false;
793
	}
794 55eb9c44 --global
795
	return true;
796
}
797
798 fe2031ab Ermal
function ldap_setup_caenv($authcfg) {
799
	global $g;
800 007e59d2 jim-p
	require_once("certs.inc");
801 fe2031ab Ermal
802
	unset($caref);
803 a7702ed5 Ermal
	if (empty($authcfg['ldap_caref']) || !strstr($authcfg['ldap_urltype'], "SSL")) {
804 fe2031ab Ermal
		putenv('LDAPTLS_REQCERT=never');
805
		return;
806
	} else {
807 a7702ed5 Ermal
		$caref = lookup_ca($authcfg['ldap_caref']);
808 fe2031ab Ermal
		if (!$caref) {
809 a7702ed5 Ermal
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
810 fe2031ab Ermal
			/* XXX: Prevent for credential leaking since we cannot setup the CA env. Better way? */
811
			putenv('LDAPTLS_REQCERT=hard');
812
			return;
813
		}
814 1e0b1727 Phil Davis
		if (!is_dir("{$g['varrun_path']}/certs")) {
815 fe2031ab Ermal
			@mkdir("{$g['varrun_path']}/certs");
816 1e0b1727 Phil Davis
		}
817
		if (file_exists("{$g['varrun_path']}/certs/{$caref['refid']}.ca")) {
818 b2a0a8e9 jim-p
			@unlink("{$g['varrun_path']}/certs/{$caref['refid']}.ca");
819 1e0b1727 Phil Davis
		}
820 b2a0a8e9 jim-p
		file_put_contents("{$g['varrun_path']}/certs/{$caref['refid']}.ca", base64_decode($caref['crt']));
821
		@chmod("{$g['varrun_path']}/certs/{$caref['refid']}.ca", 0600);
822 fe2031ab Ermal
		putenv('LDAPTLS_REQCERT=hard');
823
		/* XXX: Probably even the hashed link should be created for this? */
824 906daddc Ermal
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
825 b2a0a8e9 jim-p
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
826 fe2031ab Ermal
	}
827
}
828
829 6306b5dd Ermal Lu?i
function ldap_test_bind($authcfg) {
830 55eb9c44 --global
	global $debug, $config, $g;
831
832 c61e4626 Ermal Lu?i
	if ($authcfg) {
833 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
834
			$ldapproto = "ldap";
835
		} else {
836
			$ldapproto = "ldaps";
837
		}
838
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
839
		$ldapport = $authcfg['ldap_port'];
840
		if (!empty($ldapport)) {
841 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
842 1e0b1727 Phil Davis
		}
843
		$ldapbasedn = $authcfg['ldap_basedn'];
844
		$ldapbindun = $authcfg['ldap_binddn'];
845
		$ldapbindpw = $authcfg['ldap_bindpw'];
846
		$ldapver = $authcfg['ldap_protver'];
847 d6b4dfe3 jim-p
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 25;
848 1e0b1727 Phil Davis
		if (empty($ldapbndun) || empty($ldapbindpw)) {
849
			$ldapanon = true;
850
		} else {
851
			$ldapanon = false;
852
		}
853
	} else {
854 6306b5dd Ermal Lu?i
		return false;
855 1e0b1727 Phil Davis
	}
856 c61e4626 Ermal Lu?i
857
	/* first check if there is even an LDAP server populated */
858 1e0b1727 Phil Davis
	if (!$ldapserver) {
859
		return false;
860
	}
861 c61e4626 Ermal Lu?i
862 fe2031ab Ermal
	/* Setup CA environment if needed. */
863
	ldap_setup_caenv($authcfg);
864
865 1e0b1727 Phil Davis
	/* connect and see if server is up */
866
	$error = false;
867
	if (!($ldap = ldap_connect($ldapserver))) {
868 9f27de6d jim-p
		$error = true;
869 1e0b1727 Phil Davis
	}
870 c61e4626 Ermal Lu?i
871 1e0b1727 Phil Davis
	if ($error == true) {
872
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
873
		return false;
874
	}
875 55eb9c44 --global
876
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
877 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
878 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
879 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
880
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
881 1180e4f0 Sjon Hortensius
882 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
883
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
884 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
885 6306b5dd Ermal Lu?i
		if (!($res = @ldap_bind($ldap))) {
886
			@ldap_close($ldap);
887 c61e4626 Ermal Lu?i
			return false;
888 6306b5dd Ermal Lu?i
		}
889
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
890
		@ldap_close($ldap);
891 55eb9c44 --global
		return false;
892 6306b5dd Ermal Lu?i
	}
893 55eb9c44 --global
894 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
895 c61e4626 Ermal Lu?i
896 55eb9c44 --global
	return true;
897
}
898
899 6306b5dd Ermal Lu?i
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
900 55eb9c44 --global
	global $debug, $config, $g;
901
902 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
903 55eb9c44 --global
		return;
904 1e0b1727 Phil Davis
	}
905 55eb9c44 --global
906 7a938f1b Ermal
	$ous = array();
907
908 c61e4626 Ermal Lu?i
	if ($authcfg) {
909 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
910
			$ldapproto = "ldap";
911
		} else {
912
			$ldapproto = "ldaps";
913
		}
914
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
915
		$ldapport = $authcfg['ldap_port'];
916
		if (!empty($ldapport)) {
917 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
918 1e0b1727 Phil Davis
		}
919
		$ldapbasedn = $authcfg['ldap_basedn'];
920
		$ldapbindun = $authcfg['ldap_binddn'];
921
		$ldapbindpw = $authcfg['ldap_bindpw'];
922
		$ldapver = $authcfg['ldap_protver'];
923
		if (empty($ldapbindun) || empty($ldapbindpw)) {
924
			$ldapanon = true;
925
		} else {
926
			$ldapanon = false;
927
		}
928
		$ldapname = $authcfg['name'];
929
		$ldapfallback = false;
930
		$ldapscope = $authcfg['ldap_scope'];
931 d6b4dfe3 jim-p
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 25;
932 1e0b1727 Phil Davis
	} else {
933 6306b5dd Ermal Lu?i
		return false;
934 1e0b1727 Phil Davis
	}
935 55eb9c44 --global
936 1e0b1727 Phil Davis
	/* first check if there is even an LDAP server populated */
937
	if (!$ldapserver) {
938
		log_error(gettext("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined."));
939
		return $ous;
940
	}
941 c61e4626 Ermal Lu?i
942 fe2031ab Ermal
	/* Setup CA environment if needed. */
943
	ldap_setup_caenv($authcfg);
944
945 c61e4626 Ermal Lu?i
	/* connect and see if server is up */
946 1e0b1727 Phil Davis
	$error = false;
947
	if (!($ldap = ldap_connect($ldapserver))) {
948 9f27de6d jim-p
		$error = true;
949 1e0b1727 Phil Davis
	}
950 c61e4626 Ermal Lu?i
951 1e0b1727 Phil Davis
	if ($error == true) {
952
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
953
		return $ous;
954
	}
955 c61e4626 Ermal Lu?i
956
	$ldapfilter = "(|(ou=*)(cn=Users))";
957 55eb9c44 --global
958
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
959 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
960 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
961 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
962
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
963 55eb9c44 --global
964 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
965
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
966 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
967 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
968 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind anonymously to server %s."), $ldapname));
969 6306b5dd Ermal Lu?i
			@ldap_close($ldap);
970 1e0b1727 Phil Davis
			return $ous;
971 c61e4626 Ermal Lu?i
		}
972
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
973 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind to server %s."), $ldapname));
974 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
975 c61e4626 Ermal Lu?i
		return $ous;
976 55eb9c44 --global
	}
977
978 1e0b1727 Phil Davis
	if ($ldapscope == "one") {
979 c61e4626 Ermal Lu?i
		$ldapfunc = "ldap_list";
980 1e0b1727 Phil Davis
	} else {
981 c61e4626 Ermal Lu?i
		$ldapfunc = "ldap_search";
982 1e0b1727 Phil Davis
	}
983 55eb9c44 --global
984 7a938f1b Ermal
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
985
	$info = @ldap_get_entries($ldap, $search);
986 55eb9c44 --global
987
	if (is_array($info)) {
988
		foreach ($info as $inf) {
989
			if (!$show_complete_ou) {
990 cfbfd941 smos
				$inf_split = explode(",", $inf['dn']);
991 55eb9c44 --global
				$ou = $inf_split[0];
992 4de8f7ba Phil Davis
				$ou = str_replace("OU=", "", $ou);
993
				$ou = str_replace("CN=", "", $ou);
994 1e0b1727 Phil Davis
			} else {
995
				if ($inf['dn']) {
996 55eb9c44 --global
					$ou = $inf['dn'];
997 1e0b1727 Phil Davis
				}
998
			}
999
			if ($ou) {
1000 55eb9c44 --global
				$ous[] = $ou;
1001 1e0b1727 Phil Davis
			}
1002 55eb9c44 --global
		}
1003
	}
1004
1005 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1006
1007 55eb9c44 --global
	return $ous;
1008
}
1009
1010 6306b5dd Ermal Lu?i
function ldap_get_groups($username, $authcfg) {
1011 55eb9c44 --global
	global $debug, $config;
1012 1180e4f0 Sjon Hortensius
1013 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
1014 55eb9c44 --global
		return;
1015 1e0b1727 Phil Davis
	}
1016 1180e4f0 Sjon Hortensius
1017 1e0b1727 Phil Davis
	if (!$username) {
1018 55eb9c44 --global
		return false;
1019 1e0b1727 Phil Davis
	}
1020 55eb9c44 --global
1021 1e0b1727 Phil Davis
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1022 2ce660ad smos
		$username_split = explode("@", $username);
1023 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1024 55eb9c44 --global
	}
1025
1026 1e0b1727 Phil Davis
	if (stristr($username, "\\")) {
1027 cfbfd941 smos
		$username_split = explode("\\", $username);
1028 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1029
	}
1030
1031 55eb9c44 --global
	//log_error("Getting LDAP groups for {$username}.");
1032 1e0b1727 Phil Davis
	if ($authcfg) {
1033
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
1034
			$ldapproto = "ldap";
1035
		} else {
1036
			$ldapproto = "ldaps";
1037
		}
1038
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1039
		$ldapport = $authcfg['ldap_port'];
1040
		if (!empty($ldapport)) {
1041 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
1042 1e0b1727 Phil Davis
		}
1043
		$ldapbasedn = $authcfg['ldap_basedn'];
1044
		$ldapbindun = $authcfg['ldap_binddn'];
1045
		$ldapbindpw = $authcfg['ldap_bindpw'];
1046
		$ldapauthcont = $authcfg['ldap_authcn'];
1047
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1048
		$ldapgroupattribute = strtolower($authcfg['ldap_attr_member']);
1049 149efbea jim-p
		if (isset($authcfg['ldap_rfc2307'])) {
1050
			$ldapfilter         = "(&(objectClass={$authcfg['ldap_attr_groupobj']})({$ldapgroupattribute}={$username}))";
1051
		} else {
1052
			$ldapfilter         = "({$ldapnameattribute}={$username})";
1053
		}
1054 1e0b1727 Phil Davis
		$ldaptype = "";
1055
		$ldapver = $authcfg['ldap_protver'];
1056
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1057
			$ldapanon = true;
1058
		} else {
1059
			$ldapanon = false;
1060
		}
1061
		$ldapname = $authcfg['name'];
1062
		$ldapfallback = false;
1063
		$ldapscope = $authcfg['ldap_scope'];
1064 d6b4dfe3 jim-p
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 25;
1065 1e0b1727 Phil Davis
	} else {
1066 6306b5dd Ermal Lu?i
		return false;
1067 1e0b1727 Phil Davis
	}
1068 c61e4626 Ermal Lu?i
1069 149efbea jim-p
	if (isset($authcfg['ldap_rfc2307'])) {
1070
		$ldapdn = $ldapbasedn;
1071
	} else {
1072
		$ldapdn = $_SESSION['ldapdn'];
1073
	}
1074 c61e4626 Ermal Lu?i
1075 55eb9c44 --global
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
1076
	$ldapgroupattribute = strtolower($ldapgroupattribute);
1077 c61e4626 Ermal Lu?i
	$memberof = array();
1078 55eb9c44 --global
1079 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
1080
	ldap_setup_caenv($authcfg);
1081 fe2031ab Ermal
1082 55eb9c44 --global
	/* connect and see if server is up */
1083 c61e4626 Ermal Lu?i
	$error = false;
1084 1e0b1727 Phil Davis
	if (!($ldap = ldap_connect($ldapserver))) {
1085 9f27de6d jim-p
		$error = true;
1086 1e0b1727 Phil Davis
	}
1087 c61e4626 Ermal Lu?i
1088
	if ($error == true) {
1089 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_groups() Could not connect to server %s."), $ldapname));
1090 1e0b1727 Phil Davis
		return memberof;
1091
	}
1092 1180e4f0 Sjon Hortensius
1093 55eb9c44 --global
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1094 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1095 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1096 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1097
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1098 55eb9c44 --global
1099
	/* bind as user that has rights to read group attributes */
1100 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1101
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1102 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
1103 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
1104 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
1105 6306b5dd Ermal Lu?i
			@ldap_close($ldap);
1106 1e0b1727 Phil Davis
			return false;
1107 6306b5dd Ermal Lu?i
		}
1108 c61e4626 Ermal Lu?i
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1109 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
1110 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
1111 c61e4626 Ermal Lu?i
		return memberof;
1112 55eb9c44 --global
	}
1113
1114
	/* get groups from DN found */
1115
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
1116
	/* since we know the DN is in $_SESSION['ldapdn'] */
1117
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
1118 1e0b1727 Phil Davis
	if ($ldapscope == "one") {
1119
		$ldapfunc = "ldap_list";
1120
	} else {
1121
		$ldapfunc = "ldap_search";
1122
	}
1123 c61e4626 Ermal Lu?i
1124 1e0b1727 Phil Davis
	$search = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
1125
	$info = @ldap_get_entries($ldap, $search);
1126 55eb9c44 --global
1127 149efbea jim-p
	$gresults = isset($authcfg['ldap_rfc2307']) ? $info : $info[0][$ldapgroupattribute];
1128 1180e4f0 Sjon Hortensius
1129 4e322e2c Phil Davis
	if (is_array($gresults)) {
1130 55eb9c44 --global
		/* Iterate through the groups and throw them into an array */
1131 149efbea jim-p
		foreach ($gresults as $grp) {
1132 4e322e2c Phil Davis
			if (((isset($authcfg['ldap_rfc2307'])) && (stristr($grp["dn"], "CN=") !== false)) ||
1133
			    ((!isset($authcfg['ldap_rfc2307'])) && (stristr($grp, "CN=") !== false))) {
1134 149efbea jim-p
				$grpsplit = isset($authcfg['ldap_rfc2307']) ? explode(",", $grp["dn"]) : explode(",", $grp);
1135
				$memberof[] = preg_replace("/CN=/i", "", $grpsplit[0]);
1136 55eb9c44 --global
			}
1137
		}
1138
	}
1139 1180e4f0 Sjon Hortensius
1140 55eb9c44 --global
	/* Time to close LDAP connection */
1141 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1142 1180e4f0 Sjon Hortensius
1143 4de8f7ba Phil Davis
	$groups = print_r($memberof, true);
1144 1180e4f0 Sjon Hortensius
1145 55eb9c44 --global
	//log_error("Returning groups ".$groups." for user $username");
1146 1180e4f0 Sjon Hortensius
1147 55eb9c44 --global
	return $memberof;
1148
}
1149
1150 83e0d4c8 jim-p
function ldap_format_host($host) {
1151
	return is_ipaddrv6($host) ? "[$host]" : $host ;
1152
}
1153
1154 6306b5dd Ermal Lu?i
function ldap_backed($username, $passwd, $authcfg) {
1155 55eb9c44 --global
	global $debug, $config;
1156 1180e4f0 Sjon Hortensius
1157 1e0b1727 Phil Davis
	if (!$username) {
1158 55eb9c44 --global
		return;
1159 1e0b1727 Phil Davis
	}
1160 55eb9c44 --global
1161 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
1162 55eb9c44 --global
		return;
1163 1e0b1727 Phil Davis
	}
1164 55eb9c44 --global
1165 1e0b1727 Phil Davis
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1166 2ce660ad smos
		$username_split = explode("@", $username);
1167 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1168 55eb9c44 --global
	}
1169 1e0b1727 Phil Davis
	if (stristr($username, "\\")) {
1170 cfbfd941 smos
		$username_split = explode("\\", $username);
1171 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1172 55eb9c44 --global
	}
1173
1174 c61e4626 Ermal Lu?i
	if ($authcfg) {
1175 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
1176 c61e4626 Ermal Lu?i
			$ldapproto = "ldap";
1177 1e0b1727 Phil Davis
		} else {
1178 c61e4626 Ermal Lu?i
			$ldapproto = "ldaps";
1179 1e0b1727 Phil Davis
		}
1180
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1181
		$ldapport = $authcfg['ldap_port'];
1182
		if (!empty($ldapport)) {
1183 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
1184 1e0b1727 Phil Davis
		}
1185
		$ldapbasedn = $authcfg['ldap_basedn'];
1186
		$ldapbindun = $authcfg['ldap_binddn'];
1187
		$ldapbindpw = $authcfg['ldap_bindpw'];
1188
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1189 c61e4626 Ermal Lu?i
			$ldapanon = true;
1190 1e0b1727 Phil Davis
		} else {
1191 c61e4626 Ermal Lu?i
			$ldapanon = false;
1192 1e0b1727 Phil Davis
		}
1193
		$ldapauthcont = $authcfg['ldap_authcn'];
1194
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1195
		$ldapextendedqueryenabled = $authcfg['ldap_extended_enabled'];
1196
		$ldapextendedquery = $authcfg['ldap_extended_query'];
1197
		$ldapfilter = "";
1198
		if (!$ldapextendedqueryenabled) {
1199
			$ldapfilter = "({$ldapnameattribute}={$username})";
1200
		} else {
1201
			$ldapfilter = "(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
1202
		}
1203
		$ldaptype = "";
1204
		$ldapver = $authcfg['ldap_protver'];
1205
		$ldapname = $authcfg['name'];
1206
		$ldapscope = $authcfg['ldap_scope'];
1207 d6b4dfe3 jim-p
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 25;
1208 1e0b1727 Phil Davis
	} else {
1209 6306b5dd Ermal Lu?i
		return false;
1210 1e0b1727 Phil Davis
	}
1211 55eb9c44 --global
1212 1180e4f0 Sjon Hortensius
	/* first check if there is even an LDAP server populated */
1213 1e0b1727 Phil Davis
	if (!$ldapserver) {
1214 c61e4626 Ermal Lu?i
		if ($ldapfallback) {
1215 94021404 Carlos Eduardo Ramos
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager."));
1216 c61e4626 Ermal Lu?i
			return local_backed($username, $passwd);
1217 1e0b1727 Phil Davis
		} else {
1218 94021404 Carlos Eduardo Ramos
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined."));
1219 1e0b1727 Phil Davis
		}
1220 c61e4626 Ermal Lu?i
1221
		return false;
1222 55eb9c44 --global
	}
1223 1180e4f0 Sjon Hortensius
1224 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
1225
	ldap_setup_caenv($authcfg);
1226 fe2031ab Ermal
1227 906daddc Ermal
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1228 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1229 906daddc Ermal
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1230 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1231
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1232 906daddc Ermal
1233 55eb9c44 --global
	/* Make sure we can connect to LDAP */
1234 c61e4626 Ermal Lu?i
	$error = false;
1235 1e0b1727 Phil Davis
	if (!($ldap = ldap_connect($ldapserver))) {
1236 c61e4626 Ermal Lu?i
		$error = true;
1237 1e0b1727 Phil Davis
	}
1238 c61e4626 Ermal Lu?i
1239
	if ($error == true) {
1240 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1241 c61e4626 Ermal Lu?i
		return false;
1242 55eb9c44 --global
	}
1243 c61e4626 Ermal Lu?i
1244 55eb9c44 --global
	/* ok, its up.  now, lets bind as the bind user so we can search it */
1245 c61e4626 Ermal Lu?i
	$error = false;
1246 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1247
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1248 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
1249 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
1250
			$error = true;
1251
		}
1252
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1253 c61e4626 Ermal Lu?i
		$error = true;
1254 1e0b1727 Phil Davis
	}
1255 c61e4626 Ermal Lu?i
1256
	if ($error == true) {
1257 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
1258 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1259 c61e4626 Ermal Lu?i
		return false;
1260 55eb9c44 --global
	}
1261 1180e4f0 Sjon Hortensius
1262 55eb9c44 --global
	/* Get LDAP Authcontainers and split em up. */
1263 cfbfd941 smos
	$ldac_splits = explode(";", $ldapauthcont);
1264 1180e4f0 Sjon Hortensius
1265 086cf944 Phil Davis
	/* setup the usercount so we think we haven't found anyone yet */
1266 4de8f7ba Phil Davis
	$usercount = 0;
1267 55eb9c44 --global
1268
	/*****************************************************************/
1269 6990ad35 Phil Davis
	/*  We first find the user based on username and filter          */
1270
	/*  then, once we find the first occurrence of that person       */
1271
	/*  we set session variables to point to the OU and DN of the    */
1272
	/*  person.  To later be used by ldap_get_groups.                */
1273 55eb9c44 --global
	/*  that way we don't have to search twice.                      */
1274
	/*****************************************************************/
1275 1e0b1727 Phil Davis
	if ($debug) {
1276 3ac8324f Ermal
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1277 1e0b1727 Phil Davis
	}
1278 c61e4626 Ermal Lu?i
	/* Iterate through the user containers for search */
1279
	foreach ($ldac_splits as $i => $ldac_split) {
1280 a5cd1c5a jim-p
		$ldac_split = isset($authcfg['ldap_utf8']) ? utf8_encode($ldac_split) : $ldac_split;
1281
		$ldapfilter = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapfilter) : $ldapfilter;
1282
		$ldapsearchbasedn = isset($authcfg['ldap_utf8']) ? utf8_encode("{$ldac_split},{$ldapbasedn}") : "{$ldac_split},{$ldapbasedn}";
1283 c61e4626 Ermal Lu?i
		/* Make sure we just use the first user we find */
1284 1e0b1727 Phil Davis
		if ($debug) {
1285 a5cd1c5a jim-p
			log_auth(sprintf(gettext('Now Searching in server %1$s, container %2$s with filter %3$s.'), $ldapname, utf8_decode($ldac_split), utf8_decode($ldapfilter)));
1286 1e0b1727 Phil Davis
		}
1287
		if ($ldapscope == "one") {
1288 c61e4626 Ermal Lu?i
			$ldapfunc = "ldap_list";
1289 1e0b1727 Phil Davis
		} else {
1290 c61e4626 Ermal Lu?i
			$ldapfunc = "ldap_search";
1291 1e0b1727 Phil Davis
		}
1292 c61e4626 Ermal Lu?i
		/* Support legacy auth container specification. */
1293 1e0b1727 Phil Davis
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn)) {
1294 6990ad35 Phil Davis
			$search = @$ldapfunc($ldap, $ldac_split, $ldapfilter);
1295 1e0b1727 Phil Davis
		} else {
1296 6990ad35 Phil Davis
			$search = @$ldapfunc($ldap, $ldapsearchbasedn, $ldapfilter);
1297 1e0b1727 Phil Davis
		}
1298 c61e4626 Ermal Lu?i
		if (!$search) {
1299 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1300 c61e4626 Ermal Lu?i
			continue;
1301 55eb9c44 --global
		}
1302 4de8f7ba Phil Davis
		$info = ldap_get_entries($ldap, $search);
1303 c61e4626 Ermal Lu?i
		$matches = $info['count'];
1304 1e0b1727 Phil Davis
		if ($matches == 1) {
1305 c61e4626 Ermal Lu?i
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1306
			$_SESSION['ldapou'] = $ldac_split[$i];
1307
			$_SESSION['ldapon'] = "true";
1308
			$usercount = 1;
1309
			break;
1310 55eb9c44 --global
		}
1311
	}
1312
1313 1e0b1727 Phil Davis
	if ($usercount != 1) {
1314 6306b5dd Ermal Lu?i
		@ldap_unbind($ldap);
1315 94021404 Carlos Eduardo Ramos
		log_error(gettext("ERROR! Either LDAP search failed, or multiple users were found."));
1316 1180e4f0 Sjon Hortensius
		return false;
1317 55eb9c44 --global
	}
1318 c61e4626 Ermal Lu?i
1319 55eb9c44 --global
	/* Now lets bind as the user we found */
1320 a5cd1c5a jim-p
	$passwd = isset($authcfg['ldap_utf8']) ? utf8_encode($passwd) : $passwd;
1321 c61e4626 Ermal Lu?i
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
1322 3697adb2 jim-p
		log_error(sprintf(gettext('ERROR! Could not login to server %1$s as user %2$s: %3$s'), $ldapname, $username, ldap_error($ldap)));
1323 6306b5dd Ermal Lu?i
		@ldap_unbind($ldap);
1324 c61e4626 Ermal Lu?i
		return false;
1325 55eb9c44 --global
	}
1326
1327 a5cd1c5a jim-p
	if ($debug) {
1328
		$userdn = isset($authcfg['ldap_utf8']) ? utf8_decode($userdn) : $userdn;
1329 2004def5 Ermal
		log_auth(sprintf(gettext('Logged in successfully as %1$s via LDAP server %2$s with DN = %3$s.'), $username, $ldapname, $userdn));
1330 a5cd1c5a jim-p
	}
1331 c61e4626 Ermal Lu?i
1332
	/* At this point we are bound to LDAP so the user was auth'd okay. Close connection. */
1333 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1334 55eb9c44 --global
1335
	return true;
1336
}
1337
1338 1492e02c Ermal
function radius_backed($username, $passwd, $authcfg, &$attributes = array()) {
1339 a13ce628 Ermal Lu?i
	global $debug, $config;
1340 55eb9c44 --global
	$ret = false;
1341
1342 868c6826 Ermal
	require_once("radius.inc");
1343
1344 55eb9c44 --global
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1345 c61e4626 Ermal Lu?i
	if ($authcfg) {
1346
		$radiusservers = array();
1347
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1348
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1349
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1350 bddd2be8 jim-p
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1351 1e0b1727 Phil Davis
	} else {
1352 6306b5dd Ermal Lu?i
		return false;
1353 1e0b1727 Phil Davis
	}
1354 c61e4626 Ermal Lu?i
1355 1e0b1727 Phil Davis
	/* Add new servers to our instance */
1356 bddd2be8 jim-p
	foreach ($radiusservers as $radsrv) {
1357
		$timeout = (is_numeric($radsrv['timeout'])) ? $radsrv['timeout'] : 5;
1358
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret'], $timeout);
1359
	}
1360 55eb9c44 --global
1361 6e815096 Ermal
	if (PEAR::isError($rauth->start())) {
1362 55eb9c44 --global
		$retvalue['auth_val'] = 1;
1363
		$retvalue['error'] = $rauth->getError();
1364 1e0b1727 Phil Davis
		if ($debug) {
1365 8cd558b6 ayvis
			printf(gettext("Radius start: %s<br />\n"), $retvalue['error']);
1366 1e0b1727 Phil Davis
		}
1367 55eb9c44 --global
	}
1368
1369
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1370
1371
	/* Send request */
1372
	$result = $rauth->send();
1373
	if (PEAR::isError($result)) {
1374
		$retvalue['auth_val'] = 1;
1375
		$retvalue['error'] = $result->getMessage();
1376 1e0b1727 Phil Davis
		if ($debug) {
1377 8cd558b6 ayvis
			printf(gettext("Radius send failed: %s<br />\n"), $retvalue['error']);
1378 1e0b1727 Phil Davis
		}
1379 55eb9c44 --global
	} else if ($result === true) {
1380 1e0b1727 Phil Davis
		if ($rauth->getAttributes()) {
1381 1492e02c Ermal
			$attributes = $rauth->listAttributes();
1382 1e0b1727 Phil Davis
		}
1383 55eb9c44 --global
		$retvalue['auth_val'] = 2;
1384 1e0b1727 Phil Davis
		if ($debug) {
1385 8cd558b6 ayvis
			printf(gettext("Radius Auth succeeded")."<br />\n");
1386 1e0b1727 Phil Davis
		}
1387 55eb9c44 --global
		$ret = true;
1388
	} else {
1389
		$retvalue['auth_val'] = 3;
1390 1e0b1727 Phil Davis
		if ($debug) {
1391 8cd558b6 ayvis
			printf(gettext("Radius Auth rejected")."<br />\n");
1392 1e0b1727 Phil Davis
		}
1393 55eb9c44 --global
	}
1394
1395
	// close OO RADIUS_AUTHENTICATION
1396
	$rauth->close();
1397
1398
	return $ret;
1399
}
1400
1401 c4a9f99a jim-p
/*
1402
	$attributes must contain a "class" key containing the groups and local
1403
	groups must exist to match.
1404
*/
1405
function radius_get_groups($attributes) {
1406
	$groups = array();
1407
	if (!empty($attributes) && is_array($attributes) && !empty($attributes['class'])) {
1408
		$groups = explode(";", $attributes['class']);
1409
		foreach ($groups as & $grp) {
1410 916fc1f8 jim-p
			$grp = trim($grp);
1411
			if (strtolower(substr($grp, 0, 3)) == "ou=") {
1412 c4a9f99a jim-p
				$grp = substr($grp, 3);
1413
			}
1414
		}
1415
	}
1416
	return $groups;
1417
}
1418
1419 7dd044f2 sullrich
function get_user_expiration_date($username) {
1420 a13ce628 Ermal Lu?i
	$user = getUserEntry($username);
1421 1e0b1727 Phil Davis
	if ($user['expires']) {
1422 a13ce628 Ermal Lu?i
		return $user['expires'];
1423 1e0b1727 Phil Davis
	}
1424 a13ce628 Ermal Lu?i
}
1425
1426
function is_account_expired($username) {
1427
	$expirydate = get_user_expiration_date($username);
1428
	if ($expirydate) {
1429 4de8f7ba Phil Davis
		if (strtotime("-1 day") > strtotime(date("m/d/Y", strtotime($expirydate)))) {
1430 a13ce628 Ermal Lu?i
			return true;
1431 1e0b1727 Phil Davis
		}
1432 7dd044f2 sullrich
	}
1433 a13ce628 Ermal Lu?i
1434
	return false;
1435 7dd044f2 sullrich
}
1436
1437 b4bfd25d sullrich
function is_account_disabled($username) {
1438 a13ce628 Ermal Lu?i
	$user = getUserEntry($username);
1439 1e0b1727 Phil Davis
	if (isset($user['disabled'])) {
1440 a13ce628 Ermal Lu?i
		return true;
1441 1e0b1727 Phil Davis
	}
1442 a13ce628 Ermal Lu?i
1443 b4bfd25d sullrich
	return false;
1444
}
1445
1446 c61e4626 Ermal Lu?i
function auth_get_authserver($name) {
1447 1e0b1727 Phil Davis
	global $config;
1448
1449
	if (is_array($config['system']['authserver'])) {
1450
		foreach ($config['system']['authserver'] as $authcfg) {
1451
			if ($authcfg['name'] == $name) {
1452
				return $authcfg;
1453
			}
1454
		}
1455
	}
1456
	if ($name == "Local Database") {
1457 96568521 Vinicius Coque
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1458 1e0b1727 Phil Davis
	}
1459 6306b5dd Ermal Lu?i
}
1460
1461
function auth_get_authserver_list() {
1462 1e0b1727 Phil Davis
	global $config;
1463 6306b5dd Ermal Lu?i
1464
	$list = array();
1465
1466 1e0b1727 Phil Davis
	if (is_array($config['system']['authserver'])) {
1467
		foreach ($config['system']['authserver'] as $authcfg) {
1468 6306b5dd Ermal Lu?i
			/* Add support for disabled entries? */
1469
			$list[$authcfg['name']] = $authcfg;
1470 1e0b1727 Phil Davis
		}
1471
	}
1472 6306b5dd Ermal Lu?i
1473 4de8f7ba Phil Davis
	$list["Local Database"] = array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1474 6306b5dd Ermal Lu?i
	return $list;
1475 c61e4626 Ermal Lu?i
}
1476
1477 c4a9f99a jim-p
function getUserGroups($username, $authcfg, &$attributes = array()) {
1478 fb0f22c0 Ermal Lu?i
	global $config;
1479
1480
	$allowed_groups = array();
1481
1482 1e0b1727 Phil Davis
	switch ($authcfg['type']) {
1483
		case 'ldap':
1484
			$allowed_groups = @ldap_get_groups($username, $authcfg);
1485
			break;
1486
		case 'radius':
1487 c4a9f99a jim-p
			$allowed_groups = @radius_get_groups($attributes);
1488 1e0b1727 Phil Davis
			break;
1489
		default:
1490
			$user = getUserEntry($username);
1491
			$allowed_groups = @local_user_get_groups($user, true);
1492
			break;
1493 fb0f22c0 Ermal Lu?i
	}
1494
1495
	$member_groups = array();
1496 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
1497
		foreach ($config['system']['group'] as $group) {
1498
			if (in_array($group['name'], $allowed_groups)) {
1499 fb0f22c0 Ermal Lu?i
				$member_groups[] = $group['name'];
1500 1e0b1727 Phil Davis
			}
1501
		}
1502 fb0f22c0 Ermal Lu?i
	}
1503
1504
	return $member_groups;
1505
}
1506
1507 1492e02c Ermal
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1508 c61e4626 Ermal Lu?i
1509
	if (!$authcfg) {
1510
		return local_backed($username, $password);
1511
	}
1512
1513
	$authenticated = false;
1514 1e0b1727 Phil Davis
	switch ($authcfg['type']) {
1515
		case 'ldap':
1516
			if (ldap_backed($username, $password, $authcfg)) {
1517
				$authenticated = true;
1518
			}
1519
			break;
1520
		case 'radius':
1521
			if (radius_backed($username, $password, $authcfg, $attributes)) {
1522
				$authenticated = true;
1523
			}
1524
			break;
1525
		default:
1526
			/* lookup user object by name */
1527
			if (local_backed($username, $password)) {
1528
				$authenticated = true;
1529
			}
1530
			break;
1531
		}
1532 c61e4626 Ermal Lu?i
1533
	return $authenticated;
1534
}
1535
1536 6306b5dd Ermal Lu?i
function session_auth() {
1537 aa205c3b Ermal
	global $config, $_SESSION, $page;
1538 55eb9c44 --global
1539 49ddf9a1 Warren Baker
	// Handle HTTPS httponly and secure flags
1540 16789caa Renato Botelho
	$currentCookieParams = session_get_cookie_params();
1541
	session_set_cookie_params(
1542
		$currentCookieParams["lifetime"],
1543
		$currentCookieParams["path"],
1544
		NULL,
1545
		($config['system']['webgui']['protocol'] == "https"),
1546
		true
1547
	);
1548 49ddf9a1 Warren Baker
1549 1e0b1727 Phil Davis
	if (!session_id()) {
1550 9252d093 Ermal
		session_start();
1551 1e0b1727 Phil Davis
	}
1552 55eb9c44 --global
1553 dd030de9 Renato Botelho
	// Detect protocol change
1554 1e0b1727 Phil Davis
	if (!isset($_POST['login']) && !empty($_SESSION['Logged_In']) && $_SESSION['protocol'] != $config['system']['webgui']['protocol']) {
1555 dd030de9 Renato Botelho
		return false;
1556 1e0b1727 Phil Davis
	}
1557 dd030de9 Renato Botelho
1558 55eb9c44 --global
	/* Validate incoming login request */
1559 c4a9f99a jim-p
	$attributes = array();
1560 88165371 Ermal
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1561 6306b5dd Ermal Lu?i
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1562 c4a9f99a jim-p
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg, $attributes) ||
1563 6306b5dd Ermal Lu?i
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1564 526f5b11 Renato Botelho
			// Generate a new id to avoid session fixation
1565 8588095f Renato Botelho
			session_regenerate_id();
1566 6306b5dd Ermal Lu?i
			$_SESSION['Logged_In'] = "True";
1567
			$_SESSION['Username'] = $_POST['usernamefld'];
1568 c4a9f99a jim-p
			$_SESSION['user_radius_attributes'] = $attributes;
1569 6306b5dd Ermal Lu?i
			$_SESSION['last_access'] = time();
1570 dd030de9 Renato Botelho
			$_SESSION['protocol'] = $config['system']['webgui']['protocol'];
1571 1e0b1727 Phil Davis
			if (!isset($config['system']['webgui']['quietlogin'])) {
1572 54bdff75 Vinicius Coque
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1573 4fc3855f smos
			}
1574 1e0b1727 Phil Davis
			if (isset($_POST['postafterlogin'])) {
1575 92140621 Ermal
				return true;
1576 1e0b1727 Phil Davis
			} else {
1577
				if (empty($page)) {
1578 80b292f3 Ermal
					$page = "/";
1579 1e0b1727 Phil Davis
				}
1580 80b292f3 Ermal
				header("Location: {$page}");
1581
			}
1582 f23e6363 Ermal
			exit;
1583 a13ce628 Ermal Lu?i
		} else {
1584
			/* give the user an error message */
1585
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1586 65f7fba8 Scott Ullrich
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1587 1e0b1727 Phil Davis
			if (isAjax()) {
1588 a13ce628 Ermal Lu?i
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1589
				return;
1590 55eb9c44 --global
			}
1591
		}
1592
	}
1593
1594
	/* Show login page if they aren't logged in */
1595 1e0b1727 Phil Davis
	if (empty($_SESSION['Logged_In'])) {
1596 55eb9c44 --global
		return false;
1597 1e0b1727 Phil Davis
	}
1598 55eb9c44 --global
1599
	/* If session timeout isn't set, we don't mark sessions stale */
1600 02647583 Ermal
	if (!isset($config['system']['webgui']['session_timeout'])) {
1601 bdadaf3c Chris Buechler
		/* Default to 4 hour timeout if one is not set */
1602
		if ($_SESSION['last_access'] < (time() - 14400)) {
1603
			$_GET['logout'] = true;
1604
			$_SESSION['Logout'] = true;
1605 1e0b1727 Phil Davis
		} else {
1606 1180e4f0 Sjon Hortensius
			$_SESSION['last_access'] = time();
1607 1e0b1727 Phil Davis
		}
1608 02647583 Ermal
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1609
		/* only update if it wasn't ajax */
1610 1e0b1727 Phil Davis
		if (!isAjax()) {
1611 02647583 Ermal
			$_SESSION['last_access'] = time();
1612 1e0b1727 Phil Davis
		}
1613 bdadaf3c Chris Buechler
	} else {
1614 55eb9c44 --global
		/* Check for stale session */
1615
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1616
			$_GET['logout'] = true;
1617
			$_SESSION['Logout'] = true;
1618
		} else {
1619
			/* only update if it wasn't ajax */
1620 1e0b1727 Phil Davis
			if (!isAjax()) {
1621 55eb9c44 --global
				$_SESSION['last_access'] = time();
1622 1e0b1727 Phil Davis
			}
1623 55eb9c44 --global
		}
1624
	}
1625
1626
	/* user hit the logout button */
1627
	if (isset($_GET['logout'])) {
1628
1629 1e0b1727 Phil Davis
		if ($_SESSION['Logout']) {
1630 addc0439 Renato Botelho
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1631 1e0b1727 Phil Davis
		} else {
1632 addc0439 Renato Botelho
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1633 1e0b1727 Phil Davis
		}
1634 55eb9c44 --global
1635
		/* wipe out $_SESSION */
1636
		$_SESSION = array();
1637
1638 1e0b1727 Phil Davis
		if (isset($_COOKIE[session_name()])) {
1639 55eb9c44 --global
			setcookie(session_name(), '', time()-42000, '/');
1640 1e0b1727 Phil Davis
		}
1641 55eb9c44 --global
1642
		/* and destroy it */
1643
		session_destroy();
1644
1645 cfbfd941 smos
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1646 55eb9c44 --global
		$scriptElms = count($scriptName);
1647
		$scriptName = $scriptName[$scriptElms-1];
1648
1649 1e0b1727 Phil Davis
		if (isAjax()) {
1650 55eb9c44 --global
			return false;
1651 1e0b1727 Phil Davis
		}
1652 55eb9c44 --global
1653
		/* redirect to page the user is on, it'll prompt them to login again */
1654 6f3d2063 Renato Botelho
		header("Location: {$scriptName}");
1655 55eb9c44 --global
1656
		return false;
1657
	}
1658
1659
	/*
1660
	 * this is for debugging purpose if you do not want to use Ajax
1661 1e0b1727 Phil Davis
	 * to submit a HTML form. It basically disables the observation
1662 55eb9c44 --global
	 * of the submit event and hence does not trigger Ajax.
1663
	 */
1664 1e0b1727 Phil Davis
	if ($_GET['disable_ajax']) {
1665 55eb9c44 --global
		$_SESSION['NO_AJAX'] = "True";
1666 1e0b1727 Phil Davis
	}
1667 55eb9c44 --global
1668
	/*
1669
	 * Same to re-enable Ajax.
1670
	 */
1671 1e0b1727 Phil Davis
	if ($_GET['enable_ajax']) {
1672 55eb9c44 --global
		unset($_SESSION['NO_AJAX']);
1673 1e0b1727 Phil Davis
	}
1674 55eb9c44 --global
1675
	return true;
1676
}
1677
1678 88165371 Ermal
?>