s3:registry avoid updating keys which are going to be deleted in
[metze/samba/wip.git] / source3 / registry / reg_dispatcher.c
index e6e76134570512f1efaa812bbe8de8ff6fb6b0a7..5b52e98e08cd5653baf4e9a215db9a050f901ac7 100644 (file)
@@ -24,6 +24,9 @@
  */
 
 #include "includes.h"
+#include "registry.h"
+#include "reg_dispatcher.h"
+#include "../libcli/security/security.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
@@ -34,49 +37,57 @@ static const struct generic_mapping reg_generic_map =
 /********************************************************************
 ********************************************************************/
 
-static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
+static WERROR construct_registry_sd(TALLOC_CTX *ctx, struct security_descriptor **psd)
 {
-       SEC_ACE ace[3];
-       SEC_ACCESS mask;
+       struct security_ace ace[3];
        size_t i = 0;
-       SEC_DESC *sd;
-       SEC_ACL *acl;
+       struct security_descriptor *sd;
+       struct security_acl *theacl;
        size_t sd_size;
 
        /* basic access for Everyone */
 
-       init_sec_access(&mask, REG_KEY_READ );
-       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    REG_KEY_READ, 0);
 
        /* Full Access 'BUILTIN\Administrators' */
 
-       init_sec_access(&mask, REG_KEY_ALL );
-       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
+                    SEC_ACE_TYPE_ACCESS_ALLOWED, REG_KEY_ALL, 0);
 
        /* Full Access 'NT Authority\System' */
 
-       init_sec_access(&mask, REG_KEY_ALL );
-       init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    REG_KEY_ALL, 0);
 
        /* create the security descriptor */
 
-       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
-               return NULL;
+       theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
+       if (theacl == NULL) {
+               return WERR_NOMEM;
+       }
 
-       if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
-               return NULL;
+       sd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
+                          &global_sid_Builtin_Administrators,
+                          &global_sid_System, NULL, theacl,
+                          &sd_size);
+       if (sd == NULL) {
+               return WERR_NOMEM;
+       }
 
-       return sd;
+       *psd = sd;
+       return WERR_OK;
 }
 
 /***********************************************************************
  High level wrapper function for storing registry subkeys
  ***********************************************************************/
 
-bool store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
+bool store_reg_keys(struct registry_key_handle *key,
+                   struct regsubkey_ctr *subkeys)
 {
-       if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
-               return key->hook->ops->store_subkeys( key->name, subkeys );
+       if (key->ops && key->ops->store_subkeys)
+               return key->ops->store_subkeys(key->name, subkeys);
 
        return false;
 }
@@ -85,25 +96,44 @@ bool store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
  High level wrapper function for storing registry values
  ***********************************************************************/
 
-bool store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
+bool store_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
 {
-       if ( key->hook && key->hook->ops && key->hook->ops->store_values )
-               return key->hook->ops->store_values( key->name, val );
+       if (key->ops && key->ops->store_values)
+               return key->ops->store_values(key->name, val);
 
        return false;
 }
 
+WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey)
+{
+       if (key->ops && key->ops->create_subkey) {
+               return key->ops->create_subkey(key->name, subkey);
+       }
+
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy)
+{
+       if (key->ops && key->ops->delete_subkey) {
+               return key->ops->delete_subkey(key->name, subkey, lazy);
+       }
+
+       return WERR_NOT_SUPPORTED;
+}
+
 /***********************************************************************
  High level wrapper function for enumerating registry subkeys
  Initialize the TALLOC_CTX if necessary
  ***********************************************************************/
 
-int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
+int fetch_reg_keys(struct registry_key_handle *key,
+                  struct regsubkey_ctr *subkey_ctr)
 {
        int result = -1;
 
-       if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
-               result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
+       if (key->ops && key->ops->fetch_subkeys)
+               result = key->ops->fetch_subkeys(key->name, subkey_ctr);
 
        return result;
 }
@@ -112,15 +142,15 @@ int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
  High level wrapper function for enumerating registry values
  ***********************************************************************/
 
