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.
339 340 341 |
# File 'lib/ruby_smb/client/authentication.rb', line 339 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.to_s 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 |
# File 'lib/ruby_smb/client/authentication.rb', line 201 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) unless .os_version.empty? 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.
306 307 308 309 310 311 |
# File 'lib/ruby_smb/client/authentication.rb', line 306 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.
295 296 297 298 |
# File 'lib/ruby_smb/client/authentication.rb', line 295 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
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/ruby_smb/client/authentication.rb', line 235 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.to_s end packet end |
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/ruby_smb/client/authentication.rb', line 220 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.
257 258 259 260 |
# File 'lib/ruby_smb/client/authentication.rb', line 257 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
267 268 269 270 271 272 273 274 275 276 |
# File 'lib/ruby_smb/client/authentication.rb', line 267 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
282 283 284 285 286 287 |
# File 'lib/ruby_smb/client/authentication.rb', line 282 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.
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/ruby_smb/client/authentication.rb', line 317 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 |