Project

General

Profile

Download (14.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * system_groupmanager.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2005 Paul Taylor <paultaylor@winn-dixie.com>
8
 * Copyright (c) 2008 Shrew Soft Inc
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-groupmanager
30
##|*NAME=System: Group Manager
31
##|*DESCR=Allow access to the 'System: Group Manager' page.
32
##|*WARN=standard-warning-root
33
##|*MATCH=system_groupmanager.php*
34
##|-PRIV
35

    
36
require_once("guiconfig.inc");
37
require_once("pfsense-utils.inc");
38

    
39
$logging_level = LOG_WARNING;
40
$logging_prefix = gettext("Local User Database");
41

    
42
if (!is_array($config['system']['group'])) {
43
	$config['system']['group'] = array();
44
}
45

    
46
$a_group = &$config['system']['group'];
47

    
48
unset($id);
49
$id = $_REQUEST['groupid'];
50
$act = (isset($_REQUEST['act']) ? $_REQUEST['act'] : '');
51

    
52
function cpusercmp($a, $b) {
53
	return strcasecmp($a['name'], $b['name']);
54
}
55

    
56
function admin_groups_sort() {
57
	global $a_group;
58

    
59
	if (!is_array($a_group)) {
60
		return;
61
	}
62

    
63
	usort($a_group, "cpusercmp");
64
}
65

    
66
if ($_POST['act'] == "delgroup") {
67

    
68
	if (!isset($id) || !isset($_REQUEST['groupname']) || !isset($a_group[$id]) || ($_REQUEST['groupname'] != $a_group[$id]['name'])) {
69
		pfSenseHeader("system_groupmanager.php");
70
		exit;
71
	}
72

    
73
	local_group_del($a_group[$id]);
74
	$groupdeleted = $a_group[$id]['name'];
75
	unset($a_group[$id]);
76
	/* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
77
	$a_group = array_values($a_group);
78

    
79
	$savemsg = sprintf(gettext("Successfully deleted group: %s"), $groupdeleted);
80
	write_config($savemsg);
81
	syslog($logging_level, "{$logging_prefix}: {$savemsg}");
82
}
83

    
84
if ($_POST['act'] == "delpriv") {
85

    
86
	if (!isset($id) || !isset($a_group[$id])) {
87
		pfSenseHeader("system_groupmanager.php");
88
		exit;
89
	}
90

    
91
	$privdeleted = $priv_list[$a_group[$id]['priv'][$_REQUEST['privid']]]['name'];
92
	unset($a_group[$id]['priv'][$_REQUEST['privid']]);
93

    
94
	if (is_array($a_group[$id]['member'])) {
95
		foreach ($a_group[$id]['member'] as $uid) {
96
			$user = getUserEntryByUID($uid);
97
			if ($user) {
98
				local_user_set($user);
99
			}
100
		}
101
	}
102

    
103
	$savemsg = sprintf(gettext("Removed Privilege \"%s\" from group %s"), $privdeleted, $a_group[$id]['name']);
104
	write_config($savemsg);
105
	syslog($logging_level, "{$logging_prefix}: {$savemsg}");
106

    
107
	$act = "edit";
108
}
109

    
110
if ($act == "edit") {
111
	if (isset($id) && isset($a_group[$id])) {
112
		$pconfig['name'] = $a_group[$id]['name'];
113
		$pconfig['gid'] = $a_group[$id]['gid'];
114
		$pconfig['gtype'] = empty($a_group[$id]['scope']) ? "local" : $a_group[$id]['scope'];
115
		$pconfig['description'] = $a_group[$id]['description'];
116
		$pconfig['members'] = $a_group[$id]['member'];
117
		$pconfig['priv'] = $a_group[$id]['priv'];
118
	}
119
}
120

    
121
if (isset($_POST['dellall_x'])) {
122

    
123
	$del_groups = $_POST['delete_check'];
124
	$deleted_groups = array();
125

    
126
	if (!empty($del_groups)) {
127
		foreach ($del_groups as $groupid) {
128
			if (isset($a_group[$groupid]) && $a_group[$groupid]['scope'] != "system") {
129
				$deleted_groups[] = $a_group[$groupid]['name'];
130
				local_group_del($a_group[$groupid]);
131
				unset($a_group[$groupid]);
132
			}
133
		}
134

    
135
		$savemsg = sprintf(gettext("Successfully deleted %s: %s"), (count($deleted_groups) == 1) ? gettext("group") : gettext("groups"), implode(', ', $deleted_groups));
136
		/* Reindex the array to avoid operating on an incorrect index https://redmine.pfsense.org/issues/7733 */
137
		$a_group = array_values($a_group);
138
		write_config($savemsg);
139
		syslog($logging_level, "{$logging_prefix}: {$savemsg}");
140
	}
141
}
142

    
143
if (isset($_POST['save'])) {
144
	unset($input_errors);
145
	$pconfig = $_POST;
146

    
147
	/* input validation */
148
	$reqdfields = explode(" ", "groupname");
149
	$reqdfieldsn = array(gettext("Group Name"));
150

    
151
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
152

    
153
	if ($_POST['gtype'] != "remote") {
154
		if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['groupname'])) {
155
			$input_errors[] = sprintf(gettext("The (%s) group name contains invalid characters."), $_POST['gtype']);
156
		}
