Project

General

Profile

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