Project

General

Profile

Download (52 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * auth.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2003-2006 Manuel Kasper <mk@neon1.net>
7
 * Copyright (c) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
8
 * Copyright (c) 2006 Paul Taylor <paultaylor@winn-dixie.com>
9
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions are met:
14
 *
15
 * 1. Redistributions of source code must retain the above copyright notice,
16
 *    this list of conditions and the following disclaimer.
17
 *
18
 * 2. Redistributions in binary form must reproduce the above copyright
19
 *    notice, this list of conditions and the following disclaimer in
20
 *    the documentation and/or other materials provided with the
21
 *    distribution.
22
 *
23
 * 3. All advertising materials mentioning features or use of this software
24
 *    must display the following acknowledgment:
25
 *    "This product includes software developed by the pfSense Project
26
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
27
 *
28
 * 4. The names "pfSense" and "pfSense Project" must not be used to
29
 *    endorse or promote products derived from this software without
30
 *    prior written permission. For written permission, please contact
31
 *    coreteam@pfsense.org.
32
 *
33
 * 5. Products derived from this software may not be called "pfSense"
34
 *    nor may "pfSense" appear in their names without prior written
35
 *    permission of the Electric Sheep Fencing, LLC.
36
 *
37
 * 6. Redistributions of any form whatsoever must retain the following
38
 *    acknowledgment:
39
 *
40
 * "This product includes software developed by the pfSense Project
41
 * for use in the pfSense software distribution (http://www.pfsense.org/).
42
 *
43
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
44
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
47
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
50
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
55
 */
56

    
57
/*
58
 * NOTE : Portions of the mschapv2 support was based on the BSD licensed CHAP.php
59
 * file courtesy of Michael Retterklieber.
60
 */
61
if (!$do_not_include_config_gui_inc) {
62
	require_once("config.gui.inc");
63
}
64

    
65
// Will be changed to false if security checks fail
66
$security_passed = true;
67

    
68
/* If this function doesn't exist, we're being called from Captive Portal or
69
   another internal subsystem which does not include authgui.inc */
70
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
71
	/* DNS ReBinding attack prevention.  https://redmine.pfsense.org/issues/708 */
72
	$found_host = false;
73

    
74
	/* Either a IPv6 address with or without a alternate port */
75
	if (strstr($_SERVER['HTTP_HOST'], "]")) {
76
		$http_host_port = explode("]", $_SERVER['HTTP_HOST']);
77
		/* v6 address has more parts, drop the last part */
78
		if (count($http_host_port) > 1) {
79
			array_pop($http_host_port);
80
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
81
		} else {
82
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
83
		}
84
	} else {
85
		$http_host = explode(":", $_SERVER['HTTP_HOST']);
86
		$http_host = $http_host[0];
87
	}
88
	if (is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
89
		strcasecmp($http_host, "localhost") == 0 or $_SERVER['SERVER_ADDR'] == "::1") {
90
		$found_host = true;
91
	}
92
	if (strcasecmp($http_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 or
93
		strcasecmp($http_host, $config['system']['hostname']) == 0) {
94
		$found_host = true;
95
	}
96

    
97
	if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
98
		foreach ($config['dyndnses']['dyndns'] as $dyndns) {
99
			if (strcasecmp($dyndns['host'], $http_host) == 0) {
100
				$found_host = true;
101
				break;
102
			}
103
		}
104
	}
105

    
106
	if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
107
		foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
108
			if (strcasecmp($rfc2136['host'], $http_host) == 0) {
109
				$found_host = true;
110
				break;
111
			}
112
		}
113
	}
114

    
115
	if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
116
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
117
		foreach ($althosts as $ah) {
118
			if (strcasecmp($ah, $http_host) == 0 or strcasecmp($ah, $_SERVER['SERVER_ADDR']) == 0) {
119
				$found_host = true;
120
				break;
121
			}
122
		}
123
	}
124

    
125
	if ($found_host == false) {
126
		if (!security_checks_disabled()) {
127
			display_error_form("501", gettext("Potential DNS Rebind attack detected, see http://en.wikipedia.org/wiki/DNS_rebinding<br />Try accessing the router by IP address instead of by hostname."));
128
			exit;
129
		}
130
		$security_passed = false;
131
	}
132
}
133

    
134
// If the HTTP_REFERER is something other than ourselves then disallow.
135
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nohttpreferercheck'])) {
136
	if ($_SERVER['HTTP_REFERER']) {
137
		if (file_exists("{$g['tmp_path']}/setupwizard_lastreferrer")) {
138
			if ($_SERVER['HTTP_REFERER'] == file_get_contents("{$g['tmp_path']}/setupwizard_lastreferrer")) {
139
				unlink("{$g['tmp_path']}/setupwizard_lastreferrer");
140
				header("Refresh: 1; url=index.php");
141
?>
142
<!DOCTYPE html>
143
<html lang="en">
144
<head>
145
	<link rel="stylesheet" href="/css/pfSense.css" />
146
	<title><?=gettext("Redirecting..."); ?></title>
147
</head>
148
<body id="error" class="no-menu">
149
	<div id="jumbotron">
150
		<div class="container">
151
			<div class="col-sm-offset-3 col-sm-6 col-xs-12">
152
				<p><?=gettext("Redirecting to the dashboard...")?></p>
153
			</div>
154
		</div>
155
	</div>
156
</body>
157
</html>
158
<?php
159
				exit;
160
			}
161
		}
162
		$found_host = false;
163
		$referrer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
164
		$referrer_host = str_replace(array("[", "]"), "", $referrer_host);
165
		if ($referrer_host) {
166
			if (strcasecmp($referrer_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 ||
167
			    strcasecmp($referrer_host, $config['system']['hostname']) == 0) {
168
				$found_host = true;
169
			}
170

    
171
			if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
172
				$althosts = explode(" ", $config['system']['webgui']['althostnames']);
173
				foreach ($althosts as $ah) {
174
					if (strcasecmp($referrer_host, $ah) == 0) {
175
						$found_host = true;
176
						break;
177
					}
178
				}
179
			}
180

    
181
			if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
182
				foreach ($config['dyndnses']['dyndns'] as $dyndns) {
183
					if (strcasecmp($dyndns['host'], $referrer_host) == 0) {
184
						$found_host = true;
185
						break;
186
					}
187
				}
188
			}
189

    
190
			if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
191
				foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
192
					if (strcasecmp($rfc2136['host'], $referrer_host) == 0) {
193
						$found_host = true;
194
						break;
195
					}
196
				}
197
			}
198

    
199
			if (!$found_host) {
200
				$interface_list_ips = get_configured_ip_addresses();
201
				foreach ($interface_list_ips as $ilips) {
202
					if (strcasecmp($referrer_host, $ilips) == 0) {
203
						$found_host = true;
204
						break;
205
					}
206
				}
207
				$interface_list_ipv6s = get_configured_ipv6_addresses(true);
208
				foreach ($interface_list_ipv6s as $ilipv6s) {
209
					$ilipv6s = explode('%', $ilipv6s)[0];
210
					if (strcasecmp($referrer_host, $ilipv6s) == 0) {
211
						$found_host = true;
212
						break;
213
					}
214
				}
215
				if ($referrer_host == "127.0.0.1" || $referrer_host == "localhost") {
216
					// allow SSH port forwarded connections and links from localhost
217
					$found_host = true;
218
				}
219
			}
220
		}
221
		if ($found_host == false) {
222
			if (!security_checks_disabled()) {
223
				display_error_form("501", "An HTTP_REFERER was detected other than what is defined in System -> Advanced (" . htmlspecialchars($_SERVER['HTTP_REFERER']) . ").  If not needed, this check can be disabled in System -> Advanced -> Admin.");
224
				exit;
225
			}
226
			$security_passed = false;
227
		}
