Project

General

Profile

Download (53.2 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")) {
71
	/* Extra layer of lockout protection. Check if the user is in the GUI
72
	 * lockout table before processing a request */
73

    
74
	/* Fetch the contents of the lockout table. */
75
	exec("/sbin/pfctl -t 'webConfiguratorlockout' -T show", $entries);
76

    
77
	/* If the client is in the lockout table, print an error, kill states, and exit */
78
	if (in_array($_SERVER['REMOTE_ADDR'], array_map('trim', $entries))) {
79
		if (!security_checks_disabled()) {
80
			/* They may never see the error since the connection will be cut off, but try to be nice anyhow. */
81
			display_error_form("501", gettext("Access Denied<br/><br/>Access attempt from a temporarily locked out client address.<br /><br />Try accessing the firewall again after the lockout expires."));
82
			/* If they are locked out, they shouldn't have a state. Disconnect their connections. */
83
			$retval = pfSense_kill_states($_SERVER['REMOTE_ADDR']);
84
			if (is_ipaddrv4($_SERVER['REMOTE_ADDR'])) {
85
				$retval = pfSense_kill_states("0.0.0.0/0", $_SERVER['REMOTE_ADDR']);
86
			} elseif (is_ipaddrv6($_SERVER['REMOTE_ADDR'])) {
87
				$retval = pfSense_kill_states("::", $_SERVER['REMOTE_ADDR']);
88
			}
89
			exit;
90
		}
91
		$security_passed = false;
92
	}
93
}
94

    
95
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
96
	/* DNS ReBinding attack prevention.  https://redmine.pfsense.org/issues/708 */
97
	$found_host = false;
98

    
99
	/* Either a IPv6 address with or without a alternate port */
100
	if (strstr($_SERVER['HTTP_HOST'], "]")) {
101
		$http_host_port = explode("]", $_SERVER['HTTP_HOST']);
102
		/* v6 address has more parts, drop the last part */
103
		if (count($http_host_port) > 1) {
104
			array_pop($http_host_port);
105
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
106
		} else {
107
			$http_host = str_replace(array("[", "]"), "", implode(":", $http_host_port));
108
		}
109
	} else {
110
		$http_host = explode(":", $_SERVER['HTTP_HOST']);
111
		$http_host = $http_host[0];
112
	}
113
	if (is_ipaddr($http_host) or $_SERVER['SERVER_ADDR'] == "127.0.0.1" or
114
		strcasecmp($http_host, "localhost") == 0 or $_SERVER['SERVER_ADDR'] == "::1") {
115
		$found_host = true;
116
	}
117
	if (strcasecmp($http_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 or
118
		strcasecmp($http_host, $config['system']['hostname']) == 0) {
119
		$found_host = true;
120
	}
121

    
122
	if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
123
		foreach ($config['dyndnses']['dyndns'] as $dyndns) {
124
			if (strcasecmp($dyndns['host'], $http_host) == 0) {
125
				$found_host = true;
126
				break;
127
			}
128
		}
129
	}
130

    
131
	if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
132
		foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
133
			if (strcasecmp($rfc2136['host'], $http_host) == 0) {
134
				$found_host = true;
135
				break;
136
			}
137
		}
138
	}
139

    
140
	if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
141
		$althosts = explode(" ", $config['system']['webgui']['althostnames']);
142
		foreach ($althosts as $ah) {
143
			if (strcasecmp($ah, $http_host) == 0 or strcasecmp($ah, $_SERVER['SERVER_ADDR']) == 0) {
144
				$found_host = true;
145
				break;
146
			}
147
		}
148
	}
149

    
150
	if ($found_host == false) {
151
		if (!security_checks_disabled()) {
152
			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."));
153
			exit;
154
		}
155
		$security_passed = false;
156
	}
