From f57cd1f63c900a7b17955cc7e11cd1f6b6b12474 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 Nov 2006 07:52:46 +0000 Subject: r19914: The "default" value with the name "" need different 0-length treatment as the other StringBufs, otherwise clicking on a key with this value being set leads to regedit.exe on w2k3 chew all memory. (This used to be commit b148cde7f39859102288a87b6f0bd2b250947a85) --- source3/libmsrpc/cac_winreg.c | 2 +- source3/librpc/gen_ndr/cli_winreg.c | 2 +- source3/librpc/gen_ndr/cli_winreg.h | 2 +- source3/librpc/gen_ndr/ndr_winreg.c | 83 ++++++++++++++++++++++++++++++++++--- source3/librpc/gen_ndr/ndr_winreg.h | 1 + source3/librpc/gen_ndr/srv_winreg.h | 2 +- source3/librpc/gen_ndr/winreg.h | 10 ++++- source3/librpc/idl/winreg.idl | 12 +++++- source3/rpc_server/srv_winreg_nt.c | 10 +---- source3/utils/net_rpc_registry.c | 2 +- 10 files changed, 102 insertions(+), 24 deletions(-) diff --git a/source3/libmsrpc/cac_winreg.c b/source3/libmsrpc/cac_winreg.c index be7bc0a220..a43febb0d6 100644 --- a/source3/libmsrpc/cac_winreg.c +++ b/source3/libmsrpc/cac_winreg.c @@ -841,7 +841,7 @@ int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx, uint32 *pdata_size = &data_size; uint32 data_length = 0; uint32 *pdata_length = &data_length; - struct winreg_StringBuf name_buf; + struct winreg_ValNameBuf name_buf; enum winreg_Type *ptype = &types_out[num_values_out]; memset( name_buffer, 0x0, max_valnamelen ); diff --git a/source3/librpc/gen_ndr/cli_winreg.c b/source3/librpc/gen_ndr/cli_winreg.c index 88ea868f60..7ace36ca52 100644 --- a/source3/librpc/gen_ndr/cli_winreg.c +++ b/source3/librpc/gen_ndr/cli_winreg.c @@ -334,7 +334,7 @@ NTSTATUS rpccli_winreg_EnumKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, return werror_to_ntstatus(r.out.result); } -NTSTATUS rpccli_winreg_EnumValue(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type **type, uint8_t **data, uint32_t **data_size, uint32_t **value_length) +NTSTATUS rpccli_winreg_EnumValue(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t enum_index, struct winreg_ValNameBuf *name, enum winreg_Type **type, uint8_t **data, uint32_t **data_size, uint32_t **value_length) { struct winreg_EnumValue r; NTSTATUS status; diff --git a/source3/librpc/gen_ndr/cli_winreg.h b/source3/librpc/gen_ndr/cli_winreg.h index 0e451f5145..edd4c3e7e4 100644 --- a/source3/librpc/gen_ndr/cli_winreg.h +++ b/source3/librpc/gen_ndr/cli_winreg.h @@ -11,7 +11,7 @@ NTSTATUS rpccli_winreg_CreateKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct NTSTATUS rpccli_winreg_DeleteKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct winreg_String key); NTSTATUS rpccli_winreg_DeleteValue(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct winreg_String value); NTSTATUS rpccli_winreg_EnumKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, struct winreg_StringBuf **keyclass, NTTIME **last_changed_time); -NTSTATUS rpccli_winreg_EnumValue(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type **type, uint8_t **data, uint32_t **data_size, uint32_t **value_length); +NTSTATUS rpccli_winreg_EnumValue(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t enum_index, struct winreg_ValNameBuf *name, enum winreg_Type **type, uint8_t **data, uint32_t **data_size, uint32_t **value_length); NTSTATUS rpccli_winreg_FlushKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle); NTSTATUS rpccli_winreg_GetKeySecurity(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd); NTSTATUS rpccli_winreg_LoadKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename); diff --git a/source3/librpc/gen_ndr/ndr_winreg.c b/source3/librpc/gen_ndr/ndr_winreg.c index 811749d759..bc931dafe8 100644 --- a/source3/librpc/gen_ndr/ndr_winreg.c +++ b/source3/librpc/gen_ndr/ndr_winreg.c @@ -335,6 +335,77 @@ _PUBLIC_ void ndr_print_winreg_StringBuf(struct ndr_print *ndr, const char *name ndr->depth--; } +NTSTATUS ndr_push_winreg_ValNameBuf(struct ndr_push *ndr, int ndr_flags, const struct winreg_ValNameBuf *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, strlen_m_term(r->name)*2)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->size)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->name)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->name) { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size/2)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, strlen_m_term(r->name)*2/2)); + NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->name, strlen_m_term(r->name)*2/2, sizeof(uint16_t), CH_UTF16)); + } + } + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_winreg_ValNameBuf(struct ndr_pull *ndr, int ndr_flags, struct winreg_ValNameBuf *r) +{ + uint32_t _ptr_name; + TALLOC_CTX *_mem_save_name_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size)); + NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_name)); + if (_ptr_name) { + NDR_PULL_ALLOC(ndr, r->name); + } else { + r->name = NULL; + } + } + if (ndr_flags & NDR_BUFFERS) { + if (r->name) { + _mem_save_name_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->name, 0); + NDR_CHECK(ndr_pull_array_size(ndr, &r->name)); + NDR_CHECK(ndr_pull_array_length(ndr, &r->name)); + if (ndr_get_array_length(ndr, &r->name) > ndr_get_array_size(ndr, &r->name)) { + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->name), ndr_get_array_length(ndr, &r->name)); + } + NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->name, ndr_get_array_length(ndr, &r->name), sizeof(uint16_t), CH_UTF16)); + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_name_0, 0); + } + if (r->name) { + NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->name, r->size/2)); + } + if (r->name) { + NDR_CHECK(ndr_check_array_length(ndr, (void*)&r->name, r->length/2)); + } + } + return NT_STATUS_OK; +} + +_PUBLIC_ void ndr_print_winreg_ValNameBuf(struct ndr_print *ndr, const char *name, const struct winreg_ValNameBuf *r) +{ + ndr_print_struct(ndr, name, "winreg_ValNameBuf"); + ndr->depth++; + ndr_print_uint16(ndr, "length", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?strlen_m_term(r->name)*2:r->length); + ndr_print_uint16(ndr, "size", r->size); + ndr_print_ptr(ndr, "name", r->name); + ndr->depth++; + if (r->name) { + ndr_print_string(ndr, "name", r->name); + } + ndr->depth--; + ndr->depth--; +} + NTSTATUS ndr_push_KeySecurityAttribute(struct ndr_push *ndr, int ndr_flags, const struct KeySecurityAttribute *r) { if (ndr_flags & NDR_SCALARS) { @@ -1394,7 +1465,7 @@ NTSTATUS ndr_push_winreg_EnumValue(struct ndr_push *ndr, int flags, const struct NDR_CHECK(ndr_push_policy_handle(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.handle)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.enum_index)); if (r->in.name == NULL) return NT_STATUS_INVALID_PARAMETER_MIX; - NDR_CHECK(ndr_push_winreg_StringBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.name)); + NDR_CHECK(ndr_push_winreg_ValNameBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.name)); NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.type)); if (r->in.type) { NDR_CHECK(ndr_push_winreg_Type(ndr, NDR_SCALARS, *r->in.type)); @@ -1417,7 +1488,7 @@ NTSTATUS ndr_push_winreg_EnumValue(struct ndr_push *ndr, int flags, const struct } if (flags & NDR_OUT) { if (r->out.name == NULL) return NT_STATUS_INVALID_PARAMETER_MIX; - NDR_CHECK(ndr_push_winreg_StringBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.name)); + NDR_CHECK(ndr_push_winreg_ValNameBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.name)); NDR_CHECK(ndr_push_unique_ptr(ndr, r->out.type)); if (r->out.type) { NDR_CHECK(ndr_push_winreg_Type(ndr, NDR_SCALARS, *r->out.type)); @@ -1470,7 +1541,7 @@ NTSTATUS ndr_pull_winreg_EnumValue(struct ndr_pull *ndr, int flags, struct winre } _mem_save_name_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->in.name, LIBNDR_FLAG_REF_ALLOC); - NDR_CHECK(ndr_pull_winreg_StringBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.name)); + NDR_CHECK(ndr_pull_winreg_ValNameBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.name)); NDR_PULL_SET_MEM_CTX(ndr, _mem_save_name_0, LIBNDR_FLAG_REF_ALLOC); NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_type)); if (_ptr_type) { @@ -1543,7 +1614,7 @@ NTSTATUS ndr_pull_winreg_EnumValue(struct ndr_pull *ndr, int flags, struct winre } _mem_save_name_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->out.name, LIBNDR_FLAG_REF_ALLOC); - NDR_CHECK(ndr_pull_winreg_StringBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.name)); + NDR_CHECK(ndr_pull_winreg_ValNameBuf(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.name)); NDR_PULL_SET_MEM_CTX(ndr, _mem_save_name_0, LIBNDR_FLAG_REF_ALLOC); NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_type)); if (_ptr_type) { @@ -1629,7 +1700,7 @@ _PUBLIC_ void ndr_print_winreg_EnumValue(struct ndr_print *ndr, const char *name ndr_print_uint32(ndr, "enum_index", r->in.enum_index); ndr_print_ptr(ndr, "name", r->in.name); ndr->depth++; - ndr_print_winreg_StringBuf(ndr, "name", r->in.name); + ndr_print_winreg_ValNameBuf(ndr, "name", r->in.name); ndr->depth--; ndr_print_ptr(ndr, "type", r->in.type); ndr->depth++; @@ -1662,7 +1733,7 @@ _PUBLIC_ void ndr_print_winreg_EnumValue(struct ndr_print *ndr, const char *name ndr->depth++; ndr_print_ptr(ndr, "name", r->out.name); ndr->depth++; - ndr_print_winreg_StringBuf(ndr, "name", r->out.name); + ndr_print_winreg_ValNameBuf(ndr, "name", r->out.name); ndr->depth--; ndr_print_ptr(ndr, "type", r->out.type); ndr->depth++; diff --git a/source3/librpc/gen_ndr/ndr_winreg.h b/source3/librpc/gen_ndr/ndr_winreg.h index b214f8c170..a224db006c 100644 --- a/source3/librpc/gen_ndr/ndr_winreg.h +++ b/source3/librpc/gen_ndr/ndr_winreg.h @@ -92,6 +92,7 @@ void ndr_print_KeySecurityData(struct ndr_print *ndr, const char *name, const st void ndr_print_winreg_SecBuf(struct ndr_print *ndr, const char *name, const struct winreg_SecBuf *r); void ndr_print_winreg_CreateAction(struct ndr_print *ndr, const char *name, enum winreg_CreateAction r); void ndr_print_winreg_StringBuf(struct ndr_print *ndr, const char *name, const struct winreg_StringBuf *r); +void ndr_print_winreg_ValNameBuf(struct ndr_print *ndr, const char *name, const struct winreg_ValNameBuf *r); void ndr_print_KeySecurityAttribute(struct ndr_print *ndr, const char *name, const struct KeySecurityAttribute *r); void ndr_print_QueryMultipleValue(struct ndr_print *ndr, const char *name, const struct QueryMultipleValue *r); void ndr_print_winreg_OpenHKCR(struct ndr_print *ndr, const char *name, int flags, const struct winreg_OpenHKCR *r); diff --git a/source3/librpc/gen_ndr/srv_winreg.h b/source3/librpc/gen_ndr/srv_winreg.h index 8c5505a878..dfa557f90c 100644 --- a/source3/librpc/gen_ndr/srv_winreg.h +++ b/source3/librpc/gen_ndr/srv_winreg.h @@ -11,7 +11,7 @@ WERROR _winreg_CreateKey(pipes_struct *p, struct policy_handle *handle, struct w WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key); WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value); WERROR _winreg_EnumKey(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, struct winreg_StringBuf *keyclass, NTTIME *last_changed_time); -WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length); +WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_ValNameBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length); WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle); WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd); WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename); diff --git a/source3/librpc/gen_ndr/winreg.h b/source3/librpc/gen_ndr/winreg.h index 87ba27e623..4703c3dc07 100644 --- a/source3/librpc/gen_ndr/winreg.h +++ b/source3/librpc/gen_ndr/winreg.h @@ -53,6 +53,12 @@ struct winreg_StringBuf { const char *name;/* [unique,length_is(length/2),charset(UTF16),size_is(size/2)] */ }; +struct winreg_ValNameBuf { + uint16_t length;/* [value(strlen_m_term(name)*2)] */ + uint16_t size; + const char *name;/* [unique,length_is(length/2),charset(UTF16),size_is(size/2)] */ +}; + struct KeySecurityAttribute { uint32_t data_size; struct KeySecurityData sec_data; @@ -219,7 +225,7 @@ struct winreg_EnumValue { struct { struct policy_handle *handle;/* [ref] */ uint32_t enum_index; - struct winreg_StringBuf *name;/* [ref] */ + struct winreg_ValNameBuf *name;/* [ref] */ enum winreg_Type *type;/* [unique] */ uint8_t *data;/* [unique,length_is(*value_length),size_is(*data_size)] */ uint32_t *data_size;/* [unique] */ @@ -227,7 +233,7 @@ struct winreg_EnumValue { } in; struct { - struct winreg_StringBuf *name;/* [ref] */ + struct winreg_ValNameBuf *name;/* [ref] */ enum winreg_Type *type;/* [unique] */ uint8_t *data;/* [unique,length_is(*value_length),size_is(*data_size)] */ uint32_t *data_size;/* [unique] */ diff --git a/source3/librpc/idl/winreg.idl b/source3/librpc/idl/winreg.idl index a69079bf8e..c4907a199f 100644 --- a/source3/librpc/idl/winreg.idl +++ b/source3/librpc/idl/winreg.idl @@ -140,7 +140,6 @@ import "lsa.idl", "initshutdown.idl", "security.idl"; [size_is(size/2),length_is(length/2),charset(UTF16)] uint16 *name; } winreg_StringBuf; - /******************/ /* Function: 0x09 */ WERROR winreg_EnumKey( @@ -151,13 +150,22 @@ import "lsa.idl", "initshutdown.idl", "security.idl"; [in,out,unique] NTTIME *last_changed_time ); + typedef struct { + [value(strlen_m_term(name)*2)] uint16 length; + /* size cannot be auto-set by value() as it is the + amount of space the server is allowed to use for this + string in the reply, not its current size */ + uint16 size; + [size_is(size/2),length_is(length/2),charset(UTF16)] uint16 *name; + } winreg_ValNameBuf; + /******************/ /* Function: 0x0a */ WERROR winreg_EnumValue( [in,ref] policy_handle *handle, [in] uint32 enum_index, - [in,out,ref] winreg_StringBuf *name, + [in,out,ref] winreg_ValNameBuf *name, [in,out,unique] winreg_Type *type, [in,out,unique,size_is(*data_size),length_is(*value_length)] uint8 *data, [in,out,unique] uint32 *data_size, diff --git a/source3/rpc_server/srv_winreg_nt.c b/source3/rpc_server/srv_winreg_nt.c index ce3e2e4b7d..cac06888e4 100644 --- a/source3/rpc_server/srv_winreg_nt.c +++ b/source3/rpc_server/srv_winreg_nt.c @@ -626,7 +626,7 @@ WERROR _winreg_EnumKey(pipes_struct *p, struct policy_handle *handle, uint32_t e ****************************************************************************/ WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, - uint32_t enum_index, struct winreg_StringBuf *name, + uint32_t enum_index, struct winreg_ValNameBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length) { @@ -1317,14 +1317,6 @@ WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct wi key = info->key; - if (!name.name || (strlen(name.name) == 0)) { - /* - * This is the "Standard Value" for a key, we don't support - * that (yet...) - */ - return WERR_ACCESS_DENIED; - } - /* access checks first */ if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) ) diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c index 49149db19e..c684b04b8e 100644 --- a/source3/utils/net_rpc_registry.c +++ b/source3/utils/net_rpc_registry.c @@ -265,7 +265,7 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx, uint32 *pvalue_length = &value_length; char n; - struct winreg_StringBuf name_buf; + struct winreg_ValNameBuf name_buf; n = '\0'; name_buf.name = &n; -- cgit