Project

General

Profile

Download (33.2 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
	/* configure shell type */
252
	if (!(userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all"))) {
253
		if (!userHasPrivilege($user, "user-copy-files"))
254
			$user_shell = "/sbin/nologin";
255
		else
256
			$user_shell = "/usr/local/bin/scponly";
257
	} else {
258
		$user_shell = "/bin/tcsh";
259
	}
260

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

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

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

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

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

    
297
	/* create user directory if required */
298
	if (!is_dir($user_home)) {
299
		mkdir($user_home, 0700);
300
		mwexec("cp /root/.* {$home_base}/");
301
	}
302
	chown($user_home, $user_name);
303
	chgrp($user_home, $user_group);
304

    
305
	/* write out ssh authorized key file */
306
	if($user['authorizedkeys']) {
307
		if (!is_dir("{$user_home}/.ssh")) {
308
			mkdir("{$user_home}/.ssh", 0700);
309
			chown("{$user_home}/.ssh", $user_name);
310
		}
311
		$keys = base64_decode($user['authorizedkeys']);
312
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
313
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
314
	}
315
	
316
	conf_mount_ro();
317
}
318

    
319
function local_user_del($user) {
320
	global $debug;
321

    
322
	/* remove all memberships */
323
	local_user_set_groups($user);
324

    
325
	/* delete from pw db */
326
	$cmd = "/usr/sbin/pw userdel {$user['name']}";
327

    
328
	if($debug)
329
		log_error("Running: {$cmd}");
330
	mwexec($cmd);
331

    
332
	/* Delete user from groups needs a call to write_config() */
333
	local_group_del_user($user);
334
}
335

    
336
function local_user_set_password(& $user, $password) {
337

    
338
	$user['password'] = crypt($password);
339
	$user['md5-hash'] = md5($password);
340

    
341
	// Converts ascii to unicode.
342
	$astr = (string) $password;
343
	$ustr = '';
344
	for ($i = 0; $i < strlen($astr); $i++) {
345
		$a = ord($astr{$i}) << 8;
346
		$ustr.= sprintf("%X", $a);
347
	}
348

    
349
	// Generate the NT-HASH from the unicode string
350
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
351
}
352

    
353
function local_user_get_groups($user, $all = false) {
354
	global $debug, $config;
355

    
356
	$groups = array();
357
	if (!is_array($config['system']['group']))
358
		return $groups;
359

    
360
	foreach ($config['system']['group'] as $group)
361
		if ( $all || ( !$all && ($group['name'] != "all")))
362
			if (is_array($group['member']))
363
				if (in_array($user['uid'], $group['member']))
364
					$groups[] = $group['name'];
365

    
366
	sort($groups);
367

    
368
	return $groups;
369
	
370
}
371

    
372
function local_user_set_groups($user, $new_groups = NULL ) {
373
	global $debug, $config, $groupindex;
374

    
375
	if (!is_array($config['system']['group']))
376
		return;
377

    
378
	$cur_groups = local_user_get_groups($user);
379
	$mod_groups = array();
380

    
381
	if (!is_array($new_groups))
382
		$new_groups = array();
383

    
384
	if (!is_array($cur_groups))
385
		$cur_groups = array();
386

    
387
	/* determine which memberships to add */
388
	foreach ($new_groups as $groupname) {
389
		if (in_array($groupname,$cur_groups))
390
			continue;
391
		$group = & $config['system']['group'][$groupindex[$groupname]];
392
		$group['member'][] = $user['uid'];
393
		$mod_groups[] = $group;
394
	}
395

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

    
406
	/* sync all modified groups */
407
	foreach ($mod_groups as $group)
408
		local_group_set($group);
409
}
410

    
411
function local_group_del_user($user) {
412
	global $config;
413

    
414
	if (!is_array($config['system']['group']))
415
                return;
416

    
417
        foreach ($config['system']['group'] as $group) {
418
		if (is_array($group['member'])) {
419
			foreach ($group['member'] as $idx => $uid) {
420
				if ($user['uid'] == $uid)
421
					unset($config['system']['group']['member'][$idx]);
422
			}
423
		}
424
	}
425
}
426

    
427
function local_group_set($group, $reset = false) {
428
	global $debug;
429

    
430
	$group_name = $group['name'];
431
	$group_gid = $group['gid'];
432
	$group_members = "''";
433
	if (!$reset && count($group['member']))
434
		$group_members = implode(",",$group['member']);
435

    
436
	/* read from group db */
437
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
438
	$pwread = fgets($fd);
439
	pclose($fd);
440

    
441
	/* determine add or mod */
442
	if (!strncmp($pwread, "pw:", 3))
443
		$group_op = "groupadd";
444
	else
445
		$group_op = "groupmod";
446

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

    
450
	if($debug)
451
		log_error("Running: {$cmd}");
452
	mwexec($cmd);
453

    
454
}
455

    
456
function local_group_del($group) {
457
	global $debug;
458

    
459
	/* delete from group db */
460
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
461

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

    
467
function ldap_test_connection($authcfg) {
468
	global $debug, $config, $g;
469

    
470
	if ($authcfg) {
471
                if (strstr($authcfg['ldap_urltype'], "Standard"))
472
                        $ldapproto = "ldap";
473
                else
474
                        $ldapproto = "ldaps";
475
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
476
                $ldapport           = $authcfg['ldap_port'];
477
                $ldapbasedn         = $authcfg['ldap_basedn'];
478
                $ldapbindun         = $authcfg['ldap_binddn'];
479
                $ldapbindpw         = $authcfg['ldap_bindpw'];
480
        } else
481
		return false;
482

    
483
        /* first check if there is even an LDAP server populated */
484
        if(!$ldapserver)
485
                return false;
486

    
487
        /* connect and see if server is up */
488
        putenv('LDAPTLS_REQCERT=never');
489
        $error = false;
490
        if (empty($ldapport)) {
491
                if (!($ldap = ldap_connect($ldapserver)))
492
                        $error = true;
493
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
494
                $error = true;
495

    
496
        if ($error == true) {
497
                log_error("ERROR!  Could not connect to server {$ldapname}.");
498
                return false;
499
        }
500

    
501
	return true;
502
}
503

    
504
function ldap_test_bind($authcfg) {
505
	global $debug, $config, $g;
506

    
507
	if ($authcfg) {
508
                if (strstr($authcfg['ldap_urltype'], "Standard"))
509
                        $ldapproto = "ldap";
510
                else
511
                        $ldapproto = "ldaps";
512
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
513
                $ldapport           = $authcfg['ldap_port'];
514
                $ldapbasedn         = $authcfg['ldap_basedn'];
515
                $ldapbindun         = $authcfg['ldap_binddn'];
516
                $ldapbindpw         = $authcfg['ldap_bindpw'];
517
                $ldapver            = $authcfg['ldap_protver'];
518
		if (empty($ldapbndun) || empty($ldapbindpw))
519
                        $ldapanon = true;
520
                else
521
                        $ldapanon = false;
522
	} else
523
		return false;
524

    
525
	/* first check if there is even an LDAP server populated */
526
        if(!$ldapserver)
527
                return false;
528

    
529
        /* connect and see if server is up */
530
        putenv('LDAPTLS_REQCERT=never');
531
        $error = false;
532
        if (empty($ldapport)) {
533
                if (!($ldap = ldap_connect($ldapserver)))
534
                        $error = true;
535
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
536
                $error = true;
537

    
538
        if ($error == true) {
539
                log_error("ERROR!  Could not connect to server {$ldapname}.");
540
                return false;
541
        }
542

    
543
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
544
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
545
 
546
	if ($ldapanon == true) {
547
		if (!($res = @ldap_bind($ldap))) {
548
			@ldap_close($ldap);
549
			return false;
550
		}
551
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
552
		@ldap_close($ldap);
553
		return false;
554
	}
555

    
556
	@ldap_unbind($ldap);
557

    
558
	return true;
559
}
560

    
561
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
562
	global $debug, $config, $g;
563

    
564
	if(!function_exists("ldap_connect"))
565
		return;
566

    
567
	$ous = array();
568

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

    
590
        /* first check if there is even an LDAP server populated */
591
        if(!$ldapserver) {
592
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
593
                return $ous;
594
        }
595

    
596
	/* connect and see if server is up */
597
        putenv('LDAPTLS_REQCERT=never');
598
        $error = false;
599
        if (empty($ldapport)) {
600
                if (!($ldap = ldap_connect($ldapserver)))
601
                        $error = true;
602
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
603
                $error = true;
604

    
605
        if ($error == true) {
606
		log_error("ERROR!  Could not connect to server {$ldapname}.");
607
                return $ous;
608
        }
609

    
610
	$ldapfilter = "(|(ou=*)(cn=Users))";
611

    
612
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
613
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
614

    
615
	if ($ldapanon == true) {
616
                if (!($res = @ldap_bind($ldap))) {
617
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
618
			@ldap_close($ldap);
619
                        return $ous;
620
		}
621
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
622
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
623
		@ldap_close($ldap);
624
		return $ous;
625
	}
626

    
627
	if ($ldapscope == "one")
628
		$ldapfunc = "ldap_list";
629
	else
630
		$ldapfunc = "ldap_search";
631

    
632
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
633
	$info = @ldap_get_entries($ldap, $search);
634

    
635
	if (is_array($info)) {
636
		foreach ($info as $inf) {
637
			if (!$show_complete_ou) {
638
				$inf_split = split(",", $inf['dn']);
639
				$ou = $inf_split[0];
640
				$ou = str_replace("OU=","", $ou);
641
				$ou = str_replace("CN=","", $ou);
642
			} else
643
				if($inf['dn'])
644
					$ou = $inf['dn'];
645
			if($ou)
646
				$ous[] = $ou;
647
		}
648
	}
649

    
650
	@ldap_unbind($ldap);
651

    
652
	return $ous;
653
}
654

    
655
function ldap_get_groups($username, $authcfg) {
656
	global $debug, $config;
657
	
658
	if(!function_exists("ldap_connect"))
659
		return;
660
	
661
	if(!$username) 
662
		return false;
663

    
664
	if(stristr($username, "@")) {
665
		$username_split=split("\@", $username);
666
		$username = $username_split[0];		
667
	}
668

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

    
701
	$ldapdn             = $_SESSION['ldapdn'];
702

    
703
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
704
	$ldapgroupattribute = strtolower($ldapgroupattribute);
705
	$memberof = array();
706

    
707
	/* connect and see if server is up */
708
	putenv('LDAPTLS_REQCERT=never');
709
	$error = false;
710
        if (empty($ldapport)) {
711
                if (!($ldap = ldap_connect($ldapserver)))
712
                        $error = true;
713
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
714
                $error = true;
715

    
716
	if ($error == true) {
717
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
718
                return memberof;
719
        }
720
    
721
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
722
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
723

    
724
	/* bind as user that has rights to read group attributes */
725
	if ($ldapanon == true) {
726
                if (!($res = @ldap_bind($ldap))) {
727
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
728
			@ldap_close($ldap);
729
                        return false;
730
		}
731
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
732
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
733
		@ldap_close($ldap);
734
		return memberof;
735
	}
736

    
737
	/* get groups from DN found */
738
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
739
	/* since we know the DN is in $_SESSION['ldapdn'] */
740
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
741
	if ($ldapscope == "one")
742
                $ldapfunc = "ldap_list";
743
        else
744
                $ldapfunc = "ldap_search";
745

    
746
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
747
	$info      = @ldap_get_entries($ldap, $search);
748

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

    
771
function ldap_backed($username, $passwd, $authcfg) {
772
	global $debug, $config;
773
	
774
	if(!$username) 
775
		return;
776

    
777
	if(!function_exists("ldap_connect"))
778
		return;
779

    
780
	if(stristr($username, "@")) {
781
		$username_split=split("\@", $username);
782
		$username = $username_split[0];        
783
	}
784
	if(stristr($username, "\\")) {
785
		$username_split=split("\\", $username);
786
		$username = $username_split[0];        
787
	}
788

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

    
813
	/* first check if there is even an LDAP server populated */ 
814
	if(!$ldapserver) {
815
		if ($ldapfallback) {
816
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
817
			return local_backed($username, $passwd);
818
		} else
819
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
820

    
821
		return false;
822
	}
823
	
824
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
825
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
826

    
827
	/* Make sure we can connect to LDAP */
828
	putenv('LDAPTLS_REQCERT=never');
829
	$error = false;
830
	if (empty($ldapport)) {
831
		if (!($ldap = ldap_connect($ldapserver)))
832
			$error = true;
833
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
834
		$error = true;
835

    
836
	if ($error == true) {
837
		log_error("ERROR!  Could not connect to server {$ldapname}.");
838
		return false;
839
	}
840

    
841
	/* ok, its up.  now, lets bind as the bind user so we can search it */
842
	$error = false;
843
	if ($ldapanon == true) {
844
                if (!($res = @ldap_bind($ldap)))
845
                        $error = true;
846
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
847
		$error = true;
848

    
849
	if ($error == true) {
850
		@ldap_close($ldap);
851
		log_error("ERROR! Could not bind to server {$ldapname}.");
852
		return false;
853
	}
854
	
855
	/* Get LDAP Authcontainers and split em up. */
856
	$ldac_splits = split(";", $ldapauthcont);
857
	
858
	/* setup the usercount so we think we havn't found anyone yet */
859
	$usercount  = 0;
860

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

    
897
	if ($usercount != 1){
898
		@ldap_unbind($ldap);
899
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
900
		return false;                         
901
	}
902

    
903
	/* Now lets bind as the user we found */
904
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
905
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
906
		@ldap_unbind($ldap);
907
		return false;
908
	}
909

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

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

    
915
	return true;
916
}
917

    
918
function radius_backed($username, $passwd, $authcfg){
919
	global $debug, $config;
920
	$ret = false;
921

    
922
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
923
	if ($authcfg) {
924
		$radiusservers = array();
925
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
926
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
927
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
928
	} else
929
		return false;
930

    
931
	/* Add a new servers to our instance */
932
	foreach ($radiusservers as $radsrv)
933
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
934

    
935
	if (PEAR::isError($rauth->start())) {
936
		$retvalue['auth_val'] = 1;
937
		$retvalue['error'] = $rauth->getError();
938
		if ($debug)
939
			printf("Radius start: %s<br>\n", $retvalue['error']);
940
	}
941

    
942
	// XXX - billm - somewhere in here we need to handle securid challenge/response
943

    
944
	/* Send request */
945
	$result = $rauth->send();
946
	if (PEAR::isError($result)) {
947
		$retvalue['auth_val'] = 1;
948
		$retvalue['error'] = $result->getMessage();
949
		if ($debug)
950
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
951
	} else if ($result === true) {
952
		$retvalue['auth_val'] = 2;
953
		if ($debug)
954
			printf(gettext("Radius Auth succeeded")."<br>\n");
955
		$ret = true;
956
	} else {
957
		$retvalue['auth_val'] = 3;
958
		if ($debug)
959
			printf(gettext("Radius Auth rejected")."<br>\n");
960
	}
961

    
962
	// close OO RADIUS_AUTHENTICATION
963
	$rauth->close();
964

    
965
	return $ret;
966
}
967

    
968
function get_user_expiration_date($username) {
969
	$user = getUserEntry($username);
970
	if ($user['expires']) 
971
		return $user['expires'];
972
}
973

    
974
function is_account_expired($username) {
975
	$expirydate = get_user_expiration_date($username);
976
	if ($expirydate) {
977
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
978
			return true;
979
	}
980

    
981
	return false;
982
}
983

    
984
function is_account_disabled($username) {
985
	$user = getUserEntry($username);
986
	if (isset($user['disabled']))
987
		return true;
988

    
989
	return false;
990
}
991

    
992
function auth_get_authserver($name) {
993
        global $config;
994

    
995
        if (is_array($config['system']['authserver'])) {
996
                foreach ($config['system']['authserver'] as $authcfg) {
997
                        if ($authcfg['name'] == $name)
998
                                return $authcfg;
999
                }
1000
        }
1001
	if ($name == "Local Database")
1002
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1003
}
1004

    
1005
function auth_get_authserver_list() {
1006
        global $config;
1007

    
1008
	$list = array();
1009

    
1010
        if (is_array($config['system']['authserver'])) {
1011
                foreach ($config['system']['authserver'] as $authcfg) {
1012
			/* Add support for disabled entries? */
1013
			$list[$authcfg['name']] = $authcfg;
1014
                }
1015
        }
1016

    
1017
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1018
	return $list;
1019
}
1020

    
1021
function getUserGroups($username, $authcfg) {
1022
	global $config;
1023

    
1024
	$allowed_groups = array();
1025

    
1026
	switch($authcfg['type']) {
1027
        case 'ldap':
1028
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1029
		break;
1030
	case 'radius':
1031
		break;
1032
	default:
1033
		$user = getUserEntry($username);
1034
		$allowed_groups = @local_user_get_groups($user, true);
1035
		break;
1036
	}
1037

    
1038
	$member_groups = array();
1039
        if (is_array($config['system']['group'])) {
1040
                foreach ($config['system']['group'] as $group)
1041
                        if (in_array($group['name'], $allowed_groups))
1042
				$member_groups[] = $group['name'];
1043
	}
1044

    
1045
	return $member_groups;
1046
}
1047

    
1048
function authenticate_user($username, $password, $authcfg = NULL) {
1049

    
1050
	if (!$authcfg) {
1051
		return local_backed($username, $password);
1052
	}
1053

    
1054
	$authenticated = false;
1055
	switch($authcfg['type']) {
1056
        case 'ldap':
1057
                if (ldap_backed($username, $password, $authcfg))
1058
                        $authenticated = true;
1059
                break;
1060
        case 'radius':
1061
                if (radius_backed($username, $password, $authcfg))
1062
                        $authenticated = true;
1063
                break;
1064
        default:
1065
                /* lookup user object by name */
1066
                if (local_backed($username, $password))
1067
                        $authenticated = true;
1068
                break;
1069
        }
1070

    
1071
	return $authenticated;
1072
}
1073

    
1074
function session_auth() {
1075
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1076

    
1077
	session_start();
1078

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

    
1108
	/* Show login page if they aren't logged in */
1109
	if (empty($_SESSION['Logged_In']))
1110
		return false;
1111

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

    
1136
	/* user hit the logout button */
1137
	if (isset($_GET['logout'])) {
1138

    
1139
		if ($_SESSION['Logout'])
1140
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1141
		else
1142
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1143

    
1144
		/* wipe out $_SESSION */
1145
		$_SESSION = array();
1146

    
1147
		if (isset($_COOKIE[session_name()]))
1148
			setcookie(session_name(), '', time()-42000, '/');
1149

    
1150
		/* and destroy it */
1151
		session_destroy();
1152

    
1153
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1154
		$scriptElms = count($scriptName);
1155
		$scriptName = $scriptName[$scriptElms-1];
1156

    
1157
		if (isAjax())
1158
			return false;
1159

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

    
1163
		return false;
1164
	}
1165

    
1166
	/*
1167
	 * this is for debugging purpose if you do not want to use Ajax
1168
	 * to submit a HTML form. It basically diables the observation
1169
	 * of the submit event and hence does not trigger Ajax.
1170
	 */
1171
	if ($_GET['disable_ajax'])
1172
		$_SESSION['NO_AJAX'] = "True";
1173

    
1174
	/*
1175
	 * Same to re-enable Ajax.
1176
	 */
1177
	if ($_GET['enable_ajax'])
1178
		unset($_SESSION['NO_AJAX']);
1179

    
1180
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1181
	return true;
1182
}
1183

    
1184
?>
(4-4/50)