ruby_smb 2.0.10 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +5 -16
  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/smb2/negotiate_context.rb +18 -2
  128. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  129. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  130. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  131. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  132. data/lib/ruby_smb/smb2/pipe.rb +4 -0
  133. data/lib/ruby_smb/smb2.rb +3 -1
  134. data/lib/ruby_smb/version.rb +1 -1
  135. data/lib/ruby_smb.rb +2 -1
  136. data/spec/lib/ruby_smb/client_spec.rb +8 -11
  137. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  138. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  139. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  140. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  141. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3792 -1373
  142. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +4 -4
  143. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +4 -4
  144. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +2 -2
  146. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  147. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  148. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  149. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  150. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  151. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +29 -28
  152. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  153. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  154. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  155. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  156. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  157. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  158. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  159. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  160. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  161. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  162. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  163. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  164. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  165. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  166. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  167. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  168. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  169. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  170. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +56 -79
  171. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +4 -4
  172. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +19 -29
  176. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +2 -2
  177. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +9 -15
  178. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +2 -2
  179. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +2 -2
  180. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +22 -22
  181. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +2 -2
  182. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +18 -14
  183. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +5 -4
  184. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +2 -2
  185. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +1 -5
  186. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  187. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  188. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +4 -41
  189. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +4 -4
  190. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -52
  191. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  192. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  193. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  194. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  195. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  196. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -25
  197. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  198. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  199. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  200. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +10 -22
  201. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  202. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +0 -12
  203. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +2 -2
  204. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +18 -47
  205. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  206. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  207. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  208. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  209. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  210. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  211. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  212. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  213. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  214. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  215. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +18 -37
  216. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  217. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +18 -16
  218. data/spec/support/bin_helper.rb +9 -0
  219. data.tar.gz.sig +0 -0
  220. metadata +119 -6
  221. metadata.gz.sig +0 -0
  222. data/lib/ruby_smb/client/signing.rb +0 -64
  223. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -38
  224. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -135
@@ -11,26 +11,16 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  logonsrv_handle :primary_name
14
- string :pad1, length: -> { pad_length(self.primary_name) }
15
- ndr_string :account_name
14
+ ndr_conf_var_wide_stringz :account_name
16
15
  netlogon_secure_channel_type :secure_channel_type
17
- string :pad2, length: -> { pad_length(self.secure_channel_type) }
18
- ndr_string :computer_name
16
+ ndr_conf_var_wide_stringz :computer_name
19
17
  netlogon_credential :client_credential
20
- string :pad3, length: -> { pad_length(self.client_credential) }
21
- uint32 :flags
18
+ ndr_uint32 :flags
22
19
 
23
20
  def initialize_instance
24
21
  super
25
22
  @opnum = NETR_SERVER_AUTHENTICATE3
26
23
  end
27
-
28
- # Determines the correct length for the padding, so that the next
29
- # field is 4-byte aligned.
30
- def pad_length(prev_element)
31
- offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
32
- (4 - offset) % 4
33
- end
34
24
  end
35
25
  end
36
26
  end
@@ -11,9 +11,9 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  netlogon_credential :server_credential
14
- uint32 :negotiate_flags
15
- uint32 :account_rid
16
- uint32 :error_status
14
+ ndr_uint32 :negotiate_flags
15
+ ndr_uint32 :account_rid
16
+ ndr_uint32 :error_status
17
17
 
18
18
  def initialize_instance
19
19
  super
@@ -11,26 +11,16 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  logonsrv_handle :primary_name
14
- string :pad1, length: -> { pad_length(self.primary_name) }
15
- ndr_string :account_name
14
+ ndr_conf_var_wide_stringz :account_name
16
15
  netlogon_secure_channel_type :secure_channel_type
17
- string :pad2, length: -> { pad_length(self.secure_channel_type) }
18
- ndr_string :computer_name
19
- string :pad3, length: -> { pad_length(self.computer_name) }
16
+ ndr_conf_var_wide_stringz :computer_name
20
17
  netlogon_authenticator :authenticator
21
- ndr_fixed_byte_array :clear_new_password, length: 516 # this is an encrypted NL_TRUST_PASSWORD
18
+ ndr_fixed_byte_array :clear_new_password, initial_length: 516 # this is an encrypted NL_TRUST_PASSWORD
22
19
 
