Project

General

Profile

Download (44.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	Copyright (C) 2010 Ermal Lu�i
5
	All rights reserved.
6

    
7
	Copyright (C) 2007, 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9

    
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
	pfSense_BUILDER_BINARIES:	/usr/sbin/pw	/bin/cp
41
	pfSense_MODULE:	auth
42
*/
43

    
44
/*
45
 * NOTE : Portions of the mschapv2 support was based on the BSD licensed CHAP.php
46
 * file courtesy of Michael Retterklieber.
47
 */
48
if(!$do_not_include_config_gui_inc)
49
	require_once("config.gui.inc");
50

    
51
// Will be changed to false if security checks fail
52
$security_passed = true;
53

    
54
/* If this function doesn't exist, we're being called from Captive Portal or 
55
   another internal subsystem which does not include authgui.inc */
56
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
57
	/* DNS ReBinding attack prevention.  https://redmine.pfsense.org/issues/708 */
58
	$found_host = false;
59

    
60
	/* Either a IPv6 address with or without a alternate port */
61
	if(strstr($_SERVER['HTTP_HOST'], "]")) {
62
		$http_host_port = explode("]", $_SERVER['HTTP_HOST']);
63
		/* v6 address has more parts, drop the last part */
64
		if(count($http_host_port) > 1) {
65
			array_pop($http_host_port);
66
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
67
		} else {
68
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
69
		}
70
	} else {
71
		$http_host = explode(":", $_SERVER['HTTP_HOST']);
72
		$http_host = $http_host[0];
73
	}
74
	if(is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
75
			strcasecmp($http_host, "localhost") == 0 or $_SERVER['SERVER_ADDR'] == "::1")
76
		$found_host = true;
77
	if(strcasecmp($http_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 or
78
			strcasecmp($http_host, $config['system']['hostname']) == 0)
79
		$found_host = true;
80

    
81
	if(is_array($config['dyndnses']['dyndns']) && !$found_host)
82
		foreach($config['dyndnses']['dyndns'] as $dyndns)
83
			if(strcasecmp($dyndns['host'], $http_host) == 0) {
84
				$found_host = true;
85
				break;
86
			}
87

    
88
	if(is_array($config['dnsupdates']['dnsupdate']) && !$found_host)
89
		foreach($config['dnsupdates']['dnsupdate'] as $rfc2136)
90
			if(strcasecmp($rfc2136['host'], $http_host) == 0) {
91
				$found_host = true;
92
				break;
93
			}
94

    
95
	if(!empty($config['system']['webgui']['althostnames']) && !$found_host) {
96
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
97
		foreach ($althosts as $ah)
98
			if(strcasecmp($ah, $http_host) == 0 or strcasecmp($ah, $_SERVER['SERVER_ADDR']) == 0) {
99
				$found_host = true;
100
				break;
101
			}
102
	}
103

    
104
	if($found_host == false) {
105
		if(!security_checks_disabled()) {
106
			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."));
107
			exit;
108
		}
109
		$security_passed = false;
110
	}
111
}
112

    
113
// If the HTTP_REFERER is something other than ourselves then disallow.
114
if(function_exists("display_error_form") && !isset($config['system']['webgui']['nohttpreferercheck'])) {
115
	if($_SERVER['HTTP_REFERER']) {
116
		if(file_exists("{$g['tmp_path']}/setupwizard_lastreferrer")) {
117
			if($_SERVER['HTTP_REFERER'] == file_get_contents("{$g['tmp_path']}/setupwizard_lastreferrer")) {
118
				unlink("{$g['tmp_path']}/setupwizard_lastreferrer");
119
				header("Refresh: 1; url=index.php");
120
				echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n        \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
121
				echo "<html><head><title>" . gettext("Redirecting...") . "</title></head><body>" . gettext("Redirecting to the dashboard...") . "</body></html>";
122
				exit;
123
			}
124
		}
125
		$found_host = false;
126
		$referrer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
127
		$referrer_host = str_replace(array("[", "]"), "", $referrer_host);
128
		if($referrer_host) {
129
			if(strcasecmp($referrer_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0
130
					|| strcasecmp($referrer_host, $config['system']['hostname']) == 0)
131
				$found_host = true;
132

    
133
			if(!empty($config['system']['webgui']['althostnames']) && !$found_host) {
134
				$althosts = explode(" ", $config['system']['webgui']['althostnames']);
135
				foreach ($althosts as $ah) {
136
					if(strcasecmp($referrer_host, $ah) == 0) {
137
						$found_host = true;
138
						break;
139
					}
140
				}
141
			}
142

    
143
			if(is_array($config['dyndnses']['dyndns']) && !$found_host)
144
				foreach($config['dyndnses']['dyndns'] as $dyndns)
145
					if(strcasecmp($dyndns['host'], $referrer_host) == 0) {
146
						$found_host = true;
147
						break;
148
					}
149

    
150
			if(is_array($config['dnsupdates']['dnsupdate']) && !$found_host)
151
				foreach($config['dnsupdates']['dnsupdate'] as $rfc2136)
152
					if(strcasecmp($rfc2136['host'], $referrer_host) == 0) {
153
						$found_host = true;
154
						break;
155
					}
156

    
157
			if(!$found_host) {
158
				$interface_list_ips = get_configured_ip_addresses();
159
				foreach($interface_list_ips as $ilips) {
160
					if(strcasecmp($referrer_host, $ilips) == 0) {
161
						$found_host = true;
162
						break;
163
					}
164
				}
165
				$interface_list_ipv6s = get_configured_ipv6_addresses();
166
				foreach($interface_list_ipv6s as $ilipv6s) {
167
					if(strcasecmp($referrer_host, $ilipv6s) == 0) {
168
						$found_host = true;
169
						break;
170
					}
171
				}
172
				if($referrer_host == "127.0.0.1" || $referrer_host == "localhost") {
173
					// allow SSH port forwarded connections and links from localhost
174
					$found_host = true;
175
				}
176
			}
177
		}
178
		if($found_host == false) {
179
			if(!security_checks_disabled()) {
180
				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.");
181
				exit;
182
			}
183
			$security_passed = false;
184
		}
185
	} else
186
		$security_passed = false;
187
}
188

    
189
if (function_exists("display_error_form") && $security_passed)
190
	/* Security checks passed, so it should be OK to turn them back on */
191
	restore_security_checks();
192
unset($security_passed);
193

    
194
$groupindex = index_groups();
195
$userindex = index_users();
196

    
197
function index_groups() {
198
	global $g, $debug, $config, $groupindex;
199

    
200
	$groupindex = array();
201

    
202
	if (is_array($config['system']['group'])) {
203
		$i = 0;
204
		foreach($config['system']['group'] as $groupent) {
205
			$groupindex[$groupent['name']] = $i;
206
			$i++;
207
		}
208
	}
209

    
210
	return ($groupindex);
211
}
212

    
213
function index_users() {
214
	global $g, $debug, $config;
215

    
216
	if (is_array($config['system']['user'])) {
217
		$i = 0;
218
		foreach($config['system']['user'] as $userent) {
219
			$userindex[$userent['name']] = $i;
220
			$i++;
221
		}
222
	}
223

    
224
	return ($userindex);
225
}
226

    
227
function & getUserEntry($name) {
228
	global $debug, $config, $userindex;
229
	if (isset($userindex[$name]))
230
		return $config['system']['user'][$userindex[$name]];
231
}
232

    
233
function & getUserEntryByUID($uid) {
234
	global $debug, $config;
235

    
236
	if (is_array($config['system']['user']))
237
		foreach ($config['system']['user'] as & $user)
238
			if ($user['uid'] == $uid)
239
				return $user;
240

    
241
	return false;
242
}
243

    
244
function & getGroupEntry($name) {
245
	global $debug, $config, $groupindex;
246
	if (isset($groupindex[$name]))
247
		return $config['system']['group'][$groupindex[$name]];
248
}
249

    
250
function & getGroupEntryByGID($gid) {
251
	global $debug, $config;
252

    
253
	if (is_array($config['system']['group']))
254
		foreach ($config['system']['group'] as & $group)
255
			if ($group['gid'] == $gid)
256
				return $group;
257

    
258
	return false;
259
}
260

    
261
function get_user_privileges(& $user) {
262

    
263
        $privs = $user['priv'];
264
        if (!is_array($privs))
265
                $privs = array();
266

    
267
        $names = local_user_get_groups($user, true);
268

    
269
        foreach ($names as $name) {
270
                $group = getGroupEntry($name);
271
                if (is_array($group['priv']))
272
                        $privs = array_merge( $privs, $group['priv']);
273
        }
274

    
275
        return $privs;
276
}
277

    
278
function userHasPrivilege($userent, $privid = false) {
279

    
280
        if (!$privid || !is_array($userent))
281
                return false;
282

    
283
        $privs = get_user_privileges($userent);
284

    
285
        if (!is_array($privs))
286
                return false;
287

    
288
        if (!in_array($privid, $privs))
289
                return false;
290

    
291
        return true;
292
}
293

    
294
function local_backed($username, $passwd) {
295

    
296
	$user = getUserEntry($username);
297
	if (!$user)
298
		return false;
299

    
300
	if (is_account_disabled($username) || is_account_expired($username))
301
		return false;
302

    
303
	if ($user['password'])
304
	{
305
		if (crypt($passwd, $user['password']) == $user['password'])
306
			return true;
307
	}
308

    
309
	if ($user['md5-hash'])
310
	{
311
		if (md5($passwd) == $user['md5-hash'])
312
			return true;
313
	}
314

    
315
	return false;
316
}
317

    
318
function local_sync_accounts() {
319
	global $debug, $config;
320
	conf_mount_rw();
321

    
322
	/* remove local users to avoid uid conflicts */
323
	$fd = popen("/usr/sbin/pw usershow -a", "r");
324
	if ($fd) {
325
		while (!feof($fd)) {
326
			$line = explode(":",fgets($fd));
327
			if (((!strncmp($line[0], "_", 1)) || ($line[2] < 2000) || ($line[2] > 65000)) && ($line[0] != "admin"))
328
				continue;
329
			/*
330
			 * If a crontab was created to user, pw userdel will be interactive and
331
			 * can cause issues. Just remove crontab before run it when necessary
332
			 */
333
			unlink_if_exists("/var/cron/tabs/{$line[0]}");
334
			$cmd = "/usr/sbin/pw userdel -n '{$line[0]}'";
335
			if($debug)
336
				log_error(sprintf(gettext("Running: %s"), $cmd));
337
			mwexec($cmd);
338
		}
339
		pclose($fd);
340
	}
341

    
342
	/* remove local groups to avoid gid conflicts */
343
	$gids = array();
344
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
345
	if ($fd) {
346
		while (!feof($fd)) {
347
			$line = explode(":",fgets($fd));
348
			if (!strncmp($line[0], "_", 1))
349
				continue;
350
			if ($line[2] < 2000)
351
				continue;
352
			if ($line[2] > 65000)
353
				continue;
354
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
355
			if($debug)
356
				log_error(sprintf(gettext("Running: %s"), $cmd));
357
			mwexec($cmd);
358
		}
359
		pclose($fd);
360
	}
361

    
362
	/* make sure the all group exists */
363
	$allgrp = getGroupEntryByGID(1998);
364
	local_group_set($allgrp, true);
365

    
366
	/* sync all local users */
367
	if (is_array($config['system']['user']))
368
		foreach ($config['system']['user'] as $user)
369
			local_user_set($user);
370

    
371
	/* sync all local groups */
372
	if (is_array($config['system']['group']))
373
		foreach ($config['system']['group'] as $group)
374
			local_group_set($group);
375

    
376
	conf_mount_ro();
377

    
378
}
379

    
380
function local_user_set(& $user) {
381
	global $g, $debug;
382

    
383
	if (empty($user['password'])) {
384
		log_error("There is something wrong in your config because user {$user['name']} password is missing!");
385
		return;
386
	}
387

    
388
	conf_mount_rw();
389

    
390
	$home_base = "/home/";	
391
	$user_uid = $user['uid'];
392
	$user_name = $user['name'];
393
	$user_home = "{$home_base}{$user_name}";
394
	$user_shell = "/etc/rc.initial";
395
	$user_group = "nobody";
396

    
397
	// Ensure $home_base exists and is writable
398
	if (!is_dir($home_base)) 
399
		mkdir($home_base, 0755);
400

    
401
	$lock_account = false;
402
	/* configure shell type */
403
	/* Cases here should be ordered by most privileged to least privileged. */
404
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
405
		$user_shell = "/bin/tcsh";
406
	} elseif (userHasPrivilege($user, "user-copy-files")) {
407
		$user_shell = "/usr/local/bin/scponly";
408
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
409
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
410
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
411
		$user_shell = "/sbin/nologin";
412
	} else {
413
		$user_shell = "/sbin/nologin";
414
		$lock_account = true;
415
	}
416

    
417
	/* Lock out disabled or expired users, unless it's root/admin. */
418
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
419
		$user_shell = "/sbin/nologin";
420
		$lock_account = true;
421
	}
422

    
423
	/* root user special handling */
424
	if ($user_uid == 0) {
425
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
426
		if($debug)
427
			log_error(sprintf(gettext("Running: %s"), $cmd));
428
		$fd = popen($cmd, "w");
429
		fwrite($fd, $user['password']);
430
		pclose($fd);
431
		$user_group = "wheel";
432
		$user_home = "/root";
433
		$user_shell = "/etc/rc.initial";
434
	}
435

    
436
	/* read from pw db */
437
	$fd = popen("/usr/sbin/pw usershow -n {$user_name} 2>&1", "r");
438
	$pwread = fgets($fd);
439
	pclose($fd);
440
	$userattrs = explode(":", trim($pwread));
441

    
442
	/* determine add or mod */
443
	if (($userattrs[0] != $user['name']) || (!strncmp($pwread, "pw:", 3))) {
444
		$user_op = "useradd -m -k /etc/skel -o";
445
	} else {
446
		$user_op = "usermod";
447
	}
448

    
449
	$comment = str_replace(array(":", "!", "@"), " ", $user['descr']); 
450
	/* add or mod pw db */
451
	$cmd = "/usr/sbin/pw {$user_op} -q -u {$user_uid} -n {$user_name}".
452
			" -g {$user_group} -s {$user_shell} -d {$user_home}".
453
			" -c ".escapeshellarg($comment)." -H 0 2>&1";
454

    
455
	if($debug)
456
		log_error(sprintf(gettext("Running: %s"), $cmd));
457
	$fd = popen($cmd, "w");
458
	fwrite($fd, $user['password']);
459
	pclose($fd);
460

    
461
	/* create user directory if required */
462
	if (!is_dir($user_home)) {
463
		mkdir($user_home, 0700);
464
		mwexec("/bin/cp /root/.* {$home_base}/", true);
465
	}
466
	@chown($user_home, $user_name);
467
	@chgrp($user_home, $user_group);
468

    
469
	/* write out ssh authorized key file */
470
	if($user['authorizedkeys']) {
471
		if (!is_dir("{$user_home}/.ssh")) {
472
			@mkdir("{$user_home}/.ssh", 0700);
473
			@chown("{$user_home}/.ssh", $user_name);
474
		}
475
		$keys = base64_decode($user['authorizedkeys']);
476
		@file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
477
		@chown("{$user_home}/.ssh/authorized_keys", $user_name);
478
	} else
479
		unlink_if_exists("{$user_home}/.ssh/authorized_keys");
480

    
481
	$un = $lock_account ? "" : "un";
482
	exec("/usr/sbin/pw {$un}lock {$user_name} -q");
483
	
484
	conf_mount_ro();
485
}
486

    
487
function local_user_del($user) {
488
	global $debug;
489

    
490
	/* remove all memberships */
491
	local_user_set_groups($user);
492

    
493
	/* Don't remove /root */
494
	if ($user['uid'] != 0)
495
		$rmhome = "-r";
496

    
497
	/* read from pw db */
498
	$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
499
	$pwread = fgets($fd);
500
	pclose($fd);
501
	$userattrs = explode(":", trim($pwread));
502

    
503
	if ($userattrs[0] != $user['name']) {
504
		log_error("Tried to remove user {$user['name']} but got user {$userattrs[0]} instead. Bailing.");
505
		return;
506
	}
507

    
508
	/* delete from pw db */
509
	$cmd = "/usr/sbin/pw userdel -n {$user['name']} {$rmhome}";
510

    
511
	if($debug)
512
		log_error(sprintf(gettext("Running: %s"), $cmd));
513
	mwexec($cmd);
514

    
515
	/* Delete user from groups needs a call to write_config() */
516
	local_group_del_user($user);
517
}
518

    
519
function local_user_set_password(& $user, $password) {
520

    
521
	$user['password'] = crypt($password);
522
	$user['md5-hash'] = md5($password);
523

    
524
	// Converts ascii to unicode.
525
	$astr = (string) $password;
526
	$ustr = '';
527
	for ($i = 0; $i < strlen($astr); $i++) {
528
		$a = ord($astr{$i}) << 8;
529
		$ustr.= sprintf("%X", $a);
530
	}
531

    
532
	// Generate the NT-HASH from the unicode string
533
       $user['nt-hash'] = bin2hex(hash("md4", $ustr));
534
}
535

    
536
function local_user_get_groups($user, $all = false) {
537
	global $debug, $config;
538

    
539
	$groups = array();
540
	if (!is_array($config['system']['group']))
541
		return $groups;
542

    
543
	foreach ($config['system']['group'] as $group)
544
		if ( $all || ( !$all && ($group['name'] != "all")))
545
			if (is_array($group['member']))
546
				if (in_array($user['uid'], $group['member']))
547
					$groups[] = $group['name'];
548

    
549
	if ( $all )
550
		$groups[] = "all";
551

    
552
	sort($groups);
553

    
554
	return $groups;
555
	
556
}
557

    
558
function local_user_set_groups($user, $new_groups = NULL ) {
559
	global $debug, $config, $groupindex;
560

    
561
	if (!is_array($config['system']['group']))
562
		return;
563

    
564
	$cur_groups = local_user_get_groups($user, true);
565
	$mod_groups = array();
566

    
567
	if (!is_array($new_groups))
568
		$new_groups = array();
569

    
570
	if (!is_array($cur_groups))
571
		$cur_groups = array();
572

    
573
	/* determine which memberships to add */
574
	foreach ($new_groups as $groupname) {
575
		if ($groupname == '' || in_array($groupname,$cur_groups))
576
			continue;
577
		$group = & $config['system']['group'][$groupindex[$groupname]];
578
		$group['member'][] = $user['uid'];
579
		$mod_groups[] = $group;
580
	}
581
	unset($group);
582

    
583
	/* determine which memberships to remove */
584
	foreach ($cur_groups as $groupname) {
585
		if (in_array($groupname,$new_groups))
586
			continue;
587
		if (!isset($config['system']['group'][$groupindex[$groupname]]))
588
			continue;
589
		$group = & $config['system']['group'][$groupindex[$groupname]];
590
		if (is_array($group['member'])) {
591
			$index = array_search($user['uid'], $group['member']);
592
			array_splice($group['member'], $index, 1);
593
			$mod_groups[] = $group;
594
		}
595
	}
596
	unset($group);
597

    
598
	/* sync all modified groups */
599
	foreach ($mod_groups as $group)
600
		local_group_set($group);
601
}
602

    
603
function local_group_del_user($user) {
604
	global $config;
605

    
606
	if (!is_array($config['system']['group']))
607
                return;
608

    
609
        foreach ($config['system']['group'] as $group) {
610
		if (is_array($group['member'])) {
611
			foreach ($group['member'] as $idx => $uid) {
612
				if ($user['uid'] == $uid)
613
					unset($config['system']['group']['member'][$idx]);
614
			}
615
		}
616
	}
617
}
618

    
619
function local_group_set($group, $reset = false) {
620
	global $debug;
621

    
622
	$group_name = $group['name'];
623
	$group_gid = $group['gid'];
624
	$group_members = '';
625
	if (!$reset && !empty($group['member']) && count($group['member']) > 0)
626
		$group_members = implode(",",$group['member']);
627

    
628
	if (empty($group_name))
629
		return;
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
		log_error(sprintf(gettext("Running: %s"), $cmd));
647
	mwexec($cmd);
648

    
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
		log_error(sprintf(gettext("Running: %s"), $cmd));
659
	mwexec($cmd);
660
}
661

    
662
function ldap_test_connection($authcfg) {
663
	global $debug, $config, $g;
664

    
665
	if ($authcfg) {
666
                if (strstr($authcfg['ldap_urltype'], "Standard"))
667
                        $ldapproto = "ldap";
668
                else
669
                        $ldapproto = "ldaps";
670
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
671
                $ldapport           = $authcfg['ldap_port'];
672
		if (!empty($ldapport))
673
			$ldapserver .= ":{$ldapport}";
674
                $ldapbasedn         = $authcfg['ldap_basedn'];
675
                $ldapbindun         = $authcfg['ldap_binddn'];
676
                $ldapbindpw         = $authcfg['ldap_bindpw'];
677
        } else
678
		return false;
679

    
680
        /* first check if there is even an LDAP server populated */
681
        if(!$ldapserver)
682
                return false;
683

    
684
        /* Setup CA environment if needed. */
685
        ldap_setup_caenv($authcfg);
686

    
687
        /* connect and see if server is up */
688
        $error = false;
689
	if (!($ldap = ldap_connect($ldapserver)))
690
		$error = true;
691

    
692
        if ($error == true) {
693
                log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
694
                return false;
695
        }
696

    
697
	return true;
698
}
699

    
700
function ldap_setup_caenv($authcfg) {
701
	global $g;
702
	require_once("certs.inc");
703

    
704
	unset($caref);
705
	if (empty($authcfg['ldap_caref']) || !strstr($authcfg['ldap_urltype'], "SSL")) {
706
		putenv('LDAPTLS_REQCERT=never');
707
		return;
708
	} else {
709
		$caref = lookup_ca($authcfg['ldap_caref']);
710
		if (!$caref) {
711
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
712
			/* 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
		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
		putenv('LDAPTLS_REQCERT=hard');
723
		/* XXX: Probably even the hashed link should be created for this? */
724
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
725
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
726
	}
727
}
728

    
729
function ldap_test_bind($authcfg) {
730
	global $debug, $config, $g;
731

    
732
	if ($authcfg) {
733
                if (strstr($authcfg['ldap_urltype'], "Standard"))
734
                        $ldapproto = "ldap";
735
                else
736
                        $ldapproto = "ldaps";
737
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
738
                $ldapport           = $authcfg['ldap_port'];
739
		if (!empty($ldapport))
740
			$ldapserver .= ":{$ldapport}";
741
                $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
	} else
750
		return false;
751

    
752
	/* first check if there is even an LDAP server populated */
753
        if(!$ldapserver)
754
                return false;
755

    
756
	/* Setup CA environment if needed. */
757
	ldap_setup_caenv($authcfg);
758

    
759
        /* connect and see if server is up */
760
        $error = false;
761
	if (!($ldap = ldap_connect($ldapserver)))
762
		$error = true;
763

    
764
        if ($error == true) {
765
                log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
766
                return false;
767
        }
768

    
769
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
770
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
771
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
772
 
773
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
774
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
775
	if ($ldapanon == true) {
776
		if (!($res = @ldap_bind($ldap))) {
777
			@ldap_close($ldap);
778
			return false;
779
		}
780
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
781
		@ldap_close($ldap);
782
		return false;
783
	}
784

    
785
	@ldap_unbind($ldap);
786

    
787
	return true;
788
}
789

    
790
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
791
	global $debug, $config, $g;
792

    
793
	if(!function_exists("ldap_connect"))
794
		return;
795

    
796
	$ous = array();
797

    
798
	if ($authcfg) {
799
                if (strstr($authcfg['ldap_urltype'], "Standard"))
800
                        $ldapproto = "ldap";
801
                else
802
                        $ldapproto = "ldaps";
803
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
804
                $ldapport           = $authcfg['ldap_port'];
805
		if (!empty($ldapport))
806
			$ldapserver .= ":{$ldapport}";
807
                $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
        } else
819
		return false;
820

    
821
        /* first check if there is even an LDAP server populated */
822
        if(!$ldapserver) {
823
                log_error(gettext("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined."));
824
                return $ous;
825
        }
826

    
827
	/* Setup CA environment if needed. */
828
	ldap_setup_caenv($authcfg);
829

    
830
	/* connect and see if server is up */
831
        $error = false;
832
	if (!($ldap = ldap_connect($ldapserver)))
833
		$error = true;
834

    
835
        if ($error == true) {
836
        log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
837
                return $ous;
838
        }
839

    
840
	$ldapfilter = "(|(ou=*)(cn=Users))";
841

    
842
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
843
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
844
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
845

    
846
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
847
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
848
	if ($ldapanon == true) {
849
                if (!($res = @ldap_bind($ldap))) {
850
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind anonymously to server %s."), $ldapname));
851
			@ldap_close($ldap);
852
                        return $ous;
853
		}
854
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
855
		log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind to server %s."), $ldapname));
856
		@ldap_close($ldap);
857
		return $ous;
858
	}
859

    
860
	if ($ldapscope == "one")
861
		$ldapfunc = "ldap_list";
862
	else
863
		$ldapfunc = "ldap_search";
864

    
865
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
866
	$info = @ldap_get_entries($ldap, $search);
867

    
868
	if (is_array($info)) {
869
		foreach ($info as $inf) {
870
			if (!$show_complete_ou) {
871
				$inf_split = explode(",", $inf['dn']);
872
				$ou = $inf_split[0];
873
				$ou = str_replace("OU=","", $ou);
874
				$ou = str_replace("CN=","", $ou);
875
			} else
876
				if($inf['dn'])
877
					$ou = $inf['dn'];
878
			if($ou)
879
				$ous[] = $ou;
880
		}
881
	}
882

    
883
	@ldap_unbind($ldap);
884

    
885
	return $ous;
886
}
887

    
888
function ldap_get_groups($username, $authcfg) {
889
	global $debug, $config;
890
	
891
	if(!function_exists("ldap_connect"))
892
		return;
893
	
894
	if(!$username) 
895
		return false;
896

    
897
	if(!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
898
		$username_split = explode("@", $username);
899
		$username = $username_split[0];		
900
	}
901

    
902
	if(stristr($username, "\\")) {
903
		$username_split = explode("\\", $username);
904
		$username = $username_split[0];        
905
	}    
906
	
907
	//log_error("Getting LDAP groups for {$username}.");
908
        if ($authcfg) {
909
                if (strstr($authcfg['ldap_urltype'], "Standard"))
910
                        $ldapproto = "ldap";
911
                else
912
                        $ldapproto = "ldaps";
913
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
914
                $ldapport           = $authcfg['ldap_port'];
915
		if (!empty($ldapport))
916
			$ldapserver .= ":{$ldapport}";
917
                $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
	} else
934
		return false;
935

    
936
	$ldapdn             = $_SESSION['ldapdn'];
937

    
938
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
939
	$ldapgroupattribute = strtolower($ldapgroupattribute);
940
	$memberof = array();
941

    
942
        /* Setup CA environment if needed. */
943
        ldap_setup_caenv($authcfg);
944

    
945
	/* connect and see if server is up */
946
	$error = false;
947
	if (!($ldap = ldap_connect($ldapserver)))
948
		$error = true;
949

    
950
	if ($error == true) {
951
		log_error(sprintf(gettext("ERROR! ldap_get_groups() Could not connect to server %s."), $ldapname));
952
                return memberof;
953
        }
954
    
955
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
956
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
957
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
958

    
959
	/* bind as user that has rights to read group attributes */
960
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
961
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
962
	if ($ldapanon == true) {
963
                if (!($res = @ldap_bind($ldap))) {
964
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
965
			@ldap_close($ldap);
966
                        return false;
967
		}
968
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
969
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
970
		@ldap_close($ldap);
971
		return memberof;
972
	}
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
	if ($ldapscope == "one")
979
                $ldapfunc = "ldap_list";
980
        else
981
                $ldapfunc = "ldap_search";
982

    
983
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
984
	$info      = @ldap_get_entries($ldap, $search);
985

    
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
				$membersplit = explode(",", $member);
993
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
994
			}
