r19963: Add 'registry shares = yes' and registry key security descriptors.
authorVolker Lendecke <vlendec@samba.org>
Thu, 30 Nov 2006 07:38:40 +0000 (07:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:16:16 +0000 (12:16 -0500)
14 files changed:
source/Makefile.in
source/include/reg_objects.h
source/lib/secdesc.c
source/param/loadparm.c
source/registry/reg_db.c
source/registry/reg_frontend.c
source/registry/reg_printing.c
source/registry/reg_shares.c
source/registry/reg_smbconf.c [new file with mode: 0644]
source/rpc_server/srv_srvsvc_nt.c
source/rpc_server/srv_winreg_nt.c
source/smbd/lanman.c
source/smbd/msdfs.c
source/smbd/service.c

index 95de6a436ac8213b3b2f26e45204bebac9012fc2..35355becdfd3ccccc17e44acef7125ae18adf027 100644 (file)
@@ -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
 
index 99da22f8cd7b7f33df7788129df1d96d24b4c8ae..e3226b7ae9d5ada531f4c6b8560bffdbab5edc86 100644 (file)
@@ -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 {
index 2f592769b3b14d95c371641a2e1167c83011aafc..762dc2f6d8cc4fc4df3da94557c701d2ac32b69c 100644 (file)
@@ -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.
 ********************************************************************/
index 81c642daf8bfd37411b3ddd67ce1d04991713223..60d686f24590cb148d8788e8543a7e0d343bac32 100644 (file)
@@ -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));
 }
 
index 2afecffec7592867f8afd0bf67d0cd50a06b32e1..345193716e1825459215ed4f9a6ed229e5a38185 100644 (file)
@@ -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
 };
-
-
index 90b068dcb98866a8edd2d661b541d31d0000d70f..79fbc8ef52b50cb85cd58f5ddb0cf9229d6400f3 100644 (file)
@@ -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;
+}
+
index ba79092ea5b3fbf6a64fbce0e1450bdeaa0c3ce1..c20d5ab96fdcf9199ff9e69bc8beb145df44fbaf 100644 (file)
@@ -1239,7 +1239,7 @@ REGISTRY_OPS printing_ops = {
        regprint_fetch_reg_values,
        regprint_store_reg_keys,
        regprint_store_reg_values,
-       NULL
+       NULL, NULL, NULL
 };
 
 
index 5a3e9a131b62629f958e1240ac0503fd404fd89b..d2113a647df8986d62a8399b9a5a42e14b6194a3 100644 (file)
@@ -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/source/registry/reg_smbconf.c b/source/registry/reg_smbconf.c
new file mode 100644 (file)
index 0000000..b17422f
--- /dev/null
@@ -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
+};
index 35938d087e289f657137868438723c7688583556..ac9a1132e1a84ad4b7bfe1f0bc0fbd9b21d6458d 100644 (file)
@@ -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;
index 16c271427e75800a63532256900d8754755ac5d6..847bc967c566a3b5fea589cf63285ee4736ebc65 100644 (file)
@@ -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);
 }
 
 /*******************************************************************
index 8ecc965c0d3671aa30a6124872fcf0428196109f..e42d96b11e96aefd07170b9bac52af4531faea87 100644 (file)
@@ -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();
 
index 1f04356b4f3e4cc666fdafb749d6d7bb7398114c..12fd333efefdbc2eaf846326dbc9a5514b25cace 100644 (file)
@@ -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();
 
index 60ba85ab65ef005628126ea3df449f6c17ef5dbd..e63bc01a7d34789ce8a0cba466d190703edf1586 100644 (file)
@@ -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. */