ruby_smb 2.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +46 -0
  4. data/README.md +0 -1
  5. data/examples/anonymous_auth.rb +3 -3
  6. data/examples/append_file.rb +10 -8
  7. data/examples/auth_capture.rb +71 -0
  8. data/examples/authenticate.rb +9 -5
  9. data/examples/delete_file.rb +8 -6
  10. data/examples/dump_secrets_from_sid.rb +207 -0
  11. data/examples/enum_domain_users.rb +75 -0
  12. data/examples/enum_registry_key.rb +5 -4
  13. data/examples/enum_registry_values.rb +5 -4
  14. data/examples/get_computer_info.rb +42 -0
  15. data/examples/list_directory.rb +8 -6
  16. data/examples/negotiate_with_netbios_service.rb +9 -5
  17. data/examples/net_share_enum_all.rb +6 -4
  18. data/examples/pipes.rb +11 -12
  19. data/examples/query_service_status.rb +102 -0
  20. data/examples/read_file.rb +8 -6
  21. data/examples/read_registry_key_value.rb +6 -5
  22. data/examples/rename_file.rb +9 -7
  23. data/examples/tree_connect.rb +7 -5
  24. data/examples/write_file.rb +9 -7
  25. data/lib/ruby_smb/client/authentication.rb +5 -10
  26. data/lib/ruby_smb/client/echo.rb +2 -4
  27. data/lib/ruby_smb/client/negotiation.rb +13 -16
  28. data/lib/ruby_smb/client/tree_connect.rb +2 -4
  29. data/lib/ruby_smb/client/utils.rb +16 -10
  30. data/lib/ruby_smb/client/winreg.rb +1 -1
  31. data/lib/ruby_smb/client.rb +102 -75
  32. data/lib/ruby_smb/compression/lznt1.rb +164 -0
  33. data/lib/ruby_smb/compression.rb +7 -0
  34. data/lib/ruby_smb/dcerpc/bind.rb +28 -20
  35. data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
  36. data/lib/ruby_smb/dcerpc/client.rb +542 -0
  37. data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
  38. data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
  39. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
  40. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
  41. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
  42. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
  43. data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
  44. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
  45. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
  46. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
  47. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
  48. data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
  49. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
  50. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
  51. data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
  52. data/lib/ruby_smb/dcerpc/epm.rb +75 -0
  53. data/lib/ruby_smb/dcerpc/error.rb +20 -0
  54. data/lib/ruby_smb/dcerpc/ndr.rb +1204 -80
  55. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +27 -0
  56. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
  57. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +27 -0
  58. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
  59. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +24 -0
  60. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
  61. data/lib/ruby_smb/dcerpc/netlogon.rb +102 -0
  62. data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
  63. data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
  64. data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
  65. data/lib/ruby_smb/dcerpc/request.rb +85 -19
  66. data/lib/ruby_smb/dcerpc/response.rb +45 -10
  67. data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
  68. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
  69. data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
  70. data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
  71. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
  72. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
  73. data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
  74. data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
  75. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
  76. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
  77. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
  78. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
  79. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
  80. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
  81. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
  82. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
  83. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
  84. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
  85. data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
  86. data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
  87. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
  88. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
  89. data/lib/ruby_smb/dcerpc/samr.rb +613 -0
  90. data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
  91. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
  92. data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
  93. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +36 -0
  94. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
  95. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
  96. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
  97. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
  98. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
  99. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +25 -0
  100. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
  101. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +23 -0
  102. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
  103. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
  104. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +45 -0
  105. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
  106. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
  107. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +26 -0
  108. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
  109. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
  110. data/lib/ruby_smb/dcerpc/svcctl.rb +477 -0
  111. data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
  112. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
  113. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +62 -0
  114. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
  115. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +2 -19
  116. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
  117. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
  118. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
  119. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
  120. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
  121. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +6 -7
  122. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
  123. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
  124. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
  125. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -13
  126. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
  127. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
  128. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +28 -0
  129. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
  130. data/lib/ruby_smb/dcerpc/winreg.rb +99 -22
  131. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
  132. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
  133. data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
  134. data/lib/ruby_smb/dcerpc.rb +45 -11
  135. data/lib/ruby_smb/dialect.rb +45 -0
  136. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  137. data/lib/ruby_smb/dispatcher/socket.rb +2 -2
  138. data/lib/ruby_smb/error.rb +21 -5
  139. data/lib/ruby_smb/field/file_time.rb +1 -1
  140. data/lib/ruby_smb/field/string16.rb +5 -1
  141. data/lib/ruby_smb/field/stringz16.rb +17 -1
  142. data/lib/ruby_smb/generic_packet.rb +11 -1
  143. data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
  144. data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
  145. data/lib/ruby_smb/gss/provider.rb +35 -0
  146. data/lib/ruby_smb/gss.rb +56 -63
  147. data/lib/ruby_smb/nbss/session_header.rb +4 -4
  148. data/lib/ruby_smb/ntlm.rb +61 -0
  149. data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
  150. data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
  151. data/lib/ruby_smb/server/server_client.rb +162 -0
  152. data/lib/ruby_smb/server.rb +54 -0
  153. data/lib/ruby_smb/signing.rb +59 -0
  154. data/lib/ruby_smb/smb1/file.rb +10 -25
  155. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
  156. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
  157. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  158. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
  159. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
  160. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
  161. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
  162. data/lib/ruby_smb/smb1/pipe.rb +12 -6
  163. data/lib/ruby_smb/smb1/tree.rb +13 -9
  164. data/lib/ruby_smb/smb2/file.rb +33 -33
  165. data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
  166. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
  167. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  168. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  169. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  170. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  171. data/lib/ruby_smb/smb2/pipe.rb +13 -6
  172. data/lib/ruby_smb/smb2/tree.rb +21 -11
  173. data/lib/ruby_smb/smb2.rb +3 -1
  174. data/lib/ruby_smb/version.rb +1 -1
  175. data/lib/ruby_smb.rb +5 -3
  176. data/spec/lib/ruby_smb/client_spec.rb +199 -86
  177. data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
  178. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  179. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  180. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  181. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  182. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3977 -239
  183. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
  184. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
  185. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
  186. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
  187. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
  188. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
  189. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  190. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  191. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  192. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  193. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  194. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +162 -0
  195. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  196. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  197. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  198. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  199. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  200. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  201. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  202. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  203. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  204. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  205. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  206. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  207. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  208. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  209. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  210. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  211. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  212. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  213. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +168 -0
  214. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
  215. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
  216. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
  217. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
  218. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
  219. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +68 -0
  220. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
  221. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +53 -0
  222. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
  223. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
  224. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
  225. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
  226. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
  227. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +76 -0
  228. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +47 -0
  229. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
  230. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +508 -0
  231. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  232. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  233. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +73 -0
  234. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
  235. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -56
  236. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  237. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  238. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  239. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  240. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  241. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -20
  242. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  243. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
  244. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  245. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  246. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +18 -42
  247. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  248. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +45 -0
  249. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
  250. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +219 -62
  251. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  252. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  253. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  254. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
  255. data/spec/lib/ruby_smb/error_spec.rb +34 -5
  256. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  257. data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
  258. data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
  259. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  260. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  261. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  262. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  263. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
  264. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  265. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  266. data/spec/lib/ruby_smb/smb1/file_spec.rb +2 -4
  267. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
  268. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
  269. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
  270. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
  271. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +20 -14
  272. data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
  273. data/spec/lib/ruby_smb/smb2/file_spec.rb +61 -9
  274. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  275. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +20 -14
  276. data/spec/lib/ruby_smb/smb2/tree_spec.rb +58 -1
  277. data/spec/spec_helper.rb +1 -1
  278. data/spec/support/bin_helper.rb +9 -0
  279. data.tar.gz.sig +0 -0
  280. metadata +229 -23
  281. metadata.gz.sig +0 -0
  282. data/.travis.yml +0 -6
  283. data/lib/ruby_smb/client/signing.rb +0 -64
  284. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -35
  285. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -98
