ruby_smb 2.0.9 → 2.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +5 -15
  4. data/examples/auth_capture.rb +71 -0
  5. data/examples/dump_secrets_from_sid.rb +207 -0
  6. data/examples/enum_domain_users.rb +75 -0
  7. data/examples/get_computer_info.rb +42 -0
  8. data/examples/query_service_status.rb +42 -4
  9. data/lib/ruby_smb/client/negotiation.rb +1 -1
  10. data/lib/ruby_smb/client.rb +10 -20
  11. data/lib/ruby_smb/dcerpc/bind.rb +28 -20
  12. data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
  13. data/lib/ruby_smb/dcerpc/client.rb +542 -0
  14. data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
  15. data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
  16. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
  17. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
  18. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
  19. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
  20. data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
  21. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
  22. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
  23. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
  24. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
  25. data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
  26. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
  27. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
  28. data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
  29. data/lib/ruby_smb/dcerpc/epm.rb +75 -0
  30. data/lib/ruby_smb/dcerpc/error.rb +17 -0
  31. data/lib/ruby_smb/dcerpc/ndr.rb +1159 -297
  32. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +3 -13
  33. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +3 -3
  34. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +3 -13
  35. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +1 -1
  36. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +3 -11
  37. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +1 -1
  38. data/lib/ruby_smb/dcerpc/netlogon.rb +5 -4
  39. data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
  40. data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
  41. data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
  42. data/lib/ruby_smb/dcerpc/request.rb +79 -32
  43. data/lib/ruby_smb/dcerpc/response.rb +45 -10
  44. data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
  45. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +11 -11
  46. data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
  47. data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
  48. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
  49. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
  50. data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
  51. data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
  52. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
  53. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
  54. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
  55. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
  56. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
  57. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
  58. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
  59. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
  60. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
  61. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
  62. data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
  63. data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
  64. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
  65. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
  66. data/lib/ruby_smb/dcerpc/samr.rb +613 -0
  67. data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
  68. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
  69. data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
  70. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +13 -25
  71. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +2 -2
  72. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +1 -1
  73. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +1 -1
  74. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +1 -1
  75. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +4 -14
  76. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +1 -1
  77. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +3 -11
  78. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +1 -1
  79. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +1 -1
  80. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +12 -11
  81. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +1 -1
  82. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +9 -8
  83. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +3 -3
  84. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +1 -1
  85. data/lib/ruby_smb/dcerpc/svcctl.rb +1 -3
  86. data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
  87. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
  88. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +2 -13
  89. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +3 -3
  90. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +3 -20
  91. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
  92. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
  93. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
  94. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
  95. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
  96. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +5 -6
  97. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
  98. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
  99. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -14
  100. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
  101. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
  102. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +0 -9
  103. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +1 -1
  104. data/lib/ruby_smb/dcerpc/winreg.rb +10 -14
  105. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
  106. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
  107. data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
  108. data/lib/ruby_smb/dcerpc.rb +41 -11
  109. data/lib/ruby_smb/dialect.rb +45 -0
  110. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  111. data/lib/ruby_smb/field/file_time.rb +1 -1
  112. data/lib/ruby_smb/field/string16.rb +5 -1
  113. data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
  114. data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
  115. data/lib/ruby_smb/gss/provider.rb +35 -0
  116. data/lib/ruby_smb/gss.rb +56 -63
  117. data/lib/ruby_smb/ntlm.rb +61 -0
  118. data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
  119. data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
  120. data/lib/ruby_smb/server/server_client.rb +162 -0
  121. data/lib/ruby_smb/server.rb +54 -0
  122. data/lib/ruby_smb/signing.rb +59 -0
  123. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
  124. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
  125. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  126. data/lib/ruby_smb/smb1/pipe.rb +4 -0
  127. data/lib/ruby_smb/smb1/tree.rb +1 -1
  128. data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
  129. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  130. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  131. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  132. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  133. data/lib/ruby_smb/smb2/pipe.rb +4 -0
  134. data/lib/ruby_smb/smb2/tree.rb +1 -1
  135. data/lib/ruby_smb/smb2.rb +3 -1
  136. data/lib/ruby_smb/version.rb +1 -1
  137. data/lib/ruby_smb.rb +2 -1
  138. data/spec/lib/ruby_smb/client_spec.rb +8 -11
  139. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  140. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  141. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  142. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  143. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3792 -1373
  144. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +4 -4
  145. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +4 -4
  146. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +2 -2
  147. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +2 -2
  148. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  149. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  150. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  151. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  152. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  153. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +29 -28
  154. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  155. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  156. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  157. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  158. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  159. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  160. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  161. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  162. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  163. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  164. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  165. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  166. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  167. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  168. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  169. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  170. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  171. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  172. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +56 -79
  173. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +4 -4
  174. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +2 -2
  176. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +2 -2
  177. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +19 -29
  178. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +2 -2
  179. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +9 -15
  180. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +2 -2
  181. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +2 -2
  182. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +22 -22
  183. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +2 -2
  184. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +18 -14
  185. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +5 -4
  186. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +2 -2
  187. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +1 -5
  188. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  189. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  190. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +4 -41
  191. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +4 -4
  192. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -52
  193. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  194. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  195. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  196. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  197. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  198. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -25
  199. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  200. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  201. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  202. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +10 -22
  203. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  204. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +0 -12
  205. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +2 -2
  206. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +18 -47
  207. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  208. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  209. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  210. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  211. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  212. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  213. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  214. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  215. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  216. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  217. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +18 -37
  218. data/spec/lib/ruby_smb/smb1/tree_spec.rb +4 -4
  219. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  220. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +18 -16
  221. data/spec/lib/ruby_smb/smb2/tree_spec.rb +5 -5
  222. data/spec/support/bin_helper.rb +9 -0
  223. data.tar.gz.sig +2 -1
  224. metadata +119 -6
  225. metadata.gz.sig +0 -0
  226. data/lib/ruby_smb/client/signing.rb +0 -64
  227. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -38
  228. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -135
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Gss::Provider::NTLM do
4
+ let(:provider) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :allow_anonymous }
7
+ it { is_expected.to respond_to :default_domain }
8
+
9
+ describe '#initialize' do
10
+ it 'defaults to false for allowing anonymous access' do
11
+ expect(provider.allow_anonymous).to be false
12
+ end
13
+
14
+ it 'defaults to a default domain of WORKGROUP' do
15
+ expect(provider.default_domain).to eq 'WORKGROUP'
16
+ end
17
+
18
+ it 'defaults to a random challenge generator' do
19
+ expect(provider.generate_server_challenge).to_not eq provider.generate_server_challenge
20
+ end
21
+ end
22
+
23
+ describe '#generate_server_challenge' do
24
+ it 'generates a valid 8-byte challenge' do
25
+ challenge = provider.generate_server_challenge
26
+ expect(challenge).to be_a String
27
+ expect(challenge.length).to eq 8
28
+ end
29
+
30
+ it 'should take a generator block' do
31
+ random_challenge = Random.new.bytes(8)
32
+ provider.generate_server_challenge do
33
+ random_challenge
34
+ end
35
+ expect(provider.generate_server_challenge).to eq random_challenge
36
+ end
37
+ end
38
+
39
+ describe '#get_account' do
40
+ let(:username) { 'RubySMB' }
41
+ let(:password) { 'password' }
42
+ let(:domain) { 'WORKGROUP' }
43
+
44
+ context 'when getting accounts' do
45
+ before(:each) do
46
+ provider.put_account(username, password)
47
+ end
48
+
49
+ it 'should return nil for an unknown account' do
50
+ account = provider.get_account('Spencer')
51
+ expect(account).to be_nil
52
+ end
53
+
54
+ it 'should work with a case sensitive name' do
55
+ account = provider.get_account(username)
56
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
57
+ expect(account.username).to eq username
58
+ end
59
+
60
+ it 'should work with a case insensitive name' do
61
+ account = provider.get_account(username.downcase)
62
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
63
+ expect(account.username).to eq username
64
+ end
65
+
66
+ it 'should work with a case sensitive domain' do
67
+ account = provider.get_account(username, domain: domain)
68
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
69
+ expect(account.domain).to eq domain
70
+ end
71
+
72
+ it 'should work with a case insensitive domain' do
73
+ account = provider.get_account(username, domain: domain.downcase)
74
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
75
+ expect(account.domain).to eq domain
76
+ end
77
+
78
+ it 'should work with the special . domain' do
79
+ account = provider.get_account(username, domain: '.')
80
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
81
+ expect(account.domain).to eq domain
82
+ end
83
+
84
+ # UTF-16LE is optionally used for encoding some Net-NTLM message fields, the #get_account method should handle it
85
+ # transparently
86
+ it 'should work with a UTF16-LE name' do
87
+ account = provider.get_account(username.encode('UTF-16LE'))
88
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
89
+ expect(account.username).to eq username
90
+ end
91
+
92
+ it 'should work with a UTF16-LE domain' do
93
+ account = provider.get_account(username, domain: domain.encode('UTF-16LE'))
94
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
95
+ expect(account.domain).to eq domain
96
+ end
97
+ end
98
+
99
+ context 'when putting accounts' do
100
+ it 'should accept new accounts with the default domain' do
101
+ provider.put_account(username, password)
102
+ end
103
+
104
+ after(:each) do
105
+ account = provider.get_account(username, domain: domain)
106
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
107
+ expect(account.username).to eq username
108
+ expect(account.password).to eq password
109
+ expect(account.domain).to eq domain
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,156 @@
1
+ RSpec.describe RubySMB::Server::ServerClient do
2
+ let(:server) { RubySMB::Server.new(server_sock: ::TCPServer.new(0)) }
3
+ let(:sock) { double('Socket', peeraddr: '192.168.1.5') }
4
+ let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
5
+ subject(:server_client) { described_class.new(server, dispatcher) }
6
+
7
+ it { is_expected.to respond_to :dialect }
8
+ it { is_expected.to respond_to :identity }
9
+ it { is_expected.to respond_to :state }
10
+ it { is_expected.to respond_to :session_key }
11
+
12
+ describe '#disconnect!' do
13
+ it 'closes the socket' do
14
+ expect(dispatcher.tcp_socket).to receive(:close).with(no_args).and_return(nil)
15
+ server_client.disconnect!
16
+ end
17
+ end
18
+
19
+ describe '#initialize' do
20
+ it 'starts in the negotiate state' do
21
+ expect(server_client.state).to eq :negotiate
22
+ end
23
+
24
+ it 'starts without a dialect' do
25
+ expect(server_client.dialect).to be_nil
26
+ expect(server_client.metadialect).to be_nil
27
+ end
28
+
29
+ it 'starts without an identity' do
30
+ expect(server_client.identity).to be_nil
31
+ end
32
+
33
+ it 'starts without a session_key' do
34
+ expect(server_client.session_key).to be_nil
35
+ end
36
+
37
+ it 'creates a new authenticator instance' do
38
+ expect(server.gss_provider).to receive(:new_authenticator).and_call_original
39
+ described_class.new(server, dispatcher)
40
+ end
41
+ end
42
+
43
+ describe '#process_gss' do
44
+ before(:each) do
45
+ expect(server_client.instance_eval { @gss_authenticator }).to receive(:process).and_call_original
46
+ end
47
+
48
+ it 'should handle an empty GSS buffer' do
49
+ result = server_client.process_gss
50
+ expect(result).to be_a RubySMB::Gss::Provider::Result
51
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
52
+ expect(result.buffer).to_not be_empty
53
+ expect(result.identity).to be_nil
54
+ end
55
+ end
56
+
57
+ describe '#recv_packet' do
58
+ it 'receives a new packet from the dispatcher' do
59
+ expect(dispatcher).to receive(:recv_packet).with(no_args)
60
+ server_client.recv_packet
61
+ end
62
+ end
63
+
64
+ describe '#run' do
65
+ let(:packet) { Random.new.bytes(16) }
66
+ before(:each) do
67
+ expect(server_client).to receive(:recv_packet).and_return(packet)
68
+ # this hook should ensure that the dispatcher loop returns after processing a single request
69
+ expect(dispatcher.tcp_socket).to receive(:closed?).and_return(true)
70
+ end
71
+
72
+ it 'calls #handle_negotiate when the state is negotiate' do
73
+ expect(server_client).to receive(:handle_negotiate).with(packet).and_return(nil)
74
+ server_client.instance_eval { @state = :negotiate }
75
+ server_client.run
76
+ end
77
+
78
+ it 'calls #handle_session_setup when the state is session_setup' do
79
+ expect(server_client).to receive(:handle_session_setup).with(packet).and_return(nil)
80
+ server_client.instance_eval { @state = :session_setup }
81
+ server_client.run
82
+ end
83
+
84
+ it 'calls #authenticated when the state is authenticated' do
85
+ expect(server_client).to receive(:handle_authenticated).with(packet).and_return(nil)
86
+ server_client.instance_eval { @state = :authenticated }
87
+ server_client.run
88
+ end
89
+ end
90
+
91
+ describe '#send_packet' do
92
+ let(:packet) { RubySMB::GenericPacket.new }
93
+
94
+ before(:each) do
95
+ expect(dispatcher).to receive(:send_packet).with(packet).and_return(nil)
96
+ end
97
+
98
+ it 'sends a packet to the dispatcher' do
99
+ server_client.send_packet(packet)
100
+ end
101
+
102
+ %w{ 0x0202 0x0210 0x0300 0x0302 0x0311 }.each do |dialect|
103
+ context "when the dialect is #{dialect}" do
104
+ before(:each) do
105
+ server_client.instance_eval { @dialect = dialect }
106
+ end
107
+
108
+ context 'and the state is authenticated' do
109
+ before(:each) do
110
+ server_client.instance_eval { @state = :authenticated }
111
+ end
112
+
113
+ context 'and the identity is anonymous' do
114
+ before(:each) do
115
+ server_client.instance_eval { @identity = RubySMB::Gss::Provider::IDENTITY_ANONYMOUS }
116
+ end
117
+
118
+ it 'does not sign packets' do
119
+ expect(server_client).to_not receive(:smb2_sign)
120
+ expect(server_client).to_not receive(:smb3_sign)
121
+ server_client.send_packet(packet)
122
+ end
123
+ end
124
+
125
+ context 'and the identity is not anonymous' do
126
+ before(:each) do
127
+ server_client.instance_eval { @identity = 'WORKGROUP\RubySMB'; @session_key = Random.new.bytes(16) }
128
+ end
129
+
130
+ it 'does sign packets' do
131
+ packet = RubySMB::GenericPacket.new
132
+ dialect_family = RubySMB::Dialect[dialect].family
133
+ if dialect_family == RubySMB::Dialect::FAMILY_SMB2
134
+ expect(server_client).to receive(:smb2_sign).with(packet).and_return(packet)
135
+ expect(server_client).to_not receive(:smb3_sign)
136
+ elsif dialect_family == RubySMB::Dialect::FAMILY_SMB3
137
+ expect(server_client).to receive(:smb3_sign).with(packet).and_return(packet)
138
+ expect(server_client).to_not receive(:smb2_sign)
139
+ end
140
+ server_client.send_packet(packet)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ describe '#update_preauth_hash' do
149
+ it 'raises an EncryptionError exception if the preauth integrity hash algorithm is not known' do
150
+ expect { server_client.update_preauth_hash('Test') }.to raise_error(
151
+ RubySMB::Error::EncryptionError,
152
+ 'Cannot compute the Preauth Integrity Hash value: Preauth Integrity Hash Algorithm is nil'
153
+ )
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Server do
2
+ before(:each) do
3
+ allow(::TCPServer).to receive(:new).and_return(::TCPServer.new(0))
4
+ end
5
+
6
+ it { is_expected.to respond_to :dialects }
7
+ it { is_expected.to respond_to :gss_provider }
8
+ it { is_expected.to respond_to :guid }
9
+
10
+ describe '#initialize' do
11
+ it 'should bind to TCP port 445 by default' do
12
+ expect(::TCPServer).to receive(:new).with(445).and_return(::TCPServer.new(0))
13
+ described_class.new
14
+ end
15
+
16
+ it 'should create a new NTLM GSS provider by default' do
17
+ expect(RubySMB::Gss::Provider::NTLM).to receive(:new).and_call_original
18
+ described_class.new
19
+ end
20
+
21
+ it 'should generate a random 16-byte GUID' do
22
+ server_guid = described_class.new.guid
23
+ expect(server_guid).to be_a String
24
+ expect(server_guid.length).to eq 16
25
+ expect(server_guid).to_not eq described_class.new.guid
26
+ end
27
+
28
+ it 'should support some dialects' do
29
+ expect(described_class.new.dialects).to_not be_empty
30
+ end
31
+ end
32
+ end
@@ -140,45 +140,26 @@ RSpec.describe RubySMB::SMB1::Pipe do
140
140
  expect(pipe.size_on_disk).to eq(nt_create_andx_response.parameter_block.allocation_size)
