* Copyright (C) 2006 Paul Taylor . * Copyright (C) 2008 Shrew Soft Inc * Copyright (C) 2003-2006 Manuel Kasper . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * "This product includes software developed by the pfSense Project * for use in the pfSense® software distribution. (http://www.pfsense.org/). * * 4. The names "pfSense" and "pfSense Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * coreteam@pfsense.org. * * 5. Products derived from this software may not be called "pfSense" * nor may "pfSense" appear in their names without prior written * permission of the Electric Sheep Fencing, LLC. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * * "This product includes software developed by the pfSense Project * for use in the pfSense software distribution (http://www.pfsense.org/). * * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ require_once("priv.defs.inc"); /* Load and process custom privs. */ function get_priv_files($directory) { $dir_array = array(); if (!is_dir($directory)) { return; } if ($dh = opendir($directory)) { while (($file = readdir($dh)) !== false) { $canadd = 0; if ($file == ".") { $canadd = 1; } if ($file == "..") { $canadd = 1; } if ($canadd == 0) { array_push($dir_array, $file); } } closedir($dh); } if (!is_array($dir_array)) { return; } return $dir_array; } // Load and sort privs $dir_array = get_priv_files("/etc/inc/priv"); foreach ($dir_array as $file) { if (!is_dir("/etc/inc/priv/{$file}") && stristr($file, ".inc")) { include_once("/etc/inc/priv/{$file}"); } } if (is_dir("/usr/local/pkg/priv")) { $dir_array = get_priv_files("/usr/local/pkg/priv"); foreach ($dir_array as $file) { if (!is_dir("/usr/local/pkg/priv/{$file}") && stristr($file, ".inc")) { include_once("/usr/local/pkg/priv/{$file}"); } } } if (is_array($priv_list)) { sort_privs($priv_list); } function cmp_privkeys($a, $b) { /* user privs at the top */ $auser = strncmp("user-", $a, 5); $buser = strncmp("user-", $b, 5); if ($auser != $buser) { return $auser - $buser; } /* name compare others */ return strcasecmp($a, $b); } function sort_privs(& $privs) { uksort($privs, "cmp_privkeys"); } function cmp_page_matches($page, & $matches, $fullwc = true) { // $dbg_matches = implode(",", $matches); // log_error("debug: checking page {$page} match with {$dbg_matches}"); if (!is_array($matches)) { return false; } /* skip any leading fwdslash */ $test = strpos($page, "/"); if ($test !== false && $test == 0) { $page = substr($page, 1); } /* look for a match */ foreach ($matches as $match) { /* possibly ignore full wildcard match */ if (!$fullwc && !strcmp($match , "*")) { continue; } /* compare exact or wildcard match */ $match = str_replace(array(".", "*", "?"), array("\.", ".*", "\?"), $match); $result = preg_match("@^/{$match}$@", "/{$page}"); if ($result) { return true; } } return false; } function map_page_privname($page) { global $priv_list; foreach ($priv_list as $pname => $pdata) { if (strncmp($pname, "page-", 5)) { continue; } $fullwc = false; if (!strcasecmp($page, "any")||!strcmp($page, "*")) { $fullwc = true; } if (cmp_page_matches($page, $pdata['match'], $fullwc)) { return $pname; } } return false; } function get_user_privdesc(& $user) { global $priv_list; $privs = array(); $user_privs = $user['priv']; if (!is_array($user_privs)) { $user_privs = array(); } $names = local_user_get_groups($user, true); foreach ($names as $name) { $group = getGroupEntry($name); $group_privs = $group['priv']; if (!is_array($group_privs)) { continue; } foreach ($group_privs as $pname) { if (in_array($pname, $user_privs)) { continue; } if (!$priv_list[$pname]) { continue; } $priv = $priv_list[$pname]; $priv['group'] = $group['name']; $privs[] = $priv; } } foreach ($user_privs as $pname) { if ($priv_list[$pname]) { $privs[] = $priv_list[$pname]; } } return $privs; } function isAllowed($username, $page) { global $_SESSION; if (!isset($username)) { return false; } /* admin/root access check */ $user = getUserEntry($username); if (isset($user)) { if (isset($user['uid'])) { if ($user['uid'] == 0) { return true; } } } /* user privilege access check */ if (cmp_page_matches($page, $_SESSION['page-match'])) { return true; } return false; } function isAllowedPage($page) { global $_SESSION; $username = $_SESSION['Username']; if (!isset($username)) { return false; } /* admin/root access check */ $user = getUserEntry($username); if (isset($user)) { if (isset($user['uid'])) { if ($user['uid'] == 0) { return true; } } } /* user privilege access check */ return cmp_page_matches($page, $_SESSION['page-match']); } function getPrivPages(& $entry, & $allowed_pages) { global $priv_list; if (!is_array($entry['priv'])) { return; } foreach ($entry['priv'] as $pname) { if (strncmp($pname, "page-", 5)) { continue; } $priv = &$priv_list[$pname]; if (!is_array($priv)) { continue; } $matches = &$priv['match']; if (!is_array($matches)) { continue; } foreach ($matches as $match) { $allowed_pages[] = $match; } } } function getAllowedPages($username, &$attributes = array()) { global $config, $_SESSION; if (!function_exists("ldap_connect")) { return; } $allowed_pages = array(); $allowed_groups = array(); $authcfg = auth_get_authserver($config['system']['webgui']['authmode']); // obtain ldap groups if we are in ldap mode if ($authcfg['type'] == "ldap") { $allowed_groups = @ldap_get_groups($username, $authcfg); } elseif ($authcfg['type'] == "radius") { $allowed_groups = @radius_get_groups($attributes); } if (!$allowed_groups) { // search for a local user by name $local_user = getUserEntry($username); // obtain local user pages and groups if we have a local user if ($local_user) { getPrivPages($local_user, $allowed_pages); $allowed_groups = local_user_get_groups($local_user); } } // build a list of allowed pages if (is_array($config['system']['group']) && is_array($allowed_groups)) { foreach ($config['system']['group'] as $group) { if (in_array($group['name'], $allowed_groups)) { getPrivPages($group, $allowed_pages); } } } // $dbg_pages = implode(",", $allowed_pages); // $dbg_groups = implode(",", $allowed_groups); // log_error("debug: user {$username} groups = {$dbg_groups}"); // log_error("debug: user {$username} pages = {$dbg_pages}"); $_SESSION['page-match'] = $allowed_pages; return $allowed_pages; } function sort_user_privs($privs) { // Privileges to place first, to redirect properly. $priority_privs = array("page-dashboard-all", "page-system-login-logout"); $fprivs = array_intersect($privs, $priority_privs); $sprivs = array_diff($privs, $priority_privs); return array_merge($fprivs, $sprivs); } ?>