diff options
-rw-r--r-- | source3/include/rpc_svcctl.h | 2 | ||||
-rw-r--r-- | source3/rpc_client/cli_svcctl.c | 192 | ||||
-rw-r--r-- | source3/rpc_parse/parse_svcctl.c | 2 | ||||
-rw-r--r-- | source3/utils/net_rpc_service.c | 100 |
4 files changed, 281 insertions, 15 deletions
diff --git a/source3/include/rpc_svcctl.h b/source3/include/rpc_svcctl.h index 069d544b1f..6fcfd6f52d 100644 --- a/source3/include/rpc_svcctl.h +++ b/source3/include/rpc_svcctl.h @@ -148,7 +148,7 @@ typedef struct { typedef struct { POLICY_HND handle; UNISTR2 servicename; - uint32 access_mask; + uint32 access; } SVCCTL_Q_OPEN_SERVICE; typedef struct { diff --git a/source3/rpc_client/cli_svcctl.c b/source3/rpc_client/cli_svcctl.c index 74d6483b17..c9fdc61379 100644 --- a/source3/rpc_client/cli_svcctl.c +++ b/source3/rpc_client/cli_svcctl.c @@ -22,6 +22,42 @@ #include "includes.h" #include "rpc_client.h" +struct svc_state_msg { + uint32 flag; + const char *message; +}; + +static struct svc_state_msg state_msg_table[] = { + { SVCCTL_STOPPED, "SVCCTL_STOPPED" }, + { SVCCTL_START_PENDING, "SVCCTL_START_PENDING" }, + { SVCCTL_STOP_PENDING, "SVCCTL_STOP_PENDING" }, + { SVCCTL_RUNNING, "SVCCTL_RUNNING" }, + { SVCCTL_CONTINUE_PENDING, "SVCCTL_CONTINUE_PENDING" }, + { SVCCTL_PAUSE_PENDING, "SVCCTL_PAUSE_PENDING" }, + { SVCCTL_PAUSED, "SVCCTL_PAUSED" }, + { 0, NULL } +}; + + +/******************************************************************** +********************************************************************/ +const char* svc_status_string( uint32 state ) +{ + static fstring msg; + int i; + + fstr_sprintf( msg, "Unknown State [%d]", state ); + + for ( i=0; state_msg_table[i].message; i++ ) { + if ( state_msg_table[i].flag == state ) { + fstrcpy( msg, state_msg_table[i].message ); + break; + } + } + + return msg; +} + /******************************************************************** ********************************************************************/ @@ -67,6 +103,39 @@ WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ +WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, POLICY_HND *hService, + const char *servicename, uint32 access_desired ) +{ + SVCCTL_Q_OPEN_SERVICE in; + SVCCTL_R_OPEN_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE ); + in.access = access_desired; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_open_service, + svcctl_io_r_open_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hService, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/******************************************************************** +********************************************************************/ + WERROR close_service_handle( struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService ) { SVCCTL_Q_CLOSE_SERVICE in; @@ -125,7 +194,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx /* second time with correct buffer size...should be ok */ - if ( !W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) { in.buffer_size = out.needed; CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, @@ -150,33 +219,98 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx *service_array = services; *returned = out.returned; - - return out.status; } /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_start_service(struct cli_state *cli, TALLOC_CTX *mem_ctx ) +WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, SERVICE_STATUS *status ) { + SVCCTL_Q_QUERY_STATUS in; + SVCCTL_R_QUERY_STATUS out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, + in, out, + qbuf, rbuf, + svcctl_io_q_query_status, + svcctl_io_r_query_status, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; - return WERR_OK; + memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) ); + + return out.status; } /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_control_service(struct cli_state *cli, TALLOC_CTX *mem_ctx ) +WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, SERVICE_CONFIG *config ) { + SVCCTL_Q_QUERY_SERVICE_CONFIG in; + SVCCTL_R_QUERY_SERVICE_CONFIG out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.buffer_size = 0; + + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + in, out, + qbuf, rbuf, + svcctl_io_q_query_service_config, + svcctl_io_r_query_service_config, + WERR_GENERAL_FAILURE ); + + if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + in.buffer_size = out.needed; - return WERR_OK; + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + in, out, + qbuf, rbuf, + svcctl_io_q_query_service_config, + svcctl_io_r_query_service_config, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( config, &out.config, sizeof(SERVICE_CONFIG) ); + + config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + + copy_unistr2( config->executablepath, out.config.executablepath ); + copy_unistr2( config->loadordergroup, out.config.loadordergroup ); + copy_unistr2( config->dependencies, out.config.dependencies ); + copy_unistr2( config->startname, out.config.startname ); + copy_unistr2( config->displayname, out.config.displayname ); + + return out.status; } /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_query_status(struct cli_state *cli, TALLOC_CTX *mem_ctx ) +WERROR cli_svcctl_start_service(struct cli_state *cli, TALLOC_CTX *mem_ctx ) { return WERR_OK; @@ -185,18 +319,54 @@ WERROR cli_svcctl_query_status(struct cli_state *cli, TALLOC_CTX *mem_ctx ) /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx ) +WERROR cli_svcctl_control_service(struct cli_state *cli, TALLOC_CTX *mem_ctx ) { return WERR_OK; } + /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx ) +WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, fstring displayname ) { + SVCCTL_Q_GET_DISPLAY_NAME in; + SVCCTL_R_GET_DISPLAY_NAME out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.display_name_len = 0; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + + /* second time with correct buffer size...should be ok */ + + if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + in.display_name_len = out.display_name_len; - return WERR_OK; + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + rpcstr_pull( displayname, out.displayname.buffer, sizeof(displayname), -1, STR_TERMINATE ); + + return out.status; } diff --git a/source3/rpc_parse/parse_svcctl.c b/source3/rpc_parse/parse_svcctl.c index f13f01a05a..acebcf34c6 100644 --- a/source3/rpc_parse/parse_svcctl.c +++ b/source3/rpc_parse/parse_svcctl.c @@ -325,7 +325,7 @@ BOOL svcctl_io_q_open_service(const char *desc, SVCCTL_Q_OPEN_SERVICE *q_u, prs_ if(!prs_align(ps)) return False; - if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask)) + if(!prs_uint32("access", ps, depth, &q_u->access)) return False; return True; diff --git a/source3/utils/net_rpc_service.c b/source3/utils/net_rpc_service.c index d3343e92ad..5e933e76cd 100644 --- a/source3/utils/net_rpc_service.c +++ b/source3/utils/net_rpc_service.c @@ -70,6 +70,102 @@ done: return werror_to_ntstatus(result); } +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM, hService; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + SERVICE_STATUS service_status; + SERVICE_CONFIG config; + fstring ascii_string; + + if (argc != 1 ) { + d_printf("Usage: net rpc service status <service>\n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Open the Service */ + + result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, servicename, + (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG) ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open service. [%s]\n", dos_errstr(result)); + goto done; + } + + /* get the status */ + + result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Query status request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + d_printf("%s service is %s.\n", servicename, svc_status_string(service_status.state)); + + /* get the config */ + + result = cli_svcctl_query_config( cli, mem_ctx, &hService, &config ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Query config request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + /* print out the configuration information for the service */ + + d_printf("Configuration details:\n"); + d_printf("\tService Type = 0x%x\n", config.service_type); + d_printf("\tStart Type = 0x%x\n", config.start_type); + d_printf("\tError Control = 0x%x\n", config.error_control); + d_printf("\tTag ID = 0x%x\n", config.tag_id); + + if ( config.executablepath ) { + rpcstr_pull( ascii_string, config.executablepath->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tExecutable Path = %s\n", ascii_string); + } + + if ( config.loadordergroup ) { + rpcstr_pull( ascii_string, config.loadordergroup->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tLoad Order Group = %s\n", ascii_string); + } + + if ( config.dependencies ) { + rpcstr_pull( ascii_string, config.dependencies->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tDependencies = %s\n", ascii_string); + } + + if ( config.startname ) { + rpcstr_pull( ascii_string, config.startname->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tStart Name = %s\n", ascii_string); + } + + if ( config.displayname ) { + rpcstr_pull( ascii_string, config.displayname->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tDisplay Name = %s\n", ascii_string); + } + +done: + close_service_handle( cli, mem_ctx, &hService ); + close_service_handle( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} /******************************************************************** ********************************************************************/ @@ -112,8 +208,8 @@ static int rpc_service_pause( int argc, const char **argv ) static int rpc_service_status( int argc, const char **argv ) { - d_printf("not implemented\n"); - return 0; + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_status_internal, argc, argv ); } /******************************************************************** |