From 515dea007a20574c0227be9c59bdb5c5241e49da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 20 Nov 2006 23:20:07 +0000 Subject: r19807: First attempt at wrapping something sane around the registry API. Will be extended. Volker (This used to be commit 40922eb924a8e21f28720f2651f087eefc3e3aed) --- source3/include/reg_objects.h | 25 ++ source3/utils/net_rpc_registry.c | 480 ++++++++++++++++++++++++++++----------- 2 files changed, 370 insertions(+), 135 deletions(-) (limited to 'source3') diff --git a/source3/include/reg_objects.h b/source3/include/reg_objects.h index 09f124f1c8..6ddbb89cc7 100644 --- a/source3/include/reg_objects.h +++ b/source3/include/reg_objects.h @@ -32,6 +32,31 @@ typedef struct { uint8 *data_p; } REGISTRY_VALUE; +/* + * A registry string is not necessarily NULL terminated. When retrieving it + * from the net, we guarantee this however. A server might want to push it + * without the terminator though. + */ + +struct registry_string { + size_t len; + char *str; +}; + +struct registry_value { + enum winreg_Type type; + union { + uint32 dword; + uint64 qword; + struct registry_string sz; + struct { + uint32 num_strings; + struct registry_string *strings; + } multi_sz; + DATA_BLOB binary; + } v; +}; + /* container for registry values */ typedef struct { diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c index 9bcf1ce244..a04c527502 100644 --- a/source3/utils/net_rpc_registry.c +++ b/source3/utils/net_rpc_registry.c @@ -26,6 +26,7 @@ /******************************************************************** ********************************************************************/ +#if 0 void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer ) { pstring string; @@ -69,6 +70,311 @@ void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer ) d_printf( "\tUnknown type [%d]\n", type ); } } +#endif + +static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx, + struct rpc_pipe_client *pipe_hnd, + struct policy_handle *key_hnd, + uint32 *pnum_keys, char ***pnames, + char ***pclasses, NTTIME ***pmodtimes) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS status; + uint32 num_subkeys, max_subkeylen, max_classlen; + uint32 num_values, max_valnamelen, max_valbufsize; + uint32 i; + NTTIME last_changed_time; + uint32 secdescsize; + struct winreg_String classname; + char **names, **classes; + NTTIME **modtimes; + + if (!(mem_ctx = talloc_new(ctx))) { + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCT(classname); + status = rpccli_winreg_QueryInfoKey( + pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys, + &max_subkeylen, &max_classlen, &num_values, &max_valnamelen, + &max_valbufsize, &secdescsize, &last_changed_time ); + + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + if (num_subkeys == 0) { + *pnum_keys = 0; + TALLOC_FREE(mem_ctx); + return NT_STATUS_OK; + } + + if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) || + (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) || + (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *, + num_subkeys)))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + + for (i=0; iname)))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + + if (!(names[i] = talloc_strdup(names, name_buf.name))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + + if ((pmodtime) && + (!(modtimes[i] = (NTTIME *)talloc_memdup( + modtimes, pmodtime, sizeof(*pmodtime))))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + } + + *pnum_keys = num_subkeys; + + if (pnames) { + *pnames = talloc_move(ctx, &names); + } + if (pclasses) { + *pclasses = talloc_move(ctx, &classes); + } + if (pmodtimes) { + *pmodtimes = talloc_move(ctx, &modtimes); + } + + status = NT_STATUS_OK; + + error: + TALLOC_FREE(mem_ctx); + return status; +} + +static NTSTATUS registry_pull_value(TALLOC_CTX *mem_ctx, + struct registry_value **pvalue, + enum winreg_Type type, uint8 *data, + uint32 size, uint32 length) +{ + struct registry_value *value; + NTSTATUS status; + + if (!(value = TALLOC_P(mem_ctx, struct registry_value))) { + return NT_STATUS_NO_MEMORY; + } + + value->type = type; + + switch (type) { + case REG_DWORD: + if ((size != 4) || (length != 4)) { + status = NT_STATUS_INVALID_PARAMETER; + goto error; + } + value->v.dword = IVAL(data, 0); + break; + case REG_SZ: + case REG_EXPAND_SZ: + { + /* + * Make sure we get a NULL terminated string for + * convert_string_talloc(). + */ + + smb_ucs2_t *tmp; + uint32 num_ucs2 = length / 2; + + if ((length % 2) != 0) { + status = NT_STATUS_INVALID_PARAMETER; + goto error; + } + + if (!(tmp = SMB_MALLOC_ARRAY(smb_ucs2_t, num_ucs2+1))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + + memcpy((void *)tmp, (const void *)data, length); + tmp[num_ucs2] = 0; + + value->v.sz.len = convert_string_talloc( + value, CH_UTF16LE, CH_UNIX, tmp, length+2, + &value->v.sz.str, False); + + SAFE_FREE(tmp); + + if (value->v.sz.len == (size_t)-1) { + status = NT_STATUS_INVALID_PARAMETER; + goto error; + } + break; + } + default: + status = NT_STATUS_INVALID_PARAMETER; + goto error; + } + + *pvalue = value; + return NT_STATUS_OK; + + error: + TALLOC_FREE(value); + return status; +} + +static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx, + struct rpc_pipe_client *pipe_hnd, + struct policy_handle *key_hnd, + uint32 *pnum_values, char ***pvalnames, + struct registry_value ***pvalues) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS status; + uint32 num_subkeys, max_subkeylen, max_classlen; + uint32 num_values, max_valnamelen, max_valbufsize; + uint32 i; + NTTIME last_changed_time; + uint32 secdescsize; + struct winreg_String classname; + struct registry_value **values; + char **names; + + if (!(mem_ctx = talloc_new(ctx))) { + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCT(classname); + status = rpccli_winreg_QueryInfoKey( + pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys, + &max_subkeylen, &max_classlen, &num_values, &max_valnamelen, + &max_valbufsize, &secdescsize, &last_changed_time ); + + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + if (num_values == 0) { + *pnum_values = 0; + TALLOC_FREE(mem_ctx); + return NT_STATUS_OK; + } + + if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) || + (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *, + num_values)))) { + status = NT_STATUS_NO_MEMORY; + goto error; + } + + for (i=0; i [recurse]\n"); @@ -126,144 +429,51 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid, return werror_to_ntstatus(result); } - classname.name = NULL; - status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, &pol_key, - &classname, &num_subkeys, &max_subkeylen, - &max_classlen, &num_values, &max_valnamelen, - &max_valbufsize, &secdescsize, &last_changed_time ); - - if ( !NT_STATUS_IS_OK(status) ) { - d_fprintf(stderr, "Unable to determine subkeys (%s)\n", - nt_errstr(status)); + status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys, + &names, &classes, &modtimes); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "enumerating keys failed: %s\n", + nt_errstr(status)); return status; } - /* values do not include the terminating NULL */ - - max_subkeylen += 2; - max_valnamelen += 2; - - if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) { - d_fprintf(stderr, "Memory allocation error.\n"); - return NT_STATUS_NO_MEMORY; - } - - /* get the subkeys */ - - status = NT_STATUS_OK; - idx = 0; - while ( NT_STATUS_IS_OK(status) ) { - struct winreg_StringBuf class_namebuf; - struct winreg_StringBuf *p_class_namebuf = &class_namebuf; - fstring kname; - NTTIME *modtime = NULL; - - class_namebuf.name = NULL; - class_namebuf.size = 0; - class_namebuf.length = 0; - - /* zero out each time */ - - subkey_namebuf.length = 0; - subkey_namebuf.size = max_subkeylen; - memset( name_buffer, 0x0, max_subkeylen ); - subkey_namebuf.name = name_buffer; - - status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, &pol_key, - idx, &subkey_namebuf, - &p_class_namebuf, &modtime); - - if ( W_ERROR_EQUAL(ntstatus_to_werror(status), WERR_NO_MORE_ITEMS) ) { - status = NT_STATUS_OK; - break; - } - - if ( !NT_STATUS_IS_OK(status) ) - goto out; - - StrnCpy( kname, subkey_namebuf.name, MIN(subkey_namebuf.length,sizeof(kname))-1 ); - kname[MIN(subkey_namebuf.length,sizeof(kname))-1] = '\0'; - d_printf("Keyname = %s\n", kname); - d_printf("Modtime = %s\n", modtime - ? http_timestring(nt_time_to_unix(*modtime)):"None"); + for (i=0; itype)); + switch(v->type) { + case REG_DWORD: + d_printf("Value = %d\n", v->v.dword); + break; + case REG_SZ: + case REG_EXPAND_SZ: + d_printf("Value = \"%s\"\n", v->v.sz.str); + break; + default: + d_printf("Value = \n"); break; } - - if ( !NT_STATUS_IS_OK(status) ) - goto out; - - init_regval_buffer( &value, data, value_length ); - StrnCpy( name, value_namebuf.name, MIN(max_valnamelen, sizeof(name)-1) ); - name[MIN(max_valnamelen, sizeof(name)-1)] = '\0'; - - d_printf("Valuename = %s\n", name ); - d_printf("Type = %s\n", reg_type_lookup(type)); - d_printf("Data = " ); - dump_regval_buffer( type, &value ); - d_printf("\n" ); - - idx++; + d_printf("\n"); } - -out: - /* cleanup */ - + if ( strlen( subpath ) != 0 ) rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key ); rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive ); -- cgit