Project

General

Profile

Download (34.8 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
/* 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 (isset($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 (isset($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 groups */
259
	if (is_array($config['system']['group']))
260
		foreach ($config['system']['group'] as $group)
261
			local_group_set($group);
262

    
263
	/* sync all local users */
264
	if (is_array($config['system']['user']))
265
		foreach ($config['system']['user'] as $user)
266
			local_user_set($user);
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
	/* configure shell type */
289
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
290
		$user_shell = "/bin/tcsh";
291
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
292
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
293
	} elseif (userHasPrivilege($user, "user-copy-files")) {
294
		$user_shell = "/usr/local/bin/scponly";
295
	} else {
296
		$user_shell = "/sbin/nologin";
297
	}
298

    
299
	/* root user special handling */
300
	if ($user_uid == 0) {
301
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -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
		$user_home = "/root";
309
		$user_shell = "/etc/rc.initial";
310
	}
311

    
312
	/* read from pw db */
313
	$fd = popen("/usr/sbin/pw usershow {$user_name} 2>&1", "r");
314
	$pwread = fgets($fd);
315
	pclose($fd);
316

    
317
	/* determine add or mod */
318
	if (!strncmp($pwread, "pw:", 3)) {
319
		$user_op = "useradd -m -k /etc/skel -o";
320
	} else {
321
		$user_op = "usermod";
322
	}
323

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

    
329
	if($debug)
330
		log_error("Running: {$cmd}");
331
	$fd = popen($cmd, "w");
332
	fwrite($fd, $user['password']);
333
	pclose($fd);
334

    
335
	/* create user directory if required */
336
	if (!is_dir($user_home)) {
337
		mkdir($user_home, 0700);
338
		mwexec("cp /root/.* {$home_base}/");
339
	}
340
	chown($user_home, $user_name);
341
	chgrp($user_home, $user_group);
342

    
343
	/* write out ssh authorized key file */
344
	if($user['authorizedkeys']) {
345
		if (!is_dir("{$user_home}/.ssh")) {
346
			mkdir("{$user_home}/.ssh", 0700);
347
			chown("{$user_home}/.ssh", $user_name);
348
		}
349
		$keys = base64_decode($user['authorizedkeys']);
350
		file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
351
		chown("{$user_home}/.ssh/authorized_keys", $user_name);
352
	}
353
	
354
	conf_mount_ro();
