Projet

Général

Profil

Télécharger (45,1 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / auth.inc @ 340ce958

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
		$passwd = crypt($passwd, $user['password']);
306
		if ($passwd == $user['password'])
307
			return true;
308
	}
309

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

    
317
	return false;
318
}
319

    
320
function local_sync_accounts() {
321
	global $debug, $config;
322
	conf_mount_rw();
323

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

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

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

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

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

    
378
	conf_mount_ro();
379

    
380
}
381

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

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

    
390
	conf_mount_rw();
391

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
521
function local_user_set_password(& $user, $password) {
522

    
523
	$user['password'] = crypt($password);
524
	$user['md5-hash'] = md5($password);
525

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

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

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

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

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

    
551
	if ( $all )
552
		$groups[] = "all";
553

    
554
	sort($groups);
555

    
556
	return $groups;
557
	
558
}
559

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

    
563
	if (!is_array($config['system']['group']))
564
		return;
565

    
566
	$cur_groups = local_user_get_groups($user, true);
567
	$mod_groups = array();
568

    
569
	if (!is_array($new_groups))
570
		$new_groups = array();
571

    
572
	if (!is_array($cur_groups))
573
		$cur_groups = array();
574

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

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

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

    
605
function local_group_del_user($user) {
606
	global $config;
607

    
608
	if (!is_array($config['system']['group']))
609
                return;
610

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

    
621
function local_group_set($group, $reset = false) {
622
	global $debug;
623

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

    
630
	if (empty($group_name))
631
		return;
632

    
633
	/* read from group db */
634
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
635
	$pwread = fgets($fd);
636
	pclose($fd);
637

    
638
	/* determine add or mod */
639
	if (!strncmp($pwread, "pw:", 3))
640
		$group_op = "groupadd";
641
	else
642
		$group_op = "groupmod";
643

    
644
	/* add or mod group db */
645
	$cmd = "/usr/sbin/pw {$group_op} {$group_name} -g {$group_gid} -M {$group_members} 2>&1";
646

    
647
	if($debug)
648
		log_error(sprintf(gettext("Running: %s"), $cmd));
649
	mwexec($cmd);
650

    
651
}
652

    
653
function local_group_del($group) {
654
	global $debug;
655

    
656
	/* delete from group db */
657
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
658

    
659
	if($debug)
660
		log_error(sprintf(gettext("Running: %s"), $cmd));
661
	mwexec($cmd);
662
}
663

    
664
function ldap_test_connection($authcfg) {
665
	global $debug, $config, $g;
666

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

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

    
686
        /* Setup CA environment if needed. */
687
        ldap_setup_caenv($authcfg);
688

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

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

    
699
	return true;
700
}
701

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

    
706
	unset($caref);
707
	if (empty($authcfg['ldap_caref']) || !strstr($authcfg['ldap_urltype'], "SSL")) {
708
		putenv('LDAPTLS_REQCERT=never');
709
		return;
710
	} else {
711
		$caref = lookup_ca($authcfg['ldap_caref']);
712
		if (!$caref) {
713
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
714
			/* XXX: Prevent for credential leaking since we cannot setup the CA env. Better way? */
715
			putenv('LDAPTLS_REQCERT=hard');
716
			return;
717
		}
718
		if (!is_dir("{$g['varrun_path']}/certs"))
719
			@mkdir("{$g['varrun_path']}/certs");
720
		if (file_exists("{$g['varrun_path']}/certs/{$caref['refid']}.ca"))
721
			@unlink("{$g['varrun_path']}/certs/{$caref['refid']}.ca");
722
		file_put_contents("{$g['varrun_path']}/certs/{$caref['refid']}.ca", base64_decode($caref['crt']));
723
		@chmod("{$g['varrun_path']}/certs/{$caref['refid']}.ca", 0600);
724
		putenv('LDAPTLS_REQCERT=hard');
725
		/* XXX: Probably even the hashed link should be created for this? */
726
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
727
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
728
	}
729
}
730

    
731
function ldap_test_bind($authcfg) {
732
	global $debug, $config, $g;
733

    
734
	if ($authcfg) {
735
                if (strstr($authcfg['ldap_urltype'], "Standard"))
736
                        $ldapproto = "ldap";
737
                else
738
                        $ldapproto = "ldaps";
739
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
740
                $ldapport           = $authcfg['ldap_port'];
741
		if (!empty($ldapport))
742
			$ldapserver .= ":{$ldapport}";
743
                $ldapbasedn         = $authcfg['ldap_basedn'];
744
                $ldapbindun         = $authcfg['ldap_binddn'];
745
                $ldapbindpw         = $authcfg['ldap_bindpw'];
746
                $ldapver            = $authcfg['ldap_protver'];
747
		if (empty($ldapbndun) || empty($ldapbindpw))
748
                        $ldapanon = true;
749
                else
750
                        $ldapanon = false;
751
	} else
752
		return false;
753

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

    
758
	/* Setup CA environment if needed. */
759
	ldap_setup_caenv($authcfg);
760

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

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

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

    
787
	@ldap_unbind($ldap);
788

    
789
	return true;
790
}
791

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

    
795
	if(!function_exists("ldap_connect"))