228
	} else {
229
		$security_passed = false;
230
	}
231
}
232

    
233
if (function_exists("display_error_form") && $security_passed) {
234
	/* Security checks passed, so it should be OK to turn them back on */
235
	restore_security_checks();
236
}
237
unset($security_passed);
238

    
239
$groupindex = index_groups();
240
$userindex = index_users();
241

    
242
function index_groups() {
243
	global $g, $debug, $config, $groupindex;
244

    
245
	$groupindex = array();
246

    
247
	if (is_array($config['system']['group'])) {
248
		$i = 0;
249
		foreach ($config['system']['group'] as $groupent) {
250
			$groupindex[$groupent['name']] = $i;
251
			$i++;
252
		}
253
	}
254

    
255
	return ($groupindex);
256
}
257

    
258
function index_users() {
259
	global $g, $debug, $config;
260

    
261
	if (is_array($config['system']['user'])) {
262
		$i = 0;
263
		foreach ($config['system']['user'] as $userent) {
264
			$userindex[$userent['name']] = $i;
265
			$i++;
266
		}
267
	}
268

    
269
	return ($userindex);
270
}
271

    
272
function & getUserEntry($name) {
273
	global $debug, $config, $userindex;
274
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
275

    
276
	if (isset($userindex[$name])) {
277
		return $config['system']['user'][$userindex[$name]];
278
	} elseif ($authcfg['type'] != "Local Database") {
279
		$user = array();
280
		$user['name'] = $name;
281
		return $user;
282
	}
283
}
284

    
285
function & getUserEntryByUID($uid) {
286
	global $debug, $config;
287

    
288
	if (is_array($config['system']['user'])) {
289
		foreach ($config['system']['user'] as & $user) {
290
			if ($user['uid'] == $uid) {
291
				return $user;
292
			}
293
		}
294
	}
295

    
296
	return false;
297
}
298

    
299
function & getGroupEntry($name) {
300
	global $debug, $config, $groupindex;
301
	if (isset($groupindex[$name])) {
302
		return $config['system']['group'][$groupindex[$name]];
303
	}
304
}
305

    
306
function & getGroupEntryByGID($gid) {
307
	global $debug, $config;
308

    
309
	if (is_array($config['system']['group'])) {
310
		foreach ($config['system']['group'] as & $group) {
311
			if ($group['gid'] == $gid) {
312
				return $group;
313
			}
314
		}
315
	}
316

    
317
	return false;
318
}
319

    
320
function get_user_privileges(& $user) {
321
	global $config;
322

    
323
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
324
	$names = array();
325

    
326
	$privs = $user['priv'];
327
	if (!is_array($privs)) {
328
		$privs = array();
329
	}
330

    
331
	if ($authcfg['type'] == "ldap") {
332
		$names = @ldap_get_groups($user['name'], $authcfg);
333
	} elseif ($authcfg['type'] == "radius") {
334
		$names = @radius_get_groups($_SESSION['user_radius_attributes']);
335
	}
336

    
337
	if (empty($names)) {
338
		$names = local_user_get_groups($user, true);
339
	}
340

    
341
	foreach ($names as $name) {
342
		$group = getGroupEntry($name);
343
		if (is_array($group['priv'])) {
344
			$privs = array_merge($privs, $group['priv']);
345
		}
346
	}
347

    
348
	return $privs;
349
}
350

    
351
function userHasPrivilege($userent, $privid = false) {
352

    
353
	if (!$privid || !is_array($userent)) {
354
		return false;
355
	}
356

    
357
	$privs = get_user_privileges($userent);
358

    
359
	if (!is_array($privs)) {
360
		return false;
361
	}
362

    
363
	if (!in_array($privid, $privs)) {
364
		return false;
365
	}
366

    
367
	return true;
368
}
369

    
370
function local_backed($username, $passwd) {
371

    
372
	$user = getUserEntry($username);
373
	if (!$user) {
374
		return false;
375
	}
376

    
377
	if (is_account_disabled($username) || is_account_expired($username)) {
378
		return false;
379
	}
380

    
381
	if ($user['bcrypt-hash']) {
382
		if (password_verify($passwd, $user['bcrypt-hash'])) {
383
			return true;
384
		}
385
	}
386

    
387
	//for backwards compatibility
388
	if ($user['password']) {
389
		if (crypt($passwd, $user['password']) == $user['password']) {
390
			return true;
391
		}
392
	}
393

    
394
	if ($user['md5-hash']) {
395
		if (md5($passwd) == $user['md5-hash']) {
396
			return true;
397
		}
398
	}
399

    
400
	return false;
401
}
402

    
403
function local_sync_accounts() {
404
	global $debug, $config;
405
	conf_mount_rw();
406

    
407
	/* remove local users to avoid uid conflicts */
408
	$fd = popen("/usr/sbin/pw usershow -a", "r");
409
	if ($fd) {
410
		while (!feof($fd)) {
411
			$line = explode(":", fgets($fd));
412
			if ($line[0] != "admin") {
413
				if (!strncmp($line[0], "_", 1)) {
414
					continue;
415
				}
416
				if ($line[2] < 2000) {
417
					continue;
418
				}
419
				if ($line[2] > 65000) {
420
					continue;
421
				}
422
			}
423
			/*
424
			 * If a crontab was created to user, pw userdel will be interactive and
425
			 * can cause issues. Just remove crontab before run it when necessary
426
			 */
427
			unlink_if_exists("/var/cron/tabs/{$line[0]}");
428
			$cmd = "/usr/sbin/pw userdel -n " . escapeshellarg($line[0]);
429
			if ($debug) {
430
				log_error(sprintf(gettext("Running: %s"), $cmd));
431
			}
432
			mwexec($cmd);
433
		}
434
		pclose($fd);
435
	}
436

    
437
	/* remove local groups to avoid gid conflicts */
438
	$gids = array();
439
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
440
	if ($fd) {
441
		while (!feof($fd)) {
442
			$line = explode(":", fgets($fd));
443
			if (!strncmp($line[0], "_", 1)) {
444
				continue;
445
			}
446
			if ($line[2] < 2000) {
447
				continue;
448
			}
449
			if ($line[2] > 65000) {
450
				continue;
451
			}
452
			$cmd = "/usr/sbin/pw groupdel -g " . escapeshellarg($line[2]);
453
			if ($debug) {
454
				log_error(sprintf(gettext("Running: %s"), $cmd));
455
			}
456
			mwexec($cmd);
457
		}
458
		pclose($fd);
459
	}
460

    
461
	/* make sure the all group exists */
462
	$allgrp = getGroupEntryByGID(1998);
463
	local_group_set($allgrp, true);
464

    
465
	/* sync all local users */
466
	if (is_array($config['system']['user'])) {
467
		foreach ($config['system']['user'] as $user) {
468
			local_user_set($user);
469
		}
470
	}
471

    
472
	/* sync all local groups */
473
	if (is_array($config['system']['group'])) {
474
		foreach ($config['system']['group'] as $group) {
475
			local_group_set($group);
476
		}
477
	}
478

    
479
	conf_mount_ro();
480

    
481
}
482

    
483
function local_user_set(& $user) {
484
	global $g, $debug;
485

    
486
	if (empty($user['password']) && empty($user['bcrypt-hash'])) {
487
		log_error("There is something wrong in the config because user {$user['name']} password is missing!");
488
		return;
489
	}
490

    
491
	conf_mount_rw();
492

    
493
	$home_base = "/home/";
494
	$user_uid = $user['uid'];
495
	$user_name = $user['name'];
496
	$user_home = "{$home_base}{$user_name}";
497
	$user_shell = "/etc/rc.initial";
498
	$user_group = "nobody";
499

    
500
	// Ensure $home_base exists and is writable
501
	if (!is_dir($home_base)) {
502
		mkdir($home_base, 0755);
503
	}
504

    
505
	$lock_account = false;
506
	/* configure shell type */
507
	/* Cases here should be ordered by most privileged to least privileged. */
508
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
509
		$user_shell = "/bin/tcsh";
510
	} elseif (userHasPrivilege($user, "user-copy-files")) {
511
		$user_shell = "/usr/local/bin/scponly";
512
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
513
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
514
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
515
		$user_shell = "/sbin/nologin";
516
	} else {
517
		$user_shell = "/sbin/nologin";
518
		$lock_account = true;
519
	}
