Projet

Général

Profil

Télécharger (44,8 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / auth.inc @ 6f3d2063

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
		DISABLE_PHP_LINT_CHECKING
41
		pfSense_BUILDER_BINARIES:	/usr/sbin/pw	/bin/cp
42
		pfSense_MODULE:	auth
43
*/
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
if(!$do_not_include_config_gui_inc)
50
	require_once("config.gui.inc");
51

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

    
55
/* 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
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
58
	/* DNS ReBinding attack prevention.  https://redmine.pfsense.org/issues/708 */
59
	$found_host = false;
60

    
61
	/* 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
		/* 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
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
70
		}
71
	} else {
72
		$http_host = explode(":", $_SERVER['HTTP_HOST']);
73
		$http_host = $http_host[0];
74
	}
75
	if(is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
76
			strcasecmp($http_host, "localhost") == 0 or $_SERVER['SERVER_ADDR'] == "::1")
77
		$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
		$found_host = true;
81

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

    
89
	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
	if(!empty($config['system']['webgui']['althostnames']) && !$found_host) {
97
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
98
		foreach ($althosts as $ah)
99
			if(strcasecmp($ah, $http_host) == 0 or strcasecmp($ah, $_SERVER['SERVER_ADDR']) == 0) {
100
				$found_host = true;
101
				break;
102
			}
103
	}
104

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

    
114
// 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
		$referrer_host = str_replace(array("[", "]"), "", $referrer_host);
129
		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

    
134
			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

    
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
			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
				$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
				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
			}
178
		}
179
		if($found_host == false) {
180
			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
				exit;
183
			}
184
			$security_passed = false;
185
		}
186
	} else
187
		$security_passed = false;
188
}
189

    
190
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
$groupindex = index_groups();
196
$userindex = index_users();
197

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

    
201
	$groupindex = array();
202

    
203
	if (is_array($config['system']['group'])) {
204
		$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
	if (is_array($config['system']['user'])) {
218
		$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

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

    
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

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

    
259
	return false;
260
}
261

    
262
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
function local_backed($username, $passwd) {
296

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

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

    
304
	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
			if (((!strncmp($line[0], "_", 1)) || ($line[2] < 2000) || ($line[2] > 65000)) && ($line[0] != "admin"))
331
				continue;
332
			/*
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
			$cmd = "/usr/sbin/pw userdel -n '{$line[0]}'";
338
			if($debug)
339
				log_error(sprintf(gettext("Running: %s"), $cmd));
340
			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
				log_error(sprintf(gettext("Running: %s"), $cmd));
360
			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
	/* 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
	/* 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
	conf_mount_ro();
380

    
381
}
382

    
383
function local_user_set(& $user) {
384
	global $g, $debug;
385

    
386
	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
	conf_mount_rw();
392

    
393
	$home_base = "/home/";	
394
	$user_uid = $user['uid'];
395
	$user_name = $user['name'];
396
	$user_home = "{$home_base}{$user_name}";
397
	$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
	$lock_account = false;
405
	/* configure shell type */
406
	/* Cases here should be ordered by most privileged to least privileged. */
407
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
408
		$user_shell = "/bin/tcsh";
409
	} elseif (userHasPrivilege($user, "user-copy-files")) {
410
		$user_shell = "/usr/local/bin/scponly";
411
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
412
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
413
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
414
		$user_shell = "/sbin/nologin";
415
	} else {
416
		$user_shell = "/sbin/nologin";
417
		$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
	}
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
			log_error(sprintf(gettext("Running: %s"), $cmd));
431
		$fd = popen($cmd, "w");
432
		fwrite($fd, $user['password']);
433
		pclose($fd);
434
		$user_group = "wheel";
435
		$user_home = "/root";
436
		$user_shell = "/etc/rc.initial";
437
	}
438

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

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

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

    
458
	if($debug)
459
		log_error(sprintf(gettext("Running: %s"), $cmd));
460
	$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
		mwexec("/bin/cp /root/.* {$home_base}/", true);
468
	}
469
	@chown($user_home, $user_name);
470
	@chgrp($user_home, $user_group);
471

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

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

    
490
function local_user_del($user) {
491
	global $debug;
492

    
493
	/* remove all memberships */
494
	local_user_set_groups($user);
495

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

    
500
	/* 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
	/* delete from pw db */
512
	$cmd = "/usr/sbin/pw userdel -n {$user['name']} {$rmhome}";
513

    
514
	if($debug)
515
		log_error(sprintf(gettext("Running: %s"), $cmd));
516
	mwexec($cmd);
517

    
518
	/* Delete user from groups needs a call to write_config() */
519
	local_group_del_user($user);
520
}
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
       $user['nt-hash'] = bin2hex(hash("md4", $ustr));
537
}
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
	if ( $all )
553
		$groups[] = "all";
554

    
555
	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
	$cur_groups = local_user_get_groups($user, true);
568
	$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
	unset($group);
585

    
586
	/* determine which memberships to remove */
587
	foreach ($cur_groups as $groupname) {
588
		if (in_array($groupname,$new_groups))
589
			continue;
590
		if (!isset($config['system']['group'][$groupindex[$groupname]]))
591
			continue;
592
		$group = & $config['system']['group'][$groupindex[$groupname]];
593
		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
	}
599
	unset($group);
600

    
601
	/* sync all modified groups */
602
	foreach ($mod_groups as $group)
603
		local_group_set($group);
604
}
605

    
606
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
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
	if (!$reset && !empty($group['member']) && count($group['member']) > 0)
629
		$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
		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
	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
	if (!session_id())
1362
		session_start();
1363

    
1364
	/* Validate incoming login request */
1365
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1366
		$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
			if(! isset($config['system']['webgui']['quietlogin'])) {
1373
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1374
			}
1375
			if (isset($_POST['postafterlogin']))
1376
				return true;
1377
			else {
1378
				if (empty($page))
1379
					$page = "/";
1380
				header("Location: {$page}");
1381
			}
1382
			exit;
1383
		} else {
1384
			/* give the user an error message */
1385
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1386
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1387
			if(isAjax()) {
1388
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1389
				return;
1390
			}
1391
		}
1392
	}
1393

    
1394
	/* Show login page if they aren't logged in */
1395
	if (empty($_SESSION['Logged_In']))
1396
		return false;
1397

    
1398
	/* If session timeout isn't set, we don't mark sessions stale */
1399
	if (!isset($config['system']['webgui']['session_timeout'])) {
1400
		/* 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
		} else
1405
			$_SESSION['last_access'] = time();	
1406
	} 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
	} else {
1411
		/* 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
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1427
		else
1428
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1429

    
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
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1440
		$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
		header("Location: {$scriptName}");
1448

    
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
	if ($_GET['disable_ajax'])
1458
		$_SESSION['NO_AJAX'] = "True";
1459

    
1460
	/*
1461
	 * Same to re-enable Ajax.
1462
	 */
1463
	if ($_GET['enable_ajax'])
1464
		unset($_SESSION['NO_AJAX']);
1465

    
1466
	return true;
1467
}
1468

    
1469
?>
(5-5/68)