Project

General

Profile

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

    
60
##|+PRIV
61
##|*IDENT=page-system-usermanager
62
##|*NAME=System: User Manager
63
##|*DESCR=Allow access to the 'System: User Manager' page.
64
##|*MATCH=system_usermanager.php*
65
##|-PRIV
66

    
67
require_once("certs.inc");
68
require_once("guiconfig.inc");
69

    
70
// start admin user code
71
if (isset($_POST['userid']) && is_numericint($_POST['userid'])) {
72
	$id = $_POST['userid'];
73
}
74

    
75
if (isset($_GET['userid']) && is_numericint($_GET['userid'])) {
76
	$id = $_GET['userid'];
77
}
78

    
79
if (!isset($config['system']['user']) || !is_array($config['system']['user'])) {
80
	$config['system']['user'] = array();
81
}
82

    
83
$a_user = &$config['system']['user'];
84
$act = $_GET['act'];
85

    
86
if (isset($_SERVER['HTTP_REFERER'])) {
87
	$referer = $_SERVER['HTTP_REFERER'];
88
} else {
89
	$referer = '/system_usermanager.php';
90
}
91

    
92
if (isset($id) && $a_user[$id]) {
93
	$pconfig['usernamefld'] = $a_user[$id]['name'];
94
	$pconfig['descr'] = $a_user[$id]['descr'];
95
	$pconfig['expires'] = $a_user[$id]['expires'];
96
	$pconfig['customsettings'] = isset($a_user[$id]['customsettings']);
97
	$pconfig['webguicss'] = $a_user[$id]['webguicss'];
98
	$pconfig['webguifixedmenu'] = $a_user[$id]['webguifixedmenu'];
99
	$pconfig['webguihostnamemenu'] = $a_user[$id]['webguihostnamemenu'];
100
	$pconfig['dashboardcolumns'] = $a_user[$id]['dashboardcolumns'];
101
	$pconfig['interfacessort'] = isset($a_user[$id]['interfacessort']);
102
	$pconfig['dashboardavailablewidgetspanel'] = isset($a_user[$id]['dashboardavailablewidgetspanel']);
103
	$pconfig['systemlogsfilterpanel'] = isset($a_user[$id]['systemlogsfilterpanel']);
104
	$pconfig['systemlogsmanagelogpanel'] = isset($a_user[$id]['systemlogsmanagelogpanel']);
105
	$pconfig['statusmonitoringsettingspanel'] = isset($a_user[$id]['statusmonitoringsettingspanel']);
106
	$pconfig['webguileftcolumnhyper'] = isset($a_user[$id]['webguileftcolumnhyper']);
107
	$pconfig['pagenamefirst'] = isset($a_user[$id]['pagenamefirst']);
108
	$pconfig['groups'] = local_user_get_groups($a_user[$id]);
109
	$pconfig['utype'] = $a_user[$id]['scope'];
110
	$pconfig['uid'] = $a_user[$id]['uid'];
111
	$pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
112
	$pconfig['priv'] = $a_user[$id]['priv'];
113
	$pconfig['ipsecpsk'] = $a_user[$id]['ipsecpsk'];
114
	$pconfig['disabled'] = isset($a_user[$id]['disabled']);
115
}
116

    
117
if ($_GET['act'] == "deluser") {
118

    
119
	if (!isset($_GET['username']) || !isset($a_user[$id]) || ($_GET['username'] != $a_user[$id]['name'])) {
120
		pfSenseHeader("system_usermanager.php");
121
		exit;
122
	}
123

    
124
	if ($_GET['username'] == $_SESSION['Username']) {
125
		$delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $_GET['username']);
126
	} else {
127
		conf_mount_rw();
128
		local_user_del($a_user[$id]);
129
		conf_mount_ro();
130
		$userdeleted = $a_user[$id]['name'];
131
		unset($a_user[$id]);
132
		write_config();
133
		$savemsg = sprintf(gettext("User %s successfully deleted."), $userdeleted);
134
	}
