s3: Fix a winbind race leading to 100% CPU
[Samba.git] / source3 / rpc_client / cli_winreg.c
blob304d5b49e4672320e41bf72e1d981ff6ef4e0f3e
1 /*
2 * Unix SMB/CIFS implementation.
4 * WINREG client routines
6 * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "../librpc/gen_ndr/ndr_winreg_c.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "rpc_client/cli_winreg.h"
26 #include "../libcli/registry/util_reg.h"
28 NTSTATUS dcerpc_winreg_query_dword(TALLOC_CTX *mem_ctx,
29 struct dcerpc_binding_handle *h,
30 struct policy_handle *key_handle,
31 const char *value,
32 uint32_t *data,
33 WERROR *pwerr)
35 struct winreg_String wvalue;
36 enum winreg_Type type = REG_NONE;
37 uint32_t value_len = 0;
38 uint32_t data_size = 0;
39 WERROR result = WERR_OK;
40 NTSTATUS status;
41 DATA_BLOB blob;
43 wvalue.name = value;
45 status = dcerpc_winreg_QueryValue(h,
46 mem_ctx,
47 key_handle,
48 &wvalue,
49 &type,
50 NULL,
51 &data_size,
52 &value_len,
53 &result);
54 if (!NT_STATUS_IS_OK(status)) {
55 return status;
57 if (!W_ERROR_IS_OK(result)) {
58 *pwerr = result;
59 return status;
62 if (type != REG_DWORD) {
63 *pwerr = WERR_INVALID_DATATYPE;
64 return status;
67 if (data_size != 4) {
68 *pwerr = WERR_INVALID_DATA;
69 return status;
72 blob = data_blob_talloc_zero(mem_ctx, data_size);
73 if (blob.data == NULL) {
74 *pwerr = WERR_NOMEM;
75 return status;
77 value_len = 0;
79 status = dcerpc_winreg_QueryValue(h,
80 mem_ctx,
81 key_handle,
82 &wvalue,
83 &type,
84 blob.data,
85 &data_size,
86 &value_len,
87 &result);
88 if (!NT_STATUS_IS_OK(status)) {
89 return status;
91 if (!W_ERROR_IS_OK(result)) {
92 *pwerr = result;
93 return status;
96 if (data) {
97 *data = IVAL(blob.data, 0);
100 return status;
103 NTSTATUS dcerpc_winreg_query_binary(TALLOC_CTX *mem_ctx,
104 struct dcerpc_binding_handle *h,
105 struct policy_handle *key_handle,
106 const char *value,
107 DATA_BLOB *data,
108 WERROR *pwerr)
110 struct winreg_String wvalue;
111 enum winreg_Type type = REG_NONE;
112 WERROR result = WERR_OK;
113 uint32_t value_len = 0;
114 uint32_t data_size = 0;
115 NTSTATUS status;
116 DATA_BLOB blob;
118 ZERO_STRUCT(wvalue);
119 wvalue.name = value;
121 status = dcerpc_winreg_QueryValue(h,
122 mem_ctx,
123 key_handle,
124 &wvalue,
125 &type,
126 NULL,
127 &data_size,
128 &value_len,
129 &result);
130 if (!NT_STATUS_IS_OK(status)) {
131 return status;
133 if (!W_ERROR_IS_OK(result)) {
134 *pwerr = result;
135 return status;
138 if (type != REG_BINARY) {
139 *pwerr = WERR_INVALID_DATATYPE;
140 return status;
143 blob = data_blob_talloc_zero(mem_ctx, data_size);
144 if (blob.data == NULL) {
145 *pwerr = WERR_NOMEM;
146 return status;
148 value_len = 0;
150 status = dcerpc_winreg_QueryValue(h,
151 mem_ctx,
152 key_handle,
153 &wvalue,
154 &type,
155 blob.data,
156 &data_size,
157 &value_len,
158 &result);
159 if (!NT_STATUS_IS_OK(status)) {
160 return status;
162 if (!W_ERROR_IS_OK(result)) {
163 *pwerr = result;
164 return status;
167 if (data) {
168 data->data = blob.data;
169 data->length = blob.length;
172 return status;
175 NTSTATUS dcerpc_winreg_query_multi_sz(TALLOC_CTX *mem_ctx,
176 struct dcerpc_binding_handle *h,
177 struct policy_handle *key_handle,
178 const char *value,
179 const char ***data,
180 WERROR *pwerr)
182 struct winreg_String wvalue;
183 enum winreg_Type type = REG_NONE;
184 WERROR result = WERR_OK;
185 uint32_t value_len = 0;
186 uint32_t data_size = 0;
187 NTSTATUS status;
188 DATA_BLOB blob;
190 wvalue.name = value;
192 status = dcerpc_winreg_QueryValue(h,
193 mem_ctx,
194 key_handle,
195 &wvalue,
196 &type,
197 NULL,
198 &data_size,
199 &value_len,
200 &result);
201 if (!NT_STATUS_IS_OK(status)) {
202 return status;
204 if (!W_ERROR_IS_OK(result)) {
205 *pwerr = result;
206 return status;
209 if (type != REG_MULTI_SZ) {
210 *pwerr = WERR_INVALID_DATATYPE;
211 return status;
214 blob = data_blob_talloc_zero(mem_ctx, data_size);
215 if (blob.data == NULL) {
216 *pwerr = WERR_NOMEM;
217 return status;
219 value_len = 0;
221 status = dcerpc_winreg_QueryValue(h,
222 mem_ctx,
223 key_handle,
224 &wvalue,
225 &type,
226 blob.data,
227 &data_size,
228 &value_len,
229 &result);
230 if (!NT_STATUS_IS_OK(status)) {
231 return status;
233 if (!W_ERROR_IS_OK(result)) {
234 *pwerr = result;
235 return status;
238 if (data) {
239 bool ok;
241 ok = pull_reg_multi_sz(mem_ctx, &blob, data);
242 if (!ok) {
243 *pwerr = WERR_NOMEM;
247 return status;
250 NTSTATUS dcerpc_winreg_query_sz(TALLOC_CTX *mem_ctx,
251 struct dcerpc_binding_handle *h,
252 struct policy_handle *key_handle,
253 const char *value,
254 const char **data,
255 WERROR *pwerr)
257 struct winreg_String wvalue;
258 enum winreg_Type type = REG_NONE;
259 WERROR result = WERR_OK;
260 uint32_t value_len = 0;
261 uint32_t data_size = 0;
262 NTSTATUS status;
263 DATA_BLOB blob;
265 wvalue.name = value;
267 status = dcerpc_winreg_QueryValue(h,
268 mem_ctx,
269 key_handle,
270 &wvalue,
271 &type,
272 NULL,
273 &data_size,
274 &value_len,
275 &result);
276 if (!NT_STATUS_IS_OK(status)) {
277 return status;
279 if (!W_ERROR_IS_OK(result)) {
280 *pwerr = result;
281 return status;
284 if (type != REG_SZ) {
285 *pwerr = WERR_INVALID_DATATYPE;
286 return status;
289 blob = data_blob_talloc_zero(mem_ctx, data_size);
290 if (blob.data == NULL) {
291 *pwerr = WERR_NOMEM;
292 return status;
294 value_len = 0;
296 status = dcerpc_winreg_QueryValue(h,
297 mem_ctx,
298 key_handle,
299 &wvalue,
300 &type,
301 blob.data,
302 &data_size,
303 &value_len,
304 &result);
305 if (!NT_STATUS_IS_OK(status)) {
306 return status;
308 if (!W_ERROR_IS_OK(result)) {
309 *pwerr = result;
310 return status;
313 if (data) {
314 bool ok;
316 ok = pull_reg_sz(mem_ctx, &blob, data);
317 if (!ok) {
318 *pwerr = WERR_NOMEM;
322 return status;
325 NTSTATUS dcerpc_winreg_query_sd(TALLOC_CTX *mem_ctx,
326 struct dcerpc_binding_handle *h,
327 struct policy_handle *key_handle,
328 const char *value,
329 struct security_descriptor **data,
330 WERROR *pwerr)
332 WERROR result = WERR_OK;
333 NTSTATUS status;
334 DATA_BLOB blob;
336 status = dcerpc_winreg_query_binary(mem_ctx,
338 key_handle,
339 value,
340 &blob,
341 &result);
342 if (!NT_STATUS_IS_OK(status)) {
343 return status;
345 if (!W_ERROR_IS_OK(result)) {
346 *pwerr = result;
347 return status;
350 if (data) {
351 struct security_descriptor *sd;
352 enum ndr_err_code ndr_err;
354 sd = talloc_zero(mem_ctx, struct security_descriptor);
355 if (sd == NULL) {
356 *pwerr = WERR_NOMEM;
357 return NT_STATUS_OK;
360 ndr_err = ndr_pull_struct_blob(&blob,
363 (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
364 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
365 DEBUG(2, ("dcerpc_winreg_query_sd: Failed to marshall "
366 "security descriptor\n"));
367 *pwerr = WERR_NOMEM;
368 return NT_STATUS_OK;
371 *data = sd;
374 return status;
377 NTSTATUS dcerpc_winreg_set_dword(TALLOC_CTX *mem_ctx,
378 struct dcerpc_binding_handle *h,
379 struct policy_handle *key_handle,
380 const char *value,
381 uint32_t data,
382 WERROR *pwerr)
384 struct winreg_String wvalue;
385 DATA_BLOB blob;
386 WERROR result = WERR_OK;
387 NTSTATUS status;
389 ZERO_STRUCT(wvalue);
390 wvalue.name = value;
391 blob = data_blob_talloc_zero(mem_ctx, 4);
392 SIVAL(blob.data, 0, data);
394 status = dcerpc_winreg_SetValue(h,
395 mem_ctx,
396 key_handle,
397 wvalue,
398 REG_DWORD,
399 blob.data,
400 blob.length,
401 &result);
402 if (!NT_STATUS_IS_OK(status)) {
403 return status;
405 if (!W_ERROR_IS_OK(result)) {
406 *pwerr = result;
409 return status;
412 NTSTATUS dcerpc_winreg_set_sz(TALLOC_CTX *mem_ctx,
413 struct dcerpc_binding_handle *h,
414 struct policy_handle *key_handle,
415 const char *value,
416 const char *data,
417 WERROR *pwerr)
419 struct winreg_String wvalue = { 0, };
420 DATA_BLOB blob;
421 WERROR result = WERR_OK;
422 NTSTATUS status;
424 wvalue.name = value;
425 if (data == NULL) {
426 blob = data_blob_string_const("");
427 } else {
428 if (!push_reg_sz(mem_ctx, &blob, data)) {
429 DEBUG(2, ("dcerpc_winreg_set_sz: Could not marshall "
430 "string %s for %s\n",
431 data, wvalue.name));
432 *pwerr = WERR_NOMEM;
433 return NT_STATUS_OK;
437 status = dcerpc_winreg_SetValue(h,
438 mem_ctx,
439 key_handle,
440 wvalue,
441 REG_SZ,
442 blob.data,
443 blob.length,
444 &result);
445 if (!NT_STATUS_IS_OK(status)) {
446 return status;
448 if (!W_ERROR_IS_OK(result)) {
449 *pwerr = result;
452 return status;
455 NTSTATUS dcerpc_winreg_set_expand_sz(TALLOC_CTX *mem_ctx,
456 struct dcerpc_binding_handle *h,
457 struct policy_handle *key_handle,
458 const char *value,
459 const char *data,
460 WERROR *pwerr)
462 struct winreg_String wvalue = { 0, };
463 DATA_BLOB blob;
464 WERROR result = WERR_OK;
465 NTSTATUS status;
467 wvalue.name = value;
468 if (data == NULL) {
469 blob = data_blob_string_const("");
470 } else {
471 if (!push_reg_sz(mem_ctx, &blob, data)) {
472 DEBUG(2, ("dcerpc_winreg_set_expand_sz: Could not marshall "
473 "string %s for %s\n",
474 data, wvalue.name));
475 *pwerr = WERR_NOMEM;
476 return NT_STATUS_OK;
480 status = dcerpc_winreg_SetValue(h,
481 mem_ctx,
482 key_handle,
483 wvalue,
484 REG_EXPAND_SZ,
485 blob.data,
486 blob.length,
487 &result);
488 if (!NT_STATUS_IS_OK(status)) {
489 return status;
491 if (!W_ERROR_IS_OK(result)) {
492 *pwerr = result;
495 return status;
498 NTSTATUS dcerpc_winreg_set_multi_sz(TALLOC_CTX *mem_ctx,
499 struct dcerpc_binding_handle *h,
500 struct policy_handle *key_handle,
501 const char *value,
502 const char **data,
503 WERROR *pwerr)
505 struct winreg_String wvalue = { 0, };
506 DATA_BLOB blob;
507 WERROR result = WERR_OK;
508 NTSTATUS status;
510 wvalue.name = value;
511 if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
512 DEBUG(2, ("dcerpc_winreg_set_multi_sz: Could not marshall "
513 "string multi sz for %s\n",
514 wvalue.name));
515 *pwerr = WERR_NOMEM;
516 return NT_STATUS_OK;
519 status = dcerpc_winreg_SetValue(h,
520 mem_ctx,
521 key_handle,
522 wvalue,
523 REG_MULTI_SZ,
524 blob.data,
525 blob.length,
526 &result);
527 if (!NT_STATUS_IS_OK(status)) {
528 return status;
530 if (!W_ERROR_IS_OK(result)) {
531 *pwerr = result;
534 return status;
537 NTSTATUS dcerpc_winreg_set_binary(TALLOC_CTX *mem_ctx,
538 struct dcerpc_binding_handle *h,
539 struct policy_handle *key_handle,
540 const char *value,
541 DATA_BLOB *data,
542 WERROR *pwerr)
544 struct winreg_String wvalue = { 0, };
545 WERROR result = WERR_OK;
546 NTSTATUS status;
548 wvalue.name = value;
550 status = dcerpc_winreg_SetValue(h,
551 mem_ctx,
552 key_handle,
553 wvalue,
554 REG_BINARY,
555 data->data,
556 data->length,
557 &result);
558 if (!NT_STATUS_IS_OK(status)) {
559 return status;
561 if (!W_ERROR_IS_OK(result)) {
562 *pwerr = result;
565 return status;
568 NTSTATUS dcerpc_winreg_set_sd(TALLOC_CTX *mem_ctx,
569 struct dcerpc_binding_handle *h,
570 struct policy_handle *key_handle,
571 const char *value,
572 const struct security_descriptor *data,
573 WERROR *pwerr)
575 enum ndr_err_code ndr_err;
576 DATA_BLOB blob;
578 ndr_err = ndr_push_struct_blob(&blob,
579 mem_ctx,
580 data,
581 (ndr_push_flags_fn_t) ndr_push_security_descriptor);
582 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
583 DEBUG(2, ("dcerpc_winreg_set_sd: Failed to marshall security "
584 "descriptor\n"));
585 *pwerr = WERR_NOMEM;
586 return NT_STATUS_OK;
589 return dcerpc_winreg_set_binary(mem_ctx,
591 key_handle,
592 value,
593 &blob,
594 pwerr);
597 NTSTATUS dcerpc_winreg_add_multi_sz(TALLOC_CTX *mem_ctx,
598 struct dcerpc_binding_handle *h,
599 struct policy_handle *key_handle,
600 const char *value,
601 const char *data,
602 WERROR *pwerr)
604 const char **a = NULL;
605 const char **p;
606 uint32_t i;
607 WERROR result = WERR_OK;
608 NTSTATUS status;
610 status = dcerpc_winreg_query_multi_sz(mem_ctx,
612 key_handle,
613 value,
615 &result);
617 /* count the elements */
618 for (p = a, i = 0; p && *p; p++, i++);
620 p = TALLOC_REALLOC_ARRAY(mem_ctx, a, const char *, i + 2);
621 if (p == NULL) {
622 *pwerr = WERR_NOMEM;
623 return NT_STATUS_OK;
626 p[i] = data;
627 p[i + 1] = NULL;
629 status = dcerpc_winreg_set_multi_sz(mem_ctx,
631 key_handle,
632 value,
634 pwerr);
636 return status;
639 NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx,
640 struct dcerpc_binding_handle *h,
641 struct policy_handle *key_hnd,
642 uint32_t *pnum_subkeys,
643 const char ***psubkeys,
644 WERROR *pwerr)
646 const char **subkeys;
647 uint32_t num_subkeys, max_subkeylen, max_classlen;
648 uint32_t num_values, max_valnamelen, max_valbufsize;
649 uint32_t i;
650 NTTIME last_changed_time;
651 uint32_t secdescsize;
652 struct winreg_String classname;
653 WERROR result = WERR_OK;
654 NTSTATUS status;
655 TALLOC_CTX *tmp_ctx;
657 tmp_ctx = talloc_stackframe();
658 if (tmp_ctx == NULL) {
659 return NT_STATUS_NO_MEMORY;
662 ZERO_STRUCT(classname);
664 status = dcerpc_winreg_QueryInfoKey(h,
665 tmp_ctx,
666 key_hnd,
667 &classname,
668 &num_subkeys,
669 &max_subkeylen,
670 &max_classlen,
671 &num_values,
672 &max_valnamelen,
673 &max_valbufsize,
674 &secdescsize,
675 &last_changed_time,
676 &result);
677 if (!NT_STATUS_IS_OK(status)) {
678 goto error;
680 if (!W_ERROR_IS_OK(result)) {
681 *pwerr = result;
682 goto error;
685 subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
686 if (subkeys == NULL) {
687 *pwerr = WERR_NOMEM;
688 goto error;
691 if (num_subkeys == 0) {
692 subkeys[0] = talloc_strdup(subkeys, "");
693 if (subkeys[0] == NULL) {
694 *pwerr = WERR_NOMEM;
695 goto error;
697 *pnum_subkeys = 0;
698 if (psubkeys) {
699 *psubkeys = talloc_move(mem_ctx, &subkeys);
702 TALLOC_FREE(tmp_ctx);
703 return NT_STATUS_OK;
706 for (i = 0; i < num_subkeys; i++) {
707 char c = '\0';
708 char n = '\0';
709 char *name = NULL;
710 struct winreg_StringBuf class_buf;
711 struct winreg_StringBuf name_buf;
712 NTTIME modtime;
714 class_buf.name = &c;
715 class_buf.size = max_classlen + 2;
716 class_buf.length = 0;
718 name_buf.name = &n;
719 name_buf.size = max_subkeylen + 2;
720 name_buf.length = 0;
722 ZERO_STRUCT(modtime);
724 status = dcerpc_winreg_EnumKey(h,
725 tmp_ctx,
726 key_hnd,
728 &name_buf,
729 &class_buf,
730 &modtime,
731 &result);
732 if (!NT_STATUS_IS_OK(status)) {
733 DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
734 nt_errstr(status)));
735 goto error;
738 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
739 *pwerr = WERR_OK;
740 break;
742 if (!W_ERROR_IS_OK(result)) {
743 DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
744 win_errstr(result)));
745 *pwerr = result;
746 goto error;
749 if (name_buf.name == NULL) {
750 *pwerr = WERR_INVALID_PARAMETER;
751 goto error;
754 name = talloc_strdup(subkeys, name_buf.name);
755 if (name == NULL) {
756 *pwerr = WERR_NOMEM;
757 goto error;
760 subkeys[i] = name;
763 *pnum_subkeys = num_subkeys;
764 if (psubkeys) {
765 *psubkeys = talloc_move(mem_ctx, &subkeys);
768 error:
769 TALLOC_FREE(tmp_ctx);
771 return status;
774 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */