Project

General

Profile

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

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

    
10
        Copyright (C) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
11
        All rights reserved.
12

    
13
        Copyright (C) 2006 Paul Taylor <paultaylor@winn-dixie.com>.
14
        All rights reserved.
15

    
16
        Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
17
        All rights reserved.
18

    
19
        Redistribution and use in source and binary forms, with or without
20
        modification, are permitted provided that the following conditions are met:
21

    
22
        1. Redistributions of source code must retain the above copyright notice,
23
           this list of conditions and the following disclaimer.
24

    
25
        2. Redistributions in binary form must reproduce the above copyright
26
           notice, this list of conditions and the following disclaimer in the
27
           documentation and/or other materials provided with the distribution.
28

    
29
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
30
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
31
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
33
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
        POSSIBILITY OF SUCH DAMAGE.
39

    
40
		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
/* If this function doesn't exist, we're being called from Captive Portal or 
53
   another internal subsystem which does not include authgui.inc */
54
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
55
	/* DNS ReBinding attack prevention.  http://redmine.pfsense.org/issues/708 */
56
	$found_host = false;
57
	if(strstr($_SERVER['HTTP_HOST'], ":")) {
58
		$http_host_port = explode(":", $_SERVER['HTTP_HOST']);
59
		$http_host = $http_host_port[0];
60
	} else {
61
		$http_host = $_SERVER['HTTP_HOST'];
62
	}
63
	if(is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
64
	   $http_host == "localhost" or $_SERVER['SERVER_ADDR'] == "localhost")
65
		$found_host = true;
66
	if($config['dyndnses']['dyndns'])
67
		foreach($config['dyndnses']['dyndns'] as $dyndns)
68
			if($dyndns['host'] == $http_host or $dyndns['host'] == $_SERVER['SERVER_ADDR'])
69
				$found_host = true;
70

    
71
	if(!empty($config['system']['webgui']['althostnames'])) {
72
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
73
		foreach ($althosts as $ah)
74
			if($ah == $http_host or $ah == $_SERVER['SERVER_ADDR'])
75
				$found_host = true;
76
	}
77

    
78
	if($http_host == $config['system']['hostname'] . "." . $config['system']['domain'] or
79
			$http_host == $_SERVER['SERVER_ADDR'] or
80
			$http_host == $config['system']['hostname'])
81
		$found_host = true;
82

    
83
	if($found_host == false) {
84
		display_error_form("501", "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.");
85
		exit;
86
	}
