Project

General

Profile

Download (29.2 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
 * Licensed under the Apache License, Version 2.0 (the "License");
16
 * you may not use this file except in compliance with the License.
17
 * You may obtain a copy of the License at
18
 *
19
 * http://www.apache.org/licenses/LICENSE-2.0
20
 *
21
 * Unless required by applicable law or agreed to in writing, software
22
 * distributed under the License is distributed on an "AS IS" BASIS,
23
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
 * See the License for the specific language governing permissions and
25
 * limitations under the License.
26
 */
27

    
28
##|+PRIV
29
##|*IDENT=page-system-usermanager
30
##|*NAME=System: User Manager
31
##|*DESCR=Allow access to the 'System: User Manager' page.
32
##|*WARN=standard-warning-root
33
##|*MATCH=system_usermanager.php*
34
##|-PRIV
35

    
36
require_once("certs.inc");
37
require_once("guiconfig.inc");
38

    
39
// start admin user code
40
if (isset($_POST['userid']) && is_numericint($_POST['userid'])) {
41
	$id = $_POST['userid'];
42
}
43

    
44
if (isset($_GET['userid']) && is_numericint($_GET['userid'])) {
45
	$id = $_GET['userid'];
46
}
47

    
48
if (!isset($config['system']['user']) || !is_array($config['system']['user'])) {
49
	$config['system']['user'] = array();
50
}
51

    
52
$a_user = &$config['system']['user'];
53
$act = $_GET['act'];
54

    
55
if (isset($_SERVER['HTTP_REFERER'])) {
56
	$referer = $_SERVER['HTTP_REFERER'];
57
} else {
58
	$referer = '/system_usermanager.php';
59
}
60

    
61
if (isset($id) && $a_user[$id]) {
62
	$pconfig['usernamefld'] = $a_user[$id]['name'];
63
	$pconfig['descr'] = $a_user[$id]['descr'];
64
	$pconfig['expires'] = $a_user[$id]['expires'];
65
	$pconfig['customsettings'] = isset($a_user[$id]['customsettings']);
66
	$pconfig['webguicss'] = $a_user[$id]['webguicss'];
67
	$pconfig['webguifixedmenu'] = $a_user[$id]['webguifixedmenu'];
68
	$pconfig['webguihostnamemenu'] = $a_user[$id]['webguihostnamemenu'];
69
	$pconfig['dashboardcolumns'] = $a_user[$id]['dashboardcolumns'];
70
	$pconfig['dashboardavailablewidgetspanel'] = isset($a_user[$id]['dashboardavailablewidgetspanel']);
71
	$pconfig['systemlogsfilterpanel'] = isset($a_user[$id]['systemlogsfilterpanel']);
72
	$pconfig['systemlogsmanagelogpanel'] = isset($a_user[$id]['systemlogsmanagelogpanel']);
73
	$pconfig['statusmonitoringsettingspanel'] = isset($a_user[$id]['statusmonitoringsettingspanel']);
74
	$pconfig['webguileftcolumnhyper'] = isset($a_user[$id]['webguileftcolumnhyper']);
75
	$pconfig['pagenamefirst'] = isset($a_user[$id]['pagenamefirst']);
76
	$pconfig['groups'] = local_user_get_groups($a_user[$id]);
77
	$pconfig['utype'] = $a_user[$id]['scope'];
78
	$pconfig['uid'] = $a_user[$id]['uid'];
79
	$pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
80
	$pconfig['priv'] = $a_user[$id]['priv'];
81
	$pconfig['ipsecpsk'] = $a_user[$id]['ipsecpsk'];
82
	$pconfig['disabled'] = isset($a_user[$id]['disabled']);
83
}
84

    
85
if ($_GET['act'] == "deluser") {
86

    
87
	if (!isset($_GET['username']) || !isset($a_user[$id]) || ($_GET['username'] != $a_user[$id]['name'])) {
88
		pfSenseHeader("system_usermanager.php");
89
		exit;
90
	}
91

    
92
	if ($_GET['username'] == $_SESSION['Username']) {
93
		$delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $_GET['username']);
94
	} else {
95
		local_user_del($a_user[$id]);
96
		$userdeleted = $a_user[$id]['name'];
97
		unset($a_user[$id]);
98
		write_config();
99
		$savemsg = sprintf(gettext("User %s successfully deleted."), $userdeleted);
100
	}
101
} else if ($act == "new") {
102
	/*
103
	 * set this value cause the text field is read only
104
	 * and the user should not be able to mess with this
105
	 * setting.
106
	 */
107
	$pconfig['utype'] = "user";
108
	$pconfig['lifetime'] = 3650;
109
}
110

    
111
if (isset($_POST['dellall'])) {
112

    
113
	$del_users = $_POST['delete_check'];
114
	$deleted_users = "";
115
	$deleted_count = 0;
116
	$comma = "";
117

    
118
	if (!empty($del_users)) {
119
		foreach ($del_users as $userid) {
120
			if (isset($a_user[$userid]) && $a_user[$userid]['scope'] != "system") {
121
				if ($a_user[$userid]['name'] == $_SESSION['Username']) {
122
					$delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $a_user[$userid]['name']);
123
				} else {
124
					$deleted_users = $deleted_users . $comma . $a_user[$userid]['name'];
125
					$comma = ", ";
126
					$deleted_count++;
127
					local_user_del($a_user[$userid]);
128
					unset($a_user[$userid]);
129
				}
130
			} else {
131
				$delete_errors[] = sprintf(gettext("Cannot delete user %s because it is a system user."), $a_user[$userid]['name']);
132
			}
133
		}
134

    
135
		if ($deleted_count > 0) {
136
			if ($deleted_count == 1) {
137
				$savemsg = sprintf(gettext("User %s successfully deleted."), $deleted_users);
138
			} else {
139
				$savemsg = sprintf(gettext("Users %s successfully deleted."), $deleted_users);
140
			}
141
			write_config($savemsg);
142
		}
143
	}
