ruby_smb 0.0.18 → 0.0.19

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 (298) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +247 -7
  5. data/examples/anonymous_auth.rb +6 -3
  6. data/examples/append_file.rb +40 -0
  7. data/examples/authenticate.rb +12 -7
  8. data/examples/delete_file.rb +40 -0
  9. data/examples/list_directory.rb +45 -0
  10. data/examples/negotiate.rb +0 -1
  11. data/examples/negotiate_with_netbios_service.rb +36 -0
  12. data/examples/net_share_enum_all.rb +30 -0
  13. data/examples/read_file.rb +39 -0
  14. data/examples/rename_file.rb +41 -0
  15. data/examples/tree_connect.rb +2 -4
  16. data/examples/write_file.rb +40 -0
  17. data/lib/ruby_smb.rb +5 -0
  18. data/lib/ruby_smb/client.rb +196 -43
  19. data/lib/ruby_smb/client/authentication.rb +89 -48
  20. data/lib/ruby_smb/client/echo.rb +1 -4
  21. data/lib/ruby_smb/client/negotiation.rb +46 -45
  22. data/lib/ruby_smb/client/signing.rb +9 -16
  23. data/lib/ruby_smb/client/tree_connect.rb +8 -13
  24. data/lib/ruby_smb/client/utils.rb +79 -0
  25. data/lib/ruby_smb/dcerpc.rb +30 -0
  26. data/lib/ruby_smb/dcerpc/bind.rb +60 -0
  27. data/lib/ruby_smb/dcerpc/handle.rb +60 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +41 -0
  29. data/lib/ruby_smb/dcerpc/request.rb +43 -0
  30. data/lib/ruby_smb/dcerpc/response.rb +46 -0
  31. data/lib/ruby_smb/dcerpc/srvsvc.rb +17 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +93 -0
  33. data/lib/ruby_smb/dcerpc/uuid.rb +28 -0
  34. data/lib/ruby_smb/dispatcher.rb +7 -3
  35. data/lib/ruby_smb/dispatcher/base.rb +23 -14
  36. data/lib/ruby_smb/dispatcher/socket.rb +71 -51
  37. data/lib/ruby_smb/dispositions.rb +32 -0
  38. data/lib/ruby_smb/error.rb +24 -18
  39. data/lib/ruby_smb/field.rb +5 -2
  40. data/lib/ruby_smb/field/extended_attribute_flag.rb +1 -1
  41. data/lib/ruby_smb/field/file_time.rb +3 -1
  42. data/lib/ruby_smb/field/security_descriptor.rb +6 -6
  43. data/lib/ruby_smb/field/smb2_fileid.rb +11 -0
  44. data/lib/ruby_smb/field/smb_fea.rb +3 -3
  45. data/lib/ruby_smb/field/smb_fea_list.rb +3 -3
  46. data/lib/ruby_smb/field/smb_gea.rb +12 -0
  47. data/lib/ruby_smb/field/smb_gea_list.rb +13 -0
  48. data/lib/ruby_smb/field/string16.rb +14 -0
  49. data/lib/ruby_smb/field/stringz16.rb +3 -7
  50. data/lib/ruby_smb/field/utime.rb +11 -10
  51. data/lib/ruby_smb/fscc.rb +12 -0
  52. data/lib/ruby_smb/fscc/control_codes.rb +26 -0
  53. data/lib/ruby_smb/{field → fscc}/ea_info_array.rb +12 -14
  54. data/lib/ruby_smb/fscc/file_attributes.rb +29 -0
  55. data/lib/ruby_smb/{field → fscc}/file_full_ea_info.rb +5 -5
  56. data/lib/ruby_smb/fscc/file_information.rb +60 -0
  57. data/lib/ruby_smb/fscc/file_information/file_both_directory_information.rb +29 -0
  58. data/lib/ruby_smb/fscc/file_information/file_directory_information.rb +25 -0
  59. data/lib/ruby_smb/fscc/file_information/file_disposition_information.rb +15 -0
  60. data/lib/ruby_smb/fscc/file_information/file_full_directory_information.rb +26 -0
  61. data/lib/ruby_smb/fscc/file_information/file_id_both_directory_information.rb +31 -0
  62. data/lib/ruby_smb/fscc/file_information/file_id_full_directory_information.rb +28 -0
  63. data/lib/ruby_smb/fscc/file_information/file_names_information.rb +18 -0
  64. data/lib/ruby_smb/fscc/file_information/file_rename_information.rb +44 -0
  65. data/lib/ruby_smb/generic_packet.rb +40 -18
  66. data/lib/ruby_smb/gss.rb +49 -56
  67. data/lib/ruby_smb/impersonation_levels.rb +7 -2
  68. data/lib/ruby_smb/nbss.rb +16 -0
  69. data/lib/ruby_smb/nbss/negative_session_response.rb +30 -0
  70. data/lib/ruby_smb/nbss/session_header.rb +13 -0
  71. data/lib/ruby_smb/nbss/session_request.rb +13 -0
  72. data/lib/ruby_smb/smb1.rb +20 -17
  73. data/lib/ruby_smb/smb1/bit_field.rb +3 -0
  74. data/lib/ruby_smb/smb1/bit_field/create_options.rb +5 -5
  75. data/lib/ruby_smb/smb1/bit_field/file_status_flags.rb +18 -0
  76. data/lib/ruby_smb/smb1/bit_field/open2_access_mode.rb +11 -11
  77. data/lib/ruby_smb/smb1/bit_field/open2_open_mode.rb +1 -1
  78. data/lib/ruby_smb/smb1/bit_field/optional_support.rb +0 -1
  79. data/lib/ruby_smb/smb1/bit_field/security_flags.rb +15 -0
  80. data/lib/ruby_smb/smb1/bit_field/share_access.rb +2 -3
  81. data/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes.rb +21 -24
  82. data/lib/ruby_smb/smb1/bit_field/smb_file_attributes.rb +1 -1
  83. data/lib/ruby_smb/smb1/commands.rb +5 -0
  84. data/lib/ruby_smb/smb1/create_actions.rb +3 -5
  85. data/lib/ruby_smb/smb1/file.rb +289 -0
  86. data/lib/ruby_smb/smb1/oplock_levels.rb +2 -4
  87. data/lib/ruby_smb/smb1/packet.rb +10 -0
  88. data/lib/ruby_smb/smb1/packet/close_request.rb +31 -0
  89. data/lib/ruby_smb/smb1/packet/close_response.rb +28 -0
  90. data/lib/ruby_smb/smb1/packet/echo_request.rb +5 -7
  91. data/lib/ruby_smb/smb1/packet/echo_response.rb +5 -7
  92. data/lib/ruby_smb/smb1/packet/empty_packet.rb +1 -2
  93. data/lib/ruby_smb/smb1/packet/logoff_request.rb +1 -4
  94. data/lib/ruby_smb/smb1/packet/logoff_response.rb +1 -4
  95. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +22 -0
  96. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +22 -0
  97. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +62 -0
  98. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +66 -0
  99. data/lib/ruby_smb/smb1/packet/nt_trans.rb +1 -2
  100. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +19 -13
  101. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +8 -10
  102. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +11 -11
  103. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +10 -10
  104. data/lib/ruby_smb/smb1/packet/nt_trans/subcommands.rb +8 -1
  105. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +84 -0
  106. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +47 -0
  107. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -6
  108. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +1 -4
  109. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -6
  110. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -4
  111. data/lib/ruby_smb/smb1/packet/trans2.rb +8 -2
  112. data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +6 -7
  113. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +77 -0
  114. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +87 -0
  115. data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +32 -0
  116. data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info.rb +45 -0
  117. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +77 -0
  118. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +86 -0
  119. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +10 -10
  120. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +10 -12
  121. data/lib/ruby_smb/smb1/packet/trans2/request.rb +15 -17
  122. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +8 -10
  123. data/lib/ruby_smb/smb1/packet/trans2/response.rb +11 -13
  124. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +66 -0
  125. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +57 -0
  126. data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +5 -2
  127. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -6
  128. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +5 -7
  129. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  130. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -4
  131. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +68 -0
  132. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +35 -0
  133. data/lib/ruby_smb/smb1/resource_type.rb +18 -0
  134. data/lib/ruby_smb/smb1/tree.rb +188 -5
  135. data/lib/ruby_smb/smb2.rb +16 -11
  136. data/lib/ruby_smb/smb2/bit_field.rb +1 -0
  137. data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +1 -1
  138. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +1 -2
  139. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +4 -6
  140. data/lib/ruby_smb/smb2/create_context.rb +29 -0
  141. data/lib/ruby_smb/smb2/file.rb +251 -0
  142. data/lib/ruby_smb/smb2/info_type.rb +21 -0
  143. data/lib/ruby_smb/smb2/packet.rb +16 -0
  144. data/lib/ruby_smb/smb2/packet/close_request.rb +22 -0
  145. data/lib/ruby_smb/smb2/packet/close_response.rb +29 -0
  146. data/lib/ruby_smb/smb2/packet/create_request.rb +54 -0
  147. data/lib/ruby_smb/smb2/packet/create_response.rb +35 -0
  148. data/lib/ruby_smb/smb2/packet/echo_request.rb +1 -3
  149. data/lib/ruby_smb/smb2/packet/echo_response.rb +1 -3
  150. data/lib/ruby_smb/smb2/packet/error_packet.rb +1 -3
  151. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +54 -0
  152. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +39 -0
  153. data/lib/ruby_smb/smb2/packet/logoff_request.rb +1 -4
  154. data/lib/ruby_smb/smb2/packet/logoff_response.rb +1 -4
  155. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +1 -1
  156. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +1 -1
  157. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +35 -0
  158. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +45 -0
  159. data/lib/ruby_smb/smb2/packet/read_request.rb +30 -0
  160. data/lib/ruby_smb/smb2/packet/read_response.rb +26 -0
  161. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  162. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +4 -7
  163. data/lib/ruby_smb/smb2/packet/set_info_request.rb +58 -0
  164. data/lib/ruby_smb/smb2/packet/set_info_response.rb +20 -0
  165. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +3 -4
  166. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +5 -9
  167. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +1 -4
  168. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -4
  169. data/lib/ruby_smb/smb2/packet/write_request.rb +29 -0
  170. data/lib/ruby_smb/smb2/packet/write_response.rb +26 -0
  171. data/lib/ruby_smb/smb2/tree.rb +163 -7
  172. data/lib/ruby_smb/version.rb +1 -1
  173. data/spec/lib/ruby_smb/client_spec.rb +459 -120
  174. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +14 -0
  175. data/spec/lib/ruby_smb/dcerpc/handle_spec.rb +31 -0
  176. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +21 -0
  177. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +15 -0
  178. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +13 -0
  179. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +12 -0
  180. data/spec/lib/ruby_smb/dispatcher/base_spec.rb +26 -0
  181. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +118 -18
  182. data/spec/lib/ruby_smb/field/extended_attribute_flag_spec.rb +0 -3
  183. data/spec/lib/ruby_smb/field/file_time_spec.rb +4 -2
  184. data/spec/lib/ruby_smb/field/security_descriptor.rb +0 -1
  185. data/spec/lib/ruby_smb/field/smb2_fileid_spec.rb +10 -0
  186. data/spec/lib/ruby_smb/field/smb_fea_list_spec.rb +3 -5
  187. data/spec/lib/ruby_smb/field/smb_gea_list_spec.rb +37 -0
  188. data/spec/lib/ruby_smb/field/smb_gea_spec.rb +22 -0
  189. data/spec/lib/ruby_smb/field/stringz16_spec.rb +7 -9
  190. data/spec/lib/ruby_smb/field/utime_spec.rb +4 -2
  191. data/spec/lib/ruby_smb/{field → fscc}/ea_info_array_spec.rb +7 -9
  192. data/spec/lib/ruby_smb/{field → fscc}/file_full_ea_info_spec.rb +2 -3
  193. data/spec/lib/ruby_smb/fscc/file_information/file_both_directory_information_spec.rb +71 -0
  194. data/spec/lib/ruby_smb/fscc/file_information/file_directory_information_spec.rb +68 -0
  195. data/spec/lib/ruby_smb/fscc/file_information/file_disposition_information_spec.rb +26 -0
  196. data/spec/lib/ruby_smb/fscc/file_information/file_full_directory_information_spec.rb +69 -0
  197. data/spec/lib/ruby_smb/fscc/file_information/file_id_both_directory_information_spec.rb +72 -0
  198. data/spec/lib/ruby_smb/fscc/file_information/file_id_full_directory_information_spec.rb +70 -0
  199. data/spec/lib/ruby_smb/fscc/file_information/file_names_information_spec.rb +41 -0
  200. data/spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb +133 -0
  201. data/spec/lib/ruby_smb/fscc/fscc_file_attributes_spec.rb +143 -0
  202. data/spec/lib/ruby_smb/generic_packet_spec.rb +46 -21
  203. data/spec/lib/ruby_smb/nbss/negative_session_response_spec.rb +29 -0
  204. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +30 -0
  205. data/spec/lib/ruby_smb/nbss/session_request_spec.rb +30 -0
  206. data/spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb +9 -1
  207. data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +0 -2
  208. data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +0 -2
  209. data/spec/lib/ruby_smb/smb1/bit_field/file_status_flags_spec.rb +35 -0
  210. data/spec/lib/ruby_smb/smb1/bit_field/open2_access_mode_spec.rb +1 -3
  211. data/spec/lib/ruby_smb/smb1/bit_field/open2_flags_spec.rb +0 -2
  212. data/spec/lib/ruby_smb/smb1/bit_field/open2_open_mode_spec.rb +0 -1
  213. data/spec/lib/ruby_smb/smb1/bit_field/optional_support_spec.rb +0 -1
  214. data/spec/lib/ruby_smb/smb1/bit_field/security_flags_spec.rb +26 -0
  215. data/spec/lib/ruby_smb/smb1/bit_field/share_access_spec.rb +0 -3
  216. data/spec/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes_spec.rb +20 -39
  217. data/spec/lib/ruby_smb/smb1/bit_field/smb_file_attributes_spec.rb +0 -6
  218. data/spec/lib/ruby_smb/smb1/bit_field/smb_nmpipe_status_spec.rb +0 -2
  219. data/spec/lib/ruby_smb/smb1/bit_field/trans2_flags_spec.rb +0 -2
  220. data/spec/lib/ruby_smb/smb1/bit_field/tree_connect_flags_spec.rb +0 -2
  221. data/spec/lib/ruby_smb/smb1/file_spec.rb +469 -0
  222. data/spec/lib/ruby_smb/smb1/packet/close_request_spec.rb +54 -0
  223. data/spec/lib/ruby_smb/smb1/packet/close_response_spec.rb +45 -0
  224. data/spec/lib/ruby_smb/smb1/packet/echo_request_spec.rb +1 -4
  225. data/spec/lib/ruby_smb/smb1/packet/echo_response_spec.rb +1 -4
  226. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +1 -3
  227. data/spec/lib/ruby_smb/smb1/packet/logoff_request_spec.rb +1 -4
  228. data/spec/lib/ruby_smb/smb1/packet/logoff_response_spec.rb +1 -4
  229. data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +1 -1
  230. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +37 -0
  231. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +37 -0
  232. data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_request_spec.rb +151 -0
  233. data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_response_spec.rb +157 -0
  234. data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_request_spec.rb +13 -6
  235. data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_response_spec.rb +1 -7
  236. data/spec/lib/ruby_smb/smb1/packet/nt_trans/request_spec.rb +1 -6
  237. data/spec/lib/ruby_smb/smb1/packet/nt_trans/response_spec.rb +1 -5
  238. data/spec/lib/ruby_smb/smb1/packet/read_andx_request_spec.rb +149 -0
  239. data/spec/lib/ruby_smb/smb1/packet/read_andx_response_spec.rb +93 -0
  240. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +1 -5
  241. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +1 -5
  242. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +3 -8
  243. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +2 -4
  244. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +180 -0
  245. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +104 -0
  246. data/spec/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info_spec.rb +128 -0
  247. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +174 -0
  248. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +102 -0
  249. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_request_spec.rb +1 -6
  250. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +2 -7
  251. data/spec/lib/ruby_smb/smb1/packet/trans2/request_secondary_spec.rb +1 -5
  252. data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +1 -5
  253. data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +1 -4
  254. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +98 -0
  255. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +56 -0
  256. data/spec/lib/ruby_smb/smb1/packet/tree_connect_request_spec.rb +1 -5
  257. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +1 -6
  258. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_request_spec.rb +1 -4
  259. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_response_spec.rb +1 -4
  260. data/spec/lib/ruby_smb/smb1/packet/write_andx_request_spec.rb +148 -0
  261. data/spec/lib/ruby_smb/smb1/packet/write_andx_response_spec.rb +54 -0
  262. data/spec/lib/ruby_smb/smb1/tree_spec.rb +409 -7
  263. data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +0 -2
  264. data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +0 -2
  265. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +1 -1
  266. data/spec/lib/ruby_smb/smb2/bit_field/share_capabilities_spec.rb +0 -1
  267. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +0 -2
  268. data/spec/lib/ruby_smb/smb2/create_context_spec.rb +42 -0
  269. data/spec/lib/ruby_smb/smb2/file_spec.rb +233 -0
  270. data/spec/lib/ruby_smb/smb2/packet/close_request_spec.rb +40 -0
  271. data/spec/lib/ruby_smb/smb2/packet/close_response_spec.rb +40 -0
  272. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +101 -0
  273. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +64 -0
  274. data/spec/lib/ruby_smb/smb2/packet/echo_request_spec.rb +1 -3
  275. data/spec/lib/ruby_smb/smb2/packet/echo_response_spec.rb +1 -3
  276. data/spec/lib/ruby_smb/smb2/packet/ioctl_request_spec.rb +48 -0
  277. data/spec/lib/ruby_smb/smb2/packet/logoff_request_spec.rb +1 -3
  278. data/spec/lib/ruby_smb/smb2/packet/logoff_response_spec.rb +1 -3
  279. data/spec/lib/ruby_smb/smb2/packet/query_directory_request_spec.rb +80 -0
  280. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +64 -0
  281. data/spec/lib/ruby_smb/smb2/packet/read_request_spec.rb +43 -0
  282. data/spec/lib/ruby_smb/smb2/packet/read_response_spec.rb +50 -0
  283. data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +3 -4
  284. data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +2 -3
  285. data/spec/lib/ruby_smb/smb2/packet/set_info_request_spec.rb +205 -0
  286. data/spec/lib/ruby_smb/smb2/packet/set_info_response_spec.rb +32 -0
  287. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +3 -5
  288. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +1 -2
  289. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_request_spec.rb +1 -3
  290. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_response_spec.rb +1 -3
  291. data/spec/lib/ruby_smb/smb2/packet/write_request_spec.rb +51 -0
  292. data/spec/lib/ruby_smb/smb2/packet/write_response_spec.rb +38 -0
  293. data/spec/lib/ruby_smb/smb2/tree_spec.rb +191 -5
  294. data/spec/spec_helper.rb +1 -1
  295. metadata +195 -12
  296. metadata.gz.sig +0 -0
  297. data/lib/ruby_smb/smb1/dispositions.rb +0 -36
  298. data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +0 -22