141
141
  end
142
142
 
143
- context 'with \'srvsvc\' filename' do
144
- it 'extends Srvsvc class' do
145
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'srvsvc')
146
- expect(pipe.respond_to?(:net_share_enum_all)).to be true
147
- end
148
- end
149
-
150
- context 'with \'\\srvsvc\' filename' do
151
- it 'extends Srvsvc class' do
152
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\srvsvc')
153
- expect(pipe.respond_to?(:net_share_enum_all)).to be true
154
- end
155
- end
156
-
157
- context 'with \'winreg\' filename' do
158
- it 'extends Winreg class' do
159
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'winreg')
160
- expect(pipe.respond_to?(:has_registry_key?)).to be true
161
- end
162
- end
163
-
164
- context 'with \'\\winreg\' filename' do
165
- it 'extends Winreg class' do
166
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\winreg')
167
- expect(pipe.respond_to?(:has_registry_key?)).to be true
168
- end
169
- end
170
-
171
- context 'with \'svcctl\' filename' do
172
- it 'extends svcctl class' do
173
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'svcctl')
174
- expect(pipe.respond_to?(:query_service_config)).to be true
143
+ {
144
+ netlogon: RubySMB::Dcerpc::Netlogon,
145
+ srvsvc: RubySMB::Dcerpc::Srvsvc,
146
+ svcctl: RubySMB::Dcerpc::Svcctl,
147
+ winreg: RubySMB::Dcerpc::Winreg,
148
+ samr: RubySMB::Dcerpc::Samr,
149
+ wkssvc: RubySMB::Dcerpc::Wkssvc
150
+ }.each do |endpoint, klass|
151
+ context "with \'#{endpoint}\' filename" do
152
+ it "extends #{klass} class" do
153
+ pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: endpoint.to_s)
154
+ expect(pipe).to be_a klass
155
+ end
175
156
  end