144
}
145

    
146
if ($_POST['act'] == "delcert") {
147

    
148
	if (!$a_user[$id]) {
149
		pfSenseHeader("system_usermanager.php");
150
		exit;
151
	}
152

    
153
	$certdeleted = lookup_cert($a_user[$id]['cert'][$_POST['certid']]);
154
	$certdeleted = $certdeleted['descr'];
155
	unset($a_user[$id]['cert'][$_POST['certid']]);
156
	write_config();
157
	$_POST['act'] = "edit";
158
	$savemsg = sprintf(gettext("Certificate %s association removed."), $certdeleted);
159
}
160

    
161
if ($_POST['act'] == "delprivid") {
162
	$privdeleted = $priv_list[$a_user[$id]['priv'][$_POST['privid']]]['name'];
163
	unset($a_user[$id]['priv'][$_POST['privid']]);
164
	local_user_set($a_user[$id]);
165
	write_config();
166
	$_POST['act'] = "edit";
167
	$savemsg = sprintf(gettext("Privilege %s removed."), $privdeleted);
168
}
169

    
170
if ($_POST['save']) {
171
	unset($input_errors);
172
	$pconfig = $_POST;
173

    
174
	/* input validation */
175
	if (isset($id) && ($a_user[$id])) {
176
		$reqdfields = explode(" ", "usernamefld");
177
		$reqdfieldsn = array(gettext("Username"));
178
	} else {
179
		if (empty($_POST['name'])) {
180
			$reqdfields = explode(" ", "usernamefld passwordfld1");
181
			$reqdfieldsn = array(
182
				gettext("Username"),
183
				gettext("Password"));
184
		} else {
185
			$reqdfields = explode(" ", "usernamefld passwordfld1 name caref keylen lifetime");
186
			$reqdfieldsn = array(
187
				gettext("Username"),
188
				gettext("Password"),
189
				gettext("Descriptive name"),
190
				gettext("Certificate authority"),
191
				gettext("Key length"),
192
				gettext("Lifetime"));
193
		}
194
	}
195

    
196
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
197

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

    
202
	if (strlen($_POST['usernamefld']) > 16) {
203
		$input_errors[] = gettext("The username is longer than 16 characters.");
204
	}
205

    
206
	if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) {
207
		$input_errors[] = gettext("The passwords do not match.");
208
	}
209

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

    
214
	/* Check the POSTed groups to ensure they are valid and exist */
215
	if (is_array($_POST['groups'])) {
216
		foreach ($_POST['groups'] as $newgroup) {
217
			if (empty(getGroupEntry($newgroup))) {
218
				$input_errors[] = gettext("One or more invalid groups was submitted.");
219
			}
220
		}
221
	}
222

    
223
	if (isset($id) && $a_user[$id]) {
224
		$oldusername = $a_user[$id]['name'];
225
	} else {
226
		$oldusername = "";
227
	}