995
		}
996
	}
997
	
998
	/* Time to close LDAP connection */
999
	@ldap_unbind($ldap);
1000
	
1001
	$groups = print_r($memberof,true);
1002
	
1003
	//log_error("Returning groups ".$groups." for user $username");
1004
	
1005
	return $memberof;
1006
}
1007

    
1008
function ldap_format_host($host) {
1009
	return is_ipaddrv6($host) ? "[$host]" : $host ;
1010
}
1011

    
1012
function ldap_backed($username, $passwd, $authcfg) {
1013
	global $debug, $config;
1014
	
1015
	if(!$username) 
1016
		return;
1017

    
1018
	if(!function_exists("ldap_connect"))
1019
		return;
1020

    
1021
	if(!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1022
		$username_split = explode("@", $username);
1023
		$username = $username_split[0];        
1024
	}
1025
	if(stristr($username, "\\")) {
1026
		$username_split = explode("\\", $username);
1027
		$username = $username_split[0];        
1028
	}
1029

    
1030
	if ($authcfg) {
1031
		if (strstr($authcfg['ldap_urltype'], "Standard"))
1032
			$ldapproto = "ldap";
1033
		else
1034
			$ldapproto = "ldaps";
1035
		$ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1036
		$ldapport	    = $authcfg['ldap_port'];
1037
		if (!empty($ldapport))
1038
			$ldapserver .= ":{$ldapport}";
1039
                $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
                $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
                $ldaptype           = "";
1061
                $ldapver            = $authcfg['ldap_protver'];
1062
		$ldapname	    = $authcfg['name'];
1063
		$ldapscope	    = $authcfg['ldap_scope'];
1064
	} else
1065
		return false;
1066

    
1067
	/* first check if there is even an LDAP server populated */ 
1068
	if(!$ldapserver) {
1069
		if ($ldapfallback) {
1070
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager."));
1071
			return local_backed($username, $passwd);
1072
		} else
1073
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined."));
1074

    
1075
		return false;
1076
	}
1077
	
1078
        /* Setup CA environment if needed. */
1079
        ldap_setup_caenv($authcfg);
1080

    
1081
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1082
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1083
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1084

    
1085
	/* Make sure we can connect to LDAP */
1086
	$error = false;
1087
	if (!($ldap = ldap_connect($ldapserver)))
1088
		$error = true;
1089

    
1090
	if ($error == true) {
1091
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1092
		return false;
1093
	}
1094

    
1095
	/* ok, its up.  now, lets bind as the bind user so we can search it */
1096
	$error = false;
1097
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1098
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1099
	if ($ldapanon == true) {
1100
                if (!($res = @ldap_bind($ldap)))
1101
                        $error = true;
1102
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
1103
		$error = true;
1104

    
1105
	if ($error == true) {
1106
		@ldap_close($ldap);
1107
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1108
		return false;
1109
	}
1110
	
1111
	/* Get LDAP Authcontainers and split em up. */
1112
	$ldac_splits = explode(";", $ldapauthcont);
1113
	
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
	if ($debug)
1125
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1126
	/* Iterate through the user containers for search */
1127
	foreach ($ldac_splits as $i => $ldac_split) {
1128
		$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
		/* Make sure we just use the first user we find */
1132
		if ($debug)
1133
			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
		if ($ldapscope == "one")
1135
			$ldapfunc = "ldap_list";
1136
		else
1137
			$ldapfunc = "ldap_search";
1138
		/* Support legacy auth container specification. */
1139
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn))
1140
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
1141
		else
1142
			$search  = @$ldapfunc($ldap,$ldapsearchbasedn,$ldapfilter);
1143
		if (!$search) {
1144
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1145
			continue;
1146
		}
1147
		$info	 = ldap_get_entries($ldap,$search);
1148
		$matches = $info['count'];
1149
		if ($matches == 1){
1150
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1151
			$_SESSION['ldapou'] = $ldac_split[$i];
1152
			$_SESSION['ldapon'] = "true";
1153
			$usercount = 1;
1154
			break;
1155
		}
1156
	}