157
}
158

    
159
// If the HTTP_REFERER is something other than ourselves then disallow.
160
if (function_exists("display_error_form") && !isset($config['system']['webgui']['nohttpreferercheck'])) {
161
	if ($_SERVER['HTTP_REFERER']) {
162
		if (file_exists("{$g['tmp_path']}/setupwizard_lastreferrer")) {
163
			if ($_SERVER['HTTP_REFERER'] == file_get_contents("{$g['tmp_path']}/setupwizard_lastreferrer")) {
164
				unlink("{$g['tmp_path']}/setupwizard_lastreferrer");
165
				header("Refresh: 1; url=index.php");
166
?>
167
<!DOCTYPE html>
168
<html lang="en">
169
<head>
170
	<link rel="stylesheet" href="/css/pfSense.css" />
171
	<title><?=gettext("Redirecting..."); ?></title>
172
</head>
173
<body id="error" class="no-menu">
174
	<div id="jumbotron">
175
		<div class="container">
176
			<div class="col-sm-offset-3 col-sm-6 col-xs-12">
177
				<p><?=gettext("Redirecting to the dashboard...")?></p>
178
			</div>
179
		</div>
180
	</div>
181
</body>
182
</html>
183
<?php
184
				exit;
185
			}
186
		}
187
		$found_host = false;
188
		$referrer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
189
		$referrer_host = str_replace(array("[", "]"), "", $referrer_host);
190
		if ($referrer_host) {
191
			if (strcasecmp($referrer_host, $config['system']['hostname'] . "." . $config['system']['domain']) == 0 ||
192
			    strcasecmp($referrer_host, $config['system']['hostname']) == 0) {
193
				$found_host = true;
194
			}
195

    
196
			if (!empty($config['system']['webgui']['althostnames']) && !$found_host) {
197
				$althosts = explode(" ", $config['system']['webgui']['althostnames']);
198
				foreach ($althosts as $ah) {
199
					if (strcasecmp($referrer_host, $ah) == 0) {
200
						$found_host = true;
201
						break;
202
					}
203
				}
204
			}
205

    
206
			if (is_array($config['dyndnses']['dyndns']) && !$found_host) {
207
				foreach ($config['dyndnses']['dyndns'] as $dyndns) {
208
					if (strcasecmp($dyndns['host'], $referrer_host) == 0) {
209
						$found_host = true;
210
						break;
211
					}
212
				}
213
			}
214

    
215
			if (is_array($config['dnsupdates']['dnsupdate']) && !$found_host) {
216
				foreach ($config['dnsupdates']['dnsupdate'] as $rfc2136) {
217
					if (strcasecmp($rfc2136['host'], $referrer_host) == 0) {
218
						$found_host = true;
219
						break;
220
					}
221
				}
222
			}
223

    
224
			if (!$found_host) {
225
				$interface_list_ips = get_configured_ip_addresses();
226
				foreach ($interface_list_ips as $ilips) {
227
					if (strcasecmp($referrer_host, $ilips) == 0) {
228
						$found_host = true;
229
						break;
230
					}
231
				}
232
				$interface_list_ipv6s = get_configured_ipv6_addresses(true);
233
				foreach ($interface_list_ipv6s as $ilipv6s) {
234
					$ilipv6s = explode('%', $ilipv6s)[0];
235
					if (strcasecmp($referrer_host, $ilipv6s) == 0) {
236
						$found_host = true;
237
						break;
238
					}
239
				}
240
				if ($referrer_host == "127.0.0.1" || $referrer_host == "localhost") {
241
					// allow SSH port forwarded connections and links from localhost
242
					$found_host = true;
243
				}
244
			}
245
		}
246
		if ($found_host == false) {
247
			if (!security_checks_disabled()) {
248
				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.");
249
				exit;
250
			}
251
			$security_passed = false;
252
		}
253
	} else {
254
		$security_passed = false;
255
	}
256
}
257

    
258
if (function_exists("display_error_form") && $security_passed) {
259
	/* Security checks passed, so it should be OK to turn them back on */
260
	restore_security_checks();
261
}
262
unset($security_passed);
263

    
264
$groupindex = index_groups();
265
$userindex = index_users();
266

    
267
function index_groups() {
268
	global $g, $debug, $config, $groupindex;
269

    
270
	$groupindex = array();
271

    
272
	if (is_array($config['system']['group'])) {
273
		$i = 0;
274
		foreach ($config['system']['group'] as $groupent) {
275
			$groupindex[$groupent['name']] = $i;
276
			$i++;
277
		}
278
	}
279

    
280
	return ($groupindex);
281
}
282

    
283
function index_users() {
284
	global $g, $debug, $config;
285

    
286
	if (is_array($config['system']['user'])) {
287
		$i = 0;
288
		foreach ($config['system']['user'] as $userent) {
289
			$userindex[$userent['name']] = $i;
290
			$i++;
291
		}
292
	}
293

    
294
	return ($userindex);
295
}
296

    
297
function & getUserEntry($name) {
298
	global $debug, $config, $userindex;
299
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
300

    
301
	if (isset($userindex[$name])) {
302
		return $config['system']['user'][$userindex[$name]];
303
	} elseif ($authcfg['type'] != "Local Database") {
304
		$user = array();
305
		$user['name'] = $name;
306
		return $user;
307
	}
308
}
309

    
310
function & getUserEntryByUID($uid) {
311
	global $debug, $config;
312

    
313
	if (is_array($config['system']['user'])) {
314
		foreach ($config['system']['user'] as & $user) {
315
			if ($user['uid'] == $uid) {
316
				return $user;
317
			}
318
		}
319
	}
320

    
321
	return false;
322
}
323

    
324
function & getGroupEntry($name) {
325
	global $debug, $config, $groupindex;
326
	if (isset($groupindex[$name])) {
327
		return $config['system']['group'][$groupindex[$name]];
328
	}
329
}
330

    
331
function & getGroupEntryByGID($gid) {
332
	global $debug, $config;
333

    
334
	if (is_array($config['system']['group'])) {
335
		foreach ($config['system']['group'] as & $group) {
336
			if ($group['gid'] == $gid) {
337
				return $group;
338
			}
339
		}
340
	}
341

    
342
	return false;
343
}
344

    
345
function get_user_privileges(& $user) {
346
	global $config;
347

    
348
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
349
	$names = array();
350

    
351
	$privs = $user['priv'];
352
	if (!is_array($privs)) {
353
		$privs = array();
354
	}
355

    
356
	if ($authcfg['type'] == "ldap") {
357
		$names = @ldap_get_groups($user['name'], $authcfg);
358
	} elseif ($authcfg['type'] == "radius") {
359
		$names = @radius_get_groups($_SESSION['user_radius_attributes']);
360
	}
361

    
362
	if (empty($names)) {
363
		$names = local_user_get_groups($user, true);
364
	}
365

    
366
	foreach ($names as $name) {
367
		$group = getGroupEntry($name);
368
		if (is_array($group['priv'])) {
369
			$privs = array_merge($privs, $group['priv']);
370
		}
371
	}
372

    
373
	return $privs;
374
}
375

    
376
function userHasPrivilege($userent, $privid = false) {
377

    
378
	if (!$privid || !is_array($userent)) {
379
		return false;
380
	}
381

    
382
	$privs = get_user_privileges($userent);
383

    
384
	if (!is_array($privs)) {
385
		return false;
386
	}
387

    
388
	if (!in_array($privid, $privs)) {
389
		return false;
390
	}
391

    
392
	return true;
393
}
394

    
395
function local_backed($username, $passwd) {
396

    
397
	$user = getUserEntry($username);
398
	if (!$user) {
399
		return false;
400
	}
401

    
402
	if (is_account_disabled($username) || is_account_expired($username)) {
403
		return false;
404
	}
405

    
406
	if ($user['bcrypt-hash']) {
407
		if (password_verify($passwd, $user['bcrypt-hash'])) {
408
			return true;
409
		}
410
	}
411

    
412
	//for backwards compatibility
413
	if ($user['password']) {
414
		if (crypt($passwd, $user['password']) == $user['password']) {
415
			return true;
416
		}
417
	}
418

    
419
	if ($user['md5-hash']) {
420
		if (md5($passwd) == $user['md5-hash']) {
421
			return true;
422
		}
423
	}
424

    
425
	return false;
426
}
427

    
428
function local_sync_accounts() {
429
	global $debug, $config;
430
	conf_mount_rw();
431

    
432
	/* remove local users to avoid uid conflicts */
433
	$fd = popen("/usr/sbin/pw usershow -a", "r");
434
	if ($fd) {
435
		while (!feof($fd)) {
436
			$line = explode(":", fgets($fd));
437
			if ($line[0] != "admin") {
438
				if (!strncmp($line[0], "_", 1)) {
439
					continue;
440
				}
441
				if ($line[2] < 2000) {
442
					continue;
443
				}
444
				if ($line[2] > 65000) {
445
					continue;
446
				}
447
			}
448
			/*
449
			 * If a crontab was created to user, pw userdel will be interactive and
450
			 * can cause issues. Just remove crontab before run it when necessary
451
			 */
452
			unlink_if_exists("/var/cron/tabs/{$line[0]}");
453
			$cmd = "/usr/sbin/pw userdel -n " . escapeshellarg($line[0]);
454
			if ($debug) {
455
				log_error(sprintf(gettext("Running: %s"), $cmd));
456
			}
457
			mwexec($cmd);
458
		}
459
		pclose($fd);
460
	}
461

    
462
	/* remove local groups to avoid gid conflicts */
463
	$gids = array();
464
	$fd = popen("/usr/sbin/pw groupshow -a", "r");
465
	if ($fd) {
466
		while (!feof($fd)) {
467
			$line = explode(":", fgets($fd));
468
			if (!strncmp($line[0], "_", 1)) {
469
				continue;
470
			}
471
			if ($line[2] < 2000) {
472
				continue;
473
			}
474
			if ($line[2] > 65000) {
475
				continue;
476
			}
477
			$cmd = "/usr/sbin/pw groupdel -g " . escapeshellarg($line[2]);
478
			if ($debug) {
479
				log_error(sprintf(gettext("Running: %s"), $cmd));
480
			}
481
			mwexec($cmd);
482
		}
483
		pclose($fd);
484
	}
485

    
486
	/* make sure the all group exists */
487
	$allgrp = getGroupEntryByGID(1998);
488
	local_group_set($allgrp, true);
489

    
490
	/* sync all local users */
491
	if (is_array($config['system']['user'])) {
492
		foreach ($config['system']['user'] as $user) {
493
			local_user_set($user);
494
		}
495
	}
496

    
497
	/* sync all local groups */
498
	if (is_array($config['system']['group'])) {
499
		foreach ($config['system']['group'] as $group) {
500
			local_group_set($group);
501
		}
502
	}
503

    
504
	conf_mount_ro();
505

    
506
}
507

    
508
function local_user_set(& $user) {
509
	global $g, $debug;
510

    
511
	if (empty($user['password']) && empty($user['bcrypt-hash'])) {
512
		log_error("There is something wrong in the config because user {$user['name']} password is missing!");
513
		return;
514
	}
515

    
516
	conf_mount_rw();
517

    
518
	$home_base = "/home/";
519
	$user_uid = $user['uid'];
520
	$user_name = $user['name'];
521
	$user_home = "{$home_base}{$user_name}";
522
	$user_shell = "/etc/rc.initial";
523
	$user_group = "nobody";
524

    
525
	// Ensure $home_base exists and is writable
526
	if (!is_dir($home_base)) {
527
		mkdir($home_base, 0755);
528
	}
529

    
530
	$lock_account = false;
531
	/* configure shell type */
532
	/* Cases here should be ordered by most privileged to least privileged. */
533
	if (userHasPrivilege($user, "user-shell-access") || userHasPrivilege($user, "page-all")) {
534
		$user_shell = "/bin/tcsh";
535
	} elseif (userHasPrivilege($user, "user-copy-files")) {
536
		$user_shell = "/usr/local/bin/scponly";
537
	} elseif (userHasPrivilege($user, "user-ssh-tunnel")) {
538
		$user_shell = "/usr/local/sbin/ssh_tunnel_shell";
539
	} elseif (userHasPrivilege($user, "user-ipsec-xauth-dialin")) {
540
		$user_shell = "/sbin/nologin";
541
	} else {
542
		$user_shell = "/sbin/nologin";
543
		$lock_account = true;
544
	}
545

    
546
	/* Lock out disabled or expired users, unless it's root/admin. */
547
	if ((is_account_disabled($user_name) || is_account_expired($user_name)) && ($user_uid != 0)) {
548
		$user_shell = "/sbin/nologin";
549
		$lock_account = true;
550
	}
551

    
552
	/* root user special handling */
553
	if ($user_uid == 0) {
554
		$cmd = "/usr/sbin/pw usermod -q -n root -s /bin/sh -H 0";
555
		if ($debug) {
556
			log_error(sprintf(gettext("Running: %s"), $cmd));
557
		}
558
		$fd = popen($cmd, "w");
559
		if (empty($user['bcrypt-hash'])) {
560
			fwrite($fd, $user['password']);
561
		} else {
562
			fwrite($fd, $user['bcrypt-hash']);
563
		}
564
		pclose($fd);
565
		$user_group = "wheel";
566
		$user_home = "/root";
567
		$user_shell = "/etc/rc.initial";
568
	}
569

    
570
	/* read from pw db */
571
	$fd = popen("/usr/sbin/pw usershow -n {$user_name} 2>&1", "r");
572
	$pwread = fgets($fd);
573
	pclose($fd);
574
	$userattrs = explode(":", trim($pwread));
575

    
576
	/* determine add or mod */
577
	if (($userattrs[0] != $user['name']) || (!strncmp($pwread, "pw:", 3))) {
578
		$user_op = "useradd -m -k /etc/skel -o";
579
	} else {
580
		$user_op = "usermod";
581
	}
582

    
583
	$comment = str_replace(array(":", "!", "@"), " ", $user['descr']);
584
	/* add or mod pw db */
585
	$cmd = "/usr/sbin/pw {$user_op} -q " .
586
			" -u " . escapeshellarg($user_uid) .
587
			" -n " . escapeshellarg($user_name) .
588
			" -g " . escapeshellarg($user_group) .
589
			" -s " . escapeshellarg($user_shell) .
590
			" -d " . escapeshellarg($user_home) .
591
			" -c " . escapeshellarg($comment) .
592
			" -H 0 2>&1";
593

    
594
	if ($debug) {
595
		log_error(sprintf(gettext("Running: %s"), $cmd));
596
	}
597
	$fd = popen($cmd, "w");
598
	if (empty($user['bcrypt-hash'])) {
599
		fwrite($fd, $user['password']);
600
	} else {
601
		fwrite($fd, $user['bcrypt-hash']);
602
	}
603
	pclose($fd);
604

    
605
	/* create user directory if required */
606
	if (!is_dir($user_home)) {
607
		mkdir($user_home, 0700);
608
	}
609
	@chown($user_home, $user_name);
610
	@chgrp($user_home, $user_group);
611

    
612
	/* write out ssh authorized key file */
613
	if ($user['authorizedkeys']) {
614
		if (!is_dir("{$user_home}/.ssh")) {
615
			@mkdir("{$user_home}/.ssh", 0700);
616
			@chown("{$user_home}/.ssh", $user_name);
617
		}
618
		$keys = base64_decode($user['authorizedkeys']);
619
		@file_put_contents("{$user_home}/.ssh/authorized_keys", $keys);
620
		@chown("{$user_home}/.ssh/authorized_keys", $user_name);
621
	} else {
622
		unlink_if_exists("{$user_home}/.ssh/authorized_keys");
623
	}
624

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

    
628
	conf_mount_ro();
629
}
630

    
631
function local_user_del($user) {
632
	global $debug;
633

    
634
	/* remove all memberships */
635
	local_user_set_groups($user);
636

    
637
	/* Don't remove /root */
638
	if ($user['uid'] != 0) {
639
		$rmhome = "-r";
640
	}
641

    
642
	/* read from pw db */
643
	$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
644
	$pwread = fgets($fd);
645
	pclose($fd);
646
	$userattrs = explode(":", trim($pwread));
647

    
648
	if ($userattrs[0] != $user['name']) {
649
		log_error("Tried to remove user {$user['name']} but got user {$userattrs[0]} instead. Bailing.");
650
		return;
651
	}
652

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

    
656
	if ($debug) {
657
		log_error(sprintf(gettext("Running: %s"), $cmd));
658
	}
659
	mwexec($cmd);
660

    
661
	/* Delete user from groups needs a call to write_config() */
662
	local_group_del_user($user);
663
}
664

    
665
function local_user_set_password(&$user, $password) {
666

    
667
	unset($user['password']);
668
	unset($user['md5-hash']);
669
	$user['bcrypt-hash'] = password_hash($password, PASSWORD_BCRYPT);
670

    
671
	/* Maintain compatibility with FreeBSD - change $2y$ prefix to $2b$
672
	 * https://reviews.freebsd.org/D2742
673
	 * XXX: Can be removed as soon as r284483 is MFC'd.
674
	 */
675
	if ($user['bcrypt-hash'][2] == "y") {
676
		$user['bcrypt-hash'][2] = "b";
677
	}
678

    
679
	// Converts ascii to unicode.
680
	$astr = (string) $password;
681
	$ustr = '';
682
	for ($i = 0; $i < strlen($astr); $i++) {
683
		$a = ord($astr{$i}) << 8;
684
		$ustr .= sprintf("%X", $a);
685
	}
686

    
687
}
688

    
689
function local_user_get_groups($user, $all = false) {
690
	global $debug, $config;
691

    
692
	$groups = array();
693
	if (!is_array($config['system']['group'])) {
694
		return $groups;
695
	}
696

    
697
	foreach ($config['system']['group'] as $group) {
698
		if ($all || (!$all && ($group['name'] != "all"))) {
699
			if (is_array($group['member'])) {
700
				if (in_array($user['uid'], $group['member'])) {
701
					$groups[] = $group['name'];
702
				}
703
			}
704
		}
705
	}
706

    
707
	if ($all) {
708
		$groups[] = "all";
709
	}
710

    
711
	sort($groups);
712

    
713
	return $groups;
714

    
715
}
716

    
717
function local_user_set_groups($user, $new_groups = NULL) {
718
	global $debug, $config, $groupindex;
719

    
720
	if (!is_array($config['system']['group'])) {
721
		return;
722
	}
723

    
724
	$cur_groups = local_user_get_groups($user, true);
725
	$mod_groups = array();
726

    
727
	if (!is_array($new_groups)) {
728
		$new_groups = array();
729
	}
730

    
731
	if (!is_array($cur_groups)) {
732
		$cur_groups = array();
733
	}
734

    
735
	/* determine which memberships to add */
736
	foreach ($new_groups as $groupname) {
737
		if ($groupname == '' || in_array($groupname, $cur_groups)) {
738
			continue;
739
		}
740
		$group = & $config['system']['group'][$groupindex[$groupname]];
741
		$group['member'][] = $user['uid'];
742
		$mod_groups[] = $group;
743
	}
744
	unset($group);
745

    
746
	/* determine which memberships to remove */
747
	foreach ($cur_groups as $groupname) {
748
		if (in_array($groupname, $new_groups)) {
749
			continue;
750
		}
751
		if (!isset($config['system']['group'][$groupindex[$groupname]])) {
752
			continue;
753
		}
754
		$group = & $config['system']['group'][$groupindex[$groupname]];
755
		if (is_array($group['member'])) {
756
			$index = array_search($user['uid'], $group['member']);
757
			array_splice($group['member'], $index, 1);
758
			$mod_groups[] = $group;
759
		}
760
	}
761
	unset($group);
762

    
763
	/* sync all modified groups */
764
	foreach ($mod_groups as $group) {
765
		local_group_set($group);
766
	}
767
}
768

    
769
function local_group_del_user($user) {
770
	global $config;
771

    
772
	if (!is_array($config['system']['group'])) {
773
		return;
774
	}
775

    
776
	foreach ($config['system']['group'] as $group) {
777
		if (is_array($group['member'])) {
778
			foreach ($group['member'] as $idx => $uid) {
779
				if ($user['uid'] == $uid) {
780
					unset($config['system']['group']['member'][$idx]);
781
				}
782
			}
783
		}
784
	}
785
}
786

    
787
function local_group_set($group, $reset = false) {
788
	global $debug;
789

    
790
	$group_name = $group['name'];
791
	$group_gid = $group['gid'];
792
	$group_members = '';
793
	if (!$reset && !empty($group['member']) && count($group['member']) > 0) {
794
		$group_members = implode(",", $group['member']);
795
	}
796

    
797
	if (empty($group_name) || $group['scope'] == "remote") {
798
		return;
799
	}
800

    
801
	/* determine add or mod */
802
	if (mwexec("/usr/sbin/pw groupshow -g " . escapeshellarg($group_gid) . " 2>&1", true) == 0) {
803
		$group_op = "groupmod -l";
804
	} else {
805
		$group_op = "groupadd -n";
806
	}
807

    
808
	/* add or mod group db */
809
	$cmd = "/usr/sbin/pw {$group_op} " .
810
		escapeshellarg($group_name) .
811
		" -g " . escapeshellarg($group_gid) .
812
		" -M " . escapeshellarg($group_members) . " 2>&1";
813

    
814
	if ($debug) {
815
		log_error(sprintf(gettext("Running: %s"), $cmd));
816
	}
817
	mwexec($cmd);
818

    
819
}
820

    
821
function local_group_del($group) {
822
	global $debug;
823

    
824
	/* delete from group db */
825
	$cmd = "/usr/sbin/pw groupdel " . escapeshellarg($group['name']);
826

    
827
	if ($debug) {
828
		log_error(sprintf(gettext("Running: %s"), $cmd));
829
	}
830
	mwexec($cmd);
831
}
832

    
833
function ldap_test_connection($authcfg) {
834
	global $debug, $config, $g;
835

    
836
	if ($authcfg) {
837
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
838
			$ldapproto = "ldaps";
839
		} else {
840
			$ldapproto = "ldap";
841
		}
842
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
843
		$ldapport = $authcfg['ldap_port'];
844
		if (!empty($ldapport)) {
845
			$ldapserver .= ":{$ldapport}";
846
		}
847
		$ldapbasedn = $authcfg['ldap_basedn'];
848
		$ldapbindun = $authcfg['ldap_binddn'];
849
		$ldapbindpw = $authcfg['ldap_bindpw'];
850
	} else {
851
		return false;
852
	}
853

    
854
	/* first check if there is even an LDAP server populated */
855
	if (!$ldapserver) {
856
		return false;
857
	}
858

    
859
	/* Setup CA environment if needed. */
860
	ldap_setup_caenv($authcfg);
861

    
862
	/* connect and see if server is up */
863
	$error = false;
864
	if (!($ldap = ldap_connect($ldapserver))) {
865
		$error = true;
866
	}
867

    
868
	if ($error == true) {
869
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
870
		return false;
871
	}
872

    
873
	return true;
874
}
875

    
876
function ldap_setup_caenv($authcfg) {
877
	global $g;
878
	require_once("certs.inc");
879

    
880
	unset($caref);
881
	if (empty($authcfg['ldap_caref']) || strstr($authcfg['ldap_urltype'], "Standard")) {
882
		putenv('LDAPTLS_REQCERT=never');
883
		return;
884
	} else {
885
		$caref = lookup_ca($authcfg['ldap_caref']);
886
		if (!$caref) {
887
			log_error(sprintf(gettext("LDAP: Could not lookup CA by reference for host %s."), $authcfg['ldap_caref']));
888
			/* XXX: Prevent for credential leaking since we cannot setup the CA env. Better way? */
889
			putenv('LDAPTLS_REQCERT=hard');
890
			return;
891
		}
892
		if (!is_dir("{$g['varrun_path']}/certs")) {
893
			@mkdir("{$g['varrun_path']}/certs");
894
		}
895
		if (file_exists("{$g['varrun_path']}/certs/{$caref['refid']}.ca")) {
896
			@unlink("{$g['varrun_path']}/certs/{$caref['refid']}.ca");
897
		}
898
		file_put_contents("{$g['varrun_path']}/certs/{$caref['refid']}.ca", base64_decode($caref['crt']));
899
		@chmod("{$g['varrun_path']}/certs/{$caref['refid']}.ca", 0600);
900
		putenv('LDAPTLS_REQCERT=hard');
901
		/* XXX: Probably even the hashed link should be created for this? */
902
		putenv("LDAPTLS_CACERTDIR={$g['varrun_path']}/certs");
903
		putenv("LDAPTLS_CACERT={$g['varrun_path']}/certs/{$caref['refid']}.ca");
904
	}
905
}
906

    
907
function ldap_test_bind($authcfg) {
908
	global $debug, $config, $g;
909

    
910
	if ($authcfg) {
911
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
912
			$ldapproto = "ldaps";
913
		} else {
914
			$ldapproto = "ldap";
915
		}
916
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
917
		$ldapport = $authcfg['ldap_port'];
918
		if (!empty($ldapport)) {
919
			$ldapserver .= ":{$ldapport}";
920
		}
921
		$ldapbasedn = $authcfg['ldap_basedn'];
922
		$ldapbindun = $authcfg['ldap_binddn'];
923
		$ldapbindpw = $authcfg['ldap_bindpw'];
924
		$ldapver = $authcfg['ldap_protver'];
925
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
926
		if (empty($ldapbndun) || empty($ldapbindpw)) {
927
			$ldapanon = true;
928
		} else {
929
			$ldapanon = false;
930
		}
931
	} else {
932
		return false;
933
	}
