Project

General

Profile

Download (48.2 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 b4738ddc NewEraCracker
	<link rel="stylesheet" href="/css/pfSense.css" />
147 1180e4f0 Sjon Hortensius
	<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 530e4707 NOYB
				display_error_form("501", "An HTTP_REFERER was detected other than what is defined in System -> Advanced (" . htmlspecialchars($_SERVER['HTTP_REFERER']) . ").  If not needed, this check can be disabled 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 0ef6fddc jim-p
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
275
276 1e0b1727 Phil Davis
	if (isset($userindex[$name])) {
277 55eb9c44 --global
		return $config['system']['user'][$userindex[$name]];
278 0ef6fddc jim-p
	} elseif ($authcfg['type'] != "Local Database") {
279
		$user = array();
280
		$user['name'] = $name;
281
		return $user;
282 1e0b1727 Phil Davis
	}
283 55eb9c44 --global
}
284
285
function & getUserEntryByUID($uid) {
286
	global $debug, $config;
287 84924e76 Ermal
288 1e0b1727 Phil Davis
	if (is_array($config['system']['user'])) {
289
		foreach ($config['system']['user'] as & $user) {
290
			if ($user['uid'] == $uid) {
291 84924e76 Ermal
				return $user;
292 1e0b1727 Phil Davis
			}
293
		}
294
	}
295 55eb9c44 --global
296
	return false;
297
}
298
299
function & getGroupEntry($name) {
300
	global $debug, $config, $groupindex;
301 1e0b1727 Phil Davis
	if (isset($groupindex[$name])) {
302 55eb9c44 --global
		return $config['system']['group'][$groupindex[$name]];
303 1e0b1727 Phil Davis
	}
304 55eb9c44 --global
}
305
306
function & getGroupEntryByGID($gid) {
307
	global $debug, $config;
308 84924e76 Ermal
309 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
310
		foreach ($config['system']['group'] as & $group) {
311
			if ($group['gid'] == $gid) {
312 84924e76 Ermal
				return $group;
313 1e0b1727 Phil Davis
			}
314
		}
315
	}
316 55eb9c44 --global
317
	return false;
318
}
319
320 6dc88d53 Ermal Luci
function get_user_privileges(& $user) {
321 0ef6fddc jim-p
	global $config;
322
323
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
324
	$names = array();
325 6dc88d53 Ermal Luci
326 1e0b1727 Phil Davis
	$privs = $user['priv'];
327
	if (!is_array($privs)) {
328
		$privs = array();
329
	}
330 6dc88d53 Ermal Luci
331 0ef6fddc jim-p
	if ($authcfg['type'] == "ldap") {
332
		$names = @ldap_get_groups($user['name'], $authcfg);
333
	} elseif ($authcfg['type'] == "radius") {
334
		$names = @radius_get_groups($_SESSION['user_radius_attributes']);
335
	}
336
337
	if (empty($names)) {
338
		$names = local_user_get_groups($user, true);
339
	}
340 6dc88d53 Ermal Luci
341 1e0b1727 Phil Davis
	foreach ($names as $name) {
342
		$group = getGroupEntry($name);
343
		if (is_array($group['priv'])) {
344 4de8f7ba Phil Davis
			$privs = array_merge($privs, $group['priv']);
345 1e0b1727 Phil Davis
		}
346
	}
347 6dc88d53 Ermal Luci
348 1e0b1727 Phil Davis
	return $privs;
349 6dc88d53 Ermal Luci
}
350
351
function userHasPrivilege($userent, $privid = false) {
352
353 1e0b1727 Phil Davis
	if (!$privid || !is_array($userent)) {
354
		return false;
355
	}
356 6dc88d53 Ermal Luci
357 1e0b1727 Phil Davis
	$privs = get_user_privileges($userent);
358 6dc88d53 Ermal Luci
359 1e0b1727 Phil Davis
	if (!is_array($privs)) {
360
		return false;
361
	}
362 6dc88d53 Ermal Luci
363 1e0b1727 Phil Davis
	if (!in_array($privid, $privs)) {
364
		return false;
365
	}
366 6dc88d53 Ermal Luci
367 1e0b1727 Phil Davis
	return true;
368 6dc88d53 Ermal Luci
}
369
370 55eb9c44 --global
function local_backed($username, $passwd) {
371
372
	$user = getUserEntry($username);
373 1e0b1727 Phil Davis
	if (!$user) {
374 55eb9c44 --global
		return false;
375 1e0b1727 Phil Davis
	}
376 55eb9c44 --global
377 1e0b1727 Phil Davis
	if (is_account_disabled($username) || is_account_expired($username)) {
378 a13ce628 Ermal Lu?i
		return false;
379 1e0b1727 Phil Davis
	}
380 a13ce628 Ermal Lu?i
381 9219378b daniel
	if ($user['bcrypt-hash']) {
382
		if (password_verify($passwd, $user['bcrypt-hash'])) {
383
			return true;
384
		}
385
	}
386
387
	//for backwards compatibility
388 1e0b1727 Phil Davis
	if ($user['password']) {
389
		if (crypt($passwd, $user['password']) == $user['password']) {
390 55eb9c44 --global
			return true;
391 1e0b1727 Phil Davis
		}
392 55eb9c44 --global
	}
393
394 1e0b1727 Phil Davis
	if ($user['md5-hash']) {
395
		if (md5($passwd) == $user['md5-hash']) {
396 55eb9c44 --global
			return true;
397 1e0b1727 Phil Davis
		}
398 55eb9c44 --global
	}
399
400
	return false;
401
}
402
403
function local_sync_accounts() {
404
	global $debug, $config;
405
	conf_mount_rw();
406
407
	/* remove local users to avoid uid conflicts */
408
	$fd = popen("/usr/sbin/pw usershow -a", "r");
409
	if ($fd) {
410
		while (!feof($fd)) {
411 4de8f7ba Phil Davis
			$line = explode(":", fgets($fd));
412 3ee1e659 Renato Botelho
			if ($line[0] != "admin") {
413
				if (!strncmp($line[0], "_", 1)) {
414
					continue;
415
				}
416
				if ($line[2] < 2000) {
417
					continue;
418
				}
419
				if ($line[2] > 65000) {
420
					continue;
421
				}
422 1e0b1727 Phil Davis
			}
423 2b41df9c Renato Botelho
			/*
424
			 * If a crontab was created to user, pw userdel will be interactive and
425
			 * can cause issues. Just remove crontab before run it when necessary
426
			 */
427
			unlink_if_exists("/var/cron/tabs/{$line[0]}");
428 0a39f78f jim-p
			$cmd = "/usr/sbin/pw userdel -n " . escapeshellarg($line[0]);
429 1e0b1727 Phil Davis
			if ($debug) {
430 94021404 Carlos Eduardo Ramos
				log_error(sprintf(gettext("Running: %s"), $cmd));
431 1e0b1727 Phil Davis
			}
432 55eb9c44 --global
			mwexec($cmd);
433
		}
434
		pclose($fd);
435
	}
436
437
	/* remove local groups to avoid gid conflicts */
438
	$gids = array();
439
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
440
	if ($fd) {
441
		while (!feof($fd)) {
442 4de8f7ba Phil Davis
			$line = explode(":", fgets($fd));
443 1e0b1727 Phil Davis
			if (!strncmp($line[0], "_", 1)) {
444 55eb9c44 --global
				continue;
445 1e0b1727 Phil Davis
			}
446
			if ($line[2] < 2000) {
447 55eb9c44 --global
				continue;
448 1e0b1727 Phil Davis
			}
449
			if ($line[2] > 65000) {
450 55eb9c44 --global
				continue;
451 1e0b1727 Phil Davis
			}
452 0a39f78f jim-p
			$cmd = "/usr/sbin/pw groupdel -g " . escapeshellarg($line[2]);
453 1e0b1727 Phil Davis
			if ($debug) {
454 94021404 Carlos Eduardo Ramos
				log_error(sprintf(gettext("Running: %s"), $cmd));
455 1e0b1727 Phil Davis
			}
456 55eb9c44 --global
			mwexec($cmd);
457
		}
458
		pclose($fd);
459
	}
460
461
	/* make sure the all group exists */
462
	$allgrp = getGroupEntryByGID(1998);
463
	local_group_set($allgrp, true);
464
465 5af2baf7 jim-p
	/* sync all local users */
466 1e0b1727 Phil Davis
	if (is_array($config['system']['user'])) {
467
		foreach ($config['system']['user'] as $user) {
468 5af2baf7 jim-p
			local_user_set($user);
469 1e0b1727 Phil Davis
		}
470
	}
471 5af2baf7 jim-p
472 f3e0a111 jim-p
	/* sync all local groups */
473 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
474
		foreach ($config['system']['group'] as $group) {
475 f3e0a111 jim-p
			local_group_set($group);
476 1e0b1727 Phil Davis
		}
477
	}
