summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-06-17 18:57:37 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:57:19 -0500
commitc25b67b24d3c7ec04a58410aaa05c1aae9688e32 (patch)
tree4c58725f37a14273333371b15a96dc02fa2a70ae
parent5c9963c287e20a4a4b8bbaa088328438eb4f942c (diff)
downloadsamba-c25b67b24d3c7ec04a58410aaa05c1aae9688e32.tar.gz
samba-c25b67b24d3c7ec04a58410aaa05c1aae9688e32.tar.bz2
samba-c25b67b24d3c7ec04a58410aaa05c1aae9688e32.zip
r7698: * clean upserver frontend for RegDeleteKey()
* implement RegDeleteKey() for reg_db backend (This used to be commit 91b81a23b8e2a096747e02fd9392ef590e7f0d61)
-rw-r--r--source3/registry/reg_db.c43
-rw-r--r--source3/registry/reg_objects.c65
-rw-r--r--source3/rpc_server/srv_reg_nt.c76
3 files changed, 147 insertions, 37 deletions
diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c
index ce44e490ab..1ae1d6be54 100644
--- a/source3/registry/reg_db.c
+++ b/source3/registry/reg_db.c
@@ -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;
}
}
diff --git a/source3/registry/reg_objects.c b/source3/registry/reg_objects.c
index 2dd61f515f..582a696529 100644
--- a/source3/registry/reg_objects.c
+++ b/source3/registry/reg_objects.c
@@ -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.
**********************************************************************/
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index 3491cc2c76..a3ab63d06e 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -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;
}