示例#1
0
 /**
  * Find if the given member id and password is valid. If username is NULL, then the member id is used instead.
  * All authorisation, cookies, and form-logins, are passed through this function.
  * Some forums do cookie logins differently, so a Boolean is passed in to indicate whether it is a cookie login.
  *
  * @param  ?SHORT_TEXT	The member username (NULL: don't use this in the authentication - but look it up using the ID if needed)
  * @param  ?MEMBER		The member id (NULL: use member name)
  * @param  MD5				The md5-hashed password
  * @param  string			The raw password
  * @param  boolean		Whether this is a cookie login, determines how the hashed password is treated for the value passed in
  * @return array			A map of 'id' and 'error'. If 'id' is NULL, an error occurred and 'error' is set
  */
 function forum_authorise_login($username, $userid, $password_hashed, $password_raw, $cookie_login = false)
 {
     $out = array();
     $out['id'] = NULL;
     require_code('ocf_members');
     require_code('ocf_groups');
     if (!function_exists('require_lang')) {
         require_code('lang');
     }
     if (!function_exists('do_lang_tempcode')) {
         require_code('tempcode');
     }
     if (!function_exists('require_lang')) {
         return $out;
     }
     require_lang('ocf');
     require_code('mail');
     $skip_auth = false;
     if ($userid === NULL) {
         $rows = $this->connection->query('SELECT * FROM ' . $this->connection->get_table_prefix() . 'f_members WHERE ' . db_string_equal_to('m_username', $username), 1);
         if (!array_key_exists(0, $rows) && get_option('one_per_email_address') == '1') {
             $rows = $this->connection->query('SELECT * FROM ' . $this->connection->get_table_prefix() . 'f_members WHERE ' . db_string_equal_to('m_email_address', $username) . ' ORDER BY id ASC', 1);
         }
         if (array_key_exists(0, $rows)) {
             $this->MEMBER_ROWS_CACHED[$rows[0]['id']] = $rows[0];
             $userid = $rows[0]['id'];
         }
     } else {
         $rows[0] = $this->get_member_row($userid);
     }
     // LDAP to the rescue if we couldn't get a row
     global $LDAP_CONNECTION;
     if (!array_key_exists(0, $rows) && $LDAP_CONNECTION !== NULL && $userid === NULL) {
         // See if LDAP has it -- if so, we can add
         $test = ocf_is_on_ldap($username);
         if (!$test) {
             $out['error'] = is_null($username) ? do_lang_tempcode('USER_NO_EXIST') : do_lang_tempcode('_USER_NO_EXIST', escape_html($username));
             return $out;
         }
         $test_auth = ocf_ldap_authorise_login($username, $password_raw);
         if ($test_auth['m_pass_hash_salted'] == '!!!') {
             $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
             return $out;
         }
         if ($test) {
             require_code('ocf_members_action');
             require_code('ocf_members_action2');
             $completion_form_submitted = trim(post_param('email_address', '')) != '';
             if (!$completion_form_submitted && get_value('no_finish_profile') !== '1') {
                 @ob_end_clean();
                 if (!function_exists('do_header')) {
                     require_code('site');
                 }
                 $middle = ocf_member_external_linker_ask($username, 'ldap', ocf_ldap_guess_email($username));
                 $tpl = globalise($middle, NULL, '', true);
                 $tpl->evaluate_echo();
                 exit;
             } else {
                 $userid = ocf_member_external_linker($username, uniqid('', true), 'ldap');
                 $row = $this->get_member_row($userid);
             }
         }
     }
     if (!array_key_exists(0, $rows) || $rows[0] === NULL) {
         $out['error'] = is_null($username) ? do_lang_tempcode('USER_NO_EXIST') : do_lang_tempcode('_USER_NO_EXIST', escape_html($username));
         return $out;
     }
     $row = $rows[0];
     // Now LDAP can kick in and get the correct hash
     if (ocf_is_ldap_member($userid)) {
         //$rows[0]['m_pass_hash_salted']=ocf_get_ldap_hash($userid);
         // Doesn't exist any more? This is a special case - the 'LDAP member' exists in our DB, but not LDAP. It has been deleted from LDAP or LDAP server has jumped
         /*if (is_null($rows[0]['m_pass_hash_salted']))
         		{
         			$out['error']=(do_lang_tempcode('_USER_NO_EXIST',$username));
         			return $out;
         		} No longer appropriate with new authentication mode - instead we just have to give an invalid password message  */
         $row = array_merge($row, ocf_ldap_authorise_login($username, $password_hashed));
     }
     if (addon_installed('unvalidated')) {
         if ($row['m_validated'] == 0) {
             $out['error'] = do_lang_tempcode('USER_NOT_VALIDATED_STAFF');
             return $out;
         }
     }
     if ($row['m_validated_email_confirm_code'] != '') {
         $out['error'] = do_lang_tempcode('USER_NOT_VALIDATED_EMAIL');
         return $out;
     }
     if ($this->is_banned($row['id'])) {
         $out['error'] = do_lang_tempcode('USER_BANNED');
         return $out;
     }
     // Check password
     if (!$skip_auth) {
         // Choose a compatibility screen.
         // Note that almost all cookie logins are the same. This is because the cookie logins use OCF cookies, regardless of compatibility scheme.
         $password_compatibility_scheme = $row['m_password_compat_scheme'];
         switch ($password_compatibility_scheme) {
             case 'remote':
                 // This will work too - we're logging in with the username of a remote profile, so no resynching will happen
             // This will work too - we're logging in with the username of a remote profile, so no resynching will happen
             case '':
                 // ocPortal style salted MD5 algorithm
                 if ($cookie_login) {
                     if ($password_hashed !== $row['m_pass_hash_salted']) {
                         require_code('tempcode');
                         // This can be incidental even in fast AJAX scripts, if an old invalid cookie is present, so we need tempcode for do_lang_tempcode
                         $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
                         return $out;
                     }
                 } else {
                     if (md5($row['m_pass_salt'] . $password_hashed) !== $row['m_pass_hash_salted']) {
                         $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
                         return $out;
                     }
                 }
                 break;
             case 'plain':
                 if ($password_hashed !== md5($row['m_pass_hash_salted'])) {
                     $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
                     return $out;
                 }
                 break;
             case 'md5':
                 // Old style plain md5		(also works if both are unhashed: used for LDAP)
                 if ($password_hashed !== $row['m_pass_hash_salted'] && $password_hashed != '!!!') {
                     $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
                     return $out;
                 }
                 break;
                 /*		case 'httpauth':
                 				// This is handled in get_member()  */
                 break;
             case 'ldap':
                 if ($password_hashed !== $row['m_pass_hash_salted']) {
                     $out['error'] = do_lang_tempcode('USER_BAD_PASSWORD');
                     return $out;
                 }
                 break;
             default:
                 $path = get_file_base() . '/sources_custom/hooks/systems/ocf_auth/' . $password_compatibility_scheme . '.php';
                 if (!file_exists($path)) {
                     $path = get_file_base() . '/sources/hooks/systems/ocf_auth/' . $password_compatibility_scheme . '.php';
                 }
                 if (!file_exists($path)) {
                     $out['error'] = do_lang_tempcode('UNKNOWN_AUTH_SCHEME_IN_DB');
                     return $out;
                 }
                 require_code('hooks/systems/ocf_auth/' . $password_compatibility_scheme);
                 $ob = object_factory('Hook_ocf_auth_' . $password_compatibility_scheme);
                 $error = $ob->auth($username, $userid, $password_hashed, $password_raw, $cookie_login, $row);
                 if (!is_null($error)) {
                     $out['error'] = $error;
                     return $out;
                 }
                 break;
         }
     }
     // Ok, authorised basically, but we need to see if this is a valid login IP
     if (ocf_get_best_group_property($this->get_members_groups($row['id']), 'enquire_on_new_ips') == 1) {
         global $SENT_OUT_VALIDATE_NOTICE;
         $ip = get_ip_address(3);
         $test2 = $this->connection->query_value_null_ok('f_member_known_login_ips', 'i_val_code', array('i_member_id' => $row['id'], 'i_ip' => $ip));
         if ((is_null($test2) || $test2 != '') && !compare_ip_address($ip, $row['m_ip_address'])) {
             if (!$SENT_OUT_VALIDATE_NOTICE) {
                 if (!is_null($test2)) {
                     $this->connection->query_delete('f_member_known_login_ips', array('i_member_id' => $row['id'], 'i_ip' => $ip), '', 1);
                 }
                 $code = !is_null($test2) ? $test2 : uniqid('', true);
                 $this->connection->query_insert('f_member_known_login_ips', array('i_val_code' => $code, 'i_member_id' => $row['id'], 'i_ip' => $ip));
                 $url = find_script('validateip') . '?code=' . $code;
                 $url_simple = find_script('validateip');
                 require_code('comcode');
                 $mail = do_lang('IP_VERIFY_MAIL', comcode_escape($url), comcode_escape(get_ip_address()), array($url_simple, $code), get_lang($row['id']));
                 $email_address = $row['m_email_address'];
                 if ($email_address == '') {
                     $email_address = get_option('staff_address');
                 }
                 if (running_script('index')) {
                     mail_wrap(do_lang('IP_VERIFY_MAIL_SUBJECT', NULL, NULL, NULL, get_lang($row['id'])), $mail, array($email_address), $row['m_username'], '', '', 1);
                 }
                 $SENT_OUT_VALIDATE_NOTICE = true;
             }
             $out['error'] = do_lang_tempcode('REQUIRES_IP_VALIDATION');
             return $out;
         }
     }
     $this->ocf_flood_control($row['id']);
     $out['id'] = $row['id'];
     return $out;
 }
