r7698: * clean upserver frontend for RegDeleteKey()
authorGerald Carter <jerry@samba.org>
Fri, 17 Jun 2005 18:57:37 +0000 (18:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:57:19 +0000 (10:57 -0500)
* implement RegDeleteKey() for reg_db backend
(This used to be commit 91b81a23b8e2a096747e02fd9392ef590e7f0d61)

source3/registry/reg_db.c
source3/registry/reg_objects.c
source3/rpc_server/srv_reg_nt.c

index ce44e490ab663b55a22ff25bbb4cb7a737cf628d..1ae1d6be54d5802d440b2f19f4002a0f8be68afa 100644 (file)
@@ -163,16 +163,22 @@ BOOL init_registry_db( void )
        return True;
 }
 
+/**********************************************************************
+ The full path to the registry key is used as database after the 
+ \'s are converted to /'s.  Key string is also normalized to UPPER
+ case. 
+**********************************************************************/
 
+static void normalize_reg_path( pstring keyname )
+{
+       pstring_sub( keyname, "\\", "/" );
+       strupper_m( keyname  );
+}
 
 /***********************************************************************
  Add subkey strings to the registry tdb under a defined key
  fmt is the same format as tdb_pack except this function only supports
  fstrings
-
- The full path to the registry key is used as database after the 
- \'s are converted to /'s.  Key string is also normalized to UPPER
- case. 
  ***********************************************************************/
  
 static BOOL regdb_store_reg_keys_internal( char *key, REGSUBKEY_CTR *ctr )
@@ -189,12 +195,8 @@ static BOOL regdb_store_reg_keys_internal( char *key, REGSUBKEY_CTR *ctr )
                return False;
 
        pstrcpy( keyname, key );
-       
-       /* convert to key format */
-       
-       pstring_sub( keyname, "\\", "/" ); 
-       strupper_m( keyname  );
-       
+       normalize_reg_path( keyname );
+
        /* allocate some initial memory */
                
        buffer = SMB_MALLOC(sizeof(pstring));
@@ -249,7 +251,13 @@ static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
 {
        int num_subkeys, i;
        pstring path;
-       REGSUBKEY_CTR subkeys;
+       REGSUBKEY_CTR subkeys, old_subkeys;
+       char *oldkeyname;
+       
+       /* fetch a list of the old subkeys so we can difure out if any were deleted */
+       
+       regsubkey_ctr_init( &old_subkeys );
+       regdb_fetch_reg_keys( key, &old_subkeys );
        
        /* store the subkey list for the parent */
        
@@ -258,6 +266,18 @@ static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
                return False;
        }
        
+       /* now delete removed keys */
+       
+       num_subkeys = regsubkey_ctr_numkeys( &old_subkeys );
+       for ( i=0; i<num_subkeys; i++ ) {
+               oldkeyname = regsubkey_ctr_specific_key( &old_subkeys, i );
+               if ( !regsubkey_ctr_key_exists( ctr, oldkeyname ) ) {
+                       pstr_sprintf( path, "%s%c%s", key, '/', oldkeyname );
+                       normalize_reg_path( path );
+                       tdb_delete_bystring( tdb_reg, path );
+               }
+       }
+       
        /* now create records for any subkeys that don't already exist */
        
        num_subkeys = regsubkey_ctr_numkeys( ctr );
@@ -268,6 +288,7 @@ static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
                        /* create a record with 0 subkeys */
                        if ( !regdb_store_reg_keys_internal( path, &subkeys ) ) {
                                DEBUG(0,("regdb_store_reg_keys: Failed to store new record for key [%s}\n", path ));
+                               regsubkey_ctr_destroy( &subkeys );
                                return False;
                        }
                }
index 2dd61f515faea6cbab017d99da256b3c3018df52..582a696529f1341bd2214e85cc5ed02ee59c87cd 100644 (file)
@@ -43,22 +43,16 @@ void regsubkey_ctr_init( REGSUBKEY_CTR *ctr )
 
 int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
 {
-       uint32 len;
        char **pp;
-       int i;
-       
+
        if ( !keyname )
                return ctr->num_subkeys;
 
-       len = strlen( keyname );
-
        /* make sure the keyname is not already there */
 
-       for ( i=0; i<ctr->num_subkeys; i++ ) {
-               if ( strequal( ctr->subkeys[i], keyname ) )
-                       return ctr->num_subkeys;
-       }
-
+       if ( regsubkey_ctr_key_exists( ctr, keyname ) )
+               return ctr->num_subkeys;
+               
        /* allocate a space for the char* in the array */
                
        if (  ctr->subkeys == 0 )
@@ -71,13 +65,58 @@ int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
 
        /* allocate the string and save it in the array */
        
-       ctr->subkeys[ctr->num_subkeys] = TALLOC( ctr->ctx, len+1 );
-       strncpy( ctr->subkeys[ctr->num_subkeys], keyname, len+1 );
+       ctr->subkeys[ctr->num_subkeys] = talloc_strdup( ctr->ctx, keyname );
        ctr->num_subkeys++;
        
        return ctr->num_subkeys;
 }
  