520

    
521
	/* Lock out disabled or expired users, unless it's root/admin. */
522
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
523
		$user_shell = "/sbin/nologin";
524
		$lock_account = true;
525
	}
526

    
527
	/* root user special handling */
528
	if ($user_uid == 0) {
529
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
530
		if ($debug) {
531
			log_error(sprintf(gettext("Running: %s"), $cmd));
532
		}
533
		$fd = popen($cmd, "w");
534
		if (empty($user['bcrypt-hash'])) {
535
			fwrite($fd, $user['password']);
536
		} else {
537
			fwrite($fd, $user['bcrypt-hash']);
538
		}
539
		pclose($fd);
540
		$user_group = "wheel";
541
		$user_home = "/root";
542
		$user_shell = "/etc/rc.initial";
543
	}
544

    
545
	/* read from pw db */
546
	$fd = popen("/usr/sbin/pw usershow -n {$user_name} 2>&1", "r");
547
	$pwread = fgets($fd);
548
	pclose($fd);
549
	$userattrs = explode(":", trim($pwread));
550

    
551
	/* determine add or mod */
552
	if (($userattrs[0] != $user['name']) || (!strncmp($pwread, "pw:", 3))) {
553
		$user_op = "useradd -m -k /etc/skel -o";
554
	} else {
555
		$user_op = "usermod";
556
	}
557

    
558
	$comment = str_replace(array(":", "!", "@"), " ", $user['descr']);
559
	/* add or mod pw db */
560
	$cmd = "/usr/sbin/pw {$user_op} -q " .
561
			" -u " . escapeshellarg($user_uid) .
562
			" -n " . escapeshellarg($user_name) .
563
			" -g " . escapeshellarg($user_group) .
564
			" -s " . escapeshellarg($user_shell) .
565
			" -d " . escapeshellarg($user_home) .
566
			" -c " . escapeshellarg($comment) .
567
			" -H 0 2>&1";
568

    
569
	if ($debug) {
570
		log_error(sprintf(gettext("Running: %s"), $cmd));
571
	}
572
	$fd = popen($cmd, "w");
573
	if (empty($user['bcrypt-hash'])) {
574
		fwrite($fd, $user['password']);
575
	} else {
576
		fwrite($fd, $user['bcrypt-hash']);
577
	}
578
	pclose($fd);
579

    
580
	/* create user directory if required */
581
	if (!is_dir($user_home)) {
582
		mkdir($user_home, 0700);
583
	}
584
	@chown($user_home, $user_name);
585
	@chgrp($user_home, $user_group);
586

    
587
	/* write out ssh authorized key file */
588
	if ($user['authorizedkeys']) {
589
		if (!is_dir("{$user_home}/.ssh")) {
590
			@mkdir("{$user_home}/.ssh", 0700);
591
			@chown("{$user_home}/.ssh", $user_name);
592
		}
593
		$keys = base64_decode($user['authorizedkeys']);
594
		@file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
595
		@chown("{$user_home}/.ssh/authorized_keys", $user_name);
596
	} else {
597
		unlink_if_exists("{$user_home}/.ssh/authorized_keys");
598
	}
599

    
600
	$un = $lock_account ? "" : "un";
601
	exec("/usr/sbin/pw {$un}lock " . escapeshellarg($user_name) . " -q 2>/dev/null");
602

    
603
	conf_mount_ro();
604
}
605

    
606
function local_user_del($user) {
607
	global $debug;
608

    
609
	/* remove all memberships */
610
	local_user_set_groups($user);
611

    
612
	/* Don't remove /root */
613
	if ($user['uid'] != 0) {
614
		$rmhome = "-r";
615
	}
616

    
617
	/* read from pw db */
618
	$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
619
	$pwread = fgets($fd);
620
	pclose($fd);
621
	$userattrs = explode(":", trim($pwread));
622

    
623
	if ($userattrs[0] != $user['name']) {
624
		log_error("Tried to remove user {$user['name']} but got user {$userattrs[0]} instead. Bailing.");
625
		return;
626
	}
627

    
628
	/* delete from pw db */
629
	$cmd = "/usr/sbin/pw userdel -n " . escapeshellarg($user['name']) . " " . escapeshellarg($rmhome);
630

    
631
	if ($debug) {
632
		log_error(sprintf(gettext("Running: %s"), $cmd));
633
	}
634
	mwexec($cmd);
635

    
636
	/* Delete user from groups needs a call to write_config() */
637
	local_group_del_user($user);
638
}
639

    
640
function local_user_set_password(&$user, $password) {
641

    
642
	unset($user['password']);
643
	unset($user['md5-hash']);
644
	$user['bcrypt-hash'] = password_hash($password, PASSWORD_BCRYPT);
645

    
646
	/* Maintain compatibility with FreeBSD - change $2y$ prefix to $2b$
647
	 * https://reviews.freebsd.org/D2742
648
	 * XXX: Can be removed as soon as r284483 is MFC'd.
649
	 */
650
	if ($user['bcrypt-hash'][2] == "y") {
651
		$user['bcrypt-hash'][2] = "b";
652
	}
653

    
654
	// Converts ascii to unicode.
655
	$astr = (string) $password;
656
	$ustr = '';
657
	for ($i = 0; $i < strlen($astr); $i++) {
658
		$a = ord($astr{$i}) << 8;
659
		$ustr .= sprintf("%X", $a);
660
	}
661

    
662
}
663

    
664
function local_user_get_groups($user, $all = false) {
665
	global $debug, $config;
666

    
667
	$groups = array();
668
	if (!is_array($config['system']['group'])) {
669
		return $groups;
670
	}
671

    
672
	foreach ($config['system']['group'] as $group) {
673
		if ($all || (!$all && ($group['name'] != "all"))) {
674
			if (is_array($group['member'])) {
675
				if (in_array($user['uid'], $group['member'])) {
676
					$groups[] = $group['name'];
677
				}
678
			}
679
		}
680
	}
681

    
682
	if ($all) {
683
		$groups[] = "all";
684
	}
685

    
686
	sort($groups);
687

    
688
	return $groups;
689

    
690
}
691

    
692
function local_user_set_groups($user, $new_groups = NULL) {
693
	global $debug, $config, $groupindex;
694

    
695
	if (!is_array($config['system']['group'])) {
696
		return;
697
	}
698

    
699
	$cur_groups = local_user_get_groups($user, true);
700
	$mod_groups = array();
701

    
702
	if (!is_array($new_groups)) {
703
		$new_groups = array();
704
	}
705

    
706
	if (!is_array($cur_groups)) {
707
		$cur_groups = array();
708
	}
709

    
710
	/* determine which memberships to add */
711
	foreach ($new_groups as $groupname) {
712
		if ($groupname == '' || in_array($groupname, $cur_groups)) {
713
			continue;
714
		}
715
		$group = & $config['system']['group'][$groupindex[$groupname]];
716
		$group['member'][] = $user['uid'];
717
		$mod_groups[] = $group;
718
	}
719
	unset($group);
720

    
721
	/* determine which memberships to remove */
722
	foreach ($cur_groups as $groupname) {
723
		if (in_array($groupname, $new_groups)) {
724
			continue;
725
		}
726
		if (!isset($config['system']['group'][$groupindex[$groupname]])) {
727
			continue;
728
		}
729
		$group = & $config['system']['group'][$groupindex[$groupname]];
730
		if (is_array($group['member'])) {
731
			$index = array_search($user['uid'], $group['member']);
732
			array_splice($group['member'], $index, 1);
733
			$mod_groups[] = $group;
734
		}
735
	}
736
	unset($group);
737

    
738
	/* sync all modified groups */
739
	foreach ($mod_groups as $group) {
740
		local_group_set($group);
741
	}
742
}
743

    
744
function local_group_del_user($user) {
745
	global $config;
746

    
747
	if (!is_array($config['system']['group'])) {
748
		return;
749
	}
750

    
751
	foreach ($config['system']['group'] as $group) {
752
		if (is_array($group['member'])) {
753
			foreach ($group['member'] as $idx => $uid) {
754
				if ($user['uid'] == $uid) {
755
					unset($config['system']['group']['member'][$idx]);
756
				}
757
			}
758
		}
759
	}
760
}
761

    
762
function local_group_set($group, $reset = false) {
763
	global $debug;
764

    
765
	$group_name = $group['name'];
766
	$group_gid = $group['gid'];
767
	$group_members = '';
768
	if (!$reset && !empty($group['member']) && count($group['member']) > 0) {
769
		$group_members = implode(",", $group['member']);
770
	}
771

    
772
	if (empty($group_name) || $group['scope'] == "remote") {
773
		return;
774
	}
775

    
776
	/* determine add or mod */
777
	if (mwexec("/usr/sbin/pw groupshow -g " . escapeshellarg($group_gid) . " 2>&1", true) == 0) {
778
		$group_op = "groupmod -l";
779
	} else {
780
		$group_op = "groupadd -n";
781
	}
782

    
783
	/* add or mod group db */
784
	$cmd = "/usr/sbin/pw {$group_op} " .
785
		escapeshellarg($group_name) .
786
		" -g " . escapeshellarg($group_gid) .
787
		" -M " . escapeshellarg($group_members) . " 2>&1";
788

    
789
	if ($debug) {
790
		log_error(sprintf(gettext("Running: %s"), $cmd));
791
	}
792
	mwexec($cmd);
793

    
794
}
795

    
796
function local_group_del($group) {
797
	global $debug;
798

    
799
	/* delete from group db */
800
	$cmd = "/usr/sbin/pw groupdel " . escapeshellarg($group['name']);
801

    
802
	if ($debug) {
803
		log_error(sprintf(gettext("Running: %s"), $cmd));
804
	}
805
	mwexec($cmd);
806
}
807

    
808
function ldap_test_connection($authcfg) {
809
	global $debug, $config, $g;
810

    
811
	if ($authcfg) {
812
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
813
			$ldapproto = "ldaps";
814
		} else {
815
			$ldapproto = "ldap";
816
		}
817
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
818
		$ldapport = $authcfg['ldap_port'];
819
		if (!empty($ldapport)) {
820
			$ldapserver .= ":{$ldapport}";
821
		}
822
		$ldapbasedn = $authcfg['ldap_basedn'];
823
		$ldapbindun = $authcfg['ldap_binddn'];
824
		$ldapbindpw = $authcfg['ldap_bindpw'];
825
	} else {
826
		return false;
827
	}
