ruby_smb 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/examples/auth_capture.rb +28 -0
  4. data/examples/file_server.rb +76 -0
  5. data/lib/ruby_smb/create_actions.rb +21 -0
  6. data/lib/ruby_smb/field/nt_status.rb +20 -1
  7. data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +14 -0
  8. data/lib/ruby_smb/fscc/file_information/file_network_open_information.rb +22 -0
  9. data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +16 -0
  10. data/lib/ruby_smb/fscc/file_information.rb +29 -0
  11. data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +46 -0
  12. data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +19 -0
  13. data/lib/ruby_smb/fscc/file_system_information.rb +22 -0
  14. data/lib/ruby_smb/fscc.rb +1 -0
  15. data/lib/ruby_smb/generic_packet.rb +6 -0
  16. data/lib/ruby_smb/gss/provider/authenticator.rb +4 -0
  17. data/lib/ruby_smb/gss/provider/ntlm.rb +13 -3
  18. data/lib/ruby_smb/server/server_client/negotiation.rb +0 -2
  19. data/lib/ruby_smb/server/server_client/session_setup.rb +43 -32
  20. data/lib/ruby_smb/server/server_client/share_io.rb +28 -0
  21. data/lib/ruby_smb/server/server_client/tree_connect.rb +60 -0
  22. data/lib/ruby_smb/server/server_client.rb +214 -24
  23. data/lib/ruby_smb/server/session.rb +71 -0
  24. data/lib/ruby_smb/server/share/provider/disk.rb +437 -0
  25. data/lib/ruby_smb/server/share/provider/pipe.rb +27 -0
  26. data/lib/ruby_smb/server/share/provider/processor.rb +76 -0
  27. data/lib/ruby_smb/server/share/provider.rb +38 -0
  28. data/lib/ruby_smb/server/share.rb +11 -0
  29. data/lib/ruby_smb/server.rb +35 -3
  30. data/lib/ruby_smb/signing.rb +37 -11
  31. data/lib/ruby_smb/smb1/commands.rb +4 -0
  32. data/lib/ruby_smb/smb1.rb +0 -1
  33. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +2 -1
  34. data/lib/ruby_smb/smb2/commands.rb +4 -0
  35. data/lib/ruby_smb/smb2/create_context/request.rb +64 -0
  36. data/lib/ruby_smb/smb2/create_context/response.rb +62 -0
  37. data/lib/ruby_smb/smb2/create_context.rb +74 -22
  38. data/lib/ruby_smb/smb2/packet/create_request.rb +44 -11
  39. data/lib/ruby_smb/smb2/packet/create_response.rb +17 -3
  40. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +1 -1
  41. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +2 -2
  42. data/lib/ruby_smb/smb2/packet/query_info_request.rb +43 -0
  43. data/lib/ruby_smb/smb2/packet/query_info_response.rb +23 -0
  44. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +1 -1
  45. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -0
  46. data/lib/ruby_smb/smb2/packet.rb +2 -0
  47. data/lib/ruby_smb/smb2.rb +11 -0
  48. data/lib/ruby_smb/smb_error.rb +110 -0
  49. data/lib/ruby_smb/version.rb +1 -1
  50. data/lib/ruby_smb.rb +2 -0
  51. data/ruby_smb.gemspec +1 -1
  52. data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
  53. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
  54. data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
  55. data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
  56. data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
  57. data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
  58. data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
  59. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
  60. data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
  61. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
  62. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
  63. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
  64. data.tar.gz.sig +0 -0
  65. metadata +35 -7
  66. metadata.gz.sig +0 -0
  67. data/lib/ruby_smb/smb1/create_actions.rb +0 -20
@@ -8,24 +8,35 @@ module RubySMB
8
8
 
9
9
  # Take an SMB1 packet and sign it.
10
10
  #
11
- # @param packet [RubySMB::GenericPacket] the packet to sign
11
+ # @param [RubySMB::GenericPacket] packet The packet to sign.
12
12
  # @return [RubySMB::GenericPacket] the signed packet
13
13
  def smb1_sign(packet)
14
14
  # Pack the Sequence counter into a int64le
