Project

General

Profile

Download (30.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 Electric Sheep Fencing, LLC
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['dashboardavailablewidgetspanel'] = isset($a_user[$id]['dashboardavailablewidgetspanel']);
102
	$pconfig['systemlogsfilterpanel'] = isset($a_user[$id]['systemlogsfilterpanel']);
103
	$pconfig['systemlogsmanagelogpanel'] = isset($a_user[$id]['systemlogsmanagelogpanel']);
104
	$pconfig['statusmonitoringsettingspanel'] = isset($a_user[$id]['statusmonitoringsettingspanel']);
105
	$pconfig['webguileftcolumnhyper'] = isset($a_user[$id]['webguileftcolumnhyper']);
106
	$pconfig['pagenamefirst'] = isset($a_user[$id]['pagenamefirst']);
107
	$pconfig['groups'] = local_user_get_groups($a_user[$id]);
108
	$pconfig['utype'] = $a_user[$id]['scope'];
109
	$pconfig['uid'] = $a_user[$id]['uid'];
110
	$pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
111
	$pconfig['priv'] = $a_user[$id]['priv'];
112
	$pconfig['ipsecpsk'] = $a_user[$id]['ipsecpsk'];
113
	$pconfig['disabled'] = isset($a_user[$id]['disabled']);
114
}
115

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
309
	if (!$input_errors) {
310

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
407
		if (isset($id) && $a_user[$id]) {
408
			$a_user[$id] = $userent;
409
		} else {
410
			if (!empty($_POST['name'])) {
411
				$cert = array();
412
				$cert['refid'] = uniqid();
413
				$userent['cert'] = array();
414

    
415
				$cert['descr'] = $_POST['name'];
416

    
417
				$subject = cert_get_subject_array($ca['crt']);
418

    
419
				$dn = array(
420
					'countryName' => $subject[0]['v'],
421
					'stateOrProvinceName' => $subject[1]['v'],
422
					'localityName' => $subject[2]['v'],
423
					'organizationName' => $subject[3]['v'],
424
					'emailAddress' => $subject[4]['v'],
425
					'commonName' => $userent['name']);
426

    
427
				cert_create($cert, $_POST['caref'], $_POST['keylen'],
428
					(int)$_POST['lifetime'], $dn);
429

    
430
				if (!is_array($config['cert'])) {
431
					$config['cert'] = array();
432
				}
433
				$config['cert'][] = $cert;
434
				$userent['cert'][] = $cert['refid'];
435
			}
436
			$userent['uid'] = $config['system']['nextuid']++;
437
			/* Add the user to All Users group. */
438
			foreach ($config['system']['group'] as $gidx => $group) {
439
				if ($group['name'] == "all") {
440
					if (!is_array($config['system']['group'][$gidx]['member'])) {
441
						$config['system']['group'][$gidx]['member'] = array();
442
					}
443
					$config['system']['group'][$gidx]['member'][] = $userent['uid'];
444
					break;
445
				}
446
			}
447

    
448
			$a_user[] = $userent;
449
		}
450

    
451
		/* 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. */
452
		local_user_set_groups($userent, $_POST['groups']);
453
		local_user_set($userent);
454
		/* 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. */
455
		local_user_set_groups($userent, $_POST['groups']);
456
		write_config();
457

    
458
		if (is_dir("/etc/inc/privhooks")) {
459
			run_plugins("/etc/inc/privhooks");
460
		}
461

    
462
		conf_mount_ro();
463

    
464
		pfSenseHeader("system_usermanager.php");
465
	}
