From: Jon Langseth Date: Wed, 18 Jan 2012 23:17:00 +0000 (+0100) Subject: Starting to get parts of an auth-framework operational... X-Git-Url: https://git.defcon.no/?a=commitdiff_plain;h=726f4037a48240b4104070bad824ea2e31e959e1;p=hermes Starting to get parts of an auth-framework operational... --- diff --git a/api/auth.php b/api/auth.php index 38b1560..1cad402 100644 --- a/api/auth.php +++ b/api/auth.php @@ -21,10 +21,86 @@ if ( !$config['sql_link'] ) //************************************************************************************* switch ( $_SERVER['PATH_INFO'] ) { + case "/login": + // Allow login using username and password, or API key. + // On successful login, a named session should be started, + // some data related to the session should be stored, + // and the name of the session provided to the user + // in the result. + $type = false; + $authid = false; + + if ( array_key_exists('username', $_GET) + && array_key_exists('password', $_GET) ) + { + if ( 1 == authuser_verify( sql_clean($_GET['username']), sql_clean($_GET['password']))) + { + $type = "user"; + $authid = $_GET['username']; + } + else + { + print json_encode( array( 'response' => 'failed', 'cause' => 'unauthorized', 'description' => 'Login failed') ); + exit; + } + } + else if ( array_key_exists('api_key', $_GET) ) + { + if ( apikey_verify( sql_clean( $_GET['api_key'] ) ) == 1 ) + { + $type = "key"; + $authid = $_GET['api_key']; + } + else + { + print json_encode( array( 'response' => 'failed', 'cause' => 'unauthorized', 'description' => 'Login failed') ); + exit; + } + } + else + { + print json_encode ( array( 'response' => 'invalid') ); + break; + } + $session_name = set_credentials( $authid, $type ); + $auth_key = update_authkey( $session_name, $authid ); + print json_encode( array( 'response' => 'ok', 'session' => $session_name, 'auth_key' => $auth_key )); + break; + case "/ping": + // API clients are required to periodically ping the server + // The time between pings (interval) is 5 minutes? + // A ping call should refresh cookie lifetimes and + // generate and store a new auth_key + // The ping required a valid session... + // A successful ping returns a 'response' => 'pong' + // along with the new auth_key. + token_auth(); + $session_name = $_GET['session']; + $authid = $_SESSION['authid']; + $auth_key = update_authkey( $session_name, $authid ); + print json_encode( array( 'response' => 'pong', 'auth_key' => $auth_key )); + break; + case "/logout": + // De-authenticate/deauthorize the ongoing session. + // I.e. destroy session data, remove session cookies. + $session_name = ""; + if ( array_key_exists('session', $_GET ) ) + $session_name = $_GET['session']; + session_name($session_name); + session_start(); + clear_credentials($session_name); + + if ( $_SESSION ) + print json_encode ( array( 'response' => 'wtffailed?') ); + else + print json_encode ( array( 'response' => 'ok') ); + break; case "/list_users": // List valid API user-acounts. // Fail with notauthorized if current authentication // does not have write access. + // Should not return users from backend, + // but should only return users with authorization. case "/authorize_user": // Add or update a valid back-end user in authorization // if the current authentication has write access. diff --git a/api/lib/auth_base.php b/api/lib/auth_base.php index ae8a5eb..dfecae7 100644 --- a/api/lib/auth_base.php +++ b/api/lib/auth_base.php @@ -15,15 +15,13 @@ else { print json_encode( array( 'response' => 'error', 'cause' => 'config-error' ) ); exit; } /*******************************/ -function check_authkey ( $key ) +function apikey_verify( $key ) { - global $config; - if ( $key == "6327c08b70f9" ) return true; + if ( $key == "6327c08b70f9" ) return 1; 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 @@ -33,8 +31,13 @@ function new_key( ) $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); + else + { + $string .= crypt( substr(sha1(rand()), 0, $length) ); + $string = preg_replace( '/\W/', '', $string); + } } return substr( $string, 0, $length ); } @@ -49,14 +52,114 @@ function token_auth( ) { 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 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 update_authkey ( $session, $authid ) +{ + $key = substr(new_key(), 0, 8); + return $key; +} + +function check_session ( $name ) +{ + 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); + } + + // TODO: Database checks? + + // TODO: Refresh cookie + + // 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() ); + + // TODO: Stuff data to database for further checks? + // TODO: Do magic with the KEY + + return $name; +} + +function clear_credentials($name) +{ + setcookie('client_key', '', 0, get_cookie_path() ); + setcookie($name, '', 0, "/"); + + $_SESSION = array(); + session_destroy(); + return false; +} +function get_authorization() +{ + return 1; +} function can_write ( ) { - // Stub, to be called on any API nodes taht write data in the DB. + // 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 ); return true; } diff --git a/api/lib/auth_plugins/permitall.php b/api/lib/auth_plugins/permitall.php index 24a1ad4..8bcd2ba 100644 --- a/api/lib/auth_plugins/permitall.php +++ b/api/lib/auth_plugins/permitall.php @@ -33,6 +33,10 @@ function authmethod_readonly () // Fetch user geckos (basic display info) function authuser_getinfo ( $username ) { + // Obviously we are returning dummy data here. + // on a real auth method, valid returns values + // would be a $user array on success, or false + // on error. $user['name'] = "Default User"; $user['email'] = "example@example.com"; return $user;