Project

General

Profile

Download (35.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	Copyright (C) 2010 Ermal Lu?i
5
	All rights reserved.
6

    
7
	Copyright (C) 2007, 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9

    
10
        Copyright (C) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
11
        All rights reserved.
12

    
13
        Copyright (C) 2006 Paul Taylor <paultaylor@winn-dixie.com>.
14
        All rights reserved.
15

    
16
        Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
17
        All rights reserved.
18

    
19
        Redistribution and use in source and binary forms, with or without
20
        modification, are permitted provided that the following conditions are met:
21

    
22
        1. Redistributions of source code must retain the above copyright notice,
23
           this list of conditions and the following disclaimer.
24

    
25
        2. Redistributions in binary form must reproduce the above copyright
26
           notice, this list of conditions and the following disclaimer in the
27
           documentation and/or other materials provided with the distribution.
28

    
29
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
30
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
31
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
33
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
        POSSIBILITY OF SUCH DAMAGE.
39

    
40
		DISABLE_PHP_LINT_CHECKING
41
		pfSense_BUILDER_BINARIES:	/usr/sbin/pw	/bin/cp
42
		pfSense_MODULE:	auth
43
*/
44

    
45
/*
46
 * NOTE : Portions of the mschapv2 support was based on the BSD licensed CHAP.php
47
 * file courtesy of Michael Retterklieber.
48
 */
49
if(!$do_not_include_config_gui_inc)
50
	require_once("config.gui.inc");
51

    
52
/* If this function doesn't exist, we're being called from Captive Portal or 
53
   another internal subsystem which does not include authgui.inc */
54
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
55
	/* DNS ReBinding attack prevention.  http://redmine.pfsense.org/issues/708 */
56
	$found_host = false;
57
	if(strstr($_SERVER['HTTP_HOST'], ":")) {
58
		$http_host_port = explode(":", $_SERVER['HTTP_HOST']);
59
		$http_host = $http_host_port[0];
60
	} else {
61
		$http_host = $_SERVER['HTTP_HOST'];
62
	}
63
	if(is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
64
	   $http_host == "localhost" or $_SERVER['SERVER_ADDR'] == "localhost")
65
		$found_host = true;
66
	if($config['dyndnses']['dyndns'])
67
		foreach($config['dyndnses']['dyndns'] as $dyndns)
68
			if($dyndns['host'] == $http_host or $dyndns['host'] == $_SERVER['SERVER_ADDR'])
69
				$found_host = true;
70

    
71
	if(!empty($config['system']['webgui']['althostnames'])) {
72
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
73
		foreach ($althosts as $ah)
74
			if($ah == $http_host or $ah == $_SERVER['SERVER_ADDR'])
75
				$found_host = true;
76
	}
77

    
78
	if($http_host == $config['system']['hostname'] . "." . $config['system']['domain'] or
79
			$http_host == $_SERVER['SERVER_ADDR'] or
80
			$http_host == $config['system']['hostname'])
81
		$found_host = true;
82

    
83
	if($found_host == false) {
84
		display_error_form("501", "Potential DNS Rebind attack detected, see http://en.wikipedia.org/wiki/DNS_rebinding");
85
		exit;
86
	}
87
}
88

    
89
$groupindex = index_groups();
90
$userindex = index_users();
91

    
92
function index_groups() {
93
	global $g, $debug, $config, $groupindex;
94

    
95
	$groupindex = array();
96

    
97
	if (is_array($config['system']['group'])) {
98
		$i = 0;
99
		foreach($config['system']['group'] as $groupent) {
100
			$groupindex[$groupent['name']] = $i;
101
			$i++;
102
		}
103
	}
104

    
105
	return ($groupindex);
106
}
107

    
108
function index_users() {
109
	global $g, $debug, $config;
110

    
111
	if (is_array($config['system']['user'])) {
112
		$i = 0;
113
		foreach($config['system']['user'] as $userent) {
114
			$userindex[$userent['name']] = $i;
115
			$i++;
116
		}
117
	}
118

    
119
	return ($userindex);
120
}
121

    
122
function & getUserEntry($name) {
123
	global $debug, $config, $userindex;
124
	if (isset($userindex[$name]))
125
		return $config['system']['user'][$userindex[$name]];
126
}
127

    
128
function & getUserEntryByUID($uid) {
129
	global $debug, $config;
130
	foreach ($config['system']['user'] as & $user)
131
		if ($user['uid'] == $uid)
132
			return $user;
133

    
134
	return false;
135
}
136

    
137
function & getGroupEntry($name) {
138
	global $debug, $config, $groupindex;
139
	if (isset($groupindex[$name]))
140
		return $config['system']['group'][$groupindex[$name]];
141
}
142

    
143
function & getGroupEntryByGID($gid) {
144
	global $debug, $config;
145
	foreach ($config['system']['group'] as & $group)
146
		if ($group['gid'] == $gid)
147
			return $group;
148

    
149
	return false;
150
}
151

    
152
function get_user_privileges(& $user) {
153

    
154
        $privs = $user['priv'];
155
        if (!is_array($privs))
156
                $privs = array();
157

    
158
        $names = local_user_get_groups($user, true);
159

    
160
        foreach ($names as $name) {
161
                $group = getGroupEntry($name);
162
                if (is_array($group['priv']))
163
                        $privs = array_merge( $privs, $group['priv']);
164
        }
165

    
166
        return $privs;
167
}
168

    
169
function userHasPrivilege($userent, $privid = false) {
170

    
171
        if (!$privid || !is_array($userent))
172
                return false;
173

    
174
        $privs = get_user_privileges($userent);
175

    
176
        if (!is_array($privs))
177
                return false;
178

    
179
        if (!in_array($privid, $privs))
180
                return false;
181

    
182
        return true;
183
}
184

    
185
function local_backed($username, $passwd) {
186

    
187
	$user = getUserEntry($username);
188
	if (!$user)
189
		return false;
190

    
191
	if (is_account_disabled($username) || is_account_expired($username))
192
		return false;
193

    
194
	if ($user['password'])
195
	{
196
		$passwd = crypt($passwd, $user['password']);
197
		if ($passwd == $user['password'])
198
			return true;
199
	}
200

    
201
	if ($user['md5-hash'])
202
	{
203
		$passwd = md5($passwd);
204
		if ($passwd == $user['md5-hash'])
205
			return true;
206
	}
207

    
208
	return false;
209
}
210

    
211
function local_sync_accounts() {
212
	global $debug, $config;
213
	conf_mount_rw();
214

    
215
	/* remove local users to avoid uid conflicts */
216
	$fd = popen("/usr/sbin/pw usershow -a", "r");
217
	if ($fd) {
218
		while (!feof($fd)) {
219
			$line = explode(":",fgets($fd));
220
			if (!strncmp($line[0], "_", 1))
221
				continue;
222
			if ($line[2] < 2000)
223
				continue;
224
			if ($line[2] > 65000)
225
				continue;
226
			$cmd = "/usr/sbin/pw userdel {$line[2]}";
227
			if($debug)
228
				log_error("Running: {$cmd}");
229
			mwexec($cmd);
230
		}
231
		pclose($fd);
232
	}
233

    
234
	/* remove local groups to avoid gid conflicts */
235
	$gids = array();
236
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
237
	if ($fd) {
238
		while (!feof($fd)) {
239
			$line = explode(":",fgets($fd));
240
			if (!strncmp($line[0], "_", 1))
241
				continue;
242
			if ($line[2] < 2000)
243
				continue;
244
			if ($line[2] > 65000)
245
				continue;
246
			$cmd = "/usr/sbin/pw groupdel {$line[2]}";
247
			if($debug)
248
				log_error("Running: {$cmd}");
249
			mwexec($cmd);
250
		}
251
		pclose($fd);
252
	}
253

    
254
	/* make sure the all group exists */
255
	$allgrp = getGroupEntryByGID(1998);
256
	local_group_set($allgrp, true);
257

    
258
	/* sync all local users */
259
	if (is_array($config['system']['user']))
260
		foreach ($config['system']['user'] as $user)
261
			local_user_set($user);
262

    
263
	/* sync all local groups */
264
	if (is_array($config['system']['group']))
265
		foreach ($config['system']['group'] as $group)
266
			local_group_set($group);
267

    
268
	conf_mount_ro();
269

    
270
}
271

    
272
function local_user_set(& $user) {
273
	global $g, $debug;
274

    
275
	conf_mount_rw();
276

    
277
	$home_base = "/home/";	
278
	$user_uid = $user['uid'];
279
	$user_name = $user['name'];
280
	$user_home = "{$home_base}{$user_name}";
281
	$user_shell = "/etc/rc.initial";
282
	$user_group = "nobody";
283

    
284
	// Ensure $home_base exists and is writable
285
	if (!is_dir($home_base)) 
286
		mkdir($home_base, 0755);
287

    
288
	$lock_account = false;
289
	/* configure shell type */
290
	/* Cases here should be ordered by most privileged to least privileged. */
291
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
292
		$user_shell = "/bin/tcsh";
293
	} elseif (userHasPrivilege($user, "user-copy-files")) {
294
		$user_shell = "/usr/local/bin/scponly";
295
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
296
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
297
	} else {
298
		$user_shell = "/sbin/nologin";
299
		$lock_account = true;
300
	}
301

    
302
	/* Lock out disabled or expired users, unless it's root/admin. */
303
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
304
		$user_shell = "/sbin/nologin";
305
		$lock_account = true;
306
	}
307

    
308
	/* root user special handling */
309
	if ($user_uid == 0) {
310
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
311
		if($debug)
312
			log_error("Running: {$cmd}");
313
		$fd = popen($cmd, "w");
314
		fwrite($fd, $user['password']);
315
		pclose($fd);
316
		$user_group = "wheel";
317
		$user_home = "/root";
318
		$user_shell = "/etc/rc.initial";
319
	}
320

    
321
	/* read from pw db */
322
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
323
	$pwread = fgets($fd);
324
	pclose($fd);
325

    
326
	/* determine add or mod */
327
	if (!strncmp($pwread, "pw:", 3)) {
328
		$user_op = "useradd -m -k /etc/skel -o";
329
	} else {
330
		$user_op = "usermod";
331
	}
332

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

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

    
344
	/* create user directory if required */
345
	if (!is_dir($user_home)) {
346
		mkdir($user_home, 0700);
347
		mwexec("cp /root/.* {$home_base}/");
348
	}
349
	chown($user_home, $user_name);
350
	chgrp($user_home, $user_group);
351

    
352
	/* write out ssh authorized key file */
