ruby_smb 2.0.10 → 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 (224) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +5 -16
  4. data/examples/auth_capture.rb +71 -0
  5. data/examples/dump_secrets_from_sid.rb +207 -0
  6. data/examples/enum_domain_users.rb +75 -0
  7. data/examples/get_computer_info.rb +42 -0
  8. data/examples/query_service_status.rb +42 -4
  9. data/lib/ruby_smb/client/negotiation.rb +1 -1
  10. data/lib/ruby_smb/client.rb +10 -20
  11. data/lib/ruby_smb/dcerpc/bind.rb +28 -20
  12. data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
  13. data/lib/ruby_smb/dcerpc/client.rb +542 -0
  14. data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
  15. data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
  16. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
  17. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
  18. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
  19. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
  20. data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
  21. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
  22. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
  23. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
  24. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
  25. data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
  26. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
  27. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
  28. data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
  29. data/lib/ruby_smb/dcerpc/epm.rb +75 -0
  30. data/lib/ruby_smb/dcerpc/error.rb +17 -0
  31. data/lib/ruby_smb/dcerpc/ndr.rb +1159 -297
  32. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +3 -13
  33. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +3 -3
  34. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +3 -13
  35. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +1 -1
  36. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +3 -11
  37. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +1 -1
  38. data/lib/ruby_smb/dcerpc/netlogon.rb +5 -4
  39. data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
  40. data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
  41. data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
  42. data/lib/ruby_smb/dcerpc/request.rb +79 -32
  43. data/lib/ruby_smb/dcerpc/response.rb +45 -10
  44. data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
  45. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +11 -11
  46. data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
  47. data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
  48. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
  49. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
  50. data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
  51. data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
  52. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
  53. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
  54. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
  55. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
  56. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
  57. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
  58. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
  59. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
  60. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
  61. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
  62. data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
  63. data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
  64. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
  65. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
  66. data/lib/ruby_smb/dcerpc/samr.rb +613 -0
  67. data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
  68. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
  69. data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
  70. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +13 -25
  71. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +2 -2
  72. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +1 -1
  73. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +1 -1
  74. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +1 -1
  75. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +4 -14
  76. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +1 -1
  77. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +3 -11
  78. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +1 -1
  79. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +1 -1
  80. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +12 -11
  81. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +1 -1
  82. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +9 -8
  83. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +3 -3
  84. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +1 -1
  85. data/lib/ruby_smb/dcerpc/svcctl.rb +1 -3
  86. data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
  87. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
  88. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +2 -13
  89. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +3 -3
  90. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +3 -20
  91. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
  92. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
  93. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
  94. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
  95. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
  96. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +5 -6
  97. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
  98. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
  99. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -14
  100. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
  101. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
  102. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +0 -9
  103. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +1 -1
  104. data/lib/ruby_smb/dcerpc/winreg.rb +10 -14
  105. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
  106. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
  107. data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
  108. data/lib/ruby_smb/dcerpc.rb +41 -11
  109. data/lib/ruby_smb/dialect.rb +45 -0
  110. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  111. data/lib/ruby_smb/field/file_time.rb +1 -1
  112. data/lib/ruby_smb/field/string16.rb +5 -1
  113. data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
  114. data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
  115. data/lib/ruby_smb/gss/provider.rb +35 -0
  116. data/lib/ruby_smb/gss.rb +56 -63
  117. data/lib/ruby_smb/ntlm.rb +61 -0
  118. data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
  119. data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
  120. data/lib/ruby_smb/server/server_client.rb +162 -0
  121. data/lib/ruby_smb/server.rb +54 -0
  122. data/lib/ruby_smb/signing.rb +59 -0
  123. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
  124. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
  125. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  126. data/lib/ruby_smb/smb1/pipe.rb +4 -0
  127. data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
  128. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  129. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  130. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  131. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  132. data/lib/ruby_smb/smb2/pipe.rb +4 -0
  133. data/lib/ruby_smb/smb2.rb +3 -1
  134. data/lib/ruby_smb/version.rb +1 -1
  135. data/lib/ruby_smb.rb +2 -1
  136. data/spec/lib/ruby_smb/client_spec.rb +8 -11
  137. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  138. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  139. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  140. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  141. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3792 -1373
  142. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +4 -4
  143. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +4 -4
  144. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +2 -2
  146. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  147. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  148. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  149. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  150. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  151. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +29 -28
  152. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  153. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  154. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  155. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  156. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  157. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  158. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  159. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  160. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  161. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  162. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  163. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  164. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  165. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  166. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  167. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  168. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  169. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  170. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +56 -79
  171. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +4 -4
  172. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +19 -29
  176. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +2 -2
  177. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +9 -15
  178. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +2 -2
  179. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +2 -2
  180. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +22 -22
  181. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +2 -2
  182. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +18 -14
  183. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +5 -4
  184. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +2 -2
  185. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +1 -5
  186. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  187. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  188. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +4 -41
  189. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +4 -4
  190. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -52
  191. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  192. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  193. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  194. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  195. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  196. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -25
  197. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  198. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  199. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  200. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +10 -22
  201. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  202. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +0 -12
  203. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +2 -2
  204. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +18 -47
  205. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  206. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  207. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  208. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  209. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  210. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  211. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  212. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  213. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  214. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  215. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +18 -37
  216. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  217. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +18 -16
  218. data/spec/support/bin_helper.rb +9 -0
  219. data.tar.gz.sig +0 -0
  220. metadata +119 -6
  221. metadata.gz.sig +0 -0
  222. data/lib/ruby_smb/client/signing.rb +0 -64
  223. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -38
  224. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -135
