Project

General

Profile

Download (33 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
		$user_home = "/root";
273
	}
274

    
275
	/* admin user special handling */
276
	if ($user_uid == 0) {
277
		$cmd = "/usr/sbin/pw usermod -q -n admin -s /bin/sh -H 0";
278
		if($debug)
279
			log_error("Running: {$cmd}");
280
		$fd = popen($cmd, "w");
281
		fwrite($fd, $user['password']);
282
		pclose($fd);
283
		$user_group = "wheel";
284
	}
285

    
286
	/* read from pw db */
287
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
288
	$pwread = fgets($fd);
289
	pclose($fd);
290

    
291
	/* determine add or mod */
292
	if (!strncmp($pwread, "pw:", 3))
293
		$user_op = "useradd";
294
	else
295
		$user_op = "usermod";
296

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

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

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

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

    
330
function local_user_del($user) {
331
	global $debug;
332

    
333
	/* remove all memberships */
334
	local_user_get_groups($user);
335

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

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

    
345
}
346

    
347
function local_user_set_password(& $user, $password) {
348

    
349
	$user['password'] = crypt($password);
350
	$user['md5-hash'] = md5($password);
351

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

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

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

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

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

    
377
	sort($groups);
378

    
379
	return $groups;
380
	
381
}
382

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

    
386
	if (!is_array($config['system']['group']))
387
		return;
388

    
389
	$cur_groups = local_user_get_groups($user);
390
	$mod_groups = array();
391

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

    
395
	if (!is_array($cur_groups))
396
		$cur_groups = array();
397

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

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

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

    
422
function local_group_set($group, $reset = false) {
423
	global $debug;
424

    
425
	$group_name = $group['name'];
426
	$group_gid = $group['gid'];
427
	$group_members = "''";
428
	if (!$reset && count($group['member']))
429
		$group_members = implode(",",$group['member']);
430

    
431
	/* read from group db */
432
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
433
	$pwread = fgets($fd);
434
	pclose($fd);
435

    
436
	/* determine add or mod */
437
	if (!strncmp($pwread, "pw:", 3))
438
		$group_op = "groupadd";
439
	else
440
		$group_op = "groupmod";
441

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

    
445
	if($debug)
446
		log_error("Running: {$cmd}");
447
	$fd = popen($cmd, "w");
448
	fwrite($fd, $user['password']);
449
	pclose($fd);
450

    
451
}
452

    
453
function local_group_del($group) {
454
	global $debug;
455

    
456
	/* delete from group db */
457
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
458

    
459
	if($debug)
460
		log_error("Running: {$cmd}");
461
	$fd = popen($cmd, "w");
462
	fwrite($fd, $user['password']);
463
	pclose($fd);
464

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

    
588
	$ous = array();
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 succesfully 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::iserError($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
			require_once("functions.inc");
1089
			pfSenseHeader("/{$page}");
1090
		} else {
1091
			/* give the user an error message */
1092
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1093
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1094
			if(isAjax()) {
1095
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1096
				return;
1097
			}
1098
		}
1099
	}
1100

    
1101
	/* Show login page if they aren't logged in */
1102
	if (empty($_SESSION['Logged_In']))
1103
		return false;
1104

    
1105
	/* If session timeout isn't set, we don't mark sessions stale */
1106
	if (!isset($config['system']['webgui']['session_timeout'])) {
1107
		/* Default to 4 hour timeout if one is not set */
1108
		if ($_SESSION['last_access'] < (time() - 14400)) {
1109
			$_GET['logout'] = true;
1110
			$_SESSION['Logout'] = true;
1111
		}
1112
	} else if (empty($config['system']['webgui']['session_timeout'])) {
1113
		$_SESSION['last_access'] = time();	
1114
	} else {
1115
		/* Check for stale session */
1116
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1117
			$_GET['logout'] = true;
1118
			$_SESSION['Logout'] = true;
1119
		} else {
1120
			/* only update if it wasn't ajax */
1121
			if (!isAjax())
1122
				$_SESSION['last_access'] = time();
1123
		}
1124
	}
1125

    
1126
	/* user hit the logout button */
1127
	if (isset($_GET['logout'])) {
1128

    
1129
		if ($_SESSION['Logout'])
1130
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1131
		else
1132
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1133

    
1134
		/* wipe out $_SESSION */
1135
		$_SESSION = array();
1136

    
1137
		if (isset($_COOKIE[session_name()]))
1138
			setcookie(session_name(), '', time()-42000, '/');
1139

    
1140
		/* and destroy it */
1141
		session_destroy();
1142

    
1143
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1144
		$scriptElms = count($scriptName);
1145
		$scriptName = $scriptName[$scriptElms-1];
1146

    
1147
		if (isAjax())
1148
			return false;
1149

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

    
1153
		return false;
1154
	}
1155

    
1156
	/*
1157
	 * this is for debugging purpose if you do not want to use Ajax
1158
	 * to submit a HTML form. It basically diables the observation
1159
	 * of the submit event and hence does not trigger Ajax.
1160
	 */
1161
	if ($_GET['disable_ajax']) {
1162
		$_SESSION['NO_AJAX'] = "True";
1163
		$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1164
		return true;
1165
	}
1166

    
1167
	/*
1168
	 * Same to re-enable Ajax.
1169
	 */
1170
	if ($_GET['enable_ajax']) {
1171
		unset($_SESSION['NO_AJAX']);
1172
		$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1173
		return true;
1174
	}
1175

    
1176
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1177
	return true;
1178
}
1179

    
1180
?>
(4-4/50)