diff --git a/core/authentication_api.php b/core/authentication_api.php index 7293041e39..018ea2cdf7 100644 --- a/core/authentication_api.php +++ b/core/authentication_api.php @@ -43,6 +43,8 @@ * @uses utility_api.php */ +use Mantis\Exceptions\ClientException; + require_api( 'access_api.php' ); require_api( 'config_api.php' ); require_api( 'constant_inc.php' ); @@ -76,10 +78,12 @@ /** * Gets set of flags for authentication for the specified user. - * @param int|null|bool $p_user_id The user id or null for logged in user or NO_USER/false for user that doesn't exist - * in the system, that may be auto-provisioned. - * @param string $p_username The username or email + * @param int|null|bool $p_user_id The user id or null for logged in user or + * NO_USER/false for user that doesn't exist + * in the system, that may be auto-provisioned. + * @param string $p_username The username or email * @return AuthFlags The auth flags object to use. + * @throws ClientException */ function auth_flags( $p_user_id = null, $p_username = '' ) { if( !$p_user_id ) { @@ -138,6 +142,7 @@ function auth_flags( $p_user_id = null, $p_username = '' ) { /** * The message to show to indicate to user that password is managed elsewhere. * @return string The message. + * @throws ClientException */ function auth_password_managed_elsewhere_message() { $t_auth_flags = auth_flags(); @@ -146,9 +151,10 @@ function auth_password_managed_elsewhere_message() { /** * Check if permanent login is enabled. - * @param int|bool $p_user_id The user id, or NO_USER/false for unknown user. - * @param string $p_username The username user typed in sign-in form. + * @param int|bool $p_user_id The user id, or NO_USER/false for unknown user. + * @param string $p_username The username user typed in sign-in form. * @return boolean true: yes, false: otherwise. + * @throws ClientException */ function auth_allow_perm_login( $p_user_id, $p_username ) { $t_auth_flags = auth_flags( $p_user_id, $p_username ); @@ -189,9 +195,10 @@ function auth_anonymous_account() { /** * Get the auth cookie expiry time. - * @param integer $p_user_id The user id to get session expiry for. + * @param integer $p_user_id The user id to get session expiry for. * @param boolean $p_perm_login Use permanent login. * @return integer cookie lifetime or 0 for browser session. + * @throws ClientException */ function auth_session_expiry( $p_user_id, $p_perm_login ) { $t_auth_flags = auth_flags( $p_user_id ); @@ -210,9 +217,11 @@ function auth_session_expiry( $p_user_id, $p_perm_login ) { } /** - * Gets the login page to redirect to when login is needed, it will return a relative url. + * Gets the login page to redirect to when login is needed, it will return a + * relative url. * @param string $p_query_string query string parameters. * @return string login page (e.g. 'login_page.php' ) + * @throws ClientException */ function auth_login_page( $p_query_string = '' ) { $t_auth_flags = auth_flags(); @@ -222,12 +231,14 @@ function auth_login_page( $p_query_string = '' ) { } /** - * Gets the page that asks the user for credentials based on the user's authentication model. + * Gets the page that asks the user for credentials based on the user's + * authentication model. * - * @param string $p_query_string The query string, can be empty. - * @param int|null $p_user_id The user id or null for current logged in user. - * @param string $p_username The username + * @param string $p_query_string The query string, can be empty. + * @param int|null $p_user_id The user id or null for current logged in user. + * @param string $p_username The username * @return string The credentials page with query string. + * @throws ClientException */ function auth_credential_page( $p_query_string, $p_user_id = null, $p_username = '' ) { $t_auth_flags = auth_flags( $p_user_id, $p_username ); @@ -235,8 +246,10 @@ function auth_credential_page( $p_query_string, $p_user_id = null, $p_username = } /** - * Gets the logout page to redirect to for logging out the user, it will return a relative url + * Gets the logout page to redirect to for logging out the user, it will return + * a relative url * @return string logout page (e.g. 'logout_page.php' ) + * @throws ClientException */ function auth_logout_page() { $t_auth_flags = auth_flags(); @@ -246,6 +259,7 @@ function auth_logout_page() { /** * Gets the page to redirect to after logout. * @return string the logout redirect page. + * @throws ClientException */ function auth_logout_redirect_page() { $t_auth_flags = auth_flags(); @@ -256,6 +270,7 @@ function auth_logout_redirect_page() { * Checks if specified user can set their own password. * @param integer|null $p_user_id The user id or null for logged in user or 0 for signup scenarios. * @return bool true: can set password, false: otherwise. + * @throws ClientException */ function auth_can_set_password( $p_user_id = null ) { $t_auth_flags = auth_flags( $p_user_id ); @@ -270,7 +285,8 @@ function auth_can_set_password( $p_user_id = null ) { /** * Checks if specified user can use standard login (e.g. username and password). * @param integer|null $p_user_id The user id or null for logged in user. - * @return bool true: can login using username and passord, false otherwise. + * @return bool true: can login using username and password, false otherwise. + * @throws ClientException */ function auth_can_use_standard_login( $p_user_id = null ) { $t_auth_flags = auth_flags( $p_user_id ); @@ -286,6 +302,7 @@ function auth_can_use_standard_login( $p_user_id = null ) { * @param string $p_return_page Page to redirect to following successful logon, defaults to current page. * @access public * @return void + * @throws ClientException */ function auth_ensure_user_authenticated( $p_return_page = '' ) { # if logged in @@ -313,6 +330,7 @@ function auth_ensure_user_authenticated( $p_return_page = '' ) { * * @return boolean * @access public + * @throws ClientException */ function auth_is_user_authenticated() { global $g_cache_cookie_valid, $g_login_anonymous; @@ -369,6 +387,7 @@ function auth_prepare_username( $p_username ) { * @access public */ function auth_prepare_password( $p_password ) { + $f_password = $p_password; switch( config_get_global( 'login_method' ) ) { case BASIC_AUTH: $f_password = $_SERVER['PHP_AUTH_PW']; @@ -388,9 +407,6 @@ function auth_prepare_password( $p_password ) { return null; } break; - default: - $f_password = $p_password; - break; } return $f_password; } @@ -400,10 +416,12 @@ function auth_prepare_password( $p_password ) { * Check if the authentication provider supports auto-creation of users and * whether the password matches. * - * @param string $p_username A prepared username. - * @param string $p_password A prepared password. + * @param string $p_username A prepared username. + * @param string $p_password A prepared password. * @return int|boolean user id or false in case of failure. * @access private + * + * @throws ClientException */ function auth_auto_create_user( $p_username, $p_password ) { $t_login_method = config_get_global( 'login_method' ); @@ -439,16 +457,19 @@ function auth_auto_create_user( $p_username, $p_password ) { * * @param string $p_login_name The login name. * @return integer|boolean user id or false. + * + * @throws ClientException */ function auth_get_user_id_from_login_name( $p_login_name ) { $t_user_id = user_get_id_by_name( $p_login_name ); # If user is not found by name, check by email as long as there is only # a single match. - if( $t_user_id === false && - !is_blank( $p_login_name ) && - config_get_global( 'email_login_enabled' ) && - email_is_valid( $p_login_name ) ) { + if( $t_user_id === false + && !is_blank( $p_login_name ) + && config_get_global( 'email_login_enabled' ) + && email_is_valid( $p_login_name ) + ) { $t_user_ids_by_email = user_get_enabled_ids_by_email( $p_login_name ); if ( count( $t_user_ids_by_email ) == 1 ) { $t_user_id = $t_user_ids_by_email[0]; @@ -469,6 +490,8 @@ function auth_get_user_id_from_login_name( $p_login_name ) { * @param boolean $p_perm_login Whether to create a long-term cookie. * @return boolean indicates if authentication was successful * @access public + * + * @throws ClientException */ function auth_attempt_login( $p_username, $p_password, $p_perm_login = false ) { $t_user_id = auth_get_user_id_from_login_name( $p_username ); @@ -498,10 +521,14 @@ function auth_attempt_login( $p_username, $p_password, $p_perm_login = false ) { } /** - * Login the user with the specified id, if enabled. This is typically used by auth plugins. - * @param integer $p_user_id The user id. + * Login the user with the specified id, if enabled. + * + * This is typically used by auth plugins. + * + * @param integer $p_user_id The user id. * @param boolean $p_perm_login Whether to create a long-term cookie. * @return bool true: success; false; otherwise. + * @throws ClientException */ function auth_login_user( $p_user_id, $p_perm_login = false ) { # check for disabled account @@ -528,19 +555,21 @@ function auth_login_user( $p_user_id, $p_perm_login = false ) { * * @param int $p_user_id The user id. * @return void + * @throws ClientException */ function auth_impersonate( $p_user_id ) { auth_ensure_can_impersonate( $p_user_id ); - auth_set_cookies( $p_user_id, /* perm_login */ false ); + auth_set_cookies( $p_user_id ); auth_set_tokens( $p_user_id ); } /** * Check whether the logged in user can impersonate the specified user. * - * @param int $p_user_id The user id to be impersonated. + * @param int $p_user_id The user id to be impersonated. * @return bool true: can impersonate, false: can't. + * @throws ClientException */ function auth_can_impersonate( $p_user_id ) { if( !access_has_global_level( config_get_global( 'impersonate_user_threshold' ) ) ) { @@ -563,8 +592,9 @@ function auth_can_impersonate( $p_user_id ) { * Ensure that the logged in user can impersonate the specified user. If not, * then an error page will be generated. * - * @param int $p_user_id The user id to be impersonated. + * @param int $p_user_id The user id to be impersonated. * @return void. + * @throws ClientException */ function auth_ensure_can_impersonate( $p_user_id ) { if( !auth_can_impersonate( $p_user_id ) ) { @@ -579,14 +609,16 @@ function auth_ensure_can_impersonate( $p_user_id ) { * - Anonymous login (blank username supplied). * - Anonymous login with anonymous user name specified. * - Anonymous login with account not existing or disabled. - * - Pre-authenticated user via some secret hash from email verify or rss feed, where username - * is specified but password is null. + * - Pre-authenticated user via some secret hash from email verify or rss feed, + * where username is specified but password is null. * - Standard authentication with username and password specified. * * @param string $p_username Username. * @param string $p_password Password. * @return boolean indicates if authentication was successful * @access public + * + * @throws ClientException */ function auth_attempt_script_login( $p_username, $p_password = null ) { global $g_script_login_cookie; @@ -654,6 +686,7 @@ function auth_attempt_script_login( $p_username, $p_password = null ) { * Returns true on success, false otherwise * @access public * @return void + * @throws ClientException */ function auth_logout() { global $g_cache_current_user_id, $g_cache_cookie_valid; @@ -685,8 +718,8 @@ function auth_logout() { } /** - * Identicates whether to bypass logon form e.g. when using http authentication - * @return boolean true: by pass, false: show form. + * Indicates whether to bypass logon form e.g. when using http authentication + * @return boolean true: bypass, false: show form. * @access public */ function auth_automatic_logon_bypass_form() { @@ -720,6 +753,7 @@ function auth_get_password_max_size() { * @param string $p_test_password Password. * @return boolean indicating whether password matches given the user id * @access public + * @throws ClientException */ function auth_does_password_match( $p_user_id, $p_test_password ) { $t_configured_login_method = config_get_global( 'login_method' ); @@ -830,9 +864,8 @@ function auth_generate_confirm_hash( $p_user_id ) { # Note: We truncate the last 8 bits from the hash output so that base64 # encoding can be performed without any trailing padding. $t_confirm_hash_base64_encoded = base64_encode( substr( $t_confirm_hash_raw, 0, 63 ) ); - $t_confirm_hash = strtr( $t_confirm_hash_base64_encoded, '+/', '-_' ); - return $t_confirm_hash; + return strtr( $t_confirm_hash_base64_encoded, '+/', '-_' ); } /** @@ -842,6 +875,7 @@ function auth_generate_confirm_hash( $p_user_id ) { * @param boolean $p_perm_login Indicates whether to generate a long-term cookie. * @access public * @return void + * @throws ClientException */ function auth_set_cookies( $p_user_id, $p_perm_login = false ) { $t_cookie_string = user_get_field( $p_user_id, 'cookie_string' ); @@ -874,10 +908,14 @@ function auth_clear_cookies() { } /** - * Generate a random and unique string to use as the identifier for the login - * cookie. - * @return string Random and unique 384bit cookie string of encoded according to the base64 with URI safe alphabet approach described in RFC4648 + * Generate a unique random identifier for the login cookie. + * + * The generated string is base64-encoded with the URI-safe alphabet + * approach described in RFC4648. + * + * @return string Random and unique 384bit cookie string. * @access public + * @throws ClientException */ function auth_generate_unique_cookie_string() { do { @@ -888,10 +926,13 @@ function auth_generate_unique_cookie_string() { } /** - * Return true if the cookie login identifier is unique, false otherwise + * Determine whether a cookie string is unique. + * * @param string $p_cookie_string Cookie string. - * @return boolean indicating whether cookie string is unique + * @return bool True if the cookie string is unique, false otherwise. * @access public + * + * @throws ClientException */ function auth_is_cookie_string_unique( $p_cookie_string ) { db_param_push(); @@ -908,14 +949,15 @@ function auth_is_cookie_string_unique( $p_cookie_string ) { } /** - * Return the current user login cookie string, - * note that the cookie cached by a script login superceeds the cookie provided by - * the browser. This shouldn't normally matter, except that the password verification uses - * this routine to bypass the normal authentication, and can get confused when a normal user - * logs in, then runs the verify script. the act of fetching config variables may get the wrong - * userid. - * if no user is logged in and anonymous login is enabled, returns cookie for anonymous user - * otherwise returns '' (an empty string) + * Return the current user's login cookie string. + * + * Note that the cookie cached by a script login supersedes the cookie provided + * by the browser. This shouldn't normally matter, except that the password + * verification uses this routine to bypass the normal authentication, and can + * get confused when a normal user logs in, then runs the verify script. + * The act of fetching config variables may get the wrong userid. + * If no user is logged in and anonymous login is enabled, returns cookie for + * anonymous user, otherwise returns '' (an empty string) * * @param boolean $p_login_anonymous Auto-login anonymous user. * @return string current user login cookie string @@ -939,13 +981,9 @@ function auth_get_current_user_cookie( $p_login_anonymous = true ) { if( $g_cache_anonymous_user_cookie_string === null ) { if( function_exists( 'db_is_connected' ) && db_is_connected() ) { # get anonymous information if database is available - db_param_push(); - $t_query = 'SELECT id, cookie_string FROM {user} WHERE username = ' . db_param(); - $t_result = db_query( $t_query, array( auth_anonymous_account() ) ); - - if( $t_row = db_fetch_array( $t_result ) ) { + $t_row = user_get_row_by_name( auth_anonymous_account() ); + if( $t_row ) { $t_cookie = $t_row['cookie_string']; - $g_cache_anonymous_user_cookie_string = $t_cookie; current_user_set( $t_row['id'] ); } @@ -964,6 +1002,7 @@ function auth_get_current_user_cookie( $p_login_anonymous = true ) { * @param integer $p_user_id User identifier. * @access public * @return void + * @throws ClientException */ function auth_set_tokens( $p_user_id ) { $t_auth_token = token_get( TOKEN_AUTHENTICATED, $p_user_id ); @@ -977,6 +1016,7 @@ function auth_set_tokens( $p_user_id ) { /** * Checks if reauthentication is enabled. * @return bool true: enabled; false: otherwise. + * @throws ClientException */ function auth_reauthentication_enabled() { $t_auth_flags = auth_flags(); @@ -986,6 +1026,7 @@ function auth_reauthentication_enabled() { /** * Gets the reauthentication timeout/expiry. * @return integer The re-authentication expiry in seconds. + * @throws ClientException */ function auth_reauthentication_expiry() { $t_auth_flags = auth_flags(); @@ -993,15 +1034,18 @@ function auth_reauthentication_expiry() { } /** - * Check for authentication tokens, and redirect to login page for re-authentication. - * Currently, if using BASIC or HTTP authentication methods, or if logged in anonymously, - * this function will always "authenticate" the user (do nothing). + * Check for authentication tokens, and redirect to login page for + * re-authentication. Currently, if using BASIC or HTTP authentication methods, + * or if logged in anonymously, this function will always "authenticate" the + * user (do nothing). * * @return boolean * @access public + * @throws ClientException */ function auth_reauthenticate() { - if( !auth_reauthentication_enabled() || BASIC_AUTH == config_get_global( 'login_method' ) || HTTP_AUTH == config_get_global( 'login_method' ) ) { + $t_login_method = config_get_global( 'login_method' ); + if( !auth_reauthentication_enabled() || BASIC_AUTH == $t_login_method || HTTP_AUTH == $t_login_method ) { return true; } @@ -1021,27 +1065,25 @@ function auth_reauthenticate() { return true; } - $t_request_uri = string_url( $_SERVER['REQUEST_URI'] ); - - $t_query_params = http_build_query( - array( - 'reauthenticate' => 1, - 'username' => $t_username, - 'return' => $t_request_uri, - ), - '', '&' - ); + $t_query_params = http_build_query( array( + 'reauthenticate' => 1, + 'username' => $t_username, + 'return' => string_url( $_SERVER['REQUEST_URI'] ), + ) ); # redirect to login page - print_header_redirect( auth_credential_page( $t_query_params ) ); + return print_header_redirect( auth_credential_page( $t_query_params ) ); } } /** - * is cookie valid? + * Determines if the cookie string is valid. + * * @param string $p_cookie_string Cookie string. - * @return boolean + * @return bool True if valid, false otherwise. * @access public + * + * @throws ClientException */ function auth_is_cookie_valid( $p_cookie_string ) { global $g_cache_current_user_id; @@ -1080,9 +1122,12 @@ function auth_is_cookie_valid( $p_cookie_string ) { } /** - * Retrieve user id of current user + * Retrieve current user's Id. + * * @return integer user id * @access public + * + * @throws ClientException */ function auth_get_current_user_id() { global $g_cache_current_user_id; @@ -1123,13 +1168,14 @@ function auth_get_current_user_id() { * A method that looks up a user id given their cookie. * * @param string $p_cookie_string The cookie string to lookup - * @return bool|int The user id or false if not user match found. + * @return bool|int The user id or false if no user match found. * @access public + * + * @throws ClientException */ function auth_user_id_from_cookie( $p_cookie_string ) { if( $t_result = user_search_cache( 'cookie_string', $p_cookie_string ) ) { - $t_user_id = (int)$t_result['id']; - return $t_user_id; + return (int)$t_result['id']; } db_param_push(); @@ -1169,7 +1215,7 @@ function auth_http_set_logout_pending( $p_pending ) { $t_cookie_name = config_get_global( 'logout_cookie' ); if( $p_pending ) { - gpc_set_cookie( $t_cookie_name, '1', false ); + gpc_set_cookie( $t_cookie_name, '1' ); } else { $t_cookie_path = config_get_global( 'cookie_path' ); gpc_clear_cookie( $t_cookie_name, $t_cookie_path );