mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
8f39b2fd24
Guenther Signed-off-by: Guenther Deschner <gd@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
366 lines
8.8 KiB
C
366 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_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;
|
|
}
|
|
|
|
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: */
|