@@ -0,0 +1,93 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Srvsvc
4
+
5
+ #https://msdn.microsoft.com/en-us/library/cc247293.aspx
6
+
7
+ class NetShareEnumAll < BinData::Record
8
+ Opnum = 0xF
9
+
10
+ endian :little
11
+
12
+ uint32 :referent_id, initial_value: 0x00000001
13
+ uint32 :max_count, initial_value: -> { server_unc.do_num_bytes / 2 }
14
+ uint32 :offset, initial_value: 0
15
+ uint32 :actual_count, initial_value: -> {max_count}
16
+ stringz16 :server_unc, pad_front: false, read_length: -> { actual_count * 2 },
17
+ initial_value: -> {host.encode('utf-16le')}
18
+
19
+ uint32 :level, initial_value: 1
20
+
21
+ uint32 :ctr, initial_value: 1
22
+ uint32 :ctr_referent_id, initial_value: 0x00000001
23
+ uint32 :ctr_count, initial_value: 0
24
+ uint32 :pointer_to_array, initial_value: 0
25
+
26
+ uint32 :max_buffer, initial_value: 4294967295
27
+
28
+ uint32 :resume_referent_id, initial_value: 0x00000001
29
+ uint32 :resume_handle, initial_value: 0
30
+
31
+ def self.parse_response(response)
32
+
33
+ shares = []
34
+
35
+ res = response.dup
36
+ win_error = res.slice!(-4, 4).unpack("V")[0]
37
+
38
+ if win_error != 0
39
+ raise RuntimeError, "Invalid DCERPC response: win_error = #{win_error}"
40
+ end
41
+
42
+ # Remove unused data
43
+ res.slice!(0, 12) # level, CTR header, Reference ID of CTR
44
+ share_count = res.slice!(0, 4).unpack("V")[0]
45
+ res.slice!(0, 4) # Reference ID of CTR1
46
+ share_max_count = res.slice!(0, 4).unpack("V")[0]
47
+
48
+ if share_max_count != share_count
49
+ raise RuntimeError, "Invalid DCERPC response: count != count max (#{share_count}/#{share_max_count})"
50
+ end
51
+
52
+ # ReferenceID / Type / ReferenceID of Comment
53
+ types = res.slice!(0, share_count * 12).scan(/.{12}/n).map { |a| a[4, 2].unpack("v")[0] }
54
+
55
+ share_count.times do |t|
56
+ length, offset, max_length = res.slice!(0, 12).unpack("VVV")
57
+ if offset != 0
58
+ raise RuntimeError, "Invalid DCERPC response: offset != 0 (#{offset})"
59
+ end
60
+
61
+ if length != max_length
62
+ raise RuntimeError, "Invalid DCERPC response: length !=max_length (#{length}/#{max_length})"
63
+ end
64
+ name = res.slice!(0, 2 * length).gsub('\x00', '')
65
+ res.slice!(0, 2) if length % 2 == 1 # pad
66
+
67
+ comment_length, comment_offset, comment_max_length = res.slice!(0, 12).unpack("VVV")
68
+
69
+ if comment_offset != 0
70
+ raise RuntimeError, "Invalid DCERPC response: comment_offset != 0 (#{comment_offset})"
71
+ end
72
+
73
+ if comment_length != comment_max_length
74
+ raise RuntimeError, "Invalid DCERPC response: comment_length != comment_max_length (#{comment_length}/#{comment_max_length})"
75
+ end
76
+
77
+ comment = res.slice!(0, 2 * comment_length)
78
+
79
+ res.slice!(0, 2) if comment_length % 2 == 1 # pad
80
+
81
+ name = name.gsub("\x00", "")
82
+ s_type = ['DISK', 'PRINTER', 'DEVICE', 'IPC', 'SPECIAL', 'TEMPORARY'][types[t]].gsub("\x00", "")
83
+ comment = comment.gsub("\x00", "")
84
+
85
+ shares << [name, s_type, comment]
86
+ end
87
+
88
+ shares
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,28 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+
4
+ #https://msdn.microsoft.com/en-us/library/windows/desktop/aa379358(v=vs.85).aspx
5
+ class Uuid < BinData::Primitive
6
+ uint32le :time_low
7
+ uint16le :time_mid
8
+ uint16le :time_hi_and_version
9
+
10
+ uint16be :clock_seq_hi_and_res
11
+ uint48be :node
12
+
13
+ def get
14
+ self.to_binary_s
15
+ end
16
+
17
+ def set(uuid_string)
18
+ components = uuid_string.split('-')
19
+ self.time_low = components[0].hex
20
+ self.time_mid = components[1].hex
21
+ self.time_hi_and_version = components[2].hex
22
+ self.clock_seq_hi_and_res = components[3].hex
23
+ self.node = components[4].hex
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -1,4 +1,8 @@
1
- module RubySMB::Dispatcher
2
- require 'ruby_smb/dispatcher/base'
3
- require 'ruby_smb/dispatcher/socket'
1
+ module RubySMB
2
+ # Namespace for all of the packet Dispatcher code. This is what
3
+ # handles network level transport.
4
+ module Dispatcher
5
+ require 'ruby_smb/dispatcher/base'
6
+ require 'ruby_smb/dispatcher/socket'
7
+ end
4
8
  end