934

    
935
	/* first check if there is even an LDAP server populated */
936
	if (!$ldapserver) {
937
		return false;
938
	}
939

    
940
	/* Setup CA environment if needed. */
941
	ldap_setup_caenv($authcfg);
942

    
943
	/* connect and see if server is up */
944
	$error = false;
945
	if (!($ldap = ldap_connect($ldapserver))) {
946
		$error = true;
947
	}
948

    
949
	if ($error == true) {
950
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
951
		return false;
952
	}
953

    
954
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
955
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
956
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
957
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
958
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
959

    
960
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
961
		if (!(ldap_start_tls($ldap))) {
962
			log_error(sprintf(gettext("ERROR! ldap_test_bind() could not STARTTLS to server %s."), $ldapname));
963
			@ldap_close($ldap);
964
			return false;
965
		}
966
	}
967

    
968
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
969
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
970
	if ($ldapanon == true) {
971
		if (!($res = @ldap_bind($ldap))) {
972
			@ldap_close($ldap);
973
			return false;
974
		}
975
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
976
		@ldap_close($ldap);
977
		return false;
978
	}
979

    
980
	@ldap_unbind($ldap);
981

    
982
	return true;
983
}
984

    
985
function ldap_get_user_ous($show_complete_ou=true, $authcfg) {
986
	global $debug, $config, $g;
987

    
988
	if (!function_exists("ldap_connect")) {
989
		return;
990
	}
991

    
992
	$ous = array();
993

    
994
	if ($authcfg) {
995
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
996
			$ldapproto = "ldaps";
997
		} else {
998
			$ldapproto = "ldap";
999
		}
1000
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1001
		$ldapport = $authcfg['ldap_port'];
1002
		if (!empty($ldapport)) {
1003
			$ldapserver .= ":{$ldapport}";
1004
		}
1005
		$ldapbasedn = $authcfg['ldap_basedn'];
1006
		$ldapbindun = $authcfg['ldap_binddn'];
1007
		$ldapbindpw = $authcfg['ldap_bindpw'];
1008
		$ldapver = $authcfg['ldap_protver'];
1009
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1010
			$ldapanon = true;
1011
		} else {
1012
			$ldapanon = false;
1013
		}
1014
		$ldapname = $authcfg['name'];
1015
		$ldapfallback = false;
1016
		$ldapscope = $authcfg['ldap_scope'];
1017
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1018
	} else {
1019
		return false;
1020
	}
1021

    
1022
	/* first check if there is even an LDAP server populated */
1023
	if (!$ldapserver) {
1024
		log_error(gettext("ERROR!  ldap_get_user_ous() backed selected with no LDAP authentication server defined."));
1025
		return $ous;
1026
	}
1027

    
1028
	/* Setup CA environment if needed. */
1029
	ldap_setup_caenv($authcfg);
1030

    
1031
	/* connect and see if server is up */
1032
	$error = false;
1033
	if (!($ldap = ldap_connect($ldapserver))) {
1034
		$error = true;
1035
	}
1036

    
1037
	if ($error == true) {
1038
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1039
		return $ous;
1040
	}
