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; }
struct security_descriptor *svcctl_get_secdesc(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, const struct auth_session_info *session_info, const char *name) { struct dcerpc_binding_handle *h = NULL; uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED; struct policy_handle hive_hnd, key_hnd; struct security_descriptor *sd = NULL; char *key = NULL; NTSTATUS status; WERROR result = WERR_OK; key = talloc_asprintf(mem_ctx, "%s\\%s\\Security", TOP_LEVEL_SERVICES_KEY, name); if (key == NULL) { return NULL; } status = dcerpc_winreg_int_hklm_openkey(mem_ctx, session_info, msg_ctx, &h, key, false, access_mask, &hive_hnd, &key_hnd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n", key, nt_errstr(status))); return NULL; } if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n", key, win_errstr(result))); return NULL; } status = dcerpc_winreg_query_sd(mem_ctx, h, &key_hnd, "Security", &sd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': " "%s\n", nt_errstr(status))); return NULL; } if (W_ERROR_EQUAL(result, WERR_FILE_NOT_FOUND)) { goto fallback_to_default_sd; } else if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': " "%s\n", win_errstr(result))); return NULL; } goto done; fallback_to_default_sd: DEBUG(6, ("svcctl_get_secdesc: constructing default secdesc for " "service [%s]\n", name)); sd = svcctl_gen_service_sd(mem_ctx); done: return sd; }