228
	/* make sure this user name is unique */
229
	if (!$input_errors) {
230
		foreach ($a_user as $userent) {
231
			if ($userent['name'] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
232
				$input_errors[] = gettext("Another entry with the same username already exists.");
233
				break;
234
			}
235
		}
236
	}
237
	/* also make sure it is not reserved */
238
	if (!$input_errors) {
239
		$system_users = explode("\n", file_get_contents("/etc/passwd"));
240
		foreach ($system_users as $s_user) {
241
			$ent = explode(":", $s_user);
242
			if ($ent[0] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
243
				$input_errors[] = gettext("That username is reserved by the system.");
244
				break;
245
			}
246
		}
247
	}
248

    
249
	/*
250
	 * Check for a valid expiration date if one is set at all (valid means,
251
	 * DateTime puts out a time stamp so any DateTime compatible time
252
	 * format may be used. to keep it simple for the enduser, we only
253
	 * claim to accept MM/DD/YYYY as inputs. Advanced users may use inputs
254
	 * like "+1 day", which will be converted to MM/DD/YYYY based on "now".
255
	 * Otherwise such an entry would lead to an invalid expiration data.
256
	 */
257
	if ($_POST['expires']) {
258
		try {
259
			$expdate = new DateTime($_POST['expires']);
260
			//convert from any DateTime compatible date to MM/DD/YYYY
261
			$_POST['expires'] = $expdate->format("m/d/Y");
262
		} catch (Exception $ex) {
263
			$input_errors[] = gettext("Invalid expiration date format; use MM/DD/YYYY instead.");
264
		}
265
	}
266

    
267
	if (!empty($_POST['name'])) {
268
		$ca = lookup_ca($_POST['caref']);
269
		if (!$ca) {
270
			$input_errors[] = gettext("Invalid internal Certificate Authority") . "\n";
271
		}
272
	}
273

    
274
	if (!$input_errors) {
275

    
276
		$userent = array();
277
		if (isset($id) && $a_user[$id]) {
278
			$userent = $a_user[$id];
279
		}
280

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

    
283
		/* the user name was modified */
284
		if (!empty($_POST['oldusername']) && ($_POST['usernamefld'] <> $_POST['oldusername'])) {
285
			$_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
286
			local_user_del($userent);
287
		}
288

    
289
		/* the user password was modified */
290
		if ($_POST['passwordfld1']) {
291
			local_user_set_password($userent, $_POST['passwordfld1']);
292
		}
293

    
294
		/* only change description if sent */
295
		if (isset($_POST['descr'])) {
296
			$userent['descr'] = $_POST['descr'];
297
		}
298

    
299
		$userent['name'] = $_POST['usernamefld'];
300
		$userent['expires'] = $_POST['expires'];
301
		$userent['dashboardcolumns'] = $_POST['dashboardcolumns'];
302
		$userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
303
		$userent['ipsecpsk'] = $_POST['ipsecpsk'];
304

    
305
		if ($_POST['disabled']) {
306
			$userent['disabled'] = true;
307
		} else {
308
			unset($userent['disabled']);
309
		}
310

    
311
		if ($_POST['customsettings']) {
312
			$userent['customsettings'] = true;
313
		} else {
314
			unset($userent['customsettings']);
315
		}
316

    
317
		if ($_POST['webguicss']) {
318
			$userent['webguicss'] = $_POST['webguicss'];
319
		} else {
320
			unset($userent['webguicss']);
321
		}
322

    
323
		if ($_POST['webguifixedmenu']) {
324
			$userent['webguifixedmenu'] = $_POST['webguifixedmenu'];
325
		} else {
326
			unset($userent['webguifixedmenu']);
327
		}
328

    
329
		if ($_POST['webguihostnamemenu']) {
330
			$userent['webguihostnamemenu'] = $_POST['webguihostnamemenu'];
331
		} else {
332
			unset($userent['webguihostnamemenu']);
333
		}
334

    
335
		if ($_POST['dashboardavailablewidgetspanel']) {
336
			$userent['dashboardavailablewidgetspanel'] = true;
337
		} else {
338
			unset($userent['dashboardavailablewidgetspanel']);
339
		}
340

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

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

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

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

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

    
371
		if (isset($id) && $a_user[$id]) {
372
			$a_user[$id] = $userent;
373
		} else {
374
			if (!empty($_POST['name'])) {
375
				$cert = array();
376
				$cert['refid'] = uniqid();
377
				$userent['cert'] = array();
378

    
379
				$cert['descr'] = $_POST['name'];
380

    
381
				$subject = cert_get_subject_array($ca['crt']);
382

    
383
				$dn = array(
384
					'countryName' => $subject[0]['v'],
385
					'stateOrProvinceName' => $subject[1]['v'],
386
					'localityName' => $subject[2]['v'],
387
					'organizationName' => $subject[3]['v'],
388
					'emailAddress' => $subject[4]['v'],
389
					'commonName' => $userent['name']);
390

    
391
				cert_create($cert, $_POST['caref'], $_POST['keylen'],
392
					(int)$_POST['lifetime'], $dn);
393

    
394
				if (!is_array($config['cert'])) {
395
					$config['cert'] = array();
396
				}
397
				$config['cert'][] = $cert;
398
				$userent['cert'][] = $cert['refid'];
399
			}
400
			$userent['uid'] = $config['system']['nextuid']++;
401
			/* Add the user to All Users group. */
402
			foreach ($config['system']['group'] as $gidx => $group) {
403
				if ($group['name'] == "all") {
404
					if (!is_array($config['system']['group'][$gidx]['member'])) {
405
						$config['system']['group'][$gidx]['member'] = array();
406
					}
407
					$config['system']['group'][$gidx]['member'][] = $userent['uid'];
408
					break;
409
				}
410
			}
411

    
412
			$a_user[] = $userent;
413
		}
414

    
415
		/* 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. */
416
		local_user_set_groups($userent, $_POST['groups']);
417
		local_user_set($userent);
418
		/* 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. */
419
		local_user_set_groups($userent, $_POST['groups']);
420
		write_config();
421

    
422
		if (is_dir("/etc/inc/privhooks")) {
423
			run_plugins("/etc/inc/privhooks");
424
		}
425

    
426

    
427
		pfSenseHeader("system_usermanager.php");
428
	}
