Project

General

Profile

Download (31.1 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

    
54
if (isset($_POST['act'])) {
55
	$act = $_POST['act'];
56
} else {
57
	$act = $_GET['act'];
58
}
59

    
60
if (isset($_SERVER['HTTP_REFERER'])) {
61
	$referer = $_SERVER['HTTP_REFERER'];
62
} else {
63
	$referer = '/system_usermanager.php';
64
}
65

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

    
90
if ($_POST['act'] == "deluser") {
91

    
92
	if (!isset($_POST['username']) || !isset($a_user[$id]) || ($_POST['username'] != $a_user[$id]['name'])) {
93
		pfSenseHeader("system_usermanager.php");
94
		exit;
95
	}
96

    
97
	if ($_POST['username'] == $_SESSION['Username']) {
98
		$delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $_POST['username']);
99
	} else {
100
		local_user_del($a_user[$id]);
101
		$userdeleted = $a_user[$id]['name'];
102
		unset($a_user[$id]);
103
		write_config();
104
		$savemsg = sprintf(gettext("User %s successfully deleted."), $userdeleted);
105
	}
106

    
107
} else if ($act == "new") {
108
	/*
109
	 * set this value cause the text field is read only
110
	 * and the user should not be able to mess with this
111
	 * setting.
112
	 */
113
	$pconfig['utype'] = "user";
114
	$pconfig['lifetime'] = 3650;
115
}
116

    
117
if (isset($_POST['dellall'])) {
118

    
119
	$del_users = $_POST['delete_check'];
120
	$deleted_users = "";
121
	$deleted_count = 0;
122
	$comma = "";
123

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

    
141
		if ($deleted_count > 0) {
142
			if ($deleted_count == 1) {
143
				$savemsg = sprintf(gettext("User %s successfully deleted."), $deleted_users);
144
			} else {
145
				$savemsg = sprintf(gettext("Users %s successfully deleted."), $deleted_users);
146
			}
147
			write_config($savemsg);
148
		}
149
	}
150
}
151

    
152
if ($_POST['act'] == "delcert") {
153

    
154
	if (!$a_user[$id]) {
155
		pfSenseHeader("system_usermanager.php");
156
		exit;
157
	}
158

    
159
	$certdeleted = lookup_cert($a_user[$id]['cert'][$_POST['certid']]);
160
	$certdeleted = $certdeleted['descr'];
161
	unset($a_user[$id]['cert'][$_POST['certid']]);
162
	write_config();
163
	$_POST['act'] = "edit";
164
	$savemsg = sprintf(gettext("Certificate %s association removed."), $certdeleted);
165
}
166

    
167
if ($_POST['act'] == "delprivid") {
168
	$privdeleted = $priv_list[$a_user[$id]['priv'][$_POST['privid']]]['name'];
169
	unset($a_user[$id]['priv'][$_POST['privid']]);
170
	local_user_set($a_user[$id]);
171
	write_config();
172
	$_POST['act'] = "edit";
173
	$savemsg = sprintf(gettext("Privilege %s removed."), $privdeleted);
174
}
175

    
176
if ($_POST['save']) {
177
	unset($input_errors);
178
	$pconfig = $_POST;
179

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

    
202
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
203

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

    
208
	if (strlen($_POST['usernamefld']) > 16) {
209
		$input_errors[] = gettext("The username is longer than 16 characters.");
210
	}
211

    
212
	if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) {
213
		$input_errors[] = gettext("The passwords do not match.");
214
	}
215

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

    
220
	/* Check the POSTed groups to ensure they are valid and exist */
221
	if (is_array($_POST['groups'])) {
222
		foreach ($_POST['groups'] as $newgroup) {
223
			if (empty(getGroupEntry($newgroup))) {
224
				$input_errors[] = gettext("One or more invalid groups was submitted.");
225
			}
226
		}
227
	}
228

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

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

    
273
	if (!empty($_POST['name'])) {
274
		$ca = lookup_ca($_POST['caref']);
275
		if (!$ca) {
276
			$input_errors[] = gettext("Invalid internal Certificate Authority") . "\n";
277
		}
278
	}