157
	} else {
158
		if (preg_match("/[^a-zA-Z0-9\.\- _]/", $_POST['groupname'])) {
159
			$input_errors[] = sprintf(gettext("The (%s) group name contains invalid characters."), $_POST['gtype']);
160
		}
161
	}
162

    
163
	if (strlen($_POST['groupname']) > 16) {
164
		$input_errors[] = gettext("The group name is longer than 16 characters.");
165
	}
166

    
167
	/* Check the POSTed members to ensure they are valid and exist */
168
	if (is_array($_POST['members'])) {
169
		foreach ($_POST['members'] as $newmember) {
170
			if (!is_numeric($newmember) || empty(getUserEntryByUID($newmember))) {
171
				$input_errors[] = gettext("One or more invalid group members was submitted.");
172
			}
173
		}
174
	}
175

    
176
	if (!$input_errors && !(isset($id) && $a_group[$id])) {
177
		/* make sure there are no dupes */
178
		foreach ($a_group as $group) {
179
			if ($group['name'] == $_POST['groupname']) {
180
				$input_errors[] = gettext("Another entry with the same group name already exists.");
181
				break;
182
			}
183
		}
184
	}
185

    
186
	if (!$input_errors) {
187
		$group = array();
188
		if (isset($id) && $a_group[$id]) {
189
			$group = $a_group[$id];
190
		}
191

    
192
		$group['name'] = $_POST['groupname'];
193
		$group['description'] = $_POST['description'];
194
		$group['scope'] = $_POST['gtype'];
195

    
196
		if (empty($_POST['members'])) {
197
			unset($group['member']);
198
		} else if ($group['gid'] != 1998) { // all group
199
			$group['member'] = $_POST['members'];
200
		}
201

    
202
		if (isset($id) && $a_group[$id]) {
203
			$a_group[$id] = $group;
204
		} else {
205
			$group['gid'] = $config['system']['nextgid']++;
206
			$a_group[] = $group;
207
		}
208

    
209
		admin_groups_sort();
210

    
211
		local_group_set($group);
212

    
213
		/* Refresh users in this group since their privileges may have changed. */
214
		if (is_array($group['member'])) {
215
			$a_user = &$config['system']['user'];
216
			foreach ($a_user as & $user) {
217
				if (in_array($user['uid'], $group['member'])) {
218
					local_user_set($user);
219
				}
220
			}
221
		}
222

    
223
		/* Sort it alphabetically */
224
		usort($config['system']['group'], function($a, $b) {
225
			return strcmp($a['name'], $b['name']);
226
		});
227

    
228
		$savemsg = sprintf(gettext("Successfully %s group %s"), (strlen($id) > 0) ? gettext("edited") : gettext("created"), $group['name']);
229
		write_config($savemsg);
230
		syslog($logging_level, "{$logging_prefix}: {$savemsg}");
231

    
232
		header("Location: system_groupmanager.php");
233
		exit;
234
	}
235

    
236
	$pconfig['name'] = $_POST['groupname'];