429
}
430

    
431
function build_priv_table() {
432
	global $a_user, $id;
433

    
434
	$privhtml = '<div class="table-responsive">';
435
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
436
	$privhtml .=		'<thead>';
437
	$privhtml .=			'<tr>';
438
	$privhtml .=				'<th>' . gettext('Inherited from') . '</th>';
439
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
440
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
441
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
442
	$privhtml .=			'</tr>';
443
	$privhtml .=		'</thead>';
444
	$privhtml .=		'<tbody>';
445

    
446
	$i = 0;
447
	$user_has_root_priv = false;
448

    
449
	foreach (get_user_privdesc($a_user[$id]) as $priv) {
450
		$group = false;
451
		if ($priv['group']) {
452
			$group = $priv['group'];
453
		}
454

    
455
		$privhtml .=		'<tr>';
456
		$privhtml .=			'<td>' . htmlspecialchars($priv['group']) . '</td>';
457
		$privhtml .=			'<td>' . htmlspecialchars($priv['name']) . '</td>';
458
		$privhtml .=			'<td>' . htmlspecialchars($priv['descr']);
459
		if (isset($priv['warn']) && ($priv['warn'] == 'standard-warning-root')) {
460
			$privhtml .=			' ' . gettext('(admin privilege)');
461
			$user_has_root_priv = true;
462
		}
463
		$privhtml .=			'</td>';
464
		$privhtml .=			'<td>';
465
		if (!$group) {
466
			$privhtml .=			'<a class="fa fa-trash no-confirm icon-pointer" title="' . gettext('Delete Privilege') . '" id="delprivid' . $i . '"></a>';
467
		}
468

    
469
		$privhtml .=			'</td>';
470
		$privhtml .=		'</tr>';
471

    
472
		if (!$group) {
473
			$i++;
474
		}
475
	}
476

    
477
	if ($user_has_root_priv) {
478
		$privhtml .=		'<tr>';
479
		$privhtml .=			'<td colspan="3">';
480
		$privhtml .=				'<b>' . gettext('Security notice: This user effectively has administrator-level access') . '</b>';
481
		$privhtml .=			'</td>';
482
		$privhtml .=			'<td>';
483
		$privhtml .=			'</td>';
484
		$privhtml .=		'</tr>';
485
		
486
	}
487

    
488
	$privhtml .=		'</tbody>';
489
	$privhtml .=	'</table>';
490
	$privhtml .= '</div>';
491

    
492
	$privhtml .= '<nav class="action-buttons">';
493
	$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>';
494
	$privhtml .= '</nav>';
495

    
496
	return($privhtml);
497
}
498

    
499
function build_cert_table() {
500
	global $a_user, $id;
501

    
502
	$certhtml = '<div class="table-responsive">';
503
	$certhtml .=	'<table class="table table-striped table-hover table-condensed">';
504
	$certhtml .=		'<thead>';
505
	$certhtml .=			'<tr>';
506
	$certhtml .=				'<th>' . gettext('Name') . '</th>';
507
	$certhtml .=				'<th>' . gettext('CA') . '</th>';
508
	$certhtml .=				'<th></th>';
509
	$certhtml .=			'</tr>';
510
	$certhtml .=		'</thead>';
511
	$certhtml .=		'<tbody>';
512

    
513
	$a_cert = $a_user[$id]['cert'];
514
	if (is_array($a_cert)) {
515
		$i = 0;
516
		foreach ($a_cert as $certref) {
517
			$cert = lookup_cert($certref);
518
			$ca = lookup_ca($cert['caref']);
519
			$revokedstr =	is_cert_revoked($cert) ? '<b> Revoked</b>':'';
520

    
521
			$certhtml .=	'<tr>';
522
			$certhtml .=		'<td>' . htmlspecialchars($cert['descr']) . $revokedstr . '</td>';
523
			$certhtml .=		'<td>' . htmlspecialchars($ca['descr']) . '</td>';
524
			$certhtml .=		'<td>';
525
			$certhtml .=			'<a id="delcert' . $i .'" class="fa fa-trash no-confirm icon-pointer" title="';
526
			$certhtml .=			gettext('Remove this certificate association? (Certificate will not be deleted)') . '"></a>';
527
			$certhtml .=		'</td>';
528
			$certhtml .=	'</tr>';
529
			$i++;
530
		}
531

    
532
	}
533

    
534
	$certhtml .=		'</tbody>';
535
	$certhtml .=	'</table>';
536
	$certhtml .= '</div>';
537

    
538
	$certhtml .= '<nav class="action-buttons">';
539
	$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>';
540
	$certhtml .= '</nav>';
541

    
542
	return($certhtml);
543
}
544

    
545
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
546
$pglinks = array("", "system_usermanager.php", "system_usermanager.php");
547

    
548
if ($act == "new" || $act == "edit" || $input_errors) {
549
	$pgtitle[] = gettext('Edit');
550
	$pglinks[] = "@self";
551
}
552
include("head.inc");
553

    
554
if ($delete_errors) {
555
	print_input_errors($delete_errors);
556
}
557

    
558
if ($input_errors) {
559
	print_input_errors($input_errors);
560
}
561

    
562
if ($savemsg) {
563
	print_info_box($savemsg, 'success');
564
}
565

    
566
$tab_array = array();
567
$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
568
$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
569
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
570
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
571
display_top_tabs($tab_array);
572

    
573
if (!($act == "new" || $act == "edit" || $input_errors)) {
574
?>
575
<form method="post">
576
<div class="panel panel-default">
577
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Users')?></h2></div>
578
	<div class="panel-body">
579
		<div class="table-responsive">
580
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
581
				<thead>
582
					<tr>
583
						<th>&nbsp;</th>
584
						<th><?=gettext("Username")?></th>
585
						<th><?=gettext("Full name")?></th>
586
						<th><?=gettext("Disabled")?></th>
587
						<th><?=gettext("Groups")?></th>
588
						<th><?=gettext("Actions")?></th>
589
					</tr>
590
				</thead>
591
				<tbody>
592
<?php
593
foreach ($a_user as $i => $userent):
594
	?>
595
					<tr>
596
						<td>
597
							<input type="checkbox" id="frc<?=$i?>" name="delete_check[]" value="<?=$i?>" <?=((($userent['scope'] == "system") || ($userent['name'] == $_SESSION['Username'])) ? 'disabled' : '')?>/>
598
						</td>
599
						<td>
600
<?php
601
	if ($userent['scope'] != "user") {
602
		$usrimg = 'eye-open';
603
	} else {
604
		$usrimg = 'user';
605
	}
606
?>
607
							<i class="fa fa-<?=$usrimg?>"></i>
608
							<?=htmlspecialchars($userent['name'])?>
609
						</td>
610
						<td><?=htmlspecialchars($userent['descr'])?></td>
611
						<td><?php if (isset($userent['disabled'])) echo "*"?></td>
612
						<td><?=implode(",", local_user_get_groups($userent))?></td>
613
						<td>
614
							<a class="fa fa-pencil" title="<?=gettext("Edit user"); ?>" href="?act=edit&amp;userid=<?=$i?>"></a>
615
<?php if (($userent['scope'] != "system") && ($userent['name'] != $_SESSION['Username'])): ?>
616
							<a class="fa fa-trash"	title="<?=gettext("Delete user")?>" href="?act=deluser&amp;userid=<?=$i?>&amp;username=<?=$userent['name']?>"></a>
617
<?php endif; ?>
618
						</td>
619
					</tr>
620
<?php endforeach; ?>
621
				</tbody>
622
			</table>
623
		</div>
624
	</div>
625
</div>
626
<nav class="action-buttons">
627
	<a href="?act=new" class="btn btn-sm btn-success">
628
		<i class="fa fa-plus icon-embed-btn"></i>
629
		<?=gettext("Add")?>
630
	</a>
631

    
632
	<button type="submit" class="btn btn-sm btn-danger" name="dellall" value="dellall" title="<?=gettext('Delete selected users')?>">
633
		<i class="fa fa-trash icon-embed-btn"></i>
634
		<?=gettext("Delete")?>
635
	</button>
636
</nav>
637
</form>
638
<div class="infoblock">
639
<?php
640
	print_callout('<p>' . gettext("Additional users can be added here. User permissions for accessing " .
641
		"the webConfigurator can be assigned directly or inherited from group memberships. " .
642
		"Some system object properties can be modified but they cannot be deleted.") . '</p>' .
643
		'<p>' . gettext("Accounts added here are also used for other parts of the system " .
644
		"such as OpenVPN, IPsec, and Captive Portal.") . '</p>'
645
	);
646
?></div><?php
647
	include("foot.inc");
648
	exit;
649
}
650

    
651
$form = new Form;
652

    
653
if ($act == "new" || $act == "edit" || $input_errors):
654

    
655
	$form->addGlobal(new Form_Input(
656
		'act',
657
		null,
658
		'hidden',
659
		''
660
	));