23
20
  def initialize_instance
24
21
  super
25
22
  @opnum = Netlogon::NETR_SERVER_PASSWORD_SET2
26
23
  end
27
-
28
- # Determines the correct length for the padding, so that the next
29
- # field is 4-byte aligned.
30
- def pad_length(prev_element)
31
- offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
32
- (4 - offset) % 4
33
- end
34
24
  end
35
25
  end
36
26
  end
@@ -11,7 +11,7 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  netlogon_authenticator :return_authenticator
14
- uint32 :error_status
14
+ ndr_uint32 :error_status
15
15
 
16
16
  def initialize_instance
17
17
  super
@@ -10,22 +10,14 @@ module RubySMB
10
10
 
11
11
  endian :little
12
12
 
13
- logonsrv_handle :primary_name
14
- string :pad1, length: -> { pad_length(self.primary_name) }
15
- ndr_string :computer_name
16
- netlogon_credential :client_challenge
13
+ logonsrv_handle :primary_name
14
+ ndr_conf_var_wide_stringz :computer_name
15
+ netlogon_credential :client_challenge
17
16
 
18
17
  def initialize_instance
19
18
  super
20
19
  @opnum = NETR_SERVER_REQ_CHALLENGE
21
20
  end
22
-
23
- # Determines the correct length for the padding, so that the next
24
- # field is 4-byte aligned.
25
- def pad_length(prev_element)
26
- offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
27
- (4 - offset) % 4
28
- end
29
21
  end
30
22
  end
31
23
  end
@@ -11,7 +11,7 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  netlogon_credential :server_challenge
14
- uint32 :error_status
14
+ ndr_uint32 :error_status
15
15
 
16
16
  def initialize_instance
17
17
  super
@@ -13,19 +13,20 @@ module RubySMB
13
13
  NETR_SERVER_PASSWORD_SET2 = 30
14
14
 
15
15
  # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3b224201-b531-43e2-8c79-b61f6dea8640
16
- class LogonsrvHandle < Ndr::NdrLpStr; end
16
+ class LogonsrvHandle < Ndr::NdrWideStringzPtr; end
17
17
 
18
18
  # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/d55e2632-7163-4f6c-b662-4b870e8cc1cd
19
19
  class NetlogonCredential < Ndr::NdrFixedByteArray
20
- default_parameters length: 8
20
+ default_parameters initial_length: 8
21
21
  end
22
22
 
23
23
  # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/76c93227-942a-4687-ab9d-9d972ffabdab
24
- class NetlogonAuthenticator < BinData::Record
24
+ class NetlogonAuthenticator < Ndr::NdrStruct
25
+ default_parameter byte_align: 4
25
26
  endian :little
26
27
 
27
28
  netlogon_credential :credential
28
- uint32 :timestamp
29
+ ndr_uint32 :timestamp
29
30
  end
30
31
 
31
32
  # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/4d1235e3-2c96-4e9f-a147-3cb338a0d09f
@@ -1,11 +1,12 @@
1
1
  module RubySMB
2
2
  module Dcerpc
3
- class PSyntaxIdT < BinData::Record
3
+ class PSyntaxIdT < Ndr::NdrStruct
4
+ default_parameter byte_align: 4
4
5
  endian :little
5
6
 
6
7
  uuid :if_uuid, initial_value: -> { uuid }
7
- uint16 :if_ver_major, initial_value: -> { ver_major }
8
- uint16 :if_ver_minor, initial_value: -> { ver_minor }
8
+ ndr_uint16 :if_ver_major, initial_value: -> { ver_major }
9
+ ndr_uint16 :if_ver_minor, initial_value: -> { ver_minor }
9
10
  end
10
11
  end
11
12
  end
@@ -10,14 +10,14 @@ module RubySMB
10
10
  uint8 :ptype, label: 'PDU type'
11
11
 
12
12
  struct :pfc_flags do
13
- bit1 :object_uuid, label: 'Object UUID'
14
- bit1 :maybe, label: 'Maybe call semantics'
13
+ bit1 :object_uuid, label: 'Object UUID'
14
+ bit1 :maybe, label: 'Maybe call semantics'
15
15
  bit1 :did_not_execute, label: 'Did not execute'