@@ -1,18 +1,27 @@
1
- # Provides the base class for the packet dispatcher.
2
- class RubySMB::Dispatcher::Base
3
- # @param packet [#length]
4
- # @return [Fixnum] NBSS header to go in front of `packet`
5
- def nbss(packet)
6
- [packet.do_num_bytes].pack('N')
7
- end
1
+ module RubySMB
2
+ module Dispatcher
3
+ # Provides the base class for the packet dispatcher.
4
+ class Base
5
+ # Creates a NetBIOS Session Service (NBSS) header
6
+ #
7
+ # @param packet [#do_num_bytes] the packet to be sent
8
+ # @return [String] NBSS header to go in front of `packet`
9
+ def nbss(packet)
10
+ nbss = RubySMB::Nbss::SessionHeader.new
11
+ nbss.session_packet_type = RubySMB::Nbss::SESSION_MESSAGE
12
+ nbss.packet_length = packet.do_num_bytes
13
+ nbss.to_binary_s
14
+ end
8
15
 
9
- # @abstract
10
- def send_packet(packet)
11
- raise NotImplementedError
12
- end
16
+ # @abstract
17
+ def send_packet(_packet)
18
+ raise NotImplementedError
19
+ end
13
20
 
14
- # @abstract
15
- def recv_packet
16
- raise NotImplementedError
21
+ # @abstract
22
+ def recv_packet
23
+ raise NotImplementedError
24
+ end
25
+ end
17
26
  end
