Project

General

Profile

Download (7.81 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * priv.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
8
 * Copyright (c) 2006 Paul Taylor <paultaylor@winn-dixie.com>.
9
 * Copyright (c) 2008 Shrew Soft Inc
10
 * Copyright (c) 2003-2006 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12
 *
13
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16
 *
17
 * http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24
 */
25

    
26
require_once("priv.defs.inc");
27

    
28
/* Load and process custom privs. */
29
function get_priv_files($directory) {
30
	$dir_array = array();
31
	if (!is_dir($directory)) {
32
		return;
33
	}
34
	if ($dh = opendir($directory)) {
35
		while (($file = readdir($dh)) !== false) {
36
			$canadd = 0;
37
			if ($file == ".") {
38
				$canadd = 1;
39
			}
40
			if ($file == "..") {
41
				$canadd = 1;
42
			}
43
			if ($canadd == 0) {
44
				array_push($dir_array, $file);
45
			}
46
		}
47
		closedir($dh);
48
	}
49
	if (!is_array($dir_array)) {
50
		return;
51
	}
52
	return $dir_array;
53
}
54

    
55
// Load and sort privs
56
$dir_array = get_priv_files("/etc/inc/priv");
57
foreach ($dir_array as $file) {
58
	if (!is_dir("/etc/inc/priv/{$file}") && substr($file, -4) == ".inc") {
59
		include_once("/etc/inc/priv/{$file}");
60
	}
61
}
62
if (is_dir("/usr/local/pkg/priv")) {
63
	$dir_array = get_priv_files("/usr/local/pkg/priv");
64
	foreach ($dir_array as $file) {
65
		if (!is_dir("/usr/local/pkg/priv/{$file}") &&
66
		    substr($file, -4) == ".inc") {
67
			include_once("/usr/local/pkg/priv/{$file}");
68
		}
69
	}
70
}
71

    
72
if (is_array($priv_list)) {
73
	sort_privs($priv_list);
74
}
75

    
76
function cmp_privkeys($a, $b) {
77
	/* user privs at the top */
78
	$auser = strncmp("user-", $a, 5);
79
	$buser = strncmp("user-", $b, 5);
80
	if ($auser != $buser) {
81
		return $auser - $buser;
82
	}
83

    
84
	/* name compare others */
85
	return strcasecmp($a, $b);
86
}
87

    
88
function sort_privs(& $privs) {
89
	uksort($privs, "cmp_privkeys");
90
}
91

    
92
function cmp_page_matches($page, & $matches, $fullwc = true) {
93

    
94
//	$dbg_matches = implode(",", $matches);
95
//	log_error("debug: checking page {$page} match with {$dbg_matches}");
96

    
97
	if (!is_array($matches)) {
98
		return false;
99
	}
100

    
101
	/* skip any leading fwdslash */
102
	$test = strpos($page, "/");
103
	if ($test !== false && $test == 0) {
104
		$page = substr($page, 1);
105
	}
106

    
107
	/* look for a match */
108
	foreach ($matches as $match) {
109

    
110
		/* possibly ignore full wildcard match */
111
		if (!$fullwc && !strcmp($match , "*")) {
112
			continue;
113
		}
114

    
115
		/* compare exact or wildcard match */
116
		$match = str_replace(array(".", "*", "?"), array("\.", ".*", "\?"), $match);
117
		$result = preg_match("@^/{$match}$@", "/{$page}");
118

    
119
		if ($result) {
120
			return true;
121
		}
122
	}
123

    
124
	return false;
125
}
126

    
127
function map_page_privname($page) {
128
	global $priv_list;
129

    
130
	foreach ($priv_list as $pname => $pdata) {
131
		if (strncmp($pname, "page-", 5)) {
132
			continue;
133
		}
134
		$fullwc = false;
135
		if (!strcasecmp($page, "any")||!strcmp($page, "*")) {
136
			$fullwc = true;
137
		}
138
		if (cmp_page_matches($page, $pdata['match'], $fullwc)) {
139
			return $pname;
140
		}
141
	}
142

    
143
	return false;
144
}
145

    
146
function get_user_privdesc(& $user) {
147
	global $priv_list;
148

    
149
	$privs = array();
150

    
151
	$user_privs = $user['priv'];
152
	if (!is_array($user_privs)) {
153
		$user_privs = array();
154
	}
155

    
156
	$names = local_user_get_groups($user, true);
157

    
158
	foreach ($names as $name) {
159
		$group = getGroupEntry($name);
160
		$group_privs = $group['priv'];
161
		if (!is_array($group_privs)) {
162
			continue;
163
		}
164
		foreach ($group_privs as $pname) {
165
			if (in_array($pname, $user_privs)) {
166
				continue;
167
			}
168
			if (!$priv_list[$pname]) {
169
				continue;
170
			}
171
			$priv = $priv_list[$pname];
172
			$priv['group'] = $group['name'];
173
			$privs[] = $priv;
174
		}
175
	}
176

    
177
	foreach ($user_privs as $pname) {
178
		if ($priv_list[$pname]) {
179
			$privs[] = $priv_list[$pname];
180
		}
181
	}
182

    
183
	return $privs;
184
}
185

    
186
function isAdminUID($username) {
187
	global $_SESSION;
188

    
189
	if (!isset($username)) {
190
		return false;
191
	}
192

    
193
	/* admin/root access check */
194
	$user = getUserEntry($username);
195
	if (isset($user)) {
196
		if (isset($user['uid'])) {
197
			if ($user['uid'] == 0) {
198
				return true;
199
			}
200
		}
201
	}
202

    
203
	return false;
204
}
205

    
206
function isAllowed($username, $page) {
207
	global $_SESSION;
208

    
209
	if (!isset($username)) {
210
		return false;
211
	}
212

    
213
	if (isAdminUID($username)) {
214
		return true;
215
	}
216

    
217
	/* user privilege access check */
218
	if (cmp_page_matches($page, $_SESSION['page-match'])) {
219
		return true;
220
	}
221

    
222
	return false;
223
}
224

    
225
function isAllowedPage($page) {
226
	global $_SESSION;
227

    
228

    
229
	$username = $_SESSION['Username'];
230

    
231
	if (!isset($username)) {
232
		return false;
233
	}
234

    
235
	if (isAdminUID($username)) {
236
		return true;
237
	}
238

    
239
	/* user privilege access check */
240
	return cmp_page_matches($page, $_SESSION['page-match']);
241
}
242

    
243
function getPrivPages(& $entry, & $allowed_pages) {
244
	global $priv_list;
245

    
246
	if (!is_array($entry['priv'])) {
247
		return;
248
	}
249

    
250
	foreach ($entry['priv'] as $pname) {
251
		if (strncmp($pname, "page-", 5)) {
252
			continue;
253
		}
254
		$priv = &$priv_list[$pname];
255
		if (!is_array($priv)) {
256
			continue;
257
		}
258
		$matches = &$priv['match'];
259
		if (!is_array($matches)) {
260
			continue;
261
		}
262
		foreach ($matches as $match) {
263
			$allowed_pages[] = $match;
264
		}
265
	}
266
}
267

    
268
function getAllowedPages($username, &$attributes = array()) {
269
	global $config, $_SESSION;
270

    
271
	if (!function_exists("ldap_connect")) {
272
		return;
273
	}
274

    
275
	$allowed_pages = array();
276
	$allowed_groups = array();
277

    
278
	if ($_SESSION['remoteauth']) {
279
		$authcfg = auth_get_authserver($config['system']['webgui']['authmode']);
280
		// cache auth results for a short time to ease load on auth services & logs
281
		if (isset($config['system']['webgui']['auth_refresh_time'])) {
282
			$recheck_time = $config['system']['webgui']['auth_refresh_time'];
283
		} else {
284
			$recheck_time = 30;
285
		}
286
		// obtain ldap groups if we are in ldap mode
287
		if ($authcfg['type'] == "ldap") {
288
			if  ( isset($_SESSION["ldap_allowed_groups"]) &&
289
			    ( time() <= $_SESSION["auth_check_time"]+ $recheck_time) ) {
290
				$allowed_groups = $_SESSION["ldap_allowed_groups"];
291
			} else {
292
				$allowed_groups = @ldap_get_groups($username, $authcfg);
293
				$_SESSION["ldap_allowed_groups"] = $allowed_groups;
294
				$_SESSION["auth_check_time"] = time();
295
			}
296
		} elseif ($authcfg['type'] == "radius") {
297
			if  ( isset($_SESSION["radius_allowed_groups"]) &&
298
			    (time() <= $_SESSION["auth_check_time"] + $recheck_time) ) {
299
				$allowed_groups = $_SESSION["radius_allowed_groups"];
300
			} else {
301
				$allowed_groups = @radius_get_groups($attributes);
302
				$_SESSION["radius_allowed_groups"] = $allowed_groups;
303
				$_SESSION["auth_check_time"] = time();
304
			}
305
		}
306

    
307
	}
308
	if (!$allowed_groups) {
309
		// search for a local user by name
310
		$local_user = getUserEntry($username);
311

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

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

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

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

    
335
	return $allowed_pages;
336
}
337

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

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

    
345
	return array_merge($fprivs, $sprivs);
346
}
347
?>
(33-33/51)