r14408: More on fix for coverity #36. The previous fix would cause us to
[Samba/bb.git] / source3 / libmsrpc / cac_winreg.c
blobacd83f40760ded09bec8980497026149a6c49766
1 /*
2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (WINREG pipe)
4 * Copyright (C) Chris Nicholls 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libmsrpc.h"
22 #include "libmsrpc_internal.h"
25 int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op) {
26 SMBCSRV *srv = NULL;
27 struct rpc_pipe_client *pipe_hnd = NULL;
28 POLICY_HND *key = NULL;
29 WERROR err;
31 if(!hnd)
32 return CAC_FAILURE;
34 if(!hnd->_internal.ctx) {
35 hnd->status = NT_STATUS_INVALID_HANDLE;
36 return CAC_FAILURE;
39 if(!op || !op->in.root || !mem_ctx) {
40 hnd->status = NT_STATUS_INVALID_PARAMETER;
41 return CAC_FAILURE;
44 srv = cac_GetServer(hnd);
45 if(!srv) {
46 hnd->status = NT_STATUS_INVALID_CONNECTION;
47 return CAC_FAILURE;
50 /*initialize for winreg pipe if we have to*/
51 if(!hnd->_internal.pipes[PI_WINREG]) {
52 if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_WINREG, &(hnd->status)))) {
53 return CAC_FAILURE;
56 hnd->_internal.pipes[PI_WINREG] = True;
59 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
60 if(!pipe_hnd) {
61 hnd->status = NT_STATUS_INVALID_HANDLE;
62 return CAC_FAILURE;
65 key = talloc(mem_ctx, POLICY_HND);
66 if(!key) {
67 hnd->status = NT_STATUS_NO_MEMORY;
70 err = rpccli_reg_connect( pipe_hnd, mem_ctx, op->in.root, op->in.access, key);
71 hnd->status = werror_to_ntstatus(err);
73 if(!NT_STATUS_IS_OK(hnd->status)) {
74 return CAC_FAILURE;
77 op->out.key = key;
79 return CAC_SUCCESS;
82 int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
83 struct rpc_pipe_client *pipe_hnd = NULL;
84 WERROR err;
86 if(!hnd)
87 return CAC_FAILURE;
89 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
90 hnd->status = NT_STATUS_INVALID_HANDLE;
91 return CAC_FAILURE;
94 if(!key || !mem_ctx) {
95 hnd->status = NT_STATUS_INVALID_PARAMETER;
96 return CAC_FAILURE;
99 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
100 if(!pipe_hnd) {
101 hnd->status = NT_STATUS_INVALID_HANDLE;
102 return CAC_FAILURE;
105 err = rpccli_reg_close(pipe_hnd, mem_ctx, key);
106 hnd->status = werror_to_ntstatus(err);
108 if(!NT_STATUS_IS_OK(hnd->status)) {
109 return CAC_FAILURE;
112 return CAC_SUCCESS;
115 int cac_RegOpenKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegOpenKey *op) {
116 struct rpc_pipe_client *pipe_hnd = NULL;
117 WERROR err;
119 POLICY_HND *key_out;
120 POLICY_HND *parent_key;
122 char *key_name = NULL;
123 uint32 reg_type = 0;
125 struct RegConnect rc;
127 if(!hnd)
128 return CAC_FAILURE;
130 if(!hnd->_internal.ctx) {
131 hnd->status = NT_STATUS_INVALID_HANDLE;
132 return CAC_FAILURE;
135 if(!op || !op->in.name || !mem_ctx) {
136 hnd->status = NT_STATUS_INVALID_PARAMETER;
137 return CAC_FAILURE;
141 key_out = talloc(mem_ctx, POLICY_HND);
142 if(!key_out) {
143 hnd->status = NT_STATUS_NO_MEMORY;
144 return CAC_FAILURE;
147 if(!op->in.parent_key) {
148 /*then we need to connect to the registry*/
149 if(!cac_ParseRegPath(op->in.name, &reg_type, &key_name)) {
150 hnd->status = NT_STATUS_INVALID_PARAMETER;
151 return CAC_FAILURE;
154 /*use cac_RegConnect because it handles the session setup*/
155 ZERO_STRUCT(rc);
157 rc.in.access = op->in.access;
158 rc.in.root = reg_type;
160 if(!cac_RegConnect(hnd, mem_ctx, &rc)) {
161 return CAC_FAILURE;
164 /**if they only specified the root key, return the key we just opened*/
165 if(key_name == NULL) {
166 op->out.key = rc.out.key;
167 return CAC_SUCCESS;
170 parent_key = rc.out.key;
172 else {
173 parent_key = op->in.parent_key;
174 key_name = op->in.name;
177 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
178 if(!pipe_hnd) {
179 hnd->status = NT_STATUS_INVALID_HANDLE;
180 return CAC_FAILURE;
183 err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, parent_key, key_name, op->in.access, key_out);
184 hnd->status = werror_to_ntstatus(err);
186 if(!NT_STATUS_IS_OK(hnd->status)) {
187 return CAC_FAILURE;
190 if(!op->in.parent_key) {
191 /*then close the one that we opened above*/
192 err = rpccli_reg_close( pipe_hnd, mem_ctx, parent_key);
193 hnd->status = werror_to_ntstatus(err);
195 if(!NT_STATUS_IS_OK(hnd->status)) {
196 return CAC_FAILURE;
200 op->out.key = key_out;
202 return CAC_SUCCESS;
205 int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKeys *op) {
206 struct rpc_pipe_client *pipe_hnd = NULL;
207 WERROR err;
209 /*buffers for rpccli_reg_enum_key call*/
210 fstring key_name_in;
211 fstring class_name_in;
213 /*output buffers*/
214 char **key_names_out = NULL;
215 char **class_names_out = NULL;
216 time_t *mod_times_out = NULL;
217 uint32 num_keys_out = 0;
218 uint32 resume_idx = 0;
220 if(!hnd)
221 return CAC_FAILURE;
223 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
224 if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED))
225 return CAC_FAILURE;
227 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
228 hnd->status = NT_STATUS_INVALID_HANDLE;
229 return CAC_FAILURE;
232 if(!op || op->in.max_keys == 0 || !mem_ctx) {
233 hnd->status = NT_STATUS_INVALID_PARAMETER;
234 return CAC_FAILURE;
237 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
238 if(!pipe_hnd) {
239 hnd->status = NT_STATUS_INVALID_HANDLE;
240 return CAC_FAILURE;
243 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
244 key_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys);
245 if(!key_names_out) {
246 hnd->status = NT_STATUS_NO_MEMORY;
247 return CAC_FAILURE;
250 class_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys);
251 if(!class_names_out) {
252 hnd->status = NT_STATUS_NO_MEMORY;
253 TALLOC_FREE(key_names_out);
254 return CAC_FAILURE;
257 mod_times_out = TALLOC_ARRAY(mem_ctx, time_t, op->in.max_keys);
258 if(!mod_times_out) {
259 hnd->status = NT_STATUS_NO_MEMORY;
260 TALLOC_FREE(key_names_out);
261 TALLOC_FREE(class_names_out);
263 return CAC_FAILURE;
266 resume_idx = op->out.resume_idx;
268 do {
269 err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, op->in.key, resume_idx, key_name_in, class_name_in, &mod_times_out[num_keys_out]);
270 hnd->status = werror_to_ntstatus(err);
272 if(!NT_STATUS_IS_OK(hnd->status)) {
273 /*don't increment any values*/
274 break;
277 key_names_out[num_keys_out] = talloc_strdup(mem_ctx, key_name_in);
279 class_names_out[num_keys_out] = talloc_strdup(mem_ctx, class_name_in);
281 if(!key_names_out[num_keys_out] || !class_names_out[num_keys_out]) {
282 hnd->status = NT_STATUS_NO_MEMORY;
283 break;
286 resume_idx++;
287 num_keys_out++;
288 } while(num_keys_out < op->in.max_keys);
290 if(CAC_OP_FAILED(hnd->status)) {
291 op->out.num_keys = 0;
292 return CAC_FAILURE;
295 op->out.resume_idx = resume_idx;
296 op->out.num_keys = num_keys_out;
297 op->out.key_names = key_names_out;
298 op->out.class_names = class_names_out;
299 op->out.mod_times = mod_times_out;
301 return CAC_SUCCESS;
304 int cac_RegCreateKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegCreateKey *op) {
305 struct rpc_pipe_client *pipe_hnd = NULL;
306 WERROR err;
308 POLICY_HND *key_out;
310 struct RegOpenKey rok;
312 if(!hnd)
313 return CAC_FAILURE;
315 if(!hnd->_internal.ctx) {
316 hnd->status = NT_STATUS_INVALID_HANDLE;
317 return CAC_FAILURE;
320 if(!op || !op->in.parent_key || !op->in.key_name || !mem_ctx) {
321 hnd->status = NT_STATUS_INVALID_PARAMETER;
322 return CAC_FAILURE;
325 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
326 ZERO_STRUCT(rok);
328 rok.in.name = op->in.key_name;
329 rok.in.access = op->in.access;
330 rok.in.parent_key = op->in.parent_key;
332 if(cac_RegOpenKey(hnd, mem_ctx, &rok)) {
333 /*then we got the key, return*/
334 op->out.key = rok.out.key;
335 return CAC_SUCCESS;
338 /*just be ultra-safe*/
339 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
340 if(!pipe_hnd) {
341 hnd->status = NT_STATUS_INVALID_HANDLE;
342 return CAC_FAILURE;
345 key_out = talloc(mem_ctx, POLICY_HND);
346 if(!key_out) {
347 hnd->status = NT_STATUS_NO_MEMORY;
348 return CAC_FAILURE;
351 err = rpccli_reg_create_key_ex( pipe_hnd, mem_ctx, op->in.parent_key, op->in.key_name, op->in.class_name, op->in.access, key_out);
352 hnd->status = werror_to_ntstatus(err);
354 if(!NT_STATUS_IS_OK(hnd->status)) {
355 return CAC_FAILURE;
358 op->out.key = key_out;
360 return CAC_SUCCESS;
364 WERROR cac_delete_subkeys_recursive(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
365 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
366 * so we use the cli_reg functions directly*/
368 WERROR err = WERR_OK;
370 POLICY_HND subkey;
371 fstring subkey_name;
372 fstring class_buf;
373 time_t mod_time_buf;
375 int cur_key = 0;
377 while(W_ERROR_IS_OK(err)) {
378 err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, key, cur_key, subkey_name, class_buf, &mod_time_buf);
380 if(!W_ERROR_IS_OK(err))
381 break;
383 /*try to open the key with full access*/
384 err = rpccli_reg_open_entry(pipe_hnd, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey);
386 if(!W_ERROR_IS_OK(err))
387 break;
389 err = cac_delete_subkeys_recursive(pipe_hnd, mem_ctx, &subkey);
391 if(!W_ERROR_EQUAL(err,WERR_NO_MORE_ITEMS) && !W_ERROR_IS_OK(err))
392 break;
394 /*flush the key just to be safe*/
395 rpccli_reg_flush_key(pipe_hnd, mem_ctx, key);
397 /*close the key that we opened*/
398 rpccli_reg_close(pipe_hnd, mem_ctx, &subkey);
400 /*now we delete the subkey*/
401 err = rpccli_reg_delete_key(pipe_hnd, mem_ctx, key, subkey_name);
404 cur_key++;
408 return err;
413 int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {
414 struct rpc_pipe_client *pipe_hnd = NULL;
415 WERROR err;
417 if(!hnd)
418 return CAC_FAILURE;
420 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
421 hnd->status = NT_STATUS_INVALID_HANDLE;
422 return CAC_FAILURE;
425 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
426 hnd->status = NT_STATUS_INVALID_PARAMETER;
427 return CAC_FAILURE;
430 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
431 if(!pipe_hnd) {
432 hnd->status = NT_STATUS_INVALID_HANDLE;
433 return CAC_FAILURE;
436 if(op->in.recursive) {
437 /*first open the key, and then delete all of it's subkeys recursively*/
438 struct RegOpenKey rok;
439 ZERO_STRUCT(rok);
441 rok.in.parent_key = op->in.parent_key;
442 rok.in.name = op->in.name;
443 rok.in.access = REG_KEY_ALL;
445 if(!cac_RegOpenKey(hnd, mem_ctx, &rok))
446 return CAC_FAILURE;
448 err = cac_delete_subkeys_recursive(pipe_hnd, mem_ctx, rok.out.key);
450 /*close the key that we opened*/
451 cac_RegClose(hnd, mem_ctx, rok.out.key);
453 hnd->status = werror_to_ntstatus(err);
455 if(NT_STATUS_V(hnd->status) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED) && !NT_STATUS_IS_OK(hnd->status))
456 return CAC_FAILURE;
458 /*now go on to actually delete the key*/
461 err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, op->in.parent_key, op->in.name);
462 hnd->status = werror_to_ntstatus(err);
464 if(!NT_STATUS_IS_OK(hnd->status)) {
465 return CAC_FAILURE;
468 return CAC_SUCCESS;
471 int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op) {
472 struct rpc_pipe_client *pipe_hnd = NULL;
473 WERROR err;
475 if(!hnd)
476 return CAC_FAILURE;
478 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
479 hnd->status = NT_STATUS_INVALID_HANDLE;
480 return CAC_FAILURE;
483 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
484 hnd->status = NT_STATUS_INVALID_PARAMETER;
485 return CAC_FAILURE;
488 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
489 if(!pipe_hnd) {
490 hnd->status = NT_STATUS_INVALID_HANDLE;
491 return CAC_FAILURE;
494 err = rpccli_reg_delete_val( pipe_hnd, mem_ctx, op->in.parent_key, op->in.name);
495 hnd->status = werror_to_ntstatus(err);
497 if(!NT_STATUS_IS_OK(hnd->status)) {
498 return CAC_FAILURE;
501 return CAC_SUCCESS;
504 #if 0
505 /* JRA - disabled until fix. */
506 /* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
507 cleanly and resubmit the query. */
509 int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op) {
510 struct rpc_pipe_client *pipe_hnd = NULL;
511 WERROR err;
513 char *class_name_out = NULL;
514 uint32 class_len = 0;
515 uint32 num_subkeys_out = 0;
516 uint32 long_subkey_out = 0;
517 uint32 long_class_out = 0;
518 uint32 num_values_out = 0;
519 uint32 long_value_out = 0;
520 uint32 long_data_out = 0;
521 uint32 secdesc_size = 0;
522 NTTIME mod_time;
524 if(!hnd)
525 return CAC_FAILURE;
527 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
528 hnd->status = NT_STATUS_INVALID_HANDLE;
529 return CAC_FAILURE;
532 if(!op || !op->in.key || !mem_ctx) {
533 hnd->status = NT_STATUS_INVALID_PARAMETER;
534 return CAC_FAILURE;
537 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
538 if(!pipe_hnd) {
539 hnd->status = NT_STATUS_INVALID_HANDLE;
540 return CAC_FAILURE;
543 err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
544 class_name_out,
545 &class_len,
546 &num_subkeys_out,
547 &long_subkey_out,
548 &long_class_out,
549 &num_values_out,
550 &long_value_out,
551 &long_data_out,
552 &secdesc_size,
553 &mod_time);
555 hnd->status = werror_to_ntstatus(err);
557 if(!NT_STATUS_IS_OK(hnd->status))
558 return CAC_FAILURE;
560 if(!class_name_out) {
561 op->out.class_name = talloc_strdup(mem_ctx, "");
563 else if(class_len != 0 && class_name_out[class_len - 1] != '\0') {
564 /*then we need to add a '\0'*/
565 op->out.class_name = talloc_size(mem_ctx, sizeof(char)*(class_len + 1));
567 memcpy(op->out.class_name, class_name_out, class_len);
569 op->out.class_name[class_len] = '\0';
571 else { /*then everything worked out fine in the function*/
572 op->out.class_name = talloc_strdup(mem_ctx, class_name_out);
575 if(!op->out.class_name) {
576 hnd->status = NT_STATUS_NO_MEMORY;
577 return CAC_FAILURE;
580 op->out.num_subkeys = num_subkeys_out;
581 op->out.longest_subkey = long_subkey_out;
582 op->out.longest_class = long_class_out;
583 op->out.num_values = num_values_out;
584 op->out.longest_value_name = long_value_out;
585 op->out.longest_value_data = long_data_out;
586 op->out.security_desc_size = secdesc_size;
587 op->out.last_write_time = nt_time_to_unix(&mod_time);
589 return CAC_FAILURE;
591 #endif
593 int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) {
594 struct rpc_pipe_client *pipe_hnd = NULL;
595 WERROR err;
597 uint32 val_type;
598 REGVAL_BUFFER buffer;
599 REG_VALUE_DATA *data_out = NULL;
601 if(!hnd)
602 return CAC_FAILURE;
604 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
605 hnd->status = NT_STATUS_INVALID_HANDLE;
606 return CAC_FAILURE;
609 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
610 hnd->status = NT_STATUS_INVALID_PARAMETER;
611 return CAC_FAILURE;
614 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
615 if(!pipe_hnd) {
616 hnd->status = NT_STATUS_INVALID_HANDLE;
617 return CAC_FAILURE;
620 err = rpccli_reg_query_value(pipe_hnd, mem_ctx, op->in.key, op->in.val_name, &val_type, &buffer);
621 hnd->status = werror_to_ntstatus(err);
623 if(!NT_STATUS_IS_OK(hnd->status))
624 return CAC_FAILURE;
626 data_out = cac_MakeRegValueData(mem_ctx, val_type, buffer);
627 if(!data_out) {
628 if(errno == ENOMEM)
629 hnd->status = NT_STATUS_NO_MEMORY;
630 else
631 hnd->status = NT_STATUS_INVALID_PARAMETER;
633 return CAC_FAILURE;
636 op->out.type = val_type;
637 op->out.data = data_out;
639 return CAC_SUCCESS;
643 int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumValues *op) {
644 struct rpc_pipe_client *pipe_hnd = NULL;
645 WERROR err;
647 /*buffers for rpccli_reg_enum_key call*/
648 fstring val_name_buf;
649 REGVAL_BUFFER val_buf;
651 /*output buffers*/
652 uint32 *types_out = NULL;
653 REG_VALUE_DATA **values_out = NULL;
654 char **val_names_out = NULL;
655 uint32 num_values_out = 0;
656 uint32 resume_idx = 0;
658 if(!hnd)
659 return CAC_FAILURE;
661 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
662 if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED))
663 return CAC_FAILURE;
665 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
666 hnd->status = NT_STATUS_INVALID_HANDLE;
667 return CAC_FAILURE;
670 if(!op || !op->in.key || op->in.max_values == 0 || !mem_ctx) {
671 hnd->status = NT_STATUS_INVALID_PARAMETER;
672 return CAC_FAILURE;
675 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
676 if(!pipe_hnd) {
677 hnd->status = NT_STATUS_INVALID_HANDLE;
678 return CAC_FAILURE;
681 /*we need to assume that the max number of values will be enumerated*/
682 types_out = (uint32 *)talloc_array(mem_ctx, int, op->in.max_values);
683 if(!types_out) {
684 hnd->status = NT_STATUS_NO_MEMORY;
685 return CAC_FAILURE;
688 values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values);
689 if(!values_out) {
690 TALLOC_FREE(types_out);
691 hnd->status = NT_STATUS_NO_MEMORY;
692 return CAC_FAILURE;
695 val_names_out = talloc_array(mem_ctx, char *, op->in.max_values);
696 if(!val_names_out) {
697 TALLOC_FREE(types_out);
698 TALLOC_FREE(values_out);
699 hnd->status = NT_STATUS_NO_MEMORY;
700 return CAC_FAILURE;
703 resume_idx = op->out.resume_idx;
704 do {
705 ZERO_STRUCT(val_buf);
707 err = rpccli_reg_enum_val(pipe_hnd, mem_ctx, op->in.key, resume_idx, val_name_buf, &types_out[num_values_out], &val_buf);
708 hnd->status = werror_to_ntstatus(err);
710 if(!NT_STATUS_IS_OK(hnd->status))
711 break;
713 values_out[num_values_out] = cac_MakeRegValueData(mem_ctx, types_out[num_values_out], val_buf);
714 val_names_out[num_values_out] = talloc_strdup(mem_ctx, val_name_buf);
716 if(!val_names_out[num_values_out] || !values_out[num_values_out]) {
717 hnd->status = NT_STATUS_NO_MEMORY;
718 break;
721 num_values_out++;
722 resume_idx++;
723 } while(num_values_out < op->in.max_values);
725 if(CAC_OP_FAILED(hnd->status))
726 return CAC_FAILURE;
728 op->out.types = types_out;
729 op->out.num_values = num_values_out;
730 op->out.value_names = val_names_out;
731 op->out.values = values_out;
732 op->out.resume_idx = resume_idx;
734 return CAC_SUCCESS;
737 int cac_RegSetValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetValue *op) {
738 struct rpc_pipe_client *pipe_hnd = NULL;
739 WERROR err;
741 RPC_DATA_BLOB *buffer;
743 if(!hnd)
744 return CAC_FAILURE;
746 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
747 hnd->status = NT_STATUS_INVALID_HANDLE;
748 return CAC_FAILURE;
751 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
752 hnd->status = NT_STATUS_INVALID_PARAMETER;
753 return CAC_FAILURE;
756 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
757 if(!pipe_hnd) {
758 hnd->status = NT_STATUS_INVALID_HANDLE;
759 return CAC_FAILURE;
762 buffer = cac_MakeRpcDataBlob(mem_ctx, op->in.type, op->in.value);
764 if(!buffer) {
765 if(errno == ENOMEM)
766 hnd->status = NT_STATUS_NO_MEMORY;
767 else
768 hnd->status = NT_STATUS_INVALID_PARAMETER;
770 return CAC_FAILURE;
773 err = rpccli_reg_set_val(pipe_hnd, mem_ctx, op->in.key, op->in.val_name, op->in.type, buffer);
774 hnd->status = werror_to_ntstatus(err);
776 if(!NT_STATUS_IS_OK(hnd->status))
777 return CAC_FAILURE;
779 /*flush*/
780 err = rpccli_reg_flush_key(pipe_hnd, mem_ctx, op->in.key);
781 hnd->status = werror_to_ntstatus(err);
783 if(!NT_STATUS_IS_OK(hnd->status))
784 return CAC_FAILURE;
786 return CAC_SUCCESS;
791 int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op) {
792 struct rpc_pipe_client *pipe_hnd = NULL;
793 WERROR err;
795 uint32 version_out;
797 if(!hnd)
798 return CAC_FAILURE;
800 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
801 hnd->status = NT_STATUS_INVALID_HANDLE;
802 return CAC_FAILURE;
805 if(!op || !op->in.key || !mem_ctx) {
806 hnd->status = NT_STATUS_INVALID_PARAMETER;
807 return CAC_FAILURE;
810 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
811 if(!pipe_hnd) {
812 hnd->status = NT_STATUS_INVALID_HANDLE;
813 return CAC_FAILURE;
816 err = rpccli_reg_getversion( pipe_hnd, mem_ctx, op->in.key, &version_out);
817 hnd->status = werror_to_ntstatus(err);
819 if(!NT_STATUS_IS_OK(hnd->status))
820 return CAC_FAILURE;
822 op->out.version = version_out;
824 return CAC_SUCCESS;
827 int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetKeySecurity *op) {
828 struct rpc_pipe_client *pipe_hnd = NULL;
829 WERROR err;
831 uint32 buf_size;
832 SEC_DESC_BUF buf;
834 ZERO_STRUCT(buf);
836 if(!hnd)
837 return CAC_FAILURE;
839 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
840 hnd->status = NT_STATUS_INVALID_HANDLE;
841 return CAC_FAILURE;
844 if(!op || !op->in.key || op->in.info_type == 0 || !mem_ctx) {
845 hnd->status = NT_STATUS_INVALID_PARAMETER;
846 return CAC_FAILURE;
849 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
850 if(!pipe_hnd) {
851 hnd->status = NT_STATUS_INVALID_HANDLE;
852 return CAC_FAILURE;
855 err = rpccli_reg_get_key_sec(pipe_hnd, mem_ctx, op->in.key, op->in.info_type, &buf_size, &buf);
856 hnd->status = werror_to_ntstatus(err);
859 if(!NT_STATUS_IS_OK(hnd->status)) {
860 return CAC_FAILURE;
863 op->out.size = buf.len;
864 op->out.descriptor = dup_sec_desc(mem_ctx, buf.sec);
866 if (op->out.descriptor == NULL) {
867 return CAC_FAILURE;
870 return CAC_SUCCESS;
873 int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) {
874 struct rpc_pipe_client *pipe_hnd = NULL;
875 WERROR err;
877 if(!hnd)
878 return CAC_FAILURE;
880 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
881 hnd->status = NT_STATUS_INVALID_HANDLE;
882 return CAC_FAILURE;
885 if(!op || !op->in.key || op->in.info_type == 0 || op->in.size == 0 || !op->in.descriptor || !mem_ctx) {
886 hnd->status = NT_STATUS_INVALID_PARAMETER;
887 return CAC_FAILURE;
890 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
891 if(!pipe_hnd) {
892 hnd->status = NT_STATUS_INVALID_HANDLE;
893 return CAC_FAILURE;
896 err = rpccli_reg_set_key_sec(pipe_hnd, mem_ctx, op->in.key, op->in.info_type, op->in.size, op->in.descriptor);
897 hnd->status = werror_to_ntstatus(err);
900 if(!NT_STATUS_IS_OK(hnd->status)) {
901 return CAC_FAILURE;
904 return CAC_SUCCESS;
907 int cac_RegSaveKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSaveKey *op) {
908 struct rpc_pipe_client *pipe_hnd = NULL;
909 WERROR err;
911 if(!hnd)
912 return CAC_FAILURE;
914 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
915 hnd->status = NT_STATUS_INVALID_HANDLE;
916 return CAC_FAILURE;
919 if(!op || !op->in.key || !op->in.filename || !mem_ctx) {
920 hnd->status = NT_STATUS_INVALID_PARAMETER;
921 return CAC_FAILURE;
924 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
925 if(!pipe_hnd) {
926 hnd->status = NT_STATUS_INVALID_HANDLE;
927 return CAC_FAILURE;
930 err = rpccli_reg_save_key( pipe_hnd, mem_ctx, op->in.key, op->in.filename);
931 hnd->status = werror_to_ntstatus(err);
934 if(!NT_STATUS_IS_OK(hnd->status)) {
935 return CAC_FAILURE;
938 return CAC_SUCCESS;
941 int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) {
942 SMBCSRV *srv = NULL;
943 struct rpc_pipe_client *pipe_hnd = NULL;
945 char *msg;
947 if(!hnd)
948 return CAC_FAILURE;
950 if(!hnd->_internal.ctx) {
951 hnd->status = NT_STATUS_INVALID_HANDLE;
952 return CAC_FAILURE;
955 if(!op || !mem_ctx) {
956 hnd->status = NT_STATUS_INVALID_PARAMETER;
957 return CAC_FAILURE;
960 srv = cac_GetServer(hnd);
961 if(!srv) {
962 hnd->status = NT_STATUS_INVALID_HANDLE;
963 return CAC_FAILURE;
966 /*initialize for winreg pipe if we have to*/
967 if(!hnd->_internal.pipes[PI_SHUTDOWN]) {
968 if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SHUTDOWN, &(hnd->status)))) {
969 return CAC_FAILURE;
972 hnd->_internal.pipes[PI_SHUTDOWN] = True;
975 pipe_hnd = cac_GetPipe(hnd, PI_SHUTDOWN);
976 if(!pipe_hnd) {
977 hnd->status = NT_STATUS_INVALID_HANDLE;
978 return CAC_FAILURE;
981 msg = (op->in.message != NULL) ? op->in.message : talloc_strdup(mem_ctx, "");
983 hnd->status = NT_STATUS_OK;
985 if(hnd->_internal.srv_level > SRV_WIN_NT4) {
986 hnd->status = rpccli_shutdown_init_ex( pipe_hnd, mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force, op->in.reason);
989 if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) {
990 hnd->status = rpccli_shutdown_init( pipe_hnd, mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force);
992 hnd->_internal.srv_level = SRV_WIN_NT4;
995 if(!NT_STATUS_IS_OK(hnd->status)) {
996 return CAC_FAILURE;
999 return CAC_SUCCESS;
1002 int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx) {
1003 struct rpc_pipe_client *pipe_hnd = NULL;
1005 if(!hnd)
1006 return CAC_FAILURE;
1008 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) {
1009 hnd->status = NT_STATUS_INVALID_HANDLE;
1010 return CAC_FAILURE;
1013 pipe_hnd = cac_GetPipe(hnd, PI_SHUTDOWN);
1014 if(!pipe_hnd) {
1015 hnd->status = NT_STATUS_INVALID_HANDLE;
1016 return CAC_FAILURE;
1019 hnd->status = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
1021 if(!NT_STATUS_IS_OK(hnd->status))
1022 return CAC_FAILURE;
1024 return CAC_SUCCESS;