18
27
  end
@@ -1,62 +1,82 @@
1
1
  require 'socket'
2
+ module RubySMB
3
+ module Dispatcher
4
+ # This class provides a wrapper around a Socket for the packet Dispatcher.
5
+ # It allows for dependency injection of different Socket implementations.
6
+ class Socket < RubySMB::Dispatcher::Base
7
+ READ_TIMEOUT = 30
2
8
 
3
- # This class provides a wrapper around a Socket for the packet Dispatcher.
4
- # It allows for dependency injection of different Socket implementations.
5
- class RubySMB::Dispatcher::Socket < RubySMB::Dispatcher::Base
6
- # The underlying socket that we select on
7
- # @!attribute [rw] tcp_socket
8
- # @return [IO]
9
- attr_accessor :tcp_socket
10
-
11
- # @param tcp_socket [IO]
12
- def initialize(tcp_socket)
13
- @tcp_socket = tcp_socket
14
- if @tcp_socket.respond_to?(:setsockopt)
15
- @tcp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
16
- end
17
- end
9
+ # The underlying socket that we select on
10
+ # @!attribute [rw] tcp_socket
11
+ # @return [IO]
12
+ attr_accessor :tcp_socket
18
13
 
19
- # @param host [String] passed to TCPSocket.new
20
- # @param port [Fixnum] passed to TCPSocket.new
21
- def self.connect(host, port: 445, socket: TCPSocket.new(host, port))
22
- new(socket)
23
- end
14
+ # The read timeout
15
+ # @!attribute [rw] read_timeout
16
+ # @return [Integer]
17
+ attr_accessor :read_timeout
24
18
 
