2
* Unix SMB/CIFS implementation.
3
* MS-RPC client library implementation (SVCCTL pipe)
4
* Copyright (C) Chris Nicholls 2005.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
#include "libsmb_internal.h"
24
#define WAIT_SLEEP_TIME 300000
26
int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op) {
28
struct rpc_pipe_client *pipe_hnd = NULL;
31
POLICY_HND *scm_out = NULL;
36
if(!hnd->_internal.ctx) {
37
hnd->status = NT_STATUS_INVALID_HANDLE;
41
if(!op || op->in.access == 0 || !mem_ctx) {
42
hnd->status = NT_STATUS_INVALID_PARAMETER;
46
srv = cac_GetServer(hnd);
48
hnd->status = NT_STATUS_INVALID_CONNECTION;
52
/*initialize for samr pipe if we have to*/
53
if(!hnd->_internal.pipes[PI_SVCCTL]) {
54
if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SVCCTL, &(hnd->status)))) {
55
hnd->status = NT_STATUS_UNSUCCESSFUL;
59
hnd->_internal.pipes[PI_SVCCTL] = True;
62
scm_out = talloc(mem_ctx, POLICY_HND);
64
hnd->status = NT_STATUS_NO_MEMORY;
68
err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out, op->in.access);
69
hnd->status = werror_to_ntstatus(err);
71
if(!NT_STATUS_IS_OK(hnd->status))
74
op->out.scm_hnd = scm_out;
79
int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd) {
80
struct rpc_pipe_client *pipe_hnd = NULL;
86
if(!hnd->_internal.ctx) {
87
hnd->status = NT_STATUS_INVALID_HANDLE;
91
if(!scm_hnd || !mem_ctx) {
92
hnd->status = NT_STATUS_INVALID_PARAMETER;
96
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
98
hnd->status = NT_STATUS_INVALID_HANDLE;
102
err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd);
103
hnd->status = werror_to_ntstatus(err);
105
if(!NT_STATUS_IS_OK(hnd->status))
111
int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) {
112
struct rpc_pipe_client *pipe_hnd = NULL;
116
uint32 state_buf = 0;
118
uint32 num_svc_out = 0;
120
ENUM_SERVICES_STATUS *svc_buf = NULL;
125
if(!hnd->_internal.ctx) {
126
hnd->status = NT_STATUS_INVALID_HANDLE;
130
if(!op || !op->in.scm_hnd || !mem_ctx) {
131
hnd->status = NT_STATUS_INVALID_PARAMETER;
135
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
137
hnd->status = NT_STATUS_INVALID_HANDLE;
141
type_buf = (op->in.type != 0) ? op->in.type : (SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32);
142
state_buf = (op->in.state != 0) ? op->in.state : SVCCTL_STATE_ALL;
144
err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx, op->in.scm_hnd, type_buf, state_buf, &num_svc_out, &svc_buf);
145
hnd->status = werror_to_ntstatus(err);
147
if(!NT_STATUS_IS_OK(hnd->status))
150
op->out.services = cac_MakeServiceArray(mem_ctx, svc_buf, num_svc_out);
152
if(!op->out.services) {
153
hnd->status = NT_STATUS_NO_MEMORY;
157
TALLOC_FREE(svc_buf);
159
op->out.num_services = num_svc_out;
164
int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) {
165
struct rpc_pipe_client *pipe_hnd = NULL;
168
POLICY_HND *svc_hnd_out = NULL;
173
if(!hnd->_internal.ctx) {
174
hnd->status = NT_STATUS_INVALID_HANDLE;
178
if(!op || !op->in.scm_hnd || !op->in.name || !mem_ctx) {
179
hnd->status = NT_STATUS_INVALID_PARAMETER;
183
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
185
hnd->status = NT_STATUS_INVALID_HANDLE;
189
svc_hnd_out = talloc(mem_ctx, POLICY_HND);
191
hnd->status = NT_STATUS_NO_MEMORY;
195
err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd, svc_hnd_out, op->in.name, op->in.access);
196
hnd->status = werror_to_ntstatus(err);
198
if(!NT_STATUS_IS_OK(hnd->status))
201
op->out.svc_hnd = svc_hnd_out;
206
int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) {
207
struct rpc_pipe_client *pipe_hnd = NULL;
210
SERVICE_STATUS status_out;
215
if(!hnd->_internal.ctx) {
216
hnd->status = NT_STATUS_INVALID_HANDLE;
220
if(!op || !op->in.svc_hnd || !mem_ctx) {
221
hnd->status = NT_STATUS_INVALID_PARAMETER;
225
if(op->in.control < SVCCTL_CONTROL_STOP || op->in.control > SVCCTL_CONTROL_SHUTDOWN) {
226
hnd->status = NT_STATUS_INVALID_PARAMETER;
230
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
232
hnd->status = NT_STATUS_INVALID_HANDLE;
236
err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, op->in.control, &status_out);
237
hnd->status = werror_to_ntstatus(err);
239
if(!NT_STATUS_IS_OK(hnd->status))
245
int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) {
246
struct rpc_pipe_client *pipe_hnd = NULL;
249
SERVICE_STATUS status_out;
254
if(!hnd->_internal.ctx) {
255
hnd->status = NT_STATUS_INVALID_HANDLE;
259
if(!op || !op->in.svc_hnd || !mem_ctx) {
260
hnd->status = NT_STATUS_INVALID_PARAMETER;
264
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
266
hnd->status = NT_STATUS_INVALID_HANDLE;
270
err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd, &status_out);
271
hnd->status = werror_to_ntstatus(err);
273
if(!NT_STATUS_IS_OK(hnd->status))
276
op->out.status = status_out;
283
/*Internal function - similar to code found in utils/net_rpc_service.c
284
* Waits for a service to reach a specific state.
285
* svc_hnd - Handle to the service
286
* state - the state we are waiting for
287
* timeout - number of seconds to wait
288
* returns CAC_FAILURE if the state is never reached
289
* or CAC_SUCCESS if the state is reached
291
int cac_WaitForService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *svc_hnd, uint32 state, uint32 timeout, SERVICE_STATUS *status) {
292
struct rpc_pipe_client *pipe_hnd = NULL;
293
/*number of milliseconds we have spent*/
294
uint32 time_spent = 0;
297
if(!hnd || !mem_ctx || !svc_hnd || !status)
300
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
302
hnd->status = NT_STATUS_INVALID_HANDLE;
306
while(status->state != state && time_spent < (timeout * 1000000) && NT_STATUS_IS_OK(hnd->status)) {
307
/*if this is the first call, then we _just_ got the status.. sleep now*/
308
usleep(WAIT_SLEEP_TIME);
309
time_spent += WAIT_SLEEP_TIME;
311
err = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, svc_hnd, status);
312
hnd->status = werror_to_ntstatus(err);
315
if(status->state == state)
321
int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) {
322
struct rpc_pipe_client *pipe_hnd = NULL;
325
SERVICE_STATUS status_buf;
330
if(!hnd->_internal.ctx) {
331
hnd->status = NT_STATUS_INVALID_HANDLE;
335
if(!op || !op->in.svc_hnd || !mem_ctx) {
336
hnd->status = NT_STATUS_INVALID_PARAMETER;
340
if(op->in.num_parms != 0 && op->in.parms == NULL) {
341
hnd->status = NT_STATUS_INVALID_PARAMETER;
345
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
347
hnd->status = NT_STATUS_INVALID_HANDLE;
351
err = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, op->in.svc_hnd, (const char **)op->in.parms, op->in.num_parms);
352
hnd->status = werror_to_ntstatus(err);
354
if(!NT_STATUS_IS_OK(hnd->status))
357
if(op->in.timeout == 0)
360
return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &status_buf);
363
int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op) {
364
struct rpc_pipe_client *pipe_hnd = NULL;
367
SERVICE_STATUS status_out;
372
if(!hnd->_internal.ctx) {
373
hnd->status = NT_STATUS_INVALID_HANDLE;
377
if(!op || !op->in.svc_hnd || !mem_ctx) {
378
hnd->status = NT_STATUS_INVALID_PARAMETER;
382
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
384
hnd->status = NT_STATUS_INVALID_HANDLE;
388
err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_STOP, &status_out);
389
hnd->status = werror_to_ntstatus(err);
391
if(!NT_STATUS_IS_OK(hnd->status))
394
op->out.status = status_out;
396
if(op->in.timeout == 0)
399
return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_STOPPED, op->in.timeout, &op->out.status);
402
int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op) {
403
struct rpc_pipe_client *pipe_hnd = NULL;
406
SERVICE_STATUS status_out;
411
if(!hnd->_internal.ctx) {
412
hnd->status = NT_STATUS_INVALID_HANDLE;
416
if(!op || !op->in.svc_hnd || !mem_ctx) {
417
hnd->status = NT_STATUS_INVALID_PARAMETER;
421
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
423
hnd->status = NT_STATUS_INVALID_HANDLE;
427
err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_PAUSE, &status_out);
428
hnd->status = werror_to_ntstatus(err);
430
if(!NT_STATUS_IS_OK(hnd->status))
433
op->out.status = status_out;
435
if(op->in.timeout == 0)
438
return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_PAUSED, op->in.timeout, &op->out.status);
441
int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op) {
442
struct rpc_pipe_client *pipe_hnd = NULL;
445
SERVICE_STATUS status_out;
450
if(!hnd->_internal.ctx) {
451
hnd->status = NT_STATUS_INVALID_HANDLE;
455
if(!op || !op->in.svc_hnd || !mem_ctx) {
456
hnd->status = NT_STATUS_INVALID_PARAMETER;
460
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
462
hnd->status = NT_STATUS_INVALID_HANDLE;
466
err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_CONTINUE, &status_out);
467
hnd->status = werror_to_ntstatus(err);
469
if(!NT_STATUS_IS_OK(hnd->status))
472
op->out.status = status_out;
474
if(op->in.timeout == 0)
477
return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &op->out.status);
480
int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op) {
481
struct rpc_pipe_client *pipe_hnd = NULL;
484
fstring disp_name_out;
489
if(!hnd->_internal.ctx) {
490
hnd->status = NT_STATUS_INVALID_HANDLE;
494
if(!op || !op->in.svc_hnd || !mem_ctx) {
495
hnd->status = NT_STATUS_INVALID_PARAMETER;
499
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
501
hnd->status = NT_STATUS_INVALID_HANDLE;
505
err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd, disp_name_out);
506
hnd->status = werror_to_ntstatus(err);
508
if(!NT_STATUS_IS_OK(hnd->status))
511
op->out.display_name = talloc_strdup(mem_ctx, disp_name_out);
513
if(!op->out.display_name) {
514
hnd->status = NT_STATUS_NO_MEMORY;
522
int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) {
523
struct rpc_pipe_client *pipe_hnd = NULL;
526
SERVICE_CONFIG config_out;
531
if(!hnd->_internal.ctx) {
532
hnd->status = NT_STATUS_INVALID_HANDLE;
536
if(!op || !op->in.svc_hnd || !mem_ctx) {
537
hnd->status = NT_STATUS_INVALID_PARAMETER;
541
pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
543
hnd->status = NT_STATUS_INVALID_HANDLE;
547
err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd, &config_out);
548
hnd->status = werror_to_ntstatus(err);
550
if(!NT_STATUS_IS_OK(hnd->status))
553
if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) {
554
hnd->status = NT_STATUS_NO_MEMORY;