Project

General

Profile

Download (33.6 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

    
50
require_once("config.gui.inc");
51

    
52
/* DNS Binding attack prevention.  http://redmine.pfsense.org/issues/708 */
53
if ($_SERVER['HTTP_HOST'] != $config['system']['hostname'] . "." . $config['system']['domain'] and
54
	$_SERVER['HTTP_HOST'] != $_SERVER['SERVER_ADDR'] and 
55
	$_SERVER['HTTP_HOST'] != $config['system']['hostname']) {
56
    display_error_form("501", "DNS Rebind attack detected, see http://en.wikipedia.org/wiki/DNS_rebinding");
57
    exit;
58
}
59

    
60
$groupindex = index_groups();
61
$userindex = index_users();
62

    
63
function index_groups() {
64
	global $g, $debug, $config, $groupindex;
65

    
66
	$groupindex = array();
67

    
68
	if (isset($config['system']['group'])) {
69
		$i = 0;
70
		foreach($config['system']['group'] as $groupent) {
71
			$groupindex[$groupent['name']] = $i;
72
			$i++;
73
		}
74
	}
75

    
76
	return ($groupindex);
77
}
78

    
79
function index_users() {
80
	global $g, $debug, $config;
81

    
82
	if (isset($config['system']['user'])) {
83
		$i = 0;
84
		foreach($config['system']['user'] as $userent) {
85
			$userindex[$userent['name']] = $i;
86
			$i++;
87
		}
88
	}
89

    
90
	return ($userindex);
91
}
92

    
93
function & getUserEntry($name) {
94
	global $debug, $config, $userindex;
95
	if (isset($userindex[$name]))
96
		return $config['system']['user'][$userindex[$name]];
97
}
98

    
99
function & getUserEntryByUID($uid) {
100
	global $debug, $config;
101
	foreach ($config['system']['user'] as & $user)
102
		if ($user['uid'] == $uid)
103
			return $user;
104

    
105
	return false;
106
}
107

    
108
function & getGroupEntry($name) {
109
	global $debug, $config, $groupindex;
110
	if (isset($groupindex[$name]))
111
		return $config['system']['group'][$groupindex[$name]];
112
}
113

    
114
function & getGroupEntryByGID($gid) {
115
	global $debug, $config;
116
	foreach ($config['system']['group'] as & $group)
117
		if ($group['gid'] == $gid)
118
			return $group;
119

    
120
	return false;
121
}
122

    
123
function get_user_privileges(& $user) {
124

    
125
        $privs = $user['priv'];
126
        if (!is_array($privs))
127
                $privs = array();
128

    
129
        $names = local_user_get_groups($user, true);
130

    
131
        foreach ($names as $name) {
132
                $group = getGroupEntry($name);
133
                if (is_array($group['priv']))
134
                        $privs = array_merge( $privs, $group['priv']);
135
        }
136

    
137
        return $privs;
138
}
139

    
140
function userHasPrivilege($userent, $privid = false) {
141

    
142
        if (!$privid || !is_array($userent))
143
                return false;
144

    
145
        $privs = get_user_privileges($userent);
146

    
147
        if (!is_array($privs))
148
                return false;
149

    
150
        if (!in_array($privid, $privs))
151
                return false;
152

    
153
        return true;
154
}
155

    
156
function local_backed($username, $passwd) {
157

    
158
	$user = getUserEntry($username);
159
	if (!$user)
160
		return false;
161

    
162
	if (is_account_disabled($username) || is_account_expired($username))
163
		return false;
164

    
165
	if ($user['password'])
166
	{
167
		$passwd = crypt($passwd, $user['password']);
168
		if ($passwd == $user['password'])
169
			return true;
170
	}
171

    
172
	if ($user['md5-hash'])
173
	{
174
		$passwd = md5($passwd);
175
		if ($passwd == $user['md5-hash'])
176
			return true;
177
	}
178

    
179
	return false;
180
}
181

    
182
function local_sync_accounts() {
183
	global $debug, $config;
184
	conf_mount_rw();
185

    
186
	/* remove local users to avoid uid conflicts */
187
	$fd = popen("/usr/sbin/pw usershow -a", "r");
188
	if ($fd) {
189
		while (!feof($fd)) {
190
			$line = explode(":",fgets($fd));
191
			if (!strncmp($line[0], "_", 1))
192
				continue;
193
			if ($line[2] < 2000)
194
				continue;
195
			if ($line[2] > 65000)
196
				continue;
197
			$cmd = "/usr/sbin/pw userdel {$line[2]}";
198
			if($debug)
199
				log_error("Running: {$cmd}");
200
			mwexec($cmd);
201
		}
202
		pclose($fd);
203
	}
204

    
205
	/* remove local groups to avoid gid conflicts */
206
	$gids = array();
207
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
208
	if ($fd) {
209
		while (!feof($fd)) {
210
			$line = explode(":",fgets($fd));
211
			if (!strncmp($line[0], "_", 1))
212
				continue;
213
			if ($line[2] < 2000)
214
				continue;
215
			if ($line[2] > 65000)
216
				continue;
217
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
218
			if($debug)
219
				log_error("Running: {$cmd}");
220
			mwexec($cmd);
221
		}
222
		pclose($fd);
223
	}
224

    
225
	/* make sure the all group exists */
226
	$allgrp = getGroupEntryByGID(1998);
227
	local_group_set($allgrp, true);
228

    
229
	/* sync all local users */
230
	if (is_array($config['system']['user']))
231
		foreach ($config['system']['user'] as $user)
232
			local_user_set($user);
233

    
234
	/* sync all local groups */
235
	if (is_array($config['system']['group']))
236
		foreach ($config['system']['group'] as $group)
237
			local_group_set($group);
238

    
239
	conf_mount_ro();
240

    
241
}
242

    
243
function local_user_set(& $user) {
244
	global $g, $debug;
245

    
246
	conf_mount_rw();
247

    
248
	$home_base = "/home/";	
249
	$user_uid = $user['uid'];
250
	$user_name = $user['name'];
251
	$user_home = "{$home_base}{$user_name}";
252
	$user_shell = "/etc/rc.initial";
253
	$user_group = "nobody";
254

    
255
	// Ensure $home_base exists and is writable
256
	if (!is_dir($home_base)) 
257
		mkdir($home_base, 0755);
258

    
259
	/* configure shell type */
260
	if (!(userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all"))) {
261
		if (!userHasPrivilege($user, "user-copy-files"))
262
			$user_shell = "/sbin/nologin";
263
		else
264
			$user_shell = "/usr/local/bin/scponly";
265
	} else {
266
		$user_shell = "/bin/tcsh";
267
	}
268

    
269
	/* root user special handling */
270
	if ($user_uid == 0) {
271
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
272
		if($debug)
273
			log_error("Running: {$cmd}");
274
		$fd = popen($cmd, "w");
275
		fwrite($fd, $user['password']);
276
		pclose($fd);
277
		$user_group = "wheel";
278
		$user_home = "/root";
279
		$user_shell = "/etc/rc.initial";
280
	}
281

    
282
	/* read from pw db */
283
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
284
	$pwread = fgets($fd);
285
	pclose($fd);
286

    
287
	/* determine add or mod */
288
	if (!strncmp($pwread, "pw:", 3)) {
289
		$user_op = "useradd -m -k /usr/share/skel -o";
290
	} else {
291
		$user_op = "usermod";
292
	}
293

    
294
	/* add or mod pw db */
295
	$cmd = "/usr/sbin/pw {$user_op} -q -u {$user_uid} -n {$user_name}".
296
			" -g {$user_group} -s {$user_shell} -d {$user_home}".
297
			" -c ".escapeshellarg($user['fullname'])." -H 0 2>&1";
298

    
299
	if($debug)
300
		log_error("Running: {$cmd}");
301
	$fd = popen($cmd, "w");
302
	fwrite($fd, $user['password']);
303
	pclose($fd);
304

    
305
	/* create user directory if required */
306
	if (!is_dir($user_home)) {
307
		mkdir($user_home, 0700);
308
		mwexec("cp /root/.* {$home_base}/");
309
	}
310
	chown($user_home, $user_name);
311
	chgrp($user_home, $user_group);
312

    
313
	/* write out ssh authorized key file */
314
	if($user['authorizedkeys']) {
315
		if (!is_dir("{$user_home}/.ssh")) {
316
			mkdir("{$user_home}/.ssh", 0700);
317
			chown("{$user_home}/.ssh", $user_name);
318
		}
319
		$keys = base64_decode($user['authorizedkeys']);
320
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
321
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
322
	}
323
	
324
	conf_mount_ro();
325
}
326

    
327
function local_user_del($user) {
328
	global $debug;
329

    
330
	/* remove all memberships */
331
	local_user_set_groups($user);
332

    
333
	/* delete from pw db */
334
	$cmd = "/usr/sbin/pw userdel {$user['name']}";
335

    
336
	if($debug)
337
		log_error("Running: {$cmd}");
338
	mwexec($cmd);
339

    
340
	/* Delete user from groups needs a call to write_config() */
341
	local_group_del_user($user);
342
}
343

    
344
function local_user_set_password(& $user, $password) {
345

    
346
	$user['password'] = crypt($password);
347
	$user['md5-hash'] = md5($password);
348

    
349
	// Converts ascii to unicode.
350
	$astr = (string) $password;
351
	$ustr = '';
352
	for ($i = 0; $i < strlen($astr); $i++) {
353
		$a = ord($astr{$i}) << 8;
354
		$ustr.= sprintf("%X", $a);
355
	}
356

    
357
	// Generate the NT-HASH from the unicode string
358
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
359
}
360

    
361
function local_user_get_groups($user, $all = false) {
362
	global $debug, $config;
363

    
364
	$groups = array();
365
	if (!is_array($config['system']['group']))
366
		return $groups;
367

    
368
	foreach ($config['system']['group'] as $group)
369
		if ( $all || ( !$all && ($group['name'] != "all")))
370
			if (is_array($group['member']))
371
				if (in_array($user['uid'], $group['member']))
372
					$groups[] = $group['name'];
373

    
374
	sort($groups);
375

    
376
	return $groups;
377
	
378
}
379

    
380
function local_user_set_groups($user, $new_groups = NULL ) {
381
	global $debug, $config, $groupindex;
382

    
383
	if (!is_array($config['system']['group']))
384
		return;
385

    
386
	$cur_groups = local_user_get_groups($user);
387
	$mod_groups = array();
388

    
389
	if (!is_array($new_groups))
390
		$new_groups = array();
391

    
392
	if (!is_array($cur_groups))
393
		$cur_groups = array();
394

    
395
	/* determine which memberships to add */
396
	foreach ($new_groups as $groupname) {
397
		if (in_array($groupname,$cur_groups))
398
			continue;
399
		$group = & $config['system']['group'][$groupindex[$groupname]];
400
		$group['member'][] = $user['uid'];
401
		$mod_groups[] = $group;
402
	}
403

    
404
	/* determine which memberships to remove */
405
	foreach ($cur_groups as $groupname) {
406
		if (in_array($groupname,$new_groups))
407
			continue;
408
		$group = & $config['system']['group'][$groupindex[$groupname]];
409
		$index = array_search($user['uid'], $group['member']);
410
		array_splice($group['member'], $index, 1);
411
		$mod_groups[] = $group;
412
	}
413

    
414
	/* sync all modified groups */
415
	foreach ($mod_groups as $group)
416
		local_group_set($group);
417
}
418

    
419
function local_group_del_user($user) {
420
	global $config;
421

    
422
	if (!is_array($config['system']['group']))
423
                return;
424

    
425
        foreach ($config['system']['group'] as $group) {
426
		if (is_array($group['member'])) {
427
			foreach ($group['member'] as $idx => $uid) {
428
				if ($user['uid'] == $uid)
429
					unset($config['system']['group']['member'][$idx]);
430
			}
431
		}
432
	}
433
}
434

    
435
function local_group_set($group, $reset = false) {
436
	global $debug;
437

    
438
	$group_name = $group['name'];
439
	$group_gid = $group['gid'];
440
	$group_members = "''";
441
	if (!$reset && count($group['member']))
442
		$group_members = implode(",",$group['member']);
443

    
444
	/* read from group db */
445
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
446
	$pwread = fgets($fd);
447
	pclose($fd);
448

    
449
	/* determine add or mod */
450
	if (!strncmp($pwread, "pw:", 3))
451
		$group_op = "groupadd";
452
	else
453
		$group_op = "groupmod";
454

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

    
458
	if($debug)
459
		log_error("Running: {$cmd}");
460
	mwexec($cmd);
461

    
462
}
463

    
464
function local_group_del($group) {
465
	global $debug;
466

    
467
	/* delete from group db */
468
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
469

    
470
	if($debug)
471
		log_error("Running: {$cmd}");
472
	mwexec($cmd);
473
}
474

    
475
function ldap_test_connection($authcfg) {
476
	global $debug, $config, $g;
477

    
478
	if ($authcfg) {
479
                if (strstr($authcfg['ldap_urltype'], "Standard"))
480
                        $ldapproto = "ldap";
481
                else
482
                        $ldapproto = "ldaps";
483
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
484
                $ldapport           = $authcfg['ldap_port'];
485
                $ldapbasedn         = $authcfg['ldap_basedn'];
486
                $ldapbindun         = $authcfg['ldap_binddn'];
487
                $ldapbindpw         = $authcfg['ldap_bindpw'];
488
        } else
489
		return false;
490

    
491
        /* first check if there is even an LDAP server populated */
492
        if(!$ldapserver)
493
                return false;
494

    
495
        /* connect and see if server is up */
496
        putenv('LDAPTLS_REQCERT=never');
497
        $error = false;
498
        if (empty($ldapport)) {
499
                if (!($ldap = ldap_connect($ldapserver)))
500
                        $error = true;
501
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
502
                $error = true;
503

    
504
        if ($error == true) {
505
                log_error("ERROR!  Could not connect to server {$ldapname}.");
506
                return false;
507
        }
508

    
509
	return true;
510
}
511

    
512
function ldap_test_bind($authcfg) {
513
	global $debug, $config, $g;
514

    
515
	if ($authcfg) {
516
                if (strstr($authcfg['ldap_urltype'], "Standard"))
517
                        $ldapproto = "ldap";
518
                else
519
                        $ldapproto = "ldaps";
520
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
521
                $ldapport           = $authcfg['ldap_port'];
522
                $ldapbasedn         = $authcfg['ldap_basedn'];
523
                $ldapbindun         = $authcfg['ldap_binddn'];
524
                $ldapbindpw         = $authcfg['ldap_bindpw'];
525
                $ldapver            = $authcfg['ldap_protver'];
526
		if (empty($ldapbndun) || empty($ldapbindpw))
527
                        $ldapanon = true;
528
                else
529
                        $ldapanon = false;
530
	} else
531
		return false;
532

    
533
	/* first check if there is even an LDAP server populated */
534
        if(!$ldapserver)
535
                return false;
536

    
537
        /* connect and see if server is up */
538
        putenv('LDAPTLS_REQCERT=never');
539
        $error = false;
540
        if (empty($ldapport)) {
541
                if (!($ldap = ldap_connect($ldapserver)))
542
                        $error = true;
543
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
544
                $error = true;
545

    
546
        if ($error == true) {
547
                log_error("ERROR!  Could not connect to server {$ldapname}.");
548
                return false;
549
        }
550

    
551
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
552
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
553
 
554
	if ($ldapanon == true) {
555
		if (!($res = @ldap_bind($ldap))) {
556
			@ldap_close($ldap);
557
			return false;
558
		}
559
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
560
		@ldap_close($ldap);
561
		return false;
562
	}
563

    
564
	@ldap_unbind($ldap);
565

    
566
	return true;
567
}
568

    
569
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
570
	global $debug, $config, $g;
571

    
572
	if(!function_exists("ldap_connect"))
573
		return;
574

    
575
	$ous = array();
576

    
577
	if ($authcfg) {
578
                if (strstr($authcfg['ldap_urltype'], "Standard"))
579
                        $ldapproto = "ldap";
580
                else
581
                        $ldapproto = "ldaps";
582
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
583
                $ldapport           = $authcfg['ldap_port'];
584
                $ldapbasedn         = $authcfg['ldap_basedn'];
585
                $ldapbindun         = $authcfg['ldap_binddn'];
586
                $ldapbindpw         = $authcfg['ldap_bindpw'];
587
                $ldapver            = $authcfg['ldap_protver'];
588
		if (empty($ldapbindun) || empty($ldapbindpw))
589
                        $ldapanon = true;
590
                else
591
                        $ldapanon = false;
592
                $ldapname           = $authcfg['name'];
593
                $ldapfallback       = false;
594
		$ldapscope          = $authcfg['ldap_scope'];
595
        } else
596
		return false;
597

    
598
        /* first check if there is even an LDAP server populated */
599
        if(!$ldapserver) {
600
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
601
                return $ous;
602
        }
603

    
604
	/* connect and see if server is up */
605
        putenv('LDAPTLS_REQCERT=never');
606
        $error = false;
607
        if (empty($ldapport)) {
608
                if (!($ldap = ldap_connect($ldapserver)))
609
                        $error = true;
610
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
611
                $error = true;
612

    
613
        if ($error == true) {
614
		log_error("ERROR!  Could not connect to server {$ldapname}.");
615
                return $ous;
616
        }
617

    
618
	$ldapfilter = "(|(ou=*)(cn=Users))";
619

    
620
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
621
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
622

    
623
	if ($ldapanon == true) {
624
                if (!($res = @ldap_bind($ldap))) {
625
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
626
			@ldap_close($ldap);
627
                        return $ous;
628
		}
629
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
630
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
631
		@ldap_close($ldap);
632
		return $ous;
633
	}
634

    
635
	if ($ldapscope == "one")
636
		$ldapfunc = "ldap_list";
637
	else
638
		$ldapfunc = "ldap_search";
639

    
640
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
641
	$info = @ldap_get_entries($ldap, $search);
642

    
643
	if (is_array($info)) {
644
		foreach ($info as $inf) {
645
			if (!$show_complete_ou) {
646
				$inf_split = split(",", $inf['dn']);
647
				$ou = $inf_split[0];
648
				$ou = str_replace("OU=","", $ou);
649
				$ou = str_replace("CN=","", $ou);
650
			} else
651
				if($inf['dn'])
652
					$ou = $inf['dn'];
653
			if($ou)
654
				$ous[] = $ou;
655
		}
656
	}
657

    
658
	@ldap_unbind($ldap);
659

    
660
	return $ous;
661
}
662

    
663
function ldap_get_groups($username, $authcfg) {
664
	global $debug, $config;
665
	
666
	if(!function_exists("ldap_connect"))
667
		return;
668
	
669
	if(!$username) 
670
		return false;
671

    
672
	if(stristr($username, "@")) {
673
		$username_split=split("\@", $username);
674
		$username = $username_split[0];		
675
	}
676

    
677
	if(stristr($username, "\\")) {
678
		$username_split=split("\\", $username);
679
		$username = $username_split[0];        
680
	}    
681
	
682
	//log_error("Getting LDAP groups for {$username}.");
683
        if ($authcfg) {
684
                if (strstr($authcfg['ldap_urltype'], "Standard"))
685
                        $ldapproto = "ldap";
686
                else
687
                        $ldapproto = "ldaps";
688
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
689
                $ldapport           = $authcfg['ldap_port'];
690
                $ldapbasedn         = $authcfg['ldap_basedn'];
691
                $ldapbindun         = $authcfg['ldap_binddn'];
692
                $ldapbindpw         = $authcfg['ldap_bindpw'];
693
                $ldapauthcont       = $authcfg['ldap_authcn'];
694
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
695
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
696
                $ldapfilter         = "({$ldapnameattribute}={$username})";
697
                $ldaptype           = "";
698
                $ldapver            = $authcfg['ldap_protver'];
699
		if (empty($ldapbindun) || empty($ldapbindpw))
700
                        $ldapanon = true;
701
                else
702
                        $ldapanon = false;
703
                $ldapname           = $authcfg['name'];
704
                $ldapfallback       = false;
705
		$ldapscope          = $authcfg['ldap_scope'];
706
	} else
707
		return false;
708

    
709
	$ldapdn             = $_SESSION['ldapdn'];
710

    
711
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
712
	$ldapgroupattribute = strtolower($ldapgroupattribute);
713
	$memberof = array();
714

    
715
	/* connect and see if server is up */
716
	putenv('LDAPTLS_REQCERT=never');
717
	$error = false;
718
        if (empty($ldapport)) {
719
                if (!($ldap = ldap_connect($ldapserver)))
720
                        $error = true;
721
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
722
                $error = true;
723

    
724
	if ($error == true) {
725
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
726
                return memberof;
727
        }
728
    
729
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
730
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
731

    
732
	/* bind as user that has rights to read group attributes */
733
	if ($ldapanon == true) {
734
                if (!($res = @ldap_bind($ldap))) {
735
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
736
			@ldap_close($ldap);
737
                        return false;
738
		}
739
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
740
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
741
		@ldap_close($ldap);
742
		return memberof;
743
	}
744

    
745
	/* get groups from DN found */
746
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
747
	/* since we know the DN is in $_SESSION['ldapdn'] */
748
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
749
	if ($ldapscope == "one")
750
                $ldapfunc = "ldap_list";
751
        else
752
                $ldapfunc = "ldap_search";
753

    
754
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
755
	$info      = @ldap_get_entries($ldap, $search);
756

    
757
	$countem = $info["count"];	
758
	
759
	if(is_array($info[0][$ldapgroupattribute])) {
760
		/* Iterate through the groups and throw them into an array */
761
		foreach ($info[0][$ldapgroupattribute] as $member) {
762
			if (stristr($member, "CN=") !== false) {
763
				$membersplit = split(",", $member);
764
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
765
			}
766
		}
767
	}
768
	
769
	/* Time to close LDAP connection */
770
	@ldap_unbind($ldap);
771
	
772
	$groups = print_r($memberof,true);
773
	
774
	//log_error("Returning groups ".$groups." for user $username");
775
	
776
	return $memberof;
777
}
778

    
779
function ldap_backed($username, $passwd, $authcfg) {
780
	global $debug, $config;
781
	
782
	if(!$username) 
783
		return;
784

    
785
	if(!function_exists("ldap_connect"))
786
		return;
787

    
788
	if(stristr($username, "@")) {
789
		$username_split=split("\@", $username);
790
		$username = $username_split[0];        
791
	}
792
	if(stristr($username, "\\")) {
793
		$username_split=split("\\", $username);
794
		$username = $username_split[0];        
795
	}
796

    
797
	if ($authcfg) {
798
		if (strstr($authcfg['ldap_urltype'], "Standard"))
799
			$ldapproto = "ldap";
800
		else
801
			$ldapproto = "ldaps";
802
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
803
		$ldapport	    = $authcfg['ldap_port'];
804
                $ldapbasedn         = $authcfg['ldap_basedn'];
805
                $ldapbindun         = $authcfg['ldap_binddn'];
806
                $ldapbindpw         = $authcfg['ldap_bindpw'];
807
		if (empty($ldapbindun) || empty($ldapbindpw))
808
			$ldapanon = true;
809
		else
810
			$ldapanon = false;
811
                $ldapauthcont       = $authcfg['ldap_authcn'];
812
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
813
                $ldapfilter         = "({$ldapnameattribute}={$username})";
814
                $ldaptype           = "";
815
                $ldapver            = $authcfg['ldap_protver'];
816
		$ldapname	    = $authcfg['name'];
817
		$ldapscope	    = $authcfg['ldap_scope'];
818
	} else
819
		return false;
820

    
821
	/* first check if there is even an LDAP server populated */ 
822
	if(!$ldapserver) {
823
		if ($ldapfallback) {
824
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
825
			return local_backed($username, $passwd);
826
		} else
827
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
828

    
829
		return false;
830
	}
831
	
832
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
833
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
834

    
835
	/* Make sure we can connect to LDAP */
836
	putenv('LDAPTLS_REQCERT=never');
837
	$error = false;
838
	if (empty($ldapport)) {
839
		if (!($ldap = ldap_connect($ldapserver)))
840
			$error = true;
841
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
842
		$error = true;
843

    
844
	if ($error == true) {
845
		log_error("ERROR!  Could not connect to server {$ldapname}.");
846
		return false;
847
	}
848

    
849
	/* ok, its up.  now, lets bind as the bind user so we can search it */
850
	$error = false;
851
	if ($ldapanon == true) {
852
                if (!($res = @ldap_bind($ldap)))
853
                        $error = true;
854
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
855
		$error = true;
856

    
857
	if ($error == true) {
858
		@ldap_close($ldap);
859
		log_error("ERROR! Could not bind to server {$ldapname}.");
860
		return false;
861
	}
862
	
863
	/* Get LDAP Authcontainers and split em up. */
864
	$ldac_splits = split(";", $ldapauthcont);
865
	
866
	/* setup the usercount so we think we havn't found anyone yet */
867
	$usercount  = 0;
868

    
869
	/*****************************************************************/
870
	/*  We First find the user based on username and filter          */
871
	/*  Then, once we find the first occurance of that person        */
872
	/*  We set seesion variables to ponit to the OU and DN of the    */
873
	/*  Person.  To later be used by ldap_get_groups.                */
874
	/*  that way we don't have to search twice.                      */
875
	/*****************************************************************/
876
	log_error("Now Searching for {$username} in directory.");
877
	/* Iterate through the user containers for search */
878
	foreach ($ldac_splits as $i => $ldac_split) {
879
		/* Make sure we just use the first user we find */
880
		log_error("Now Searching in server {$ldapname}, container {$ldac_split} with filter {$ldapfilter}.");
881
		if ($ldapscope == "one")
882
			$ldapfunc = "ldap_list";
883
		else
884
			$ldapfunc = "ldap_search";
885
		/* Support legacy auth container specification. */
886
		if (stristr($ldac_split, "DC="))
887
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
888
		else
889
			$search  = @$ldapfunc($ldap,"{$ldac_split},{$ldapbasedn}",$ldapfilter);
890
		if (!$search) {
891
			log_error("Search resulted in error: " . ldap_error($ldap));
892
			continue;
893
		}
894
		$info	 = ldap_get_entries($ldap,$search);
895
		$matches = $info['count'];
896
		if ($matches == 1){
897
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
898
			$_SESSION['ldapou'] = $ldac_split[$i];
899
			$_SESSION['ldapon'] = "true";
900
			$usercount = 1;
901
			break;
902
		}
903
	}
904

    
905
	if ($usercount != 1){
906
		@ldap_unbind($ldap);
907
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
908
		return false;                         
909
	}
910

    
911
	/* Now lets bind as the user we found */
912
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
913
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
914
		@ldap_unbind($ldap);
915
		return false;
916
	}
917

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

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

    
923
	return true;
924
}
925

    
926
function radius_backed($username, $passwd, $authcfg){
927
	global $debug, $config;
928
	$ret = false;
929

    
930
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
931
	if ($authcfg) {
932
		$radiusservers = array();
933
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
934
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
935
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
936
	} else
937
		return false;
938

    
939
	/* Add a new servers to our instance */
940
	foreach ($radiusservers as $radsrv)
941
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
942

    
943
	if (PEAR::isError($rauth->start())) {
944
		$retvalue['auth_val'] = 1;
945
		$retvalue['error'] = $rauth->getError();
946
		if ($debug)
947
			printf("Radius start: %s<br>\n", $retvalue['error']);
948
	}
949

    
950
	// XXX - billm - somewhere in here we need to handle securid challenge/response
951

    
952
	/* Send request */
953
	$result = $rauth->send();
954
	if (PEAR::isError($result)) {
955
		$retvalue['auth_val'] = 1;
956
		$retvalue['error'] = $result->getMessage();
957
		if ($debug)
958
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
959
	} else if ($result === true) {
960
		$retvalue['auth_val'] = 2;
961
		if ($debug)
962
			printf(gettext("Radius Auth succeeded")."<br>\n");
963
		$ret = true;
964
	} else {
965
		$retvalue['auth_val'] = 3;
966
		if ($debug)
967
			printf(gettext("Radius Auth rejected")."<br>\n");
968
	}
969

    
970
	// close OO RADIUS_AUTHENTICATION
971
	$rauth->close();
972

    
973
	return $ret;
974
}
975

    
976
function get_user_expiration_date($username) {
977
	$user = getUserEntry($username);
978
	if ($user['expires']) 
979
		return $user['expires'];
980
}
981

    
982
function is_account_expired($username) {
983
	$expirydate = get_user_expiration_date($username);
984
	if ($expirydate) {
985
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
986
			return true;
987
	}
988

    
989
	return false;
990
}
991

    
992
function is_account_disabled($username) {
993
	$user = getUserEntry($username);
994
	if (isset($user['disabled']))
995
		return true;
996

    
997
	return false;
998
}
999

    
1000
function auth_get_authserver($name) {
1001
        global $config;
1002

    
1003
        if (is_array($config['system']['authserver'])) {
1004
                foreach ($config['system']['authserver'] as $authcfg) {
1005
                        if ($authcfg['name'] == $name)
1006
                                return $authcfg;
1007
                }
1008
        }
1009
	if ($name == "Local Database")
1010
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1011
}
1012

    
1013
function auth_get_authserver_list() {
1014
        global $config;
1015

    
1016
	$list = array();
1017

    
1018
        if (is_array($config['system']['authserver'])) {
1019
                foreach ($config['system']['authserver'] as $authcfg) {
1020
			/* Add support for disabled entries? */
1021
			$list[$authcfg['name']] = $authcfg;
1022
                }
1023
        }
1024

    
1025
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1026
	return $list;
1027
}
1028

    
1029
function getUserGroups($username, $authcfg) {
1030
	global $config;
1031

    
1032
	$allowed_groups = array();
1033

    
1034
	switch($authcfg['type']) {
1035
        case 'ldap':
1036
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1037
		break;
1038
	case 'radius':
1039
		break;
1040
	default:
1041
		$user = getUserEntry($username);
1042
		$allowed_groups = @local_user_get_groups($user, true);
1043
		break;
1044
	}
1045

    
1046
	$member_groups = array();
1047
        if (is_array($config['system']['group'])) {
1048
                foreach ($config['system']['group'] as $group)
1049
                        if (in_array($group['name'], $allowed_groups))
1050
				$member_groups[] = $group['name'];
1051
	}
1052

    
1053
	return $member_groups;
1054
}
1055

    
1056
function authenticate_user($username, $password, $authcfg = NULL) {
1057

    
1058
	if (!$authcfg) {
1059
		return local_backed($username, $password);
1060
	}
1061

    
1062
	$authenticated = false;
1063
	switch($authcfg['type']) {
1064
        case 'ldap':
1065
                if (ldap_backed($username, $password, $authcfg))
1066
                        $authenticated = true;
1067
                break;
1068
        case 'radius':
1069
                if (radius_backed($username, $password, $authcfg))
1070
                        $authenticated = true;
1071
                break;
1072
        default:
1073
                /* lookup user object by name */
1074
                if (local_backed($username, $password))
1075
                        $authenticated = true;
1076
                break;
1077
        }
1078

    
1079
	return $authenticated;
1080
}
1081

    
1082
function session_auth() {
1083
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1084

    
1085
	session_start();
1086

    
1087
	/* Validate incoming login request */
1088
	if (isset($_POST['login'])) {
1089
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1090
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1091
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1092
			$_SESSION['Logged_In'] = "True";
1093
			$_SESSION['Username'] = $_POST['usernamefld'];
1094
			$_SESSION['last_access'] = time();
1095
			log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1096
			$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1097
			if (isset($_POST['postafterlogin']))
1098
				return true;
1099
			else {
1100
				if (empty($page))
1101
					$page = "/";
1102
				header("Location: {$page}");
1103
			}
1104
			exit;
1105
		} else {
1106
			/* give the user an error message */
1107
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1108
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1109
			if(isAjax()) {
1110
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1111
				return;
1112
			}
1113
		}
1114
	}
1115

    
1116
	/* Show login page if they aren't logged in */
1117
	if (empty($_SESSION['Logged_In']))
1118
		return false;
1119

    
1120
	/* If session timeout isn't set, we don't mark sessions stale */
1121
	if (!isset($config['system']['webgui']['session_timeout'])) {
1122
		/* Default to 4 hour timeout if one is not set */
1123
		if ($_SESSION['last_access'] < (time() - 14400)) {
1124
			$_GET['logout'] = true;
1125
			$_SESSION['Logout'] = true;
1126
		} else
1127
			$_SESSION['last_access'] = time();	
1128
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1129
		/* only update if it wasn't ajax */
1130
		if (!isAjax())
1131
			$_SESSION['last_access'] = time();
1132
	} else {
1133
		/* Check for stale session */
1134
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1135
			$_GET['logout'] = true;
1136
			$_SESSION['Logout'] = true;
1137
		} else {
1138
			/* only update if it wasn't ajax */
1139
			if (!isAjax())
1140
				$_SESSION['last_access'] = time();
1141
		}
1142
	}
1143

    
1144
	/* user hit the logout button */
1145
	if (isset($_GET['logout'])) {
1146

    
1147
		if ($_SESSION['Logout'])
1148
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1149
		else
1150
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1151

    
1152
		/* wipe out $_SESSION */
1153
		$_SESSION = array();
1154

    
1155
		if (isset($_COOKIE[session_name()]))
1156
			setcookie(session_name(), '', time()-42000, '/');
1157

    
1158
		/* and destroy it */
1159
		session_destroy();
1160

    
1161
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1162
		$scriptElms = count($scriptName);
1163
		$scriptName = $scriptName[$scriptElms-1];
1164

    
1165
		if (isAjax())
1166
			return false;
1167

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

    
1171
		return false;
1172
	}
1173

    
1174
	/*
1175
	 * this is for debugging purpose if you do not want to use Ajax
1176
	 * to submit a HTML form. It basically diables the observation
1177
	 * of the submit event and hence does not trigger Ajax.
1178
	 */
1179
	if ($_GET['disable_ajax'])
1180
		$_SESSION['NO_AJAX'] = "True";
1181

    
1182
	/*
1183
	 * Same to re-enable Ajax.
1184
	 */
1185
	if ($_GET['enable_ajax'])
1186
		unset($_SESSION['NO_AJAX']);
1187

    
1188
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1189
	return true;
1190
}
1191

    
1192
?>
(4-4/50)