ruby_smb 2.0.9 → 2.0.13

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 (228) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +5 -15
  4. data/examples/auth_capture.rb +71 -0
  5. data/examples/dump_secrets_from_sid.rb +207 -0
  6. data/examples/enum_domain_users.rb +75 -0
  7. data/examples/get_computer_info.rb +42 -0
  8. data/examples/query_service_status.rb +42 -4
  9. data/lib/ruby_smb/client/negotiation.rb +1 -1
  10. data/lib/ruby_smb/client.rb +10 -20
  11. data/lib/ruby_smb/dcerpc/bind.rb +28 -20
  12. data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
  13. data/lib/ruby_smb/dcerpc/client.rb +542 -0
  14. data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
  15. data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
  16. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
  17. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
  18. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
  19. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
  20. data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
  21. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
  22. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
  23. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
  24. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
  25. data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
  26. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
  27. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
  28. data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
  29. data/lib/ruby_smb/dcerpc/epm.rb +75 -0
  30. data/lib/ruby_smb/dcerpc/error.rb +17 -0
  31. data/lib/ruby_smb/dcerpc/ndr.rb +1159 -297
  32. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +3 -13
  33. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +3 -3
  34. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +3 -13
  35. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +1 -1
  36. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +3 -11
  37. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +1 -1
  38. data/lib/ruby_smb/dcerpc/netlogon.rb +5 -4
  39. data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
  40. data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
  41. data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
  42. data/lib/ruby_smb/dcerpc/request.rb +79 -32
  43. data/lib/ruby_smb/dcerpc/response.rb +45 -10
  44. data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
  45. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +11 -11
  46. data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
  47. data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
  48. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
  49. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
  50. data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
  51. data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
  52. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
  53. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
  54. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
  55. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
  56. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
  57. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
  58. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
  59. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
  60. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
  61. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
  62. data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
  63. data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
  64. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
  65. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
  66. data/lib/ruby_smb/dcerpc/samr.rb +613 -0
  67. data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
  68. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
  69. data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
  70. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +13 -25
  71. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +2 -2
  72. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +1 -1
  73. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +1 -1
  74. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +1 -1
  75. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +4 -14
  76. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +1 -1
  77. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +3 -11
  78. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +1 -1
  79. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +1 -1
  80. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +12 -11
  81. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +1 -1
  82. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +9 -8
  83. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +3 -3
  84. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +1 -1
  85. data/lib/ruby_smb/dcerpc/svcctl.rb +1 -3
  86. data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
  87. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
  88. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +2 -13
  89. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +3 -3
  90. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +3 -20
  91. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
  92. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
  93. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
  94. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
  95. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
  96. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +5 -6
  97. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
  98. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
  99. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -14
  100. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
  101. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
  102. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +0 -9
  103. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +1 -1
  104. data/lib/ruby_smb/dcerpc/winreg.rb +10 -14
  105. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
  106. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
  107. data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
  108. data/lib/ruby_smb/dcerpc.rb +41 -11
  109. data/lib/ruby_smb/dialect.rb +45 -0
  110. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  111. data/lib/ruby_smb/field/file_time.rb +1 -1
  112. data/lib/ruby_smb/field/string16.rb +5 -1
  113. data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
  114. data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
  115. data/lib/ruby_smb/gss/provider.rb +35 -0
  116. data/lib/ruby_smb/gss.rb +56 -63
  117. data/lib/ruby_smb/ntlm.rb +61 -0
  118. data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
  119. data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
  120. data/lib/ruby_smb/server/server_client.rb +162 -0
  121. data/lib/ruby_smb/server.rb +54 -0
  122. data/lib/ruby_smb/signing.rb +59 -0
  123. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
  124. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
  125. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  126. data/lib/ruby_smb/smb1/pipe.rb +4 -0
  127. data/lib/ruby_smb/smb1/tree.rb +1 -1
  128. data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
  129. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  130. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  131. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  132. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  133. data/lib/ruby_smb/smb2/pipe.rb +4 -0
  134. data/lib/ruby_smb/smb2/tree.rb +1 -1
  135. data/lib/ruby_smb/smb2.rb +3 -1
  136. data/lib/ruby_smb/version.rb +1 -1
  137. data/lib/ruby_smb.rb +2 -1
  138. data/spec/lib/ruby_smb/client_spec.rb +8 -11
  139. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  140. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  141. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  142. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  143. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3792 -1373
  144. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +4 -4
  145. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +4 -4
  146. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +2 -2
  147. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +2 -2
  148. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  149. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  150. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  151. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  152. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  153. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +29 -28
  154. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  155. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  156. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  157. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  158. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  159. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  160. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  161. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  162. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  163. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  164. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  165. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  166. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  167. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  168. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  169. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  170. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  171. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  172. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +56 -79
  173. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +4 -4
  174. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +2 -2
  176. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +2 -2
  177. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +19 -29
  178. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +2 -2
  179. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +9 -15
  180. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +2 -2
  181. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +2 -2
  182. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +22 -22
  183. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +2 -2
  184. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +18 -14
  185. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +5 -4
  186. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +2 -2
  187. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +1 -5
  188. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  189. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  190. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +4 -41
  191. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +4 -4
  192. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -52
  193. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  194. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  195. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  196. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  197. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  198. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -25
  199. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  200. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  201. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  202. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +10 -22
  203. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  204. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +0 -12
  205. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +2 -2
  206. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +18 -47
  207. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  208. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  209. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  210. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  211. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  212. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  213. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  214. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  215. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  216. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  217. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +18 -37
  218. data/spec/lib/ruby_smb/smb1/tree_spec.rb +4 -4
  219. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  220. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +18 -16
  221. data/spec/lib/ruby_smb/smb2/tree_spec.rb +5 -5
  222. data/spec/support/bin_helper.rb +9 -0
  223. data.tar.gz.sig +2 -1
  224. metadata +119 -6
  225. metadata.gz.sig +0 -0
  226. data/lib/ruby_smb/client/signing.rb +0 -64
  227. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -38
  228. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -135