135
} else if ($act == "new") {
136
	/*
137
	 * set this value cause the text field is read only
138
	 * and the user should not be able to mess with this
139
	 * setting.
140
	 */
141
	$pconfig['utype'] = "user";
142
	$pconfig['lifetime'] = 3650;
143
}
144

    
145
if (isset($_POST['dellall'])) {
146

    
147
	$del_users = $_POST['delete_check'];
148
	$deleted_users = "";
149
	$deleted_count = 0;
150
	$comma = "";
151

    
152
	if (!empty($del_users)) {
153
		foreach ($del_users as $userid) {
154
			if (isset($a_user[$userid]) && $a_user[$userid]['scope'] != "system") {
155
				if ($a_user[$userid]['name'] == $_SESSION['Username']) {
156
					$delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $a_user[$userid]['name']);
157
				} else {
158
					conf_mount_rw();
159
					$deleted_users = $deleted_users . $comma . $a_user[$userid]['name'];
160
					$comma = ", ";
161
					$deleted_count++;
162
					local_user_del($a_user[$userid]);
163
					conf_mount_ro();
164
					unset($a_user[$userid]);
165
				}
166
			} else {
167
				$delete_errors[] = sprintf(gettext("Cannot delete user %s because it is a system user."), $a_user[$userid]['name']);
168
			}
169
		}
170

    
171
		if ($deleted_count > 0) {
172
			if ($deleted_count == 1) {
173
				$savemsg = sprintf(gettext("User %s successfully deleted."), $deleted_users);
174
			} else {
175
				$savemsg = sprintf(gettext("Users %s successfully deleted."), $deleted_users);
176
			}
177
			write_config($savemsg);
178
		}
179
	}
180
}
181

    
182
if ($_POST['act'] == "delcert") {
183

    
184
	if (!$a_user[$id]) {
185
		pfSenseHeader("system_usermanager.php");
186
		exit;
187
	}
188

    
189
	$certdeleted = lookup_cert($a_user[$id]['cert'][$_POST['certid']]);
190
	$certdeleted = $certdeleted['descr'];
191
	unset($a_user[$id]['cert'][$_POST['certid']]);
192
	write_config();
193
	$_POST['act'] = "edit";
194
	$savemsg = sprintf(gettext("Certificate %s association removed."), $certdeleted);
195
}
196

    
197
if ($_POST['act'] == "delprivid") {
198
	$privdeleted = $priv_list[$a_user[$id]['priv'][$_POST['privid']]]['name'];
199
	unset($a_user[$id]['priv'][$_POST['privid']]);
200
	local_user_set($a_user[$id]);
201
	write_config();
202
	$_POST['act'] = "edit";
203
	$savemsg = sprintf(gettext("Privilege %s removed."), $privdeleted);
204
}
205

    
206
if ($_POST['save']) {
207
	unset($input_errors);
208
	$pconfig = $_POST;
209

    
210
	/* input validation */
211
	if (isset($id) && ($a_user[$id])) {
212
		$reqdfields = explode(" ", "usernamefld");
213
		$reqdfieldsn = array(gettext("Username"));
214
	} else {
215
		if (empty($_POST['name'])) {
216
			$reqdfields = explode(" ", "usernamefld passwordfld1");
217
			$reqdfieldsn = array(
218
				gettext("Username"),
219
				gettext("Password"));
220
		} else {
221
			$reqdfields = explode(" ", "usernamefld passwordfld1 name caref keylen lifetime");
222
			$reqdfieldsn = array(
223
				gettext("Username"),
224
				gettext("Password"),
225
				gettext("Descriptive name"),
226
				gettext("Certificate authority"),
227
				gettext("Key length"),
228
				gettext("Lifetime"));
229
		}
230
	}
231

    
232
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
233

    
234
	if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['usernamefld'])) {
235
		$input_errors[] = gettext("The username contains invalid characters.");
236
	}
237

    
238
	if (strlen($_POST['usernamefld']) > 16) {
239
		$input_errors[] = gettext("The username is longer than 16 characters.");
240
	}
241

    
242
	if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) {
243
		$input_errors[] = gettext("The passwords do not match.");
244
	}
245

    
246
	if (isset($_POST['ipsecpsk']) && !preg_match('/^[[:ascii:]]*$/', $_POST['ipsecpsk'])) {
247
		$input_errors[] = gettext("IPsec Pre-Shared Key contains invalid characters.");
248
	}
249

    
250
	/* Check the POSTed groups to ensure they are valid and exist */
251
	if (is_array($_POST['groups'])) {
252
		foreach ($_POST['groups'] as $newgroup) {
253
			if (empty(getGroupEntry($newgroup))) {
254
				$input_errors[] = gettext("One or more invalid groups was submitted.");
255
			}
256
		}
257
	}
258

    
259
	if (isset($id) && $a_user[$id]) {
260
		$oldusername = $a_user[$id]['name'];
261
	} else {
262
		$oldusername = "";
263
	}
264
	/* make sure this user name is unique */
265
	if (!$input_errors) {
266
		foreach ($a_user as $userent) {
267
			if ($userent['name'] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
268
				$input_errors[] = gettext("Another entry with the same username already exists.");
269
				break;
270
			}
271
		}
272
	}
273
	/* also make sure it is not reserved */
274
	if (!$input_errors) {
275
		$system_users = explode("\n", file_get_contents("/etc/passwd"));
276
		foreach ($system_users as $s_user) {
277
			$ent = explode(":", $s_user);
278
			if ($ent[0] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
279
				$input_errors[] = gettext("That username is reserved by the system.");
280
				break;
281
			}
282
		}
283
	}