176
- end
177
157
 
178
- context 'with \'\\svcctl\' filename' do
179
- it 'extends svcctl class' do
180
- pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\svcctl')
181
- expect(pipe.respond_to?(:query_service_config)).to be true
158
+ context "with \'\\#{endpoint}\' filename" do
159
+ it "extends #{klass} class" do
160
+ pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: "\\#{endpoint.to_s}")
161
+ expect(pipe).to be_a klass
162
+ end
182
163
  end
183
164
  end
184
165
  end
@@ -501,16 +501,16 @@ RSpec.describe RubySMB::SMB1::Tree do
501
501
  it 'calls #open_file with the provided options' do
502
502
  opts[:filename] ='\\test'
503
503
  expect(tree).to receive(:open_file).with(opts)
504
- tree.open_pipe(opts)
504
+ tree.open_pipe(**opts)
505
505
  end
506
506
 
507
507
  it 'prepends the filename with \\ if needed' do
508
- expect(tree).to receive(:open_file).with( { filename: '\\test', write: true } )
509
- tree.open_pipe(opts)
508
+ expect(tree).to receive(:open_file).with(filename: '\\test', write: true)
509
+ tree.open_pipe(**opts)
510
510
  end
511
511
 
512
512
  it 'does not modify the original option hash' do