1157

    
1158
	if ($usercount != 1){
1159
		@ldap_unbind($ldap);
1160
		log_error(gettext("ERROR! Either LDAP search failed, or multiple users were found."));
1161
		return false;                         
1162
	}
1163

    
1164
	/* Now lets bind as the user we found */
1165
	$passwd = isset($authcfg['ldap_utf8']) ? utf8_encode($passwd) : $passwd;
1166
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
1167
		log_error(sprintf(gettext('ERROR! Could not login to server %1$s as user %2$s: %3$s'), $ldapname, $username, ldap_error($ldap)));
1168
		@ldap_unbind($ldap);
1169
		return false;
1170
	}
1171

    
1172
	if ($debug) {
1173
		$userdn = isset($authcfg['ldap_utf8']) ? utf8_decode($userdn) : $userdn;
1174
		log_auth(sprintf(gettext('Logged in successfully as %1$s via LDAP server %2$s with DN = %3$s.'), $username, $ldapname, $userdn));
1175
	}
1176

    
1177
	/* At this point we are bound to LDAP so the user was auth'd okay. Close connection. */
1178
	@ldap_unbind($ldap);
1179

    
1180
	return true;
1181
}
1182

    
1183
function radius_backed($username, $passwd, $authcfg, &$attributes = array()) {
1184
	global $debug, $config;
1185
	$ret = false;
1186

    
1187
	require_once("radius.inc");
1188

    
1189
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1190
	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
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1196
	} else