284

    
285
	/*
286
	 * Check for a valid expiration date if one is set at all (valid means,
287
	 * DateTime puts out a time stamp so any DateTime compatible time
288
	 * format may be used. to keep it simple for the enduser, we only
289
	 * claim to accept MM/DD/YYYY as inputs. Advanced users may use inputs
290
	 * like "+1 day", which will be converted to MM/DD/YYYY based on "now".
291
	 * Otherwise such an entry would lead to an invalid expiration data.
292
	 */
293
	if ($_POST['expires']) {
294
		try {
295
			$expdate = new DateTime($_POST['expires']);
296
			//convert from any DateTime compatible date to MM/DD/YYYY
297
			$_POST['expires'] = $expdate->format("m/d/Y");
298
		} catch (Exception $ex) {
299
			$input_errors[] = gettext("Invalid expiration date format; use MM/DD/YYYY instead.");
300
		}
301
	}
302

    
303
	if (!empty($_POST['name'])) {
304
		$ca = lookup_ca($_POST['caref']);
305
		if (!$ca) {
306
			$input_errors[] = gettext("Invalid internal Certificate Authority") . "\n";
307
		}
308
	}
309

    
310
	if (!$input_errors) {
311

    
312
		conf_mount_rw();
313
		$userent = array();
314
		if (isset($id) && $a_user[$id]) {
315
			$userent = $a_user[$id];
316
		}
317

    
318
		isset($_POST['utype']) ? $userent['scope'] = $_POST['utype'] : $userent['scope'] = "system";
319

    
320
		/* the user name was modified */
321
		if (!empty($_POST['oldusername']) && ($_POST['usernamefld'] <> $_POST['oldusername'])) {
322
			$_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
323
			local_user_del($userent);
324
		}
325

    
326
		/* the user password was modified */
327
		if ($_POST['passwordfld1']) {
328
			local_user_set_password($userent, $_POST['passwordfld1']);
329
		}
330

    
331
		/* only change description if sent */
332
		if (isset($_POST['descr'])) {
333
			$userent['descr'] = $_POST['descr'];
334
		}
335

    
336
		$userent['name'] = $_POST['usernamefld'];
337
		$userent['expires'] = $_POST['expires'];
338
		$userent['dashboardcolumns'] = $_POST['dashboardcolumns'];
339
		$userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
340
		$userent['ipsecpsk'] = $_POST['ipsecpsk'];
341

    
342
		if ($_POST['disabled']) {
343
			$userent['disabled'] = true;
344
		} else {
345
			unset($userent['disabled']);
346
		}
347

    
348
		if ($_POST['customsettings']) {
349
			$userent['customsettings'] = true;
350
		} else {
351
			unset($userent['customsettings']);
352
		}
353

    
354
		if ($_POST['webguicss']) {
355
			$userent['webguicss'] = $_POST['webguicss'];
356
		} else {
357
			unset($userent['webguicss']);
358
		}
359

    
360
		if ($_POST['webguifixedmenu']) {
361
			$userent['webguifixedmenu'] = $_POST['webguifixedmenu'];
362
		} else {
363
			unset($userent['webguifixedmenu']);
364
		}
365

    
366
		if ($_POST['webguihostnamemenu']) {
367
			$userent['webguihostnamemenu'] = $_POST['webguihostnamemenu'];
368
		} else {
369
			unset($userent['webguihostnamemenu']);
370
		}
371

    
372
		if ($_POST['interfacessort']) {
373
			$userent['interfacessort'] = true;
374
		} else {
375
			unset($userent['interfacessort']);
376
		}
377

    
378
		if ($_POST['dashboardavailablewidgetspanel']) {
379
			$userent['dashboardavailablewidgetspanel'] = true;
380
		} else {
381
			unset($userent['dashboardavailablewidgetspanel']);
382
		}
383

    
384
		if ($_POST['systemlogsfilterpanel']) {
385
			$userent['systemlogsfilterpanel'] = true;
386
		} else {
387
			unset($userent['systemlogsfilterpanel']);
388
		}
389

    
390
		if ($_POST['systemlogsmanagelogpanel']) {
391
			$userent['systemlogsmanagelogpanel'] = true;
392
		} else {
393
			unset($userent['systemlogsmanagelogpanel']);
394
		}
395

    
396
		if ($_POST['statusmonitoringsettingspanel']) {
397
			$userent['statusmonitoringsettingspanel'] = true;
398
		} else {
399
			unset($userent['statusmonitoringsettingspanel']);
400
		}
401

    
402
		if ($_POST['webguileftcolumnhyper']) {
403
			$userent['webguileftcolumnhyper'] = true;
404
		} else {
405
			unset($userent['webguileftcolumnhyper']);
406
		}
407

    
408
		if ($_POST['pagenamefirst']) {
409
			$userent['pagenamefirst'] = true;
410
		} else {
411
			unset($userent['pagenamefirst']);
412
		}
413

    
414
		if (isset($id) && $a_user[$id]) {
415
			$a_user[$id] = $userent;
416
		} else {
417
			if (!empty($_POST['name'])) {
418
				$cert = array();
419
				$cert['refid'] = uniqid();
420
				$userent['cert'] = array();
421

    
422
				$cert['descr'] = $_POST['name'];
423

    
424
				$subject = cert_get_subject_array($ca['crt']);
425

    
426
				$dn = array(
427
					'countryName' => $subject[0]['v'],
428
					'stateOrProvinceName' => $subject[1]['v'],
429
					'localityName' => $subject[2]['v'],
430
					'organizationName' => $subject[3]['v'],
431
					'emailAddress' => $subject[4]['v'],
432
					'commonName' => $userent['name']);
433

    
434
				cert_create($cert, $_POST['caref'], $_POST['keylen'],
435
					(int)$_POST['lifetime'], $dn);
436

    
437
				if (!is_array($config['cert'])) {
438
					$config['cert'] = array();
439
				}
440
				$config['cert'][] = $cert;
441
				$userent['cert'][] = $cert['refid'];
442
			}
443
			$userent['uid'] = $config['system']['nextuid']++;
444
			/* Add the user to All Users group. */
445
			foreach ($config['system']['group'] as $gidx => $group) {
446
				if ($group['name'] == "all") {
447
					if (!is_array($config['system']['group'][$gidx]['member'])) {
448
						$config['system']['group'][$gidx]['member'] = array();
449
					}
450
					$config['system']['group'][$gidx]['member'][] = $userent['uid'];
451
					break;
452
				}
453
			}
454

    
455
			$a_user[] = $userent;
456
		}
457

    
458
		/* Add user to groups so PHP can see the memberships properly or else the user's shell account does not get proper permissions (if applicable) See #5152. */
459
		local_user_set_groups($userent, $_POST['groups']);
460
		local_user_set($userent);
461
		/* Add user to groups again to ensure they are set everywhere, otherwise the user may not appear to be a member of the group. See commit:5372d26d9d25d751d16865ed9d46869d3b0ec5e1. */
462
		local_user_set_groups($userent, $_POST['groups']);
463
		write_config();
464

    
465
		if (is_dir("/etc/inc/privhooks")) {
466
			run_plugins("/etc/inc/privhooks");
467
		}
468

    
469
		conf_mount_ro();
470

    
471
		pfSenseHeader("system_usermanager.php");
472
	}
