ruby_smb 3.0.6 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/ruby_smb/client/encryption.rb +16 -4
- data/lib/ruby_smb/client/negotiation.rb +3 -1
- data/lib/ruby_smb/fscc/file_information.rb +4 -0
- data/lib/ruby_smb/server/server_client/encryption.rb +66 -0
- data/lib/ruby_smb/server/server_client/negotiation.rb +14 -3
- data/lib/ruby_smb/server/server_client/session_setup.rb +18 -3
- data/lib/ruby_smb/server/server_client/share_io.rb +17 -0
- data/lib/ruby_smb/server/server_client/tree_connect.rb +40 -3
- data/lib/ruby_smb/server/server_client.rb +147 -37
- data/lib/ruby_smb/server/share/provider/disk/file_system.rb +28 -0
- data/lib/ruby_smb/server/share/provider/disk/processor/close.rb +42 -0
- data/lib/ruby_smb/server/share/provider/disk/processor/create.rb +143 -0
- data/lib/ruby_smb/server/share/provider/disk/processor/query.rb +359 -0
- data/lib/ruby_smb/server/share/provider/disk/processor/read.rb +69 -0
- data/lib/ruby_smb/server/share/provider/disk/processor.rb +159 -0
- data/lib/ruby_smb/server/share/provider/disk.rb +4 -416
- data/lib/ruby_smb/server/share/provider/pipe.rb +2 -2
- data/lib/ruby_smb/server/share/provider/processor.rb +16 -0
- data/lib/ruby_smb/signing.rb +18 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -0
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +11 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +5 -4
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +12 -4
- data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +9 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +52 -51
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +37 -37
- data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_both_directory_info.rb +48 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +28 -15
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +51 -51
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +36 -36
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +40 -39
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +40 -40
- data/lib/ruby_smb/smb1/packet/trans2/query_file_information_request.rb +60 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_file_information_response.rb +59 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level/query_fs_attribute_info.rb +31 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level.rb +40 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request.rb +46 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response.rb +59 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_basic_info.rb +23 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_standard_info.rb +22 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_information_level.rb +62 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_path_information_request.rb +65 -0
- data/lib/ruby_smb/smb1/packet/trans2/query_path_information_response.rb +59 -0
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +24 -8
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +4 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +29 -20
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +42 -42
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +23 -23
- data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +23 -5
- data/lib/ruby_smb/smb1/packet/trans2.rb +4 -0
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -1
- data/lib/ruby_smb/smb2/negotiate_context.rb +10 -1
- data/lib/ruby_smb/smb2/packet/transform_header.rb +7 -7
- data/lib/ruby_smb/smb2.rb +1 -0
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +20 -6
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +36 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +35 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_request_spec.rb +74 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_response_spec.rb +96 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request_spec.rb +62 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response_spec.rb +88 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_request_spec.rb +79 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_response_spec.rb +96 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +3 -3
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +3 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +7 -2
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
- data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +33 -2
- metadata.gz.sig +0 -0
@@ -8,7 +8,7 @@ module RubySMB
|
|
8
8
|
hide :reserved0
|
9
9
|
|
10
10
|
endian :little
|
11
|
-
bit32 :protocol, label: 'Protocol ID Field', initial_value:
|
11
|
+
bit32 :protocol, label: 'Protocol ID Field', initial_value: RubySMB::SMB2::SMB2_TRANSFORM_PROTOCOL_ID
|
12
12
|
string :signature, label: 'Signature', length: 16
|
13
13
|
string :nonce, label: 'Nonce', length: 16
|
14
14
|
uint32 :original_message_size, label: 'Original Message Size'
|
@@ -22,13 +22,13 @@ module RubySMB
|
|
22
22
|
encrypted_data = self.encrypted_data.to_ary.pack('C*')
|
23
23
|
|
24
24
|
case algorithm
|
25
|
-
when 'AES-128-CCM'
|
25
|
+
when 'AES-128-CCM', 'AES-256-CCM'
|
26
26
|
cipher = OpenSSL::CCM.new('AES', key, 16)
|
27
27
|
unencrypted_data = cipher.decrypt(encrypted_data + self.signature, self.nonce[0...11], auth_data)
|
28
28
|
unless unencrypted_data.length > 0
|
29
29
|
raise OpenSSL::Cipher::CipherError # raised for consistency with GCM mode
|
30
30
|
end
|
31
|
-
when 'AES-128-GCM'
|
31
|
+
when 'AES-128-GCM', 'AES-256-GCM'
|
32
32
|
cipher = OpenSSL::Cipher.new(algorithm).decrypt
|
33
33
|
cipher.key = key
|
34
34
|
cipher.iv = self.nonce[0...12]
|
@@ -37,7 +37,7 @@ module RubySMB
|
|
37
37
|
unencrypted_data = cipher.update(encrypted_data)
|
38
38
|
cipher.final # raises OpenSSL::Cipher::CipherError on signature failure
|
39
39
|
else
|
40
|
-
raise ArgumentError.new('Invalid algorithm, must be
|
40
|
+
raise ArgumentError.new('Invalid algorithm, must be one of AES-128-CCM, AES-128-GCM, AES-256-CCM, or AES-256-GCM')
|
41
41
|
end
|
42
42
|
|
43
43
|
unencrypted_data[0...self.original_message_size]
|
@@ -53,14 +53,14 @@ module RubySMB
|
|
53
53
|
self.original_message_size.assign(unencrypted_data.length)
|
54
54
|
|
55
55
|
case algorithm
|
56
|
-
when 'AES-128-CCM'
|
56
|
+
when 'AES-128-CCM', 'AES-256-CCM'
|
57
57
|
cipher = OpenSSL::CCM.new('AES', key, 16)
|
58
58
|
random_iv = OpenSSL::Random.random_bytes(11)
|
59
59
|
self.nonce.assign(random_iv)
|
60
60
|
result = cipher.encrypt(unencrypted_data, random_iv, self.to_binary_s[20...52])
|
61
61
|
encrypted_data = result[0...-16]
|
62
62
|
auth_tag = result[-16..-1]
|
63
|
-
when 'AES-128-GCM'
|
63
|
+
when 'AES-128-GCM', 'AES-256-GCM'
|
64
64
|
cipher = OpenSSL::Cipher.new(algorithm).encrypt
|
65
65
|
cipher.iv_len = 12
|
66
66
|
cipher.key = key
|
@@ -69,7 +69,7 @@ module RubySMB
|
|
69
69
|
encrypted_data = cipher.update(unencrypted_data) + cipher.final
|
70
70
|
auth_tag = cipher.auth_tag
|
71
71
|
else
|
72
|
-
raise ArgumentError.new('Invalid algorithm, must be
|
72
|
+
raise ArgumentError.new('Invalid algorithm, must be one of AES-128-CCM, AES-128-GCM, AES-256-CCM, or AES-256-GCM')
|
73
73
|
end
|
74
74
|
|
75
75
|
self.encrypted_data.assign(encrypted_data.bytes)
|
data/lib/ruby_smb/smb2.rb
CHANGED
@@ -5,6 +5,7 @@ module RubySMB
|
|
5
5
|
module SMB2
|
6
6
|
# Protocol ID value. Translates to \xFESMB
|
7
7
|
SMB2_PROTOCOL_ID = 0xFE534D42
|
8
|
+
SMB2_TRANSFORM_PROTOCOL_ID = 0xFD534D42
|
8
9
|
# Wildcard revision, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/63abf97c-0d09-47e2-88d6-6bfa552949a5
|
9
10
|
SMB2_WILDCARD_REVISION = 0x02ff
|
10
11
|
|
data/lib/ruby_smb/version.rb
CHANGED
@@ -962,8 +962,10 @@ RSpec.describe RubySMB::Client do
|
|
962
962
|
expect(nc.length).to eq(1)
|
963
963
|
expect(nc.first.data.ciphers).to eq(
|
964
964
|
[
|
965
|
-
RubySMB::SMB2::EncryptionCapabilities::
|
966
|
-
RubySMB::SMB2::EncryptionCapabilities::
|
965
|
+
RubySMB::SMB2::EncryptionCapabilities::AES_256_GCM,
|
966
|
+
RubySMB::SMB2::EncryptionCapabilities::AES_256_CCM,
|
967
|
+
RubySMB::SMB2::EncryptionCapabilities::AES_128_GCM,
|
968
|
+
RubySMB::SMB2::EncryptionCapabilities::AES_128_CCM
|
967
969
|
]
|
968
970
|
)
|
969
971
|
end
|
@@ -2681,13 +2683,15 @@ RSpec.describe RubySMB::Client do
|
|
2681
2683
|
context "with #{dialect} dialect" do
|
2682
2684
|
before :example do
|
2683
2685
|
client.dialect = dialect
|
2686
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2684
2687
|
end
|
2685
2688
|
|
2686
2689
|
it 'generates the client encryption key with the expected parameters' do
|
2687
2690
|
expect(RubySMB::Crypto::KDF).to receive(:counter_mode).with(
|
2688
2691
|
session_key,
|
2689
2692
|
"SMB2AESCCM\x00",
|
2690
|
-
"ServerIn \x00"
|
2693
|
+
"ServerIn \x00",
|
2694
|
+
{length: 128}
|
2691
2695
|
).and_call_original
|
2692
2696
|
client.smb3_encrypt(data)
|
2693
2697
|
end
|
@@ -2698,10 +2702,12 @@ RSpec.describe RubySMB::Client do
|
|
2698
2702
|
it 'generates the client encryption key with the expected parameters' do
|
2699
2703
|
client.preauth_integrity_hash_value = ''
|
2700
2704
|
client.dialect = '0x0311'
|
2705
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2701
2706
|
expect(RubySMB::Crypto::KDF).to receive(:counter_mode).with(
|
2702
2707
|
session_key,
|
2703
2708
|
"SMBC2SCipherKey\x00",
|
2704
|
-
''
|
2709
|
+
'',
|
2710
|
+
{length: 128}
|
2705
2711
|
).and_call_original
|
2706
2712
|
client.smb3_encrypt(data)
|
2707
2713
|
end
|
@@ -2723,6 +2729,7 @@ RSpec.describe RubySMB::Client do
|
|
2723
2729
|
|
2724
2730
|
it 'generates the expected client encryption key with 0x0302 dialect' do
|
2725
2731
|
client.dialect = '0x0302'
|
2732
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2726
2733
|
expected_enc_key =
|
2727
2734
|
"\xa4\xfa\x23\xc1\xb0\x65\x84\xce\x47\x08\x5b\xe0\x64\x98\xd7\x87".b
|
2728
2735
|
client.smb3_encrypt(data)
|
@@ -2731,6 +2738,7 @@ RSpec.describe RubySMB::Client do
|
|
2731
2738
|
|
2732
2739
|
it 'generates the expected client encryption key with 0x0311 dialect' do
|
2733
2740
|
client.dialect = '0x0311'
|
2741
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2734
2742
|
client.session_key =
|
2735
2743
|
"\x5c\x00\x4a\x3b\xf0\xa2\x4f\x75\x4c\xb2\x74\x0a\xcf\xc4\x8e\x1a".b
|
2736
2744
|
client.preauth_integrity_hash_value =
|
@@ -2765,13 +2773,15 @@ RSpec.describe RubySMB::Client do
|
|
2765
2773
|
context "with #{dialect} dialect" do
|
2766
2774
|
before :example do
|
2767
2775
|
client.dialect = dialect
|
2776
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2768
2777
|
end
|
2769
2778
|
|
2770
2779
|
it 'generates the client encryption key with the expected parameters' do
|
2771
2780
|
expect(RubySMB::Crypto::KDF).to receive(:counter_mode).with(
|
2772
2781
|
session_key,
|
2773
2782
|
"SMB2AESCCM\x00",
|
2774
|
-
"ServerOut\x00"
|
2783
|
+
"ServerOut\x00",
|
2784
|
+
{length: 128}
|
2775
2785
|
).and_call_original
|
2776
2786
|
client.smb3_decrypt(transform_packet)
|
2777
2787
|
end
|
@@ -2782,10 +2792,12 @@ RSpec.describe RubySMB::Client do
|
|
2782
2792
|
it 'generates the client encryption key with the expected parameters' do
|
2783
2793
|
client.preauth_integrity_hash_value = ''
|
2784
2794
|
client.dialect = '0x0311'
|
2795
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2785
2796
|
expect(RubySMB::Crypto::KDF).to receive(:counter_mode).with(
|
2786
2797
|
session_key,
|
2787
2798
|
"SMBS2CCipherKey\x00",
|
2788
|
-
''
|
2799
|
+
'',
|
2800
|
+
{length: 128}
|
2789
2801
|
).and_call_original
|
2790
2802
|
client.smb3_decrypt(transform_packet)
|
2791
2803
|
end
|
@@ -2806,6 +2818,7 @@ RSpec.describe RubySMB::Client do
|
|
2806
2818
|
|
2807
2819
|
it 'generates the expected server encryption key with 0x0302 dialect' do
|
2808
2820
|
client.dialect = '0x0302'
|
2821
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2809
2822
|
expected_enc_key =
|
2810
2823
|
"\x65\x21\xd3\x6d\xe9\xe3\x5a\x66\x09\x61\xae\x3e\xc6\x49\x6b\xdf".b
|
2811
2824
|
client.smb3_decrypt(transform_packet)
|
@@ -2814,6 +2827,7 @@ RSpec.describe RubySMB::Client do
|
|
2814
2827
|
|
2815
2828
|
it 'generates the expected server encryption key with 0x0311 dialect' do
|
2816
2829
|
client.dialect = '0x0311'
|
2830
|
+
client.encryption_algorithm = 'AES-128-CCM'
|
2817
2831
|
client.session_key =
|
2818
2832
|
"\x5c\x00\x4a\x3b\xf0\xa2\x4f\x75\x4c\xb2\x74\x0a\xcf\xc4\x8e\x1a".b
|
2819
2833
|
client.preauth_integrity_hash_value =
|
@@ -26,7 +26,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Request do
|
|
26
26
|
expect(parameter_block).to be_a RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'should have the setup set to the
|
29
|
+
it 'should have the setup set to the FIND_FIRST2 subcommand' do
|
30
30
|
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_FIRST2
|
31
31
|
end
|
32
32
|
end
|
@@ -47,7 +47,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Request do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should keep #trans2_data 4-byte aligned' do
|
50
|
-
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
50
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0 if data_block.trans2_data.num_bytes != 0
|
51
51
|
end
|
52
52
|
|
53
53
|
describe '#trans2_parameters' do
|
@@ -24,7 +24,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
24
24
|
describe '#parameter_block' do
|
25
25
|
subject(:parameter_block) { packet.parameter_block }
|
26
26
|
|
27
|
-
it 'should have the setup set to the
|
27
|
+
it 'should have the setup set to the FIND_FIRST2 subcommand' do
|
28
28
|
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_FIRST2
|
29
29
|
end
|
30
30
|
end
|
@@ -40,7 +40,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should keep #trans2_data 4-byte aligned' do
|
43
|
-
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
43
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0 if data_block.trans2_data.num_bytes != 0
|
44
44
|
end
|
45
45
|
|
46
46
|
describe '#trans2_parameters' do
|
@@ -57,6 +57,40 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
57
57
|
subject(:data) { data_block.trans2_data }
|
58
58
|
|
59
59
|
it { is_expected.to respond_to :buffer }
|
60
|
+
|
61
|
+
describe '#buffer' do
|
62
|
+
it 'is a String field' do
|
63
|
+
expect(data.buffer).to be_a BinData::String
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when the buffer is empty' do
|
68
|
+
before :each do
|
69
|
+
data.buffer = ''
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should not be padded' do
|
73
|
+
expect(data_block.pad2.num_bytes).to eq 0
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should read its own binary representation' do
|
77
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq ''
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when the buffer is not empty' do
|
82
|
+
before :each do
|
83
|
+
data.buffer = 'test'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should be padded to a 4-byte boundary' do
|
87
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should read its own binary representation' do
|
91
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq 'test'
|
92
|
+
end
|
93
|
+
end
|
60
94
|
end
|
61
95
|
end
|
62
96
|
|
@@ -26,7 +26,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Request do
|
|
26
26
|
expect(parameter_block).to be_a RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'should have the setup set to the
|
29
|
+
it 'should have the setup set to the FIND_NEXT2 subcommand' do
|
30
30
|
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_NEXT2
|
31
31
|
end
|
32
32
|
end
|
@@ -47,7 +47,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Request do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should keep #trans2_data 4-byte aligned' do
|
50
|
-
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
50
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0 if data_block.trans2_data.num_bytes != 0
|
51
51
|
end
|
52
52
|
|
53
53
|
describe '#trans2_parameters' do
|
@@ -24,7 +24,7 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
24
24
|
describe '#parameter_block' do
|
25
25
|
subject(:parameter_block) { packet.parameter_block }
|
26
26
|
|
27
|
-
it 'should have the setup set to the
|
27
|
+
it 'should have the setup set to the FIND_NEXT2 subcommand' do
|
28
28
|
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_NEXT2
|
29
29
|
end
|
30
30
|
end
|
@@ -56,6 +56,40 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
56
56
|
subject(:data) { data_block.trans2_data }
|
57
57
|
|
58
58
|
it { is_expected.to respond_to :buffer }
|
59
|
+
|
60
|
+
describe '#buffer' do
|
61
|
+
it 'is a String field' do
|
62
|
+
expect(data.buffer).to be_a BinData::String
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when the buffer is empty' do
|
67
|
+
before :each do
|
68
|
+
data.buffer = ''
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should not be padded' do
|
72
|
+
expect(data_block.pad2.num_bytes).to eq 0
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should read its own binary representation' do
|
76
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq ''
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when the buffer is not empty' do
|
81
|
+
before :each do
|
82
|
+
data.buffer = 'test'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should be padded to a 4-byte boundary' do
|
86
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should read its own binary representation' do
|
90
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq 'test'
|
91
|
+
end
|
92
|
+
end
|
59
93
|
end
|
60
94
|
end
|
61
95
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
include RubySMB::Fscc::FileInformation
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::Trans2::QueryFileInformationRequest do
|
4
|
+
subject(:packet) { described_class.new }
|
5
|
+
|
6
|
+
describe '#smb_header' do
|
7
|
+
subject(:header) { packet.smb_header }
|
8
|
+
|
9
|
+
it 'is a standard SMB Header' do
|
10
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have the command set to SMB_COM_TRANSACTION2' do
|
14
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not have the response flag set' do
|
18
|
+
expect(header.flags.reply).to eq 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#parameter_block' do
|
23
|
+
subject(:parameter_block) { packet.parameter_block }
|
24
|
+
|
25
|
+
it 'is a standard ParameterBlock' do
|
26
|
+
expect(parameter_block).to be_a RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have the setup set to the QUERY_FILE_INFORMATION subcommand' do
|
30
|
+
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::QUERY_FILE_INFORMATION
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#data_block' do
|
35
|
+
subject(:data_block) { packet.data_block }
|
36
|
+
|
37
|
+
it 'is a standard DataBlock' do
|
38
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
39
|
+
end
|
40
|
+
|
41
|
+
it { is_expected.to respond_to :name }
|
42
|
+
it { is_expected.to respond_to :trans2_parameters }
|
43
|
+
it { is_expected.to respond_to :trans2_data }
|
44
|
+
|
45
|
+
it 'should keep #trans2_parameters 4-byte aligned' do
|
46
|
+
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should keep #trans2_data 4-byte aligned' do
|
50
|
+
data_block.trans2_parameters.information_level = FILE_DISPOSITION_INFORMATION + SMB_INFO_PASSTHROUGH
|
51
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0 if data_block.trans2_data.num_bytes != 0
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#trans2_parameters' do
|
55
|
+
subject(:parameters) { data_block.trans2_parameters }
|
56
|
+
|
57
|
+
it { is_expected.to respond_to :fid }
|
58
|
+
it { is_expected.to respond_to :information_level }
|
59
|
+
|
60
|
+
describe '#fid' do
|
61
|
+
it 'is a 16-bit field' do
|
62
|
+
expect(parameters.fid).to be_a BinData::Uint16le
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#information_level' do
|
67
|
+
it 'is a 16-bit field' do
|
68
|
+
expect(parameters.information_level).to be_a BinData::Uint16le
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Packet::Trans2::QueryFileInformationResponse do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
describe '#smb_header' do
|
5
|
+
subject(:header) { packet.smb_header }
|
6
|
+
|
7
|
+
it 'is a standard SMB Header' do
|
8
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should have the command set to SMB_COM_TRANSACTION2' do
|
12
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have the response flag set' do
|
16
|
+
expect(header.flags.reply).to eq 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#parameter_block' do
|
21
|
+
subject(:parameter_block) { packet.parameter_block }
|
22
|
+
|
23
|
+
it 'should have the setup set to the QUERY_FILE_INFORMATION subcommand' do
|
24
|
+
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::QUERY_FILE_INFORMATION
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#data_block' do
|
29
|
+
subject(:data_block) { packet.data_block }
|
30
|
+
|
31
|
+
it 'is a standard DataBlock' do
|
32
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
33
|
+
end
|
34
|
+
|
35
|
+
it { is_expected.to respond_to :name }
|
36
|
+
it { is_expected.to respond_to :trans2_parameters }
|
37
|
+
it { is_expected.to respond_to :trans2_data }
|
38
|
+
|
39
|
+
it 'should keep #trans2_parameters 4-byte aligned' do
|
40
|
+
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#trans2_parameters' do
|
44
|
+
subject(:parameters) { data_block.trans2_parameters }
|
45
|
+
|
46
|
+
it { is_expected.to respond_to :ea_error_offset }
|
47
|
+
|
48
|
+
describe '#ea_error_offset' do
|
49
|
+
it 'is a 16-bit field' do
|
50
|
+
expect(parameters.ea_error_offset).to be_a BinData::Uint16le
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#trans2_data' do
|
56
|
+
subject(:data) { data_block.trans2_data }
|
57
|
+
|
58
|
+
it { is_expected.to respond_to :buffer }
|
59
|
+
|
60
|
+
describe '#buffer' do
|
61
|
+
it 'is a String field' do
|
62
|
+
expect(data.buffer).to be_a BinData::String
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when the buffer is empty' do
|
67
|
+
before :each do
|
68
|
+
data.buffer = ''
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should not be padded' do
|
72
|
+
expect(data_block.pad2.num_bytes).to eq 0
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should read its own binary representation' do
|
76
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq ''
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when the buffer is not empty' do
|
81
|
+
before :each do
|
82
|
+
data.buffer = 'test'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should be padded to a 4-byte boundary' do
|
86
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should read its own binary representation' do
|
90
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq 'test'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
include RubySMB::Fscc::FileInformation
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::Trans2::QueryFsInformationRequest do
|
4
|
+
subject(:packet) { described_class.new }
|
5
|
+
|
6
|
+
describe '#smb_header' do
|
7
|
+
subject(:header) { packet.smb_header }
|
8
|
+
|
9
|
+
it 'is a standard SMB Header' do
|
10
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have the command set to SMB_COM_TRANSACTION2' do
|
14
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not have the response flag set' do
|
18
|
+
expect(header.flags.reply).to eq 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#parameter_block' do
|
23
|
+
subject(:parameter_block) { packet.parameter_block }
|
24
|
+
|
25
|
+
it 'is a standard ParameterBlock' do
|
26
|
+
expect(parameter_block).to be_a RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have the setup set to the QUERY_FS_INFORMATION subcommand' do
|
30
|
+
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::QUERY_FS_INFORMATION
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#data_block' do
|
35
|
+
subject(:data_block) { packet.data_block }
|
36
|
+
|
37
|
+
it 'is a standard DataBlock' do
|
38
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
39
|
+
end
|
40
|
+
|
41
|
+
it { is_expected.to respond_to :name }
|
42
|
+
it { is_expected.to respond_to :trans2_parameters }
|
43
|
+
it { is_expected.to_not respond_to :trans2_data }
|
44
|
+
|
45
|
+
it 'should keep #trans2_parameters 4-byte aligned' do
|
46
|
+
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#trans2_parameters' do
|
50
|
+
subject(:parameters) { data_block.trans2_parameters }
|
51
|
+
|
52
|
+
it { is_expected.to respond_to :information_level }
|
53
|
+
|
54
|
+
describe '#information_level' do
|
55
|
+
it 'is a 16-bit field' do
|
56
|
+
expect(parameters.information_level).to be_a BinData::Uint16le
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Packet::Trans2::QueryFsInformationResponse do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
describe '#smb_header' do
|
5
|
+
subject(:header) { packet.smb_header }
|
6
|
+
|
7
|
+
it 'is a standard SMB Header' do
|
8
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should have the command set to SMB_COM_TRANSACTION2' do
|
12
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have the response flag set' do
|
16
|
+
expect(header.flags.reply).to eq 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#parameter_block' do
|
21
|
+
subject(:parameter_block) { packet.parameter_block }
|
22
|
+
|
23
|
+
it 'should have the setup set to the QUERY_FS_INFORMATION subcommand' do
|
24
|
+
expect(parameter_block.setup).to include RubySMB::SMB1::Packet::Trans2::Subcommands::QUERY_FS_INFORMATION
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#data_block' do
|
29
|
+
subject(:data_block) { packet.data_block }
|
30
|
+
|
31
|
+
it 'is a standard DataBlock' do
|
32
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
33
|
+
end
|
34
|
+
|
35
|
+
it { is_expected.to respond_to :name }
|
36
|
+
it { is_expected.to respond_to :trans2_parameters }
|
37
|
+
it { is_expected.to respond_to :trans2_data }
|
38
|
+
|
39
|
+
it 'should keep #trans2_parameters 4-byte aligned' do
|
40
|
+
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#trans2_parameters' do
|
44
|
+
subject(:parameters) { data_block.trans2_parameters }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#trans2_data' do
|
48
|
+
subject(:data) { data_block.trans2_data }
|
49
|
+
|
50
|
+
it { is_expected.to respond_to :buffer }
|
51
|
+
|
52
|
+
describe '#buffer' do
|
53
|
+
it 'is a String field' do
|
54
|
+
expect(data.buffer).to be_a BinData::String
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when the buffer is empty' do
|
59
|
+
before :each do
|
60
|
+
data.buffer = ''
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should not be padded' do
|
64
|
+
expect(data_block.pad2.num_bytes).to eq 0
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should read its own binary representation' do
|
68
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq ''
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the buffer is not empty' do
|
73
|
+
before :each do
|
74
|
+
data.buffer = 'test'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should be padded to a 4-byte boundary' do
|
78
|
+
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should read its own binary representation' do
|
82
|
+
expect(packet.class.read(packet.to_binary_s).data_block.trans2_data.buffer).to eq 'test'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|