1041

    
1042
	$ldapfilter = "(|(ou=*)(cn=Users))";
1043

    
1044
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1045
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1046
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1047
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1048
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1049

    
1050
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1051
		if (!(ldap_start_tls($ldap))) {
1052
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not STARTTLS to server %s."), $ldapname));
1053
			@ldap_close($ldap);
1054
			return false;
1055
		}
1056
	}
1057

    
1058
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1059
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1060
	if ($ldapanon == true) {
1061
		if (!($res = @ldap_bind($ldap))) {
1062
			log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind anonymously to server %s."), $ldapname));
1063
			@ldap_close($ldap);
1064
			return $ous;
1065
		}
1066
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1067
		log_error(sprintf(gettext("ERROR! ldap_get_user_ous() could not bind to server %s."), $ldapname));
1068
		@ldap_close($ldap);
1069
		return $ous;
1070
	}
1071

    
1072
	if ($ldapscope == "one") {
1073
		$ldapfunc = "ldap_list";
1074
	} else {
1075
		$ldapfunc = "ldap_search";
1076
	}
1077

    
1078
	$search = @$ldapfunc($ldap, $ldapbasedn, $ldapfilter);
1079
	$info = @ldap_get_entries($ldap, $search);
1080

    
1081
	if (is_array($info)) {
1082
		foreach ($info as $inf) {
1083
			if (!$show_complete_ou) {
1084
				$inf_split = explode(",", $inf['dn']);
1085
				$ou = $inf_split[0];
1086
				$ou = str_replace("OU=", "", $ou);
1087
				$ou = str_replace("CN=", "", $ou);
1088
			} else {
1089
				if ($inf['dn']) {
1090
					$ou = $inf['dn'];
1091
				}
1092
			}
1093
			if ($ou) {
1094
				$ous[] = $ou;
1095
			}
1096
		}
1097
	}
1098

    
1099
	@ldap_unbind($ldap);
1100

    
1101
	return $ous;
1102
}
1103

    
1104
function ldap_get_groups($username, $authcfg) {
1105
	global $debug, $config;
1106

    
1107
	if (!function_exists("ldap_connect")) {
1108
		return;
1109
	}
1110

    
1111
	if (!$username) {
1112
		return false;
1113
	}
1114

    
1115
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1116
		$username_split = explode("@", $username);
1117
		$username = $username_split[0];
1118
	}
1119

    
1120
	if (stristr($username, "\\")) {
1121
		$username_split = explode("\\", $username);
1122
		$username = $username_split[0];
1123
	}
1124

    
1125
	//log_error("Getting LDAP groups for {$username}.");
1126
	if ($authcfg) {
1127
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
1128
			$ldapproto = "ldaps";
1129
		} else {
1130
			$ldapproto = "ldap";
1131
		}
1132
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1133
		$ldapport = $authcfg['ldap_port'];
1134
		if (!empty($ldapport)) {
1135
			$ldapserver .= ":{$ldapport}";
1136
		}
1137
		$ldapbasedn = $authcfg['ldap_basedn'];
1138
		$ldapbindun = $authcfg['ldap_binddn'];
1139
		$ldapbindpw = $authcfg['ldap_bindpw'];
1140
		$ldapauthcont = $authcfg['ldap_authcn'];
1141
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1142
		$ldapgroupattribute = strtolower($authcfg['ldap_attr_member']);
1143
		if (isset($authcfg['ldap_rfc2307'])) {
1144
			$ldapfilter         = "(&(objectClass={$authcfg['ldap_attr_groupobj']})({$ldapgroupattribute}={$username}))";
1145
		} else {
1146
			$ldapfilter         = "({$ldapnameattribute}={$username})";
1147
		}
1148
		$ldaptype = "";
1149
		$ldapver = $authcfg['ldap_protver'];
1150
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1151
			$ldapanon = true;
1152
		} else {
1153
			$ldapanon = false;
1154
		}
1155
		$ldapname = $authcfg['name'];
1156
		$ldapfallback = false;
1157
		$ldapscope = $authcfg['ldap_scope'];
1158
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1159
	} else {
1160
		return false;
1161
	}
1162

    
1163
	if (isset($authcfg['ldap_rfc2307'])) {
1164
		$ldapdn = $ldapbasedn;
1165
	} else {
1166
		$ldapdn = $_SESSION['ldapdn'];
1167
	}
1168

    
1169
	/*Convert attribute to lowercase.  php ldap arrays put everything in lowercase */
1170
	$ldapgroupattribute = strtolower($ldapgroupattribute);
1171
	$memberof = array();
1172

    
1173
	/* Setup CA environment if needed. */
1174
	ldap_setup_caenv($authcfg);
1175

    
1176
	/* connect and see if server is up */
1177
	$error = false;
1178
	if (!($ldap = ldap_connect($ldapserver))) {
1179
		$error = true;
1180
	}
1181

    
1182
	if ($error == true) {
1183
		log_error(sprintf(gettext("ERROR! ldap_get_groups() Could not connect to server %s."), $ldapname));
1184
		return $memberof;
1185
	}
1186

    
1187
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1188
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1189
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1190
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1191
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1192

    
1193
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1194
		if (!(ldap_start_tls($ldap))) {
1195
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not STARTTLS to server %s."), $ldapname));
1196
			@ldap_close($ldap);
1197
			return false;
1198
		}
1199
	}
1200

    
1201
	/* bind as user that has rights to read group attributes */
1202
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1203
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1204
	if ($ldapanon == true) {
1205
		if (!($res = @ldap_bind($ldap))) {
1206
			log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind anonymously to server %s."), $ldapname));
1207
			@ldap_close($ldap);
1208
			return false;
1209
		}
1210
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1211
		log_error(sprintf(gettext("ERROR! ldap_get_groups() could not bind to server %s."), $ldapname));
1212
		@ldap_close($ldap);
1213
		return $memberof;
1214
	}
1215

    
1216
	/* get groups from DN found */
1217
	/* use ldap_read instead of search so we don't have to do a bunch of extra work */
1218
	/* since we know the DN is in $_SESSION['ldapdn'] */
1219
	//$search    = ldap_read($ldap, $ldapdn, "(objectclass=*)", array($ldapgroupattribute));
1220
	if ($ldapscope == "one") {
1221
		$ldapfunc = "ldap_list";
1222
	} else {
1223
		$ldapfunc = "ldap_search";
1224
	}
1225

    
1226
	$search = @$ldapfunc($ldap, $ldapdn, $ldapfilter, array($ldapgroupattribute));
1227
	$info = @ldap_get_entries($ldap, $search);
1228

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

    
1231
	if (is_array($gresults)) {
1232
		/* Iterate through the groups and throw them into an array */
1233
		foreach ($gresults as $grp) {
1234
			if (((isset($authcfg['ldap_rfc2307'])) && (stristr($grp["dn"], "CN=") !== false)) ||
1235
			    ((!isset($authcfg['ldap_rfc2307'])) && (stristr($grp, "CN=") !== false))) {
1236
				$grpsplit = isset($authcfg['ldap_rfc2307']) ? explode(",", $grp["dn"]) : explode(",", $grp);
1237
				$memberof[] = preg_replace("/CN=/i", "", $grpsplit[0]);
1238
			}
1239
		}
1240
	}
1241

    
1242
	/* Time to close LDAP connection */
1243
	@ldap_unbind($ldap);
1244

    
1245
	$groups = print_r($memberof, true);
1246

    
1247
	//log_error("Returning groups ".$groups." for user $username");
1248

    
1249
	return $memberof;