@@ -39,7 +39,6 @@ module RubySMB
39
39
 
40
40
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
41
41
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
42
- uint8 :name, label: 'Name', initial_value: 0x00
43
42
  string :pad1, length: -> { pad1_length }
44
43
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
45
44
  string :pad2, length: -> { pad2_length }
@@ -44,8 +44,7 @@ module RubySMB
44
44
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
45
45
  string :pad1, length: -> { pad1_length }
46
46
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
47
- string :pad2, length: -> { pad2_length }
48
- string :trans2_data, label: 'Trans2 Data', length: 0
47
+ # trans2_data: No data is sent by this message.
49
48
  end
50
49
 
51
50
  smb_header :smb_header
@@ -23,23 +23,11 @@ module RubySMB
23
23
  end
24
24
  end
25
25
 
26
- # The Trans2 Data Block for this particular Subcommand
27
- class Trans2Data < BinData::Record
28
-
29
- # Returns the length of the Trans2Data struct
30
- # in number of bytes
31
- def length
32
- do_num_bytes
33
- end
34
- end
35
-
36
26
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
37
27
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
38
- uint8 :name, label: 'Name', initial_value: 0x00
39
28
  string :pad1, length: -> { pad1_length }
40
29
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
41
- string :pad2, length: -> { pad2_length }
42
- trans2_data :trans2_data, label: 'Trans2 Data'
30
+ # trans2_data: No data is sent by this message.
43
31
  end
