Project

General

Profile

Download (34.7 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(($http_host == "localhost" or $_SERVER['SERVER_ADDR'] == "localhost") or
64
	   ($http_host == "127.0.0.1" or $_SERVER['SERVER_ADDR'] == "127.0.0.1"))
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 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
	/* configure shell type */
289
	if (!(userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all"))) {
290
		if (!userHasPrivilege($user, "user-copy-files"))
291
			$user_shell = "/sbin/nologin";
292
		else
293
			$user_shell = "/usr/local/bin/scponly";
294
	} else {
295
		$user_shell = "/bin/tcsh";
296
	}
297

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

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

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

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

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

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

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

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

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

    
362
	/* delete from pw db */
363
	$cmd = "/usr/sbin/pw userdel {$user['name']}";
364

    
365
	if($debug)
366
		log_error("Running: {$cmd}");
367
	mwexec($cmd);
368

    
369
	/* Delete user from groups needs a call to write_config() */
370
	local_group_del_user($user);
371
}
372

    
373
function local_user_set_password(& $user, $password) {
374

    
375
	$user['password'] = crypt($password);
376
	$user['md5-hash'] = md5($password);
377

    
378
	// Converts ascii to unicode.
379
	$astr = (string) $password;
380
	$ustr = '';
381
	for ($i = 0; $i < strlen($astr); $i++) {
382
		$a = ord($astr{$i}) << 8;
383
		$ustr.= sprintf("%X", $a);
384
	}
385

    
386
	// Generate the NT-HASH from the unicode string
387
	$user['nt-hash'] = bin2hex(mhash(MHASH_MD4, $ustr));
388
}
389

    
390
function local_user_get_groups($user, $all = false) {
391
	global $debug, $config;
392

    
393
	$groups = array();
394
	if (!is_array($config['system']['group']))
395
		return $groups;
396

    
397
	foreach ($config['system']['group'] as $group)
398
		if ( $all || ( !$all && ($group['name'] != "all")))
399
			if (is_array($group['member']))
400
				if (in_array($user['uid'], $group['member']))
401
					$groups[] = $group['name'];
402

    
403
	sort($groups);
404

    
405
	return $groups;
406
	
407
}
408

    
409
function local_user_set_groups($user, $new_groups = NULL ) {
410
	global $debug, $config, $groupindex;
411

    
412
	if (!is_array($config['system']['group']))
413
		return;
414

    
415
	$cur_groups = local_user_get_groups($user);
416
	$mod_groups = array();
417

    
418
	if (!is_array($new_groups))
419
		$new_groups = array();
420

    
421
	if (!is_array($cur_groups))
422
		$cur_groups = array();
423

    
424
	/* determine which memberships to add */
425
	foreach ($new_groups as $groupname) {
426
		if (in_array($groupname,$cur_groups))
427
			continue;
428
		$group = & $config['system']['group'][$groupindex[$groupname]];
429
		$group['member'][] = $user['uid'];
430
		$mod_groups[] = $group;
431
	}
432

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

    
443
	/* sync all modified groups */
444
	foreach ($mod_groups as $group)
445
		local_group_set($group);
446
}
447

    
448
function local_group_del_user($user) {
449
	global $config;
450

    
451
	if (!is_array($config['system']['group']))
452
                return;
453

    
454
        foreach ($config['system']['group'] as $group) {
455
		if (is_array($group['member'])) {
456
			foreach ($group['member'] as $idx => $uid) {
457
				if ($user['uid'] == $uid)
458
					unset($config['system']['group']['member'][$idx]);
459
			}
460
		}
461
	}
462
}
463

    
464
function local_group_set($group, $reset = false) {
465
	global $debug;
466

    
467
	$group_name = $group['name'];
468
	$group_gid = $group['gid'];
469
	$group_members = "''";
470
	if (!$reset && count($group['member']))
471
		$group_members = implode(",",$group['member']);
472

    
473
	/* read from group db */
474
	$fd = popen("/usr/sbin/pw groupshow {$group_name} 2>&1", "r");
475
	$pwread = fgets($fd);
476
	pclose($fd);
477

    
478
	/* determine add or mod */
479
	if (!strncmp($pwread, "pw:", 3))
480
		$group_op = "groupadd";
481
	else
482
		$group_op = "groupmod";
483

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

    
487
	if($debug)
488
		log_error("Running: {$cmd}");
489
	mwexec($cmd);
490

    
491
}
492

    
493
function local_group_del($group) {
494
	global $debug;
495

    
496
	/* delete from group db */
497
	$cmd = "/usr/sbin/pw groupdel {$group['name']}";
498

    
499
	if($debug)
500
		log_error("Running: {$cmd}");
501
	mwexec($cmd);
502
}
503

    
504
function ldap_test_connection($authcfg) {
505
	global $debug, $config, $g;
506

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

    
520
        /* first check if there is even an LDAP server populated */
521
        if(!$ldapserver)
522
                return false;
523

    
524
        /* connect and see if server is up */
525
        putenv('LDAPTLS_REQCERT=never');
526
        $error = false;
527
        if (empty($ldapport)) {
528
                if (!($ldap = ldap_connect($ldapserver)))
529
                        $error = true;
530
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
531
                $error = true;
532

    
533
        if ($error == true) {
534
                log_error("ERROR!  Could not connect to server {$ldapname}.");
535
                return false;
536
        }
537

    
538
	return true;
539
}
540

    
541
function ldap_test_bind($authcfg) {
542
	global $debug, $config, $g;
543

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

    
562
	/* first check if there is even an LDAP server populated */
563
        if(!$ldapserver)
564
                return false;
565

    
566
        /* connect and see if server is up */
567
        putenv('LDAPTLS_REQCERT=never');
568
        $error = false;
569
        if (empty($ldapport)) {
570
                if (!($ldap = ldap_connect($ldapserver)))
571
                        $error = true;
572
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
573
                $error = true;
574

    
575
        if ($error == true) {
576
                log_error("ERROR!  Could not connect to server {$ldapname}.");
577
                return false;
578
        }
579

    
580
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
581
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
582
 
583
	if ($ldapanon == true) {
584
		if (!($res = @ldap_bind($ldap))) {
585
			@ldap_close($ldap);
586
			return false;
587
		}
588
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
589
		@ldap_close($ldap);
590
		return false;
591
	}
592

    
593
	@ldap_unbind($ldap);
594

    
595
	return true;
596
}
597

    
598
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
599
	global $debug, $config, $g;
600

    
601
	if(!function_exists("ldap_connect"))
602
		return;
603

    
604
	$ous = array();
605

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

    
627
        /* first check if there is even an LDAP server populated */
628
        if(!$ldapserver) {
629
                log_error("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined.");
630
                return $ous;
631
        }
632

    
633
	/* connect and see if server is up */
634
        putenv('LDAPTLS_REQCERT=never');
635
        $error = false;
636
        if (empty($ldapport)) {
637
                if (!($ldap = ldap_connect($ldapserver)))
638
                        $error = true;
639
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
640
                $error = true;
641

    
642
        if ($error == true) {
643
		log_error("ERROR!  Could not connect to server {$ldapname}.");
644
                return $ous;
645
        }
646

    
647
	$ldapfilter = "(|(ou=*)(cn=Users))";
648

    
649
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
650
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
651

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

    
664
	if ($ldapscope == "one")
665
		$ldapfunc = "ldap_list";
666
	else
667
		$ldapfunc = "ldap_search";
668

    
669
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
670
	$info = @ldap_get_entries($ldap, $search);
671

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

    
687
	@ldap_unbind($ldap);
688

    
689
	return $ous;
690
}
691

    
692
function ldap_get_groups($username, $authcfg) {
693
	global $debug, $config;
694
	
695
	if(!function_exists("ldap_connect"))
696
		return;
697
	
698
	if(!$username) 
699
		return false;
700

    
701
	if(stristr($username, "@")) {
702
		$username_split=split("\@", $username);
703
		$username = $username_split[0];		
704
	}
705

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

    
738
	$ldapdn             = $_SESSION['ldapdn'];
739

    
740
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
741
	$ldapgroupattribute = strtolower($ldapgroupattribute);
742
	$memberof = array();
743

    
744
	/* connect and see if server is up */
745
	putenv('LDAPTLS_REQCERT=never');
746
	$error = false;
747
        if (empty($ldapport)) {
748
                if (!($ldap = ldap_connect($ldapserver)))
749
                        $error = true;
750
        } else if (!($ldap = ldap_connect($ldapserver, $ldapport)))
751
                $error = true;
752

    
753
	if ($error == true) {
754
		log_error("ERROR! ldap_get_groups() Could not connect to server {$ldapname}.");
755
                return memberof;
756
        }
757
    
758
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
759
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
760

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

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

    
783
	$search    = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
784
	$info      = @ldap_get_entries($ldap, $search);
785

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

    
808
function ldap_backed($username, $passwd, $authcfg) {
809
	global $debug, $config;
810
	
811
	if(!$username) 
812
		return;
813

    
814
	if(!function_exists("ldap_connect"))
815
		return;
816

    
817
	if(stristr($username, "@")) {
818
		$username_split=split("\@", $username);
819
		$username = $username_split[0];        
820
	}
821
	if(stristr($username, "\\")) {
822
		$username_split=split("\\", $username);
823
		$username = $username_split[0];        
824
	}
825

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

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

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

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

    
873
	if ($error == true) {
874
		log_error("ERROR!  Could not connect to server {$ldapname}.");
875
		return false;
876
	}
877

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

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

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

    
934
	if ($usercount != 1){
935
		@ldap_unbind($ldap);
936
		log_error("ERROR! Either LDAP search failed, or multiple users were found.");
937
		return false;                         
938
	}
939

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

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

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

    
952
	return true;
953
}
954

    
955
function radius_backed($username, $passwd, $authcfg){
956
	global $debug, $config;
957
	$ret = false;
958

    
959
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
960
	if ($authcfg) {
961
		$radiusservers = array();
962
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
963
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
964
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
965
	} else
966
		return false;
967

    
968
	/* Add a new servers to our instance */
969
	foreach ($radiusservers as $radsrv)
970
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
971

    
972
	if (PEAR::isError($rauth->start())) {
973
		$retvalue['auth_val'] = 1;
974
		$retvalue['error'] = $rauth->getError();
975
		if ($debug)
976
			printf("Radius start: %s<br>\n", $retvalue['error']);
977
	}
978

    
979
	// XXX - billm - somewhere in here we need to handle securid challenge/response
980

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

    
999
	// close OO RADIUS_AUTHENTICATION
1000
	$rauth->close();
1001

    
1002
	return $ret;
1003
}
1004

    
1005
function get_user_expiration_date($username) {
1006
	$user = getUserEntry($username);
1007
	if ($user['expires']) 
1008
		return $user['expires'];
1009
}
1010

    
1011
function is_account_expired($username) {
1012
	$expirydate = get_user_expiration_date($username);
1013
	if ($expirydate) {
1014
		if (strtotime("-1 day") > strtotime(date("m/d/Y",strtotime($expirydate))))
1015
			return true;
1016
	}
1017

    
1018
	return false;
1019
}
1020

    
1021
function is_account_disabled($username) {
1022
	$user = getUserEntry($username);
1023
	if (isset($user['disabled']))
1024
		return true;
1025

    
1026
	return false;
1027
}
1028

    
1029
function auth_get_authserver($name) {
1030
        global $config;
1031

    
1032
        if (is_array($config['system']['authserver'])) {
1033
                foreach ($config['system']['authserver'] as $authcfg) {
1034
                        if ($authcfg['name'] == $name)
1035
                                return $authcfg;
1036
                }
1037
        }
1038
	if ($name == "Local Database")
1039
		return array("name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1040
}
1041

    
1042
function auth_get_authserver_list() {
1043
        global $config;
1044

    
1045
	$list = array();
1046

    
1047
        if (is_array($config['system']['authserver'])) {
1048
                foreach ($config['system']['authserver'] as $authcfg) {
1049
			/* Add support for disabled entries? */
1050
			$list[$authcfg['name']] = $authcfg;
1051
                }
1052
        }
1053

    
1054
	$list["Local Database"] = array( "name" => "Local Database", "type" => "Local Auth", "host" => $config['system']['hostname']);
1055
	return $list;
1056
}
1057

    
1058
function getUserGroups($username, $authcfg) {
1059
	global $config;
1060

    
1061
	$allowed_groups = array();
1062

    
1063
	switch($authcfg['type']) {
1064
        case 'ldap':
1065
		$allowed_groups = @ldap_get_groups($username, $authcfg);
1066
		break;
1067
	case 'radius':
1068
		break;
1069
	default:
1070
		$user = getUserEntry($username);
1071
		$allowed_groups = @local_user_get_groups($user, true);
1072
		break;
1073
	}
1074

    
1075
	$member_groups = array();
1076
        if (is_array($config['system']['group'])) {
1077
                foreach ($config['system']['group'] as $group)
1078
                        if (in_array($group['name'], $allowed_groups))
1079
				$member_groups[] = $group['name'];
1080
	}
1081

    
1082
	return $member_groups;
1083
}
1084

    
1085
function authenticate_user($username, $password, $authcfg = NULL) {
1086

    
1087
	if (!$authcfg) {
1088
		return local_backed($username, $password);
1089
	}
1090

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

    
1108
	return $authenticated;
1109
}
1110

    
1111
function session_auth() {
1112
	global $HTTP_SERVER_VARS, $config, $_SESSION, $page;
1113

    
1114
	session_start();
1115

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

    
1145
	/* Show login page if they aren't logged in */
1146
	if (empty($_SESSION['Logged_In']))
1147
		return false;
1148

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

    
1173
	/* user hit the logout button */
1174
	if (isset($_GET['logout'])) {
1175

    
1176
		if ($_SESSION['Logout'])
1177
			log_error("Session timed out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1178
		else
1179
			log_error("User logged out for user '{$_SESSION['Username']}' from: {$_SERVER['REMOTE_ADDR']}");
1180

    
1181
		/* wipe out $_SESSION */
1182
		$_SESSION = array();
1183

    
1184
		if (isset($_COOKIE[session_name()]))
1185
			setcookie(session_name(), '', time()-42000, '/');
1186

    
1187
		/* and destroy it */
1188
		session_destroy();
1189

    
1190
		$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
1191
		$scriptElms = count($scriptName);
1192
		$scriptName = $scriptName[$scriptElms-1];
1193

    
1194
		if (isAjax())
1195
			return false;
1196

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

    
1200
		return false;
1201
	}
1202

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

    
1211
	/*
1212
	 * Same to re-enable Ajax.
1213
	 */
1214
	if ($_GET['enable_ajax'])
1215
		unset($_SESSION['NO_AJAX']);
1216

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

    
1221
?>
(4-4/50)