1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/source3/services/svc_winreg_glue.c
Andreas Schneider 09dafc4a25 s3-rpc_server: Added a svcctl shutdown function.
Signed-off-by: Günther Deschner <gd@samba.org>
2011-02-07 12:32:01 +01:00

365 lines
8.8 KiB
C

/*
* Unix SMB/CIFS implementation.
*
* SVC winreg glue
*
* Copyright (c) 2005 Marcin Krzysztof Porwit
* Copyright (c) 2005 Gerald (Jerry) Carter
* Copyright (c) 2011 Andreas Schneider <asn@samba.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "services/services.h"
#include "services/svc_winreg_glue.h"
#include "rpc_client/cli_winreg_int.h"
#include "rpc_client/cli_winreg.h"
#include "../librpc/gen_ndr/ndr_winreg_c.h"
#include "../libcli/security/security.h"
#define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
struct security_descriptor* svcctl_gen_service_sd(TALLOC_CTX *mem_ctx)
{
struct security_descriptor *sd = NULL;
struct security_acl *theacl = NULL;
struct security_ace ace[4];
size_t sd_size;
size_t i = 0;
/* Basic access for everyone */
init_sec_ace(&ace[i++], &global_sid_World,
SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_READ_ACCESS, 0);
init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users,
SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_EXECUTE_ACCESS, 0);
init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators,
SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
/* Create the security descriptor */
theacl = make_sec_acl(mem_ctx,
NT4_ACL_REVISION,
i,
ace);
if (theacl == NULL) {
return NULL;
}
sd = make_sec_desc(mem_ctx,
SECURITY_DESCRIPTOR_REVISION_1,
SEC_DESC_SELF_RELATIVE,
NULL,
NULL,
NULL,
theacl,
&sd_size);
if (sd == NULL) {
return NULL;
}
return sd;
}
struct security_descriptor *svcctl_get_secdesc(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
const struct auth_serversupplied_info *server_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,
server_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_BADFILE)) {
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;
}
bool svcctl_set_secdesc(struct messaging_context *msg_ctx,
const struct auth_serversupplied_info *server_info,
const char *name,
struct security_descriptor *sd)
{
struct dcerpc_binding_handle *h = NULL;
uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
struct policy_handle hive_hnd, key_hnd;
char *key = NULL;
bool ok = false;
TALLOC_CTX *tmp_ctx;
NTSTATUS status;
WERROR result = WERR_OK;
tmp_ctx = talloc_stackframe();
if (tmp_ctx == NULL) {
return false;
}
key = talloc_asprintf(tmp_ctx, "%s\\%s", TOP_LEVEL_SERVICES_KEY, name);
if (key == NULL) {
goto done;
}
status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
server_info,
msg_ctx,
&h,
key,
false,
access_mask,
&hive_hnd,
&key_hnd,
&result);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
key, nt_errstr(status)));
goto done;
}
if (!W_ERROR_IS_OK(result)) {
DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
key, win_errstr(result)));
goto done;
}
if (is_valid_policy_hnd(&key_hnd)) {
dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
}
{
enum winreg_CreateAction action = REG_ACTION_NONE;
struct winreg_String wkey;
struct winreg_String wkeyclass;
wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key);
if (wkey.name == NULL) {
result = WERR_NOMEM;
goto done;
}
ZERO_STRUCT(wkeyclass);
wkeyclass.name = "";
status = dcerpc_winreg_CreateKey(h,
tmp_ctx,
&hive_hnd,
wkey,
wkeyclass,
0,
access_mask,
NULL,
&key_hnd,
&action,
&result);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
wkey.name, nt_errstr(status)));
goto done;
}
if (!W_ERROR_IS_OK(result)) {
DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
wkey.name, win_errstr(result)));
goto done;
}
status = dcerpc_winreg_set_sd(tmp_ctx,
h,
&key_hnd,
"Security",
sd,
&result);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
if (!W_ERROR_IS_OK(result)) {
goto done;
}
}
ok = true;
done:
if (is_valid_policy_hnd(&key_hnd)) {
dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
}
talloc_free(tmp_ctx);
return ok;
}
const char *svcctl_get_string_value(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
const struct auth_serversupplied_info *server_info,
const char *key_name,
const char *value_name)
{
struct dcerpc_binding_handle *h = NULL;
uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
struct policy_handle hive_hnd, key_hnd;
const char *data = NULL;
char *path = NULL;
TALLOC_CTX *tmp_ctx;
NTSTATUS status;
WERROR result = WERR_OK;
tmp_ctx = talloc_stackframe();
if (tmp_ctx == NULL) {
return NULL;
}
path = talloc_asprintf(tmp_ctx, "%s\\%s",
TOP_LEVEL_SERVICES_KEY, key_name);
if (path == NULL) {
goto done;
}
status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
server_info,
msg_ctx,
&h,
path,
false,
access_mask,
&hive_hnd,
&key_hnd,
&result);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
path, nt_errstr(status)));
goto done;
}
if (!W_ERROR_IS_OK(result)) {
DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
path, win_errstr(result)));
goto done;
}
status = dcerpc_winreg_query_sz(mem_ctx,
h,
&key_hnd,
value_name,
&data,
&result);
done:
talloc_free(tmp_ctx);
return data;
}
/********************************************************************
********************************************************************/
const char *svcctl_lookup_dispname(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
const struct auth_serversupplied_info *server_info,
const char *name)
{
const char *display_name = NULL;
display_name = svcctl_get_string_value(mem_ctx,
msg_ctx,
server_info,
name,
"DisplayName");
if (display_name == NULL) {
display_name = talloc_strdup(mem_ctx, name);
}
return display_name;
}
/********************************************************************
********************************************************************/
const char *svcctl_lookup_description(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
const struct auth_serversupplied_info *server_info,
const char *name)
{
const char *description = NULL;
description = svcctl_get_string_value(mem_ctx,
msg_ctx,
server_info,
name,
"Description");
if (description == NULL) {
description = talloc_strdup(mem_ctx, "Unix Service");
}
return description;
}
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */