mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
a63aafb05d
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
371 lines
8.9 KiB
C
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: */
|