796
		return;
797

    
798
	$ous = array();
799

    
800
	if ($authcfg) {
801
                if (strstr($authcfg['ldap_urltype'], "Standard"))
802
                        $ldapproto = "ldap";
803
                else
804
                        $ldapproto = "ldaps";
805
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
806
                $ldapport           = $authcfg['ldap_port'];
807
		if (!empty($ldapport))
808
			$ldapserver .= ":{$ldapport}";
809
                $ldapbasedn         = $authcfg['ldap_basedn'];
810
                $ldapbindun         = $authcfg['ldap_binddn'];
811
                $ldapbindpw         = $authcfg['ldap_bindpw'];
812
                $ldapver            = $authcfg['ldap_protver'];
813
		if (empty($ldapbindun) || empty($ldapbindpw))
814
                        $ldapanon = true;
815
                else
816
                        $ldapanon = false;
817
                $ldapname           = $authcfg['name'];
818
                $ldapfallback       = false;
819
		$ldapscope          = $authcfg['ldap_scope'];
820
        } else
821
		return false;
822

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

    
829
	/* Setup CA environment if needed. */
830
	ldap_setup_caenv($authcfg);
831

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

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

    
842
	$ldapfilter = "(|(ou=*)(cn=Users))";
843

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

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

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

    
867
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
868
	$info = @ldap_get_entries($ldap, $search);
869

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

    
885
	@ldap_unbind($ldap);
886

    
887
	return $ous;
888
}
889

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

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

    
904
	if(stristr($username, "\\")) {
905
		$username_split = explode("\\", $username);
906
		$username = $username_split[0];        
907
	}    
908
	
909
	//log_error("Getting LDAP groups for {$username}.");
910
        if ($authcfg) {
911
                if (strstr($authcfg['ldap_urltype'], "Standard"))
912
                        $ldapproto = "ldap";
913
                else
914
                        $ldapproto = "ldaps";
915
                $ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
916
                $ldapport           = $authcfg['ldap_port'];
917
		if (!empty($ldapport))
918
			$ldapserver .= ":{$ldapport}";
919
                $ldapbasedn         = $authcfg['ldap_basedn'];
920
                $ldapbindun         = $authcfg['ldap_binddn'];
921
                $ldapbindpw         = $authcfg['ldap_bindpw'];
922
                $ldapauthcont       = $authcfg['ldap_authcn'];
923
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
924
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
925
                $ldapfilter         = "({$ldapnameattribute}={$username})";
926
                $ldaptype           = "";
927
                $ldapver            = $authcfg['ldap_protver'];
928
		if (empty($ldapbindun) || empty($ldapbindpw))
929
                        $ldapanon = true;
930
                else
931
                        $ldapanon = false;
932
                $ldapname           = $authcfg['name'];
933
                $ldapfallback       = false;
934
		$ldapscope          = $authcfg['ldap_scope'];
935
	} else
936
		return false;
937

    
938
	$ldapdn             = $_SESSION['ldapdn'];
939

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

    
944
        /* Setup CA environment if needed. */
945
        ldap_setup_caenv($authcfg);
946

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

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

    
961
	/* bind as user that has rights to read group attributes */
962
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
963
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
964
	if ($ldapanon == true) {
965
                if (!($res = @ldap_bind($ldap))) {
966
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
967
			@ldap_close($ldap);
968
                        return false;
969
		}
970
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
971
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
972
		@ldap_close($ldap);
973
		return memberof;
974
	}
975

    
976
	/* get groups from DN found */
977
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
978
	/* since we know the DN is in $_SESSION['ldapdn'] */
979
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
980
	if ($ldapscope == "one")
981
                $ldapfunc = "ldap_list";
982
        else
983
                $ldapfunc = "ldap_search";
984

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

    
988
	$countem = $info["count"];	
989
	
990
	if(is_array($info[0][$ldapgroupattribute])) {
991
		/* Iterate through the groups and throw them into an array */
992
		foreach ($info[0][$ldapgroupattribute] as $member) {
993
			if (stristr($member, "CN=") !== false) {
994
				$membersplit = explode(",", $member);
995
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
996
			}
997
		}
998
	}
999
	
1000
	/* Time to close LDAP connection */
1001
	@ldap_unbind($ldap);
1002
	
1003
	$groups = print_r($memberof,true);
1004
	