16
- bit1 :conc_mpx, label: 'Concurrent multiplexing'
17
- bit1 :reserved_1, label: 'Reserved'
18
- bit1 :pending_cancel, label: 'Pending cancel'
19
- bit1 :last_frag, label: 'Last fragment', initial_value: 1
20
- bit1 :first_frag, label: 'First fragment', initial_value: 1
16
+ bit1 :conc_mpx, label: 'Concurrent multiplexing'
17
+ bit1 :reserved_1, label: 'Reserved'
18
+ bit1 :support_header_sign, label: 'Support Header Signing'
19
+ bit1 :last_frag, label: 'Last fragment', initial_value: 1
20
+ bit1 :first_frag, label: 'First fragment', initial_value: 1
21
21
  end
22
22
 
23
23
  uint32 :packed_drep, label: 'NDR data representation format label', initial_value: 0x10
@@ -17,6 +17,7 @@ module RubySMB
17
17
  BIND_NAK = 13
18
18
  ALTER_CONTEXT = 14
19
19
  ALTER_CONTEXT_RESP = 15
20
+ RPC_AUTH3 = 16
20
21
  SHUTDOWN = 17
21
22
  CO_CANCEL = 18
22
23
  ORPHANED = 19
@@ -3,66 +3,113 @@ module RubySMB
3
3
  # The Request PDU as defined in
4
4
  # [The request PDU](http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06_04_09)
5
5
  class Request < BinData::Record
6
+ PTYPE = PTypes::REQUEST
7
+
6
8
  endian :little
7
9
 
8
- pdu_header :pdu_header, label: 'PDU header'
10
+ # PDU Header
11
+ pdu_header :pdu_header, label: 'PDU header common fields'
9
12
  uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.num_bytes }
10
13
  uint16 :p_cont_id, label: 'Presentation context identification'
11
14
  uint16 :opnum, label: 'Operation Number'
12
15
  uuid :object, label: 'Object UID', onlyif: -> { pdu_header.pfc_flags.object_uuid == 1 }
13
16
 
17
+ # PDU Body
14
18
  choice :stub, label: 'Stub', selection: -> { @obj.parent.get_parameter(:endpoint) || '' } do
19
+ string 'Encrypted'
15
20
  choice 'Winreg', selection: -> { opnum } do
16
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCR, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCR
17
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCU, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCU
18
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKLM, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKLM
19
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPD, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPD
20
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKU, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKU
21
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCC, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCC
22
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPT, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPT
23
- open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPN, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPN
24
- close_key_request RubySMB::Dcerpc::Winreg::REG_CLOSE_KEY
25
- enum_key_request RubySMB::Dcerpc::Winreg::REG_ENUM_KEY
26
- enum_value_request RubySMB::Dcerpc::Winreg::REG_ENUM_VALUE
27
- open_key_request RubySMB::Dcerpc::Winreg::REG_OPEN_KEY
28
- query_info_key_request RubySMB::Dcerpc::Winreg::REG_QUERY_INFO_KEY
29
- query_value_request RubySMB::Dcerpc::Winreg::REG_QUERY_VALUE
30
- create_key_request RubySMB::Dcerpc::Winreg::REG_CREATE_KEY
31
- save_key_request RubySMB::Dcerpc::Winreg::REG_SAVE_KEY
21
+ open_root_key_request Winreg::OPEN_HKCR, opnum: Winreg::OPEN_HKCR
22
+ open_root_key_request Winreg::OPEN_HKCU, opnum: Winreg::OPEN_HKCU
23
+ open_root_key_request Winreg::OPEN_HKLM, opnum: Winreg::OPEN_HKLM
24
+ open_root_key_request Winreg::OPEN_HKPD, opnum: Winreg::OPEN_HKPD
25
+ open_root_key_request Winreg::OPEN_HKU, opnum: Winreg::OPEN_HKU
26
+ open_root_key_request Winreg::OPEN_HKCC, opnum: Winreg::OPEN_HKCC
27
+ open_root_key_request Winreg::OPEN_HKPT, opnum: Winreg::OPEN_HKPT
28
+ open_root_key_request Winreg::OPEN_HKPN, opnum: Winreg::OPEN_HKPN
29
+ close_key_request Winreg::REG_CLOSE_KEY
30
+ enum_key_request Winreg::REG_ENUM_KEY
31
+ enum_value_request Winreg::REG_ENUM_VALUE
32
+ open_key_request Winreg::REG_OPEN_KEY
33
+ query_info_key_request Winreg::REG_QUERY_INFO_KEY
34
+ query_value_request Winreg::REG_QUERY_VALUE
35
+ create_key_request Winreg::REG_CREATE_KEY
36
+ save_key_request Winreg::REG_SAVE_KEY
32
37
  string :default
