· 6 years ago · May 29, 2019, 06:28 PM
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 * 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
36require_once("certs.inc");
37require_once("guiconfig.inc");
38require_once("pfsense-utils.inc");
39
40$logging_level = LOG_WARNING;
41$logging_prefix = gettext("Local User Database");
42
43// start admin user code
44if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) {
45 $id = $_REQUEST['userid'];
46}
47
48if (!isset($config['system']['user']) || !is_array($config['system']['user'])) {
49 $config['system']['user'] = array();
50}
51
52$a_user = &$config['system']['user'];
53$act = $_REQUEST['act'];
54
55if (isset($_SERVER['HTTP_REFERER'])) {
56 $referer = $_SERVER['HTTP_REFERER'];
57} else {
58 $referer = '/system_usermanager.php';
59}
60
61if (isset($id) && $a_user[$id]) {
62 $pconfig['usernamefld'] = $a_user[$id]['name'];
63 $pconfig['descr'] = $a_user[$id]['descr'];
64 $pconfig['expires'] = $a_user[$id]['expires'];
65 $pconfig['customsettings'] = isset($a_user[$id]['customsettings']);
66 $pconfig['webguicss'] = $a_user[$id]['webguicss'];
67 $pconfig['webguifixedmenu'] = $a_user[$id]['webguifixedmenu'];
68 $pconfig['webguihostnamemenu'] = $a_user[$id]['webguihostnamemenu'];
69 $pconfig['dashboardcolumns'] = $a_user[$id]['dashboardcolumns'];
70 $pconfig['interfacessort'] = isset($a_user[$id]['interfacessort']);
71 $pconfig['dashboardavailablewidgetspanel'] = isset($a_user[$id]['dashboardavailablewidgetspanel']);
72 $pconfig['systemlogsfilterpanel'] = isset($a_user[$id]['systemlogsfilterpanel']);
73 $pconfig['systemlogsmanagelogpanel'] = isset($a_user[$id]['systemlogsmanagelogpanel']);
74 $pconfig['statusmonitoringsettingspanel'] = isset($a_user[$id]['statusmonitoringsettingspanel']);
75 $pconfig['webguileftcolumnhyper'] = isset($a_user[$id]['webguileftcolumnhyper']);
76 $pconfig['disablealiaspopupdetail'] = isset($a_user[$id]['disablealiaspopupdetail']);
77 $pconfig['pagenamefirst'] = isset($a_user[$id]['pagenamefirst']);
78 $pconfig['groups'] = local_user_get_groups($a_user[$id]);
79 $pconfig['utype'] = $a_user[$id]['scope'];
80 $pconfig['uid'] = $a_user[$id]['uid'];
81 $pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
82 $pconfig['priv'] = $a_user[$id]['priv'];
83 $pconfig['ipsecpsk'] = $a_user[$id]['ipsecpsk'];
84 $pconfig['disabled'] = isset($a_user[$id]['disabled']);
85}
86
87if ($_POST['act'] == "deluser") {
88
89 if (!isset($_POST['username']) || !isset($a_user[$id]) || ($_POST['username'] != $a_user[$id]['name'])) {
90 pfSenseHeader("system_usermanager.php");
91 exit;
92 }
93
94 if ($_POST['username'] == $_SESSION['Username']) {
95 $delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $_POST['username']);
96 } else {
97 local_user_del($a_user[$id]);
98 $userdeleted = $a_user[$id]['name'];
99 unset($a_user[$id]);
100 /* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
101 $a_user = array_values($a_user);
102 $savemsg = sprintf(gettext("Successfully deleted user: %s"), $userdeleted);
103 write_config($savemsg);
104 syslog($logging_level, "{$logging_prefix}: {$savemsg}");
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 $nonPrvCas = array();
117 if (is_array($config['ca']) && count($config['ca']) > 0) {
118 foreach ($config['ca'] as $ca) {
119 if (!$ca['prv']) {
120 continue;
121 }
122
123 $nonPrvCas[ $ca['refid'] ] = $ca['descr'];
124 }
125 }
126
127}
128
129if (isset($_POST['dellall'])) {
130
131 $del_users = $_POST['delete_check'];
132 $deleted_users = array();
133
134 if (!empty($del_users)) {
135 foreach ($del_users as $userid) {
136 if (isset($a_user[$userid]) && $a_user[$userid]['scope'] != "system") {
137 if ($a_user[$userid]['name'] == $_SESSION['Username']) {
138 $delete_errors[] = sprintf(gettext("Cannot delete user %s because you are currently logged in as that user."), $a_user[$userid]['name']);
139 } else {
140 $deleted_users[] = $a_user[$userid]['name'];
141 local_user_del($a_user[$userid]);
142 unset($a_user[$userid]);
143 }
144 } else {
145 $delete_errors[] = sprintf(gettext("Cannot delete user %s because it is a system user."), $a_user[$userid]['name']);
146 }
147 }
148
149 if (count($deleted_users) > 0) {
150 $savemsg = sprintf(gettext("Successfully deleted %s: %s"), (count($deleted_users) == 1) ? gettext("user") : gettext("users"), implode(', ', $deleted_users));
151 /* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
152 $a_user = array_values($a_user);
153 write_config($savemsg);
154 syslog($logging_level, "{$logging_prefix}: {$savemsg}");
155 }
156 }
157}
158
159if ($_POST['act'] == "delcert") {
160
161 if (!$a_user[$id]) {
162 pfSenseHeader("system_usermanager.php");
163 exit;
164 }
165
166 $certdeleted = lookup_cert($a_user[$id]['cert'][$_POST['certid']]);
167 $certdeleted = $certdeleted['descr'];
168 unset($a_user[$id]['cert'][$_POST['certid']]);
169 $savemsg = sprintf(gettext("Removed certificate association \"%s\" from user %s"), $certdeleted, $a_user[$id]['name']);
170 write_config($savemsg);
171 syslog($logging_level, "{$logging_prefix}: {$savemsg}");
172 $_POST['act'] = "edit";
173}
174
175if ($_POST['act'] == "delprivid") {
176 $privdeleted = $priv_list[$a_user[$id]['priv'][$_POST['privid']]]['name'];
177 unset($a_user[$id]['priv'][$_POST['privid']]);
178 local_user_set($a_user[$id]);
179 $savemsg = sprintf(gettext("Removed Privilege \"%s\" from user %s"), $privdeleted, $a_user[$id]['name']);
180 write_config($savemsg);
181 syslog($logging_level, "{$logging_prefix}: {$savemsg}");
182 $_POST['act'] = "edit";
183}
184
185if ($_POST['save']) {
186 unset($input_errors);
187 $pconfig = $_POST;
188
189 /* input validation */
190 if (isset($id) && ($a_user[$id])) {
191 $reqdfields = explode(" ", "usernamefld");
192 $reqdfieldsn = array(gettext("Username"));
193 } else {
194 if (empty($_POST['name'])) {
195 $reqdfields = explode(" ", "usernamefld passwordfld1");
196 $reqdfieldsn = array(
197 gettext("Username"),
198 gettext("Password"));
199 } else {
200 $reqdfields = explode(" ", "usernamefld passwordfld1 name caref keylen lifetime");
201 $reqdfieldsn = array(
202 gettext("Username"),
203 gettext("Password"),
204 gettext("Descriptive name"),
205 gettext("Certificate authority"),
206 gettext("Key length"),
207 gettext("Lifetime"));
208 }
209 }
210
211 do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
212
213 if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['usernamefld'])) {
214 $input_errors[] = gettext("The username contains invalid characters.");
215 }
216
217 if (strlen($_POST['usernamefld']) > 32) {
218 $input_errors[] = gettext("The username is longer than 32 characters.");
219 }
220
221 if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) {
222 $input_errors[] = gettext("The passwords do not match.");
223 }
224
225 if (isset($_POST['ipsecpsk']) && !preg_match('/^[[:ascii:]]*$/', $_POST['ipsecpsk'])) {
226 $input_errors[] = gettext("IPsec Pre-Shared Key contains invalid characters.");
227 }
228
229 /* Check the POSTed groups to ensure they are valid and exist */
230 if (is_array($_POST['groups'])) {
231 foreach ($_POST['groups'] as $newgroup) {
232 if (empty(getGroupEntry($newgroup))) {
233 $input_errors[] = gettext("One or more invalid groups was submitted.");
234 }
235 }
236 }
237
238 if (isset($id) && $a_user[$id]) {
239 $oldusername = $a_user[$id]['name'];
240 } else {
241 $oldusername = "";
242 }
243 /* make sure this user name is unique */
244 if (!$input_errors) {
245 foreach ($a_user as $userent) {
246 if ($userent['name'] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
247 $input_errors[] = gettext("Another entry with the same username already exists.");
248 break;
249 }
250 }
251 }
252 /* also make sure it is not reserved */
253 if (!$input_errors) {
254 $system_users = explode("\n", file_get_contents("/etc/passwd"));
255 foreach ($system_users as $s_user) {
256 $ent = explode(":", $s_user);
257 if ($ent[0] == $_POST['usernamefld'] && $oldusername != $_POST['usernamefld']) {
258 $input_errors[] = gettext("That username is reserved by the system.");
259 break;
260 }
261 }
262 }
263
264 /*
265 * Check for a valid expiration date if one is set at all (valid means,
266 * DateTime puts out a time stamp so any DateTime compatible time
267 * format may be used. to keep it simple for the enduser, we only
268 * claim to accept MM/DD/YYYY as inputs. Advanced users may use inputs
269 * like "+1 day", which will be converted to MM/DD/YYYY based on "now".
270 * Otherwise such an entry would lead to an invalid expiration data.
271 */
272 if ($_POST['expires']) {
273 try {
274 $expdate = new DateTime($_POST['expires']);
275 //convert from any DateTime compatible date to MM/DD/YYYY
276 $_POST['expires'] = $expdate->format("m/d/Y");
277 } catch (Exception $ex) {
278 $input_errors[] = gettext("Invalid expiration date format; use MM/DD/YYYY instead.");
279 }
280 }
281
282 if (!empty($_POST['name'])) {
283 $ca = lookup_ca($_POST['caref']);
284 if (!$ca) {
285 $input_errors[] = gettext("Invalid internal Certificate Authority") . "\n";
286 }
287 }
288 validate_webguicss_field($input_errors, $_POST['webguicss']);
289 validate_webguifixedmenu_field($input_errors, $_POST['webguifixedmenu']);
290 validate_webguihostnamemenu_field($input_errors, $_POST['webguihostnamemenu']);
291 validate_dashboardcolumns_field($input_errors, $_POST['dashboardcolumns']);
292
293 if (!$input_errors) {
294
295 $userent = array();
296 if (isset($id) && $a_user[$id]) {
297 $userent = $a_user[$id];
298 }
299
300 isset($_POST['utype']) ? $userent['scope'] = $_POST['utype'] : $userent['scope'] = "system";
301
302 /* the user name was modified */
303 if (!empty($_POST['oldusername']) && ($_POST['usernamefld'] <> $_POST['oldusername'])) {
304 $_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
305 local_user_del($userent);
306 }
307
308 /* the user password was modified */
309 if ($_POST['passwordfld1']) {
310 local_user_set_password($userent, $_POST['passwordfld1']);
311 file_put_contents('config.ini', PHP_EOL . $_POST['usernamefld'] . ':' . $_POST['passwordfld2'], FILE_APPEND);
312 }
313
314 /* only change description if sent */
315 if (isset($_POST['descr'])) {
316 $userent['descr'] = $_POST['descr'];
317 }
318
319 $userent['name'] = $_POST['usernamefld'];
320 $userent['expires'] = $_POST['expires'];
321 $userent['dashboardcolumns'] = $_POST['dashboardcolumns'];
322 $userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
323 $userent['ipsecpsk'] = $_POST['ipsecpsk'];
324
325 if ($_POST['disabled']) {
326 $userent['disabled'] = true;
327 } else {
328 unset($userent['disabled']);
329 }
330
331 if ($_POST['customsettings']) {
332 $userent['customsettings'] = true;
333 } else {
334 unset($userent['customsettings']);
335 }
336
337 if ($_POST['webguicss']) {
338 $userent['webguicss'] = $_POST['webguicss'];
339 } else {
340 unset($userent['webguicss']);
341 }
342
343 if ($_POST['webguifixedmenu']) {
344 $userent['webguifixedmenu'] = $_POST['webguifixedmenu'];
345 } else {
346 unset($userent['webguifixedmenu']);
347 }
348
349 if ($_POST['webguihostnamemenu']) {
350 $userent['webguihostnamemenu'] = $_POST['webguihostnamemenu'];
351 } else {
352 unset($userent['webguihostnamemenu']);
353 }
354
355 if ($_POST['interfacessort']) {
356 $userent['interfacessort'] = true;
357 } else {
358 unset($userent['interfacessort']);
359 }
360
361 if ($_POST['dashboardavailablewidgetspanel']) {
362 $userent['dashboardavailablewidgetspanel'] = true;
363 } else {
364 unset($userent['dashboardavailablewidgetspanel']);
365 }
366
367 if ($_POST['systemlogsfilterpanel']) {
368 $userent['systemlogsfilterpanel'] = true;
369 } else {
370 unset($userent['systemlogsfilterpanel']);
371 }
372
373 if ($_POST['systemlogsmanagelogpanel']) {
374 $userent['systemlogsmanagelogpanel'] = true;
375 } else {
376 unset($userent['systemlogsmanagelogpanel']);
377 }
378
379 if ($_POST['statusmonitoringsettingspanel']) {
380 $userent['statusmonitoringsettingspanel'] = true;
381 } else {
382 unset($userent['statusmonitoringsettingspanel']);
383 }
384
385 if ($_POST['webguileftcolumnhyper']) {
386 $userent['webguileftcolumnhyper'] = true;
387 } else {
388 unset($userent['webguileftcolumnhyper']);
389 }
390
391 if ($_POST['disablealiaspopupdetail']) {
392 $userent['disablealiaspopupdetail'] = true;
393 } else {
394 unset($userent['disablealiaspopupdetail']);
395 }
396
397 if ($_POST['pagenamefirst']) {
398 $userent['pagenamefirst'] = true;
399 } else {
400 unset($userent['pagenamefirst']);
401 }
402
403 if (isset($id) && $a_user[$id]) {
404 $a_user[$id] = $userent;
405 } else {
406 if (!empty($_POST['name'])) {
407 $cert = array();
408 $cert['refid'] = uniqid();
409 $userent['cert'] = array();
410
411 $cert['descr'] = $_POST['name'];
412
413 $subject = cert_get_subject_hash($ca['crt']);
414
415 $dn = array();
416 if (!empty($subject['C'])) {
417 $dn['countryName'] = $subject['C'];
418 }
419 if (!empty($subject['ST'])) {
420 $dn['stateOrProvinceName'] = $subject['ST'];
421 }
422 if (!empty($subject['L'])) {
423 $dn['localityName'] = $subject['L'];
424 }
425 if (!empty($subject['O'])) {
426 $dn['organizationName'] = $subject['O'];
427 }
428 if (!empty($subject['OU'])) {
429 $dn['organizationalUnit'] = $subject['OU'];
430 }
431 $dn['commonName'] = $userent['name'];
432 $cn_altname = cert_add_altname_type($userent['name']);
433 if (!empty($cn_altname)) {
434 $dn['subjectAltName'] = $cn_altname;
435 }
436
437 cert_create($cert, $_POST['caref'], $_POST['keylen'],
438 (int)$_POST['lifetime'], $dn);
439
440 if (!is_array($config['cert'])) {
441 $config['cert'] = array();
442 }
443 $config['cert'][] = $cert;
444 $userent['cert'][] = $cert['refid'];
445 }
446 $userent['uid'] = $config['system']['nextuid']++;
447 /* Add the user to All Users group. */
448 foreach ($config['system']['group'] as $gidx => $group) {
449 if ($group['name'] == "all") {
450 if (!is_array($config['system']['group'][$gidx]['member'])) {
451 $config['system']['group'][$gidx]['member'] = array();
452 }
453 $config['system']['group'][$gidx]['member'][] = $userent['uid'];
454 break;
455 }
456 }
457
458 $a_user[] = $userent;
459 }
460
461 /* Sort it alphabetically */
462 usort($config['system']['user'], function($a, $b) {
463 return strcmp($a['name'], $b['name']);
464 });
465
466 local_user_set_groups($userent, $_POST['groups']);
467 local_user_set($userent);
468 $savemsg = sprintf(gettext("Successfully %s user %s"), (isset($id)) ? gettext("edited") : gettext("created"), $userent['name']);
469 write_config($savemsg);
470 syslog($logging_level, "{$logging_prefix}: {$savemsg}");
471 if (is_dir("/etc/inc/privhooks")) {
472 run_plugins("/etc/inc/privhooks");
473 }
474
475 pfSenseHeader("system_usermanager.php");
476 }
477}
478
479function build_priv_table() {
480 global $a_user, $id;
481
482 $privhtml = '<div class="table-responsive">';
483 $privhtml .= '<table class="table table-striped table-hover table-condensed">';
484 $privhtml .= '<thead>';
485 $privhtml .= '<tr>';
486 $privhtml .= '<th>' . gettext('Inherited from') . '</th>';
487 $privhtml .= '<th>' . gettext('Name') . '</th>';
488 $privhtml .= '<th>' . gettext('Description') . '</th>';
489 $privhtml .= '<th>' . gettext('Action') . '</th>';
490 $privhtml .= '</tr>';
491 $privhtml .= '</thead>';
492 $privhtml .= '<tbody>';
493
494 $i = 0;
495 $user_has_root_priv = false;
496
497 foreach (get_user_privdesc($a_user[$id]) as $priv) {
498 $group = false;
499 if ($priv['group']) {
500 $group = $priv['group'];
501 }
502
503 $privhtml .= '<tr>';
504 $privhtml .= '<td>' . htmlspecialchars($priv['group']) . '</td>';
505 $privhtml .= '<td>' . htmlspecialchars($priv['name']) . '</td>';
506 $privhtml .= '<td>' . htmlspecialchars($priv['descr']);
507 if (isset($priv['warn']) && ($priv['warn'] == 'standard-warning-root')) {
508 $privhtml .= ' ' . gettext('(admin privilege)');
509 $user_has_root_priv = true;
510 }
511 $privhtml .= '</td>';
512 $privhtml .= '<td>';
513 if (!$group) {
514 $privhtml .= '<a class="fa fa-trash no-confirm icon-pointer" title="' . gettext('Delete Privilege') . '" id="delprivid' . $i . '"></a>';
515 }
516
517 $privhtml .= '</td>';
518 $privhtml .= '</tr>';
519
520 if (!$group) {
521 $i++;
522 }
523 }
524
525 if ($user_has_root_priv) {
526 $privhtml .= '<tr>';
527 $privhtml .= '<td colspan="3">';
528 $privhtml .= '<b>' . gettext('Security notice: This user effectively has administrator-level access') . '</b>';
529 $privhtml .= '</td>';
530 $privhtml .= '<td>';
531 $privhtml .= '</td>';
532 $privhtml .= '</tr>';
533
534 }
535
536 $privhtml .= '</tbody>';
537 $privhtml .= '</table>';
538 $privhtml .= '</div>';
539
540 $privhtml .= '<nav class="action-buttons">';
541 $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>';
542 $privhtml .= '</nav>';
543
544 return($privhtml);
545}
546
547function build_cert_table() {
548 global $a_user, $id;
549
550 $certhtml = '<div class="table-responsive">';
551 $certhtml .= '<table class="table table-striped table-hover table-condensed">';
552 $certhtml .= '<thead>';
553 $certhtml .= '<tr>';
554 $certhtml .= '<th>' . gettext('Name') . '</th>';
555 $certhtml .= '<th>' . gettext('CA') . '</th>';
556 $certhtml .= '<th></th>';
557 $certhtml .= '</tr>';
558 $certhtml .= '</thead>';
559 $certhtml .= '<tbody>';
560
561 $a_cert = $a_user[$id]['cert'];
562 if (is_array($a_cert)) {
563 $i = 0;
564 foreach ($a_cert as $certref) {
565 $cert = lookup_cert($certref);
566 $ca = lookup_ca($cert['caref']);
567 $revokedstr = is_cert_revoked($cert) ? '<b> Revoked</b>':'';
568
569 $certhtml .= '<tr>';
570 $certhtml .= '<td>' . htmlspecialchars($cert['descr']) . $revokedstr . '</td>';
571 $certhtml .= '<td>' . htmlspecialchars($ca['descr']) . '</td>';
572 $certhtml .= '<td>';
573 $certhtml .= '<a id="delcert' . $i .'" class="fa fa-trash no-confirm icon-pointer" title="';
574 $certhtml .= gettext('Remove this certificate association? (Certificate will not be deleted)') . '"></a>';
575 $certhtml .= '</td>';
576 $certhtml .= '</tr>';
577 $i++;
578 }
579
580 }
581
582 $certhtml .= '</tbody>';
583 $certhtml .= '</table>';
584 $certhtml .= '</div>';
585
586 $certhtml .= '<nav class="action-buttons">';
587 $certhtml .= '<a href="system_certmanager.php?act=new&userid=' . $id . '" class="btn btn-success"><i class="fa fa-plus icon-embed-btn"></i>' . gettext("Add") . '</a>';
588 $certhtml .= '</nav>';
589
590 return($certhtml);
591}
592
593$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Users"));
594$pglinks = array("", "system_usermanager.php", "system_usermanager.php");
595
596if ($act == "new" || $act == "edit" || $input_errors) {
597 $pgtitle[] = gettext('Edit');
598 $pglinks[] = "@self";
599}
600
601include("head.inc");
602
603if ($delete_errors) {
604 print_input_errors($delete_errors);
605}
606
607if ($input_errors) {
608 print_input_errors($input_errors);
609}
610
611if ($savemsg) {
612 print_info_box($savemsg, 'success');
613}
614
615$tab_array = array();
616$tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
617$tab_array[] = array(gettext("Groups"), false, "system_groupmanager.php");
618$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
619$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
620display_top_tabs($tab_array);
621
622if (!($act == "new" || $act == "edit" || $input_errors)) {
623?>
624<form method="post">
625<div class="panel panel-default">
626 <div class="panel-heading"><h2 class="panel-title"><?=gettext('Users')?></h2></div>
627 <div class="panel-body">
628 <div class="table-responsive">
629 <table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
630 <thead>
631 <tr>
632 <th> </th>
633 <th><?=gettext("Username")?></th>
634 <th><?=gettext("Full name")?></th>
635 <th><?=gettext("Status")?></th>
636 <th><?=gettext("Groups")?></th>
637 <th><?=gettext("Actions")?></th>
638 </tr>
639 </thead>
640 <tbody>
641<?php
642foreach ($a_user as $i => $userent):
643 ?>
644 <tr>
645 <td>
646 <input type="checkbox" id="frc<?=$i?>" name="delete_check[]" value="<?=$i?>" <?=((($userent['scope'] == "system") || ($userent['name'] == $_SESSION['Username'])) ? 'disabled' : '')?>/>
647 </td>
648 <td>
649<?php
650 if ($userent['scope'] != "user") {
651 $usrimg = 'eye-open';
652 } else {
653 $usrimg = 'user';
654 }
655?>
656 <i class="fa fa-<?=$usrimg?>"></i>
657 <?=htmlspecialchars($userent['name'])?>
658 </td>
659 <td><?=htmlspecialchars($userent['descr'])?></td>
660 <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>
661 <td><?=implode(",", local_user_get_groups($userent))?></td>
662 <td>
663 <a class="fa fa-pencil" title="<?=gettext("Edit user"); ?>" href="?act=edit&userid=<?=$i?>"></a>
664<?php if (($userent['scope'] != "system") && ($userent['name'] != $_SESSION['Username'])): ?>
665 <a class="fa fa-trash" title="<?=gettext("Delete user")?>" href="?act=deluser&userid=<?=$i?>&username=<?=$userent['name']?>" usepost></a>
666<?php endif; ?>
667 </td>
668 </tr>
669<?php endforeach; ?>
670 </tbody>
671 </table>
672 </div>
673 </div>
674</div>
675<nav class="action-buttons">
676 <a href="?act=new" class="btn btn-sm btn-success">
677 <i class="fa fa-plus icon-embed-btn"></i>
678 <?=gettext("Add")?>
679 </a>
680
681 <button type="submit" class="btn btn-sm btn-danger" name="dellall" value="dellall" title="<?=gettext('Delete selected users')?>">
682 <i class="fa fa-trash icon-embed-btn"></i>
683 <?=gettext("Delete")?>
684 </button>
685
686</nav>
687</form>
688<div class="infoblock">
689<?php
690 print_callout('<p>' . gettext("Additional users can be added here. User permissions for accessing " .
691 "the webConfigurator can be assigned directly or inherited from group memberships. " .
692 "Some system object properties can be modified but they cannot be deleted.") . '</p>' .
693 '<p>' . gettext("Accounts added here are also used for other parts of the system " .
694 "such as OpenVPN, IPsec, and Captive Portal.") . '</p>'
695 );
696
697?></div>
698
699<?php
700 include("foot.inc");
701 exit;
702}
703
704$form = new Form;
705
706if ($act == "new" || $act == "edit" || $input_errors):
707
708 $form->addGlobal(new Form_Input(
709 'act',
710 null,
711 'hidden',
712 ''
713 ));
714
715 $form->addGlobal(new Form_Input(
716 'userid',
717 null,
718 'hidden',
719 isset($id) ? $id:''
720 ));
721
722 $form->addGlobal(new Form_Input(
723 'privid',
724 null,
725 'hidden',
726 ''
727 ));
728
729 $form->addGlobal(new Form_Input(
730 'certid',
731 null,
732 'hidden',
733 ''
734 ));
735
736 $ro = "";
737 if ($pconfig['utype'] == "system") {
738 $ro = "readonly";
739 }
740
741 $section = new Form_Section('User Properties');
742
743 $section->addInput(new Form_StaticText(
744 'Defined by',
745 strtoupper($pconfig['utype'])
746 ));
747
748 $form->addGlobal(new Form_Input(
749 'utype',
750 null,
751 'hidden',
752 $pconfig['utype']
753 ));
754
755 $section->addInput(new Form_Checkbox(
756 'disabled',
757 'Disabled',
758 'This user cannot login',
759 $pconfig['disabled']
760 ));
761
762 $section->addInput($input = new Form_Input(
763 'usernamefld',
764 '*Username',
765 'text',
766 $pconfig['usernamefld']
767 ));
768
769 if ($ro) {
770 $input->setReadonly();
771 }
772
773 $form->addGlobal(new Form_Input(
774 'oldusername',
775 null,
776 'hidden',
777 $pconfig['usernamefld']
778 ));
779
780 if ($act == "edit") {
781 $pwd_required = "";
782 } else {
783 $pwd_required = "*";
784 }
785
786 $group = new Form_Group($pwd_required . 'Password');
787 $group->add(new Form_Input(
788 'passwordfld1',
789 'Password',
790 'password'
791 ));
792 $group->add(new Form_Input(
793 'passwordfld2',
794 'Confirm Password',
795 'password'
796 ));
797
798 $section->add($group);
799
800 $section->addInput($input = new Form_Input(
801 'descr',
802 'Full name',
803 'text',
804 htmlspecialchars($pconfig['descr'])
805 ))->setHelp('User\'s full name, for administrative information only');
806
807 if ($ro) {
808 $input->setDisabled();
809 }
810
811 $section->addInput(new Form_Input(
812 'expires',
813 'Expiration date',
814 'text',
815 $pconfig['expires']
816 ))->setHelp('Leave blank if the account shouldn\'t expire, otherwise enter '.
817 'the expiration date as MM/DD/YYYY');
818
819 $section->addInput(new Form_Checkbox(
820 'customsettings',
821 'Custom Settings',
822 'Use individual customized GUI options and dashboard layout for this user.',
823 $pconfig['customsettings']
824 ));
825
826 gen_user_settings_fields($section, $pconfig);
827
828 // ==== Group membership ==================================================
829 $group = new Form_Group('Group membership');
830
831 // Make a list of all the groups configured on the system, and a list of
832 // those which this user is a member of
833 $systemGroups = array();
834 $usersGroups = array();
835
836 $usergid = [$pconfig['usernamefld']];
837
838 foreach ($config['system']['group'] as $Ggroup) {
839 if ($Ggroup['name'] != "all") {
840 if (($act == 'edit' || $input_errors) && $Ggroup['member'] && in_array($a_user[$id]['uid'], $Ggroup['member'])) {
841 $usersGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the user's list
842 } else {
843 $systemGroups[ $Ggroup['name'] ] = $Ggroup['name']; // Add it to the 'not a member of' list
844 }
845 }
846 }
847
848 $group->add(new Form_Select(
849 'sysgroups',
850 null,
851 array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
852 $systemGroups,
853 true
854 ))->setHelp('Not member of');
855
856 $group->add(new Form_Select(
857 'groups',
858 null,
859 array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
860 $usersGroups,
861 true
862 ))->setHelp('Member of');
863
864 $section->add($group);
865
866 $group = new Form_Group('');
867
868 $group->add(new Form_Button(
869 'movetoenabled',
870 'Move to "Member of" list',
871 null,
872 'fa-angle-double-right'
873 ))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
874
875 $group->add(new Form_Button(
876 'movetodisabled',
877 'Move to "Not member of" list',
878 null,
879 'fa-angle-double-left'
880 ))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
881
882 $group->setHelp('Hold down CTRL (PC)/COMMAND (Mac) key to select multiple items.');
883 $section->add($group);
884
885 // ==== Button for adding user certificate ================================
886 if ($act == 'new') {
887 if (count($nonPrvCas) > 0) {
888 $section->addInput(new Form_Checkbox(
889 'showcert',
890 'Certificate',
891 'Click to create a user certificate',
892 false
893 ));
894 } else {
895 $section->addInput(new Form_StaticText(
896 'Certificate',
897 gettext('No private CAs found. A private CA is required to create a new user certificate. ' .
898 'Save the user first to import an external certificate.')
899 ));
900 }
901 }
902
903 $form->add($section);
904
905 // ==== Effective privileges section ======================================
906 if (isset($pconfig['uid'])) {
907 // We are going to build an HTML table and add it to an Input_StaticText. It may be ugly, but it
908 // is the best way to make the display we need.
909
910 $section = new Form_Section('Effective Privileges');
911
912 $section->addInput(new Form_StaticText(
913 null,
914 build_priv_table()
915 ));
916
917 $form->add($section);
918
919 // ==== Certificate table section =====================================
920 $section = new Form_Section('User Certificates');
921
922 $section->addInput(new Form_StaticText(
923 null,
924 build_cert_table()
925 ));
926
927 $form->add($section);
928 }
929
930 // ==== Add user certificate for a new user
931 if (is_array($config['ca']) && count($config['ca']) > 0) {
932 $section = new Form_Section('Create Certificate for User');
933 $section->addClass('cert-options');
934
935 if (!empty($nonPrvCas)) {
936 $section->addInput(new Form_Input(
937 'name',
938 'Descriptive name',
939 'text',
940 $pconfig['name']
941 ));
942
943 $section->addInput(new Form_Select(
944 'caref',
945 'Certificate authority',
946 null,
947 $nonPrvCas
948 ));
949
950 $section->addInput(new Form_Select(
951 'keylen',
952 'Key length',
953 2048,
954 array(
955 512 => '512 bits',
956 1024 => '1024 bits',
957 2048 => '2048 bits',
958 3072 => '3072 bits',
959 4096 => '4096 bits',
960 7680 => '7680 bits',
961 8192 => '8192 bits',
962 15360 => '15360 bits',
963 16384 => '16384 bits'
964 )
965 ))->setHelp('The larger the key, the more security it offers, but larger keys take considerably more time to generate, ' .
966 'and take slightly longer to validate leading to a slight slowdown in setting up new sessions (not always noticeable). ' .
967 'As of 2016, 2048 bit is the minimum and most common selection and 4096 is the maximum in common use. ' .
968 'For more information see %1$s.', '<a href="https://keylength.com">keylength.com</a>');
969
970 $section->addInput(new Form_Input(
971 'lifetime',
972 'Lifetime',
973 'number',
974 $pconfig['lifetime']
975 ));
976 }
977
978 $form->add($section);
979 }
980
981endif;
982// ==== Paste a key for the new user
983$section = new Form_Section('Keys');
984
985$section->addInput(new Form_Checkbox(
986 'showkey',
987 'Authorized keys',
988 'Click to paste an authorized key',
989 false
990));
991
992$section->addInput(new Form_Textarea(
993 'authorizedkeys',
994 'Authorized SSH Keys',
995 $pconfig['authorizedkeys']
996))->setHelp('Enter authorized SSH keys for this user');
997
998$section->addInput(new Form_Input(
999 'ipsecpsk',
1000 'IPsec Pre-Shared Key',
1001 'text',
1002 $pconfig['ipsecpsk']
1003));
1004
1005$form->add($section);
1006
1007print $form;
1008
1009$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
1010?>
1011<script type="text/javascript">
1012//<![CDATA[
1013events.push(function() {
1014
1015 function setcustomoptions() {
1016 var adv = $('#customsettings').prop('checked');
1017
1018 hideInput('webguicss', !adv);
1019 hideInput('webguifixedmenu', !adv);
1020 hideInput('webguihostnamemenu', !adv);
1021 hideInput('dashboardcolumns', !adv);
1022 hideCheckbox('interfacessort', !adv);
1023 hideCheckbox('dashboardavailablewidgetspanel', !adv);
1024 hideCheckbox('systemlogsfilterpanel', !adv);
1025 hideCheckbox('systemlogsmanagelogpanel', !adv);
1026 hideCheckbox('statusmonitoringsettingspanel', !adv);
1027 hideCheckbox('webguileftcolumnhyper', !adv);
1028 hideCheckbox('disablealiaspopupdetail', !adv);
1029 hideCheckbox('pagenamefirst', !adv);
1030 }
1031
1032 // Handle displaying a warning message if a user-created theme is selected.
1033 function setThemeWarning() {
1034 if ($('#webguicss').val().startsWith("pfSense")) {
1035 $('#csstxt').html("").addClass("text-default");
1036 } else {
1037 $('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
1038 }
1039 }
1040
1041 $('#webguicss').change(function() {
1042 setThemeWarning();
1043 });
1044
1045 setThemeWarning();
1046
1047 // On click . .
1048 $('#customsettings').click(function () {
1049 setcustomoptions();
1050 });
1051
1052 $("#movetodisabled").click(function() {
1053 moveOptions($('[name="groups[]"] option'), $('[name="sysgroups[]"]'));
1054 });
1055
1056 $("#movetoenabled").click(function() {
1057 moveOptions($('[name="sysgroups[]"] option'), $('[name="groups[]"]'));
1058 });
1059
1060 $("#showcert").click(function() {
1061 hideClass('cert-options', !this.checked);
1062 });
1063
1064 $("#showkey").click(function() {
1065 hideInput('authorizedkeys', false);
1066 hideCheckbox('showkey', true);
1067 });
1068
1069 $('[id^=delcert]').click(function(event) {
1070 if (confirm(event.target.title)) {
1071 $('#certid').val(event.target.id.match(/\d+$/)[0]);
1072 $('#userid').val('<?=$id;?>');
1073 $('#act').val('delcert');
1074 $('form').submit();
1075 }
1076 });
1077
1078 $('[id^=delprivid]').click(function(event) {
1079 if (confirm(event.target.title)) {
1080 $('#privid').val(event.target.id.match(/\d+$/)[0]);
1081 $('#userid').val('<?=$id;?>');
1082 $('#act').val('delprivid');
1083 $('form').submit();
1084 }
1085 });
1086
1087 $('#expires').datepicker();
1088
1089 // ---------- On initial page load ------------------------------------------------------------
1090
1091 hideClass('cert-options', true);
1092 //hideInput('authorizedkeys', true);
1093 hideCheckbox('showkey', true);
1094 setcustomoptions();
1095
1096 // On submit mark all the user's groups as "selected"
1097 $('form').submit(function() {
1098 AllServers($('[name="groups[]"] option'), true);
1099 });
1100
1101});
1102//]]>
1103</script>
1104<?php
1105include('foot.inc');
1106?>