Project

General

Profile

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