@@ -0,0 +1,2169 @@
1
+ require 'ruby_smb/dcerpc/client'
2
+
3
+ RSpec.describe RubySMB::Dcerpc::Drsr do
4
+ def random_str(nb = 8)
5
+ nb.times.map { rand('a'.ord..'z'.ord).chr }.join
6
+ end
7
+
8
+ let(:drsr) do
9
+ RubySMB::Dcerpc::Client.new('1.2.3.4', RubySMB::Dcerpc::Drsr)
10
+ end
11
+
12
+ describe described_class::DrsHandle do
13
+ subject(:packet) { described_class.new }
14
+
15
+ it 'is a Ndr::NdrContextHandle' do
16
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrContextHandle
17
+ end
18
+ it 'reads itself' do
19
+ value = {
20
+ context_handle_attributes: rand(0xFFFFFFFF),
21
+ context_handle_uuid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003'
22
+ }
23
+ new_struct = described_class.new
24
+ new_struct.set(value)
25
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
26
+ end
27
+ end
28
+
29
+ describe described_class::DrsConfStringz16 do
30
+ subject(:packet) { described_class.new }
31
+
32
+ it 'is a Ndr::NdrConfArray' do
33
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
34
+ end
35
+ it 'has elements of type RubySMB::Dcerpc::Ndr::NdrWideChar' do
36
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Ndr::NdrWideChar
37
+ end
38
+ it 'reads itself' do
39
+ value = 'Test String'.encode('utf-16le').chars
40
+ new_struct = described_class.new(value)
41
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
42
+ end
43
+ end
44
+
45
+ describe described_class::DsName do
46
+ subject(:packet) { described_class.new }
47
+
48
+ it { is_expected.to respond_to :struct_len }
49
+ it { is_expected.to respond_to :sid_len }
50
+ it { is_expected.to respond_to :guid }
51
+ it { is_expected.to respond_to :sid }
52
+ it { is_expected.to respond_to :name_len }
53
+ it { is_expected.to respond_to :string_name }
54
+
55
+ it 'is a Ndr::NdrStruct' do
56
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
57
+ end
58
+ it 'is little endian' do
59
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
60
+ end
61
+ describe '#struct_len' do
62
+ it 'is a NdrUint32 structure' do
63
+ expect(packet.struct_len).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
64
+ end
65
+ it 'defaults to the size of the structure' do
66
+ expect(packet.struct_len).to eq(packet.num_bytes)
67
+ end
68
+ end
69
+ describe '#sid_len' do
70
+ it 'is a NdrUint32 structure' do
71
+ expect(packet.sid_len).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
72
+ end
73
+ end
74
+ describe '#guid' do
75
+ it 'is a Uuid structure' do
76
+ expect(packet.guid).to be_a RubySMB::Dcerpc::Uuid
77
+ end
78
+ end
79
+ describe '#sid' do
80
+ it 'is a String' do
81
+ expect(packet.sid).to be_a BinData::String
82
+ end
83
+ it 'is always 28 bytes long' do
84
+ expect(packet.sid.size).to eq(28)
85
+ packet.sid = 'AAA'
86
+ expect(packet.sid.size).to eq(28)
87
+ end
88
+ end
89
+ describe '#name_len' do
90
+ it 'is a NdrUint32 structure' do
91
+ expect(packet.name_len).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
92
+ end
93
+ it 'is the length of #string_name without the null terminator' do
94
+ packet.string_name = "Test123\x00".encode('utf-16le').chars
95
+ expect(packet.name_len).to eq('Test123'.size)
96
+ end
97
+ end
98
+ describe '#string_name' do
99
+ it 'is a DrsConfStringz16 structure' do
100
+ expect(packet.string_name).to be_a RubySMB::Dcerpc::Drsr::DrsConfStringz16
101
+ end
102
+ end
103
+ it 'reads itself' do
104
+ value = {
105
+ struct_len: 30,
106
+ sid_len: 4,
107
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
108
+ sid: 'A' * 28,
109
+ string_name: 'Test string'.encode('utf-16le').chars
110
+ }
111
+ new_struct = described_class.new(value)
112
+ expect(packet.read(new_struct.to_binary_s)).to eq(value.merge(name_len: value[:string_name].size - 1))
113
+ end
114
+ end
115
+
116
+ describe described_class::DsNamePtr do
117
+ subject(:packet) { described_class.new }
118
+
119
+ it 'is a DsName' do
120
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::DsName
121
+ end
122
+ it 'is a NdrPointer' do
123
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
124
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
125
+ end
126
+ it 'has a referent which is 4-bytes aligned' do
127
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(4)
128
+ end
129
+ it 'reads itself' do
130
+ value = {
131
+ struct_len: rand(0xFFFFFFFF),
132
+ sid_len: rand(0xFFFFFFFF),
133
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
134
+ sid: 'A' * 28,
135
+ string_name: 'Test string'.encode('utf-16le').chars
136
+ }
137
+ new_struct = described_class.new(value)
138
+ expect(packet.read(new_struct.to_binary_s)).to eq(value.merge(name_len: value[:string_name].size - 1))
139
+ end
140
+ end
141
+
142
+ describe described_class::Usn do
143
+ subject(:packet) { described_class.new }
144
+
145
+ it 'is a BinData::Int64le' do
146
+ expect(described_class).to be < BinData::Int64le
147
+ end
148
+ it 'is 8-bytes aligned' do
149
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
150
+ end
151
+ it 'reads itself' do
152
+ value = rand(0xFFFFFFFF)
153
+ new_struct = described_class.new(value)
154
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
155
+ end
156
+ end
157
+
158
+ describe described_class::UsnVector do
159
+ subject(:packet) { described_class.new }
160
+
161
+ it { is_expected.to respond_to :usn_high_obj_update }
162
+ it { is_expected.to respond_to :usn_reserved }
163
+ it { is_expected.to respond_to :usn_high_prop_update }
164
+
165
+ it 'is a Ndr::NdrStruct' do
166
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
167
+ end
168
+ it 'is 8-bytes aligned' do
169
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
170
+ end
171
+ describe '#usn_high_obj_update' do
172
+ it 'is a Usn structure' do
173
+ expect(packet.usn_high_obj_update).to be_a RubySMB::Dcerpc::Drsr::Usn
174
+ end
175
+ end
176
+ describe '#usn_reserved' do
177
+ it 'is a Usn structure' do
178
+ expect(packet.usn_reserved).to be_a RubySMB::Dcerpc::Drsr::Usn
179
+ end
180
+ end
181
+ describe '#usn_high_prop_update' do
182
+ it 'is a Usn structure' do
183
+ expect(packet.usn_high_prop_update).to be_a RubySMB::Dcerpc::Drsr::Usn
184
+ end
185
+ end
186
+ it 'reads itself' do
187
+ value = {
188
+ usn_high_obj_update: rand(0xFFFFFFFF),
189
+ usn_reserved: rand(0xFFFFFFFF),
190
+ usn_high_prop_update:rand(0xFFFFFFFF)
191
+ }
192
+ new_struct = described_class.new(value)
193
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
194
+ end
195
+ end
196
+
197
+ describe described_class::UptodateCursorV1 do
198
+ subject(:packet) { described_class.new }
199
+
200
+ it { is_expected.to respond_to :uuid_dsa }
201
+ it { is_expected.to respond_to :usn_high_prop_update }
202
+
203
+ it 'is a Ndr::NdrStruct' do
204
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
205
+ end
206
+ it 'is 8-bytes aligned' do
207
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
208
+ end
209
+ describe '#uuid_dsa' do
210
+ it 'is a Uuid structure' do
211
+ expect(packet.uuid_dsa).to be_a RubySMB::Dcerpc::Uuid
212
+ end
213
+ end
214
+ describe '#usn_high_prop_update' do
215
+ it 'is a Usn structure' do
216
+ expect(packet.usn_high_prop_update).to be_a RubySMB::Dcerpc::Drsr::Usn
217
+ end
218
+ end
219
+ it 'reads itself' do
220
+ value = {
221
+ uuid_dsa:'ee1ecfe6-109d-11ec-82a8-0242ac130003',
222
+ usn_high_prop_update: rand(0xFFFFFFFF)
223
+ }
224
+ new_struct = described_class.new(value)
225
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
226
+ end
227
+ end
228
+
229
+ describe described_class::UptodateVectorV1Ext do
230
+ subject(:packet) { described_class.new }
231
+
232
+ it { is_expected.to respond_to :dw_version }
233
+ it { is_expected.to respond_to :dw_reserved1 }
234
+ it { is_expected.to respond_to :c_num_cursors }
235
+ it { is_expected.to respond_to :dw_reserved2 }
236
+ it { is_expected.to respond_to :rg_cursors }
237
+
238
+ it 'is a Ndr::NdrStruct' do
239
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
240
+ end
241
+ it 'is 8-bytes aligned' do
242
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
243
+ end
244
+ describe '#dw_version' do
245
+ it 'is a NdrUint32 structure' do
246
+ expect(packet.dw_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
247
+ end
248
+ end
249
+ describe '#dw_reserved1' do
250
+ it 'is a NdrUint32 structure' do
251
+ expect(packet.dw_reserved1).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
252
+ end
253
+ end
254
+ describe '#c_num_cursors' do
255
+ it 'is a NdrUint32 structure' do
256
+ expect(packet.c_num_cursors).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
257
+ end
258
+ end
259
+ describe '#dw_reserved2' do
260
+ it 'is a NdrUint32 structure' do
261
+ expect(packet.dw_reserved2).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
262
+ end
263
+ end
264
+ describe '#rg_cursors' do
265
+ it 'is a NdrConfArray structure' do
266
+ expect(packet.rg_cursors).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
267
+ end
268
+ it 'has elements of type UptodateCursorV1' do
269
+ expect(packet.rg_cursors[0]).to be_a RubySMB::Dcerpc::Drsr::UptodateCursorV1
270
+ end
271
+ end
272
+ it 'reads itself' do
273
+ value = {
274
+ dw_version: rand(0xFFFFFFFF),
275
+ dw_reserved1: rand(0xFFFFFFFF),
276
+ c_num_cursors: rand(0xFFFFFFFF),
277
+ dw_reserved2: rand(0xFFFFFFFF),
278
+ rg_cursors: [{
279
+ uuid_dsa:'ee1ecfe6-109d-11ec-82a8-0242ac130003',
280
+ usn_high_prop_update: rand(0xFFFFFFFF)
281
+ }]
282
+ }
283
+ new_struct = described_class.new(value)
284
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
285
+ end
286
+ end
287
+
288
+ describe described_class::UptodateVectorV1ExtPtr do
289
+ subject(:packet) { described_class.new }
290
+
291
+ it 'is a UptodateVectorV1Ext' do
292
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::UptodateVectorV1Ext
293
+ end
294
+ it 'is a NdrPointer' do
295
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
296
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
297
+ end
298
+ it 'has a referent which is 8-bytes aligned' do
299
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(8)
300
+ end
301
+ it 'reads itself' do
302
+ value = {
303
+ dw_version: rand(0xFFFFFFFF),
304
+ dw_reserved1: rand(0xFFFFFFFF),
305
+ c_num_cursors: rand(0xFFFFFFFF),
306
+ dw_reserved2: rand(0xFFFFFFFF),
307
+ rg_cursors: [{
308
+ uuid_dsa:'ee1ecfe6-109d-11ec-82a8-0242ac130003',
309
+ usn_high_prop_update: rand(0xFFFFFFFF)
310
+ }]
311
+ }
312
+ new_struct = described_class.new(value)
313
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
314
+ end
315
+ end
316
+
317
+ describe described_class::AttrtypRequestPlugin do
318
+ let(:test_struct) do
319
+ Class.new(BinData::Record) do
320
+ include RubySMB::Dcerpc::Drsr::AttrtypRequestPlugin
321
+ partial_attr_vector_v1_ext_ptr :p_partial_attr_set
322
+ schema_prefix_table :prefix_table_dest
323
+ end.new
324
+ end
325
+
326
+ describe '#add_attrtyp_from_oid' do
327
+ it 'correctly adds ATTRYP from OID' do
328
+ oid = '1.2.840.113556.1.2.1'
329
+ expected_struct = {
330
+ p_partial_attr_set: {
331
+ dw_version: 1,
332
+ dw_reserved1: 0,
333
+ c_attrs: 1,
334
+ rg_partial_attr: [1]
335
+ },
336
+ prefix_table_dest: {
337
+ prefix_count: 1,
338
+ p_prefix_entry: [{ ndx: 0, prefix: {oid_length: 8, elements: [42, 134, 72, 134, 247, 20, 1, 2]}}]
339
+ }
340
+ }
341
+ test_struct.add_attrtyp_from_oid(oid)
342
+ expect(test_struct).to eq(expected_struct)
343
+ end
344
+ end
345
+ end
346
+
347
+ describe described_class::AttrtypResponsePlugin do
348
+ let(:test_struct) do
349
+ values = {
350
+ prefix_table_src: {
351
+ p_prefix_entry: [
352
+ { ndx: 1, prefix: {elements: [96, 134, 72, 1, 101, 2, 1, 4]}},
353
+ { ndx: 2, prefix: {elements: [42, 134, 72, 134, 247, 20, 1, 2]}}
354
+ ]
355
+ }
356
+ }
357
+ Class.new(BinData::Record) do
358
+ include RubySMB::Dcerpc::Drsr::AttrtypResponsePlugin
359
+ schema_prefix_table :prefix_table_src
360
+ end.new(values)
361
+ end
362
+
363
+ describe '#oid_from_attid' do
364
+ it 'correctly converts ATTRYP to OID' do
365
+ attr_typ = 131073
366
+ oid = '1.2.840.113556.1.2.1'
367
+ expect(test_struct.oid_from_attid(attr_typ)).to eq(oid)
368
+ end
369
+ end
370
+ end
371
+
372
+ describe described_class::Attrtyp do
373
+ it 'is a Ndr::NdrUint32' do
374
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrUint32
375
+ end
376
+ end
377
+
378
+ describe described_class::PartialAttrVectorV1Ext do
379
+ subject(:packet) { described_class.new }
380
+
381
+ it { is_expected.to respond_to :dw_version }
382
+ it { is_expected.to respond_to :dw_reserved1 }
383
+ it { is_expected.to respond_to :c_attrs }
384
+ it { is_expected.to respond_to :rg_partial_attr }
385
+
386
+ it 'is a Ndr::NdrStruct' do
387
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
388
+ end
389
+ describe '#dw_version' do
390
+ it 'is a NdrUint32 structure' do
391
+ expect(packet.dw_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
392
+ end
393
+ it 'defaults to 1' do
394
+ expect(packet.dw_version).to eq(1)
395
+ end
396
+ end
397
+ describe '#dw_reserved1' do
398
+ it 'is a NdrUint32 structure' do
399
+ expect(packet.dw_reserved1).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
400
+ end
401
+ end
402
+ describe '#c_attrs' do
403
+ it 'is a NdrUint32 structure' do
404
+ expect(packet.c_attrs).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
405
+ end
406
+ it 'defaults to #rg_partial_attr max_count value' do
407
+ packet.rg_partial_attr = [1,2,3]
408
+ expect(packet.c_attrs).to eq(3)
409
+ end
410
+ end
411
+ describe '#rg_partial_attr' do
412
+ it 'is a Ndr::NdrConfArray' do
413
+ expect(packet.rg_partial_attr).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
414
+ end
415
+ it 'has elements of type Attrtyp' do
416
+ expect(packet.rg_partial_attr[0]).to be_a RubySMB::Dcerpc::Drsr::Attrtyp
417
+ end
418
+ end
419
+ it 'reads itself' do
420
+ value = {
421
+ dw_version: rand(0xFFFFFFFF),
422
+ dw_reserved1: rand(0xFFFFFFFF),
423
+ c_attrs: 3,
424
+ rg_partial_attr: [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)]
425
+ }
426
+ new_struct = described_class.new(value)
427
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
428
+ end
429
+ end
430
+
431
+ describe described_class::PartialAttrVectorV1ExtPtr do
432
+ subject(:packet) { described_class.new }
433
+
434
+ it 'is a PartialAttrVectorV1Ext' do
435
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::PartialAttrVectorV1Ext
436
+ end
437
+ it 'is a NdrPointer' do
438
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
439
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
440
+ end
441
+ it 'has a referent which is 4-bytes aligned' do
442
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(4)
443
+ end
444
+ it 'reads itself' do
445
+ value = {
446
+ dw_version: rand(0xFFFFFFFF),
447
+ dw_reserved1: rand(0xFFFFFFFF),
448
+ c_attrs: 3,
449
+ rg_partial_attr: [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)]
450
+ }
451
+ new_struct = described_class.new(value)
452
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
453
+ end
454
+ end
455
+
456
+ describe described_class::DrsByteArrayPtr do
457
+ subject(:packet) { described_class.new }
458
+
459
+ it 'is a Ndr::NdrConfArray' do
460
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
461
+ end
462
+ it 'is a NdrPointer' do
463
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
464
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
465
+ end
466
+ it 'has elements of type Ndr::NdrUint8' do
467
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Ndr::NdrUint8
468
+ end
469
+ it 'reads itself' do
470
+ value = [rand(0xFF), rand(0xFF), rand(0xFF)]
471
+ new_struct = described_class.new(value)
472
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
473
+ end
474
+ end
475
+
476
+ describe described_class::OidT do
477
+ subject(:packet) { described_class.new }
478
+
479
+ it { is_expected.to respond_to :oid_length }
480
+ it { is_expected.to respond_to :elements }
481
+
482
+ it 'is a Ndr::NdrStruct' do
483
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
484
+ end
485
+ describe '#oid_length' do
486
+ it 'is a NdrUint32 structure' do
487
+ expect(packet.oid_length).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
488
+ end
489
+ it 'defaults to the size of #drs_byte_array_ptr' do
490
+ packet.elements = [1,2,3,4]
491
+ expect(packet.oid_length).to eq(4)
492
+ end
493
+ end
494
+ describe '#elements' do
495
+ it 'is a DrsByteArrayPtr' do
496
+ expect(packet.elements).to be_a RubySMB::Dcerpc::Drsr::DrsByteArrayPtr
497
+ end
498
+ end
499
+ it 'reads itself' do
500
+ value = {
501
+ oid_length: 3,
502
+ elements: [rand(0xFF), rand(0xFF), rand(0xFF)]
503
+ }
504
+ new_struct = described_class.new(value)
505
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
506
+ end
507
+ end
508
+
509
+ describe described_class::PrefixTableEntry do
510
+ subject(:packet) { described_class.new }
511
+
512
+ it { is_expected.to respond_to :ndx }
513
+ it { is_expected.to respond_to :prefix }
514
+
515
+ it 'is a Ndr::NdrStruct' do
516
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
517
+ end
518
+ describe '#ndx' do
519
+ it 'is a NdrUint32 structure' do
520
+ expect(packet.ndx).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
521
+ end
522
+ end
523
+ describe '#prefix' do
524
+ it 'is a OidT' do
525
+ expect(packet.prefix).to be_a RubySMB::Dcerpc::Drsr::OidT
526
+ end
527
+ end
528
+ it 'reads itself' do
529
+ value = {
530
+ ndx: rand(0xFFFFFFFF),
531
+ prefix: {oid_length: 3, elements: [rand(0xFF), rand(0xFF), rand(0xFF)]}
532
+ }
533
+ new_struct = described_class.new(value)
534
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
535
+ end
536
+ end
537
+
538
+ describe described_class::PrefixTableEntryArrayPtr do
539
+ subject(:packet) { described_class.new }
540
+
541
+ it 'is a Ndr::NdrConfArray' do
542
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
543
+ end
544
+ it 'is a NdrPointer' do
545
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
546
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
547
+ end
548
+ it 'has elements of type PrefixTableEntry' do
549
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Drsr::PrefixTableEntry
550
+ end
551
+ it 'reads itself' do
552
+ value = [{
553
+ ndx: rand(0xFFFFFFFF),
554
+ prefix: {oid_length: 3, elements: [rand(0xFF), rand(0xFF), rand(0xFF)]}
555
+ }]
556
+ new_struct = described_class.new(value)
557
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
558
+ end
559
+ end
560
+
561
+ describe described_class::SchemaPrefixTable do
562
+ subject(:packet) { described_class.new }
563
+
564
+ it { is_expected.to respond_to :prefix_count }
565
+ it { is_expected.to respond_to :p_prefix_entry }
566
+
567
+ it 'is a Ndr::NdrStruct' do
568
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
569
+ end
570
+ it 'is 4-bytes aligned' do
571
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
572
+ end
573
+ describe '#prefix_count' do
574
+ it 'is a NdrUint32 structure' do
575
+ expect(packet.prefix_count).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
576
+ end
577
+ it 'defaults to the size #p_prefix_entry max_count' do
578
+ packet.p_prefix_entry.max_count = 3
579
+ expect(packet.prefix_count).to eq(3)
580
+ end
581
+ end
582
+ describe '#p_prefix_entry' do
583
+ it 'is a PrefixTableEntryArrayPtr' do
584
+ expect(packet.p_prefix_entry).to be_a RubySMB::Dcerpc::Drsr::PrefixTableEntryArrayPtr
585
+ end
586
+ end
587
+ it 'reads itself' do
588
+ value = {
589
+ prefix_count: 5,
590
+ p_prefix_entry: [{
591
+ ndx: rand(0xFFFFFFFF),
592
+ prefix: {oid_length: 3, elements: [rand(0xFF), rand(0xFF), rand(0xFF)]}
593
+ }]
594
+ }
595
+ new_struct = described_class.new(value)
596
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
597
+ end
598
+ end
599
+
600
+ describe described_class::DrsConfStringz do
601
+ subject(:packet) { described_class.new }
602
+
603
+ it 'is a Ndr::NdrConfArray' do
604
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
605
+ end
606
+ it 'has elements of type RubySMB::Dcerpc::Ndr::NdrChar' do
607
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Ndr::NdrChar
608
+ end
609
+ it 'reads itself' do
610
+ value = 'Test String'.chars
611
+ new_struct = described_class.new(value)
612
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
613
+ end
614
+ end
615
+
616
+ describe described_class::MtxAddr do
617
+ subject(:packet) { described_class.new }
618
+
619
+ it { is_expected.to respond_to :mtx_name_len }
620
+ it { is_expected.to respond_to :mtx_name }
621
+
622
+ it 'is a Ndr::NdrStruct' do
623
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
624
+ end
625
+ it 'is 4-bytes aligned' do
626
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
627
+ end
628
+ describe '#mtx_name_len' do
629
+ it 'is a NdrUint32 structure' do
630
+ expect(packet.mtx_name_len).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
631
+ end
632
+ it 'defaults to the length of #mtx_name including the terminating null character' do
633
+ packet.mtx_name = ['A', 'B', 'C', "\x00"]
634
+ expect(packet.mtx_name_len).to eq(4)
635
+ end
636
+ end
637
+ describe '#mtx_name' do
638
+ it 'is a DrsConfStringz' do
639
+ expect(packet.mtx_name).to be_a RubySMB::Dcerpc::Drsr::DrsConfStringz
640
+ end
641
+ end
642
+ it 'reads itself' do
643
+ value = {
644
+ mtx_name_len: 4,
645
+ mtx_name: ['A', 'B', 'C', "\x00"]
646
+ }
647
+ new_struct = described_class.new(value)
648
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
649
+ end
650
+ end
651
+
652
+ describe described_class::MtxAddrPtr do
653
+ subject(:packet) { described_class.new }
654
+
655
+ it 'is a MtxAddr' do
656
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::MtxAddr
657
+ end
658
+ it 'is a NdrPointer' do
659
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
660
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
661
+ end
662
+ it 'has a referent which is 4-bytes aligned' do
663
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(4)
664
+ end
665
+ it 'reads itself' do
666
+ value = {
667
+ mtx_name_len: 4,
668
+ mtx_name: ['A', 'B', 'C', "\x00"]
669
+ }
670
+ new_struct = described_class.new(value)
671
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
672
+ end
673
+ end
674
+
675
+ describe described_class::VarSizeBufferWithVersion do
676
+ subject(:packet) { described_class.new }
677
+
678
+ it { is_expected.to respond_to :ul_version }
679
+ it { is_expected.to respond_to :cb_byte_buffer }
680
+ it { is_expected.to respond_to :ul_padding }
681
+ it { is_expected.to respond_to :rg_buffer }
682
+
683
+ it 'is a Ndr::NdrStruct' do
684
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
685
+ end
686
+ it 'is 8-bytes aligned' do
687
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
688
+ end
689
+ describe '#ul_version' do
690
+ it 'is a NdrUint32 structure' do
691
+ expect(packet.ul_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
692
+ end
693
+ end
694
+ describe '#cb_byte_buffer' do
695
+ it 'is a NdrUint32 structure' do
696
+ expect(packet.cb_byte_buffer).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
697
+ end
698
+ it 'defaults to the length of #rg_buffer' do
699
+ packet.rg_buffer = [rand(0xFF)] * 4
700
+ expect(packet.cb_byte_buffer).to eq(4)
701
+ end
702
+ end
703
+ describe '#ul_padding' do
704
+ it 'is a NdrUint64 structure' do
705
+ expect(packet.ul_padding).to be_a RubySMB::Dcerpc::Ndr::NdrUint64
706
+ end
707
+ end
708
+ describe '#rg_buffer' do
709
+ it 'is a NdrConfArray structure' do
710
+ expect(packet.rg_buffer).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
711
+ end
712
+ it 'has elements of type Ndr::NdrUint8' do
713
+ expect(packet.rg_buffer[0]).to be_a RubySMB::Dcerpc::Ndr::NdrUint8
714
+ end
715
+ end
716
+ it 'reads itself' do
717
+ value = {
718
+ ul_version: rand(0xFFFFFFFF),
719
+ cb_byte_buffer: rand(0xFFFFFFFF),
720
+ ul_padding: rand(0xFFFFFFFFFFFFFFFF),
721
+ rg_buffer: [rand(0xFF)] * 4
722
+ }
723
+ new_struct = described_class.new(value)
724
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
725
+ end
726
+ end
727
+
728
+ describe described_class::VarSizeBufferWithVersionPtr do
729
+ subject(:packet) { described_class.new }
730
+
731
+ it 'is a VarSizeBufferWithVersion' do
732
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::VarSizeBufferWithVersion
733
+ end
734
+ it 'is a NdrPointer' do
735
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
736
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
737
+ end
738
+ it 'has a referent which is 8-bytes aligned' do
739
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(8)
740
+ end
741
+ it 'reads itself' do
742
+ value = {
743
+ ul_version: rand(0xFFFFFFFF),
744
+ cb_byte_buffer: rand(0xFFFFFFFF),
745
+ ul_padding: rand(0xFFFFFFFFFFFFFFFF),
746
+ rg_buffer: [rand(0xFF)] * 4
747
+ }
748
+ new_struct = described_class.new(value)
749
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
750
+ end
751
+ end
752
+
753
+ describe described_class::Attrval do
754
+ subject(:packet) { described_class.new }
755
+
756
+ it { is_expected.to respond_to :val_len }
757
+ it { is_expected.to respond_to :p_val }
758
+
759
+ it 'is a Ndr::NdrStruct' do
760
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
761
+ end
762
+ it 'is 4-bytes aligned' do
763
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
764
+ end
765
+ describe '#val_len' do
766
+ it 'is a NdrUint32 structure' do
767
+ expect(packet.val_len).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
768
+ end
769
+ it 'defaults to the length of #p_val in bytes' do
770
+ packet.p_val = [rand(0xFF)] * 4
771
+ expect(packet.val_len).to eq(4)
772
+ end
773
+ end
774
+ describe '#p_val' do
775
+ it 'is a DrsByteArrayPtr structure' do
776
+ expect(packet.p_val).to be_a RubySMB::Dcerpc::Drsr::DrsByteArrayPtr
777
+ end
778
+ end
779
+ it 'reads itself' do
780
+ value = {
781
+ val_len: rand(0xFFFFFFFF),
782
+ p_val: [rand(0xFF)] * 4
783
+ }
784
+ new_struct = described_class.new(value)
785
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
786
+ end
787
+ end
788
+
789
+ describe described_class::AttrvalArrayPtr do
790
+ subject(:packet) { described_class.new }
791
+
792
+ it 'is a Ndr::NdrConfArray' do
793
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
794
+ end
795
+ it 'is a NdrPointer' do
796
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
797
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
798
+ end
799
+ it 'has elements of type Attrval' do
800
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Drsr::Attrval
801
+ end
802
+ it 'reads itself' do
803
+ value = [{
804
+ val_len: rand(0xFFFFFFFF),
805
+ p_val: [rand(0xFF)] * 4
806
+ }]
807
+ new_struct = described_class.new(value)
808
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
809
+ end
810
+ end
811
+
812
+ describe described_class::Attrvalblock do
813
+ subject(:packet) { described_class.new }
814
+
815
+ it { is_expected.to respond_to :val_count }
816
+ it { is_expected.to respond_to :p_aval }
817
+
818
+ it 'is a Ndr::NdrStruct' do
819
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
820
+ end
821
+ it 'is 4-bytes aligned' do
822
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
823
+ end
824
+ describe '#val_count' do
825
+ it 'is a NdrUint32' do
826
+ expect(packet.val_count).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
827
+ end
828
+ it 'defaults to the size of #p_aval' do
829
+ packet.p_aval = [{p_val: [rand(0xFF)] * 4}] * 6
830
+ expect(packet.val_count).to eq(6)
831
+ end
832
+ end
833
+ describe '#p_aval' do
834
+ it 'is a AttrvalArrayPtr structure' do
835
+ expect(packet.p_aval).to be_a RubySMB::Dcerpc::Drsr::AttrvalArrayPtr
836
+ end
837
+ end
838
+ it 'reads itself' do
839
+ value = {
840
+ val_count: rand(0xFFFFFFFF),
841
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
842
+ }
843
+ new_struct = described_class.new(value)
844
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
845
+ end
846
+ end
847
+
848
+ describe described_class::Attr do
849
+ subject(:packet) { described_class.new }
850
+
851
+ it { is_expected.to respond_to :attr_typ }
852
+ it { is_expected.to respond_to :attr_val }
853
+
854
+ it 'is a Ndr::NdrStruct' do
855
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
856
+ end
857
+ it 'is 4-bytes aligned' do
858
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
859
+ end
860
+ describe '#attr_typ' do
861
+ it 'is a Attrtyp structure' do
862
+ expect(packet.attr_typ).to be_a RubySMB::Dcerpc::Drsr::Attrtyp
863
+ end
864
+ end
865
+ describe '#attr_val' do
866
+ it 'is a Attrvalblock structure' do
867
+ expect(packet.attr_val).to be_a RubySMB::Dcerpc::Drsr::Attrvalblock
868
+ end
869
+ end
870
+ it 'reads itself' do
871
+ value = {
872
+ attr_typ: rand(0xFFFFFFFF),
873
+ attr_val: {
874
+ val_count: rand(0xFFFFFFFF),
875
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
876
+ }
877
+ }
878
+ new_struct = described_class.new(value)
879
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
880
+ end
881
+ end
882
+
883
+ describe described_class::AttrArrayPtr do
884
+ subject(:packet) { described_class.new }
885
+
886
+ it 'is a Ndr::NdrConfArray' do
887
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
888
+ end
889
+ it 'is a NdrPointer' do
890
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
891
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
892
+ end
893
+ it 'has elements of type Attr' do
894
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Drsr::Attr
895
+ end
896
+ it 'reads itself' do
897
+ value = [{
898
+ attr_typ: rand(0xFFFFFFFF),
899
+ attr_val: {
900
+ val_count: rand(0xFFFFFFFF),
901
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
902
+ }
903
+ }]
904
+ new_struct = described_class.new(value)
905
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
906
+ end
907
+ end
908
+
909
+ describe described_class::Attrblock do
910
+ subject(:packet) { described_class.new }
911
+
912
+ it { is_expected.to respond_to :attr_count }
913
+ it { is_expected.to respond_to :p_attr }
914
+
915
+ it 'is a Ndr::NdrStruct' do
916
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
917
+ end
918
+ it 'is 4-bytes aligned' do
919
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
920
+ end
921
+ describe '#attr_count' do
922
+ it 'is a NdrUint32' do
923
+ expect(packet.attr_count).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
924
+ end
925
+ it 'defaults to the size of #p_attr' do
926
+ packet.p_attr = [{ attr_typ: rand(0xFFFFFFFF) }] * 6
927
+ expect(packet.attr_count).to eq(6)
928
+ end
929
+ end
930
+ describe '#p_attr' do
931
+ it 'is a AttrArrayPtr structure' do
932
+ expect(packet.p_attr).to be_a RubySMB::Dcerpc::Drsr::AttrArrayPtr
933
+ end
934
+ end
935
+ it 'reads itself' do
936
+ value = {
937
+ attr_count: rand(0xFFFFFFFF),
938
+ p_attr: [{
939
+ attr_typ: rand(0xFFFFFFFF),
940
+ attr_val: {
941
+ val_count: rand(0xFFFFFFFF),
942
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
943
+ }
944
+ }]
945
+ }
946
+ new_struct = described_class.new(value)
947
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
948
+ end
949
+ end
950
+
951
+ describe described_class::Entinf do
952
+ subject(:packet) { described_class.new }
953
+
954
+ it { is_expected.to respond_to :p_name }
955
+ it { is_expected.to respond_to :ul_flags }
956
+ it { is_expected.to respond_to :attr_block }
957
+
958
+ it 'is a Ndr::NdrStruct' do
959
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
960
+ end
961
+ it 'is 4-bytes aligned' do
962
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
963
+ end
964
+ describe '#p_name' do
965
+ it 'is a DsNamePtr' do
966
+ expect(packet.p_name).to be_a RubySMB::Dcerpc::Drsr::DsNamePtr
967
+ end
968
+ end
969
+ describe '#ul_flags' do
970
+ it 'is a NdrUint32' do
971
+ expect(packet.ul_flags).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
972
+ end
973
+ end
974
+ describe '#attr_block' do
975
+ it 'is a Attrblock structure' do
976
+ expect(packet.attr_block).to be_a RubySMB::Dcerpc::Drsr::Attrblock
977
+ end
978
+ end
979
+ it 'reads itself' do
980
+ value = {
981
+ p_name: {
982
+ struct_len: rand(0xFFFFFFFF),
983
+ sid_len: rand(0xFFFFFFFF),
984
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
985
+ sid: 'A' * 28,
986
+ name_len: 10,
987
+ string_name: 'Test string'.encode('utf-16le').chars
988
+ },
989
+ ul_flags: rand(0xFFFFFFFF),
990
+ attr_block: {
991
+ attr_count: rand(0xFFFFFFFF),
992
+ p_attr: [{
993
+ attr_typ: rand(0xFFFFFFFF),
994
+ attr_val: {
995
+ val_count: rand(0xFFFFFFFF),
996
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
997
+ }
998
+ }]
999
+ }
1000
+ }
1001
+ new_struct = described_class.new(value)
1002
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1003
+ end
1004
+ end
1005
+
1006
+ describe described_class::Dstime do
1007
+ subject(:packet) { described_class.new }
1008
+
1009
+ it 'is a BinData::Int64le' do
1010
+ expect(described_class).to be < BinData::Int64le
1011
+ end
1012
+ it 'is 8-bytes aligned' do
1013
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1014
+ end
1015
+ it 'reads itself' do
1016
+ value = rand(0xFFFFFFFF)
1017
+ new_struct = described_class.new(value)
1018
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1019
+ end
1020
+ end
1021
+
1022
+ describe described_class::PropertyMetaDataExt do
1023
+ subject(:packet) { described_class.new }
1024
+
1025
+ it { is_expected.to respond_to :dw_version }
1026
+ it { is_expected.to respond_to :time_changed }
1027
+ it { is_expected.to respond_to :uuid_dsa_originating }
1028
+ it { is_expected.to respond_to :usn_originating }
1029
+
1030
+ it 'is a Ndr::NdrStruct' do
1031
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1032
+ end
1033
+ it 'is 8-bytes aligned' do
1034
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1035
+ end
1036
+ describe '#dw_version' do
1037
+ it 'is a NdrUint32' do
1038
+ expect(packet.dw_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1039
+ end
1040
+ end
1041
+ describe '#time_changed' do
1042
+ it 'is a Dstime structure' do
1043
+ expect(packet.time_changed).to be_a RubySMB::Dcerpc::Drsr::Dstime
1044
+ end
1045
+ end
1046
+ describe '#uuid_dsa_originating' do
1047
+ it 'is a Uuid structure' do
1048
+ expect(packet.uuid_dsa_originating).to be_a RubySMB::Dcerpc::Uuid
1049
+ end
1050
+ end
1051
+ describe '#usn_originating' do
1052
+ it 'is a Usn structure' do
1053
+ expect(packet.usn_originating).to be_a RubySMB::Dcerpc::Drsr::Usn
1054
+ end
1055
+ end
1056
+ it 'reads itself' do
1057
+ value = {
1058
+ dw_version: rand(0xFFFFFFFF),
1059
+ time_changed: rand(0xFFFFFFFF),
1060
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1061
+ usn_originating: rand(0xFFFFFFFF),
1062
+ }
1063
+ new_struct = described_class.new(value)
1064
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1065
+ end
1066
+ end
1067
+
1068
+ describe described_class::PropertyMetaDataExtVector do
1069
+ subject(:packet) { described_class.new }
1070
+
1071
+ it { is_expected.to respond_to :c_num_props }
1072
+ it { is_expected.to respond_to :rg_meta_data }
1073
+
1074
+ it 'is a Ndr::NdrStruct' do
1075
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1076
+ end
1077
+ it 'is 8-bytes aligned' do
1078
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1079
+ end
1080
+ describe '#c_num_props' do
1081
+ it 'is a NdrUint32' do
1082
+ expect(packet.c_num_props).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1083
+ end
1084
+ it 'defaults to the size of #rg_meta_data' do
1085
+ packet.rg_meta_data = [RubySMB::Dcerpc::Drsr::PropertyMetaDataExt.new] * 4
1086
+ expect(packet.c_num_props).to eq(4)
1087
+ end
1088
+ end
1089
+ describe '#rg_meta_data' do
1090
+ it 'is a NdrConfArray structure' do
1091
+ expect(packet.rg_meta_data).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
1092
+ end
1093
+ it 'has elements of type PropertyMetaDataExt' do
1094
+ expect(packet.rg_meta_data[0]).to be_a RubySMB::Dcerpc::Drsr::PropertyMetaDataExt
1095
+ end
1096
+ end
1097
+ it 'reads itself' do
1098
+ value = {
1099
+ c_num_props: rand(0xFFFFFFFF),
1100
+ rg_meta_data: [{
1101
+ dw_version: rand(0xFFFFFFFF),
1102
+ time_changed: rand(0xFFFFFFFF),
1103
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1104
+ usn_originating: rand(0xFFFFFFFF),
1105
+ }]
1106
+ }
1107
+ new_struct = described_class.new(value)
1108
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1109
+ end
1110
+ end
1111
+
1112
+ describe described_class::PropertyMetaDataExtVectorPtr do
1113
+ subject(:packet) { described_class.new }
1114
+
1115
+ it 'is a PropertyMetaDataExtVector' do
1116
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::PropertyMetaDataExtVector
1117
+ end
1118
+ it 'is a NdrPointer' do
1119
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
1120
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
1121
+ end
1122
+ it 'has a referent which is 8-bytes aligned' do
1123
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(8)
1124
+ end
1125
+ it 'reads itself' do
1126
+ value = {
1127
+ c_num_props: rand(0xFFFFFFFF),
1128
+ rg_meta_data: [{
1129
+ dw_version: rand(0xFFFFFFFF),
1130
+ time_changed: rand(0xFFFFFFFF),
1131
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1132
+ usn_originating: rand(0xFFFFFFFF),
1133
+ }]
1134
+ }
1135
+ new_struct = described_class.new(value)
1136
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1137
+ end
1138
+ end
1139
+
1140
+ describe described_class::ReplentinflistPtr do
1141
+ subject(:packet) { described_class.new }
1142
+
1143
+ it { is_expected.to respond_to :p_next_ent_inf }
1144
+ it { is_expected.to respond_to :entinf }
1145
+ it { is_expected.to respond_to :f_is_nc_prefix }
1146
+ it { is_expected.to respond_to :p_parent_guid }
1147
+ it { is_expected.to respond_to :p_meta_data_ext }
1148
+
1149
+ it 'is a Ndr::NdrStruct' do
1150
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1151
+ end
1152
+ it 'is a NdrPointer' do
1153
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
1154
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
1155
+ end
1156
+ it 'is 4-bytes aligned' do
1157
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
1158
+ end
1159
+ it 'has a referent which is 4-bytes aligned' do
1160
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(4)
1161
+ end
1162
+ describe '#p_next_ent_inf' do
1163
+ it 'is a ReplentinflistPtr structure' do
1164
+ expect(packet.p_next_ent_inf).to be_a RubySMB::Dcerpc::Drsr::ReplentinflistPtr
1165
+ end
1166
+ end
1167
+ describe '#entinf' do
1168
+ it 'is a Entinf structure' do
1169
+ expect(packet.entinf).to be_a RubySMB::Dcerpc::Drsr::Entinf
1170
+ end
1171
+ end
1172
+ describe '#f_is_nc_prefix' do
1173
+ it 'is a Ndr::NdrBoolean structure' do
1174
+ expect(packet.f_is_nc_prefix).to be_a RubySMB::Dcerpc::Ndr::NdrBoolean
1175
+ end
1176
+ end
1177
+ describe '#p_parent_guid' do
1178
+ it 'is a UuidPtr structure' do
1179
+ expect(packet.p_parent_guid).to be_a RubySMB::Dcerpc::Ndr::UuidPtr
1180
+ end
1181
+ end
1182
+ describe '#p_meta_data_ext' do
1183
+ it 'is a PropertyMetaDataExtVector structure' do
1184
+ expect(packet.p_meta_data_ext).to be_a RubySMB::Dcerpc::Drsr::PropertyMetaDataExtVector
1185
+ end
1186
+ end
1187
+ it 'reads itself' do
1188
+ value = {
1189
+ p_next_ent_inf: :null,
1190
+ entinf: {
1191
+ p_name: {
1192
+ struct_len: rand(0xFFFFFFFF),
1193
+ sid_len: rand(0xFFFFFFFF),
1194
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1195
+ sid: 'A' * 28,
1196
+ name_len: 10,
1197
+ string_name: 'Test string'.encode('utf-16le').chars
1198
+ },
1199
+ ul_flags: rand(0xFFFFFFFF),
1200
+ attr_block: {
1201
+ attr_count: rand(0xFFFFFFFF),
1202
+ p_attr: [{
1203
+ attr_typ: rand(0xFFFFFFFF),
1204
+ attr_val: {
1205
+ val_count: rand(0xFFFFFFFF),
1206
+ p_aval: [{val_len: 4, p_val: [rand(0xFF)] * 4}] * 6
1207
+ }
1208
+ }]
1209
+ }
1210
+ },
1211
+ f_is_nc_prefix: true,
1212
+ p_parent_guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1213
+ p_meta_data_ext: {
1214
+ c_num_props: rand(0xFFFFFFFF),
1215
+ rg_meta_data: [{
1216
+ dw_version: rand(0xFFFFFFFF),
1217
+ time_changed: rand(0xFFFFFFFF),
1218
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1219
+ usn_originating: rand(0xFFFFFFFF),
1220
+ }]
1221
+ }
1222
+ }
1223
+ new_struct = described_class.new(value)
1224
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1225
+ end
1226
+ end
1227
+
1228
+ describe described_class::DrsCompressedBlob do
1229
+ subject(:packet) { described_class.new }
1230
+
1231
+ it { is_expected.to respond_to :cb_uncompressed_size }
1232
+ it { is_expected.to respond_to :cb_compressed_size }
1233
+ it { is_expected.to respond_to :pb_compressed_data }
1234
+
1235
+ it 'is a Ndr::NdrStruct' do
1236
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1237
+ end
1238
+ it 'is 4-bytes aligned' do
1239
+ expect(packet.eval_parameter(:byte_align)).to eq(4)
1240
+ end
1241
+ describe '#cb_uncompressed_size' do
1242
+ it 'is a Ndr::NdrUint32 structure' do
1243
+ expect(packet.cb_uncompressed_size).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1244
+ end
1245
+ end
1246
+ describe '#cb_compressed_size' do
1247
+ it 'is a Ndr::NdrUint32 structure' do
1248
+ expect(packet.cb_compressed_size).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1249
+ end
1250
+ end
1251
+ describe '#pb_compressed_data' do
1252
+ it 'is a Ndr::NdrConfArray' do
1253
+ expect(packet.pb_compressed_data).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
1254
+ end
1255
+ it 'has elements of type Ndr::NdrUint8' do
1256
+ expect(packet.pb_compressed_data[0]).to be_a RubySMB::Dcerpc::Ndr::NdrUint8
1257
+ end
1258
+ end
1259
+ it 'reads itself' do
1260
+ value = {
1261
+ cb_uncompressed_size: rand(0xFFFFFFFF),
1262
+ cb_compressed_size: rand(0xFFFFFFFF),
1263
+ pb_compressed_data: [rand(0xFF)] * 4
1264
+ }
1265
+ new_struct = described_class.new(value)
1266
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1267
+ end
1268
+ end
1269
+
1270
+ describe described_class::ValueMetaDataExtV1 do
1271
+ subject(:packet) { described_class.new }
1272
+
1273
+ it { is_expected.to respond_to :time_created }
1274
+ it { is_expected.to respond_to :meta_data }
1275
+
1276
+ it 'is a Ndr::NdrStruct' do
1277
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1278
+ end
1279
+ it 'is 8-bytes aligned' do
1280
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1281
+ end
1282
+ describe '#time_created' do
1283
+ it 'is a Dstime' do
1284
+ expect(packet.time_created).to be_a RubySMB::Dcerpc::Drsr::Dstime
1285
+ end
1286
+ end
1287
+ describe '#meta_data' do
1288
+ it 'is a PropertyMetaDataExt' do
1289
+ expect(packet.meta_data).to be_a RubySMB::Dcerpc::Drsr::PropertyMetaDataExt
1290
+ end
1291
+ end
1292
+ it 'reads itself' do
1293
+ value = {
1294
+ time_created: rand(0xFFFFFFFF),
1295
+ meta_data: {
1296
+ dw_version: rand(0xFFFFFFFF),
1297
+ time_changed: rand(0xFFFFFFFF),
1298
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1299
+ usn_originating: rand(0xFFFFFFFF),
1300
+ }
1301
+ }
1302
+ new_struct = described_class.new(value)
1303
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1304
+ end
1305
+ end
1306
+
1307
+ describe described_class::ReplvalinfV1 do
1308
+ subject(:packet) { described_class.new }
1309
+
1310
+ it { is_expected.to respond_to :p_object }
1311
+ it { is_expected.to respond_to :attr_typ }
1312
+ it { is_expected.to respond_to :aval }
1313
+ it { is_expected.to respond_to :f_is_present }
1314
+ it { is_expected.to respond_to :meta_data }
1315
+
1316
+ it 'is a Ndr::NdrStruct' do
1317
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1318
+ end
1319
+ it 'is 8-bytes aligned' do
1320
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1321
+ end
1322
+ describe '#p_object' do
1323
+ it 'is a DsNamePtr structure' do
1324
+ expect(packet.p_object).to be_a RubySMB::Dcerpc::Drsr::DsNamePtr
1325
+ end
1326
+ end
1327
+ describe '#attr_typ' do
1328
+ it 'is a Attrtyp structure' do
1329
+ expect(packet.attr_typ).to be_a RubySMB::Dcerpc::Drsr::Attrtyp
1330
+ end
1331
+ end
1332
+ describe '#aval' do
1333
+ it 'is a Attrval structure' do
1334
+ expect(packet.aval).to be_a RubySMB::Dcerpc::Drsr::Attrval
1335
+ end
1336
+ end
1337
+ describe '#f_is_present' do
1338
+ it 'is a Ndr::NdrBoolean structure' do
1339
+ expect(packet.f_is_present).to be_a RubySMB::Dcerpc::Ndr::NdrBoolean
1340
+ end
1341
+ end
1342
+ describe '#meta_data' do
1343
+ it 'is a ValueMetaDataExtV1 structure' do
1344
+ expect(packet.meta_data).to be_a RubySMB::Dcerpc::Drsr::ValueMetaDataExtV1
1345
+ end
1346
+ end
1347
+ it 'reads itself' do
1348
+ value = {
1349
+ p_object: {
1350
+ struct_len: rand(0xFFFFFFFF),
1351
+ sid_len: rand(0xFFFFFFFF),
1352
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1353
+ sid: 'A' * 28,
1354
+ name_len: 10,
1355
+ string_name: 'Test string'.encode('utf-16le').chars
1356
+ },
1357
+ attr_typ: rand(0xFFFFFFFF),
1358
+ aval: {
1359
+ val_len: rand(0xFFFFFFFF),
1360
+ p_val: [rand(0xFF)] * 4
1361
+ },
1362
+ f_is_present: true,
1363
+ meta_data: {
1364
+ time_created: rand(0xFFFFFFFF),
1365
+ meta_data: {
1366
+ dw_version: rand(0xFFFFFFFF),
1367
+ time_changed: rand(0xFFFFFFFF),
1368
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1369
+ usn_originating: rand(0xFFFFFFFF),
1370
+ }
1371
+ }
1372
+ }
1373
+ new_struct = described_class.new(value)
1374
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1375
+ end
1376
+ end
1377
+
1378
+ describe described_class::ReplvalinfV1ArrayPtr do
1379
+ subject(:packet) { described_class.new }
1380
+
1381
+ it 'is a Ndr::NdrConfArray' do
1382
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
1383
+ end
1384
+ it 'is a NdrPointer' do
1385
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
1386
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
1387
+ end
1388
+ it 'has elements of type ReplvalinfV1' do
1389
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Drsr::ReplvalinfV1
1390
+ end
1391
+ it 'reads itself' do
1392
+ value = [{
1393
+ p_object: {
1394
+ struct_len: rand(0xFFFFFFFF),
1395
+ sid_len: rand(0xFFFFFFFF),
1396
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1397
+ sid: 'A' * 28,
1398
+ name_len: 10,
1399
+ string_name: 'Test string'.encode('utf-16le').chars
1400
+ },
1401
+ attr_typ: rand(0xFFFFFFFF),
1402
+ aval: {
1403
+ val_len: rand(0xFFFFFFFF),
1404
+ p_val: [rand(0xFF)] * 4
1405
+ },
1406
+ f_is_present: true,
1407
+ meta_data: {
1408
+ time_created: rand(0xFFFFFFFF),
1409
+ meta_data: {
1410
+ dw_version: rand(0xFFFFFFFF),
1411
+ time_changed: rand(0xFFFFFFFF),
1412
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1413
+ usn_originating: rand(0xFFFFFFFF),
1414
+ }
1415
+ }
1416
+ }]
1417
+ new_struct = described_class.new(value)
1418
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1419
+ end
1420
+ end
1421
+
1422
+ describe described_class::DrsCompAlgType do
1423
+ it 'is a Ndr::NdrUint32' do
1424
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrUint32
1425
+ end
1426
+ end
1427
+
1428
+ describe described_class::ValueMetaDataExtV3 do
1429
+ subject(:packet) { described_class.new }
1430
+
1431
+ it { is_expected.to respond_to :time_created }
1432
+ it { is_expected.to respond_to :meta_data }
1433
+ it { is_expected.to respond_to :unused1 }
1434
+ it { is_expected.to respond_to :unused2 }
1435
+ it { is_expected.to respond_to :unused3 }
1436
+ it { is_expected.to respond_to :time_expired }
1437
+
1438
+ it 'is a Ndr::NdrStruct' do
1439
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1440
+ end
1441
+ it 'is 8-bytes aligned' do
1442
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1443
+ end
1444
+ describe '#time_created' do
1445
+ it 'is a Dstime'do
1446
+ expect(packet.time_created).to be_a RubySMB::Dcerpc::Drsr::Dstime
1447
+ end
1448
+ end
1449
+ describe '#meta_data' do
1450
+ it 'is a PropertyMetaDataExt structure' do
1451
+ expect(packet.meta_data).to be_a RubySMB::Dcerpc::Drsr::PropertyMetaDataExt
1452
+ end
1453
+ end
1454
+ describe '#unused1' do
1455
+ it 'is a Ndr::NdrUint32 structure' do
1456
+ expect(packet.unused1).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1457
+ end
1458
+ end
1459
+ describe '#unused2' do
1460
+ it 'is a Ndr::NdrUint32 structure' do
1461
+ expect(packet.unused2).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1462
+ end
1463
+ end
1464
+ describe '#unused3' do
1465
+ it 'is a Ndr::NdrUint32 structure' do
1466
+ expect(packet.unused3).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1467
+ end
1468
+ end
1469
+ describe '#time_expired' do
1470
+ it 'is a Dstime'do
1471
+ expect(packet.time_expired).to be_a RubySMB::Dcerpc::Drsr::Dstime
1472
+ end
1473
+ end
1474
+ it 'reads itself' do
1475
+ value = {
1476
+ time_created: rand(0xFFFFFFFF),
1477
+ meta_data: {
1478
+ dw_version: rand(0xFFFFFFFF),
1479
+ time_changed: rand(0xFFFFFFFF),
1480
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1481
+ usn_originating: rand(0xFFFFFFFF),
1482
+ },
1483
+ unused1: rand(0xFFFFFFFF),
1484
+ unused2: rand(0xFFFFFFFF),
1485
+ unused3: rand(0xFFFFFFFF),
1486
+ time_expired: rand(0xFFFFFFFF)
1487
+ }
1488
+ new_struct = described_class.new(value)
1489
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1490
+ end
1491
+ end
1492
+
1493
+ describe described_class::ReplvalinfV3 do
1494
+ subject(:packet) { described_class.new }
1495
+
1496
+ it { is_expected.to respond_to :p_object }
1497
+ it { is_expected.to respond_to :attr_typ }
1498
+ it { is_expected.to respond_to :aval }
1499
+ it { is_expected.to respond_to :f_is_present }
1500
+ it { is_expected.to respond_to :meta_data }
1501
+
1502
+ it 'is a Ndr::NdrStruct' do
1503
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1504
+ end
1505
+ it 'is 8-bytes aligned' do
1506
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1507
+ end
1508
+ describe '#p_object' do
1509
+ it 'is a DsNamePtr structure' do
1510
+ expect(packet.p_object).to be_a RubySMB::Dcerpc::Drsr::DsNamePtr
1511
+ end
1512
+ end
1513
+ describe '#attr_typ' do
1514
+ it 'is a Attrtyp structure' do
1515
+ expect(packet.attr_typ).to be_a RubySMB::Dcerpc::Drsr::Attrtyp
1516
+ end
1517
+ end
1518
+ describe '#aval' do
1519
+ it 'is a Attrval structure' do
1520
+ expect(packet.aval).to be_a RubySMB::Dcerpc::Drsr::Attrval
1521
+ end
1522
+ end
1523
+ describe '#f_is_present' do
1524
+ it 'is a Ndr::NdrBoolean structure' do
1525
+ expect(packet.f_is_present).to be_a RubySMB::Dcerpc::Ndr::NdrBoolean
1526
+ end
1527
+ end
1528
+ describe '#meta_data' do
1529
+ it 'is a ValueMetaDataExtV3 structure' do
1530
+ expect(packet.meta_data).to be_a RubySMB::Dcerpc::Drsr::ValueMetaDataExtV3
1531
+ end
1532
+ end
1533
+ it 'reads itself' do
1534
+ value = {
1535
+ p_object: {
1536
+ struct_len: rand(0xFFFFFFFF),
1537
+ sid_len: rand(0xFFFFFFFF),
1538
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1539
+ sid: 'A' * 28,
1540
+ name_len: 10,
1541
+ string_name: 'Test string'.encode('utf-16le').chars
1542
+ },
1543
+ attr_typ: rand(0xFFFFFFFF),
1544
+ aval: {
1545
+ val_len: rand(0xFFFFFFFF),
1546
+ p_val: [rand(0xFF)] * 4
1547
+ },
1548
+ f_is_present: true,
1549
+ meta_data: {
1550
+ time_created: rand(0xFFFFFFFF),
1551
+ meta_data: {
1552
+ dw_version: rand(0xFFFFFFFF),
1553
+ time_changed: rand(0xFFFFFFFF),
1554
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1555
+ usn_originating: rand(0xFFFFFFFF),
1556
+ },
1557
+ unused1: rand(0xFFFFFFFF),
1558
+ unused2: rand(0xFFFFFFFF),
1559
+ unused3: rand(0xFFFFFFFF),
1560
+ time_expired: rand(0xFFFFFFFF)
1561
+ }
1562
+ }
1563
+ new_struct = described_class.new(value)
1564
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1565
+ end
1566
+ end
1567
+
1568
+ describe described_class::ReplvalinfV3ArrayPtr do
1569
+ subject(:packet) { described_class.new }
1570
+
1571
+ it 'is a Ndr::NdrConfArray' do
1572
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrConfArray
1573
+ end
1574
+ it 'is a NdrPointer' do
1575
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
1576
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
1577
+ end
1578
+ it 'has elements of type ReplvalinfV3' do
1579
+ expect(packet[0]).to be_a RubySMB::Dcerpc::Drsr::ReplvalinfV3
1580
+ end
1581
+ it 'reads itself' do
1582
+ value = [{
1583
+ p_object: {
1584
+ struct_len: rand(0xFFFFFFFF),
1585
+ sid_len: rand(0xFFFFFFFF),
1586
+ guid: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1587
+ sid: 'A' * 28,
1588
+ name_len: 10,
1589
+ string_name: 'Test string'.encode('utf-16le').chars
1590
+ },
1591
+ attr_typ: rand(0xFFFFFFFF),
1592
+ aval: {
1593
+ val_len: rand(0xFFFFFFFF),
1594
+ p_val: [rand(0xFF)] * 4
1595
+ },
1596
+ f_is_present: true,
1597
+ meta_data: {
1598
+ time_created: rand(0xFFFFFFFF),
1599
+ meta_data: {
1600
+ dw_version: rand(0xFFFFFFFF),
1601
+ time_changed: rand(0xFFFFFFFF),
1602
+ uuid_dsa_originating: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1603
+ usn_originating: rand(0xFFFFFFFF),
1604
+ },
1605
+ unused1: rand(0xFFFFFFFF),
1606
+ unused2: rand(0xFFFFFFFF),
1607
+ unused3: rand(0xFFFFFFFF),
1608
+ time_expired: rand(0xFFFFFFFF)
1609
+ }
1610
+ }]
1611
+ new_struct = described_class.new(value)
1612
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1613
+ end
1614
+ end
1615
+
1616
+ describe described_class::UptodateCursorV2 do
1617
+ subject(:packet) { described_class.new }
1618
+
1619
+ it { is_expected.to respond_to :uuid_dsa }
1620
+ it { is_expected.to respond_to :usn_high_prop_update }
1621
+ it { is_expected.to respond_to :time_last_sync_success }
1622
+
1623
+ it 'is a Ndr::NdrStruct' do
1624
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1625
+ end
1626
+ it 'is 8-bytes aligned' do
1627
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1628
+ end
1629
+ describe '#uuid_dsa' do
1630
+ it 'is a Uuid structure' do
1631
+ expect(packet.uuid_dsa).to be_a RubySMB::Dcerpc::Uuid
1632
+ end
1633
+ end
1634
+ describe '#usn_high_prop_update' do
1635
+ it 'is a Usn structure' do
1636
+ expect(packet.usn_high_prop_update).to be_a RubySMB::Dcerpc::Drsr::Usn
1637
+ end
1638
+ end
1639
+ describe '#time_last_sync_success' do
1640
+ it 'is a Dstime structure' do
1641
+ expect(packet.time_last_sync_success).to be_a RubySMB::Dcerpc::Drsr::Dstime
1642
+ end
1643
+ end
1644
+ it 'reads itself' do
1645
+ value = {
1646
+ uuid_dsa: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1647
+ usn_high_prop_update: rand(0xFFFFFFFF),
1648
+ time_last_sync_success: rand(0xFFFFFFFF)
1649
+ }
1650
+ new_struct = described_class.new(value)
1651
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1652
+ end
1653
+ end
1654
+
1655
+ describe described_class::UptodateVectorV2Ext do
1656
+ subject(:packet) { described_class.new }
1657
+
1658
+ it { is_expected.to respond_to :dw_version }
1659
+ it { is_expected.to respond_to :dw_reserved1 }
1660
+ it { is_expected.to respond_to :c_num_cursors }
1661
+ it { is_expected.to respond_to :dw_reserved2 }
1662
+ it { is_expected.to respond_to :rg_cursors }
1663
+
1664
+ it 'is a Ndr::NdrStruct' do
1665
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
1666
+ end
1667
+ it 'is 8-bytes aligned' do
1668
+ expect(packet.eval_parameter(:byte_align)).to eq(8)
1669
+ end
1670
+ describe '#dw_version' do
1671
+ it 'is a NdrUint32 structure' do
1672
+ expect(packet.dw_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1673
+ end
1674
+ end
1675
+ describe '#dw_reserved1' do
1676
+ it 'is a NdrUint32 structure' do
1677
+ expect(packet.dw_reserved1).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1678
+ end
1679
+ end
1680
+ describe '#c_num_cursors' do
1681
+ it 'is a NdrUint32 structure' do
1682
+ expect(packet.c_num_cursors).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1683
+ end
1684
+ end
1685
+ describe '#dw_reserved2' do
1686
+ it 'is a NdrUint32 structure' do
1687
+ expect(packet.dw_reserved2).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
1688
+ end
1689
+ end
1690
+ describe '#rg_cursors' do
1691
+ it 'is a NdrConfArray structure' do
1692
+ expect(packet.rg_cursors).to be_a RubySMB::Dcerpc::Ndr::NdrConfArray
1693
+ end
1694
+ it 'has elements of type UptodateCursorV2' do
1695
+ expect(packet.rg_cursors[0]).to be_a RubySMB::Dcerpc::Drsr::UptodateCursorV2
1696
+ end
1697
+ end
1698
+ it 'reads itself' do
1699
+ value = {
1700
+ dw_version: rand(0xFFFFFFFF),
1701
+ dw_reserved1: rand(0xFFFFFFFF),
1702
+ c_num_cursors: rand(0xFFFFFFFF),
1703
+ dw_reserved2: rand(0xFFFFFFFF),
1704
+ rg_cursors: [{
1705
+ uuid_dsa: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1706
+ usn_high_prop_update: rand(0xFFFFFFFF),
1707
+ time_last_sync_success: rand(0xFFFFFFFF)
1708
+ }]
1709
+ }
1710
+ new_struct = described_class.new(value)
1711
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1712
+ end
1713
+ end
1714
+
1715
+ describe described_class::UptodateVectorV2ExtPtr do
1716
+ subject(:packet) { described_class.new }
1717
+
1718
+ it 'is a UptodateVectorV2Ext' do
1719
+ expect(described_class).to be < RubySMB::Dcerpc::Drsr::UptodateVectorV2Ext
1720
+ end
1721
+ it 'is a NdrPointer' do
1722
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
1723
+ expect(packet).to be_a(RubySMB::Dcerpc::Ndr::PointerPlugin)
1724
+ end
1725
+ it 'has a referent which is 8-bytes aligned' do
1726
+ expect(packet.eval_parameter(:referent_byte_align)).to eq(8)
1727
+ end
1728
+ it 'reads itself' do
1729
+ value = {
1730
+ dw_version: rand(0xFFFFFFFF),
1731
+ dw_reserved1: rand(0xFFFFFFFF),
1732
+ c_num_cursors: rand(0xFFFFFFFF),
1733
+ dw_reserved2: rand(0xFFFFFFFF),
1734
+ rg_cursors: [{
1735
+ uuid_dsa: 'ee1ecfe6-109d-11ec-82a8-0242ac130003',
1736
+ usn_high_prop_update: rand(0xFFFFFFFF),
1737
+ time_last_sync_success: rand(0xFFFFFFFF)
1738
+ }]
1739
+ }
1740
+ new_struct = described_class.new(value)
1741
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
1742
+ end
1743
+ end
1744
+
1745
+ describe '#drs_bind' do
1746
+ let(:args) { [:drs_bind] }
1747
+ let(:request_struct) { described_class::DrsBindRequest }
1748
+ let(:response_struct) { described_class::DrsBindResponse }
1749
+ let(:values) do
1750
+ {
1751
+ pext_client: {
1752
+ dw_flags: described_class::DRS_EXT_GETCHGREQ_V6 |
1753
+ described_class::DRS_EXT_GETCHGREPLY_V6 |
1754
+ described_class::DRS_EXT_GETCHGREQ_V8 |
1755
+ described_class::DRS_EXT_STRONG_ENCRYPTION,
1756
+ dw_ext_caps: 0xFFFFFFFF
1757
+ }
1758
+ }
1759
+ end
1760
+ let(:request) { request_struct.new(values) }
1761
+ let(:response) { response_struct.new }
1762
+ before :example do
1763
+ allow(drsr).to receive(:dcerpc_request).and_return(response.to_binary_s)
1764
+ allow(response_struct).to receive(:read).and_return(response)
1765
+ end
1766
+
1767
+ it 'sends the correct request packet with authentication parameters' do
1768
+ drsr.send(*args)
1769
+ expect(drsr).to have_received(:dcerpc_request).with(
1770
+ request,
1771
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1772
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1773
+ )
1774
+ end
1775
+ it 'receives the expected response' do
1776
+ drsr.send(*args)
1777
+ expect(response_struct).to have_received(:read).with(response.to_binary_s)
1778
+ end
1779
+ context 'with an invalid response' do
1780
+ it 'raise an InvalidPacket exception' do
1781
+ allow(response_struct).to receive(:read).and_raise(IOError)
1782
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
1783
+ end
1784
+ end
1785
+ context 'when the response status is not STATUS_SUCCESS' do
1786
+ it 'raise an DrsrError exception' do
1787
+ response.error_status = WindowsError::NTStatus::STATUS_ACCESS_DENIED.value
1788
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::DrsrError)
1789
+ end
1790
+ end
1791
+ it 'returns the correct handle' do
1792
+ handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'}
1793
+ response.ph_drs = handle
1794
+ expect(drsr.send(*args)).to eq(handle)
1795
+ end
1796
+ context 'with a different epoch in the response' do
1797
+ before :example do
1798
+ drs_ext = described_class::DrsExtensionsInt.new(dw_repl_epoch: 444)
1799
+ response.ppext_server = drs_ext
1800
+ end
1801
+
1802
+ it 'calls DRSBind again with the correct epoch' do
1803
+
1804
+ drs_ext2 = described_class::DrsExtensionsInt.new(
1805
+ dw_flags: described_class::DRS_EXT_GETCHGREQ_V6 |
1806
+ described_class::DRS_EXT_GETCHGREPLY_V6 |
1807
+ described_class::DRS_EXT_GETCHGREQ_V8 |
1808
+ described_class::DRS_EXT_STRONG_ENCRYPTION,
1809
+ dw_ext_caps: 0xFFFFFFFF,
1810
+ dw_repl_epoch: 444
1811
+ )
1812
+ request2 = request_struct.new(values)
1813
+ request2.pext_client = drs_ext2
1814
+
1815
+ expect(drsr).to receive(:dcerpc_request).with(
1816
+ request,
1817
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1818
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1819
+ ).ordered
1820
+ expect(drsr).to receive(:dcerpc_request).once.with(
1821
+ request2,
1822
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1823
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1824
+ ).ordered
1825
+
1826
+ drsr.send(*args)
1827
+ end
1828
+ it 'returns the correct handle' do
1829
+ handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'}
1830
+ second = false
1831
+ allow(described_class::DrsBindResponse).to receive(:read) do
1832
+ response.ph_drs = handle if second
1833
+ second = true
1834
+ response
1835
+ end
1836
+ expect(drsr.send(*args)).to eq(handle)
1837
+ end
1838
+ end
1839
+ end
1840
+
1841
+ describe '#drs_unbind' do
1842
+ let(:ph_drs) { handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'} }
1843
+ let(:args) { [:drs_unbind, ph_drs] }
1844
+ let(:request_struct) { described_class::DrsUnbindRequest }
1845
+ let(:response_struct) { described_class::DrsUnbindResponse }
1846
+ let(:values) { { ph_drs: ph_drs } }
1847
+ let(:request) { request_struct.new(values) }
1848
+ let(:response) { response_struct.new }
1849
+ before :example do
1850
+ allow(drsr).to receive(:dcerpc_request).and_return(response.to_binary_s)
1851
+ allow(response_struct).to receive(:read).and_return(response)
1852
+ end
1853
+
1854
+ it 'sends the correct request packet with authentication parameters' do
1855
+ drsr.send(*args)
1856
+ expect(drsr).to have_received(:dcerpc_request).with(
1857
+ request,
1858
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1859
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1860
+ )
1861
+ end
1862
+ it 'receives the expected response' do
1863
+ drsr.send(*args)
1864
+ expect(response_struct).to have_received(:read).with(response.to_binary_s)
1865
+ end
1866
+ context 'with an invalid response' do
1867
+ it 'raise an InvalidPacket exception' do
1868
+ allow(response_struct).to receive(:read).and_raise(IOError)
1869
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
1870
+ end
1871
+ end
1872
+ context 'when the response status is not STATUS_SUCCESS' do
1873
+ it 'raise an DrsrError exception' do
1874
+ response.error_status = WindowsError::NTStatus::STATUS_ACCESS_DENIED.value
1875
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::DrsrError)
1876
+ end
1877
+ end
1878
+ end
1879
+
1880
+ describe '#drs_domain_controller_info' do
1881
+ let(:h_drs) { handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'} }
1882
+ let(:domain) { 'rubysmb.local' }
1883
+ let(:args) { [:drs_domain_controller_info, h_drs, domain] }
1884
+ let(:request_struct) { described_class::DrsDomainControllerInfoRequest }
1885
+ let(:response_struct) { described_class::DrsDomainControllerInfoResponse }
1886
+ let(:values) do
1887
+ {
1888
+ h_drs: h_drs,
1889
+ pmsg_in: {
1890
+ switch_type: 1,
1891
+ msg_dcinfo: {
1892
+ domain: domain,
1893
+ info_level: 2
1894
+ }
1895
+ }
1896
+ }
1897
+ end
1898
+ let(:request) { request_struct.new(values) }
1899
+ let(:response) { response_struct.new(pmsg_out: {switch_type: 2}) }
1900
+ before :example do
1901
+ allow(drsr).to receive(:dcerpc_request).and_return(response.to_binary_s)
1902
+ allow(response_struct).to receive(:read).and_return(response)
1903
+ end
1904
+
1905
+ it 'sends the correct request packet with authentication parameters' do
1906
+ drsr.send(*args)
1907
+ expect(drsr).to have_received(:dcerpc_request).with(
1908
+ request,
1909
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1910
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1911
+ )
1912
+ end
1913
+ it 'receives the expected response' do
1914
+ drsr.send(*args)
1915
+ expect(response_struct).to have_received(:read).with(response.to_binary_s)
1916
+ end
1917
+ context 'with an invalid response' do
1918
+ it 'raise an InvalidPacket exception' do
1919
+ allow(response_struct).to receive(:read).and_raise(IOError)
1920
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
1921
+ end
1922
+ end
1923
+ context 'when the response status is not STATUS_SUCCESS' do
1924
+ it 'raise an DrsrError exception' do
1925
+ response.error_status = WindowsError::NTStatus::STATUS_ACCESS_DENIED.value
1926
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::DrsrError)
1927
+ end
1928
+ end
1929
+ it 'returns the correct array of domain controller infos' do
1930
+ info_array = [
1931
+ described_class::DsDomainControllerInfo2w.new(computer_object_name: random_str),
1932
+ described_class::DsDomainControllerInfo2w.new(computer_object_name: random_str),
1933
+ described_class::DsDomainControllerInfo2w.new(computer_object_name: random_str)
1934
+ ]
1935
+ response.pmsg_out.msg_dcinfo.r_items = info_array
1936
+ expect(drsr.send(*args)).to be_a ::Array
1937
+ expect(drsr.send(*args)).to eq(info_array)
1938
+ end
1939
+ end
1940
+
1941
+ describe '#drs_crack_names' do
1942
+ let(:h_drs) { handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'} }
1943
+ let(:domain) { 'rubysmb.local' }
1944
+ let(:args) { [ :drs_crack_names, h_drs ] }
1945
+ let(:request_struct) { described_class::DrsCrackNamesRequest }
1946
+ let(:response_struct) { described_class::DrsCrackNamesResponse }
1947
+ let(:flags) { 0 }
1948
+ let(:format_offered) { described_class::DS_SID_OR_SID_HISTORY_NAME }
1949
+ let(:format_desired) { described_class::DS_UNIQUE_ID_NAME }
1950
+ let(:rp_names) { [] }
1951
+ let(:values) do
1952
+ {
1953
+ h_drs: h_drs,
1954
+ pmsg_in: {
1955
+ switch_type: 1,
1956
+ msg_crack: {
1957
+ dw_flags: flags,
1958
+ format_offered: format_offered,
1959
+ format_desired: format_desired,
1960
+ rp_names: rp_names
1961
+ }
1962
+ }
1963
+ }
1964
+ end
1965
+ let(:request) { request_struct.new(values) }
1966
+ let(:response) { response_struct.new(pmsg_out: {switch_type: 1}) }
1967
+ before :example do
1968
+ allow(drsr).to receive(:dcerpc_request).and_return(response.to_binary_s)
1969
+ allow(response_struct).to receive(:read).and_return(response)
1970
+ end
1971
+
1972
+ it 'sends the correct request packet with authentication parameters' do
1973
+ drsr.send(*args)
1974
+ expect(drsr).to have_received(:dcerpc_request).with(
1975
+ request,
1976
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1977
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1978
+ )
1979
+ end
1980
+ context 'when passing specific values as arguments' do
1981
+ let(:flags) { rand(0xFF) }
1982
+ let(:format_offered) { described_class::DS_USER_PRINCIPAL_NAME }
1983
+ let(:format_desired) { described_class::DS_USER_PRINCIPAL_NAME }
1984
+ let(:rp_names) { ['Test1', 'Test2'] }
1985
+ it 'sends the correct request packet with authentication parameters' do
1986
+ kwargs = {flags: flags, format_offered: format_offered, format_desired: format_desired, rp_names: rp_names}
1987
+ drsr.send(*args, **kwargs)
1988
+ expect(drsr).to have_received(:dcerpc_request).with(
1989
+ request,
1990
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
1991
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
1992
+ )
1993
+ end
1994
+ end
1995
+ it 'receives the expected response' do
1996
+ drsr.send(*args)
1997
+ expect(response_struct).to have_received(:read).with(response.to_binary_s)
1998
+ end
1999
+ context 'with an invalid response' do
2000
+ it 'raise an InvalidPacket exception' do
2001
+ allow(response_struct).to receive(:read).and_raise(IOError)
2002
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
2003
+ end
2004
+ end
2005
+ context 'when the response status is not STATUS_SUCCESS' do
2006
+ it 'raise an DrsrError exception' do
2007
+ response.error_status = WindowsError::NTStatus::STATUS_ACCESS_DENIED.value
2008
+ expect { drsr.send(*args) }.to raise_error(RubySMB::Dcerpc::Error::DrsrError)
2009
+ end
2010
+ end
2011
+ it 'returns the correct array of translated names' do
2012
+ name_array = [
2013
+ described_class::DsNameResultItemw.new(p_domain: random_str),
2014
+ described_class::DsNameResultItemw.new(p_domain: random_str),
2015
+ described_class::DsNameResultItemw.new(p_domain: random_str)
2016
+ ]
2017
+ response.pmsg_out.msg_crack.p_result.r_items = name_array
2018
+ expect(drsr.send(*args)).to be_a ::Array
2019
+ expect(drsr.send(*args)).to eq(name_array)
2020
+ end
2021
+ end
2022
+
2023
+ describe described_class::EncryptedPayload do
2024
+ subject(:packet) { described_class.new }
2025
+
2026
+ it 'is a BinData::Record' do
2027
+ expect(described_class).to be < BinData::Record
2028
+ end
2029
+ it 'is little endian' do
2030
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
2031
+ end
2032
+
2033
+ it { is_expected.to respond_to :salt }
2034
+ it { is_expected.to respond_to :check_sum }
2035
+ it { is_expected.to respond_to :encrypted_data }
2036
+
2037
+ describe '#salt' do
2038
+ it 'is a Uint8Array structure' do
2039
+ expect(packet.salt).to be_a BinData::Uint8Array
2040
+ end
2041
+ end
2042
+ describe '#check_sum' do
2043
+ it 'is a BinData::Uint32le structure' do
2044
+ expect(packet.check_sum).to be_a BinData::Uint32le
2045
+ end
2046
+ end
2047
+ describe '#encrypted_data' do
2048
+ it 'is a Uint8Array structure' do
2049
+ expect(packet.encrypted_data).to be_a BinData::Uint8Array
2050
+ end
2051
+ end
2052
+ it 'reads itself' do
2053
+ value = {
2054
+ salt: [rand(0xFF)] * 16,
2055
+ check_sum: rand(0xFF),
2056
+ encrypted_data: [rand(0xFF)] * rand(40)
2057
+ }
2058
+ new_struct = described_class.new(value)
2059
+ expect(packet.read(new_struct.to_binary_s)).to eq(value)
2060
+ end
2061
+ end
2062
+
2063
+ describe '#decrypt_attribute_value' do
2064
+ it 'correctly decrypts the attribute value' do
2065
+ drsr.instance_variable_set(:@session_key, 'fd96e4fee462a67f8db319d72fcf818b'.unhexlify)
2066
+ attribute = '2302d5755f87896fab6e1dcd63e3b1e7ed4d8e8ebfb29e2bc36580c98d919356d340d442'.unhexlify
2067
+ decrypted = '7997edef91334c0182ee1cb5a9757769'.unhexlify
2068
+ expect(drsr.decrypt_attribute_value(attribute)).to eq(decrypted)
2069
+ end
2070
+ context 'when the session key is empty' do
2071
+ it 'raise an EncryptionError' do
2072
+ expect { drsr.decrypt_attribute_value('AAA') }.to raise_error(RubySMB::Error::EncryptionError)
2073
+ end
2074
+ end
2075
+ end
2076
+
2077
+ describe '#transform_key' do
2078
+ it 'correctly transforms the key' do
2079
+ input_key = '51040000510400'.unhexlify
2080
+ transformed = '5082000004881000'.unhexlify
2081
+ expect(drsr.transform_key(input_key)).to eq(transformed)
2082
+ end
2083
+ end
2084
+
2085
+ describe '#derive_key' do
2086
+ it 'correctly derives an unsigned integer into two keys' do
2087
+ base_key = 1105
2088
+ derived = ['5082000004881000'.unhexlify, '0028408000024408'.unhexlify]
2089
+ expect(drsr.derive_key(base_key)).to eq(derived)
2090
+ end
2091
+ end
2092
+
2093
+ describe '#remove_des_layer' do
2094
+ it 'correctly decrypts the hash' do
2095
+ crypted_hash = '7997edef91334c0182ee1cb5a9757769'.unhexlify
2096
+ rid = 1105
2097
+ decrypted = '32ed87bdb5fdc5e9cba88547376818d4'.unhexlify
2098
+ expect(drsr.remove_des_layer(crypted_hash, rid)).to eq(decrypted)
2099
+ end
2100
+ end
2101
+
2102
+ describe '#drs_get_nc_changes' do
2103
+ let(:h_drs) { handle = {context_handle_attributes: rand(0xFF), context_handle_uuid: '57800405-0301-3330-5566-040023007000'} }
2104
+ let(:nc_guid) { 'ee1ecfe6-109d-11ec-82a8-0242ac130003' }
2105
+ let(:dsa_object_guid) { '8609c6ea-8268-4c4f-a08a-001bca9bd1d7' }
2106
+ let(:args) { [ :drs_get_nc_changes, h_drs ] }
2107
+ let(:kwargs) { { nc_guid: nc_guid, dsa_object_guid: dsa_object_guid } }
2108
+ let(:request_struct) { described_class::DrsGetNcChangesRequest }
2109
+ let(:response_struct) { described_class::DrsGetNcChangesResponse }
2110
+ let(:values) do
2111
+ {
2112
+ h_drs: h_drs,
2113
+ dw_in_version: 8,
2114
+ pmsg_in: {
2115
+ msg_getchg: {
2116
+ uuid_dsa_obj_dest: dsa_object_guid,
2117
+ uuid_invoc_id_src: dsa_object_guid,
2118
+ p_nc: {
2119
+ guid: nc_guid,
2120
+ string_name: ["\0"]
2121
+ },
2122
+ ul_flags: described_class::DRS_INIT_SYNC | described_class::DRS_WRIT_REP,
2123
+ c_max_objects: 1,
2124
+ ul_extended_op: described_class::EXOP_REPL_OBJ
2125
+ }
2126
+ }
2127
+ }
2128
+ end
2129
+ let(:request) { request_struct.new(values) }
2130
+ let(:response) { response_struct.new(pmsg_out: {switch_type: 6}) }
2131
+ before :example do
2132
+ described_class::ATTRTYP_TO_ATTID.values.each do |oid|
2133
+ request.pmsg_in.msg_getchg.add_attrtyp_from_oid(oid)
2134
+ end
2135
+ allow(drsr).to receive(:dcerpc_request).and_return(response.to_binary_s)
2136
+ allow(response_struct).to receive(:read).and_return(response)
2137
+ end
2138
+
2139
+ it 'sends the correct request packet with authentication parameters' do
2140
+ drsr.send(*args, **kwargs)
2141
+ expect(drsr).to have_received(:dcerpc_request).with(
2142
+ request,
2143
+ auth_level: RubySMB::Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
2144
+ auth_type: RubySMB::Dcerpc::RPC_C_AUTHN_WINNT
2145
+ )
2146
+ end
2147
+ it 'receives the expected response' do
2148
+ drsr.send(*args, **kwargs)
2149
+ expect(response_struct).to have_received(:read).with(response.to_binary_s)
2150
+ end
2151
+ context 'with an invalid response' do
2152
+ it 'raise an InvalidPacket exception' do
2153
+ allow(response_struct).to receive(:read).and_raise(IOError)
2154
+ expect { drsr.send(*args, **kwargs) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
2155
+ end
2156
+ end
2157
+ context 'when the response status is not STATUS_SUCCESS' do
2158
+ it 'raise an DrsrError exception' do
2159
+ response.error_status = WindowsError::NTStatus::STATUS_ACCESS_DENIED.value
2160
+ expect { drsr.send(*args, **kwargs) }.to raise_error(RubySMB::Dcerpc::Error::DrsrError)
2161
+ end
2162
+ end
2163
+ it 'returns the correct DrsGetNcChanges response' do
2164
+ expect(drsr.send(*args, **kwargs)).to eq(response)
2165
+ end
2166
+ end
2167
+
2168
+ end
2169
+