Project

General

Profile

Download (35.5 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");
85
		exit;
86
	}
87
}
88

    
89
$groupindex = index_groups();
90
$userindex = index_users();
91

    
92
function index_groups() {
93
	global $g, $debug, $config, $groupindex;
94

    
95
	$groupindex = array();
96

    
97
	if (is_array($config['system']['group'])) {
98
		$i = 0;
99
		foreach($config['system']['group'] as $groupent) {
100
			$groupindex[$groupent['name']] = $i;
101
			$i++;
102
		}
103
	}
104

    
105
	return ($groupindex);
106
}
107

    
108
function index_users() {
109
	global $g, $debug, $config;
110

    
111
	if (is_array($config['system']['user'])) {
112
		$i = 0;
113
		foreach($config['system']['user'] as $userent) {
114
			$userindex[$userent['name']] = $i;
115
			$i++;
116
		}
117
	}
118

    
119
	return ($userindex);
120
}
121

    
122
function & getUserEntry($name) {
123
	global $debug, $config, $userindex;
124
	if (isset($userindex[$name]))
125
		return $config['system']['user'][$userindex[$name]];
126
}
127

    
128
function & getUserEntryByUID($uid) {
129
	global $debug, $config;
130
	foreach ($config['system']['user'] as & $user)
131
		if ($user['uid'] == $uid)
132
			return $user;
133

    
134
	return false;
135
}
136

    
137
function & getGroupEntry($name) {
138
	global $debug, $config, $groupindex;
139
	if (isset($groupindex[$name]))
140
		return $config['system']['group'][$groupindex[$name]];
141
}
142

    
143
function & getGroupEntryByGID($gid) {
144
	global $debug, $config;
145
	foreach ($config['system']['group'] as & $group)
146
		if ($group['gid'] == $gid)
147
			return $group;
148

    
149
	return false;
150
}
151

    
152
function get_user_privileges(& $user) {
153

    
154
        $privs = $user['priv'];
155
        if (!is_array($privs))
156
                $privs = array();
157

    
158
        $names = local_user_get_groups($user, true);
159

    
160
        foreach ($names as $name) {
161
                $group = getGroupEntry($name);
162
                if (is_array($group['priv']))
163
                        $privs = array_merge( $privs, $group['priv']);
164
        }
165

    
166
        return $privs;
167
}
168

    
169
function userHasPrivilege($userent, $privid = false) {
170

    
171
        if (!$privid || !is_array($userent))
172
                return false;
173

    
174
        $privs = get_user_privileges($userent);
175

    
176
        if (!is_array($privs))
177
                return false;
178

    
179
        if (!in_array($privid, $privs))
180
                return false;
181

    
182
        return true;
183
}
184

    
185
function local_backed($username, $passwd) {
186

    
187
	$user = getUserEntry($username);
188
	if (!$user)
189
		return false;
190

    
191
	if (is_account_disabled($username) || is_account_expired($username))
192
		return false;
193

    
194
	if ($user['password'])
195
	{
196
		$passwd = crypt($passwd, $user['password']);
197
		if ($passwd == $user['password'])
198
			return true;
199
	}
200

    
201
	if ($user['md5-hash'])
202
	{
203
		$passwd = md5($passwd);
204
		if ($passwd == $user['md5-hash'])
205
			return true;
206
	}
207

    
208
	return false;
209
}
210

    
211
function local_sync_accounts() {
212
	global $debug, $config;
213
	conf_mount_rw();
214

    
215
	/* remove local users to avoid uid conflicts */
216
	$fd = popen("/usr/sbin/pw usershow -a", "r");
217
	if ($fd) {
218
		while (!feof($fd)) {
219
			$line = explode(":",fgets($fd));
220
			if (!strncmp($line[0], "_", 1))
221
				continue;
222
			if ($line[2] < 2000)
223
				continue;
224
			if ($line[2] > 65000)
225
				continue;
226
			$cmd = "/usr/sbin/pw userdel {$line[2]}";
227
			if($debug)
228
				log_error("Running: {$cmd}");
229
			mwexec($cmd);
230
		}
231
		pclose($fd);
232
	}
233

    
234
	/* remove local groups to avoid gid conflicts */
235
	$gids = array();
236
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
237
	if ($fd) {
238
		while (!feof($fd)) {
239
			$line = explode(":",fgets($fd));
240
			if (!strncmp($line[0], "_", 1))
241
				continue;
242
			if ($line[2] < 2000)
243
				continue;
244
			if ($line[2] > 65000)
245
				continue;
246
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
247
			if($debug)
248
				log_error("Running: {$cmd}");
249
			mwexec($cmd);
250
		}
251
		pclose($fd);
252
	}
253

    
254
	/* make sure the all group exists */
255
	$allgrp = getGroupEntryByGID(1998);
256
	local_group_set($allgrp, true);
257

    
258
	/* sync all local users */
259
	if (is_array($config['system']['user']))
260
		foreach ($config['system']['user'] as $user)
261
			local_user_set($user);
262

    
263
	/* sync all local groups */
264
	if (is_array($config['system']['group']))
265
		foreach ($config['system']['group'] as $group)
266
			local_group_set($group);
267

    
268
	conf_mount_ro();
269

    
270
}
271

    
272
function local_user_set(& $user) {
273
	global $g, $debug;
274

    
275
	conf_mount_rw();
276

    
277
	$home_base = "/home/";	
278
	$user_uid = $user['uid'];
279
	$user_name = $user['name'];
280
	$user_home = "{$home_base}{$user_name}";
281
	$user_shell = "/etc/rc.initial";
282
	$user_group = "nobody";
283

    
284
	// Ensure $home_base exists and is writable
285
	if (!is_dir($home_base)) 
286
		mkdir($home_base, 0755);
287

    
288
	$lock_account = false;
289
	/* configure shell type */
290
	/* Cases here should be ordered by most privileged to least privileged. */
291
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
292
		$user_shell = "/bin/tcsh";
293
	} elseif (userHasPrivilege($user, "user-copy-files")) {
294
		$user_shell = "/usr/local/bin/scponly";
295
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
296
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
297
	} else {
298
		$user_shell = "/sbin/nologin";
299
		$lock_account = true;
300
	}