478 f3e0a111 jim-p
479 55eb9c44 --global
	conf_mount_ro();
480
481
}
482
483
function local_user_set(& $user) {
484
	global $g, $debug;
485
486 9219378b daniel
	if (empty($user['password']) && empty($user['bcrypt-hash'])) {
487 530e4707 NOYB
		log_error("There is something wrong in the config because user {$user['name']} password is missing!");
488 b3c106a0 Ermal
		return;
489
	}
490
491 2bb07efc Scott Ullrich
	conf_mount_rw();
492
493 1180e4f0 Sjon Hortensius
	$home_base = "/home/";
494 55eb9c44 --global
	$user_uid = $user['uid'];
495
	$user_name = $user['name'];
496 461df7c0 jim-p
	$user_home = "{$home_base}{$user_name}";
497 55eb9c44 --global
	$user_shell = "/etc/rc.initial";
498
	$user_group = "nobody";
499
500
	// Ensure $home_base exists and is writable
501 1e0b1727 Phil Davis
	if (!is_dir($home_base)) {
502 55eb9c44 --global
		mkdir($home_base, 0755);
503 1e0b1727 Phil Davis
	}
504 55eb9c44 --global
505 df8d74de jim-p
	$lock_account = false;
506 55eb9c44 --global
	/* configure shell type */
507 3e251b12 Erik Fonnesbeck
	/* Cases here should be ordered by most privileged to least privileged. */
508 a137fedd jim-p
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
509 29293dce jim-p
		$user_shell = "/bin/tcsh";
510 1ed86bc6 jim-p
	} elseif (userHasPrivilege($user, "user-copy-files")) {
511 a137fedd jim-p
		$user_shell = "/usr/local/bin/scponly";
512 3e251b12 Erik Fonnesbeck
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
513
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
514 fbfd675a jim-p
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
515
		$user_shell = "/sbin/nologin";
516 1ed86bc6 jim-p
	} else {
517
		$user_shell = "/sbin/nologin";
518 df8d74de jim-p
		$lock_account = true;
519
	}
520
521
	/* Lock out disabled or expired users, unless it's root/admin. */
522
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
523
		$user_shell = "/sbin/nologin";
524
		$lock_account = true;
525 55eb9c44 --global
	}
526
527
	/* root user special handling */
528
	if ($user_uid == 0) {
529
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
530 1e0b1727 Phil Davis
		if ($debug) {
531 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("Running: %s"), $cmd));
532 1e0b1727 Phil Davis
		}
533 55eb9c44 --global
		$fd = popen($cmd, "w");
534 9219378b daniel
		if (empty($user['bcrypt-hash'])) {
535
			fwrite($fd, $user['password']);
536 9a7911eb Daniel Vinakovsky
		} else {
537 9219378b daniel
			fwrite($fd, $user['bcrypt-hash']);
538
		}
539 55eb9c44 --global
		pclose($fd);
540
		$user_group = "wheel";
541 2708e399 jim-p
		$user_home = "/root";
542 29293dce jim-p
		$user_shell = "/etc/rc.initial";
543 55eb9c44 --global
	}
544
545
	/* read from pw db */
546 9fd14591 jim-p
	$fd = popen("/usr/sbin/pw usershow -n {$user_name} 2>&1", "r");
547 55eb9c44 --global
	$pwread = fgets($fd);
548
	pclose($fd);
549 9fd14591 jim-p
	$userattrs = explode(":", trim($pwread));
550 55eb9c44 --global
551 13a70e7d Renato Botelho
	$skel_dir = '/etc/skel';
552
553 55eb9c44 --global
	/* determine add or mod */
554 9fd14591 jim-p
	if (($userattrs[0] != $user['name']) || (!strncmp($pwread, "pw:", 3))) {
555 4bf17edc jim-p
		$user_op = "useradd -m -k " . escapeshellarg($skel_dir) . " -o";
556 38564fde smos
	} else {
557 55eb9c44 --global
		$user_op = "usermod";
558 38564fde smos
	}
559 55eb9c44 --global
560 1180e4f0 Sjon Hortensius
	$comment = str_replace(array(":", "!", "@"), " ", $user['descr']);
561 55eb9c44 --global
	/* add or mod pw db */
562 0a39f78f jim-p
	$cmd = "/usr/sbin/pw {$user_op} -q " .
563
			" -u " . escapeshellarg($user_uid) .
564
			" -n " . escapeshellarg($user_name) .
565
			" -g " . escapeshellarg($user_group) .
566
			" -s " . escapeshellarg($user_shell) .
567
			" -d " . escapeshellarg($user_home) .
568
			" -c " . escapeshellarg($comment) .
569
			" -H 0 2>&1";
570 55eb9c44 --global
571 1e0b1727 Phil Davis
	if ($debug) {
572 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
573 1e0b1727 Phil Davis
	}
574 55eb9c44 --global
	$fd = popen($cmd, "w");
575 9219378b daniel
	if (empty($user['bcrypt-hash'])) {
576
		fwrite($fd, $user['password']);
577 9a7911eb Daniel Vinakovsky
	} else {
578 9219378b daniel
		fwrite($fd, $user['bcrypt-hash']);
579
	}
580 55eb9c44 --global
	pclose($fd);
581
582
	/* create user directory if required */
583
	if (!is_dir($user_home)) {
584
		mkdir($user_home, 0700);
585
	}
586 23c652cd Ermal
	@chown($user_home, $user_name);
587
	@chgrp($user_home, $user_group);
588 55eb9c44 --global
589 13a70e7d Renato Botelho
	/* Make sure all users have last version of config files */
590
	foreach (glob("{$skel_dir}/dot.*") as $dot_file) {
591
		$target = $user_home . '/' . substr(basename($dot_file), 3);
592
		@copy($dot_file, $target);
593
		@chown($target, $user_name);
594
		@chgrp($target, $user_group);
595
	}
596
597 55eb9c44 --global
	/* write out ssh authorized key file */
598 1e0b1727 Phil Davis
	if ($user['authorizedkeys']) {
599 a2286360 Ermal Lu?i
		if (!is_dir("{$user_home}/.ssh")) {
600 23c652cd Ermal
			@mkdir("{$user_home}/.ssh", 0700);
601
			@chown("{$user_home}/.ssh", $user_name);
602 a2286360 Ermal Lu?i
		}
603
		$keys = base64_decode($user['authorizedkeys']);
604 23c652cd Ermal
		@file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
605
		@chown("{$user_home}/.ssh/authorized_keys", $user_name);
606 1e0b1727 Phil Davis
	} else {
607 cdab65cc Erik Fonnesbeck
		unlink_if_exists("{$user_home}/.ssh/authorized_keys");
608 1e0b1727 Phil Davis
	}
609 df8d74de jim-p
610
	$un = $lock_account ? "" : "un";
611 0a39f78f jim-p
	exec("/usr/sbin/pw {$un}lock " . escapeshellarg($user_name) . " -q 2>/dev/null");
612 1180e4f0 Sjon Hortensius
613 2bb07efc Scott Ullrich
	conf_mount_ro();
614 55eb9c44 --global
}
615
616
function local_user_del($user) {
617
	global $debug;
618 2bb07efc Scott Ullrich
619 55eb9c44 --global
	/* remove all memberships */
620 019e6c3f jim-p
	local_user_set_groups($user);
621 55eb9c44 --global
622 a39675ec jim-p
	/* Don't remove /root */
623 1e0b1727 Phil Davis
	if ($user['uid'] != 0) {
624 a39675ec jim-p
		$rmhome = "-r";
625 1e0b1727 Phil Davis
	}
626 a39675ec jim-p
627 9fd14591 jim-p
	/* read from pw db */
628
	$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
629
	$pwread = fgets($fd);
630
	pclose($fd);
631
	$userattrs = explode(":", trim($pwread));
632
633
	if ($userattrs[0] != $user['name']) {
634
		log_error("Tried to remove user {$user['name']} but got user {$userattrs[0]} instead. Bailing.");
635
		return;
636
	}
637
638 55eb9c44 --global
	/* delete from pw db */
639 0a39f78f jim-p
	$cmd = "/usr/sbin/pw userdel -n " . escapeshellarg($user['name']) . " " . escapeshellarg($rmhome);
640 55eb9c44 --global
641 1e0b1727 Phil Davis
	if ($debug) {
642 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
643 1e0b1727 Phil Davis
	}
644 0914b6bb Ermal
	mwexec($cmd);
645 2bb07efc Scott Ullrich
646 0914b6bb Ermal
	/* Delete user from groups needs a call to write_config() */
647
	local_group_del_user($user);
648 55eb9c44 --global
}
649
650 4d9801c2 Jim Thompson
function local_user_set_password(&$user, $password) {
651 55eb9c44 --global
652 33386b07 Daniel Vinakovsky
	unset($user['password']);
653
	unset($user['md5-hash']);
654
	$user['bcrypt-hash'] = password_hash($password, PASSWORD_BCRYPT);
655 55eb9c44 --global
656 4d4e9a11 Daniel Vinakovsky
	/* Maintain compatibility with FreeBSD - change $2y$ prefix to $2b$
657
	 * https://reviews.freebsd.org/D2742
658 6fadbf9b Dan Vinakovsky
	 * XXX: Can be removed as soon as r284483 is MFC'd.
659 4d4e9a11 Daniel Vinakovsky
	 */
660 4b737f6e Daniel Vinakovsky
	if ($user['bcrypt-hash'][2] == "y") {
661
		$user['bcrypt-hash'][2] = "b";
662
	}
663
664 55eb9c44 --global
	// Converts ascii to unicode.
665
	$astr = (string) $password;
666
	$ustr = '';
667
	for ($i = 0; $i < strlen($astr); $i++) {
668
		$a = ord($astr{$i}) << 8;
669 4de8f7ba Phil Davis
		$ustr .= sprintf("%X", $a);
670 55eb9c44 --global
	}
671
672
}
673
674
function local_user_get_groups($user, $all = false) {
675
	global $debug, $config;
676
677
	$groups = array();
678 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
679 55eb9c44 --global
		return $groups;
680 1e0b1727 Phil Davis
	}