1005
	//log_error("Returning groups ".$groups." for user $username");
1006
	
1007
	return $memberof;
1008
}
1009

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

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

    
1020
	if(!function_exists("ldap_connect"))
1021
		return;
1022

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

    
1032
	if ($authcfg) {
1033
		if (strstr($authcfg['ldap_urltype'], "Standard"))
1034
			$ldapproto = "ldap";
1035
		else
1036
			$ldapproto = "ldaps";
1037
		$ldapserver         = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1038
		$ldapport	    = $authcfg['ldap_port'];
1039
		if (!empty($ldapport))
1040
			$ldapserver .= ":{$ldapport}";
1041
                $ldapbasedn         = $authcfg['ldap_basedn'];
1042
                $ldapbindun         = $authcfg['ldap_binddn'];
1043
                $ldapbindpw         = $authcfg['ldap_bindpw'];
1044
		if (empty($ldapbindun) || empty($ldapbindpw))
1045
			$ldapanon = true;
1046
		else
1047
			$ldapanon = false;
1048
                $ldapauthcont       = $authcfg['ldap_authcn'];
1049
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
1050
                $ldapextendedqueryenabled  = $authcfg['ldap_extended_enabled'];
1051
                $ldapextendedquery = $authcfg['ldap_extended_query'];
1052
                $ldapfilter         = "";
1053
                if(!$ldapextendedqueryenabled)
1054
                {
1055
                        $ldapfilter = "({$ldapnameattribute}={$username})";
1056
                }
1057
                else
1058
                {
1059
                        $ldapfilter = 
1060
"(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
1061
                } 
1062
                $ldaptype           = "";
1063
                $ldapver            = $authcfg['ldap_protver'];
1064
		$ldapname	    = $authcfg['name'];
1065
		$ldapscope	    = $authcfg['ldap_scope'];
1066
	} else
1067
		return false;
1068

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

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

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

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

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

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

    
1107
	if ($error == true) {
1108
		@ldap_close($ldap);
1109
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1110
		return false;
1111
	}
1112
	
1113
	/* Get LDAP Authcontainers and split em up. */
1114
	$ldac_splits = explode(";", $ldapauthcont);
1115
	
1116
	/* setup the usercount so we think we havn't found anyone yet */
1117
	$usercount  = 0;
1118

    
1119
	/*****************************************************************/
1120
	/*  We First find the user based on username and filter          */
1121
	/*  Then, once we find the first occurance of that person        */
1122
	/*  We set seesion variables to ponit to the OU and DN of the    */
1123
	/*  Person.  To later be used by ldap_get_groups.                */
1124
	/*  that way we don't have to search twice.                      */
1125
	/*****************************************************************/
1126
	if ($debug)
1127
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1128
	/* Iterate through the user containers for search */
1129
	foreach ($ldac_splits as $i => $ldac_split) {
1130
		$ldac_split = isset($authcfg['ldap_utf8']) ? utf8_encode($ldac_split) : $ldac_split;
1131
		$ldapfilter = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapfilter) : $ldapfilter;
1132
		$ldapsearchbasedn = isset($authcfg['ldap_utf8']) ? utf8_encode("{$ldac_split},{$ldapbasedn}") : "{$ldac_split},{$ldapbasedn}";
1133
		/* Make sure we just use the first user we find */
1134
		if ($debug)
1135
			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)));
1136
		if ($ldapscope == "one")
1137
			$ldapfunc = "ldap_list";
1138
		else
1139
			$ldapfunc = "ldap_search";
1140
		/* Support legacy auth container specification. */
1141
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn))
1142
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
1143
		else
1144
			$search  = @$ldapfunc($ldap,$ldapsearchbasedn,$ldapfilter);
1145
		if (!$search) {
1146
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1147
			continue;
1148
		}
1149
		$info	 = ldap_get_entries($ldap,$search);
1150
		$matches = $info['count'];
1151
		if ($matches == 1){
1152
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1153
			$_SESSION['ldapou'] = $ldac_split[$i];
1154
			$_SESSION['ldapon'] = "true";
1155
			$usercount = 1;
1156
			break;
1157
		}
1158
	}
1159

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

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

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

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

    
1182
	return true;
1183
}
1184

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

    
1189
	require_once("radius.inc");
1190

    
1191
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1192
	if ($authcfg) {
1193
		$radiusservers = array();
1194
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1195
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1196
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1197
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1198
	} else
1199
		return false;
1200

    
1201
	/* Add a new servers to our instance */
1202
	foreach ($radiusservers as $radsrv) {
1203
		$timeout = (is_numeric($radsrv['timeout'])) ? $radsrv['timeout'] : 5;
1204
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret'], $timeout);
1205
	}
