Module: ActiveLdap::UserPassword

Includes:
GetText
Defined in:
lib/active_ldap/user_password.rb

Defined Under Namespace

Modules: Salt

Class Method Summary collapse

Class Method Details

.crypt(password, salt = nil) ⇒ Object



36
37
38
39
# File 'lib/active_ldap/user_password.rb', line 36

def crypt(password, salt=nil)
  salt ||= "$1$#{Salt.generate(8)}"
  "{CRYPT}#{password.crypt(salt)}"
end

.extract_salt_at_pos(hashed_password, position) ⇒ Object



91
92
93
94
# File 'lib/active_ldap/user_password.rb', line 91

def extract_salt_at_pos(hashed_password, position)
  salt = Base64.decode64(hashed_password)[position..-1]
  salt == '' ? nil : salt
end

.extract_salt_for_crypt(crypted_password) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/active_ldap/user_password.rb', line 41

def extract_salt_for_crypt(crypted_password)
  if /\A\$(?:1|5|6|2a)\$[a-zA-Z0-9.\/]{,16}\$/ =~ crypted_password
    $MATCH
  else
    salt = crypted_password[0, 2]
    if salt.size != 2
      raise ArgumentError, _("salt size must be 2: <%s>") % salt
    end
    unless /\A[a-zA-Z0-9.\/]{2}\z/ =~ salt
      message = _("salt character must be [a-zA-Z0-9./]: <%s>") % salt
      raise ArgumentError, message
    end
    salt
  end
end

.extract_salt_for_smd5(smd5ed_password) ⇒ Object



70
71
72
# File 'lib/active_ldap/user_password.rb', line 70

def extract_salt_for_smd5(smd5ed_password)
  extract_salt_at_pos(smd5ed_password, 16)
end

.extract_salt_for_ssha(sshaed_password) ⇒ Object



87
88
89
# File 'lib/active_ldap/user_password.rb', line 87

def extract_salt_for_ssha(sshaed_password)
  extract_salt_at_pos(sshaed_password, 20)
end

.md5(password) ⇒ Object



57
58
59
# File 'lib/active_ldap/user_password.rb', line 57

def md5(password)
  "{MD5}#{[Digest::MD5.digest(password)].pack('m').chomp}"
end

.sha(password) ⇒ Object



74
75
76
# File 'lib/active_ldap/user_password.rb', line 74

def sha(password)
  "{SHA}#{[Digest::SHA1.digest(password)].pack('m').chomp}"
end

.smd5(password, salt = nil) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/active_ldap/user_password.rb', line 61

def smd5(password, salt=nil)
  if salt and salt.size < 4
    raise ArgumentError, _("salt size must be >= 4: %s") % salt.inspect
  end
  salt ||= Salt.generate(4)
  md5_hash_with_salt = "#{Digest::MD5.digest(password + salt)}#{salt}"
  "{SMD5}#{[md5_hash_with_salt].pack('m').gsub("\n", '')}"
end

.ssha(password, salt = nil) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/active_ldap/user_password.rb', line 78

def ssha(password, salt=nil)
  if salt and salt.size < 4
    raise ArgumentError, _("salt size must be >= 4: %s") % salt.inspect
  end
  salt ||= Salt.generate(4)
  sha1_hash_with_salt = "#{Digest::SHA1.digest(password + salt)}#{salt}"
  "{SSHA}#{[sha1_hash_with_salt].pack('m').gsub("\n", '')}"
end

.valid?(password, hashed_password) ⇒ Boolean

Returns:

  • (Boolean)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/active_ldap/user_password.rb', line 11

def valid?(password, hashed_password)
  unless /^\{([A-Za-z][A-Za-z\d]+)\}/ =~ hashed_password
    # Plain text password
    return hashed_password == password
  end
  type = $1
  hashed_password_without_type = $POSTMATCH
  normalized_type = type.downcase
  unless respond_to?(normalized_type)
    raise ArgumentError, _("Unknown Hash type: %s") % type
  end
  salt_extractor = "extract_salt_for_#{normalized_type}"
  if respond_to?(salt_extractor)
    salt = send(salt_extractor, hashed_password_without_type)
    if salt.nil?
      raise ArgumentError,
        _("Can't extract salt from hashed password: %s") % hashed_password
    end
    generated_password = send(normalized_type, password, salt)
  else
    generated_password = send(normalized_type, password)
  end
  hashed_password == generated_password
end