279

    
280
	if (!$input_errors) {
281

    
282
		$userent = array();
283
		if (isset($id) && $a_user[$id]) {
284
			$userent = $a_user[$id];
285
		}
286

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

    
289
		/* the user name was modified */
290
		if (!empty($_POST['oldusername']) && ($_POST['usernamefld'] <> $_POST['oldusername'])) {
291
			$_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
292
			local_user_del($userent);
293
		}
294

    
295
		/* the user password was modified */
296
		if ($_POST['passwordfld1']) {
297
			local_user_set_password($userent, $_POST['passwordfld1']);
298
		}
299

    
300
		/* only change description if sent */
301
		if (isset($_POST['descr'])) {
302
			$userent['descr'] = $_POST['descr'];
303
		}
304

    
305
		$userent['name'] = $_POST['usernamefld'];
306
		$userent['expires'] = $_POST['expires'];
307
		$userent['dashboardcolumns'] = $_POST['dashboardcolumns'];
308
		$userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
309
		$userent['ipsecpsk'] = $_POST['ipsecpsk'];
310

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

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

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

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

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

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

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

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

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

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

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

    
377
		if (isset($id) && $a_user[$id]) {
378
			$a_user[$id] = $userent;
379
		} else {
380
			if (!empty($_POST['name'])) {
381
				$cert = array();
382
				$cert['refid'] = uniqid();
383
				$userent['cert'] = array();
384

    
385
				$cert['descr'] = $_POST['name'];
386

    
387
				$subject = cert_get_subject_array($ca['crt']);
388

    
389
				$dn = array(
390
					'countryName' => $subject[0]['v'],
391
					'stateOrProvinceName' => $subject[1]['v'],
392
					'localityName' => $subject[2]['v'],
393
					'organizationName' => $subject[3]['v'],
394
					'emailAddress' => $subject[4]['v'],
395
					'commonName' => $userent['name']);
396

    
397
				cert_create($cert, $_POST['caref'], $_POST['keylen'],
398
					(int)$_POST['lifetime'], $dn);
399

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

    
418
			$a_user[] = $userent;
419
		}
420

    
421
		/* 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. */
422
		local_user_set_groups($userent, $_POST['groups']);
423
		local_user_set($userent);
424
		/* 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. */
425
		local_user_set_groups($userent, $_POST['groups']);
426
		write_config();
427

    
428
		if (is_dir("/etc/inc/privhooks")) {
429
			run_plugins("/etc/inc/privhooks");
430
		}
431

    
432

    
433
		pfSenseHeader("system_usermanager.php");
434
	}
435
}
436

    
437
function build_priv_table() {
438
	global $a_user, $id;
439

    
440
	$privhtml = '<div class="table-responsive">';
441
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
442
	$privhtml .=		'<thead>';
443
	$privhtml .=			'<tr>';
444
	$privhtml .=				'<th>' . gettext('Inherited from') . '</th>';
445
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
446
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
447
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
448
	$privhtml .=			'</tr>';
449
	$privhtml .=		'</thead>';
450
	$privhtml .=		'<tbody>';
451

    
452
	$i = 0;
453
	$user_has_root_priv = false;
454

    
455
	foreach (get_user_privdesc($a_user[$id]) as $priv) {
456
		$group = false;
457
		if ($priv['group']) {
458
			$group = $priv['group'];
459
		}
460

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

    
475
		$privhtml .=			'</td>';
476
		$privhtml .=		'</tr>';
477

    
478
		if (!$group) {
479
			$i++;
480
		}
481
	}
482

    
483
	if ($user_has_root_priv) {
484
		$privhtml .=		'<tr>';
485
		$privhtml .=			'<td colspan="3">';
486
		$privhtml .=				'<b>' . gettext('Security notice: This user effectively has administrator-level access') . '</b>';
487
		$privhtml .=			'</td>';
488
		$privhtml .=			'<td>';
489
		$privhtml .=			'</td>';
490
		$privhtml .=		'</tr>';
491

    
492
	}
493

    
494
	$privhtml .=		'</tbody>';
495
	$privhtml .=	'</table>';
496
	$privhtml .= '</div>';
497

    
498
	$privhtml .= '<nav class="action-buttons">';
499
	$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>';
500
	$privhtml .= '</nav>';
501

    
502
	return($privhtml);
503
}
504

    
505
function build_cert_table() {
506
	global $a_user, $id;
507

    
508
	$certhtml = '<div class="table-responsive">';
509
	$certhtml .=	'<table class="table table-striped table-hover table-condensed">';
510
	$certhtml .=		'<thead>';
511
	$certhtml .=			'<tr>';
512
	$certhtml .=				'<th>' . gettext('Name') . '</th>';
513
	$certhtml .=				'<th>' . gettext('CA') . '</th>';
514
	$certhtml .=				'<th></th>';
515
	$certhtml .=			'</tr>';
516
	$certhtml .=		'</thead>';
517
	$certhtml .=		'<tbody>';
518

    
519
	$a_cert = $a_user[$id]['cert'];
520
	if (is_array($a_cert)) {
521
		$i = 0;
522
		foreach ($a_cert as $certref) {
523
			$cert = lookup_cert($certref);
524
			$ca = lookup_ca($cert['caref']);
525
			$revokedstr =	is_cert_revoked($cert) ? '<b> Revoked</b>':'';
526

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

    
538
	}
539

    
540
	$certhtml .=		'</tbody>';
541
	$certhtml .=	'</table>';
542
	$certhtml .= '</div>';
543

    
544
	$certhtml .= '<nav class="action-buttons">';
545
	$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>';
546
	$certhtml .= '</nav>';
547

    
548
	return($certhtml);
549
}
550

    
551
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
552
$pglinks = array("", "system_usermanager.php", "system_usermanager.php");
553

    
554
if ($act == "new" || $act == "edit" || $input_errors) {
555
	$pgtitle[] = gettext('Edit');
556
	$pglinks[] = "@self";
557
}
558
include("head.inc");
559

    
560
if ($delete_errors) {
561
	print_input_errors($delete_errors);
562
}
563

    
564
if ($input_errors) {
565
	print_input_errors($input_errors);
566
}
567

    
568
if ($savemsg) {
569
	print_info_box($savemsg, 'success');
570
}
571

    
572
$tab_array = array();
573
$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
574
$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
575
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
576
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
577
display_top_tabs($tab_array);
578

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

    
638
	<button type="submit" class="btn btn-sm btn-danger" name="dellall" value="dellall" title="<?=gettext('Delete selected users')?>">
639
		<i class="fa fa-trash icon-embed-btn"></i>
640
		<?=gettext("Delete")?>
641
	</button>
642

    
643
</nav>
644
</form>
645
<div class="infoblock">
646
<?php
647
	print_callout('<p>' . gettext("Additional users can be added here. User permissions for accessing " .
648
		"the webConfigurator can be assigned directly or inherited from group memberships. " .
649
		"Some system object properties can be modified but they cannot be deleted.") . '</p>' .
650
		'<p>' . gettext("Accounts added here are also used for other parts of the system " .
651
		"such as OpenVPN, IPsec, and Captive Portal.") . '</p>'
652
	);
653

    
654

    
655
// The scripts that follow are an EXPERIMENT in using jQuery/Javascript to automatically convert
656
// GET calls to POST calls
657
// Any anchor with the attribute "usepost" usses these functions. In this file "Edit user", "Delete user" and "Add"
658
// have that attribute
659
// These function can be moved to an included file
660

    
661
?></div>
662

    
663
<script type="text/javascript">
664
//<![CDATA[
665
events.push(function() {
666

    
667
	// Any time an anchor is clicked and the "usepost" attibute is present, convert the href attribute
668
	// to POST format, make a POST form and submit it
669
	$('a').click(function(e) {
670
		// Does the clicker anchor have the "usepost" attribute?
671
		var attr = $(this).attr('usepost');
672

    
673
		if (typeof attr !== typeof undefined && attr !== false) {
674
			var href = $(this).attr("href");
675

    
676
			postSubmit(get2post(href));
677

    
678
			return false;
679
		}
680
	});
681

    
682

    
683
	// Convert a GET argument list such as ?name=fred&action=delete into an array of POST
684
	// parameters such as [[name, fred],[action, delete]]
685
	function get2post(getargs) {
686
		var arglist = new Array();
687

    
688
		getargs = getargs.substring(getargs.indexOf("?") + 1);
689
		var argarray = getargs.split('&');
690

    
691
		for (var i=0;i<argarray.length;i++) {
692
			var thisarg = argarray[i].split('=');
693
			var arg = new Array(thisarg[0], thisarg[1]);
694
			arglist[i] = arg;
695
		}
696

    
697
		return arglist;
698
	}
699

    
700
	// Create a form, add, the POST data and submit it
701
	function postSubmit(data) {
702

    
703
	    var form = $(document.createElement('form'));
704

    
705
	    $(form).attr("method", "POST");
706

    
707
	    for (var i=0;i<data.length;i++) {
708
			var input = $("<input>").attr("type", "hidden").attr("name", data[i][0]).val(data[i][1]);
709
			$(form).append($(input));
710
	    }
711

    
712
		// The CSRF magic is required because we will be viewing the results of the POST
713
		var input = $("<input>").attr("type", "hidden").attr("name", "__csrf_magic").val($('[name=__csrf_magic]').val());
714
		$(form).append($(input));
715

    
716
        $(form).appendTo('body').submit();
717
	}
718

    
719
});
720
//]]>
721
</script>
722

    
723
<?php
724
	include("foot.inc");
725
	exit;
726
}
727

    
728
$form = new Form;
729

    
730
if ($act == "new" || $act == "edit" || $input_errors):
731

    
732
	$form->addGlobal(new Form_Input(
733
		'act',
734
		null,
735
		'hidden',
736
		''
737
	));
