From 34ab809c0981b510ae9436131fac1acf2abda129 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 9 Jun 2020 22:07:35 -0400 Subject: [PATCH 1/4] Store server system and start time values --- lib/ruby_smb/client.rb | 14 ++++++++++++++ lib/ruby_smb/client/negotiation.rb | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/ruby_smb/client.rb b/lib/ruby_smb/client.rb index 98d5d1e04..1e89a2cb6 100644 --- a/lib/ruby_smb/client.rb +++ b/lib/ruby_smb/client.rb @@ -233,6 +233,20 @@ class Client # (constants defined in RubySMB::SMB2::CompressionCapabilities) attr_accessor :server_compression_algorithms + # The server's start time if it is reported as part of the negotiation + # process (SMB 2.x and 3.x). This value is nil if the server does not report + # it (reports a value of 0). + # @!attribute [rw] server_start_time + # @return [Time] the time that the server reports that it was started at + attr_accessor :server_start_time + + # The server's current time if it is reported as part of the negotiation + # process (SMB 2.x and 3.x). This value is nil if the server does not report + # it (reports a value of 0). + # @!attribute [rw] server_system_time + # @return [Time] the time that the server reports as current + attr_accessor :server_system_time + # The SMB version that has been successfully negotiated. This value is only # set after the NEGOTIATE handshake has been performed. # @!attribute [rw] negotiated_smb_version diff --git a/lib/ruby_smb/client/negotiation.rb b/lib/ruby_smb/client/negotiation.rb index b6f3bae26..62831a6a4 100644 --- a/lib/ruby_smb/client/negotiation.rb +++ b/lib/ruby_smb/client/negotiation.rb @@ -24,6 +24,16 @@ def negotiate when '0x0311' parse_smb3_encryption_data(request_packet, response_packet) end + + if %w{0x0202 0x0210 0x0300 0x0302 0x0311 0x02ff}.include? @dialect + if response_packet.server_start_time != 0 + @server_start_time = response_packet.server_start_time.to_time + end + if response_packet.system_time != 0 + @server_system_time = response_packet.system_time.to_time + end + end + # If the response contains the SMB2 wildcard revision number dialect; # it indicates that the server implements SMB 2.1 or future dialect # revisions and expects the client to send a subsequent SMB2 Negotiate From 42daf68437dc90de87d06a27248046ee36469fcf Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 10 Jun 2020 09:14:10 -0400 Subject: [PATCH 2/4] Check that the response_packet is not nil before processing it --- lib/ruby_smb/client/negotiation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby_smb/client/negotiation.rb b/lib/ruby_smb/client/negotiation.rb index 62831a6a4..a5797b551 100644 --- a/lib/ruby_smb/client/negotiation.rb +++ b/lib/ruby_smb/client/negotiation.rb @@ -25,7 +25,7 @@ def negotiate parse_smb3_encryption_data(request_packet, response_packet) end - if %w{0x0202 0x0210 0x0300 0x0302 0x0311 0x02ff}.include? @dialect + if response_packet && %w{0x0202 0x0210 0x0300 0x0302 0x0311 0x02ff}.include?(@dialect) if response_packet.server_start_time != 0 @server_start_time = response_packet.server_start_time.to_time end From f726317c0de0d4003287683e16ac3477c7182767 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 10 Jun 2020 18:26:59 -0400 Subject: [PATCH 3/4] Also store the server_guid value --- lib/ruby_smb/client.rb | 5 +++++ lib/ruby_smb/client/negotiation.rb | 1 + lib/ruby_smb/smb2/packet/negotiate_response.rb | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/ruby_smb/client.rb b/lib/ruby_smb/client.rb index 1e89a2cb6..f74e0321e 100644 --- a/lib/ruby_smb/client.rb +++ b/lib/ruby_smb/client.rb @@ -233,6 +233,11 @@ class Client # (constants defined in RubySMB::SMB2::CompressionCapabilities) attr_accessor :server_compression_algorithms + # The GUID of the server (SMB 2.x and 3.x). + # @!attribute [rw] server_guid + # @return [String] + attr_accessor :server_guid + # The server's start time if it is reported as part of the negotiation # process (SMB 2.x and 3.x). This value is nil if the server does not report # it (reports a value of 0). diff --git a/lib/ruby_smb/client/negotiation.rb b/lib/ruby_smb/client/negotiation.rb index a5797b551..20cc84c24 100644 --- a/lib/ruby_smb/client/negotiation.rb +++ b/lib/ruby_smb/client/negotiation.rb @@ -26,6 +26,7 @@ def negotiate end if response_packet && %w{0x0202 0x0210 0x0300 0x0302 0x0311 0x02ff}.include?(@dialect) + @server_guid = response_packet.server_guid if response_packet.server_start_time != 0 @server_start_time = response_packet.server_start_time.to_time end diff --git a/lib/ruby_smb/smb2/packet/negotiate_response.rb b/lib/ruby_smb/smb2/packet/negotiate_response.rb index faad4a5fb..066816cd8 100644 --- a/lib/ruby_smb/smb2/packet/negotiate_response.rb +++ b/lib/ruby_smb/smb2/packet/negotiate_response.rb @@ -15,7 +15,7 @@ class NegotiateResponse < RubySMB::GenericPacket uint16 :dialect_revision, label: 'Dialect Revision' uint16 :negotiate_context_count, label: 'Negotiate Context Count', initial_value: -> { negotiate_context_list.size }, onlyif: -> { has_negotiate_context? } uint16 :reserved1, label: 'Reserved', initial_value: 0, onlyif: -> { !has_negotiate_context? } - string :server_guid, label: 'Server GUID', length: 16 + string :server_guid, label: 'Server GUID', length: 16 smb2_capabilities :capabilities uint32 :max_transact_size, label: 'Max Transaction Size' uint32 :max_read_size, label: 'Max Read Size' From 2a61d9e628cf2262f68756f83df83fe5661ef0e8 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 12 Jun 2020 08:51:56 -0400 Subject: [PATCH 4/4] Move the additional server attributes to parse_negotiate_response --- lib/ruby_smb/client/negotiation.rb | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/ruby_smb/client/negotiation.rb b/lib/ruby_smb/client/negotiation.rb index 20cc84c24..b4d1f2239 100644 --- a/lib/ruby_smb/client/negotiation.rb +++ b/lib/ruby_smb/client/negotiation.rb @@ -25,16 +25,6 @@ def negotiate parse_smb3_encryption_data(request_packet, response_packet) end - if response_packet && %w{0x0202 0x0210 0x0300 0x0302 0x0311 0x02ff}.include?(@dialect) - @server_guid = response_packet.server_guid - if response_packet.server_start_time != 0 - @server_start_time = response_packet.server_start_time.to_time - end - if response_packet.system_time != 0 - @server_system_time = response_packet.system_time.to_time - end - end - # If the response contains the SMB2 wildcard revision number dialect; # it indicates that the server implements SMB 2.1 or future dialect # revisions and expects the client to send a subsequent SMB2 Negotiate @@ -148,6 +138,9 @@ def parse_negotiate_response(packet) # This value is used in SMB1 only but calculate a valid value anyway self.server_max_buffer_size = [self.server_max_read_size, self.server_max_write_size, self.server_max_transact_size].min self.negotiated_smb_version = self.smb2 ? 2 : 3 + self.server_guid = packet.server_guid + self.server_start_time = packet.server_start_time.to_time if packet.server_start_time != 0 + self.server_system_time = packet.system_time.to_time if packet.system_time != 0 return "SMB#{self.negotiated_smb_version}" else error = 'Unable to negotiate with remote host'