Project

General

Profile

Download (31.4 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-2018 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
		/* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
133
		$a_user = array_values($a_user);
134
		write_config();
135
		$savemsg = sprintf(gettext("User %s successfully deleted."), $userdeleted);
136
	}
137
} else if ($act == "new") {
138
	/*
139
	 * set this value cause the text field is read only
140
	 * and the user should not be able to mess with this
141
	 * setting.
142
	 */
143
	$pconfig['utype'] = "user";
144
	$pconfig['lifetime'] = 3650;
145
}
146

    
147
if (isset($_POST['dellall'])) {
148

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

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

    
173
		if ($deleted_count > 0) {
174
			if ($deleted_count == 1) {
175
				$savemsg = sprintf(gettext("User %s successfully deleted."), $deleted_users);
176
			} else {
177
				$savemsg = sprintf(gettext("Users %s successfully deleted."), $deleted_users);
178
			}
179
			/* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
180
			$a_user = array_values($a_user);
181
			write_config($savemsg);
182
		}
183
	}
184
}
185

    
186
if ($_POST['act'] == "delcert") {
187

    
188
	if (!$a_user[$id]) {
189
		pfSenseHeader("system_usermanager.php");
190
		exit;
191
	}
192

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

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

    
210
if ($_POST['save']) {
211
	unset($input_errors);
212
	$pconfig = $_POST;
213

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

    
236
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
237

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

    
242
	if (strlen($_POST['usernamefld']) > 16) {
243
		$input_errors[] = gettext("The username is longer than 16 characters.");
244
	}
245

    
246
	if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) {
247
		$input_errors[] = gettext("The passwords do not match.");
248
	}
249

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

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

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

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

    
307
	if (!empty($_POST['name'])) {
308
		$ca = lookup_ca($_POST['caref']);
309
		if (!$ca) {
310
			$input_errors[] = gettext("Invalid internal Certificate Authority") . "\n";
311
		}
312
	}
313
	validate_webguicss_field($input_errors, $_POST['webguicss']);
314
	validate_webguifixedmenu_field($input_errors, $_POST['webguifixedmenu']);
315
	validate_webguihostnamemenu_field($input_errors, $_POST['webguihostnamemenu']);
316
	validate_dashboardcolumns_field($input_errors, $_POST['dashboardcolumns']);
317

    
318
	if (!$input_errors) {
319

    
320
		conf_mount_rw();
321
		$userent = array();
322
		if (isset($id) && $a_user[$id]) {
323
			$userent = $a_user[$id];
324
		}
325

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

    
328
		/* the user name was modified */
329
		if (!empty($_POST['oldusername']) && ($_POST['usernamefld'] <> $_POST['oldusername'])) {
330
			$_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
331
			local_user_del($userent);
332
		}
333

    
334
		/* the user password was modified */
335
		if ($_POST['passwordfld1']) {
336
			local_user_set_password($userent, $_POST['passwordfld1']);
337
		}
338

    
339
		/* only change description if sent */
340
		if (isset($_POST['descr'])) {
341
			$userent['descr'] = $_POST['descr'];
342
		}
343

    
344
		$userent['name'] = $_POST['usernamefld'];
345
		$userent['expires'] = $_POST['expires'];
346
		$userent['dashboardcolumns'] = $_POST['dashboardcolumns'];
347
		$userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
348
		$userent['ipsecpsk'] = $_POST['ipsecpsk'];
349

    
350
		if ($_POST['disabled']) {
351
			$userent['disabled'] = true;
352
		} else {
353
			unset($userent['disabled']);
354
		}
355

    
356
		if ($_POST['customsettings']) {
357
			$userent['customsettings'] = true;
358
		} else {
359
			unset($userent['customsettings']);
360
		}
361

    
362
		if ($_POST['webguicss']) {
363
			$userent['webguicss'] = $_POST['webguicss'];
364
		} else {
365
			unset($userent['webguicss']);
366
		}
367

    
368
		if ($_POST['webguifixedmenu']) {
369
			$userent['webguifixedmenu'] = $_POST['webguifixedmenu'];
370
		} else {
371
			unset($userent['webguifixedmenu']);
372
		}
373

    
374
		if ($_POST['webguihostnamemenu']) {
375
			$userent['webguihostnamemenu'] = $_POST['webguihostnamemenu'];
376
		} else {
377
			unset($userent['webguihostnamemenu']);
378
		}
379

    
380
		if ($_POST['interfacessort']) {
381
			$userent['interfacessort'] = true;
382
		} else {
383
			unset($userent['interfacessort']);
384
		}
385

    
386
		if ($_POST['dashboardavailablewidgetspanel']) {
387
			$userent['dashboardavailablewidgetspanel'] = true;
388
		} else {
389
			unset($userent['dashboardavailablewidgetspanel']);
390
		}
391

    
392
		if ($_POST['systemlogsfilterpanel']) {
393
			$userent['systemlogsfilterpanel'] = true;
394
		} else {
395
			unset($userent['systemlogsfilterpanel']);
396
		}
397

    
398
		if ($_POST['systemlogsmanagelogpanel']) {
399
			$userent['systemlogsmanagelogpanel'] = true;
400
		} else {
401
			unset($userent['systemlogsmanagelogpanel']);
402
		}
403

    
404
		if ($_POST['statusmonitoringsettingspanel']) {
405
			$userent['statusmonitoringsettingspanel'] = true;
406
		} else {
407
			unset($userent['statusmonitoringsettingspanel']);
408
		}
409

    
410
		if ($_POST['webguileftcolumnhyper']) {
411
			$userent['webguileftcolumnhyper'] = true;
412
		} else {
413
			unset($userent['webguileftcolumnhyper']);
414
		}
415

    
416
		if ($_POST['pagenamefirst']) {
417
			$userent['pagenamefirst'] = true;
418
		} else {
419
			unset($userent['pagenamefirst']);
420
		}
421

    
422
		if (isset($id) && $a_user[$id]) {
423
			$a_user[$id] = $userent;
424
		} else {
425
			if (!empty($_POST['name'])) {
426
				$cert = array();
427
				$cert['refid'] = uniqid();
428
				$userent['cert'] = array();
429

    
430
				$cert['descr'] = $_POST['name'];
431

    
432
				$subject = cert_get_subject_array($ca['crt']);
433

    
434
				$dn = array(
435
					'countryName' => $subject[0]['v'],
436
					'stateOrProvinceName' => $subject[1]['v'],
437
					'localityName' => $subject[2]['v'],
438
					'organizationName' => $subject[3]['v'],
439
					'emailAddress' => $subject[4]['v'],
440
					'commonName' => $userent['name']);
441

    
442
				cert_create($cert, $_POST['caref'], $_POST['keylen'],
443
					(int)$_POST['lifetime'], $dn);
444

    
445
				if (!is_array($config['cert'])) {
446
					$config['cert'] = array();
447
				}
448
				$config['cert'][] = $cert;
449
				$userent['cert'][] = $cert['refid'];
450
			}
451
			$userent['uid'] = $config['system']['nextuid']++;
452
			/* Add the user to All Users group. */
453
			foreach ($config['system']['group'] as $gidx => $group) {
454
				if ($group['name'] == "all") {
455
					if (!is_array($config['system']['group'][$gidx]['member'])) {
456
						$config['system']['group'][$gidx]['member'] = array();
457
					}
458
					$config['system']['group'][$gidx]['member'][] = $userent['uid'];
459
					break;
460
				}
461
			}
462

    
463
			$a_user[] = $userent;
464
		}
465

    
466
		/* 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. */
467
		local_user_set_groups($userent, $_POST['groups']);
468
		local_user_set($userent);
469
		/* 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. */
470
		local_user_set_groups($userent, $_POST['groups']);
471
		write_config();
472

    
473
		if (is_dir("/etc/inc/privhooks")) {
474
			run_plugins("/etc/inc/privhooks");
475
		}
476

    
477
		conf_mount_ro();
478

    
479
		pfSenseHeader("system_usermanager.php");
480
	}
481
}
482

    
483
function build_priv_table() {
484
	global $a_user, $id;
485

    
486
	$privhtml = '<div class="table-responsive">';
487
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
488
	$privhtml .=		'<thead>';
489
	$privhtml .=			'<tr>';
490
	$privhtml .=				'<th>' . gettext('Inherited from') . '</th>';
491
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
492
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
493
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
494
	$privhtml .=			'</tr>';
495
	$privhtml .=		'</thead>';
496
	$privhtml .=		'<tbody>';
497

    
498
	$i = 0;
499

    
500
	foreach (get_user_privdesc($a_user[$id]) as $priv) {
501
		$group = false;
502
		if ($priv['group']) {
503
			$group = $priv['group'];
504
		}
505

    
506
		$privhtml .=		'<tr>';
507
		$privhtml .=			'<td>' . htmlspecialchars($priv['group']) . '</td>';
508
		$privhtml .=			'<td>' . htmlspecialchars($priv['name']) . '</td>';
509
		$privhtml .=			'<td>' . htmlspecialchars($priv['descr']) . '</td>';
510
		$privhtml .=			'<td>';
511
		if (!$group) {
512
			$privhtml .=			'<a class="fa fa-trash no-confirm icon-pointer" title="' . gettext('Delete Privilege') . '" id="delprivid' . $i . '"></a>';
513
		}
514

    
515
		$privhtml .=			'</td>';
516
		$privhtml .=		'</tr>';
517

    
518
		if (!$group) {
519
			$i++;
520
		}
521
	}
522

    
523
	$privhtml .=		'</tbody>';
524
	$privhtml .=	'</table>';
525
	$privhtml .= '</div>';
526

    
527
	$privhtml .= '<nav class="action-buttons">';
528
	$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>';
529
	$privhtml .= '</nav>';
530

    
531
	return($privhtml);
532
}
533

    
534
function build_cert_table() {
535
	global $a_user, $id;
536

    
537
	$certhtml = '<div class="table-responsive">';
538
	$certhtml .=	'<table class="table table-striped table-hover table-condensed">';
539
	$certhtml .=		'<thead>';
540
	$certhtml .=			'<tr>';
541
	$certhtml .=				'<th>' . gettext('Name') . '</th>';
542
	$certhtml .=				'<th>' . gettext('CA') . '</th>';
543
	$certhtml .=				'<th></th>';
544
	$certhtml .=			'</tr>';
545
	$certhtml .=		'</thead>';
546
	$certhtml .=		'<tbody>';
547

    
548
	$a_cert = $a_user[$id]['cert'];
549
	if (is_array($a_cert)) {
550
		$i = 0;
551
		foreach ($a_cert as $certref) {
552
			$cert = lookup_cert($certref);
553
			$ca = lookup_ca($cert['caref']);
554
			$revokedstr =	is_cert_revoked($cert) ? '<b> Revoked</b>':'';
555

    
556
			$certhtml .=	'<tr>';
557
			$certhtml .=		'<td>' . htmlspecialchars($cert['descr']) . $revokedstr . '</td>';
558
			$certhtml .=		'<td>' . htmlspecialchars($ca['descr']) . '</td>';
559
			$certhtml .=		'<td>';
560
			$certhtml .=			'<a id="delcert' . $i .'" class="fa fa-trash no-confirm icon-pointer" title="';
561
			$certhtml .=			gettext('Remove this certificate association? (Certificate will not be deleted)') . '"></a>';
562
			$certhtml .=		'</td>';
563
			$certhtml .=	'</tr>';
564
			$i++;
565
		}
566

    
567
	}
568

    
569
	$certhtml .=		'</tbody>';
570
	$certhtml .=	'</table>';
571
	$certhtml .= '</div>';
572

    
573
	$certhtml .= '<nav class="action-buttons">';
574
	$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>';
575
	$certhtml .= '</nav>';
576

    
577
	return($certhtml);
578
}
579

    
580
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
581
$pglinks = array("", "system_usermanager.php", "system_usermanager.php");
582

    
583
if ($act == "new" || $act == "edit" || $input_errors) {
584
	$pgtitle[] = gettext('Edit');
585
	$pglinks[] = "@self";
586
}
587
include("head.inc");
588

    
589
if ($delete_errors) {
590
	print_input_errors($delete_errors);
591
}
592

    
593
if ($input_errors) {
594
	print_input_errors($input_errors);
595
}
596

    
597
if ($savemsg) {
598
	print_info_box($savemsg, 'success');
599
}
600

    
601
$tab_array = array();
602
$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
603
$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
604
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
605
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
606
display_top_tabs($tab_array);
607

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

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

    
686
$form = new Form;
687

    
688
if ($act == "new" || $act == "edit" || $input_errors):
689

    
690
	$form->addGlobal(new Form_Input(
691
		'act',
692
		null,
693
		'hidden',
694
		''
695
	));