681 55eb9c44 --global
682 1e0b1727 Phil Davis
	foreach ($config['system']['group'] as $group) {
683 4de8f7ba Phil Davis
		if ($all || (!$all && ($group['name'] != "all"))) {
684 1e0b1727 Phil Davis
			if (is_array($group['member'])) {
685
				if (in_array($user['uid'], $group['member'])) {
686 55eb9c44 --global
					$groups[] = $group['name'];
687 1e0b1727 Phil Davis
				}
688
			}
689
		}
690
	}
691 55eb9c44 --global
692 1e0b1727 Phil Davis
	if ($all) {
693 b0c231e4 jim-p
		$groups[] = "all";
694 1e0b1727 Phil Davis
	}
695 b0c231e4 jim-p
696 55eb9c44 --global
	sort($groups);
697
698
	return $groups;
699 1180e4f0 Sjon Hortensius
700 55eb9c44 --global
}
701
702 4de8f7ba Phil Davis
function local_user_set_groups($user, $new_groups = NULL) {
703 55eb9c44 --global
	global $debug, $config, $groupindex;
704 4de8f7ba Phil Davis
705 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
706 55eb9c44 --global
		return;
707 1e0b1727 Phil Davis
	}
708 55eb9c44 --global
709 739c78ac jim-p
	$cur_groups = local_user_get_groups($user, true);
710 55eb9c44 --global
	$mod_groups = array();
711
712 1e0b1727 Phil Davis
	if (!is_array($new_groups)) {
713 55eb9c44 --global
		$new_groups = array();
714 1e0b1727 Phil Davis
	}
715 55eb9c44 --global
716 1e0b1727 Phil Davis
	if (!is_array($cur_groups)) {
717 55eb9c44 --global
		$cur_groups = array();
718 1e0b1727 Phil Davis
	}
719 55eb9c44 --global
720
	/* determine which memberships to add */
721
	foreach ($new_groups as $groupname) {
722 4de8f7ba Phil Davis
		if ($groupname == '' || in_array($groupname, $cur_groups)) {
723 55eb9c44 --global
			continue;
724 1e0b1727 Phil Davis
		}
725 55eb9c44 --global
		$group = & $config['system']['group'][$groupindex[$groupname]];
726
		$group['member'][] = $user['uid'];
727
		$mod_groups[] = $group;
728
	}
729 9ae11a62 Scott Ullrich
	unset($group);
730 55eb9c44 --global
731
	/* determine which memberships to remove */
732
	foreach ($cur_groups as $groupname) {
733 4de8f7ba Phil Davis
		if (in_array($groupname, $new_groups)) {
734 e879fc81 Ermal
			continue;
735 1e0b1727 Phil Davis
		}
736
		if (!isset($config['system']['group'][$groupindex[$groupname]])) {
737 25fec9b3 jim-p
			continue;
738 1e0b1727 Phil Davis
		}
739 55eb9c44 --global
		$group = & $config['system']['group'][$groupindex[$groupname]];
740 7b5c56ea jim-p
		if (is_array($group['member'])) {
741
			$index = array_search($user['uid'], $group['member']);
742
			array_splice($group['member'], $index, 1);
743
			$mod_groups[] = $group;
744
		}
745 55eb9c44 --global
	}
746 9ae11a62 Scott Ullrich
	unset($group);
747 55eb9c44 --global
748
	/* sync all modified groups */
749 1e0b1727 Phil Davis
	foreach ($mod_groups as $group) {
750 55eb9c44 --global
		local_group_set($group);
751 1e0b1727 Phil Davis
	}
752 55eb9c44 --global
}
753
754 0914b6bb Ermal
function local_group_del_user($user) {
755
	global $config;
756
757 1e0b1727 Phil Davis
	if (!is_array($config['system']['group'])) {
758
		return;
759
	}
760 0914b6bb Ermal
761 1e0b1727 Phil Davis
	foreach ($config['system']['group'] as $group) {
762 0914b6bb Ermal
		if (is_array($group['member'])) {
763
			foreach ($group['member'] as $idx => $uid) {
764 1e0b1727 Phil Davis
				if ($user['uid'] == $uid) {
765 0914b6bb Ermal
					unset($config['system']['group']['member'][$idx]);
766 1e0b1727 Phil Davis
				}
767 0914b6bb Ermal
			}
768
		}
769
	}
770
}
771
772 55eb9c44 --global
function local_group_set($group, $reset = false) {
773
	global $debug;
774
775
	$group_name = $group['name'];
776
	$group_gid = $group['gid'];
777 baca968c Ermal
	$group_members = '';
778 1e0b1727 Phil Davis
	if (!$reset && !empty($group['member']) && count($group['member']) > 0) {
779 4de8f7ba Phil Davis
		$group_members = implode(",", $group['member']);
780 1e0b1727 Phil Davis
	}
781 55eb9c44 --global
782 792adb45 Chris Buechler
	if (empty($group_name) || $group['scope'] == "remote") {
783 baca968c Ermal
		return;
784 1e0b1727 Phil Davis
	}
785 baca968c Ermal
786 55eb9c44 --global
	/* determine add or mod */
787 0a39f78f jim-p
	if (mwexec("/usr/sbin/pw groupshow -g " . escapeshellarg($group_gid) . " 2>&1", true) == 0) {
788 7cb01159 Chris Buechler
		$group_op = "groupmod -l";
789 1e0b1727 Phil Davis
	} else {
790 7cb01159 Chris Buechler
		$group_op = "groupadd -n";
791 1e0b1727 Phil Davis
	}
792 55eb9c44 --global
793
	/* add or mod group db */
794 0a39f78f jim-p
	$cmd = "/usr/sbin/pw {$group_op} " .
795
		escapeshellarg($group_name) .
796
		" -g " . escapeshellarg($group_gid) .
797
		" -M " . escapeshellarg($group_members) . " 2>&1";
798 55eb9c44 --global
799 1e0b1727 Phil Davis
	if ($debug) {
800 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
801 1e0b1727 Phil Davis
	}
802 0914b6bb Ermal
	mwexec($cmd);
803 55eb9c44 --global
804
}
805
806
function local_group_del($group) {
807
	global $debug;
808
809
	/* delete from group db */
810 0a39f78f jim-p
	$cmd = "/usr/sbin/pw groupdel " . escapeshellarg($group['name']);
811 55eb9c44 --global
812 1e0b1727 Phil Davis
	if ($debug) {
813 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("Running: %s"), $cmd));
814 1e0b1727 Phil Davis
	}
815 0914b6bb Ermal
	mwexec($cmd);
816 55eb9c44 --global
}
817
818 6306b5dd Ermal Lu?i
function ldap_test_connection($authcfg) {
819 55eb9c44 --global
	global $debug, $config, $g;
820
821 c61e4626 Ermal Lu?i
	if ($authcfg) {
822 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
823
			$ldapproto = "ldap";
824
		} else {
825
			$ldapproto = "ldaps";
826
		}
827
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
828
		$ldapport = $authcfg['ldap_port'];
829
		if (!empty($ldapport)) {
830 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
831 1e0b1727 Phil Davis
		}
832
		$ldapbasedn = $authcfg['ldap_basedn'];
833
		$ldapbindun = $authcfg['ldap_binddn'];
834
		$ldapbindpw = $authcfg['ldap_bindpw'];
835
	} else {
836 6306b5dd Ermal Lu?i
		return false;
837 1e0b1727 Phil Davis
	}
838 55eb9c44 --global
839 1e0b1727 Phil Davis
	/* first check if there is even an LDAP server populated */
