Project

General

Profile

Download (36 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))
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 = NULL) {
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
                $ldapserver = $config['system']['webgui']['ldapserver'];
482
                $ldapbindun = $config['system']['webgui']['ldapbindun'];
483
                $ldapbindpw = $config['system']['webgui']['ldapbindpw'];
484
        }
485

    
486
        /* first check if there is even an LDAP server populated */
487
        if(!$ldapserver)
488
                return false;
489

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

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

    
504
	return true;
505
}
506

    
507
function ldap_test_bind($authcfg = NULL) {
508
	global $debug, $config, $g;
509

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

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

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

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

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

    
560
	$ldap_unbind($ldap);
561

    
562
	return true;
563
}
564

    
565
function ldap_get_user_ous($show_complete_ou=true, $authcfg = NULL) {
566
	global $debug, $config, $g;
567

    
568
	if(!function_exists("ldap_connect"))
569
		return;
570

    
571
	if ($authcfg) {
572
                if (strstr($authcfg['ldap_urltype'], "Standard"))
573
                        $ldapproto = "ldap";
574
                else
575
                        $ldapproto = "ldaps";
576
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
577
                $ldapport           = $authcfg['ldap_port'];
578
                $ldapbasedn         = $authcfg['ldap_basedn'];
579
                $ldapbindun         = $authcfg['ldap_binddn'];
580
                $ldapbindpw         = $authcfg['ldap_bindpw'];
581
                $ldapver            = $authcfg['ldap_protver'];
582
		if (empty($ldapbindun) || empty($ldapbindpw))
583
                        $ldapanon = true;
584
                else
585
                        $ldapanon = false;
586
                $ldapname           = $authcfg['name'];
587
                $ldapfallback       = false;
588
		$ldapscope          = $authcfg['ldap_scope'];
589
        } else {
590
                $ldapserver         = $config['system']['webgui']['ldapserver'];
591
                $ldapport           = "";
592
                $ldapbasedn         = $config['system']['webgui']['ldapsearchbase'];
593
                $ldapbindun         = $config['system']['webgui']['ldapbindun'];
594
                $ldapbindpw         = $config['system']['webgui']['ldapbindpw'];
595
                $ldapver            = 3;
596
                $ldapanon           = false;
597
                $ldapname           = "system-settings";
598
                $ldapfallback       = true;
599
		$ldapscope	    = "all";
600
        }
601

    
602
	$ous = array();
603

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

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

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

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

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

    
629
	if ($ldapanon == true) {
630
                if (!($res = @ldap_bind($ldap))) {
631
			log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
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
		return $ous;
637
	}
638

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

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

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

    
662
	return $ous;
663
}
664

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

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

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

    
724
	$ldapdn             = $_SESSION['ldapdn'];
725

    
726
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
727
	$ldapgroupattribute = strtolower($ldapgroupattribute);
728
	$memberof = array();
729

    
730
	/* connect and see if server is up */
731
	putenv('LDAPTLS_REQCERT=never');
732
	$error = false;
733
        if (empty($ldapport)) {
734
                if (!($ldap = ldap_connect($ldapserver)))
735
                        $error = true;
736
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
737
                $error = true;
738

    
739
	if ($error == true) {
740
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
741
                return memberof;
742
        }
743
    
744
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
745
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
746

    
747
	/* bind as user that has rights to read group attributes */
748
	if ($ldapanon == true) {
749
                if (!($res = @ldap_bind($ldap)))
750
                        return false;
751
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
752
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
753
		return memberof;
754
	}
755

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

    
765
	$search    = $ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
766
	$info      = ldap_get_entries($ldap, $search);
767

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

    
790
function ldap_backed($username, $passwd, $authcfg = NULL) {
791
	global $debug, $config;
792
	
793
	if(!$username) 
794
		return;
795

    
796
	if(!function_exists("ldap_connect"))
797
		return;
798

    
799
	$adbindas = $username;
800
    
801
	if(stristr($username, "@")) {
802
		$username_split=split("\@", $username);
803
		$username = $username_split[0];        
804
	}
805
	if(stristr($username, "\\")) {
806
		$username_split=split("\\", $username);
807
		$username = $username_split[0];        
808
	}
809

    
810
	if ($authcfg) {
811
		if (strstr($authcfg['ldap_urltype'], "Standard"))
812
			$ldapproto = "ldap";
813
		else
814
			$ldapproto = "ldaps";
815
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
816
		$ldapport	    = $authcfg['ldap_port'];
817
                $ldapbasedn         = $authcfg['ldap_basedn'];
818
                $ldapbindun         = $authcfg['ldap_binddn'];
819
                $ldapbindpw         = $authcfg['ldap_bindpw'];
820
		if (empty($ldapbindun) || empty($ldapbindpw))
821
			$ldapanon = true;
822
		else
823
			$ldapanon = false;
824
                $ldapauthcont       = $authcfg['ldap_authcn'];
825
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
826
                $ldapfilter         = "({$ldapnameattribute}={$username})";
827
                $ldaptype           = "";
828
                $ldapver            = $authcfg['ldap_protver'];
829
		$ldapname	    = $authcfg['name'];
830
		$ldapfallback	    = false;
831
		$ldapscope	    = $authcfg['ldap_scope'];
832
	} else {
833
		$ldapserver         = $config['system']['webgui']['ldapserver'];
834
		$ldapport	    = "";
835
		$ldapbasedn	    = $config['system']['webgui']['ldapsearchbase'];
836
		$ldapbindun         = $config['system']['webgui']['ldapbindun'];
837
		$ldapbindpw         = $config['system']['webgui']['ldapbindpw'];
838
		$ldapauthcont       = $config['system']['webgui']['ldapauthcontainers'];   
839
		$ldapnameattribute  = $config['system']['webgui']['ldapnameattribute'];  
840
		$ldapfilter         = $config['system']['webgui']['ldapfilter'];
841
		$ldaptype           = $config['system']['webgui']['backend'];
842
		$ldapver	    = 3;
843
		$ldapfilter	    = str_replace("_username_", $username, $ldapfilter);
844
		$ldapanon	    = false;
845
		$ldapname	    = "system-settings";
846
		$ldapfallback	    = true;
847
		$ldapscope	    = "all";
848
	}
849

    
850

    
851
	/* first check if there is even an LDAP server populated */ 
852
	if(!$ldapserver) {
853
		if ($ldapfallback) {
854
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
855
			return local_backed($username, $passwd);
856
		} else
857
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
858

    
859
		return false;
860
	}
861
	
862
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
863
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
864

    
865
	/* Make sure we can connect to LDAP */
866
	putenv('LDAPTLS_REQCERT=never');
867
	$error = false;
868
	if (empty($ldapport)) {
869
		if (!($ldap = ldap_connect($ldapserver)))
870
			$error = true;
871
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
872
		$error = true;
873

    
874
	if ($error == true) {
875
		if ($ldapfallback) {
876
			log_error("ERROR!  Could not connect to server {$ldapname}.  Defaulting to built-in local user database. Visit System -> User Manager for correcting it.");
877
			return local_backed($username, $passwd);		
878
		} else
879
			log_error("ERROR!  Could not connect to server {$ldapname}.");
880

    
881
		return false;
882
	}
883

    
884
	/* ok, its up.  now, lets bind as the bind user so we can search it */
885
	$error = false;
886
	if ($ldapanon == true) {
887
                if (!($res = @ldap_bind($ldap)))
888
                        $error = true;
889
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
890
		$error = true;
891

    
892
	if ($error == true) {
893
		ldap_close($ldap);
894
		if ($ldapfallback) {
895
			log_error("ERROR! ldap_backed() could not bind to {$ldapserver} - {$ldapfilter}.  Defaulting to built-in local_backed()");
896
			return local_backed($username, $passwd);
897
		} else
898
			log_error("ERROR! Could not bind to server {$ldapname}.");
899

    
900
		return false;
901
	}
902
	
903
	/* Get LDAP Authcontainers and split em up. */
904
	$ldac_splits = split(";", $ldapauthcont);
905
	
906
	/* setup the usercount so we think we havn't found anyone yet */
907
	$usercount  = 0;
908

    
909
	/******************************/
910
	/* Currently LDAP Types are   */
911
	/* LDAP = Active Directory    */
912
	/* LDAPOTHER = eDir/Openldap  */
913
	/******************************/      
914
        
915
	/*****************************************************************/
916
	/* Now Active Directory We keep this seperate for future addons. */
917
	/*****************************************************************/
918
	/* Now LDAP other.  eDirectory or Netscape or Sunone or OpenLDAP */
919
	/*****************************************************************/
920
	/*  We First find the user based on username and filter          */
921
	/*  Then, once we find the first occurance of that person        */
922
	/*  We set seesion variables to ponit to the OU and DN of the    */
923
	/*  Person.  To later be used by ldap_get_groups.                */
924
	/*  that way we don't have to search twice.                      */
925
	/*****************************************************************/
926
	log_error("Now Searching for {$username} in directory.");
927
	/* Iterate through the user containers for search */
928
	foreach ($ldac_splits as $i => $ldac_split) {
929
		/* Make sure we just use the first user we find */
930
		log_error("Now Searching in server {$ldapname}, container {$ldac_split} with filter {$ldapfilter}.");
931
		if ($ldapscope == "one")
932
			$ldapfunc = "ldap_list";
933
		else
934
			$ldapfunc = "ldap_search";
935
		/* Support legacy auth container specification. */
936
		if (stristr($ldac_split, "DC="))
937
			$search	 = $ldapfunc($ldap,$ldac_split,$ldapfilter);
938
		else
939
			$search  = $ldapfunc($ldap,"{$ldac_split},{$ldapbasedn}",$ldapfilter);
940
		if (!$search) {
941
			log_error("Search resulted in error: " . ldap_error($ldap));
942
			continue;
943
		}
944
		$info	 = ldap_get_entries($ldap,$search);
945
		$matches = $info['count'];
946
		if ($matches == 1){
947
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
948
			$_SESSION['ldapou'] = $ldac_split[$i];
949
			$_SESSION['ldapon'] = "true";
950
			$usercount = 1;
951
			break;
952
		}
953
	}
954

    
955
	if ($usercount != 1){
956
		ldap_unbind($ldap);
957
		if ($ldapfallback) {
958
			log_error("ERROR! Either LDAP search failed, or multiple users were found. Falling back to local user database.");
959
			$status = local_backed($username, $passwd);
960
			$_SESSION['ldapon'] = "false";
961
			return $status;
962
		} else
963
			log_error("ERROR! Either LDAP search failed, or multiple users were found.");
964
		return false;                         
965
	}
966

    
967
	/* Now lets bind as the user we found */
968
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
969
		if ($ldapfallback) {
970
			log_error("ERROR! Could not login to server {$ldapname} as user {$username}. Defaulting to local user database. Visit System -> User Manager.");
971
			$status = local_backed($username, $passwd);
972
			$_SESSION['ldapon'] = "false";
973
			return $status;
974
		} else
975
			log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
976
		
977
		return false;
978
	}
979

    
980
	log_error("Logged in succesfully as {$username} via LDAP server {$ldapname} with DN = {$userdn}.");
981

    
982
	/* At this point we are bound to LDAP so the user was auth'd okay. Close connection. */
983
	ldap_unbind($ldap);
984

    
985
	return true;
986
}
987

    
988
function radius_backed($username, $passwd, $authcfg = NULL){
989
	global $debug, $config;
990
	$ret = false;
991

    
992
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
993
	if ($authcfg) {
994
		$radiusservers = array();
995
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
996
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
997
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
998
	} else
999
		$radiusservers = $config['system']['radius']['servers'];
1000

    
1001
	/* Add a new servers to our instance */
1002
	foreach ($radiusservers as $radsrv)
1003
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
1004

    
1005
	if (PEAR::iserError($rauth->start())) {
1006
		$retvalue['auth_val'] = 1;
1007
		$retvalue['error'] = $rauth->getError();
1008
		if ($debug)
1009
			printf("Radius start: %s<br>\n", $retvalue['error']);
1010
	}
1011

    
1012
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1013

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

    
1032
	// close OO RADIUS_AUTHENTICATION
1033
	$rauth->close();
1034

    
1035
	return $ret;
1036
}
1037

    
1038
function get_user_expiration_date($username) {
1039
	$user = getUserEntry($username);
1040
	if ($user['expires']) 
1041
		return $user['expires'];
1042
}
1043

    
1044
function is_account_expired($username) {
1045
	$expirydate = get_user_expiration_date($username);
1046
	if ($expirydate) {
1047
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1048
			return true;
1049
	}
1050

    
1051
	return false;
1052
}
1053

    
1054
function is_account_disabled($username) {
1055
	$user = getUserEntry($username);
1056
	if (isset($user['disabled']))
1057
		return true;
1058

    
1059
	return false;
1060
}
1061

    
1062
function auth_get_authserver($name) {
1063
        global $config;
1064

    
1065
        if (is_array($config['system']['authserver'])) {
1066
                foreach ($config['system']['authserver'] as $authcfg) {
1067
                        if ($authcfg['name'] == $name)
1068
                                return $authcfg;
1069
                }
1070
        }
1071
}
1072

    
1073
function authenticate_user($username, $password, $authcfg = NULL) {
1074

    
1075
	if (!$authcfg) {
1076
		return local_backed($username, $password);
1077
	}
1078

    
1079
	$authenticated = false;
1080
	switch($authcfg['type']) {
1081
        case 'ldap':
1082
                if (ldap_backed($username, $password, $authcfg))
1083
                        $authenticated = true;
1084
                break;
1085
        case 'radius':
1086
                if (radius_backed($username, $password, $authcfg))
1087
                        $authenticated = true;
1088
                break;
1089
        default:
1090
                /* lookup user object by name */
1091
                if (local_backed($username, $password))
1092
                        $authenticated = true;
1093
                break;
1094
        }
1095

    
1096
	return $authenticated;
1097
}
1098

    
1099
function session_auth($backing) {
1100
	global $debug, $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1101

    
1102
	session_start();
1103

    
1104
	/* Validate incoming login request */
1105
	if (isset($_POST['login'])) {
1106
		if ($backing($_POST['usernamefld'], $_POST['passwordfld'])) {
1107
			if(is_account_disabled($_POST['usernamefld']) || is_account_disabled($_POST['usernamefld'])) {
1108
				$_SESSION['Login_Error'] = "Username or Password incorrect";
1109
				log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1110
				if(isAjax()) {
1111
					echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1112
					return;
1113
				}
1114
			} else {
1115
				$_SESSION['Logged_In'] = "True";
1116
				$_SESSION['Username'] = $_POST['usernamefld'];
1117
				$_SESSION['last_access'] = time();
1118
				log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1119
				require_once("functions.inc");
1120
				pfSenseHeader("/{$page}");
1121
			}
1122
		} else {
1123
			/* give the user an error message */
1124
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1125
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1126
			if(isAjax()) {
1127
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1128
				return;
1129
			}
1130
		}
1131
	}
1132

    
1133
	/* Show login page if they aren't logged in */
1134
	if (empty($_SESSION['Logged_In'])) {
1135
		/* Don't display login forms to AJAX */
1136
		if (isAjax())
1137
			return false;
1138
		require_once("authgui.inc");
1139
		display_login_form();
1140
		return false;
1141
	}
1142

    
1143
	/* If session timeout isn't set, we don't mark sessions stale */
1144
	if ( $config['system']['webgui']['session_timeout'] == 0 ||
1145
		$config['system']['webgui']['session_timeout'] == "") {
1146
		$_SESSION['last_access'] = time();	
1147
	} elseif (!isset($config['system']['webgui']['session_timeout'])) {
1148
		/* Default to 4 hour timeout if one is not set */
1149
		if ($_SESSION['last_access'] < (time() - 14400)) {
1150
			$_GET['logout'] = true;
1151
			$_SESSION['Logout'] = true;
1152
		}
1153
	} else {
1154
		/* Check for stale session */
1155
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1156
			$_GET['logout'] = true;
1157
			$_SESSION['Logout'] = true;
1158
		} else {
1159
			/* only update if it wasn't ajax */
1160
			if (!isAjax())
1161
				$_SESSION['last_access'] = time();
1162
		}
1163
	}
1164

    
1165
	/* obtain user object */
1166
	$user = getUserEntry($_SESSION['Username']);
1167

    
1168
	/* user hit the logout button */
1169
	if (isset($_GET['logout'])) {
1170

    
1171
		if ($_SESSION['Logout'])
1172
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1173
		else
1174
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1175

    
1176
		/* wipe out $_SESSION */
1177
		$_SESSION = array();
1178

    
1179
		if (isset($_COOKIE[session_name()]))
1180
			setcookie(session_name(), '', time()-42000, '/');
1181

    
1182
		/* and destroy it */
1183
		session_destroy();
1184

    
1185
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1186
		$scriptElms = count($scriptName);
1187
		$scriptName = $scriptName[$scriptElms-1];
1188

    
1189
		if (isAjax())
1190
			return false;
1191

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

    
1195
		return false;
1196
	}
1197

    
1198
	/*
1199
	 * this is for debugging purpose if you do not want to use Ajax
1200
	 * to submit a HTML form. It basically diables the observation
1201
	 * of the submit event and hence does not trigger Ajax.
1202
	 */
1203
	if ($_GET['disable_ajax']) {
1204
		$_SESSION['NO_AJAX'] = "True";
1205
		$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1206
		return true;
1207
	}
1208

    
1209
	/*
1210
	 * Same to re-enable Ajax.
1211
	 */
1212
	if ($_GET['enable_ajax']) {
1213
		unset($_SESSION['NO_AJAX']);
1214
		$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1215
		return true;
1216
	}
1217

    
1218
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1219
	return true;
1220
}
1221

    
1222
?>
(4-4/50)