661

    
662
	$form->addGlobal(new Form_Input(
663
		'userid',
664
		null,
665
		'hidden',
666
		isset($id) ? $id:''
667
	));
668

    
669
	$form->addGlobal(new Form_Input(
670
		'privid',
671
		null,
672
		'hidden',
673
		''
674
	));
675

    
676
	$form->addGlobal(new Form_Input(
677
		'certid',
678
		null,
679
		'hidden',
680
		''
681
	));
682

    
683
	$ro = "";
684
	if ($pconfig['utype'] == "system") {
685
		$ro = "readonly";
686
	}
687

    
688
	$section = new Form_Section('User Properties');
689

    
690
	$section->addInput(new Form_StaticText(
691
		'Defined by',
692
		strtoupper($pconfig['utype'])
693
	));
694

    
695
	$form->addGlobal(new Form_Input(
696
		'utype',
697
		null,
698
		'hidden',
699
		$pconfig['utype']
700
	));
701

    
702
	$section->addInput(new Form_Checkbox(
703
		'disabled',
704
		'Disabled',
705
		'This user cannot login',
706
		$pconfig['disabled']
707
	));
708

    
709
	$section->addInput($input = new Form_Input(
710
		'usernamefld',
711
		'*Username',
712
		'text',
713
		$pconfig['usernamefld']
714
	));