466
}
467

    
468
function build_priv_table() {
469
	global $a_user, $id;
470

    
471
	$privhtml = '<div class="table-responsive">';
472
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
473
	$privhtml .=		'<thead>';
474
	$privhtml .=			'<tr>';
475
	$privhtml .=				'<th>' . gettext('Inherited from') . '</th>';
476
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
477
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
478
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
479
	$privhtml .=			'</tr>';
480
	$privhtml .=		'</thead>';
481
	$privhtml .=		'<tbody>';
482

    
483
	$i = 0;
484

    
485
	foreach (get_user_privdesc($a_user[$id]) as $priv) {
486
		$group = false;
487
		if ($priv['group']) {
488
			$group = $priv['group'];
489
		}
490

    
491
		$privhtml .=		'<tr>';
492
		$privhtml .=			'<td>' . htmlspecialchars($priv['group']) . '</td>';
493
		$privhtml .=			'<td>' . htmlspecialchars($priv['name']) . '</td>';
494
		$privhtml .=			'<td>' . htmlspecialchars($priv['descr']) . '</td>';
495
		$privhtml .=			'<td>';
496
		if (!$group) {
497
			$privhtml .=			'<a class="fa fa-trash no-confirm icon-pointer" title="' . gettext('Delete Privilege') . '" id="delprivid' . $i . '"></a>';
498
		}
499

    
500
		$privhtml .=			'</td>';
501
		$privhtml .=		'</tr>';
502

    
503
		if (!$group) {
504
			$i++;
505
		}
506
	}
507

    
508
	$privhtml .=		'</tbody>';
509
	$privhtml .=	'</table>';
510
	$privhtml .= '</div>';
511

    
512
	$privhtml .= '<nav class="action-buttons">';
513
	$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>';
514
	$privhtml .= '</nav>';
515

    
516
	return($privhtml);
517
}
518

    
519
function build_cert_table() {
520
	global $a_user, $id;
521

    
522
	$certhtml = '<div class="table-responsive">';
523
	$certhtml .=	'<table class="table table-striped table-hover table-condensed">';
524
	$certhtml .=		'<thead>';
525
	$certhtml .=			'<tr>';
526
	$certhtml .=				'<th>' . gettext('Name') . '</th>';
527
	$certhtml .=				'<th>' . gettext('CA') . '</th>';
528
	$certhtml .=				'<th></th>';
529
	$certhtml .=			'</tr>';
530
	$certhtml .=		'</thead>';
531
	$certhtml .=		'<tbody>';
532

    
533
	$a_cert = $a_user[$id]['cert'];
534
	if (is_array($a_cert)) {
535
		$i = 0;
536
		foreach ($a_cert as $certref) {
537
			$cert = lookup_cert($certref);
538
			$ca = lookup_ca($cert['caref']);
539
			$revokedstr =	is_cert_revoked($cert) ? '<b> Revoked</b>':'';
540

    
541
			$certhtml .=	'<tr>';
542
			$certhtml .=		'<td>' . htmlspecialchars($cert['descr']) . $revokedstr . '</td>';
543
			$certhtml .=		'<td>' . htmlspecialchars($ca['descr']) . '</td>';
544
			$certhtml .=		'<td>';
545
			$certhtml .=			'<a id="delcert' . $i .'" class="fa fa-trash no-confirm icon-pointer" title="';
546
			$certhtml .=			gettext('Remove this certificate association? (Certificate will not be deleted)') . '"></a>';
547
			$certhtml .=		'</td>';
548
			$certhtml .=	'</tr>';
549
			$i++;
550
		}
551

    
552
	}
553

    
554
	$certhtml .=		'</tbody>';
555
	$certhtml .=	'</table>';
556
	$certhtml .= '</div>';
557

    
558
	$certhtml .= '<nav class="action-buttons">';
559
	$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>';
560
	$certhtml .= '</nav>';
561

    
562
	return($certhtml);
563
}
564

    
565
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
566

    
567
if ($act == "new" || $act == "edit" || $input_errors) {
568
	$pgtitle[] = gettext('Edit');
569
}
570
include("head.inc");
571

    
572
if ($delete_errors) {
573
	print_input_errors($delete_errors);
574
}
575

    
576
if ($input_errors) {
577
	print_input_errors($input_errors);
578
}
579

    
580
if ($savemsg) {
581
	print_info_box($savemsg, 'success');
582
}
583

    
584
$tab_array = array();
585
$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
586
$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
587
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
588
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
589
display_top_tabs($tab_array);
590

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

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

    
669
$form = new Form;
670

    
671
if ($act == "new" || $act == "edit" || $input_errors):
672

    
673
	$form->addGlobal(new Form_Input(
674
		'act',
675
		null,
676
		'hidden',
677
		''
678
	));
679

    
680
	$form->addGlobal(new Form_Input(
681
		'userid',
682
		null,
683
		'hidden',
684
		isset($id) ? $id:''
685
	));
686

    
687
	$form->addGlobal(new Form_Input(
688
		'privid',
689
		null,
690
		'hidden',
691
		''
692
	));
693

    
694
	$form->addGlobal(new Form_Input(
695
		'certid',
696
		null,
697
		'hidden',
698
		''
699
	));
700

    
701
	$ro = "";
702
	if ($pconfig['utype'] == "system") {
703
		$ro = "readonly";
704
	}
705

    
706
	$section = new Form_Section('User Properties');
707

    
708
	$section->addInput(new Form_StaticText(
709
		'Defined by',
710
		strtoupper($pconfig['utype'])
711
	));
712

    
713
	$form->addGlobal(new Form_Input(
714
		'utype',
715
		null,
716
		'hidden',
717
		$pconfig['utype']
718
	));
719

    
720
	$section->addInput(new Form_Checkbox(
721
		'disabled',
722
		'Disabled',
723
		'This user cannot login',
724
		$pconfig['disabled']
725
	));