473
}
474

    
475
function build_priv_table() {
476
	global $a_user, $id;
477

    
478
	$privhtml = '<div class="table-responsive">';
479
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
480
	$privhtml .=		'<thead>';
481
	$privhtml .=			'<tr>';
482
	$privhtml .=				'<th>' . gettext('Inherited from') . '</th>';
483
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
484
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
485
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
486
	$privhtml .=			'</tr>';
487
	$privhtml .=		'</thead>';
488
	$privhtml .=		'<tbody>';
489

    
490
	$i = 0;
491

    
492
	foreach (get_user_privdesc($a_user[$id]) as $priv) {
493
		$group = false;
494
		if ($priv['group']) {
495
			$group = $priv['group'];
496
		}
497

    
498
		$privhtml .=		'<tr>';
499
		$privhtml .=			'<td>' . htmlspecialchars($priv['group']) . '</td>';
500
		$privhtml .=			'<td>' . htmlspecialchars($priv['name']) . '</td>';
501
		$privhtml .=			'<td>' . htmlspecialchars($priv['descr']) . '</td>';
502
		$privhtml .=			'<td>';
503
		if (!$group) {
504
			$privhtml .=			'<a class="fa fa-trash no-confirm icon-pointer" title="' . gettext('Delete Privilege') . '" id="delprivid' . $i . '"></a>';
505
		}
506

    
507
		$privhtml .=			'</td>';
508
		$privhtml .=		'</tr>';
509

    
510
		if (!$group) {
511
			$i++;
512
		}
513
	}
514

    
515
	$privhtml .=		'</tbody>';
516
	$privhtml .=	'</table>';
517
	$privhtml .= '</div>';
518

    
519
	$privhtml .= '<nav class="action-buttons">';
520
	$privhtml .=	'<a href="system_usermanager_addprivs.php?userid=' . $id . '" class="btn btn-success"><i class="fa fa-plus icon-embed-btn"></i>' . gettext("Add") . '</a>';
521
	$privhtml .= '</nav>';
522

    
523
	return($privhtml);
524
}
525

    
526
function build_cert_table() {
527
	global $a_user, $id;
528

    
529
	$certhtml = '<div class="table-responsive">';
530
	$certhtml .=	'<table class="table table-striped table-hover table-condensed">';
531
	$certhtml .=		'<thead>';
532
	$certhtml .=			'<tr>';
533
	$certhtml .=				'<th>' . gettext('Name') . '</th>';
534
	$certhtml .=				'<th>' . gettext('CA') . '</th>';
535
	$certhtml .=				'<th></th>';
536
	$certhtml .=			'</tr>';
537
	$certhtml .=		'</thead>';
538
	$certhtml .=		'<tbody>';
539

    
540
	$a_cert = $a_user[$id]['cert'];
541
	if (is_array($a_cert)) {
542
		$i = 0;
543
		foreach ($a_cert as $certref) {
544
			$cert = lookup_cert($certref);
545
			$ca = lookup_ca($cert['caref']);
546
			$revokedstr =	is_cert_revoked($cert) ? '<b> Revoked</b>':'';
547

    
548
			$certhtml .=	'<tr>';
549
			$certhtml .=		'<td>' . htmlspecialchars($cert['descr']) . $revokedstr . '</td>';
550
			$certhtml .=		'<td>' . htmlspecialchars($ca['descr']) . '</td>';
551
			$certhtml .=		'<td>';
552
			$certhtml .=			'<a id="delcert' . $i .'" class="fa fa-trash no-confirm icon-pointer" title="';
553
			$certhtml .=			gettext('Remove this certificate association? (Certificate will not be deleted)') . '"></a>';
554
			$certhtml .=		'</td>';
555
			$certhtml .=	'</tr>';
556
			$i++;
557
		}
558

    
559
	}
560

    
561
	$certhtml .=		'</tbody>';
562
	$certhtml .=	'</table>';
563
	$certhtml .= '</div>';
564

    
565
	$certhtml .= '<nav class="action-buttons">';
566
	$certhtml .=	'<a href="system_certmanager.php?act=new&amp;userid=' . $id . '" class="btn btn-success"><i class="fa fa-plus icon-embed-btn"></i>' . gettext("Add") . '</a>';
567
	$certhtml .= '</nav>';
568

    
569
	return($certhtml);
570
}
571

    
572
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
573
$pglinks = array("", "system_usermanager.php", "system_usermanager.php");
574

    
575
if ($act == "new" || $act == "edit" || $input_errors) {
576
	$pgtitle[] = gettext('Edit');
577
	$pglinks[] = "@self";
578
}
579
include("head.inc");
580

    
581
if ($delete_errors) {
582
	print_input_errors($delete_errors);
583
}
584

    
585
if ($input_errors) {
586
	print_input_errors($input_errors);
587
}
588

    
589
if ($savemsg) {
590
	print_info_box($savemsg, 'success');
591
}
592

    
593
$tab_array = array();
594
$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
595
$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
596
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
597
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
598
display_top_tabs($tab_array);
599

    
600
if (!($act == "new" || $act == "edit" || $input_errors)) {
601
?>
602
<form method="post">
603
<div class="panel panel-default">
604
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Users')?></h2></div>
605
	<div class="panel-body">
606
		<div class="table-responsive">
607
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
608
				<thead>
609
					<tr>
610
						<th>&nbsp;</th>
611
						<th><?=gettext("Username")?></th>
612
						<th><?=gettext("Full name")?></th>
613
						<th><?=gettext("Status")?></th>
614
						<th><?=gettext("Groups")?></th>
615
						<th><?=gettext("Actions")?></th>
616
					</tr>
617
				</thead>
618
				<tbody>
619
<?php
620
foreach ($a_user as $i => $userent):
621
	?>
622
					<tr>
623
						<td>
624
							<input type="checkbox" id="frc<?=$i?>" name="delete_check[]" value="<?=$i?>" <?=((($userent['scope'] == "system") || ($userent['name'] == $_SESSION['Username'])) ? 'disabled' : '')?>/>
625
						</td>
626
						<td>
627
<?php
628
	if ($userent['scope'] != "user") {
629
		$usrimg = 'eye-open';
630
	} else {
631
		$usrimg = 'user';
632
	}
633
?>
634
							<i class="fa fa-<?=$usrimg?>"></i>
635
							<?=htmlspecialchars($userent['name'])?>
636
						</td>
637
						<td><?=htmlspecialchars($userent['descr'])?></td>
638
						<td><i class="fa fa-<?= (isset($userent['disabled'])) ? 'ban" title="' . gettext("Disabled") . '"' : 'check" title="' . gettext("Enabled") . '"' ; ?>><span style='display: none'><?= (isset($userent['disabled'])) ? gettext("Disabled") : gettext("Enabled") ; ?></span></i></td>
639
						<td><?=implode(",", local_user_get_groups($userent))?></td>
640
						<td>
641
							<a class="fa fa-pencil" title="<?=gettext("Edit user"); ?>" href="?act=edit&amp;userid=<?=$i?>"></a>
642
<?php if (($userent['scope'] != "system") && ($userent['name'] != $_SESSION['Username'])): ?>
643
							<a class="fa fa-trash"	title="<?=gettext("Delete user")?>" href="?act=deluser&amp;userid=<?=$i?>&amp;username=<?=$userent['name']?>"></a>
644
<?php endif; ?>
645
						</td>
646
					</tr>
647
<?php endforeach; ?>
648
				</tbody>
649
			</table>
650
		</div>
651
	</div>
652
</div>
653
<nav class="action-buttons">
654
	<a href="?act=new" class="btn btn-sm btn-success">
655
		<i class="fa fa-plus icon-embed-btn"></i>
656
		<?=gettext("Add")?>
657
	</a>
658

    
659
	<button type="submit" class="btn btn-sm btn-danger" name="dellall" value="dellall" title="<?=gettext('Delete selected users')?>">
660
		<i class="fa fa-trash icon-embed-btn"></i>
661
		<?=gettext("Delete")?>
662
	</button>
663
</nav>
664
</form>
665
<div class="infoblock">
666
<?php
667
	print_callout('<p>' . gettext("Additional users can be added here. User permissions for accessing " .
668
		"the webConfigurator can be assigned directly or inherited from group memberships. " .
669
		"Some system object properties can be modified but they cannot be deleted.") . '</p>' .
670
		'<p>' . gettext("Accounts added here are also used for other parts of the system " .
671
		"such as OpenVPN, IPsec, and Captive Portal.") . '</p>'
672
	);
673
?></div><?php
674
	include("foot.inc");
675
	exit;
676
}
677

    
678
$form = new Form;
679

    
680
if ($act == "new" || $act == "edit" || $input_errors):
681

    
682
	$form->addGlobal(new Form_Input(
683
		'act',
684
		null,
685
		'hidden',
686
		''
687
	));