15
- packed_sequence_counter = [sequence_counter].pack('Q<')
15
+ packed_sequence_counter = [@sequence_counter].pack('Q<')
16
16
  packet.smb_header.security_features = packed_sequence_counter
17
- signature = OpenSSL::Digest::MD5.digest(session_key + packet.to_binary_s)[0, 8]
17
+ signature = OpenSSL::Digest::MD5.digest(@session_key + packet.to_binary_s)[0, 8]
18
18
  packet.smb_header.security_features = signature
19
19
  @sequence_counter += 1
20
20
 
21
21
  packet
22
22
  end
23
23
 
24
- # Take an SMB2 packet and sign it.
24
+ # Take an SMB2 packet and sign it. This version is an instance method that
25
+ # accesses the necessary values from the object instance.
25
26
  #
26
- # @param packet [RubySMB::GenericPacket] the packet to sign
27
+ # @param [RubySMB::GenericPacket] packet The packet to sign.
27
28
  # @return [RubySMB::GenericPacket] the signed packet
28
29
  def smb2_sign(packet)
30
+ Signing::smb2_sign(packet, @session_key)
31
+ end
32
+
33
+ # Take an SMB2 packet and sign it. This version is a module function that
34
+ # requires the necessary values to be explicitly passed to it.
35
+ #
36
+ # @param [RubySMB::GenericPacket] packet The packet to sign.
37
+ # @param [String] session_key The key to use for signing.
38
+ # @return [RubySMB::GenericPacket] the signed packet
39
+ def self.smb2_sign(packet, session_key)
29
40
  packet.smb2_header.flags.signed = 1
30
41
  packet.smb2_header.signature = "\x00" * 16
31
42
  hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), session_key, packet.to_binary_s)
@@ -34,18 +45,33 @@ module RubySMB
34
45
  packet
35
46
  end
36
47
 
37
- # Take an SMB3 packet and sign it.
48
+ # Take an SMB3 packet and sign it. This version is an instance method that
49
+ # accesses the necessary values from the object instance.
38
50
  #
39
- # @param packet [RubySMB::GenericPacket] the packet to sign
51
+ # @param [RubySMB::GenericPacket] packet The packet to sign.
40
52
  # @return [RubySMB::GenericPacket] the signed packet
41
53
  def smb3_sign(packet)
42
- case @dialect
54
+ Signing::smb3_sign(packet, @session_key, @dialect, @preauth_integrity_hash_value)
55
+ end
56
+
57
+ # Take an SMB3 packet and sign it. This version is a module function that
58
+ # requires the necessary values to be explicitly passed to it.
59
+ #
60
+ # @param [RubySMB::GenericPacket] packet The packet to sign.
61
+ # @param [String] session_key The key to use for signing.
62
+ # @param [String] dialect The SMB3 dialect to sign for.
63
+ # @param [String] preauth_integrity_hash The preauth integrity hash as
64
+ # required by the 3.1.1 dialect.
65
+ # @return [RubySMB::GenericPacket] the signed packet
66
+ def self.smb3_sign(packet, session_key, dialect, preauth_integrity_hash=nil)
67
+ case dialect
43
68
  when '0x0300', '0x0302'
44
- signing_key = Crypto::KDF.counter_mode(@session_key, "SMB2AESCMAC\x00", "SmbSign\x00")
69
+ signing_key = Crypto::KDF.counter_mode(session_key, "SMB2AESCMAC\x00", "SmbSign\x00")
45
70
  when '0x0311'
46
- signing_key = Crypto::KDF.counter_mode(@session_key, "SMBSigningKey\x00", @preauth_integrity_hash_value)
71
+ raise ArgumentError.new('the preauth integrity hash is required for the specified dialect') if preauth_integrity_hash.nil?
72
+ signing_key = Crypto::KDF.counter_mode(session_key, "SMBSigningKey\x00", preauth_integrity_hash)
47
73
  else
48
- raise Error::SigningError.new("Dialect #{@dialect.inspect} is incompatible with SMBv3 signing")
74
+ raise Error::SigningError.new("Dialect #{dialect.inspect} is incompatible with SMBv3 signing")
49
75
  end
50
76
 
51
77
  packet.smb2_header.flags.signed = 1
@@ -17,6 +17,10 @@ module RubySMB
17
17
  SMB_COM_NT_TRANSACT_SECONDARY = 0xA1