738

    
739
	$form->addGlobal(new Form_Input(
740
		'userid',
741
		null,
742
		'hidden',
743
		isset($id) ? $id:''
744
	));
745

    
746
	$form->addGlobal(new Form_Input(
747
		'privid',
748
		null,
749
		'hidden',
750
		''
751
	));
752

    
753
	$form->addGlobal(new Form_Input(
754
		'certid',
755
		null,
756
		'hidden',
757
		''
758
	));
759

    
760
	$ro = "";
761
	if ($pconfig['utype'] == "system") {
762
		$ro = "readonly";
763
	}
764

    
765
	$section = new Form_Section('User Properties');
766

    
767
	$section->addInput(new Form_StaticText(
768
		'Defined by',
769
		strtoupper($pconfig['utype'])
770
	));
771

    
772
	$form->addGlobal(new Form_Input(
773
		'utype',
774
		null,
775
		'hidden',
776
		$pconfig['utype']
777
	));
778

    
779
	$section->addInput(new Form_Checkbox(
780
		'disabled',
781
		'Disabled',
782
		'This user cannot login',
783
		$pconfig['disabled']
784
	));
785

    
786
	$section->addInput($input = new Form_Input(
787
		'usernamefld',
788
		'*Username',
789
		'text',
790
		$pconfig['usernamefld']
791
	));