44
32
 
45
33
  smb_header :smb_header
@@ -16,10 +16,18 @@ module RubySMB
16
16
  def initialize(tree:, response:, name:)
17
17
  raise ArgumentError, 'No Name Provided' if name.nil?
18
18
  case name
19
- when 'srvsvc'
19
+ when 'netlogon', '\\netlogon'
20
+ extend RubySMB::Dcerpc::Netlogon
21
+ when 'srvsvc', '\\srvsvc'
20
22
  extend RubySMB::Dcerpc::Srvsvc
21
- when 'winreg'
23
+ when 'svcctl', '\\svcctl'
24
+ extend RubySMB::Dcerpc::Svcctl
25
+ when 'winreg', '\\winreg'
22
26
  extend RubySMB::Dcerpc::Winreg
27
+ when 'samr', '\\samr'
28
+ extend RubySMB::Dcerpc::Samr
29
+ when 'wkssvc', '\\wkssvc'
30
+ extend RubySMB::Dcerpc::Wkssvc
23
31
  end
24
32
  super(tree: tree, response: response, name: name)
25
33
  end
@@ -41,8 +49,7 @@ module RubySMB
41
49
  raise RubySMB::Error::InvalidPacket.new(
42
50
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
43
51
  expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
44
- received_proto: response.smb_header.protocol,
45
- received_cmd: response.smb_header.command
52
+ packet: response
46
53
  )
47
54
  end
48
55
 
@@ -100,8 +107,7 @@ module RubySMB
100
107
  raise RubySMB::Error::InvalidPacket.new(
101
108
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
102
109
  expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND,
103
- received_proto: trans_nmpipe_response.smb_header.protocol,
104
- received_cmd: trans_nmpipe_response.smb_header.command
110
+ packet: trans_nmpipe_response
105
111
  )
106
112
  end