688

    
689
	$form->addGlobal(new Form_Input(
690
		'userid',
691
		null,
692
		'hidden',
693
		isset($id) ? $id:''
694
	));
695

    
696
	$form->addGlobal(new Form_Input(
697
		'privid',
698
		null,
699
		'hidden',
700
		''
701
	));
702

    
703
	$form->addGlobal(new Form_Input(
704
		'certid',
705
		null,
706
		'hidden',
707
		''
708
	));
709

    
710
	$ro = "";
711
	if ($pconfig['utype'] == "system") {
712
		$ro = "readonly";
713
	}
714

    
715
	$section = new Form_Section('User Properties');
716

    
717
	$section->addInput(new Form_StaticText(
718
		'Defined by',
719
		strtoupper($pconfig['utype'])
720
	));
721

    
722
	$form->addGlobal(new Form_Input(
723
		'utype',
724
		null,
725
		'hidden',
726
		$pconfig['utype']
727
	));
728

    
729
	$section->addInput(new Form_Checkbox(
730
		'disabled',
731
		'Disabled',
732
		'This user cannot login',
733
		$pconfig['disabled']
734
	));
735

    
736
	$section->addInput($input = new Form_Input(
737
		'usernamefld',
738
		'*Username',
739
		'text',
740
		$pconfig['usernamefld']
741
	));