715

    
716
	if ($ro) {
717
		$input->setReadonly();
718
	}
719

    
720
	$form->addGlobal(new Form_Input(
721
		'oldusername',
722
		null,
723
		'hidden',
724
		$pconfig['usernamefld']
725
	));
726

    
727
	if ($act == "edit") {
728
		$pwd_required = "";
729
	} else {
730
		$pwd_required = "*";
731
	}
732

    
733
	$group = new Form_Group($pwd_required . 'Password');
734
	$group->add(new Form_Input(
735
		'passwordfld1',
736
		'Password',
737
		'password'
738
	));
739
	$group->add(new Form_Input(
740
		'passwordfld2',
741
		'Confirm Password',
742
		'password'
743
	));
744

    
745
	$section->add($group);
746

    
747
	$section->addInput($input = new Form_Input(
748
		'descr',
749
		'Full name',
750
		'text',
751
		htmlspecialchars($pconfig['descr'])
752
	))->setHelp('User\'s full name, for administrative information only');
753

    
754
	if ($ro) {
755
		$input->setDisabled();
756
	}
757

    
758
	$section->addInput(new Form_Input(
759
		'expires',
760
		'Expiration date',
761
		'text',
762
		$pconfig['expires']
763
	))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
764
		'the expiration date as MM/DD/YYYY');