18
18
  SMB_COM_NT_CREATE_ANDX = 0xA2
19
19
  SMB_COM_NO_ANDX_COMMAND = 0xFF
20
+
21
+ def self.name(value)
22
+ constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
23
+ end
20
24
  end
21
25
  end
22
26
  end
data/lib/ruby_smb/smb1.rb CHANGED
@@ -5,7 +5,6 @@ module RubySMB
5
5
  # Protocol ID value. Translates to \xFFSMB
6
6
  SMB_PROTOCOL_ID = 0xFF534D42
7
7
 
8
- require 'ruby_smb/smb1/create_actions'
9
8
  require 'ruby_smb/smb1/oplock_levels'
10
9
  require 'ruby_smb/smb1/resource_type'
11
10
  require 'ruby_smb/smb1/commands'
@@ -5,7 +5,8 @@ module RubySMB
5
5
  # [2.2.1.2 SMB2 Packet Header - SYNC](https://msdn.microsoft.com/en-us/library/cc246529.aspx)
6
6
  class Smb2HeaderFlags < BinData::Record
7
7
  endian :little
8
- bit4 :reserved3, label: 'Reserved', initial_value: 0
8
+ bit1 :reserved3, label: 'Reserved', initial_value: 0
9
+ bit3 :priority, label: 'Priority'
9
10
  bit1 :signed, label: 'Packet Signed'
10
11
  bit1 :related_operations, label: 'Chained Request'
11
12
  bit1 :async_command, label: 'ASYNC Command', initial_value: 0
@@ -20,6 +20,10 @@ module RubySMB
20
20
  CHANGE_NOTIFY = 0x0f
21
21
  QUERY_INFO = 0x10
22
22
  SET_INFO = 0x11
23
+
24
+ def self.name(value)
25
+ constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
26
+ end
23
27
  end
24
28
  end
25
29
  end