513
- tree.open_pipe(opts)
513
+ tree.open_pipe(**opts)
514
514
  expect(opts).to eq( { filename: 'test', write: true } )
515
515
  end
516
516
  end
@@ -162,7 +162,7 @@ RSpec.describe RubySMB::SMB2::CompressionCapabilities do
162
162
  end
163
163
  end
164
164
 
165
- RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
165
+ RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
166
166
  subject(:capability) { described_class.new }
167
167
 
168
168
  it { is_expected.to respond_to :net_name }
@@ -173,7 +173,7 @@ RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
173
173
 
174
174
  describe '#net_name' do
175
175
  it 'is a unicode string' do
176
- expect(capability.net_name).to be_a RubySMB::Field::Stringz16
176
+ expect(capability.net_name).to be_a RubySMB::Field::String16
177
177
  end
178
178
  end
179
179
 
@@ -146,24 +146,26 @@ RSpec.describe RubySMB::SMB2::Pipe do
146
146
  expect(pipe.size_on_disk).to eq(create_response.allocation_size)
147
147
  end
148
148
 
149
- context 'with \'srvsvc\' filename' do
150
- it 'extends Srvsvc class' do
151
- pipe = described_class.new(tree: tree, response: create_response, name: 'srvsvc')
152
- expect(pipe.respond_to?(:net_share_enum_all)).to be true
153
- end
154
- end
155
-
156
- context 'with \'winreg\' filename' do
157
- it 'extends Winreg class' do
158
- pipe = described_class.new(tree: tree, response: create_response, name: 'winreg')
159
- expect(pipe.respond_to?(:has_registry_key?)).to be true
149
+ {
150
+ netlogon: RubySMB::Dcerpc::Netlogon,
151
+ srvsvc: RubySMB::Dcerpc::Srvsvc,
152
+ svcctl: RubySMB::Dcerpc::Svcctl,
153
+ winreg: RubySMB::Dcerpc::Winreg,
154
+ samr: RubySMB::Dcerpc::Samr,
155
+ wkssvc: RubySMB::Dcerpc::Wkssvc
156
+ }.each do |endpoint, klass|
157
+ context "with \'#{endpoint}\' filename" do
158
+ it "extends #{klass} class" do
159
+ pipe = described_class.new(tree: tree, response: create_response, name: endpoint.to_s)
160
+ expect(pipe).to be_a klass
161
+ end
160
162
  end
