ruby_smb 2.0.12 → 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 (194) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +1 -1
  4. data/examples/dump_secrets_from_sid.rb +207 -0
  5. data/examples/enum_domain_users.rb +75 -0
  6. data/examples/get_computer_info.rb +42 -0
  7. data/examples/query_service_status.rb +42 -4
  8. data/lib/ruby_smb/client.rb +3 -14
  9. data/lib/ruby_smb/dcerpc/bind.rb +28 -20
  10. data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
  11. data/lib/ruby_smb/dcerpc/client.rb +542 -0
  12. data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
  13. data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
  14. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
  15. data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
  16. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
  17. data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
  18. data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
  19. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
  20. data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
  21. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
  22. data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
  23. data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
  24. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
  25. data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
  26. data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
  27. data/lib/ruby_smb/dcerpc/epm.rb +75 -0
  28. data/lib/ruby_smb/dcerpc/error.rb +17 -0
  29. data/lib/ruby_smb/dcerpc/ndr.rb +1159 -297
  30. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +3 -13
  31. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +3 -3
  32. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +3 -13
  33. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +1 -1
  34. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +3 -11
  35. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +1 -1
  36. data/lib/ruby_smb/dcerpc/netlogon.rb +5 -4
  37. data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
  38. data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
  39. data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
  40. data/lib/ruby_smb/dcerpc/request.rb +79 -32
  41. data/lib/ruby_smb/dcerpc/response.rb +45 -10
  42. data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
  43. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +11 -11
  44. data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
  45. data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
  46. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
  47. data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
  48. data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
  49. data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
  50. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
  51. data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
  52. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
  53. data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
  54. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
  55. data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
  56. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
  57. data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
  58. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
  59. data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
  60. data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
  61. data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
  62. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
  63. data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
  64. data/lib/ruby_smb/dcerpc/samr.rb +613 -0
  65. data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
  66. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
  67. data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
  68. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +13 -25
  69. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +2 -2
  70. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +1 -1
  71. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +1 -1
  72. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +1 -1
  73. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +4 -14
  74. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +1 -1
  75. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +3 -11
  76. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +1 -1
  77. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +1 -1
  78. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +12 -11
  79. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +1 -1
  80. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +9 -8
  81. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +3 -3
  82. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +1 -1
  83. data/lib/ruby_smb/dcerpc/svcctl.rb +1 -3
  84. data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
  85. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
  86. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +2 -13
  87. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +3 -3
  88. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +3 -20
  89. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
  90. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
  91. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
  92. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
  93. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
  94. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +5 -6
  95. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
  96. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
  97. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -14
  98. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
  99. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
  100. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +0 -9
  101. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +1 -1
  102. data/lib/ruby_smb/dcerpc/winreg.rb +10 -14
  103. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
  104. data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
  105. data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
  106. data/lib/ruby_smb/dcerpc.rb +41 -11
  107. data/lib/ruby_smb/field/file_time.rb +1 -1
  108. data/lib/ruby_smb/field/string16.rb +5 -1
  109. data/lib/ruby_smb/ntlm.rb +18 -2
  110. data/lib/ruby_smb/smb1/pipe.rb +4 -0
  111. data/lib/ruby_smb/smb2/pipe.rb +4 -0
  112. data/lib/ruby_smb/version.rb +1 -1
  113. data/spec/lib/ruby_smb/client_spec.rb +1 -2
  114. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
  115. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
  116. data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
  117. data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
  118. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3792 -1373
  119. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +4 -4
  120. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +4 -4
  121. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +2 -2
  122. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +2 -2
  123. data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
  124. data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
  125. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
  126. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
  127. data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
  128. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +29 -28
  129. data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
  130. data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
  131. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
  132. data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
  133. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
  134. data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
  135. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
  136. data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
  137. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
  138. data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
  139. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
  140. data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
  141. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
  142. data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
  143. data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
  144. data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
  145. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
  146. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
  147. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +56 -79
  148. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +4 -4
  149. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +2 -2
  150. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +2 -2
  151. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +2 -2
  152. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +19 -29
  153. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +2 -2
  154. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +9 -15
  155. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +2 -2
  156. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +2 -2
  157. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +22 -22
  158. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +2 -2
  159. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +18 -14
  160. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +5 -4
  161. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +2 -2
  162. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +1 -5
  163. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
  164. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
  165. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +4 -41
  166. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +4 -4
  167. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -52
  168. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
  169. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
  170. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
  171. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
  172. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -25
  174. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
  176. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
  177. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +10 -22
  178. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
  179. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +0 -12
  180. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +2 -2
  181. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +18 -47
  182. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
  183. data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
  184. data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
  185. data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
  186. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +1 -1
  187. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +18 -37
  188. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +18 -16
  189. data/spec/support/bin_helper.rb +9 -0
  190. data.tar.gz.sig +0 -0
  191. metadata +96 -5
  192. metadata.gz.sig +0 -0
  193. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -38
  194. 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
@@ -15,7 +15,7 @@ RSpec.describe RubySMB::Gss::Provider::NTLM::OSVersion do
15
15
  describe '#read' do
16
16
  it 'reads a packed version correctly' do
17
17
  # Version 6.1 (Build 7601); NTLM Current Revision 15
18
- os_version = RubySMB::Gss::Provider::NTLM::OSVersion.read("\x06\x01\x1d\xb1\x00\x00\x00\x0f")
18
+ os_version = RubySMB::Gss::Provider::NTLM::OSVersion.read("\x06\x01\xb1\x1d\x00\x00\x00\x0f")
19
19
  expect(os_version.major).to eq 6
20
20
  expect(os_version.minor).to eq 1
21
21
  expect(os_version.build).to eq 7601
@@ -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
@@ -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
@@ -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
Binary file