742

    
743
	if ($ro) {
744
		$input->setReadonly();
745
	}
746

    
747
	$form->addGlobal(new Form_Input(
748
		'oldusername',
749
		null,
750
		'hidden',
751
		$pconfig['usernamefld']
752
	));
753

    
754
	if ($act == "edit") {
755
		$pwd_required = "";
756
	} else {
757
		$pwd_required = "*";
758
	}
759

    
760
	$group = new Form_Group($pwd_required . 'Password');
761
	$group->add(new Form_Input(
762
		'passwordfld1',
763
		'Password',
764
		'password'
765
	));
766
	$group->add(new Form_Input(
767
		'passwordfld2',
768
		'Confirm Password',
769
		'password'
770
	));
771

    
772
	$section->add($group);
773

    
774
	$section->addInput($input = new Form_Input(
775
		'descr',
776
		'Full name',
777
		'text',
778
		htmlspecialchars($pconfig['descr'])
779
	))->setHelp('User\'s full name, for administrative information only');
780

    
781
	if ($ro) {
782
		$input->setDisabled();
783
	}
784

    
785
	$section->addInput(new Form_Input(
786
		'expires',
787
		'Expiration date',
788
		'text',
789
		$pconfig['expires']
790
	))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
791
		'the expiration date as MM/DD/YYYY');
