r25370: Allow to delete registry keys recursively without deleting the final key.
[Samba/nascimento.git] / source3 / libmsrpc / cac_winreg.c
blob0470d2a80f9bb92dffadeef39b21f218091ce7d6
2 /*
3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (WINREG pipe)
5 * Copyright (C) Chris Nicholls 2005.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "libmsrpc.h"
22 #include "libmsrpc_internal.h"
24 NTSTATUS cac_delete_subkeys_recursive(struct rpc_pipe_client * pipe_hnd,
25 TALLOC_CTX * mem_ctx, POLICY_HND * key);
27 int cac_RegConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
28 struct RegConnect *op )
30 SMBCSRV *srv = NULL;
31 struct rpc_pipe_client *pipe_hnd = NULL;
32 POLICY_HND *key = NULL;
34 if ( !hnd )
35 return CAC_FAILURE;
37 if ( !hnd->_internal.ctx ) {
38 hnd->status = NT_STATUS_INVALID_HANDLE;
39 return CAC_FAILURE;
42 if ( !op || !op->in.root || !mem_ctx ) {
43 hnd->status = NT_STATUS_INVALID_PARAMETER;
44 return CAC_FAILURE;
47 srv = cac_GetServer( hnd );
48 if ( !srv ) {
49 hnd->status = NT_STATUS_INVALID_CONNECTION;
50 return CAC_FAILURE;
53 /*initialize for winreg pipe if we have to */
54 if ( !hnd->_internal.pipes[PI_WINREG] ) {
55 if ( !
56 ( pipe_hnd =
57 cli_rpc_pipe_open_noauth( srv->cli, PI_WINREG,
58 &hnd->status ) ) ) {
59 return CAC_FAILURE;
62 hnd->_internal.pipes[PI_WINREG] = True;
65 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
66 if ( !pipe_hnd ) {
67 hnd->status = NT_STATUS_INVALID_HANDLE;
68 return CAC_FAILURE;
71 key = talloc( mem_ctx, POLICY_HND );
72 if ( !key ) {
73 hnd->status = NT_STATUS_NO_MEMORY;
74 return CAC_FAILURE;
77 hnd->status =
78 rpccli_winreg_Connect( pipe_hnd, mem_ctx, op->in.root,
79 op->in.access, key );
81 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
82 return CAC_FAILURE;
85 op->out.key = key;
87 return CAC_SUCCESS;
90 int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
91 POLICY_HND * key )
93 struct rpc_pipe_client *pipe_hnd = NULL;
95 if ( !hnd )
96 return CAC_FAILURE;
98 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
99 hnd->status = NT_STATUS_INVALID_HANDLE;
100 return CAC_FAILURE;
103 if ( !key || !mem_ctx ) {
104 hnd->status = NT_STATUS_INVALID_PARAMETER;
105 return CAC_FAILURE;
108 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
109 if ( !pipe_hnd ) {
110 hnd->status = NT_STATUS_INVALID_HANDLE;
111 return CAC_FAILURE;
114 hnd->status = rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, key );
116 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
117 return CAC_FAILURE;
120 return CAC_SUCCESS;
123 int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
124 struct RegOpenKey *op )
126 struct rpc_pipe_client *pipe_hnd = NULL;
127 struct winreg_String key_string;
129 POLICY_HND *key_out;
130 POLICY_HND *parent_key;
132 char *key_name = NULL;
133 uint32 reg_type = 0;
135 struct RegConnect rc;
137 if ( !hnd )
138 return CAC_FAILURE;
140 if ( !hnd->_internal.ctx ) {
141 hnd->status = NT_STATUS_INVALID_HANDLE;
142 return CAC_FAILURE;
145 if ( !op || !op->in.name || !mem_ctx ) {
146 hnd->status = NT_STATUS_INVALID_PARAMETER;
147 return CAC_FAILURE;
151 key_out = talloc( mem_ctx, POLICY_HND );
152 if ( !key_out ) {
153 hnd->status = NT_STATUS_NO_MEMORY;
154 return CAC_FAILURE;
157 if ( !op->in.parent_key ) {
158 /*then we need to connect to the registry */
159 if ( !cac_ParseRegPath( op->in.name, &reg_type, &key_name ) ) {
160 hnd->status = NT_STATUS_INVALID_PARAMETER;
161 return CAC_FAILURE;
164 /*use cac_RegConnect because it handles the session setup */
165 ZERO_STRUCT( rc );
167 rc.in.access = op->in.access;
168 rc.in.root = reg_type;
170 if ( !cac_RegConnect( hnd, mem_ctx, &rc ) ) {
171 return CAC_FAILURE;
174 /**if they only specified the root key, return the key we just opened*/
175 if ( key_name == NULL ) {
176 op->out.key = rc.out.key;
177 return CAC_SUCCESS;
180 parent_key = rc.out.key;
181 } else {
182 parent_key = op->in.parent_key;
183 key_name = op->in.name;
186 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
187 if ( !pipe_hnd ) {
188 hnd->status = NT_STATUS_INVALID_HANDLE;
189 return CAC_FAILURE;
192 key_string.name = key_name;
193 hnd->status =
194 rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, parent_key,
195 key_string, 0, op->in.access,
196 key_out );
198 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
199 return CAC_FAILURE;
202 if ( !op->in.parent_key ) {
203 /*then close the one that we opened above */
204 hnd->status =
205 rpccli_winreg_CloseKey( pipe_hnd, mem_ctx,
206 parent_key );
208 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
209 return CAC_FAILURE;
213 op->out.key = key_out;
215 return CAC_SUCCESS;
218 int cac_RegEnumKeys( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
219 struct RegEnumKeys *op )
221 struct rpc_pipe_client *pipe_hnd = NULL;
223 /*buffers for rpccli_reg_enum_key call */
224 fstring key_name_in;
225 fstring class_name_in;
227 /*output buffers */
228 char **key_names_out = NULL;
229 char **class_names_out = NULL;
230 time_t *mod_times_out = NULL;
231 uint32 num_keys_out = 0;
232 uint32 resume_idx = 0;
234 if ( !hnd )
235 return CAC_FAILURE;
237 /* This is to avoid useless rpc calls, if the last call
238 exhausted all the keys, then we don't need to go
239 through everything again */
241 if ( NT_STATUS_V( hnd->status ) ==
242 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
243 return CAC_FAILURE;
245 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
246 hnd->status = NT_STATUS_INVALID_HANDLE;
247 return CAC_FAILURE;
250 if ( !op || op->in.max_keys == 0 || !mem_ctx ) {
251 hnd->status = NT_STATUS_INVALID_PARAMETER;
252 return CAC_FAILURE;
255 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
256 if ( !pipe_hnd ) {
257 hnd->status = NT_STATUS_INVALID_HANDLE;
258 return CAC_FAILURE;
261 /* The only way to know how many keys to expect is to
262 assume max_keys keys will be found */
264 key_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
265 if ( !key_names_out ) {
266 hnd->status = NT_STATUS_NO_MEMORY;
267 return CAC_FAILURE;
270 class_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
271 if ( !class_names_out ) {
272 hnd->status = NT_STATUS_NO_MEMORY;
273 TALLOC_FREE( key_names_out );
274 return CAC_FAILURE;
277 mod_times_out = TALLOC_ARRAY( mem_ctx, time_t, op->in.max_keys );
278 if ( !mod_times_out ) {
279 hnd->status = NT_STATUS_NO_MEMORY;
280 TALLOC_FREE( key_names_out );
281 TALLOC_FREE( class_names_out );
283 return CAC_FAILURE;
286 resume_idx = op->out.resume_idx;
288 do {
289 #if 0
290 hnd->status =
291 rpccli_winreg_EnumKey( pipe_hnd, mem_ctx, op->in.key,
292 resume_idx, key_name_in,
293 class_name_in,
294 &mod_times_out );
295 #endif
297 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
298 /*don't increment any values */
299 break;
302 key_names_out[num_keys_out] =
303 talloc_strdup( mem_ctx, key_name_in );
305 class_names_out[num_keys_out] =
306 talloc_strdup( mem_ctx, class_name_in );
308 if ( !key_names_out[num_keys_out]
309 || !class_names_out[num_keys_out] ) {
310 hnd->status = NT_STATUS_NO_MEMORY;
311 break;
314 resume_idx++;
315 num_keys_out++;
316 } while ( num_keys_out < op->in.max_keys );
318 if ( CAC_OP_FAILED( hnd->status ) ) {
319 op->out.num_keys = 0;
320 return CAC_FAILURE;
323 op->out.resume_idx = resume_idx;
324 op->out.num_keys = num_keys_out;
325 op->out.key_names = key_names_out;
326 op->out.class_names = class_names_out;
327 op->out.mod_times = mod_times_out;
329 return CAC_SUCCESS;
332 int cac_RegCreateKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
333 struct RegCreateKey *op )
335 struct rpc_pipe_client *pipe_hnd = NULL;
336 POLICY_HND *key_out;
337 struct RegOpenKey rok;
338 struct winreg_String key_string, class_string;
339 enum winreg_CreateAction action = 0;
341 if ( !hnd )
342 return CAC_FAILURE;
344 if ( !hnd->_internal.ctx ) {
345 hnd->status = NT_STATUS_INVALID_HANDLE;
346 return CAC_FAILURE;
349 if ( !op || !op->in.parent_key || !op->in.key_name || !mem_ctx ) {
350 hnd->status = NT_STATUS_INVALID_PARAMETER;
351 return CAC_FAILURE;
354 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
355 ZERO_STRUCT( rok );
357 rok.in.name = op->in.key_name;
358 rok.in.access = op->in.access;
359 rok.in.parent_key = op->in.parent_key;
361 if ( cac_RegOpenKey( hnd, mem_ctx, &rok ) ) {
362 /*then we got the key, return */
363 op->out.key = rok.out.key;
364 return CAC_SUCCESS;
367 /*just be ultra-safe */
368 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
369 if ( !pipe_hnd ) {
370 hnd->status = NT_STATUS_INVALID_HANDLE;
371 return CAC_FAILURE;
374 key_out = talloc( mem_ctx, POLICY_HND );
375 if ( !key_out ) {
376 hnd->status = NT_STATUS_NO_MEMORY;
377 return CAC_FAILURE;
380 key_string.name = op->in.key_name;
381 class_string.name = op->in.class_name;
382 hnd->status =
383 rpccli_winreg_CreateKey( pipe_hnd, mem_ctx, op->in.parent_key,
384 key_string, class_string, 0,
385 op->in.access, NULL, key_out,
386 &action );
388 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
389 return CAC_FAILURE;
392 op->out.key = key_out;
394 return CAC_SUCCESS;
398 NTSTATUS cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
399 TALLOC_CTX * mem_ctx, POLICY_HND * key )
401 POLICY_HND subkey;
402 fstring subkey_name;
403 int cur_key = 0;
404 NTSTATUS status;
405 uint32 num_subkeys, max_subkeylen, max_classlen;
406 uint32 num_values, max_valnamelen, maxvalbufsize;
407 char *name_buffer;
408 struct winreg_String class_string;
410 NTTIME modtime;
411 uint32 secdescsize;
413 /* First get the max subkey name length */
415 class_string.name = NULL;
416 status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, key,
417 &class_string, &num_subkeys,
418 &max_subkeylen, &max_classlen,
419 &num_values, &max_valnamelen,
420 &maxvalbufsize, &secdescsize,
421 &modtime );
424 if ( !NT_STATUS_IS_OK( status ) ) {
425 return status;
428 if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) {
429 d_fprintf(stderr, "Memory allocation error.\n");
430 return NT_STATUS_NO_MEMORY;
434 while ( NT_STATUS_IS_OK( status ) ) {
435 struct winreg_String key_string;
436 struct winreg_StringBuf subkey_string;
437 fstring subkeyname;
439 memset( name_buffer, 0x0, max_subkeylen );
440 subkey_string.name = name_buffer;
441 subkey_string.length = 0;
442 subkey_string.size = max_subkeylen;
444 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key, cur_key,
445 &subkey_string, NULL, NULL);
447 if ( !NT_STATUS_IS_OK( status ) )
448 break;
450 /* copy the keyname and add the terminating NULL */
452 StrnCpy( subkeyname, subkey_string.name,
453 MIN(subkey_string.length, sizeof(subkeyname)-1) );
454 subkeyname[MIN(subkey_string.length, sizeof(subkeyname)-1)] = '\0';
456 /*try to open the key with full access */
458 key_string.name = subkeyname;
459 status = rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, key,
460 key_string, 0, REG_KEY_ALL,
461 &subkey );
463 if ( !NT_STATUS_IS_OK( status ) )
464 break;
466 status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
467 &subkey );
469 if ( !W_ERROR_EQUAL( ntstatus_to_werror(status), WERR_NO_MORE_ITEMS )
470 && !NT_STATUS_IS_OK( status ) )
471 break;
473 /*flush the key just to be safe */
474 rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, key );
476 /*close the key that we opened */
477 rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, &subkey );
479 /*now we delete the subkey */
480 key_string.name = subkey_name;
481 status = rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, key,
482 key_string );
484 cur_key++;
488 return status;
493 int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
494 struct RegDeleteKey *op )
496 struct rpc_pipe_client *pipe_hnd = NULL;
497 struct winreg_String key_string;
499 if ( !hnd )
500 return CAC_FAILURE;
502 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
503 hnd->status = NT_STATUS_INVALID_HANDLE;
504 return CAC_FAILURE;
507 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
508 hnd->status = NT_STATUS_INVALID_PARAMETER;
509 return CAC_FAILURE;
512 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
513 if ( !pipe_hnd ) {
514 hnd->status = NT_STATUS_INVALID_HANDLE;
515 return CAC_FAILURE;
518 if ( op->in.recursive ) {
520 /* first open the key, and then delete all of
521 it's subkeys recursively */
523 struct RegOpenKey rok;
525 ZERO_STRUCT( rok );
527 rok.in.parent_key = op->in.parent_key;
528 rok.in.name = op->in.name;
529 rok.in.access = REG_KEY_ALL;
531 if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
532 return CAC_FAILURE;
534 hnd->status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
535 rok.out.key );
537 /*close the key that we opened */
538 cac_RegClose( hnd, mem_ctx, rok.out.key );
540 if ( NT_STATUS_V( hnd->status ) !=
541 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
542 && !NT_STATUS_IS_OK( hnd->status ) )
543 return CAC_FAILURE;
545 /*now go on to actually delete the key */
548 key_string.name = op->in.name;
549 hnd->status =
550 rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, op->in.parent_key,
551 key_string );
553 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
554 return CAC_FAILURE;
557 return CAC_SUCCESS;
560 int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
561 struct RegDeleteValue *op )
563 struct rpc_pipe_client *pipe_hnd = NULL;
564 struct winreg_String value_string;
566 if ( !hnd )
567 return CAC_FAILURE;
569 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
570 hnd->status = NT_STATUS_INVALID_HANDLE;
571 return CAC_FAILURE;
574 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
575 hnd->status = NT_STATUS_INVALID_PARAMETER;
576 return CAC_FAILURE;
579 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
580 if ( !pipe_hnd ) {
581 hnd->status = NT_STATUS_INVALID_HANDLE;
582 return CAC_FAILURE;
585 value_string.name = op->in.name;
586 hnd->status =
587 rpccli_winreg_DeleteValue( pipe_hnd, mem_ctx,
588 op->in.parent_key, value_string );
590 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
591 return CAC_FAILURE;
594 return CAC_SUCCESS;
597 int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
598 struct RegQueryKeyInfo *op )
600 struct rpc_pipe_client *pipe_hnd = NULL;
601 uint32 num_subkeys_out = 0;
602 uint32 long_subkey_out = 0;
603 uint32 long_class_out = 0;
604 uint32 num_values_out = 0;
605 uint32 long_value_out = 0;
606 uint32 long_data_out = 0;
607 uint32 secdesc_size = 0;
608 NTTIME mod_time;
609 struct winreg_String class_string;
611 if ( !hnd )
612 return CAC_FAILURE;
614 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
615 hnd->status = NT_STATUS_INVALID_HANDLE;
616 return CAC_FAILURE;
619 if ( !op || !op->in.key || !mem_ctx ) {
620 hnd->status = NT_STATUS_INVALID_PARAMETER;
621 return CAC_FAILURE;
624 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
625 if ( !pipe_hnd ) {
626 hnd->status = NT_STATUS_INVALID_HANDLE;
627 return CAC_FAILURE;
630 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx,
631 op->in.key,
632 &class_string,
633 &num_subkeys_out,
634 &long_subkey_out,
635 &long_class_out,
636 &num_values_out,
637 &long_value_out,
638 &long_data_out,
639 &secdesc_size, &mod_time );
641 if ( !NT_STATUS_IS_OK( hnd->status ) )
642 return CAC_FAILURE;
644 if ( !class_string.name ) {
645 op->out.class_name = talloc_strdup( mem_ctx, "" );
646 } else {
647 op->out.class_name = talloc_strdup( mem_ctx, class_string.name );
650 if ( !op->out.class_name ) {
651 hnd->status = NT_STATUS_NO_MEMORY;
652 return CAC_FAILURE;
655 op->out.num_subkeys = num_subkeys_out;
656 op->out.longest_subkey = long_subkey_out;
657 op->out.longest_class = long_class_out;
658 op->out.num_values = num_values_out;
659 op->out.longest_value_name = long_value_out;
660 op->out.longest_value_data = long_data_out;
661 op->out.security_desc_size = secdesc_size;
662 op->out.last_write_time = nt_time_to_unix( mod_time );
664 return CAC_FAILURE;
667 int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
668 struct RegQueryValue *op )
670 struct rpc_pipe_client *pipe_hnd = NULL;
671 struct winreg_String value_string;
672 REGVAL_BUFFER buffer;
673 REG_VALUE_DATA *data_out = NULL;
674 enum winreg_Type val_type;
675 uint8 *buf;
676 uint32 buf_size = 4096;
677 uint32 length = 0;
679 if ( !hnd )
680 return CAC_FAILURE;
682 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
683 hnd->status = NT_STATUS_INVALID_HANDLE;
684 return CAC_FAILURE;
687 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
688 hnd->status = NT_STATUS_INVALID_PARAMETER;
689 return CAC_FAILURE;
692 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
693 if ( !pipe_hnd ) {
694 hnd->status = NT_STATUS_INVALID_HANDLE;
695 return CAC_FAILURE;
698 value_string.name = op->in.val_name;
700 if ( ( buf = TALLOC_ARRAY( mem_ctx, uint8, buf_size ) ) == NULL ) {
701 hnd->status = NT_STATUS_NO_MEMORY;
702 return CAC_FAILURE;
705 hnd->status = rpccli_winreg_QueryValue( pipe_hnd, mem_ctx, op->in.key,
706 value_string, &val_type, buf,
707 &buf_size, &length );
709 if ( !NT_STATUS_IS_OK( hnd->status ) )
710 return CAC_FAILURE;
712 init_regval_buffer( &buffer, buf, length );
714 data_out = cac_MakeRegValueData( mem_ctx, val_type, buffer );
715 if ( !data_out ) {
716 if ( errno == ENOMEM )
717 hnd->status = NT_STATUS_NO_MEMORY;
718 else
719 hnd->status = NT_STATUS_INVALID_PARAMETER;
721 return CAC_FAILURE;
724 op->out.type = val_type;
725 op->out.data = data_out;
727 return CAC_SUCCESS;
731 int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
732 struct RegEnumValues *op )
734 struct rpc_pipe_client *pipe_hnd = NULL;
735 char *name_buffer;
736 REGVAL_BUFFER val_buf;
737 uint32 *types_out = NULL;
738 REG_VALUE_DATA **values_out = NULL;
739 char **val_names_out = NULL;
740 uint32 num_values_out = 0;
741 uint32 resume_idx = 0;
742 uint32 num_subkeys, max_subkeylen, max_classlen;
743 uint32 num_values, max_valnamelen, maxvalbufsize;
744 struct winreg_String class_string;
745 NTTIME modtime;
746 uint32 secdescsize;
747 uint8 *buffer;
749 if ( !hnd )
750 return CAC_FAILURE;
752 /* This is to avoid useless rpc calls, if the last
753 call exhausted all the keys, then we don't need
754 to go through everything again */
756 if ( NT_STATUS_V( hnd->status ) ==
757 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
758 return CAC_FAILURE;
760 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
761 hnd->status = NT_STATUS_INVALID_HANDLE;
762 return CAC_FAILURE;
765 if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
766 hnd->status = NT_STATUS_INVALID_PARAMETER;
767 return CAC_FAILURE;
770 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
771 if ( !pipe_hnd ) {
772 hnd->status = NT_STATUS_INVALID_HANDLE;
773 return CAC_FAILURE;
776 /*we need to assume that the max number of values will be enumerated */
777 types_out = TALLOC_ARRAY( mem_ctx, uint32, op->in.max_values );
779 if ( !types_out ) {
780 hnd->status = NT_STATUS_NO_MEMORY;
781 return CAC_FAILURE;
784 values_out = TALLOC_ARRAY( mem_ctx, REG_VALUE_DATA *,
785 op->in.max_values );
787 if ( !values_out ) {
788 TALLOC_FREE( types_out );
789 hnd->status = NT_STATUS_NO_MEMORY;
790 return CAC_FAILURE;
793 val_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_values );
795 if ( !val_names_out ) {
796 TALLOC_FREE( types_out );
797 TALLOC_FREE( values_out );
798 hnd->status = NT_STATUS_NO_MEMORY;
799 return CAC_FAILURE;
802 resume_idx = op->out.resume_idx;
804 class_string.name = NULL;
805 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, op->in.key,
806 &class_string, &num_subkeys,
807 &max_subkeylen, &max_classlen,
808 &num_values, &max_valnamelen,
809 &maxvalbufsize, &secdescsize,
810 &modtime );
812 if ( !NT_STATUS_IS_OK(hnd->status) ) {
813 TALLOC_FREE( types_out );
814 TALLOC_FREE( values_out );
816 return CAC_FAILURE;
819 if ( (buffer = TALLOC_ARRAY( mem_ctx, uint8, maxvalbufsize )) == NULL ) {
820 TALLOC_FREE( types_out );
821 TALLOC_FREE( values_out );
822 hnd->status = NT_STATUS_NO_MEMORY;
824 return CAC_FAILURE;
827 if ( (name_buffer = TALLOC_ARRAY(mem_ctx, char, max_valnamelen)) == NULL ) {
828 TALLOC_FREE( types_out );
829 TALLOC_FREE( values_out );
830 TALLOC_FREE( buffer );
831 hnd->status = NT_STATUS_NO_MEMORY;
833 return CAC_FAILURE;
836 do {
837 uint32 data_size = maxvalbufsize;
838 uint32 data_length = 0;
839 struct winreg_ValNameBuf name_buf;
841 memset( name_buffer, 0x0, max_valnamelen );
842 name_buf.name = name_buffer;
843 name_buf.size = max_valnamelen;
844 name_buf.length = 0;
846 hnd->status = rpccli_winreg_EnumValue( pipe_hnd, mem_ctx,
847 op->in.key,
848 resume_idx, &name_buf,
849 &types_out[num_values_out], buffer,
850 &data_size,
851 &data_length );
853 if ( !NT_STATUS_IS_OK( hnd->status ) )
854 break;
856 ZERO_STRUCT( val_buf );
857 init_regval_buffer( &val_buf, buffer, data_length );
859 values_out[num_values_out] = cac_MakeRegValueData( mem_ctx,
860 types_out[num_values_out],
861 val_buf );
862 val_names_out[num_values_out] = TALLOC_ARRAY( mem_ctx, char, name_buf.length+1 );
864 if ( !val_names_out[num_values_out]
865 || !values_out[num_values_out] ) {
866 hnd->status = NT_STATUS_NO_MEMORY;
867 break;
870 StrnCpy( val_names_out[num_values_out], name_buf.name, name_buf.length );
871 (val_names_out[num_values_out])[name_buf.length] = '\0';
873 num_values_out++;
874 resume_idx++;
875 } while ( num_values_out < op->in.max_values );
877 if ( CAC_OP_FAILED( hnd->status ) )
878 return CAC_FAILURE;
880 op->out.types = types_out;
881 op->out.num_values = num_values_out;
882 op->out.value_names = val_names_out;
883 op->out.values = values_out;
884 op->out.resume_idx = resume_idx;
886 return CAC_SUCCESS;
889 int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
890 struct RegSetValue *op )
892 struct rpc_pipe_client *pipe_hnd = NULL;
893 struct winreg_String value_string;
895 RPC_DATA_BLOB *buffer;
897 if ( !hnd )
898 return CAC_FAILURE;
900 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
901 hnd->status = NT_STATUS_INVALID_HANDLE;
902 return CAC_FAILURE;
905 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
906 hnd->status = NT_STATUS_INVALID_PARAMETER;
907 return CAC_FAILURE;
910 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
911 if ( !pipe_hnd ) {
912 hnd->status = NT_STATUS_INVALID_HANDLE;
913 return CAC_FAILURE;
916 buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
918 if ( !buffer ) {
919 if ( errno == ENOMEM )
920 hnd->status = NT_STATUS_NO_MEMORY;
921 else
922 hnd->status = NT_STATUS_INVALID_PARAMETER;
924 return CAC_FAILURE;
927 value_string.name = op->in.val_name;
928 hnd->status =
929 rpccli_winreg_SetValue( pipe_hnd, mem_ctx, op->in.key,
930 value_string, op->in.type,
931 buffer->buffer, buffer->buf_len );
933 if ( !NT_STATUS_IS_OK( hnd->status ) )
934 return CAC_FAILURE;
936 /*flush */
937 hnd->status = rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, op->in.key );
939 if ( !NT_STATUS_IS_OK( hnd->status ) )
940 return CAC_FAILURE;
942 return CAC_SUCCESS;
947 int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
948 struct RegGetVersion *op )
950 struct rpc_pipe_client *pipe_hnd = NULL;
951 uint32 version_out;
953 if ( !hnd )
954 return CAC_FAILURE;
956 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
957 hnd->status = NT_STATUS_INVALID_HANDLE;
958 return CAC_FAILURE;
961 if ( !op || !op->in.key || !mem_ctx ) {
962 hnd->status = NT_STATUS_INVALID_PARAMETER;
963 return CAC_FAILURE;
966 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
967 if ( !pipe_hnd ) {
968 hnd->status = NT_STATUS_INVALID_HANDLE;
969 return CAC_FAILURE;
972 hnd->status =
973 rpccli_winreg_GetVersion( pipe_hnd, mem_ctx, op->in.key,
974 &version_out );
976 if ( !NT_STATUS_IS_OK( hnd->status ) )
977 return CAC_FAILURE;
979 op->out.version = version_out;
981 return CAC_SUCCESS;
984 int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
985 struct RegGetKeySecurity *op )
987 struct rpc_pipe_client *pipe_hnd = NULL;
988 struct KeySecurityData keysec;
990 ZERO_STRUCT( keysec );
992 if ( !hnd )
993 return CAC_FAILURE;
995 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
996 hnd->status = NT_STATUS_INVALID_HANDLE;
997 return CAC_FAILURE;
1000 if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
1001 hnd->status = NT_STATUS_INVALID_PARAMETER;
1002 return CAC_FAILURE;
1005 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1006 if ( !pipe_hnd ) {
1007 hnd->status = NT_STATUS_INVALID_HANDLE;
1008 return CAC_FAILURE;
1011 hnd->status =
1012 rpccli_winreg_GetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1013 op->in.info_type, &keysec );
1015 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1016 return CAC_FAILURE;
1019 #if 0 /* FIX ME!!!! unmarshall the security descriptor */
1020 op->out.size = buf.sd_size;
1021 op->out.descriptor = dup_sec_desc( mem_ctx, buf.sd );
1022 #endif
1024 if ( op->out.descriptor == NULL ) {
1025 return CAC_FAILURE;
1028 return CAC_SUCCESS;
1031 int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1032 struct RegSetKeySecurity *op )
1034 struct rpc_pipe_client *pipe_hnd = NULL;
1035 struct KeySecurityData keysec;
1037 ZERO_STRUCT( keysec );
1039 if ( !hnd )
1040 return CAC_FAILURE;
1042 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1043 hnd->status = NT_STATUS_INVALID_HANDLE;
1044 return CAC_FAILURE;
1047 if ( !op || !op->in.key || op->in.info_type == 0 || op->in.size == 0
1048 || !op->in.descriptor || !mem_ctx ) {
1049 hnd->status = NT_STATUS_INVALID_PARAMETER;
1050 return CAC_FAILURE;
1053 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1054 if ( !pipe_hnd ) {
1055 hnd->status = NT_STATUS_INVALID_HANDLE;
1056 return CAC_FAILURE;
1059 /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
1060 hnd->status =
1061 rpccli_winreg_SetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1062 op->in.info_type, &keysec );
1064 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1065 return CAC_FAILURE;
1068 return CAC_SUCCESS;
1071 int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1072 struct Shutdown *op )
1074 SMBCSRV *srv = NULL;
1075 struct rpc_pipe_client *pipe_hnd = NULL;
1076 struct initshutdown_String msg_string;
1077 struct initshutdown_String_sub s;
1079 char *msg;
1081 if ( !hnd )
1082 return CAC_FAILURE;
1084 if ( !hnd->_internal.ctx ) {
1085 hnd->status = NT_STATUS_INVALID_HANDLE;
1086 return CAC_FAILURE;
1089 if ( !op || !mem_ctx ) {
1090 hnd->status = NT_STATUS_INVALID_PARAMETER;
1091 return CAC_FAILURE;
1094 srv = cac_GetServer( hnd );
1095 if ( !srv ) {
1096 hnd->status = NT_STATUS_INVALID_HANDLE;
1097 return CAC_FAILURE;
1100 /*initialize for winreg pipe if we have to */
1101 if ( !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1102 if ( !
1103 ( pipe_hnd =
1104 cli_rpc_pipe_open_noauth( srv->cli, PI_INITSHUTDOWN,
1105 &( hnd->status ) ) ) ) {
1106 return CAC_FAILURE;
1109 hnd->_internal.pipes[PI_INITSHUTDOWN] = True;
1112 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1113 if ( !pipe_hnd ) {
1114 hnd->status = NT_STATUS_INVALID_HANDLE;
1115 return CAC_FAILURE;
1118 msg = ( op->in.message !=
1119 NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
1120 msg_string.name = &s;
1121 msg_string.name->name = msg;
1123 hnd->status = NT_STATUS_OK;
1125 if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
1126 hnd->status =
1127 rpccli_initshutdown_InitEx( pipe_hnd, mem_ctx, NULL,
1128 &msg_string,
1129 op->in.timeout,
1130 op->in.reboot,
1131 op->in.force,
1132 op->in.reason );
1135 if ( hnd->_internal.srv_level < SRV_WIN_2K
1136 || !NT_STATUS_IS_OK( hnd->status ) ) {
1137 hnd->status =
1138 rpccli_initshutdown_Init( pipe_hnd, mem_ctx, NULL,
1139 &msg_string, op->in.timeout,
1140 op->in.reboot,
1141 op->in.force );
1143 hnd->_internal.srv_level = SRV_WIN_NT4;
1146 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1147 return CAC_FAILURE;
1150 return CAC_SUCCESS;
1153 int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
1155 struct rpc_pipe_client *pipe_hnd = NULL;
1157 if ( !hnd )
1158 return CAC_FAILURE;
1160 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1161 hnd->status = NT_STATUS_INVALID_HANDLE;
1162 return CAC_FAILURE;
1165 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1166 if ( !pipe_hnd ) {
1167 hnd->status = NT_STATUS_INVALID_HANDLE;
1168 return CAC_FAILURE;
1171 hnd->status = rpccli_initshutdown_Abort( pipe_hnd, mem_ctx, NULL );
1173 if ( !NT_STATUS_IS_OK( hnd->status ) )
1174 return CAC_FAILURE;
1176 return CAC_SUCCESS;