696

    
697
	$form->addGlobal(new Form_Input(
698
		'userid',
699
		null,
700
		'hidden',
701
		isset($id) ? $id:''
702
	));
703

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

    
711
	$form->addGlobal(new Form_Input(
712
		'certid',
713
		null,
714
		'hidden',
715
		''
716
	));
717

    
718
	$ro = "";
719
	if ($pconfig['utype'] == "system") {
720
		$ro = "readonly";
721
	}
722

    
723
	$section = new Form_Section('User Properties');
724

    
725
	$section->addInput(new Form_StaticText(
726
		'Defined by',
727
		strtoupper($pconfig['utype'])
728
	));
729

    
730
	$form->addGlobal(new Form_Input(
731
		'utype',
732
		null,
733
		'hidden',
734
		$pconfig['utype']
735
	));
736

    
737
	$section->addInput(new Form_Checkbox(
738
		'disabled',
739
		'Disabled',
740
		'This user cannot login',
741
		$pconfig['disabled']
742
	));
743

    
744
	$section->addInput($input = new Form_Input(
745
		'usernamefld',
746
		'*Username',
747
		'text',
748
		$pconfig['usernamefld']
749
	));
750

    
751
	if ($ro) {
752
		$input->setReadonly();
753
	}
754

    
755
	$form->addGlobal(new Form_Input(
756
		'oldusername',
757
		null,
758
		'hidden',
759
		$pconfig['usernamefld']
760
	));