1197
		return false;
1198

    
1199
	/* Add a new servers to our instance */
1200
	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

    
1205
	if (PEAR::isError($rauth->start())) {
1206
		$retvalue['auth_val'] = 1;
1207
		$retvalue['error'] = $rauth->getError();
1208
		if ($debug)
1209
			printf(gettext("Radius start: %s<br />\n"), $retvalue['error']);
1210
	}
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
			printf(gettext("Radius send failed: %s<br />\n"), $retvalue['error']);
1221
	} else if ($result === true) {
1222
		if ($rauth->getAttributes())
1223
			$attributes = $rauth->listAttributes();
1224
		$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
function get_user_expiration_date($username) {
1241
	$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
	}
1252

    
1253
	return false;
1254
}
1255

    
1256
function is_account_disabled($username) {
1257
	$user = getUserEntry($username);
1258
	if (isset($user['disabled']))
1259
		return true;
1260

    
1261
	return false;
1262
}
1263

    
1264
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
	if ($name == "Local Database")
1274
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1275
}
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
	$list["Local Database"] = array( "name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1290
	return $list;
1291
}
1292

    
1293
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
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1321

    
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
                if (radius_backed($username, $password, $authcfg, $attributes))
1334
                        $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
function session_auth() {
1347
	global $config, $_SESSION, $page;
1348

    
1349
	// Handle HTTPS httponly and secure flags
1350
	$currentCookieParams = session_get_cookie_params();
1351
	session_set_cookie_params(
1352
		$currentCookieParams["lifetime"],
1353
		$currentCookieParams["path"],
1354
		NULL,
1355
		($config['system']['webgui']['protocol'] == "https"),
1356
		true
1357
	);
1358

    
1359
	if (!session_id())
1360
		session_start();
1361

    
1362
	// Detect protocol change
1363
	if (!isset($_POST['login']) && !empty($_SESSION['Logged_In']) && $_SESSION['protocol'] != $config['system']['webgui']['protocol'])
1364
		return false;
1365

    
1366
	/* Validate incoming login request */
1367
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1368
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1369
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1370
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1371
			// Generate a new id to avoid session fixation
1372
			session_regenerate_id();
1373
			$_SESSION['Logged_In'] = "True";
1374
			$_SESSION['Username'] = $_POST['usernamefld'];
1375
			$_SESSION['last_access'] = time();
1376
			$_SESSION['protocol'] = $config['system']['webgui']['protocol'];
1377
			if(! isset($config['system']['webgui']['quietlogin'])) {
1378
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1379
			}
1380
			if (isset($_POST['postafterlogin']))
1381
				return true;
1382
			else {
1383
				if (empty($page))
1384
					$page = "/";
1385
				header("Location: {$page}");
1386
			}
1387
			exit;
1388
		} else {
1389
			/* give the user an error message */
1390
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1391
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1392
			if(isAjax()) {
1393
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1394
				return;
1395
			}
1396
		}
