diff --git a/etc/inc/auth.inc b/etc/inc/auth.inc index a13faaf6dc..c9318bcb03 100644 --- a/etc/inc/auth.inc +++ b/etc/inc/auth.inc @@ -4,6 +4,12 @@ Copyright (C) 2005-2006 Bill Marquette All rights reserved. + Copyright (C) 2006 Paul Taylor . + All rights reserved. + + 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: @@ -26,107 +32,605 @@ POSSIBILITY OF SUCH DAMAGE. */ -require_once("config.inc"); -require_once("globals.inc"); +require_once("functions.inc"); +$groupindex = index_groups(); +$userindex = index_users(); -/* We only support file backed HTTP Basic auth right now */ -$auth_method="htpasswd_backed_basic_auth"; +function &getSystemAdminNames() { + global $config, $g, $userindex; + $adminUsers = array(); -/* Authenticate user - exit if failed (we should have a callback for this maybe) */ -if (!$auth_method()) - exit; + if (is_array($config['system']['user'])) { + foreach($config['system']['user'] as $user){ + if (isSystemAdmin($user['name'])) { + $adminUsers[] = $user['name']; + } + } + } -function basic_auth_prompt(){ - header("WWW-Authenticate: Basic realm=\".\""); - header("HTTP/1.0 401 Unauthorized"); - echo "You must enter valid credentials to access this resource."; - exit; + return $adminUsers; } -function passwd_backed_basic_auth() { - global $HTTP_SERVER_VARS; +function &getSystemPrivs() { + global $g; - $authfile = file("/etc/master.passwd"); + $privs = array(); - /* Prompt three times and give up */ - for($attempt = 0; $attempt <= 3; basic_auth_prompt()){ - $attempt++; - /* Check for AUTH_USER */ - if ($HTTP_SERVER_VARS['PHP_AUTH_USER'] <> "") { - $HTTP_SERVER_VARS['AUTH_USER'] = $HTTP_SERVER_VARS['PHP_AUTH_USER']; - $HTTP_SERVER_VARS['AUTH_PW'] = $HTTP_SERVER_VARS['PHP_AUTH_PW']; - } - if (!isset($HTTP_SERVER_VARS['AUTH_USER'])) - continue; + $privs[] = array("id" => "lockwc", + "name" => "Lock webConfigurator", + "desc" => "Indicates whether this user will lock access to " . + "the webConfigurator for other users."); + $privs[] = array("id" => "lock-ipages", + "name" => "Lock individual pages", + "desc" => "Indicates whether this user will lock individual " . + "HTML pages after having accessed a particular page" . + "(the lock will be freed if the user leaves or " . + "saves the page form)."); + $privs[] = array("id" => "hasshell", + "name" => "Has shell access", + "desc" => "Indicates whether this user is able to login for " . + "example via SSH."); + $privs[] = array("id" => "copyfiles", + "name" => "Is allowed to copy files", + "desc" => "Indicates whether this user is allowed to copy files " . + "onto the {$g['product_name']} appliance via SCP/SFTP. " . + "If you are going to use this privilege, you must install " . + "scponly on the appliance (Hint: pkg_add -r scponly)."); + $privs[] = array("id" => "isroot", + "name" => "Is root user", + "desc" => "This user is associated with the UNIX root user " . + "(you should associate this privilege only with one " . + "single user)."); - /* Check to see if user even exists */ - $username = $HTTP_SERVER_VARS['AUTH_USER']; - if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile)))) - continue; - - /* Get crypted password */ - $matches = ""; - preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches); - $pass = $matches[1]; - $salt = $matches[2]; - - /* Encrypt entered password with salt */ - $authpass = crypt($HTTP_SERVER_VARS['AUTH_PW'], $salt); - - /* And finally validate password */ - if($authpass == $pass) - return true; - else - continue; - } - - /* Should only get here if user fails login three times */ - return false; + return $privs; } -function htpasswd_backed_basic_auth() { - global $HTTP_SERVER_VARS; +function assignUID($username = "") { + global $userindex, $config, $g; - $authfile = file("/var/run/htpasswd"); + if ($username == "") { return; } - /* sanity check to ensure that /usr/local/www/.htpasswd doesn't exist */ - unlink_if_exists("/usr/local/www/.htpasswd"); + $nextuid = $config['system']['nextuid']; + $user =& $config['system']['user'][$userindex[$username]]; - /* Prompt three times and give up */ - for($attempt = 0; $attempt <= 3; basic_auth_prompt()){ - $attempt++; - - /* Check for AUTH_USER */ - if ($HTTP_SERVER_VARS['PHP_AUTH_USER'] <> "") { - $HTTP_SERVER_VARS['AUTH_USER'] = $HTTP_SERVER_VARS['PHP_AUTH_USER']; - $HTTP_SERVER_VARS['AUTH_PW'] = $HTTP_SERVER_VARS['PHP_AUTH_PW']; - } - if (!isset($HTTP_SERVER_VARS['AUTH_USER'])) - continue; + if (empty($user['uid'])) { + $user['uid'] = $nextuid; + $nextuid++; + $config['system']['nextuid'] = $nextuid; - /* Check to see if user even exists */ - $username = $HTTP_SERVER_VARS['AUTH_USER']; - if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile)))) - continue; + write_config(); - /* Get crypted password */ - $matches = ""; - preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches); - $pass = $matches[1]; - $salt = $matches[2]; + return $user; + } +} - /* Encrypt entered password with salt */ - $authpass = crypt($HTTP_SERVER_VARS['AUTH_PW'], $salt); +function assignGID($groupname = "") { + global $groupindex, $config, $g; - /* And finally validate password */ - if($authpass == $pass) - return true; - else - continue; - } + if ($groupname == "") { return; } - /* Should only get here if user fails login three times */ + $nextgid = $config['system']['nextgid']; + $group =& $config['system']['group'][$groupindex[$groupname]]; + + if (empty($group['gid'])) { + $group['gid'] = $nextgid; + $nextgid++; + $config['system']['nextgid'] = $nextgid; + + write_config(); + + return $group; + } +} + +function hasPrivilege($user, $privid = "") { + global $userindex, $config, $g; + + if ($privid == "" || ! isset($userindex[$user])) { return 0; } + + $privs = &$config['system']['user'][$userindex[$user]]['priv']; + + if (is_array($privs)) { + foreach($privs as $priv){ + if ($priv['id'] == $privid) { + return 1; + } + } + } + + return 0; +} + +function isAllowedToCopyFiles($username) { + global $userindex, $config, $g; + + if ($username == "") { return 0; } + + return hasPrivilege($username, "copyfiles"); +} + +function hasLockAbility($username) { + global $userindex, $config, $g; + + if ($username == "") { return 0; } + + return hasPrivilege($username, "lockwc"); +} + +function hasPageLockAbility($username) { + global $userindex, $config, $g; + + if ($username == "") { return 0; } + + return hasPrivilege($username, "lock-ipages"); +} + +function hasShellAccess($username) { + global $userindex, $config, $g; + + if ($username == "") { return 0; } + + return hasPrivilege($username, "hasshell"); +} + +function isUNIXRoot($username = "") { + global $userindex, $config; + + if ($username == "") { return 0; } + + if (isSystemAdmin($username)) { + return hasPrivilege($username, "isroot"); + } + + return 0; +} + +function setUserFullName($name = "", $new_name = "") { + global $config, $g, $userindex; + + if ($name == "" || $new_name == "") { return; } + + $user = &$config['system']['user'][$userindex[$name]]; + $user['fullname'] = $new_name; +} + +function setUserName($name = "", $new_name = "") { + global $config, $g, $userindex; + + if ($name == "" || $new_name == "") { return; } + + $user = &$config['system']['user'][$userindex[$name]]; + $user['name'] = $new_name; +} + +function setUserPWD($name = "", $password = "") { + global $config, $g, $userindex; + + if ($name == "" || $password == "") { return; } + + $user = &$config['system']['user'][$userindex[$name]]; + $user['password'] = crypt($password); +} + +function setUserGroupName($name = "", $new_name = "") { + global $config, $g, $userindex; + + if ($name == "" || $new_name == "") { return; } + + $user = &$config['system']['user'][$userindex[$name]]; + $user['groupname'] = $new_name; +} + +function setUserType($name = "", $new_type = "") { + global $config, $g, $userindex; + + if ($name == "" || $new_type == "") { return; } + + $user = &$config['system']['user'][$userindex[$name]]; + $user['scope'] = $new_type; +} + +function getUNIXRoot() { + global $config, $g, $userindex; + + if (is_array($config['system']['user'])) { + foreach($config['system']['user'] as $user){ + if (isUNIXRoot($user['name'])) { + $root = &$config['system']['user'][$userindex[$user['name']]]; + return $root; + } + } + } + + return NULL; +} + +function getUNIXRootName() { + global $config, $g, $userindex; + + if (is_array($config['system']['user'])) { + foreach($config['system']['user'] as $user){ + if (isUNIXRoot($user['name'])) { + return $user['name']; + } + } + } + + return NULL; +} + +function getGroupHomePage($group = "") { + global $groupindex, $config, $g; + + if ($group == "") { return ""; } + + $page = $config['system']['group'][$groupindex[$group]]['home']; + if(empty($page)) { $page = ""; } + return $page; +} + +function isSystemAdmin($username = "") { + global $groupindex, $userindex, $config, $g; + + if ($username == "") { return 0; } + + $gname = $config['system']['group'][$groupindex[$config['system']['user'][$userindex[$username]]['groupname']]]['name']; + + if (isset($gname)) { + return ($gname === $g["admin_group"]); + } + + return 0; +} + +function getRealName($username = "") { + global $userindex, $config; + + if ($username == "") { return ""; } + + return $config['system']['user'][$userindex[$username]]['fullname']; + +} + +function basic_auth($backing) { + global $HTTP_SERVER_VARS; + + /* Check for AUTH_USER */ + if ($HTTP_SERVER_VARS['PHP_AUTH_USER'] <> "") { + $HTTP_SERVER_VARS['AUTH_USER'] = $HTTP_SERVER_VARS['PHP_AUTH_USER']; + $HTTP_SERVER_VARS['AUTH_PW'] = $HTTP_SERVER_VARS['PHP_AUTH_PW']; + } + if (!isset($HTTP_SERVER_VARS['AUTH_USER'])) { + require_once("authgui.inc"); + header("WWW-Authenticate: Basic realm=\".\""); + header("HTTP/1.0 401 Unauthorized"); + display_error_form("401", gettext("You must enter valid credentials to access this resource.")); + exit; + } else { + return $backing($HTTP_SERVER_VARS['AUTH_USER'],$HTTP_SERVER_VARS['AUTH_PW']); + } +} + +function session_auth($backing) { + global $g, $HTTP_SERVER_VARS, $userindex, $config; + + session_start(); + + /* Validate incoming login request */ + if (isset($_POST['login'])) { + if ($backing($_POST['usernamefld'], $_POST['passwordfld'])) { + $_SESSION['Logged_In'] = "True"; + $_SESSION['Username'] = $_POST['usernamefld']; + $_SESSION['last_access'] = time(); + } else { + /* give the user a more detailed error message */ + if (isset($userindex[$_POST['usernamefld']])) { + $_SESSION['Login_Error'] = "Wrong password"; + } else { + $_SESSION['Login_Error'] = "User does not exist"; + } + } + } + + /* Show login page if they aren't logged in */ + if (empty($_SESSION['Logged_In'])) { + /* Don't display login forms to AJAX */ + if (isAjax()) + return false; + require_once("authgui.inc"); + display_login_form(); + return false; + } else { + /* If session timeout isn't set, we don't mark sessions stale */ + if (!isset($config['system']['webgui']['session_timeout']) or + $config['system']['webgui']['session_timeout'] == 0 or + $config['system']['webgui']['session_timeout'] == "") + $_SESSION['last_access'] = time(); + else + /* Check for stale session */ + if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60))) + $_GET['logout'] = true; + else + /* only update if it wasn't ajax */ + if (!isAjax()) + $_SESSION['last_access'] = time(); + + /* user hit the logout button */ + if (isset($_GET['logout'])) { + if (hasLockAbility($_SESSION['Username'])) { + unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock"); + } + + /* wipe out $_SESSION */ + $_SESSION = array(); + + if (isset($_COOKIE[session_name()])) { + setcookie(session_name(), '', time()-42000, '/'); + } + + /* and destroy it */ + session_destroy(); + + $scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]); + $scriptElms = count($scriptName); + $scriptName = $scriptName[$scriptElms-1]; + + if (isAjax()) return false; + + /* redirect to page the user is on, it'll prompt them to login again */ + pfSenseHeader($scriptName); + + return false; + + /* user wants to explicitely delete the log file. + * Requires a particular privilege. + */ + } else if ($_GET['deletelock'] && hasLockAbility($_SESSION['Username'])) { + unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock"); + $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username']; + return true; + + /* this is for debugging purpose if you do not want to use Ajax + * to submit a HTML form. It basically diables the observation + * of the submit event and hence does not trigger Ajax. + */ + } else if ($_GET['disable_ajax']) { + $_SESSION['NO_AJAX'] = "True"; + $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username']; + return true; + + /* Same to re-enable Ajax. + */ + } else if ($_GET['enable_ajax']) { + unset($_SESSION['NO_AJAX']); + $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username']; + return true; + + /* user wants to explicitely create a lock. + * Requires a particular privilege. + */ + } else if ($_GET['createlock'] && hasLockAbility($_SESSION['Username'])) { + $fd = fopen("{$g['tmp_path']}/webconfigurator.lock", "w"); + fputs($fd, "{$_SERVER['REMOTE_ADDR']} (" . + getRealName($_SESSION['Username']) . ")"); + fclose($fd); + /* if the user did delete the lock manually, do not + * re-create it while the session is valide. + */ + $_SESSION['Lock_Created'] = "True"; + $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username']; + return true; + + /* proceed with the login process */ + } else { + /* if the user is allowed to create a lock, + * create it once per session. + */ + if (hasLockAbility($_SESSION['Username']) && + ! isset($_SESSION['Lock_Created'])) { + + $fd = fopen("{$g['tmp_path']}/webconfigurator.lock", "w"); + fputs($fd, "{$_SERVER['REMOTE_ADDR']} (" . + getRealName($_SESSION['Username']) . ")"); + fclose($fd); + /* if the user did delete the lock manually, do not + * re-create it while the session is valide. + */ + $_SESSION['Lock_Created'] = "True"; + + /* give regular users a chance to automatically invalidate + * a lock if its older than a particular time. + */ + } else if (! hasLockAbility($_SESSION['Username']) && + file_exists("{$g['tmp_path']}/webconfigurator.lock")) { + + $offset = 12; //hours + $mtime = filemtime("{$g['tmp_path']}/webconfigurator.lock"); + $now_minus_offset = mktime(date("H") - $offset, 0, 0, date("m"), date("d"), date("Y")); + + if (($mtime - $now_minus_offset) < $mtime) { + require_once("authgui.inc"); + display_login_form(); + return false; + } else { + /* file is older than mtime + offset which may + * indicate a stale lockfile, hence we are going + * to remove it. + */ + unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock"); + } + } + + $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username']; + return true; + } + } } -?> \ No newline at end of file +function pam_backed($username = "", $password = "") { + /* we do not support blank pwds, don't we? */ + if ($username == "" || password == "") { return false; } + + if(! extension_loaded( 'pam_auth' )) { + if(! @dl( 'pam_auth.so' )) { + return false; + } else { + /* no php file no auth, sorry */ + if (! file_exists("/etc/pam.d/php")) { + if (! file_exists("/etc/pam.d")) { mkdir("/etc/pam.d"); } + + $pam_php = <<addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']); + } + + if (!$rauth->start()) { + $retvalue['auth_val'] = 1; + $retvalue['error'] = $rauth->getError(); + if ($debug) + printf("Radius start: %s
\n", $retvalue['error']); + } + + // XXX - billm - somewhere in here we need to handle securid challenge/response + + // Send request + $result = $rauth->send(); + if (PEAR::isError($result)) { + $retvalue['auth_val'] = 1; + $retvalue['error'] = $result->getMessage(); + if ($debug) + printf("Radius send failed: %s
\n", $retvalue['error']); + } else if ($result === true) { + $retvalue['auth_val'] = 2; + if ($debug) + printf (gettext("Radius Auth succeeded") . "
\n"); + $ret = true; + } else { + $retvalue['auth_val'] = 3; + if ($debug) + printf (gettext("Radius Auth rejected") . "
\n"); + } + // close OO RADIUS_AUTHENTICATION + $rauth->close(); + + return $ret; +} + + +function index_groups() { + global $g, $config, $groupindex; + + $groupindex = array(); + + if (isset($config['system']['group'])) { + $i = 0; + foreach($config['system']['group'] as $groupent) { + $groupindex[$groupent['name']] = $i; + $i++; + } + } + return ($groupindex); +} + +function index_users() { + global $g, $config; + + if (isset($config['system']['user'])) { + $i = 0; + foreach($config['system']['user'] as $userent) { + $userindex[$userent['name']] = $i; + $i++; + } + } + return ($userindex); +} + +?> diff --git a/etc/inc/authgui.inc b/etc/inc/authgui.inc new file mode 100644 index 0000000000..2d7975a89d --- /dev/null +++ b/etc/inc/authgui.inc @@ -0,0 +1,306 @@ + + All rights reserved. + + Copyright (C) 2006 Paul Taylor . + All rights reserved. + + 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS 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 + AUTHOR 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. +*/ + +include_once("auth.inc"); +require_once("functions.inc"); +/* TODO: Needs testing... require_once("pages.inc"); */ + +/* We only support htpasswd backed HTTP Basic auth right now + * backing methods + * passwd_backed - this will use the system passwd file in /etc + * radius_backed - this will allow you to use a radius server + * htpasswd_backed - this uses the "standard" .htpasswd file + * pam_backed - this uses the system's PAM facility .htpasswd file + */ +//$auth_method="basic_auth"; +$auth_method="session_auth"; +$backing_method="htpasswd_backed"; + +/* Authenticate user - exit if failed (we should have a callback for this maybe) */ +if (!$auth_method($backing_method)) { exit; } + +/* scriptname is set in headjs.php if the user did try to access a page other + * than index.php without beeing logged in. + */ +if (isset($_POST['scriptname']) && isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { + pfSenseHeader("{$_POST['scriptname']}"); + exit; +} + +/* TODO: Needs testing +if ($_SESSION) { + if (isset($_SESSION['Pages'])) { + $pfPages = getPageObjectFromSession(); + } else { + $pfPages = getPageObject($HTTP_SERVER_VARS['AUTH_USER']); + $pages =& $pfPages->getPages(); + $pages_index =& $pfPages->getPagesIndex(); + $allowed_pages_index =& $pfPages->getAllowedPagesIndex(); + + $_SESSION['Pages'] = serialize($pages); + $_SESSION['Pages_Index'] = serialize($pages_index); + $_SESSION['Allowed_Pages_Index'] = serialize($allowed_pages_index); + } +} else { + $pfPages = getPageObject($HTTP_SERVER_VARS['AUTH_USER']); +} +*/ + +// Once here, the user has authenticated with the web server. +// Now, we give them access only to the appropriate pages for their group. +if (!(isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER']))) { + $allowed[] = ''; + if (isset($config['system']['group'][$groupindex[$config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname']]]['pages'][0])) { + $allowed = &$config['system']['group'][$groupindex[$config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname']]]['pages']; + } + + $group = $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname']; + /* get the group homepage, to be able to forward + * the user to this particular PHP page. + */ + getGroupHomePage($group) == "" ? $home = "/index.php" : $home = "/" . getGroupHomePage($group); + + /* okay but if the user realy tries to explicitely access a particular + * page, set $home to that page instead. + */ + if (isset($_POST['scriptname']) && $_POST['scriptname'] <> "/" && $_POST['scriptname'] <> "/index.php") + $home = basename($_POST['scriptname']); + + // If the user is attempting to hit the default page, set it to specifically look for /index.php. + // Without this, any user would have access to the index page. + //if ($_SERVER['SCRIPT_NAME'] == '/') + // $_SERVER['SCRIPT_NAME'] = $home; + + // Strip the leading / from the currently requested PHP page + if (!in_array(basename($_SERVER['SCRIPT_NAME']),$allowed) && !in_array("ANY", $allowed)) { + // The currently logged in user is not allowed to access the page + // they are attempting to go to. Redirect them to an allowed page. + + if(stristr($_SERVER['SCRIPT_NAME'],"sajax")) { + echo "||Access to AJAX has been disallowed for this user."; + exit; + } + + if ($home <> "" && (in_array($home, $allowed) || in_array("ANY", $allowed))) { + pfSenseHeader("{$home}"); + exit; + } else { + header("HTTP/1.0 401 Unauthorized"); + header("Status: 401 Unauthorized"); + + echo display_error_form("401", "401 Unauthorized. Authorization required."); + exit; + } + } + + if (isset($_SESSION['Logged_In'])) { + /* + * only forward if the user has just logged in + * TODO: session auth based - may be an issue. + */ + if ($_SERVER['SCRIPT_NAME'] <> $home && empty($_SESSION['First_Visit'])) { + $_SESSION['First_Visit'] = "False"; + pfSenseHeader("{$home}"); + exit; + } + } +} + +function display_error_form($http_code, $desc) { + global $config, $g; + $g['theme'] = $config['theme']; + + $htmlstr = << + + + + An error occurred: {$http_code} + + + + + + + + + +
+

 

+

{$desc}

+
+ + + +EOD; + + return $htmlstr; +} + +function display_login_form() { + require_once("globals.inc"); + global $config, $g; + $g['theme'] = $config['theme']; + + unset($input_errors); + + if(isAjax()) { + if (isset($_POST['login'])) { + if($_SESSION['Logged_In'] <> "True") { + isset($_SESSION['Login_Error']) ? $login_error = $_SESSION['Login_Error'] : $login_error = "unknown reason"; + echo "showajaxmessage('Invalid login ({$login_error}).');"; + } + if (file_exists("{$g['tmp_path']}/webconfigurator.lock")) { + // TODO: add the IP from the user who did lock the device + $whom = file_get_contents("{$g['tmp_path']}/webconfigurator.lock"); + echo "showajaxmessage('This device is currently beeing maintained by: {$whom}.');"; + } + } + exit; + } + +?> + + + + + + <?=gettext("Login"); ?> + + + + + + + +
+

 

+
+
+

+ + :   + + +

+

+ + :   + + +

+ + + + + +

" tabindex="3" />
+
+
+ + + diff --git a/etc/inc/config.inc b/etc/inc/config.inc index f4af73c329..abedcf36e2 100644 --- a/etc/inc/config.inc +++ b/etc/inc/config.inc @@ -955,6 +955,57 @@ function convert_config() { $config['version'] = "2.9"; } + /* Convert 2.9 -> 3.0 */ + if ($config['version'] <= 2.9) { + $config['system']['webgui']['auth_method'] = "session"; + $config['system']['webgui']['backing_method'] = "htpasswd"; + + if (isset ($config['system']['username'])) { + $config['system']['group'] = array(); + $config['system']['group'][0]['name'] = "admins"; + $config['system']['group'][0]['description'] = "System Administrators"; + $config['system']['group'][0]['scope'] = "system"; + $config['system']['group'][0]['pages'] = "ANY"; + $config['system']['group'][0]['home'] = "index.php"; + $config['system']['group'][0]['gid'] = "110"; + + $config['system']['user'] = array(); + $config['system']['user'][0]['name'] = "{$config['system']['username']}"; + $config['system']['user'][0]['fullname'] = "System Administrator"; + $config['system']['user'][0]['scope'] = "system"; + $config['system']['user'][0]['groupname'] = "admins"; + $config['system']['user'][0]['password'] = "{$config['system']['password']}"; + $config['system']['user'][0]['uid'] = "0"; + + $config['system']['user'][0]['priv'] = array(); + $config['system']['user'][0]['priv'][0]['id'] = "lockwc"; + $config['system']['user'][0]['priv'][0]['name'] = "Lock webConfigurator"; + $config['system']['user'][0]['priv'][0]['descr'] = "Indicates whether this user will lock access to the webConfigurator for other users."; + $config['system']['user'][0]['priv'][1]['id'] = "lock-ipages"; + $config['system']['user'][0]['priv'][1]['name'] = "Lock individual pages"; + $config['system']['user'][0]['priv'][1]['decr'] = "Indicates whether this user will lock individual HTML pages after having accessed a particular page (the lock will be freed if the user leaves or saves the page form)."; + $config['system']['user'][0]['priv'][2]['id'] = "hasshell"; + $config['system']['user'][0]['priv'][2]['name'] = "Has shell access"; + $config['system']['user'][0]['priv'][2]['descr'] = "Indicates whether this user is able to login for example via SSH."; + $config['system']['user'][0]['priv'][3]['id'] = "copyfiles"; + $config['system']['user'][0]['priv'][3]['name'] = "Is allowed to copy files"; + $config['system']['user'][0]['priv'][3]['descr'] = "Indicates whether this user is allowed to copy files onto the {$g['product_name']} appliance via SCP/SFTP. If you are going to use this privilege, you must install scponly on the appliance (Hint: pkg_add -r scponly)."; + $config['system']['user'][0]['priv'][4]['id'] = "isroot"; + $config['system']['user'][0]['priv'][4]['name'] = "Is root user"; + $config['system']['user'][0]['priv'][4]['descr'] = "This user is associated with the UNIX root user (you should associate this privilege only with one single user)."; + + $config['system']['nextuid'] = "111"; + $config['system']['nextgid'] = "111"; + + /* wipe previous auth configuration */ + unset ($config['system']['username']); + unset ($config['system']['password']); + } + + $config['version'] = "3.0"; + } + + if ($prev_version != $config['version']) write_config("Upgraded config version level from {$prev_version} to {$config['version']}"); } @@ -1758,4 +1809,4 @@ function set_device_perms() { if($g['booting']) echo "."; $config = parse_config(); -?> \ No newline at end of file +?> diff --git a/etc/inc/functions.inc b/etc/inc/functions.inc index 77a08cb706..7fdbcbfd69 100644 --- a/etc/inc/functions.inc +++ b/etc/inc/functions.inc @@ -46,6 +46,7 @@ if(!function_exists("pfSenseHeader")) { /* END compatibility goo with HEAD */ /* include all configuration functions */ +require_once("auth.inc"); require_once("captiveportal.inc"); require_once("filter.inc"); require_once("interfaces.inc"); @@ -57,4 +58,4 @@ require_once("util.inc"); require_once("vpn.inc"); require_once("vslb.inc"); -?> \ No newline at end of file +?> diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc index 69bf9732c1..00063ebe7b 100644 --- a/etc/inc/globals.inc +++ b/etc/inc/globals.inc @@ -47,13 +47,14 @@ $g = array( "cf_conf_path" => "/cf/conf", "www_path" => "/usr/local/www", "xml_rootobj" => "pfsense", + "admin_group" => "admins", "pppoe_interface" => "ng0", "n_pptp_units" => 16, /* this value can be overriden in pptp->n_pptp_units */ "pptp_subnet" => 28, /* this value can be overriden in pptp->pptp_subnet */ "n_pppoe_units" => 16, /* this value can be overriden in pppoe->n_pppoe_units */ "pppoe_subnet" => 28, /* this value can be overriden in pppoe->pppoe_subnet */ "debug" => false, - "latest_config" => "2.9", + "latest_config" => "3.0", "nopkg_platforms" => array("cdrom"), "nopccard_platforms" => array("wrap", "net48xx"), "xmlrpcbaseurl" => "www.pfsense.com", @@ -73,4 +74,4 @@ $iptos = array("lowdelay", "throughput", "reliability"); /* TCP flags */ $tcpflags = array("syn", "ack", "fin", "rst", "psh", "urg"); -?> \ No newline at end of file +?> diff --git a/etc/inc/pfsense-utils.inc b/etc/inc/pfsense-utils.inc index 2d7d27ba8b..ca0a7aaeac 100644 --- a/etc/inc/pfsense-utils.inc +++ b/etc/inc/pfsense-utils.inc @@ -2293,26 +2293,38 @@ function reload_interfaces() { * none ******/ function sync_webgui_passwords() { - global $config, $g; + global $config, $g, $groupindex, $userindex; + conf_mount_rw(); $fd = fopen("{$g['varrun_path']}/htpasswd", "w"); + if (!$fd) { - printf("Error: cannot open htpasswd in system_password_configure().\n"); + log_error("Error: cannot open htpasswd in sync_webgui_passwords().\n"); return 1; } - /* set admin account */ - $username = $config['system']['username']; - /* set defined user account */ - if($username <> "admin") { - $username = $config['system']['username']; - fwrite($fd, $username . ":" . $config['system']['password'] . "\n"); - } else { - fwrite($fd, $username . ":" . $config['system']['password'] . "\n"); + /* loop through custom users and add "virtual" entries */ + if ($config['system']['user']) { + foreach ($config['system']['user'] as $user) + fwrite($fd, "{$user['name']}:{$user['password']}\n"); } + fclose($fd); chmod("{$g['varrun_path']}/htpasswd", 0600); - $crypted_pw = $config['system']['password']; + + if ($config['system']['user']) { + $root =& getUNIXRoot(); + $crypted_pw = $root['password']; + } + + if (empty ($crypted_pw)) { + log_error("Error: cannot determine root pwd in sync_webgui_passwords().\nRoot user struct follows:\n"); + empty($root) ? log_error("Unable to determine root user!\n") : print_r($root); + log_error("Testing whether your system has the necessary users... "); + empty($config['system']['user']) ? log_error("users are missing.\n") : log_error("users found.\n"); + return 1; + } + mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd"); mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd"); /* sync root */ @@ -2320,16 +2332,79 @@ function sync_webgui_passwords() { fwrite($fd, $crypted_pw); pclose($fd); mwexec("/usr/sbin/pw usermod -n root -s /bin/sh"); - /* sync admin */ - $fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w"); - fwrite($fd, $crypted_pw); - pclose($fd); - mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial"); + + /* and again for shell users */ + /* only users with hasShellAccess() == true should be synced */ + if($config['system']['user']) { + $home_base = $g['platform'] == "pfSense" ? "/home" : "/var/home"; + + if(! is_dir($home_base)) + mkdir($home_base, 0755); + + foreach($config['system']['user'] as $user) { + if (hasShellAccess($user['name']) || isAllowedToCopyFiles($user['name'])) { + $home = hasShellAccess($user['name']) ? "{$home_base}/{$user['name']}" : "{$home_base}/scponly"; + $shell = isAllowedToCopyFiles($user['name']) ? "/usr/local/bin/scponly" : "/etc/rc.initial"; + if (isAllowedToCopyFiles($user['name'])) + $user['groupname'] = "scponly"; + + $fd = popen("/usr/sbin/pw groupshow -n {$user['groupname']} 2>&1", "r"); + $pwread = fgets($fd, 4096); + pclose($fd); + + if (strpos($pwread, "unknown group") !== false) { + $groupname = $user['groupname']; + $group = $config['system']['group'][$groupindex[$groupname]]; + + if (isset($group) && is_array($group)) { + $fd = popen("/usr/sbin/pw groupadd -g {$group['gid']} -n {$group['name']}", "r"); + pclose($fd); + } elseif (isAllowedToCopyFiles($user['name'])) { + $fd = popen("/usr/sbin/pw groupadd -g 100 -n scponly", "r"); + pclose($fd); + } + } + + $fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r"); + $pwread = fgets($fd, 4096); + pclose($fd); + + isSystemAdmin($user['name']) ? $group = "wheel" : $group = "staff"; + + if (strpos($pwread, "no such user") === false) { + $fd = popen("/usr/sbin/pw usermod -n {$user['name']} -g ${user['groupname']} -G {$group} -H 0", "w"); + fwrite($fd, $user['password']); + pclose($fd); + } else { + $fd = popen("/usr/sbin/pw useradd -u {$user['uid']} -n {$user['name']} -c '{$user['fullname']}' -g ${user['groupname']} -G {$group} -H 0", "w"); + fwrite($fd, $user['password']); + pclose($fd); + } + + /* common user related operations */ + mwexec("/usr/sbin/pw usermod -n {$user['name']} -s {$shell}"); + + if(! is_dir($home)) mkdir($home, 0755); + mwexec("/usr/sbin/pw usermod -n {$user['name']} -d {$home} -m"); + + if (isAllowedToCopyFiles($user['name'])) { + mwexec("/usr/sbin/pw usermod -n {$user['name']} -g scponly"); + } + + if (file_exists("{$home_base}/scponly")) + mwexec("chmod 0660 {$home_base}/scponly"); + + if(isset($config['system']['ssh']['sshdkeyonly']) && ! isAllowedToCopyFiles($user['name'])) { + create_authorized_keys($user['name'], $home); + } + } + } + } + mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd"); mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd"); conf_mount_ro(); } - /****f* pfsense-utils/cleanup_opt_interfaces_after_removal * NAME * cleanup_opt_interfaces_after_removal - renumber interfaces after removing @@ -3291,4 +3366,17 @@ function interface_has_gateway($friendly) { } } +/****f* pfsense-utils/isAjax + * NAME + * isAjax - reports if the request is driven from prototype + * INPUTS + * none + * RESULT + * true/false + ******/ +function isAjax() { + return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'; +} + + ?> diff --git a/usr/local/www/fbegin.inc b/usr/local/www/fbegin.inc index dc8f5bd424..d4d467471f 100755 --- a/usr/local/www/fbegin.inc +++ b/usr/local/www/fbegin.inc @@ -122,11 +122,13 @@ require_once("notices.inc");
  • Advanced
  • Firmware
  • General Setup
  • +
  • Logout
  • Packages
  • Setup wizard
  • Static routes
  • +
  • User Manager
  • @@ -280,4 +282,4 @@ require_once("notices.inc"); echo ""; } -?> \ No newline at end of file +?> diff --git a/usr/local/www/guiconfig.inc b/usr/local/www/guiconfig.inc index a6c1c00bdb..b140bf45dd 100755 --- a/usr/local/www/guiconfig.inc +++ b/usr/local/www/guiconfig.inc @@ -41,7 +41,7 @@ if (!$omit_nocacheheaders) { /* Include authentication routines */ /* THIS MUST BE ABOVE ALL OTHER CODE */ -require_once("auth.inc"); +require_once("authgui.inc"); /* parse the configuration and include all configuration functions */ require_once("config.inc"); @@ -305,6 +305,26 @@ function captiveportal_users_sort() { usort($config['captiveportal']['user'], "cpusercmp"); } +function admin_groups_sort() { + global $g, $config; + + function cpusercmp($a, $b) { + return strcasecmp($a['name'], $b['name']); + } + + usort($config['system']['group'], "cpusercmp"); +} + +function admin_users_sort() { + global $g, $config; + + function cpusercmp($a, $b) { + return strcasecmp($a['name'], $b['name']); + } + + usort($config['system']['user'], "cpusercmp"); +} + /* sort by interface only, retain the original order of rules that apply to the same interface */ function filter_rules_sort() { diff --git a/usr/local/www/headjs.php b/usr/local/www/headjs.php new file mode 100644 index 0000000000..e2b4e20833 --- /dev/null +++ b/usr/local/www/headjs.php @@ -0,0 +1,156 @@ +<\/div>\"; + new Insertion.Before('submit', to_insert); + } + } + + function submit_form(e){ + // debugging helper + //alert(Form.serialize($('iform'))); + + if($('inputerrors')) + $('inputerrors').innerHTML = ''; + + /* dsh: Introduced because pkg_edit tries to set some hidden fields + * if executing submit's onclick event. Tho click gets deleted + * by Ajax. Hence using onkeydown instead. + */ + if($('submit') && $('submit').onkeydown) + $('submit').onkeydown(); + if($('submit')) + $('submit').style.visibility = 'hidden'; + if($('cancelbutton')) + $('cancelbutton').style.visibility = 'hidden'; + $('loading').style.visibility = 'visible'; + // submit the form using Ajax + "; + + + isset($HTTP_SERVER_VARS['AUTH_USER']) ? $scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]) : $scriptName = split("/", "/index.php"); + isset($HTTP_SERVER_VARS['AUTH_USER']) ? $loggedin = "var isLoggedIn = true;" : $loggedin = "var isLoggedIn = false;"; + $scriptElms = count($scriptName); + $scriptName = $scriptName[$scriptElms-1]; + $realScriptName = $_SERVER["SCRIPT_NAME"]; + + $headjs .= " + {$loggedin} + + if (! isLoggedIn) { + var newInput = document.createElement('input'); + newInput.setAttribute('id', 'scriptname'); + newInput.setAttribute('name', 'scriptname'); + newInput.setAttribute('value', '$realScriptName'); + newInput.setAttribute('type', 'hidden'); + + $('iform').appendChild(newInput); + } + + new Ajax.Request('{$scriptName}', { + method : 'post', + parameters : Form.serialize($('iform')), + onSuccess : formSubmitted, + onFailure : formFailure + }); + } + + function formSubmitted(resp) { + var responseText = resp.responseText; + + // debugging helper + //alert(responseText); + + if(responseText.indexOf('html') > 0) { + /* somehow we have been fed an html page! */ + //alert('Somehow we have been fed an html page! Forwarding to /.'); + document.location.href = '/'; + } + + eval(responseText); + } + + /* this function will be called if an HTTP error will be triggered */ + function formFailure(resp) { + alert('An error occured while saving the data ' + resp.responseText); + } + + function showajaxmessage(message) { + var message_html; + + if (message == '') { + NiftyCheck(); + Rounded(\"div#redbox\",\"all\",\"#FFF\",\"#990000\",\"smooth\"); + Rounded(\"td#blackbox\",\"all\",\"#FFF\",\"#000000\",\"smooth\"); + + if($('submit')) + $('submit').style.visibility = 'visible'; + if($('cancelbutton')) + $('cancelbutton').style.visibility = 'visible'; + if($('loading')) + $('loading').style.visibility = 'hidden'; + + return; + } + + message_html = '
    '; + message_html += '
    '; + message_html += ' +
    '; + message_html += '   '; + message_html += ''; + message_html += '<\/td>'; + message_html += '' + message + '<\/b><\/font><\/td>'; + + if(message.indexOf('apply') > 0) { + message_html += ''; + message_html += ''; + message_html += '<\/td>'; + } + + message_html += '<\/tr><\/table><\/div><\/td><\/table>
    '; + $('inputerrors').innerHTML = message_html; + + NiftyCheck(); + Rounded(\"div#redbox\",\"all\",\"#FFF\",\"#990000\",\"smooth\"); + Rounded(\"td#blackbox\",\"all\",\"#FFF\",\"#000000\",\"smooth\"); + + if($('submit')) + $('submit').style.visibility = 'visible'; + if($('cancelbutton')) + $('cancelbutton').style.visibility = 'visible'; + if($('loading')) + $('loading').style.visibility = 'hidden'; + if($('inputerrors')) + window.scrollTo(0, 0); + if($('inputerrors')) + new Effect.Shake($('inputerrors')); + } + "; + + return $headjs; +} + +?> diff --git a/usr/local/www/system_groupmanager.php b/usr/local/www/system_groupmanager.php new file mode 100644 index 0000000000..ca63f9d4fc --- /dev/null +++ b/usr/local/www/system_groupmanager.php @@ -0,0 +1,798 @@ +. + All rights reserved. + + Copyright (C) 2005 Paul Taylor . + All rights reserved. + + Copyright (C) 2003-2005 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS 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 + AUTHOR 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("guiconfig.inc"); + +$_SESSION['NO_AJAX'] = true; + +$pgtitle = array(gettext("System"), gettext("Group manager")); +$treeItemID = 0; + +function walkArea($title, + $t, + $area, + $id, + &$counter, + &$script_tag, + $tmpfname, + &$group) { + global $treeItemID; + + foreach($area as $a => $aa) { + if (is_array($aa) && count($aa) > 0) { + $title .= "_{$a}"; + echo "
  • $a
      "; + $treeItemID++; + walkArea($title, + $a, + $aa, + $id, + $counter, + $script_tag, + $tmpfname, + $group); + echo "
    \n"; + } else { + $tmp_string = "{$t}"; + $tmp_string .= ": "; + $tmp_string .= $a; + $trimmed_title = trim($title); + $trimmed_a = trim($a); + $this_id = "{$trimmed_title}_{$trimmed_a}_{$counter}"; + $this_id = str_replace(" ", "", $this_id); + $this_id = str_replace("/", "", $this_id); + $stripped_session = str_replace("/tmp/", "", $tmpfname); + $allowed = false; + if (is_array($group['pages'][0]['page'])) { + foreach($group['pages'][0]['page'] as $page) { + if (stristr($aa, $page)) + $allowed = true; + // echo "$page || $aa"; + } + } + $allowed ? $checked = " checked=\"checked\"" : $checked = ""; + echo "
  •  "; + $idForOnClick = $treeItemID; + $treeItemID++; + echo " "; + $treeItemID++; + echo "{$a}
  • \n"; + $idForScript = $treeItemID; + $treeItemID++; + +//echo "$script_tag
    "; + $script_tag .= "var item = document.getElementById('treeitem_{$idForScript}');\n"; + if ($allowed) { + $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_play.gif')\";\n"; + } else { + $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_x.gif')\";\n"; + } + $counter++; + } // end if + } // end foreach +} + +function init_ajax_helper_file($tmpfname) +{ + global $config, $id, $global; + $a_group = &$config['system']['group']; + $id = $_GET['id']; + if (isset($id) && $a_group[$id]) + $group = $a_group[$id]; + else + $group = array(); + $fd = fopen("/tmp/{$tmpfname}", "w"); + if ($group['pages'][0]['page']) + foreach($group['pages'][0]['page'] as $page) { + fwrite($fd, $page . "\n"); + } + fclose($fd); + return; +} + +if ($_GET['toggle'] <> "") { + /* AJAX is calling, lets take care of it */ + if (!file_exists("/tmp/" . $_GET['session'])) { + init_ajax_helper_file($_GET['session']); + } + $fc = file_get_contents("/tmp/" . $_GET['session']); + $file_split = split("\n", $fc); + $found = -1; + for($x = 0; $x < count($file_split); $x++) { + if ($file_split[$x] == $_GET['toggle']) { + $found = $x; + } + } + if ($found == -1) { + $file_split[] = $_GET['toggle']; + $image = "/tree/page-file_play.gif"; + } else { + unset($file_split[$found]); + $image = "/tree/page-file_x.gif"; + } + $fd = fopen("/tmp/{$_GET['session']}", "w"); + if ($file_split) + foreach($file_split as $fs) { + if ($fs) + fwrite($fd, $fs . "\n"); + } + fclose($fd); + echo $_GET['item'] . "_a||" . "{$image}"; + exit; +} + +function convert_array_to_pgtitle($orig) +{ + $newstring = ""; + foreach($orig as $o) { + if ($newstring <> "") + $newstring .= ": "; + $newstring .= $o; + } + return $newstring; +} +// Returns an array of pages with their descriptions +function getAdminPageList() +{ + global $g; + + $tmp = Array(); + + if ($dir = opendir($g['www_path'])) { + while ($file = readdir($dir)) { + // Make sure the file exists and is not a directory + if ($file == "." or $file == ".." or $file[0] == '.') + continue; + // Is this a .inc.php file? pfSense! + if (fnmatch('guiconfig.inc', $file)) + continue; + if (fnmatch('*.inc', $file)) + continue; + if (fnmatch('*.inc.php', $file)) + continue; + if (fnmatch('*.php', $file)) { + // Read the description out of the file + $contents = file_get_contents($file); + $contents_split = split("\n", $contents); + $mlinestr = ""; + foreach($contents_split as $contents) { + $pgtitle = ""; + // Looking for a line like: + // $pgtitle = array(gettext("System"), gettext("Group manager")); // - DO NOT REMOVE. + if ($mlinestr == "" && stristr($contents, "\$pgtitle") == false) + continue; + if ($mlinestr == "" && stristr($contents, "=") == false) + continue; + if (stristr($contents, "<")) + continue; + if (stristr($contents, ">")) + continue; + /* at this point its evalable */ + $contents = trim ($contents); + $lastchar = substr($contents, strlen($contents) - 1, strlen($contents)); + $firstchar = substr($contents, 0, 1); + + /* check whether pgtitle is on one or multible lines */ + if ($firstchar <> "/" && $firstchar <> "#" && $lastchar <> ";") { + /* remember the partitial pgtitle string for the next loop iteration */ + $mlinestr .= $contents; + continue; + } else if ($mlinestr <> "" && $lastchar == ";") { + /* this is the final pgtitle part including the semicolon */ + $mlinestr .= $contents; + } else if ($mlinestr == "" && $lastchar == ";") { + /* this is a single line pgtitle, hence just + * copy its contents into mlinestr + */ + $mlinestr = $contents; + } else if ($firstchar == "/" || $firstchar == "#") { + /* same applies for comment lines */ + $mlinestr = $contents; + } + + eval($mlinestr); + + /* after eval, if not an array, continue */ + if (!is_array($pgtitle)) { + /* reset mlinestr for the next loop iteration */ + $mlinestr = ""; + continue; + } + + $tmp[$file] = convert_array_to_pgtitle($pgtitle); + + /* break out of the for loop, on to next file */ + break; + } + } + } + + /* loop through and read in wizard information */ + if ($dir = opendir("{$g['www_path']}/wizards")) { + while ($file = readdir($dir)) { + // Make sure the file exists and is not directory + if ($file == "." or $file == ".." or $file[0] == '.') + continue; + // Is this a .xml file? pfSense! + if (fnmatch('*.xml', $file)) { + /* parse package and retrieve the package title */ + $pkg = parse_xml_config_pkg("{$g['www_path']}/wizards/{$file}", "pfsensewizard"); + $title = $pkg['title']; + if ($title) + $tmp[$file] = trim($title); + } + } + } + + /* loop through and read in package information */ + if ($dir = opendir("{$g['pkg_path']}")) { + while ($file = readdir($dir)) { + // Make sure the file exists and is not directory + if ($file == "." or $file == ".." or $file[0] == '.') + continue; + // Is this a .xml file? pfSense! + if (fnmatch('*.xml', $file)) { + /* parse package and retrieve the package title */ + $pkg = parse_xml_config_pkg("{$g['pkg_path']}/{$file}", "packagegui"); + $title = $pkg['title']; + if ($title) + $tmp[$file] = trim($title); + } + } + closedir($dir); + } + + // Sets Interfaces:Optional page that didn't read in properly with the above method, + // and pages that don't have descriptions. + $tmp['interfaces_opt.php'] = ("Interfaces: Optional"); + $tmp['graph.php'] = ("Status: Traffic Graph"); + $tmp['graph_cpu.php'] = ("Diagnostics: CPU Utilization"); + $tmp['exec_raw.php'] = ("Hidden: Exec Raw"); + $tmp['uploadconfig.php'] = ("Hidden: Upload Configuration"); + $tmp['index.php'] = ("Status: System"); + $tmp['system_usermanager.php'] = ("System: User Password"); + $tmp['diag_logs_settings.php'] = ("Diagnostics: Logs: Settings"); + $tmp['diag_logs_vpn.php'] = ("Diagnostics: Logs: PPTP VPN"); + $tmp['diag_logs_filter.php'] = ("Diagnostics: Logs: Firewall"); + $tmp['diag_logs_portal.php'] = ("Diagnostics: Logs: Captive Portal"); + $tmp['diag_logs_dhcp.php'] = ("Diagnostics: Logs: DHCP"); + $tmp['diag_logs.php'] = ("Diagnostics: Logs: System"); + + $tmp['ifstats.php'] = ("Hidden: *XMLRPC Interface Stats"); + $tmp['license.php'] = ("System: License"); + $tmp['progress.php'] = ("Hidden: *No longer included"); + $tmp['diag_logs_filter_dynamic.php'] = ("Hidden: *No longer included"); + $tmp['preload.php'] = ("Hidden: *XMLRPC Preloader"); + $tmp['xmlrpc.php'] = ("Hidden: *XMLRPC Library"); + $tmp['pkg.php'] = ("System: *Renderer for XML based package GUIs (Part I)"); + $tmp['pkg_edit.php'] = ("System: *Renderer for XML based package GUIs (Part II)"); + + $tmp['functions.inc.php'] = ("Hidden: Ajax Helper 1"); + $tmp['javascript.inc.php'] = ("Hidden: Ajax Helper 2 "); + $tmp['sajax.class.php'] = ("Hidden: Ajax Helper 3"); + + asort($tmp); + + return $tmp; + } +} +// Get a list of all admin pages & Descriptions +$pages = getAdminPageList(); + +if (!is_array($config['system']['group'])) { + $config['system']['group'] = array(); +} +admin_groups_sort(); +$a_group = &$config['system']['group']; + +$id = $_GET['id']; +if (isset($_POST['id'])) + $id = $_POST['id']; + +if ($_GET['act'] == "del") { + if ($a_group[$_GET['id']]) { + $ok_to_delete = true; + if (isset($config['system']['user'])) { + foreach ($config['system']['user'] as $userent) { + if ($userent['groupname'] == $a_group[$_GET['id']]['name']) { + $ok_to_delete = false; + $input_errors[] = gettext("users still exist who are members of this group!"); + break; + } + } + } + if ($ok_to_delete) { + unset($a_group[$_GET['id']]); + write_config(); + pfSenseHeader("system_groupmanager.php"); + exit; + } + } +} + +if ($_POST) { + unset($input_errors); + $pconfig = $_POST; + /* input validation */ + $reqdfields = explode(" ", "groupname"); + $reqdfieldsn = explode(",", "Group Name"); + + do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + if (preg_match("/[^a-zA-Z0-9\.\-_ ]/", $_POST['groupname'])) + $input_errors[] = gettext("The group name contains invalid characters."); + + if (!$input_errors && !(isset($id) && $a_group[$id])) { + /* make sure there are no dupes */ + foreach ($a_group as $group) { + if ($group['name'] == $_POST['groupname']) { + $input_errors[] = gettext("Another entry with the same group name already exists."); + break; + } + } + } + + if (!$input_errors) { + if (isset($id) && $a_group[$id]) + $group = $a_group[$id]; + + $group['name'] = $_POST['groupname']; + isset($_POST['homepage']) ? $group['home'] = $_POST['homepage'] : $group['home'] = "index.php"; + isset($_POST['gtype']) ? $group['scope'] = $_POST['gtype'] : $group['scope'] = "system"; + $group['description'] = $_POST['description']; + unset($group['pages'][0]['page']); + + $file_split = split("\n", file_get_contents("/tmp/" . $_POST['session'])); + for($x = 0; $x < count($file_split); $x++) { + if ($file_split[$x]) + $group['pages'][0]['page'][] = $file_split[$x]; + } + + if (isset($id) && $a_group[$id]) + $a_group[$id] = $group; + else + $a_group[] = $group; + + write_config(); + + unlink_if_exists("/tmp/" . $_GET['session']); + + pfSenseHeader("system_groupmanager.php"); + exit; + } +} + +include("head.inc"); + +$checkallstr = <<= 0) { + document.iform.elements[i].checked = true; + document.iform.elements[i].click(); + } + } + } + +EOD; + +// XXX: billm TODO +//$pfSenseHead->addScript("\n"); +//$pfSenseHead->addLink(""); +//echo $pfSenseHead->getHTML(); + +?> +"> + + + + + + + + + + +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + +
    + + + +
    + +
    + +
    + +
    + + $title) { + $identifier = str_replace('.php', '', $fname); + $identifier = $fname; + $title_split = split(": ", $title); + $tmp = "\$menu_array"; + foreach($title_split as $ts) + $tmp .= "['{$ts}']"; + $tmp .= " = \"{$identifier}\";"; + echo "\n"; + eval($tmp); + } + + echo "" . gettext("webConfigurator") . "
      \n"; + $counter = 0; + /* XXX: we may wanna pull from or add to each row a +e item (+edit) */ + $script_tag = ""; + + if (is_array($menu_array) && count($menu_array) > 0) { + foreach($menu_array as $title => $m) { + echo "
    • $title
        "; + $treeItemID++; + if (is_array($m) && count($m) > 0) { + foreach($m as $t => $area) { + if (is_array($area) && count($area) > 0) { + echo "
      • $t
          "; + $treeItemID++; + walkArea("{$title}_{$t}", + $t, + $area, + $id, + $counter, + $script_tag, + $tmpfname, + $group); + echo "
        \n"; + } else { + $trimmed_title = trim($title); + $trimmed_t = trim($t); + $this_id = "{$trimmed_title}_{$trimmed_t}_{$counter}"; + $this_id = str_replace(" ", "", $this_id); + $this_id = str_replace("/", "", $this_id); + $allowed = false; + if (is_array($group['pages'][0]['page'])) { + foreach($group['pages'][0]['page'] as $page) { + if (stristr($area, $page)) + $allowed = true; + // echo "$page || $area || $t"; + } + } + $allowed ? $checked = " checked=\"checked\"" : $checked = ""; + $stripped_session = str_replace("/tmp/", "", $tmpfname); + echo"
      •  "; + $idForOnClick = $treeItemID; + $treeItemID++; + echo "  "; + echo " {$t}
      • \n"; + $treeItemID++; + $script_tag .= "var item = document.getElementById('treeitem_{$idForScript}');\n"; + if ($allowed) { + $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_play.gif')\";\n"; + } else { + $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_x.gif')\";\n"; + } + $counter++; + } + } + } + echo "
      \n"; + } + } + echo "
    \n"; + +?> +
    + + + + + + + + + + + + + +
    +
    + +
    + " /> + + + +

    + + + : + + + +

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + +
    + + Group + + Group + +   + + +
    +
    + + + + + + + + + + + + " width="17" height="17" border="0" alt="" /> + + ')"> + " width="17" height="17" border="0" alt="" /> + +
    + + " width="17" height="17" border="0" alt="" /> + +
    +

    + +

    +

    + +

    +
    +
    + + + + + + diff --git a/usr/local/www/system_usermanager.php b/usr/local/www/system_usermanager.php new file mode 100644 index 0000000000..19a69ec649 --- /dev/null +++ b/usr/local/www/system_usermanager.php @@ -0,0 +1,478 @@ +. + All rights reserved. + + Copyright (C) 2003-2005 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS 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 + AUTHOR 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("guiconfig.inc"); +// The page title for non-admins +$pgtitle = array(gettext("System"), gettext("User password")); + +if (isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { + // Page title for main admin + $pgtitle = array(gettext("System"), gettext("User manager")); + + $id = $_GET['id']; + if (isset($_POST['id'])) + $id = $_POST['id']; + + if (!is_array($config['system']['user'])) { + $config['system']['user'] = array(); + } + + admin_users_sort(); + $a_user = &$config['system']['user']; + $t_privs = $a_user[$id]['priv']; + + if ($_GET['act'] == "del" && $_GET['what'] == "user") { + if ($a_user[$_GET['id']]) { + $userdeleted = $a_user[$_GET['id']]['name']; + unset($a_user[$_GET['id']]); + write_config(); + $retval = system_password_configure(); + $savemsg = get_std_save_message($retval); + $savemsg = gettext("User") . " " . $userdeleted . " " . gettext("successfully deleted") . "
    "; + } + } else if ($_GET['act'] == "del" && $_GET['what'] == "priv") { + if ($t_privs[$_GET['privid']]) { + $privdeleted = $t_privs[$_GET['privid']]['id']; + unset($t_privs[$_GET['privid']]); + write_config(); + $_GET['act'] = "edit"; + $retval = 0; + $savemsg = get_std_save_message($retval); + $savemsg = gettext("Privilege") . " " . $privdeleted . " " . gettext("of user") . " " . $a_user[$_GET['id']]['name'] . " " . gettext("successfully deleted") . "
    "; + } + } + + if ($_POST) { + unset($input_errors); + $pconfig = $_POST; + + /* input validation */ + if (isset($id) && ($a_user[$id])) { + $reqdfields = explode(" ", "usernamefld"); + $reqdfieldsn = explode(",", "Username"); + } else { + $reqdfields = explode(" ", "usernamefld passwordfld1"); + $reqdfieldsn = explode(",", "Username,Password"); + } + + do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + if (hasShellAccess($_POST['usernamefld'])) { + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['usernamefld'])) + $input_errors[] = gettext("The username contains invalid characters."); + } else { + if (preg_match("/[^a-zA-Z0-9\@\.\-_]/", $_POST['usernamefld'])) + $input_errors[] = gettext("The username contains invalid characters."); + } + + if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2'])) + $input_errors[] = gettext("The passwords do not match."); + + if (!$input_errors && !(isset($id) && $a_user[$id])) { + /* make sure there are no dupes */ + foreach ($a_user as $userent) { + if ($userent['name'] == $_POST['usernamefld']) { + $input_errors[] = gettext("Another entry with the same username already exists."); + break; + } + } + } + + if ($pconfig['utype'] <> "system" && !isset($groupindex[$_POST['groupname']])) { + $input_errors[] = gettext("group does not exist, please define the group before assigning users."); + } + + if (isset($config['system']['ssh']['sshdkeyonly']) && + empty($_POST['authorizedkeys'])) { + $input_errors[] = gettext("You must provide an authorized key otherwise you won't be able to login into this system."); + } + + /* if this is an AJAX caller then handle via JSON */ + if (isAjax() && is_array($input_errors)) { + input_errors2Ajax($input_errors); + exit; + } + + if (!$input_errors) { + if (isset($id) && $a_user[$id]) + $userent = $a_user[$id]; + + /* the user did change his username */ + if ($_POST['usernamefld'] <> $_POST['oldusername']) { + $_SERVER['REMOTE_USER'] = $_POST['usernamefld']; + } + + $userent['name'] = $_POST['usernamefld']; + $userent['fullname'] = $_POST['fullname']; + if ($pconfig['utype'] <> "system") { + $userent['groupname'] = $_POST['groupname']; + } + isset($_POST['utype']) ? $userent['scope'] = $_POST['utype'] : $userent['scope'] = "system"; + + if ($_POST['passwordfld1']) + $userent['password'] = crypt($_POST['passwordfld1']); + + if(isset($config['system']['ssh']['sshdkeyonly'])) { + $userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']); + } + + if (isset($id) && $a_user[$id]) + $a_user[$id] = $userent; + else + $a_user[] = $userent; + + write_config(); + $retval = system_password_configure(); + sync_webgui_passwords(); + + pfSenseHeader("system_usermanager.php"); + } + } + + include("head.inc"); + //echo $pfSenseHead->getHTML(); +?> + +"> + + + + + + + + + + +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + /> + +
    + +
    +   +
    + /> +
    + +
    + +
    + +
    + + + + + + + + + + + ""): ?> + + + + + + + + + + + + + + + + +
    > + + > + + > +   + + + + + + + +
    ')">
    + +
    + + + + +
    +
    +
    + +
    + +
    + +
    + +
      + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    UsernameFull nameGroup
    + + + + + +
    + + User + + User + +   + + +
    +
      +   + + + edit user + + +   + ')"> + delete user + + +
    + + add user + +
    +

    + +

    +

    + +

    +
    + +
    + saving changes + $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['password'] = crypt(trim($_POST['passwordfld1'])); + + write_config(); + + sync_webgui_passwords(); + + $retval = system_password_configure(); + $savemsg = get_std_save_message($retval); + $savemsg = "Password successfully changed
    "; + } + } +?> + +getHTML(); +?> + + + + "> +
    + + + + + + + + + + + + + + + +
    's Password
    Password + +
    + +   +
    + +
      + " /> +
    +
    + + + + + diff --git a/usr/local/www/system_usermanager_settings.php b/usr/local/www/system_usermanager_settings.php new file mode 100755 index 0000000000..c62771cd19 --- /dev/null +++ b/usr/local/www/system_usermanager_settings.php @@ -0,0 +1,111 @@ + + 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS 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 + AUTHOR 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("guiconfig.inc"); +$pconfig['session_timeout'] = &$config['system']['webgui']['session_timeout']; + +// Page title for main admin +$pgtitle = array(gettext("System"), gettext("User manager settings")); + +if ($_POST) { + unset($input_errors); + + /* input validation */ + $reqdfields = explode(" ", "session_timeout"); + $reqdfieldsn = explode(",", "Session Timeout"); + + do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + if ($_POST['session_timeout'] != "" && !is_numeric($_POST['session_timeout'])) + $input_errors[] = gettext("Session timeout must be an integer with value 0 or greater."); + + /* if this is an AJAX caller then handle via JSON */ + if (isAjax() && is_array($input_errors)) { + input_errors2Ajax($input_errors); + exit; + } + + + if (!$input_errors) { + $pconfig['session_timeout'] = $_POST['session_timeout']; + + write_config(); + + pfSenseHeader("system_usermanager_settings.php"); + } +} + +include("head.inc"); +// XXX billm FIXME +//echo $pfSenseHead->getHTML(); +?> + +"> + + + + + + + + + +
    + +
    +
    +
    + + + + + + + + + + +
    Session Timeout +
    +
    +
      " /> +
    +
    +
    +
    + + + +