33
38
  end
34
39
  choice 'Netlogon', selection: -> { opnum } do
35
- netr_server_authenticate3_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_AUTHENTICATE3
36
- netr_server_password_set2_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_PASSWORD_SET2
37
- netr_server_req_challenge_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_REQ_CHALLENGE
40
+ netr_server_authenticate3_request Netlogon::NETR_SERVER_AUTHENTICATE3
41
+ netr_server_password_set2_request Netlogon::NETR_SERVER_PASSWORD_SET2
42
+ netr_server_req_challenge_request Netlogon::NETR_SERVER_REQ_CHALLENGE
38
43
  string :default
39
44
  end
40
45
  choice 'Srvsvc', selection: -> { opnum } do
41
- net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
46
+ net_share_enum_all_request Srvsvc::NET_SHARE_ENUM_ALL
42
47
  string :default
43
48
  end
44
49
  choice 'Svcctl', selection: -> { opnum } do
45
- open_sc_manager_w_request RubySMB::Dcerpc::Svcctl::OPEN_SC_MANAGER_W
46
- open_service_w_request RubySMB::Dcerpc::Svcctl::OPEN_SERVICE_W
47
- query_service_status_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS
48
- query_service_config_w_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_CONFIG_W
49
- change_service_config_w_request RubySMB::Dcerpc::Svcctl::CHANGE_SERVICE_CONFIG_W
50
- start_service_w_request RubySMB::Dcerpc::Svcctl::START_SERVICE_W
51
- control_service_request RubySMB::Dcerpc::Svcctl::CONTROL_SERVICE
52
- close_service_handle_request RubySMB::Dcerpc::Svcctl::CLOSE_SERVICE_HANDLE
50
+ open_sc_manager_w_request Svcctl::OPEN_SC_MANAGER_W
51
+ open_service_w_request Svcctl::OPEN_SERVICE_W
52
+ query_service_status_request Svcctl::QUERY_SERVICE_STATUS
53
+ query_service_config_w_request Svcctl::QUERY_SERVICE_CONFIG_W
54
+ change_service_config_w_request Svcctl::CHANGE_SERVICE_CONFIG_W
55
+ start_service_w_request Svcctl::START_SERVICE_W
56
+ control_service_request Svcctl::CONTROL_SERVICE
57
+ close_service_handle_request Svcctl::CLOSE_SERVICE_HANDLE
53
58
  string :default
54
59
  end
60
+ choice 'Samr', selection: -> { opnum } do
61
+ samr_connect_request Samr::SAMR_CONNECT
62
+ samr_lookup_domain_in_sam_server_request Samr::SAMR_LOOKUP_DOMAIN_IN_SAM_SERVER
63
+ samr_open_domain_request Samr::SAMR_OPEN_DOMAIN
64
+ samr_enumerate_users_in_domain_request Samr::SAMR_ENUMERATE_USERS_IN_DOMAIN
65
+ samr_rid_to_sid_request Samr::SAMR_RID_TO_SID
66
+ samr_close_handle_request Samr::SAMR_CLOSE_HANDLE
67
+ samr_get_alias_membership_request Samr::SAMR_GET_ALIAS_MEMBERSHIP
68
+ samr_open_user_request Samr::SAMR_OPEN_USER
69
+ samr_get_groups_for_user_request Samr::SAMR_GET_GROUPS_FOR_USER
70
+ string :default
71
+ end
72
+ choice 'Wkssvc', selection: -> { opnum } do
73
+ netr_wksta_get_info_request Wkssvc::NETR_WKSTA_GET_INFO
74
+ string :default
75
+ end
76
+ choice 'Epm', selection: -> { opnum } do
77
+ epm_ept_map_request RubySMB::Dcerpc::Epm::EPT_MAP
78
+ string :default
79
+ end
80
+ choice 'Drsr', selection: -> { opnum } do
81
+ drs_bind_request Drsr::DRS_BIND
82
+ drs_unbind_request Drsr::DRS_UNBIND
83
+ drs_domain_controller_info_request Drsr::DRS_DOMAIN_CONTROLLER_INFO
84
+ drs_crack_names_request Drsr::DRS_CRACK_NAMES
85
+ drs_get_nc_changes_request Drsr::DRS_GET_NC_CHANGES
86
+ string :default
87
+ end
55
88
  string :default
