summaryrefslogtreecommitdiffstats
path: root/etc/inc/auth.inc
diff options
context:
space:
mode:
authorBill Marquette <billm@pfsense.org>2007-04-13 03:26:35 +0000
committerBill Marquette <billm@pfsense.org>2007-04-13 03:26:35 +0000
commitfab7ff44cbc8d2faf0d0a270d8edb8d65807557e (patch)
treee6dcf342fb2e18d8de67ed7ed9589519d4c64ec3 /etc/inc/auth.inc
parent6d838c8378006c84402993ab631c1b9947fc41a3 (diff)
downloadpfsense-fab7ff44cbc8d2faf0d0a270d8edb8d65807557e.zip
pfsense-fab7ff44cbc8d2faf0d0a270d8edb8d65807557e.tar.gz
Backport usermanager code from HEAD so I can get it in the snaps and
start testing it properly There's still some CSS/HTML fixes needed but the code seems to work
Diffstat (limited to 'etc/inc/auth.inc')
-rw-r--r--etc/inc/auth.inc702
1 files changed, 603 insertions, 99 deletions
diff --git a/etc/inc/auth.inc b/etc/inc/auth.inc
index a13faaf..c9318bc 100644
--- a/etc/inc/auth.inc
+++ b/etc/inc/auth.inc
@@ -4,6 +4,12 @@
Copyright (C) 2005-2006 Bill Marquette <bill.marquette@gmail.com>
All rights reserved.
+ Copyright (C) 2006 Paul Taylor <paultaylor@winn-dixie.com>.
+ All rights reserved.
+
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ 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");
-
-/* We only support file backed HTTP Basic auth right now */
-$auth_method="htpasswd_backed_basic_auth";
-
-/* Authenticate user - exit if failed (we should have a callback for this maybe) */
-if (!$auth_method())
- exit;
-
-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;
-}
-
-function passwd_backed_basic_auth() {
- global $HTTP_SERVER_VARS;
-
- $authfile = file("/etc/master.passwd");
-
- /* 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;
-
- /* 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;
-}
-
-function htpasswd_backed_basic_auth() {
- global $HTTP_SERVER_VARS;
-
- $authfile = file("/var/run/htpasswd");
-
- /* sanity check to ensure that /usr/local/www/.htpasswd doesn't exist */
- unlink_if_exists("/usr/local/www/.htpasswd");
-
- /* 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;
-
- /* 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;
+require_once("functions.inc");
+$groupindex = index_groups();
+$userindex = index_users();
+
+function &getSystemAdminNames() {
+ global $config, $g, $userindex;
+ $adminUsers = array();
+
+ if (is_array($config['system']['user'])) {
+ foreach($config['system']['user'] as $user){
+ if (isSystemAdmin($user['name'])) {
+ $adminUsers[] = $user['name'];
+ }
+ }
+ }
+
+ return $adminUsers;
+}
+
+function &getSystemPrivs() {
+ global $g;
+
+ $privs = array();
+
+ $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).");
+
+ return $privs;
+}
+
+function assignUID($username = "") {
+ global $userindex, $config, $g;
+
+ if ($username == "") { return; }
+
+ $nextuid = $config['system']['nextuid'];
+ $user =& $config['system']['user'][$userindex[$username]];
+
+ if (empty($user['uid'])) {
+ $user['uid'] = $nextuid;
+ $nextuid++;
+ $config['system']['nextuid'] = $nextuid;
+
+ write_config();
+
+ return $user;
+ }
+}
+
+function assignGID($groupname = "") {
+ global $groupindex, $config, $g;
+
+ if ($groupname == "") { return; }
+
+ $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;
+ }
+ }
+}
+
+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 = <<<EOD
+# /etc/pam.d/php
+#
+# note: both an auth and account entry are required
+
+# auth
+auth required pam_nologin.so no_warn
+auth sufficient pam_opie.so no_warn no_fake_prompts
+auth requisite pam_opieaccess.so no_warn allow_local
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+account required pam_unix.so
+
+# session
+session required pam_permit.so
- /* Should only get here if user fails login three times */
+# password
+password required pam_unix.so no_warn try_first_pass
+
+EOD;
+
+ file_put_contents("/etc/pam.d/php", $pam_php);
+ } // end if
+
+ if (pam_auth($username, $password, &$error)) {
+ return true;
+ } else {
return false;
+ }
+ }
+ }
+}
+
+function passwd_backed($username, $passwd) {
+ $authfile = file("/etc/master.passwd");
+
+ $matches="";
+
+ /* Check to see if user even exists */
+ if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile))))
+ return false;
+
+ /* Get crypted password */
+ preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches);
+ $pass = $matches[1];
+ $salt = $matches[2];
+
+ /* Encrypt entered password with salt
+ * And finally validate password
+ */
+ if ($pass == crypt($passwd, $salt))
+ return true;
+ else
+ return false;
+}
+
+function htpasswd_backed($username, $passwd) {
+ $authfile = file("/var/run/htpasswd");
+
+ /* sanity check to ensure that /usr/local/www/.htpasswd doesn't exist */
+ unlink_if_exists("/usr/local/www/.htpasswd");
+
+ $matches="";
+ if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile))))
+ return false;
+
+ /* Get crypted password */
+ preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches);
+ $pass = $matches[1];
+ $salt = $matches[2];
+
+ /* Encrypt entered password with salt
+ * And finally validate password
+ */
+ if ($pass == crypt($passwd, $salt))
+ return true;
+ else
+ return false;
+}
+
+function radius_backed($username, $passwd){
+ global $config, $debug;
+ $ret = false;
+ $radiusservers = $config['system']['radius']['servers'];
+
+ $rauth = new Auth_RADIUS_PAP($username, $passwd);
+ foreach ($radiusservers as $radsrv) {
+ // Add a new server to our instance
+ $rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
+ }
+
+ if (!$rauth->start()) {
+ $retvalue['auth_val'] = 1;
+ $retvalue['error'] = $rauth->getError();
+ if ($debug)
+ printf("Radius start: %s<br>\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<br>\n", $retvalue['error']);
+ } else if ($result === true) {
+ $retvalue['auth_val'] = 2;
+ if ($debug)
+ printf (gettext("Radius Auth succeeded") . "<br>\n");
+ $ret = true;
+ } else {
+ $retvalue['auth_val'] = 3;
+ if ($debug)
+ printf (gettext("Radius Auth rejected") . "<br>\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);
}
-?> \ No newline at end of file
+?>
OpenPOWER on IntegriCloud