@@ -0,0 +1,64 @@
1
+ require 'ruby_smb/dcerpc/uuid'
2
+
3
+ module RubySMB
4
+ module SMB2
5
+ module CreateContext
6
+ # [2.2.13.2.3 SMB2_CREATE_DURABLE_HANDLE_REQUEST](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/9999d870-b664-4e51-a187-1c3c16a1ae1c)
7
+ class CreateDurableHandleRequest < BinData::Record
8
+ NAME = CREATE_DURABLE_HANDLE
9
+
10
+ endian :little
11
+ string :reserved, label: 'Reserved', length: 16
12
+ end
13
+
14
+ # [2.2.13.2.11 SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5e361a29-81a7-4774-861d-f290ea53a00e)
15
+ class CreateDurableHandleV2Request < BinData::Record
16
+ NAME = CREATE_DURABLE_HANDLE_V2
17
+
18
+ endian :little
19
+ uint32 :timeout, label: 'Timeout'
20
+ struct :flags, label: 'Flags' do
21
+ bit6 :reserved
22
+ bit1 :persistent, label: 'Persistent Handle'
23
+ bit1 :reserved1
24
+ skip length: 3
25
+ end
26
+ string :reserved, length: 8
27
+ uuid :create_guid, label: 'Create GUID'
28
+ end
29
+
30
+ # [2.2.13.2.5 SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5ea40835-5d40-4e85-977d-13cd745d3af8)
31
+ class CreateQueryMaximalAccessRequest < BinData::Record
32
+ NAME = CREATE_QUERY_MAXIMAL_ACCESS
33
+
34
+ default_parameter length: 0
35
+
36
+ endian :little
37
+ file_time :timestamp, label: 'Timestamp', onlyif: -> { length != 0 }
38
+ end
39
+
40
+ # [2.2.13.2.9 SMB2_CREATE_QUERY_ON_DISK_ID](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/6eb9162a-3278-4513-988a-6b52bed30fc3)
41
+ class CreateQueryOnDiskIdRequest < BinData::Record
42
+ NAME = CREATE_QUERY_ON_DISK_ID
43
+
44
+ endian :little
45
+ end
46
+
47
+ class CreateContextRequest < CreateContext
48
+ delayed_io :data, read_abs_offset: -> { abs_offset + data_offset } do
49
+ choice :data, selection: -> { name.snapshot } do
50
+ create_durable_handle_request CREATE_DURABLE_HANDLE, length: :data_length
51
+ create_durable_handle_v2_request CREATE_DURABLE_HANDLE_V2, length: :data_length
52
+ create_query_maximal_access_request CREATE_QUERY_MAXIMAL_ACCESS, length: :data_length
53
+ create_query_on_disk_id_request CREATE_QUERY_ON_DISK_ID, length: :data_length
54
+ string :default, read_length: :data_length
55
+ end
56
+ end
57
+ end
58
+
59
+ class CreateContextArrayRequest < CreateContextArray
60
+ default_parameters type: :create_context_request
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module CreateContext
4
+ # [2.2.14.2.3 SMB2_CREATE_DURABLE_HANDLE_RESPONSE](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/a3a11598-f228-47da-82bb-9418b9397041)
5
+ class CreateDurableHandleResponse < BinData::Record
6
+ NAME = CREATE_DURABLE_HANDLE
7
+
8
+ endian :little
9
+ string :reserved, label: 'Reserved', length: 8
10
+ end
11
+
12
+ # [2.2.14.2.12 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/48c1049f-25a4-4f23-9a57-11ddd72ce985)
13
+ class CreateDurableHandleV2Response < BinData::Record
14
+ NAME = CREATE_DURABLE_HANDLE_V2
15
+
16
+ endian :little
17
+ uint32 :timeout, label: 'Timeout'
18
+ struct :flags, label: 'Flags' do
19
+ bit6 :reserved
20
+ bit1 :persistent, label: 'Persistent Handle'
21
+ bit1 :reserved1
22
+ skip length: 3
23
+ end
24
+ end
25
+
26
+ # [2.2.14.2.5 SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/0fe6be15-3a76-4032-9a44-56f846ac6244)
27
+ class CreateQueryMaximalAccessResponse < BinData::Record
28
+ NAME = CREATE_QUERY_MAXIMAL_ACCESS
29
+
30
+ endian :little
31
+ nt_status :query_status, label: 'Query Status'
32
+ file_access_mask :maximal_access, label: 'Maximal Access'
33
+ end
34
+
35
+ # [2.2.14.2.9 SMB2_CREATE_QUERY_ON_DISK_ID](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5c977939-1d8f-4774-9111-21e9195f3aca)
36
+ class CreateQueryOnDiskIdResponse < BinData::Record
37
+ NAME = CREATE_QUERY_ON_DISK_ID
38
+
39
+ endian :little
40
+ uint64 :disk_file_id, label: 'Disk File Id', initial_value: 0xffffffffffffffff
41
+ uint64 :volume_id, label: 'Volume Id'
42
+ string :reserved, label: 'Reserved', length: 16
43
+ end
44
+
45
+ class CreateContextResponse < CreateContext
46
+ delayed_io :data, read_abs_offset: -> { abs_offset + data_offset } do
47
+ choice :data, selection: -> { name.snapshot } do
48
+ create_durable_handle_response CREATE_DURABLE_HANDLE, length: :data_length
49
+ create_durable_handle_v2_response CREATE_DURABLE_HANDLE_V2, length: :data_length
50
+ create_query_maximal_access_response CREATE_QUERY_MAXIMAL_ACCESS, length: :data_length
51
+ create_query_on_disk_id_response CREATE_QUERY_ON_DISK_ID, length: :data_length
52
+ string :default, read_length: :data_length
53
+ end
54
+ end
55
+ end
56
+
57
+ class CreateContextArrayResponse < CreateContextArray
58
+ default_parameters type: :create_context_response
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,29 +1,81 @@
1
1
  module RubySMB
2
2
  module SMB2
