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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/examples/auth_capture.rb +28 -0
- data/examples/file_server.rb +76 -0
- data/lib/ruby_smb/create_actions.rb +21 -0
- data/lib/ruby_smb/field/nt_status.rb +20 -1
- data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +14 -0
- data/lib/ruby_smb/fscc/file_information/file_network_open_information.rb +22 -0
- data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +16 -0
- data/lib/ruby_smb/fscc/file_information.rb +29 -0
- data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +46 -0
- data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +19 -0
- data/lib/ruby_smb/fscc/file_system_information.rb +22 -0
- data/lib/ruby_smb/fscc.rb +1 -0
- data/lib/ruby_smb/generic_packet.rb +6 -0
- data/lib/ruby_smb/gss/provider/authenticator.rb +4 -0
- data/lib/ruby_smb/gss/provider/ntlm.rb +13 -3
- data/lib/ruby_smb/server/server_client/negotiation.rb +0 -2
- data/lib/ruby_smb/server/server_client/session_setup.rb +43 -32
- data/lib/ruby_smb/server/server_client/share_io.rb +28 -0
- data/lib/ruby_smb/server/server_client/tree_connect.rb +60 -0
- data/lib/ruby_smb/server/server_client.rb +214 -24
- data/lib/ruby_smb/server/session.rb +71 -0
- data/lib/ruby_smb/server/share/provider/disk.rb +437 -0
- data/lib/ruby_smb/server/share/provider/pipe.rb +27 -0
- data/lib/ruby_smb/server/share/provider/processor.rb +76 -0
- data/lib/ruby_smb/server/share/provider.rb +38 -0
- data/lib/ruby_smb/server/share.rb +11 -0
- data/lib/ruby_smb/server.rb +35 -3
- data/lib/ruby_smb/signing.rb +37 -11
- data/lib/ruby_smb/smb1/commands.rb +4 -0
- data/lib/ruby_smb/smb1.rb +0 -1
- data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +2 -1
- data/lib/ruby_smb/smb2/commands.rb +4 -0
- data/lib/ruby_smb/smb2/create_context/request.rb +64 -0
- data/lib/ruby_smb/smb2/create_context/response.rb +62 -0
- data/lib/ruby_smb/smb2/create_context.rb +74 -22
- data/lib/ruby_smb/smb2/packet/create_request.rb +44 -11
- data/lib/ruby_smb/smb2/packet/create_response.rb +17 -3
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +1 -1
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +2 -2
- data/lib/ruby_smb/smb2/packet/query_info_request.rb +43 -0
- data/lib/ruby_smb/smb2/packet/query_info_response.rb +23 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +1 -1
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/smb2.rb +11 -0
- data/lib/ruby_smb/smb_error.rb +110 -0
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +2 -0
- data/ruby_smb.gemspec +1 -1
- data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
- data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
- data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
- data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
- data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
- data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
- data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
- data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
- data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
- data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
- data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
- data.tar.gz.sig +0 -0
- metadata +35 -7
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/create_actions.rb +0 -20
data/lib/ruby_smb/signing.rb
CHANGED
@@ -8,24 +8,35 @@ module RubySMB
|
|
8
8
|
|
9
9
|
# Take an SMB1 packet and sign it.
|
10
10
|
#
|
11
|
-
# @param
|
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
|
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
|
51
|
+
# @param [RubySMB::GenericPacket] packet The packet to sign.
|
40
52
|
# @return [RubySMB::GenericPacket] the signed packet
|
41
53
|
def smb3_sign(packet)
|
42
|
-
|
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(
|
69
|
+
signing_key = Crypto::KDF.counter_mode(session_key, "SMB2AESCMAC\x00", "SmbSign\x00")
|
45
70
|
when '0x0311'
|
46
|
-
|
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 #{
|
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
|
data/lib/ruby_smb/smb1.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
39
|
-
create_options
|
40
|
-
uint16
|
41
|
-
uint16
|
42
|
-
uint32
|
43
|
-
uint32
|
44
|
-
|
45
|
-
|
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
|
-
|
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 :
|
25
|
-
uint32 :
|
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
|
-
|
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
|
-
|
24
|
+
file_access_mask :maximal_access, label: 'Maximal Access'
|
25
25
|
|
26
26
|
def initialize_instance
|
27
27
|
super
|
data/lib/ruby_smb/smb2/packet.rb
CHANGED
@@ -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'
|