1250
}
1251

    
1252
function ldap_format_host($host) {
1253
	return is_ipaddrv6($host) ? "[$host]" : $host ;
1254
}
1255

    
1256
function ldap_backed($username, $passwd, $authcfg) {
1257
	global $debug, $config;
1258

    
1259
	if (!$username) {
1260
		return;
1261
	}
1262

    
1263
	if (!function_exists("ldap_connect")) {
1264
		return;
1265
	}
1266

    
1267
	if (!isset($authcfg['ldap_nostrip_at']) && stristr($username, "@")) {
1268
		$username_split = explode("@", $username);
1269
		$username = $username_split[0];
1270
	}
1271
	if (stristr($username, "\\")) {
1272
		$username_split = explode("\\", $username);
1273
		$username = $username_split[0];
1274
	}
1275

    
1276
	if ($authcfg) {
1277
		if (strstr($authcfg['ldap_urltype'], "SSL")) {
1278
			$ldapproto = "ldaps";
1279
		} else {
1280
			$ldapproto = "ldap";
1281
		}
1282
		$ldapserver = "{$ldapproto}://" . ldap_format_host($authcfg['host']);
1283
		$ldapport = $authcfg['ldap_port'];
1284
		if (!empty($ldapport)) {
1285
			$ldapserver .= ":{$ldapport}";
1286
		}
1287
		$ldapbasedn = $authcfg['ldap_basedn'];
1288
		$ldapbindun = $authcfg['ldap_binddn'];
1289
		$ldapbindpw = $authcfg['ldap_bindpw'];
1290
		if (empty($ldapbindun) || empty($ldapbindpw)) {
1291
			$ldapanon = true;
1292
		} else {
1293
			$ldapanon = false;
1294
		}
1295
		$ldapauthcont = $authcfg['ldap_authcn'];
1296
		$ldapnameattribute = strtolower($authcfg['ldap_attr_user']);
1297
		$ldapextendedqueryenabled = $authcfg['ldap_extended_enabled'];
1298
		$ldapextendedquery = $authcfg['ldap_extended_query'];
1299
		$ldapfilter = "";
1300
		if (!$ldapextendedqueryenabled) {
1301
			$ldapfilter = "({$ldapnameattribute}={$username})";
1302
		} else {
1303
			$ldapfilter = "(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
1304
		}
1305
		$ldaptype = "";
1306
		$ldapver = $authcfg['ldap_protver'];
1307
		$ldapname = $authcfg['name'];
1308
		$ldapscope = $authcfg['ldap_scope'];
1309
		$ldaptimeout = is_numeric($authcfg['ldap_timeout']) ? $authcfg['ldap_timeout'] : 5;
1310
	} else {
1311
		return false;
1312
	}
1313

    
1314
	/* first check if there is even an LDAP server populated */
1315
	if (!$ldapserver) {
1316
		if ($ldapfallback) {
1317
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined.  Defaulting to local user database. Visit System -> User Manager."));
1318
			return local_backed($username, $passwd);
1319
		} else {
1320
			log_error(gettext("ERROR! ldap_backed() called with no LDAP authentication server defined."));
1321
		}
1322

    
1323
		return false;
1324
	}
1325

    
1326
	/* Setup CA environment if needed. */
1327
	ldap_setup_caenv($authcfg);
1328

    
1329
	/* Make sure we can connect to LDAP */
1330
	$error = false;
1331
	if (!($ldap = ldap_connect($ldapserver))) {
1332
		$error = true;
1333
	}
1334

    
1335
	ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
1336
	ldap_set_option($ldap, LDAP_OPT_DEREF, LDAP_DEREF_SEARCHING);
1337
	ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$ldapver);
1338
	ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, (int)$ldaptimeout);
1339
	ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, (int)$ldaptimeout);
1340

    
1341
	if (strstr($authcfg['ldap_urltype'], "STARTTLS")) {
1342
		if (!(ldap_start_tls($ldap))) {
1343
			log_error(sprintf(gettext("ERROR! ldap_backed() could not STARTTLS to server %s."), $ldapname));
1344
			@ldap_close($ldap);
1345
			return false;
1346
		}
1347
	}
1348

    
1349
	if ($error == true) {
1350
		log_error(sprintf(gettext("ERROR!  Could not connect to server %s."), $ldapname));
1351
		return false;
1352
	}
1353

    
1354
	/* ok, its up.  now, lets bind as the bind user so we can search it */
1355
	$error = false;
1356
	$ldapbindun = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindun) : $ldapbindun;
1357
	$ldapbindpw = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapbindpw) : $ldapbindpw;
1358
	if ($ldapanon == true) {
1359
		if (!($res = @ldap_bind($ldap))) {
1360
			$error = true;
1361
		}
1362
	} else if (!($res = @ldap_bind($ldap, $ldapbindun, $ldapbindpw))) {
1363
		$error = true;
1364
	}
1365

    
1366
	if ($error == true) {
1367
		@ldap_close($ldap);
1368
		log_error(sprintf(gettext("ERROR! Could not bind to server %s."), $ldapname));
1369
		return false;
1370
	}
1371

    
1372
	/* Get LDAP Authcontainers and split em up. */
1373
	$ldac_splits = explode(";", $ldapauthcont);
1374

    
1375
	/* setup the usercount so we think we haven't found anyone yet */
1376
	$usercount = 0;
1377

    
1378
	/*****************************************************************/
1379
	/*  We first find the user based on username and filter          */
1380
	/*  then, once we find the first occurrence of that person       */
1381
	/*  we set session variables to point to the OU and DN of the    */
1382
	/*  person.  To later be used by ldap_get_groups.                */
1383
	/*  that way we don't have to search twice.                      */
1384
	/*****************************************************************/
1385
	if ($debug) {
1386
		log_auth(sprintf(gettext("Now Searching for %s in directory."), $username));
1387
	}
1388
	/* Iterate through the user containers for search */
1389
	foreach ($ldac_splits as $i => $ldac_split) {
1390
		$ldac_split = isset($authcfg['ldap_utf8']) ? utf8_encode($ldac_split) : $ldac_split;
1391
		$ldapfilter = isset($authcfg['ldap_utf8']) ? utf8_encode($ldapfilter) : $ldapfilter;
1392
		$ldapsearchbasedn = isset($authcfg['ldap_utf8']) ? utf8_encode("{$ldac_split},{$ldapbasedn}") : "{$ldac_split},{$ldapbasedn}";
1393
		/* Make sure we just use the first user we find */
1394
		if ($debug) {
1395
			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)));
1396
		}
1397
		if ($ldapscope == "one") {
1398
			$ldapfunc = "ldap_list";
1399
		} else {
1400
			$ldapfunc = "ldap_search";
1401
		}
1402
		/* Support legacy auth container specification. */
1403
		if (stristr($ldac_split, "DC=") || empty($ldapbasedn)) {
1404
			$search = @$ldapfunc($ldap, $ldac_split, $ldapfilter);
1405
		} else {
1406
			$search = @$ldapfunc($ldap, $ldapsearchbasedn, $ldapfilter);
1407
		}
1408
		if (!$search) {
1409
			log_error(sprintf(gettext("Search resulted in error: %s"), ldap_error($ldap)));
1410
			continue;
1411
		}
1412
		$info = ldap_get_entries($ldap, $search);
1413
		$matches = $info['count'];
1414
		if ($matches == 1) {
1415
			$userdn = $_SESSION['ldapdn'] = $info[0]['dn'];
1416
			$_SESSION['ldapou'] = $ldac_split[$i];
1417
			$_SESSION['ldapon'] = "true";
1418
			$usercount = 1;
1419
			break;
1420
		}
1421
	}
1422

    
1423
	if ($usercount != 1) {
1424
		@ldap_unbind($ldap);
1425
		log_error(gettext("ERROR! Either LDAP search failed, or multiple users were found."));
1426
		return false;
1427
	}
1428

    
1429
	/* Now lets bind as the user we found */
1430
	$passwd = isset($authcfg['ldap_utf8']) ? utf8_encode($passwd) : $passwd;
1431
	if (!($res = @ldap_bind($ldap, $userdn, $passwd))) {
1432
		log_error(sprintf(gettext('ERROR! Could not login to server %1$s as user %2$s: %3$s'), $ldapname, $username, ldap_error($ldap)));
1433
		@ldap_unbind($ldap);
1434
		return false;
1435
	}
1436

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

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

    
1445
	return true;