56
89
  end
90
+ string :auth_pad,
91
+ onlyif: -> { has_auth_verifier? },
92
+ length: -> { (16 - (stub.num_bytes % 16)) % 16 }
57
93
 
58
- string :auth_verifier, label: 'Authentication verifier',
59
- onlyif: -> { pdu_header.auth_length > 0 },
94
+ # Auth Verifier
95
+ sec_trailer :sec_trailer, onlyif: -> { has_auth_verifier? }
96
+ string :auth_value, label: 'Authentication verifier',
97
+ onlyif: -> { has_auth_verifier? },
60
98
  read_length: -> { pdu_header.auth_length }
61
99
 
62
100
  def initialize_instance
63
101
  super
64
- pdu_header.ptype = RubySMB::Dcerpc::PTypes::REQUEST
102
+ pdu_header.ptype = PTYPE
65
103
  end
104
+
105
+ def enable_encrypted_stub
106
+ @params[:endpoint] = 'Encrypted'
107
+ end
108
+
109
+ def has_auth_verifier?
110
+ self.pdu_header.auth_length > 0
111
+ end
112
+
66
113
  end
67
114
  end
68
115
  end
@@ -3,24 +3,59 @@ module RubySMB
3
3
  # The Response PDU as defined in
4
4
  # [The response PDU](http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06_04_10)
5
5
  class Response < BinData::Record
6
- endian :little
6
+ PTYPE = PTypes::RESPONSE
7
7
 
8
- pdu_header :pdu_header, label: 'PDU header'
8
+ endian :little
9
9
 
10
- uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.do_num_bytes }
11
- uint16 :p_cont_id, label: 'Presentation context identification'
12
- uint8 :cancel_count, label: 'Cancel count'
13
- uint8 :reserved
10
+ # PDU Header
11
+ pdu_header :pdu_header, label: 'PDU header common fields'
12
+ uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.do_num_bytes }
13
+ uint16 :p_cont_id, label: 'Presentation context identification'
14
+ uint8 :cancel_count, label: 'Cancel count'
15
+ uint8 :reserved
14
16
 
15
- string :stub, label: 'Stub', read_length: -> { pdu_header.frag_length - stub.abs_offset - pdu_header.auth_length }
17
+ # PDU Body
18
+ string :stub, label: 'Stub', read_length: -> { stub_length }
19
+ string :auth_pad,
20
+ onlyif: -> { has_auth_verifier? },
21
+ length: -> { (16 - (stub.num_bytes % 16)) % 16 }
16
22
 
17
- string :auth_verifier, label: 'Authentication verifier',
18
- onlyif: -> { pdu_header.auth_length > 0 },
23
+ # Auth Verifier
24
+ sec_trailer :sec_trailer, onlyif: -> { has_auth_verifier? }
25
+ string :auth_value, label: 'Authentication verifier',
26
+ onlyif: -> { has_auth_verifier? },
19
27
  read_length: -> { pdu_header.auth_length }
20
28
 
21
29
  def initialize_instance
22
30
  super