+ /***********************************************************************
+ Add a new key to the array
+ **********************************************************************/
+
+int regsubkey_ctr_delkey( REGSUBKEY_CTR *ctr, const char *keyname )
+{
+       int i;
+
+       if ( !keyname )
+               return ctr->num_subkeys;
+
+       /* make sure the keyname is actually already there */
+
+       for ( i=0; i<ctr->num_subkeys; i++ ) {
+               if ( strequal( ctr->subkeys[i], keyname ) )
+                       break;
+       }
+       
+       if ( i == ctr->num_subkeys )
+               return ctr->num_subkeys;
+
+       /* update if we have any keys left */
+       ctr->num_subkeys--;
+       if ( ctr->num_subkeys )
+               memmove( &ctr->subkeys[i], &ctr->subkeys[i+1], sizeof(char*) * (ctr->num_subkeys-i) );
+       
+       return ctr->num_subkeys;
+}
+
+/***********************************************************************
+ Check for the existance of a key
+ **********************************************************************/
+
+BOOL regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname )
+{
+       int     i;
+       
+       for ( i=0; i<ctr->num_subkeys; i++ ) {
+               if ( strequal( ctr->subkeys[i],keyname ) )
+                       return True;
+       }
+       
+       return False;
+
+}
+
 /***********************************************************************
  How many keys does the container hold ?
  **********************************************************************/
@@ -351,7 +390,7 @@ int regval_ctr_delvalue( REGVAL_CTR *ctr, const char *name )
 }
 
 /***********************************************************************
Delete a single value from the registry container.
Retrieve single value from the registry container.
  No need to free memory since it is talloc'd.
  **********************************************************************/
 
index 3491cc2c7609f1035d6cecaa983bba7c8547a984..a3ab63d06ec1259c3c4578b19909f549095724ff 100644 (file)
@@ -1304,40 +1304,90 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE  *q_u, REG_R_SET_VALUE *r
 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY *r_u)
 {
        REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
+       REGISTRY_KEY *newparent;
+       POLICY_HND newparent_handle;
        REGSUBKEY_CTR subkeys;
        BOOL write_result;
-       fstring name;
+       pstring name;
+       WERROR result;
 
        if ( !parent )
                return WERR_BADFID;
                
        rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
+               
+       /* ok.  Here's what we do.  */
+
+       if ( strrchr( name, '\\' ) ) {
+               pstring newkeyname;
+               char *ptr;
+               uint32 access_granted;
+               
+               /* (1) check for enumerate rights on the parent handle.  CLients can try 
+                      create things like 'SOFTWARE\Samba' on the HKLM handle. 
+                  (2) open the path to the child parent key if necessary */
        
-       /* access checks first */
-       
-       if ( !(parent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) )
-               return WERR_ACCESS_DENIED;
+               if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
+                       return WERR_ACCESS_DENIED;
                
+               pstrcpy( newkeyname, name );
+               ptr = strrchr( newkeyname, '\\' );
+               *ptr = '\0';
+
+               result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
+               if ( !W_ERROR_IS_OK(result) )
+                       return result;
+               
+               newparent = find_regkey_index_by_hnd(p, &newparent_handle);
+               SMB_ASSERT( newparent != NULL );
+                       
+               if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
+                       result = WERR_ACCESS_DENIED;
+                       goto done;
+               }
+
+               newparent->access_granted = access_granted;
+
+               /* copy the new key name (just the lower most keyname) */
+
+               pstrcpy( name, ptr+1 );
+       }
+       else {
+               /* use the existing open key information */
+               newparent = parent;
+               memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
+       }
+       
+       /* (3) check for create subkey rights on the correct parent */
+       
+       if ( !(newparent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
+               result = WERR_ACCESS_DENIED;
+               goto done;
+       }
+
        regsubkey_ctr_init( &subkeys );
        
-       /* lookup the current keys and add the new one */
+       /* lookup the current keys and delete the new one */
        
-       fetch_reg_keys( parent, &subkeys );
+       fetch_reg_keys( newparent, &subkeys );
        
-       /* FIXME!!! regsubkey_ctr_delkey( &subkeys, name ); */
+       regsubkey_ctr_delkey( &subkeys, name );
        
        /* now write to the registry backend */
        
-       write_result = store_reg_keys( parent, &subkeys );
+       write_result = store_reg_keys( newparent, &subkeys );
        
        regsubkey_ctr_destroy( &subkeys );
        
-       if ( !write_result )
-               return WERR_REG_IO_FAILURE;
-               
+done:
+       /* close any intermediate key handles */
+       
+       if ( newparent != parent )
+               close_registry_key( p, &newparent_handle );
+
        /* rpc_reg.h says there is a POLICY_HDN in the reply...no idea if that is correct */
        
-       return WERR_OK;
+       return write_result ? WERR_OK : WERR_REG_IO_FAILURE;
 }