Class: WIKK::Password

Inherits:
Object
  • Object
show all
Defined in:
lib/wikk_password.rb

Overview

READS/WRITES our private password file entries.

Constant Summary collapse

VERSION =
'0.1.2'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user, config, new_user = false) ⇒ WIKK::Password

New. Fetches a user entry from the password file, or creates a new user (call via Passwd::add_user)

Parameters:

  • user (String)

    User name to fetch from password file, or to create, if new_user == true

  • config (WIKK:Configuration)

    or hash or class with attr_readers :passwordFile, :encryption, :key

  • new_user (Boolean) (defaults to: false)

    If true, then the user shouldn't be in password file.

Raises:

  • (IndexError)

    if the user entry exists.



23
24
25
26
27
28
29
30
31
# File 'lib/wikk_password.rb', line 23

def initialize(user, config, new_user=false)
   if config.class == Hash
     sym = config.each_with_object({}) { |(k,v),h| h[k.to_sym] = v }
     @config = Struct.new(*(k = sym.keys)).new(*sym.values_at(*k))
   else
 	  @config = config
   end
  raise IndexError, "User \"#{user}\" not found" if getpwnam(user) == false && !new_user
end

Instance Attribute Details

#passwordString (readonly)

the encrypted password, in form $type$initial_vector$encrypted_text

Returns:

  • (String)

    the current value of password



11
12
13
# File 'lib/wikk_password.rb', line 11

def password
  @password
end

#userString (readonly)

the decrypted text

Returns:

  • (String)

    the current value of user



11
12
13
# File 'lib/wikk_password.rb', line 11

def user
  @user
end

Class Method Details

.add_user(user, password, config) ⇒ Object

Note:

Modifies the password file.

Adds a user to the password file

Parameters:

  • user (String)

    New user name. Raises an error if the user exists

  • password (String)

    Clear text password. Raises an error if this is nil or ''

Raises:

  • (IndexError)

    if the user entry exists.

  • (ArgumentError)

    if the password is nil or empty.



89
90
91
92
93
94
95
# File 'lib/wikk_password.rb', line 89

def self.add_user(user,password,config)
  user_record = self.new(user, config, true)
  raise IndexError, "User \"#{user}\" is already present"  if user_record.password != nil
  raise ArgumentError, "Password can't be empty" if password == nil || password == ''
  user_record.set_password(password)
  user_record.save
end

.valid_sha256_response?(user, config, challenge, response) ⇒ Boolean

Note:

The password entry must be decryptable, not a UNIX style hash.

Compare an SHA256 hashed password + challenge with this users password

Parameters:

  • user (String)

    User name to fetch from password file, or to create, if new_user == true

  • config (WIKK:Configuration)

    or hash or class with attr_readers :passwordFile, :encryption, :key

  • challenge (String)

    a random string, sent to the remote client, added to the password, and SHA256 hashed

  • response (String)

    the remote clients hex_SHA256(password + challenge)

Returns:

  • (Boolean)

    True if the users password matches the one that created the response.

Raises:

  • (ArgumentError)

    if the encryption method is unknown.



61
62
63
# File 'lib/wikk_password.rb', line 61

def self.valid_sha256_response?(user, config, challenge, response)
  self.new(user, config).valid_sha256_response?(challenge, response)
end

Instance Method Details

#saveObject

Saves changes or a new user entry into the password file



99
100
101
102
103
# File 'lib/wikk_password.rb', line 99

def save
  loadfile
  @pwent[@user] = @password
  writefile
end

#set_password(password) ⇒ String

Returns the password file password entry.

Parameters:

  • password (String)

    the clear text password to encypt

Returns:

  • (String)

    the password file password entry.



37
38
39
# File 'lib/wikk_password.rb', line 37

def set_password(password) 
  @password = encrypt(password, @config.encryption)
end

#to_sString

Outputs password file entry as a string

Returns:

  • (String)

    password file entry.



108
109
110
# File 'lib/wikk_password.rb', line 108

def to_s
  "#{@user}:#{@password}"
end

#valid?(ct_password) ⇒ Boolean

Compares the password with the user's password by encrypting the password passed in

Parameters:

  • password (String)

    The clear text password

Returns:

  • (Boolean)

    True if the passwords match

Raises:

  • (ArgumentError)

    if the encryption method is unknown.



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/wikk_password.rb', line 70

def valid?(ct_password)
  ignore,encryption,iv,password = @password.split('$')
  encryption = 'DES' if ignore != '' #No $'s in DES password, so ignore has text.
  case encryption
  when 'ct'; return ct_password == @password
  when 'aes256'; return encrypt(ct_password, encryption, iv) == @password
  when 'DES'; return UnixCrypt.valid?(ct_password, @password) 
  when 'MD5','1','SHA256','5','SHA512','6'; return UnixCrypt.valid?(ct_password, @password)
  else raise ArgumentError, "Unsupported encryption algorithm $#{encryption}"
  end
end

#valid_sha256_response?(challenge, response) ⇒ Boolean

Note:

The password entry must be decryptable, not a UNIX style hash.

Compare an SHA256 hashed password + challenge with this users password

Parameters:

  • challenge (String)

    a random string, sent to the remote client, added to the password, and SHA256 hashed

  • response (String)

    the remote clients hex_SHA256(password + challenge)

Returns:

  • (Boolean)

    True if the users password matches the one that created the response.

Raises:

  • (ArgumentError)

    if the encryption method is unknown.



48
49
50
# File 'lib/wikk_password.rb', line 48

def valid_sha256_response?(challenge, response)
  return response == Digest::SHA256.digest(decrypt + challenge).unpack('H*')[0]
end