301

    
302
	/* Lock out disabled or expired users, unless it's root/admin. */
303
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
304
		$user_shell = "/sbin/nologin";
305
		$lock_account = true;
306
	}
307

    
308
	/* root user special handling */
309
	if ($user_uid == 0) {
310
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
311
		if($debug)
312
			log_error("Running: {$cmd}");
313
		$fd = popen($cmd, "w");
314
		fwrite($fd, $user['password']);
315
		pclose($fd);
316
		$user_group = "wheel";
317
		$user_home = "/root";
318
		$user_shell = "/etc/rc.initial";
319
	}
320

    
321
	/* read from pw db */
322
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
323
	$pwread = fgets($fd);
324
	pclose($fd);
325

    
326
	/* determine add or mod */
327
	if (!strncmp($pwread, "pw:", 3)) {
328
		$user_op = "useradd -m -k /etc/skel -o";
329
	} else {
330
		$user_op = "usermod";
331
	}
332

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

    
338
	if($debug)
339
		log_error("Running: {$cmd}");
340
	$fd = popen($cmd, "w");
341
	fwrite($fd, $user['password']);
342
	pclose($fd);
343

    
344
	/* create user directory if required */
345
	if (!is_dir($user_home)) {
346
		mkdir($user_home, 0700);
347
		mwexec("cp /root/.* {$home_base}/");
348
	}
349
	chown($user_home, $user_name);
350
	chgrp($user_home, $user_group);
351

    
352
	/* write out ssh authorized key file */
353
	if($user['authorizedkeys']) {
354
		if (!is_dir("{$user_home}/.ssh")) {
355
			mkdir("{$user_home}/.ssh", 0700);
356
			chown("{$user_home}/.ssh", $user_name);
357
		}
358
		$keys = base64_decode($user['authorizedkeys']);
359
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
360
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
361
	}
362

    
363
	$un = $lock_account ? "" : "un";
364
	exec("/usr/sbin/pw {$un}lock -q {$user_name}");
365
	
366
	conf_mount_ro();