353
	if($user['authorizedkeys']) {
354
		if (!is_dir("{$user_home}/.ssh")) {
355
			mkdir("{$user_home}/.ssh", 0700);
356
			chown("{$user_home}/.ssh", $user_name);
357
		}
358
		$keys = base64_decode($user['authorizedkeys']);
359
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
360
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
361
	}
362

    
363
	$un = $lock_account ? "" : "un";
364
	exec("/usr/sbin/pw {$un}lock -q {$user_name}");
365
	
366
	conf_mount_ro();
367
}
368

    
369
function local_user_del($user) {
370
	global $debug;
371

    
372
	/* remove all memberships */
373
	local_user_set_groups($user);
374

    
375
	/* Don't remove /root */
376
	if ($user['uid'] != 0)
377
		$rmhome = "-r";
378

    
379
	/* delete from pw db */
380
	$cmd = "/usr/sbin/pw userdel {$user['name']} {$rmhome}";
381

    
382
	if($debug)
383
		log_error("Running: {$cmd}");
384
	mwexec($cmd);
385

    
386
	/* Delete user from groups needs a call to write_config() */
387
	local_group_del_user($user);
388
}
389

    
390
function local_user_set_password(& $user, $password) {
391

    
392
	$user['password'] = crypt($password);
393
	$user['md5-hash'] = md5($password);
394

    
395
	// Converts ascii to unicode.
396
	$astr = (string) $password;
397
	$ustr = '';
398
	for ($i = 0; $i < strlen($astr); $i++) {
399
		$a = ord($astr{$i}) << 8;
400
		$ustr.= sprintf("%X", $a);
401
	}
402

    
403
	// Generate the NT-HASH from the unicode string
404
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
405
}
406

    
407
function local_user_get_groups($user, $all = false) {
408
	global $debug, $config;
409

    
410
	$groups = array();
411
	if (!is_array($config['system']['group']))
412
		return $groups;
413

    
414
	foreach ($config['system']['group'] as $group)
415
		if ( $all || ( !$all && ($group['name'] != "all")))
416
			if (is_array($group['member']))
417
				if (in_array($user['uid'], $group['member']))
418
					$groups[] = $group['name'];
419

    
420
	if ( $all )
421
		$groups[] = "all";
422

    
423
	sort($groups);
424

    
425
	return $groups;
426
	
427
}
428

    
429
function local_user_set_groups($user, $new_groups = NULL ) {
430
	global $debug, $config, $groupindex;
431

    
432
	if (!is_array($config['system']['group']))
433
		return;
434

    
435
	$cur_groups = local_user_get_groups($user, true);
436
	$mod_groups = array();
437

    
438
	if (!is_array($new_groups))
439
		$new_groups = array();
440

    
441
	if (!is_array($cur_groups))
442
		$cur_groups = array();
443

    
444
	/* determine which memberships to add */
445
	foreach ($new_groups as $groupname) {
446
		if (in_array($groupname,$cur_groups))
447
			continue;
448
		$group = & $config['system']['group'][$groupindex[$groupname]];
449
		$group['member'][] = $user['uid'];
450
		$mod_groups[] = $group;
451
	}
452

    
453
	/* determine which memberships to remove */
454
	foreach ($cur_groups as $groupname) {
455
		if (in_array($groupname,$new_groups))
456
			continue;
457
		$group = & $config['system']['group'][$groupindex[$groupname]];
458
		if (is_array($group['member'])) {
459
			$index = array_search($user['uid'], $group['member']);
460
			array_splice($group['member'], $index, 1);
461
			$mod_groups[] = $group;
462
		}
463
	}
464

    
465
	/* sync all modified groups */
466
	foreach ($mod_groups as $group)
467
		local_group_set($group);
468
}
469

    
470
function local_group_del_user($user) {
471
	global $config;
472

    
473
	if (!is_array($config['system']['group']))
474
                return;
475

    
476
        foreach ($config['system']['group'] as $group) {
477
		if (is_array($group['member'])) {
478
			foreach ($group['member'] as $idx => $uid) {
479
				if ($user['uid'] == $uid)
480
					unset($config['system']['group']['member'][$idx]);
481
			}
482
		}
483
	}
484
}
485

    
486
function local_group_set($group, $reset = false) {
487
	global $debug;
488

    
489
	$group_name = $group['name'];
490
	$group_gid = $group['gid'];
491
	$group_members = "''";
492
	if (!$reset && !empty($group['member']) && count($group['member']) > 0)
493
		$group_members = implode(",",$group['member']);
494

    
495
	/* read from group db */
496
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
497
	$pwread = fgets($fd);
498
	pclose($fd);
499

    
500
	/* determine add or mod */
501
	if (!strncmp($pwread, "pw:", 3))
502
		$group_op = "groupadd";
503
	else
504
		$group_op = "groupmod";
505

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

    
509
	if($debug)
510
		log_error("Running: {$cmd}");
511
	mwexec($cmd);
512

    
513
}
514

    
515
function local_group_del($group) {
516
	global $debug;
517

    
518
	/* delete from group db */
519
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
520

    
521
	if($debug)
522
		log_error("Running: {$cmd}");
523
	mwexec($cmd);
524
}
525

    
526
function ldap_test_connection($authcfg) {
527
	global $debug, $config, $g;
528

    
529
	if ($authcfg) {
530
                if (strstr($authcfg['ldap_urltype'], "Standard"))
531
                        $ldapproto = "ldap";
532
                else
533
                        $ldapproto = "ldaps";
534
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
535
                $ldapport           = $authcfg['ldap_port'];
536
                $ldapbasedn         = $authcfg['ldap_basedn'];
537
                $ldapbindun         = $authcfg['ldap_binddn'];
538
                $ldapbindpw         = $authcfg['ldap_bindpw'];
539
        } else
540
		return false;
541

    
542
        /* first check if there is even an LDAP server populated */
543
        if(!$ldapserver)
544
                return false;
545

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

    
555
        if ($error == true) {
556
                log_error("ERROR!  Could not connect to server {$ldapname}.");
557
                return false;
558
        }
559

    
560
	return true;
561
}
562

    
563
function ldap_test_bind($authcfg) {
564
	global $debug, $config, $g;
565

    
566
	if ($authcfg) {
567
                if (strstr($authcfg['ldap_urltype'], "Standard"))
568
                        $ldapproto = "ldap";
569
                else
570
                        $ldapproto = "ldaps";
571
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
572
                $ldapport           = $authcfg['ldap_port'];
573
                $ldapbasedn         = $authcfg['ldap_basedn'];
574
                $ldapbindun         = $authcfg['ldap_binddn'];
575
                $ldapbindpw         = $authcfg['ldap_bindpw'];
576
                $ldapver            = $authcfg['ldap_protver'];
577
		if (empty($ldapbndun) || empty($ldapbindpw))
578
                        $ldapanon = true;
579
                else
580
                        $ldapanon = false;
581
	} else
582
		return false;
583

    
584
	/* first check if there is even an LDAP server populated */
585
        if(!$ldapserver)
586
                return false;
587

    
588
        /* connect and see if server is up */
589
        putenv('LDAPTLS_REQCERT=never');
590
        $error = false;
591
        if (empty($ldapport)) {
592
                if (!($ldap = ldap_connect($ldapserver)))
593
                        $error = true;
594
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
595
                $error = true;
596

    
597
        if ($error == true) {
598
                log_error("ERROR!  Could not connect to server {$ldapname}.");
599
                return false;
600
        }
601

    
602
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
603
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
604
 
605
	if ($ldapanon == true) {
606
		if (!($res = @ldap_bind($ldap))) {
607
			@ldap_close($ldap);
608
			return false;
609
		}
610
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
611
		@ldap_close($ldap);
612
		return false;
613
	}
614

    
615
	@ldap_unbind($ldap);
616

    
617
	return true;
618
}
619

    
620
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
621
	global $debug, $config, $g;
622

    
623
	if(!function_exists("ldap_connect"))
624
		return;
625

    
626
	$ous = array();
627

    
628
	if ($authcfg) {
629
                if (strstr($authcfg['ldap_urltype'], "Standard"))
630
                        $ldapproto = "ldap";
631
                else
632
                        $ldapproto = "ldaps";
633
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
634
                $ldapport           = $authcfg['ldap_port'];
635
                $ldapbasedn         = $authcfg['ldap_basedn'];
636
                $ldapbindun         = $authcfg['ldap_binddn'];
637
                $ldapbindpw         = $authcfg['ldap_bindpw'];
638
                $ldapver            = $authcfg['ldap_protver'];
639
		if (empty($ldapbindun) || empty($ldapbindpw))
640
                        $ldapanon = true;
641
                else
642
                        $ldapanon = false;
643
                $ldapname           = $authcfg['name'];
644
                $ldapfallback       = false;
645
		$ldapscope          = $authcfg['ldap_scope'];
646
        } else
647
		return false;
648

    
649
        /* first check if there is even an LDAP server populated */
650
        if(!$ldapserver) {
651
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
652
                return $ous;
653
        }
654

    
655
	/* connect and see if server is up */
656
        putenv('LDAPTLS_REQCERT=never');
657
        $error = false;
658
        if (empty($ldapport)) {
659
                if (!($ldap = ldap_connect($ldapserver)))
660
                        $error = true;
661
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
662
                $error = true;
663

    
664
        if ($error == true) {
665
		log_error("ERROR!  Could not connect to server {$ldapname}.");
666
                return $ous;
667
        }
668

    
669
	$ldapfilter = "(|(ou=*)(cn=Users))";
670

    
671
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
672
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
673

    
674
	if ($ldapanon == true) {
675
                if (!($res = @ldap_bind($ldap))) {
676
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
677
			@ldap_close($ldap);
678
                        return $ous;
679
		}
680
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
681
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
682
		@ldap_close($ldap);
683
		return $ous;
684
	}
685

    
686
	if ($ldapscope == "one")
687
		$ldapfunc = "ldap_list";
688
	else
689
		$ldapfunc = "ldap_search";
690

    
691
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
692
	$info = @ldap_get_entries($ldap, $search);
693

    
694
	if (is_array($info)) {
695
		foreach ($info as $inf) {
696
			if (!$show_complete_ou) {
697
				$inf_split = split(",", $inf['dn']);
698
				$ou = $inf_split[0];
699
				$ou = str_replace("OU=","", $ou);
700
				$ou = str_replace("CN=","", $ou);
701
			} else
702
				if($inf['dn'])
703
					$ou = $inf['dn'];
704
			if($ou)
705
				$ous[] = $ou;
706
		}
707
	}
708

    
709
	@ldap_unbind($ldap);
710

    
711
	return $ous;
712
}
713

    
714
function ldap_get_groups($username, $authcfg) {
715
	global $debug, $config;
716
	
717
	if(!function_exists("ldap_connect"))
718
		return;
719
	
720
	if(!$username) 
721
		return false;
722

    
723
	if(stristr($username, "@")) {
724
		$username_split=split("\@", $username);
725
		$username = $username_split[0];		
726
	}
727

    
728
	if(stristr($username, "\\")) {
729
		$username_split=split("\\", $username);
730
		$username = $username_split[0];        
731
	}    
732
	
733
	//log_error("Getting LDAP groups for {$username}.");
734
        if ($authcfg) {
735
                if (strstr($authcfg['ldap_urltype'], "Standard"))
736
                        $ldapproto = "ldap";
737
                else
738
                        $ldapproto = "ldaps";
739
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
740
                $ldapport           = $authcfg['ldap_port'];
741
                $ldapbasedn         = $authcfg['ldap_basedn'];
742
                $ldapbindun         = $authcfg['ldap_binddn'];
743
                $ldapbindpw         = $authcfg['ldap_bindpw'];
744
                $ldapauthcont       = $authcfg['ldap_authcn'];
745
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
746
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
747
                $ldapfilter         = "({$ldapnameattribute}={$username})";
748
                $ldaptype           = "";
749
                $ldapver            = $authcfg['ldap_protver'];
750
		if (empty($ldapbindun) || empty($ldapbindpw))
751
                        $ldapanon = true;
752
                else
753
                        $ldapanon = false;
754
                $ldapname           = $authcfg['name'];
755
                $ldapfallback       = false;
756
		$ldapscope          = $authcfg['ldap_scope'];
757
	} else
758
		return false;
759

    
760
	$ldapdn             = $_SESSION['ldapdn'];
761

    
762
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
763
	$ldapgroupattribute = strtolower($ldapgroupattribute);
764
	$memberof = array();
765

    
766
	/* connect and see if server is up */
767
	putenv('LDAPTLS_REQCERT=never');
768
	$error = false;
769
        if (empty($ldapport)) {
770
                if (!($ldap = ldap_connect($ldapserver)))
771
                        $error = true;
772
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
773
                $error = true;
774

    
775
	if ($error == true) {
776
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
777
                return memberof;
778
        }
779
    
780
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
781
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
782

    
783
	/* bind as user that has rights to read group attributes */
784
	if ($ldapanon == true) {
785
                if (!($res = @ldap_bind($ldap))) {
786
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
787
			@ldap_close($ldap);
788
                        return false;
789
		}
790
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
791
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
792
		@ldap_close($ldap);
793
		return memberof;
794
	}
795

    
796
	/* get groups from DN found */
797
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
798
	/* since we know the DN is in $_SESSION['ldapdn'] */
799
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
800
	if ($ldapscope == "one")
801
                $ldapfunc = "ldap_list";
802
        else
803
                $ldapfunc = "ldap_search";
804

    
805
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
806
	$info      = @ldap_get_entries($ldap, $search);
807

    
808
	$countem = $info["count"];	
809
	
810
	if(is_array($info[0][$ldapgroupattribute])) {
811
		/* Iterate through the groups and throw them into an array */
812
		foreach ($info[0][$ldapgroupattribute] as $member) {
813
			if (stristr($member, "CN=") !== false) {
814
				$membersplit = split(",", $member);
815
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
816
			}
817
		}
818
	}
819
	
820
	/* Time to close LDAP connection */
821
	@ldap_unbind($ldap);
822
	
823
	$groups = print_r($memberof,true);
824
	
825
	//log_error("Returning groups ".$groups." for user $username");
826
	
827
	return $memberof;
828
}
829

    
830
function ldap_backed($username, $passwd, $authcfg) {
831
	global $debug, $config;
832
	
833
	if(!$username) 
834
		return;
835

    
836
	if(!function_exists("ldap_connect"))
837
		return;
838

    
839
	if(stristr($username, "@")) {
840
		$username_split=split("\@", $username);
841
		$username = $username_split[0];        
842
	}
843
	if(stristr($username, "\\")) {
844
		$username_split=split("\\", $username);
845
		$username = $username_split[0];        
846
	}
847

    
848
	if ($authcfg) {
849
		if (strstr($authcfg['ldap_urltype'], "Standard"))
850
			$ldapproto = "ldap";
851
		else
852
			$ldapproto = "ldaps";
853
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
854
		$ldapport	    = $authcfg['ldap_port'];
855
                $ldapbasedn         = $authcfg['ldap_basedn'];
856
                $ldapbindun         = $authcfg['ldap_binddn'];
857
                $ldapbindpw         = $authcfg['ldap_bindpw'];
858
		if (empty($ldapbindun) || empty($ldapbindpw))
859
			$ldapanon = true;
860
		else
861
			$ldapanon = false;
862
                $ldapauthcont       = $authcfg['ldap_authcn'];
863
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
864
                $ldapfilter         = "({$ldapnameattribute}={$username})";
865
                $ldaptype           = "";
866
                $ldapver            = $authcfg['ldap_protver'];
867
		$ldapname	    = $authcfg['name'];
868
		$ldapscope	    = $authcfg['ldap_scope'];
869
	} else
870
		return false;
871

    
872
	/* first check if there is even an LDAP server populated */ 
873
	if(!$ldapserver) {
874
		if ($ldapfallback) {
875
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager.");
876
			return local_backed($username, $passwd);
877
		} else
878
			log_error("ERROR! ldap_backed() called with no LDAP authentication server defined.");
879

    
880
		return false;
881
	}
882
	
883
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
884
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
885

    
886
	/* Make sure we can connect to LDAP */
887
	putenv('LDAPTLS_REQCERT=never');
888
	$error = false;
889
	if (empty($ldapport)) {
890
		if (!($ldap = ldap_connect($ldapserver)))
891
			$error = true;
892
	} else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
893
		$error = true;
894

    
895
	if ($error == true) {
896
		log_error("ERROR!  Could not connect to server {$ldapname}.");
897
		return false;
898
	}
899

    
900
	/* ok, its up.  now, lets bind as the bind user so we can search it */
901
	$error = false;
902
	if ($ldapanon == true) {
903
                if (!($res = @ldap_bind($ldap)))
904
                        $error = true;
905
	} else if (!($res = ldap_bind($ldap, $ldapbindun, $ldapbindpw)))
906
		$error = true;
907

    
908
	if ($error == true) {
909
		@ldap_close($ldap);
910
		log_error("ERROR! Could not bind to server {$ldapname}.");
911
		return false;
912
	}
913
	
914
	/* Get LDAP Authcontainers and split em up. */
915
	$ldac_splits = split(";", $ldapauthcont);
916
	
917
	/* setup the usercount so we think we havn't found anyone yet */
918
	$usercount  = 0;
919

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

    
956
	if ($usercount != 1){
957
		@ldap_unbind($ldap);
958
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
959
		return false;                         
960
	}
961

    
962
	/* Now lets bind as the user we found */
963
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
964
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
965
		@ldap_unbind($ldap);
966
		return false;
967
	}
968

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

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

    
974
	return true;
975
}
976

    
977
function radius_backed($username, $passwd, $authcfg){
978
	global $debug, $config;
979
	$ret = false;
980

    
981
	require_once("radius.inc");
982

    
983
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
984
	if ($authcfg) {
985
		$radiusservers = array();
986
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
987
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
988
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
989
	} else
990
		return false;
991

    
992
	/* Add a new servers to our instance */
993
	foreach ($radiusservers as $radsrv)
994
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
995

    
996
	if (PEAR::isError($rauth->start())) {
997
		$retvalue['auth_val'] = 1;
998
		$retvalue['error'] = $rauth->getError();
999
		if ($debug)
1000
			printf("Radius start: %s<br>\n", $retvalue['error']);
1001
	}
1002

    
1003
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1004

    
1005
	/* Send request */
1006
	$result = $rauth->send();
1007
	if (PEAR::isError($result)) {
1008
		$retvalue['auth_val'] = 1;
1009
		$retvalue['error'] = $result->getMessage();
1010
		if ($debug)
1011
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
1012
	} else if ($result === true) {
1013
		$retvalue['auth_val'] = 2;
1014
		if ($debug)
1015
			printf(gettext("Radius Auth succeeded")."<br>\n");
1016
		$ret = true;
1017
	} else {
1018
		$retvalue['auth_val'] = 3;
1019
		if ($debug)
1020
			printf(gettext("Radius Auth rejected")."<br>\n");
1021
	}
1022

    
1023
	// close OO RADIUS_AUTHENTICATION
1024
	$rauth->close();
1025

    
1026
	return $ret;
1027
}
1028

    
1029
function get_user_expiration_date($username) {
1030
	$user = getUserEntry($username);
1031
	if ($user['expires']) 
1032
		return $user['expires'];
1033
}
1034

    
1035
function is_account_expired($username) {
1036
	$expirydate = get_user_expiration_date($username);
1037
	if ($expirydate) {
1038
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1039
			return true;
1040
	}
1041

    
1042
	return false;
1043
}
1044

    
1045
function is_account_disabled($username) {
1046
	$user = getUserEntry($username);
1047
	if (isset($user['disabled']))
1048
		return true;
1049

    
1050
	return false;
1051
}
1052

    
1053
function auth_get_authserver($name) {
1054
        global $config;
1055

    
1056
        if (is_array($config['system']['authserver'])) {
1057
                foreach ($config['system']['authserver'] as $authcfg) {
1058
                        if ($authcfg['name'] == $name)
1059
                                return $authcfg;
1060
                }
1061
        }
1062
	if ($name == "Local Database")
1063
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1064
}
1065

    
1066
function auth_get_authserver_list() {
1067
        global $config;
1068

    
1069
	$list = array();
1070

    
1071
        if (is_array($config['system']['authserver'])) {
1072
                foreach ($config['system']['authserver'] as $authcfg) {
1073
			/* Add support for disabled entries? */
1074
			$list[$authcfg['name']] = $authcfg;
1075
                }
1076
        }
1077

    
1078
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1079
	return $list;
1080
}
1081

    
1082
function getUserGroups($username, $authcfg) {
1083
	global $config;
1084

    
1085
	$allowed_groups = array();
1086

    
1087
	switch($authcfg['type']) {
1088
        case 'ldap':
1089
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1090
		break;
1091
	case 'radius':
1092
		break;
1093
	default:
1094
		$user = getUserEntry($username);
1095
		$allowed_groups = @local_user_get_groups($user, true);
1096
		break;
1097
	}
1098

    
1099
	$member_groups = array();
1100
        if (is_array($config['system']['group'])) {
1101
                foreach ($config['system']['group'] as $group)
1102
                        if (in_array($group['name'], $allowed_groups))
1103
				$member_groups[] = $group['name'];
1104
	}
1105

    
1106
	return $member_groups;
1107
}
1108

    
1109
function authenticate_user($username, $password, $authcfg = NULL) {
1110

    
1111
	if (!$authcfg) {
1112
		return local_backed($username, $password);
1113
	}
1114

    
1115
	$authenticated = false;
1116
	switch($authcfg['type']) {
1117
        case 'ldap':
1118
                if (ldap_backed($username, $password, $authcfg))
1119
                        $authenticated = true;
1120
                break;
1121
        case 'radius':
1122
                if (radius_backed($username, $password, $authcfg))
1123
                        $authenticated = true;
1124
                break;
1125
        default:
1126
                /* lookup user object by name */
1127
                if (local_backed($username, $password))
1128
                        $authenticated = true;
1129
                break;
1130
        }
1131

    
1132
	return $authenticated;
1133
}
1134

    
1135
function session_auth() {
1136
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1137

    
1138
	session_start();
1139

    
1140
	/* Validate incoming login request */
1141
	if (isset($_POST['login'])) {
1142
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1143
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1144
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1145
			$_SESSION['Logged_In'] = "True";
1146
			$_SESSION['Username'] = $_POST['usernamefld'];
1147
			$_SESSION['last_access'] = time();
1148
			log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1149
			$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1150
			if (isset($_POST['postafterlogin']))
1151
				return true;
1152
			else {
1153
				if (empty($page))
1154
					$page = "/";
1155
				header("Location: {$page}");
1156
			}
1157
			exit;
1158
		} else {
1159
			/* give the user an error message */
1160
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1161
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1162
			if(isAjax()) {
1163
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1164
				return;
1165
			}
1166
		}
1167
	}
1168

    
1169
	/* Show login page if they aren't logged in */
1170
	if (empty($_SESSION['Logged_In']))
1171
		return false;
1172

    
1173
	/* If session timeout isn't set, we don't mark sessions stale */
1174
	if (!isset($config['system']['webgui']['session_timeout'])) {
1175
		/* Default to 4 hour timeout if one is not set */
1176
		if ($_SESSION['last_access'] < (time() - 14400)) {
1177
			$_GET['logout'] = true;
1178
			$_SESSION['Logout'] = true;
1179
		} else
1180
			$_SESSION['last_access'] = time();	
1181
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1182
		/* only update if it wasn't ajax */
1183
		if (!isAjax())
1184
			$_SESSION['last_access'] = time();
1185
	} else {
1186
		/* Check for stale session */
1187
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1188
			$_GET['logout'] = true;
1189
			$_SESSION['Logout'] = true;
1190
		} else {
1191
			/* only update if it wasn't ajax */
1192
			if (!isAjax())
1193
				$_SESSION['last_access'] = time();
1194
		}
1195
	}