1206

    
1207
	if (PEAR::isError($rauth->start())) {
1208
		$retvalue['auth_val'] = 1;
1209
		$retvalue['error'] = $rauth->getError();
1210
		if ($debug)
1211
			printf(gettext("Radius start: %s<br />\n"), $retvalue['error']);
1212
	}
1213

    
1214
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1215

    
1216
	/* Send request */
1217
	$result = $rauth->send();
1218
	if (PEAR::isError($result)) {
1219
		$retvalue['auth_val'] = 1;
1220
		$retvalue['error'] = $result->getMessage();
1221
		if ($debug)
1222
			printf(gettext("Radius send failed: %s<br />\n"), $retvalue['error']);
1223
	} else if ($result === true) {
1224
		if ($rauth->getAttributes())
1225
			$attributes = $rauth->listAttributes();
1226
		$retvalue['auth_val'] = 2;
1227
		if ($debug)
1228
			printf(gettext("Radius Auth succeeded")."<br />\n");
1229
		$ret = true;
1230
	} else {
1231
		$retvalue['auth_val'] = 3;
1232
		if ($debug)
1233
			printf(gettext("Radius Auth rejected")."<br />\n");
1234
	}
1235

    
1236
	// close OO RADIUS_AUTHENTICATION
1237
	$rauth->close();
1238

    
1239
	return $ret;
1240
}
1241

    
1242
function get_user_expiration_date($username) {
1243
	$user = getUserEntry($username);
1244
	if ($user['expires']) 
1245
		return $user['expires'];
1246
}
1247

    
1248
function is_account_expired($username) {
1249
	$expirydate = get_user_expiration_date($username);
1250
	if ($expirydate) {
1251
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1252
			return true;
1253
	}
1254

    
1255
	return false;
1256
}
1257

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

    
1263
	return false;
1264
}
1265

    
1266
function auth_get_authserver($name) {
1267
        global $config;
1268

    
1269
        if (is_array($config['system']['authserver'])) {
1270
                foreach ($config['system']['authserver'] as $authcfg) {
1271
                        if ($authcfg['name'] == $name)
1272
                                return $authcfg;
1273
                }
1274
        }
1275
	if ($name == "Local Database")
1276
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1277
}
1278

    
1279
function auth_get_authserver_list() {
1280
        global $config;
1281

    
1282
	$list = array();
1283

    
1284
        if (is_array($config['system']['authserver'])) {
1285
                foreach ($config['system']['authserver'] as $authcfg) {
1286
			/* Add support for disabled entries? */
1287
			$list[$authcfg['name']] = $authcfg;
1288
                }
1289
        }
1290

    
1291
	$list["Local Database"] = array( "name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1292
	return $list;
1293
}
1294

    
1295
function getUserGroups($username, $authcfg) {
1296
	global $config;
1297

    
1298
	$allowed_groups = array();
1299

    
1300
	switch($authcfg['type']) {
1301
        case 'ldap':
1302
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1303
		break;
1304
	case 'radius':
1305
		break;
1306
	default:
1307
		$user = getUserEntry($username);
1308
		$allowed_groups = @local_user_get_groups($user, true);
1309
		break;
1310
	}
1311

    
1312
	$member_groups = array();
1313
        if (is_array($config['system']['group'])) {
1314
                foreach ($config['system']['group'] as $group)
1315
                        if (in_array($group['name'], $allowed_groups))
1316
				$member_groups[] = $group['name'];
1317
	}
1318

    
1319
	return $member_groups;
1320
}
1321

    
1322
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1323

    
1324
	if (!$authcfg) {
1325
		return local_backed($username, $password);
1326
	}
1327

    
1328
	$authenticated = false;
1329
	switch($authcfg['type']) {
1330
        case 'ldap':
1331
                if (ldap_backed($username, $password, $authcfg))
1332
                        $authenticated = true;
1333
                break;
1334
        case 'radius':
1335
                if (radius_backed($username, $password, $authcfg, $attributes))
1336
                        $authenticated = true;
1337
                break;
1338
        default:
1339
                /* lookup user object by name */
1340
                if (local_backed($username, $password))
1341
                        $authenticated = true;
1342
                break;
1343
        }
1344

    
1345
	return $authenticated;
1346
}
1347

    
1348
function session_auth() {
1349
	global $config, $_SESSION, $page;
1350

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

    
1361
	if (!session_id())
1362
		session_start();
1363

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

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

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

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

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

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

    
1437
		/* wipe out $_SESSION */
1438
		$_SESSION = array();
1439

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

    
1443
		/* and destroy it */
1444
		session_destroy();
1445

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

    
1450
		if (isAjax())
1451
			return false;
1452

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

    
1456
		return false;
1457
	}
1458

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

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

    
1473
	return true;
1474
}
1475

    
1476
?>
(5-5/68)