237
}
238

    
239
function build_priv_table() {
240
	global $a_group, $id;
241

    
242
	$privhtml = '<div class="table-responsive">';
243
	$privhtml .=	'<table class="table table-striped table-hover table-condensed">';
244
	$privhtml .=		'<thead>';
245
	$privhtml .=			'<tr>';
246
	$privhtml .=				'<th>' . gettext('Name') . '</th>';
247
	$privhtml .=				'<th>' . gettext('Description') . '</th>';
248
	$privhtml .=				'<th>' . gettext('Action') . '</th>';
249
	$privhtml .=			'</tr>';
250
	$privhtml .=		'</thead>';
251
	$privhtml .=		'<tbody>';
252

    
253
	$user_has_root_priv = false;
254

    
255
	foreach (get_user_privdesc($a_group[$id]) as $i => $priv) {
256
		$privhtml .=		'<tr>';
257
		$privhtml .=			'<td>' . htmlspecialchars($priv['name']) . '</td>';
258
		$privhtml .=			'<td>' . htmlspecialchars($priv['descr']);
259
		if (isset($priv['warn']) && ($priv['warn'] == 'standard-warning-root')) {
260
			$privhtml .=			' ' . gettext('(admin privilege)');
261
			$user_has_root_priv = true;
262
		}
263
		$privhtml .=			'</td>';
264
		$privhtml .=			'<td><a class="fa fa-trash" title="' . gettext('Delete Privilege') . '"	href="system_groupmanager.php?act=delpriv&amp;groupid=' . $id . '&amp;privid=' . $i . '" usepost></a></td>';
265
		$privhtml .=		'</tr>';
266

    
267
	}
268

    
269
	if ($user_has_root_priv) {
270
		$privhtml .=		'<tr>';
271
		$privhtml .=			'<td colspan="2">';
272
		$privhtml .=				'<b>' . gettext('Security notice: Users in this group effectively have administrator-level access') . '</b>';
273
		$privhtml .=			'</td>';
274
		$privhtml .=			'<td>';
275
		$privhtml .=			'</td>';
276
		$privhtml .=		'</tr>';
277

    
278
	}
279

    
280
	$privhtml .=		'</tbody>';
281
	$privhtml .=	'</table>';
282
	$privhtml .= '</div>';
283

    
284
	$privhtml .= '<nav class="action-buttons">';
285
	$privhtml .=	'<a href="system_groupmanager_addprivs.php?groupid=' . $id . '" class="btn btn-success"><i class="fa fa-plus icon-embed-btn"></i>' . gettext("Add") . '</a>';
286
	$privhtml .= '</nav>';
287

    
288
	return($privhtml);
289
}
290

    
291
$pgtitle = array(gettext("System"), gettext("User Manager"), gettext("Groups"));
292
$pglinks = array("", "system_usermanager.php", "system_groupmanager.php");
293

    
294
if ($act == "new" || $act == "edit") {
295
	$pgtitle[] = gettext('Edit');
296
	$pglinks[] = "@self";
297
}
298

    
299
include("head.inc");
300

    
301
if ($input_errors) {
302
	print_input_errors($input_errors);
303
}
304

    
305
if ($savemsg) {
306
	print_info_box($savemsg, 'success');
307
}
308

    
309
$tab_array = array();
310
$tab_array[] = array(gettext("Users"), false, "system_usermanager.php");
311
$tab_array[] = array(gettext("Groups"), true, "system_groupmanager.php");
312
$tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
313
$tab_array[] = array(gettext("Authentication Servers"), false, "system_authservers.php");
314
display_top_tabs($tab_array);
315

    
316
if (!($act == "new" || $act == "edit")) {
317
?>
318
<div class="panel panel-default">
319
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Groups')?></h2></div>
320
	<div class="panel-body">
321
		<div class="table-responsive">
322
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
323
				<thead>
324
					<tr>
325
						<th><?=gettext("Group name")?></th>
326
						<th><?=gettext("Description")?></th>
327
						<th><?=gettext("Member Count")?></th>
328
						<th><?=gettext("Actions")?></th>
329
					</tr>
330
				</thead>
331
				<tbody>
332
<?php
333
	foreach ($a_group as $i => $group):
334
		if ($group["name"] == "all") {
335
			$groupcount = count($config['system']['user']);
336
		} else {
337
			$groupcount = count($group['member']);
338
		}
339
?>
340
					<tr>
341
						<td>
342
							<?=htmlspecialchars($group['name'])?>
343
						</td>
344
						<td>
345
							<?=htmlspecialchars($group['description'])?>
346
						</td>
347
						<td>
348
							<?=$groupcount?>
349
						</td>
350
						<td>
351
							<a class="fa fa-pencil" title="<?=gettext("Edit group"); ?>" href="?act=edit&amp;groupid=<?=$i?>"></a>
352
							<?php if ($group['scope'] != "system"): ?>
353
								<a class="fa fa-trash"	title="<?=gettext("Delete group")?>" href="?act=delgroup&amp;groupid=<?=$i?>&amp;groupname=<?=$group['name']?>" usepost></a>
354
							<?php endif;?>
355
						</td>
356
					</tr>
357
<?php
358
	endforeach;
359
?>
360
				</tbody>
361
			</table>
362
		</div>
363
	</div>
364
</div>
365

    
366
<nav class="action-buttons">
367
	<a href="?act=new" class="btn btn-success btn-sm">
368
		<i class="fa fa-plus icon-embed-btn"></i>
369
		<?=gettext("Add")?>
370
	</a>
371
</nav>
372
<?php
373
	include('foot.inc');
374
	exit;
375
}
376

    
377
$form = new Form;
378
$form->setAction('system_groupmanager.php?act=edit');
379
$form->addGlobal(new Form_Input(
380
	'groupid',
381
	null,
382
	'hidden',
383
	$id
384
));
385

    
386
if (isset($id) && $a_group[$id]) {
387
	$form->addGlobal(new Form_Input(
388
		'id',
389
		null,
390
		'hidden',
391
		$id
392
	));
393

    
394
	$form->addGlobal(new Form_Input(
395
		'gid',
396
		null,
397
		'hidden',
398
		$pconfig['gid']
399
	));
400
}
401

    
402
$section = new Form_Section('Group Properties');
403

    
404
$section->addInput($input = new Form_Input(
405
	'groupname',
406
	'*Group name',
407
	'text',
408
	$pconfig['name']
409
));
410

    
411
if ($pconfig['gtype'] == "system") {
412
	$input->setReadonly();
413

    
414
	$section->addInput(new Form_Input(
415
		'gtype',
416
		'*Scope',
417
		'text',
418
		$pconfig['gtype']
419
	))->setReadonly();
420
} else {
421
	$section->addInput(new Form_Select(
422
		'gtype',
423
		'*Scope',
424
		$pconfig['gtype'],
425
		["local" => gettext("Local"), "remote" => gettext("Remote")]
426
	));
427
}
428

    
429
$section->addInput(new Form_Input(
430
	'description',
431
	'Description',
432
	'text',
433
	$pconfig['description']
434
))->setHelp('Group description, for administrative information only');
435

    
436

    
437
$form->add($section);
438
if ($pconfig['gid'] != 1998) { // all users group
439

    
440
	// ==== Group membership ==================================================
441
	$group = new Form_Group('Group membership');
442

    
443
	// Make a list of all the groups configured on the system, and a list of
444
	// those which this user is a member of
445
	$systemGroups = array();
446
	$usersGroups = array();
447

    
448
	foreach ($config['system']['user'] as $user) {
449
		if (is_array($pconfig['members']) && in_array($user['uid'], $pconfig['members'])) {
450
			$usersGroups[ $user['uid'] ] = $user['name'];	// Add it to the user's list
451
		} else {
452
			$systemGroups[ $user['uid'] ] = $user['name']; // Add it to the 'not a member of' list
453
		}
454
	}
455

    
456
	$group->add(new Form_Select(
457
		'notmembers',
458
		null,
459
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
460
		$systemGroups,
461
		true
462
	))->setHelp('Not members');
463

    
464
	$group->add(new Form_Select(
465
		'members',
466
		null,
467
		array_combine((array)$pconfig['groups'], (array)$pconfig['groups']),
468
		$usersGroups,
469
		true
470
	))->setHelp('Members');
471

    
472
	$section->add($group);
473

    
474
	$group = new Form_Group('');
475

    
476
	$group->add(new Form_Button(
477
		'movetoenabled',
478
		'Move to "Members"',
479
		null,
480
		'fa-angle-double-right'
481
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
482

    
483
	$group->add(new Form_Button(
484
		'movetodisabled',
485
		'Move to "Not members',
486
		null,
487
		'fa-angle-double-left'
488
	))->setAttribute('type','button')->removeClass('btn-primary')->addClass('btn-info btn-sm');
489

    
490
	$group->setHelp('Hold down CTRL (PC)/COMMAND (Mac) key to select multiple items.');
491
	$section->add($group);
492

    
493
}
494

    
495
if (isset($pconfig['gid'])) {
496
	$section = new Form_Section('Assigned Privileges');
497

    
498
	$section->addInput(new Form_StaticText(
499
		null,
500
		build_priv_table()
501
	));
502

    
503

    
504
	$form->add($section);
505
}
506

    
507
print $form;
508
?>
509
<script type="text/javascript">
510
//<![CDATA[
511
events.push(function() {
512

    
513
	// On click . .
514
	$("#movetodisabled").click(function() {
515
		moveOptions($('[name="members[]"] option'), $('[name="notmembers[]"]'));
516
	});
517

    
518
	$("#movetoenabled").click(function() {
519
		moveOptions($('[name="notmembers[]"] option'), $('[name="members[]"]'));
520
	});
521

    
522
	// On submit mark all the user's groups as "selected"
523
	$('form').submit(function() {
524
		AllServers($('[name="members[]"] option'), true);
525
	});
526
});
527
//]]>
528
</script>
529
<?php
530
include('foot.inc');
(205-205/232)