355
}
356

    
357
function local_user_del($user) {
358
	global $debug;
359

    
360
	/* remove all memberships */
361
	local_user_set_groups($user);
362

    
363
	/* Don't remove /root */
364
	if ($user['uid'] != 0)
365
		$rmhome = "-r";
366

    
367
	/* delete from pw db */
368
	$cmd = "/usr/sbin/pw userdel {$user['name']} {$rmhome}";
369

    
370
	if($debug)
371
		log_error("Running: {$cmd}");
372
	mwexec($cmd);
373

    
374
	/* Delete user from groups needs a call to write_config() */
375
	local_group_del_user($user);
376
}
377

    
378
function local_user_set_password(& $user, $password) {
379

    
380
	$user['password'] = crypt($password);
381
	$user['md5-hash'] = md5($password);
382

    
383
	// Converts ascii to unicode.
384
	$astr = (string) $password;
385
	$ustr = '';
386
	for ($i = 0; $i < strlen($astr); $i++) {
387
		$a = ord($astr{$i}) << 8;
388
		$ustr.= sprintf("%X", $a);
389
	}
390

    
391
	// Generate the NT-HASH from the unicode string
392
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
393
}
394

    
395
function local_user_get_groups($user, $all = false) {
396
	global $debug, $config;
397

    
398
	$groups = array();
399
	if (!is_array($config['system']['group']))
400
		return $groups;
401

    
402
	foreach ($config['system']['group'] as $group)
403
		if ( $all || ( !$all && ($group['name'] != "all")))
404
			if (is_array($group['member']))
405
				if (in_array($user['uid'], $group['member']))
406
					$groups[] = $group['name'];
407

    
408
	sort($groups);
409

    
410
	return $groups;
411
	
412
}
413

    
414
function local_user_set_groups($user, $new_groups = NULL ) {
415
	global $debug, $config, $groupindex;
416

    
417
	if (!is_array($config['system']['group']))
418
		return;
419

    
420
	$cur_groups = local_user_get_groups($user, true);
421
	$mod_groups = array();
422

    
423
	if (!is_array($new_groups))
424
		$new_groups = array();
425

    
426
	if (!is_array($cur_groups))
427
		$cur_groups = array();
428

    
429
	/* determine which memberships to add */
430
	foreach ($new_groups as $groupname) {
431
		if (in_array($groupname,$cur_groups))
432
			continue;
433
		$group = & $config['system']['group'][$groupindex[$groupname]];
434
		$group['member'][] = $user['uid'];
435
		$mod_groups[] = $group;
436
	}
437

    
438
	/* determine which memberships to remove */
439
	foreach ($cur_groups as $groupname) {
440
		if (in_array($groupname,$new_groups))
441
			continue;
442
		$group = & $config['system']['group'][$groupindex[$groupname]];
443
		$index = array_search($user['uid'], $group['member']);
444
		array_splice($group['member'], $index, 1);
445
		$mod_groups[] = $group;
446
	}
447

    
448
	/* sync all modified groups */
449
	foreach ($mod_groups as $group)
450
		local_group_set($group);
451
}
452

    
453
function local_group_del_user($user) {
454
	global $config;
455

    
456
	if (!is_array($config['system']['group']))
457
                return;
458

    
459
        foreach ($config['system']['group'] as $group) {
460
		if (is_array($group['member'])) {
461
			foreach ($group['member'] as $idx => $uid) {
462
				if ($user['uid'] == $uid)
463
					unset($config['system']['group']['member'][$idx]);
464
			}
465
		}
466
	}
467
}
468

    
469
function local_group_set($group, $reset = false) {
470
	global $debug;
471

    
472
	$group_name = $group['name'];
473
	$group_gid = $group['gid'];
474
	$group_members = "''";
475
	if (!$reset && count($group['member']))
476
		$group_members = implode(",",$group['member']);
477

    
478
	/* read from group db */
479
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
480
	$pwread = fgets($fd);
481
	pclose($fd);
482

    
483
	/* determine add or mod */
484
	if (!strncmp($pwread, "pw:", 3))
485
		$group_op = "groupadd";
486
	else
487
		$group_op = "groupmod";
488

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

    
492
	if($debug)
493
		log_error("Running: {$cmd}");
494
	mwexec($cmd);
495

    
496
}
497

    
498
function local_group_del($group) {
499
	global $debug;
500

    
501
	/* delete from group db */
502
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
503

    
504
	if($debug)
505
		log_error("Running: {$cmd}");
506
	mwexec($cmd);
507
}
508

    
509
function ldap_test_connection($authcfg) {
510
	global $debug, $config, $g;
511

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

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

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

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

    
543
	return true;
544
}
545

    
546
function ldap_test_bind($authcfg) {
547
	global $debug, $config, $g;
548

    
549
	if ($authcfg) {
550
                if (strstr($authcfg['ldap_urltype'], "Standard"))
551
                        $ldapproto = "ldap";
552
                else
553
                        $ldapproto = "ldaps";
554
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
555
                $ldapport           = $authcfg['ldap_port'];
556
                $ldapbasedn         = $authcfg['ldap_basedn'];
557
                $ldapbindun         = $authcfg['ldap_binddn'];
558
                $ldapbindpw         = $authcfg['ldap_bindpw'];
559
                $ldapver            = $authcfg['ldap_protver'];
560
		if (empty($ldapbndun) || empty($ldapbindpw))
561
                        $ldapanon = true;
562
                else
563
                        $ldapanon = false;
564
	} else
565
		return false;
566

    
567
	/* first check if there is even an LDAP server populated */
568
        if(!$ldapserver)
569
                return false;
570

    
571
        /* connect and see if server is up */
572
        putenv('LDAPTLS_REQCERT=never');
573
        $error = false;
574
        if (empty($ldapport)) {
575
                if (!($ldap = ldap_connect($ldapserver)))
576
                        $error = true;
577
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
578
                $error = true;
579

    
580
        if ($error == true) {
581
                log_error("ERROR!  Could not connect to server {$ldapname}.");
582
                return false;
583
        }
584

    
585
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
586
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
587
 
588
	if ($ldapanon == true) {
589
		if (!($res = @ldap_bind($ldap))) {
590
			@ldap_close($ldap);
591
			return false;
592
		}
593
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
594
		@ldap_close($ldap);
595
		return false;
596
	}
597

    
598
	@ldap_unbind($ldap);
599

    
600
	return true;
601
}
602

    
603
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
604
	global $debug, $config, $g;
605

    
606
	if(!function_exists("ldap_connect"))
607
		return;
608

    
609
	$ous = array();
610

    
611
	if ($authcfg) {
612
                if (strstr($authcfg['ldap_urltype'], "Standard"))
613
                        $ldapproto = "ldap";
614
                else
615
                        $ldapproto = "ldaps";
616
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
617
                $ldapport           = $authcfg['ldap_port'];
618
                $ldapbasedn         = $authcfg['ldap_basedn'];
619
                $ldapbindun         = $authcfg['ldap_binddn'];
620
                $ldapbindpw         = $authcfg['ldap_bindpw'];
621
                $ldapver            = $authcfg['ldap_protver'];
622
		if (empty($ldapbindun) || empty($ldapbindpw))
623
                        $ldapanon = true;
624
                else
625
                        $ldapanon = false;
626
                $ldapname           = $authcfg['name'];
627
                $ldapfallback       = false;
628
		$ldapscope          = $authcfg['ldap_scope'];
629
        } else
630
		return false;
631

    
632
        /* first check if there is even an LDAP server populated */
633
        if(!$ldapserver) {
634
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
635
                return $ous;
636
        }
637

    
638
	/* connect and see if server is up */
639
        putenv('LDAPTLS_REQCERT=never');
640
        $error = false;
641
        if (empty($ldapport)) {
642
                if (!($ldap = ldap_connect($ldapserver)))
643
                        $error = true;
644
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
645
                $error = true;
646

    
647
        if ($error == true) {
648
		log_error("ERROR!  Could not connect to server {$ldapname}.");
649
                return $ous;
650
        }
651

    
652
	$ldapfilter = "(|(ou=*)(cn=Users))";
653

    
654
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
655
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
656

    
657
	if ($ldapanon == true) {
658
                if (!($res = @ldap_bind($ldap))) {
659
			log_error("ERROR! ldap_get_user_ous() could not bind anonymously to server {$ldapname}.");
660
			@ldap_close($ldap);
661
                        return $ous;
662
		}
663
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
664
		log_error("ERROR! ldap_get_user_ous() could not bind to server {$ldapname}.");
665
		@ldap_close($ldap);
666
		return $ous;
667
	}
668

    
669
	if ($ldapscope == "one")
670
		$ldapfunc = "ldap_list";
671
	else
672
		$ldapfunc = "ldap_search";
673

    
674
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
675
	$info = @ldap_get_entries($ldap, $search);
676

    
677
	if (is_array($info)) {
678
		foreach ($info as $inf) {
679
			if (!$show_complete_ou) {
680
				$inf_split = split(",", $inf['dn']);
681
				$ou = $inf_split[0];
682
				$ou = str_replace("OU=","", $ou);
683
				$ou = str_replace("CN=","", $ou);
684
			} else
685
				if($inf['dn'])
686
					$ou = $inf['dn'];
687
			if($ou)
688
				$ous[] = $ou;
689
		}
690
	}
691

    
692
	@ldap_unbind($ldap);
693

    
694
	return $ous;
695
}
696

    
697
function ldap_get_groups($username, $authcfg) {
698
	global $debug, $config;
699
	
700
	if(!function_exists("ldap_connect"))
701
		return;
702
	
703
	if(!$username) 
704
		return false;
705

    
706
	if(stristr($username, "@")) {
707
		$username_split=split("\@", $username);
708
		$username = $username_split[0];		
709
	}
710

    
711
	if(stristr($username, "\\")) {
712
		$username_split=split("\\", $username);
713
		$username = $username_split[0];        
714
	}    
715
	
716
	//log_error("Getting LDAP groups for {$username}.");
717
        if ($authcfg) {
718
                if (strstr($authcfg['ldap_urltype'], "Standard"))
719
                        $ldapproto = "ldap";
720
                else
721
                        $ldapproto = "ldaps";
722
                $ldapserver         = "{$ldapproto}://{$authcfg['host']}";
723
                $ldapport           = $authcfg['ldap_port'];
724
                $ldapbasedn         = $authcfg['ldap_basedn'];
725
                $ldapbindun         = $authcfg['ldap_binddn'];
726
                $ldapbindpw         = $authcfg['ldap_bindpw'];
727
                $ldapauthcont       = $authcfg['ldap_authcn'];
728
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
729
                $ldapgroupattribute  = strtolower($authcfg['ldap_attr_member']);
730
                $ldapfilter         = "({$ldapnameattribute}={$username})";
731
                $ldaptype           = "";
732
                $ldapver            = $authcfg['ldap_protver'];
733
		if (empty($ldapbindun) || empty($ldapbindpw))
734
                        $ldapanon = true;
735
                else
736
                        $ldapanon = false;
737
                $ldapname           = $authcfg['name'];
738
                $ldapfallback       = false;
739
		$ldapscope          = $authcfg['ldap_scope'];
740
	} else
741
		return false;
742

    
743
	$ldapdn             = $_SESSION['ldapdn'];
744

    
745
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
746
	$ldapgroupattribute = strtolower($ldapgroupattribute);
747
	$memberof = array();
748

    
749
	/* connect and see if server is up */
750
	putenv('LDAPTLS_REQCERT=never');
751
	$error = false;
752
        if (empty($ldapport)) {
753
                if (!($ldap = ldap_connect($ldapserver)))
754
                        $error = true;
755
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
756
                $error = true;
757

    
758
	if ($error == true) {
759
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
760
                return memberof;
761
        }
762
    
763
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
764
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
765

    
766
	/* bind as user that has rights to read group attributes */
767
	if ($ldapanon == true) {
768
                if (!($res = @ldap_bind($ldap))) {
769
			log_error("ERROR! ldap_get_groups() could not bind anonymously to server {$ldapname}.");
770
			@ldap_close($ldap);
771
                        return false;
772
		}
773
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
774
		log_error("ERROR! ldap_get_groups() could not bind to server {$ldapname}.");
775
		@ldap_close($ldap);
776
		return memberof;
777
	}
778

    
779
	/* get groups from DN found */
780
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
781
	/* since we know the DN is in $_SESSION['ldapdn'] */
782
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
783
	if ($ldapscope == "one")
784
                $ldapfunc = "ldap_list";
785
        else
786
                $ldapfunc = "ldap_search";
787

    
788
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
789
	$info      = @ldap_get_entries($ldap, $search);
790

    
791
	$countem = $info["count"];	
792
	
793
	if(is_array($info[0][$ldapgroupattribute])) {
794
		/* Iterate through the groups and throw them into an array */
795
		foreach ($info[0][$ldapgroupattribute] as $member) {
796
			if (stristr($member, "CN=") !== false) {
797
				$membersplit = split(",", $member);
798
				$memberof[] = preg_replace("/CN=/i", "", $membersplit[0]);
799
			}
800
		}
801
	}
802
	
803
	/* Time to close LDAP connection */
804
	@ldap_unbind($ldap);
805
	
806
	$groups = print_r($memberof,true);
807
	
808
	//log_error("Returning groups ".$groups." for user $username");
809
	
810
	return $memberof;
811
}
812

    
813
function ldap_backed($username, $passwd, $authcfg) {
814
	global $debug, $config;
815
	
816
	if(!$username) 
817
		return;
818

    
819
	if(!function_exists("ldap_connect"))
820
		return;
821

    
822
	if(stristr($username, "@")) {
823
		$username_split=split("\@", $username);
824
		$username = $username_split[0];        
825
	}
826
	if(stristr($username, "\\")) {
827
		$username_split=split("\\", $username);
828
		$username = $username_split[0];        
829
	}
830

    
831
	if ($authcfg) {
832
		if (strstr($authcfg['ldap_urltype'], "Standard"))
833
			$ldapproto = "ldap";
834
		else
835
			$ldapproto = "ldaps";
836
		$ldapserver         = "{$ldapproto}://{$authcfg['host']}";
837
		$ldapport	    = $authcfg['ldap_port'];
838
                $ldapbasedn         = $authcfg['ldap_basedn'];
839
                $ldapbindun         = $authcfg['ldap_binddn'];
840
                $ldapbindpw         = $authcfg['ldap_bindpw'];
841
		if (empty($ldapbindun) || empty($ldapbindpw))
842
			$ldapanon = true;
843
		else
844
			$ldapanon = false;
845
                $ldapauthcont       = $authcfg['ldap_authcn'];
846
                $ldapnameattribute  = strtolower($authcfg['ldap_attr_user']);
847
                $ldapfilter         = "({$ldapnameattribute}={$username})";
848
                $ldaptype           = "";
849
                $ldapver            = $authcfg['ldap_protver'];
850
		$ldapname	    = $authcfg['name'];
851
		$ldapscope	    = $authcfg['ldap_scope'];
852
	} else
853
		return false;
854

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

    
863
		return false;
864
	}
865
	
866
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
867
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
868

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

    
878
	if ($error == true) {
879
		log_error("ERROR!  Could not connect to server {$ldapname}.");
880
		return false;
881
	}
882

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

    
891
	if ($error == true) {
892
		@ldap_close($ldap);
893
		log_error("ERROR! Could not bind to server {$ldapname}.");
894
		return false;
895
	}
896
	
897
	/* Get LDAP Authcontainers and split em up. */
898
	$ldac_splits = split(";", $ldapauthcont);
899
	
900
	/* setup the usercount so we think we havn't found anyone yet */
901
	$usercount  = 0;
902

    
903
	/*****************************************************************/
904
	/*  We First find the user based on username and filter          */
905
	/*  Then, once we find the first occurance of that person        */
906
	/*  We set seesion variables to ponit to the OU and DN of the    */
907
	/*  Person.  To later be used by ldap_get_groups.                */
908
	/*  that way we don't have to search twice.                      */
909
	/*****************************************************************/
910
	log_error("Now Searching for {$username} in directory.");
911
	/* Iterate through the user containers for search */
912
	foreach ($ldac_splits as $i => $ldac_split) {
913
		/* Make sure we just use the first user we find */
914
		log_error("Now Searching in server {$ldapname}, container {$ldac_split} with filter {$ldapfilter}.");
915
		if ($ldapscope == "one")
916
			$ldapfunc = "ldap_list";
917
		else
918
			$ldapfunc = "ldap_search";
919
		/* Support legacy auth container specification. */
920
		if (stristr($ldac_split, "DC="))
921
			$search	 = @$ldapfunc($ldap,$ldac_split,$ldapfilter);
922
		else
923
			$search  = @$ldapfunc($ldap,"{$ldac_split},{$ldapbasedn}",$ldapfilter);
924
		if (!$search) {
925
			log_error("Search resulted in error: " . ldap_error($ldap));
926
			continue;
927
		}
928
		$info	 = ldap_get_entries($ldap,$search);
929
		$matches = $info['count'];
930
		if ($matches == 1){
931
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
932
			$_SESSION['ldapou'] = $ldac_split[$i];
933
			$_SESSION['ldapon'] = "true";
934
			$usercount = 1;
935
			break;
936
		}
937
	}
938

    
939
	if ($usercount != 1){
940
		@ldap_unbind($ldap);
941
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
942
		return false;                         
943
	}
944

    
945
	/* Now lets bind as the user we found */
946
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
947
		log_error("ERROR! Could not login to server {$ldapname} as user {$username}.");
948
		@ldap_unbind($ldap);
949
		return false;
950
	}
951

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

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

    
957
	return true;
958
}
959

    
960
function radius_backed($username, $passwd, $authcfg){
961
	global $debug, $config;
962
	$ret = false;
963

    
964
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
965
	if ($authcfg) {
966
		$radiusservers = array();
967
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
968
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
969
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
970
	} else
971
		return false;
972

    
973
	/* Add a new servers to our instance */
974
	foreach ($radiusservers as $radsrv)
975
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
976

    
977
	if (PEAR::isError($rauth->start())) {
978
		$retvalue['auth_val'] = 1;
979
		$retvalue['error'] = $rauth->getError();
980
		if ($debug)
981
			printf("Radius start: %s<br>\n", $retvalue['error']);
982
	}
983

    
984
	// XXX - billm - somewhere in here we need to handle securid challenge/response
985

    
986
	/* Send request */
987
	$result = $rauth->send();
988
	if (PEAR::isError($result)) {
989
		$retvalue['auth_val'] = 1;
990
		$retvalue['error'] = $result->getMessage();
991
		if ($debug)
992
			printf("Radius send failed: %s<br>\n", $retvalue['error']);
993
	} else if ($result === true) {
994
		$retvalue['auth_val'] = 2;
995
		if ($debug)
996
			printf(gettext("Radius Auth succeeded")."<br>\n");
997
		$ret = true;
998
	} else {
999
		$retvalue['auth_val'] = 3;
1000
		if ($debug)
1001
			printf(gettext("Radius Auth rejected")."<br>\n");
1002
	}
1003

    
1004
	// close OO RADIUS_AUTHENTICATION
1005
	$rauth->close();
1006

    
1007
	return $ret;
1008
}
1009

    
1010
function get_user_expiration_date($username) {
1011
	$user = getUserEntry($username);
1012
	if ($user['expires']) 
1013
		return $user['expires'];
1014
}
1015

    
1016
function is_account_expired($username) {
1017
	$expirydate = get_user_expiration_date($username);
1018
	if ($expirydate) {
1019
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1020
			return true;
1021
	}
1022

    
1023
	return false;
1024
}
1025

    
1026
function is_account_disabled($username) {
1027
	$user = getUserEntry($username);
1028
	if (isset($user['disabled']))
1029
		return true;
1030

    
1031
	return false;
1032
}
1033

    
1034
function auth_get_authserver($name) {
1035
        global $config;
1036

    
1037
        if (is_array($config['system']['authserver'])) {
1038
                foreach ($config['system']['authserver'] as $authcfg) {
1039
                        if ($authcfg['name'] == $name)
1040
                                return $authcfg;
1041
                }
1042
        }
1043
	if ($name == "Local Database")
1044
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1045
}
1046

    
1047
function auth_get_authserver_list() {
1048
        global $config;
1049

    
1050
	$list = array();
1051

    
1052
        if (is_array($config['system']['authserver'])) {
1053
                foreach ($config['system']['authserver'] as $authcfg) {
1054
			/* Add support for disabled entries? */
1055
			$list[$authcfg['name']] = $authcfg;
1056
                }
1057
        }
1058

    
1059
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1060
	return $list;
1061
}
1062

    
1063
function getUserGroups($username, $authcfg) {
1064
	global $config;
1065

    
1066
	$allowed_groups = array();
1067

    
1068
	switch($authcfg['type']) {
1069
        case 'ldap':
1070
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1071
		break;
1072
	case 'radius':
1073
		break;
1074
	default:
1075
		$user = getUserEntry($username);
1076
		$allowed_groups = @local_user_get_groups($user, true);
1077
		break;
1078
	}
1079

    
1080
	$member_groups = array();
1081
        if (is_array($config['system']['group'])) {
1082
                foreach ($config['system']['group'] as $group)
1083
                        if (in_array($group['name'], $allowed_groups))
1084
				$member_groups[] = $group['name'];
1085
	}
1086

    
1087
	return $member_groups;
1088
}
1089

    
1090
function authenticate_user($username, $password, $authcfg = NULL) {
1091

    
1092
	if (!$authcfg) {
1093
		return local_backed($username, $password);
1094
	}
1095

    
1096
	$authenticated = false;
1097
	switch($authcfg['type']) {
1098
        case 'ldap':
1099
                if (ldap_backed($username, $password, $authcfg))
1100
                        $authenticated = true;
1101
                break;
1102
        case 'radius':
1103
                if (radius_backed($username, $password, $authcfg))
1104
                        $authenticated = true;
1105
                break;
1106
        default:
1107
                /* lookup user object by name */
1108
                if (local_backed($username, $password))
1109
                        $authenticated = true;
1110
                break;
1111
        }
1112

    
1113
	return $authenticated;
1114
}
1115

    
1116
function session_auth() {
1117
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1118

    
1119
	session_start();
1120

    
1121
	/* Validate incoming login request */
1122
	if (isset($_POST['login'])) {
1123
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1124
		if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || 
1125
		    authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1126
			$_SESSION['Logged_In'] = "True";
1127
			$_SESSION['Username'] = $_POST['usernamefld'];
1128
			$_SESSION['last_access'] = time();
1129
			log_error("Successful login for user '{$_POST['usernamefld']}' from: {$_SERVER['REMOTE_ADDR']}");
1130
			$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1131
			if (isset($_POST['postafterlogin']))
1132
				return true;
1133
			else {
1134
				if (empty($page))
1135
					$page = "/";
1136
				header("Location: {$page}");
1137
			}
1138
			exit;
1139
		} else {
1140
			/* give the user an error message */
1141
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1142
			log_error("Login attempt with user: '{$_POST['usernamefld']}' from: '{$_SERVER['REMOTE_ADDR']}' failed.");
1143
			if(isAjax()) {
1144
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1145
				return;
1146
			}
1147
		}
1148
	}
