class Net::NTLM::Client::Session
Constants
- CLIENT_TO_SERVER_SEALING
- CLIENT_TO_SERVER_SIGNING
- MAX64
- SERVER_TO_CLIENT_SEALING
- SERVER_TO_CLIENT_SIGNING
- TIME_OFFSET
- VERSION_MAGIC
Attributes
challenge_message[R]
channel_binding[R]
client[R]
Public Class Methods
new(client, challenge_message, channel_binding = nil)
click to toggle source
@param client [Net::NTLM::Client] the client instance @param challenge_message
[Net::NTLM::Message::Type2] server message
# File lib/net/ntlm/client/session.rb, line 17 def initialize(client, challenge_message, channel_binding = nil) @client = client @challenge_message = challenge_message @channel_binding = channel_binding end
Public Instance Methods
authenticate!()
click to toggle source
Generate an NTLMv2 AUTHENTICATE_MESSAGE @see msdn.microsoft.com/en-us/library/cc236643.aspx @return [Net::NTLM::Message::Type3]
# File lib/net/ntlm/client/session.rb, line 26 def authenticate! calculate_user_session_key! type3_opts = { :lm_response => is_anonymous? ? "\x00".b : lmv2_resp, :ntlm_response => is_anonymous? ? '' : ntlmv2_resp, :domain => domain, :user => username, :workstation => workstation, :flag => (challenge_message.flag & client.flags) } t3 = Message::Type3.create type3_opts if negotiate_key_exchange? t3.enable(:session_key) rc4 = Net::NTLM::Rc4.new(user_session_key) sk = rc4.encrypt exported_session_key t3.session_key = sk end t3 end
exported_session_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 46 def exported_session_key @exported_session_key ||= begin if negotiate_key_exchange? OpenSSL::Random.random_bytes(16) else user_session_key end end end
is_anonymous?()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 83 def is_anonymous? username == '' && password == '' end
seal_message(message)
click to toggle source
# File lib/net/ntlm/client/session.rb, line 75 def seal_message(message) client_cipher.encrypt(message) end
sign_message(message)
click to toggle source
# File lib/net/ntlm/client/session.rb, line 57 def sign_message(message) seq = sequence sig = OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, client_sign_key, "#{seq}#{message}")[0..7] if negotiate_key_exchange? sig = client_cipher.encrypt sig end "#{VERSION_MAGIC}#{sig}#{seq}" end
unseal_message(emessage)
click to toggle source
# File lib/net/ntlm/client/session.rb, line 79 def unseal_message(emessage) server_cipher.encrypt(emessage) end
verify_signature(signature, message)
click to toggle source
# File lib/net/ntlm/client/session.rb, line 66 def verify_signature(signature, message) seq = signature[-4..-1] sig = OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, server_sign_key, "#{seq}#{message}")[0..7] if negotiate_key_exchange? sig = server_cipher.encrypt sig end "#{VERSION_MAGIC}#{sig}#{seq}" == signature end
Private Instance Methods
blob()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 202 def blob @blob ||= begin b = Blob.new b.timestamp = timestamp b.challenge = client_challenge b.target_info = target_info b.serialize end end
calculate_user_session_key!()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 181 def calculate_user_session_key! if is_anonymous? # see MS-NLMP section 3.4 @user_session_key = "\x00".b * 16 else @user_session_key = OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmv2_hash, nt_proof_str) end end
client_challenge()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 130 def client_challenge @client_challenge ||= NTLM.pack_int64le(rand(MAX64)) end
client_cipher()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 122 def client_cipher @client_cipher ||= Net::NTLM::Rc4.new(client_seal_key) end
client_seal_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 114 def client_seal_key @client_seal_key ||= OpenSSL::Digest::MD5.digest "#{exported_session_key}#{CLIENT_TO_SERVER_SEALING}" end
client_sign_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 106 def client_sign_key @client_sign_key ||= OpenSSL::Digest::MD5.digest "#{exported_session_key}#{CLIENT_TO_SERVER_SIGNING}" end
domain()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 165 def domain (client.domain ? oem_or_unicode_str(client.domain) : "") end
lmv2_resp()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 190 def lmv2_resp OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmv2_hash, server_challenge + client_challenge) + client_challenge end
negotiate_key_exchange?()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 149 def negotiate_key_exchange? challenge_message.has_flag? :KEY_EXCHANGE end
nt_proof_str()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 198 def nt_proof_str @nt_proof_str ||= OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmv2_hash, server_challenge + blob) end
ntlmv2_hash()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 177 def ntlmv2_hash @ntlmv2_hash ||= NTLM.ntlmv2_hash(username, password, domain, {:client_challenge => client_challenge, :unicode => !use_oem_strings?}) end
ntlmv2_resp()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 194 def ntlmv2_resp nt_proof_str + blob end
oem_or_unicode_str(str)
click to toggle source
# File lib/net/ntlm/client/session.rb, line 169 def oem_or_unicode_str(str) if use_oem_strings? NTLM::EncodeUtil.decode_utf16le str else NTLM::EncodeUtil.encode_utf16le str end end
password()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 157 def password oem_or_unicode_str client.password end
raw_sequence()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 98 def raw_sequence if defined? @raw_sequence @raw_sequence += 1 else @raw_sequence = 0 end end
sequence()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 94 def sequence [raw_sequence].pack("V*") end
server_challenge()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 134 def server_challenge @server_challenge ||= challenge_message[:challenge].serialize end
server_cipher()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 126 def server_cipher @server_cipher ||= Net::NTLM::Rc4.new(server_seal_key) end
server_seal_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 118 def server_seal_key @server_seal_key ||= OpenSSL::Digest::MD5.digest "#{exported_session_key}#{SERVER_TO_CLIENT_SEALING}" end
server_sign_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 110 def server_sign_key @server_sign_key ||= OpenSSL::Digest::MD5.digest "#{exported_session_key}#{SERVER_TO_CLIENT_SIGNING}" end
target_info()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 213 def target_info @target_info ||= begin if channel_binding t = Net::NTLM::TargetInfo.new(challenge_message.target_info) av_id = Net::NTLM::TargetInfo::MSV_AV_CHANNEL_BINDINGS t.av_pairs[av_id] = channel_binding.channel_binding_token t.to_s else challenge_message.target_info end end end
timestamp()
click to toggle source
epoch -> milsec from Jan 1, 1601 @see support.microsoft.com/kb/188768
# File lib/net/ntlm/client/session.rb, line 140 def timestamp @timestamp ||= 10_000_000 * (Time.now.to_i + TIME_OFFSET) end
use_oem_strings?()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 144 def use_oem_strings? # @see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832 !challenge_message.has_flag?(:UNICODE) && challenge_message.has_flag?(:OEM) end
user_session_key()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 90 def user_session_key @user_session_key ||= nil end
username()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 153 def username oem_or_unicode_str client.username end
workstation()
click to toggle source
# File lib/net/ntlm/client/session.rb, line 161 def workstation (client.workstation ? oem_or_unicode_str(client.workstation) : "") end