samba-tool/backup: set the right permissions on our root dir
[samba4-gss.git] / source4 / rpc_server / winreg / rpc_winreg.c
blobf8bd8c1926b0536273827cc3172a7c0f749d25e1
1 /*
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/>.
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "lib/registry/registry.h"
26 #include "librpc/gen_ndr/ndr_winreg.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "libcli/security/session.h"
30 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
32 static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
33 TALLOC_CTX *mem_ctx, uint32_t hkey,
34 struct policy_handle **outh)
36 struct auth_session_info *session_info =
37 dcesrv_call_session_info(dce_call);
38 struct registry_context *ctx = NULL;
39 struct dcesrv_handle *h;
40 WERROR result;
42 h = dcesrv_handle_create(dce_call, HTYPE_REGKEY);
43 W_ERROR_HAVE_NO_MEMORY(h);
45 result = reg_open_samba(h, &ctx,
46 dce_call->event_ctx,
47 dce_call->conn->dce_ctx->lp_ctx,
48 session_info,
49 NULL);
50 if (!W_ERROR_IS_OK(result)) {
51 DEBUG(0, ("Error opening registry: %s\n", win_errstr(result)));
52 return result;
55 result = reg_get_predefined_key(ctx, hkey,
56 (struct registry_key **)&h->data);
57 if (!W_ERROR_IS_OK(result)) {
58 return result;
60 *outh = &h->wire_handle;
62 return result;
65 #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) \
66 { \
67 return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
70 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
71 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
72 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
73 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
74 func_winreg_OpenHive(HKU,HKEY_USERS)
75 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
76 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
77 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
78 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
81 winreg_CloseKey
83 static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
84 TALLOC_CTX *mem_ctx,
85 struct winreg_CloseKey *r)
87 struct dcesrv_handle *h;
89 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
91 talloc_unlink(dce_call->context, h);
93 ZERO_STRUCTP(r->out.handle);
95 return WERR_OK;
99 winreg_CreateKey
101 static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
102 TALLOC_CTX *mem_ctx,
103 struct winreg_CreateKey *r)
105 struct auth_session_info *session_info =
106 dcesrv_call_session_info(dce_call);
107 struct dcesrv_handle *h, *newh;
108 struct security_descriptor sd;
109 struct registry_key *key;
110 WERROR result;
112 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
113 key = h->data;
115 newh = dcesrv_handle_create(dce_call, HTYPE_REGKEY);
117 switch (security_session_user_level(session_info, NULL))
119 case SECURITY_SYSTEM:
120 case SECURITY_ADMINISTRATOR:
121 /* we support only non volatile keys */
122 if (r->in.options != REG_OPTION_NON_VOLATILE) {
123 return WERR_NOT_SUPPORTED;
126 /* the security descriptor is optional */
127 if (r->in.secdesc != NULL) {
128 DATA_BLOB sdblob;
129 enum ndr_err_code ndr_err;
130 sdblob.data = r->in.secdesc->sd.data;
131 sdblob.length = r->in.secdesc->sd.len;
132 if (sdblob.data == NULL) {
133 return WERR_INVALID_PARAMETER;
135 ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, &sd,
136 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
137 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
138 return WERR_INVALID_PARAMETER;
142 result = reg_key_add_name(newh, key, r->in.name.name, NULL,
143 r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data);
145 r->out.action_taken = talloc(mem_ctx, enum winreg_CreateAction);
146 if (r->out.action_taken == NULL) {
147 talloc_free(newh);
148 return WERR_NOT_ENOUGH_MEMORY;
150 *r->out.action_taken = REG_ACTION_NONE;
152 if (W_ERROR_IS_OK(result)) {
153 r->out.new_handle = &newh->wire_handle;
154 *r->out.action_taken = REG_CREATED_NEW_KEY;
155 } else {
156 talloc_free(newh);
159 return result;
160 default:
161 return WERR_ACCESS_DENIED;
167 winreg_DeleteKey
169 static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
170 TALLOC_CTX *mem_ctx,
171 struct winreg_DeleteKey *r)
173 struct auth_session_info *session_info =
174 dcesrv_call_session_info(dce_call);
175 struct dcesrv_handle *h;
176 struct registry_key *key;
177 WERROR result;
179 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
180 key = h->data;
182 switch (security_session_user_level(session_info, NULL))
184 case SECURITY_SYSTEM:
185 case SECURITY_ADMINISTRATOR:
186 result = reg_key_del(mem_ctx, key, r->in.key.name);
187 talloc_unlink(dce_call->context, h);
189 return result;
190 default:
191 return WERR_ACCESS_DENIED;
197 winreg_DeleteValue
199 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
200 TALLOC_CTX *mem_ctx,
201 struct winreg_DeleteValue *r)
203 struct auth_session_info *session_info =
204 dcesrv_call_session_info(dce_call);
205 struct dcesrv_handle *h;
206 struct registry_key *key;
208 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
209 key = h->data;
211 switch (security_session_user_level(session_info, NULL))
213 case SECURITY_SYSTEM:
214 case SECURITY_ADMINISTRATOR:
215 return reg_del_value(mem_ctx, key, r->in.value.name);
216 default:
217 return WERR_ACCESS_DENIED;
223 winreg_EnumKey
225 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
226 TALLOC_CTX *mem_ctx,
227 struct winreg_EnumKey *r)
229 struct dcesrv_handle *h;
230 struct registry_key *key;
231 const char *name, *classname;
232 NTTIME last_mod;
233 WERROR result;
235 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
236 key = h->data;
238 result = reg_key_get_subkey_by_index(mem_ctx,
239 key, r->in.enum_index, &name, &classname, &last_mod);
241 if (2*strlen_m_term(name) > r->in.name->size) {
242 return WERR_MORE_DATA;
245 if (name != NULL) {
246 r->out.name->name = name;
247 r->out.name->length = 2*strlen_m_term(name);
248 } else {
249 r->out.name->name = r->in.name->name;
250 r->out.name->length = r->in.name->length;
252 r->out.name->size = r->in.name->size;
254 r->out.keyclass = r->in.keyclass;
255 if (classname != NULL) {
256 r->out.keyclass->name = classname;
257 r->out.keyclass->length = 2*strlen_m_term(classname);
258 } else {
259 r->out.keyclass->name = r->in.keyclass->name;
260 r->out.keyclass->length = r->in.keyclass->length;
262 r->out.keyclass->size = r->in.keyclass->size;
264 if (r->in.last_changed_time != NULL)
265 r->out.last_changed_time = &last_mod;
267 return result;
272 winreg_EnumValue
274 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
275 TALLOC_CTX *mem_ctx,
276 struct winreg_EnumValue *r)
278 struct dcesrv_handle *h;
279 struct registry_key *key;
280 const char *data_name;
281 uint32_t data_type;
282 DATA_BLOB data;
283 WERROR result;
285 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
286 key = h->data;
288 result = reg_key_get_value_by_index(mem_ctx, key,
289 r->in.enum_index, &data_name, &data_type, &data);
291 if (!W_ERROR_IS_OK(result)) {
292 /* if the lookup wasn't successful, send client query back */
293 data_name = r->in.name->name;
294 data_type = *r->in.type;
295 data.data = r->in.value;
296 data.length = *r->in.length;
299 /* "data_name" is NULL when we query the default attribute */
300 if (data_name != NULL) {
301 r->out.name->name = data_name;
302 r->out.name->length = 2*strlen_m_term(data_name);
303 } else {
304 r->out.name->name = r->in.name->name;
305 r->out.name->length = r->in.name->length;
307 r->out.name->size = r->in.name->size;
309 r->out.type = talloc(mem_ctx, enum winreg_Type);
310 if (!r->out.type) {
311 return WERR_NOT_ENOUGH_MEMORY;
313 *r->out.type = (enum winreg_Type) data_type;
315 if (r->in.size != NULL) {
316 r->out.size = talloc(mem_ctx, uint32_t);
317 *r->out.size = data.length;
319 /* check the client has enough room for the value */
320 if (r->in.value != NULL &&
321 r->in.size != NULL &&
322 data.length > *r->in.size) {
323 return WERR_MORE_DATA;
326 if (r->in.value != NULL) {
327 r->out.value = data.data;
330 if (r->in.length != NULL) {
331 r->out.length = r->out.size;
334 return result;
339 winreg_FlushKey
341 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
342 TALLOC_CTX *mem_ctx,
343 struct winreg_FlushKey *r)
345 struct auth_session_info *session_info =
346 dcesrv_call_session_info(dce_call);
347 struct dcesrv_handle *h;
348 struct registry_key *key;
350 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
351 key = h->data;
353 switch (security_session_user_level(session_info, NULL))
355 case SECURITY_SYSTEM:
356 case SECURITY_ADMINISTRATOR:
357 return reg_key_flush(key);
358 default:
359 return WERR_ACCESS_DENIED;
365 winreg_GetKeySecurity
367 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
368 TALLOC_CTX *mem_ctx,
369 struct winreg_GetKeySecurity *r)
371 struct dcesrv_handle *h;
373 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
375 return WERR_NOT_SUPPORTED;
380 winreg_LoadKey
382 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
383 TALLOC_CTX *mem_ctx,
384 struct winreg_LoadKey *r)
386 return WERR_NOT_SUPPORTED;
391 winreg_NotifyChangeKeyValue
393 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
394 TALLOC_CTX *mem_ctx,
395 struct winreg_NotifyChangeKeyValue *r)
397 return WERR_NOT_SUPPORTED;
402 winreg_OpenKey
404 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
405 TALLOC_CTX *mem_ctx,
406 struct winreg_OpenKey *r)
408 struct auth_session_info *session_info =
409 dcesrv_call_session_info(dce_call);
410 struct dcesrv_handle *h, *newh;
411 struct registry_key *key;
412 WERROR result;
414 DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
415 key = h->data;
417 switch (security_session_user_level(session_info, NULL))
419 case SECURITY_SYSTEM:
420 case SECURITY_ADMINISTRATOR:
421 case SECURITY_USER:
422 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
423 newh = talloc_reference(dce_call->context, h);
424 result = WERR_OK;
425 } else {
426 newh = dcesrv_handle_create(dce_call, HTYPE_REGKEY);
427 result = reg_open_key(newh, key, r->in.keyname.name,
428 (struct registry_key **)&newh->data);
431 if (W_ERROR_IS_OK(result)) {
432 r->out.handle = &newh->wire_handle;
433 } else {
434 talloc_free(newh);
436 return result;
437 default:
438 return WERR_ACCESS_DENIED;
444 winreg_QueryInfoKey
446 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
447 TALLOC_CTX *mem_ctx,
448 struct winreg_QueryInfoKey *r)
450 struct auth_session_info *session_info =
451 dcesrv_call_session_info(dce_call);
452 struct dcesrv_handle *h;
453 struct registry_key *key;
454 const char *classname = NULL;
455 WERROR result;
457 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
458 key = h->data;
460 switch (security_session_user_level(session_info, NULL))
462 case SECURITY_SYSTEM:
463 case SECURITY_ADMINISTRATOR:
464 case SECURITY_USER:
465 result = reg_key_get_info(mem_ctx, key, &classname,
466 r->out.num_subkeys, r->out.num_values,
467 r->out.last_changed_time, r->out.max_subkeylen,
468 r->out.max_valnamelen, r->out.max_valbufsize);
470 if (r->out.max_subkeylen != NULL) {
471 /* for UTF16 encoding */
472 *r->out.max_subkeylen *= 2;
474 if (r->out.max_valnamelen != NULL) {
475 /* for UTF16 encoding */
476 *r->out.max_valnamelen *= 2;
479 if (classname != NULL) {
480 r->out.classname->name = classname;
481 r->out.classname->name_len = 2*strlen_m_term(classname);
482 } else {
483 r->out.classname->name = r->in.classname->name;
484 r->out.classname->name_len = r->in.classname->name_len;
486 r->out.classname->name_size = r->in.classname->name_size;
488 return result;
489 default:
490 return WERR_ACCESS_DENIED;
496 winreg_QueryValue
498 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
499 TALLOC_CTX *mem_ctx,
500 struct winreg_QueryValue *r)
502 struct auth_session_info *session_info =
503 dcesrv_call_session_info(dce_call);
504 struct dcesrv_handle *h;
505 struct registry_key *key;
506 uint32_t value_type;
507 DATA_BLOB value_data;
508 WERROR result;
510 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
511 key = h->data;
513 switch (security_session_user_level(session_info, NULL))
515 case SECURITY_SYSTEM:
516 case SECURITY_ADMINISTRATOR:
517 case SECURITY_USER:
518 if ((r->in.type == NULL) || (r->in.data_length == NULL) ||
519 (r->in.data_size == NULL)) {
520 return WERR_INVALID_PARAMETER;
523 result = reg_key_get_value_by_name(mem_ctx, key,
524 r->in.value_name->name, &value_type, &value_data);
526 if (!W_ERROR_IS_OK(result)) {
527 /* if the lookup wasn't successful, send client query back */
528 value_type = *r->in.type;
529 value_data.data = r->in.data;
530 value_data.length = *r->in.data_length;
531 } else {
532 if ((r->in.data != NULL)
533 && (*r->in.data_size < value_data.length)) {
534 result = WERR_MORE_DATA;
538 r->out.type = talloc(mem_ctx, enum winreg_Type);
539 if (!r->out.type) {
540 return WERR_NOT_ENOUGH_MEMORY;
542 *r->out.type = (enum winreg_Type) value_type;
543 r->out.data_length = talloc(mem_ctx, uint32_t);
544 if (!r->out.data_length) {
545 return WERR_NOT_ENOUGH_MEMORY;
547 *r->out.data_length = value_data.length;
548 r->out.data_size = talloc(mem_ctx, uint32_t);
549 if (!r->out.data_size) {
550 return WERR_NOT_ENOUGH_MEMORY;
552 *r->out.data_size = value_data.length;
553 r->out.data = value_data.data;
555 return result;
556 default:
557 return WERR_ACCESS_DENIED;
563 winreg_ReplaceKey
565 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
566 TALLOC_CTX *mem_ctx,
567 struct winreg_ReplaceKey *r)
569 return WERR_NOT_SUPPORTED;
574 winreg_RestoreKey
576 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
577 TALLOC_CTX *mem_ctx,
578 struct winreg_RestoreKey *r)
580 return WERR_NOT_SUPPORTED;
585 winreg_SaveKey
587 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
588 TALLOC_CTX *mem_ctx,
589 struct winreg_SaveKey *r)
591 return WERR_NOT_SUPPORTED;
596 winreg_SetKeySecurity
598 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
599 TALLOC_CTX *mem_ctx,
600 struct winreg_SetKeySecurity *r)
602 return WERR_NOT_SUPPORTED;
607 winreg_SetValue
609 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
610 TALLOC_CTX *mem_ctx,
611 struct winreg_SetValue *r)
613 struct auth_session_info *session_info =
614 dcesrv_call_session_info(dce_call);
615 struct dcesrv_handle *h;
616 struct registry_key *key;
617 DATA_BLOB data;
618 WERROR result;
620 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
621 key = h->data;
623 switch (security_session_user_level(session_info, NULL))
625 case SECURITY_SYSTEM:
626 case SECURITY_ADMINISTRATOR:
627 data.data = r->in.data;
628 data.length = r->in.size;
629 result = reg_val_set(key, r->in.name.name, r->in.type, data);
630 return result;
631 default:
632 return WERR_ACCESS_DENIED;
638 winreg_UnLoadKey
640 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
641 TALLOC_CTX *mem_ctx,
642 struct winreg_UnLoadKey *r)
644 return WERR_NOT_SUPPORTED;
649 winreg_InitiateSystemShutdown
651 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
652 TALLOC_CTX *mem_ctx,
653 struct winreg_InitiateSystemShutdown *r)
655 return WERR_NOT_SUPPORTED;
660 winreg_AbortSystemShutdown
662 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
663 TALLOC_CTX *mem_ctx,
664 struct winreg_AbortSystemShutdown *r)
666 return WERR_NOT_SUPPORTED;
671 winreg_GetVersion
673 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
674 TALLOC_CTX *mem_ctx,
675 struct winreg_GetVersion *r)
677 struct dcesrv_handle *h;
679 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
681 r->out.version = talloc(mem_ctx, uint32_t);
682 W_ERROR_HAVE_NO_MEMORY(r->out.version);
684 *r->out.version = 5;
686 return WERR_OK;
691 winreg_QueryMultipleValues
693 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
694 TALLOC_CTX *mem_ctx,
695 struct winreg_QueryMultipleValues *r)
697 return WERR_NOT_SUPPORTED;
702 winreg_InitiateSystemShutdownEx
704 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
705 TALLOC_CTX *mem_ctx,
706 struct winreg_InitiateSystemShutdownEx *r)
708 return WERR_NOT_SUPPORTED;
713 winreg_SaveKeyEx
715 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
716 TALLOC_CTX *mem_ctx,
717 struct winreg_SaveKeyEx *r)
719 return WERR_NOT_SUPPORTED;
724 winreg_QueryMultipleValues2
726 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
727 TALLOC_CTX *mem_ctx,
728 struct winreg_QueryMultipleValues2 *r)
730 return WERR_NOT_SUPPORTED;
734 winreg_DeleteKeyEx
736 static WERROR dcesrv_winreg_DeleteKeyEx(struct dcesrv_call_state *dce_call,
737 TALLOC_CTX *mem_ctx,
738 struct winreg_DeleteKeyEx *r)
740 return WERR_NOT_SUPPORTED;
743 /* include the generated boilerplate */
744 #include "librpc/gen_ndr/ndr_winreg_s.c"