840 4de8f7ba Phil Davis
	if (!$ldapserver) {
841 1e0b1727 Phil Davis
		return false;
842
	}
843 c61e4626 Ermal Lu?i
844 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
845
	ldap_setup_caenv($authcfg);
846 fe2031ab Ermal
847 1e0b1727 Phil Davis
	/* connect and see if server is up */
848
	$error = false;
849
	if (!($ldap = ldap_connect($ldapserver))) {
850 9f27de6d jim-p
		$error = true;
851 1e0b1727 Phil Davis
	}
852 c61e4626 Ermal Lu?i
853 1e0b1727 Phil Davis
	if ($error == true) {
854
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
855
		return false;
856
	}
857 55eb9c44 --global
858
	return true;
859
}
860
861 fe2031ab Ermal
function ldap_setup_caenv($authcfg) {
862
	global $g;
863 007e59d2 jim-p
	require_once("certs.inc");
864 fe2031ab Ermal
865
	unset($caref);
866 a7702ed5 Ermal
	if (empty($authcfg['ldap_caref']) || !strstr($authcfg['ldap_urltype'], "SSL")) {
867 fe2031ab Ermal
		putenv('LDAPTLS_REQCERT=never');
868
		return;
869
	} else {
870 a7702ed5 Ermal
		$caref = lookup_ca($authcfg['ldap_caref']);
871 fe2031ab Ermal
		if (!$caref) {
872 a7702ed5 Ermal
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
873 fe2031ab Ermal
			/* XXX: Prevent for credential leaking since we cannot setup the CA env. Better way? */
874
			putenv('LDAPTLS_REQCERT=hard');
875
			return;
876
		}
877 1e0b1727 Phil Davis
		if (!is_dir("{$g['varrun_path']}/certs")) {
878 fe2031ab Ermal
			@mkdir("{$g['varrun_path']}/certs");
879 1e0b1727 Phil Davis
		}
880
		if (file_exists("{$g['varrun_path']}/certs/{$caref['refid']}.ca")) {
881 b2a0a8e9 jim-p
			@unlink("{$g['varrun_path']}/certs/{$caref['refid']}.ca");
882 1e0b1727 Phil Davis
		}
883 b2a0a8e9 jim-p
		file_put_contents("{$g['varrun_path']}/certs/{$caref['refid']}.ca", base64_decode($caref['crt']));
884
		@chmod("{$g['varrun_path']}/certs/{$caref['refid']}.ca", 0600);
885 fe2031ab Ermal
		putenv('LDAPTLS_REQCERT=hard');
886
		/* XXX: Probably even the hashed link should be created for this? */
887 906daddc Ermal
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
888 b2a0a8e9 jim-p
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
889 fe2031ab Ermal
	}
890
}
891
892 6306b5dd Ermal Lu?i
function ldap_test_bind($authcfg) {
893 55eb9c44 --global
	global $debug, $config, $g;
894
895 c61e4626 Ermal Lu?i
	if ($authcfg) {
896 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
897
			$ldapproto = "ldap";
898
		} else {
899
			$ldapproto = "ldaps";
900
		}
901
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
902
		$ldapport = $authcfg['ldap_port'];
903
		if (!empty($ldapport)) {
904 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
905 1e0b1727 Phil Davis
		}
906
		$ldapbasedn = $authcfg['ldap_basedn'];
907
		$ldapbindun = $authcfg['ldap_binddn'];
908
		$ldapbindpw = $authcfg['ldap_bindpw'];
909
		$ldapver = $authcfg['ldap_protver'];
910 e8c09a23 Chris Buechler
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
911 1e0b1727 Phil Davis
		if (empty($ldapbndun) || empty($ldapbindpw)) {
912
			$ldapanon = true;
913
		} else {
914
			$ldapanon = false;
915
		}
916
	} else {
917 6306b5dd Ermal Lu?i
		return false;
918 1e0b1727 Phil Davis
	}
919 c61e4626 Ermal Lu?i
920
	/* first check if there is even an LDAP server populated */
921 1e0b1727 Phil Davis
	if (!$ldapserver) {
922
		return false;
923
	}
924 c61e4626 Ermal Lu?i
925 fe2031ab Ermal
	/* Setup CA environment if needed. */
926
	ldap_setup_caenv($authcfg);
927
928 1e0b1727 Phil Davis
	/* connect and see if server is up */
929
	$error = false;
930
	if (!($ldap = ldap_connect($ldapserver))) {
931 9f27de6d jim-p
		$error = true;
932 1e0b1727 Phil Davis
	}
933 c61e4626 Ermal Lu?i
934 1e0b1727 Phil Davis
	if ($error == true) {
935
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
936
		return false;
937
	}
938 55eb9c44 --global
939
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
940 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
941 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
942 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
943
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
944 1180e4f0 Sjon Hortensius
945 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
946
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
947 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
948 6306b5dd Ermal Lu?i
		if (!($res = @ldap_bind($ldap))) {
949
			@ldap_close($ldap);
950 c61e4626 Ermal Lu?i
			return false;
951 6306b5dd Ermal Lu?i
		}
952
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
953
		@ldap_close($ldap);
954 55eb9c44 --global
		return false;
955 6306b5dd Ermal Lu?i
	}
956 55eb9c44 --global
957 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
958 c61e4626 Ermal Lu?i
959 55eb9c44 --global
	return true;
960
}
961
962 6306b5dd Ermal Lu?i
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
963 55eb9c44 --global
	global $debug, $config, $g;
964
965 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
966 55eb9c44 --global
		return;
967 1e0b1727 Phil Davis
	}
968 55eb9c44 --global
969 7a938f1b Ermal
	$ous = array();
970
971 c61e4626 Ermal Lu?i
	if ($authcfg) {
972 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
973
			$ldapproto = "ldap";
974
		} else {
975
			$ldapproto = "ldaps";
976
		}
977
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
978
		$ldapport = $authcfg['ldap_port'];
979
		if (!empty($ldapport)) {
980 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
981 1e0b1727 Phil Davis
		}
982
		$ldapbasedn = $authcfg['ldap_basedn'];
983
		$ldapbindun = $authcfg['ldap_binddn'];
984
		$ldapbindpw = $authcfg['ldap_bindpw'];
985
		$ldapver = $authcfg['ldap_protver'];
986
		if (empty($ldapbindun) || empty($ldapbindpw)) {
987
			$ldapanon = true;
988
		} else {
989
			$ldapanon = false;
990
		}
991
		$ldapname = $authcfg['name'];
992
		$ldapfallback = false;
993
		$ldapscope = $authcfg['ldap_scope'];
994 e8c09a23 Chris Buechler
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
995 1e0b1727 Phil Davis
	} else {
996 6306b5dd Ermal Lu?i
		return false;
997 1e0b1727 Phil Davis
	}
998 55eb9c44 --global
999 1e0b1727 Phil Davis
	/* first check if there is even an LDAP server populated */
1000
	if (!$ldapserver) {
1001
		log_error(gettext("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined."));
1002
		return $ous;
1003
	}
1004 c61e4626 Ermal Lu?i
1005 fe2031ab Ermal
	/* Setup CA environment if needed. */
1006
	ldap_setup_caenv($authcfg);
1007
1008 c61e4626 Ermal Lu?i
	/* connect and see if server is up */
1009 1e0b1727 Phil Davis
	$error = false;
1010
	if (!($ldap = ldap_connect($ldapserver))) {
1011 9f27de6d jim-p
		$error = true;
1012 1e0b1727 Phil Davis
	}
1013 c61e4626 Ermal Lu?i
1014 1e0b1727 Phil Davis
	if ($error == true) {
1015
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1016
		return $ous;
1017
	}
1018 c61e4626 Ermal Lu?i
1019
	$ldapfilter = "(|(ou=*)(cn=Users))";
1020 55eb9c44 --global
1021
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1022 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1023 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1024 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1025
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1026 55eb9c44 --global
1027 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1028
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1029 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
1030 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
1031 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind anonymously to server %s."), $ldapname));
1032 6306b5dd Ermal Lu?i
			@ldap_close($ldap);
1033 1e0b1727 Phil Davis
			return $ous;
1034 c61e4626 Ermal Lu?i
		}
1035
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1036 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind to server %s."), $ldapname));
1037 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
1038 c61e4626 Ermal Lu?i
		return $ous;
1039 55eb9c44 --global
	}
1040
1041 1e0b1727 Phil Davis
	if ($ldapscope == "one") {
1042 c61e4626 Ermal Lu?i
		$ldapfunc = "ldap_list";
1043 1e0b1727 Phil Davis
	} else {
1044 c61e4626 Ermal Lu?i
		$ldapfunc = "ldap_search";
1045 1e0b1727 Phil Davis
	}
1046 55eb9c44 --global
1047 7a938f1b Ermal
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
1048
	$info = @ldap_get_entries($ldap, $search);
