diff --git a/lib/vertica.rb b/lib/vertica.rb index 7a53fe8..a97f1d0 100644 --- a/lib/vertica.rb +++ b/lib/vertica.rb @@ -10,7 +10,7 @@ module Vertica # The protocol version (3.0.0) implemented in this library. - PROTOCOL_VERSION = 3 << 16 + PROTOCOL_VERSION = 3 << 16 | 5 # Opens a new connection to a Vertica database. # @param (see Vertica::Connection#initialize) diff --git a/lib/vertica/connection.rb b/lib/vertica/connection.rb index fce3f78..4f785de 100644 --- a/lib/vertica/connection.rb +++ b/lib/vertica/connection.rb @@ -392,7 +392,7 @@ def startup_connection case message = read_message when Vertica::Protocol::Authentication if message.code != Vertica::Protocol::Authentication::OK - write_message(Vertica::Protocol::Password.new(@options[:password], auth_method: message.code, user: @options[:username], salt: message.salt)) + write_message(Vertica::Protocol::Password.new(@options[:password], auth_method: message.code, user: @options[:username], salt: message.salt, userSalt: message.userSalt)) end else process_message(message) diff --git a/lib/vertica/protocol/backend/authentication.rb b/lib/vertica/protocol/backend/authentication.rb index 367ea30..036cf02 100644 --- a/lib/vertica/protocol/backend/authentication.rb +++ b/lib/vertica/protocol/backend/authentication.rb @@ -4,6 +4,7 @@ class Authentication < BackendMessage message_id 'R' OK = 0 + KERBEROS_V4 = 1 KERBEROS_V5 = 2 CLEARTEXT_PASSWORD = 3 CRYPT_PASSWORD = 4 @@ -11,17 +12,32 @@ class Authentication < BackendMessage SCM_CREDENTIAL = 6 GSS = 7 GSS_CONTINUE = 8 - SSPI = 9 + CHANGE_PASSWORD = 9 + PASSWORD_CHANGED = 10 + PASSWORD_GRACE = 11 + HASH = 65536 + HASH_MD5 = 65536+5 + HASH_SHA512 = 65536+512 attr_reader :code attr_reader :salt + attr_reader :userSalt attr_reader :auth_data def initialize(data) @code, other = data.unpack('Na*') case @code - when CRYPT_PASSWORD, MD5_PASSWORD then @salt = other + when CRYPT_PASSWORD then @salt = other + when MD5_PASSWORD, HASH_MD5 then @salt = other[0...4] when GSS_CONTINUE then @auth_data = other + when HASH, HASH_SHA512 + @salt = other[0...4] + @userSaltLen = other[4...8].unpack('I>').first + if @userSaltLen != 16 + puts "user salt length isn't 16, raise error" + end + userSaltArray = other[8...other.size].unpack('a*') + @userSalt = userSaltArray.first end end end diff --git a/lib/vertica/protocol/frontend/password.rb b/lib/vertica/protocol/frontend/password.rb index b6b21de..d4a4658 100644 --- a/lib/vertica/protocol/frontend/password.rb +++ b/lib/vertica/protocol/frontend/password.rb @@ -3,9 +3,9 @@ module Protocol class Password < FrontendMessage message_id 'p' - def initialize(password, auth_method: Vertica::Protocol::Authentication::CLEARTEXT_PASSWORD, salt: nil, user: nil) + def initialize(password, auth_method: Vertica::Protocol::Authentication::CLEARTEXT_PASSWORD, salt: nil, user: nil, userSalt: nil) @password = password - @auth_method, @salt, @user = auth_method, salt, user + @auth_method, @salt, @user, @userSalt = auth_method, salt, user, userSalt end def encoded_password @@ -14,11 +14,20 @@ def encoded_password @password when Vertica::Protocol::Authentication::CRYPT_PASSWORD @password.crypt(@salt) - when Vertica::Protocol::Authentication::MD5_PASSWORD + when Vertica::Protocol::Authentication::MD5_PASSWORD, \ + Vertica::Protocol::Authentication::HASH_MD5 require 'digest/md5' @password = Digest::MD5.hexdigest("#{@password}#{@user}") @password = Digest::MD5.hexdigest("#{@password}#{@salt}") - @password = "md5#{@password}" + prefix = "md5".bytes + @password = "#{prefix}#{@password}" + when Vertica::Protocol::Authentication::HASH, \ + Vertica::Protocol::Authentication::HASH_SHA512 + require 'digest' + @password = Digest::SHA512.hexdigest("#{@password}#{@userSalt}") + @password = Digest::SHA512.hexdigest("#{@password}#{@salt}") + prefix = "sha512" + @password = "#{prefix}#{@password}" else raise ArgumentError.new("unsupported authentication method: #{@auth_method}") end diff --git a/lib/vertica/version.rb b/lib/vertica/version.rb index 8753d20..ce243ad 100644 --- a/lib/vertica/version.rb +++ b/lib/vertica/version.rb @@ -1,5 +1,5 @@ module Vertica # The version of the package. We adhere to semantic versioning. # To release a new version, update this constant, commit to master, and run `rake release` - VERSION = "1.0.3" + VERSION = "1.0.34" end diff --git a/vagrant/configure_vertica_passwords.sql b/vagrant/configure_vertica_passwords.sql new file mode 100644 index 0000000..5c24769 --- /dev/null +++ b/vagrant/configure_vertica_passwords.sql @@ -0,0 +1,5 @@ +select SET_CONFIG_PARAMETER('SecurityAlgorithm', 'SHA512'); +CREATE AUTHENTICATION default_network METHOD 'hash' HOST '0.0.0.0/0'; +CREATE AUTHENTICATION default_local METHOD 'hash' LOCAL; +GRANT AUTHENTICATION default_network to public; +GRANT AUTHENTICATION default_local to public;