792

    
793
	if ($ro) {
794
		$input->setReadonly();
795
	}
796

    
797
	$form->addGlobal(new Form_Input(
798
		'oldusername',
799
		null,
800
		'hidden',
801
		$pconfig['usernamefld']
802
	));
803

    
804
	if ($act == "edit") {
805
		$pwd_required = "";
806
	} else {
807
		$pwd_required = "*";
808
	}
809

    
810
	$group = new Form_Group($pwd_required . 'Password');
811
	$group->add(new Form_Input(
812
		'passwordfld1',
813
		'Password',
814
		'password'
815
	));
816
	$group->add(new Form_Input(
817
		'passwordfld2',
818
		'Confirm Password',
819
		'password'
820
	));
821

    
822
	$section->add($group);
823

    
824
	$section->addInput($input = new Form_Input(
825
		'descr',
826
		'Full name',
827
		'text',
828
		htmlspecialchars($pconfig['descr'])
829
	))->setHelp('User\'s full name, for administrative information only');
830

    
831
	if ($ro) {
832
		$input->setDisabled();
833
	}
834

    
835
	$section->addInput(new Form_Input(
836
		'expires',
837
		'Expiration date',
838
		'text',
839
		$pconfig['expires']
840
	))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
841
		'the expiration date as MM/DD/YYYY');
842

    
843
	$section->addInput(new Form_Checkbox(
844
		'customsettings',
845
		'Custom Settings',
846
		'Use individual customized GUI options and dashboard layout for this user.',
847
		$pconfig['customsettings']
848
	));
