ruby_smb 1.0.3 → 2.0.1

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 (200) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +233 -22
  15. data/lib/ruby_smb/client/authentication.rb +70 -33
  16. data/lib/ruby_smb/client/echo.rb +20 -2
  17. data/lib/ruby_smb/client/encryption.rb +62 -0
  18. data/lib/ruby_smb/client/negotiation.rb +172 -24
  19. data/lib/ruby_smb/client/signing.rb +19 -0
  20. data/lib/ruby_smb/client/tree_connect.rb +24 -18
  21. data/lib/ruby_smb/client/utils.rb +8 -7
  22. data/lib/ruby_smb/client/winreg.rb +46 -0
  23. data/lib/ruby_smb/crypto.rb +30 -0
  24. data/lib/ruby_smb/dcerpc.rb +38 -0
  25. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  27. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  29. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  30. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  31. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  33. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  34. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  36. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  40. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  44. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  48. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  49. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  50. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  51. data/lib/ruby_smb/error.rb +68 -2
  52. data/lib/ruby_smb/generic_packet.rb +33 -4
  53. data/lib/ruby_smb/smb1/commands.rb +1 -1
  54. data/lib/ruby_smb/smb1/file.rb +66 -15
  55. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  56. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  57. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  58. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  60. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  64. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  65. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  66. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  67. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  69. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  70. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  71. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  72. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  73. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  74. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
  75. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  76. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
  77. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  79. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  80. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  81. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  82. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  85. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  86. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  87. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  88. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  90. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  91. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  92. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  93. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  94. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  95. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  96. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  97. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  98. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
  99. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  100. data/lib/ruby_smb/smb1/pipe.rb +87 -6
  101. data/lib/ruby_smb/smb1/tree.rb +50 -3
  102. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  103. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  104. data/lib/ruby_smb/smb2/file.rb +103 -25
  105. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  106. data/lib/ruby_smb/smb2/packet.rb +2 -0
  107. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  109. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  110. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  111. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  112. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  113. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  114. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  115. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  117. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
  120. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
  121. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  122. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  123. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  124. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  125. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  126. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  127. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  128. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  129. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  130. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
  131. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
  132. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  133. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  134. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  135. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  136. data/lib/ruby_smb/smb2/pipe.rb +86 -12
  137. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  138. data/lib/ruby_smb/smb2/tree.rb +65 -21
  139. data/lib/ruby_smb/version.rb +1 -1
  140. data/ruby_smb.gemspec +5 -3
  141. data/spec/lib/ruby_smb/client_spec.rb +1612 -108
  142. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  143. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  144. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  146. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  147. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  148. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  149. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  163. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  164. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  165. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  166. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  167. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  168. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  169. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  170. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  171. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  176. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  177. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  178. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  179. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  180. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  181. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  182. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  183. data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
  184. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  185. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  186. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  187. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  188. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  189. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  190. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  191. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  192. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
  193. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
  194. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  195. data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
  196. metadata +191 -83
  197. metadata.gz.sig +0 -0
  198. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  199. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  200. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -0,0 +1,332 @@
