summaryrefslogtreecommitdiff
path: root/source3/registry
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2006-11-30 07:38:40 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:16:16 -0500
commit575845ccbeb2acc5dcb5133b80fd19b1d80169f2 (patch)
tree0ec427819a9f6e9e417a1e34b9bbcfd23badc1b7 /source3/registry
parent3fda843ac16d3d8c66a398a93b5de81f7d74276d (diff)
downloadsamba-575845ccbeb2acc5dcb5133b80fd19b1d80169f2.tar.gz
samba-575845ccbeb2acc5dcb5133b80fd19b1d80169f2.tar.bz2
samba-575845ccbeb2acc5dcb5133b80fd19b1d80169f2.zip
r19963: Add 'registry shares = yes' and registry key security descriptors.
(This used to be commit 6cab254c49e07b11c170511ec613f0f33914c3e6)
Diffstat (limited to 'source3/registry')
-rw-r--r--source3/registry/reg_db.c92
-rw-r--r--source3/registry/reg_frontend.c211
-rw-r--r--source3/registry/reg_printing.c2
-rw-r--r--source3/registry/reg_shares.c2
-rw-r--r--source3/registry/reg_smbconf.c85
5 files changed, 334 insertions, 58 deletions
diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c
index 2afecffec7..345193716e 100644
--- a/source3/registry/reg_db.c
+++ b/source3/registry/reg_db.c
@@ -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
};
-
-
diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c
index 90b068dcb9..79fbc8ef52 100644
--- a/source3/registry/reg_frontend.c
+++ b/source3/registry/reg_frontend.c
@@ -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, &reg_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, &reg_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;
+}
+
diff --git a/source3/registry/reg_printing.c b/source3/registry/reg_printing.c
index ba79092ea5..c20d5ab96f 100644
--- a/source3/registry/reg_printing.c
+++ b/source3/registry/reg_printing.c
@@ -1239,7 +1239,7 @@ REGISTRY_OPS printing_ops = {
regprint_fetch_reg_values,
regprint_store_reg_keys,
regprint_store_reg_values,
- NULL
+ NULL, NULL, NULL
};
diff --git a/source3/registry/reg_shares.c b/source3/registry/reg_shares.c
index 5a3e9a131b..d2113a647d 100644
--- a/source3/registry/reg_shares.c
+++ b/source3/registry/reg_shares.c
@@ -160,7 +160,7 @@ REGISTRY_OPS shares_reg_ops = {
shares_value_info,
shares_store_subkey,
shares_store_value,
- NULL
+ NULL, NULL, NULL
};
diff --git a/source3/registry/reg_smbconf.c b/source3/registry/reg_smbconf.c
new file mode 100644
index 0000000000..b17422fdcb
--- /dev/null
+++ b/source3/registry/reg_smbconf.c
@@ -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
+};