mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r19963: Add 'registry shares = yes' and registry key security descriptors.
(This used to be commit 6cab254c49
)
This commit is contained in:
parent
3fda843ac1
commit
575845ccbe
@ -321,7 +321,8 @@ REGOBJS_OBJ = registry/reg_objects.o
|
||||
|
||||
REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \
|
||||
registry/reg_db.o registry/reg_eventlog.o registry/reg_shares.o \
|
||||
registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o
|
||||
registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o \
|
||||
registry/reg_smbconf.o
|
||||
|
||||
RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o librpc/gen_ndr/srv_lsa.o
|
||||
|
||||
|
@ -98,6 +98,7 @@ typedef struct {
|
||||
#define KEY_PRINTING_PORTS "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports"
|
||||
#define KEY_EVENTLOG "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Eventlog"
|
||||
#define KEY_SHARES "HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares"
|
||||
#define KEY_SMBCONF "HKLM\\SOFTWARE\\Samba\\smbconf"
|
||||
#define KEY_TREE_ROOT ""
|
||||
|
||||
/*
|
||||
@ -121,7 +122,13 @@ typedef struct {
|
||||
int (*fetch_values) ( const char *key, REGVAL_CTR *val );
|
||||
BOOL (*store_subkeys)( const char *key, REGSUBKEY_CTR *subkeys );
|
||||
BOOL (*store_values)( const char *key, REGVAL_CTR *val );
|
||||
BOOL (*reg_access_check)( const char *keyname, uint32 requested, uint32 *granted, NT_USER_TOKEN *token );
|
||||
BOOL (*reg_access_check)( const char *keyname, uint32 requested,
|
||||
uint32 *granted,
|
||||
const NT_USER_TOKEN *token );
|
||||
WERROR (*get_secdesc)(TALLOC_CTX *mem_ctx, const char *key,
|
||||
struct security_descriptor **psecdesc);
|
||||
WERROR (*set_secdesc)(const char *key,
|
||||
struct security_descriptor *sec_desc);
|
||||
} REGISTRY_OPS;
|
||||
|
||||
typedef struct {
|
||||
|
@ -216,16 +216,16 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
|
||||
dst->sacl = NULL;
|
||||
dst->dacl = NULL;
|
||||
|
||||
if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
|
||||
if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
|
||||
goto error_exit;
|
||||
|
||||
if(grp_sid && ((dst->group_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
|
||||
if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
|
||||
goto error_exit;
|
||||
|
||||
if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
|
||||
if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
|
||||
goto error_exit;
|
||||
|
||||
if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
|
||||
if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
|
||||
goto error_exit;
|
||||
|
||||
offset = SEC_DESC_HEADER_SIZE;
|
||||
@ -274,6 +274,63 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
|
||||
src->dacl, &dummy);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Convert a secdesc into a byte stream
|
||||
********************************************************************/
|
||||
NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
|
||||
struct security_descriptor *secdesc,
|
||||
uint8 **data, size_t *len)
|
||||
{
|
||||
prs_struct ps;
|
||||
|
||||
if (!prs_init(&ps, sec_desc_size(secdesc), mem_ctx, MARSHALL)) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
|
||||
prs_mem_free(&ps);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!(*data = (uint8 *)talloc_memdup(mem_ctx, ps.data_p,
|
||||
prs_offset(&ps)))) {
|
||||
prs_mem_free(&ps);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*len = prs_offset(&ps);
|
||||
prs_mem_free(&ps);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Parse a byte stream into a secdesc
|
||||
********************************************************************/
|
||||
NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
|
||||
struct security_descriptor **psecdesc)
|
||||
{
|
||||
prs_struct ps;
|
||||
struct security_descriptor *secdesc = NULL;
|
||||
|
||||
if (!(secdesc = TALLOC_ZERO_P(mem_ctx, struct security_descriptor))) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!prs_init(&ps, 0, secdesc, UNMARSHALL)) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
prs_give_memory(&ps, (char *)data, len, False);
|
||||
|
||||
if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
prs_mem_free(&ps);
|
||||
*psecdesc = secdesc;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Creates a SEC_DESC structure with typical defaults.
|
||||
********************************************************************/
|
||||
|
@ -304,6 +304,7 @@ typedef struct {
|
||||
BOOL bASUSupport;
|
||||
BOOL bUsershareOwnerOnly;
|
||||
BOOL bUsershareAllowGuests;
|
||||
BOOL bRegistryShares;
|
||||
int restrict_anonymous;
|
||||
int name_cache_timeout;
|
||||
int client_signing;
|
||||
@ -1225,6 +1226,7 @@ static struct parm_struct parm_table[] = {
|
||||
{"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
|
||||
{"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"registry shares", P_BOOL, P_GLOBAL, &Globals.bRegistryShares, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED},
|
||||
@ -1652,6 +1654,9 @@ static void init_globals(BOOL first_time_only)
|
||||
Globals.bUsershareOwnerOnly = True;
|
||||
/* By default disallow guest access to usershares. */
|
||||
Globals.bUsershareAllowGuests = False;
|
||||
|
||||
/* By default no shares out of the registry */
|
||||
Globals.bRegistryShares = False;
|
||||
}
|
||||
|
||||
static TALLOC_CTX *lp_talloc;
|
||||
@ -1860,6 +1865,7 @@ FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList
|
||||
|
||||
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
|
||||
|
||||
FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
|
||||
FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
|
||||
FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
|
||||
FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
|
||||
@ -2606,6 +2612,10 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService,
|
||||
|
||||
int lp_add_service(const char *pszService, int iDefaultService)
|
||||
{
|
||||
if (iDefaultService < 0) {
|
||||
return add_a_service(&sDefault, pszService);
|
||||
}
|
||||
|
||||
return (add_a_service(ServicePtrs[iDefaultService], pszService));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ static TDB_CONTEXT *tdb_reg;
|
||||
static int tdb_refcount;
|
||||
|
||||
#define VALUE_PREFIX "SAMBA_REGVAL"
|
||||
#define SECDESC_PREFIX "SAMBA_SECDESC"
|
||||
|
||||
/* List the deepest path into the registry. All part components will be created.*/
|
||||
|
||||
@ -46,6 +47,7 @@ static const char *builtin_registry_paths[] = {
|
||||
KEY_PRINTING,
|
||||
KEY_SHARES,
|
||||
KEY_EVENTLOG,
|
||||
KEY_SMBCONF,
|
||||
"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
|
||||
"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",
|
||||
"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
|
||||
@ -661,6 +663,90 @@ BOOL regdb_store_values( const char *key, REGVAL_CTR *values )
|
||||
return ret != -1 ;
|
||||
}
|
||||
|
||||
void normalize_dbkey(char *key)
|
||||
{
|
||||
size_t len = strlen(key);
|
||||
string_sub(key, "\\", "/", len+1);
|
||||
strupper_m(key);
|
||||
}
|
||||
|
||||
static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
|
||||
struct security_descriptor **psecdesc)
|
||||
{
|
||||
char *tdbkey;
|
||||
TDB_DATA data;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
|
||||
|
||||
if (asprintf(&tdbkey, "%s/%s", SECDESC_PREFIX, key) == -1) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
normalize_dbkey(tdbkey);
|
||||
|
||||
data = tdb_fetch_bystring(tdb_reg, tdbkey);
|
||||
SAFE_FREE(tdbkey);
|
||||
|
||||
if (data.dptr == NULL) {
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
status = unmarshall_sec_desc(mem_ctx, (uint8 *)data.dptr, data.dsize,
|
||||
psecdesc);
|
||||
|
||||
SAFE_FREE(data.dptr);
|
||||
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return WERR_REG_CORRUPT;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR regdb_set_secdesc(const char *key,
|
||||
struct security_descriptor *secdesc)
|
||||
{
|
||||
prs_struct ps;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
char *tdbkey;
|
||||
WERROR err = WERR_NOMEM;
|
||||
uint8 *data;
|
||||
TDB_DATA tdbdata;
|
||||
|
||||
if (!(mem_ctx = talloc_init("regdb_set_secdesc"))) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(ps);
|
||||
|
||||
if (!(tdbkey = talloc_asprintf(mem_ctx, "%s/%s", SECDESC_PREFIX,
|
||||
key))) {
|
||||
goto done;
|
||||
}
|
||||
normalize_dbkey(tdbkey);
|
||||
|
||||
err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc, &data,
|
||||
&tdbdata.dsize));
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
tdbdata.dptr = (char *)data;
|
||||
|
||||
if (tdb_trans_store_bystring(tdb_reg, tdbkey, tdbdata, 0) == -1) {
|
||||
err = ntstatus_to_werror(map_nt_error_from_unix(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
prs_mem_free(&ps);
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Table of function pointers for default access
|
||||
@ -671,7 +757,7 @@ REGISTRY_OPS regdb_ops = {
|
||||
regdb_fetch_values,
|
||||
regdb_store_keys,
|
||||
regdb_store_values,
|
||||
NULL
|
||||
NULL,
|
||||
regdb_get_secdesc,
|
||||
regdb_set_secdesc
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
extern REGISTRY_OPS printing_ops;
|
||||
extern REGISTRY_OPS eventlog_ops;
|
||||
extern REGISTRY_OPS shares_reg_ops;
|
||||
extern REGISTRY_OPS smbconf_reg_ops;
|
||||
extern REGISTRY_OPS regdb_ops; /* these are the default */
|
||||
|
||||
/* array of REGISTRY_HOOK's which are read into a tree for easy access */
|
||||
@ -39,6 +40,7 @@ REGISTRY_HOOK reg_hooks[] = {
|
||||
{ KEY_PRINTING_2K, &printing_ops },
|
||||
{ KEY_PRINTING_PORTS, &printing_ops },
|
||||
{ KEY_SHARES, &shares_reg_ops },
|
||||
{ KEY_SMBCONF, &smbconf_reg_ops },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -50,25 +52,6 @@ static struct generic_mapping reg_generic_map =
|
||||
/********************************************************************
|
||||
********************************************************************/
|
||||
|
||||
static NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
|
||||
uint32 access_desired, uint32 *access_granted )
|
||||
{
|
||||
NTSTATUS result;
|
||||
|
||||
if ( geteuid() == sec_initial_uid() ) {
|
||||
DEBUG(5,("registry_access_check: using root's token\n"));
|
||||
token = get_root_nt_token();
|
||||
}
|
||||
|
||||
se_map_generic( &access_desired, ®_generic_map );
|
||||
se_access_check( sec_desc, token, access_desired, access_granted, &result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
********************************************************************/
|
||||
|
||||
static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
|
||||
{
|
||||
SEC_ACE ace[2];
|
||||
@ -268,23 +251,46 @@ NTSTATUS registry_fetch_values(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
|
||||
underlying registry backend
|
||||
***********************************************************************/
|
||||
|
||||
BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, NT_USER_TOKEN *token )
|
||||
BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
|
||||
const struct nt_user_token *token )
|
||||
{
|
||||
/* use the default security check if the backend has not defined its own */
|
||||
|
||||
if ( !(key->hook && key->hook->ops && key->hook->ops->reg_access_check) ) {
|
||||
SEC_DESC *sec_desc;
|
||||
NTSTATUS status;
|
||||
|
||||
if ( !(sec_desc = construct_registry_sd( get_talloc_ctx() )) )
|
||||
return False;
|
||||
|
||||
status = registry_access_check( sec_desc, token, requested, granted );
|
||||
|
||||
return NT_STATUS_IS_OK(status);
|
||||
SEC_DESC *sec_desc;
|
||||
NTSTATUS status;
|
||||
WERROR err;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
/* use the default security check if the backend has not defined its
|
||||
* own */
|
||||
|
||||
if (key->hook && key->hook->ops && key->hook->ops->reg_access_check) {
|
||||
return key->hook->ops->reg_access_check( key->name, requested,
|
||||
granted, token );
|
||||
}
|
||||
|
||||
return key->hook->ops->reg_access_check( key->name, requested, granted, token );
|
||||
|
||||
/*
|
||||
* The secdesc routines can't yet cope with a NULL talloc ctx sanely.
|
||||
*/
|
||||
|
||||
if (!(mem_ctx = talloc_init("regkey_access_check"))) {
|
||||
return False;
|
||||
}
|
||||
|
||||
err = regkey_get_secdesc(mem_ctx, key, &sec_desc);
|
||||
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
se_map_generic( &requested, ®_generic_map );
|
||||
|
||||
if (!se_access_check(sec_desc, token, requested, granted, &status)) {
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return NT_STATUS_IS_OK(status);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -295,17 +301,22 @@ static int regkey_destructor(REGISTRY_KEY *key)
|
||||
return regdb_close();
|
||||
}
|
||||
|
||||
WERROR regkey_open_internal( TALLOC_CTX *mem_ctx, REGISTRY_KEY *parent,
|
||||
WERROR regkey_open_onelevel( TALLOC_CTX *mem_ctx, REGISTRY_KEY *parent,
|
||||
REGISTRY_KEY **regkey, const char *name,
|
||||
NT_USER_TOKEN *token, uint32 access_desired )
|
||||
const struct nt_user_token *token,
|
||||
uint32 access_desired )
|
||||
{
|
||||
WERROR result = WERR_OK;
|
||||
REGISTRY_KEY *key;
|
||||
REGSUBKEY_CTR *subkeys = NULL;
|
||||
size_t path_len;
|
||||
|
||||
DEBUG(7,("regkey_open_internal: name = [%s]\n", name));
|
||||
|
||||
if ((parent != NULL) &&
|
||||
((parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) == 0)) {
|
||||
return WERR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if ( !(key = TALLOC_ZERO_P(mem_ctx, REGISTRY_KEY)) ) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
@ -320,27 +331,30 @@ WERROR regkey_open_internal( TALLOC_CTX *mem_ctx, REGISTRY_KEY *parent,
|
||||
/* initialization */
|
||||
|
||||
key->type = REG_KEY_GENERIC;
|
||||
if (!(key->name = talloc_strdup(key, name))) {
|
||||
result = WERR_NOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (parent != NULL) {
|
||||
char *tmp;
|
||||
if (!(tmp = talloc_asprintf(key, "%s%s%s",
|
||||
parent ? parent->name : "",
|
||||
parent ? "\\" : "",
|
||||
key->name))) {
|
||||
result = WERR_NOMEM;
|
||||
if (name[0] == '\0') {
|
||||
/*
|
||||
* Open a copy of the parent key
|
||||
*/
|
||||
if (!parent) {
|
||||
result = WERR_BADFILE;
|
||||
goto done;
|
||||
}
|
||||
TALLOC_FREE(key->name);
|
||||
key->name = tmp;
|
||||
key->name = talloc_strdup(key, parent->name);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Normal open, concat parent and new keynames
|
||||
*/
|
||||
key->name = talloc_asprintf(key, "%s%s%s",
|
||||
parent ? parent->name : "",
|
||||
parent ? "\\": "",
|
||||
name);
|
||||
}
|
||||
|
||||
path_len = strlen( key->name );
|
||||
if ( (path_len != 0) && (key->name[path_len-1] == '\\') ) {
|
||||
key->name[path_len-1] = '\0';
|
||||
if (key->name == NULL) {
|
||||
result = WERR_NOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Tag this as a Performance Counter Key */
|
||||
@ -388,3 +402,94 @@ done:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
WERROR regkey_open_internal( TALLOC_CTX *ctx, REGISTRY_KEY *parent,
|
||||
REGISTRY_KEY **regkey, const char *name,
|
||||
NT_USER_TOKEN *token, uint32 access_desired )
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
const char *p;
|
||||
BOOL free_parent = False;
|
||||
WERROR err;
|
||||
size_t len;
|
||||
|
||||
if (!(mem_ctx = talloc_new(ctx))) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
len = strlen(name);
|
||||
if ((len > 0) && (name[len-1] == '\\')) {
|
||||
if (!(name = talloc_strndup(mem_ctx, name, len-1))) {
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
while ((p = strchr(name, '\\')) != NULL) {
|
||||
char *name_component;
|
||||
REGISTRY_KEY *intermediate;
|
||||
|
||||
|
||||
if (!(name_component = talloc_strndup(
|
||||
mem_ctx, name, (p - name)))) {
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
err = regkey_open_onelevel(mem_ctx, parent, &intermediate,
|
||||
name_component, token,
|
||||
SEC_RIGHTS_ENUM_SUBKEYS);
|
||||
TALLOC_FREE(name_component);
|
||||
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
if (free_parent) {
|
||||
TALLOC_FREE(parent);
|
||||
}
|
||||
parent = intermediate;
|
||||
free_parent = True;
|
||||
name = p+1;
|
||||
}
|
||||
|
||||
err = regkey_open_onelevel(ctx, parent, regkey, name, token,
|
||||
access_desired);
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
|
||||
struct security_descriptor **psecdesc)
|
||||
{
|
||||
struct security_descriptor *secdesc;
|
||||
|
||||
if (key->hook && key->hook->ops && key->hook->ops->get_secdesc) {
|
||||
WERROR err;
|
||||
|
||||
err = key->hook->ops->get_secdesc(mem_ctx, key->name,
|
||||
psecdesc);
|
||||
if (W_ERROR_IS_OK(err)) {
|
||||
return WERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(secdesc = construct_registry_sd(mem_ctx))) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
*psecdesc = secdesc;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR regkey_set_secdesc(REGISTRY_KEY *key,
|
||||
struct security_descriptor *psecdesc)
|
||||
{
|
||||
if (key->hook && key->hook->ops && key->hook->ops->set_secdesc) {
|
||||
return key->hook->ops->set_secdesc(key->name, psecdesc);
|
||||
}
|
||||
|
||||
return WERR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ REGISTRY_OPS printing_ops = {
|
||||
regprint_fetch_reg_values,
|
||||
regprint_store_reg_keys,
|
||||
regprint_store_reg_values,
|
||||
NULL
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
|
@ -160,7 +160,7 @@ REGISTRY_OPS shares_reg_ops = {
|
||||
shares_value_info,
|
||||
shares_store_subkey,
|
||||
shares_store_value,
|
||||
NULL
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
|
85
source3/registry/reg_smbconf.c
Normal file
85
source3/registry/reg_smbconf.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Virtual Windows Registry Layer
|
||||
* Copyright (C) Volker Lendecke 2006
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_RPC_SRV
|
||||
|
||||
extern REGISTRY_OPS regdb_ops; /* these are the default */
|
||||
|
||||
static int smbconf_fetch_keys( const char *key, REGSUBKEY_CTR *subkey_ctr )
|
||||
{
|
||||
return regdb_ops.fetch_subkeys(key, subkey_ctr);
|
||||
}
|
||||
|
||||
static BOOL smbconf_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
|
||||
{
|
||||
return regdb_ops.store_subkeys(key, subkeys);
|
||||
}
|
||||
|
||||
static int smbconf_fetch_values( const char *key, REGVAL_CTR *val )
|
||||
{
|
||||
return regdb_ops.fetch_values(key, val);
|
||||
}
|
||||
|
||||
static BOOL smbconf_store_values( const char *key, REGVAL_CTR *val )
|
||||
{
|
||||
return regdb_ops.store_values(key, val);
|
||||
}
|
||||
|
||||
static BOOL smbconf_reg_access_check(const char *keyname, uint32 requested,
|
||||
uint32 *granted,
|
||||
const struct nt_user_token *token)
|
||||
{
|
||||
if (!(user_has_privileges(token, &se_disk_operators))) {
|
||||
return False;
|
||||
}
|
||||
|
||||
*granted = REG_KEY_ALL;
|
||||
return True;
|
||||
}
|
||||
|
||||
static WERROR smbconf_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
|
||||
struct security_descriptor **psecdesc)
|
||||
{
|
||||
return regdb_ops.get_secdesc(mem_ctx, key, psecdesc);
|
||||
}
|
||||
|
||||
static WERROR smbconf_set_secdesc(const char *key,
|
||||
struct security_descriptor *secdesc)
|
||||
{
|
||||
return regdb_ops.set_secdesc(key, secdesc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Table of function pointers for accessing smb.conf data
|
||||
*/
|
||||
|
||||
REGISTRY_OPS smbconf_reg_ops = {
|
||||
smbconf_fetch_keys,
|
||||
smbconf_fetch_values,
|
||||
smbconf_store_keys,
|
||||
smbconf_store_values,
|
||||
smbconf_reg_access_check,
|
||||
smbconf_get_secdesc,
|
||||
smbconf_set_secdesc
|
||||
};
|
@ -516,6 +516,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
|
||||
/* Ensure all the usershares are loaded. */
|
||||
become_root();
|
||||
load_usershare_shares();
|
||||
load_registry_shares();
|
||||
unbecome_root();
|
||||
|
||||
*total_entries = 0;
|
||||
|
@ -1478,6 +1478,10 @@ WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct
|
||||
WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
|
||||
{
|
||||
REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
|
||||
WERROR err;
|
||||
struct security_descriptor *secdesc;
|
||||
uint8 *data;
|
||||
size_t len;
|
||||
|
||||
if ( !key )
|
||||
return WERR_BADFID;
|
||||
@ -1486,8 +1490,28 @@ WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uin
|
||||
|
||||
if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
|
||||
return WERR_ACCESS_DENIED;
|
||||
|
||||
err = regkey_get_secdesc(p->mem_ctx, key, &secdesc);
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
|
||||
&data, &len));
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (len > sd->size) {
|
||||
sd->size = len;
|
||||
return WERR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
sd->size = len;
|
||||
sd->len = len;
|
||||
sd->data = data;
|
||||
|
||||
return WERR_ACCESS_DENIED;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -1496,6 +1520,8 @@ WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uin
|
||||
WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
|
||||
{
|
||||
REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
|
||||
struct security_descriptor *secdesc;
|
||||
WERROR err;
|
||||
|
||||
if ( !key )
|
||||
return WERR_BADFID;
|
||||
@ -1504,8 +1530,14 @@ WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uin
|
||||
|
||||
if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
|
||||
return WERR_ACCESS_DENIED;
|
||||
|
||||
return WERR_ACCESS_DENIED;
|
||||
|
||||
err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, sd->data,
|
||||
sd->len, &secdesc));
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return regkey_set_secdesc(key, secdesc);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -1671,6 +1671,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
|
||||
|
||||
/* Ensure all the usershares are loaded. */
|
||||
become_root();
|
||||
load_registry_shares();
|
||||
count = load_usershare_shares();
|
||||
unbecome_root();
|
||||
|
||||
|
@ -1114,6 +1114,7 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
|
||||
|
||||
/* Ensure all the usershares are loaded. */
|
||||
become_root();
|
||||
load_registry_shares();
|
||||
sharecount = load_usershare_shares();
|
||||
unbecome_root();
|
||||
|
||||
|
@ -229,6 +229,115 @@ int add_home_service(const char *service, const char *username, const char *home
|
||||
|
||||
}
|
||||
|
||||
static int load_registry_service(const char *servicename)
|
||||
{
|
||||
REGISTRY_KEY *key;
|
||||
char *path;
|
||||
WERROR err;
|
||||
NTSTATUS status;
|
||||
|
||||
uint32 i, num_values;
|
||||
char **value_names;
|
||||
struct registry_value **values = NULL;
|
||||
|
||||
int res;
|
||||
|
||||
if (!lp_registry_shares()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = regkey_open_internal(NULL, NULL, &key, path, get_root_nt_token(),
|
||||
REG_KEY_READ);
|
||||
SAFE_FREE(path);
|
||||
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = registry_fetch_values(NULL, key, &num_values, &value_names,
|
||||
&values);
|
||||
|
||||
TALLOC_FREE(key);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = lp_add_service(servicename, -1);
|
||||
if (res == -1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i=0; i<num_values; i++) {
|
||||
switch (values[i]->type) {
|
||||
case REG_DWORD: {
|
||||
char *val;
|
||||
if (asprintf(&val, "%d", values[i]->v.dword) == -1) {
|
||||
continue;
|
||||
}
|
||||
lp_do_parameter(res, value_names[i], val);
|
||||
SAFE_FREE(val);
|
||||
break;
|
||||
}
|
||||
case REG_SZ: {
|
||||
lp_do_parameter(res, value_names[i],
|
||||
values[i]->v.sz.str);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Ignore all the rest */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(value_names);
|
||||
TALLOC_FREE(values);
|
||||
return res;
|
||||
|
||||
error:
|
||||
|
||||
TALLOC_FREE(value_names);
|
||||
TALLOC_FREE(values);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void load_registry_shares(void)
|
||||
{
|
||||
REGISTRY_KEY *key;
|
||||
REGSUBKEY_CTR *keys;
|
||||
WERROR err;
|
||||
int i;
|
||||
|
||||
if (!lp_registry_shares()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(keys = TALLOC_ZERO_P(NULL, REGSUBKEY_CTR))) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = regkey_open_internal(keys, NULL, &key, KEY_SMBCONF,
|
||||
get_root_nt_token(), REG_KEY_READ);
|
||||
if (!(W_ERROR_IS_OK(err))) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fetch_reg_keys(key, keys) == -1) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i=0; i<keys->num_subkeys; i++) {
|
||||
load_registry_service(keys->subkeys[i]);
|
||||
}
|
||||
|
||||
done:
|
||||
TALLOC_FREE(keys);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a service entry.
|
||||
@ -307,6 +416,10 @@ int find_service(fstring service)
|
||||
}
|
||||
}
|
||||
|
||||
if (iService < 0) {
|
||||
iService = load_registry_service(service);
|
||||
}
|
||||
|
||||
/* Is it a usershare service ? */
|
||||
if (iService < 0 && *lp_usershare_path()) {
|
||||
/* Ensure the name is canonicalized. */
|
||||
|
Loading…
Reference in New Issue
Block a user