1049 55eb9c44 --global
1050
	if (is_array($info)) {
1051
		foreach ($info as $inf) {
1052
			if (!$show_complete_ou) {
1053 cfbfd941 smos
				$inf_split = explode(",", $inf['dn']);
1054 55eb9c44 --global
				$ou = $inf_split[0];
1055 4de8f7ba Phil Davis
				$ou = str_replace("OU=", "", $ou);
1056
				$ou = str_replace("CN=", "", $ou);
1057 1e0b1727 Phil Davis
			} else {
1058
				if ($inf['dn']) {
1059 55eb9c44 --global
					$ou = $inf['dn'];
1060 1e0b1727 Phil Davis
				}
1061
			}
1062
			if ($ou) {
1063 55eb9c44 --global
				$ous[] = $ou;
1064 1e0b1727 Phil Davis
			}
1065 55eb9c44 --global
		}
1066
	}
1067
1068 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1069
1070 55eb9c44 --global
	return $ous;
1071
}
1072
1073 6306b5dd Ermal Lu?i
function ldap_get_groups($username, $authcfg) {
1074 55eb9c44 --global
	global $debug, $config;
1075 1180e4f0 Sjon Hortensius
1076 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
1077 55eb9c44 --global
		return;
1078 1e0b1727 Phil Davis
	}
1079 1180e4f0 Sjon Hortensius
1080 1e0b1727 Phil Davis
	if (!$username) {
1081 55eb9c44 --global
		return false;
1082 1e0b1727 Phil Davis
	}
1083 55eb9c44 --global
1084 1e0b1727 Phil Davis
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1085 2ce660ad smos
		$username_split = explode("@", $username);
1086 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1087 55eb9c44 --global
	}
1088
1089 1e0b1727 Phil Davis
	if (stristr($username, "\\")) {
1090 cfbfd941 smos
		$username_split = explode("\\", $username);
1091 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1092
	}
1093
1094 55eb9c44 --global
	//log_error("Getting LDAP groups for {$username}.");
1095 1e0b1727 Phil Davis
	if ($authcfg) {
1096
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
1097
			$ldapproto = "ldap";
1098
		} else {
1099
			$ldapproto = "ldaps";
1100
		}
1101
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1102
		$ldapport = $authcfg['ldap_port'];
1103
		if (!empty($ldapport)) {
1104 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
1105 1e0b1727 Phil Davis
		}
1106
		$ldapbasedn = $authcfg['ldap_basedn'];
1107
		$ldapbindun = $authcfg['ldap_binddn'];
1108
		$ldapbindpw = $authcfg['ldap_bindpw'];
1109
		$ldapauthcont = $authcfg['ldap_authcn'];
1110
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1111
		$ldapgroupattribute = strtolower($authcfg['ldap_attr_member']);
1112 149efbea jim-p
		if (isset($authcfg['ldap_rfc2307'])) {
1113
			$ldapfilter         = "(&(objectClass={$authcfg['ldap_attr_groupobj']})({$ldapgroupattribute}={$username}))";
1114
		} else {
1115
			$ldapfilter         = "({$ldapnameattribute}={$username})";
1116
		}
1117 1e0b1727 Phil Davis
		$ldaptype = "";
1118
		$ldapver = $authcfg['ldap_protver'];
1119
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1120
			$ldapanon = true;
1121
		} else {
1122
			$ldapanon = false;
1123
		}
1124
		$ldapname = $authcfg['name'];
1125
		$ldapfallback = false;
1126
		$ldapscope = $authcfg['ldap_scope'];
1127 e8c09a23 Chris Buechler
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1128 1e0b1727 Phil Davis
	} else {
1129 6306b5dd Ermal Lu?i
		return false;
1130 1e0b1727 Phil Davis
	}
1131 c61e4626 Ermal Lu?i
1132 149efbea jim-p
	if (isset($authcfg['ldap_rfc2307'])) {
1133
		$ldapdn = $ldapbasedn;
1134
	} else {
1135
		$ldapdn = $_SESSION['ldapdn'];
1136
	}
1137 c61e4626 Ermal Lu?i
1138 55eb9c44 --global
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
1139
	$ldapgroupattribute = strtolower($ldapgroupattribute);
1140 c61e4626 Ermal Lu?i
	$memberof = array();
1141 55eb9c44 --global
1142 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
1143
	ldap_setup_caenv($authcfg);
1144 fe2031ab Ermal
1145 55eb9c44 --global
	/* connect and see if server is up */
1146 c61e4626 Ermal Lu?i
	$error = false;
1147 1e0b1727 Phil Davis
	if (!($ldap = ldap_connect($ldapserver))) {
1148 9f27de6d jim-p
		$error = true;
1149 1e0b1727 Phil Davis
	}
1150 c61e4626 Ermal Lu?i
1151
	if ($error == true) {
1152 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_groups() Could not connect to server %s."), $ldapname));
1153 1e0b1727 Phil Davis
		return memberof;
1154
	}
1155 1180e4f0 Sjon Hortensius
1156 55eb9c44 --global
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1157 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1158 c61e4626 Ermal Lu?i
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1159 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1160
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1161 55eb9c44 --global
1162
	/* bind as user that has rights to read group attributes */
1163 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1164
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1165 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
1166 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
1167 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
1168 6306b5dd Ermal Lu?i
			@ldap_close($ldap);
1169 1e0b1727 Phil Davis
			return false;
1170 6306b5dd Ermal Lu?i
		}
1171 c61e4626 Ermal Lu?i
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1172 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
1173 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
1174 c61e4626 Ermal Lu?i
		return memberof;
1175 55eb9c44 --global
	}
1176
1177
	/* get groups from DN found */
1178
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
1179
	/* since we know the DN is in $_SESSION['ldapdn'] */
1180
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
1181 1e0b1727 Phil Davis
	if ($ldapscope == "one") {
1182
		$ldapfunc = "ldap_list";
1183
	} else {
1184
		$ldapfunc = "ldap_search";
1185
	}
1186 c61e4626 Ermal Lu?i
1187 1e0b1727 Phil Davis
	$search = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
1188
	$info = @ldap_get_entries($ldap, $search);
1189 55eb9c44 --global
1190 149efbea jim-p
	$gresults = isset($authcfg['ldap_rfc2307']) ? $info : $info[0][$ldapgroupattribute];
1191 1180e4f0 Sjon Hortensius
1192 4e322e2c Phil Davis
	if (is_array($gresults)) {
1193 55eb9c44 --global
		/* Iterate through the groups and throw them into an array */
1194 149efbea jim-p
		foreach ($gresults as $grp) {
1195 4e322e2c Phil Davis
			if (((isset($authcfg['ldap_rfc2307'])) && (stristr($grp["dn"], "CN=") !== false)) ||
1196
			    ((!isset($authcfg['ldap_rfc2307'])) && (stristr($grp, "CN=") !== false))) {
1197 149efbea jim-p
				$grpsplit = isset($authcfg['ldap_rfc2307']) ? explode(",", $grp["dn"]) : explode(",", $grp);
1198
				$memberof[] = preg_replace("/CN=/i", "", $grpsplit[0]);
1199 55eb9c44 --global
			}
1200
		}
1201
	}
1202 1180e4f0 Sjon Hortensius
1203 55eb9c44 --global
	/* Time to close LDAP connection */
1204 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1205 1180e4f0 Sjon Hortensius
1206 4de8f7ba Phil Davis
	$groups = print_r($memberof, true);
1207 1180e4f0 Sjon Hortensius
1208 55eb9c44 --global
	//log_error("Returning groups ".$groups." for user $username");
1209 1180e4f0 Sjon Hortensius
1210 55eb9c44 --global
	return $memberof;
1211
}
1212
1213 83e0d4c8 jim-p
function ldap_format_host($host) {
1214
	return is_ipaddrv6($host) ? "[$host]" : $host ;
1215
}
1216
1217 6306b5dd Ermal Lu?i
function ldap_backed($username, $passwd, $authcfg) {
1218 55eb9c44 --global
	global $debug, $config;
1219 1180e4f0 Sjon Hortensius
1220 1e0b1727 Phil Davis
	if (!$username) {
1221 55eb9c44 --global
		return;
1222 1e0b1727 Phil Davis
	}
1223 55eb9c44 --global
1224 1e0b1727 Phil Davis
	if (!function_exists("ldap_connect")) {
1225 55eb9c44 --global
		return;
1226 1e0b1727 Phil Davis
	}
1227 55eb9c44 --global
1228 1e0b1727 Phil Davis
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1229 2ce660ad smos
		$username_split = explode("@", $username);
1230 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1231 55eb9c44 --global
	}
1232 1e0b1727 Phil Davis
	if (stristr($username, "\\")) {
1233 cfbfd941 smos
		$username_split = explode("\\", $username);
1234 1180e4f0 Sjon Hortensius
		$username = $username_split[0];
1235 55eb9c44 --global
	}
