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
Volker Lendecke a63aafb05d srcctl3: Improve debug messages
A customer's syslog was filled with

_svcctl_OpenServiceW: Failed to get a valid security descriptor

messages. This improves the messages to give info about which service failed
with which error code. Also, it makes OpenServiceW fail with the same error
message Windows fails with for unknown services.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>

Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Tue Jan 16 02:43:03 CET 2018 on sn-devel-144
2018-01-16 02:43:03 +01:00

371 lines
8.9 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;
}
WERROR svcctl_get_secdesc(struct messaging_context *msg_ctx,
const struct auth_session_info *session_info,
const char *name,
TALLOC_CTX *mem_ctx,
struct security_descriptor **psd)
{
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 WERR_NOT_ENOUGH_MEMORY;
}
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 WERR_INTERNAL_ERROR;
}
if (!W_ERROR_IS_OK(result)) {
DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n",
key, win_errstr(result)));
return result;
}
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 WERR_INTERNAL_ERROR;
}
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 result;
}
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);
if (sd == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
done:
*psd = sd;
return WERR_OK;
}
bool svcctl_set_secdesc(struct messaging_context *msg_ctx,
const struct auth_session_info *session_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;
struct policy_handle key_hnd = { 0, };
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,
session_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 = { 0, };
struct winreg_String wkeyclass;
wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key);
if (wkey.name == NULL) {
result = WERR_NOT_ENOUGH_MEMORY;
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_session_info *session_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,
session_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_session_info *session_info,
const char *name)
{
const char *display_name = NULL;
display_name = svcctl_get_string_value(mem_ctx,
msg_ctx,
session_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_session_info *session_info,
const char *name)
{
const char *description = NULL;
description = svcctl_get_string_value(mem_ctx,
msg_ctx,
session_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: */