849

    
850
	gen_user_settings_fields($section, $pconfig);
851

    
852
	// ==== Group membership ==================================================
853
	$group = new Form_Group('Group membership');
854

    
855
	// Make a list of all the groups configured on the system, and a list of
856
	// those which this user is a member of
857
	$systemGroups = array();
858
	$usersGroups = array();
859

    
860
	$usergid = [$pconfig['usernamefld']];
861

    
862
	foreach ($config['system']['group'] as $Ggroup) {
863
		if ($Ggroup['name'] != "all") {
864
			if (($act == 'edit') && $Ggroup['member'] && in_array($pconfig['uid'], $Ggroup['member'])) {
865
				$usersGroups[ $Ggroup['name'] ] = $Ggroup['name'];	// Add it to the user's list
866
			} else {
867
				$systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
868
			}
869
		}
870
	}
871

    
872
	$group->add(new Form_Select(
873
		'sysgroups',
874
		null,
875
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
876
		$systemGroups,
877
		true
878
	))->setHelp('Not member of');
879

    
880
	$group->add(new Form_Select(
881
		'groups',
882
		null,
883
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
884
		$usersGroups,
885
		true
886
	))->setHelp('Member of');
887

    
888
	$section->add($group);
889

    
890
	$group = new Form_Group('');