1196

    
1197
	/* user hit the logout button */
1198
	if (isset($_GET['logout'])) {
1199

    
1200
		if ($_SESSION['Logout'])
1201
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1202
		else
1203
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1204

    
1205
		/* wipe out $_SESSION */
1206
		$_SESSION = array();
1207

    
1208
		if (isset($_COOKIE[session_name()]))
1209
			setcookie(session_name(), '', time()-42000, '/');
1210

    
1211
		/* and destroy it */
1212
		session_destroy();
1213

    
1214
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1215
		$scriptElms = count($scriptName);
1216
		$scriptName = $scriptName[$scriptElms-1];
1217

    
1218
		if (isAjax())
1219
			return false;
1220

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

    
1224
		return false;
1225
	}
1226

    
1227
	/*
1228
	 * this is for debugging purpose if you do not want to use Ajax
1229
	 * to submit a HTML form. It basically diables the observation
1230
	 * of the submit event and hence does not trigger Ajax.
1231
	 */
1232
	if ($_GET['disable_ajax'])
1233
		$_SESSION['NO_AJAX'] = "True";
1234

    
1235
	/*
1236
	 * Same to re-enable Ajax.
1237
	 */
1238
	if ($_GET['enable_ajax'])
1239
		unset($_SESSION['NO_AJAX']);
1240

    
1241
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1242
	return true;
1243
}
1244

    
1245
?>
(4-4/54)