765

    
766
	$section->addInput(new Form_Checkbox(
767
		'customsettings',
768
		'Custom Settings',
769
		'Use individual customized GUI options and dashboard layout for this user.',
770
		$pconfig['customsettings']
771
	));
772

    
773
	gen_user_settings_fields($section, $pconfig);
774

    
775
	// ==== Group membership ==================================================
776
	$group = new Form_Group('Group membership');
777

    
778
	// Make a list of all the groups configured on the system, and a list of
779
	// those which this user is a member of
780
	$systemGroups = array();
781
	$usersGroups = array();
782

    
783
	$usergid = [$pconfig['usernamefld']];
784

    
785
	foreach ($config['system']['group'] as $Ggroup) {
786
		if ($Ggroup['name'] != "all") {
787
			if (($act == 'edit') && $Ggroup['member'] && in_array($pconfig['uid'], $Ggroup['member'])) {
788
				$usersGroups[ $Ggroup['name'] ] = $Ggroup['name'];	// Add it to the user's list
789
			} else {
790
				$systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
791
			}
792
		}
793
	}
794

    
795
	$group->add(new Form_Select(
796
		'sysgroups',
797
		null,
798
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
799
		$systemGroups,
800
		true
801
	))->setHelp('Not member of');
802

    
803
	$group->add(new Form_Select(
804
		'groups',
805
		null,
806
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
807
		$usersGroups,
808
		true
809
	))->setHelp('Member of');
810

    
811
	$section->add($group);
812

    
813
	$group = new Form_Group('');