1236
1237 c61e4626 Ermal Lu?i
	if ($authcfg) {
1238 1e0b1727 Phil Davis
		if (strstr($authcfg['ldap_urltype'], "Standard")) {
1239 c61e4626 Ermal Lu?i
			$ldapproto = "ldap";
1240 1e0b1727 Phil Davis
		} else {
1241 c61e4626 Ermal Lu?i
			$ldapproto = "ldaps";
1242 1e0b1727 Phil Davis
		}
1243
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1244
		$ldapport = $authcfg['ldap_port'];
1245
		if (!empty($ldapport)) {
1246 9f27de6d jim-p
			$ldapserver .= ":{$ldapport}";
1247 1e0b1727 Phil Davis
		}
1248
		$ldapbasedn = $authcfg['ldap_basedn'];
1249
		$ldapbindun = $authcfg['ldap_binddn'];
1250
		$ldapbindpw = $authcfg['ldap_bindpw'];
1251
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1252 c61e4626 Ermal Lu?i
			$ldapanon = true;
1253 1e0b1727 Phil Davis
		} else {
1254 c61e4626 Ermal Lu?i
			$ldapanon = false;
1255 1e0b1727 Phil Davis
		}
1256
		$ldapauthcont = $authcfg['ldap_authcn'];
1257
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1258
		$ldapextendedqueryenabled = $authcfg['ldap_extended_enabled'];
1259
		$ldapextendedquery = $authcfg['ldap_extended_query'];
1260
		$ldapfilter = "";
1261
		if (!$ldapextendedqueryenabled) {
1262
			$ldapfilter = "({$ldapnameattribute}={$username})";
1263
		} else {
1264
			$ldapfilter = "(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
1265
		}
1266
		$ldaptype = "";
1267
		$ldapver = $authcfg['ldap_protver'];
1268
		$ldapname = $authcfg['name'];
1269
		$ldapscope = $authcfg['ldap_scope'];
1270 e8c09a23 Chris Buechler
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1271 1e0b1727 Phil Davis
	} else {
1272 6306b5dd Ermal Lu?i
		return false;
1273 1e0b1727 Phil Davis
	}
1274 55eb9c44 --global
1275 1180e4f0 Sjon Hortensius
	/* first check if there is even an LDAP server populated */
1276 1e0b1727 Phil Davis
	if (!$ldapserver) {
1277 c61e4626 Ermal Lu?i
		if ($ldapfallback) {
1278 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."));
1279 c61e4626 Ermal Lu?i
			return local_backed($username, $passwd);
1280 1e0b1727 Phil Davis
		} else {
1281 94021404 Carlos Eduardo Ramos
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined."));
1282 1e0b1727 Phil Davis
		}
1283 c61e4626 Ermal Lu?i
1284
		return false;
1285 55eb9c44 --global
	}
1286 1180e4f0 Sjon Hortensius
1287 1e0b1727 Phil Davis
	/* Setup CA environment if needed. */
1288
	ldap_setup_caenv($authcfg);
1289 fe2031ab Ermal
1290 906daddc Ermal
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1291 3d3081ec Andrew MacIsaac
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1292 906daddc Ermal
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1293 d6b4dfe3 jim-p
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1294
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1295 906daddc Ermal
1296 55eb9c44 --global
	/* Make sure we can connect to LDAP */
1297 c61e4626 Ermal Lu?i
	$error = false;
1298 1e0b1727 Phil Davis
	if (!($ldap = ldap_connect($ldapserver))) {
1299 c61e4626 Ermal Lu?i
		$error = true;
1300 1e0b1727 Phil Davis
	}
1301 c61e4626 Ermal Lu?i
1302
	if ($error == true) {
1303 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1304 c61e4626 Ermal Lu?i
		return false;
1305 55eb9c44 --global
	}
1306 c61e4626 Ermal Lu?i
1307 55eb9c44 --global
	/* ok, its up.  now, lets bind as the bind user so we can search it */
1308 c61e4626 Ermal Lu?i
	$error = false;
1309 a5cd1c5a jim-p
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1310
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1311 c61e4626 Ermal Lu?i
	if ($ldapanon == true) {
1312 1e0b1727 Phil Davis
		if (!($res = @ldap_bind($ldap))) {
1313
			$error = true;
1314
		}
1315
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1316 c61e4626 Ermal Lu?i
		$error = true;
1317 1e0b1727 Phil Davis
	}
1318 c61e4626 Ermal Lu?i
1319
	if ($error == true) {
1320 6306b5dd Ermal Lu?i
		@ldap_close($ldap);
1321 94021404 Carlos Eduardo Ramos
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1322 c61e4626 Ermal Lu?i
		return false;
1323 55eb9c44 --global
	}
1324 1180e4f0 Sjon Hortensius
1325 55eb9c44 --global
	/* Get LDAP Authcontainers and split em up. */
1326 cfbfd941 smos
	$ldac_splits = explode(";", $ldapauthcont);
1327 1180e4f0 Sjon Hortensius
1328 086cf944 Phil Davis
	/* setup the usercount so we think we haven't found anyone yet */
1329 4de8f7ba Phil Davis
	$usercount = 0;
1330 55eb9c44 --global
1331
	/*****************************************************************/
1332 6990ad35 Phil Davis
	/*  We first find the user based on username and filter          */
1333
	/*  then, once we find the first occurrence of that person       */
1334
	/*  we set session variables to point to the OU and DN of the    */
1335
	/*  person.  To later be used by ldap_get_groups.                */
1336 55eb9c44 --global
	/*  that way we don't have to search twice.                      */
1337
	/*****************************************************************/
1338 1e0b1727 Phil Davis
	if ($debug) {
1339 3ac8324f Ermal
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1340 1e0b1727 Phil Davis
	}
1341 c61e4626 Ermal Lu?i
	/* Iterate through the user containers for search */
1342
	foreach ($ldac_splits as $i => $ldac_split) {
1343 a5cd1c5a jim-p
		$ldac_split = isset($authcfg['ldap_utf8']) ? utf8_encode($ldac_split) : $ldac_split;
1344
		$ldapfilter = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapfilter) : $ldapfilter;
1345
		$ldapsearchbasedn = isset($authcfg['ldap_utf8']) ? utf8_encode("{$ldac_split},{$ldapbasedn}") : "{$ldac_split},{$ldapbasedn}";
1346 c61e4626 Ermal Lu?i
		/* Make sure we just use the first user we find */
1347 1e0b1727 Phil Davis
		if ($debug) {
1348 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)));
1349 1e0b1727 Phil Davis
		}
1350
		if ($ldapscope == "one") {
1351 c61e4626 Ermal Lu?i
			$ldapfunc = "ldap_list";
1352 1e0b1727 Phil Davis
		} else {
1353 c61e4626 Ermal Lu?i
			$ldapfunc = "ldap_search";
1354 1e0b1727 Phil Davis
		}
1355 c61e4626 Ermal Lu?i
		/* Support legacy auth container specification. */
1356 1e0b1727 Phil Davis
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn)) {
1357 6990ad35 Phil Davis
			$search = @$ldapfunc($ldap, $ldac_split, $ldapfilter);
1358 1e0b1727 Phil Davis
		} else {
1359 6990ad35 Phil Davis
			$search = @$ldapfunc($ldap, $ldapsearchbasedn, $ldapfilter);
1360 1e0b1727 Phil Davis
		}
1361 c61e4626 Ermal Lu?i
		if (!$search) {
1362 94021404 Carlos Eduardo Ramos
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1363 c61e4626 Ermal Lu?i
			continue;
1364 55eb9c44 --global
		}
1365 4de8f7ba Phil Davis
		$info = ldap_get_entries($ldap, $search);
1366 c61e4626 Ermal Lu?i
		$matches = $info['count'];
1367 1e0b1727 Phil Davis
		if ($matches == 1) {
1368 c61e4626 Ermal Lu?i
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1369
			$_SESSION['ldapou'] = $ldac_split[$i];
1370
			$_SESSION['ldapon'] = "true";
1371
			$usercount = 1;
1372
			break;
1373 55eb9c44 --global
		}
1374
	}
1375
1376 1e0b1727 Phil Davis
	if ($usercount != 1) {
1377 6306b5dd Ermal Lu?i
		@ldap_unbind($ldap);
1378 94021404 Carlos Eduardo Ramos
		log_error(gettext("ERROR! Either LDAP search failed, or multiple users were found."));
1379 1180e4f0 Sjon Hortensius
		return false;
1380 55eb9c44 --global
	}
1381 c61e4626 Ermal Lu?i
1382 55eb9c44 --global
	/* Now lets bind as the user we found */
1383 a5cd1c5a jim-p
	$passwd = isset($authcfg['ldap_utf8']) ? utf8_encode($passwd) : $passwd;
