static WERROR rcinit_status( const char *service, struct SERVICE_STATUS *status ) { char *command = NULL; int ret, fd; if (asprintf(&command, "%s/%s/%s status", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, service) < 0) { return WERR_NOT_ENOUGH_MEMORY; } /* we've already performed the access check when the service was opened */ /* assume as return code of 0 means that the service is ok. Anything else is STOPPED */ become_root(); ret = smbrun(command, &fd, NULL); unbecome_root(); DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); close(fd); SAFE_FREE(command); ZERO_STRUCTP( status ); status->type = SERVICE_TYPE_WIN32_SHARE_PROCESS; status->state = (ret == 0 ) ? SVCCTL_RUNNING : SVCCTL_STOPPED; status->controls_accepted = SVCCTL_ACCEPT_STOP | SVCCTL_ACCEPT_SHUTDOWN; return WERR_OK; }
static WERROR rcinit_status( const char *service, SERVICE_STATUS *status ) { char *command = NULL; int ret, fd; if (asprintf(&command, "%s/%s/%s status", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, service) < 0) { return WERR_NOMEM; } /* we've already performed the access check when the service was opened */ /* assume as return code of 0 means that the service is ok. Anything else is STOPPED */ become_root(); ret = smbrun( command , &fd ); unbecome_root(); DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); close(fd); SAFE_FREE(command); ZERO_STRUCTP( status ); status->type = 0x0020; status->state = (ret == 0 ) ? 0x0004 : 0x0001; status->controls_accepted = 0x0005; return WERR_OK; }
static WERROR rcinit_stop( const char *service, SERVICE_STATUS *status ) { char *command = NULL; int ret, fd; if (asprintf(&command, "%s/%s/%s stop", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, service) < 0) { return WERR_NOMEM; } /* we've already performed the access check when the service was opened */ become_root(); ret = smbrun( command , &fd ); unbecome_root(); DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); close(fd); SAFE_FREE(command); ZERO_STRUCTP( status ); status->type = 0x0020; status->state = (ret == 0 ) ? 0x0001 : 0x0004; status->controls_accepted = 0x0005; return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED; }
static WERROR rcinit_start( const char *service ) { char *command = NULL; int ret, fd; if (asprintf(&command, "%s/%s/%s start", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, service) < 0) { return WERR_NOT_ENOUGH_MEMORY; } /* we've already performed the access check when the service was opened */ become_root(); ret = smbrun(command, &fd, NULL); unbecome_root(); DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); close(fd); SAFE_FREE(command); return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED; }
static bool svcctl_add_service(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *h, struct policy_handle *hive_hnd, const char *key, uint32_t access_mask, const char *name) { enum winreg_CreateAction action = REG_ACTION_NONE; struct security_descriptor *sd = NULL; struct policy_handle key_hnd; struct winreg_String wkey; struct winreg_String wkeyclass; char *description = NULL; char *dname = NULL; char *ipath = NULL; bool ok = false; uint32_t i; NTSTATUS status; WERROR result = WERR_OK; ZERO_STRUCT(key_hnd); ZERO_STRUCT(wkey); wkey.name = talloc_asprintf(mem_ctx, "%s\\%s", key, name); if (wkey.name == NULL) { goto done; } ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; status = dcerpc_winreg_CreateKey(h, mem_ctx, hive_hnd, wkey, wkeyclass, 0, access_mask, NULL, &key_hnd, &action, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, win_errstr(result))); goto done; } /* These values are hardcoded in all QueryServiceConfig() replies. I'm just storing them here for cosmetic purposes */ status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "Start", SVCCTL_AUTO_START, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "Type", SERVICE_TYPE_WIN32_OWN_PROCESS, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "ErrorControl", SVCCTL_SVC_ERROR_NORMAL, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "ObjectName", "LocalSystem", &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } /* * Special considerations for internal services and the DisplayName * value. */ for (i = 0; builtin_svcs[i].servicename; i++) { if (strequal(name, builtin_svcs[i].servicename)) { ipath = talloc_asprintf(mem_ctx, "%s/%s/%s", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, builtin_svcs[i].daemon); description = talloc_strdup(mem_ctx, builtin_svcs[i].description); dname = talloc_strdup(mem_ctx, builtin_svcs[i].dispname); break; } } /* Default to an external service if we haven't found a match */ if (builtin_svcs[i].servicename == NULL) { struct rcinit_file_information *init_info = NULL; char *dispname = NULL; ipath = talloc_asprintf(mem_ctx, "%s/%s/%s", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, name); /* lookup common unix display names */ dispname = svcctl_get_common_service_dispname(mem_ctx, name); dname = talloc_strdup(mem_ctx, dispname ? dispname : ""); /* get info from init file itself */ if (read_init_file(mem_ctx, name, &init_info)) { description = talloc_strdup(mem_ctx, init_info->description); } else { description = talloc_strdup(mem_ctx, "External Unix Service"); } } if (ipath == NULL || dname == NULL || description == NULL) { goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "DisplayName", dname, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "ImagePath", ipath, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "Description", description, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } sd = svcctl_gen_service_sd(mem_ctx); if (sd == NULL) { DEBUG(0, ("add_new_svc_name: Failed to create default " "sec_desc!\n")); goto done; } if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result); } ZERO_STRUCT(key_hnd); ZERO_STRUCT(wkey); wkey.name = talloc_asprintf(mem_ctx, "%s\\%s\\Security", key, name); if (wkey.name == NULL) { result = WERR_NOMEM; goto done; } ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; status = dcerpc_winreg_CreateKey(h, mem_ctx, hive_hnd, wkey, wkeyclass, 0, access_mask, NULL, &key_hnd, &action, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, win_errstr(result))); goto done; } status = dcerpc_winreg_set_sd(mem_ctx, h, &key_hnd, "Security", sd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } ok = true; done: if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result); } return ok; }
static bool read_init_file(TALLOC_CTX *mem_ctx, const char *servicename, struct rcinit_file_information **service_info) { struct rcinit_file_information *info = NULL; char *filepath = NULL; char str[1024]; XFILE *f = NULL; char *p = NULL; info = talloc_zero(mem_ctx, struct rcinit_file_information); if (info == NULL) { return false; } /* attempt the file open */ filepath = talloc_asprintf(mem_ctx, "%s/%s/%s", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, servicename); if (filepath == NULL) { return false; } f = x_fopen( filepath, O_RDONLY, 0 ); if (f == NULL) { DEBUG(0,("read_init_file: failed to open [%s]\n", filepath)); return false; } while ((x_fgets(str, sizeof(str) - 1, f)) != NULL) { /* ignore everything that is not a full line comment starting with a '#' */ if (str[0] != '#') { continue; } /* Look for a line like '^#.*Description:' */ p = strstr(str, "Description:"); if (p != NULL) { char *desc; p += strlen( "Description:" ) + 1; if (p == NULL) { break; } desc = svcctl_cleanup_string(mem_ctx, p); if (desc != NULL) { info->description = talloc_strdup(info, desc); } } } x_fclose(f); if (info->description == NULL) { info->description = talloc_strdup(info, "External Unix Service"); if (info->description == NULL) { return false; } } *service_info = info; return true; }