25
- # @param packet [SMB2::Packet,#to_s]
26
- # @return [void]
27
- def send_packet(packet)
28
- data = nbss(packet) + packet.to_binary_s
29
- bytes_written = 0
30
- begin
31
- while bytes_written < data.size
32
- bytes_written += @tcp_socket.write(data[bytes_written..-1])
19
+ # @param tcp_socket [IO]
20
+ def initialize(tcp_socket, read_timeout: READ_TIMEOUT)
21
+ @tcp_socket = tcp_socket
22
+ @tcp_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if @tcp_socket.respond_to?(:setsockopt)
23
+ @read_timeout = read_timeout
33
24
  end
34
- rescue IOError, Errno::ECONNABORTED, Errno::ECONNRESET => e
35
- raise RubySMB::Error::CommunicationError, "An error occured writing to the Socket"
36
- end
37
- nil
38
- end
39
25
 
40
- # Read a packet off the wire and parse it into a string
41
- # Throw Error::NetBiosSessionService if there's an error reading the first 4 bytes,
42
- # which are assumed to be the NetBiosSessionService header.
43
- # @return [String]
44
- def recv_packet
45
- begin
46
- IO.select([@tcp_socket])
47
- nbss_header = @tcp_socket.read(4) # Length of NBSS header. TODO: remove to a constant
48
- if nbss_header.nil?
49
- raise ::RubySMB::Error::NetBiosSessionService, 'NBSS Header is missing'
50
- else
51
- length = nbss_header.unpack('N').first
26
+ # @param host [String] passed to TCPSocket.new
27
+ # @param port [Fixnum] passed to TCPSocket.new
28
+ def self.connect(host, port: 445, socket: TCPSocket.new(host, port))
29
+ new(socket)
52
30
  end