828

    
829
	/* first check if there is even an LDAP server populated */
830
	if (!$ldapserver) {
831
		return false;
832
	}
833

    
834
	/* Setup CA environment if needed. */
835
	ldap_setup_caenv($authcfg);
836

    
837
	/* connect and see if server is up */
838
	$error = false;
839
	if (!($ldap = ldap_connect($ldapserver))) {
840
		$error = true;
841
	}
842

    
843
	if ($error == true) {
844
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
845
		return false;
846
	}
847

    
848
	return true;
849
}
850

    
851
function ldap_setup_caenv($authcfg) {
852
	global $g;
853
	require_once("certs.inc");
854

    
855
	unset($caref);
856
	if (empty($authcfg['ldap_caref']) || strstr($authcfg['ldap_urltype'], "Standard")) {
857
		putenv('LDAPTLS_REQCERT=never');
858
		return;
859
	} else {
860
		$caref = lookup_ca($authcfg['ldap_caref']);
861
		if (!$caref) {
862
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
863
			/* XXX: Prevent for credential leaking since we cannot setup the CA env. Better way? */
864
			putenv('LDAPTLS_REQCERT=hard');
865
			return;
866
		}
867
		if (!is_dir("{$g['varrun_path']}/certs")) {
868
			@mkdir("{$g['varrun_path']}/certs");
869
		}
870
		if (file_exists("{$g['varrun_path']}/certs/{$caref['refid']}.ca")) {
871
			@unlink("{$g['varrun_path']}/certs/{$caref['refid']}.ca");
872
		}
873
		file_put_contents("{$g['varrun_path']}/certs/{$caref['refid']}.ca", base64_decode($caref['crt']));
874
		@chmod("{$g['varrun_path']}/certs/{$caref['refid']}.ca", 0600);
875
		putenv('LDAPTLS_REQCERT=hard');
876
		/* XXX: Probably even the hashed link should be created for this? */
877
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
878
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
879
	}
880
}
881

    
882
function ldap_test_bind($authcfg) {
883
	global $debug, $config, $g;
884

    
885
	if ($authcfg) {
886
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
887
			$ldapproto = "ldaps";
888
		} else {
889
			$ldapproto = "ldap";
890
		}
891
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
892
		$ldapport = $authcfg['ldap_port'];
893
		if (!empty($ldapport)) {
894
			$ldapserver .= ":{$ldapport}";
895
		}
896
		$ldapbasedn = $authcfg['ldap_basedn'];
897
		$ldapbindun = $authcfg['ldap_binddn'];
898
		$ldapbindpw = $authcfg['ldap_bindpw'];
899
		$ldapver = $authcfg['ldap_protver'];
900
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
901
		if (empty($ldapbndun) || empty($ldapbindpw)) {
902
			$ldapanon = true;
903
		} else {
904
			$ldapanon = false;
905
		}
906
	} else {
907
		return false;
908
	}
909

    
910
	/* first check if there is even an LDAP server populated */
911
	if (!$ldapserver) {
912
		return false;
913
	}
914

    
915
	/* Setup CA environment if needed. */
916
	ldap_setup_caenv($authcfg);
917

    
918
	/* connect and see if server is up */
919
	$error = false;
920
	if (!($ldap = ldap_connect($ldapserver))) {
921
		$error = true;
922
	}
923

    
924
	if ($error == true) {
925
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
926
		return false;
927
	}
928

    
929
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
930
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
931
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
932
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
933
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
934

    
935
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
936
		if (!(ldap_start_tls($ldap))) {
937
			log_error(sprintf(gettext("ERROR! ldap_test_bind() could not STARTTLS to server %s."), $ldapname));
938
			@ldap_close($ldap);
939
			return false;
940
		}
941
	}
942

    
943
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
944
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
945
	if ($ldapanon == true) {
946
		if (!($res = @ldap_bind($ldap))) {
947
			@ldap_close($ldap);
948
			return false;
949
		}
950
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
951
		@ldap_close($ldap);
952
		return false;
953
	}
954

    
955
	@ldap_unbind($ldap);
956

    
957
	return true;
958
}
959

    
960
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
961
	global $debug, $config, $g;
962

    
963
	if (!function_exists("ldap_connect")) {
964
		return;
965
	}
966

    
967
	$ous = array();
968

    
969
	if ($authcfg) {
970
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
971
			$ldapproto = "ldaps";
972
		} else {
973
			$ldapproto = "ldap";
974
		}
975
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
976
		$ldapport = $authcfg['ldap_port'];
