cms/drupal/includes/password.inc
author ymh <ymh.work@gmail.com>
Tue, 20 Mar 2018 15:02:40 +0100
changeset 573 25f3d28f51b2
parent 541 e756a8c72c3d
permissions -rwxr-xr-x
Added tag 0.0.25 for changeset 190ae1dee68d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
541
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * @file
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * Secure password hashing functions for user authentication.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * Based on the Portable PHP password hashing framework.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * @see http://www.openwall.com/phpass/
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * An alternative or custom version of this password hashing API may be
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * used by setting the variable password_inc to the name of the PHP file
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * containing replacement user_hash_password(), user_check_password(), and
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * user_needs_new_hash() functions.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * The standard log2 number of iterations for password stretching. This should
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 * increase by 1 every Drupal version in order to counteract increases in the
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
 * speed and power of computers available to crack the hashes.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
define('DRUPAL_HASH_COUNT', 15);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
 * The minimum allowed log2 number of iterations for password stretching.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
define('DRUPAL_MIN_HASH_COUNT', 7);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
 * The maximum allowed log2 number of iterations for password stretching.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
define('DRUPAL_MAX_HASH_COUNT', 30);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
 * The expected (and maximum) number of characters in a hashed password.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
define('DRUPAL_HASH_LENGTH', 55);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
 * Returns a string for mapping an int to the corresponding base 64 character.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
function _password_itoa64() {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
  return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
 * Encodes bytes into printable base 64 using the *nix standard from crypt().
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
 * @param $input
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
 *   The string containing bytes to encode.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
 * @param $count
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
 *   The number of characters (bytes) to encode.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
 *   Encoded string
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
function _password_base64_encode($input, $count) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
  $output = '';
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
  $i = 0;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
  $itoa64 = _password_itoa64();
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
  do {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
    $value = ord($input[$i++]);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    $output .= $itoa64[$value & 0x3f];
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    if ($i < $count) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
      $value |= ord($input[$i]) << 8;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    $output .= $itoa64[($value >> 6) & 0x3f];
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
    if ($i++ >= $count) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
      break;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
    }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    if ($i < $count) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
      $value |= ord($input[$i]) << 16;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
    }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
    $output .= $itoa64[($value >> 12) & 0x3f];
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
    if ($i++ >= $count) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
      break;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
    }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
    $output .= $itoa64[($value >> 18) & 0x3f];
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
  } while ($i < $count);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
  return $output;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
 * Generates a random base 64-encoded salt prefixed with settings for the hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
 * Proper use of salts may defeat a number of attacks, including:
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
 *  - The ability to try candidate passwords against multiple hashes at once.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
 *  - The ability to use pre-hashed lists of candidate passwords.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
 *  - The ability to determine whether two users have the same (or different)
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
 *    password without actually having to guess one of the passwords.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
 * @param $count_log2
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
 *   Integer that determines the number of iterations used in the hashing
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
 *   process. A larger value is more secure, but takes more time to complete.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
 *   A 12 character string containing the iteration count and a random salt.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
function _password_generate_salt($count_log2) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
  $output = '$S$';
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
  // Ensure that $count_log2 is within set bounds.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
  $count_log2 = _password_enforce_log2_boundaries($count_log2);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
  // We encode the final log2 iteration count in base 64.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
  $itoa64 = _password_itoa64();
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
  $output .= $itoa64[$count_log2];
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
  // 6 bytes is the standard salt for a portable phpass hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
  $output .= _password_base64_encode(drupal_random_bytes(6), 6);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
  return $output;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
 * Ensures that $count_log2 is within set bounds.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
 * @param $count_log2
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
 *   Integer that determines the number of iterations used in the hashing
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
 *   process. A larger value is more secure, but takes more time to complete.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
 *   Integer within set bounds that is closest to $count_log2.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
function _password_enforce_log2_boundaries($count_log2) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
  if ($count_log2 < DRUPAL_MIN_HASH_COUNT) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
    return DRUPAL_MIN_HASH_COUNT;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
  elseif ($count_log2 > DRUPAL_MAX_HASH_COUNT) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
    return DRUPAL_MAX_HASH_COUNT;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
  return (int) $count_log2;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
 * Hash a password using a secure stretched hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
 * By using a salt and repeated hashing the password is "stretched". Its
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
 * security is increased because it becomes much more computationally costly
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
 * for an attacker to try to break the hash by brute-force computation of the
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
 * hashes of a large number of plain-text words or strings to find a match.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
 * @param $algo
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
 *   The string name of a hashing algorithm usable by hash(), like 'sha256'.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
 * @param $password
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
 *   Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
 * @param $setting
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
 *   An existing hash or the output of _password_generate_salt().  Must be
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
 *   at least 12 characters (the settings and salt).
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
 *   A string containing the hashed password (and salt) or FALSE on failure.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
 *   The return string will be truncated at DRUPAL_HASH_LENGTH characters max.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