23
- pdu_header.ptype = RubySMB::Dcerpc::PTypes::RESPONSE
31
+ pdu_header.ptype = PTYPE
32
+ end
33
+
34
+ def has_auth_verifier?
35
+ self.pdu_header.auth_length > 0
36
+ end
37
+
38
+ def stub_length
39
+ stub_length = pdu_header.frag_length - stub.rel_offset
40
+ if has_auth_verifier?
41
+ # Note that the resulting stub length includes auth_pad. We will be
42
+ # able to separate the auth_pad from the stub once the sec_trailer
43
+ # structure is read.
44
+ stub_length -= (sec_trailer.num_bytes + pdu_header.auth_length)
45
+ end
46
+ stub_length
47
+ end
48
+
49
+ def read(io)
50
+ super
51
+ if has_auth_verifier? && sec_trailer.auth_pad_length > 0
52
+ # At this point, auth_pad is at the end of the stub. We need to move
53
+ # it to the correct field. It is now possible since we know its
54
+ # length from the sec_trailer auth_pad_length field.
55
+ pad = stub[-(sec_trailer.auth_pad_length)..-1]
56
+ stub.assign(stub[0...-(sec_trailer.auth_pad_length)])
57
+ auth_pad.assign(pad)
58
+ end
24
59
  end
25
60
  end
26
61
  end
@@ -0,0 +1,28 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+
4
+ # [2.2.2.10 rpc_auth_3 PDU](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/a6b7b03c-4ac5-4c25-8c52-f2bec872ac97)
5
+ class RpcAuth3 < BinData::Record
6
+ PTYPE = PTypes::RPC_AUTH3
7
+
8
+ endian :little
9
+
10
+ # PDU Header
11
+ pdu_header :pdu_header
12
+ uint32 :pad
13
+
14
+ # Auth Verifier
15
+ sec_trailer :sec_trailer, onlyif: -> { pdu_header.auth_length > 0 }
16
+ string :auth_value,
17
+ onlyif: -> { pdu_header.auth_length > 0 },
18
+ read_length: -> { pdu_header.auth_length }
19
+
20
+ def initialize_instance
21
+ super
22
+ pdu_header.ptype = PTYPE
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+
@@ -3,30 +3,30 @@ module RubySMB
3
3
 
4
4
  # This class represents a RPC_SECURITY_DESCRIPTOR structure as defined in
5
5
  # [2.2.8 RPC_SECURITY_DESCRIPTOR](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/9729e781-8eb9-441b-82ca-e898f98d29c2)
6
- class RpcSecurityDescriptor < BinData::Record
6
+ class RpcSecurityDescriptor < Ndr::NdrStruct
7
+ default_parameters byte_align: 4
7
8
  endian :little
8
9
 
9
- ndr_lp_byte_array :lp_security_descriptor
10
- uint32 :cb_in_security_descriptor
11
- uint32 :cb_out_security_descriptor
10
+ ndr_byte_array_ptr :lp_security_descriptor
11
+ ndr_uint32 :cb_in_security_descriptor
12
+ ndr_uint32 :cb_out_security_descriptor
12
13
  end
13
14
 
14
15
  # This class represents a RPC_SECURITY_ATTRIBUTES structure as defined in
15
16
  # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
16
- class RpcSecurityAttributes < BinData::Record
17
+ class RpcSecurityAttributes < Ndr::NdrStruct
18
+ default_parameters byte_align: 4
17
19
  endian :little
18
20
 
19
- uint32 :n_length
21
+ ndr_uint32 :n_length
20
22
  rpc_security_descriptor :rpc_security_descriptor
21
- uint8 :b_inheritHandle
23
+ ndr_uint8 :b_inheritHandle
22
24
  end
23
25
 
24
26
  # This class represents a pointer to a RPC_SECURITY_ATTRIBUTES structure as defined in
25
27
  # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
26
- class PrpcSecurityAttributes < Ndr::NdrPointer
27
- endian :little
28
-
29
- rpc_security_attributes :referent, onlyif: -> { self.referent_id != 0 }
28
+ class PrpcSecurityAttributes < RpcSecurityAttributes
29
+ extend Ndr::PointerClassPlugin
30
30
  end
31
31
 
32
32
  end