977
		if (!empty($ldapport)) {
978
			$ldapserver .= ":{$ldapport}";
979
		}
980
		$ldapbasedn = $authcfg['ldap_basedn'];
981
		$ldapbindun = $authcfg['ldap_binddn'];
982
		$ldapbindpw = $authcfg['ldap_bindpw'];
983
		$ldapver = $authcfg['ldap_protver'];
984
		if (empty($ldapbindun) || empty($ldapbindpw)) {
985
			$ldapanon = true;
986
		} else {
987
			$ldapanon = false;
988
		}
989
		$ldapname = $authcfg['name'];
990
		$ldapfallback = false;
991
		$ldapscope = $authcfg['ldap_scope'];
992
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
993
	} else {
994
		return false;
995
	}
996

    
997
	/* first check if there is even an LDAP server populated */
998
	if (!$ldapserver) {
999
		log_error(gettext("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined."));
1000
		return $ous;
1001
	}
1002

    
1003
	/* Setup CA environment if needed. */
1004
	ldap_setup_caenv($authcfg);
1005

    
1006
	/* connect and see if server is up */
1007
	$error = false;
1008
	if (!($ldap = ldap_connect($ldapserver))) {
1009
		$error = true;
1010
	}
1011

    
1012
	if ($error == true) {
1013
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1014
		return $ous;
1015
	}
1016

    
1017
	$ldapfilter = "(|(ou=*)(cn=Users))";
1018

    
1019
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1020
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1021
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1022
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1023
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1024

    
1025
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1026
		if (!(ldap_start_tls($ldap))) {
1027
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not STARTTLS to server %s."), $ldapname));
1028
			@ldap_close($ldap);
1029
			return false;
1030
		}
1031
	}
1032

    
1033
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1034
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1035
	if ($ldapanon == true) {
1036
		if (!($res = @ldap_bind($ldap))) {
1037
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind anonymously to server %s."), $ldapname));
1038
			@ldap_close($ldap);
1039
			return $ous;
1040
		}
1041
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1042
		log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind to server %s."), $ldapname));
1043
		@ldap_close($ldap);
1044
		return $ous;
1045
	}
1046

    
1047
	if ($ldapscope == "one") {
1048
		$ldapfunc = "ldap_list";
1049
	} else {
1050
		$ldapfunc = "ldap_search";
1051
	}
1052

    
1053
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
1054
	$info = @ldap_get_entries($ldap, $search);
1055

    
1056
	if (is_array($info)) {
1057
		foreach ($info as $inf) {
1058
			if (!$show_complete_ou) {
1059
				$inf_split = explode(",", $inf['dn']);
1060
				$ou = $inf_split[0];
1061
				$ou = str_replace("OU=", "", $ou);
1062
				$ou = str_replace("CN=", "", $ou);
1063
			} else {
1064
				if ($inf['dn']) {
1065
					$ou = $inf['dn'];
1066
				}
1067
			}
1068
			if ($ou) {
1069
				$ous[] = $ou;
1070
			}
1071
		}
1072
	}
1073

    
1074
	@ldap_unbind($ldap);
1075

    
1076
	return $ous;
1077
}
1078

    
1079
function ldap_get_groups($username, $authcfg) {
1080
	global $debug, $config;
1081

    
1082
	if (!function_exists("ldap_connect")) {
1083
		return;
1084
	}
1085

    
1086
	if (!$username) {
1087
		return false;
1088
	}
1089

    
1090
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1091
		$username_split = explode("@", $username);
1092
		$username = $username_split[0];
1093
	}
1094

    
1095
	if (stristr($username, "\\")) {
1096
		$username_split = explode("\\", $username);
1097
		$username = $username_split[0];
1098
	}
1099

    
1100
	//log_error("Getting LDAP groups for {$username}.");
1101
	if ($authcfg) {
1102
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
1103
			$ldapproto = "ldaps";
1104
		} else {
1105
			$ldapproto = "ldap";
1106
		}
1107
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1108
		$ldapport = $authcfg['ldap_port'];
1109
		if (!empty($ldapport)) {
1110
			$ldapserver .= ":{$ldapport}";
1111
		}
1112
		$ldapbasedn = $authcfg['ldap_basedn'];
1113
		$ldapbindun = $authcfg['ldap_binddn'];
1114
		$ldapbindpw = $authcfg['ldap_bindpw'];
1115
		$ldapauthcont = $authcfg['ldap_authcn'];
1116
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1117
		$ldapgroupattribute = strtolower($authcfg['ldap_attr_member']);
1118
		if (isset($authcfg['ldap_rfc2307'])) {
1119
			$ldapfilter         = "(&(objectClass={$authcfg['ldap_attr_groupobj']})({$ldapgroupattribute}={$username}))";
1120
		} else {
1121
			$ldapfilter         = "({$ldapnameattribute}={$username})";
1122
		}
1123
		$ldaptype = "";
1124
		$ldapver = $authcfg['ldap_protver'];
1125
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1126
			$ldapanon = true;
1127
		} else {
1128
			$ldapanon = false;
1129
		}
1130
		$ldapname = $authcfg['name'];
1131
		$ldapfallback = false;
1132
		$ldapscope = $authcfg['ldap_scope'];
1133
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1134
	} else {
1135
		return false;
1136
	}
1137

    
1138
	if (isset($authcfg['ldap_rfc2307'])) {
1139
		$ldapdn = $ldapbasedn;
1140
	} else {
1141
		$ldapdn = $_SESSION['ldapdn'];
1142
	}
1143

    
1144
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
1145
	$ldapgroupattribute = strtolower($ldapgroupattribute);
1146
	$memberof = array();
1147

    
1148
	/* Setup CA environment if needed. */
1149
	ldap_setup_caenv($authcfg);
1150

    
1151
	/* connect and see if server is up */
1152
	$error = false;
1153
	if (!($ldap = ldap_connect($ldapserver))) {
1154
		$error = true;
1155
	}
1156

    
1157
	if ($error == true) {
1158
		log_error(sprintf(gettext("ERROR! ldap_get_groups() Could not connect to server %s."), $ldapname));
1159
		return $memberof;
1160
	}
1161

    
1162
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1163
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1164
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1165
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1166
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1167

    
1168
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1169
		if (!(ldap_start_tls($ldap))) {
1170
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not STARTTLS to server %s."), $ldapname));
1171
			@ldap_close($ldap);
1172
			return false;
1173
		}
1174
	}
1175

    
1176
	/* bind as user that has rights to read group attributes */
1177
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1178
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1179
	if ($ldapanon == true) {
1180
		if (!($res = @ldap_bind($ldap))) {
1181
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
1182
			@ldap_close($ldap);
1183
			return false;
1184
		}
1185
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1186
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
1187
		@ldap_close($ldap);
1188
		return $memberof;
1189
	}
1190

    
1191
	/* get groups from DN found */
1192
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
1193
	/* since we know the DN is in $_SESSION['ldapdn'] */
1194
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
1195
	if ($ldapscope == "one") {
1196
		$ldapfunc = "ldap_list";
1197
	} else {
1198
		$ldapfunc = "ldap_search";
1199
	}
1200

    
1201
	$search = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
1202
	$info = @ldap_get_entries($ldap, $search);
1203

    
1204
	$gresults = isset($authcfg['ldap_rfc2307']) ? $info : $info[0][$ldapgroupattribute];
1205

    
1206
	if (is_array($gresults)) {
1207
		/* Iterate through the groups and throw them into an array */
1208
		foreach ($gresults as $grp) {
1209
			if (((isset($authcfg['ldap_rfc2307'])) && (stristr($grp["dn"], "CN=") !== false)) ||
1210
			    ((!isset($authcfg['ldap_rfc2307'])) && (stristr($grp, "CN=") !== false))) {
1211
				$grpsplit = isset($authcfg['ldap_rfc2307']) ? explode(",", $grp["dn"]) : explode(",", $grp);
1212
				$memberof[] = preg_replace("/CN=/i", "", $grpsplit[0]);
1213
			}
1214
		}
1215
	}