761

    
762
	if ($act == "edit") {
763
		$pwd_required = "";
764
	} else {
765
		$pwd_required = "*";
766
	}
767

    
768
	$group = new Form_Group($pwd_required . 'Password');
769
	$group->add(new Form_Input(
770
		'passwordfld1',
771
		'Password',
772
		'password'
773
	));
774
	$group->add(new Form_Input(
775
		'passwordfld2',
776
		'Confirm Password',
777
		'password'
778
	));
779

    
780
	$section->add($group);
781

    
782
	$section->addInput($input = new Form_Input(
783
		'descr',
784
		'Full name',
785
		'text',
786
		htmlspecialchars($pconfig['descr'])
787
	))->setHelp('User\'s full name, for administrative information only');
788

    
789
	if ($ro) {
790
		$input->setDisabled();
791
	}
792

    
793
	$section->addInput(new Form_Input(
794
		'expires',
795
		'Expiration date',
796
		'text',
797
		$pconfig['expires']
798
	))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
799
		'the expiration date as MM/DD/YYYY');
800

    
801
	$section->addInput(new Form_Checkbox(
802
		'customsettings',
803
		'Custom Settings',
804
		'Use individual customized GUI options and dashboard layout for this user.',
805
		$pconfig['customsettings']
806
	));