367
}
368

    
369
function local_user_del($user) {
370
	global $debug;
371

    
372
	/* remove all memberships */
373
	local_user_set_groups($user);
374

    
375
	/* Don't remove /root */
376
	if ($user['uid'] != 0)
377
		$rmhome = "-r";
378

    
379
	/* delete from pw db */
380
	$cmd = "/usr/sbin/pw userdel {$user['name']} {$rmhome}";
381

    
382
	if($debug)
383
		log_error("Running: {$cmd}");
384
	mwexec($cmd);
385

    
386
	/* Delete user from groups needs a call to write_config() */
387
	local_group_del_user($user);
388
}
389

    
390
function local_user_set_password(& $user, $password) {
391

    
392
	$user['password'] = crypt($password);
393
	$user['md5-hash'] = md5($password);
394

    
395
	// Converts ascii to unicode.
396
	$astr = (string) $password;
397
	$ustr = '';
398
	for ($i = 0; $i < strlen($astr); $i++) {
399
		$a = ord($astr{$i}) << 8;
400
		$ustr.= sprintf("%X", $a);
401
	}
402

    
403
	// Generate the NT-HASH from the unicode string
404
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
405
}
406

    
407
function local_user_get_groups($user, $all = false) {
408
	global $debug, $config;
409

    
410
	$groups = array();
411
	if (!is_array($config['system']['group']))
412
		return $groups;
413

    
414
	foreach ($config['system']['group'] as $group)
415
		if ( $all || ( !$all && ($group['name'] != "all")))
416
			if (is_array($group['member']))
417
				if (in_array($user['uid'], $group['member']))
418
					$groups[] = $group['name'];
419

    
420
	if ( $all )
421
		$groups[] = "all";
422

    
423
	sort($groups);
424

    
425
	return $groups;
426
	
427
}
428

    
429
function local_user_set_groups($user, $new_groups = NULL ) {
430
	global $debug, $config, $groupindex;
431

    
432
	if (!is_array($config['system']['group']))
433
		return;
434

    
435
	$cur_groups = local_user_get_groups($user, true);
436
	$mod_groups = array();
437

    
438
	if (!is_array($new_groups))
439
		$new_groups = array();
440

    
441
	if (!is_array($cur_groups))
442
		$cur_groups = array();
443

    
444
	/* determine which memberships to add */
445
	foreach ($new_groups as $groupname) {
446
		if (in_array($groupname,$cur_groups))
447
			continue;
448
		$group = & $config['system']['group'][$groupindex[$groupname]];
449
		$group['member'][] = $user['uid'];
450
		$mod_groups[] = $group;
451
	}
452

    
453
	/* determine which memberships to remove */
454
	foreach ($cur_groups as $groupname) {
455
		if (in_array($groupname,$new_groups))
456
			continue;
457
		if (!isset($config['system']['group'][$groupindex[$groupname]]))
458
			continue;
459
		$group = & $config['system']['group'][$groupindex[$groupname]];
460
		if (is_array($group['member'])) {
461
			$index = array_search($user['uid'], $group['member']);
462
			array_splice($group['member'], $index, 1);
463
			$mod_groups[] = $group;
464
		}
465
	}
466

    
467
	/* sync all modified groups */
468
	foreach ($mod_groups as $group)
469
		local_group_set($group);
470
}
471

    
472
function local_group_del_user($user) {
473
	global $config;
474

    
475
	if (!is_array($config['system']['group']))
476
                return;
477

    
478
        foreach ($config['system']['group'] as $group) {
479
		if (is_array($group['member'])) {
480
			foreach ($group['member'] as $idx => $uid) {
481
				if ($user['uid'] == $uid)
482
					unset($config['system']['group']['member'][$idx]);
483
			}
484
		}
485
	}
486
}
487

    
488
function local_group_set($group, $reset = false) {
489
	global $debug;
490

    
491
	$group_name = $group['name'];
492
	$group_gid = $group['gid'];
493
	$group_members = "''";
494
	if (!$reset && !empty($group['member']) && count($group['member']) > 0)
495
		$group_members = implode(",",$group['member']);
496

    
497
	/* read from group db */
498
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
499
	$pwread = fgets($fd);
500
	pclose($fd);
501

    
502
	/* determine add or mod */
503
	if (!strncmp($pwread, "pw:", 3))
504
		$group_op = "groupadd";
505
	else
506
		$group_op = "groupmod";
507

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

    
511
	if($debug)
512
		log_error("Running: {$cmd}");
513
	mwexec($cmd);
514

    
515
}
516

    
517
function local_group_del($group) {
518
	global $debug;
519

    
520
	/* delete from group db */
521
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
522

    
523
	if($debug)
524
		log_error("Running: {$cmd}");
525
	mwexec($cmd);
526
}
527

    
528
function ldap_test_connection($authcfg) {
529
	global $debug, $config, $g;
530

    
531
	if ($authcfg) {
532
                if (strstr($authcfg['ldap_urltype'], "Standard"))
533
                        $ldapproto = "ldap";
534
                else
535
                        $ldapproto = "ldaps";
536
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
537
                $ldapport           = $authcfg['ldap_port'];
538
                $ldapbasedn         = $authcfg['ldap_basedn'];
539
                $ldapbindun         = $authcfg['ldap_binddn'];
540
                $ldapbindpw         = $authcfg['ldap_bindpw'];
541
        } else
542
		return false;
543

    
544
        /* first check if there is even an LDAP server populated */
545
        if(!$ldapserver)
546
                return false;
547

    
548
        /* connect and see if server is up */
549
        putenv('LDAPTLS_REQCERT=never');
550
        $error = false;
551
        if (empty($ldapport)) {
552
                if (!($ldap = ldap_connect($ldapserver)))
553
                        $error = true;
554
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
555
                $error = true;
556

    
557
        if ($error == true) {
558
                log_error("ERROR!  Could not connect to server {$ldapname}.");
559
                return false;
560
        }
561

    
562
	return true;
563
}
564

    
565
function ldap_test_bind($authcfg) {
566
	global $debug, $config, $g;
567

    
568
	if ($authcfg) {
569
                if (strstr($authcfg['ldap_urltype'], "Standard"))
570
                        $ldapproto = "ldap";
571
                else
572
                        $ldapproto = "ldaps";
573
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
574
                $ldapport           = $authcfg['ldap_port'];
575
                $ldapbasedn         = $authcfg['ldap_basedn'];
576
                $ldapbindun         = $authcfg['ldap_binddn'];
577
                $ldapbindpw         = $authcfg['ldap_bindpw'];
578
                $ldapver            = $authcfg['ldap_protver'];
579
		if (empty($ldapbndun) || empty($ldapbindpw))
580
                        $ldapanon = true;
581
                else
582
                        $ldapanon = false;
583
	} else
584
		return false;
585

    
586
	/* first check if there is even an LDAP server populated */
587
        if(!$ldapserver)
588
                return false;
589

    
590
        /* connect and see if server is up */
591
        putenv('LDAPTLS_REQCERT=never');
592
        $error = false;
593
        if (empty($ldapport)) {
594
                if (!($ldap = ldap_connect($ldapserver)))
595
                        $error = true;
596
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
597
                $error = true;
598

    
599
        if ($error == true) {
600
                log_error("ERROR!  Could not connect to server {$ldapname}.");
601
                return false;
602
        }
603

    
604
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
605
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
606
 
607
	if ($ldapanon == true) {
608
		if (!($res = @ldap_bind($ldap))) {
609
			@ldap_close($ldap);
610
			return false;
611
		}
612
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
613
		@ldap_close($ldap);
614
		return false;
615
	}
616

    
617
	@ldap_unbind($ldap);
618

    
619
	return true;
620
}
621

    
622
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
623
	global $debug, $config, $g;
624

    
625
	if(!function_exists("ldap_connect"))
626
		return;
627

    
628
	$ous = array();
629

    
630
	if ($authcfg) {
631
                if (strstr($authcfg['ldap_urltype'], "Standard"))
632
                        $ldapproto = "ldap";
633
                else
634
                        $ldapproto = "ldaps";
635
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
636
                $ldapport           = $authcfg['ldap_port'];
637
                $ldapbasedn         = $authcfg['ldap_basedn'];
638
                $ldapbindun         = $authcfg['ldap_binddn'];
639
                $ldapbindpw         = $authcfg['ldap_bindpw'];
640
                $ldapver            = $authcfg['ldap_protver'];
641
		if (empty($ldapbindun) || empty($ldapbindpw))
642
                        $ldapanon = true;
643
                else
644
                        $ldapanon = false;
645
                $ldapname           = $authcfg['name'];
646
                $ldapfallback       = false;
647
		$ldapscope          = $authcfg['ldap_scope'];
648
        } else
649
		return false;
650

    
651
        /* first check if there is even an LDAP server populated */
652
        if(!$ldapserver) {
653
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
654
                return $ous;
655
        }
656

    
657
	/* connect and see if server is up */
658
        putenv('LDAPTLS_REQCERT=never');
659
        $error = false;
660
        if (empty($ldapport)) {
661
                if (!($ldap = ldap_connect($ldapserver)))
662
                        $error = true;
663
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
664
                $error = true;
665

    
666
        if ($error == true) {
667
		log_error("ERROR!  Could not connect to server {$ldapname}.");
668
                return $ous;
669
        }
670

    
671
	$ldapfilter = "(|(ou=*)(cn=Users))";
672

    
673
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
674
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
675

    
676
	if ($ldapanon == true) {
677
                if (!($res = @ldap_bind($ldap))) {
678
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
679
			@ldap_close($ldap);
680
                        return $ous;
681
		}
682
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
683
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
684
		@ldap_close($ldap);
685
		return $ous;
686
	}
687

    
688
	if ($ldapscope == "one")
689
		$ldapfunc = "ldap_list";
690
	else
691
		$ldapfunc = "ldap_search";
692

    
693
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
694
	$info = @ldap_get_entries($ldap, $search);
695

    
696
	if (is_array($info)) {
697
		foreach ($info as $inf) {
698
			if (!$show_complete_ou) {
699
				$inf_split = split(",", $inf['dn']);
700
				$ou = $inf_split[0];
701
				$ou = str_replace("OU=","", $ou);
702
				$ou = str_replace("CN=","", $ou);
703
			} else
704
				if($inf['dn'])
705
					$ou = $inf['dn'];
706
			if($ou)
707
				$ous[] = $ou;
708
		}
709
	}
710

    
711
	@ldap_unbind($ldap);
712

    
713
	return $ous;
714
}
715

    
716
function ldap_get_groups($username, $authcfg) {
717
	global $debug, $config;
718
	
719
	if(!function_exists("ldap_connect"))
720
		return;
721
	
722
	if(!$username) 
723
		return false;
724

    
725
	if(stristr($username, "@")) {
726
		$username_split=split("\@", $username);
727
		$username = $username_split[0];		
728
	}
729

    
730
	if(stristr($username, "\\")) {
731
		$username_split=split("\\", $username);
732
		$username = $username_split[0];        
733
	}    
734
	
735
	//log_error("Getting LDAP groups for {$username}.");
736
        if ($authcfg) {
737
                if (strstr($authcfg['ldap_urltype'], "Standard"))
738
                        $ldapproto = "ldap";
739
                else
740
                        $ldapproto = "ldaps";
741
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
742
                $ldapport           = $authcfg['ldap_port'];
743
                $ldapbasedn         = $authcfg['ldap_basedn'];
744
                $ldapbindun         = $authcfg['ldap_binddn'];
745
                $ldapbindpw         = $authcfg['ldap_bindpw'];
746
                $ldapauthcont       = $authcfg['ldap_authcn'];
747
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
748
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
749
                $ldapfilter         = "({$ldapnameattribute}={$username})";
750
                $ldaptype           = "";
751
                $ldapver            = $authcfg['ldap_protver'];
752
		if (empty($ldapbindun) || empty($ldapbindpw))
753
                        $ldapanon = true;
754
                else
755
                        $ldapanon = false;
756
                $ldapname           = $authcfg['name'];
757
                $ldapfallback       = false;
758
		$ldapscope          = $authcfg['ldap_scope'];
759
	} else
760
		return false;
761

    
762
	$ldapdn             = $_SESSION['ldapdn'];
763

    
764
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
765
	$ldapgroupattribute = strtolower($ldapgroupattribute);
766
	$memberof = array();
767

    
768
	/* connect and see if server is up */
769
	putenv('LDAPTLS_REQCERT=never');
770
	$error = false;
771
        if (empty($ldapport)) {
772
                if (!($ldap = ldap_connect($ldapserver)))
773
                        $error = true;
774
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
775
                $error = true;
776

    
777
	if ($error == true) {
778
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
779
                return memberof;
780
        }
781
    
782
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
783
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
784

    
785
	/* bind as user that has rights to read group attributes */
786
	if ($ldapanon == true) {
787
                if (!($res = @ldap_bind($ldap))) {
788
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
789
			@ldap_close($ldap);
790
                        return false;
791
		}
792
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
793
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
794
		@ldap_close($ldap);
795
		return memberof;
796
	}
797

    
798
	/* get groups from DN found */
799
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
800
	/* since we know the DN is in $_SESSION['ldapdn'] */
801
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
802
	if ($ldapscope == "one")
803
                $ldapfunc = "ldap_list";
804
        else
805
                $ldapfunc = "ldap_search";
806

    
807
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
808
	$info      = @ldap_get_entries($ldap, $search);
809

    
810
	$countem = $info["count"];	
811
	
812
	if(is_array($info[0][$ldapgroupattribute])) {
813
		/* Iterate through the groups and throw them into an array */
814
		foreach ($info[0][$ldapgroupattribute] as $member) {
815
			if (stristr($member, "CN=") !== false) {
816
				$membersplit = split(",", $member);
817
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
818
			}
819
		}
820
	}
821
	
822
	/* Time to close LDAP connection */
823
	@ldap_unbind($ldap);
824
	
825
	$groups = print_r($memberof,true);
826
	
827
	//log_error("Returning groups ".$groups." for user $username");
828
	
829
	return $memberof;
830
}
831

    
832
function ldap_backed($username, $passwd, $authcfg) {
833
	global $debug, $config;
834
	
835
	if(!$username) 
836
		return;
837

    
838
	if(!function_exists("ldap_connect"))
839
		return;
840

    
841
	if(stristr($username, "@")) {
842
		$username_split=split("\@", $username);
843
		$username = $username_split[0];        
844
	}
845
	if(stristr($username, "\\")) {
846
		$username_split=split("\\", $username);
847
		$username = $username_split[0];        
848
	}
849

    
850
	if ($authcfg) {
851
		if (strstr($authcfg['ldap_urltype'], "Standard"))
852
			$ldapproto = "ldap";
853
		else
854
			$ldapproto = "ldaps";
855
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
856
		$ldapport	    = $authcfg['ldap_port'];
857
                $ldapbasedn         = $authcfg['ldap_basedn'];
858
                $ldapbindun         = $authcfg['ldap_binddn'];
859
                $ldapbindpw         = $authcfg['ldap_bindpw'];
860
		if (empty($ldapbindun) || empty($ldapbindpw))
861
			$ldapanon = true;
862
		else
863
			$ldapanon = false;
864
                $ldapauthcont       = $authcfg['ldap_authcn'];
865
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
866
                $ldapfilter         = "({$ldapnameattribute}={$username})";
867
                $ldaptype           = "";
868
                $ldapver            = $authcfg['ldap_protver'];
869
		$ldapname	    = $authcfg['name'];
870
		$ldapscope	    = $authcfg['ldap_scope'];
871
	} else
872
		return false;
873

    
874
	/* first check if there is even an LDAP server populated */ 
875
	if(!$ldapserver) {
876
		if ($ldapfallback) {
877
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
878
			return local_backed($username, $passwd);
879
		} else
880
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
881

    
882
		return false;
883
	}
884
	
885
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
886
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
887

    
888
	/* Make sure we can connect to LDAP */
889
	putenv('LDAPTLS_REQCERT=never');
890
	$error = false;
891
	if (empty($ldapport)) {
892
		if (!($ldap = ldap_connect($ldapserver)))
893
			$error = true;
894
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
895
		$error = true;
896

    
897
	if ($error == true) {
898
		log_error("ERROR!  Could not connect to server {$ldapname}.");
899
		return false;
900
	}
901

    
902
	/* ok, its up.  now, lets bind as the bind user so we can search it */
903
	$error = false;
904
	if ($ldapanon == true) {
905
                if (!($res = @ldap_bind($ldap)))
906
                        $error = true;
907
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
908
		$error = true;
909

    
910
	if ($error == true) {
911
		@ldap_close($ldap);
912
		log_error("ERROR! Could not bind to server {$ldapname}.");
913
		return false;
914
	}
915
	
916
	/* Get LDAP Authcontainers and split em up. */
917
	$ldac_splits = split(";", $ldapauthcont);
918
	
919
	/* setup the usercount so we think we havn't found anyone yet */
920
	$usercount  = 0;
921

    
922
	/*****************************************************************/
923
	/*  We First find the user based on username and filter          */
924
	/*  Then, once we find the first occurance of that person        */
925
	/*  We set seesion variables to ponit to the OU and DN of the    */
926
	/*  Person.  To later be used by ldap_get_groups.                */
927
	/*  that way we don't have to search twice.                      */
928
	/*****************************************************************/
929
	log_error("Now Searching for {$username} in directory.");
930
	/* Iterate through the user containers for search */
931
	foreach ($ldac_splits as $i => $ldac_split) {
932
		/* Make sure we just use the first user we find */
933
		log_error("Now Searching in server {$ldapname}, container {$ldac_split} with filter {$ldapfilter}.");
934
		if ($ldapscope == "one")
935
			$ldapfunc = "ldap_list";
936
		else
937
			$ldapfunc = "ldap_search";
938
		/* Support legacy auth container specification. */
939
		if (stristr($ldac_split, "DC="))
940
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
941
		else
942
			$search  = @$ldapfunc($ldap,"{$ldac_split},{$ldapbasedn}",$ldapfilter);
943
		if (!$search) {
944
			log_error("Search resulted in error: " . ldap_error($ldap));
945
			continue;
946
		}
947
		$info	 = ldap_get_entries($ldap,$search);
948
		$matches = $info['count'];
949
		if ($matches == 1){
950
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
951
			$_SESSION['ldapou'] = $ldac_split[$i];
952
			$_SESSION['ldapon'] = "true";
953
			$usercount = 1;
954
			break;
955
		}
956
	}
957

    
958
	if ($usercount != 1){
959
		@ldap_unbind($ldap);
960
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
961
		return false;                         
962
	}
963

    
964
	/* Now lets bind as the user we found */
965
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
966
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
967
		@ldap_unbind($ldap);
968
		return false;
969
	}
970

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

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

    
976
	return true;
977
}
978

    
979
function radius_backed($username, $passwd, $authcfg){
980
	global $debug, $config;
981
	$ret = false;
982

    
983
	require_once("radius.inc");
984

    
985
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
986
	if ($authcfg) {
987
		$radiusservers = array();
988
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
989
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
990
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
991
	} else
992
		return false;
993

    
994
	/* Add a new servers to our instance */
995
	foreach ($radiusservers as $radsrv)
996
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
997

    
998
	if (PEAR::isError($rauth->start())) {
999
		$retvalue['auth_val'] = 1;
1000
		$retvalue['error'] = $rauth->getError();
1001
		if ($debug)
1002
			printf("Radius start: %s<br>\n", $retvalue['error']);
1003
	}
1004

    
1005
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1006

    
1007
	/* Send request */
1008
	$result = $rauth->send();
1009
	if (PEAR::isError($result)) {
1010
		$retvalue['auth_val'] = 1;
1011
		$retvalue['error'] = $result->getMessage();
1012
		if ($debug)
1013
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
1014
	} else if ($result === true) {
1015
		$retvalue['auth_val'] = 2;
1016
		if ($debug)
1017
			printf(gettext("Radius Auth succeeded")."<br>\n");
1018
		$ret = true;
1019
	} else {
1020
		$retvalue['auth_val'] = 3;
1021
		if ($debug)
1022
			printf(gettext("Radius Auth rejected")."<br>\n");
1023
	}
1024

    
1025
	// close OO RADIUS_AUTHENTICATION
1026
	$rauth->close();
1027

    
1028
	return $ret;
1029
}
1030

    
1031
function get_user_expiration_date($username) {
1032
	$user = getUserEntry($username);
1033
	if ($user['expires']) 
1034
		return $user['expires'];
1035
}
1036

    
1037
function is_account_expired($username) {
1038
	$expirydate = get_user_expiration_date($username);
1039
	if ($expirydate) {
1040
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1041
			return true;
1042
	}
1043

    
1044
	return false;
1045
}
1046

    
1047
function is_account_disabled($username) {
1048
	$user = getUserEntry($username);
1049
	if (isset($user['disabled']))
1050
		return true;
1051

    
1052
	return false;
1053
}
1054

    
1055
function auth_get_authserver($name) {
1056
        global $config;
1057

    
1058
        if (is_array($config['system']['authserver'])) {
1059
                foreach ($config['system']['authserver'] as $authcfg) {
1060
                        if ($authcfg['name'] == $name)
1061
                                return $authcfg;
1062
                }
1063
        }
1064
	if ($name == "Local Database")
1065
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1066
}
1067

    
1068
function auth_get_authserver_list() {
1069
        global $config;
1070

    
1071
	$list = array();
1072

    
1073
        if (is_array($config['system']['authserver'])) {
1074
                foreach ($config['system']['authserver'] as $authcfg) {
1075
			/* Add support for disabled entries? */
1076
			$list[$authcfg['name']] = $authcfg;
1077
                }
1078
        }
1079

    
1080
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1081
	return $list;
1082
}
1083

    
1084
function getUserGroups($username, $authcfg) {
1085
	global $config;
1086

    
1087
	$allowed_groups = array();
1088

    
1089
	switch($authcfg['type']) {
1090
        case 'ldap':
1091
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1092
		break;
1093
	case 'radius':
1094
		break;
1095
	default:
1096
		$user = getUserEntry($username);
1097
		$allowed_groups = @local_user_get_groups($user, true);
1098
		break;
1099
	}
1100

    
1101
	$member_groups = array();
1102
        if (is_array($config['system']['group'])) {
1103
                foreach ($config['system']['group'] as $group)
1104
                        if (in_array($group['name'], $allowed_groups))
1105
				$member_groups[] = $group['name'];
1106
	}
1107

    
1108
	return $member_groups;
1109
}
1110

    
1111
function authenticate_user($username, $password, $authcfg = NULL) {
1112

    
1113
	if (!$authcfg) {
1114
		return local_backed($username, $password);
1115
	}
1116

    
1117
	$authenticated = false;
1118
	switch($authcfg['type']) {
1119
        case 'ldap':
1120
                if (ldap_backed($username, $password, $authcfg))
1121
                        $authenticated = true;
1122
                break;
1123
        case 'radius':
1124
                if (radius_backed($username, $password, $authcfg))
1125
                        $authenticated = true;
1126
                break;
1127
        default:
1128
                /* lookup user object by name */
1129
                if (local_backed($username, $password))
1130
                        $authenticated = true;
1131
                break;
1132
        }
1133

    
1134
	return $authenticated;
1135
}
1136

    
1137
function session_auth() {
1138
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1139

    
1140
	session_start();
1141

    
1142
	/* Validate incoming login request */
1143
	if (isset($_POST['login'])) {
1144
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1145
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1146
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1147
			$_SESSION['Logged_In'] = "True";
1148
			$_SESSION['Username'] = $_POST['usernamefld'];
1149
			$_SESSION['last_access'] = time();
1150
			log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1151
			$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1152
			if (isset($_POST['postafterlogin']))
1153
				return true;
1154
			else {
1155
				if (empty($page))
1156
					$page = "/";
1157
				header("Location: {$page}");
1158
			}
1159
			exit;
1160
		} else {
1161
			/* give the user an error message */
1162
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1163
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1164
			if(isAjax()) {
1165
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1166
				return;
1167
			}
1168
		}
1169
	}
1170

    
1171
	/* Show login page if they aren't logged in */
1172
	if (empty($_SESSION['Logged_In']))
1173
		return false;
1174

    
1175
	/* If session timeout isn't set, we don't mark sessions stale */
1176
	if (!isset($config['system']['webgui']['session_timeout'])) {
1177
		/* Default to 4 hour timeout if one is not set */
1178
		if ($_SESSION['last_access'] < (time() - 14400)) {
1179
			$_GET['logout'] = true;
1180
			$_SESSION['Logout'] = true;
1181
		} else
1182
			$_SESSION['last_access'] = time();	
1183
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1184
		/* only update if it wasn't ajax */
1185
		if (!isAjax())
1186
			$_SESSION['last_access'] = time();
1187
	} else {
1188
		/* Check for stale session */
1189
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1190
			$_GET['logout'] = true;
1191
			$_SESSION['Logout'] = true;
1192
		} else {
1193
			/* only update if it wasn't ajax */
1194
			if (!isAjax())
1195
				$_SESSION['last_access'] = time();
1196
		}
1197
	}
1198

    
1199
	/* user hit the logout button */
1200
	if (isset($_GET['logout'])) {
1201

    
1202
		if ($_SESSION['Logout'])
1203
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1204
		else
1205
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1206

    
1207
		/* wipe out $_SESSION */
1208
		$_SESSION = array();
1209

    
1210
		if (isset($_COOKIE[session_name()]))
1211
			setcookie(session_name(), '', time()-42000, '/');
1212

    
1213
		/* and destroy it */
1214
		session_destroy();
1215

    
1216
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1217
		$scriptElms = count($scriptName);
1218
		$scriptName = $scriptName[$scriptElms-1];
1219

    
1220
		if (isAjax())
1221
			return false;
1222

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

    
1226
		return false;
1227
	}
1228

    
1229
	/*
1230
	 * this is for debugging purpose if you do not want to use Ajax
1231
	 * to submit a HTML form. It basically diables the observation
1232
	 * of the submit event and hence does not trigger Ajax.
1233
	 */
1234
	if ($_GET['disable_ajax'])
1235
		$_SESSION['NO_AJAX'] = "True";
1236

    
1237
	/*
1238
	 * Same to re-enable Ajax.
1239
	 */
1240
	if ($_GET['enable_ajax'])
1241
		unset($_SESSION['NO_AJAX']);
1242

    
1243
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1244
	return true;
1245
}
1246

    
1247
?>
(4-4/54)