1216

    
1217
	/* Time to close LDAP connection */
1218
	@ldap_unbind($ldap);
1219

    
1220
	$groups = print_r($memberof, true);
1221

    
1222
	//log_error("Returning groups ".$groups." for user $username");
1223

    
1224
	return $memberof;
1225
}
1226

    
1227
function ldap_format_host($host) {
1228
	return is_ipaddrv6($host) ? "[$host]" : $host ;
1229
}
1230

    
1231
function ldap_backed($username, $passwd, $authcfg) {
1232
	global $debug, $config;
1233

    
1234
	if (!$username) {
1235
		return;
1236
	}
1237

    
1238
	if (!function_exists("ldap_connect")) {
1239
		return;
1240
	}
1241

    
1242
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1243
		$username_split = explode("@", $username);
1244
		$username = $username_split[0];
1245
	}
1246
	if (stristr($username, "\\")) {
1247
		$username_split = explode("\\", $username);
1248
		$username = $username_split[0];
1249
	}
1250

    
1251
	if ($authcfg) {
1252
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
1253
			$ldapproto = "ldaps";
1254
		} else {
1255
			$ldapproto = "ldap";
1256
		}
1257
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1258
		$ldapport = $authcfg['ldap_port'];
1259
		if (!empty($ldapport)) {
1260
			$ldapserver .= ":{$ldapport}";
1261
		}
1262
		$ldapbasedn = $authcfg['ldap_basedn'];
1263
		$ldapbindun = $authcfg['ldap_binddn'];
1264
		$ldapbindpw = $authcfg['ldap_bindpw'];
1265
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1266
			$ldapanon = true;
1267
		} else {
1268
			$ldapanon = false;
1269
		}
1270
		$ldapauthcont = $authcfg['ldap_authcn'];
1271
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1272
		$ldapextendedqueryenabled = $authcfg['ldap_extended_enabled'];
1273
		$ldapextendedquery = $authcfg['ldap_extended_query'];
1274
		$ldapfilter = "";
1275
		if (!$ldapextendedqueryenabled) {
1276
			$ldapfilter = "({$ldapnameattribute}={$username})";
1277
		} else {
1278
			$ldapfilter = "(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
1279
		}
1280
		$ldaptype = "";
1281
		$ldapver = $authcfg['ldap_protver'];
1282
		$ldapname = $authcfg['name'];
1283
		$ldapscope = $authcfg['ldap_scope'];
1284
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1285
	} else {
1286
		return false;
1287
	}
1288

    
1289
	/* first check if there is even an LDAP server populated */
1290
	if (!$ldapserver) {
1291
		if ($ldapfallback) {
1292
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager."));
1293
			return local_backed($username, $passwd);
1294
		} else {
1295
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined."));
1296
		}
1297

    
1298
		return false;
1299
	}
1300

    
1301
	/* Setup CA environment if needed. */
1302
	ldap_setup_caenv($authcfg);
1303

    
1304
	/* Make sure we can connect to LDAP */
1305
	$error = false;
1306
	if (!($ldap = ldap_connect($ldapserver))) {
1307
		$error = true;
1308
	}
1309

    
1310
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1311
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1312
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1313
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1314
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1315

    
1316
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1317
		if (!(ldap_start_tls($ldap))) {
1318
			log_error(sprintf(gettext("ERROR! ldap_backed() could not STARTTLS to server %s."), $ldapname));
1319
			@ldap_close($ldap);
1320
			return false;
1321
		}
1322
	}
1323

    
1324
	if ($error == true) {
1325
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1326
		return false;
1327
	}
1328

    
1329
	/* ok, its up.  now, lets bind as the bind user so we can search it */
1330
	$error = false;
1331
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1332
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1333
	if ($ldapanon == true) {
1334
		if (!($res = @ldap_bind($ldap))) {
1335
			$error = true;
1336
		}
1337
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1338
		$error = true;
1339
	}
1340

    
1341
	if ($error == true) {
1342
		@ldap_close($ldap);
1343
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1344
		return false;
1345
	}
1346

    
1347
	/* Get LDAP Authcontainers and split em up. */
1348
	$ldac_splits = explode(";", $ldapauthcont);
1349

    
1350
	/* setup the usercount so we think we haven't found anyone yet */
1351
	$usercount = 0;
1352

    
1353
	/*****************************************************************/
1354
	/*  We first find the user based on username and filter          */
1355
	/*  then, once we find the first occurrence of that person       */
1356
	/*  we set session variables to point to the OU and DN of the    */
1357
	/*  person.  To later be used by ldap_get_groups.                */
1358
	/*  that way we don't have to search twice.                      */
1359
	/*****************************************************************/
1360
	if ($debug) {
1361
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1362
	}
1363
	/* Iterate through the user containers for search */
1364
	foreach ($ldac_splits as $i => $ldac_split) {
1365
		$ldac_split = isset($authcfg['ldap_utf8']) ? utf8_encode($ldac_split) : $ldac_split;
1366
		$ldapfilter = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapfilter) : $ldapfilter;
1367
		$ldapsearchbasedn = isset($authcfg['ldap_utf8']) ? utf8_encode("{$ldac_split},{$ldapbasedn}") : "{$ldac_split},{$ldapbasedn}";
1368
		/* Make sure we just use the first user we find */
1369
		if ($debug) {
1370
			log_auth(sprintf(gettext('Now Searching in server %1$s, container %2$s with filter %3$s.'), $ldapname, utf8_decode($ldac_split), utf8_decode($ldapfilter)));
1371
		}
1372
		if ($ldapscope == "one") {
1373
			$ldapfunc = "ldap_list";
1374
		} else {
1375
			$ldapfunc = "ldap_search";
1376
		}
1377
		/* Support legacy auth container specification. */
1378
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn)) {
1379
			$search = @$ldapfunc($ldap, $ldac_split, $ldapfilter);
1380
		} else {
1381
			$search = @$ldapfunc($ldap, $ldapsearchbasedn, $ldapfilter);
1382
		}
1383
		if (!$search) {
1384
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1385
			continue;
1386
		}
1387
		$info = ldap_get_entries($ldap, $search);
1388
		$matches = $info['count'];
1389
		if ($matches == 1) {
1390
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1391
			$_SESSION['ldapou'] = $ldac_split[$i];
1392
			$_SESSION['ldapon'] = "true";
1393
			$usercount = 1;
1394
			break;
1395
		}
1396
	}
1397

    
1398
	if ($usercount != 1) {
1399
		@ldap_unbind($ldap);
1400
		log_error(gettext("ERROR! Either LDAP search failed, or multiple users were found."));
1401
		return false;
1402
	}
1403

    
1404
	/* Now lets bind as the user we found */
1405
	$passwd = isset($authcfg['ldap_utf8']) ? utf8_encode($passwd) : $passwd;
1406
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
1407
		log_error(sprintf(gettext('ERROR! Could not login to server %1$s as user %2$s: %3$s'), $ldapname, $username, ldap_error($ldap)));
1408
		@ldap_unbind($ldap);
1409
		return false;
1410
	}
1411

    
1412
	if ($debug) {
1413
		$userdn = isset($authcfg['ldap_utf8']) ? utf8_decode($userdn) : $userdn;
1414
		log_auth(sprintf(gettext('Logged in successfully as %1$s via LDAP server %2$s with DN = %3$s.'), $username, $ldapname, $userdn));
1415
	}
1416

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

    
1420
	return true;
