Example #1
2
/**
 * API Login via basic-auth or OAuth
 */
function api_login(&$a)
{
    $record = null;
    require_once 'include/oauth.php';
    // login with oauth
    try {
        $oauth = new ZotOAuth1();
        $req = OAuth1Request::from_request();
        list($consumer, $token) = $oauth->verify_request($req);
        if (!is_null($token)) {
            $oauth->loginUser($token->uid);
            App::set_oauth_key($consumer->key);
            call_hooks('logged_in', App::$user);
            return;
        }
        killme();
    } catch (Exception $e) {
        logger($e->getMessage());
    }
    // workarounds for HTTP-auth in CGI mode
    if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
        $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6));
        if (strlen($userpass)) {
            list($name, $password) = explode(':', $userpass);
            $_SERVER['PHP_AUTH_USER'] = $name;
            $_SERVER['PHP_AUTH_PW'] = $password;
        }
    }
    if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
        $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6));
        if (strlen($userpass)) {
            list($name, $password) = explode(':', $userpass);
            $_SERVER['PHP_AUTH_USER'] = $name;
            $_SERVER['PHP_AUTH_PW'] = $password;
        }
    }
    require_once 'include/auth.php';
    require_once 'include/security.php';
    // process normal login request
    if (isset($_SERVER['PHP_AUTH_USER'])) {
        $channel_login = 0;
        $record = account_verify_password($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
        if ($record && $record['channel']) {
            $channel_login = $record['channel']['channel_id'];
        }
    }
    if ($record['account']) {
        authenticate_success($record['account']);
        if ($channel_login) {
            change_channel($channel_login);
        }
        $_SESSION['allow_api'] = true;
        return true;
    } else {
        $_SERVER['PHP_AUTH_PW'] = '*****';
        logger('API_login failure: ' . print_r($_SERVER, true), LOGGER_DEBUG);
        log_failed_login('API login failure');
        retry_basic_auth();
    }
}
Example #2
0
/**
 * @brief Verify login credentials.
 *
 * If system <i>authlog</i> is set a log entry will be added for failed login
 * attempts.
 *
 * @param string $email
 *  The email address to verify.
 * @param string $pass
 *  The provided password to verify.
 * @return array|null
 *  Returns account record on success, null on failure.
 */
function account_verify_password($email, $pass)
{
    $email_verify = get_config('system', 'verify_email');
    $register_policy = get_config('system', 'register_policy');
    // Currently we only verify email address if there is an open registration policy.
    // This isn't because of any policy - it's because the workflow gets too complicated if
    // you have to verify the email and then go through the account approval workflow before
    // letting them login.
    if ($email_verify && $register_policy == REGISTER_OPEN && $record['account_flags'] & ACCOUNT_UNVERIFIED) {
        return null;
    }
    $r = q("select * from account where account_email = '%s'", dbesc($email));
    if (!($r && count($r))) {
        return null;
    }
    foreach ($r as $record) {
        if ($record['account_flags'] == ACCOUNT_OK && hash('whirlpool', $record['account_salt'] . $pass) === $record['account_password']) {
            logger('password verified for ' . $email);
            return $record;
        }
    }
    $error = 'password failed for ' . $email;
    logger($error);
    if ($record['account_flags'] & ACCOUNT_UNVERIFIED) {
        logger('Account is unverified. account_flags = ' . $record['account_flags']);
    }
    if ($record['account_flags'] & ACCOUNT_BLOCKED) {
        logger('Account is blocked. account_flags = ' . $record['account_flags']);
    }
    if ($record['account_flags'] & ACCOUNT_EXPIRED) {
        logger('Account is expired. account_flags = ' . $record['account_flags']);
    }
    if ($record['account_flags'] & ACCOUNT_REMOVED) {
        logger('Account is removed. account_flags = ' . $record['account_flags']);
    }
    if ($record['account_flags'] & ACCOUNT_PENDING) {
        logger('Account is pending. account_flags = ' . $record['account_flags']);
    }
    log_failed_login($error);
    return null;
}
Example #3
0
/**
 * @brief Verify login credentials.
 *
 * If system.authlog is set a log entry will be added for failed login
 * attempts.
 *
 * @param string $login
 *  The login to verify (channel address, account email or guest login token).
 * @param string $pass
 *  The provided password to verify.
 * @return array|null
 *  Returns account record on success, null on failure.
 *  The return array is dependent on the login mechanism.
 *    $ret['account'] will be set if either an email or channel address validation was successful (local login).
 *    $ret['channel'] will be set if a channel address validation was successful.
 *    $ret['xchan'] will be set if a guest access token validation was successful. 
 *   Keys will exist for invalid return arrays but will be set to null. 
 *   This function does not perform a login. It merely validates systems passwords and tokens.  
 *
 */