function _password_crypt($algo, $password, $setting) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
  // Prevent DoS attacks by refusing to hash large passwords.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
  if (strlen($password) > 512) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
    return FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
  // The first 12 characters of an existing hash are its setting string.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
  $setting = substr($setting, 0, 12);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
  if ($setting[0] != '$' || $setting[2] != '$') {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
    return FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
  $count_log2 = _password_get_count_log2($setting);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
  // Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
  if ($count_log2 < DRUPAL_MIN_HASH_COUNT || $count_log2 > DRUPAL_MAX_HASH_COUNT) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
    return FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
  $salt = substr($setting, 4, 8);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
  // Hashes must have an 8 character salt.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
  if (strlen($salt) != 8) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
    return FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
  // Convert the base 2 logarithm into an integer.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
  $count = 1 << $count_log2;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
  // We rely on the hash() function being available in PHP 5.2+.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
  $hash = hash($algo, $salt . $password, TRUE);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
  do {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
    $hash = hash($algo, $hash . $password, TRUE);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
  } while (--$count);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
  $len = strlen($hash);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
  $output =  $setting . _password_base64_encode($hash, $len);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
  // _password_base64_encode() of a 16 byte MD5 will always be 22 characters.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
  // _password_base64_encode() of a 64 byte sha512 will always be 86 characters.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
  $expected = 12 + ceil((8 * $len) / 6);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
  return (strlen($output) == $expected) ? substr($output, 0, DRUPAL_HASH_LENGTH) : FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
 * Parse the log2 iteration count from a stored hash or setting string.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
function _password_get_count_log2($setting) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
  $itoa64 = _password_itoa64();
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
  return strpos($itoa64, $setting[3]);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
 * Hash a password using a secure hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
 * @param $password
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
 *   A plain-text password.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
 * @param $count_log2
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
 *   Optional integer to specify the iteration count. Generally used only during
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
 *   mass operations where a value less than the default is needed for speed.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
 *   A string containing the hashed password (and a salt), or FALSE on failure.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
function user_hash_password($password, $count_log2 = 0) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
  if (empty($count_log2)) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
    // Use the standard iteration count.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
    $count_log2 = variable_get('password_count_log2', DRUPAL_HASH_COUNT);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
  return _password_crypt('sha512', $password, _password_generate_salt($count_log2));
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
 * Check whether a plain text password matches a stored hashed password.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
 * Alternative implementations of this function may use other data in the
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
 * $account object, for example the uid to look up the hash in a custom table
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
 * or remote database.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
 * @param $password
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
 *   A plain-text password
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
 * @param $account
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
 *   A user object with at least the fields from the {users} table.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
 *   TRUE or FALSE.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
function user_check_password($password, $account) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
  if (substr($account->pass, 0, 2) == 'U$') {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
    // This may be an updated password from user_update_7000(). Such hashes
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
    // have 'U' added as the first character and need an extra md5().
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
    $stored_hash = substr($account->pass, 1);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
    $password = md5($password);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
  else {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
    $stored_hash = $account->pass;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
  $type = substr($stored_hash, 0, 3);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
  switch ($type) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
    case '$S$':
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
      // A normal Drupal 7 password using sha512.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
      $hash = _password_crypt('sha512', $password, $stored_hash);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
      break;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
    case '$H$':
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
      // phpBB3 uses "$H$" for the same thing as "$P$".
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
    case '$P$':
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
      // A phpass password generated using md5.  This is an
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
      // imported password or from an earlier Drupal version.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
      $hash = _password_crypt('md5', $password, $stored_hash);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
      break;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
    default:
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
      return FALSE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
  return ($hash && $stored_hash == $hash);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
}
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
/**
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
 * Check whether a user's hashed password needs to be replaced with a new hash.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
 * This is typically called during the login process when the plain text
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
 * password is available. A new hash is needed when the desired iteration count
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
 * has changed through a change in the variable password_count_log2 or
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
 * DRUPAL_HASH_COUNT or if the user's password hash was generated in an update
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
 * like user_update_7000().
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
 * Alternative implementations of this function might use other criteria based
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
 * on the fields in $account.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
 * @param $account
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
 *   A user object with at least the fields from the {users} table.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
 *
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
 * @return
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
 *   TRUE or FALSE.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
 */
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
function user_needs_new_hash($account) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
  // Check whether this was an updated password.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
  if ((substr($account->pass, 0, 3) != '$S$') || (strlen($account->pass) != DRUPAL_HASH_LENGTH)) {
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
    return TRUE;
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
  }
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
  // Ensure that $count_log2 is within set bounds.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
  $count_log2 = _password_enforce_log2_boundaries(variable_get('password_count_log2', DRUPAL_HASH_COUNT));
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
  // Check whether the iteration count used differs from the standard number.
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
  return (_password_get_count_log2($account->pass) !== $count_log2);
e756a8c72c3d integrate drupal and correct build process. update version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
}