Module: RubySMB::Client::Authentication
- Included in:
- RubySMB::Client
- Defined in:
- lib/ruby_smb/client/authentication.rb
Overview
This module holds all the backend client methods for authentication.
Instance Method Summary collapse
-
#authenticate ⇒ WindowsError::NTStatus
Responsible for handling Authentication and Session Setup for the SMB Client.
-
#extract_os_version(version) ⇒ String
Extract the peer/server version number from the NTLM Type 2 (challenge) Version field.
-
#smb1_anonymous_auth ⇒ WindowsError::ErrorCode
Attempts an Anonymous logon to the remote server.
-
#smb1_anonymous_auth_request ⇒ Object
Creates a SessionSetupRequest for an anonymous access session.
- #smb1_anonymous_auth_response(raw_response) ⇒ Object
-
#smb1_authenticate ⇒ Object
Handles the SMB1 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
-
#smb1_ntlmssp_auth_packet(type3_message, user_id) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
-
#smb1_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
-
#smb1_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse.
-
#smb1_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse.
-
#smb1_ntlmssp_negotiate ⇒ String
Sends the SMB1::Packet::SessionSetupRequest packet and receives the response.
-
#smb1_ntlmssp_negotiate_packet ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Creates the SMB1::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way hnadshake.
-
#smb1_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB1::Packet::SessionSetupResponse.
-
#smb2_authenticate ⇒ Object
Handles the SMB2 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
-
#smb2_ntlmssp_auth_packet(type3_message, session_id) ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Generates the SMB2::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
-
#smb2_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
-
#smb2_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse.
-
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse.
-
#smb2_ntlmssp_negotiate ⇒ String
Sends the SMB2::Packet::SessionSetupRequest packet and receives the response.
-
#smb2_ntlmssp_negotiate_packet ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Creates the SMB2::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way handshake.
-
#smb2_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB2::Packet::SessionSetupResponse.
-
#store_target_info(target_info_str) ⇒ Object
Extract and store useful information about the peer/server from the NTLM Type 2 (challenge) TargetInfo fields.
Instance Method Details
#authenticate ⇒ WindowsError::NTStatus
Responsible for handling Authentication and Session Setup for the SMB Client. It returns the final Status code from the authentication exchange.
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/ruby_smb/client/authentication.rb', line 10 def authenticate if smb1 if username.empty? && password.empty? smb1_anonymous_auth else smb1_authenticate end else smb2_authenticate end end |
#extract_os_version(version) ⇒ String
Extract the peer/server version number from the NTLM Type 2 (challenge) Version field.
321 322 323 |
# File 'lib/ruby_smb/client/authentication.rb', line 321 def extract_os_version(version) version.unpack('CCS').join('.') end |
#smb1_anonymous_auth ⇒ WindowsError::ErrorCode
Attempts an Anonymous logon to the remote server.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ruby_smb/client/authentication.rb', line 29 def smb1_anonymous_auth request = smb1_anonymous_auth_request raw_response = send_recv(request) response = smb1_anonymous_auth_response(raw_response) response_code = response.status_code if response_code == WindowsError::NTStatus::STATUS_SUCCESS self.user_id = response.smb_header.uid self.peer_native_os = response.data_block.native_os.to_s self.peer_native_lm = response.data_block.native_lan_man.to_s self.primary_domain = response.data_block.primary_domain.to_s end response_code end |
#smb1_anonymous_auth_request ⇒ Object
Creates a SessionSetupRequest for an anonymous access session.
47 48 49 50 51 52 53 54 |
# File 'lib/ruby_smb/client/authentication.rb', line 47 def smb1_anonymous_auth_request packet = RubySMB::SMB1::Packet::SessionSetupLegacyRequest.new packet.data_block.oem_password = "\x00" packet.parameter_block.max_buffer_size = self.max_buffer_size packet.parameter_block.max_mpx_count = 50 packet.parameter_block.capabilities.extended_security = 0 packet end |
#smb1_anonymous_auth_response(raw_response) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/ruby_smb/client/authentication.rb', line 56 def smb1_anonymous_auth_response(raw_response) begin packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response) rescue packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response) end unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}" end packet end |
#smb1_authenticate ⇒ Object
Handles the SMB1 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
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 |
# File 'lib/ruby_smb/client/authentication.rb', line 71 def smb1_authenticate response = smb1_ntlmssp_negotiate challenge_packet = smb1_ntlmssp_challenge_packet(response) # Store the available OS information before going forward. @peer_native_os = challenge_packet.data_block.native_os.to_s @peer_native_lm = challenge_packet.data_block.native_lan_man.to_s user_id = challenge_packet.smb_header.uid = (challenge_packet) = @ntlm_client.init_context() @session_key = @ntlm_client.session_key = @ntlm_client.session. store_target_info(.target_info) if .has_flag?(:TARGET_INFO) @os_version = extract_os_version(.os_version.to_s) raw = smb1_ntlmssp_authenticate(, user_id) response = smb1_ntlmssp_final_packet(raw) response_code = response.status_code @user_id = user_id if response_code == WindowsError::NTStatus::STATUS_SUCCESS response_code end |
#smb1_ntlmssp_auth_packet(type3_message, user_id) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
123 124 125 126 127 128 129 130 131 |
# File 'lib/ruby_smb/client/authentication.rb', line 123 def smb1_ntlmssp_auth_packet(, user_id) packet = RubySMB::SMB1::Packet::SessionSetupRequest.new packet.smb_header.uid = user_id packet.set_type3_blob(.serialize) packet.parameter_block.max_buffer_size = self.max_buffer_size packet.parameter_block.max_mpx_count = 50 packet.smb_header.flags2.extended_security = 1 packet end |
#smb1_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
112 113 114 115 |
# File 'lib/ruby_smb/client/authentication.rb', line 112 def smb1_ntlmssp_authenticate(, user_id) packet = smb1_ntlmssp_auth_packet(, user_id) send_recv(packet) end |
#smb1_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/ruby_smb/client/authentication.rb', line 163 def smb1_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s end unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}" end packet end |
#smb1_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ruby_smb/client/authentication.rb', line 149 def smb1_ntlmssp_final_packet(raw_response) begin packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) rescue packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response) end unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}" end packet end |
#smb1_ntlmssp_negotiate ⇒ String
Sends the SMB1::Packet::SessionSetupRequest packet and receives the response.
101 102 103 104 |
# File 'lib/ruby_smb/client/authentication.rb', line 101 def smb1_ntlmssp_negotiate packet = smb1_ntlmssp_negotiate_packet send_recv(packet) end |
#smb1_ntlmssp_negotiate_packet ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Creates the SMB1::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way hnadshake. This packet initializes negotiations for the NTLMSSP authentication
138 139 140 141 142 143 144 145 146 |
# File 'lib/ruby_smb/client/authentication.rb', line 138 def smb1_ntlmssp_negotiate_packet = ntlm_client.init_context packet = RubySMB::SMB1::Packet::SessionSetupRequest.new packet.set_type1_blob(.serialize) packet.parameter_block.max_buffer_size = self.max_buffer_size packet.parameter_block.max_mpx_count = 50 packet.smb_header.flags2.extended_security = 1 packet end |
#smb1_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB1::Packet::SessionSetupResponse
181 182 183 184 185 186 |
# File 'lib/ruby_smb/client/authentication.rb', line 181 def (response_packet) sec_blob = response_packet.data_block.security_blob ntlmssp_offset = sec_blob.index('NTLMSSP') type2_blob = sec_blob.slice(ntlmssp_offset..-1) [type2_blob].pack('m') end |
#smb2_authenticate ⇒ Object
Handles the SMB2 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/ruby_smb/client/authentication.rb', line 194 def smb2_authenticate response = smb2_ntlmssp_negotiate challenge_packet = smb2_ntlmssp_challenge_packet(response) @session_id = challenge_packet.smb2_header.session_id = (challenge_packet) = @ntlm_client.init_context() @session_key = @ntlm_client.session_key = ntlm_client.session. store_target_info(.target_info) if .has_flag?(:TARGET_INFO) @os_version = extract_os_version(.os_version.to_s) raw = smb2_ntlmssp_authenticate(, @session_id) response = smb2_ntlmssp_final_packet(raw) response.status_code end |
#smb2_ntlmssp_auth_packet(type3_message, session_id) ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Generates the SMB2::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
288 289 290 291 292 293 |
# File 'lib/ruby_smb/client/authentication.rb', line 288 def smb2_ntlmssp_auth_packet(, session_id) packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.smb2_header.session_id = session_id packet.set_type3_blob(.serialize) packet end |
#smb2_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
277 278 279 280 |
# File 'lib/ruby_smb/client/authentication.rb', line 277 def smb2_ntlmssp_authenticate(, user_id) packet = smb2_ntlmssp_auth_packet(, user_id) send_recv(packet) end |
#smb2_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/ruby_smb/client/authentication.rb', line 222 def smb2_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s end unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}" end packet end |
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
213 214 215 216 217 218 219 |
# File 'lib/ruby_smb/client/authentication.rb', line 213 def smb2_ntlmssp_final_packet(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}" end packet end |
#smb2_ntlmssp_negotiate ⇒ String
Sends the SMB2::Packet::SessionSetupRequest packet and receives the response.
239 240 241 242 |
# File 'lib/ruby_smb/client/authentication.rb', line 239 def smb2_ntlmssp_negotiate packet = smb2_ntlmssp_negotiate_packet send_recv(packet) end |
#smb2_ntlmssp_negotiate_packet ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Creates the SMB2::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way handshake. This packet initializes negotiations for the NTLMSSP authentication
249 250 251 252 253 254 255 256 257 258 |
# File 'lib/ruby_smb/client/authentication.rb', line 249 def smb2_ntlmssp_negotiate_packet = ntlm_client.init_context packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.set_type1_blob(.serialize) # This Message ID should always be 1, but thanks to Multi-Protocol Negotiation # the Message ID can be out of sync at this point so we re-synch it here. packet.smb2_header. = 1 self. = 2 packet end |
#smb2_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB2::Packet::SessionSetupResponse
264 265 266 267 268 269 |
# File 'lib/ruby_smb/client/authentication.rb', line 264 def (response_packet) sec_blob = response_packet.buffer ntlmssp_offset = sec_blob.index('NTLMSSP') type2_blob = sec_blob.slice(ntlmssp_offset..-1) [type2_blob].pack('m') end |
#store_target_info(target_info_str) ⇒ Object
Extract and store useful information about the peer/server from the NTLM Type 2 (challenge) TargetInfo fields.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/ruby_smb/client/authentication.rb', line 299 def store_target_info(target_info_str) target_info = Net::NTLM::TargetInfo.new(target_info_str) { Net::NTLM::TargetInfo::MSV_AV_NB_COMPUTER_NAME => :@default_name, Net::NTLM::TargetInfo::MSV_AV_NB_DOMAIN_NAME => :@default_domain, Net::NTLM::TargetInfo::MSV_AV_DNS_COMPUTER_NAME => :@dns_host_name, Net::NTLM::TargetInfo::MSV_AV_DNS_DOMAIN_NAME => :@dns_domain_name, Net::NTLM::TargetInfo::MSV_AV_DNS_TREE_NAME => :@dns_tree_name }.each do |constant, attribute| if target_info.av_pairs[constant] value = target_info.av_pairs[constant].dup value.force_encoding('UTF-16LE') instance_variable_set(attribute, value.encode('UTF-8')) end end end |