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