1397
	}
1398

    
1399
	/* Show login page if they aren't logged in */
1400
	if (empty($_SESSION['Logged_In']))
1401
		return false;
1402

    
1403
	/* If session timeout isn't set, we don't mark sessions stale */
1404
	if (!isset($config['system']['webgui']['session_timeout'])) {
1405
		/* Default to 4 hour timeout if one is not set */
1406
		if ($_SESSION['last_access'] < (time() - 14400)) {
1407
			$_GET['logout'] = true;
1408
			$_SESSION['Logout'] = true;
1409
		} else
1410
			$_SESSION['last_access'] = time();	
1411
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1412
		/* only update if it wasn't ajax */
1413
		if (!isAjax())
1414
			$_SESSION['last_access'] = time();
1415
	} else {
1416
		/* Check for stale session */
1417
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1418
			$_GET['logout'] = true;
1419
			$_SESSION['Logout'] = true;
1420
		} else {
1421
			/* only update if it wasn't ajax */
1422
			if (!isAjax())
1423
				$_SESSION['last_access'] = time();
1424
		}
1425
	}
1426

    
1427
	/* user hit the logout button */
1428
	if (isset($_GET['logout'])) {
1429

    
1430
		if ($_SESSION['Logout'])
1431
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1432
		else
1433
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1434

    
1435
		/* wipe out $_SESSION */
1436
		$_SESSION = array();
1437

    
1438
		if (isset($_COOKIE[session_name()]))
1439
			setcookie(session_name(), '', time()-42000, '/');
1440

    
1441
		/* and destroy it */
1442
		session_destroy();
1443

    
1444
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1445
		$scriptElms = count($scriptName);
1446
		$scriptName = $scriptName[$scriptElms-1];
1447

    
1448
		if (isAjax())
1449
			return false;
1450

    
1451
		/* redirect to page the user is on, it'll prompt them to login again */
1452
		header("Location: {$scriptName}");
1453

    
1454
		return false;
1455
	}
1456

    
1457
	/*
1458
	 * this is for debugging purpose if you do not want to use Ajax
1459
	 * to submit a HTML form. It basically diables the observation
1460
	 * of the submit event and hence does not trigger Ajax.
1461
	 */
1462
	if ($_GET['disable_ajax'])
1463
		$_SESSION['NO_AJAX'] = "True";
1464

    
1465
	/*
1466
	 * Same to re-enable Ajax.
1467
	 */
1468
	if ($_GET['enable_ajax'])
1469
		unset($_SESSION['NO_AJAX']);
1470

    
1471
	return true;
1472
}
1473

    
1474
?>
(5-5/68)