1421
}
1422

    
1423
function radius_backed($username, $passwd, $authcfg, &$attributes = array()) {
1424
	global $debug, $config;
1425
	$ret = false;
1426

    
1427
	require_once("radius.inc");
1428

    
1429
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1430
	if ($authcfg) {
1431
		$radiusservers = array();
1432
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1433
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1434
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1435
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1436
	} else {
1437
		return false;
1438
	}
1439

    
1440
	/* Add new servers to our instance */
1441
	foreach ($radiusservers as $radsrv) {
1442
		$timeout = (is_numeric($radsrv['timeout'])) ? $radsrv['timeout'] : 5;
1443
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret'], $timeout);
1444
	}
1445

    
1446
	if (PEAR::isError($rauth->start())) {
1447
		$retvalue['auth_val'] = 1;
1448
		$retvalue['error'] = $rauth->getError();
1449
		if ($debug) {
1450
			printf(gettext("RADIUS start: %s<br />\n"), $retvalue['error']);
1451
		}
1452
	}
1453

    
1454
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1455

    
1456
	/* Send request */
1457
	$result = $rauth->send();
1458
	if (PEAR::isError($result)) {
1459
		$retvalue['auth_val'] = 1;
1460
		$retvalue['error'] = $result->getMessage();
1461
		if ($debug) {
1462
			printf(gettext("RADIUS send failed: %s<br />\n"), $retvalue['error']);
1463
		}
1464
	} else if ($result === true) {
1465
		if ($rauth->getAttributes()) {
1466
			$attributes = $rauth->listAttributes();
1467
		}
1468
		$retvalue['auth_val'] = 2;
1469
		if ($debug) {
1470
			printf(gettext("RADIUS Auth succeeded")."<br />\n");
1471
		}
1472
		$ret = true;
1473
	} else {
1474
		$retvalue['auth_val'] = 3;
1475
		if ($debug) {
1476
			printf(gettext("RADIUS Auth rejected")."<br />\n");
1477
		}
1478
	}
1479

    
1480
	// close OO RADIUS_AUTHENTICATION
1481
	$rauth->close();
1482

    
1483
	return $ret;
1484
}
1485

    
1486
/*
1487
	$attributes must contain a "class" key containing the groups and local
1488
	groups must exist to match.
1489
*/
1490
function radius_get_groups($attributes) {
1491
	$groups = array();
1492
	if (!empty($attributes) && is_array($attributes) && (!empty($attributes['class']) || !empty($attributes['class_int']))) {
1493
		/* Some RADIUS servers return multiple class attributes, so check them all. */
1494
		$groups = array();
1495
		if (!empty($attributes['class']) && is_array($attributes['class'])) {
1496
			foreach ($attributes['class'] as $class) {
1497
				$groups = array_unique(array_merge($groups, explode(";", $class)));
1498
			}
1499
		}
1500

    
1501
		foreach ($groups as & $grp) {
1502
			$grp = trim($grp);
1503
			if (strtolower(substr($grp, 0, 3)) == "ou=") {
1504
				$grp = substr($grp, 3);
1505
			}
1506
		}
1507
	}
1508
	return $groups;
1509
}
1510

    
1511
function get_user_expiration_date($username) {
1512
	$user = getUserEntry($username);
1513
	if ($user['expires']) {
1514
		return $user['expires'];
1515
	}
1516
}
1517

    
1518
function is_account_expired($username) {
1519
	$expirydate = get_user_expiration_date($username);
1520
	if ($expirydate) {
1521
		if (strtotime("-1 day") > strtotime(date("m/d/Y", strtotime($expirydate)))) {
1522
			return true;
1523
		}
1524
	}
1525

    
1526
	return false;
1527
}
1528

    
1529
function is_account_disabled($username) {
1530
	$user = getUserEntry($username);
1531
	if (isset($user['disabled'])) {
1532
		return true;
1533
	}
1534

    
1535
	return false;
1536
}
1537

    
1538
function get_user_settings($username) {
1539
	global $config;
1540
	$settings = array();
1541
	$settings['widgets'] = $config['widgets'];
1542
	$settings['webgui']['dashboardcolumns'] = $config['system']['webgui']['dashboardcolumns'];
1543
	$settings['webgui']['webguihostnamemenu'] = $config['system']['webgui']['webguihostnamemenu'];
1544
	$settings['webgui']['webguicss'] = $config['system']['webgui']['webguicss'];
1545
	$settings['webgui']['interfacessort'] = isset($config['system']['webgui']['interfacessort']);
1546
	$settings['webgui']['dashboardavailablewidgetspanel'] = isset($config['system']['webgui']['dashboardavailablewidgetspanel']);
1547
	$settings['webgui']['webguifixedmenu'] = isset($config['system']['webgui']['webguifixedmenu']);
1548
	$settings['webgui']['webguileftcolumnhyper'] = isset($config['system']['webgui']['webguileftcolumnhyper']);
1549
	$settings['webgui']['systemlogsfilterpanel'] = isset($config['system']['webgui']['systemlogsfilterpanel']);
1550
	$settings['webgui']['systemlogsmanagelogpanel'] = isset($config['system']['webgui']['systemlogsmanagelogpanel']);
1551
	$settings['webgui']['statusmonitoringsettingspanel'] = isset($config['system']['webgui']['statusmonitoringsettingspanel']);
1552
	$settings['webgui']['pagenamefirst'] = isset($config['system']['webgui']['pagenamefirst']);
1553
	$user = getUserEntry($username);
1554
	if (isset($user['customsettings'])) {
1555
		$settings['customsettings'] = true;
1556
		if (isset($user['widgets'])) {
1557
			// This includes the 'sequence', and any widgetname-config per-widget settings.
1558
			$settings['widgets'] = $user['widgets'];
1559
		}
1560
		if (isset($user['dashboardcolumns'])) {
1561
			$settings['webgui']['dashboardcolumns'] = $user['dashboardcolumns'];
1562
		}
1563
		if (isset($user['webguicss'])) {
1564
			$settings['webgui']['webguicss'] = $user['webguicss'];
1565
		}
1566
		if (isset($user['webguihostnamemenu'])) {
1567
			$settings['webgui']['webguihostnamemenu'] = $user['webguihostnamemenu'];
1568
		}
1569
		$settings['webgui']['interfacessort'] = isset($user['interfacessort']);
1570
		$settings['webgui']['dashboardavailablewidgetspanel'] = isset($user['dashboardavailablewidgetspanel']);
1571
		$settings['webgui']['webguifixedmenu'] = isset($user['webguifixedmenu']);
1572
		$settings['webgui']['webguileftcolumnhyper'] = isset($user['webguileftcolumnhyper']);
1573
		$settings['webgui']['systemlogsfilterpanel'] = isset($user['systemlogsfilterpanel']);
1574
		$settings['webgui']['systemlogsmanagelogpanel'] = isset($user['systemlogsmanagelogpanel']);
1575
		$settings['webgui']['statusmonitoringsettingspanel'] = isset($user['statusmonitoringsettingspanel']);
1576
		$settings['webgui']['pagenamefirst'] = isset($user['pagenamefirst']);
1577
	} else {
1578
		$settings['customsettings'] = false;
1579
	}
1580

    
1581
	if ($settings['webgui']['dashboardcolumns'] < 1) {
1582
		$settings['webgui']['dashboardcolumns'] = 2;
1583
	}
1584

    
1585
	return $settings;
1586
}
1587

    
1588
function save_widget_settings($username, $settings, $message = "") {
1589
	global $config, $userindex;
1590
	$user = getUserEntry($username);
1591

    
1592
	if (strlen($message) > 0) {
1593
		$msgout = $message;
1594
	} else {
1595
		$msgout = gettext("Widget configuration has been changed.");
1596
	}
1597

    
1598
	if (isset($user['customsettings'])) {
1599
		$config['system']['user'][$userindex[$username]]['widgets'] = $settings;
1600
		write_config($msgout . " " . sprintf(gettext("(User %s)"), $username));
1601
	} else {
1602
		$config['widgets'] = $settings;
1603
		write_config($msgout);
1604
	}
1605
}
1606

    
1607
function auth_get_authserver($name) {
1608
	global $config;
1609

    
1610
	if (is_array($config['system']['authserver'])) {
1611
		foreach ($config['system']['authserver'] as $authcfg) {
1612
			if ($authcfg['name'] == $name) {
1613
				return $authcfg;
1614
			}
1615
		}
1616
	}
1617
	if ($name == "Local Database") {
1618
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1619
	}
1620
}
1621

    
1622
function auth_get_authserver_list() {
1623
	global $config;
1624

    
1625
	$list = array();
1626

    
1627
	if (is_array($config['system']['authserver'])) {
1628
		foreach ($config['system']['authserver'] as $authcfg) {
1629
			/* Add support for disabled entries? */
1630
			$list[$authcfg['name']] = $authcfg;
1631
		}
1632
	}
1633

    
1634
	$list["Local Database"] = array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1635
	return $list;
1636
}
1637

    
1638
function getUserGroups($username, $authcfg, &$attributes = array()) {
1639
	global $config;
1640

    
1641
	$allowed_groups = array();
1642

    
1643
	switch ($authcfg['type']) {
1644
		case 'ldap':
1645
			$allowed_groups = @ldap_get_groups($username, $authcfg);
1646
			break;
1647
		case 'radius':
1648
			$allowed_groups = @radius_get_groups($attributes);
1649
			break;
1650
		default:
1651
			$user = getUserEntry($username);
1652
			$allowed_groups = @local_user_get_groups($user, true);
1653
			break;
1654
	}
1655

    
1656
	$member_groups = array();
1657
	if (is_array($config['system']['group'])) {
1658
		foreach ($config['system']['group'] as $group) {
1659
			if (in_array($group['name'], $allowed_groups)) {
1660
				$member_groups[] = $group['name'];
1661
			}
1662
		}
1663
	}
1664

    
1665
	return $member_groups;
1666
}
1667

    
1668
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1669

    
1670
	if (is_array($username) || is_array($password)) {
1671
		return false;
1672
	}
