summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/rpc_reg.h4
-rw-r--r--source3/include/rpc_secdes.h2
-rw-r--r--source3/printing/nt_printing.c2
-rw-r--r--source3/registry/reg_db.c44
-rw-r--r--source3/registry/reg_frontend.c2
-rw-r--r--source3/registry/reg_objects.c10
-rw-r--r--source3/rpc_client/cli_reg.c2
-rw-r--r--source3/rpc_client/cli_spoolss.c1
-rw-r--r--source3/rpc_parse/parse_reg.c8
-rw-r--r--source3/rpc_server/srv_reg_nt.c228
-rw-r--r--source3/utils/net_rpc_registry.c3
11 files changed, 248 insertions, 58 deletions
diff --git a/source3/include/rpc_reg.h b/source3/include/rpc_reg.h
index 270ba32f4b..f89571484c 100644
--- a/source3/include/rpc_reg.h
+++ b/source3/include/rpc_reg.h
@@ -179,7 +179,7 @@ typedef struct {
/***********************************************/
typedef struct {
- POLICY_HND pol;
+ POLICY_HND handle;
UNISTR4 name;
uint32 type;
RPC_DATA_BLOB value;
@@ -228,7 +228,7 @@ typedef struct {
} REG_Q_CREATE_KEY;
typedef struct {
- POLICY_HND key_pol;
+ POLICY_HND handle;
uint32 unknown;
WERROR status;
} REG_R_CREATE_KEY;
diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h
index a14caf36c1..b2b97e391e 100644
--- a/source3/include/rpc_secdes.h
+++ b/source3/include/rpc_secdes.h
@@ -547,7 +547,7 @@ typedef struct standard_mapping {
#define REG_KEY_EXECUTE REG_KEY_READ
#define REG_KEY_WRITE \
- ( STANDARD_RIGHTS_READ_ACCESS |\
+ ( STANDARD_RIGHTS_WRITE_ACCESS |\
SEC_RIGHTS_SET_VALUE |\
SEC_RIGHTS_CREATE_SUBKEY )
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 8fd28d8cfe..75473c39f2 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -2543,8 +2543,6 @@ static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
data->num_keys++;
data->keys[key_index].name = SMB_STRDUP( name );
- ZERO_STRUCTP( &data->keys[key_index].values );
-
regval_ctr_init( &data->keys[key_index].values );
DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c
index 7efa032e39..a459aa5f5f 100644
--- a/source3/registry/reg_db.c
+++ b/source3/registry/reg_db.c
@@ -68,8 +68,6 @@ static BOOL init_registry_data( void )
int i;
const char *p, *p2;
- ZERO_STRUCTP( &subkeys );
-
/* loop over all of the predefined paths and add each component */
for ( i=0; builtin_registry_paths[i] != NULL; i++ ) {
@@ -168,10 +166,10 @@ BOOL init_registry_db( void )
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.
+ case.
***********************************************************************/
-static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
+static BOOL regdb_store_reg_keys_internal( char *key, REGSUBKEY_CTR *ctr )
{
TDB_DATA kbuf, dbuf;
char *buffer, *tmpbuf;
@@ -237,6 +235,44 @@ done:
}
/***********************************************************************
+ Store the new subkey record and create any child key records that
+ do not currently exist
+ ***********************************************************************/
+
+static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
+{
+ int num_subkeys, i;
+ pstring path;
+ REGSUBKEY_CTR subkeys;
+
+ /* store the subkey list for the parent */
+
+ if ( !regdb_store_reg_keys_internal( key, ctr ) ) {
+ DEBUG(0,("regdb_store_reg_keys: Failed to store new subkey list for parent [%s}\n", key ));
+ return False;
+ }
+
+ /* now create records for any subkeys that don't already exist */
+
+ num_subkeys = regsubkey_ctr_numkeys( ctr );
+ for ( i=0; i<num_subkeys; i++ ) {
+ pstr_sprintf( path, "%s%c%s", key, '/', regsubkey_ctr_specific_key( ctr, i ) );
+ regsubkey_ctr_init( &subkeys );
+ if ( regdb_fetch_reg_keys( path, &subkeys ) == -1 ) {
+ /* 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 ));
+ return False;
+ }
+ }
+ regsubkey_ctr_destroy( &subkeys );
+ }
+
+ return True;
+}
+
+
+/***********************************************************************
Retrieve an array of strings containing subkeys. Memory should be
released by the caller. The subkeys are stored in a catenated string
of null terminated character strings
diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c
index ab8a02812f..9c7420ef86 100644
--- a/source3/registry/reg_frontend.c
+++ b/source3/registry/reg_frontend.c
@@ -134,7 +134,6 @@ BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index
if ( !ctr_init ) {
DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
- ZERO_STRUCTP( &ctr );
regsubkey_ctr_init( &ctr );
pstrcpy( save_path, key->name );
@@ -202,7 +201,6 @@ BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32
if ( !ctr_init ) {
DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
- ZERO_STRUCTP( &ctr );
regval_ctr_init( &ctr );
pstrcpy( save_path, key->name );
diff --git a/source3/registry/reg_objects.c b/source3/registry/reg_objects.c
index add82ae0d4..2dd61f515f 100644
--- a/source3/registry/reg_objects.c
+++ b/source3/registry/reg_objects.c
@@ -28,12 +28,13 @@
/***********************************************************************
Init the talloc context held by a REGSUBKEY_CTR structure
+ This now zero's the structure
**********************************************************************/
void regsubkey_ctr_init( REGSUBKEY_CTR *ctr )
{
- if ( !ctr->ctx )
- ctr->ctx = talloc_init("regsubkey_ctr_init for ctr %p", ctr);
+ ZERO_STRUCTP( ctr );
+ ctr->ctx = talloc_init("regsubkey_ctr_init for ctr %p", ctr);
}
/***********************************************************************
@@ -117,12 +118,13 @@ void regsubkey_ctr_destroy( REGSUBKEY_CTR *ctr )
/***********************************************************************
Init the talloc context held by a REGSUBKEY_CTR structure
+ This now zero's the structure
**********************************************************************/
void regval_ctr_init( REGVAL_CTR *ctr )
{
- if ( ctr && !ctr->ctx )
- ctr->ctx = talloc_init("regval_ctr_init for ctr %p", ctr);
+ ZERO_STRUCTP( ctr );
+ ctr->ctx = talloc_init("regval_ctr_init for ctr %p", ctr);
}
/***********************************************************************
diff --git a/source3/rpc_client/cli_reg.c b/source3/rpc_client/cli_reg.c
index 3f5b7652ac..ca4b63c282 100644
--- a/source3/rpc_client/cli_reg.c
+++ b/source3/rpc_client/cli_reg.c
@@ -474,7 +474,7 @@ WERROR cli_reg_create_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
if ( !W_ERROR_IS_OK( out.status ) )
return out.status;
- memcpy( key, &out.key_pol, sizeof(POLICY_HND) );
+ memcpy( key, &out.handle, sizeof(POLICY_HND) );
return out.status;
}
diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c
index 518c20ff9b..8ed29f50fb 100644
--- a/source3/rpc_client/cli_spoolss.c
+++ b/source3/rpc_client/cli_spoolss.c
@@ -2270,7 +2270,6 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Return data */
- ZERO_STRUCTP(ctr);
regval_ctr_init(ctr);
for (i = 0; i < r.returned; i++) {
diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c
index 5eed245a28..5cc4d06f4f 100644
--- a/source3/rpc_parse/parse_reg.c
+++ b/source3/rpc_parse/parse_reg.c
@@ -297,7 +297,7 @@ BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_u,
if(!prs_align(ps))
return False;
- if(!smb_io_pol_hnd("", &r_u->key_pol, ps, depth))
+ if(!smb_io_pol_hnd("", &r_u->handle, ps, depth))
return False;
if(!prs_uint32("unknown", ps, depth, &r_u->unknown))
return False;
@@ -407,8 +407,6 @@ BOOL reg_io_q_delete_key(const char *desc, REG_Q_DELETE_KEY *q_u,
if(!prs_unistr4("", ps, depth, &q_u->name))
return False;
- if(!prs_align(ps))
- return False;
return True;
}
@@ -1219,7 +1217,7 @@ void init_reg_q_set_val(REG_Q_SET_VALUE *q_u, POLICY_HND *pol,
{
ZERO_STRUCTP(q_u);
- memcpy(&q_u->pol, pol, sizeof(q_u->pol));
+ memcpy(&q_u->handle, pol, sizeof(q_u->handle));
init_unistr4(&q_u->name, val_name, UNI_STR_TERMINATE);
@@ -1243,7 +1241,7 @@ BOOL reg_io_q_set_value(const char *desc, REG_Q_SET_VALUE *q_u, prs_struct *ps,
if(!prs_align(ps))
return False;
- if(!smb_io_pol_hnd("", &q_u->pol, ps, depth))
+ if(!smb_io_pol_hnd("", &q_u->handle, ps, depth))
return False;
if(!prs_unistr4("name", ps, depth, &q_u->name ))
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index 95af6c15c9..3491cc2c76 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -179,29 +179,23 @@ static WERROR open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *
/* check if the path really exists; failed is indicated by -1 */
/* if the subkey count failed, bail out */
- ZERO_STRUCTP( &subkeys );
-
regsubkey_ctr_init( &subkeys );
if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
-
- /* don't really know what to return here */
result = WERR_BADFILE;
+ goto done;
}
- else {
- /*
- * This would previously return NT_STATUS_TOO_MANY_SECRETS
- * that doesn't sound quite right to me --jerry
- */
-
- if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) )
- result = WERR_BADFILE;
+
+ if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) ) {
+ result = WERR_BADFILE;
+ goto done;
}
/* save the access mask */
regkey->access_granted = access_granted;
+done:
/* clean up */
regsubkey_ctr_destroy( &subkeys );
@@ -247,8 +241,6 @@ static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *m
if ( !key )
return False;
- ZERO_STRUCTP( &subkeys );
-
regsubkey_ctr_init( &subkeys );
if ( fetch_reg_keys( key, &subkeys ) == -1 )
@@ -289,9 +281,6 @@ static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
if ( !key )
return False;
-
- ZERO_STRUCTP( &values );
-
regval_ctr_init( &values );
if ( fetch_reg_values( key, &values ) == -1 )
@@ -407,27 +396,27 @@ WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u
WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
{
fstring name;
- REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->pol);
+ REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
REGISTRY_KEY *newkey;
uint32 access_granted;
WERROR result;
DEBUG(5,("reg_open_entry: Enter\n"));
- if ( !key )
+ if ( !parent )
return WERR_BADFID;
rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
/* check granted access first; what is the correct mask here? */
- if ( !(key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
+ if ( !(parent->access_granted & (SEC_RIGHTS_ENUM_SUBKEYS|SEC_RIGHTS_CREATE_SUBKEY)) )
return WERR_ACCESS_DENIED;
/* open the key first to get the appropriate REGISTRY_HOOK
and then check the premissions */
- if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, key, name, 0 )) )
+ if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, parent, name, 0 )) )
return result;
newkey = find_regkey_index_by_hnd(p, &r_u->handle);
@@ -473,8 +462,6 @@ WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
DEBUG(5,("reg_info: looking up value: [%s]\n", name));
- ZERO_STRUCTP( &regvals );
-
regval_ctr_init( &regvals );
/* couple of hard coded registry values */
@@ -891,9 +878,6 @@ static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
/* now start parsing the values and subkeys */
- ZERO_STRUCT( values );
- ZERO_STRUCT( subkeys );
-
regsubkey_ctr_init( &subkeys );
regval_ctr_init( &values );
@@ -1044,9 +1028,6 @@ static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
/* lookup the values and subkeys */
- ZERO_STRUCT( values );
- ZERO_STRUCT( subkeys );
-
regsubkey_ctr_init( &subkeys );
regval_ctr_init( &values );
@@ -1186,7 +1167,98 @@ WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
WERROR _reg_create_key(pipes_struct *p, REG_Q_CREATE_KEY *q_u, REG_R_CREATE_KEY *r_u)
{
- return WERR_ACCESS_DENIED;
+ 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;
+ 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 */
+
+ 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 & SEC_RIGHTS_CREATE_SUBKEY) ) {
+ result = WERR_ACCESS_DENIED;
+ goto done;
+ }
+
+ regsubkey_ctr_init( &subkeys );
+
+ /* (4) lookup the current keys and add the new one */
+
+ fetch_reg_keys( newparent, &subkeys );
+ regsubkey_ctr_addkey( &subkeys, name );
+
+ /* now write to the registry backend */
+
+ write_result = store_reg_keys( newparent, &subkeys );
+
+ regsubkey_ctr_destroy( &subkeys );
+
+ if ( !write_result )
+ return WERR_REG_IO_FAILURE;
+
+ /* (5) open the new key and return the handle. Note that it is probably
+ not correct to grant full access on this open handle. We should pass
+ the new open through the regkey_access_check() like we do for
+ _reg_open_entry() but this is ok for now. */
+
+ result = open_registry_key( p, &r_u->handle, newparent, name, REG_KEY_ALL );
+
+done:
+ /* close any intermediate key handles */
+
+ if ( newparent != parent )
+ close_registry_key( p, &newparent_handle );
+
+ return result;
}
@@ -1195,7 +1267,35 @@ WERROR _reg_create_key(pipes_struct *p, REG_Q_CREATE_KEY *q_u, REG_R_CREATE_KEY
WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
{
- return WERR_ACCESS_DENIED;
+ REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
+ REGVAL_CTR values;
+ BOOL write_result;
+
+ if ( !key )
+ return WERR_BADFID;
+
+ /* access checks first */
+
+ if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
+ return WERR_ACCESS_DENIED;
+
+ regval_ctr_init( &values );
+
+ /* lookup the current values and add the new one */
+
+ fetch_reg_values( key, &values );
+ /* FIXME!!!! regval_ctr_addvalue( &values, .... ); */
+
+ /* now write to the registry backend */
+
+ write_result = store_reg_values( key, &values );
+
+ regval_ctr_destroy( &values );
+
+ if ( !write_result )
+ return WERR_REG_IO_FAILURE;
+
+ return WERR_OK;
}
/*******************************************************************
@@ -1203,7 +1303,41 @@ 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)
{
- return WERR_ACCESS_DENIED;
+ REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
+ REGSUBKEY_CTR subkeys;
+ BOOL write_result;
+ fstring name;
+
+ if ( !parent )
+ return WERR_BADFID;
+
+ rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
+
+ /* access checks first */
+
+ if ( !(parent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) )
+ return WERR_ACCESS_DENIED;
+
+ regsubkey_ctr_init( &subkeys );
+
+ /* lookup the current keys and add the new one */
+
+ fetch_reg_keys( parent, &subkeys );
+
+ /* FIXME!!! regsubkey_ctr_delkey( &subkeys, name ); */
+
+ /* now write to the registry backend */
+
+ write_result = store_reg_keys( parent, &subkeys );
+
+ regsubkey_ctr_destroy( &subkeys );
+
+ if ( !write_result )
+ return WERR_REG_IO_FAILURE;
+
+ /* rpc_reg.h says there is a POLICY_HDN in the reply...no idea if that is correct */
+
+ return WERR_OK;
}
@@ -1212,6 +1346,34 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY
WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
{
- return WERR_ACCESS_DENIED;
+ REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
+ REGVAL_CTR values;
+ BOOL write_result;
+
+ if ( !key )
+ return WERR_BADFID;
+
+ /* access checks first */
+
+ if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
+ return WERR_ACCESS_DENIED;
+
+ regval_ctr_init( &values );
+
+ /* lookup the current values and add the new one */
+
+ fetch_reg_values( key, &values );
+ /* FIXME!!!! regval_ctr_delval( &values, .... ); */
+
+ /* now write to the registry backend */
+
+ write_result = store_reg_values( key, &values );
+
+ regval_ctr_destroy( &values );
+
+ if ( !write_result )
+ return WERR_REG_IO_FAILURE;
+
+ return WERR_OK;
}
diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c
index f97f67a13b..8a97f64584 100644
--- a/source3/utils/net_rpc_registry.c
+++ b/source3/utils/net_rpc_registry.c
@@ -336,9 +336,6 @@ static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
int i;
pstring path;
- ZERO_STRUCT( values );
- ZERO_STRUCT( subkeys );
-
regsubkey_ctr_init( &subkeys );
regval_ctr_init( &values );