1446
}
1447

    
1448
function radius_backed($username, $passwd, $authcfg, &$attributes = array()) {
1449
	global $debug, $config;
1450
	$ret = false;
1451

    
1452
	require_once("radius.inc");
1453

    
1454
	$rauth = new Auth_RADIUS_PAP($username, $passwd);
1455
	if ($authcfg) {
1456
		$radiusservers = array();
1457
		$radiusservers[0]['ipaddr'] = $authcfg['host'];
1458
		$radiusservers[0]['port'] = $authcfg['radius_auth_port'];
1459
		$radiusservers[0]['sharedsecret'] = $authcfg['radius_secret'];
1460
		$radiusservers[0]['timeout'] = $authcfg['radius_timeout'];
1461
	} else {
1462
		return false;
1463
	}
1464

    
1465
	/* Add new servers to our instance */
1466
	foreach ($radiusservers as $radsrv) {
1467
		$timeout = (is_numeric($radsrv['timeout'])) ? $radsrv['timeout'] : 5;
1468
		$rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret'], $timeout);
1469
	}
1470

    
1471
	if (PEAR::isError($rauth->start())) {
1472
		$retvalue['auth_val'] = 1;
1473
		$retvalue['error'] = $rauth->getError();
1474
		if ($debug) {
1475
			printf(gettext("RADIUS start: %s<br />\n"), $retvalue['error']);
1476
		}
1477
	}
1478

    
1479
	// XXX - billm - somewhere in here we need to handle securid challenge/response
1480

    
1481
	/* Send request */
1482
	$result = $rauth->send();
1483
	if (PEAR::isError($result)) {
1484
		$retvalue['auth_val'] = 1;
1485
		$retvalue['error'] = $result->getMessage();
1486
		if ($debug) {
1487
			printf(gettext("RADIUS send failed: %s<br />\n"), $retvalue['error']);
1488
		}
1489
	} else if ($result === true) {
1490
		if ($rauth->getAttributes()) {
1491
			$attributes = $rauth->listAttributes();
1492
		}
1493
		$retvalue['auth_val'] = 2;
1494
		if ($debug) {
1495
			printf(gettext("RADIUS Auth succeeded")."<br />\n");
1496
		}
1497
		$ret = true;
1498
	} else {
1499
		$retvalue['auth_val'] = 3;
1500
		if ($debug) {
1501
			printf(gettext("RADIUS Auth rejected")."<br />\n");
1502
		}
1503
	}
1504

    
1505
	// close OO RADIUS_AUTHENTICATION
1506
	$rauth->close();
1507

    
1508
	return $ret;
1509
}
1510

    
1511
/*
1512
	$attributes must contain a "class" key containing the groups and local
1513
	groups must exist to match.
1514
*/
1515
function radius_get_groups($attributes) {
1516
	$groups = array();
1517
	if (!empty($attributes) && is_array($attributes) && (!empty($attributes['class']) || !empty($attributes['class_int']))) {
1518
		/* Some RADIUS servers return multiple class attributes, so check them all. */
1519
		$groups = array();
1520
		if (!empty($attributes['class']) && is_array($attributes['class'])) {
1521
			foreach ($attributes['class'] as $class) {
1522
				$groups = array_unique(array_merge($groups, explode(";", $class)));
1523
			}
1524
		}
1525

    
1526
		foreach ($groups as & $grp) {
1527
			$grp = trim($grp);
1528
			if (strtolower(substr($grp, 0, 3)) == "ou=") {
1529
				$grp = substr($grp, 3);
1530
			}
1531
		}
1532
	}
1533
	return $groups;
1534
}
1535

    
1536
function get_user_expiration_date($username) {
1537
	$user = getUserEntry($username);
1538
	if ($user['expires']) {
1539
		return $user['expires'];
1540
	}
1541
}
1542

    
1543
function is_account_expired($username) {
1544
	$expirydate = get_user_expiration_date($username);
1545
	if ($expirydate) {
1546
		if (strtotime("-1 day") > strtotime(date("m/d/Y", strtotime($expirydate)))) {
1547
			return true;
1548
		}
1549
	}
1550

    
1551
	return false;
1552
}
1553

    
1554
function is_account_disabled($username) {
1555
	$user = getUserEntry($username);
1556
	if (isset($user['disabled'])) {
1557
		return true;
1558
	}
1559

    
1560
	return false;
1561
}
1562

    
1563
function get_user_settings($username) {
1564
	global $config;
1565
	$settings = array();
1566
	$settings['widgets'] = $config['widgets'];
1567
	$settings['webgui']['dashboardcolumns'] = $config['system']['webgui']['dashboardcolumns'];
1568
	$settings['webgui']['webguihostnamemenu'] = $config['system']['webgui']['webguihostnamemenu'];
1569
	$settings['webgui']['webguicss'] = $config['system']['webgui']['webguicss'];
1570
	$settings['webgui']['interfacessort'] = isset($config['system']['webgui']['interfacessort']);
1571
	$settings['webgui']['dashboardavailablewidgetspanel'] = isset($config['system']['webgui']['dashboardavailablewidgetspanel']);
1572
	$settings['webgui']['webguifixedmenu'] = isset($config['system']['webgui']['webguifixedmenu']);
1573
	$settings['webgui']['webguileftcolumnhyper'] = isset($config['system']['webgui']['webguileftcolumnhyper']);
1574
	$settings['webgui']['systemlogsfilterpanel'] = isset($config['system']['webgui']['systemlogsfilterpanel']);
1575
	$settings['webgui']['systemlogsmanagelogpanel'] = isset($config['system']['webgui']['systemlogsmanagelogpanel']);
1576
	$settings['webgui']['statusmonitoringsettingspanel'] = isset($config['system']['webgui']['statusmonitoringsettingspanel']);
1577
	$settings['webgui']['pagenamefirst'] = isset($config['system']['webgui']['pagenamefirst']);
1578
	$user = getUserEntry($username);
1579
	if (isset($user['customsettings'])) {
1580
		$settings['customsettings'] = true;
1581
		if (isset($user['widgets'])) {
1582
			// This includes the 'sequence', and any widgetname-config per-widget settings.
1583
			$settings['widgets'] = $user['widgets'];
1584
		}
1585
		if (isset($user['dashboardcolumns'])) {
1586
			$settings['webgui']['dashboardcolumns'] = $user['dashboardcolumns'];
1587
		}
1588
		if (isset($user['webguicss'])) {
1589
			$settings['webgui']['webguicss'] = $user['webguicss'];
1590
		}
1591
		if (isset($user['webguihostnamemenu'])) {
1592
			$settings['webgui']['webguihostnamemenu'] = $user['webguihostnamemenu'];
1593
		}
1594
		$settings['webgui']['interfacessort'] = isset($user['interfacessort']);
1595
		$settings['webgui']['dashboardavailablewidgetspanel'] = isset($user['dashboardavailablewidgetspanel']);
1596
		$settings['webgui']['webguifixedmenu'] = isset($user['webguifixedmenu']);
1597
		$settings['webgui']['webguileftcolumnhyper'] = isset($user['webguileftcolumnhyper']);
1598
		$settings['webgui']['systemlogsfilterpanel'] = isset($user['systemlogsfilterpanel']);
1599
		$settings['webgui']['systemlogsmanagelogpanel'] = isset($user['systemlogsmanagelogpanel']);
1600
		$settings['webgui']['statusmonitoringsettingspanel'] = isset($user['statusmonitoringsettingspanel']);
1601
		$settings['webgui']['pagenamefirst'] = isset($user['pagenamefirst']);
1602
	} else {
1603
		$settings['customsettings'] = false;
1604
	}
1605

    
1606
	if ($settings['webgui']['dashboardcolumns'] < 1) {
1607
		$settings['webgui']['dashboardcolumns'] = 2;
1608
	}
1609

    
1610
	return $settings;
1611
}
1612

    
1613
function save_widget_settings($username, $settings, $message = "") {
1614
	global $config, $userindex;
1615
	$user = getUserEntry($username);
1616

    
1617
	if (strlen($message) > 0) {
1618
		$msgout = $message;
1619
	} else {
1620
		$msgout = gettext("Widget configuration has been changed.");
1621
	}
1622

    
1623
	if (isset($user['customsettings'])) {
1624
		$config['system']['user'][$userindex[$username]]['widgets'] = $settings;
1625
		write_config($msgout . " " . sprintf(gettext("(User %s)"), $username));
1626
	} else {
1627
		$config['widgets'] = $settings;
1628
		write_config($msgout);
1629
	}
1630
}
1631

    
1632
function auth_get_authserver($name) {
1633
	global $config;
1634

    
1635
	if (is_array($config['system']['authserver'])) {
1636
		foreach ($config['system']['authserver'] as $authcfg) {
1637
			if ($authcfg['name'] == $name) {
1638
				return $authcfg;
1639
			}
1640
		}
1641
	}
1642
	if ($name == "Local Database") {
1643
		return array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1644
	}
1645
}
1646

    
1647
function auth_get_authserver_list() {
1648
	global $config;
1649

    
1650
	$list = array();
1651

    
1652
	if (is_array($config['system']['authserver'])) {
1653
		foreach ($config['system']['authserver'] as $authcfg) {
1654
			/* Add support for disabled entries? */
1655
			$list[$authcfg['name']] = $authcfg;
1656
		}
1657
	}
1658

    
1659
	$list["Local Database"] = array("name" => gettext("Local Database"), "type" => "Local Auth", "host" => $config['system']['hostname']);
1660
	return $list;
1661
}
1662

    
1663
function getUserGroups($username, $authcfg, &$attributes = array()) {
1664
	global $config;
1665

    
1666
	$allowed_groups = array();
1667

    
1668
	switch ($authcfg['type']) {
1669
		case 'ldap':
1670
			$allowed_groups = @ldap_get_groups($username, $authcfg);
1671
			break;
1672
		case 'radius':
1673
			$allowed_groups = @radius_get_groups($attributes);
1674
			break;
1675
		default:
1676
			$user = getUserEntry($username);
1677
			$allowed_groups = @local_user_get_groups($user, true);
1678
			break;
1679
	}
1680

    
1681
	$member_groups = array();
1682
	if (is_array($config['system']['group'])) {
1683
		foreach ($config['system']['group'] as $group) {
1684
			if (in_array($group['name'], $allowed_groups)) {
1685
				$member_groups[] = $group['name'];
1686
			}
1687
		}
1688
	}
1689

    
1690
	return $member_groups;
1691
}
1692

    
1693
function authenticate_user($username, $password, $authcfg = NULL, &$attributes = array()) {
1694

    
1695
	if (is_array($username) || is_array($password)) {
1696
		return false;
1697
	}
1698

    
1699
	if (!$authcfg) {
1700
		return local_backed($username, $password);
1701
	}
1702

    
1703
	$authenticated = false;
1704
	switch ($authcfg['type']) {
1705
		case 'ldap':
1706
			if (ldap_backed($username, $password, $authcfg)) {
1707
				$authenticated = true;
1708
			}
1709
			break;
1710
		case 'radius':
1711
			if (radius_backed($username, $password, $authcfg, $attributes)) {
1712
				$authenticated = true;
1713
			}
1714
			break;
1715
		default:
1716
			/* lookup user object by name */
1717
			if (local_backed($username, $password)) {
1718
				$authenticated = true;
1719
			}
1720
			break;
1721
		}
1722

    
1723
	return $authenticated;
1724
}
1725

    
1726
function session_auth() {
1727
	global $config, $_SESSION, $page;
1728

    
1729
	// Handle HTTPS httponly and secure flags
1730
	$currentCookieParams = session_get_cookie_params();
1731
	session_set_cookie_params(
1732
		$currentCookieParams["lifetime"],
1733
		$currentCookieParams["path"],
1734
		NULL,
1735
		($config['system']['webgui']['protocol'] == "https"),
1736
		true
1737
	);
1738

    
1739
	if (!session_id()) {
1740
		session_start();
1741
	}
1742

    
1743
	// Detect protocol change
1744
	if (!isset($_POST['login']) && !empty($_SESSION['Logged_In']) && $_SESSION['protocol'] != $config['system']['webgui']['protocol']) {
1745
		return false;
1746
	}
1747

    
1748
	/* Validate incoming login request */
1749
	$attributes = array();
1750
	if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) {
1751
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
1752
		$remoteauth = authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg, $attributes);