1673

    
1674
	if (!$authcfg) {
1675
		return local_backed($username, $password);
1676
	}
1677

    
1678
	$authenticated = false;
1679
	switch ($authcfg['type']) {
1680
		case 'ldap':
1681
			if (ldap_backed($username, $password, $authcfg)) {
1682
				$authenticated = true;
1683
			}
1684
			break;
1685
		case 'radius':
1686
			if (radius_backed($username, $password, $authcfg, $attributes)) {
1687
				$authenticated = true;
1688
			}
1689
			break;
1690
		default:
1691
			/* lookup user object by name */
1692
			if (local_backed($username, $password)) {
1693
				$authenticated = true;
1694
			}
1695
			break;
1696
		}
1697

    
1698
	return $authenticated;
1699
}
1700

    
1701
function session_auth() {
1702
	global $config, $_SESSION, $page;
1703

    
1704
	// Handle HTTPS httponly and secure flags
1705
	$currentCookieParams = session_get_cookie_params();
1706
	session_set_cookie_params(
1707
		$currentCookieParams["lifetime"],
1708
		$currentCookieParams["path"],
1709
		NULL,
1710
		($config['system']['webgui']['protocol'] == "https"),
1711
		true
1712
	);
1713

    
1714
	if (!session_id()) {
1715
		session_start();
1716
	}
1717

    
1718
	// Detect protocol change
1719
	if (!isset($_POST['login']) && !empty($_SESSION['Logged_In']) && $_SESSION['protocol'] != $config['system']['webgui']['protocol']) {
1720
		return false;
1721
	}
1722

    
1723
	/* Validate incoming login request */
1724
	$attributes = array();
1725
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1726
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1727
		$remoteauth = authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg, $attributes);
1728
		if ($remoteauth || authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1729
			// Generate a new id to avoid session fixation
1730
			session_regenerate_id();
1731
			$_SESSION['Logged_In'] = "True";
1732
			$_SESSION['remoteauth'] = $remoteauth;
1733
			$_SESSION['Username'] = $_POST['usernamefld'];
1734
			$_SESSION['user_radius_attributes'] = $attributes;
1735
			$_SESSION['last_access'] = time();
1736
			$_SESSION['protocol'] = $config['system']['webgui']['protocol'];
1737
			if (!isset($config['system']['webgui']['quietlogin'])) {
1738
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1739
			}
1740
			if (isset($_POST['postafterlogin'])) {
1741
				return true;
1742
			} else {
1743
				if (empty($page)) {
1744
					$page = "/";
1745
				}
1746
				header("Location: {$page}");
1747
			}
1748
			exit;
1749
		} else {
1750
			/* give the user an error message */
1751
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1752
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1753
			if (isAjax()) {
1754
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1755
				return;
1756
			}
1757
		}
1758
	}
1759

    
1760
	/* Show login page if they aren't logged in */
1761
	if (empty($_SESSION['Logged_In'])) {
1762
		return false;
1763
	}
1764

    
1765
	/* If session timeout isn't set, we don't mark sessions stale */
1766
	if (!isset($config['system']['webgui']['session_timeout'])) {
1767
		/* Default to 4 hour timeout if one is not set */
1768
		if ($_SESSION['last_access'] < (time() - 14400)) {
1769
			$_GET['logout'] = true;
1770
			$_SESSION['Logout'] = true;
1771
		} else {
1772
			$_SESSION['last_access'] = time();
1773
		}
1774
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1775
		/* only update if it wasn't ajax */
1776
		if (!isAjax()) {
1777
			$_SESSION['last_access'] = time();
1778
		}
1779
	} else {
1780
		/* Check for stale session */
1781
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1782
			$_GET['logout'] = true;
1783
			$_SESSION['Logout'] = true;
1784
		} else {
1785
			/* only update if it wasn't ajax */
1786
			if (!isAjax()) {
1787
				$_SESSION['last_access'] = time();
1788
			}
1789
		}
1790
	}
1791

    
1792
	/* user hit the logout button */
1793
	if (isset($_GET['logout'])) {
1794

    
1795
		if ($_SESSION['Logout']) {
1796
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1797
		} else {
1798
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1799
		}
1800

    
1801
		/* wipe out $_SESSION */
1802
		$_SESSION = array();
1803

    
1804
		if (isset($_COOKIE[session_name()])) {
1805
			setcookie(session_name(), '', time()-42000, '/');
1806
		}
1807

    
1808
		/* and destroy it */
1809
		session_destroy();
1810

    
1811
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1812
		$scriptElms = count($scriptName);
1813
		$scriptName = $scriptName[$scriptElms-1];
1814

    
1815
		if (isAjax()) {
1816
			return false;
1817
		}
1818

    
1819
		/* redirect to page the user is on, it'll prompt them to login again */
1820
		header("Location: {$scriptName}");
1821

    
1822
		return false;
1823
	}
1824

    
1825
	/*
1826
	 * this is for debugging purpose if you do not want to use Ajax
1827
	 * to submit a HTML form. It basically disables the observation
1828
	 * of the submit event and hence does not trigger Ajax.
1829
	 */
1830
	if ($_GET['disable_ajax']) {
1831
		$_SESSION['NO_AJAX'] = "True";
1832
	}
1833

    
1834
	/*
1835
	 * Same to re-enable Ajax.
1836
	 */
1837
	if ($_GET['enable_ajax']) {
1838
		unset($_SESSION['NO_AJAX']);
1839
	}
1840

    
1841
	return true;
1842
}
1843

    
1844
?>
(4-4/67)