示例#2
0
/**
 * Check to see if an IP address is banned.
 *
 * @param  string			The IP address to check for banning (potentially encoded with *'s)
 * @return boolean		Whether the IP address is banned
 */
function ip_banned($ip)
{
    if (!addon_installed('securitylogging')) {
        return false;
    }
    $ip4 = strpos($ip, '.') !== false;
    if ($ip4) {
        $ip_parts = explode('.', $ip);
    } else {
        $ip_parts = explode(':', $ip);
    }
    global $SITE_INFO;
    if (isset($SITE_INFO['known_suexec']) && $SITE_INFO['known_suexec'] == '1' || is_writable_wrap(get_file_base() . '/.htaccess')) {
        $bans = array();
        $ban_count = preg_match_all('#\\ndeny from (.*)#', file_get_contents(get_file_base() . '/.htaccess'), $bans);
        $ip_bans = array();
        for ($i = 0; $i < $ban_count; $i++) {
            $ip_bans[] = array('ip' => $bans[1][$i]);
        }
    } else {
        $ip_bans = persistant_cache_get('IP_BANS');
        if (!is_array($ip_bans)) {
            $ip_bans = $GLOBALS['SITE_DB']->query('SELECT ip FROM ' . get_table_prefix() . 'usersubmitban_ip', NULL, NULL, true);
            if (!is_null($ip_bans)) {
                persistant_cache_set('IP_BANS', $ip_bans);
            }
        }
        if (is_null($ip_bans)) {
            critical_error('DATABASE_FAIL');
        }
    }
    $self_ip = NULL;
    foreach ($ip_bans as $ban) {
        if ($ip4 && compare_ip_address_ip4($ban['ip'], $ip_parts) || !$ip4 && compare_ip_address_ip6($ban['ip'], $ip_parts)) {
            if (is_null($self_ip)) {
                $self_host = ocp_srv('HTTP_HOST');
                if ($self_host == '' || preg_match('#^localhost[\\.\\:$]#', $self_host) != 0) {
                    $self_ip = '';
                } else {
                    if (preg_match('#(\\s|,|^)gethostbyname(\\s|$|,)#i', @ini_get('disable_functions')) == 0) {
                        $self_ip = gethostbyname($self_host);
                    } else {
                        $self_ip = '';
                    }
                    if ($self_ip == '') {
                        $self_ip = ocp_srv('SERVER_ADDR');
                    }
                }
            }
            if ($self_ip != '' && compare_ip_address($ban['ip'], $self_ip)) {
                continue;
            }
            if (compare_ip_address($ban['ip'], '127.0.0.1')) {
                continue;
            }
            if (compare_ip_address($ban['ip'], 'fe00:0000:0000:0000:0000:0000:0000:0000')) {
                continue;
            }
            return true;
        }
    }
    return false;
}
示例#3
0
/**
 * Ban the specified IP address.
 *
 * @param  IP				The IP address to ban
 * @param  LONG_TEXT		Explanation for ban
 */
function ban_ip($ip, $descrip = '')
{
    $ban = trim($ip);
    if ($ban != '' && !compare_ip_address($ban, get_ip_address())) {
        require_code('failure');
        add_ip_ban($ban, $descrip);
    } elseif (compare_ip_address($ban, get_ip_address())) {
        attach_message(do_lang_tempcode('AVOIDING_BANNING_SELF'), 'warn');
    }
}