-int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
+int fetch_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
 {
        int result = -1;
 
        DEBUG(10, ("fetch_reg_values called for key '%s' (ops %p)\n", key->name,
-                  (key->hook && key->hook->ops) ? (void *)key->hook->ops : NULL));
+                  (key->ops) ? (void *)key->ops : NULL));
 
-       if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
-               result = key->hook->ops->fetch_values( key->name, val );
+       if (key->ops && key->ops->fetch_values)
+               result = key->ops->fetch_values(key->name, val);
 
        return result;
 }
@@ -130,76 +160,72 @@ int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
  underlying registry backend
  ***********************************************************************/
 
-bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
-                         const struct nt_user_token *token )
+bool regkey_access_check(struct registry_key_handle *key, uint32 requested,
+                        uint32 *granted,
+                        const struct security_token *token )
 {
-       SEC_DESC *sec_desc;
+       struct security_descriptor *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 );
+       /* root free-pass, like we have on all other pipes like samr, lsa, etc. */
+       if (geteuid() == sec_initial_uid()) {
+               *granted = REG_KEY_ALL;
+               return true;
        }
 
-       /*
-        * The secdesc routines can't yet cope with a NULL talloc ctx sanely.
-        */
+       /* use the default security check if the backend has not defined its
+        * own */
 
-       if (!(mem_ctx = talloc_init("regkey_access_check"))) {
-               return false;
+       if (key->ops && key->ops->reg_access_check) {
+               return key->ops->reg_access_check(key->name, requested,
+                                                 granted, token);
        }
 
-       err = regkey_get_secdesc(mem_ctx, key, &sec_desc);
+       err = regkey_get_secdesc(talloc_tos(), 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);
+       status =se_access_check(sec_desc, token, requested, granted);
+       TALLOC_FREE(sec_desc);
+       if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       TALLOC_FREE(mem_ctx);
        return NT_STATUS_IS_OK(status);
 }
 
-WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
+WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, struct registry_key_handle *key,
                          struct security_descriptor **psecdesc)
 {
        struct security_descriptor *secdesc;
+       WERROR werr;
 
-       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)) {
+       if (key->ops && key->ops->get_secdesc) {
+               werr = key->ops->get_secdesc(mem_ctx, key->name, psecdesc);
+               if (W_ERROR_IS_OK(werr)) {
                        return WERR_OK;
                }
        }
 
-       if (!(secdesc = construct_registry_sd(mem_ctx))) {
-               return WERR_NOMEM;
+       werr = construct_registry_sd(mem_ctx, &secdesc);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
        }
 
        *psecdesc = secdesc;
        return WERR_OK;
 }
 
-WERROR regkey_set_secdesc(REGISTRY_KEY *key,
+WERROR regkey_set_secdesc(struct registry_key_handle *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);
+       if (key->ops && key->ops->set_secdesc) {
+               return key->ops->set_secdesc(key->name, psecdesc);
        }
 
        return WERR_ACCESS_DENIED;
@@ -209,11 +235,12 @@ WERROR regkey_set_secdesc(REGISTRY_KEY *key,
  * Check whether the in-memory version of the subkyes of a
  * registry key needs update from disk.
  */
-bool reg_subkeys_need_update(REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys)
+bool reg_subkeys_need_update(struct registry_key_handle *key,
+                            struct regsubkey_ctr *subkeys)
 {
-       if (key->hook && key->hook->ops && key->hook->ops->subkeys_need_update)
+       if (key->ops && key->ops->subkeys_need_update)
        {
-               return key->hook->ops->subkeys_need_update(subkeys);
+               return key->ops->subkeys_need_update(subkeys);
        }
 
        return false;
@@ -223,11 +250,12 @@ bool reg_subkeys_need_update(REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys)
  * Check whether the in-memory version of the values of a
  * registry key needs update from disk.
  */
-bool reg_values_need_update(REGISTRY_KEY *key, REGVAL_CTR *values)
+bool reg_values_need_update(struct registry_key_handle *key,
+                           struct regval_ctr *values)
 {
-       if (key->hook && key->hook->ops && key->hook->ops->values_need_update)
+       if (key->ops && key->ops->values_need_update)
        {
-               return key->hook->ops->values_need_update(values);
+               return key->ops->values_need_update(values);
        }
 
        return false;