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,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Crypto::KDF do
4
+ describe '.counter_mode' do
5
+ it 'generates the expected 128-bit key' do
6
+ expected_key = "\x3c\x5e\x0a\x1b\x0a\xce\xa5\xb2\x64\x3f\xab\x78\xdc\x82\x31\x3b".b
7
+ expect(described_class.counter_mode('ki', 'label', 'context')).to eq(expected_key)
8
+ end
9
+
10
+ it 'generates the expected 256-bit key' do
11
+ expected_key =
12
+ "\x33\x4d\xa9\x6d\x24\x7e\xcb\x14\xf6\x24\x00\x97\x26\x51\xd5\xb4"\
13
+ "\x54\x5f\xda\x95\xf0\x5a\xcb\x25\x92\x57\xae\x71\x1c\x37\x20\x5b".b
14
+ expect(described_class.counter_mode('ki', 'label', 'context', length: 256)).to eq(expected_key)
15
+ end
16
+
17
+ it 'raises the expected exception when an error occurs' do
18
+ allow(OpenSSL::Digest).to receive(:new).and_raise(OpenSSL::OpenSSLError)
19
+ expect { described_class.counter_mode('ki', 'label', 'context') }.to raise_error(
20
+ RubySMB::Error::EncryptionError,
21
+ "Crypto::KDF.counter_mode OpenSSL error: OpenSSL::OpenSSLError"
22
+ )
23
+ end
24
+ end
25
+ end
@@ -31,7 +31,7 @@ RSpec.describe RubySMB::Dcerpc::BindAck do
31
31
  end
32
32
 
33
33
  it 'should have a default value of 0xFFFF' do
34
- expect(packet.max_xmit_frag).to eq 0xFFFF
34
+ expect(packet.max_xmit_frag).to eq RubySMB::Dcerpc::MAX_XMIT_FRAG
35
35
  end
36
36
  end
37
37
 
@@ -41,7 +41,7 @@ RSpec.describe RubySMB::Dcerpc::BindAck do
41
41
  end
42
42
 
43
43
  it 'should have a default value of 0xFFFF' do
44
- expect(packet.max_recv_frag).to eq 0xFFFF
44
+ expect(packet.max_recv_frag).to eq RubySMB::Dcerpc::MAX_RECV_FRAG
45
45
  end
46
46
  end
47
47
 
@@ -41,7 +41,7 @@ RSpec.describe RubySMB::Dcerpc::Bind do
41
41
  end
42
42
 
43
43
  it 'should have a default value of 0xFFFF' do
44
- expect(packet.max_xmit_frag).to eq 0xFFFF
44
+ expect(packet.max_xmit_frag).to eq RubySMB::Dcerpc::MAX_XMIT_FRAG
45
45
  end
46
46
  end
47
47
 
@@ -51,7 +51,7 @@ RSpec.describe RubySMB::Dcerpc::Bind do
51
51
  end
52
52
 
53
53
  it 'should have a default value of 0xFFFF' do
54
- expect(packet.max_recv_frag).to eq 0xFFFF
54
+ expect(packet.max_recv_frag).to eq RubySMB::Dcerpc::MAX_RECV_FRAG
55
55
  end
56
56
  end
57
57
 
