1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
require 'al-test-utils'
class TestUserPassword < Test::Unit::TestCase
priority :must
priority :normal
def test_valid?
{
"{CRYPT}.yNLaKqtwQbnY" => 'wibble', #CRYPT
"{MD5}DRB9CfW75Ayt495ccenptw==" => 'letmein', #MD5
"{SMD5}8L2iXJuazftLVHrAf7ptPFQIDaw=" => 'letmein', #SMD5 as generated by slappasswd (4 bytes of salt)
"{SMD5}kXibTNG+O98gaQtkugYcmSTiE+M2Z5TA" => 'letmein', #SMD5 as generated by Apache Directory Studio (8 bytes of salt)
"{SMD5}4PkkYH5qI6ydk/9pwvZD3DYwYzVlMzVlLTBkZDEtNGJhMi05NjI5LWRlODgyMDhiMWZmYQ==" => 'letmein', #SMD5 generated with 36 bytes of salt
"{SHA}t6h1/B6iKLkGEEG3zsS9PFKrPOM=" => 'letmein', #SHA
"{SSHA}YA87hc9/L/cCGR1HValcJb7a8AYxZXY4" => 'wibble', # SSHA as generated by slappasswd (4 bytes of salt)
"{SSHA}6J6Ios3l1panY9sm0+g9l3/jFz2kwOPrVA4+OA==" => 'letmein', # SSHA as generated by Apache Directory Studio (8 bytes of salt)
"{SSHA}f/j1unqoJg1C1zjw8tvxSp4xpow2MGM1ZTM1ZS0wZGQxLTRiYTItOTYyOS1kZTg4MjA4YjFmZmE=" => 'letmein', #SSHA generated with 36 bytes of salt
"letmein" => 'letmein', #Cleartext password
}.each do |hash, plain|
assert_send([ActiveLdap::UserPassword, :valid?,
plain, hash])
assert_not_send([ActiveLdap::UserPassword, :valid?,
"not#{plain}", hash])
end
end
sub_test_case("crypt") do
def test_encrypt
salt = ".WoUoU9f3IlUx9Hh7D/8y.xA6ziklGib"
assert_equal("{CRYPT}.W57FZhV52w0s",
ActiveLdap::UserPassword.crypt("password", salt))
password = "PASSWORD"
hashed_password = ActiveLdap::UserPassword.crypt(password)
salt = hashed_password.sub(/^\{CRYPT\}/, '')
assert_equal(hashed_password,
ActiveLdap::UserPassword.crypt(password, salt))
end
sub_test_case("extract_salt") do
sub_test_case("base format") do
def test_less
message = "salt size must be 2: <a>"
assert_raise(ArgumentError.new(message)) do
extract_salt(:crypt, "a")
end
end
def test_exact
assert_extract_salt(:crypt, "ab", "ab")
end
def test_more
assert_extract_salt(:crypt, "ab", "abc")
end
end
sub_test_case("glibc2 format") do
sub_test_case("ID") do
def test_md5
assert_extract_salt(:crypt, "$1$abcdefgh$", "$1$abcdefgh$")
end
def test_blowfish
assert_extract_salt(:crypt, "$2a$abcdefgh$", "$2a$abcdefgh$")
end
def test_sha256
assert_extract_salt(:crypt, "$5$abcdefgh$", "$5$abcdefgh$")
end
def test_sha512
assert_extract_salt(:crypt, "$6$abcdefgh$", "$6$abcdefgh$")
end
end
sub_test_case("salt") do
def test_not_teminated
message = "salt character must be [a-zA-Z0-9./]: <$1>"
assert_raise(ArgumentError.new(message)) do
extract_salt(:crypt, "$1$")
end
end
def test_empty
assert_extract_salt(:crypt, "$1$$", "$1$$")
end
def test_lower_case
assert_extract_salt(:crypt, "$1$abc$", "$1$abc$")
end
def test_upper_case
assert_extract_salt(:crypt, "$1$ABC$", "$1$ABC$")
end
def test_digit
assert_extract_salt(:crypt, "$1$012$", "$1$012$")
end
def test_dot
assert_extract_salt(:crypt, "$1$...$", "$1$...$")
end
def test_slash
assert_extract_salt(:crypt, "$1$///$", "$1$///$")
end
def test_mix
assert_extract_salt(:crypt, "$1$aA0./$", "$1$aA0./$")
end
def test_max
assert_extract_salt(:crypt,
"$1$0123456789abcdef$",
"$1$0123456789abcdef$")
end
def test_over
message = "salt character must be [a-zA-Z0-9./]: <$1>"
assert_raise(ArgumentError.new(message)) do
extract_salt(:crypt, "$1$0123456789abcdefg$")
end
end
end
end
end
end
def test_md5
assert_equal("{MD5}X03MO1qnZdYdgyfeuILPmQ==",
ActiveLdap::UserPassword.md5("password"))
end
def test_smd5
assert_equal("{SMD5}gjz+SUSfZaux99Xsji/No200cGI=",
ActiveLdap::UserPassword.smd5("password", "m4pb"))
password = "PASSWORD"
hashed_password = ActiveLdap::UserPassword.smd5(password)
salt = decode64(hashed_password.sub(/^\{SMD5\}/, ''))[-4, 4]
assert_equal(hashed_password,
ActiveLdap::UserPassword.smd5(password, salt))
end
def test_extract_salt_for_smd5
assert_extract_salt(:smd5, 'this', encode64("1234567890123456this"))
assert_extract_salt(:smd5, 'this is the salt', encode64("1234567890123456this is the salt"))
assert_extract_salt(:smd5, nil, encode64("123456789"))
assert_extract_salt(:smd5, nil, encode64("123456789012345"))
assert_extract_salt(:smd5, nil, encode64("1234567890123456"))
end
def test_sha
assert_equal("{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=",
ActiveLdap::UserPassword.sha("password"))
end
def test_ssha
assert_equal("{SSHA}ipnlCLA1HaK3mm3hyneJIp+Px2h1RGk3",
ActiveLdap::UserPassword.ssha("password", "uDi7"))
password = "PASSWORD"
hashed_password = ActiveLdap::UserPassword.ssha(password)
salt = decode64(hashed_password.sub(/^\{SSHA\}/, ''))[-4, 4]
assert_equal(hashed_password,
ActiveLdap::UserPassword.ssha(password, salt))
end
def test_extract_salt_for_ssha
assert_extract_salt(:ssha, 'this', encode64("12345678901234567890this"))
assert_extract_salt(:ssha, 'this is the salt', encode64("12345678901234567890this is the salt"))
assert_extract_salt(:ssha, nil, encode64("12345678901234"))
assert_extract_salt(:ssha, nil, encode64("1234567890123456789"))
assert_extract_salt(:ssha, nil, encode64("12345678901234567890"))
end
private
def extract_salt(type, hashed_password)
ActiveLdap::UserPassword.send("extract_salt_for_#{type}",
hashed_password)
end
def assert_extract_salt(type, expected, hashed_password)
assert_equal(expected, extract_salt(type, hashed_password))
end
def encode64(string)
[string].pack('m').chomp
end
def decode64(string)
string.unpack('m')[0]
end
end
|