1149

    
1150
	/* Show login page if they aren't logged in */
1151
	if (empty($_SESSION['Logged_In']))
1152
		return false;
1153

    
1154
	/* If session timeout isn't set, we don't mark sessions stale */
1155
	if (!isset($config['system']['webgui']['session_timeout'])) {
1156
		/* Default to 4 hour timeout if one is not set */
1157
		if ($_SESSION['last_access'] < (time() - 14400)) {
1158
			$_GET['logout'] = true;
1159
			$_SESSION['Logout'] = true;
1160
		} else
1161
			$_SESSION['last_access'] = time();	
1162
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1163
		/* only update if it wasn't ajax */
1164
		if (!isAjax())
1165
			$_SESSION['last_access'] = time();
1166
	} else {
1167
		/* Check for stale session */
1168
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1169
			$_GET['logout'] = true;
1170
			$_SESSION['Logout'] = true;
1171
		} else {
1172
			/* only update if it wasn't ajax */
1173
			if (!isAjax())
1174
				$_SESSION['last_access'] = time();
1175
		}
1176
	}
1177

    
1178
	/* user hit the logout button */
1179
	if (isset($_GET['logout'])) {
1180

    
1181
		if ($_SESSION['Logout'])
1182
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1183
		else
1184
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1185

    
1186
		/* wipe out $_SESSION */
1187
		$_SESSION = array();
1188

    
1189
		if (isset($_COOKIE[session_name()]))
1190
			setcookie(session_name(), '', time()-42000, '/');
1191

    
1192
		/* and destroy it */
1193
		session_destroy();
1194

    
1195
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1196
		$scriptElms = count($scriptName);
1197
		$scriptName = $scriptName[$scriptElms-1];
1198

    
1199
		if (isAjax())
1200
			return false;
1201

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

    
1205
		return false;
1206
	}
1207

    
1208
	/*
1209
	 * this is for debugging purpose if you do not want to use Ajax
1210
	 * to submit a HTML form. It basically diables the observation
1211
	 * of the submit event and hence does not trigger Ajax.
1212
	 */
1213
	if ($_GET['disable_ajax'])
1214
		$_SESSION['NO_AJAX'] = "True";
1215

    
1216
	/*
1217
	 * Same to re-enable Ajax.
1218
	 */
1219
	if ($_GET['enable_ajax'])
1220
		unset($_SESSION['NO_AJAX']);
1221

    
1222
	$HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
1223
	return true;
1224
}
1225

    
1226
?>
(4-4/51)