1384 c61e4626 Ermal Lu?i
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
1385 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)));
1386 6306b5dd Ermal Lu?i
		@ldap_unbind($ldap);
1387 c61e4626 Ermal Lu?i
		return false;
1388 55eb9c44 --global
	}
1389
1390 a5cd1c5a jim-p
	if ($debug) {
1391
		$userdn = isset($authcfg['ldap_utf8']) ? utf8_decode($userdn) : $userdn;
1392 2004def5 Ermal
		log_auth(sprintf(gettext('Logged in successfully as %1$s via LDAP server %2$s with DN = %3$s.'), $username, $ldapname, $userdn));
1393 a5cd1c5a jim-p
	}
1394 c61e4626 Ermal Lu?i
1395
	/* At this point we are bound to LDAP so the user was auth'd okay. Close connection. */
1396 6306b5dd Ermal Lu?i
	@ldap_unbind($ldap);
1397 55eb9c44 --global
1398
	return true;
1399
}
1400
1401 1492e02c Ermal
function radius_backed($username, $passwd, $authcfg, &$attributes = array()) {
1402 a13ce628 Ermal Lu?i
	global $debug, $config;
1403 55eb9c44 --global
	$ret = false;
1404
1405 868c6826 Ermal
	require_once("radius.inc");
1406
1407 55eb9c44 --global
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1408 c61e4626 Ermal Lu?i
	if ($authcfg) {
1409
		$radiusservers = array();
1410
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1411
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1412
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1413 bddd2be8 jim-p
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1414 1e0b1727 Phil Davis
	} else {
1415 6306b5dd Ermal Lu?i
		return false;
1416 1e0b1727 Phil Davis
	}
1417 c61e4626 Ermal Lu?i
1418 1e0b1727 Phil Davis
	/* Add new servers to our instance */
1419 bddd2be8 jim-p
	foreach ($radiusservers as $radsrv) {
1420
		$timeout = (is_numeric($radsrv['timeout'])) ? $radsrv['timeout'] : 5;
1421
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret'], $timeout);
1422
	}
1423 55eb9c44 --global
1424 6e815096 Ermal
	if (PEAR::isError($rauth->start())) {
1425 55eb9c44 --global
		$retvalue['auth_val'] = 1;
1426
		$retvalue['error'] = $rauth->getError();
1427 1e0b1727 Phil Davis
		if ($debug) {
1428 7aaf60a8 k-paulius
			printf(gettext("RADIUS start: %s<br />\n"), $retvalue['error']);
1429 1e0b1727 Phil Davis
		}
1430 55eb9c44 --global
	}
1431
1432
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1433
1434
	/* Send request */
1435
	$result = $rauth->send();
1436
	if (PEAR::isError($result)) {
1437
		$retvalue['auth_val'] = 1;
1438
		$retvalue['error'] = $result->getMessage();
1439 1e0b1727 Phil Davis
		if ($debug) {
1440 7aaf60a8 k-paulius
			printf(gettext("RADIUS send failed: %s<br />\n"), $retvalue['error']);
1441 1e0b1727 Phil Davis
		}
1442 55eb9c44 --global
	} else if ($result === true) {
1443 1e0b1727 Phil Davis
		if ($rauth->getAttributes()) {
1444 1492e02c Ermal
			$attributes = $rauth->listAttributes();
1445 1e0b1727 Phil Davis
		}
1446 55eb9c44 --global
		$retvalue['auth_val'] = 2;
1447 1e0b1727 Phil Davis
		if ($debug) {
1448 7aaf60a8 k-paulius
			printf(gettext("RADIUS Auth succeeded")."<br />\n");
1449 1e0b1727 Phil Davis
		}
1450 55eb9c44 --global
		$ret = true;
1451
	} else {
1452
		$retvalue['auth_val'] = 3;
1453 1e0b1727 Phil Davis
		if ($debug) {
1454 7aaf60a8 k-paulius
			printf(gettext("RADIUS Auth rejected")."<br />\n");
1455 1e0b1727 Phil Davis
		}
1456 55eb9c44 --global
	}
1457
1458
	// close OO RADIUS_AUTHENTICATION
1459
	$rauth->close();
1460
1461
	return $ret;
1462
}
1463
1464 c4a9f99a jim-p
/*
1465
	$attributes must contain a "class" key containing the groups and local
1466
	groups must exist to match.
1467
*/
1468
function radius_get_groups($attributes) {
1469
	$groups = array();
1470 461bae6b jim-p
	if (!empty($attributes) && is_array($attributes) && (!empty($attributes['class']) || !empty($attributes['class_int']))) {
1471
		/* Some RADIUS servers return multiple class attributes, so check them all. */
1472
		$groups = array();
1473
		if (!empty($attributes['class']) && is_array($attributes['class'])) {
1474
			foreach ($attributes['class'] as $class) {
1475
				$groups = array_unique(array_merge($groups, explode(";", $class)));
1476
			}
1477
		}
1478
1479 c4a9f99a jim-p
		foreach ($groups as & $grp) {
1480 916fc1f8 jim-p
			$grp = trim($grp);
1481
			if (strtolower(substr($grp, 0, 3)) == "ou=") {
1482 c4a9f99a jim-p
				$grp = substr($grp, 3);
1483
			}
1484
		}
1485
	}
1486
	return $groups;
1487
}
1488
1489 7dd044f2 sullrich
function get_user_expiration_date($username) {
1490 a13ce628 Ermal Lu?i
	$user = getUserEntry($username);
1491 1e0b1727 Phil Davis
	if ($user['expires']) {
1492 a13ce628 Ermal Lu?i
		return $user['expires'];
1493 1e0b1727 Phil Davis
	}
1494 a13ce628 Ermal Lu?i
}
1495
1496
function is_account_expired($username) {
1497
	$expirydate = get_user_expiration_date($username);
1498
	if ($expirydate) {
1499 4de8f7ba Phil Davis
		if (strtotime("-1 day") > strtotime(date("m/d/Y", strtotime($expirydate)))) {
1500 a13ce628 Ermal Lu?i
			return true;
1501 1e0b1727 Phil Davis
		}
1502 7dd044f2 sullrich
	}
1503 a13ce628 Ermal Lu?i
1504
	return false;
1505 7dd044f2 sullrich
}
1506
1507 b4bfd25d sullrich
function is_account_disabled($username) {
1508 a13ce628 Ermal Lu?i
	$user = getUserEntry($username);
1509 1e0b1727 Phil Davis
	if (isset($user['disabled'])) {
1510 a13ce628 Ermal Lu?i
		return true;
1511 1e0b1727 Phil Davis
	}
1512 a13ce628 Ermal Lu?i
1513 b4bfd25d sullrich
	return false;
1514
}
1515
1516 c61e4626 Ermal Lu?i
function auth_get_authserver($name) {
1517 1e0b1727 Phil Davis
	global $config;
1518
1519
	if (is_array($config['system']['authserver'])) {
1520
		foreach ($config['system']['authserver'] as $authcfg) {
1521
			if ($authcfg['name'] == $name) {
1522
				return $authcfg;
1523
			}
1524
		}
1525
	}
1526
	if ($name == "Local Database") {
1527 96568521 Vinicius Coque
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1528 1e0b1727 Phil Davis
	}
1529 6306b5dd Ermal Lu?i
}
1530
1531
function auth_get_authserver_list() {
1532 1e0b1727 Phil Davis
	global $config;
1533 6306b5dd Ermal Lu?i
1534
	$list = array();
1535
1536 1e0b1727 Phil Davis
	if (is_array($config['system']['authserver'])) {
1537
		foreach ($config['system']['authserver'] as $authcfg) {
1538 6306b5dd Ermal Lu?i
			/* Add support for disabled entries? */
1539
			$list[$authcfg['name']] = $authcfg;
1540 1e0b1727 Phil Davis
		}
1541
	}
1542 6306b5dd Ermal Lu?i
1543 4de8f7ba Phil Davis
	$list["Local Database"] = array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1544 6306b5dd Ermal Lu?i
	return $list;
1545 c61e4626 Ermal Lu?i
}
1546
1547 c4a9f99a jim-p
function getUserGroups($username, $authcfg, &$attributes = array()) {
1548 fb0f22c0 Ermal Lu?i
	global $config;
1549
1550
	$allowed_groups = array();
1551
1552 1e0b1727 Phil Davis
	switch ($authcfg['type']) {
1553
		case 'ldap':
1554
			$allowed_groups = @ldap_get_groups($username, $authcfg);
1555
			break;
1556
		case 'radius':
1557 c4a9f99a jim-p
			$allowed_groups = @radius_get_groups($attributes);
1558 1e0b1727 Phil Davis
			break;
1559
		default:
1560
			$user = getUserEntry($username);
1561
			$allowed_groups = @local_user_get_groups($user, true);
1562
			break;
1563 fb0f22c0 Ermal Lu?i
	}
1564
1565
	$member_groups = array();
1566 1e0b1727 Phil Davis
	if (is_array($config['system']['group'])) {
1567
		foreach ($config['system']['group'] as $group) {
1568
			if (in_array($group['name'], $allowed_groups)) {
1569 fb0f22c0 Ermal Lu?i
				$member_groups[] = $group['name'];
1570 1e0b1727 Phil Davis
			}
1571
		}
1572 fb0f22c0 Ermal Lu?i
	}
1573
1574
	return $member_groups;
1575
}
1576
1577 1492e02c Ermal
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1578 c61e4626 Ermal Lu?i
1579 b7369ff8 NewEraCracker
	if (is_array($username) || is_array($password)) {
1580
		return false;
1581
	}