87
}
88

    
89
// If the HTTP_REFERER is something other than ourselves then disallow.
90
if(!$config['system']['nohttpreferercheck']) {
91
	if($_SERVER['HTTP_REFERER']) {
92
		$found_host = false;
93
		$hostname_me = $config['system']['hostname'] . "." . $config['system']['domain'];
94
		if(stristr($_SERVER['HTTP_REFERER'], $hostname_me))
95
			$found_host = true;
96
		if(!empty($config['system']['webgui']['althostnames'])) {
97
			$althosts = explode(" ", $config['system']['webgui']['althostnames']);
98
			foreach ($althosts as $ah)
99
				if(stristr($ah, $hostname_me))
100
					$found_host = true;
101
		}
102
		$interface_list_ips = get_configured_ip_addresses();
103
		foreach($interface_list_ips as $ilips) {
104
			$hostname_me_ip = $config['webgui']['protocol'] . "://" . $ilips;
105
			if(stristr($_SERVER['HTTP_REFERER'],$hostname_me_ip)) 
106
				$found_host = true;
107
		}
108
		if($found_host == false) {
109
			display_error_form("501", "An HTTP_REFERER was detected other than what is defined in System -> Advanced (" . $_SERVER['HTTP_REFERER'] . ").  You can disable this check if needed in System -> Advanced -> Admin.");
110
			exit;
111
		}
112
	}
113
}
114

    
115
$groupindex = index_groups();
116
$userindex = index_users();
117

    
118
function index_groups() {
119
	global $g, $debug, $config, $groupindex;
120

    
121
	$groupindex = array();
122

    
123
	if (is_array($config['system']['group'])) {
124
		$i = 0;
125
		foreach($config['system']['group'] as $groupent) {
126
			$groupindex[$groupent['name']] = $i;
127
			$i++;
128
		}
129
	}
130

    
131
	return ($groupindex);
132
}
133

    
134
function index_users() {
135
	global $g, $debug, $config;
136

    
137
	if (is_array($config['system']['user'])) {
138
		$i = 0;
139
		foreach($config['system']['user'] as $userent) {
140
			$userindex[$userent['name']] = $i;
141
			$i++;
142
		}
143
	}
144

    
145
	return ($userindex);
146
}
147

    
148
function & getUserEntry($name) {
149
	global $debug, $config, $userindex;
150
	if (isset($userindex[$name]))
151
		return $config['system']['user'][$userindex[$name]];
152
}
153

    
154
function & getUserEntryByUID($uid) {
155
	global $debug, $config;
156
	foreach ($config['system']['user'] as & $user)
157
		if ($user['uid'] == $uid)
158
			return $user;
159

    
160
	return false;
161
}
162

    
163
function & getGroupEntry($name) {
164
	global $debug, $config, $groupindex;
165
	if (isset($groupindex[$name]))
166
		return $config['system']['group'][$groupindex[$name]];
167
}
168

    
169
function & getGroupEntryByGID($gid) {
170
	global $debug, $config;
171
	foreach ($config['system']['group'] as & $group)
172
		if ($group['gid'] == $gid)
173
			return $group;
174

    
175
	return false;
176
}
177

    
178
function get_user_privileges(& $user) {
179

    
180
        $privs = $user['priv'];
181
        if (!is_array($privs))
182
                $privs = array();
183

    
184
        $names = local_user_get_groups($user, true);
185

    
186
        foreach ($names as $name) {
187
                $group = getGroupEntry($name);
188
                if (is_array($group['priv']))
189
                        $privs = array_merge( $privs, $group['priv']);
190
        }
191

    
192
        return $privs;
193
}
194

    
195
function userHasPrivilege($userent, $privid = false) {
196

    
197
        if (!$privid || !is_array($userent))
198
                return false;
199

    
200
        $privs = get_user_privileges($userent);
201

    
202
        if (!is_array($privs))
203
                return false;
204

    
205
        if (!in_array($privid, $privs))
206
                return false;
207

    
208
        return true;
209
}
210

    
211
function local_backed($username, $passwd) {
212

    
213
	$user = getUserEntry($username);
214
	if (!$user)
215
		return false;
216

    
217
	if (is_account_disabled($username) || is_account_expired($username))
218
		return false;
219

    
220
	if ($user['password'])
221
	{
222
		$passwd = crypt($passwd, $user['password']);
223
		if ($passwd == $user['password'])
224
			return true;
225
	}
226

    
227
	if ($user['md5-hash'])
228
	{
229
		$passwd = md5($passwd);
230
		if ($passwd == $user['md5-hash'])
231
			return true;
232
	}
233

    
234
	return false;
235
}
236

    
237
function local_sync_accounts() {
238
	global $debug, $config;
239
	conf_mount_rw();
240

    
241
	/* remove local users to avoid uid conflicts */
242
	$fd = popen("/usr/sbin/pw usershow -a", "r");
243
	if ($fd) {
244
		while (!feof($fd)) {
245
			$line = explode(":",fgets($fd));
246
			if (!strncmp($line[0], "_", 1))
247
				continue;
248
			if ($line[2] < 2000)
249
				continue;
250
			if ($line[2] > 65000)
251
				continue;
252
			$cmd = "/usr/sbin/pw userdel {$line[2]}";
253
			if($debug)
254
				log_error("Running: {$cmd}");
255
			mwexec($cmd);
256
		}
257
		pclose($fd);
258
	}
259

    
260
	/* remove local groups to avoid gid conflicts */
261
	$gids = array();
262
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
263
	if ($fd) {
264
		while (!feof($fd)) {
265
			$line = explode(":",fgets($fd));
266
			if (!strncmp($line[0], "_", 1))
267
				continue;
268
			if ($line[2] < 2000)
269
				continue;
270
			if ($line[2] > 65000)
271
				continue;
272
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
273
			if($debug)
274
				log_error("Running: {$cmd}");
275
			mwexec($cmd);
276
		}
277
		pclose($fd);
278
	}
279

    
280
	/* make sure the all group exists */
281
	$allgrp = getGroupEntryByGID(1998);
282
	local_group_set($allgrp, true);
283

    
284
	/* sync all local users */
285
	if (is_array($config['system']['user']))
286
		foreach ($config['system']['user'] as $user)
287
			local_user_set($user);
288

    
289
	/* sync all local groups */
290
	if (is_array($config['system']['group']))
291
		foreach ($config['system']['group'] as $group)
292
			local_group_set($group);
293

    
294
	conf_mount_ro();
295

    
296
}
297

    
298
function local_user_set(& $user) {
299
	global $g, $debug;
300

    
301
	conf_mount_rw();
302

    
303
	$home_base = "/home/";	
304
	$user_uid = $user['uid'];
305
	$user_name = $user['name'];
306
	$user_home = "{$home_base}{$user_name}";
307
	$user_shell = "/etc/rc.initial";
308
	$user_group = "nobody";
309

    
310
	// Ensure $home_base exists and is writable
311
	if (!is_dir($home_base)) 
312
		mkdir($home_base, 0755);
313

    
314
	$lock_account = false;
315
	/* configure shell type */
316
	/* Cases here should be ordered by most privileged to least privileged. */
317
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
318
		$user_shell = "/bin/tcsh";
319
	} elseif (userHasPrivilege($user, "user-copy-files")) {
320
		$user_shell = "/usr/local/bin/scponly";
321
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
322
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
323
	} else {
324
		$user_shell = "/sbin/nologin";
325
		$lock_account = true;
326
	}