53
- IO.select([@tcp_socket])
54
- data = @tcp_socket.read(length)
55
- data << @tcp_socket.read(length - data.length) while data.length < length
56
31
 
57
- data
58
- rescue Errno::EINVAL, Errno::ECONNABORTED, Errno::ECONNRESET, TypeError => e
59
- raise RubySMB::Error::CommunicationError, "An error occured reading from the Socket"
32
+ # @param packet [SMB2::Packet,#to_s]
33
+ # @param nbss [Boolean] wether to include the NetBIOS Session header
34
+ # @return [void]
35
+ def send_packet(packet, nbss_header: true)
36
+ data = nbss_header ? nbss(packet) : ''
37
+ data << packet.to_binary_s
38
+ bytes_written = 0
39
+ begin
40
+ while bytes_written < data.size
41
+ bytes_written += @tcp_socket.write(data[bytes_written..-1])
42
+ end
43
+ rescue IOError, Errno::ECONNABORTED, Errno::ECONNRESET => e
44
+ raise RubySMB::Error::CommunicationError, "An error occured writing to the Socket: #{e.message}"
45
+ end
46
+ nil
47
+ end
48
+
49
+ # Read a packet off the wire and parse it into a string
50
+ #
51
+ # @param full_response [Boolean] whether to include the NetBios Session Service header in the repsonse
52
+ # @return [String] the raw response (including the NetBios Session Service header if full_response is true)
53
+ # @raise [RubySMB::Error::NetBiosSessionService] if there's an error reading the first 4 bytes,
54
+ # which are assumed to be the NetBiosSessionService header.
55
+ # @raise [RubySMB::Error::CommunicationError] if the read timeout expires or an error occurs when reading the socket
56
+ def recv_packet(full_response: false)
57
+ if IO.select([@tcp_socket], nil, nil, @read_timeout).nil?
58
+ raise RubySMB::Error::CommunicationError, "Read timeout expired when reading from the Socket (timeout=#{@read_timeout})"
59
+ end
60
+
61
+ begin
62
+ nbss_header = RubySMB::Nbss::SessionHeader.read(@tcp_socket)
63
+ rescue IOError
64
+ raise ::RubySMB::Error::NetBiosSessionService, 'NBSS Header is missing'
65
+ end
66
+
67
+ length = nbss_header.packet_length
68
+ data = full_response ? nbss_header.to_binary_s : ''
69
+ if length > 0
70
+ if IO.select([@tcp_socket], nil, nil, @read_timeout).nil?
71
+ raise RubySMB::Error::CommunicationError, "Read timeout expired when reading from the Socket (timeout=#{@read_timeout})"
72
+ end
73
+ data << @tcp_socket.read(length)
74
+ data << @tcp_socket.read(length - data.length) while data.length < length
75
+ end
76
+ data
77
+ rescue Errno::EINVAL, Errno::ECONNABORTED, Errno::ECONNRESET, TypeError, NoMethodError => e
78
+ raise RubySMB::Error::CommunicationError, "An error occured reading from the Socket #{e.message}"
79
+ end
60
80
  end