792

    
793
	$section->addInput(new Form_Checkbox(
794
		'customsettings',
795
		'Custom Settings',
796
		'Use individual customized GUI options and dashboard layout for this user.',
797
		$pconfig['customsettings']
798
	));
799

    
800
	gen_user_settings_fields($section, $pconfig);
801

    
802
	// ==== Group membership ==================================================
803
	$group = new Form_Group('Group membership');
804

    
805
	// Make a list of all the groups configured on the system, and a list of
806
	// those which this user is a member of
807
	$systemGroups = array();
808
	$usersGroups = array();
809

    
810
	$usergid = [$pconfig['usernamefld']];
811

    
812
	foreach ($config['system']['group'] as $Ggroup) {
813
		if ($Ggroup['name'] != "all") {
814
			if (($act == 'edit') && $Ggroup['member'] && in_array($pconfig['uid'], $Ggroup['member'])) {
815
				$usersGroups[ $Ggroup['name'] ] = $Ggroup['name'];	// Add it to the user's list
816
			} else {
817
				$systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
818
			}
819
		}
820
	}
821

    
822
	$group->add(new Form_Select(
823
		'sysgroups',
824
		null,
825
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
826
		$systemGroups,
827
		true
828
	))->setHelp('Not member of');
829

    
830
	$group->add(new Form_Select(
831
		'groups',
832
		null,
833
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
834
		$usersGroups,
835
		true
836
	))->setHelp('Member of');
837

    
838
	$section->add($group);
839

    
840
	$group = new Form_Group('');