@@ -0,0 +1,118 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+
4
+ # A RRP_UNICODE_STRING structure as defined in
5
+ # [2.2.4 RRP_UNICODE_STRING](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/c0c90f11-a4c4-496a-ac09-8a8a3697ceef)
6
+ class RrpUnicodeString < Ndr::NdrStruct
7
+ default_parameters byte_align: 4
8
+ endian :little
9
+
10
+ ndr_uint16 :buffer_length
11
+ ndr_uint16 :maximum_length
12
+ ndr_wide_stringz_ptr :buffer
13
+
14
+ def assign(val)
15
+ case val
16
+ when :null
17
+ self.buffer = val
18
+ self.buffer_length = 0
19
+ self.maximum_length = 0
20
+ when BinData::Stringz, BinData::String, String
21
+ self.buffer = val.to_s
22
+ val_length = val.strip.length
23
+ val_length += 1 unless val == ''
24
+ self.buffer_length = val_length * 2
25
+ self.maximum_length = val_length * 2
26
+ else
27
+ super
28
+ end
29
+ end
30
+
31
+ # Set `maximum_length` and buffer `max_count` values to `val`. It also
32
+ # takes care of initializing the buffer pointer `ref_id` if the pointer
33
+ # is null.
34
+ #
35
+ # This helper is typically called in requests where a unicode string
36
+ # field needs to contain the maximum length information without any
37
+ # string value. It is usually required by some RPC calls and used by the
38
+ # server to determine the maximum length for the corresponding output
39
+ # field in order to allocate space accordingly.
40
+ def set_max_buffer_size(val)
41
+ self.buffer.instantiate_referent if self.buffer.is_null_ptr?
42
+ self.buffer.max_count = val / 2
43
+ self.maximum_length.assign(val)
44
+ end
45
+
46
+ def to_s
47
+ return ''.encode('utf-16le') if self.buffer.is_null_ptr?
48
+ self.buffer.to_s
49
+ end
50
+ end
51
+
52
+ # A pointer to a RRP_UNICODE_STRING structure
53
+ class PrrpUnicodeString < RrpUnicodeString
54
+ extend Ndr::PointerClassPlugin
55
+ end
56
+
57
+ # A RPC_UNICODE_STRING structure as defined in
58
+ # [2.3.10 RPC_UNICODE_STRING](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/94a16bb6-c610-4cb9-8db6-26f15f560061)
59
+ class RpcUnicodeString < Ndr::NdrStruct
60
+ # Same as RrpUnicodeString, but not necessary null terminated
61
+ #
62
+ # It is the caller responsability to null terminate the string, if it has
63
+ # to. This structure won't do it automatically the way RrpUnicodeString
64
+ # do.
65
+ #
66
+ # It also takes care of detecting the terminating null character and
67
+ # exclude when calculating buffer_length and maximum_length.
68
+ default_parameters byte_align: 4
69
+ endian :little
70
+
71
+ ndr_uint16 :buffer_length
72
+ ndr_uint16 :maximum_length
73
+ ndr_wide_string_ptr :buffer
74
+
75
+ def assign(val)
76
+ case val
77
+ when :null
78
+ self.buffer = val
79
+ self.buffer_length = 0
80
+ self.maximum_length = 0
81
+ when BinData::Stringz, BinData::String, String
82
+ self.buffer = val.to_s
83
+ val_length = val.strip.length
84
+ self.buffer_length = val_length * 2
85
+ self.maximum_length = val_length * 2
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ # Set `maximum_length` and buffer `max_count` values to `val`. It also
92
+ # takes care of initializing the buffer pointer `ref_id` if the pointer
93
+ # is null.
94
+ #
95
+ # This helper is typically called in requests where a unicode string
96
+ # field needs to contain the maximum length information without any
97
+ # string value. It is usually required by some RPC calls and used by the
98
+ # server to determine the maximum length for the corresponding output
99
+ # field in order to allocate space accordingly.
100
+ def set_max_buffer_size(val)
101
+ self.buffer.instantiate_referent if self.buffer.is_null_ptr?
102
+ self.buffer.max_count = val / 2
103
+ self.maximum_length.assign(val)
104
+ end
105
+
106
+ def to_s
107
+ return ''.encode('utf-16le') if self.buffer.is_null_ptr?
108
+ self.buffer.to_s
109
+ end
110
+ end
111
+
112
+ # A pointer to a RPC_UNICODE_STRING structure
113
+ class PrpcUnicodeString < RpcUnicodeString
114
+ extend Ndr::PointerClassPlugin
115
+ end
116
+ end
117
+ end
118
+