3
- # An SMB2_CREATE_CONTEXT struct as defined in
4
- # [2.2.13.2 SMB2_CREATE_CONTEXT Request Values](https://msdn.microsoft.com/en-us/library/cc246504.aspx)
5
- class CreateContext < BinData::Record
6
- endian :little
7
-
8
- uint32 :next_offset, label: 'Offset to next Context'
9
- uint16 :name_offset, label: 'Offset to Name/Tag', initial_value: -> { name.rel_offset }
10
- uint16 :name_length, label: 'Length of Name/Tag', initial_value: -> { name.length }
11
- uint16 :reserved, label: 'Reserved Space'
12
- uint16 :data_offset, label: 'Offset to data', initial_value: -> { calc_data_offset }
13
- uint32 :data_length, label: 'Length of data', initial_value: -> { data.length }
14
- string :name, label: 'Name'
15
- uint32 :reserved2, label: 'Reserved Space'
16
- string :data, label: 'Data'
17
-
18
- private
19
-
20
- def calc_data_offset
21
- if data.empty?
22
- 0
23
- else
24
- data.rel_offset
3
+ module CreateContext
4
+ # Create name constants. Requests and responses have a shared name but some have different structures. Names are
5
+ # normalized to remove the request/response portion.
6
+ # [2.2.13.2 SMB2_CREATE_CONTEXT Request Values](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/75364667-3a93-4e2c-b771-592d8d5e876d)
7
+ CREATE_EA_BUFFER = 'ExtA'.freeze
8
+ CREATE_SD_BUFFER = 'SecD'.freeze
9
+ CREATE_DURABLE_HANDLE = 'DHnQ'.freeze
10
+ CREATE_DURABLE_HANDLE_RECONNECT = 'DHnC'.freeze
11
+ CREATE_ALLOCATION_SIZE = 'AISi'.freeze
12
+ CREATE_QUERY_MAXIMAL_ACCESS = 'MxAc'.freeze
13
+ CREATE_TIMEWARP_TOKEN = 'TWrp'.freeze
14
+ CREATE_QUERY_ON_DISK_ID = 'QFid'.freeze
15
+ CREATE_LEASE = 'RqLs'.freeze
16
+ CREATE_LEASE_V2 = 'RqLs'.freeze
17
+ CREATE_DURABLE_HANDLE_V2 = 'DH2Q'.freeze
18
+ CREATE_DURABLE_HANDLE_RECONNECT_v2 = 'DH2C'.freeze
19
+ CREATE_APP_INSTANCE_ID = "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74".b.freeze
20
+ CREATE_APP_INSTANCE_VERSION = "\xB9\x82\xD0\xB7\x3B\x56\x07\x4F\xA0\x7B\x52\x4A\x81\x16\xA0\x10".b.freeze
21
+ SVHDX_OPEN_DEVICE_CONTEXT = "\x9C\xCB\xCF\x9E\x04\xC1\xE6\x43\x98\x0E\x15\x8D\xA1\xF6\xEC\x83".b.freeze
22
+
23
+ # An SMB2_CREATE_CONTEXT struct as defined in
24
+ # [2.2.13.2 SMB2_CREATE_CONTEXT Request Values](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/75364667-3a93-4e2c-b771-592d8d5e876d?redirectedfrom=MSDN)
25
+ class CreateContext < BinData::Record
26
+ unregister_self
27
+
28
+ endian :little
29
+ uint32 :next_offset, label: 'Offset to next Context'
30
+ uint16 :name_offset, label: 'Offset to Name/Tag', initial_value: -> { buffer.rel_offset }
31
+ uint16 :name_length, label: 'Length of Name/Tag', initial_value: -> { name.num_bytes }
32
+ uint16 :reserved, label: 'Reserved Space'
33
+ uint16 :data_offset, label: 'Offset to data', initial_value: -> { calc_data_offset }
34
+ uint32 :data_length, label: 'Length of data', initial_value: -> { data.num_bytes }
35
+ string :buffer, label: 'Buffer', initial_value: -> { build_buffer }, read_length: -> { calc_buffer_size }
36
+
37
+ delayed_io :name, read_abs_offset: -> { abs_offset + name_offset } do
38
+ string :name, label: 'Name', read_length: :name_length
39
+ end
40
+
41
+ private
42
+
43
+ def build_buffer
44
+ align = 8
45
+ buf = name.dup.tap { |obj| obj.abs_offset = 0 }.to_binary_s { |obj| obj.write_now! }
46
+ buf << "\x00".b * ((align - buf.length % align) % align)
47
+ buf << data.dup.tap { |obj| obj.abs_offset = 0 }.to_binary_s { |obj| obj.write_now! }
48
+ buf << "\x00".b * ((align - buf.length % align) % align)
49
+ end
50
+
51
+ def calc_buffer_size
52
+ align = 8
53
+ size = 0
54
+ size += name_length + ((align - name_length % align) % align)
55
+ size += data_length + ((align - data_length % align) % align)
56
+ size
57
+ end
58
+
59
+ def calc_data_offset
60
+ if data.num_bytes == 0
61
+ 0
62
+ else
63
+ align = 8
64
+ buffer.rel_offset + name_length + ((align - name_length % align) % align)
65
+ end
25
66
  end