726

    
727
	$section->addInput($input = new Form_Input(
728
		'usernamefld',
729
		'Username',
730
		'text',
731
		$pconfig['usernamefld']
732
	));
733

    
734
	if ($ro) {
735
		$input->setReadonly();
736
	}
737

    
738
	$form->addGlobal(new Form_Input(
739
		'oldusername',
740
		null,
741
		'hidden',
742
		$pconfig['usernamefld']
743
	));
744

    
745
	$group = new Form_Group('Password');
746
	$group->add(new Form_Input(
747
		'passwordfld1',
748
		'Password',
749
		'password'
750
	));
751
	$group->add(new Form_Input(
752
		'passwordfld2',
753
		'Confirm Password',
754
		'password'
755
	));
756

    
757
	$section->add($group);
758

    
759
	$section->addInput($input = new Form_Input(
760
		'descr',
761
		'Full name',
762
		'text',
763
		htmlspecialchars($pconfig['descr'])
764
	))->setHelp('User\'s full name, for administrative information only');
765

    
766
	if ($ro) {
767
		$input->setDisabled();
768
	}
769

    
770
	$section->addInput(new Form_Input(
771
		'expires',
772
		'Expiration date',
773
		'text',
774
		$pconfig['expires']
775
	))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
776
		'the expiration date');
777

    
778
	$section->addInput(new Form_Checkbox(
779
		'customsettings',
780
		'Custom Settings',
781
		'Use individual customized GUI options and dashboard layout for this user.',
782
		$pconfig['customsettings']
783
	));
784

    
785
	gen_user_settings_fields($section, $pconfig);
786

    
787
	// ==== Group membership ==================================================
788
	$group = new Form_Group('Group membership');
789

    
790
	// Make a list of all the groups configured on the system, and a list of
791
	// those which this user is a member of
792
	$systemGroups = array();
793
	$usersGroups = array();
794

    
795
	$usergid = [$pconfig['usernamefld']];
796

    
797
	foreach ($config['system']['group'] as $Ggroup) {
798
		if ($Ggroup['name'] != "all") {
799
			if (($act == 'edit') && $Ggroup['member'] && in_array($pconfig['uid'], $Ggroup['member'])) {
800
				$usersGroups[ $Ggroup['name'] ] = $Ggroup['name'];	// Add it to the user's list
801
			} else {
802
				$systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
803
			}
804
		}
805
	}
806

    
807
	$group->add(new Form_Select(
808
		'sysgroups',
809
		null,
810
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
811
		$systemGroups,
812
		true
813
	))->setHelp('Not member of');
814

    
815
	$group->add(new Form_Select(
816
		'groups',
817
		null,
818
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
819
		$usersGroups,
820
		true
821
	))->setHelp('Member of');
822

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

    
825
	$group = new Form_Group('');
