Project

General

Profile

Download (33.4 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
$groupindex = index_groups();
53
$userindex = index_users();
54

    
55
function index_groups() {
56
	global $g, $debug, $config, $groupindex;
57

    
58
	$groupindex = array();
59

    
60
	if (isset($config['system']['group'])) {
61
		$i = 0;
62
		foreach($config['system']['group'] as $groupent) {
63
			$groupindex[$groupent['name']] = $i;
64
			$i++;
65
		}
66
	}
67

    
68
	return ($groupindex);
69
}
70

    
71
function index_users() {
72
	global $g, $debug, $config;
73

    
74
	if (isset($config['system']['user'])) {
75
		$i = 0;
76
		foreach($config['system']['user'] as $userent) {
77
			$userindex[$userent['name']] = $i;
78
			$i++;
79
		}
80
	}
81

    
82
	return ($userindex);
83
}
84

    
85
function & getUserEntry($name) {
86
	global $debug, $config, $userindex;
87
	if (isset($userindex[$name]))
88
		return $config['system']['user'][$userindex[$name]];
89
}
90

    
91
function & getUserEntryByUID($uid) {
92
	global $debug, $config;
93
	foreach ($config['system']['user'] as & $user)
94
		if ($user['uid'] == $uid)
95
			return $user;
96

    
97
	return false;
98
}
99

    
100
function & getGroupEntry($name) {
101
	global $debug, $config, $groupindex;
102
	if (isset($groupindex[$name]))
103
		return $config['system']['group'][$groupindex[$name]];
104
}
105

    
106
function & getGroupEntryByGID($gid) {
107
	global $debug, $config;
108
	foreach ($config['system']['group'] as & $group)
109
		if ($group['gid'] == $gid)
110
			return $group;
111

    
112
	return false;
113
}
114

    
115
function get_user_privileges(& $user) {
116

    
117
        $privs = $user['priv'];
118
        if (!is_array($privs))
119
                $privs = array();
120

    
121
        $names = local_user_get_groups($user, true);
122

    
123
        foreach ($names as $name) {
124
                $group = getGroupEntry($name);
125
                if (is_array($group['priv']))
126
                        $privs = array_merge( $privs, $group['priv']);
127
        }
128

    
129
        return $privs;
130
}
131

    
132
function userHasPrivilege($userent, $privid = false) {
133

    
134
        if (!$privid || !is_array($userent))
135
                return false;
136

    
137
        $privs = get_user_privileges($userent);
138

    
139
        if (!is_array($privs))
140
                return false;
141

    
142
        if (!in_array($privid, $privs))
143
                return false;
144

    
145
        return true;
146
}
147

    
148
function local_backed($username, $passwd) {
149

    
150
	$user = getUserEntry($username);
151
	if (!$user)
152
		return false;
153

    
154
	if (is_account_disabled($username) || is_account_expired($username))
155
		return false;
156

    
157
	if ($user['password'])
158
	{
159
		$passwd = crypt($passwd, $user['password']);
160
		if ($passwd == $user['password'])
161
			return true;
162
	}
163

    
164
	if ($user['md5-hash'])
165
	{
166
		$passwd = md5($passwd);
167
		if ($passwd == $user['md5-hash'])
168
			return true;
169
	}
170

    
171
	return false;
172
}
173

    
174
function local_sync_accounts() {
175
	global $debug, $config;
176
	conf_mount_rw();
177

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

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

    
217
	/* make sure the all group exists */
218
	$allgrp = getGroupEntryByGID(1998);
219
	local_group_set($allgrp, true);
220

    
221
	/* sync all local users */
222
	if (is_array($config['system']['user']))
223
		foreach ($config['system']['user'] as $user)
224
			local_user_set($user);
225

    
226
	/* sync all local groups */
227
	if (is_array($config['system']['group']))
228
		foreach ($config['system']['group'] as $group)
229
			local_group_set($group);
230

    
231
	conf_mount_ro();
232

    
233
}
234

    
235
function local_user_set(& $user) {
236
	global $g, $debug;
237

    
238
	conf_mount_rw();
239

    
240
	$home_base = "/home/";	
241
	$user_uid = $user['uid'];
242
	$user_name = $user['name'];
243
	$user_home = "{$home_base}{$user_name}";
244
	$user_shell = "/etc/rc.initial";
245
	$user_group = "nobody";
246

    
247
	// Ensure $home_base exists and is writable
248
	if (!is_dir($home_base)) 
249
		mkdir($home_base, 0755);
250

    
251
	// Ensure $user_home exists and is writable
252
	if(!is_dir($user_home)) 
253
		mkdir($user_home, 0755);
254

    
255
	/* configure shell type */
256
	if (!userHasPrivilege($user, "user-shell-access")) {
257
		if (!userHasPrivilege($user, "user-copy-files"))
258
			$user_shell = "/sbin/nologin";
259
		else
260
			$user_shell = "/usr/local/bin/scponly";
261
	}
262

    
263
	/* root user special handling */
264
	if ($user_uid == 0) {
265
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
266
		if($debug)
267
			log_error("Running: {$cmd}");
268
		$fd = popen($cmd, "w");
269
		fwrite($fd, $user['password']);
270
		pclose($fd);
271
		$user_group = "wheel";
272
	}
273

    
274

    
275
	/* read from pw db */
276
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
277
	$pwread = fgets($fd);
278
	pclose($fd);
279

    
280
	/* determine add or mod */
281
	if (!strncmp($pwread, "pw:", 3)) {
282
		$user_op = "useradd -o";
283
	} else {
284
		$user_op = "usermod";
285
	}
286

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

    
292
	if($debug)
293
		log_error("Running: {$cmd}");
294
	$fd = popen($cmd, "w");
295
	fwrite($fd, $user['password']);
296
	pclose($fd);
297

    
298

    
299
	/* admin user special handling */
300
	if ($user_uid == 0) {
301
		$cmd = "/usr/sbin/pw usermod -q -n {$user_name} -s /etc/rc.initial -H 0";
302
		if($debug)
303
			log_error("Running: {$cmd}");
304
		$fd = popen($cmd, "w");
305
		fwrite($fd, $user['password']);
306
		pclose($fd);
307
		$user_group = "wheel";
308
	}
309

    
310
	/* create user directory if required */
311
	if (!is_dir($user_home)) {
312
		mkdir($user_home, 0700);
313
		mwexec("cp /root/.* {$home_base}/");
314
	}
315
	chown($user_home, $user_name);
316
	chgrp($user_home, $user_group);
317

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

    
332
function local_user_del($user) {
333
	global $debug;
334

    
335
	/* remove all memberships */
336
	local_user_set_groups($user);
337

    
338
	/* delete from pw db */
339
	$cmd = "/usr/sbin/pw userdel {$user['name']}";
340

    
341
	if($debug)
342
		log_error("Running: {$cmd}");
343
	mwexec($cmd);
344

    
345
	/* Delete user from groups needs a call to write_config() */
346
	local_group_del_user($user);
347
}
348

    
349
function local_user_set_password(& $user, $password) {
350

    
351
	$user['password'] = crypt($password);
352
	$user['md5-hash'] = md5($password);
353

    
354
	// Converts ascii to unicode.
355
	$astr = (string) $password;
356
	$ustr = '';
357
	for ($i = 0; $i < strlen($astr); $i++) {
358
		$a = ord($astr{$i}) << 8;
359
		$ustr.= sprintf("%X", $a);
360
	}
361

    
362
	// Generate the NT-HASH from the unicode string
363
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
364
}
365

    
366
function local_user_get_groups($user, $all = false) {
367
	global $debug, $config;
368

    
369
	$groups = array();
370
	if (!is_array($config['system']['group']))
371
		return $groups;
372

    
373
	foreach ($config['system']['group'] as $group)
374
		if ( $all || ( !$all && ($group['name'] != "all")))
375
			if (is_array($group['member']))
376
				if (in_array($user['uid'], $group['member']))
377
					$groups[] = $group['name'];
378

    
379
	sort($groups);
380

    
381
	return $groups;
382
	
383
}
384

    
385
function local_user_set_groups($user, $new_groups = NULL ) {
386
	global $debug, $config, $groupindex;
387

    
388
	if (!is_array($config['system']['group']))
389
		return;
390

    
391
	$cur_groups = local_user_get_groups($user);
392
	$mod_groups = array();
393

    
394
	if (!is_array($new_groups))
395
		$new_groups = array();
396

    
397
	if (!is_array($cur_groups))
398
		$cur_groups = array();
399

    
400
	/* determine which memberships to add */
401
	foreach ($new_groups as $groupname) {
402
		if (in_array($groupname,$cur_groups))
403
			continue;
404
		$group = & $config['system']['group'][$groupindex[$groupname]];
405
		$group['member'][] = $user['uid'];
406
		$mod_groups[] = $group;
407
	}
408

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

    
419
	/* sync all modified groups */
420
	foreach ($mod_groups as $group)
421
		local_group_set($group);
422
}
423

    
424
function local_group_del_user($user) {
425
	global $config;
426

    
427
	if (!is_array($config['system']['group']))
428
                return;
429

    
430
        foreach ($config['system']['group'] as $group) {
431
		if (is_array($group['member'])) {
432
			foreach ($group['member'] as $idx => $uid) {
433
				if ($user['uid'] == $uid)
434
					unset($config['system']['group']['member'][$idx]);
435
			}
436
		}
437
	}
438
}
439

    
440
function local_group_set($group, $reset = false) {
441
	global $debug;
442

    
443
	$group_name = $group['name'];
444
	$group_gid = $group['gid'];
445
	$group_members = "''";
446
	if (!$reset && count($group['member']))
447
		$group_members = implode(",",$group['member']);
448

    
449
	/* read from group db */
450
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
451
	$pwread = fgets($fd);
452
	pclose($fd);
453

    
454
	/* determine add or mod */
455
	if (!strncmp($pwread, "pw:", 3))
456
		$group_op = "groupadd";
457
	else
458
		$group_op = "groupmod";
459

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

    
463
	if($debug)
464
		log_error("Running: {$cmd}");
465
	mwexec($cmd);
466

    
467
}
468

    
469
function local_group_del($group) {
470
	global $debug;
471

    
472
	/* delete from group db */
473
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
474

    
475
	if($debug)
476
		log_error("Running: {$cmd}");
477
	mwexec($cmd);
478
}
479

    
480
function ldap_test_connection($authcfg) {
481
	global $debug, $config, $g;
482

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

    
496
        /* first check if there is even an LDAP server populated */
497
        if(!$ldapserver)
498
                return false;
499

    
500
        /* connect and see if server is up */
501
        putenv('LDAPTLS_REQCERT=never');
502
        $error = false;
503
        if (empty($ldapport)) {
504
                if (!($ldap = ldap_connect($ldapserver)))
505
                        $error = true;
506
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
507
                $error = true;
508

    
509
        if ($error == true) {
510
                log_error("ERROR!  Could not connect to server {$ldapname}.");
511
                return false;
512
        }
513

    
514
	return true;
515
}
516

    
517
function ldap_test_bind($authcfg) {
518
	global $debug, $config, $g;
519

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

    
538
	/* first check if there is even an LDAP server populated */
539
        if(!$ldapserver)
540
                return false;
541

    
542
        /* connect and see if server is up */
543
        putenv('LDAPTLS_REQCERT=never');
544
        $error = false;
545
        if (empty($ldapport)) {
546
                if (!($ldap = ldap_connect($ldapserver)))
547
                        $error = true;
548
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
549
                $error = true;
550

    
551
        if ($error == true) {
552
                log_error("ERROR!  Could not connect to server {$ldapname}.");
553
                return false;
554
        }
555

    
556
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
557
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
558
 
559
	if ($ldapanon == true) {
560
		if (!($res = @ldap_bind($ldap))) {
561
			@ldap_close($ldap);
562
			return false;
563
		}
564
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
565
		@ldap_close($ldap);
566
		return false;
567
	}
568

    
569
	@ldap_unbind($ldap);
570

    
571
	return true;
572
}
573

    
574
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
575
	global $debug, $config, $g;
576

    
577
	if(!function_exists("ldap_connect"))
578
		return;
579

    
580
	$ous = array();
581

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

    
603
        /* first check if there is even an LDAP server populated */
604
        if(!$ldapserver) {
605
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
606
                return $ous;
607
        }
608

    
609
	/* connect and see if server is up */
610
        putenv('LDAPTLS_REQCERT=never');
611
        $error = false;
612
        if (empty($ldapport)) {
613
                if (!($ldap = ldap_connect($ldapserver)))
614
                        $error = true;
615
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
616
                $error = true;
617

    
618
        if ($error == true) {
619
		log_error("ERROR!  Could not connect to server {$ldapname}.");
620
                return $ous;
621
        }
622

    
623
	$ldapfilter = "(|(ou=*)(cn=Users))";
624

    
625
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
626
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
627

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

    
640
	if ($ldapscope == "one")
641
		$ldapfunc = "ldap_list";
642
	else
643
		$ldapfunc = "ldap_search";
644

    
645
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
646
	$info = @ldap_get_entries($ldap, $search);
647

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

    
663
	@ldap_unbind($ldap);
664

    
665
	return $ous;
666
}
667

    
668
function ldap_get_groups($username, $authcfg) {
669
	global $debug, $config;
670
	
671
	if(!function_exists("ldap_connect"))
672
		return;
673
	
674
	if(!$username) 
675
		return false;
676

    
677
	if(stristr($username, "@")) {
678
		$username_split=split("\@", $username);
679
		$username = $username_split[0];		
680
	}
681

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

    
714
	$ldapdn             = $_SESSION['ldapdn'];
715

    
716
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
717
	$ldapgroupattribute = strtolower($ldapgroupattribute);
718
	$memberof = array();
719

    
720
	/* connect and see if server is up */
721
	putenv('LDAPTLS_REQCERT=never');
722
	$error = false;
723
        if (empty($ldapport)) {
724
                if (!($ldap = ldap_connect($ldapserver)))
725
                        $error = true;
726
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
727
                $error = true;
728

    
729
	if ($error == true) {
730
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
731
                return memberof;
732
        }
733
    
734
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
735
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
736

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

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

    
759
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
760
	$info      = @ldap_get_entries($ldap, $search);
761

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

    
784
function ldap_backed($username, $passwd, $authcfg) {
785
	global $debug, $config;
786
	
787
	if(!$username) 
788
		return;
789

    
790
	if(!function_exists("ldap_connect"))
791
		return;
792

    
793
	if(stristr($username, "@")) {
794
		$username_split=split("\@", $username);
795
		$username = $username_split[0];        
796
	}
797
	if(stristr($username, "\\")) {
798
		$username_split=split("\\", $username);
799
		$username = $username_split[0];        
800
	}
801

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

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

    
834
		return false;
835
	}
836
	
837
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
838
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
839

    
840
	/* Make sure we can connect to LDAP */
841
	putenv('LDAPTLS_REQCERT=never');
842
	$error = false;
843
	if (empty($ldapport)) {
844
		if (!($ldap = ldap_connect($ldapserver)))
845
			$error = true;
846
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
847
		$error = true;
848

    
849
	if ($error == true) {
850
		log_error("ERROR!  Could not connect to server {$ldapname}.");
851
		return false;
852
	}
853

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

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

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

    
910
	if ($usercount != 1){
911
		@ldap_unbind($ldap);
912
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
913
		return false;                         
914
	}
915

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

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

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

    
928
	return true;
929
}
930

    
931
function radius_backed($username, $passwd, $authcfg){
932
	global $debug, $config;
933
	$ret = false;
934

    
935
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
936
	if ($authcfg) {
937
		$radiusservers = array();
938
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
939
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
940
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
941
	} else
942
		return false;
943

    
944
	/* Add a new servers to our instance */
945
	foreach ($radiusservers as $radsrv)
946
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
947

    
948
	if (PEAR::isError($rauth->start())) {
949
		$retvalue['auth_val'] = 1;
950
		$retvalue['error'] = $rauth->getError();
951
		if ($debug)
952
			printf("Radius start: %s<br>\n", $retvalue['error']);
953
	}
954

    
955
	// XXX - billm - somewhere in here we need to handle securid challenge/response
956

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

    
975
	// close OO RADIUS_AUTHENTICATION
976
	$rauth->close();
977

    
978
	return $ret;
979
}
980

    
981
function get_user_expiration_date($username) {
982
	$user = getUserEntry($username);
983
	if ($user['expires']) 
984
		return $user['expires'];
985
}
986

    
987
function is_account_expired($username) {
988
	$expirydate = get_user_expiration_date($username);
989
	if ($expirydate) {
990
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
991
			return true;
992
	}
993

    
994
	return false;
995
}
996

    
997
function is_account_disabled($username) {
998
	$user = getUserEntry($username);
999
	if (isset($user['disabled']))
1000
		return true;
1001

    
1002
	return false;
1003
}
1004

    
1005
function auth_get_authserver($name) {
1006
        global $config;
1007

    
1008
        if (is_array($config['system']['authserver'])) {
1009
                foreach ($config['system']['authserver'] as $authcfg) {
1010
                        if ($authcfg['name'] == $name)
1011
                                return $authcfg;
1012
                }
1013
        }
1014
	if ($name == "Local Database")
1015
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1016
}
1017

    
1018
function auth_get_authserver_list() {
1019
        global $config;
1020

    
1021
	$list = array();
1022

    
1023
        if (is_array($config['system']['authserver'])) {
1024
                foreach ($config['system']['authserver'] as $authcfg) {
1025
			/* Add support for disabled entries? */
1026
			$list[$authcfg['name']] = $authcfg;
1027
                }
1028
        }
1029

    
1030
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1031
	return $list;
1032
}
1033

    
1034
function getUserGroups($username, $authcfg) {
1035
	global $config;
1036

    
1037
	$allowed_groups = array();
1038

    
1039
	switch($authcfg['type']) {
1040
        case 'ldap':
1041
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1042
		break;
1043
	case 'radius':
1044
		break;
1045
	default:
1046
		$user = getUserEntry($username);
1047
		$allowed_groups = @local_user_get_groups($user, true);
1048
		break;
1049
	}
1050

    
1051
	$member_groups = array();
1052
        if (is_array($config['system']['group'])) {
1053
                foreach ($config['system']['group'] as $group)
1054
                        if (in_array($group['name'], $allowed_groups))
1055
				$member_groups[] = $group['name'];
1056
	}
1057

    
1058
	return $member_groups;
1059
}
1060

    
1061
function authenticate_user($username, $password, $authcfg = NULL) {
1062

    
1063
	if (!$authcfg) {
1064
		return local_backed($username, $password);
1065
	}
1066

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

    
1084
	return $authenticated;
1085
}
1086

    
1087
function session_auth() {
1088
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1089

    
1090
	session_start();
1091

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

    
1121
	/* Show login page if they aren't logged in */
1122
	if (empty($_SESSION['Logged_In']))
1123
		return false;
1124

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

    
1149
	/* user hit the logout button */
1150
	if (isset($_GET['logout'])) {
1151

    
1152
		if ($_SESSION['Logout'])
1153
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1154
		else
1155
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1156

    
1157
		/* wipe out $_SESSION */
1158
		$_SESSION = array();
1159

    
1160
		if (isset($_COOKIE[session_name()]))
1161
			setcookie(session_name(), '', time()-42000, '/');
1162

    
1163
		/* and destroy it */
1164
		session_destroy();
1165

    
1166
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1167
		$scriptElms = count($scriptName);
1168
		$scriptName = $scriptName[$scriptElms-1];
1169

    
1170
		if (isAjax())
1171
			return false;
1172

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

    
1176
		return false;
1177
	}
1178

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

    
1187
	/*
1188
	 * Same to re-enable Ajax.
1189
	 */
1190
	if ($_GET['enable_ajax'])
1191
		unset($_SESSION['NO_AJAX']);
1192

    
1193
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1194
	return true;
1195
}
1196

    
1197
?>
(4-4/50)