26
67
  end
68
+
69
+ class CreateContextArray < BinData::Array
70
+ unregister_self
71
+
72
+ default_parameters read_until: -> { element&.next_offset == 0 }
73
+ endian :little
74
+ end
27
75
  end
28
76
  end
29
77
  end
78
+
79
+ require 'ruby_smb/smb2/bit_field'
80
+ require 'ruby_smb/smb2/create_context/request'
81
+ require 'ruby_smb/smb2/create_context/response'
@@ -4,9 +4,8 @@ module RubySMB
4
4
  # An SMB2 Create Request Packet as defined in
5
5
  # [2.2.13 SMB2 CREATE Request](https://msdn.microsoft.com/en-us/library/cc246502.aspx)
6
6
  class CreateRequest < RubySMB::GenericPacket
7
- COMMAND = RubySMB::SMB2::Commands::CREATE
8
-
9
7
  require 'ruby_smb/smb1/bit_field/create_options'
8
+ COMMAND = RubySMB::SMB2::Commands::CREATE
10
9
 
11
10
  endian :little
12
11
  smb2_header :smb2_header
@@ -35,17 +34,51 @@ module RubySMB
35
34
  bit8 :reserved4, label: 'Reserved Space'
36
35
  end
37
36
 
38
- uint32 :create_disposition, label: 'Create Disposition'
39
- create_options :create_options
40
- uint16 :name_offset, label: 'Name Offset', initial_value: -> { name.abs_offset }
41
- uint16 :name_length, label: 'Name Length', initial_value: -> { name.do_num_bytes }
42
- uint32 :context_offset, label: 'Create Context Offset', initial_value: -> { context.abs_offset }
43
- uint32 :context_length, label: 'Create Context Length', initial_value: -> { context.do_num_bytes }
44
- string16 :name, label: 'File Name'
45
- uint32 :reserved5, label: 'Reserved Space'
37
+ uint32 :create_disposition, label: 'Create Disposition'
38
+ create_options :create_options
39
+ uint16 :name_offset, label: 'Name Offset', initial_value: -> { calc_name_offset }
40
+ uint16 :name_length, label: 'Name Length', initial_value: -> { name.num_bytes }
41
+ uint32 :contexts_offset, label: 'Create Contexts Offset', initial_value: -> { calc_contexts_offset }
42
+ uint32 :contexts_length, label: 'Create Contexts Length'
43
+ count_bytes_remaining :bytes_remaining
44
+ string :buffer, label: 'Buffer', initial_value: -> { build_buffer }, read_length: :bytes_remaining
45
+
46
+ delayed_io :name, label: 'File Name', read_abs_offset: :name_offset do
47
+ string16 read_length: :name_length
48
+ end
49
+
50
+ delayed_io :contexts, label: 'Context Array', read_abs_offset: :contexts_offset, onlyif: -> { contexts_offset != 0 } do
51
+ buffer length: :contexts_length do
52
+ create_context_array_request :contexts
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def build_buffer
59
+ align = 8
60
+ buf = name.dup.tap { |obj| obj.abs_offset = 0 }.to_binary_s { |obj| obj.write_now! }
61
+ buf << "\x00".b * ((align - buf.length % align) % align)
62
+ buf << contexts.map(&:to_binary_s).join
63
+ buf << "\x00".b * ((align - buf.length % align) % align)
64
+ end
46
65
 
47
- array :context, label: 'Contexts', type: :create_context, read_until: :eof
66
+ def calc_contexts_offset
67
+ if contexts.num_bytes == 0
68
+ 0
69
+ else
70
+ align = 8
71
+ buffer.rel_offset + name_length + ((align - name_length % align) % align)
72
+ end
73
+ end
48
74
 