826

    
827
	$group->add(new Form_Button(
828
		'movetoenabled',
829
		'Move to "Member of" list',
830
		null,
831
		'fa-angle-double-right'
832
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
833

    
834
	$group->add(new Form_Button(
835
		'movetodisabled',
836
		'Move to "Not member of" list',
837
		null,
838
		'fa-angle-double-left'
839
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
840

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

    
844
	// ==== Button for adding user certificate ================================
845
	if ($act == 'new') {
846
		$section->addInput(new Form_Checkbox(
847
			'showcert',
848
			'Certificate',
849
			'Click to create a user certificate',
850
			false
851
		));
852
	}
853

    
854
	$form->add($section);
855

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

    
861
		$section = new Form_Section('Effective Privileges');
862

    
863
		$section->addInput(new Form_StaticText(
864
			null,
865
			build_priv_table()
866
		));
867

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

    
870
		// ==== Certificate table section =====================================
871
		$section = new Form_Section('User Certificates');
872

    
873
		$section->addInput(new Form_StaticText(
874
			null,
875
			build_cert_table()
876
		));
877

    
878
		$form->add($section);
879
	}
880

    
881
	// ==== Add user certificate for a new user
882
	if (is_array($config['ca']) && count($config['ca']) > 0) {
883
		$section = new Form_Section('Create Certificate for User');
884
		$section->addClass('cert-options');
885

    
886
		$nonPrvCas = array();
887
		foreach($config['ca'] as $ca) {
888
			if (!$ca['prv']) {
889
				continue;
890
			}
891

    
892
			$nonPrvCas[ $ca['refid'] ] = $ca['descr'];
893
		}
894

    
895
		if (!empty($nonPrvCas)) {
896
			$section->addInput(new Form_Input(
897
				'name',
898
				'Descriptive name',
899
				'text',
900
				$pconfig['name']
901
			));
902

    
903
			$section->addInput(new Form_Select(
904
				'caref',
905
				'Certificate authority',
906
				null,
907
				$nonPrvCas
908
			));
909

    
910
			$section->addInput(new Form_Select(
911
				'keylen',
912
				'Key length',
913
				2048,
914
				array(
915
					512 => '512 bits',
916
					1024 => '1024 bits',
917
					2048 => '2048 bits',
918
					3072 => '3072 bits',
919
					4096 => '4096 bits',
920
					7680 => '7680 bits',
921
					8192 => '8192 bits',
922
					15360 => '15360 bits',
923
					16384 => '16384 bits'
924
				)
925
			))->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;.');
926

    
927
			$section->addInput(new Form_Input(
928
				'lifetime',
929
				'Lifetime',
930
				'number',
931
				$pconfig['lifetime']
932
			));
933
		}
934

    
935
		$form->add($section);
936
	}
937

    
938
endif;
939
// ==== Paste a key for the new user
940
$section = new Form_Section('Keys');
941

    
942
$section->addInput(new Form_Checkbox(
943
	'showkey',
944
	'Authorized keys',
945
	'Click to paste an authorized key',
946
	false
947
));
948

    
949
$section->addInput(new Form_Textarea(
950
	'authorizedkeys',
951
	'Authorized SSH Keys',
952
	$pconfig['authorizedkeys']
953
))->setHelp('Enter authorized SSH keys for this user');
954

    
955
$section->addInput(new Form_Input(
956
	'ipsecpsk',
957
	'IPsec Pre-Shared Key',
958
	'text',
959
	$pconfig['ipsecpsk']
960
));
961

    
962
$form->add($section);
963

    
964
print $form;
965

    
966
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
967
?>
968
<script type="text/javascript">
969
//<![CDATA[
970
events.push(function() {
971

    
972
	function setcustomoptions() {
973
		var adv = $('#customsettings').prop('checked');
974

    
975
		hideInput('webguicss', !adv);
976
		hideInput('webguifixedmenu', !adv);
977
		hideInput('webguihostnamemenu', !adv);
978
		hideInput('dashboardcolumns', !adv);
979
		hideCheckbox('dashboardavailablewidgetspanel', !adv);
980
		hideCheckbox('systemlogsfilterpanel', !adv);
981
		hideCheckbox('systemlogsmanagelogpanel', !adv);
982
		hideCheckbox('statusmonitoringsettingspanel', !adv);
983
		hideCheckbox('webguileftcolumnhyper', !adv);
984
		hideCheckbox('pagenamefirst', !adv);
985
	}
986

    
987
	// Handle displaying a warning message if a user-created theme is selected.
988
	function setThemeWarning() {
989
		if ($('#webguicss').val().startsWith("pfSense")) {
990
			$('#csstxt').html("").addClass("text-default");
991
		} else {
992
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
993
		}
994
	}
995

    
996
	$('#webguicss').change(function() {
997
		setThemeWarning();
998
	});
999

    
1000
	setThemeWarning();
1001

    
1002
	// On click . .
1003
	$('#customsettings').click(function () {
1004
		setcustomoptions();
1005
	});
1006

    
1007
	$("#movetodisabled").click(function() {
1008
		moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
1009
	});
1010

    
1011
	$("#movetoenabled").click(function() {
1012
		moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1013
	});
1014

    
1015
	$("#showcert").click(function() {
1016
		hideClass('cert-options', !this.checked);
1017
	});
1018

    
1019
	$("#showkey").click(function() {
1020
		hideInput('authorizedkeys', false);
1021
		hideCheckbox('showkey', true);
1022
	});
1023

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

    
1033
	$('[id^=delprivid]').click(function(event) {
1034
		if (confirm(event.target.title)) {
1035
			$('#privid').val(event.target.id.match(/\d+$/)[0]);
1036
			$('#userid').val('<?=$id;?>');
1037
			$('#act').val('delprivid');
1038
			$('form').submit();
1039
		}
1040
	});
1041

    
1042
	$('#expires').datepicker();
1043

    
1044
	// ---------- On initial page load ------------------------------------------------------------
1045

    
1046
	hideClass('cert-options', true);
1047
	//hideInput('authorizedkeys', true);
1048
	hideCheckbox('showkey', true);
1049
	setcustomoptions();
1050

    
1051
	// On submit mark all the user's groups as "selected"
1052
	$('form').submit(function() {
1053
		AllServers($('[name="groups[]"] option'), true);
1054
	});
1055
});
1056
//]]>
1057
</script>
1058
<?php
1059
include('foot.inc');
1060
?>
(208-208/227)