1582
1583 c61e4626 Ermal Lu?i
	if (!$authcfg) {
1584
		return local_backed($username, $password);
1585
	}
1586
1587
	$authenticated = false;
1588 1e0b1727 Phil Davis
	switch ($authcfg['type']) {
1589
		case 'ldap':
1590
			if (ldap_backed($username, $password, $authcfg)) {
1591
				$authenticated = true;
1592
			}
1593
			break;
1594
		case 'radius':
1595
			if (radius_backed($username, $password, $authcfg, $attributes)) {
1596
				$authenticated = true;
1597
			}
1598
			break;
1599
		default:
1600
			/* lookup user object by name */
1601
			if (local_backed($username, $password)) {
1602
				$authenticated = true;
1603
			}
1604
			break;
1605
		}
1606 c61e4626 Ermal Lu?i
1607
	return $authenticated;
1608
}
1609
1610 6306b5dd Ermal Lu?i
function session_auth() {
1611 aa205c3b Ermal
	global $config, $_SESSION, $page;
1612 55eb9c44 --global
1613 49ddf9a1 Warren Baker
	// Handle HTTPS httponly and secure flags
1614 16789caa Renato Botelho
	$currentCookieParams = session_get_cookie_params();
1615
	session_set_cookie_params(
1616
		$currentCookieParams["lifetime"],
1617
		$currentCookieParams["path"],
1618
		NULL,
1619
		($config['system']['webgui']['protocol'] == "https"),
1620
		true
1621
	);
1622 49ddf9a1 Warren Baker
1623 1e0b1727 Phil Davis
	if (!session_id()) {
1624 9252d093 Ermal
		session_start();
1625 1e0b1727 Phil Davis
	}
1626 55eb9c44 --global
1627 dd030de9 Renato Botelho
	// Detect protocol change
1628 1e0b1727 Phil Davis
	if (!isset($_POST['login']) && !empty($_SESSION['Logged_In']) && $_SESSION['protocol'] != $config['system']['webgui']['protocol']) {
1629 dd030de9 Renato Botelho
		return false;
1630 1e0b1727 Phil Davis
	}
1631 dd030de9 Renato Botelho
1632 55eb9c44 --global
	/* Validate incoming login request */
1633 c4a9f99a jim-p
	$attributes = array();
1634 88165371 Ermal
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1635 6306b5dd Ermal Lu?i
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1636 c4a9f99a jim-p
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg, $attributes) ||
1637 6306b5dd Ermal Lu?i
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1638 526f5b11 Renato Botelho
			// Generate a new id to avoid session fixation
1639 8588095f Renato Botelho
			session_regenerate_id();
1640 6306b5dd Ermal Lu?i
			$_SESSION['Logged_In'] = "True";
1641
			$_SESSION['Username'] = $_POST['usernamefld'];
1642 c4a9f99a jim-p
			$_SESSION['user_radius_attributes'] = $attributes;
1643 6306b5dd Ermal Lu?i
			$_SESSION['last_access'] = time();
1644 dd030de9 Renato Botelho
			$_SESSION['protocol'] = $config['system']['webgui']['protocol'];
1645 1e0b1727 Phil Davis
			if (!isset($config['system']['webgui']['quietlogin'])) {
1646 54bdff75 Vinicius Coque
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1647 4fc3855f smos
			}
1648 1e0b1727 Phil Davis
			if (isset($_POST['postafterlogin'])) {
1649 92140621 Ermal
				return true;
1650 1e0b1727 Phil Davis
			} else {
1651
				if (empty($page)) {
1652 80b292f3 Ermal
					$page = "/";
1653 1e0b1727 Phil Davis
				}
1654 80b292f3 Ermal
				header("Location: {$page}");
1655
			}
1656 f23e6363 Ermal
			exit;
1657 a13ce628 Ermal Lu?i
		} else {
1658
			/* give the user an error message */
1659
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1660 65f7fba8 Scott Ullrich
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1661 1e0b1727 Phil Davis
			if (isAjax()) {
1662 a13ce628 Ermal Lu?i
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1663
				return;
1664 55eb9c44 --global
			}
1665
		}
1666
	}
1667
1668
	/* Show login page if they aren't logged in */
1669 1e0b1727 Phil Davis
	if (empty($_SESSION['Logged_In'])) {
1670 55eb9c44 --global
		return false;
1671 1e0b1727 Phil Davis
	}
1672 55eb9c44 --global
1673
	/* If session timeout isn't set, we don't mark sessions stale */
1674 02647583 Ermal
	if (!isset($config['system']['webgui']['session_timeout'])) {
1675 bdadaf3c Chris Buechler
		/* Default to 4 hour timeout if one is not set */
1676
		if ($_SESSION['last_access'] < (time() - 14400)) {
1677
			$_GET['logout'] = true;
1678
			$_SESSION['Logout'] = true;
1679 1e0b1727 Phil Davis
		} else {
1680 1180e4f0 Sjon Hortensius
			$_SESSION['last_access'] = time();
1681 1e0b1727 Phil Davis
		}
1682 02647583 Ermal
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1683
		/* only update if it wasn't ajax */
1684 1e0b1727 Phil Davis
		if (!isAjax()) {
1685 02647583 Ermal
			$_SESSION['last_access'] = time();
1686 1e0b1727 Phil Davis
		}
1687 bdadaf3c Chris Buechler
	} else {
1688 55eb9c44 --global
		/* Check for stale session */
1689
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1690
			$_GET['logout'] = true;
1691
			$_SESSION['Logout'] = true;
1692
		} else {
1693
			/* only update if it wasn't ajax */
1694 1e0b1727 Phil Davis
			if (!isAjax()) {
1695 55eb9c44 --global
				$_SESSION['last_access'] = time();
1696 1e0b1727 Phil Davis
			}
1697 55eb9c44 --global
		}
1698
	}
1699
1700
	/* user hit the logout button */
1701
	if (isset($_GET['logout'])) {
1702
1703 1e0b1727 Phil Davis
		if ($_SESSION['Logout']) {
1704 addc0439 Renato Botelho
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1705 1e0b1727 Phil Davis
		} else {
1706 addc0439 Renato Botelho
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1707 1e0b1727 Phil Davis
		}
1708 55eb9c44 --global
1709
		/* wipe out $_SESSION */
1710
		$_SESSION = array();
1711
1712 1e0b1727 Phil Davis
		if (isset($_COOKIE[session_name()])) {
1713 55eb9c44 --global
			setcookie(session_name(), '', time()-42000, '/');
1714 1e0b1727 Phil Davis
		}
1715 55eb9c44 --global
1716
		/* and destroy it */
1717
		session_destroy();
1718
1719 cfbfd941 smos
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1720 55eb9c44 --global
		$scriptElms = count($scriptName);
1721
		$scriptName = $scriptName[$scriptElms-1];
1722
1723 1e0b1727 Phil Davis
		if (isAjax()) {
1724 55eb9c44 --global
			return false;
1725 1e0b1727 Phil Davis
		}
1726 55eb9c44 --global
1727
		/* redirect to page the user is on, it'll prompt them to login again */
1728 6f3d2063 Renato Botelho
		header("Location: {$scriptName}");
1729 55eb9c44 --global
1730
		return false;
1731
	}
1732
1733
	/*
1734
	 * this is for debugging purpose if you do not want to use Ajax
1735 1e0b1727 Phil Davis
	 * to submit a HTML form. It basically disables the observation
1736 55eb9c44 --global
	 * of the submit event and hence does not trigger Ajax.
1737
	 */
1738 1e0b1727 Phil Davis
	if ($_GET['disable_ajax']) {
1739 55eb9c44 --global
		$_SESSION['NO_AJAX'] = "True";
1740 1e0b1727 Phil Davis
	}
1741 55eb9c44 --global
1742
	/*
1743
	 * Same to re-enable Ajax.
1744
	 */
1745 1e0b1727 Phil Davis
	if ($_GET['enable_ajax']) {
1746 55eb9c44 --global
		unset($_SESSION['NO_AJAX']);
1747 1e0b1727 Phil Davis
	}
1748 55eb9c44 --global
1749
	return true;
1750
}
1751
1752 88165371 Ermal
?>