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
	// Ensure $user_home exists and is writable
252
	if(!is_dir($user_home)) 
253
		mkdir($user_home, 0755);
254

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

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

    
274

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

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

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

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

    
298

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

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

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

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

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

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

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

    
347
}
348

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

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

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

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

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

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

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

    
379
	sort($groups);
380

    
381
	return $groups;
382
	
383
}
384

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

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

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

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

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

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

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

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

    
424
function local_group_set($group, $reset = false) {
425
	global $debug;
426

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

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

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

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

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

    
453
}
454

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

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

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

    
467
}
468

    
469
function ldap_test_connection($authcfg) {
470
	global $debug, $config, $g;
471

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

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

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

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

    
503
	return true;
504
}
505

    
506
function ldap_test_bind($authcfg) {
507
	global $debug, $config, $g;
508

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

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

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

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

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

    
558
	@ldap_unbind($ldap);
559

    
560
	return true;
561
}
562

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

    
566
	if(!function_exists("ldap_connect"))
567
		return;
568

    
569
	$ous = array();
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
		return false;
591

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

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

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

    
612
	$ldapfilter = "(|(ou=*)(cn=Users))";
613

    
614
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
615
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
616

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

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

    
634
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
635
	$info = @ldap_get_entries($ldap, $search);
636

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

    
652
	@ldap_unbind($ldap);
653

    
654
	return $ous;
655
}
656

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

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

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

    
703
	$ldapdn             = $_SESSION['ldapdn'];
704

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

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

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

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

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

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

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

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

    
779
	if(!function_exists("ldap_connect"))
780
		return;
781

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

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

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

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

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

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

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

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

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

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

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

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

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

    
917
	return true;
918
}
919

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

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

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

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

    
944
	// XXX - billm - somewhere in here we need to handle securid challenge/response
945

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

    
964
	// close OO RADIUS_AUTHENTICATION
965
	$rauth->close();
966

    
967
	return $ret;
968
}
969

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

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

    
983
	return false;
984
}
985

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

    
991
	return false;
992
}
993

    
994
function auth_get_authserver($name) {
995
        global $config;
996

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

    
1007
function auth_get_authserver_list() {
1008
        global $config;
1009

    
1010
	$list = array();
1011

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

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

    
1023
function getUserGroups($username, $authcfg) {
1024
	global $config;
1025

    
1026
	$allowed_groups = array();
1027

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

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

    
1047
	return $member_groups;
1048
}
1049

    
1050
function authenticate_user($username, $password, $authcfg = NULL) {
1051

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

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

    
1073
	return $authenticated;
1074
}
1075

    
1076
function session_auth() {
1077
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1078

    
1079
	session_start();
1080

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

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

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

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

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

    
1142
		/* wipe out $_SESSION */
1143
		$_SESSION = array();
1144

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

    
1148
		/* and destroy it */
1149
		session_destroy();
1150

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

    
1155
		if (isAjax())
1156
			return false;
1157

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

    
1161
		return false;
1162
	}
1163

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

    
1175
	/*
1176
	 * Same to re-enable Ajax.
1177
	 */
1178
	if ($_GET['enable_ajax']) {
1179
		unset($_SESSION['NO_AJAX']);
1180
		$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1181
		return true;
1182
	}
1183

    
1184
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1185
	return true;
1186
}
1187

    
1188
?>
(4-4/50)