107
113
  unless [WindowsError::NTStatus::STATUS_SUCCESS,
@@ -49,13 +49,20 @@ module RubySMB
49
49
  raise RubySMB::Error::InvalidPacket.new(
50
50
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
51
51
  expected_cmd: RubySMB::SMB1::Packet::TreeDisconnectResponse::COMMAND,
52
- received_proto: response.smb_header.protocol,
53
- received_cmd: response.smb_header.command
52
+ packet: response
54
53
  )
55
54
  end
56
55
  response.status_code
57
56
  end
58
57
 
58
+ def open_pipe(opts)
59
+ # Make sure we don't modify the caller's hash options
60
+ opts = opts.dup
61
+ opts[:filename] = opts[:filename].dup
62
+ opts[:filename].prepend('\\') unless opts[:filename].start_with?('\\')
63
+ open_file(**opts)
64
+ end
65
+
59
66
  # Open a file on the remote share.
60
67
  #
61
68
  # @example
@@ -135,15 +142,14 @@ module RubySMB
135
142
  raise RubySMB::Error::InvalidPacket.new(
136
143
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
137
144
  expected_cmd: RubySMB::SMB1::Packet::NtCreateAndxResponse::COMMAND,
138
- received_proto: response.smb_header.protocol,
139
- received_cmd: response.smb_header.command
145
+ packet: response
140
146
  )
141
147
  end
142
148
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
143
149
  raise RubySMB::Error::UnexpectedStatusCode, response.status_code
144
150
  end
145
151
 
146
- case response.parameter_block.resource_type
152
+ case response.parameter_block.resource_type
147
153
  when RubySMB::SMB1::ResourceType::BYTE_MODE_PIPE, RubySMB::SMB1::ResourceType::MESSAGE_MODE_PIPE
148
154
  RubySMB::SMB1::Pipe.new(name: filename, tree: self, response: response)
149
155
  when RubySMB::SMB1::ResourceType::DISK
@@ -195,8 +201,7 @@ module RubySMB
195
201
  raise RubySMB::Error::InvalidPacket.new(
196
202
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
197
203
  expected_cmd: RubySMB::SMB1::Packet::Trans2::FindFirst2Response::COMMAND,
198
- received_proto: response.smb_header.protocol,
199
- received_cmd: response.smb_header.command
204
+ packet: response
200
205
  )
201
206
  end
202
207
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -230,8 +235,7 @@ module RubySMB
230
235
  raise RubySMB::Error::InvalidPacket.new(
231
236
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
232
237
  expected_cmd: RubySMB::SMB1::Packet::Trans2::FindNext2Response::COMMAND,
233
- received_proto: response.smb_header.protocol,
234
- received_cmd: response.smb_header.command
238
+ packet: response
235
239
  )
236
240
  end
237
241
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -95,8 +95,7 @@ module RubySMB
95
95
  raise RubySMB::Error::InvalidPacket.new(
96
96
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
97
97
  expected_cmd: RubySMB::SMB2::Packet::CloseResponse::COMMAND,
98
- received_proto: response.smb2_header.protocol,
99
- received_cmd: response.smb2_header.command
98
+ packet: response
100
99
  )
101
100
  end
102
101
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -115,21 +114,22 @@ module RubySMB
115
114
  # @raise [RubySMB::Error::InvalidPacket] if the response is not a ReadResponse packet
116
115
  # @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
117
116
  def read(bytes: size, offset: 0)
118
- atomic_read_size = if bytes > tree.client.server_max_read_size
119
- tree.client.server_max_read_size
120
- else
121
- bytes
122
- end
117
+ max_read = tree.client.server_max_read_size
118
+ max_read = 65536 unless tree.client.server_supports_multi_credit
119
+ atomic_read_size = [bytes, max_read].min
120
+ credit_charge = 0
121
+ if tree.client.server_supports_multi_credit
122
+ credit_charge = (atomic_read_size - 1) / 65536 + 1
123
+ end
123
124
 
124
- read_request = read_packet(read_length: atomic_read_size, offset: offset)
125
+ read_request = read_packet(read_length: atomic_read_size, offset: offset, credit_charge: credit_charge)
125
126
  raw_response = tree.client.send_recv(read_request, encrypt: @tree_connect_encrypt_data)
126
127
  response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
127
128
  unless response.valid?
128
129
  raise RubySMB::Error::InvalidPacket.new(
129
130
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
130
131
  expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
131
- received_proto: response.smb2_header.protocol,
132
- received_cmd: response.smb2_header.command
132
+ packet: response
133
133
  )
134
134
  end
135
135
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -142,17 +142,16 @@ module RubySMB
142
142
 
143
143
  while remaining_bytes > 0
144
144
  offset += atomic_read_size
145
- atomic_read_size = remaining_bytes if remaining_bytes < tree.client.server_max_read_size
145
+ atomic_read_size = remaining_bytes if remaining_bytes < max_read
146
146
 
147
- read_request = read_packet(read_length: atomic_read_size, offset: offset)
147
+ read_request = read_packet(read_length: atomic_read_size, offset: offset, credit_charge: credit_charge)
148
148
  raw_response = tree.client.send_recv(read_request, encrypt: @tree_connect_encrypt_data)
149
149
  response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
150
150
  unless response.valid?
151
151
  raise RubySMB::Error::InvalidPacket.new(
152
152
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
153
153
  expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
154
- received_proto: response.smb2_header.protocol,
155
- received_cmd: response.smb2_header.command
154
+ packet: response
156
155
  )
157
156
  end
158
157
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -169,11 +168,13 @@ module RubySMB
169
168
  #
170
169
  # @param bytes [Integer] the number of bytes to read
171
170
  # @param offset [Integer] the byte offset in the file to start reading from
171
+ # @param credit_charge [Integer] the number of credits that this request consumes
172
172
  # @return [RubySMB::SMB2::Packet::ReadRequest] the data read from the file
173
- def read_packet(read_length: 0, offset: 0)
173
+ def read_packet(read_length: 0, offset: 0, credit_charge: 1)
174
174
  read_request = set_header_fields(RubySMB::SMB2::Packet::ReadRequest.new)
175
175
  read_request.read_length = read_length
176
176
  read_request.offset = offset
177
+ read_request.smb2_header.credit_charge = credit_charge
177
178
  read_request
178
179
  end
179
180
 
@@ -185,8 +186,7 @@ module RubySMB
185
186
  raise RubySMB::Error::InvalidPacket.new(
186
187
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
187
188
  expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
188
- received_proto: response.smb2_header.protocol,
189
- received_cmd: response.smb2_header.command
189
+ packet: response
190
190
  )
191
191
  end
192
192
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -206,8 +206,7 @@ module RubySMB
206
206
  raise RubySMB::Error::InvalidPacket.new(
207
207
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
208
208
  expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
209
- received_proto: response.smb2_header.protocol,
210
- received_cmd: response.smb2_header.command
209
+ packet: response
211
210
  )
212
211
  end
213
212
  response.smb2_header.nt_status.to_nt_status
@@ -240,29 +239,30 @@ module RubySMB
240
239
  # @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
241
240
  # @raise [RubySMB::Error::InvalidPacket] if the response is not a WriteResponse packet
242
241
  def write(data:'', offset: 0)
242
+ max_write = tree.client.server_max_write_size
243
+ max_write = 65536 unless tree.client.server_supports_multi_credit
243
244
  buffer = data.dup
244
245
  bytes = data.length
245
- atomic_write_size = if bytes > tree.client.server_max_write_size
246
- tree.client.server_max_write_size
247
- else
248
- bytes
249
- end
246
+ atomic_write_size = [bytes, max_write].min
247
+ credit_charge = 0
248
+ if tree.client.server_supports_multi_credit
249
+ credit_charge = (atomic_write_size - 1) / 65536 + 1
250
+ end
250
251
 
251
252
  while buffer.length > 0 do
252
- write_request = write_packet(data: buffer.slice!(0,atomic_write_size), offset: offset)
253
+ write_request = write_packet(data: buffer.slice!(0, atomic_write_size), offset: offset, credit_charge: credit_charge)
253
254
  raw_response = tree.client.send_recv(write_request, encrypt: @tree_connect_encrypt_data)
254
255
  response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
255
256
  unless response.valid?
256
257
  raise RubySMB::Error::InvalidPacket.new(
257
258
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
258
259
  expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
259
- received_proto: response.smb2_header.protocol,
260
- received_cmd: response.smb2_header.command
260
+ packet: response
261
261
  )
262
262
  end
263
263
  status = response.smb2_header.nt_status.to_nt_status
264
264
 
265
- offset+= atomic_write_size
265
+ offset += atomic_write_size
266
266
  return status unless status == WindowsError::NTStatus::STATUS_SUCCESS
267
267
  end
268
268
 
@@ -273,11 +273,13 @@ module RubySMB
273
273
  #
274
274
  # @param data [String] the data to write to the file
275
275
  # @param offset [Integer] the offset in the file to start writing from
276
+ # @param credit_charge [Integer] the number of credits that this request consumes
276
277
  # @return []RubySMB::SMB2::Packet::WriteRequest] the request packet
277
- def write_packet(data:'', offset: 0)
278
+ def write_packet(data:'', offset: 0, credit_charge: 1)
278
279
  write_request = set_header_fields(RubySMB::SMB2::Packet::WriteRequest.new)
279
280
  write_request.write_offset = offset
280
281
  write_request.buffer = data
282
+ write_request.smb2_header.credit_charge = credit_charge
281
283
  write_request
282
284
  end
283
285
 
@@ -289,8 +291,7 @@ module RubySMB
289
291
  raise RubySMB::Error::InvalidPacket.new(
290
292
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
291
293
  expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
292
- received_proto: response.smb2_header.protocol,
293
- received_cmd: response.smb2_header.command
294
+ packet: response
294
295
  )
295
296
  end
296
297
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -311,8 +312,7 @@ module RubySMB
311
312
  raise RubySMB::Error::InvalidPacket.new(
312
313
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
313
314
  expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
314
- received_proto: response.smb2_header.protocol,
315
- received_cmd: response.smb2_header.command
315
+ packet: response
316
316
  )
317
317
  end
318
318
  response.smb2_header.nt_status.to_nt_status
@@ -69,9 +69,22 @@ module RubySMB
69
69
  class NetnameNegotiateContextId < BinData::Record
70
70
  endian :little
71
71
 
72
- stringz16 :net_name, label: 'Net Name'
72
+ count_bytes_remaining :bytes_remaining
73
+ default_parameter data_length: nil
74
+ hide :bytes_remaining
75
+
76
+ string16 :net_name, label: 'Net Name', read_length: -> { data_length.nil? ? bytes_remaining : data_length }
73
77
  end
74
78
 
79
+ # An SMB2 TRANSPORT_CAPABILITIES context struct as defined in
80
+ # [2.2.3.1.5 SMB2_TRANSPORT_CAPABILITIES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/450a1888-a645-4988-8638-5a11f4617545)
81
+ class TransportCapabilities < BinData::Record
82
+ SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY = 1 # Transport security is offered to skip SMB2 encryption on this connection.
83
+
84
+ endian :little
85
+
86
+ uint32 :flags, label: 'Flags'
87
+ end
75
88
 
76
89
  # An SMB2 NEGOTIATE_CONTEXT struct as defined in
77
90
  # [2.2.3.1 SMB2 NEGOTIATE_CONTEXT Request Values](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7)
@@ -84,6 +97,8 @@ module RubySMB
84
97
  SMB2_COMPRESSION_CAPABILITIES = 0x0003
85
98
  # The NegotiateContext Data field contains the server name to which the client connects.
86
99
  SMB2_NETNAME_NEGOTIATE_CONTEXT_ID = 0x0005
100
+ # The NegotiateContext Data field contains the transport capabilities, as specified in section 2.2.3.1.5.
101
+ SMB2_TRANSPORT_CAPABILITIES = 0x0006
87
102
 
88
103
  endian :little
89
104
 
@@ -95,7 +110,8 @@ module RubySMB
95
110
  preauth_integrity_capabilities SMB2_PREAUTH_INTEGRITY_CAPABILITIES, label: 'Preauthentication Integrity Capabilities'
96
111
  encryption_capabilities SMB2_ENCRYPTION_CAPABILITIES, label: 'Encryption Capabilities'
97
112
  compression_capabilities SMB2_COMPRESSION_CAPABILITIES, label: 'Compression Capabilities'
98
- netname_negotiate_context_id SMB2_NETNAME_NEGOTIATE_CONTEXT_ID, label: 'Netname Negotiate Context ID'
113
+ netname_negotiate_context_id SMB2_NETNAME_NEGOTIATE_CONTEXT_ID, label: 'Netname Negotiate Context ID', data_length: :data_length
114
+ transport_capabilities SMB2_TRANSPORT_CAPABILITIES, label: 'Transport Capabilities'
99
115
  end
100
116
 
101
117
  def pad_length
@@ -3,6 +3,9 @@ module RubySMB
3
3
  module Packet
4
4
  # An SMB2 COMPRESSION_TRANSFORM_HEADER Packet as defined in
5
5
  # [2.2.42 SMB2 COMPRESSION_TRANSFORM_HEADER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1d435f21-9a21-4f4c-828e-624a176cf2a0)
6
+ # NOTE: On 2021-04-06 the official documentation split the definition of COMPRESSION_TRANSFORM_HEADER into the following two variants:
7
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_CHAINED
8
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_UNCHAINED
6
9
  class CompressionTransformHeader < BinData::Record
7
10
  endian :little
8
11
 
@@ -11,6 +14,7 @@ module RubySMB
11
14
  uint16 :compression_algorithm, label: 'Compression Algorithm'
12
15
  uint16 :flags, label: 'Flags'
13
16
  uint32 :offset, label: 'Offset / Length'
17
+ array :compressed_data, label: 'Compressed Data', type: :uint8, read_until: :eof
14
18
  end
15
19
 
16
20
  # An SMB2 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD Packet as defined in
@@ -64,6 +64,15 @@ module RubySMB
64
64
  self.negotiate_context_list
65
65
  end
66
66
 
67
+ # Find the first Negotiate Context structure that matches the given
68
+ # context type
69
+ #
70
+ # @param [Integer] the Negotiate Context structure you wish to add
71
+ # @return [NegotiateContext] the Negotiate Context structure or nil if
72
+ # not found
73
+ def find_negotiate_context(type)
74
+ negotiate_context_list.find { |nc| nc.context_type == type }
75
+ end
67
76
 
68
77
  private
69
78
 
@@ -59,7 +59,6 @@ module RubySMB
59
59
  self.negotiate_context_list
60
60
  end
61
61
 
62
-
63
62
  private
64
63
 
65
64
  # Determines the correct length for the padding, so that the next
@@ -11,8 +11,8 @@ module RubySMB
11
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 9
12
12
  session_flags :session_flags
13
13
  uint16 :security_buffer_offset, label: 'Security Buffer Offset', initial_value: 0x48
14
- uint16 :security_buffer_length, label: 'Security Buffer Length'
15
- string :buffer, label: 'Security Buffer', length: -> { security_buffer_length }
14
+ uint16 :security_buffer_length, label: 'Security Buffer Length', initial_value: -> { buffer.length }
15
+ string :buffer, label: 'Security Buffer', read_length: -> { security_buffer_length }
16
16
 
17
17
  def initialize_instance
18
18
  super
@@ -101,7 +101,7 @@ module RubySMB
101
101
  path.to_binary_s.length
102
102
  end
103
103
  end
104
- string16 :path, label: 'Path Buffer', onlyif: -> { flags != SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT }
104
+ string16 :path, label: 'Path Buffer', onlyif: -> { flags != SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT }, read_length: -> { path_length }
105
105
  tree_connect_request_extension :tree_connect_request_extension, label: 'Tree Connect Request Extension', onlyif: -> { flags == SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT }
106
106
  end
107
107
  end
@@ -13,10 +13,18 @@ module RubySMB
13
13
  def initialize(tree:, response:, name:)
14
14
  raise ArgumentError, 'No Name Provided' if name.nil?
15
15
  case name
16
- when 'srvsvc'
16
+ when 'netlogon', '\\netlogon'
17
+ extend RubySMB::Dcerpc::Netlogon
18
+ when 'srvsvc', '\\srvsvc'
17
19
  extend RubySMB::Dcerpc::Srvsvc
18
- when 'winreg'
20
+ when 'svcctl', '\\svcctl'
21
+ extend RubySMB::Dcerpc::Svcctl
22
+ when 'winreg', '\\winreg'
19
23
  extend RubySMB::Dcerpc::Winreg
24
+ when 'samr', '\\samr'
25
+ extend RubySMB::Dcerpc::Samr
26
+ when 'wkssvc', '\\wkssvc'
27
+ extend RubySMB::Dcerpc::Wkssvc
20
28
  end
21
29
  super(tree: tree, response: response, name: name)
22
30
  end
@@ -40,8 +48,7 @@ module RubySMB
40
48
  raise RubySMB::Error::InvalidPacket.new(
41
49
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
42
50
  expected_cmd: RubySMB::SMB2::Packet::IoctlResponse::COMMAND,
43
- received_proto: response.smb2_header.protocol,
44
- received_cmd: response.smb2_header.command
51
+ packet: response
45
52
  )
46
53
  end
47
54
 
@@ -89,6 +96,7 @@ module RubySMB
89
96
  request = set_header_fields(RubySMB::SMB2::Packet::IoctlRequest.new(options))
90
97
  request.ctl_code = 0x0011C017
91
98
  request.flags.is_fsctl = 0x00000001
99
+ # TODO: handle fragmentation when the request size > MAX_XMIT_FRAG
92
100
  request.buffer = action.to_binary_s
93
101
 
94
102
  ioctl_raw_response = @tree.client.send_recv(request)
@@ -97,8 +105,7 @@ module RubySMB
97
105
  raise RubySMB::Error::InvalidPacket.new(
98
106
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
99
107
  expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND,
100
- received_proto: ioctl_response.smb2_header.protocol,
101
- received_cmd: ioctl_response.smb2_header.command
108
+ packet: ioctl_response
102
109
  )
103
110
  end
104
111
  unless [WindowsError::NTStatus::STATUS_SUCCESS,
@@ -50,13 +50,20 @@ module RubySMB
50
50
  raise RubySMB::Error::InvalidPacket.new(
51
51
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
52
52
  expected_cmd: RubySMB::SMB2::Packet::TreeDisconnectResponse::COMMAND,
53
- received_proto: response.smb2_header.protocol,
54
- received_cmd: response.smb2_header.command
53
+ packet: response
55
54
  )
56
55
  end
57
56
  response.status_code
58
57
  end
59
58
 
59
+ def open_pipe(opts)
60
+ # Make sure we don't modify the caller's hash options
61
+ opts = opts.dup
62
+ opts[:filename] = opts[:filename].dup
63
+ opts[:filename] = opts[:filename][1..-1] if opts[:filename].start_with? '\\'
64
+ open_file(**opts)
65
+ end
66
+
60
67
  def open_file(filename:, attributes: nil, options: nil, disposition: RubySMB::Dispositions::FILE_OPEN,
61
68
  impersonation: RubySMB::ImpersonationLevels::SEC_IMPERSONATE, read: true, write: false, delete: false)
62
69
 
@@ -108,8 +115,7 @@ module RubySMB
108
115
  raise RubySMB::Error::InvalidPacket.new(
109
116
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
110
117
  expected_cmd: RubySMB::SMB2::Packet::CreateResponse::COMMAND,
111
- received_proto: response.smb2_header.protocol,
112
- received_cmd: response.smb2_header.command
118
+ packet: response
113
119
  )
114
120
  end
115
121
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -147,12 +153,19 @@ module RubySMB
147
153
  directory_request.file_information_class = type::CLASS_LEVEL
148
154
  directory_request.file_id = file_id
149
155
  directory_request.name = pattern
150
- directory_request.output_length = 65_535
156
+
157
+ max_read = client.server_max_read_size
158
+ max_read = 65536 unless client.server_supports_multi_credit
159
+ credit_charge = 0
160
+ if client.server_supports_multi_credit
161
+ credit_charge = (max_read - 1) / 65536 + 1
162
+ end
163
+ directory_request.output_length = max_read
164
+ directory_request.smb2_header.credit_charge = credit_charge
151
165
 
152
166
  directory_request = set_header_fields(directory_request)
153
167
 
154
168
  files = []
155
-
156
169
  loop do
157
170
  response = client.send_recv(directory_request, encrypt: @tree_connect_encrypt_data)
158
171
  directory_response = RubySMB::SMB2::Packet::QueryDirectoryResponse.read(response)
@@ -160,8 +173,7 @@ module RubySMB
160
173
  raise RubySMB::Error::InvalidPacket.new(
161
174
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
162
175
  expected_cmd: RubySMB::SMB2::Packet::QueryDirectoryResponse::COMMAND,
163
- received_proto: directory_response.smb2_header.protocol,
164
- received_cmd: directory_response.smb2_header.command
176
+ packet: directory_response
165
177
  )
166
178
  end
167
179
 
@@ -205,8 +217,7 @@ module RubySMB
205
217
  raise RubySMB::Error::InvalidPacket.new(
206
218
  expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
207
219
  expected_cmd: RubySMB::SMB2::Packet::CreateResponse::COMMAND,
208
- received_proto: response.smb2_header.protocol,
209
- received_cmd: response.smb2_header.command
220
+ packet: response
210
221
  )
211
222
  end
212
223
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
@@ -256,7 +267,6 @@ module RubySMB
256
267
  # @return [RubySMB::SMB2::Packet] the modified packet.
257
268
  def set_header_fields(request)
258
269
  request.smb2_header.tree_id = id
259
- request.smb2_header.credit_charge = 1
260
270
  request.smb2_header.credits = 256
261
271
  request
262
272
  end
data/lib/ruby_smb/smb2.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  module RubySMB
2
2
  # A packet parsing and manipulation library for the SMB2 protocol
3
3
  #
4
- # [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
4
+ # [[MS-SMB2] Server Message Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
5
5
  module SMB2
6
6
  # Protocol ID value. Translates to \xFESMB
7
7
  SMB2_PROTOCOL_ID = 0xFE534D42
8
+ # Wildcard revision, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/63abf97c-0d09-47e2-88d6-6bfa552949a5
9
+ SMB2_WILDCARD_REVISION = 0x02ff
8
10
 
9
11
  require 'ruby_smb/smb2/info_type'
10
12
  require 'ruby_smb/smb2/commands'
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '3.0.0'.freeze
3
3
  end
data/lib/ruby_smb.rb CHANGED
@@ -8,8 +8,8 @@ require 'windows_error'
8
8
  require 'windows_error/nt_status'
9
9
  # A packet parsing and manipulation library for the SMB1 and SMB2 protocols
10
10
  #
11
- # [[MS-SMB] Server Mesage Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
- # [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
11
+ # [[MS-SMB] Server Message Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
+ # [[MS-SMB2] Server Message Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
13
13
  module RubySMB
14
14
  require 'ruby_smb/error'
15
15
  require 'ruby_smb/dispositions'
@@ -21,9 +21,11 @@ module RubySMB
21
21
  require 'ruby_smb/generic_packet'
22
22
  require 'ruby_smb/dispatcher'
23
23
  require 'ruby_smb/version'
24
- require 'ruby_smb/version'
25
24
  require 'ruby_smb/smb2'
26
25
  require 'ruby_smb/smb1'
27
26
  require 'ruby_smb/client'
28
27
  require 'ruby_smb/crypto'
28
+ require 'ruby_smb/compression'
29
+ require 'ruby_smb/server'
30
+ require 'ruby_smb/dialect'
29
31
  end