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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/ruby_smb/client/encryption.rb +16 -4
  4. data/lib/ruby_smb/client/negotiation.rb +3 -1
  5. data/lib/ruby_smb/fscc/file_information.rb +4 -0
  6. data/lib/ruby_smb/server/server_client/encryption.rb +66 -0
  7. data/lib/ruby_smb/server/server_client/negotiation.rb +14 -3
  8. data/lib/ruby_smb/server/server_client/session_setup.rb +18 -3
  9. data/lib/ruby_smb/server/server_client/share_io.rb +17 -0
  10. data/lib/ruby_smb/server/server_client/tree_connect.rb +40 -3
  11. data/lib/ruby_smb/server/server_client.rb +147 -37
  12. data/lib/ruby_smb/server/share/provider/disk/file_system.rb +28 -0
  13. data/lib/ruby_smb/server/share/provider/disk/processor/close.rb +42 -0
  14. data/lib/ruby_smb/server/share/provider/disk/processor/create.rb +143 -0
  15. data/lib/ruby_smb/server/share/provider/disk/processor/query.rb +359 -0
  16. data/lib/ruby_smb/server/share/provider/disk/processor/read.rb +69 -0
  17. data/lib/ruby_smb/server/share/provider/disk/processor.rb +159 -0
  18. data/lib/ruby_smb/server/share/provider/disk.rb +4 -416
  19. data/lib/ruby_smb/server/share/provider/pipe.rb +2 -2
  20. data/lib/ruby_smb/server/share/provider/processor.rb +16 -0
  21. data/lib/ruby_smb/signing.rb +18 -4
  22. data/lib/ruby_smb/smb1/commands.rb +1 -0
  23. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +11 -1
  24. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +1 -1
  25. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +5 -4
  26. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +12 -4
  27. data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +9 -1
  28. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +52 -51
  29. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +37 -37
  30. data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_both_directory_info.rb +48 -0
  31. data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +28 -15
  32. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +51 -51
  33. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +36 -36
  34. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +40 -39
  35. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +40 -40
  36. data/lib/ruby_smb/smb1/packet/trans2/query_file_information_request.rb +60 -0
  37. data/lib/ruby_smb/smb1/packet/trans2/query_file_information_response.rb +59 -0
  38. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level/query_fs_attribute_info.rb +31 -0
  39. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level.rb +40 -0
  40. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request.rb +46 -0
  41. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response.rb +59 -0
  42. data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_basic_info.rb +23 -0
  43. data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_standard_info.rb +22 -0
  44. data/lib/ruby_smb/smb1/packet/trans2/query_information_level.rb +62 -0
  45. data/lib/ruby_smb/smb1/packet/trans2/query_path_information_request.rb +65 -0
  46. data/lib/ruby_smb/smb1/packet/trans2/query_path_information_response.rb +59 -0
  47. data/lib/ruby_smb/smb1/packet/trans2/request.rb +24 -8
  48. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +4 -4
  49. data/lib/ruby_smb/smb1/packet/trans2/response.rb +29 -20
  50. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +42 -42
  51. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +23 -23
  52. data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +23 -5
  53. data/lib/ruby_smb/smb1/packet/trans2.rb +4 -0
  54. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -1
  55. data/lib/ruby_smb/smb2/negotiate_context.rb +10 -1
  56. data/lib/ruby_smb/smb2/packet/transform_header.rb +7 -7
  57. data/lib/ruby_smb/smb2.rb +1 -0
  58. data/lib/ruby_smb/version.rb +1 -1
  59. data/spec/lib/ruby_smb/client_spec.rb +20 -6
  60. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +2 -2
  61. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +36 -2
  62. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +2 -2
  63. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +35 -1
  64. data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_request_spec.rb +74 -0
  65. data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_response_spec.rb +96 -0
  66. data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request_spec.rb +62 -0
  67. data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response_spec.rb +88 -0
  68. data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_request_spec.rb +79 -0
  69. data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_response_spec.rb +96 -0
  70. data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +2 -2
  71. data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +3 -3
  72. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +3 -2
  73. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +7 -2
  74. data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
  75. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +2 -2
  76. data.tar.gz.sig +0 -0
  77. metadata +33 -2
  78. 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: 0xFD534D42
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 either AES-128-CCM or AES-128-GCM')
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 either AES-128-CCM or AES-128-GCM')
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
 
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '3.0.6'.freeze
2
+ VERSION = '3.1.0'.freeze
3
3
  end
@@ -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::AES_128_CCM,
966
- RubySMB::SMB2::EncryptionCapabilities::AES_128_GCM
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 OPEN2 subcommand' do
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 OPEN2 subcommand' do
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 OPEN2 subcommand' do
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 OPEN2 subcommand' do
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