75
+ def calc_name_offset
76
+ if name.num_bytes == 0
77
+ 0
78
+ else
79
+ buffer.rel_offset
80
+ end
81
+ end
49
82
  end
50
83
  end
51
84
  end
@@ -21,15 +21,29 @@ module RubySMB
21
21
  file_attributes :file_attributes, label: 'File Attributes'
22
22
  uint32 :reserved, label: 'Reserved Space'
23
23
  smb2_fileid :file_id, label: 'File ID'
24
- uint32 :context_offset, label: 'Create Context Offset', initial_value: -> { context.abs_offset }
25
- uint32 :context_length, label: 'Create Context Length', initial_value: -> { context.do_num_bytes }
24
+ uint32 :contexts_offset, label: 'Create Contexts Offset'
25
+ uint32 :contexts_length, label: 'Create Contexts Length'
26
+ count_bytes_remaining :bytes_remaining
27
+ string :buffer, label: 'Buffer', initial_value: -> { build_buffer }, read_length: :bytes_remaining
26
28
 
27
- array :context, label: 'Contexts', type: :create_context, read_until: :eof
29
+ delayed_io :contexts, label: 'Context Array', read_abs_offset: -> { contexts_offset }, onlyif: -> { contexts_offset != 0 } do
30
+ buffer length: :contexts_length do
31
+ create_context_array_response :contexts
32
+ end
33
+ end
28
34
 
29
35
  def initialize_instance
30
36
  super
31
37
  smb2_header.flags.reply = 1
32
38
  end
39
+
40
+ private
41
+
42
+ def build_buffer
43
+ align = 8
44
+ buf = contexts.map(&:to_binary_s).join
45
+ buf << "\x00".b * ((align - buf.length % align) % align)
46
+ end
33
47
  end
34
48
  end
35
49
  end
@@ -25,7 +25,7 @@ module RubySMB
25
25
  uint16 :name_offset, label: 'File Name Offset', initial_value: -> { name.abs_offset }
26
26
  uint16 :name_length, label: 'File Name Length', initial_value: -> { name.do_num_bytes }
27
27
  uint32 :output_length, label: 'Output Buffer Length'
28
- string16 :name, label: 'Name/Search Pattern'
28
+ string16 :name, label: 'Name/Search Pattern', read_length: :name_length
29
29
 
30
30
  end
31
31
  end
@@ -9,8 +9,8 @@ module RubySMB
9
9
  endian :little
10
10
  smb2_header :smb2_header
11
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 9
12
- uint16 :buffer_offset, label: 'Output Buffer Offset', initial_value: -> { buffer.abs_offset }
13
- uint32 :buffer_length, label: 'Output Buffer Length', initial_value: -> { buffer.do_num_bytes }
12
+ uint16 :buffer_offset, label: 'Output Buffer Offset', initial_value: -> { buffer.empty? ? 0 : buffer.abs_offset }
13
+ uint32 :buffer_length, label: 'Output Buffer Length', initial_value: -> { buffer.empty? ? 0 : buffer.do_num_bytes }
14
14
  string :buffer, read_length: -> { buffer_length }
15
15
 
16
16
  def initialize_instance