1
+ RSpec.describe RubySMB::SMB2::PreauthIntegrityCapabilities do
2
+ subject(:capability) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :hash_algorithm_count }
5
+ it { is_expected.to respond_to :salt_length }
6
+ it { is_expected.to respond_to :hash_algorithms }
7
+ it { is_expected.to respond_to :salt }
8
+
9
+ it 'is little endian' do
10
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
11
+ end
12
+
13
+ describe '#hash_algorithm_count' do
14
+ it 'is a 16-bit unsigned integer' do
15
+ expect(capability.hash_algorithm_count).to be_a BinData::Uint16le
16
+ end
17
+
18
+ it 'is set to the #hash_algorithms array size' do
19
+ array = [1, 2, 3]
20
+ capability.hash_algorithms = array
21
+ expect(capability.hash_algorithm_count).to eq(array.size)
22
+ end
23
+ end
24
+
25
+ describe '#salt_length' do
26
+ it 'is a 16-bit unsigned integer' do
27
+ expect(capability.salt_length).to be_a BinData::Uint16le
28
+ end
29
+
30
+ it 'is set to the #salt string size' do
31
+ salt = 'my_random_salt'
32
+ capability.salt = salt
33
+ expect(capability.salt_length).to eq(salt.size)
34
+ end
35
+ end
36
+
37
+ describe '#hash_algorithms' do
38
+ it 'is a BinData Array' do
39
+ expect(capability.hash_algorithms).to be_a BinData::Array
40
+ end
41
+
42
+ it 'has #hash_algorithm_count elements' do
43
+ capability.hash_algorithm_count = 3
44
+ expect(capability.hash_algorithms.size).to eq 3
45
+ end
46
+ end
47
+
48
+ describe '#salt' do
49
+ it 'is a string' do
50
+ expect(capability.salt).to be_a BinData::String
51
+ end
52
+
53
+ it 'should read #salt_length bytes' do
54
+ salt = 'my_random_salt'
55
+ capability.salt_length = 5
56
+ expect(capability.salt.read(salt)).to eq(salt[0,5])
57
+ end
58
+ end
59
+
60
+ it 'reads binary data as expected' do
61
+ data = described_class.new(
62
+ hash_algorithms: [described_class::SHA_512],
63
+ salt: 'test salt'
64
+ )
65
+ expect(described_class.read(data.to_binary_s)).to eq(data)
66
+ end
67
+ end
68
+
69
+ RSpec.describe RubySMB::SMB2::EncryptionCapabilities do
70
+ subject(:capability) { described_class.new }
71
+
72
+ it { is_expected.to respond_to :cipher_count }
73
+ it { is_expected.to respond_to :ciphers }
74
+
75
+ it 'is little endian' do
76
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
77
+ end
78
+
79
+ describe '#cipher_count' do
80
+ it 'is a 16-bit unsigned integer' do
81
+ expect(capability.cipher_count).to be_a BinData::Uint16le
82
+ end
83
+
84
+ it 'is set to the #ciphers array size' do
85
+ array = [1, 2, 3]
86
+ capability.ciphers = array
87
+ expect(capability.cipher_count).to eq(array.size)
88
+ end
89
+ end
90
+
91
+ describe '#ciphers' do
92
+ it 'is a BinData Array' do
93
+ expect(capability.ciphers).to be_a BinData::Array
94
+ end
95
+
96
+ it 'has #cipher_count elements' do
97
+ capability.cipher_count = 3
98
+ expect(capability.ciphers.size).to eq 3
99
+ end
100
+ end
101
+
102
+ it 'reads binary data as expected' do
103
+ data = described_class.new(
104
+ ciphers: [described_class::AES_128_CCM, described_class::AES_128_GCM]
105
+ )
106
+ expect(described_class.read(data.to_binary_s)).to eq(data)
107
+ end
108
+ end
109
+
110
+ RSpec.describe RubySMB::SMB2::CompressionCapabilities do
111
+ subject(:capability) { described_class.new }
112
+
113
+ it { is_expected.to respond_to :compression_algorithm_count }
114
+ it { is_expected.to respond_to :padding }
115
+ it { is_expected.to respond_to :flags }
116
+ it { is_expected.to respond_to :compression_algorithms }
117
+
118
+ it 'is little endian' do
119
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
120
+ end
121
+
122
+ describe '#compression_algorithm_count' do
123
+ it 'is a 16-bit unsigned integer' do
124
+ expect(capability.compression_algorithm_count).to be_a BinData::Uint16le
125
+ end
126
+
127
+ it 'is set to the #compression_algorithms array size' do
128
+ array = [1, 2, 3]
129
+ capability.compression_algorithms = array
130
+ expect(capability.compression_algorithm_count).to eq(array.size)
131
+ end
132
+ end
133
+
134
+ describe '#padding' do
135
+ it 'is a 16-bit unsigned integer' do
136
+ expect(capability.padding).to be_a BinData::Uint16le
137
+ end
138
+ end
139
+
140
+ describe '#flags' do
141
+ it 'is a 32-bit unsigned integer' do
142
+ expect(capability.flags).to be_a BinData::Uint32le
143
+ end
144
+ end
145
+
146
+ describe '#compression_algorithms' do
147
+ it 'is a BinData Array' do
148
+ expect(capability.compression_algorithms).to be_a BinData::Array
149
+ end
150
+
151
+ it 'has #compression_algorithm_count elements' do
152
+ capability.compression_algorithm_count = 3
153
+ expect(capability.compression_algorithms.size).to eq 3
154
+ end
155
+ end
156
+
157
+ it 'reads binary data as expected' do
158
+ data = described_class.new(
159
+ compression_algorithms: [described_class::LZNT1, described_class::LZ77]
160
+ )
161
+ expect(described_class.read(data.to_binary_s)).to eq(data)
162
+ end
163
+ end
164
+
165
+ RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
166
+ subject(:capability) { described_class.new }
167
+
168
+ it { is_expected.to respond_to :net_name }
169
+
170
+ it 'is little endian' do
171
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
172
+ end
173
+
174
+ describe '#net_name' do
175
+ it 'is a unicode string' do
176
+ expect(capability.net_name).to be_a RubySMB::Field::Stringz16
177
+ end
178
+ end
179
+
180
+ it 'reads binary data as expected' do
181
+ data = described_class.new(
182
+ net_name: 'netname test'
183
+ )
184
+ expect(described_class.read(data.to_binary_s)).to eq(data)
185
+ end
186
+ end
187
+
188
+ RSpec.describe RubySMB::SMB2::NegotiateContext do
189
+ class FakePacket < BinData::Record
190
+ endian :little
191
+ string :garbage
192
+ negotiate_context :nc
193
+ end
194
+
195
+ let(:test_packet) do
196
+ packet = FakePacket.new
197
+ packet.nc.context_type = described_class::SMB2_PREAUTH_INTEGRITY_CAPABILITIES
198
+ packet
199
+ end
200
+ subject(:negotiate_context) { described_class.new }
201
+
202
+ it { is_expected.to respond_to :pad }
203
+ it { is_expected.to respond_to :context_type }
204
+ it { is_expected.to respond_to :data_length }
205
+ it { is_expected.to respond_to :reserved }
206
+ it { is_expected.to respond_to :data }
207
+
208
+ it 'is little endian' do
209
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
210
+ end
211
+
212
+ describe '#pad' do
213
+ it 'is a string' do
214
+ expect(negotiate_context.pad).to be_a BinData::String
215
+ end
216
+
217
+ it 'should keep the #context_type 8-byte aligned' do
218
+ test_packet.garbage = 'foo'
219
+ expect(test_packet.nc.context_type.abs_offset % 8).to eq(0)
220
+ end
221
+ end
222
+
223
+ describe '#context_type ' do
224
+ it 'is a 16-bit unsigned integer' do
225
+ expect(negotiate_context.context_type).to be_a BinData::Uint16le
226
+ end
227
+ end
228
+
229
+ describe '#data_length' do
230
+ it 'is a 16-bit unsigned integer' do
231
+ expect(negotiate_context.data_length).to be_a BinData::Uint16le
232
+ end
233
+
234
+ it 'should give the #data field length in bytes' do
235
+ expect(described_class.new(context_type: described_class::SMB2_ENCRYPTION_CAPABILITIES).data_length)
236
+ .to eq(RubySMB::SMB2::EncryptionCapabilities.new.num_bytes)
237
+ end
238
+ end
239
+
240
+ describe '#data' do
241
+ it 'is a BinData choice field' do
242
+ expect(negotiate_context.data).to be_a BinData::Choice
243
+ end
244
+
245
+ context 'with a SMB2_PREAUTH_INTEGRITY_CAPABILITIES context type' do
246
+ it 'selects the PreauthIntegrityCapabilities structure' do
247
+ expect(described_class.new(context_type: described_class::SMB2_PREAUTH_INTEGRITY_CAPABILITIES).data)
248
+ .to eq(RubySMB::SMB2::PreauthIntegrityCapabilities.new)
249
+ end
250
+ end
251
+
252
+ context 'with a SMB2_ENCRYPTION_CAPABILITIES context type' do
253
+ it 'selects the PreauthIntegrityCapabilities structure' do
254
+ expect(described_class.new(context_type: described_class::SMB2_ENCRYPTION_CAPABILITIES).data)
255
+ .to eq(RubySMB::SMB2::EncryptionCapabilities.new)
256
+ end
257
+ end
258
+
259
+ context 'with a SMB2_COMPRESSION_CAPABILITIES context type' do
260
+ it 'selects the PreauthIntegrityCapabilities structure' do
261
+ expect(described_class.new(context_type: described_class::SMB2_COMPRESSION_CAPABILITIES).data)
262
+ .to eq(RubySMB::SMB2::CompressionCapabilities.new)
263
+ end
264
+ end
265
+
266
+ context 'with a SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context type' do
267
+ it 'selects the PreauthIntegrityCapabilities structure' do
268
+ expect(described_class.new(context_type: described_class::SMB2_NETNAME_NEGOTIATE_CONTEXT_ID).data)
269
+ .to eq(RubySMB::SMB2::NetnameNegotiateContextId.new)
270
+ end
271
+ end
272
+ end
273
+
274
+ describe '#pad_length' do
275
+ it 'returns 0 when #context_type is already 8-byte aligned' do
276
+ expect(test_packet.nc.pad_length).to eq(0)
277
+ end
278
+
279
+ it 'returns 2 when #context_type is only 2-byte aligned' do
280
+ test_packet.garbage = 'align' + 'A'
281
+ expect(test_packet.nc.pad_length).to eq(2)
282
+ end
283
+ end
284
+
285
+ context 'with a SMB2_PREAUTH_INTEGRITY_CAPABILITIES context type' do
286
+ it 'reads binary data as expected' do
287
+ data = described_class.new(
288
+ context_type: described_class::SMB2_PREAUTH_INTEGRITY_CAPABILITIES
289
+ )
290
+ data.data.hash_algorithms << RubySMB::SMB2::PreauthIntegrityCapabilities::SHA_512
291
+ data.data.salt = 'test salt'
292
+ expect(described_class.read(data.to_binary_s)).to eq(data)
293
+ end
294
+ end
295
+
296
+ context 'with a SMB2_ENCRYPTION_CAPABILITIES context type' do
297
+ it 'reads binary data as expected' do
298
+ data = described_class.new(
299
+ context_type: described_class::SMB2_ENCRYPTION_CAPABILITIES
300
+ )
301
+ data.data.ciphers = [
302
+ RubySMB::SMB2::EncryptionCapabilities::AES_128_CCM,
303
+ RubySMB::SMB2::EncryptionCapabilities::AES_128_GCM
304
+ ]
305
+ expect(described_class.read(data.to_binary_s)).to eq(data)
306
+ end
307
+ end
308
+
309
+ context 'with a SMB2_COMPRESSION_CAPABILITIES context type' do
310
+ it 'reads binary data as expected' do
311
+ data = described_class.new(
312
+ context_type: described_class::SMB2_COMPRESSION_CAPABILITIES
313
+ )
314
+ data.data.compression_algorithms = [
315
+ RubySMB::SMB2::CompressionCapabilities::LZNT1,
316
+ RubySMB::SMB2::CompressionCapabilities::LZ77
317
+ ]
318
+ expect(described_class.read(data.to_binary_s)).to eq(data)
319
+ end
320
+ end
321
+
322
+ context 'with a SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context type' do
323
+ it 'reads binary data as expected' do
324
+ data = described_class.new(
325
+ context_type: described_class::SMB2_NETNAME_NEGOTIATE_CONTEXT_ID
326
+ )
327
+ data.data.net_name = 'netname test'
328
+ expect(described_class.read(data.to_binary_s)).to eq(data)
329
+ end
330
+ end
331
+ end
332
+
@@ -0,0 +1,108 @@
1
+ RSpec.describe RubySMB::SMB2::Packet::CompressionTransformHeader do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :protocol }
5
+ it { is_expected.to respond_to :original_compressed_segment_size }
6
+ it { is_expected.to respond_to :compression_algorithm }
7
+ it { is_expected.to respond_to :flags }
8
+ it { is_expected.to respond_to :offset }
9
+
10
+ it 'is little endian' do
11
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
12
+ end
13
+
14
+ describe '#protocol' do
15
+ it 'is a 32-bit field' do
16
+ expect(packet.protocol).to be_a BinData::Bit32
17
+ end
18
+
19
+ it 'is initialized with the value 0xFC534D42' do
20
+ expect(packet.protocol).to eq(0xFC534D42)
21
+ end
22
+ end
23
+
24
+ describe '#original_compressed_segment_size ' do
25
+ it 'is a 32-bit unsigned integer' do
26
+ expect(packet.original_compressed_segment_size).to be_a BinData::Uint32le
27
+ end
28
+ end
29
+
30
+ describe '#compression_algorithm ' do
31
+ it 'is a 16-bit unsigned integer' do
32
+ expect(packet.compression_algorithm).to be_a BinData::Uint16le
33
+ end
34
+ end
35
+
36
+ describe '#flags ' do
37
+ it 'is a 16-bit unsigned integer' do
38
+ expect(packet.flags).to be_a BinData::Uint16le
39
+ end
40
+ end
41
+
42
+ describe '#offset' do
43
+ it 'is a 32-bit unsigned integer' do
44
+ expect(packet.offset).to be_a BinData::Uint32le
45
+ end
46
+ end
47
+
48
+ it 'reads binary data as expected' do
49
+ data = described_class.new
50
+ expect(described_class.read(data.to_binary_s)).to eq(data)
51
+ end
52
+ end
53
+
54
+ RSpec.describe RubySMB::SMB2::Packet::Smb2CompressionPayloadHeader do
55
+ subject(:packet) { described_class.new }
56
+
57
+ it { is_expected.to respond_to :algorithm_id }
58
+ it { is_expected.to respond_to :payload_length }
59
+
60
+ it 'is little endian' do
61
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
62
+ end
63
+
64
+ describe '#algorithm_id ' do
65
+ it 'is a 16-bit unsigned integer' do
66
+ expect(packet.algorithm_id).to be_a BinData::Uint16le
67
+ end
68
+ end
69
+
70
+ describe '#payload_length' do
71
+ it 'is a 32-bit unsigned integer' do
72
+ expect(packet.payload_length).to be_a BinData::Uint32le
73
+ end
74
+ end
75
+
76
+ it 'reads binary data as expected' do
77
+ data = described_class.new
78
+ expect(described_class.read(data.to_binary_s)).to eq(data)
79
+ end
80
+ end
81
+
82
+ RSpec.describe RubySMB::SMB2::Packet::Smb2CompressionPatternPayloadV1 do
83
+ subject(:packet) { described_class.new }
84
+
85
+ it { is_expected.to respond_to :pattern }
86
+ it { is_expected.to respond_to :repetitions }
87
+
88
+ it 'is little endian' do
89
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
90
+ end
91
+
92
+ describe '#pattern' do
93
+ it 'is a 8-bit unsigned integer' do
94
+ expect(packet.pattern).to be_a BinData::Uint8
95
+ end
96
+ end
97
+
98
+ describe '#repetitions' do
99
+ it 'is a 32-bit unsigned integer' do
100
+ expect(packet.repetitions).to be_a BinData::Uint32le
101
+ end
102
+ end
103
+
104
+ it 'reads binary data as expected' do
105
+ data = described_class.new
106
+ expect(described_class.read(data.to_binary_s)).to eq(data)
107
+ end
108
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::ErrorPacket do
4
+ subject(:packet) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :smb2_header }
7
+ it { is_expected.to respond_to :structure_size }
8
+ it { is_expected.to respond_to :error_data }
9
+
10
+ describe '#smb2_header' do
11
+ subject(:header) { packet.smb2_header }
12
+
13
+ it 'is a standard SMB2 Header' do
14
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
15
+ end
16
+ end
17
+
18
+ describe '#structure_size' do
19
+ it 'should be a 16-bit unsigned integer' do
20
+ expect(packet.structure_size).to be_a BinData::Uint16le
21
+ end
22
+
23
+ it 'should be 9 by default' do
24
+ expect(packet.structure_size).to eq 9
25
+ end
26
+ end
27
+
28
+ describe '#error_context_count' do
29
+ it 'should be a 8-bit unsigned integer' do
30
+ expect(packet.error_context_count).to be_a BinData::Uint8
31
+ end
32
+ end
33
+
34
+ describe '#byte_count' do
35
+ it 'should be a 32-bit unsigned integer' do
36
+ expect(packet.byte_count).to be_a BinData::Uint32le
37
+ end
38
+ end
39
+
40
+ describe '#error_data' do
41
+ it 'should be a String' do
42
+ expect(packet.error_data).to be_a BinData::String
43
+ end
44
+
45
+ it 'should read #byte_count bytes' do
46
+ packet.error_data = 'test'
47
+ packet.byte_count = 3
48
+ expect(described_class.read(packet.to_binary_s).error_data.size).to eq 3
49
+ end
50
+ end
51
+
52
+ describe '#valid?' do
53
+ before :example do
54
+ packet.original_command = RubySMB::SMB2::Commands::LOGOFF
55
+ packet.smb2_header.command = RubySMB::SMB2::Commands::LOGOFF
56
+ end
57
+
58
+ it 'returns true if the packet protocol ID and header command are valid' do
59
+ expect(packet).to be_valid
60
+ end
61
+
62
+ it 'returns false if the packet protocol ID is wrong' do
63
+ packet.smb2_header.protocol = RubySMB::SMB1::SMB_PROTOCOL_ID
64
+ expect(packet).to_not be_valid
65
+ end
66
+
67
+ it 'returns false if the packet header command is wrong' do
68
+ packet.smb2_header.command = RubySMB::SMB2::Commands::NEGOTIATE
69
+ expect(packet).to_not be_valid
70
+ end
71
+
72
+ it 'returns false if the packet #structure_size is wrong' do
73
+ packet.structure_size = 10
74
+ expect(packet).to_not be_valid
75
+ end
76
+ end
77
+ end
78
+