814

    
815
	$group->add(new Form_Button(
816
		'movetoenabled',
817
		'Move to "Member of" list',
818
		null,
819
		'fa-angle-double-right'
820
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
821

    
822
	$group->add(new Form_Button(
823
		'movetodisabled',
824
		'Move to "Not member of" list',
825
		null,
826
		'fa-angle-double-left'
827
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
828

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

    
832
	// ==== Button for adding user certificate ================================
833
	if ($act == 'new') {
834
		$section->addInput(new Form_Checkbox(
835
			'showcert',
836
			'Certificate',
837
			'Click to create a user certificate',
838
			false
839
		));
840
	}
841

    
842
	$form->add($section);
843

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

    
849
		$section = new Form_Section('Effective Privileges');
850

    
851
		$section->addInput(new Form_StaticText(
852
			null,
853
			build_priv_table()
854
		));
855

    
856
		$form->add($section);
857

    
858
		// ==== Certificate table section =====================================
859
		$section = new Form_Section('User Certificates');
860

    
861
		$section->addInput(new Form_StaticText(
862
			null,
863
			build_cert_table()
864
		));
865

    
866
		$form->add($section);
867
	}
868

    
869
	// ==== Add user certificate for a new user
870
	if (is_array($config['ca']) && count($config['ca']) > 0) {
871
		$section = new Form_Section('Create Certificate for User');
872
		$section->addClass('cert-options');
873

    
874
		$nonPrvCas = array();
875
		foreach ($config['ca'] as $ca) {
876
			if (!$ca['prv']) {
877
				continue;
878
			}
879

    
880
			$nonPrvCas[ $ca['refid'] ] = $ca['descr'];
881
		}
882

    
883
		if (!empty($nonPrvCas)) {
884
			$section->addInput(new Form_Input(
885
				'name',
886
				'Descriptive name',
887
				'text',
888
				$pconfig['name']
889
			));
890

    
891
			$section->addInput(new Form_Select(
892
				'caref',
893
				'Certificate authority',
894
				null,
895
				$nonPrvCas
896
			));
897

    
898
			$section->addInput(new Form_Select(
899
				'keylen',
900
				'Key length',
901
				2048,
902
				array(
903
					512 => '512 bits',
904
					1024 => '1024 bits',
905
					2048 => '2048 bits',
906
					3072 => '3072 bits',
907
					4096 => '4096 bits',
908
					7680 => '7680 bits',
909
					8192 => '8192 bits',
910
					15360 => '15360 bits',
911
					16384 => '16384 bits'
912
				)
913
			))->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;.');
914

    
915
			$section->addInput(new Form_Input(
916
				'lifetime',
917
				'Lifetime',
918
				'number',
919
				$pconfig['lifetime']
920
			));
921
		}
922

    
923
		$form->add($section);
924
	}
925

    
926
endif;
927
// ==== Paste a key for the new user
928
$section = new Form_Section('Keys');
929

    
930
$section->addInput(new Form_Checkbox(
931
	'showkey',
932
	'Authorized keys',
933
	'Click to paste an authorized key',
934
	false
935
));
936

    
937
$section->addInput(new Form_Textarea(
938
	'authorizedkeys',
939
	'Authorized SSH Keys',
940
	$pconfig['authorizedkeys']
941
))->setHelp('Enter authorized SSH keys for this user');
942

    
943
$section->addInput(new Form_Input(
944
	'ipsecpsk',
945
	'IPsec Pre-Shared Key',
946
	'text',
947
	$pconfig['ipsecpsk']
948
));
949

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

    
952
print $form;
953

    
954
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
955
?>
956
<script type="text/javascript">
957
//<![CDATA[
958
events.push(function() {
959

    
960
	function setcustomoptions() {
961
		var adv = $('#customsettings').prop('checked');
962

    
963
		hideInput('webguicss', !adv);
964
		hideInput('webguifixedmenu', !adv);
965
		hideInput('webguihostnamemenu', !adv);
966
		hideInput('dashboardcolumns', !adv);
967
		hideCheckbox('dashboardavailablewidgetspanel', !adv);
968
		hideCheckbox('systemlogsfilterpanel', !adv);
969
		hideCheckbox('systemlogsmanagelogpanel', !adv);
970
		hideCheckbox('statusmonitoringsettingspanel', !adv);
971
		hideCheckbox('webguileftcolumnhyper', !adv);
972
		hideCheckbox('pagenamefirst', !adv);
973
	}
974

    
975
	// Handle displaying a warning message if a user-created theme is selected.
976
	function setThemeWarning() {
977
		if ($('#webguicss').val().startsWith("pfSense")) {
978
			$('#csstxt').html("").addClass("text-default");
979
		} else {
980
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
981
		}
982
	}
983

    
984
	$('#webguicss').change(function() {
985
		setThemeWarning();
986
	});
987

    
988
	setThemeWarning();
989

    
990
	// On click . .
991
	$('#customsettings').click(function () {
992
		setcustomoptions();
993
	});
994

    
995
	$("#movetodisabled").click(function() {
996
		moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
997
	});
998

    
999
	$("#movetoenabled").click(function() {
1000
		moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1001
	});
1002

    
1003
	$("#showcert").click(function() {
1004
		hideClass('cert-options', !this.checked);
1005
	});
1006

    
1007
	$("#showkey").click(function() {
1008
		hideInput('authorizedkeys', false);
1009
		hideCheckbox('showkey', true);
1010
	});
1011

    
1012
	$('[id^=delcert]').click(function(event) {
1013
		if (confirm(event.target.title)) {
1014
			$('#certid').val(event.target.id.match(/\d+$/)[0]);
1015
			$('#userid').val('<?=$id;?>');
1016
			$('#act').val('delcert');
1017
			$('form').submit();
1018
		}
1019
	});
1020

    
1021
	$('[id^=delprivid]').click(function(event) {
1022
		if (confirm(event.target.title)) {
1023
			$('#privid').val(event.target.id.match(/\d+$/)[0]);
1024
			$('#userid').val('<?=$id;?>');
1025
			$('#act').val('delprivid');
1026
			$('form').submit();
1027
		}
1028
	});
1029

    
1030
	$('#expires').datepicker();
1031

    
1032
	// ---------- On initial page load ------------------------------------------------------------
1033

    
1034
	hideClass('cert-options', true);
1035
	//hideInput('authorizedkeys', true);
1036
	hideCheckbox('showkey', true);
1037
	setcustomoptions();
1038

    
1039
	// On submit mark all the user's groups as "selected"
1040
	$('form').submit(function() {
1041
		AllServers($('[name="groups[]"] option'), true);
1042
	});
1043
});
1044
//]]>
1045
</script>
1046
<?php
1047
include('foot.inc');
1048
?>
(206-206/225)