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