327

    
328
	/* Lock out disabled or expired users, unless it's root/admin. */
329
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
330
		$user_shell = "/sbin/nologin";
331
		$lock_account = true;
332
	}
333

    
334
	/* root user special handling */
335
	if ($user_uid == 0) {
336
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
337
		if($debug)
338
			log_error("Running: {$cmd}");
339
		$fd = popen($cmd, "w");
340
		fwrite($fd, $user['password']);
341
		pclose($fd);
342
		$user_group = "wheel";
343
		$user_home = "/root";
344
		$user_shell = "/etc/rc.initial";
345
	}
346

    
347
	/* read from pw db */
348
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
349
	$pwread = fgets($fd);
350
	pclose($fd);
351

    
352
	/* determine add or mod */
353
	if (!strncmp($pwread, "pw:", 3)) {
354
		$user_op = "useradd -m -k /etc/skel -o";
355
	} else {
356
		$user_op = "usermod";
357
	}
358

    
359
	/* add or mod pw db */
360
	$cmd = "/usr/sbin/pw {$user_op} -q -u {$user_uid} -n {$user_name}".
361
			" -g {$user_group} -s {$user_shell} -d {$user_home}".
362
			" -c ".escapeshellarg($user['descr'])." -H 0 2>&1";
363

    
364
	if($debug)
365
		log_error("Running: {$cmd}");
366
	$fd = popen($cmd, "w");
367
	fwrite($fd, $user['password']);
368
	pclose($fd);
369

    
370
	/* create user directory if required */
371
	if (!is_dir($user_home)) {
372
		mkdir($user_home, 0700);
373
		mwexec("cp /root/.* {$home_base}/");
374
	}
375
	chown($user_home, $user_name);
376
	chgrp($user_home, $user_group);
377

    
378
	/* write out ssh authorized key file */
379
	if($user['authorizedkeys']) {
380
		if (!is_dir("{$user_home}/.ssh")) {
381
			mkdir("{$user_home}/.ssh", 0700);
382
			chown("{$user_home}/.ssh", $user_name);
383
		}
384
		$keys = base64_decode($user['authorizedkeys']);
385
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
386
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
387
	}
388

    
389
	$un = $lock_account ? "" : "un";
390
	exec("/usr/sbin/pw {$un}lock -q {$user_name}");
391
	
392
	conf_mount_ro();