@@ -0,0 +1,410 @@
1
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrTopLevelFullPointer do
2
+ subject(:packet) do
3
+ Class.new(described_class) do
4
+ endian :little
5
+ string :referent
6
+ end.new
7
+ end
8
+
9
+ it { is_expected.to respond_to :referent_identifier }
10
+
11
+ it 'is little endian' do
12
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
+ end
14
+
15
+ describe '#referent_identifier' do
16
+ it 'is a 32-bit unsigned integer' do
17
+ expect(packet.referent_identifier).to be_a BinData::Uint32le
18
+ end
19
+
20
+ it 'has an initial value of 0x00020000' do
21
+ expect(packet.referent_identifier).to eq(0x00020000)
22
+ end
23
+ end
24
+
25
+ describe '#get' do
26
+ it 'returns 0 when #referent_identifier is 0' do
27
+ packet.referent_identifier = 0
28
+ expect(packet.get).to eq(0)
29
+ end
30
+
31
+ it 'returns #referent when #referent_identifier is greater than 0' do
32
+ packet.set('spec_test')
33
+ expect(packet.get).to eq(packet.referent)
34
+ end
35
+ end
36
+
37
+ describe '#set' do
38
+ context 'when the value is 0' do
39
+ it 'sets #referent_identifier to 0' do
40
+ packet.set(0)
41
+ expect(packet.referent_identifier).to eq(0)
42
+ end
43
+ end
44
+
45
+ context 'when the value is a string' do
46
+ it 'sets #referent to the value' do
47
+ str = 'spec_test'
48
+ packet.set(str)
49
+ expect(packet.referent).to eq(str)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrString do
56
+ subject(:packet) { described_class.new }
57
+
58
+ it { is_expected.to respond_to :max_count }
59
+ it { is_expected.to respond_to :offset }
60
+ it { is_expected.to respond_to :actual_count }
61
+ it { is_expected.to respond_to :str }
62
+
63
+ it 'is little endian' do
64
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
65
+ end
66
+
67
+ describe '#max_count' do
68
+ it 'is a 32-bit unsigned integer' do
69
+ expect(packet.max_count).to be_a BinData::Uint32le
70
+ end
71
+ end
72
+
73
+ describe '#offset' do
74
+ it 'is a 32-bit unsigned integer' do
75
+ expect(packet.offset).to be_a BinData::Uint32le
76
+ end
77
+
78
+ it 'has an initial valu of 0' do
79
+ expect(packet.offset).to eq(0)
80
+ end
81
+ end
82
+
83
+ describe '#actual_count' do
84
+ it 'is a 32-bit unsigned integer' do
85
+ expect(packet.actual_count).to be_a BinData::Uint32le
86
+ end
87
+ end
88
+
89
+ describe '#str' do
90
+ it 'is a RubySMB::Field::Stringz16' do
91
+ expect(packet.str).to be_a RubySMB::Field::Stringz16
92
+ end
93
+
94
+ it 'exists if #actual_count is greater than 0' do
95
+ packet.actual_count = 4
96
+ expect(packet.str?).to be true
97
+ end
98
+
99
+ it 'does not exist if #actual_count is 0' do
100
+ expect(packet.str?).to be false
101
+ end
102
+ end
103
+
104
+ describe '#get' do
105
+ it 'returns 0 when #actual_count is 0' do
106
+ expect(packet.get).to eq(0)
107
+ end
108
+
109
+ it 'returns #str when #actual_count is greater than 0' do
110
+ str = 'spec_test'
111
+ strz16 = RubySMB::Field::Stringz16.new(str)
112
+ packet.set(str)
113
+ expect(packet.get).to eq(strz16)
114
+ end
115
+ end
116
+
117
+ describe '#set' do
118
+ context 'when the value is 0' do
119
+ it 'sets #actual_count to 0' do
120
+ packet.set(0)
121
+ expect(packet.actual_count).to eq(0)
122
+ end
123
+ end
124
+
125
+ context 'when the value is a string' do
126
+ let(:str) { 'spec_test' }
127
+
128
+ it 'sets #str to the value' do
129
+ packet.set(str)
130
+ strz16 = RubySMB::Field::Stringz16.new(str)
131
+ expect(packet.str).to eq(strz16)
132
+ end
133
+
134
+ it 'sets #max_count and #actual_count to the expected value' do
135
+ packet.set(str)
136
+ expect(packet.max_count).to eq(str.length + 1)
137
+ expect(packet.actual_count).to eq(str.length + 1)
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrLpStr do
144
+ it 'is NdrTopLevelFullPointer subclass' do
145
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrTopLevelFullPointer
146
+ end
147
+
148
+ subject(:packet) { described_class.new }
149
+
150
+ it { is_expected.to respond_to :referent }
151
+
152
+ it 'is little endian' do
153
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
154
+ end
155
+
156
+ describe '#referent' do
157
+ it 'is a NdrString' do
158
+ expect(packet.referent).to be_a RubySMB::Dcerpc::Ndr::NdrString
159
+ end
160
+
161
+ it 'exists if superclass #referent_identifier is not zero' do
162
+ expect(packet.referent?).to be true
163
+ end
164
+
165
+ it 'does not exist if superclass #referent_identifier is zero' do
166
+ packet.referent_identifier = 0
167
+ expect(packet.referent?).to be false
168
+ end
169
+ end
170
+
171
+ describe '#to_s' do
172
+ it 'returns "\0" when #referent_identifier is 0' do
173
+ packet.referent_identifier = 0
174
+ expect(packet.to_s).to eq("\0")
175
+ end
176
+
177
+ it 'returns #referent when #referent_identifier is greater than 0' do
178
+ packet.set('spec_test')
179
+ expect(packet.to_s).to eq(packet.referent)
180
+ end
181
+ end
182
+ end
183
+
184
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrContextHandle do
185
+ let(:uuid) { 'c3bce70d-5155-472b-9f2f-b824e5fc9b60' }
186
+ let(:attr) { 123 }
187
+ subject(:packet) { described_class.new }
188
+
189
+ it { is_expected.to respond_to :context_handle_attributes }
190
+ it { is_expected.to respond_to :context_handle_uuid }
191
+
192
+ it 'is little endian' do
193
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
194
+ end
195
+
196
+ describe '#context_handle_attributes' do
197
+ it 'is a 32-bit unsigned integer' do
198
+ expect(packet.context_handle_attributes).to be_a BinData::Uint32le
199
+ end
200
+ end
201
+
202
+ describe '#context_handle_uuid' do
203
+ it 'is a UUID' do
204
+ expect(packet.context_handle_uuid).to be_a RubySMB::Dcerpc::Uuid
205
+ end
206
+ end
207
+
208
+ describe '#get' do
209
+ it 'returns the expeted hash' do
210
+ packet.context_handle_attributes = attr
211
+ packet.context_handle_uuid = uuid
212
+ expect(packet.get).to eq({context_handle_attributes: attr, context_handle_uuid: uuid})
213
+ end
214
+ end
215
+
216
+ describe '#set' do
217
+ let(:handle) { {context_handle_attributes: attr, context_handle_uuid: uuid} }
218
+
219
+ context 'when the value is a hash' do
220
+ it 'sets #context_handle_attributes and #context_handle_uuid to the expected values' do
221
+ packet.set(handle)
222
+ expect(packet.context_handle_attributes).to eq(attr)
223
+ expect(packet.context_handle_uuid).to eq(uuid)
224
+ end
225
+ end
226
+
227
+ context 'when the value is a NdrContextHandle'do
228
+ it 'reads the value binary representaion ' do
229
+ ndr_context_handle = described_class.new(handle)
230
+ allow(ndr_context_handle).to receive(:to_binary_s).and_call_original
231
+ packet.set(ndr_context_handle)
232
+ expect(ndr_context_handle).to have_received(:to_binary_s)
233
+ expect(packet.get).to eq(ndr_context_handle)
234
+ end
235
+ end
236
+
237
+ context 'when the value is a binary string'do
238
+ it 'reads the value' do
239
+ ndr_context_handle = described_class.new(handle)
240
+ packet.set(ndr_context_handle.to_binary_s)
241
+ expect(packet.get).to eq(ndr_context_handle)
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrLpDword do
248
+ it 'is NdrTopLevelFullPointer subclass' do
249
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrTopLevelFullPointer
250
+ end
251
+
252
+ subject(:packet) { described_class.new }
253
+
254
+ it { is_expected.to respond_to :referent }
255
+
256
+ it 'is little endian' do
257
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
258
+ end
259
+
260
+ describe '#referent' do
261
+ it 'is a 32-bit unsigned integer' do
262
+ expect(packet.referent).to be_a BinData::Uint32le
263
+ end
264
+
265
+ it 'exists if superclass #referent_identifier is not zero' do
266
+ expect(packet.referent?).to be true
267
+ end
268
+
269
+ it 'does not exist if superclass #referent_identifier is zero' do
270
+ packet.referent_identifier = 0
271
+ expect(packet.referent?).to be false
272
+ end
273
+ end
274
+ end
275
+
276
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrLpByte do
277
+ subject(:packet) { described_class.new }
278
+
279
+ it { is_expected.to respond_to :referent_identifier }
280
+ it { is_expected.to respond_to :max_count }
281
+ it { is_expected.to respond_to :offset }
282
+ it { is_expected.to respond_to :actual_count }
283
+ it { is_expected.to respond_to :bytes }
284
+
285
+ it 'is little endian' do
286
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
287
+ end
288
+
289
+ describe '#referent_identifier' do
290
+ it 'is a 32-bit unsigned integer' do
291
+ expect(packet.referent_identifier).to be_a BinData::Uint32le
292
+ end
293
+
294
+ it 'has an initial value of 0x00020000' do
295
+ expect(packet.referent_identifier).to eq(0x00020000)
296
+ end
297
+ end
298
+
299
+ describe '#max_count' do
300
+ it 'is a 32-bit unsigned integer' do
301
+ expect(packet.max_count).to be_a BinData::Uint32le
302
+ end
303
+
304
+ it 'has an initial value equal to #actual_count' do
305
+ packet.actual_count = 345
306
+ expect(packet.max_count).to eq(345)
307
+ end
308
+
309
+ it 'exists if #referent_identifier is not zero' do
310
+ expect(packet.max_count?).to be true
311
+ end
312
+
313
+ it 'does not exist if #referent_identifier is zero' do
314
+ packet.referent_identifier = 0
315
+ expect(packet.max_count?).to be false
316
+ end
317
+ end
318
+
319
+ describe '#offset' do
320
+ it 'is a 32-bit unsigned integer' do
321
+ expect(packet.offset).to be_a BinData::Uint32le
322
+ end
323
+
324
+ it 'has an initial value of 0' do
325
+ expect(packet.offset).to eq(0)
326
+ end
327
+
328
+ it 'exists if #referent_identifier is not zero' do
329
+ expect(packet.offset?).to be true
330
+ end
331
+
332
+ it 'does not exist if #referent_identifier is zero' do
333
+ packet.referent_identifier = 0
334
+ expect(packet.offset?).to be false
335
+ end
336
+ end
337
+
338
+ describe '#actual_count' do
339
+ it 'is a 32-bit unsigned integer' do
340
+ expect(packet.actual_count).to be_a BinData::Uint32le
341
+ end
342
+
343
+ it 'has an initial value equal to #bytes size' do
344
+ packet.bytes << 2 << 3 << 4 << 5
345
+ expect(packet.actual_count).to eq(4)
346
+ end
347
+
348
+ it 'exists if #referent_identifier is not zero' do
349
+ expect(packet.actual_count?).to be true
350
+ end
351
+
352
+ it 'does not exist if #referent_identifier is zero' do
353
+ packet.referent_identifier = 0
354
+ expect(packet.actual_count?).to be false
355
+ end
356
+ end
357
+
358
+ describe '#bytes' do
359
+ it 'is a Bindata::Array' do
360
+ expect(packet.bytes).to be_a BinData::Array
361
+ end
362
+
363
+ it 'has an initial length equal to #actual_count' do
364
+ packet.actual_count = 3
365
+ expect(packet.bytes.size).to eq(3)
366
+ end
367
+
368
+ it 'is 8-bit unsigned integer elements' do
369
+ expect(packet.bytes[0]).to be_a BinData::Uint8
370
+ end
371
+
372
+ it 'exists if #referent_identifier is not zero' do
373
+ expect(packet.bytes?).to be true
374
+ end
375
+
376
+ it 'does not exist if #referent_identifier is zero' do
377
+ packet.referent_identifier = 0
378
+ expect(packet.bytes?).to be false
379
+ end
380
+ end
381
+ end
382
+
383
+ RSpec.describe RubySMB::Dcerpc::Ndr::NdrLpFileTime do
384
+ it 'is NdrTopLevelFullPointer subclass' do
385
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrTopLevelFullPointer
386
+ end
387
+
388
+ subject(:packet) { described_class.new }
389
+
390
+ it { is_expected.to respond_to :referent }
391
+
392
+ it 'is little endian' do
393
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
394
+ end
395
+
396
+ describe '#referent' do
397
+ it 'is a FileTime' do
398
+ expect(packet.referent).to be_a RubySMB::Field::FileTime
399
+ end
400
+
401
+ it 'exists if superclass #referent_identifier is not zero' do
402
+ expect(packet.referent?).to be true
403
+ end
404
+
405
+ it 'does not exist if superclass #referent_identifier is zero' do
406
+ packet.referent_identifier = 0
407
+ expect(packet.referent?).to be false
408
+ end
409
+ end
410
+ end