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