841

    
842
	$group->add(new Form_Button(
843
		'movetoenabled',
844
		'Move to "Member of" list',
845
		null,
846
		'fa-angle-double-right'
847
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
848

    
849
	$group->add(new Form_Button(
850
		'movetodisabled',
851
		'Move to "Not member of" list',
852
		null,
853
		'fa-angle-double-left'
854
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
855

    
856
	$group->setHelp('Hold down CTRL (PC)/COMMAND (Mac) key to select multiple items.');
857
	$section->add($group);
858

    
859
	// ==== Button for adding user certificate ================================
860
	if ($act == 'new') {
861
		$section->addInput(new Form_Checkbox(
862
			'showcert',
863
			'Certificate',
864
			'Click to create a user certificate',
865
			false
866
		));
867
	}
868

    
869
	$form->add($section);
870

    
871
	// ==== Effective privileges section ======================================
872
	if (isset($pconfig['uid'])) {
873
		// We are going to build an HTML table and add it to an Input_StaticText. It may be ugly, but it
874
		// is the best way to make the display we need.
875

    
876
		$section = new Form_Section('Effective Privileges');
877

    
878
		$section->addInput(new Form_StaticText(
879
			null,
880
			build_priv_table()
881
		));
882

    
883
		$form->add($section);
884

    
885
		// ==== Certificate table section =====================================
886
		$section = new Form_Section('User Certificates');
887

    
888
		$section->addInput(new Form_StaticText(
889
			null,
890
			build_cert_table()
891
		));
892

    
893
		$form->add($section);
894
	}
895

    
896
	// ==== Add user certificate for a new user
897
	if (is_array($config['ca']) && count($config['ca']) > 0) {
898
		$section = new Form_Section('Create Certificate for User');
899
		$section->addClass('cert-options');
900

    
901
		$nonPrvCas = array();
902
		foreach ($config['ca'] as $ca) {
903
			if (!$ca['prv']) {
904
				continue;
905
			}
906

    
907
			$nonPrvCas[ $ca['refid'] ] = $ca['descr'];
908
		}
909

    
910
		if (!empty($nonPrvCas)) {
911
			$section->addInput(new Form_Input(
912
				'name',
913
				'Descriptive name',
914
				'text',
915
				$pconfig['name']
916
			));
917

    
918
			$section->addInput(new Form_Select(
919
				'caref',
920
				'Certificate authority',
921
				null,
922
				$nonPrvCas
923
			));
924

    
925
			$section->addInput(new Form_Select(
926
				'keylen',
927
				'Key length',
928
				2048,
929
				array(
930
					512 => '512 bits',
931
					1024 => '1024 bits',
932
					2048 => '2048 bits',
933
					3072 => '3072 bits',
934
					4096 => '4096 bits',
935
					7680 => '7680 bits',
936
					8192 => '8192 bits',
937
					15360 => '15360 bits',
938
					16384 => '16384 bits'
939
				)
940
			))->setHelp('The larger the key, the more security it offers, but larger keys take considerably more time to generate, and take slightly longer to validate leading to a slight slowdown in setting up new sessions (not always noticeable). As of 2016, 2048 bit is the minimum and most common selection and 4096 is the maximum in common use. For more information see &lt;a href="https://keylength.com"&gt;keylength.com&lt;/a&gt;.');
941

    
942
			$section->addInput(new Form_Input(
943
				'lifetime',
944
				'Lifetime',
945
				'number',
946
				$pconfig['lifetime']
947
			));
948
		}
949

    
950
		$form->add($section);
951
	}
952

    
953
endif;
954
// ==== Paste a key for the new user
955
$section = new Form_Section('Keys');
956

    
957
$section->addInput(new Form_Checkbox(
958
	'showkey',
959
	'Authorized keys',
960
	'Click to paste an authorized key',
961
	false
962
));
963

    
964
$section->addInput(new Form_Textarea(
965
	'authorizedkeys',
966
	'Authorized SSH Keys',
967
	$pconfig['authorizedkeys']
968
))->setHelp('Enter authorized SSH keys for this user');
969

    
970
$section->addInput(new Form_Input(
971
	'ipsecpsk',
972
	'IPsec Pre-Shared Key',
973
	'text',
974
	$pconfig['ipsecpsk']
975
));
976

    
977
$form->add($section);
978

    
979
print $form;
980

    
981
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
982
?>
983
<script type="text/javascript">
984
//<![CDATA[
985
events.push(function() {
986

    
987
	function setcustomoptions() {
988
		var adv = $('#customsettings').prop('checked');
989

    
990
		hideInput('webguicss', !adv);
991
		hideInput('webguifixedmenu', !adv);
992
		hideInput('webguihostnamemenu', !adv);
993
		hideInput('dashboardcolumns', !adv);
994
		hideCheckbox('interfacessort', !adv);
995
		hideCheckbox('dashboardavailablewidgetspanel', !adv);
996
		hideCheckbox('systemlogsfilterpanel', !adv);
997
		hideCheckbox('systemlogsmanagelogpanel', !adv);
998
		hideCheckbox('statusmonitoringsettingspanel', !adv);
999
		hideCheckbox('webguileftcolumnhyper', !adv);
1000
		hideCheckbox('pagenamefirst', !adv);
1001
	}
1002

    
1003
	// Handle displaying a warning message if a user-created theme is selected.
1004
	function setThemeWarning() {
1005
		if ($('#webguicss').val().startsWith("pfSense")) {
1006
			$('#csstxt').html("").addClass("text-default");
1007
		} else {
1008
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
1009
		}
1010
	}
1011

    
1012
	$('#webguicss').change(function() {
1013
		setThemeWarning();
1014
	});
1015

    
1016
	setThemeWarning();
1017

    
1018
	// On click . .
1019
	$('#customsettings').click(function () {
1020
		setcustomoptions();
1021
	});
1022

    
1023
	$("#movetodisabled").click(function() {
1024
		moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
1025
	});
1026

    
1027
	$("#movetoenabled").click(function() {
1028
		moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1029
	});
1030

    
1031
	$("#showcert").click(function() {
1032
		hideClass('cert-options', !this.checked);
1033
	});
1034

    
1035
	$("#showkey").click(function() {
1036
		hideInput('authorizedkeys', false);
1037
		hideCheckbox('showkey', true);
1038
	});
1039

    
1040
	$('[id^=delcert]').click(function(event) {
1041
		if (confirm(event.target.title)) {
1042
			$('#certid').val(event.target.id.match(/\d+$/)[0]);
1043
			$('#userid').val('<?=$id;?>');
1044
			$('#act').val('delcert');
1045
			$('form').submit();
1046
		}
1047
	});
1048

    
1049
	$('[id^=delprivid]').click(function(event) {
1050
		if (confirm(event.target.title)) {
1051
			$('#privid').val(event.target.id.match(/\d+$/)[0]);
1052
			$('#userid').val('<?=$id;?>');
1053
			$('#act').val('delprivid');
1054
			$('form').submit();
1055
		}
1056
	});
1057

    
1058
	$('#expires').datepicker();
1059

    
1060
	// ---------- On initial page load ------------------------------------------------------------
1061

    
1062
	hideClass('cert-options', true);
1063
	//hideInput('authorizedkeys', true);
1064
	hideCheckbox('showkey', true);
1065
	setcustomoptions();
1066

    
1067
	// On submit mark all the user's groups as "selected"
1068
	$('form').submit(function() {
1069
		AllServers($('[name="groups[]"] option'), true);
1070
	});
1071
});
1072
//]]>
1073
</script>
1074
<?php
1075
include('foot.inc');
1076
?>
(206-206/225)