61
81
  end
62
82
  end
@@ -0,0 +1,32 @@
1
+ module RubySMB
2
+ # This module holds the Create Dispositions used in NT_TRANSACT_CREATE and
3
+ # SMB_COM_NT_CREATE_ANDX requests. The definitions for these values can be found at
4
+ # [2.2.4.64.1 Request](https://msdn.microsoft.com/en-us/library/ee442175.aspx)
5
+ module Dispositions
6
+ # If the file already exists, it SHOULD be superseded (overwritten).
7
+ # If it does not already exist, it SHOULD be created.
8
+ FILE_SUPERSEDE = 0x00000000
9
+
10
+ # If the file already exists, it SHOULD be opened rather than creating a new file.
11
+ # If the file does not already exist, the operation MUST fail.
12
+ FILE_OPEN = 0x00000001
13
+
14
+ # If the file already exists, the operation MUST fail.
15
+ # If the file does not already exist, it SHOULD be created.
16
+ FILE_CREATE = 0x00000002
17
+
18
+ # If the file already exists, it SHOULD be opened.
19
+ # If the file does not already exist, it SHOULD be created.
20
+ FILE_OPEN_IF = 0x00000003
21
+
22
+ # If the file already exists, it SHOULD be opened and truncated.
23
+ # If the file does not already exist, the operation MUST fail.
24
+ # The client MUST open the file with at least GENERIC_WRITE access for the command to succeed.
25
+ FILE_OVERWRITE = 0x00000004
26
+
27
+ # If the file already exists, it SHOULD be opened and truncated.
28
+ # If the file does not already exist, it SHOULD be created.
29
+ # The client MUST open the file with at least GENERIC_WRITE access.
30
+ FILE_OVERWRITE_IF = 0x00000005
31
+ end
32
+ end
@@ -1,24 +1,30 @@
1
- module RubySMB::Error
2
- # Raised when there is a length or formatting issue with an ASN1-encoded string
3
- # @see https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
4
- # @todo Find an SMB-specific link for ASN1 above
5
- class ASN1Encoding < StandardError; end
1
+ module RubySMB
2
+ # Contains all the RubySMB specific Error classes.
3
+ module Error
4
+ # Base class for RubySMB errors
5
+ class RubySMBError < StandardError; end
6
6
 
7
- # Raised when there is a problem with communication over NetBios Session Service
8
- # @see https://wiki.wireshark.org/NetBIOS/NBSS
9
- class NetBiosSessionService < StandardError; end
7
+ # Raised when there is a length or formatting issue with an ASN1-encoded string
8
+ # @see https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
9
+ # @todo Find an SMB-specific link for ASN1 above
10
+ class ASN1Encoding < RubySMBError; end
10
11
 