161
- end
162
163
 
163
- context 'with \'svcctl\' filename' do
164
- it 'extends svcctl class' do
165
- pipe = described_class.new(tree: tree, response: create_response, name: 'svcctl')
166
- expect(pipe.respond_to?(:query_service_config)).to be true
164
+ context "with \'\\#{endpoint}\' filename" do
165
+ it "extends #{klass} class" do
166
+ pipe = described_class.new(tree: tree, response: create_response, name: "\\#{endpoint.to_s}")
167
+ expect(pipe).to be_a klass
168
+ end
167
169
  end
168
170
  end
169
171
  end
@@ -540,17 +540,17 @@ RSpec.describe RubySMB::SMB2::Tree do
540
540
 
541
541
  it 'calls #open_file with the provided options' do
542
542
  opts[:filename] ='test'
543
- expect(tree).to receive(:open_file).with(opts)
544
- tree.open_pipe(opts)
543
+ expect(tree).to receive(:open_file).with(**opts)
544
+ tree.open_pipe(**opts)
545
545
  end
546
546
 
547
547
  it 'remove the leading \\ from the filename if needed' do
548
- expect(tree).to receive(:open_file).with( { filename: 'test', write: true } )
549
- tree.open_pipe(opts)
548
+ expect(tree).to receive(:open_file).with(filename: 'test', write: true)
549
+ tree.open_pipe(**opts)
550
550
  end
551
551
 
552
552
  it 'does not modify the original option hash' do
553
- tree.open_pipe(opts)
553
+ tree.open_pipe(**opts)
554
554
  expect(opts).to eq( { filename: '\\test', write: true } )
555
555
  end
556
556
  end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def hexlify
3
+ self.b.bytes.map {|c| "%02x" % c.ord}.join
4
+ end
5
+
6
+ def unhexlify
7
+ self.chars.each_slice(2).map {|c| c.join.to_i(16).chr}.join
8
+ end
9
+ end
data.tar.gz.sig CHANGED
@@ -1 +1,2 @@
1
- v�����򊩟l�Ek�~����HQ��H����XK��`�[����Ȇ N�p�@�ڎ�jϑ*����
1
+ ��B����:��8i��Jis��\���x:�����1��~vk4ܧ�8H�j(�S��M� �����O��iísF�.�i����9qhK-��|.k*�����HdP���W?z��v���M_qk-Ic�����(w�<J����K �|��ۺ� �M�v�<�1�o�ZSR_(���R�������0�n��5‰� �E�l,:\�9{���6����5�����*sa%U�D�\S7hōu�nx���歒ӛ�6
2
+ :�q�k