1753
		if ($remoteauth || authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) {
1754
			// Generate a new id to avoid session fixation
1755
			session_regenerate_id();
1756
			$_SESSION['Logged_In'] = "True";
1757
			$_SESSION['remoteauth'] = $remoteauth;
1758
			$_SESSION['Username'] = $_POST['usernamefld'];
1759
			$_SESSION['user_radius_attributes'] = $attributes;
1760
			$_SESSION['last_access'] = time();
1761
			$_SESSION['protocol'] = $config['system']['webgui']['protocol'];
1762
			if (!isset($config['system']['webgui']['quietlogin'])) {
1763
				log_auth(sprintf(gettext("Successful login for user '%1\$s' from: %2\$s"), $_POST['usernamefld'], $_SERVER['REMOTE_ADDR']));
1764
			}
1765
			if (isset($_POST['postafterlogin'])) {
1766
				return true;
1767
			} else {
1768
				if (empty($page)) {
1769
					$page = "/";
1770
				}
1771
				header("Location: {$page}");
1772
			}
1773
			exit;
1774
		} else {
1775
			/* give the user an error message */
1776
			$_SESSION['Login_Error'] = "Username or Password incorrect";
1777
			log_auth("webConfigurator authentication error for '{$_POST['usernamefld']}' from {$_SERVER['REMOTE_ADDR']}");
1778
			if (isAjax()) {
1779
				echo "showajaxmessage('{$_SESSION['Login_Error']}');";
1780
				return;
1781
			}
1782
		}
1783
	}
1784

    
1785
	/* Show login page if they aren't logged in */
1786
	if (empty($_SESSION['Logged_In'])) {
1787
		return false;
1788
	}
1789

    
1790
	/* If session timeout isn't set, we don't mark sessions stale */
1791
	if (!isset($config['system']['webgui']['session_timeout'])) {
1792
		/* Default to 4 hour timeout if one is not set */
1793
		if ($_SESSION['last_access'] < (time() - 14400)) {
1794
			$_GET['logout'] = true;
1795
			$_SESSION['Logout'] = true;
1796
		} else {
1797
			$_SESSION['last_access'] = time();
1798
		}
1799
	} else if (intval($config['system']['webgui']['session_timeout']) == 0) {
1800
		/* only update if it wasn't ajax */
1801
		if (!isAjax()) {
1802
			$_SESSION['last_access'] = time();
1803
		}
1804
	} else {
1805
		/* Check for stale session */
1806
		if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) {
1807
			$_GET['logout'] = true;
1808
			$_SESSION['Logout'] = true;
1809
		} else {
1810
			/* only update if it wasn't ajax */
1811
			if (!isAjax()) {
1812
				$_SESSION['last_access'] = time();
1813
			}
1814
		}
1815
	}
1816

    
1817
	/* user hit the logout button */
1818
	if (isset($_GET['logout'])) {
1819

    
1820
		if ($_SESSION['Logout']) {
1821
			log_error(sprintf(gettext("Session timed out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1822
		} else {
1823
			log_error(sprintf(gettext("User logged out for user '%1\$s' from: %2\$s"), $_SESSION['Username'], $_SERVER['REMOTE_ADDR']));
1824
		}
1825

    
1826
		/* wipe out $_SESSION */
1827
		$_SESSION = array();
1828

    
1829
		if (isset($_COOKIE[session_name()])) {
1830
			setcookie(session_name(), '', time()-42000, '/');
1831
		}
1832

    
1833
		/* and destroy it */
1834
		session_destroy();
1835

    
1836
		$scriptName = explode("/", $_SERVER["SCRIPT_FILENAME"]);
1837
		$scriptElms = count($scriptName);
1838
		$scriptName = $scriptName[$scriptElms-1];
1839

    
1840
		if (isAjax()) {
1841
			return false;
1842
		}
1843

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

    
1847
		return false;
1848
	}
1849

    
1850
	/*
1851
	 * this is for debugging purpose if you do not want to use Ajax
1852
	 * to submit a HTML form. It basically disables the observation
1853
	 * of the submit event and hence does not trigger Ajax.
1854
	 */
1855
	if ($_GET['disable_ajax']) {
1856
		$_SESSION['NO_AJAX'] = "True";
1857
	}
1858

    
1859
	/*
1860
	 * Same to re-enable Ajax.
1861
	 */
1862
	if ($_GET['enable_ajax']) {
1863
		unset($_SESSION['NO_AJAX']);
1864
	}
1865

    
1866
	return true;
1867
}
1868

    
1869
?>
(4-4/67)