@@ -0,0 +1,43 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Query Info Request Packet as defined in
5
+ # [2.2.37 SMB2 QUERY_INFO Request](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/d623b2f7-a5cd-4639-8cc9-71fa7d9f9ba9)
6
+ class QueryInfoRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::QUERY_INFO
8
+
9
+ endian :little
10
+ smb2_header :smb2_header
11
+ uint16 :structure_size, label: 'Structure Size', initial_value: 41
12
+ uint8 :info_type, label: 'Information Type'
13
+ uint8 :file_information_class, label: 'File Information Class'
14
+ uint32 :output_buffer_length, label: 'Output Buffer Length'
15
+ uint16 :input_buffer_offset, label: 'Input Buffer Offset'
16
+ uint16 :reserved, label: 'Reserved Space'
17
+ uint32 :input_buffer_length, label: 'Input Buffer Length'
18
+ struct :additional_information do
19
+ bit1 :reserved1
20
+ bit1 :scope_security_information, label: 'Scope Security Information'
21
+ bit1 :attribute_security_information, label: 'Attribute Security Information'
22
+ bit1 :label_security_information, label: 'Label Security Information'
23
+ bit1 :sacl_security_information, label: 'SACL Security Information'
24
+ bit1 :dacl_security_information, label: 'DACL Security Information'
25
+ bit1 :group_security_information, label: 'Group Security Information'
26
+ bit1 :owner_security_information, label: 'Owner Security Information'
27
+ bit7 :reserved2
28
+ bit1 :backup_security_information, label: 'Backup Security Information'
29
+ skip length: 2
30
+ end
31
+ struct :flags do
32
+ bit5 :reserved
33
+ bit1 :sl_index_specified, label: 'Index Specified'
34
+ bit1 :sl_return_single_entry, label: 'Return Single Entry'
35
+ bit1 :sl_restart_scan, label: 'Restart Scan'
36
+ skip length: 3
37
+ end
38
+ smb2_fileid :file_id, label: 'File ID'
39
+ string :buffer, label: 'Buffer'
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Query Info Response Packet as defined in
5
+ # [2.2.38 SMB2 QUERY_INFO Response](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/3b1b3598-a898-44ca-bfac-2dcae065247f)
6
+ class QueryInfoResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::QUERY_INFO
8
+
9
+ endian :little
10
+ smb2_header :smb2_header
11
+ uint16 :structure_size, label: 'Structure Size', initial_value: 9
12
+ uint16 :buffer_offset, label: 'Output Buffer Offset', initial_value: -> { buffer.empty? ? 0 : buffer.abs_offset }
13
+ uint32 :buffer_length, label: 'Output Buffer Length', initial_value: -> { buffer.empty? ? 0 : buffer.do_num_bytes }
14
+ string :buffer, read_length: -> { buffer_length }
15
+
16
+ def initialize_instance
17
+ super
18
+ smb2_header.flags.reply = 1
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -21,7 +21,7 @@ module RubySMB
21
21
  uint8 :reserved, label: 'Reserved Space', initial_value: 0x00
22
22
  share_flags :share_flags
23
23
  share_capabilities :capabilities
24
- directory_access_mask :maximal_access, label: 'Maximal Access'
24
+ file_access_mask :maximal_access, label: 'Maximal Access'
25
25
 
26
26
  def initialize_instance
27
27
  super
@@ -9,6 +9,7 @@ module RubySMB
9
9
  endian :little
10
10
  smb2_header :smb2_header
11
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 4
12
+ uint16 :reserved, label: 'Reserved', initial_value: 0
12
13
 
13
14
  def initialize_instance
14
15
  super
@@ -32,6 +32,8 @@ module RubySMB
32
32
  require 'ruby_smb/smb2/packet/ioctl_response'
33
33
  require 'ruby_smb/smb2/packet/transform_header'
34
34
  require 'ruby_smb/smb2/packet/compression_transform_header'
35
+ require 'ruby_smb/smb2/packet/query_info_request'
36
+ require 'ruby_smb/smb2/packet/query_info_response'
35
37
  end
36
38
  end
37
39
  end
data/lib/ruby_smb/smb2.rb CHANGED
@@ -8,6 +8,17 @@ module RubySMB
8
8
  # Wildcard revision, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/63abf97c-0d09-47e2-88d6-6bfa552949a5
9
9
  SMB2_WILDCARD_REVISION = 0x02ff
10
10
 
11
+ # Channel types, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/320f04f3-1b28-45cd-aaa1-9e5aed810dca
12
+ SMB2_CHANNEL_NONE = 0
13
+ SMB2_CHANNEL_RDMA_V1 = 1
14
+ SMB2_CHANNEL_RDMA_V1_INVALIDATE = 2
15
+
16
+ # Information types, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/d623b2f7-a5cd-4639-8cc9-71fa7d9f9ba9
17
+ SMB2_INFO_FILE = 1
18
+ SMB2_INFO_FILESYSTEM = 2
19
+ SMB2_INFO_SECURITY = 3
20
+ SMB2_INFO_QUOTA = 4
21
+
11
22
  require 'ruby_smb/smb2/info_type'
12
23
  require 'ruby_smb/smb2/commands'
13
24
  require 'ruby_smb/smb2/create_context'