$config = get_config();
+function authlevel_value( $level )
+{
+ switch ( $level )
+ {
+ case 'limited_read':
+ return 1;
+ case 'full_read':
+ return 2;
+ case 'read_write':
+ return 3;
+ default:
+ return 0;
+ }
+}
+function authlevel_name( $level )
+{
+ switch ( $level )
+ {
+ case 1:
+ return 'limited_read';
+ case 2:
+ return 'full_read';
+ case 3:
+ return 'read_write';
+ default:
+ return 'no_access';
+ }
+}
+
/*******************************
* Load authentication plugin ..
*******************************/
{ print json_encode( array( 'response' => 'error', 'cause' => 'config-error' ) ); exit; }
/*******************************/
-function check_authkey ( $key )
-{
- global $config;
- if ( $key == "6327c08b70f9" ) return true;
- return false;
-
-}
-
-function new_key( )
+function new_key( $hex = false )
{
// Basically this is at the moment a slightly modified
// version of generate_password() from user_functiions.php
$string = "";
while ( strlen( $string ) < $length )
{
- $string .= crypt( substr(sha1(rand()), 0, $length) );
- $string = preg_replace( '/\W/', '', $string);
+ if ( $hex )
+ $string .= substr(md5(rand().rand()), 0, $length+1);
+ else
+ {
+ $string .= crypt( substr(sha1(rand()), 0, $length+1) );
+ $string = preg_replace( '/\W/', '', $string);
+ }
}
- return substr( $string, 0, $length );
+ return substr( $string, 1, $length );
}
function simple_authfail()
{
global $_GET;
- if ( array_key_exists('auth_key', $_GET ) )
- { if ( ! check_authkey($_GET['auth_key'] ) ) simple_authfail(); }
+ // TODO: Part of ping/pong requirement.
+ // Run a function to clear all authkeys older than 5 minutes.
+ expire_authkeys();
+
+ if ( array_key_exists('session', $_GET )
+ && array_key_exists('auth_key', $_GET ) )
+ {
+ if ( ! check_session($_GET['session'] ) ) simple_authfail();
+ if ( ! check_authkey($_GET['auth_key'] ) ) simple_authfail();
+ }
else simple_authfail();
}
-function can_write ( )
+function get_cookie_path ()
+{
+ $name = $_SERVER["SCRIPT_NAME"];
+ $file = basename($name);
+ $path = preg_replace("/".$file."/", "", $name);
+ return $path;
+
+}
+
+function check_authkey ( $key )
+{
+ // TODO: Make real, actual checks...
+ if ( $key ) return true;
+ return false;
+}
+
+function expire_authkeys()
+{
+ global $config;
+
+ // Force deletion of sessions that have expired keys.
+ $query = sprintf("SELECT session, sessid FROM %s WHERE `last` < DATE_SUB( NOW(), INTERVAL %d MINUTE)",
+ $config['sessionkeys_table'],
+ $config['sessionkey_lifetime']);
+ $result = sql_dbquery( $config['provision_db'], $query );
+ while ( $row = @mysql_fetch_row( $result ) )
+ {
+ remove_session( $row[0], $row[1] );
+ }
+
+ $query = sprintf("DELETE FROM %s WHERE `last` < DATE_SUB( NOW(), INTERVAL %d MINUTE)",
+ $config['sessionkeys_table'],
+ $config['sessionkey_lifetime']);
+
+ sql_dbexec( $config['provision_db'], $query );
+}
+
+function update_authkey ( $session, $authid )
+{
+ global $config;
+
+ $key = substr(new_key(), 0, 8);
+
+ expire_authkeys();
+
+ // TODO: Refresh cookie
+
+ $remote = $_SERVER['REMOTE_ADDR'];
+ $query = sprintf("INSERT INTO %s ( `sessid`, `session`, `authid`, `client`, `key`, `last` )
+ VALUES ( '%s', '%s', '%s', '%s', '%s', NOW() )
+ ON DUPLICATE KEY UPDATE `key` = '%s', `last` = NOW()",
+ $config['sessionkeys_table'],
+ session_id(),
+ session_name(),
+ sql_clean($authid),
+ sql_clean($remote),
+ sql_clean($key),
+ sql_clean($key));
+ if ( ! sql_dbexec( $config['provision_db'], $query ) )
+ {
+ mysql_error();
+ }
+ $_SESSION['kkey'] = $key;
+ $_SESSION['when'] = time();
+ return $key;
+}
+
+function check_session ( $name )
{
- // Stub, to be called on any API nodes taht write data in the DB.
+ session_name( $name );
+ session_start();
+ if ( ! $_SESSION['authid'] )
+ {
+ return clear_credentials($name);
+ }
+ if ( ! $_COOKIE['client_key'] )
+ {
+ return clear_credentials($name);
+ }
+
+ $authid = $_SESSION['authid'];
+ $type = $_SESSION['type'];
+ $client_key = $_COOKIE['client_key'];
+
+ $level = get_authorization( $type, $authid );
+ if ( $level == false )
+ {
+ return clear_credentials($name);
+ }
+
+ $session_key = md5( $name . $authid );
+ if ( $client_key != $session_key )
+ {
+ return clear_credentials($name);
+ }
+
+ // If we got this far, things are looking good.
return true;
}
+function set_credentials( $authid, $type )
+{
+ $name = new_key(true);
+ session_name( $name );
+ session_start();
+ $_SESSION['authid'] = $authid;
+ $_SESSION['type'] = $type;
+
+ $client_key = md5( $name . $authid );
+ setcookie('client_key', $client_key, time()+180*60, get_cookie_path() );
+
+ return $name;
+}
+
+function clear_credentials($name)
+{
+ global $config;
+
+ setcookie('client_key', '', 0, get_cookie_path() );
+
+ remove_session($name);
+ $_SESSION = array();
+
+ $query = sprintf("DELETE FROM %s WHERE `session` = '%s'",
+ $config['sessionkeys_table'],
+ sql_clean($name));
+ sql_dbexec( $config['provision_db'], $query );
+
+ return false;
+}
+
+function remove_session ($name, $id = null )
+{
+ if ( $id == null )
+ {
+ session_destroy();
+ setcookie($name, '', 0, "/");
+ return;
+ }
+ $current_session = session_name( );
+ $current_sessid = session_id( );
+ session_commit();
+
+ session_id( $id );
+ session_start();
+ setcookie( $name, '', 0, "/");
+ $_SESSION=array();
+ session_destroy();
+
+ if ( $current_session && $current_session != $name )
+ {
+ session_id($current_sessid);
+ session_start();
+ }
+}
+function add_apikey ( $host, $level )
+{
+ global $config;
+ if ( !is_numeric($level) ) return false;
+
+ $key = new_key();
+
+ // Try to add the new key to authorizations first. If this
+ // fails, there will be the least amount of data to clean up ...
+ if ( ! update_authorization( "key", $key, $level ) ) return false;
+
+ $query = sprintf("INSERT INTO %s ( host, apikey ) VALUES ( '%s', '%s' )",
+ $config['apikeys_table'],
+ sql_clean($host),
+ sql_clean($key));
+
+ if ( ! sql_dbexec( $config['provision_db'], $query ) ) return false;
+ return $key;
+}
+
+function remove_apikey( $key )
+{
+ global $config;
+ if ( ! verify_apikey( $key, true ) ) return false;
+ if ( ! remove_authorization( $key ) ) return false;
+
+ $query = sprintf("DELETE FROM %s WHERE apikey = '%s'",
+ $config['apikeys_table'],
+ sql_clean($key) );
+ if ( ! sql_dbexec( $config['provision_db'], $query ) ) return false;
+
+ return true;
+}
+
+function verify_apikey( $key, $skip_hostcheck = false )
+{
+ global $config;
+
+ $query = sprintf("SELECT host FROM %s WHERE apikey = '%s'",
+ $config['apikeys_table'],
+ sql_clean($key) );
+ $row = sql_dbquery_single( $config['provision_db'], $query );
+ if (!$row) return false;
+ $host = $row['host'];
+
+ if ( $host && ( $skip_hostcheck ) )
+ return true;
+
+ if ( $host == $_SERVER['REMOTE_ADDR'] ) return true;
+ return false;
+
+}
+
+function list_apikeys ()
+{
+ global $config;
+ $query = sprintf("SELECT k.apikey AS apikey, k.host AS host,
+ a.access_level AS access_level
+ FROM %s k INNER JOIN %s a ON k.apikey = a.authid
+ WHERE a.type = 'key'",
+ $config['apikeys_table'],
+ $config['authorizations_table']);
+ $list = array();
+ $result = sql_dbquery( $config['provision_db'], $query);
+ if ( ! $result ) return $list;
+ while ( $row = @mysql_fetch_assoc( $result ) )
+ {
+ array_push( $list, array(
+ 'api_key' => $row['apikey'],
+ 'host' => $row['host'],
+ 'level' => authlevel_name( $row['access_level'] )
+ ));
+ }
+ return $list;
+
+}
+
+function list_authusers ()
+{
+ global $config;
+ $query = sprintf("SELECT authid, access_level
+ FROM %s
+ WHERE type = 'user'",
+ $config['authorizations_table']);
+ $list = array();
+ $result = sql_dbquery( $config['provision_db'], $query);
+ if ( ! $result ) return $list;
+ while ( $row = @mysql_fetch_assoc( $result ) )
+ {
+ $username = $row['authid'];
+ $user_data = authuser_getinfo( $username );
+
+ // TODO: Remove invalid users here?
+ if ( ! $user_data ) continue;
+
+ array_push( $list, array(
+ 'user' => $username,
+ 'name' => $user_data['name'],
+ 'email' => $user_data['email'],
+ 'level' => authlevel_name( $row['access_level'] )
+ ));
+ }
+ return $list;
+
+}
+
+
+
+function update_authorization( $type, $authid, $level )
+{
+ global $config;
+ if ( !is_numeric($level) ) return false;
+ if ( ($type != "key") && ($type != "user") ) return false;
+
+ $query = sprintf("INSERT INTO %s ( authid, type, access_level ) VALUES ( '%s', '%s', %d )
+ ON DUPLICATE KEY UPDATE access_level=%d",
+ $config['authorizations_table'],
+ sql_clean($authid),
+ $type,
+ $level, $level);
+ if ( ! sql_dbexec( $config['provision_db'], $query ) ) return false;
+ return true;
+}
+
+function remove_authorization( $authid )
+{
+ global $config;
+ $query = sprintf("DELETE FROM %s WHERE authid = '%s'",
+ $config['authorizations_table'],
+ sql_clean($authid) );
+ //print $query . "\n\n";
+ if ( ! sql_dbexec( $config['provision_db'], $query ) ) return false;
+ return true;
+}
+
+
+function get_authorization( $type, $authid )
+{
+ global $config;
+
+ // If API-key is used, but key fails verification, write is impossible.
+ if ( ( $type == "key" ) && ( ! verify_apikey( $authid, true ) ) )
+ return false;
+
+ // If User-login is used, but backend is unable to provide info, fail.
+ if ( ( $type == "user" ) && ( ! authuser_getinfo( $authid ) ) )
+ return false;
+
+ // The only types of access control supported are "user" or "key".
+ if ( ($type != "user" ) && ($type != "key") )
+ return false;
+
+ $query = sprintf("SELECT access_level FROM %s WHERE authid = '%s'",
+ $config['authorizations_table'],
+ sql_clean($authid) );
+ $row = sql_dbquery_single( $config['provision_db'], $query );
+ if (!$row) return false;
+ $level = $row['access_level'];
+ return $level;
+}
+
+function can_write ( )
+{
+ // Stub, to be called on any API nodes that write data in the DB.
+ $authid = $_SESSION['authid'];
+ $type = $_SESSION['type'];
+
+ $level = get_authorization( $type, $authid );
+ if ( $level >= authlevel_value('read_write') ) return $level;
+ else return false;
+}
+
?>