@@ -0,0 +1,410 @@
1
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::WkstaInfo102 do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :wki102_platform_id }
5
+ it { is_expected.to respond_to :wki102_computername }
6
+ it { is_expected.to respond_to :wki102_langroup }
7
+ it { is_expected.to respond_to :wki102_ver_major }
8
+ it { is_expected.to respond_to :wki102_ver_minor }
9
+ it { is_expected.to respond_to :wki102_lanroot }
10
+ it { is_expected.to respond_to :wki102_logged_on_users }
11
+
12
+ it 'is little endian' do
13
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
14
+ end
15
+ it 'it is a Ndr::NdrStruct' do
16
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
17
+ end
18
+ describe '#wki102_platform_id' do
19
+ it 'is a NdrUint32 structure' do
20
+ expect(packet.wki102_platform_id).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
21
+ end
22
+ end
23
+ describe '#wki102_computername' do
24
+ it 'is a Ndr::NdrWideStringzPtr' do
25
+ expect(packet.wki102_computername).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
26
+ end
27
+ end
28
+ describe '#wki102_langroup' do
29
+ it 'is a Ndr::NdrWideStringzPtr' do
30
+ expect(packet.wki102_langroup).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
31
+ end
32
+ end
33
+ describe '#wki102_ver_major' do
34
+ it 'is a NdrUint32 structure' do
35
+ expect(packet.wki102_ver_major).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
36
+ end
37
+ end
38
+ describe '#wki102_ver_minor' do
39
+ it 'is a NdrUint32 structure' do
40
+ expect(packet.wki102_ver_minor).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
41
+ end
42
+ end
43
+ describe '#wki102_lanroot' do
44
+ it 'is a Ndr::NdrWideStringzPtr' do
45
+ expect(packet.wki102_lanroot).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
46
+ end
47
+ end
48
+ describe '#wki102_logged_on_users' do
49
+ it 'is a NdrUint32 structure' do
50
+ expect(packet.wki102_logged_on_users).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
51
+ end
52
+ end
53
+ it 'reads itself' do
54
+ new_class = described_class.new(
55
+ wki102_platform_id: 500,
56
+ wki102_computername: 'MYCOMPUTER',
57
+ wki102_langroup: 'MYDOMAIN',
58
+ wki102_ver_major: 6,
59
+ wki102_ver_minor: 2,
60
+ wki102_lanroot: 'MYLANROOT',
61
+ wki102_logged_on_users: 4,
62
+ )
63
+ expect(packet.read(new_class.to_binary_s)).to eq(
64
+ {
65
+ wki102_platform_id: 500,
66
+ wki102_computername: 'MYCOMPUTER'.encode('utf-16le'),
67
+ wki102_langroup: 'MYDOMAIN'.encode('utf-16le'),
68
+ wki102_ver_major: 6,
69
+ wki102_ver_minor: 2,
70
+ wki102_lanroot: 'MYLANROOT'.encode('utf-16le'),
71
+ wki102_logged_on_users: 4,
72
+ }
73
+ )
74
+ end
75
+ end
76
+
77
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::PwkstaInfo102 do
78
+ subject(:packet) { described_class.new }
79
+
80
+ it 'is a WkstaInfo102' do
81
+ expect(packet).to be_a(RubySMB::Dcerpc::Wkssvc::WkstaInfo102)
82
+ end
83
+ it 'is a NDR Pointer' do
84
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
85
+ end
86
+ it 'reads itself' do
87
+ new_class = described_class.new(
88
+ wki102_platform_id: 500,
89
+ wki102_computername: 'MYCOMPUTER',
90
+ wki102_langroup: 'MYDOMAIN',
91
+ wki102_ver_major: 6,
92
+ wki102_ver_minor: 2,
93
+ wki102_lanroot: 'MYLANROOT',
94
+ wki102_logged_on_users: 4,
95
+ )
96
+ expect(packet.read(new_class.to_binary_s)).to eq(
97
+ {
98
+ wki102_platform_id: 500,
99
+ wki102_computername: 'MYCOMPUTER'.encode('utf-16le'),
100
+ wki102_langroup: 'MYDOMAIN'.encode('utf-16le'),
101
+ wki102_ver_major: 6,
102
+ wki102_ver_minor: 2,
103
+ wki102_lanroot: 'MYLANROOT'.encode('utf-16le'),
104
+ wki102_logged_on_users: 4,
105
+ }
106
+ )
107
+ end
108
+ end
109
+
110
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::WkstaInfo101 do
111
+ subject(:packet) { described_class.new }
112
+
113
+ it { is_expected.to respond_to :wki101_platform_id }
114
+ it { is_expected.to respond_to :wki101_computername }
115
+ it { is_expected.to respond_to :wki101_langroup }
116
+ it { is_expected.to respond_to :wki101_ver_major }
117
+ it { is_expected.to respond_to :wki101_ver_minor }
118
+ it { is_expected.to respond_to :wki101_lanroot }
119
+
120
+ it 'is little endian' do
121
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
122
+ end
123
+ it 'it is a Ndr::NdrStruct' do
124
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
125
+ end
126
+ describe '#wki101_platform_id' do
127
+ it 'is a NdrUint32 structure' do
128
+ expect(packet.wki101_platform_id).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
129
+ end
130
+ end
131
+ describe '#wki101_computername' do
132
+ it 'is a Ndr::NdrWideStringzPtr' do
133
+ expect(packet.wki101_computername).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
134
+ end
135
+ end
136
+ describe '#wki101_langroup' do
137
+ it 'is a Ndr::NdrWideStringzPtr' do
138
+ expect(packet.wki101_langroup).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
139
+ end
140
+ end
141
+ describe '#wki101_ver_major' do
142
+ it 'is a NdrUint32 structure' do
143
+ expect(packet.wki101_ver_major).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
144
+ end
145
+ end
146
+ describe '#wki101_ver_minor' do
147
+ it 'is a NdrUint32 structure' do
148
+ expect(packet.wki101_ver_minor).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
149
+ end
150
+ end
151
+ describe '#wki101_lanroot' do
152
+ it 'is a Ndr::NdrWideStringzPtr' do
153
+ expect(packet.wki101_lanroot).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
154
+ end
155
+ end
156
+ it 'reads itself' do
157
+ new_class = described_class.new(
158
+ wki101_platform_id: 500,
159
+ wki101_computername: 'MYCOMPUTER',
160
+ wki101_langroup: 'MYDOMAIN',
161
+ wki101_ver_major: 6,
162
+ wki101_ver_minor: 2,
163
+ wki101_lanroot: 'MYLANROOT'
164
+ )
165
+ expect(packet.read(new_class.to_binary_s)).to eq(
166
+ {
167
+ wki101_platform_id: 500,
168
+ wki101_computername: 'MYCOMPUTER'.encode('utf-16le'),
169
+ wki101_langroup: 'MYDOMAIN'.encode('utf-16le'),
170
+ wki101_ver_major: 6,
171
+ wki101_ver_minor: 2,
172
+ wki101_lanroot: 'MYLANROOT'.encode('utf-16le')
173
+ }
174
+ )
175
+ end
176
+ end
177
+
178
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::PwkstaInfo101 do
179
+ subject(:packet) { described_class.new }
180
+
181
+ it 'is a WkstaInfo101' do
182
+ expect(packet).to be_a(RubySMB::Dcerpc::Wkssvc::WkstaInfo101)
183
+ end
184
+ it 'is a NDR Pointer' do
185
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
186
+ end
187
+ it 'reads itself' do
188
+ new_class = described_class.new(
189
+ wki101_platform_id: 500,
190
+ wki101_computername: 'MYCOMPUTER',
191
+ wki101_langroup: 'MYDOMAIN',
192
+ wki101_ver_major: 6,
193
+ wki101_ver_minor: 2,
194
+ wki101_lanroot: 'MYLANROOT'
195
+ )
196
+ expect(packet.read(new_class.to_binary_s)).to eq(
197
+ {
198
+ wki101_platform_id: 500,
199
+ wki101_computername: 'MYCOMPUTER'.encode('utf-16le'),
200
+ wki101_langroup: 'MYDOMAIN'.encode('utf-16le'),
201
+ wki101_ver_major: 6,
202
+ wki101_ver_minor: 2,
203
+ wki101_lanroot: 'MYLANROOT'.encode('utf-16le')
204
+ }
205
+ )
206
+ end
207
+ end
208
+
209
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::WkstaInfo100 do
210
+ subject(:packet) { described_class.new }
211
+
212
+ it { is_expected.to respond_to :wki100_platform_id }
213
+ it { is_expected.to respond_to :wki100_computername }
214
+ it { is_expected.to respond_to :wki100_langroup }
215
+ it { is_expected.to respond_to :wki100_ver_major }
216
+ it { is_expected.to respond_to :wki100_ver_minor }
217
+
218
+ it 'is little endian' do
219
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
220
+ end
221
+ it 'it is a Ndr::NdrStruct' do
222
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
223
+ end
224
+ describe '#wki100_platform_id' do
225
+ it 'is a NdrUint32 structure' do
226
+ expect(packet.wki100_platform_id).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
227
+ end
228
+ end
229
+ describe '#wki100_computername' do
230
+ it 'is a Ndr::NdrWideStringzPtr' do
231
+ expect(packet.wki100_computername).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
232
+ end
233
+ end
234
+ describe '#wki100_langroup' do
235
+ it 'is a Ndr::NdrWideStringzPtr' do
236
+ expect(packet.wki100_langroup).to be_a(RubySMB::Dcerpc::Ndr::NdrWideStringzPtr)
237
+ end
238
+ end
239
+ describe '#wki100_ver_major' do
240
+ it 'is a NdrUint32 structure' do
241
+ expect(packet.wki100_ver_major).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
242
+ end
243
+ end
244
+ describe '#wki100_ver_minor' do
245
+ it 'is a NdrUint32 structure' do
246
+ expect(packet.wki100_ver_minor).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
247
+ end
248
+ end
249
+
250
+ it 'reads itself' do
251
+ new_class = described_class.new(
252
+ wki100_platform_id: 500,
253
+ wki100_computername: 'MYCOMPUTER',
254
+ wki100_langroup: 'MYDOMAIN',
255
+ wki100_ver_major: 6,
256
+ wki100_ver_minor: 2
257
+ )
258
+ expect(packet.read(new_class.to_binary_s)).to eq(
259
+ {
260
+ wki100_platform_id: 500,
261
+ wki100_computername: 'MYCOMPUTER'.encode('utf-16le'),
262
+ wki100_langroup: 'MYDOMAIN'.encode('utf-16le'),
263
+ wki100_ver_major: 6,
264
+ wki100_ver_minor: 2
265
+ }
266
+ )
267
+ end
268
+ end
269
+
270
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::PwkstaInfo100 do
271
+ subject(:packet) { described_class.new }
272
+
273
+ it 'is a WkstaInfo100' do
274
+ expect(packet).to be_a(RubySMB::Dcerpc::Wkssvc::WkstaInfo100)
275
+ end
276
+ it 'is a NDR Pointer' do
277
+ expect(described_class).to be_a(RubySMB::Dcerpc::Ndr::PointerClassPlugin)
278
+ end
279
+ it 'reads itself' do
280
+ new_class = described_class.new(
281
+ wki100_platform_id: 500,
282
+ wki100_computername: 'MYCOMPUTER',
283
+ wki100_langroup: 'MYDOMAIN',
284
+ wki100_ver_major: 6,
285
+ wki100_ver_minor: 2
286
+ )
287
+ expect(packet.read(new_class.to_binary_s)).to eq(
288
+ {
289
+ wki100_platform_id: 500,
290
+ wki100_computername: 'MYCOMPUTER'.encode('utf-16le'),
291
+ wki100_langroup: 'MYDOMAIN'.encode('utf-16le'),
292
+ wki100_ver_major: 6,
293
+ wki100_ver_minor: 2
294
+ }
295
+ )
296
+ end
297
+ end
298
+
299
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::LpwkstaInfo do
300
+ subject(:packet) { described_class.new }
301
+
302
+ it { is_expected.to respond_to :level }
303
+ it { is_expected.to respond_to :info }
304
+
305
+ it 'is little endian' do
306
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
307
+ end
308
+ it 'it is a Ndr::NdrStruct' do
309
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrStruct
310
+ end
311
+ describe '#level' do
312
+ it 'is a NdrUint32 structure' do
313
+ expect(packet.level).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
314
+ end
315
+ end
316
+ describe '#info' do
317
+ it 'is a BinData:Choice structure' do
318
+ expect(packet.info).to be_a BinData::Choice
319
+ end
320
+ it 'selects a structure according to :level value' do
321
+ packet.level = RubySMB::Dcerpc::Wkssvc::WKSTA_INFO_100
322
+ expect(packet.info.send(:current_choice)).to be_a(RubySMB::Dcerpc::Wkssvc::WkstaInfo100)
323
+ end
324
+ end
325
+ it 'reads itself' do
326
+ new_class = described_class.new(
327
+ level: RubySMB::Dcerpc::Wkssvc::WKSTA_INFO_100,
328
+ info: {
329
+ wki100_platform_id: 500,
330
+ wki100_computername: 'MYCOMPUTER',
331
+ wki100_langroup: 'MYDOMAIN',
332
+ wki100_ver_major: 6,
333
+ wki100_ver_minor: 2
334
+ }
335
+ )
336
+ expect(packet.read(new_class.to_binary_s)).to eq(
337
+ {
338
+ level: RubySMB::Dcerpc::Wkssvc::WKSTA_INFO_100,
339
+ info: {
340
+ wki100_platform_id: 500,
341
+ wki100_computername: 'MYCOMPUTER'.encode('utf-16le'),
342
+ wki100_langroup: 'MYDOMAIN'.encode('utf-16le'),
343
+ wki100_ver_major: 6,
344
+ wki100_ver_minor: 2
345
+ }
346
+ }
347
+ )
348
+ end
349
+ end
350
+
351
+ RSpec.describe RubySMB::Dcerpc::Wkssvc::NetrWkstaGetInfoResponse do
352
+ subject(:packet) { described_class.new }
353
+
354
+ it { is_expected.to respond_to :wksta_info }
355
+ it { is_expected.to respond_to :error_status }
356
+ it { is_expected.to respond_to :opnum }
357
+
358
+ it 'is little endian' do
359
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
360
+ end
361
+ it 'is a BinData::Record' do
362
+ expect(packet).to be_a(BinData::Record)
363
+ end
364
+ describe '#wksta_info' do
365
+ it 'is a LpwkstaInfo structure' do
366
+ expect(packet.wksta_info).to be_a RubySMB::Dcerpc::Wkssvc::LpwkstaInfo
367
+ end
368
+ end
369
+ describe '#error_status' do
370
+ it 'is a NdrUint32 structure' do
371
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
372
+ end
373
+ end
374
+ describe '#initialize_instance' do
375
+ it 'sets #opnum to NETR_WKSTA_GET_INFO constant' do
376
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Wkssvc::NETR_WKSTA_GET_INFO)
377
+ end
378
+ end
379
+ it 'reads itself' do
380
+ new_class = described_class.new(
381
+ wksta_info: {
382
+ level: RubySMB::Dcerpc::Wkssvc::WKSTA_INFO_100,
383
+ info: {
384
+ wki100_platform_id: 500,
385
+ wki100_computername: 'MYCOMPUTER',
386
+ wki100_langroup: 'MYDOMAIN',
387
+ wki100_ver_major: 6,
388
+ wki100_ver_minor: 2
389
+ }
390
+ },
391
+ error_status: 0
392
+ )
393
+ expect(packet.read(new_class.to_binary_s)).to eq(
394
+ {
395
+ wksta_info: {
396
+ level: RubySMB::Dcerpc::Wkssvc::WKSTA_INFO_100,
397
+ info: {
398
+ wki100_platform_id: 500,
399
+ wki100_computername: 'MYCOMPUTER'.encode('utf-16le'),
400
+ wki100_langroup: 'MYDOMAIN'.encode('utf-16le'),
401
+ wki100_ver_major: 6,
402
+ wki100_ver_minor: 2
403
+ }
404
+ },
405
+ error_status: 0
406
+ }
407
+ )
408
+ end
409
+ end
410
+
@@ -0,0 +1,70 @@
1
+ RSpec.describe RubySMB::Dcerpc::Wkssvc do
2
+ let(:wkssvc) do
3
+ RubySMB::SMB1::Pipe.new(
4
+ tree: double('Tree'),
5
+ response: RubySMB::SMB1::Packet::NtCreateAndxResponse.new,
6
+ name: 'wkssvc'
7
+ )
8
+ end
9
+
10
+ describe '#netr_wksta_get_info' do
11
+ let(:wkst_netr_wksta_get_info_request) { double('NetrWkstaGetInfoRequest') }
12
+ let(:response) { double('Response') }
13
+ let(:wkst_netr_wksta_get_info_response) { double('NetrWkstaGetInfoResponse') }
14
+ let(:info) { double('info') }
15
+ before :example do
16
+ allow(described_class::NetrWkstaGetInfoRequest).to receive(:new).and_return(wkst_netr_wksta_get_info_request)
17
+ allow(wkssvc).to receive(:dcerpc_request).and_return(response)
18
+ allow(described_class::NetrWkstaGetInfoResponse).to receive(:read).and_return(wkst_netr_wksta_get_info_response)
19
+ allow(wkst_netr_wksta_get_info_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
20
+ allow(wkst_netr_wksta_get_info_response).to receive_message_chain(:wksta_info, :info => info)
21
+ end
22
+
23
+ it 'sets the request with the expected values' do
24
+ wkssvc.netr_wksta_get_info
25
+ expect(described_class::NetrWkstaGetInfoRequest).to have_received(:new).with(
26
+ server_name: "\x00",
27
+ level: described_class::WKSTA_INFO_100
28
+ )
29
+ end
30
+ it 'send the expected request structure' do
31
+ wkssvc.netr_wksta_get_info
32
+ expect(wkssvc).to have_received(:dcerpc_request).with(wkst_netr_wksta_get_info_request)
33
+ end
34
+ context 'when an IOError occurs while parsing the response' do
35
+ it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
36
+ allow(described_class::NetrWkstaGetInfoResponse).to receive(:read).and_raise(IOError)
37
+ expect { wkssvc.netr_wksta_get_info }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
38
+ end
39
+ end
40
+ context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
41
+ it 'raises a RubySMB::Dcerpc::Error::WinregError' do
42
+ allow(wkst_netr_wksta_get_info_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
43
+ expect { wkssvc.netr_wksta_get_info }.to raise_error(RubySMB::Dcerpc::Error::WkssvcError)
44
+ end
45
+ end
46
+ it 'returns the expected handler' do
47
+ expect(wkssvc.netr_wksta_get_info).to eq(info)
48
+ end
49
+ context 'with a real binary stream' do
50
+ it 'returns the expected value' do
51
+ raw_response =
52
+ "d\x00\x00\x00\x00\x00\x02\x00\xF4\x01\x00\x00\x04\x00\x02\x00\b"\
53
+ "\x00\x02\x00\x06\x00\x00\x00\x02\x00\x00\x00\x0F\x00\x00\x00\x00"\
54
+ "\x00\x00\x00\x0F\x00\x00\x00W\x00I\x00N\x00-\x00A\x00B\x00C\x00D"\
55
+ "\x00E\x00F\x00C\x007\x006\x008\x00\x00\x00\x00\x00\x06\x00\x00"\
56
+ "\x00\x00\x00\x00\x00\x06\x00\x00\x00M\x00Y\x00L\x00A\x00B\x00\x00"\
57
+ "\x00\x00\x00\x00\x00"
58
+ allow(wkssvc).to receive(:dcerpc_request).and_return(raw_response)
59
+ allow(described_class::NetrWkstaGetInfoResponse).to receive(:read).and_call_original
60
+ expect(wkssvc.netr_wksta_get_info).to eq({
61
+ wki100_platform_id: 500,
62
+ wki100_computername: "WIN-ABCDEFC768".encode('utf-16le'),
63
+ wki100_langroup: "MYLAB".encode('utf-16le'),
64
+ wki100_ver_major: 6,
65
+ wki100_ver_minor: 2
66
+ })
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ RSpec.describe RubySMB::Field::String16 do
2
+ subject(:field) { described_class.new }
3
+
4
+ it 'is a BinData::String' do
5
+ expect(field).to be_a BinData::String
6
+ end
7
+
8
+ it 'converts to utf-16le when assigning a String' do
9
+ expect(field.assign('Test'.encode('ASCII-8BIT')).encoding).to be Encoding::UTF_16LE
10
+ end
11
+
12
+ it 'makes sure snapshot returns a utf-16le string' do
13
+ field.new('Test'.encode('ASCII-8BIT'))
14
+ expect(field.snapshot.encoding).to be Encoding::UTF_16LE
15
+ end
16
+
17
+ it 'makes sure read operation returns a utf-16le string' do
18
+ field.read('Test'.encode('ASCII-8BIT'))
19
+ expect(field.snapshot.encoding).to be Encoding::UTF_16LE
20
+ end
21
+
22
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::Account do
2
+ let(:username) { 'RubySMB' }
3
+ let(:password) { 'password' }
4
+ let(:domain) { 'WORKGROUP' }
5
+ subject(:account) { RubySMB::Gss::Provider::NTLM::Account.new(username, password, domain) }
6
+
7
+ it { is_expected.to respond_to :username }
8
+ it { is_expected.to respond_to :password }
9
+ it { is_expected.to respond_to :domain }
10
+
11
+ it 'sets the username correct' do
12
+ expect(account.username).to eq username
13
+ end
14
+
15
+ it 'sets the password correctly' do
16
+ expect(account.password).to eq password
17
+ end
18
+
19
+ it 'sets the domain correctly' do
20
+ expect(account.domain).to eq domain
21
+ end
22
+
23
+ describe '#to_s' do
24
+ it 'converts to a string' do
25
+ expect(account.to_s).to be_a String
26
+ end
27
+
28
+ it 'formats the username and domain correctly' do
29
+ expect(account.to_s).to eq "#{domain}\\#{username}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,101 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::Authenticator do
2
+ let(:username) { 'RubySMB' }
3
+ let(:domain) { 'WORKGROUP' }
4
+ let(:password) { 'password' }
5
+ let(:provider) { RubySMB::Gss::Provider::NTLM.new.tap { |provider| provider.put_account(username, password, domain: domain) } }
6
+ let(:authenticator) { described_class.new(provider, nil) }
7
+ let(:type1_msg) do
8
+ Net::NTLM::Message::Type1.new.tap do |msg|
9
+ msg.domain = domain
10
+ end
11
+ end
12
+ let(:type3_msg) do
13
+ Net::NTLM::Message::Type2.new.response(user: username, password: '', domain: domain)
14
+ end
15
+
16
+ describe '#initialize' do
17
+ it 'defaults to a null session key' do
18
+ expect(authenticator.session_key).to be_nil
19
+ end
20
+
21
+ it 'defaults to a null server challenge' do
22
+ expect(authenticator.server_challenge).to be_nil
23
+ end
24
+ end
25
+
26
+ describe '#process' do
27
+ it 'should handle an empty GSS buffer' do
28
+ result = authenticator.process
29
+ expect(result).to be_a RubySMB::Gss::Provider::Result
30
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
31
+ expect(result.buffer).to_not be_empty
32
+ expect(result.identity).to be_nil
33
+ end
34
+
35
+ it 'should handle an embedded NTLM type 1 message' do
36
+ expect(authenticator).to receive(:process_ntlm_type1).and_call_original
37
+ result = authenticator.process(RubySMB::Gss.gss_type1(type1_msg.serialize))
38
+ expect(result).to be_a RubySMB::Gss::Provider::Result
39
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED
40
+ expect(result.buffer).to_not be_empty
41
+ expect(result.identity).to be_nil
42
+ expect(authenticator.session_key).to be_nil
43
+ end
44
+
45
+ it 'should handle an embedded NTLM type 3 message' do
46
+ authenticator.server_challenge = Random.new.bytes(8)
47
+ expect(authenticator).to receive(:process_ntlm_type3).and_call_original
48
+ result = authenticator.process(RubySMB::Gss.gss_type3(type3_msg.serialize))
49
+ expect(result).to be_a RubySMB::Gss::Provider::Result
50
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
51
+ expect(result.buffer).to be_nil
52
+ expect(result.identity).to be_nil
53
+ expect(authenticator.session_key).to be_nil
54
+ end
55
+ end
56
+
57
+ describe '#process_ntlm_type1' do
58
+ it 'should process a NTLM type 1 message and return a type2 message' do
59
+ expect(authenticator.process_ntlm_type1(type1_msg)).to be_a Net::NTLM::Message::Type2
60
+ end
61
+ end
62
+
63
+ describe '#process_ntlm_type3' do
64
+ it 'should process a NTLM type 3 message and return an error code' do
65
+ expect(authenticator.process_ntlm_type3(type3_msg)).to be_a WindowsError::ErrorCode
66
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
67
+ end
68
+ end
69
+
70
+ describe '#reset!' do
71
+ it 'should clear the server challenge' do
72
+ authenticator.instance_variable_set(:@server_challenge, Random.new.bytes(8))
73
+ authenticator.reset!
74
+ expect(authenticator.instance_variable_get(:@server_challenge)).to be_nil
75
+ end
76
+
77
+ it 'should clear the session key' do
78
+ authenticator.instance_variable_set(:@session_key, Random.new.bytes(16))
79
+ authenticator.reset!
80
+ expect(authenticator.instance_variable_get(:@session_key)).to be_nil
81
+ end
82
+ end
83
+
84
+ describe 'a full Net-NTLMv2 authentication exchange' do
85
+ let(:type2_msg) { authenticator.process_ntlm_type1(type1_msg)}
86
+
87
+ it 'should respond to a correct password with STATUS_SUCCESS' do
88
+ type3_msg = type2_msg.response({user: username, domain: domain, password: password}, ntlmv2: true)
89
+ type3_msg.user.force_encoding('UTF-16LE')
90
+ type3_msg.domain.force_encoding('UTF-16LE')
91
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_SUCCESS
92
+ end
93
+
94
+ it 'should respond to an incorrect password with STATUS_LOGON_FAILURE' do
95
+ type3_msg = type2_msg.response({user: username, domain: domain, password: password + rand(0x41..0x5b).chr}, ntlmv2: true)
96
+ type3_msg.user.force_encoding('UTF-16LE')
97
+ type3_msg.domain.force_encoding('UTF-16LE')
98
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::OSVersion do
2
+ subject(:os_version) { RubySMB::Gss::Provider::NTLM::OSVersion.new }
3
+
4
+ it { is_expected.to respond_to :major }
5
+ it { is_expected.to respond_to :minor }
6
+ it { is_expected.to respond_to :build }
7
+ it { is_expected.to respond_to :ntlm_revision }
8
+
9
+ describe '#initialize' do
10
+ it 'defaults to an NTLM revision of 15' do
11
+ expect(os_version.ntlm_revision).to eq 15
12
+ end
13
+ end
14
+
15
+ describe '#read' do
16
+ it 'reads a packed version correctly' do
17
+ # Version 6.1 (Build 7601); NTLM Current Revision 15
18
+ os_version = RubySMB::Gss::Provider::NTLM::OSVersion.read("\x06\x01\xb1\x1d\x00\x00\x00\x0f")
19
+ expect(os_version.major).to eq 6
20
+ expect(os_version.minor).to eq 1
21
+ expect(os_version.build).to eq 7601
22
+ expect(os_version.ntlm_revision).to eq 15
23
+ end
24
+ end
25
+
26
+ describe '#to_s' do
27
+ it 'creates a string representation of the OS version' do
28
+ expect(os_version.to_s).to be_a String
29
+ expect(os_version.to_s).to match /Version \d+\.\d+ \(Build \d+\); NTLM Current Revision \d+/
30
+ end
31
+ end
32
+ end