summaryrefslogtreecommitdiffstats
path: root/lib/class/vauth.class.php
diff options
context:
space:
mode:
authorPaul 'flowerysong' Arthur <flowerysong00@yahoo.com>2010-05-29 08:33:48 +0000
committerPaul 'flowerysong' Arthur <flowerysong00@yahoo.com>2010-05-29 08:33:48 +0000
commit67be60ae0997648e7ac4b2d5ab61996efedd630b (patch)
tree01d0704609d91719889c0151cd12867a081b33e5 /lib/class/vauth.class.php
parenta94a213d72cc2982cba2952d721236cc62a6d9d4 (diff)
downloadampache-67be60ae0997648e7ac4b2d5ab61996efedd630b.tar.gz
ampache-67be60ae0997648e7ac4b2d5ab61996efedd630b.tar.bz2
ampache-67be60ae0997648e7ac4b2d5ab61996efedd630b.zip
Cleanup and rationalisation of authentication related code. Among other things,
fixes FS#99.
Diffstat (limited to 'lib/class/vauth.class.php')
-rw-r--r--lib/class/vauth.class.php337
1 files changed, 181 insertions, 156 deletions
diff --git a/lib/class/vauth.class.php b/lib/class/vauth.class.php
index cc11328f..0568026b 100644
--- a/lib/class/vauth.class.php
+++ b/lib/class/vauth.class.php
@@ -27,17 +27,12 @@
*/
class vauth {
- /* Variables from DB */
-
-
/**
* Constructor
* This should never be called
*/
private function __construct() {
-
// Rien a faire
-
} // __construct
/**
@@ -45,10 +40,10 @@ class vauth {
* This function is for opening a new session so we just verify that we
* have a database connection, nothing more is needed
*/
- public static function open($save_path,$session_name) {
+ public static function open($save_path, $session_name) {
if (!is_resource(Dba::dbh())) {
- debug_event('SESSION','Error no database connection session failed','1');
+ debug_event('SESSION', 'Error: no database connection session failed', '1');
return false;
}
@@ -58,7 +53,7 @@ class vauth {
/**
* close
- * This is run on the end of a sessoin, nothing to do here for now
+ * This is run on the end of a session, nothing to do here for now
*/
public static function close() {
@@ -75,7 +70,7 @@ class vauth {
$results = self::get_session_data($key);
if (!is_array($results)) {
- debug_event('SESSION','Error unable to read session from key ' . $key . ' no data found','1');
+ debug_event('SESSION', 'Error unable to read session from key ' . $key . ' no data found', '1');
return false;
}
@@ -85,22 +80,27 @@ class vauth {
/**
* write
- * This saves the sessoin information into the database
+ * This saves the session information into the database
*/
- public static function write($key,$value) {
+ public static function write($key, $value) {
if (NO_SESSION_UPDATE == '1') { return true; }
$length = Config::get('session_length');
$value = Dba::escape($value);
$key = Dba::escape($key);
- // Check to see if remember me cookie is set, if so use remember length, otherwise use the session length
- $expire = isset($_COOKIE[Config::get('session_name') . '_remember']) ? time() + Config::get('remember_length') : time() + Config::get('session_length');
-
- $sql = "UPDATE `session` SET `value`='$value', `expire`='$expire' WHERE `id`='$key'";
+ // Check to see if remember me cookie is set, if so use remember
+ // length, otherwise use the session length
+ $expire
+ = isset($_COOKIE[Config::get('session_name') . '_remember'])
+ ? time() + Config::get('remember_length')
+ : time() + Config::get('session_length');
+
+ $sql = "UPDATE `session` SET `value`='$value', " .
+ "`expire`='$expire' WHERE `id`='$key'";
$db_results = Dba::read($sql);
- debug_event('SESSION','Writing to ' . $key . ' with expire ' . $expire . ' ' . Dba::error(),'6');
+ debug_event('SESSION', 'Writing to ' . $key . ' with expire ' . $expire . ' ' . Dba::error(), '6');
return $db_results;
@@ -120,10 +120,10 @@ class vauth {
$sql = "DELETE FROM `session` WHERE `id`='$key'";
$db_results = Dba::write($sql);
- debug_event('SESSION','Deleting Session with key:' . $key,'6');
+ debug_event('SESSION', 'Deleting Session with key:' . $key, '6');
- // Destory our cookie!
- setcookie(Config::get('session_name'),'',time() - 86400);
+ // Destroy our cookie!
+ setcookie(Config::get('session_name'), '', time() - 86400);
return true;
@@ -131,7 +131,7 @@ class vauth {
/**
* gc
- * This function is randomly called and it cleans up the poo
+ * This function is randomly called and it cleans up the spoo
*/
public static function gc($maxlifetime) {
@@ -152,7 +152,7 @@ class vauth {
* This is the function used for the Ajax logouts, if no id is passed
* it tries to find one from the session
*/
- public static function logout($key='',$relogin=true) {
+ public static function logout($key='', $relogin=true) {
// If no key is passed try to find the session id
$key = $key ? $key : session_id();
@@ -166,7 +166,7 @@ class vauth {
$target = Config::get('web_path') . '/login.php';
}
- // Do a quick check to see if this is an AJAX'd logout request
+ // Do a quick check to see if this is an AJAXed logout request
// if so use the iframe to redirect
if (AJAX_INCLUDE == '1') {
ob_end_clean();
@@ -183,10 +183,8 @@ class vauth {
$results['rfc3514'] = '<script type="text/javascript">reload_logout("'.$target.'")</script>';
echo xml_from_array($results);
}
-
-
- /* Redirect them to the login page */
- if (AJAX_INCLUDE != '1') {
+ else {
+ /* Redirect them to the login page */
header('Location: ' . $target);
}
@@ -206,19 +204,17 @@ class vauth {
$sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '" . time() . "'";
$db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
-
- if (!count($results)) {
- return false;
+ if ($results = Dba::fetch_assoc($db_results)) {
+ return $results;
}
- return $results;
+ return false;
} // get_session_data
/**
* create_cookie
- * This is seperated into its own function because of some flaws in
+ * This is separated into its own function because of some flaws in
* specific webservers *cough* IIS *cough* which prevent us from setting
* a cookie at the same time as a header redirect. As such on view of a
* login a cookie is set with the proper name
@@ -251,7 +247,7 @@ class vauth {
$session_name = Config::get('session_name');
Config::set('cookie_life',$remember_length,'1');
- setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars",time() + $remember_length,'/');
+ setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars", time() + $remember_length, '/');
} // create_remember_cookie
@@ -273,16 +269,19 @@ class vauth {
default:
session_regenerate_id();
- // Before refresh we don't have the cookie so we have to use session ID
+ // Before refresh we don't have the cookie so we
+ // have to use session ID
$key = session_id();
break;
} // end switch on data type
$username = Dba::escape($data['username']);
- $ip = $_SERVER['REMOTE_ADDR'] ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])) : '0';
+ $ip = $_SERVER['REMOTE_ADDR']
+ ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']))
+ : '0';
$type = Dba::escape($data['type']);
$value = Dba::escape($data['value']);
- $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'],0,254));
+ $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'], 0, 254));
$expire = Dba::escape(time() + Config::get('session_length'));
/* We can't have null things here people */
@@ -294,11 +293,11 @@ class vauth {
$db_results = Dba::write($sql);
if (!$db_results) {
- debug_event('SESSION',"Session Creation Failed with Query: $sql and " . Dba::error(),'1');
+ debug_event('SESSION', "Session Creation Failed with Query: $sql and " . Dba::error(), '1');
return false;
}
- debug_event('SESSION','Session Created:' . $key,'6');
+ debug_event('SESSION', 'Session Created:' . $key, '6');
return $key;
@@ -306,14 +305,14 @@ class vauth {
/**
* check_session
- * This checks for an existing sessoin and if it's still valid then go ahead and start it and return
- * true
+ * This checks for an existing session. If it's still valid we go ahead
+ * and start it and return true.
*/
public static function check_session() {
$session_name = Config::get('session_name');
- // No cookie n go!
+ // No cookie no go!
if (!isset($_COOKIE[$session_name])) { return false; }
// Check for a remember me
@@ -321,7 +320,8 @@ class vauth {
self::create_remember_cookie();
}
- // Setup the cookie params before we start the session this is vital
+ // Set up the cookie params before we start the session.
+ // This is vital
session_set_cookie_params(
Config::get('cookie_life'),
Config::get('cookie_path'),
@@ -345,7 +345,7 @@ class vauth {
* exists, it also provides an array of key'd data that may be required
* based on the type
*/
- public static function session_exists($type,$key,$data=array()) {
+ public static function session_exists($type, $key, $data=array()) {
// Switch on the type they pass
switch ($type) {
@@ -353,18 +353,24 @@ class vauth {
case 'api':
$key = Dba::escape($key);
$time = time();
- $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '$time' AND `type`='$type'";
+ $sql = "SELECT * FROM `session` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `type`='$type'";
$db_results = Dba::read($sql);
if (Dba::num_rows($db_results)) {
return true;
}
break;
- //FIXME: This should use the IN() mojo and compare against enabled auths
case 'interface':
$key = Dba::escape($key);
$time = time();
- $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '$time' AND `type`!='api' AND `type`!='xml-rpc'";
+ // Build a list of enabled authentication types
+ $enabled_types = implode("','",
+ Config::get('auth_methods'));
+ $sql = "SELECT * FROM `session` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `type` IN('$enabled_types')";
$db_results = Dba::read($sql);
if (Dba::num_rows($db_results)) {
@@ -375,7 +381,9 @@ class vauth {
$key = Dba::escape($key);
$ip = Dba::escape(inet_pton($data['ip']));
$agent = Dba::escape($data['agent']);
- $sql = "SELECT * FROM `session_stream` WHERE `id`='$key' AND `expire` > '$time' AND `ip`='$ip' AND `agent`='$agent'";
+ $sql = "SELECT * FROM `session_stream` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `ip`='$ip' AND `agent`='$agent'";
$db_results = Dba::read($sql);
if (Dba::num_rows($db_results)) {
@@ -395,19 +403,22 @@ class vauth {
/**
* session_extend
- * This should really be extend_session but hey you gotta go with the flow
- * this takes a SID and extends it's expire
+ * This should really be extend_session but hey you gotta go with the
+ * flow.
+ * This takes a SID and extends its expiration.
*/
public static function session_extend($sid) {
$sid = Dba::escape($sid);
- $expire = isset($_COOKIE[Config::get('session_name') . '_remember']) ? time() + Config::get('remember_length') : time() + Config::get('session_length');
+ $expire = isset($_COOKIE[Config::get('session_name') . '_remember'])
+ ? time() + Config::get('remember_length')
+ : time() + Config::get('session_length');
$len = $expire - time();
$sql = "UPDATE `session` SET `expire`='$expire' WHERE `id`='$sid'";
$db_results = Dba::write($sql);
- debug_event('SESSION','Session:' . $sid . ' Has been Extended to ' . date("r",$expire) . ' extension length ' . $len,'6');
+ debug_event('SESSION', 'Session:' . $sid . ' has been extended to ' . date("r",$expire) . ' extension length ' . $len, '6');
return $db_results;
@@ -415,7 +426,8 @@ class vauth {
/**
* _auto_init
- * This function is called when the object is included, this sets up the session_save_handler
+ * This function is called when the object is included, this sets up the
+ * session_save_handler
*/
public static function _auto_init() {
@@ -424,15 +436,21 @@ class vauth {
exit;
}
- session_set_save_handler(array('vauth','open'),array('vauth','close'),array('vauth','read'),array('vauth','write'),array('vauth','destroy'),array('vauth','gc'));
+ session_set_save_handler(
+ array('vauth', 'open'),
+ array('vauth', 'close'),
+ array('vauth', 'read'),
+ array('vauth', 'write'),
+ array('vauth', 'destroy'),
+ array('vauth', 'gc'));
} // auto init
/**
* ungimp_ie
* This function sets the cache limiting to public if you are running
- * some flavor of IE. The detection used here is very conservative so feel free
- * to fix it. This only has to be done if we're rolling HTTPS
+ * some flavor of IE. The detection used here is very conservative so
+ * feel free to fix it. This only has to be done if we're rolling HTTPS.
*/
public static function ungimp_ie() {
@@ -442,7 +460,8 @@ class vauth {
// Try to detect IE
$agent = trim($_SERVER['HTTP_USER_AGENT']);
- if (strstr($agent,'MSIE') || strstr($agent,'Internet Explorer/')) {
+ if ((strpos($agent, 'MSIE') !== false) ||
+ (strpos($agent,'Internet Explorer/') !== false)) {
session_cache_limiter('public');
}
@@ -452,22 +471,24 @@ class vauth {
/**
* authenticate
- * This takes a username and password and then returns true or false
- * based on what happens when we try to do the auth then
+ * This takes a username and password and then returns the results
+ * based on what happens when we try to do the auth.
*/
- public static function authenticate($username,$password) {
+ public static function authenticate($username, $password) {
// Foreach the auth methods
foreach (Config::get('auth_methods') as $method) {
- // Build the function name and call the custom method on this class
+ // Build the function name and call it
$function_name = $method . '_auth';
- if (!method_exists('vauth',$function_name)) { continue; }
+ if (!method_exists('vauth', $function_name)) {
+ continue;
+ }
- $results = self::$function_name($username,$password);
+ $results = self::$function_name($username, $password);
- // If we achive victory return
+ // If we achieve victory return
if ($results['success']) { break; }
} // end foreach
@@ -478,48 +499,49 @@ class vauth {
/**
* mysql_auth
- * This is the core function of authentication by ampache. It checks their current password
- * and then tries to figure out if it can use the new SHA password hash or if it needs to fall
- * back on the mysql method
+ * This is the core function of our built-in authentication. It checks
+ * their current password and then tries to figure out if it can use the
+ * new SHA password hash or if it needs to fall back on the old mysql
+ * method.
*/
- private static function mysql_auth($username,$password) {
+ private static function mysql_auth($username, $password) {
$username = Dba::escape($username);
- $password = Dba::escape($password);
-
- if (!strlen($password) OR !strlen($username)) {
- Error::add('general',_('Error Username or Password incorrect, please try again'));
- return false;
- }
-
- // We have to pull the password in order to figure out how to handle it *cry*
- $sql = "SELECT `password` FROM `user` WHERE `username`='$username'";
- $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
-
- // If it's using the old method then roll with that
- if (substr($row['password'],0,1) == '*' OR strlen($row['password']) < 32) {
- $response = self::vieux_mysql_auth($username,$password);
- return $response;
- }
- // Use SHA2 now... cooking with fire, SHA3 in 2012 *excitement*
- $password = hash('sha256',$password);
-
- $sql = "SELECT `username`,`id` FROM `user` WHERE `password`='$password' AND `username`='$username'";
- $db_results = Dba::read($sql);
-
- $row = Dba::fetch_assoc($db_results);
+ if (strlen($password) && strlen($username)) {
+ $sql = "SELECT `password` FROM `user` WHERE " .
+ "`username`='$username'";
+ $db_results = Dba::read($sql);
+ if ($row = Dba::fetch_assoc($db_results)) {
+
+ // If it's using the old method
+ if (substr($row['password'], 0, 1) == '*' ||
+ strlen($row['password']) < 32) {
+ $password = Dba::escape(scrub_in($password));
+ return self::vieux_mysql_auth($username, $password);
+ }
- if (!count($row)) {
- Error::add('general',_('Error Username or Password incorrect, please try again'));
- return false;
+ // Use SHA2 now... cooking with fire.
+ // For backwards compatibility, we hash a couple
+ // of different variations of the password.
+ // Increases collision chances, but doesn't
+ // break things.
+ $hashed_password[] = hash('sha256', $password);
+ $hashed_password[] = hash('sha256',
+ Dba::escape(scrub_in($password)));
+ if(in_array($row['password'], $hashed_password)) {
+ $results['success'] = true;
+ $results['type'] = 'mysql';
+ $results['username'] = $username;
+ return $results;
+ }
+ }
}
- $row['type'] = 'mysql';
- $row['success'] = true;
-
- return $row;
+ // Default to failure
+ $results['success'] = false;
+ $results['error'] = 'MySQL login attempt failed';
+ return $results;
} // mysql_auth
@@ -527,47 +549,41 @@ class vauth {
* vieux_mysql_auth
* This is a private function, it should only be called by authenticate
*/
- private static function vieux_mysql_auth($username,$password) {
+ private static function vieux_mysql_auth($username, $password) {
$password_check_sql = "PASSWORD('$password')";
- // This has to still be here because lots of people use old_password in their config file
+ // This has to still be here because lots of people use
+ // old_password in their config file
$sql = "SELECT `password` FROM `user` WHERE `username`='$username'";
$db_results = Dba::read($sql);
$row = Dba::fetch_assoc($db_results);
- $sql = "SELECT version()";
+ $sql = 'SELECT version()';
$db_results = Dba::read($sql);
$version = Dba::fetch_row($db_results);
- $mysql_version = substr(preg_replace("/(\d+)\.(\d+)\.(\d+).*/","$1$2$3",$version[0]),0,3);
+ $mysql_version = substr(
+ preg_replace("/(\d+)\.(\d+)\.(\d+).*/", "$1$2$3",
+ $version[0]),
+ 0, 3);
- if ($mysql_version > "409" AND substr($row['password'],0,1) !== "*") {
+ if ($mysql_version > '409' &&
+ substr($row['password'], 0, 1) !== "*") {
$password_check_sql = "OLD_PASSWORD('$password')";
}
$sql = "SELECT `username`,`id` FROM `user` WHERE `username`='$username' AND `password`=$password_check_sql";
$db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
-
- if (!$results) {
- Error::add('general',_('Error Username or Password incorrect, please try again'));
- return false;
+ if (Dba::fetch_assoc($db_results)) {
+ $results['type'] = 'mysql';
+ $results['password'] = 'old';
+ $results['success'] = true;
+ }
+ else {
+ $results['success'] = false;
+ $results['error'] = 'Old MySQL login attempt failed';
}
-
- if (Config::get('prevent_multiple_logins')) {
- $client = new User($results['id']);
- $current_ip = $client->is_logged_in();
- if ($current_ip AND $current_ip != inet_pton($_SERVER['REMOTE_ADDR'])) {
- debug_event('Login','Concurrent Login Failure, attempted to login from ' . $_SERVER['REMOTE_ADDR'] . ' and already logged in','1');
- Error::add('general','User Already Logged in');
- return false;
- }
- } // if prevent_multiple_logins
-
- $results['type'] = 'mysql';
- $results['password'] = 'old';
- $results['success'] = true;
return $results;
@@ -575,23 +591,26 @@ class vauth {
/**
* local_auth
- * Check to make sure the pam_auth function is implemented (module is installed) then check the credentials
+ * Check to make sure the pam_auth function is implemented (module is
+ * installed), then check the credentials.
*/
- private static function local_auth($username,$password) {
+ private static function local_auth($username, $password) {
if (!function_exists('pam_auth')) {
- $results['success'] = false;
- $results['error'] = "The PAM authentication PHP module is not installed.";
+ $results['success'] = false;
+ $results['error'] = 'The PAM PHP module is not installed';
return $results;
}
- if (pam_auth($username, $password, &$results['error'])) {
- $results['success'] = true;
- $results['type'] = 'local';
- $results['username'] = $username;
+ $password = scrub_in($password);
+
+ if (pam_auth($username, $password)) {
+ $results['success'] = true;
+ $results['type'] = 'local';
+ $results['username'] = $username;
}
else {
- $results['success'] = false;
- $results['error'] = "PAM login attempt failed";
+ $results['success'] = false;
+ $results['error'] = 'PAM login attempt failed';
}
return $results;
@@ -599,15 +618,20 @@ class vauth {
/**
* ldap_auth
- * Step one, connect to the LDAP server and perform a search for teh username provided.
- * If its found, attempt to bind using that username and the password provided.
- * Step two, figure out if they are authorized to use ampache:
- * TODO: need implimented still:
- * * require-group "The DN fetched from the LDAP directory (or the username passed by the client) occurs in the LDAP group"
- * * require-dn "Grant access if the DN in the directive matches the DN fetched from the LDAP directory"
- * * require-attribute "an attribute fetched from the LDAP directory matches the given value"
+ * Step one, connect to the LDAP server and perform a search for the
+ * username provided.
+ * Step two, attempt to bind using that username and the password
+ * provided.
+ * Step three, figure out if they are authorized to use ampache:
+ * TODO: in config but unimplemented:
+ * * require-group "The DN fetched from the LDAP directory (or the
+ * username passed by the client) occurs in the LDAP group"
+ * * require-dn "Grant access if the DN in the directive matches
+ * the DN fetched from the LDAP directory"
+ * * require-attribute "an attribute fetched from the LDAP
+ * directory matches the given value"
*/
- private static function ldap_auth($username,$password) {
+ private static function ldap_auth($username, $password) {
$ldap_username = Config::get('ldap_username');
$ldap_password = Config::get('ldap_password');
@@ -635,7 +659,7 @@ class vauth {
/* Set to Protocol 3 */
ldap_set_option($ldap_link, LDAP_OPT_PROTOCOL_VERSION, 3);
- // bind using our auth, if we need to, for initial search for username
+ // bind using our auth if we need to for initial search
if (!ldap_bind($ldap_link, $ldap_username, $ldap_password)) {
$results['success'] = false;
$results['error'] = "Could not bind to LDAP server.";
@@ -647,17 +671,18 @@ class vauth {
if ($info["count"] == 1) {
$user_entry = ldap_first_entry($ldap_link, $sr);
- $user_dn = ldap_get_dn($ldap_link, $user_entry);
+ $user_dn = ldap_get_dn($ldap_link, $user_entry);
+ $password = scrub_in($password);
// bind using the user..
$retval = ldap_bind($ldap_link, $user_dn, $password);
if ($retval) {
ldap_close($ldap_link);
- $results['success'] = true;
- $results['type'] = "ldap";
+ $results['success'] = true;
+ $results['type'] = "ldap";
$results['username'] = $username;
- $results['name'] = $info[0][$ldap_name_field][0];
- $results['email'] = $info[0][$ldap_email_field][0];
+ $results['name'] = $info[0][$ldap_name_field][0];
+ $results['email'] = $info[0][$ldap_email_field][0];
return $results;
@@ -669,7 +694,7 @@ class vauth {
/* Default to bad news */
$results['success'] = false;
- $results['error'] = "LDAP login attempt failed";
+ $results['error'] = 'LDAP login attempt failed';
return $results;
@@ -677,20 +702,20 @@ class vauth {
/**
* http_auth
- * This auth method relies on HTTP auth from Apache
+ * This auth method relies on HTTP auth from the webserver
*/
- private static function http_auth($username) {
+ private static function http_auth($username, $password) {
if (($_SERVER['REMOTE_USER'] == $username) ||
- ($_SERVER['HTTP_REMOTE_USER'] == $username)) {
- $results['success'] = true;
- $results['type'] = 'http';
- $results['username'] = $username;
- $results['name'] = $username;
- $results['email'] = '';
+ ($_SERVER['HTTP_REMOTE_USER'] == $username)) {
+ $results['success'] = true;
+ $results['type'] = 'http';
+ $results['username'] = $username;
+ $results['name'] = $username;
+ $results['email'] = '';
}
else {
$results['success'] = false;
- $results['error'] = "HTTP auth: REMOTE_USER not set";
+ $results['error'] = 'HTTP auth login attempt failed';
}
return $results;
} // http_auth