891

    
892
	$group->add(new Form_Button(
893
		'movetoenabled',
894
		'Move to "Member of" list',
895
		null,
896
		'fa-angle-double-right'
897
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
898

    
899
	$group->add(new Form_Button(
900
		'movetodisabled',
901
		'Move to "Not member of" list',
902
		null,
903
		'fa-angle-double-left'
904
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
905

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

    
909
	// ==== Button for adding user certificate ================================
910
	if ($act == 'new') {
911
		$section->addInput(new Form_Checkbox(
912
			'showcert',
913
			'Certificate',
914
			'Click to create a user certificate',
915
			false
916
		));
917
	}
918

    
919
	$form->add($section);
920

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

    
926
		$section = new Form_Section('Effective Privileges');
927

    
928
		$section->addInput(new Form_StaticText(
929
			null,
930
			build_priv_table()
931
		));
932

    
933
		$form->add($section);
934

    
935
		// ==== Certificate table section =====================================
936
		$section = new Form_Section('User Certificates');
937

    
938
		$section->addInput(new Form_StaticText(
939
			null,
940
			build_cert_table()
941
		));
942

    
943
		$form->add($section);
944
	}
945

    
946
	// ==== Add user certificate for a new user
947
	if (is_array($config['ca']) && count($config['ca']) > 0) {
948
		$section = new Form_Section('Create Certificate for User');
949
		$section->addClass('cert-options');
950

    
951
		$nonPrvCas = array();
952
		foreach ($config['ca'] as $ca) {
953
			if (!$ca['prv']) {
954
				continue;
955
			}
956

    
957
			$nonPrvCas[ $ca['refid'] ] = $ca['descr'];
958
		}
959

    
960
		if (!empty($nonPrvCas)) {
961
			$section->addInput(new Form_Input(
962
				'name',
963
				'Descriptive name',
964
				'text',
965
				$pconfig['name']
966
			));
967

    
968
			$section->addInput(new Form_Select(
969
				'caref',
970
				'Certificate authority',
971
				null,
972
				$nonPrvCas
973
			));
974

    
975
			$section->addInput(new Form_Select(
976
				'keylen',
977
				'Key length',
978
				2048,
979
				array(
980
					512 => '512 bits',
981
					1024 => '1024 bits',
982
					2048 => '2048 bits',
983
					3072 => '3072 bits',
984
					4096 => '4096 bits',
985
					7680 => '7680 bits',
986
					8192 => '8192 bits',
987
					15360 => '15360 bits',
988
					16384 => '16384 bits'
989
				)
990
			))->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;.');
991

    
992
			$section->addInput(new Form_Input(
993
				'lifetime',
994
				'Lifetime',
995
				'number',
996
				$pconfig['lifetime']
997
			));
998
		}
999

    
1000
		$form->add($section);
1001
	}
1002

    
1003
endif;
1004
// ==== Paste a key for the new user
1005
$section = new Form_Section('Keys');
1006

    
1007
$section->addInput(new Form_Checkbox(
1008
	'showkey',
1009
	'Authorized keys',
1010
	'Click to paste an authorized key',
1011
	false
1012
));
1013

    
1014
$section->addInput(new Form_Textarea(
1015
	'authorizedkeys',
1016
	'Authorized SSH Keys',
1017
	$pconfig['authorizedkeys']
1018
))->setHelp('Enter authorized SSH keys for this user');
1019

    
1020
$section->addInput(new Form_Input(
1021
	'ipsecpsk',
1022
	'IPsec Pre-Shared Key',
1023
	'text',
1024
	$pconfig['ipsecpsk']
1025
));
1026

    
1027
$form->add($section);
1028

    
1029
print $form;
1030

    
1031
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
1032
?>
1033
<script type="text/javascript">
1034
//<![CDATA[
1035
events.push(function() {
1036

    
1037
	function setcustomoptions() {
1038
		var adv = $('#customsettings').prop('checked');
1039

    
1040
		hideInput('webguicss', !adv);
1041
		hideInput('webguifixedmenu', !adv);
1042
		hideInput('webguihostnamemenu', !adv);
1043
		hideInput('dashboardcolumns', !adv);
1044
		hideCheckbox('dashboardavailablewidgetspanel', !adv);
1045
		hideCheckbox('systemlogsfilterpanel', !adv);
1046
		hideCheckbox('systemlogsmanagelogpanel', !adv);
1047
		hideCheckbox('statusmonitoringsettingspanel', !adv);
1048
		hideCheckbox('webguileftcolumnhyper', !adv);
1049
		hideCheckbox('pagenamefirst', !adv);
1050
	}
1051

    
1052
	// Handle displaying a warning message if a user-created theme is selected.
1053
	function setThemeWarning() {
1054
		if ($('#webguicss').val().startsWith("pfSense")) {
1055
			$('#csstxt').html("").addClass("text-default");
1056
		} else {
1057
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
1058
		}
1059
	}
1060

    
1061
	$('#webguicss').change(function() {
1062
		setThemeWarning();
1063
	});
1064

    
1065
	setThemeWarning();
1066

    
1067
	// On click . .
1068
	$('#customsettings').click(function () {
1069
		setcustomoptions();
1070
	});
1071

    
1072
	$("#movetodisabled").click(function() {
1073
		moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
1074
	});
1075

    
1076
	$("#movetoenabled").click(function() {
1077
		moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1078
	});
1079

    
1080
	$("#showcert").click(function() {
1081
		hideClass('cert-options', !this.checked);
1082
	});
1083

    
1084
	$("#showkey").click(function() {
1085
		hideInput('authorizedkeys', false);
1086
		hideCheckbox('showkey', true);
1087
	});
1088

    
1089
	$('[id^=delcert]').click(function(event) {
1090
		if (confirm(event.target.title)) {
1091
			$('#certid').val(event.target.id.match(/\d+$/)[0]);
1092
			$('#userid').val('<?=$id;?>');
1093
			$('#act').val('delcert');
1094
			$('form').submit();
1095
		}
1096
	});
1097

    
1098
	$('[id^=delprivid]').click(function(event) {
1099
		if (confirm(event.target.title)) {
1100
			$('#privid').val(event.target.id.match(/\d+$/)[0]);
1101
			$('#userid').val('<?=$id;?>');
1102
			$('#act').val('delprivid');
1103
			$('form').submit();
1104
		}
1105
	});
1106

    
1107
	$('#expires').datepicker();
1108

    
1109
	// ---------- On initial page load ------------------------------------------------------------
1110

    
1111
	hideClass('cert-options', true);
1112
	//hideInput('authorizedkeys', true);
1113
	hideCheckbox('showkey', true);
1114
	setcustomoptions();
1115

    
1116
	// On submit mark all the user's groups as "selected"
1117
	$('form').submit(function() {
1118
		AllServers($('[name="groups[]"] option'), true);
1119
	});
1120

    
1121
});
1122
//]]>
1123
</script>
1124
<?php
1125
include('foot.inc');
1126
?>
(204-204/223)