ruby_smb 2.0.2 → 2.0.3
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/list_directory.rb +8 -6
- data/examples/negotiate_with_netbios_service.rb +9 -5
- data/examples/net_share_enum_all.rb +6 -4
- data/examples/pipes.rb +11 -12
- data/examples/query_service_status.rb +64 -0
- data/examples/read_file.rb +8 -6
- data/examples/read_registry_key_value.rb +6 -5
- data/examples/rename_file.rb +9 -7
- data/examples/tree_connect.rb +7 -5
- data/examples/write_file.rb +9 -7
- data/lib/ruby_smb/client.rb +72 -43
- data/lib/ruby_smb/client/negotiation.rb +1 -0
- data/lib/ruby_smb/dcerpc.rb +2 -0
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
- data/lib/ruby_smb/dcerpc/request.rb +13 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
- data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +1 -1
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/smb1/file.rb +2 -10
- data/lib/ruby_smb/smb1/pipe.rb +2 -0
- data/lib/ruby_smb/smb2/file.rb +25 -17
- data/lib/ruby_smb/smb2/pipe.rb +3 -0
- data/lib/ruby_smb/smb2/tree.rb +9 -3
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +161 -60
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +215 -41
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +7 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +60 -6
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +7 -0
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +35 -1
- metadata +72 -2
- metadata.gz.sig +0 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl::QueryServiceStatusRequest do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :h_service }
|
5
|
+
|
6
|
+
it 'is little endian' do
|
7
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#h_service' do
|
11
|
+
it 'is a ScRpcHandle structure' do
|
12
|
+
expect(packet.h_service).to be_a RubySMB::Dcerpc::Svcctl::ScRpcHandle
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#initialize_instance' do
|
17
|
+
it 'sets #opnum to QUERY_SERVICE_STATUS constant' do
|
18
|
+
expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'reads its own binary representation and outputs the same packet' do
|
23
|
+
packet = described_class.new(
|
24
|
+
h_service: {context_handle_attributes: 0, context_handle_uuid: '367abb81-9844-35f1-ad32-98f038001003'}
|
25
|
+
)
|
26
|
+
binary = packet.to_binary_s
|
27
|
+
expect(described_class.read(binary)).to eq(packet)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl::QueryServiceStatusResponse do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :lp_service_status }
|
5
|
+
it { is_expected.to respond_to :error_status }
|
6
|
+
|
7
|
+
it 'is little endian' do
|
8
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#lp_service_status' do
|
12
|
+
it 'is a ServiceStatus structure' do
|
13
|
+
expect(packet.lp_service_status).to be_a RubySMB::Dcerpc::Svcctl::ServiceStatus
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#error_status' do
|
18
|
+
it 'is a 32-bit unsigned integer' do
|
19
|
+
expect(packet.error_status).to be_a BinData::Uint32le
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#initialize_instance' do
|
24
|
+
it 'sets #opnum to QUERY_SERVICE_STATUS constant' do
|
25
|
+
expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'reads its own binary representation and outputs the same packet' do
|
30
|
+
packet = described_class.new(
|
31
|
+
lp_service_status: RubySMB::Dcerpc::Svcctl::ServiceStatus.new(dw_service_type: 1, dw_current_state: 3),
|
32
|
+
error_status: 3
|
33
|
+
)
|
34
|
+
binary = packet.to_binary_s
|
35
|
+
expect(described_class.read(binary)).to eq(packet)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl::ServiceStatus do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :dw_service_type }
|
5
|
+
it { is_expected.to respond_to :dw_current_state }
|
6
|
+
it { is_expected.to respond_to :dw_controls_accepted }
|
7
|
+
it { is_expected.to respond_to :dw_win32_exit_code }
|
8
|
+
it { is_expected.to respond_to :dw_service_specific_exit_code }
|
9
|
+
it { is_expected.to respond_to :dw_check_point }
|
10
|
+
it { is_expected.to respond_to :dw_wait_hint }
|
11
|
+
|
12
|
+
it 'is little endian' do
|
13
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#dw_service_type' do
|
17
|
+
it 'is a 32-bit unsigned integer' do
|
18
|
+
expect(packet.dw_service_type).to be_a BinData::Uint32le
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#dw_current_state' do
|
23
|
+
it 'is a 32-bit unsigned integer' do
|
24
|
+
expect(packet.dw_current_state).to be_a BinData::Uint32le
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#dw_controls_accepted' do
|
29
|
+
it 'is a 32-bit unsigned integer' do
|
30
|
+
expect(packet.dw_controls_accepted).to be_a BinData::Uint32le
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#dw_win32_exit_code' do
|
35
|
+
it 'is a 32-bit unsigned integer' do
|
36
|
+
expect(packet.dw_win32_exit_code).to be_a BinData::Uint32le
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#dw_service_specific_exit_code' do
|
41
|
+
it 'is a 32-bit unsigned integer' do
|
42
|
+
expect(packet.dw_service_specific_exit_code).to be_a BinData::Uint32le
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#dw_check_point' do
|
47
|
+
it 'is a 32-bit unsigned integer' do
|
48
|
+
expect(packet.dw_check_point).to be_a BinData::Uint32le
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#dw_wait_hint' do
|
53
|
+
it 'is a 32-bit unsigned integer' do
|
54
|
+
expect(packet.dw_wait_hint).to be_a BinData::Uint32le
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'reads its own binary representation and outputs the same packet' do
|
59
|
+
packet = described_class.new(
|
60
|
+
dw_desired_access: 2,
|
61
|
+
dw_current_state: 3,
|
62
|
+
dw_controls_accepted: 4,
|
63
|
+
dw_win32_exit_code: 5,
|
64
|
+
dw_service_specific_exit_code: 6,
|
65
|
+
dw_check_point: 7,
|
66
|
+
dw_wait_hint: 8
|
67
|
+
)
|
68
|
+
binary = packet.to_binary_s
|
69
|
+
expect(described_class.read(binary)).to eq(packet)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl::StartServiceWRequest do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :h_service }
|
5
|
+
it { is_expected.to respond_to :argc }
|
6
|
+
it { is_expected.to respond_to :argv }
|
7
|
+
|
8
|
+
it 'is little endian' do
|
9
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#h_service' do
|
13
|
+
it 'is a ScRpcHandle structure' do
|
14
|
+
expect(packet.h_service).to be_a RubySMB::Dcerpc::Svcctl::ScRpcHandle
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#argc' do
|
19
|
+
it 'is a 32-bit unsigned integer' do
|
20
|
+
expect(packet.argc).to be_a BinData::Uint32le
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#argv' do
|
25
|
+
it 'is a NdrLpStringPtrsw structure' do
|
26
|
+
expect(packet.argv).to be_a RubySMB::Dcerpc::Ndr::NdrLpStringPtrsw
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#initialize_instance' do
|
31
|
+
it 'sets #opnum to START_SERVICE_W constant' do
|
32
|
+
expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::START_SERVICE_W)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'reads its own binary representation and outputs the same packet' do
|
37
|
+
packet = described_class.new(
|
38
|
+
h_service: {context_handle_attributes: 0, context_handle_uuid: '367abb81-9844-35f1-ad32-98f038001003'},
|
39
|
+
argc: 3,
|
40
|
+
argv: ['test', '-c', '-e']
|
41
|
+
)
|
42
|
+
binary = packet.to_binary_s
|
43
|
+
expect(described_class.read(binary)).to eq(packet)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl::StartServiceWResponse do
|
2
|
+
subject(:packet) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :error_status }
|
5
|
+
|
6
|
+
it 'is little endian' do
|
7
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#error_status' do
|
11
|
+
it 'is a 32-bit unsigned integer' do
|
12
|
+
expect(packet.error_status).to be_a BinData::Uint32le
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#initialize_instance' do
|
17
|
+
it 'sets #opnum to START_SERVICE_W constant' do
|
18
|
+
expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::START_SERVICE_W)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'reads its own binary representation and outputs the same packet' do
|
23
|
+
packet = described_class.new(
|
24
|
+
error_status: 3
|
25
|
+
)
|
26
|
+
binary = packet.to_binary_s
|
27
|
+
expect(described_class.read(binary)).to eq(packet)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,512 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Svcctl do
|
2
|
+
let(:svcctl) do
|
3
|
+
RubySMB::SMB1::Pipe.new(
|
4
|
+
tree: double('Tree'),
|
5
|
+
response: RubySMB::SMB1::Packet::NtCreateAndxResponse.new,
|
6
|
+
name: 'svcctl'
|
7
|
+
)
|
8
|
+
end
|
9
|
+
it 'fail' do
|
10
|
+
expect(true).to be true
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#open_sc_manager_w' do
|
14
|
+
let(:rhost) { '1.2.3.4' }
|
15
|
+
let(:open_sc_manager_w_request) { double('OpenSCManagerW Request Packet') }
|
16
|
+
let(:response) { double('Response') }
|
17
|
+
let(:open_sc_manager_w_response) { double('OpenSCManagerW Response Packet') }
|
18
|
+
let(:lp_sc_handle) { double('LpScHandle') }
|
19
|
+
before :example do
|
20
|
+
allow(described_class::OpenSCManagerWRequest).to receive(:new).and_return(open_sc_manager_w_request)
|
21
|
+
allow(open_sc_manager_w_request).to receive_messages(
|
22
|
+
:lp_machine_name= => nil,
|
23
|
+
:lp_database_name= => nil,
|
24
|
+
)
|
25
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
26
|
+
allow(described_class::OpenSCManagerWResponse).to receive(:read).and_return(open_sc_manager_w_response)
|
27
|
+
allow(open_sc_manager_w_response).to receive_messages(
|
28
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
29
|
+
:lp_sc_handle => lp_sc_handle
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'create the expected OpenSCManagerWRequest packet with the default desired access' do
|
34
|
+
access =
|
35
|
+
described_class::SERVICE_START |
|
36
|
+
described_class::SERVICE_STOP |
|
37
|
+
described_class::SERVICE_CHANGE_CONFIG |
|
38
|
+
described_class::SERVICE_QUERY_CONFIG |
|
39
|
+
described_class::SERVICE_QUERY_STATUS |
|
40
|
+
described_class::SERVICE_ENUMERATE_DEPENDENTS |
|
41
|
+
described_class::SC_MANAGER_ENUMERATE_SERVICE
|
42
|
+
svcctl.open_sc_manager_w(rhost)
|
43
|
+
expect(described_class::OpenSCManagerWRequest).to have_received(:new).with(dw_desired_access: access)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'create the expected OpenSCManagerWRequest packet with custom desired access' do
|
47
|
+
access =
|
48
|
+
described_class::SERVICE_QUERY_CONFIG |
|
49
|
+
described_class::SERVICE_ENUMERATE_DEPENDENTS |
|
50
|
+
described_class::SC_MANAGER_ENUMERATE_SERVICE
|
51
|
+
svcctl.open_sc_manager_w(rhost, access)
|
52
|
+
expect(described_class::OpenSCManagerWRequest).to have_received(:new).with(dw_desired_access: access)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'sets the expected fields on the request packet' do
|
56
|
+
svcctl.open_sc_manager_w(rhost)
|
57
|
+
expect(open_sc_manager_w_request).to have_received(:lp_machine_name=).with(rhost)
|
58
|
+
expect(open_sc_manager_w_request).to have_received(:lp_database_name=).with('ServicesActive')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'sends the expected dcerpc request' do
|
62
|
+
svcctl.open_sc_manager_w(rhost)
|
63
|
+
expect(svcctl).to have_received(:dcerpc_request).with(open_sc_manager_w_request)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'creates a OpenSCManagerWResponse structure from the expected dcerpc response' do
|
67
|
+
svcctl.open_sc_manager_w(rhost)
|
68
|
+
expect(described_class::OpenSCManagerWResponse).to have_received(:read).with(response)
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when an IOError occurs while parsing the response' do
|
72
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
73
|
+
allow(described_class::OpenSCManagerWResponse).to receive(:read).and_raise(IOError)
|
74
|
+
expect { svcctl.open_sc_manager_w(rhost) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
79
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
80
|
+
allow(open_sc_manager_w_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
81
|
+
expect { svcctl.open_sc_manager_w(rhost) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns the expected handler' do
|
86
|
+
expect(svcctl.open_sc_manager_w(rhost)).to eq(lp_sc_handle)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#open_service_w' do
|
91
|
+
let(:scm_handle) { '1.2.3.4' }
|
92
|
+
let(:service_name) { 'MyService' }
|
93
|
+
let(:open_service_w_request) { double('OpenServiceW Request Packet') }
|
94
|
+
let(:response) { double('Response') }
|
95
|
+
let(:open_service_w_response) { double('OpenServiceW Response Packet') }
|
96
|
+
let(:lp_sc_handle) { double('LpScHandle') }
|
97
|
+
before :example do
|
98
|
+
allow(described_class::OpenServiceWRequest).to receive(:new).and_return(open_service_w_request)
|
99
|
+
allow(open_service_w_request).to receive_messages(
|
100
|
+
:lp_sc_handle= => nil,
|
101
|
+
:lp_service_name= => nil,
|
102
|
+
)
|
103
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
104
|
+
allow(described_class::OpenServiceWResponse).to receive(:read).and_return(open_service_w_response)
|
105
|
+
allow(open_service_w_response).to receive_messages(
|
106
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
107
|
+
:lp_sc_handle => lp_sc_handle
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'create the expected OpenServiceWRequest packet with the default desired access' do
|
112
|
+
access = described_class::SERVICE_ALL_ACCESS
|
113
|
+
svcctl.open_service_w(scm_handle, service_name)
|
114
|
+
expect(described_class::OpenServiceWRequest).to have_received(:new).with(dw_desired_access: access)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'create the expected OpenServiceWRequest packet with custom desired access' do
|
118
|
+
access =
|
119
|
+
described_class::SERVICE_QUERY_CONFIG |
|
120
|
+
described_class::SERVICE_ENUMERATE_DEPENDENTS |
|
121
|
+
described_class::SC_MANAGER_ENUMERATE_SERVICE
|
122
|
+
svcctl.open_service_w(scm_handle, service_name, access)
|
123
|
+
expect(described_class::OpenServiceWRequest).to have_received(:new).with(dw_desired_access: access)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'sets the expected fields on the request packet' do
|
127
|
+
svcctl.open_service_w(scm_handle, service_name)
|
128
|
+
expect(open_service_w_request).to have_received(:lp_sc_handle=).with(scm_handle)
|
129
|
+
expect(open_service_w_request).to have_received(:lp_service_name=).with(service_name)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'sends the expected dcerpc request' do
|
133
|
+
svcctl.open_service_w(scm_handle, service_name)
|
134
|
+
expect(svcctl).to have_received(:dcerpc_request).with(open_service_w_request)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'creates a OpenServiceWResponse structure from the expected dcerpc response' do
|
138
|
+
svcctl.open_service_w(scm_handle, service_name)
|
139
|
+
expect(described_class::OpenServiceWResponse).to have_received(:read).with(response)
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'when an IOError occurs while parsing the response' do
|
143
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
144
|
+
allow(described_class::OpenServiceWResponse).to receive(:read).and_raise(IOError)
|
145
|
+
expect { svcctl.open_service_w(scm_handle, service_name) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
150
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
151
|
+
allow(open_service_w_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
152
|
+
expect { svcctl.open_service_w(scm_handle, service_name) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'returns the expected handler' do
|
157
|
+
expect(svcctl.open_service_w(scm_handle, service_name)).to eq(lp_sc_handle)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#query_service_status' do
|
162
|
+
let(:svc_handle) { double('Service Handle') }
|
163
|
+
let(:query_service_status_request) { double('QueryServiceStatus Request Packet') }
|
164
|
+
let(:response) { double('Response') }
|
165
|
+
let(:query_service_status_response) { double('QueryServiceStatus Response Packet') }
|
166
|
+
let(:lp_service_status) { double('LpServiceStatus') }
|
167
|
+
before :example do
|
168
|
+
allow(described_class::QueryServiceStatusRequest).to receive(:new).and_return(query_service_status_request)
|
169
|
+
allow(query_service_status_request).to receive_messages(
|
170
|
+
:h_service= => nil,
|
171
|
+
)
|
172
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
173
|
+
allow(described_class::QueryServiceStatusResponse).to receive(:read).and_return(query_service_status_response)
|
174
|
+
allow(query_service_status_response).to receive_messages(
|
175
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
176
|
+
:lp_service_status => lp_service_status
|
177
|
+
)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'create the expected QueryServiceStatusRequest packet' do
|
181
|
+
svcctl.query_service_status(svc_handle)
|
182
|
+
expect(described_class::QueryServiceStatusRequest).to have_received(:new)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'sets the expected fields on the request packet' do
|
186
|
+
svcctl.query_service_status(svc_handle)
|
187
|
+
expect(query_service_status_request).to have_received(:h_service=).with(svc_handle)
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'sends the expected dcerpc request' do
|
191
|
+
svcctl.query_service_status(svc_handle)
|
192
|
+
expect(svcctl).to have_received(:dcerpc_request).with(query_service_status_request)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'creates a QueryServiceStatusResponse structure from the expected dcerpc response' do
|
196
|
+
svcctl.query_service_status(svc_handle)
|
197
|
+
expect(described_class::QueryServiceStatusResponse).to have_received(:read).with(response)
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'when an IOError occurs while parsing the response' do
|
201
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
202
|
+
allow(described_class::QueryServiceStatusResponse).to receive(:read).and_raise(IOError)
|
203
|
+
expect { svcctl.query_service_status(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
208
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
209
|
+
allow(query_service_status_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
210
|
+
expect { svcctl.query_service_status(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'returns the expected handler' do
|
215
|
+
expect(svcctl.query_service_status(svc_handle)).to eq(lp_service_status)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#query_service_config' do
|
220
|
+
let(:svc_handle) { double('Service Handle') }
|
221
|
+
let(:query_service_config_request) { double('QueryServiceConfigW Request Packet') }
|
222
|
+
let(:response) { double('Response') }
|
223
|
+
let(:query_service_config_response) { double('QueryServiceConfigW Response Packet') }
|
224
|
+
let(:lp_service_config) { double('LpServiceConfig') }
|
225
|
+
before :example do
|
226
|
+
allow(described_class::QueryServiceConfigWRequest).to receive(:new).and_return(query_service_config_request)
|
227
|
+
allow(query_service_config_request).to receive_messages(
|
228
|
+
:h_service= => nil,
|
229
|
+
:cb_buf_size= => nil,
|
230
|
+
)
|
231
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
232
|
+
allow(described_class::QueryServiceConfigWResponse).to receive(:read).and_return(query_service_config_response)
|
233
|
+
allow(query_service_config_response).to receive_messages(
|
234
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
235
|
+
:lp_service_config => lp_service_config
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'create the expected QueryServiceConfigWRequest packet' do
|
240
|
+
svcctl.query_service_config(svc_handle)
|
241
|
+
expect(described_class::QueryServiceConfigWRequest).to have_received(:new)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'sets the expected fields on the request packet' do
|
245
|
+
svcctl.query_service_config(svc_handle)
|
246
|
+
expect(query_service_config_request).to have_received(:h_service=).with(svc_handle)
|
247
|
+
expect(query_service_config_request).to have_received(:cb_buf_size=).with(0)
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'sends the expected dcerpc request' do
|
251
|
+
svcctl.query_service_config(svc_handle)
|
252
|
+
expect(svcctl).to have_received(:dcerpc_request).with(query_service_config_request)
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'creates a QueryServiceConfigWResponse structure from the expected dcerpc response' do
|
256
|
+
svcctl.query_service_config(svc_handle)
|
257
|
+
expect(described_class::QueryServiceConfigWResponse).to have_received(:read).with(response)
|
258
|
+
end
|
259
|
+
|
260
|
+
context 'when an IOError occurs while parsing the response' do
|
261
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
262
|
+
allow(described_class::QueryServiceConfigWResponse).to receive(:read).and_raise(IOError)
|
263
|
+
expect { svcctl.query_service_config(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
268
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
269
|
+
allow(query_service_config_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
270
|
+
expect { svcctl.query_service_config(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'returns the expected handler' do
|
275
|
+
expect(svcctl.query_service_config(svc_handle)).to eq(lp_service_config)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe '#change_service_config_w' do
|
280
|
+
let(:svc_handle) { double('Service Handle') }
|
281
|
+
let(:change_service_config_w_request) { double('ChangeServiceConfigW Request Packet') }
|
282
|
+
let(:response) { double('Response') }
|
283
|
+
let(:change_service_config_w_response) { double('ChangeServiceConfigW Response Packet') }
|
284
|
+
before :example do
|
285
|
+
allow(described_class::ChangeServiceConfigWRequest).to receive(:new).and_return(change_service_config_w_request)
|
286
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
287
|
+
allow(described_class::ChangeServiceConfigWResponse).to receive(:read).and_return(change_service_config_w_response)
|
288
|
+
allow(change_service_config_w_response).to receive_messages(
|
289
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
290
|
+
)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'create the expected ChangeServiceConfigWRequest packet with the default options' do
|
294
|
+
opts = {
|
295
|
+
h_service: svc_handle,
|
296
|
+
dw_service_type: described_class::SERVICE_NO_CHANGE,
|
297
|
+
dw_start_type: described_class::SERVICE_NO_CHANGE,
|
298
|
+
dw_error_control: described_class::SERVICE_NO_CHANGE,
|
299
|
+
lp_binary_path_name: :null,
|
300
|
+
lp_load_order_group: :null,
|
301
|
+
dw_tag_id: :null,
|
302
|
+
lp_dependencies: [],
|
303
|
+
lp_service_start_name: :null,
|
304
|
+
lp_password: [],
|
305
|
+
lp_display_name: :null
|
306
|
+
}
|
307
|
+
svcctl.change_service_config_w(svc_handle)
|
308
|
+
expect(described_class::ChangeServiceConfigWRequest).to have_received(:new).with(opts)
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'create the expected ChangeServiceConfigWRequest packet with custom options' do
|
312
|
+
opts = {
|
313
|
+
service: svc_handle,
|
314
|
+
service_type: described_class::SERVICE_KERNEL_DRIVER,
|
315
|
+
start_type: described_class::SERVICE_SYSTEM_START,
|
316
|
+
error_control: described_class::SERVICE_ERROR_SEVERE,
|
317
|
+
binary_path_name: '\\path\\to\\binary',
|
318
|
+
load_order_group: 'load order',
|
319
|
+
tag_id: 2,
|
320
|
+
dependencies: [1, 2, 3],
|
321
|
+
service_start_name: 'My service',
|
322
|
+
password: [1, 2, 3],
|
323
|
+
display_name: 'Name'
|
324
|
+
}
|
325
|
+
opts2 = {
|
326
|
+
h_service: svc_handle,
|
327
|
+
dw_service_type: opts[:service_type],
|
328
|
+
dw_start_type: opts[:start_type],
|
329
|
+
dw_error_control: opts[:error_control],
|
330
|
+
lp_binary_path_name: opts[:binary_path_name],
|
331
|
+
lp_load_order_group: opts[:load_order_group],
|
332
|
+
dw_tag_id: opts[:tag_id],
|
333
|
+
lp_dependencies: opts[:dependencies],
|
334
|
+
lp_service_start_name: opts[:service_start_name],
|
335
|
+
lp_password: opts[:password],
|
336
|
+
lp_display_name: opts[:display_name]
|
337
|
+
}
|
338
|
+
svcctl.change_service_config_w(svc_handle, opts)
|
339
|
+
expect(described_class::ChangeServiceConfigWRequest).to have_received(:new).with(opts2)
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'sends the expected dcerpc request' do
|
343
|
+
svcctl.change_service_config_w(svc_handle)
|
344
|
+
expect(svcctl).to have_received(:dcerpc_request).with(change_service_config_w_request)
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'creates a ChangeServiceConfigWResponse structure from the expected dcerpc response' do
|
348
|
+
svcctl.change_service_config_w(svc_handle)
|
349
|
+
expect(described_class::ChangeServiceConfigWResponse).to have_received(:read).with(response)
|
350
|
+
end
|
351
|
+
|
352
|
+
context 'when an IOError occurs while parsing the response' do
|
353
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
354
|
+
allow(described_class::ChangeServiceConfigWResponse).to receive(:read).and_raise(IOError)
|
355
|
+
expect { svcctl.change_service_config_w(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
360
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
361
|
+
allow(change_service_config_w_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
362
|
+
expect { svcctl.change_service_config_w(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe '#start_service_w' do
|
368
|
+
let(:svc_handle) { double('Service Handle') }
|
369
|
+
let(:start_service_w_request) { double('StartServiceW Request Packet') }
|
370
|
+
let(:response) { double('Response') }
|
371
|
+
let(:start_service_w_response) { double('StartServiceW Response Packet') }
|
372
|
+
before :example do
|
373
|
+
allow(described_class::StartServiceWRequest).to receive(:new).and_return(start_service_w_request)
|
374
|
+
allow(start_service_w_request).to receive_messages(
|
375
|
+
:h_service= => nil,
|
376
|
+
:argc= => nil,
|
377
|
+
:argv= => nil,
|
378
|
+
)
|
379
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
380
|
+
allow(described_class::StartServiceWResponse).to receive(:read).and_return(start_service_w_response)
|
381
|
+
allow(start_service_w_response).to receive_messages(
|
382
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
383
|
+
)
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'create the expected StartServiceWRequest packet' do
|
387
|
+
svcctl.start_service_w(svc_handle)
|
388
|
+
expect(described_class::StartServiceWRequest).to have_received(:new)
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'sets the provided Service start arguments' do
|
392
|
+
argv = ['my', 'arguments', 'to', 'test']
|
393
|
+
ndr_string_ptrsw = RubySMB::Dcerpc::Ndr::NdrStringPtrsw.new(elements: argv)
|
394
|
+
svcctl.start_service_w(svc_handle, argv)
|
395
|
+
expect(start_service_w_request).to have_received(:argc=).with(argv.size)
|
396
|
+
expect(start_service_w_request).to have_received(:argv=).with(ndr_string_ptrsw)
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'sends the expected dcerpc request' do
|
400
|
+
svcctl.start_service_w(svc_handle)
|
401
|
+
expect(svcctl).to have_received(:dcerpc_request).with(start_service_w_request)
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'creates a StartServiceWResponse structure from the expected dcerpc response' do
|
405
|
+
svcctl.start_service_w(svc_handle)
|
406
|
+
expect(described_class::StartServiceWResponse).to have_received(:read).with(response)
|
407
|
+
end
|
408
|
+
|
409
|
+
context 'when an IOError occurs while parsing the response' do
|
410
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
411
|
+
allow(described_class::StartServiceWResponse).to receive(:read).and_raise(IOError)
|
412
|
+
expect { svcctl.start_service_w(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
417
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
418
|
+
allow(start_service_w_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
419
|
+
expect { svcctl.start_service_w(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
describe '#control_service' do
|
425
|
+
let(:svc_handle) { double('Service Handle') }
|
426
|
+
let(:control) { double('Control') }
|
427
|
+
let(:control_service_request) { double('ControlService Request Packet') }
|
428
|
+
let(:response) { double('Response') }
|
429
|
+
let(:control_service_response) { double('ControlService Response Packet') }
|
430
|
+
before :example do
|
431
|
+
allow(described_class::ControlServiceRequest).to receive(:new).and_return(control_service_request)
|
432
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
433
|
+
allow(described_class::ControlServiceResponse).to receive(:read).and_return(control_service_response)
|
434
|
+
allow(control_service_response).to receive_messages(
|
435
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
436
|
+
)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'create the expected ControlServiceRequest packet' do
|
440
|
+
svcctl.control_service(svc_handle, control)
|
441
|
+
expect(described_class::ControlServiceRequest).to have_received(:new).with(h_service: svc_handle, dw_control: control)
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'sends the expected dcerpc request' do
|
445
|
+
svcctl.control_service(svc_handle, control)
|
446
|
+
expect(svcctl).to have_received(:dcerpc_request).with(control_service_request)
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'creates a ControlServiceResponse structure from the expected dcerpc response' do
|
450
|
+
svcctl.control_service(svc_handle, control)
|
451
|
+
expect(described_class::ControlServiceResponse).to have_received(:read).with(response)
|
452
|
+
end
|
453
|
+
|
454
|
+
context 'when an IOError occurs while parsing the response' do
|
455
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
456
|
+
allow(described_class::ControlServiceResponse).to receive(:read).and_raise(IOError)
|
457
|
+
expect { svcctl.control_service(svc_handle, control) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
462
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
463
|
+
allow(control_service_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
464
|
+
expect { svcctl.control_service(svc_handle, control) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
describe '#close_service_handle' do
|
470
|
+
let(:svc_handle) { double('Service Handle') }
|
471
|
+
let(:close_service_handle_request) { double('CloseServiceHandle Request Packet') }
|
472
|
+
let(:response) { double('Response') }
|
473
|
+
let(:close_service_handle_response) { double('CloseServiceHandle Response Packet') }
|
474
|
+
before :example do
|
475
|
+
allow(described_class::CloseServiceHandleRequest).to receive(:new).and_return(close_service_handle_request)
|
476
|
+
allow(svcctl).to receive(:dcerpc_request).and_return(response)
|
477
|
+
allow(described_class::CloseServiceHandleResponse).to receive(:read).and_return(close_service_handle_response)
|
478
|
+
allow(close_service_handle_response).to receive_messages(
|
479
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
480
|
+
)
|
481
|
+
end
|
482
|
+
|
483
|
+
it 'create the expected CloseServiceHandleRequest packet' do
|
484
|
+
svcctl.close_service_handle(svc_handle)
|
485
|
+
expect(described_class::CloseServiceHandleRequest).to have_received(:new).with(h_sc_object: svc_handle)
|
486
|
+
end
|
487
|
+
|
488
|
+
it 'sends the expected dcerpc request' do
|
489
|
+
svcctl.close_service_handle(svc_handle)
|
490
|
+
expect(svcctl).to have_received(:dcerpc_request).with(close_service_handle_request)
|
491
|
+
end
|
492
|
+
|
493
|
+
it 'creates a CloseServiceHandleResponse structure from the expected dcerpc response' do
|
494
|
+
svcctl.close_service_handle(svc_handle)
|
495
|
+
expect(described_class::CloseServiceHandleResponse).to have_received(:read).with(response)
|
496
|
+
end
|
497
|
+
|
498
|
+
context 'when an IOError occurs while parsing the response' do
|
499
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
500
|
+
allow(described_class::CloseServiceHandleResponse).to receive(:read).and_raise(IOError)
|
501
|
+
expect { svcctl.close_service_handle(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
506
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
507
|
+
allow(close_service_handle_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
508
|
+
expect { svcctl.close_service_handle(svc_handle) }.to raise_error(RubySMB::Dcerpc::Error::SvcctlError)
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|