Project

General

Profile

Download (8.44 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	priv.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (C) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
7
	Copyright (C) 2006 Paul Taylor <paultaylor@winn-dixie.com>.
8
	Copyright (C) 2008 Shrew Soft Inc
9
	Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
10
	Copyright (c) 2004-2016 Electric Sheep Fencing, LLC.
11
	All rights reserved.
12

    
13
	Redistribution and use in source and binary forms, with or without
14
	modification, are permitted provided that the following conditions are met:
15

    
16
	1. Redistributions of source code must retain the above copyright notice,
17
	   this list of conditions and the following disclaimer.
18

    
19
	2. Redistributions in binary form must reproduce the above copyright
20
	   notice, this list of conditions and the following disclaimer in
21
	   the documentation and/or other materials provided with the
22
	   distribution.
23

    
24
	3. All advertising materials mentioning features or use of this software
25
	   must display the following acknowledgment:
26
	   "This product includes software developed by the pfSense Project
27
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
28

    
29
	4. The names "pfSense" and "pfSense Project" must not be used to
30
	   endorse or promote products derived from this software without
31
	   prior written permission. For written permission, please contact
32
	   coreteam@pfsense.org.
33

    
34
	5. Products derived from this software may not be called "pfSense"
35
	   nor may "pfSense" appear in their names without prior written
36
	   permission of the Electric Sheep Fencing, LLC.
37

    
38
	6. Redistributions of any form whatsoever must retain the following
39
	   acknowledgment:
40

    
41
	"This product includes software developed by the pfSense Project
42
	for use in the pfSense software distribution (http://www.pfsense.org/).
43

    
44
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
45
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
48
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55
	OF THE POSSIBILITY OF SUCH DAMAGE.
56
*/
57

    
58
require_once("priv.defs.inc");
59

    
60
/* Load and process custom privs. */
61
function get_priv_files($directory) {
62
	$dir_array = array();
63
	if (!is_dir($directory)) {
64
		return;
65
	}
66
	if ($dh = opendir($directory)) {
67
		while (($file = readdir($dh)) !== false) {
68
			$canadd = 0;
69
			if ($file == ".") {
70
				$canadd = 1;
71
			}
72
			if ($file == "..") {
73
				$canadd = 1;
74
			}
75
			if ($canadd == 0) {
76
				array_push($dir_array, $file);
77
			}
78
		}
79
		closedir($dh);
80
	}
81
	if (!is_array($dir_array)) {
82
		return;
83
	}
84
	return $dir_array;
85
}
86

    
87
// Load and sort privs
88
$dir_array = get_priv_files("/etc/inc/priv");
89
foreach ($dir_array as $file) {
90
	if (!is_dir("/etc/inc/priv/{$file}") && stristr($file, ".inc")) {
91
		include("/etc/inc/priv/{$file}");
92
	}
93
}
94
if (is_dir("/usr/local/pkg/priv")) {
95
	$dir_array = get_priv_files("/usr/local/pkg/priv");
96
	foreach ($dir_array as $file) {
97
		if (!is_dir("/usr/local/pkg/priv/{$file}") && stristr($file, ".inc")) {
98
			include("/usr/local/pkg/priv/{$file}");
99
		}
100
	}
101
}
102

    
103
if (is_array($priv_list)) {
104
	sort_privs($priv_list);
105
}
106

    
107
function cmp_privkeys($a, $b) {
108
	/* user privs at the top */
109
	$auser = strncmp("user-", $a, 5);
110
	$buser = strncmp("user-", $b, 5);
111
	if ($auser != $buser) {
112
		return $auser - $buser;
113
	}
114

    
115
	/* name compare others */
116
	return strcasecmp($a, $b);
117
}
118

    
119
function sort_privs(& $privs) {
120
	uksort($privs, "cmp_privkeys");
121
}
122

    
123
function cmp_page_matches($page, & $matches, $fullwc = true) {
124

    
125
//	$dbg_matches = implode(",", $matches);
126
//	log_error("debug: checking page {$page} match with {$dbg_matches}");
127

    
128
	if (!is_array($matches)) {
129
		return false;
130
	}
131

    
132
	/* skip any leading fwdslash */
133
	$test = strpos($page, "/");
134
	if ($test !== false && $test == 0) {
135
		$page = substr($page, 1);
136
	}
137

    
138
	/* look for a match */
139
	foreach ($matches as $match) {
140

    
141
		/* possibly ignore full wildcard match */
142
		if (!$fullwc && !strcmp($match , "*")) {
143
			continue;
144
		}
145

    
146
		/* compare exact or wildcard match */
147
		$match = str_replace(array(".", "*", "?"), array("\.", ".*", "\?"), $match);
148
		$result = preg_match("@^/{$match}$@", "/{$page}");
149

    
150
		if ($result) {
151
			return true;
152
		}
153
	}
154

    
155
	return false;
156
}
157

    
158
function map_page_privname($page) {
159
	global $priv_list;
160

    
161
	foreach ($priv_list as $pname => $pdata) {
162
		if (strncmp($pname, "page-", 5)) {
163
			continue;
164
		}
165
		$fullwc = false;
166
		if (!strcasecmp($page, "any")||!strcmp($page, "*")) {
167
			$fullwc = true;
168
		}
169
		if (cmp_page_matches($page, $pdata['match'], $fullwc)) {
170
			return $pname;
171
		}
172
	}
173

    
174
	return false;
175
}
176

    
177
function get_user_privdesc(& $user) {
178
	global $priv_list;
179

    
180
	$privs = array();
181

    
182
	$user_privs = $user['priv'];
183
	if (!is_array($user_privs)) {
184
		$user_privs = array();
185
	}
186

    
187
	$names = local_user_get_groups($user, true);
188

    
189
	foreach ($names as $name) {
190
		$group = getGroupEntry($name);
191
		$group_privs = $group['priv'];
192
		if (!is_array($group_privs)) {
193
			continue;
194
		}
195
		foreach ($group_privs as $pname) {
196
			if (in_array($pname, $user_privs)) {
197
				continue;
198
			}
199
			if (!$priv_list[$pname]) {
200
				continue;
201
			}
202
			$priv = $priv_list[$pname];
203
			$priv['group'] = $group['name'];
204
			$privs[] = $priv;
205
		}
206
	}
207

    
208
	foreach ($user_privs as $pname) {
209
		if ($priv_list[$pname]) {
210
			$privs[] = $priv_list[$pname];
211
		}
212
	}
213

    
214
	return $privs;
215
}
216

    
217
function isAllowed($username, $page) {
218
	global $_SESSION;
219

    
220
	if (!isset($username)) {
221
		return false;
222
	}
223

    
224
	/* admin/root access check */
225
	$user = getUserEntry($username);
226
	if (isset($user)) {
227
		if (isset($user['uid'])) {
228
			if ($user['uid'] == 0) {
229
				return true;
230
			}
231
		}
232
	}
233

    
234
	/* user privilege access check */
235
	if (cmp_page_matches($page, $_SESSION['page-match'])) {
236
		return true;
237
	}
238

    
239
	return false;
240
}
241

    
242

    
243
function isAllowedPage($page) {
244
	global $_SESSION;
245

    
246

    
247
	$username = $_SESSION['Username'];
248

    
249
	if (!isset($username)) {
250
		return false;
251
	}
252

    
253
	/* admin/root access check */
254
	$user = getUserEntry($username);
255
	if (isset($user)) {
256
		if (isset($user['uid'])) {
257
			if ($user['uid'] == 0) {
258
				return true;
259
			}
260
		}
261
	}
262

    
263
	/* user privilege access check */
264
	return cmp_page_matches($page, $_SESSION['page-match']);
265
}
266

    
267
function getPrivPages(& $entry, & $allowed_pages) {
268
	global $priv_list;
269

    
270
	if (!is_array($entry['priv'])) {
271
		return;
272
	}
273

    
274
	foreach ($entry['priv'] as $pname) {
275
		if (strncmp($pname, "page-", 5)) {
276
			continue;
277
		}
278
		$priv = &$priv_list[$pname];
279
		if (!is_array($priv)) {
280
			continue;
281
		}
282
		$matches = &$priv['match'];
283
		if (!is_array($matches)) {
284
			continue;
285
		}
286
		foreach ($matches as $match) {
287
			$allowed_pages[] = $match;
288
		}
289
	}
290
}
291

    
292
function getAllowedPages($username, &$attributes = array()) {
293
	global $config, $_SESSION;
294

    
295
	if (!function_exists("ldap_connect")) {
296
		return;
297
	}
298

    
299
	$allowed_pages = array();
300
	$allowed_groups = array();
301

    
302
	$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
303
	// obtain ldap groups if we are in ldap mode
304
	if ($authcfg['type'] == "ldap") {
305
		$allowed_groups = @ldap_get_groups($username, $authcfg);
306
	} elseif ($authcfg['type'] == "radius") {
307
		$allowed_groups = @radius_get_groups($attributes);
308
	}
309
	if (!$allowed_groups) {
310
		// search for a local user by name
311
		$local_user = getUserEntry($username);
312

    
313
		// obtain local user pages and groups if we have a local user
314
		if ($local_user) {
315
			getPrivPages($local_user, $allowed_pages);
316
			$allowed_groups = local_user_get_groups($local_user);
317
		}
318
	}
319

    
320
	// build a list of allowed pages
321
	if (is_array($config['system']['group']) && is_array($allowed_groups)) {
322
		foreach ($config['system']['group'] as $group) {
323
			if (in_array($group['name'], $allowed_groups)) {
324
				getPrivPages($group, $allowed_pages);
325
			}
326
		}
327
	}
328

    
329
//	$dbg_pages = implode(",", $allowed_pages);
330
//	$dbg_groups = implode(",", $allowed_groups);
331
//	log_error("debug: user {$username} groups = {$dbg_groups}");
332
//	log_error("debug: user {$username} pages = {$dbg_pages}");
333

    
334
	$_SESSION['page-match'] = $allowed_pages;
335

    
336
	return $allowed_pages;
337
}
338

    
339
function sort_user_privs($privs) {
340
	// Privileges to place first, to redirect properly.
341
	$priority_privs = array("page-dashboard-all", "page-system-login-logout");
342

    
343
	$fprivs = array_intersect($privs, $priority_privs);
344
	$sprivs = array_diff($privs, $priority_privs);
345

    
346
	return array_merge($fprivs, $sprivs);
347
}
348
?>
(43-43/65)