393
}
394

    
395
function local_user_del($user) {
396
	global $debug;
397

    
398
	/* remove all memberships */
399
	local_user_set_groups($user);
400

    
401
	/* Don't remove /root */
402
	if ($user['uid'] != 0)
403
		$rmhome = "-r";
404

    
405
	/* delete from pw db */
406
	$cmd = "/usr/sbin/pw userdel {$user['name']} {$rmhome}";
407

    
408
	if($debug)
409
		log_error("Running: {$cmd}");
410
	mwexec($cmd);
411

    
412
	/* Delete user from groups needs a call to write_config() */
413
	local_group_del_user($user);
414
}
415

    
416
function local_user_set_password(& $user, $password) {
417

    
418
	$user['password'] = crypt($password);
419
	$user['md5-hash'] = md5($password);
420

    
421
	// Converts ascii to unicode.
422
	$astr = (string) $password;
423
	$ustr = '';
424
	for ($i = 0; $i < strlen($astr); $i++) {
425
		$a = ord($astr{$i}) << 8;
426
		$ustr.= sprintf("%X", $a);
427
	}
428

    
429
	// Generate the NT-HASH from the unicode string
430
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
431
}
432

    
433
function local_user_get_groups($user, $all = false) {
434
	global $debug, $config;
435

    
436
	$groups = array();
437
	if (!is_array($config['system']['group']))
438
		return $groups;
439

    
440
	foreach ($config['system']['group'] as $group)
441
		if ( $all || ( !$all && ($group['name'] != "all")))
442
			if (is_array($group['member']))
443
				if (in_array($user['uid'], $group['member']))
444
					$groups[] = $group['name'];
445

    
446
	if ( $all )
447
		$groups[] = "all";
448

    
449
	sort($groups);
450

    
451
	return $groups;
452
	
453
}
454

    
455
function local_user_set_groups($user, $new_groups = NULL ) {
456
	global $debug, $config, $groupindex;
457

    
458
	if (!is_array($config['system']['group']))
459
		return;
460

    
461
	$cur_groups = local_user_get_groups($user, true);
462
	$mod_groups = array();
463

    
464
	if (!is_array($new_groups))
465
		$new_groups = array();
466

    
467
	if (!is_array($cur_groups))
468
		$cur_groups = array();
469

    
470
	/* determine which memberships to add */
471
	foreach ($new_groups as $groupname) {
472
		if (in_array($groupname,$cur_groups))
473
			continue;
474
		$group = & $config['system']['group'][$groupindex[$groupname]];
475
		$group['member'][] = $user['uid'];
476
		$mod_groups[] = $group;
477
	}
478

    
479
	/* determine which memberships to remove */
480
	foreach ($cur_groups as $groupname) {
481
		if (in_array($groupname,$new_groups))
482
			continue;
483
		if (!isset($config['system']['group'][$groupindex[$groupname]]))
484
			continue;
485
		$group = & $config['system']['group'][$groupindex[$groupname]];
486
		if (is_array($group['member'])) {
487
			$index = array_search($user['uid'], $group['member']);
488
			array_splice($group['member'], $index, 1);
489
			$mod_groups[] = $group;
490
		}
491
	}
492

    
493
	/* sync all modified groups */
494
	foreach ($mod_groups as $group)
495
		local_group_set($group);
496
}
497

    
498
function local_group_del_user($user) {
499
	global $config;
500

    
501
	if (!is_array($config['system']['group']))
502
                return;
503

    
504
        foreach ($config['system']['group'] as $group) {
505
		if (is_array($group['member'])) {
506
			foreach ($group['member'] as $idx => $uid) {
507
				if ($user['uid'] == $uid)
508
					unset($config['system']['group']['member'][$idx]);
509
			}
510
		}
511
	}
512
}
513

    
514
function local_group_set($group, $reset = false) {
515
	global $debug;
516

    
517
	$group_name = $group['name'];
518
	$group_gid = $group['gid'];
519
	$group_members = "''";
520
	if (!$reset && !empty($group['member']) && count($group['member']) > 0)
521
		$group_members = implode(",",$group['member']);
522

    
523
	/* read from group db */
524
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
525
	$pwread = fgets($fd);
526
	pclose($fd);
527

    
528
	/* determine add or mod */
529
	if (!strncmp($pwread, "pw:", 3))
530
		$group_op = "groupadd";
531
	else
532
		$group_op = "groupmod";
533

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

    
537
	if($debug)
538
		log_error("Running: {$cmd}");
539
	mwexec($cmd);
540

    
541
}
542

    
543
function local_group_del($group) {
544
	global $debug;
545

    
546
	/* delete from group db */
547
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
548

    
549
	if($debug)
550
		log_error("Running: {$cmd}");
551
	mwexec($cmd);
552
}
553

    
554
function ldap_test_connection($authcfg) {
555
	global $debug, $config, $g;
556

    
557
	if ($authcfg) {
558
                if (strstr($authcfg['ldap_urltype'], "Standard"))
559
                        $ldapproto = "ldap";
560
                else
561
                        $ldapproto = "ldaps";
562
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
563
                $ldapport           = $authcfg['ldap_port'];
564
                $ldapbasedn         = $authcfg['ldap_basedn'];
565
                $ldapbindun         = $authcfg['ldap_binddn'];
566
                $ldapbindpw         = $authcfg['ldap_bindpw'];
567
        } else
568
		return false;
569

    
570
        /* first check if there is even an LDAP server populated */
571
        if(!$ldapserver)
572
                return false;
573

    
574
        /* connect and see if server is up */
575
        putenv('LDAPTLS_REQCERT=never');
576
        $error = false;
577
        if (empty($ldapport)) {
578
                if (!($ldap = ldap_connect($ldapserver)))
579
                        $error = true;
580
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
581
                $error = true;
582

    
583
        if ($error == true) {
584
                log_error("ERROR!  Could not connect to server {$ldapname}.");
585
                return false;
586
        }
587

    
588
	return true;
589
}
590

    
591
function ldap_test_bind($authcfg) {
592
	global $debug, $config, $g;
593

    
594
	if ($authcfg) {
595
                if (strstr($authcfg['ldap_urltype'], "Standard"))
596
                        $ldapproto = "ldap";
597
                else
598
                        $ldapproto = "ldaps";
599
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
600
                $ldapport           = $authcfg['ldap_port'];
601
                $ldapbasedn         = $authcfg['ldap_basedn'];
602
                $ldapbindun         = $authcfg['ldap_binddn'];
603
                $ldapbindpw         = $authcfg['ldap_bindpw'];
604
                $ldapver            = $authcfg['ldap_protver'];
605
		if (empty($ldapbndun) || empty($ldapbindpw))
606
                        $ldapanon = true;
607
                else
608
                        $ldapanon = false;
609
	} else
610
		return false;
611

    
612
	/* first check if there is even an LDAP server populated */
613
        if(!$ldapserver)
614
                return false;
615

    
616
        /* connect and see if server is up */
617
        putenv('LDAPTLS_REQCERT=never');
618
        $error = false;
619
        if (empty($ldapport)) {
620
                if (!($ldap = ldap_connect($ldapserver)))
621
                        $error = true;
622
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
623
                $error = true;
624

    
625
        if ($error == true) {
626
                log_error("ERROR!  Could not connect to server {$ldapname}.");
627
                return false;
628
        }
629

    
630
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
631
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
632
 
633
	if ($ldapanon == true) {
634
		if (!($res = @ldap_bind($ldap))) {
635
			@ldap_close($ldap);
636
			return false;
637
		}
638
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
639
		@ldap_close($ldap);
640
		return false;
641
	}
642

    
643
	@ldap_unbind($ldap);
644

    
645
	return true;
646
}
647

    
648
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
649
	global $debug, $config, $g;
650

    
651
	if(!function_exists("ldap_connect"))
652
		return;
653

    
654
	$ous = array();
655

    
656
	if ($authcfg) {
657
                if (strstr($authcfg['ldap_urltype'], "Standard"))
658
                        $ldapproto = "ldap";
659
                else
660
                        $ldapproto = "ldaps";
661
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
662
                $ldapport           = $authcfg['ldap_port'];
663
                $ldapbasedn         = $authcfg['ldap_basedn'];
664
                $ldapbindun         = $authcfg['ldap_binddn'];
665
                $ldapbindpw         = $authcfg['ldap_bindpw'];
666
                $ldapver            = $authcfg['ldap_protver'];
667
		if (empty($ldapbindun) || empty($ldapbindpw))
668
                        $ldapanon = true;
669
                else
670
                        $ldapanon = false;
671
                $ldapname           = $authcfg['name'];
672
                $ldapfallback       = false;
673
		$ldapscope          = $authcfg['ldap_scope'];
674
        } else
675
		return false;
676

    
677
        /* first check if there is even an LDAP server populated */
678
        if(!$ldapserver) {
679
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
680
                return $ous;
681
        }
682

    
683
	/* connect and see if server is up */
684
        putenv('LDAPTLS_REQCERT=never');
685
        $error = false;
686
        if (empty($ldapport)) {
687
                if (!($ldap = ldap_connect($ldapserver)))
688
                        $error = true;
689
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
690
                $error = true;
691

    
692
        if ($error == true) {
693
		log_error("ERROR!  Could not connect to server {$ldapname}.");
694
                return $ous;
695
        }
696

    
697
	$ldapfilter = "(|(ou=*)(cn=Users))";
698

    
699
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
700
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
701

    
702
	if ($ldapanon == true) {
703
                if (!($res = @ldap_bind($ldap))) {
704
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
705
			@ldap_close($ldap);
706
                        return $ous;
707
		}
708
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
709
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
710
		@ldap_close($ldap);
711
		return $ous;
712
	}
713

    
714
	if ($ldapscope == "one")
715
		$ldapfunc = "ldap_list";
716
	else
717
		$ldapfunc = "ldap_search";
718

    
719
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
720
	$info = @ldap_get_entries($ldap, $search);
721

    
722
	if (is_array($info)) {
723
		foreach ($info as $inf) {
724
			if (!$show_complete_ou) {
725
				$inf_split = split(",", $inf['dn']);
726
				$ou = $inf_split[0];
727
				$ou = str_replace("OU=","", $ou);
728
				$ou = str_replace("CN=","", $ou);
729
			} else
730
				if($inf['dn'])
731
					$ou = $inf['dn'];
732
			if($ou)
733
				$ous[] = $ou;
734
		}
735
	}
736

    
737
	@ldap_unbind($ldap);
738

    
739
	return $ous;
740
}
741

    
742
function ldap_get_groups($username, $authcfg) {
743
	global $debug, $config;
744
	
745
	if(!function_exists("ldap_connect"))
746
		return;
747
	
748
	if(!$username) 
749
		return false;
750

    
751
	if(stristr($username, "@")) {
752
		$username_split=split("\@", $username);
753
		$username = $username_split[0];		
754
	}
755

    
756
	if(stristr($username, "\\")) {
757
		$username_split=split("\\", $username);
758
		$username = $username_split[0];        
759
	}    
760
	
761
	//log_error("Getting LDAP groups for {$username}.");
762
        if ($authcfg) {
763
                if (strstr($authcfg['ldap_urltype'], "Standard"))
764
                        $ldapproto = "ldap";
765
                else
766
                        $ldapproto = "ldaps";
767
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
768
                $ldapport           = $authcfg['ldap_port'];
769
                $ldapbasedn         = $authcfg['ldap_basedn'];
770
                $ldapbindun         = $authcfg['ldap_binddn'];
771
                $ldapbindpw         = $authcfg['ldap_bindpw'];
772
                $ldapauthcont       = $authcfg['ldap_authcn'];
773
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
774
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
775
                $ldapfilter         = "({$ldapnameattribute}={$username})";
776
                $ldaptype           = "";
777
                $ldapver            = $authcfg['ldap_protver'];
778
		if (empty($ldapbindun) || empty($ldapbindpw))
779
                        $ldapanon = true;
780
                else
781
                        $ldapanon = false;
782
                $ldapname           = $authcfg['name'];
783
                $ldapfallback       = false;
784
		$ldapscope          = $authcfg['ldap_scope'];
785
	} else
786
		return false;
787

    
788
	$ldapdn             = $_SESSION['ldapdn'];
789

    
790
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
791
	$ldapgroupattribute = strtolower($ldapgroupattribute);
792
	$memberof = array();
793

    
794
	/* connect and see if server is up */
795
	putenv('LDAPTLS_REQCERT=never');
796
	$error = false;
797
        if (empty($ldapport)) {
798
                if (!($ldap = ldap_connect($ldapserver)))
799
                        $error = true;
800
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
801
                $error = true;
802

    
803
	if ($error == true) {
804
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
805
                return memberof;
806
        }
807
    
808
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
809
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
810

    
811
	/* bind as user that has rights to read group attributes */
812
	if ($ldapanon == true) {
813
                if (!($res = @ldap_bind($ldap))) {
814
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
815
			@ldap_close($ldap);
816
                        return false;
817
		}
818
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
819
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
820
		@ldap_close($ldap);
821
		return memberof;
822
	}
823

    
824
	/* get groups from DN found */
825
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
826
	/* since we know the DN is in $_SESSION['ldapdn'] */
827
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
828
	if ($ldapscope == "one")
829
                $ldapfunc = "ldap_list";
830
        else
831
                $ldapfunc = "ldap_search";
832

    
833
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
834
	$info      = @ldap_get_entries($ldap, $search);
835

    
836
	$countem = $info["count"];	
837
	
838
	if(is_array($info[0][$ldapgroupattribute])) {
839
		/* Iterate through the groups and throw them into an array */
840
		foreach ($info[0][$ldapgroupattribute] as $member) {
841
			if (stristr($member, "CN=") !== false) {
842
				$membersplit = split(",", $member);
843
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
844
			}
845
		}
846
	}
847
	
848
	/* Time to close LDAP connection */
849
	@ldap_unbind($ldap);
850
	
851
	$groups = print_r($memberof,true);
852
	
853
	//log_error("Returning groups ".$groups." for user $username");
854
	
855
	return $memberof;
856
}
857

    
858
function ldap_backed($username, $passwd, $authcfg) {
859
	global $debug, $config;
860
	
861
	if(!$username) 
862
		return;
863

    
864
	if(!function_exists("ldap_connect"))
865
		return;
866

    
867
	if(stristr($username, "@")) {
868
		$username_split=split("\@", $username);
869
		$username = $username_split[0];        
870
	}
871
	if(stristr($username, "\\")) {
872
		$username_split=split("\\", $username);
873
		$username = $username_split[0];        
874
	}
875

    
876
	if ($authcfg) {
877
		if (strstr($authcfg['ldap_urltype'], "Standard"))
878
			$ldapproto = "ldap";
879
		else
880
			$ldapproto = "ldaps";
881
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
882
		$ldapport	    = $authcfg['ldap_port'];
883
                $ldapbasedn         = $authcfg['ldap_basedn'];
884
                $ldapbindun         = $authcfg['ldap_binddn'];
885
                $ldapbindpw         = $authcfg['ldap_bindpw'];
886
		if (empty($ldapbindun) || empty($ldapbindpw))
887
			$ldapanon = true;
888
		else
889
			$ldapanon = false;
890
                $ldapauthcont       = $authcfg['ldap_authcn'];
891
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
892
                $ldapfilter         = "({$ldapnameattribute}={$username})";
893
                $ldaptype           = "";
894
                $ldapver            = $authcfg['ldap_protver'];
895
		$ldapname	    = $authcfg['name'];
896
		$ldapscope	    = $authcfg['ldap_scope'];
897
	} else
898
		return false;
899

    
900
	/* first check if there is even an LDAP server populated */ 
901
	if(!$ldapserver) {
902
		if ($ldapfallback) {
903
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
904
			return local_backed($username, $passwd);
905
		} else
906
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
907

    
908
		return false;
909
	}
910
	
911
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
912
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
913

    
914
	/* Make sure we can connect to LDAP */
915
	putenv('LDAPTLS_REQCERT=never');
916
	$error = false;
917
	if (empty($ldapport)) {
918
		if (!($ldap = ldap_connect($ldapserver)))
919
			$error = true;
920
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
921
		$error = true;
922

    
923
	if ($error == true) {
924
		log_error("ERROR!  Could not connect to server {$ldapname}.");
925
		return false;
926
	}
927

    
928
	/* ok, its up.  now, lets bind as the bind user so we can search it */
929
	$error = false;
930
	if ($ldapanon == true) {
931
                if (!($res = @ldap_bind($ldap)))
932
                        $error = true;
933
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
934
		$error = true;
935

    
936
	if ($error == true) {
937
		@ldap_close($ldap);
938
		log_error("ERROR! Could not bind to server {$ldapname}.");
939
		return false;
940
	}
941
	
942
	/* Get LDAP Authcontainers and split em up. */
943
	$ldac_splits = split(";", $ldapauthcont);
944
	
945
	/* setup the usercount so we think we havn't found anyone yet */
946
	$usercount  = 0;
947

    
948
	/*****************************************************************/
949
	/*  We First find the user based on username and filter          */
950
	/*  Then, once we find the first occurance of that person        */
951
	/*  We set seesion variables to ponit to the OU and DN of the    */
952
	/*  Person.  To later be used by ldap_get_groups.                */
953
	/*  that way we don't have to search twice.                      */
954
	/*****************************************************************/
955
	log_error("Now Searching for {$username} in directory.");
956
	/* Iterate through the user containers for search */
957
	foreach ($ldac_splits as $i => $ldac_split) {
958
		/* Make sure we just use the first user we find */
959
		log_error("Now Searching in server {$ldapname}, container {$ldac_split} with filter {$ldapfilter}.");
960
		if ($ldapscope == "one")
961
			$ldapfunc = "ldap_list";
962
		else
963
			$ldapfunc = "ldap_search";
964
		/* Support legacy auth container specification. */
965
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn))
966
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
967
		else
968
			$search  = @$ldapfunc($ldap,"{$ldac_split},{$ldapbasedn}",$ldapfilter);
969
		if (!$search) {
970
			log_error("Search resulted in error: " . ldap_error($ldap));
971
			continue;
972
		}
973
		$info	 = ldap_get_entries($ldap,$search);
974
		$matches = $info['count'];
975
		if ($matches == 1){
976
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
977
			$_SESSION['ldapou'] = $ldac_split[$i];
978
			$_SESSION['ldapon'] = "true";
979
			$usercount = 1;
980
			break;
981
		}
982
	}
983

    
984
	if ($usercount != 1){
985
		@ldap_unbind($ldap);
986
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
987
		return false;                         
988
	}
989

    
990
	/* Now lets bind as the user we found */
991
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
992
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
993
		@ldap_unbind($ldap);
994
		return false;
995
	}
996

    
997
	log_error("Logged in successfully as {$username} via LDAP server {$ldapname} with DN = {$userdn}.");
998

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

    
1002
	return true;
1003
}
1004

    
1005
function radius_backed($username, $passwd, $authcfg){
1006
	global $debug, $config;
1007
	$ret = false;
1008

    
1009
	require_once("radius.inc");
1010

    
1011
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1012
	if ($authcfg) {
1013
		$radiusservers = array();
1014
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1015
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1016
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1017
	} else
1018
		return false;
1019

    
1020
	/* Add a new servers to our instance */
1021
	foreach ($radiusservers as $radsrv)
1022
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
1023

    
1024
	if (PEAR::isError($rauth->start())) {
1025
		$retvalue['auth_val'] = 1;
1026
		$retvalue['error'] = $rauth->getError();
1027
		if ($debug)
1028
			printf("Radius start: %s<br>\n", $retvalue['error']);
1029
	}
1030

    
1031
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1032

    
1033
	/* Send request */
1034
	$result = $rauth->send();
1035
	if (PEAR::isError($result)) {
1036
		$retvalue['auth_val'] = 1;
1037
		$retvalue['error'] = $result->getMessage();
1038
		if ($debug)
1039
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
1040
	} else if ($result === true) {
1041
		$retvalue['auth_val'] = 2;
1042
		if ($debug)
1043
			printf(gettext("Radius Auth succeeded")."<br>\n");
1044
		$ret = true;
1045
	} else {
1046
		$retvalue['auth_val'] = 3;
1047
		if ($debug)
1048
			printf(gettext("Radius Auth rejected")."<br>\n");
1049
	}
1050

    
1051
	// close OO RADIUS_AUTHENTICATION
1052
	$rauth->close();
1053

    
1054
	return $ret;
1055
}
1056

    
1057
function get_user_expiration_date($username) {
1058
	$user = getUserEntry($username);
1059
	if ($user['expires']) 
1060
		return $user['expires'];
1061
}
1062

    
1063
function is_account_expired($username) {
1064
	$expirydate = get_user_expiration_date($username);
1065
	if ($expirydate) {
1066
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1067
			return true;
1068
	}
1069

    
1070
	return false;
1071
}
1072

    
1073
function is_account_disabled($username) {
1074
	$user = getUserEntry($username);
1075
	if (isset($user['disabled']))
1076
		return true;
1077

    
1078
	return false;
1079
}
1080

    
1081
function auth_get_authserver($name) {
1082
        global $config;
1083

    
1084
        if (is_array($config['system']['authserver'])) {
1085
                foreach ($config['system']['authserver'] as $authcfg) {
1086
                        if ($authcfg['name'] == $name)
1087
                                return $authcfg;
1088
                }
1089
        }
1090
	if ($name == "Local Database")
1091
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1092
}
1093

    
1094
function auth_get_authserver_list() {
1095
        global $config;
1096

    
1097
	$list = array();
1098

    
1099
        if (is_array($config['system']['authserver'])) {
1100
                foreach ($config['system']['authserver'] as $authcfg) {
1101
			/* Add support for disabled entries? */
1102
			$list[$authcfg['name']] = $authcfg;
1103
                }
1104
        }
1105

    
1106
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1107
	return $list;
1108
}
1109

    
1110
function getUserGroups($username, $authcfg) {
1111
	global $config;
1112

    
1113
	$allowed_groups = array();
1114

    
1115
	switch($authcfg['type']) {
1116
        case 'ldap':
1117
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1118
		break;
1119
	case 'radius':
1120
		break;
1121
	default:
1122
		$user = getUserEntry($username);
1123
		$allowed_groups = @local_user_get_groups($user, true);
1124
		break;
1125
	}
1126

    
1127
	$member_groups = array();
1128
        if (is_array($config['system']['group'])) {
1129
                foreach ($config['system']['group'] as $group)
1130
                        if (in_array($group['name'], $allowed_groups))
1131
				$member_groups[] = $group['name'];
1132
	}
1133

    
1134
	return $member_groups;
1135
}
1136

    
1137
function authenticate_user($username, $password, $authcfg = NULL) {
1138

    
1139
	if (!$authcfg) {
1140
		return local_backed($username, $password);
1141
	}
1142

    
1143
	$authenticated = false;
1144
	switch($authcfg['type']) {
1145
        case 'ldap':
1146
                if (ldap_backed($username, $password, $authcfg))
1147
                        $authenticated = true;
1148
                break;
1149
        case 'radius':
1150
                if (radius_backed($username, $password, $authcfg))
1151
                        $authenticated = true;
1152
                break;
1153
        default:
1154
                /* lookup user object by name */
1155
                if (local_backed($username, $password))
1156
                        $authenticated = true;
1157
                break;
1158
        }
1159

    
1160
	return $authenticated;
1161
}
1162

    
1163
function session_auth() {
1164
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1165

    
1166
	session_start();
1167

    
1168
	/* Validate incoming login request */
1169
	if (isset($_POST['login'])) {
1170
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1171
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1172
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1173
			$_SESSION['Logged_In'] = "True";
1174
			$_SESSION['Username'] = $_POST['usernamefld'];
1175
			$_SESSION['last_access'] = time();
1176
			log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1177
			$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1178
			if (isset($_POST['postafterlogin']))
1179
				return true;
1180
			else {
1181
				if (empty($page))
1182
					$page = "/";
1183
				header("Location: {$page}");
1184
			}
1185
			exit;
1186
		} else {
1187
			/* give the user an error message */
1188
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1189
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1190
			if(isAjax()) {
1191
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1192
				return;
1193
			}
1194
		}
1195
	}
1196

    
1197
	/* Show login page if they aren't logged in */
1198
	if (empty($_SESSION['Logged_In']))
1199
		return false;
1200

    
1201
	/* If session timeout isn't set, we don't mark sessions stale */
1202
	if (!isset($config['system']['webgui']['session_timeout'])) {
1203
		/* Default to 4 hour timeout if one is not set */
1204
		if ($_SESSION['last_access'] < (time() - 14400)) {
1205
			$_GET['logout'] = true;
1206
			$_SESSION['Logout'] = true;
1207
		} else
1208
			$_SESSION['last_access'] = time();	
1209
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1210
		/* only update if it wasn't ajax */
1211
		if (!isAjax())
1212
			$_SESSION['last_access'] = time();
1213
	} else {
1214
		/* Check for stale session */
1215
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1216
			$_GET['logout'] = true;
1217
			$_SESSION['Logout'] = true;
1218
		} else {
1219
			/* only update if it wasn't ajax */
1220
			if (!isAjax())
1221
				$_SESSION['last_access'] = time();
1222
		}
1223
	}
1224

    
1225
	/* user hit the logout button */
1226
	if (isset($_GET['logout'])) {
1227

    
1228
		if ($_SESSION['Logout'])
1229
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1230
		else
1231
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1232

    
1233
		/* wipe out $_SESSION */
1234
		$_SESSION = array();
1235

    
1236
		if (isset($_COOKIE[session_name()]))
1237
			setcookie(session_name(), '', time()-42000, '/');
1238

    
1239
		/* and destroy it */
1240
		session_destroy();
1241

    
1242
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1243
		$scriptElms = count($scriptName);
1244
		$scriptName = $scriptName[$scriptElms-1];
1245

    
1246
		if (isAjax())
1247
			return false;
1248

    
1249
		/* redirect to page the user is on, it'll prompt them to login again */
1250
		Header("Location: {$scriptName}");
1251

    
1252
		return false;
1253
	}
1254

    
1255
	/*
1256
	 * this is for debugging purpose if you do not want to use Ajax
1257
	 * to submit a HTML form. It basically diables the observation
1258
	 * of the submit event and hence does not trigger Ajax.
1259
	 */
1260
	if ($_GET['disable_ajax'])
1261
		$_SESSION['NO_AJAX'] = "True";
1262

    
1263
	/*
1264
	 * Same to re-enable Ajax.
1265
	 */
1266
	if ($_GET['enable_ajax'])
1267
		unset($_SESSION['NO_AJAX']);
1268

    
1269
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1270
	return true;
1271
}
1272

    
1273
?>
(4-4/54)