11
- # Raised when trying to parse raw binary into a Packet and the data
12
- # is invalid.
13
- class InvalidPacket < StandardError; end
12
+ # Raised when there is a problem with communication over NetBios Session Service
13
+ # @see https://wiki.wireshark.org/NetBIOS/NBSS
14
+ class NetBiosSessionService < RubySMBError; end
14
15
 
15
- # Raised when a response packet has a NTStatus code that was unexpected.
16
- class UnexpectedStatusCode < StandardError; end
16
+ # Raised when trying to parse raw binary into a Packet and the data
17
+ # is invalid.
18
+ class InvalidPacket < RubySMBError; end
17
19
 
18
- # Raised when an error occurs with the underlying socket.
19
- class CommunicationError < StandardError; end
20
+ # Raised when a response packet has a NTStatus code that was unexpected.
21
+ class UnexpectedStatusCode < RubySMBError; end
20
22
 
21
- # Raised when Protocol Negotiation fails, possibly due to an
22
- # unsupported protocol.
23
- class NegotiationFailure < StandardError; end
23
+ # Raised when an error occurs with the underlying socket.
24
+ class CommunicationError < RubySMBError; end
25
+
26
+ # Raised when Protocol Negotiation fails, possibly due to an
27
+ # unsupported protocol.
28
+ class NegotiationFailure < RubySMBError; end
29
+ end
24
30
  end
@@ -1,4 +1,5 @@
1
1
  module RubySMB
2
+ # Namespace for all of the custom BinData fields used by RubySMB
2
3
  module Field
3
4
  require 'ruby_smb/field/file_time'
4
5
  require 'ruby_smb/field/utime'
@@ -8,7 +9,9 @@ module RubySMB
8
9
  require 'ruby_smb/field/smb_fea'
9
10
  require 'ruby_smb/field/smb_fea_list'
10
11
  require 'ruby_smb/field/security_descriptor'
11
- require 'ruby_smb/field/file_full_ea_info'
12
- require 'ruby_smb/field/ea_info_array'
12
+ require 'ruby_smb/field/string16'
13
+ require 'ruby_smb/field/smb2_fileid'
14
+ require 'ruby_smb/field/smb_gea'
15
+ require 'ruby_smb/field/smb_gea_list'
13
16
  end
14
17
  end
@@ -7,4 +7,4 @@ module RubySMB
7
7
  bit7 :reserved, label: 'Reserved Space'
8
8
  end
9
9
  end
10
- end
10
+ end
@@ -1,3 +1,5 @@
1
+ require 'date'
2
+
1
3
  module RubySMB
2
4
  module Field
3
5
  # Represents a Windows FILETIME structure as defined in
@@ -32,7 +34,7 @@ module RubySMB
32
34
  time_int *= NS_MULTIPLIER
33
35
  adjusted_epoch = time_int + EPOCH_DIFF_100NS
34
36
  set(adjusted_epoch)
35
- when Fixnum
37
+ when Integer
36
38
  self.val = value
37
39
  else
38
40
  self.val = value.to_i
@@ -4,7 +4,7 @@ module RubySMB
4
4
  # [2.4.6 SECURITY_DESCRIPTOR](https://msdn.microsoft.com/en-us/library/cc230366.aspx)
5
5
  class SecurityDescriptor < BinData::Record
6
6
  endian :little
7
- uint8 :revision, label: 'Revision', initial_value: 0x01
7
+ uint8 :revision, label: 'Revision', initial_value: 0x01
8
8
  uint8 :sbz1, label: 'Resource Manager Control Bits'
9
9
 
10
10
  struct :control do
@@ -28,10 +28,10 @@ module RubySMB
28
28
  bit1 :dacl_trusted, label: 'DACL Trusted'
29
29
  end
30
30
 
31
- uint32 :offset_owner, label: 'Offset Owner', initial_value: lambda { owner_sid.rel_offset }
32
- uint32 :offset_group, label: 'Offset Group', initial_value: lambda { group_sid.rel_offset }
33
- uint32 :offset_sacl, label: 'Offset SACL', initial_value: lambda { sacl.rel_offset }
34
- uint32 :offset_dacl, label: 'Offset DACL', initial_value: lambda { dacl.rel_offset }
31
+ uint32 :offset_owner, label: 'Offset Owner', initial_value: -> { owner_sid.rel_offset }
32
+ uint32 :offset_group, label: 'Offset Group', initial_value: -> { group_sid.rel_offset }
33
+ uint32 :offset_sacl, label: 'Offset SACL', initial_value: -> { sacl.rel_offset }
34
+ uint32 :offset_dacl, label: 'Offset DACL', initial_value: -> { dacl.rel_offset }
35
35
 
36
36
  string :owner_sid, label: 'Owner SID'
37
37
  string :group_sid, label: 'Group SID'
@@ -39,4 +39,4 @@ module RubySMB
39
39
  string :dacl, label: 'DACL'
40
40
  end
41
41
  end
42
- end
42
+ end