function account_verify_password($login, $pass)
{
    $ret = ['account' => null, 'channel' => null, 'xchan' => null];
    $email_verify = get_config('system', 'verify_email');
    $register_policy = get_config('system', 'register_policy');
    if (!$login) {
        return null;
    }
    $account = null;
    $channel = null;
    $xchan = null;
    if (!strpos($login, '@')) {
        $channel = channelx_by_nick($login);
        if (!$channel) {
            $x = q("select * from atoken where atoken_name = '%s' and atoken_token = '%s' limit 1", dbesc($login), dbesc($pass));
            if ($x) {
                $ret['xchan'] = atoken_xchan($x[0]);
                atoken_create_xchan($ret['xchan']);
                return $ret;
            }
        }
    }
    if ($channel) {
        $where = " where account_id = " . intval($channel['channel_account_id']) . " ";
    } else {
        $where = " where account_email = '" . dbesc($login) . "' ";
    }
    $a = q("select * from account {$where}");
    if (!$a) {
        return null;
    }
    $account = $a[0];
    // Currently we only verify email address if there is an open registration policy.
    // This isn't because of any policy - it's because the workflow gets too complicated if
    // you have to verify the email and then go through the account approval workflow before
    // letting them login.
    if ($email_verify && $register_policy == REGISTER_OPEN && $account['account_flags'] & ACCOUNT_UNVERIFIED) {
        logger('email verification required for ' . $login);
        return null;
    }
    if ($account['account_flags'] == ACCOUNT_OK && hash('whirlpool', $account['account_salt'] . $pass) === $account['account_password']) {
        logger('password verified for ' . $login);
        $ret['account'] = $account;
        if ($channel) {
            $ret['channel'] = $channel;
        }
        return $ret;
    }
    $error = 'password failed for ' . $login;
    logger($error);
    if ($account['account_flags'] & ACCOUNT_UNVERIFIED) {
        logger('Account is unverified. account_flags = ' . $account['account_flags']);
    }
    if ($account['account_flags'] & ACCOUNT_BLOCKED) {
        logger('Account is blocked. account_flags = ' . $account['account_flags']);
    }
    if ($account['account_flags'] & ACCOUNT_EXPIRED) {
        logger('Account is expired. account_flags = ' . $account['account_flags']);
    }
    if ($account['account_flags'] & ACCOUNT_REMOVED) {
        logger('Account is removed. account_flags = ' . $account['account_flags']);
    }
    if ($account['account_flags'] & ACCOUNT_PENDING) {
        logger('Account is pending. account_flags = ' . $account['account_flags']);
    }
    log_failed_login($error);
    return null;
}
Example #4
0
 /**
  * @brief Validates a username and password.
  *
  * Guest access is granted with the password "+++".
  *
  * @see \Sabre\DAV\Auth\Backend\AbstractBasic::validateUserPass
  * @param string $username
  * @param string $password
  * @return bool
  */
 protected function validateUserPass($username, $password)
 {
     require_once 'include/auth.php';
     $record = account_verify_password($username, $password);
     if ($record && $record['account_default_channel']) {
         $r = q("SELECT * FROM channel WHERE channel_account_id = %d AND channel_id = %d LIMIT 1", intval($record['account_id']), intval($record['account_default_channel']));
         if ($r) {
             return $this->setAuthenticated($r[0]);
         }
     }
     $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1", dbesc($username));
     if ($r) {
         $x = q("SELECT account_flags, account_salt, account_password FROM account WHERE account_id = %d LIMIT 1", intval($r[0]['channel_account_id']));
         if ($x) {
             // @fixme this foreach should not be needed?
             foreach ($x as $record) {
                 if (($record['account_flags'] == ACCOUNT_OK || $record['account_flags'] == ACCOUNT_UNVERIFIED) && hash('whirlpool', $record['account_salt'] . $password) === $record['account_password']) {
                     logger('password verified for ' . $username);
                     return $this->setAuthenticated($r[0]);
                 }
             }
         }
     }
     $error = 'password failed for ' . $username;
     logger($error);
     log_failed_login($error);
     return false;
 }
Example #5
0
 /**
  * @brief Validates a username and password.
  *
  *
  * @see \Sabre\DAV\Auth\Backend\AbstractBasic::validateUserPass
  * @param string $username
  * @param string $password
  * @return bool
  */
 protected function validateUserPass($username, $password)
 {
     require_once 'include/auth.php';
     $record = account_verify_password($username, $password);
     if ($record && $record['account']) {
         if ($record['channel']) {
             $channel = $record['channel'];
         } else {
             $r = q("SELECT * FROM channel WHERE channel_account_id = %d AND channel_id = %d LIMIT 1", intval($record['account']['account_id']), intval($record['account']['account_default_channel']));
             if ($r) {
                 $channel = $r[0];
             }
         }
     }
     if ($channel && $this->check_module_access($channel['channel_id'])) {
         return $this->setAuthenticated($channel);
     }
     if ($this->module_disabled) {
         $error = 'module not enabled for ' . $username;
     } else {
         $error = 'password failed for ' . $username;
     }
     logger($error);
     log_failed_login($error);
     return false;
 }