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.
358 359 360 |
# File 'lib/ruby_smb/client/authentication.rb', line 358 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 68 |
# File 'lib/ruby_smb/client/authentication.rb', line 56 def smb1_anonymous_auth_response(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND, received_proto: packet.smb_header.protocol, received_cmd: packet.smb_header.command ) end packet end |
#smb1_authenticate ⇒ Object
Handles the SMB1 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ruby_smb/client/authentication.rb', line 72 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) unless .os_version.empty? 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.
124 125 126 127 128 129 130 131 132 |
# File 'lib/ruby_smb/client/authentication.rb', line 124 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.
113 114 115 116 |
# File 'lib/ruby_smb/client/authentication.rb', line 113 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
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/ruby_smb/client/authentication.rb', line 165 def smb1_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND, received_proto: packet.smb_header.protocol, received_cmd: packet.smb_header.command ) end status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code end packet end |
#smb1_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/ruby_smb/client/authentication.rb', line 150 def smb1_ntlmssp_final_packet(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND, received_proto: packet.smb_header.protocol, received_cmd: packet.smb_header.command ) end packet end |
#smb1_ntlmssp_negotiate ⇒ String
Sends the SMB1::Packet::SessionSetupRequest packet and receives the response.
102 103 104 105 |
# File 'lib/ruby_smb/client/authentication.rb', line 102 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
139 140 141 142 143 144 145 146 147 |
# File 'lib/ruby_smb/client/authentication.rb', line 139 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
188 189 190 191 192 193 |
# File 'lib/ruby_smb/client/authentication.rb', line 188 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.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/ruby_smb/client/authentication.rb', line 201 def smb2_authenticate response = smb2_ntlmssp_negotiate challenge_packet = smb2_ntlmssp_challenge_packet(response) if @dialect == '0x0311' update_preauth_hash(challenge_packet) end @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) unless .os_version.empty? raw = smb2_ntlmssp_authenticate(, @session_id) response = smb2_ntlmssp_final_packet(raw) if @smb3 && !@session_encrypt_data && response.session_flags.encrypt_data == 1 @session_encrypt_data = true end ###### # DEBUG #puts "Session ID = #{@session_id.to_binary_s.each_byte.map {|e| '%02x' % e}.join}" #puts "Session key = #{@session_key.each_byte.map {|e| '%02x' % e}.join}" #puts "PreAuthHash = #{@preauth_integrity_hash_value.each_byte.map {|e| '%02x' % e}.join}" if @preauth_integrity_hash_value ###### 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.
324 325 326 327 328 329 330 |
# File 'lib/ruby_smb/client/authentication.rb', line 324 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.security_mode.signing_enabled = 1 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.
309 310 311 312 313 314 315 316 |
# File 'lib/ruby_smb/client/authentication.rb', line 309 def smb2_ntlmssp_authenticate(, user_id) packet = smb2_ntlmssp_auth_packet(, user_id) response = send_recv(packet) if @dialect == '0x0311' update_preauth_hash(packet) end response end |
#smb2_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/ruby_smb/client/authentication.rb', line 248 def smb2_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND, received_proto: packet.smb2_header.protocol, received_cmd: packet.smb2_header.command ) end status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code end packet end |
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/ruby_smb/client/authentication.rb', line 233 def smb2_ntlmssp_final_packet(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND, received_proto: packet.smb2_header.protocol, received_cmd: packet.smb2_header.command ) end packet end |
#smb2_ntlmssp_negotiate ⇒ String
Sends the SMB2::Packet::SessionSetupRequest packet and receives the response.
270 271 272 273 274 275 276 277 |
# File 'lib/ruby_smb/client/authentication.rb', line 270 def smb2_ntlmssp_negotiate packet = smb2_ntlmssp_negotiate_packet response = send_recv(packet) if @dialect == '0x0311' update_preauth_hash(packet) end response 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
284 285 286 287 288 289 290 |
# File 'lib/ruby_smb/client/authentication.rb', line 284 def smb2_ntlmssp_negotiate_packet = ntlm_client.init_context packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.set_type1_blob(.serialize) packet.security_mode.signing_enabled = 1 packet end |
#smb2_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB2::Packet::SessionSetupResponse
296 297 298 299 300 301 |
# File 'lib/ruby_smb/client/authentication.rb', line 296 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.
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/ruby_smb/client/authentication.rb', line 336 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 |