807

    
808
	gen_user_settings_fields($section, $pconfig);
809

    
810
	// ==== Group membership ==================================================
811
	$group = new Form_Group('Group membership');
812

    
813
	// Make a list of all the groups configured on the system, and a list of
814
	// those which this user is a member of
815
	$systemGroups = array();
816
	$usersGroups = array();
817

    
818
	$usergid = [$pconfig['usernamefld']];
819

    
820
	foreach ($config['system']['group'] as $Ggroup) {
821
		if ($Ggroup['name'] != "all") {
822
			if (($act == 'edit') && $Ggroup['member'] && in_array($pconfig['uid'], $Ggroup['member'])) {
823
				$usersGroups[ $Ggroup['name'] ] = $Ggroup['name'];	// Add it to the user's list
824
			} else {
825
				$systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
826
			}
827
		}
828
	}
829

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

    
838
	$group->add(new Form_Select(
839
		'groups',
840
		null,
841
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
842
		$usersGroups,
843
		true
844
	))->setHelp('Member of');
845

    
846
	$section->add($group);
847

    
848
	$group = new Form_Group('');
849

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

    
857
	$group->add(new Form_Button(
858
		'movetodisabled',
859
		'Move to "Not member of" list',
860
		null,
861
		'fa-angle-double-left'
862
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
863

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

    
867
	// ==== Button for adding user certificate ================================
868
	if ($act == 'new') {
869
		$section->addInput(new Form_Checkbox(
870
			'showcert',
871
			'Certificate',
872
			'Click to create a user certificate',
873
			false
874
		));
875
	}
876

    
877
	$form->add($section);
878

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

    
884
		$section = new Form_Section('Effective Privileges');
885

    
886
		$section->addInput(new Form_StaticText(
887
			null,
888
			build_priv_table()
889
		));
890

    
891
		$form->add($section);
892

    
893
		// ==== Certificate table section =====================================
894
		$section = new Form_Section('User Certificates');
895

    
896
		$section->addInput(new Form_StaticText(
897
			null,
898
			build_cert_table()
899
		));
900

    
901
		$form->add($section);
902
	}
903

    
904
	// ==== Add user certificate for a new user
905
	if (is_array($config['ca']) && count($config['ca']) > 0) {
906
		$section = new Form_Section('Create Certificate for User');
907
		$section->addClass('cert-options');
908

    
909
		$nonPrvCas = array();
910
		foreach ($config['ca'] as $ca) {
911
			if (!$ca['prv']) {
912
				continue;
913
			}
914

    
915
			$nonPrvCas[ $ca['refid'] ] = $ca['descr'];
916
		}
917

    
918
		if (!empty($nonPrvCas)) {
919
			$section->addInput(new Form_Input(
920
				'name',
921
				'Descriptive name',
922
				'text',
923
				$pconfig['name']
924
			));
925

    
926
			$section->addInput(new Form_Select(
927
				'caref',
928
				'Certificate authority',
929
				null,
930
				$nonPrvCas
931
			));
932

    
933
			$section->addInput(new Form_Select(
934
				'keylen',
935
				'Key length',
936
				2048,
937
				array(
938
					512 => '512 bits',
939
					1024 => '1024 bits',
940
					2048 => '2048 bits',
941
					3072 => '3072 bits',
942
					4096 => '4096 bits',
943
					7680 => '7680 bits',
944
					8192 => '8192 bits',
945
					15360 => '15360 bits',
946
					16384 => '16384 bits'
947
				)
948
			))->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;.');
949

    
950
			$section->addInput(new Form_Input(
951
				'lifetime',
952
				'Lifetime',
953
				'number',
954
				$pconfig['lifetime']
955
			));
956
		}
957

    
958
		$form->add($section);
959
	}
960

    
961
endif;
962
// ==== Paste a key for the new user
963
$section = new Form_Section('Keys');
964

    
965
$section->addInput(new Form_Checkbox(
966
	'showkey',
967
	'Authorized keys',
968
	'Click to paste an authorized key',
969
	false
970
));
971

    
972
$section->addInput(new Form_Textarea(
973
	'authorizedkeys',
974
	'Authorized SSH Keys',
975
	$pconfig['authorizedkeys']
976
))->setHelp('Enter authorized SSH keys for this user');
977

    
978
$section->addInput(new Form_Input(
979
	'ipsecpsk',
980
	'IPsec Pre-Shared Key',
981
	'text',
982
	$pconfig['ipsecpsk']
983
));
984

    
985
$form->add($section);
986

    
987
print $form;
988

    
989
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
990
?>
991
<script type="text/javascript">
992
//<![CDATA[
993
events.push(function() {
994

    
995
	function setcustomoptions() {
996
		var adv = $('#customsettings').prop('checked');
997

    
998
		hideInput('webguicss', !adv);
999
		hideInput('webguifixedmenu', !adv);
1000
		hideInput('webguihostnamemenu', !adv);
1001
		hideInput('dashboardcolumns', !adv);
1002
		hideCheckbox('interfacessort', !adv);
1003
		hideCheckbox('dashboardavailablewidgetspanel', !adv);
1004
		hideCheckbox('systemlogsfilterpanel', !adv);
1005
		hideCheckbox('systemlogsmanagelogpanel', !adv);
1006
		hideCheckbox('statusmonitoringsettingspanel', !adv);
1007
		hideCheckbox('webguileftcolumnhyper', !adv);
1008
		hideCheckbox('pagenamefirst', !adv);
1009
	}
1010

    
1011
	// Handle displaying a warning message if a user-created theme is selected.
1012
	function setThemeWarning() {
1013
		if ($('#webguicss').val().startsWith("pfSense")) {
1014
			$('#csstxt').html("").addClass("text-default");
1015
		} else {
1016
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
1017
		}
1018
	}
1019

    
1020
	$('#webguicss').change(function() {
1021
		setThemeWarning();
1022
	});
1023

    
1024
	setThemeWarning();
1025

    
1026
	// On click . .
1027
	$('#customsettings').click(function () {
1028
		setcustomoptions();
1029
	});
1030

    
1031
	$("#movetodisabled").click(function() {
1032
		moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
1033
	});
1034

    
1035
	$("#movetoenabled").click(function() {
1036
		moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1037
	});
1038

    
1039
	$("#showcert").click(function() {
1040
		hideClass('cert-options', !this.checked);
1041
	});
1042

    
1043
	$("#showkey").click(function() {
1044
		hideInput('authorizedkeys', false);
1045
		hideCheckbox('showkey', true);
1046
	});
1047

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

    
1057
	$('[id^=delprivid]').click(function(event) {
1058
		if (confirm(event.target.title)) {
1059
			$('#privid').val(event.target.id.match(/\d+$/)[0]);
1060
			$('#userid').val('<?=$id;?>');
1061
			$('#act').val('delprivid');
1062
			$('form').submit();
1063
		}
1064
	});
1065

    
1066
	$('#expires').datepicker();
1067

    
1068
	// ---------- On initial page load ------------------------------------------------------------
1069

    
1070
	hideClass('cert-options', true);
1071
	//hideInput('authorizedkeys', true);
1072
	hideCheckbox('showkey', true);
1073
	setcustomoptions();
1074

    
1075
	// On submit mark all the user's groups as "selected"
1076
	$('form').submit(function() {
1077
		AllServers($('[name="groups[]"] option'), true);
1078
	});
1079
});
1080
//]]>
1081
</script>
1082
<?php
1083
include('foot.inc');
1084
?>
(211-211/230)