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