2
Unix SMB/CIFS implementation.
4
endpoint server for the winreg pipe
6
Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
7
Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include "rpc_server/dcerpc_server.h"
25
#include "lib/registry/registry.h"
26
#include "librpc/gen_ndr/ndr_winreg.h"
27
#include "rpc_server/common/common.h"
28
#include "librpc/gen_ndr/ndr_security.h"
29
#include "param/param.h"
30
#include "libcli/security/security.h"
32
enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
34
static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call,
35
const struct dcesrv_interface *iface)
37
struct registry_context *ctx;
40
err = reg_open_samba(dce_call->context,
41
&ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info,
44
if (!W_ERROR_IS_OK(err)) {
45
DEBUG(0, ("Error opening registry: %s\n", win_errstr(err)));
46
return NT_STATUS_UNSUCCESSFUL;
49
dce_call->context->private_data = ctx;
54
#define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
56
static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
57
TALLOC_CTX *mem_ctx, uint32_t hkey,
58
struct policy_handle **outh)
60
struct registry_context *ctx = dce_call->context->private_data;
61
struct dcesrv_handle *h;
64
h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
66
result = reg_get_predefined_key(ctx, hkey,
67
(struct registry_key **)&h->data);
68
if (!W_ERROR_IS_OK(result)) {
71
*outh = &h->wire_handle;
76
#define func_winreg_OpenHive(k,n) static WERROR dcesrv_winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
78
return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
81
func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
82
func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
83
func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
84
func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
85
func_winreg_OpenHive(HKU,HKEY_USERS)
86
func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
87
func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
88
func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
89
func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
94
static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
96
struct winreg_CloseKey *r)
98
struct dcesrv_handle *h;
100
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
104
ZERO_STRUCTP(r->out.handle);
112
static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
114
struct winreg_CreateKey *r)
116
struct dcesrv_handle *h, *newh;
117
struct security_descriptor sd;
118
struct registry_key *key;
121
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
124
newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
126
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
128
case SECURITY_SYSTEM:
129
case SECURITY_ADMINISTRATOR:
130
/* the security descriptor is optional */
131
if (r->in.secdesc != NULL) {
133
enum ndr_err_code ndr_err;
134
sdblob.data = r->in.secdesc->sd.data;
135
sdblob.length = r->in.secdesc->sd.len;
136
if (sdblob.data == NULL) {
137
return WERR_INVALID_PARAM;
139
ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
140
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
141
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
142
return WERR_INVALID_PARAM;
146
result = reg_key_add_name(newh, key, r->in.name.name, NULL,
147
r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data);
148
if (W_ERROR_IS_OK(result)) {
149
r->out.new_handle = &newh->wire_handle;
156
return WERR_ACCESS_DENIED;
164
static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
166
struct winreg_DeleteKey *r)
168
struct dcesrv_handle *h;
169
struct registry_key *key;
171
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
174
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
176
case SECURITY_SYSTEM:
177
case SECURITY_ADMINISTRATOR:
178
return reg_key_del(key, r->in.key.name);
180
return WERR_ACCESS_DENIED;
188
static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
190
struct winreg_DeleteValue *r)
192
struct dcesrv_handle *h;
193
struct registry_key *key;
195
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
198
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
200
case SECURITY_SYSTEM:
201
case SECURITY_ADMINISTRATOR:
202
return reg_del_value(key, r->in.value.name);
204
return WERR_ACCESS_DENIED;
212
static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
214
struct winreg_EnumKey *r)
216
struct dcesrv_handle *h;
217
struct registry_key *key;
218
const char *name, *classname;
222
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
225
result = reg_key_get_subkey_by_index(mem_ctx,
226
key, r->in.enum_index, &name, &classname, &last_mod);
228
if (2*strlen_m_term(name) > r->in.name->size) {
229
return WERR_MORE_DATA;
233
r->out.name->name = name;
234
r->out.name->length = 2*strlen_m_term(name);
236
r->out.name->name = r->in.name->name;
237
r->out.name->length = r->in.name->length;
239
r->out.name->size = r->in.name->size;
241
r->out.keyclass = r->in.keyclass;
242
if (classname != NULL) {
243
r->out.keyclass->name = classname;
244
r->out.keyclass->length = 2*strlen_m_term(classname);
246
r->out.keyclass->name = r->in.keyclass->name;
247
r->out.keyclass->length = r->in.keyclass->length;
249
r->out.keyclass->size = r->in.keyclass->size;
251
if (r->in.last_changed_time != NULL)
252
r->out.last_changed_time = &last_mod;
261
static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
263
struct winreg_EnumValue *r)
265
struct dcesrv_handle *h;
266
struct registry_key *key;
267
const char *data_name;
272
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
275
result = reg_key_get_value_by_index(mem_ctx, key,
276
r->in.enum_index, &data_name, &data_type, &data);
278
if (!W_ERROR_IS_OK(result)) {
279
/* if the lookup wasn't successful, send client query back */
280
data_name = r->in.name->name;
281
data_type = *r->in.type;
282
data.data = r->in.value;
283
data.length = *r->in.length;
286
/* check if there is enough room for the name */
287
if (r->in.name->size < 2*strlen_m_term(data_name)) {
288
return WERR_MORE_DATA;
291
/* "data_name" is NULL when we query the default attribute */
292
if (data_name != NULL) {
293
r->out.name->name = data_name;
294
r->out.name->length = 2*strlen_m_term(data_name);
296
r->out.name->name = r->in.name->name;
297
r->out.name->length = r->in.name->length;
299
r->out.name->size = r->in.name->size;
301
r->out.type = talloc(mem_ctx, uint32_t);
305
*r->out.type = data_type;
307
/* check the client has enough room for the value */
308
if (r->in.value != NULL &&
309
r->in.size != NULL &&
310
data.length > *r->in.size) {
311
return WERR_MORE_DATA;
314
if (r->in.value != NULL) {
315
r->out.value = data.data;
318
if (r->in.size != NULL) {
319
r->out.size = talloc(mem_ctx, uint32_t);
320
*r->out.size = data.length;
321
r->out.length = r->out.size;
331
static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
333
struct winreg_FlushKey *r)
335
struct dcesrv_handle *h;
336
struct registry_key *key;
338
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
341
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
343
case SECURITY_SYSTEM:
344
case SECURITY_ADMINISTRATOR:
345
return reg_key_flush(key);
347
return WERR_ACCESS_DENIED;
353
winreg_GetKeySecurity
355
static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
357
struct winreg_GetKeySecurity *r)
359
struct dcesrv_handle *h;
361
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
363
return WERR_NOT_SUPPORTED;
370
static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
372
struct winreg_LoadKey *r)
374
return WERR_NOT_SUPPORTED;
379
winreg_NotifyChangeKeyValue
381
static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
383
struct winreg_NotifyChangeKeyValue *r)
385
return WERR_NOT_SUPPORTED;
392
static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
394
struct winreg_OpenKey *r)
396
struct dcesrv_handle *h, *newh;
397
struct registry_key *key;
400
DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
403
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
405
case SECURITY_SYSTEM:
406
case SECURITY_ADMINISTRATOR:
408
if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
409
newh = talloc_reference(dce_call->context, h);
412
newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
413
result = reg_open_key(newh, key, r->in.keyname.name,
414
(struct registry_key **)&newh->data);
417
if (W_ERROR_IS_OK(result)) {
418
r->out.handle = &newh->wire_handle;
424
return WERR_ACCESS_DENIED;
433
static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
435
struct winreg_QueryInfoKey *r)
437
struct dcesrv_handle *h;
438
struct registry_key *key;
439
const char *classname = NULL;
442
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
445
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
447
case SECURITY_SYSTEM:
448
case SECURITY_ADMINISTRATOR:
450
result = reg_key_get_info(mem_ctx, key, &classname,
451
r->out.num_subkeys, r->out.num_values,
452
r->out.last_changed_time, r->out.max_subkeylen,
453
r->out.max_valnamelen, r->out.max_valbufsize);
455
if (classname != NULL) {
456
r->out.classname->name = classname;
457
r->out.classname->name_len = 2*strlen_m_term(classname);
459
r->out.classname->name = r->in.classname->name;
460
r->out.classname->name_len = r->in.classname->name_len;
462
r->out.classname->name_size = r->in.classname->name_size;
466
return WERR_ACCESS_DENIED;
474
static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
476
struct winreg_QueryValue *r)
478
struct dcesrv_handle *h;
479
struct registry_key *key;
481
DATA_BLOB value_data;
484
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
487
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
489
case SECURITY_SYSTEM:
490
case SECURITY_ADMINISTRATOR:
492
result = reg_key_get_value_by_name(mem_ctx, key,
493
r->in.value_name->name, &value_type, &value_data);
495
if (!W_ERROR_IS_OK(result)) {
496
/* if the lookup wasn't successful, send client query back */
497
value_type = *r->in.type;
498
value_data.data = r->in.data;
499
value_data.length = *r->in.data_length;
502
r->out.type = talloc(mem_ctx, uint32_t);
506
*r->out.type = value_type;
507
r->out.data_length = talloc(mem_ctx, uint32_t);
508
if (!r->out.data_length) {
511
*r->out.data_length = value_data.length;
512
r->out.data_size = talloc(mem_ctx, uint32_t);
513
if (!r->out.data_size) {
516
*r->out.data_size = value_data.length;
517
r->out.data = value_data.data;
521
return WERR_ACCESS_DENIED;
529
static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
531
struct winreg_ReplaceKey *r)
533
return WERR_NOT_SUPPORTED;
540
static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
542
struct winreg_RestoreKey *r)
544
return WERR_NOT_SUPPORTED;
551
static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
553
struct winreg_SaveKey *r)
555
return WERR_NOT_SUPPORTED;
560
winreg_SetKeySecurity
562
static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
564
struct winreg_SetKeySecurity *r)
566
return WERR_NOT_SUPPORTED;
573
static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
575
struct winreg_SetValue *r)
577
struct dcesrv_handle *h;
578
struct registry_key *key;
582
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
585
switch (security_session_user_level(dce_call->conn->auth_state.session_info))
587
case SECURITY_SYSTEM:
588
case SECURITY_ADMINISTRATOR:
589
data.data = r->in.data;
590
data.length = r->in.size;
591
result = reg_val_set(key, r->in.name.name, r->in.type, data);
594
return WERR_ACCESS_DENIED;
602
static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
604
struct winreg_UnLoadKey *r)
606
return WERR_NOT_SUPPORTED;
611
winreg_InitiateSystemShutdown
613
static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
615
struct winreg_InitiateSystemShutdown *r)
617
return WERR_NOT_SUPPORTED;
622
winreg_AbortSystemShutdown
624
static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
626
struct winreg_AbortSystemShutdown *r)
628
return WERR_NOT_SUPPORTED;
635
static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
637
struct winreg_GetVersion *r)
639
struct dcesrv_handle *h;
641
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
643
r->out.version = talloc(mem_ctx, uint32_t);
644
W_ERROR_HAVE_NO_MEMORY(r->out.version);
653
winreg_QueryMultipleValues
655
static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
657
struct winreg_QueryMultipleValues *r)
659
return WERR_NOT_SUPPORTED;
664
winreg_InitiateSystemShutdownEx
666
static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
668
struct winreg_InitiateSystemShutdownEx *r)
670
return WERR_NOT_SUPPORTED;
677
static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
679
struct winreg_SaveKeyEx *r)
681
return WERR_NOT_SUPPORTED;
686
winreg_QueryMultipleValues2
688
static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
690
struct winreg_QueryMultipleValues2 *r)
692
return WERR_NOT_SUPPORTED;
696
/* include the generated boilerplate */
697
#include "librpc/gen_ndr/ndr_winreg_s.c"