diff -Nur samba-3.0.28a.vanilla/source/include/rpc_svcctl.h samba-3.0.28a/source/include/rpc_svcctl.h --- samba-3.0.28a.vanilla/source/include/rpc_svcctl.h 2008-03-08 17:33:34.000000000 +0200 +++ samba-3.0.28a/source/include/rpc_svcctl.h 2008-03-13 11:42:55.000000000 +0200 @@ -26,11 +26,17 @@ #define SVCCTL_CLOSE_SERVICE 0x00 #define SVCCTL_CONTROL_SERVICE 0x01 +/* danny.tylman@insightix.com: start */ +#define SVCCTL_DELETE_SERVICE 0x02 +/* danny.tylman@insightix.com: end */ #define SVCCTL_LOCK_SERVICE_DB 0x03 #define SVCCTL_QUERY_SERVICE_SEC 0x04 #define SVCCTL_SET_SERVICE_SEC 0x05 #define SVCCTL_QUERY_STATUS 0x06 #define SVCCTL_UNLOCK_SERVICE_DB 0x08 +/* danny.tylman@insightix.com: start */ +#define SVCCTL_CREATE_SERVICE_W 0x0c +/* danny.tylman@insightix.com: end */ #define SVCCTL_ENUM_DEPENDENT_SERVICES_W 0x0d #define SVCCTL_ENUM_SERVICES_STATUS_W 0x0e #define SVCCTL_OPEN_SCMANAGER_W 0x0f @@ -252,6 +258,19 @@ /**************************/ +/* danny.tylman@insightix.com: start */ +typedef struct { + POLICY_HND handle; +} SVCCTL_Q_DELETE_SERVICE; + +typedef struct { + WERROR status; +} SVCCTL_R_DELETE_SERVICE; + +/**************************/ +/* danny.tylman@insightix.com: end */ +/**************************/ + typedef struct { POLICY_HND handle; uint32 parmcount; @@ -413,6 +432,31 @@ WERROR status; } SVCCTL_R_SET_SERVICE_SEC; +/* danny.tylman@insightix.com: start */ +/**************************/ + +typedef struct { + POLICY_HND handle; + UNISTR2 service_name; + UNISTR2 display_name; + uint32 access; + uint32 service_type; + uint32 start_type; + uint32 error_control; + UNISTR2 binary_pathname; + UNISTR2 load_order_group; + uint32* tag_id; + UNISTR2 dependencies; + UNISTR2 service_start_name; + UNISTR2 password; +} SVCCTL_Q_CREATE_SERVICE; + +typedef struct { + POLICY_HND handle; + uint32 tag_id; + WERROR status; +} SVCCTL_R_CREATE_SERVICE; +/* danny.tylman@insightix.com: end */ #endif /* _RPC_SVCCTL_H */ diff -Nur samba-3.0.28a.vanilla/source/rpc_client/cli_svcctl.c samba-3.0.28a/source/rpc_client/cli_svcctl.c --- samba-3.0.28a.vanilla/source/rpc_client/cli_svcctl.c 2008-03-08 17:33:35.000000000 +0200 +++ samba-3.0.28a/source/rpc_client/cli_svcctl.c 2008-03-13 11:53:03.000000000 +0200 @@ -333,6 +333,32 @@ /******************************************************************* *******************************************************************/ +/* danny.tylman@insightix.com: start */ +WERROR rpccli_svcctl_delete_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService ) +{ + SVCCTL_Q_DELETE_SERVICE in; + SVCCTL_R_DELETE_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_DELETE_SERVICE, + in, out, + qbuf, rbuf, + svcctl_io_q_delete_service, + svcctl_io_r_delete_service, + WERR_GENERAL_FAILURE ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ +/* danny.tylman@insightix.com: end */ WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, const char **parm_array, uint32 parmcount ) @@ -435,3 +461,49 @@ return out.status; } +/* danny.tylman@insightix.com: start */ +/*******************************************************************/ + +WERROR rpccli_svcctl_create_service(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, POLICY_HND *hService, fstring servicename, fstring displayname, fstring binarypath) +{ + SVCCTL_Q_CREATE_SERVICE in; + SVCCTL_R_CREATE_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + /* uint32 types */ + in.access = SERVICE_ALL_ACCESS; + in.service_type = SERVICE_TYPE_WIN32_OWN_PROCESS; + in.start_type = SVCCTL_DEMAND_START; + in.error_control = SVCCTL_SVC_ERROR_NORMAL; + + /* UNISTR2 types */ + init_unistr2(&(in.service_name),servicename,UNI_STR_TERMINATE); + init_unistr2(&(in.display_name),displayname,UNI_STR_TERMINATE);; + init_unistr2(&(in.binary_pathname),binarypath,UNI_STR_TERMINATE); + init_unistr2(&(in.load_order_group),0,UNI_STR_TERMINATE); + init_unistr2(&(in.dependencies),0,UNI_STR_TERMINATE); + init_unistr2(&(in.service_start_name),0,UNI_STR_TERMINATE); + init_unistr2(&(in.password),0,UNI_STR_TERMINATE); + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CREATE_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_create_service, + svcctl_io_r_create_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hService, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/* danny.tylman@insightix.com: end */ diff -Nur samba-3.0.28a.vanilla/source/rpc_parse/parse_svcctl.c samba-3.0.28a/source/rpc_parse/parse_svcctl.c --- samba-3.0.28a.vanilla/source/rpc_parse/parse_svcctl.c 2008-03-08 17:33:36.000000000 +0200 +++ samba-3.0.28a/source/rpc_parse/parse_svcctl.c 2008-03-13 12:20:39.947395587 +0200 @@ -245,6 +245,103 @@ /******************************************************************* ********************************************************************/ +/* danny.tylman@insightix.com: start */ +BOOL svcctl_io_q_create_service(const char *desc, SVCCTL_Q_CREATE_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_create_service"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!smb_io_pol_hnd("handle", &q_u->handle, ps, depth)) + return False; + + if (!smb_io_unistr2("service_name", &(q_u->service_name), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + + uint32 unknown = 0x41577C; + if (!prs_uint32("unknown", ps, depth, &unknown)) + return False; + + if (!smb_io_unistr2("display_name", &(q_u->display_name), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + + if (!prs_uint32("access", ps, depth, &(q_u->access))) + return False; + if (!prs_uint32("service_type", ps, depth, &(q_u->service_type))) + return False; + if (!prs_uint32("start_type", ps, depth, &(q_u->start_type))) + return False; + if (!prs_uint32("error_control", ps, depth, &(q_u->error_control))) + return False; + if (!smb_io_unistr2("binary_pathname", &(q_u->binary_pathname), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + if (!smb_io_unistr2("load_order_group", &(q_u->load_order_group), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + if (q_u->tag_id) + { + if (!prs_uint32("tag_id", ps, depth, q_u->tag_id)) + return False; + } + if (!smb_io_unistr2("dependencies", &(q_u->dependencies), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + if (!smb_io_unistr2("service_start_name", &(q_u->service_start_name), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + if (!smb_io_unistr2("password", &(q_u->password), true, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + + +BOOL svcctl_io_r_create_service(const char *desc, SVCCTL_R_CREATE_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_create_service"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!smb_io_pol_hnd("service_pol", &r_u->handle, ps, depth)) + return False; + + if (!prs_uint32("tag_id", ps, depth, &r_u->tag_id)) + return False; + + if (!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ +/* danny.tylman@insightix.com: end */ BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u, prs_struct *ps, int depth) { @@ -570,6 +667,45 @@ } +/* danny.tylman@insightix.com: start */ +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_delete_service(const char *desc, SVCCTL_Q_DELETE_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_delete_service"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_delete_service(const char *desc, SVCCTL_R_DELETE_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_start_service"); + depth++; + + if (!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/* danny.tylman@insightix.com: end */ /******************************************************************* ********************************************************************/ diff -Nur samba-3.0.28a.vanilla/source/utils/net.c samba-3.0.28a/source/utils/net.c --- samba-3.0.28a.vanilla/source/utils/net.c 2008-03-08 17:56:27.000000000 +0200 +++ samba-3.0.28a/source/utils/net.c 2008-03-11 15:43:13.000000000 +0200 @@ -450,13 +450,19 @@ return False; } +/* danny.tylman@insightix.com - start */ struct cli_state *net_make_ipc_connection( unsigned flags ) { - return net_make_ipc_connection_ex( NULL, NULL, NULL, flags ); + return net_make_ipc_connection_status( flags, NULL ); +} + +struct cli_state *net_make_ipc_connection_status( unsigned flags, NTSTATUS* out_status) +{ + return net_make_ipc_connection_ex( NULL, NULL, NULL, flags, out_status ); } struct cli_state *net_make_ipc_connection_ex( const char *domain, const char *server, - struct in_addr *ip, unsigned flags) + struct in_addr *ip, unsigned flags, NTSTATUS* out_status) { char *server_name = NULL; struct in_addr server_ip; @@ -466,6 +472,10 @@ if ( !server || !ip ) { if (!net_find_server(domain, flags, &server_ip, &server_name)) { d_fprintf(stderr, "Unable to find a suitable server\n"); + if (out_status) + { + memcpy(out_status,&NT_STATUS_BAD_NETWORK_PATH, sizeof(NTSTATUS)); + } return NULL; } } else { diff -Nur samba-3.0.28a.vanilla/source/utils/net_rpc.c samba-3.0.28a/source/utils/net_rpc.c --- samba-3.0.28a.vanilla/source/utils/net_rpc.c 2008-03-08 17:56:27.000000000 +0200 +++ samba-3.0.28a/source/utils/net_rpc.c 2008-03-11 15:44:34.000000000 +0200 @@ -186,6 +186,96 @@ talloc_destroy(mem_ctx); return (!NT_STATUS_IS_OK(nt_status)); } +/* danny.tylman@insightix.com: start */ +NTSTATUS run_rpc_command_status(struct cli_state *cli_arg, + const int pipe_idx, + int conn_flags, + rpc_command_fn fn, + int argc, + const char **argv) +{ + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; + TALLOC_CTX *mem_ctx; + NTSTATUS nt_status = NT_STATUS_OK; + DOM_SID *domain_sid; + char *domain_name; + + /* make use of cli_state handed over as an argument, if possible */ + if (!cli_arg) { + cli = net_make_ipc_connection_status(conn_flags,&nt_status); + } else { + cli = cli_arg; + } + + if (!cli) { + return nt_status; + } + + /* Create mem_ctx */ + + if (!(mem_ctx = talloc_init("run_rpc_command"))) { + DEBUG(0, ("talloc_init() failed\n")); + cli_shutdown(cli); + return NT_STATUS_UNSUCCESSFUL; /* hhmmmf */ + } + + nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid, + &domain_name); + if (!NT_STATUS_IS_OK(nt_status)) { + cli_shutdown(cli); + return nt_status; + } + + if (!(conn_flags & NET_FLAGS_NO_PIPE)) { + if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) { + /* Always try and create an schannel netlogon pipe. */ + pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx, + PIPE_AUTH_LEVEL_PRIVACY, + domain_name, + &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n", + nt_errstr(nt_status) )); + cli_shutdown(cli); + return nt_status; + } + } else { + pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise pipe %s. Error was %s\n", + cli_get_pipe_name(pipe_idx), + nt_errstr(nt_status) )); + cli_shutdown(cli); + return nt_status; + } + } + } + + nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status))); + } else { + DEBUG(5, ("rpc command function succedded\n")); + } + + if (!(conn_flags & NET_FLAGS_NO_PIPE)) { + if (pipe_hnd) { + cli_rpc_pipe_close(pipe_hnd); + } + } + + /* close the connection only if it was opened here */ + if (!cli_arg) { + cli_shutdown(cli); + } + + talloc_destroy(mem_ctx); + return nt_status; +} + +/* danny.tylman@insightix.com: end*/ /** * Force a change of the trust acccount password. diff -Nur samba-3.0.28a.vanilla/source/utils/net_rpc_join.c samba-3.0.28a/source/utils/net_rpc_join.c --- samba-3.0.28a.vanilla/source/utils/net_rpc_join.c 2008-03-08 17:56:27.000000000 +0200 +++ samba-3.0.28a/source/utils/net_rpc_join.c 2008-03-11 16:08:21.000000000 +0200 @@ -50,7 +50,7 @@ NTSTATUS ntret = NT_STATUS_UNSUCCESSFUL; /* Connect to remote machine */ - if (!(cli = net_make_ipc_connection_ex(domain, server, ip, (NET_FLAGS_ANONYMOUS|NET_FLAGS_PDC)))) { + if (!(cli = net_make_ipc_connection_ex(domain, server, ip, (NET_FLAGS_ANONYMOUS|NET_FLAGS_PDC),NULL))) { return -1; } diff -Nur samba-3.0.28a.vanilla/source/utils/net_rpc_service.c samba-3.0.28a/source/utils/net_rpc_service.c --- samba-3.0.28a.vanilla/source/utils/net_rpc_service.c 2008-03-08 17:33:37.000000000 +0200 +++ samba-3.0.28a/source/utils/net_rpc_service.c 2008-03-13 11:49:24.000000000 +0200 @@ -406,6 +406,65 @@ return werror_to_ntstatus(result); } +/* danny.tylman@insightix.com: start */ +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_delete_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) +{ + POLICY_HND hSCM, hService; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + uint32 state = 0; + + if (argc != 1 ) { + d_printf("Usage: net rpc service start \n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Open the Service */ + + result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, + servicename, SERVICE_ALL_ACCESS ); + + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Failed to open service. [%s]\n", dos_errstr(result)); + goto done; + } + + /* get the status */ + + result = rpccli_svcctl_delete_service(pipe_hnd, mem_ctx, &hService ); + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Delete status request failed. [%s]\n", dos_errstr(result)); + goto done; + } + else { + d_printf("Successfully deleted service: %s\n", servicename ); + } +done: + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} +/* danny.tylman@insightix.com: end */ + /******************************************************************** ********************************************************************/ @@ -469,6 +528,77 @@ return werror_to_ntstatus(result); } +/* danny.tylman@insightix.com: start */ +/******************************************************************************************/ +static NTSTATUS rpc_service_create_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) +{ + POLICY_HND hSCM; + POLICY_HND hService; + WERROR result = WERR_GENERAL_FAILURE; + + if (argc != 3 ) { + d_printf("Usage: net rpc service create \n"); + return NT_STATUS_OK; + } + + fstring service_name, display_name, binary_path; + fstrcpy (service_name, argv[0] ); + fstrcpy (display_name, argv[1] ); + fstrcpy (binary_path , argv[2] ); + + /* Open the Service Control Manager */ + + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_CREATE_SERVICE); + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Create the Service */ + result = rpccli_svcctl_create_service(pipe_hnd, mem_ctx, &hSCM, &hService, service_name, display_name, binary_path ); + + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Failed to create service. [%s]\n", dos_errstr(result)); + goto done; + } + else + { + d_printf("Successfully created service: %s\n", service_name ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService ); + } + + done: + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_delete( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_delete_internal, argc, argv ); +} + + +/******************************************************************** +********************************************************************/ + +static int rpc_service_create(int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_create_internal, argc, argv ); +} + +/* danny.tylman@insightix.com: end */ /******************************************************************** ********************************************************************/ @@ -519,8 +649,10 @@ static int rpc_service_status( int argc, const char **argv ) { - return run_rpc_command( NULL, PI_SVCCTL, 0, - rpc_service_status_internal, argc, argv ); +/* danny.tylman@insightix.com: start */ + NTSTATUS stat = run_rpc_command_status( NULL, PI_SVCCTL, 0, rpc_service_status_internal, argc, argv ); + return (int)stat.v; +/* danny.tylman@insightix.com: end */ } /******************************************************************** @@ -535,6 +667,10 @@ d_printf("net rpc service resume Resume a paused service\n"); d_printf("net rpc service status View the current status of a service\n"); +/* danny.tylman@insightix.com: start */ + d_printf("net rpc service create Create (install) a service\n"); + d_printf("net rpc service delete Delete (uninstall) a service\n"); +/* danny.tylman@insightix.com: end */ return -1; } @@ -550,6 +686,10 @@ {"pause", rpc_service_pause}, {"resume", rpc_service_resume}, {"status", rpc_service_status}, +/* danny.tylman@insightix.com: start */ + {"create", rpc_service_create}, + {"delete", rpc_service_delete}, +/* danny.tylman@insightix.com: end */ {NULL, NULL} };