[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / libmsrpc / cac_winreg.c
blobd8d2047be4ef3fec298f3a0e42b43f83e246ac0f
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 2 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, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libmsrpc.h"
23 #include "libmsrpc_internal.h"
25 WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
26 TALLOC_CTX * mem_ctx, POLICY_HND * key );
28 int cac_RegConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
29 struct RegConnect *op )
31 SMBCSRV *srv = NULL;
32 struct rpc_pipe_client *pipe_hnd = NULL;
33 POLICY_HND *key = NULL;
34 WERROR err;
36 if ( !hnd )
37 return CAC_FAILURE;
39 if ( !hnd->_internal.ctx ) {
40 hnd->status = NT_STATUS_INVALID_HANDLE;
41 return CAC_FAILURE;
44 if ( !op || !op->in.root || !mem_ctx ) {
45 hnd->status = NT_STATUS_INVALID_PARAMETER;
46 return CAC_FAILURE;
49 srv = cac_GetServer( hnd );
50 if ( !srv ) {
51 hnd->status = NT_STATUS_INVALID_CONNECTION;
52 return CAC_FAILURE;
55 /*initialize for winreg pipe if we have to */
56 if ( !hnd->_internal.pipes[PI_WINREG] ) {
57 if ( !
58 ( pipe_hnd =
59 cli_rpc_pipe_open_noauth( srv->cli, PI_WINREG,
60 &( hnd->status ) ) ) ) {
61 return CAC_FAILURE;
64 hnd->_internal.pipes[PI_WINREG] = True;
67 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
68 if ( !pipe_hnd ) {
69 hnd->status = NT_STATUS_INVALID_HANDLE;
70 return CAC_FAILURE;
73 key = talloc( mem_ctx, POLICY_HND );
74 if ( !key ) {
75 hnd->status = NT_STATUS_NO_MEMORY;
76 return CAC_FAILURE;
79 err = rpccli_reg_connect( pipe_hnd, mem_ctx, op->in.root,
80 op->in.access, key );
81 hnd->status = werror_to_ntstatus( err );
83 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
84 return CAC_FAILURE;
87 op->out.key = key;
89 return CAC_SUCCESS;
92 int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
93 POLICY_HND * key )
95 struct rpc_pipe_client *pipe_hnd = NULL;
96 WERROR err;
98 if ( !hnd )
99 return CAC_FAILURE;
101 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
102 hnd->status = NT_STATUS_INVALID_HANDLE;
103 return CAC_FAILURE;
106 if ( !key || !mem_ctx ) {
107 hnd->status = NT_STATUS_INVALID_PARAMETER;
108 return CAC_FAILURE;
111 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
112 if ( !pipe_hnd ) {
113 hnd->status = NT_STATUS_INVALID_HANDLE;
114 return CAC_FAILURE;
117 err = rpccli_reg_close( pipe_hnd, mem_ctx, key );
118 hnd->status = werror_to_ntstatus( err );
120 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
121 return CAC_FAILURE;
124 return CAC_SUCCESS;
127 int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
128 struct RegOpenKey *op )
130 struct rpc_pipe_client *pipe_hnd = NULL;
131 WERROR err;
133 POLICY_HND *key_out;
134 POLICY_HND *parent_key;
136 char *key_name = NULL;
137 uint32 reg_type = 0;
139 struct RegConnect rc;
141 if ( !hnd )
142 return CAC_FAILURE;
144 if ( !hnd->_internal.ctx ) {
145 hnd->status = NT_STATUS_INVALID_HANDLE;
146 return CAC_FAILURE;
149 if ( !op || !op->in.name || !mem_ctx ) {
150 hnd->status = NT_STATUS_INVALID_PARAMETER;
151 return CAC_FAILURE;
155 key_out = talloc( mem_ctx, POLICY_HND );
156 if ( !key_out ) {
157 hnd->status = NT_STATUS_NO_MEMORY;
158 return CAC_FAILURE;
161 if ( !op->in.parent_key ) {
162 /*then we need to connect to the registry */
163 if ( !cac_ParseRegPath( op->in.name, &reg_type, &key_name ) ) {
164 hnd->status = NT_STATUS_INVALID_PARAMETER;
165 return CAC_FAILURE;
168 /*use cac_RegConnect because it handles the session setup */
169 ZERO_STRUCT( rc );
171 rc.in.access = op->in.access;
172 rc.in.root = reg_type;
174 if ( !cac_RegConnect( hnd, mem_ctx, &rc ) ) {
175 return CAC_FAILURE;
178 /**if they only specified the root key, return the key we just opened*/
179 if ( key_name == NULL ) {
180 op->out.key = rc.out.key;
181 return CAC_SUCCESS;
184 parent_key = rc.out.key;
185 } else {
186 parent_key = op->in.parent_key;
187 key_name = op->in.name;
190 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
191 if ( !pipe_hnd ) {
192 hnd->status = NT_STATUS_INVALID_HANDLE;
193 return CAC_FAILURE;
196 err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, parent_key, key_name,
197 op->in.access, key_out );
198 hnd->status = werror_to_ntstatus( err );
200 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
201 return CAC_FAILURE;
204 if ( !op->in.parent_key ) {
205 /*then close the one that we opened above */
206 err = rpccli_reg_close( pipe_hnd, mem_ctx, parent_key );
207 hnd->status = werror_to_ntstatus( err );
209 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
210 return CAC_FAILURE;
214 op->out.key = key_out;
216 return CAC_SUCCESS;
219 int cac_RegEnumKeys( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
220 struct RegEnumKeys *op )
222 struct rpc_pipe_client *pipe_hnd = NULL;
223 WERROR err;
225 /*buffers for rpccli_reg_enum_key call */
226 fstring key_name_in;
227 fstring class_name_in;
229 /*output buffers */
230 char **key_names_out = NULL;
231 char **class_names_out = NULL;
232 time_t *mod_times_out = NULL;
233 uint32 num_keys_out = 0;
234 uint32 resume_idx = 0;
236 if ( !hnd )
237 return CAC_FAILURE;
239 /*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 */
240 if ( NT_STATUS_V( hnd->status ) ==
241 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
242 return CAC_FAILURE;
244 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
245 hnd->status = NT_STATUS_INVALID_HANDLE;
246 return CAC_FAILURE;
249 if ( !op || op->in.max_keys == 0 || !mem_ctx ) {
250 hnd->status = NT_STATUS_INVALID_PARAMETER;
251 return CAC_FAILURE;
254 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
255 if ( !pipe_hnd ) {
256 hnd->status = NT_STATUS_INVALID_HANDLE;
257 return CAC_FAILURE;
260 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
261 if (op->in.max_keys) {
262 key_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
263 if ( !key_names_out ) {
264 hnd->status = NT_STATUS_NO_MEMORY;
265 return CAC_FAILURE;
268 class_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
269 if ( !class_names_out ) {
270 hnd->status = NT_STATUS_NO_MEMORY;
271 TALLOC_FREE( key_names_out );
272 return CAC_FAILURE;
275 mod_times_out = TALLOC_ARRAY( mem_ctx, time_t, op->in.max_keys );
276 if ( !mod_times_out ) {
277 hnd->status = NT_STATUS_NO_MEMORY;
278 TALLOC_FREE( key_names_out );
279 TALLOC_FREE( class_names_out );
281 return CAC_FAILURE;
283 } else {
284 key_names_out = NULL;
285 class_names_out = NULL;
286 mod_times_out = NULL;
289 resume_idx = op->out.resume_idx;
291 do {
292 err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, op->in.key,
293 resume_idx, key_name_in,
294 class_name_in,
295 &mod_times_out[num_keys_out] );
296 hnd->status = werror_to_ntstatus( err );
298 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
299 /*don't increment any values */
300 break;
303 key_names_out[num_keys_out] =
304 talloc_strdup( mem_ctx, key_name_in );
306 class_names_out[num_keys_out] =
307 talloc_strdup( mem_ctx, class_name_in );
309 if ( !key_names_out[num_keys_out]
310 || !class_names_out[num_keys_out] ) {
311 hnd->status = NT_STATUS_NO_MEMORY;
312 break;
315 resume_idx++;
316 num_keys_out++;
317 } while ( num_keys_out < op->in.max_keys );
319 if ( CAC_OP_FAILED( hnd->status ) ) {
320 op->out.num_keys = 0;
321 return CAC_FAILURE;
324 op->out.resume_idx = resume_idx;
325 op->out.num_keys = num_keys_out;
326 op->out.key_names = key_names_out;
327 op->out.class_names = class_names_out;
328 op->out.mod_times = mod_times_out;
330 return CAC_SUCCESS;
333 int cac_RegCreateKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
334 struct RegCreateKey *op )
336 struct rpc_pipe_client *pipe_hnd = NULL;
337 WERROR err;
339 POLICY_HND *key_out;
341 struct RegOpenKey rok;
343 if ( !hnd )
344 return CAC_FAILURE;
346 if ( !hnd->_internal.ctx ) {
347 hnd->status = NT_STATUS_INVALID_HANDLE;
348 return CAC_FAILURE;
351 if ( !op || !op->in.parent_key || !op->in.key_name || !mem_ctx ) {
352 hnd->status = NT_STATUS_INVALID_PARAMETER;
353 return CAC_FAILURE;
356 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
357 ZERO_STRUCT( rok );
359 rok.in.name = op->in.key_name;
360 rok.in.access = op->in.access;
361 rok.in.parent_key = op->in.parent_key;
363 if ( cac_RegOpenKey( hnd, mem_ctx, &rok ) ) {
364 /*then we got the key, return */
365 op->out.key = rok.out.key;
366 return CAC_SUCCESS;
369 /*just be ultra-safe */
370 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
371 if ( !pipe_hnd ) {
372 hnd->status = NT_STATUS_INVALID_HANDLE;
373 return CAC_FAILURE;
376 key_out = talloc( mem_ctx, POLICY_HND );
377 if ( !key_out ) {
378 hnd->status = NT_STATUS_NO_MEMORY;
379 return CAC_FAILURE;
382 err = rpccli_reg_create_key_ex( pipe_hnd, mem_ctx, op->in.parent_key,
383 op->in.key_name, op->in.class_name,
384 op->in.access, key_out );
385 hnd->status = werror_to_ntstatus( err );
387 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
388 return CAC_FAILURE;
391 op->out.key = key_out;
393 return CAC_SUCCESS;
397 WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
398 TALLOC_CTX * mem_ctx, POLICY_HND * key )
400 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
401 * so we use the cli_reg functions directly*/
403 WERROR err = WERR_OK;
405 POLICY_HND subkey;
406 fstring subkey_name;
407 fstring class_buf;
408 time_t mod_time_buf;
410 int cur_key = 0;
412 while ( W_ERROR_IS_OK( err ) ) {
413 err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, key, cur_key,
414 subkey_name, class_buf,
415 &mod_time_buf );
417 if ( !W_ERROR_IS_OK( err ) )
418 break;
420 /*try to open the key with full access */
421 err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, key,
422 subkey_name, REG_KEY_ALL,
423 &subkey );
425 if ( !W_ERROR_IS_OK( err ) )
426 break;
428 err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
429 &subkey );
431 if ( !W_ERROR_EQUAL( err, WERR_NO_MORE_ITEMS )
432 && !W_ERROR_IS_OK( err ) )
433 break;
435 /*flush the key just to be safe */
436 rpccli_reg_flush_key( pipe_hnd, mem_ctx, key );
438 /*close the key that we opened */
439 rpccli_reg_close( pipe_hnd, mem_ctx, &subkey );
441 /*now we delete the subkey */
442 err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, key,
443 subkey_name );
446 cur_key++;
450 return err;
455 int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
456 struct RegDeleteKey *op )
458 struct rpc_pipe_client *pipe_hnd = NULL;
459 WERROR err;
461 if ( !hnd )
462 return CAC_FAILURE;
464 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
465 hnd->status = NT_STATUS_INVALID_HANDLE;
466 return CAC_FAILURE;
469 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
470 hnd->status = NT_STATUS_INVALID_PARAMETER;
471 return CAC_FAILURE;
474 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
475 if ( !pipe_hnd ) {
476 hnd->status = NT_STATUS_INVALID_HANDLE;
477 return CAC_FAILURE;
480 if ( op->in.recursive ) {
481 /*first open the key, and then delete all of it's subkeys recursively */
482 struct RegOpenKey rok;
484 ZERO_STRUCT( rok );
486 rok.in.parent_key = op->in.parent_key;
487 rok.in.name = op->in.name;
488 rok.in.access = REG_KEY_ALL;
490 if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
491 return CAC_FAILURE;
493 err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
494 rok.out.key );
496 /*close the key that we opened */
497 cac_RegClose( hnd, mem_ctx, rok.out.key );
499 hnd->status = werror_to_ntstatus( err );
501 if ( NT_STATUS_V( hnd->status ) !=
502 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
503 && !NT_STATUS_IS_OK( hnd->status ) )
504 return CAC_FAILURE;
506 /*now go on to actually delete the key */
509 err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, op->in.parent_key,
510 op->in.name );
511 hnd->status = werror_to_ntstatus( err );
513 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
514 return CAC_FAILURE;
517 return CAC_SUCCESS;
520 int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
521 struct RegDeleteValue *op )
523 struct rpc_pipe_client *pipe_hnd = NULL;
524 WERROR err;
526 if ( !hnd )
527 return CAC_FAILURE;
529 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
530 hnd->status = NT_STATUS_INVALID_HANDLE;
531 return CAC_FAILURE;
534 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
535 hnd->status = NT_STATUS_INVALID_PARAMETER;
536 return CAC_FAILURE;
539 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
540 if ( !pipe_hnd ) {
541 hnd->status = NT_STATUS_INVALID_HANDLE;
542 return CAC_FAILURE;
545 err = rpccli_reg_delete_val( pipe_hnd, mem_ctx, op->in.parent_key,
546 op->in.name );
547 hnd->status = werror_to_ntstatus( err );
549 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
550 return CAC_FAILURE;
553 return CAC_SUCCESS;
556 #if 0
558 /* JRA - disabled until fix. */
560 /* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
561 cleanly and resubmit the query. */
563 int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
564 struct RegQueryKeyInfo *op )
566 struct rpc_pipe_client *pipe_hnd = NULL;
567 WERROR err;
569 char *class_name_out = NULL;
570 uint32 class_len = 0;
571 uint32 num_subkeys_out = 0;
572 uint32 long_subkey_out = 0;
573 uint32 long_class_out = 0;
574 uint32 num_values_out = 0;
575 uint32 long_value_out = 0;
576 uint32 long_data_out = 0;
577 uint32 secdesc_size = 0;
578 NTTIME mod_time;
580 if ( !hnd )
581 return CAC_FAILURE;
583 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
584 hnd->status = NT_STATUS_INVALID_HANDLE;
585 return CAC_FAILURE;
588 if ( !op || !op->in.key || !mem_ctx ) {
589 hnd->status = NT_STATUS_INVALID_PARAMETER;
590 return CAC_FAILURE;
593 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
594 if ( !pipe_hnd ) {
595 hnd->status = NT_STATUS_INVALID_HANDLE;
596 return CAC_FAILURE;
599 err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
600 class_name_out,
601 &class_len,
602 &num_subkeys_out,
603 &long_subkey_out,
604 &long_class_out,
605 &num_values_out,
606 &long_value_out,
607 &long_data_out,
608 &secdesc_size, &mod_time );
610 hnd->status = werror_to_ntstatus( err );
612 if ( !NT_STATUS_IS_OK( hnd->status ) )
613 return CAC_FAILURE;
615 if ( !class_name_out ) {
616 op->out.class_name = talloc_strdup( mem_ctx, "" );
617 } else if ( class_len != 0 && class_name_out[class_len - 1] != '\0' ) {
618 /*then we need to add a '\0' */
619 op->out.class_name =
620 TALLOC_SIZE( mem_ctx,
621 sizeof( char ) * ( class_len + 1 ) );
623 memcpy( op->out.class_name, class_name_out, class_len );
625 op->out.class_name[class_len] = '\0';
626 } else { /*then everything worked out fine in the function */
627 op->out.class_name = talloc_strdup( mem_ctx, class_name_out );
630 if ( !op->out.class_name ) {
631 hnd->status = NT_STATUS_NO_MEMORY;
632 return CAC_FAILURE;
635 op->out.num_subkeys = num_subkeys_out;
636 op->out.longest_subkey = long_subkey_out;
637 op->out.longest_class = long_class_out;
638 op->out.num_values = num_values_out;
639 op->out.longest_value_name = long_value_out;
640 op->out.longest_value_data = long_data_out;
641 op->out.security_desc_size = secdesc_size;
642 op->out.last_write_time = nt_time_to_unix( &mod_time );
644 return CAC_FAILURE;
646 #endif
648 int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
649 struct RegQueryValue *op )
651 struct rpc_pipe_client *pipe_hnd = NULL;
652 WERROR err;
654 uint32 val_type;
655 REGVAL_BUFFER buffer;
656 REG_VALUE_DATA *data_out = NULL;
658 if ( !hnd )
659 return CAC_FAILURE;
661 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
662 hnd->status = NT_STATUS_INVALID_HANDLE;
663 return CAC_FAILURE;
666 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
667 hnd->status = NT_STATUS_INVALID_PARAMETER;
668 return CAC_FAILURE;
671 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
672 if ( !pipe_hnd ) {
673 hnd->status = NT_STATUS_INVALID_HANDLE;
674 return CAC_FAILURE;
677 err = rpccli_reg_query_value( pipe_hnd, mem_ctx, op->in.key,
678 op->in.val_name, &val_type, &buffer );
679 hnd->status = werror_to_ntstatus( err );
681 if ( !NT_STATUS_IS_OK( hnd->status ) )
682 return CAC_FAILURE;
684 data_out = cac_MakeRegValueData( mem_ctx, val_type, buffer );
685 if ( !data_out ) {
686 if ( errno == ENOMEM )
687 hnd->status = NT_STATUS_NO_MEMORY;
688 else
689 hnd->status = NT_STATUS_INVALID_PARAMETER;
691 return CAC_FAILURE;
694 op->out.type = val_type;
695 op->out.data = data_out;
697 return CAC_SUCCESS;
701 int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
702 struct RegEnumValues *op )
704 struct rpc_pipe_client *pipe_hnd = NULL;
705 WERROR err;
707 /*buffers for rpccli_reg_enum_key call */
708 fstring val_name_buf;
709 REGVAL_BUFFER val_buf;
711 /*output buffers */
712 uint32 *types_out = NULL;
713 REG_VALUE_DATA **values_out = NULL;
714 char **val_names_out = NULL;
715 uint32 num_values_out = 0;
716 uint32 resume_idx = 0;
718 if ( !hnd )
719 return CAC_FAILURE;
721 /*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 */
722 if ( NT_STATUS_V( hnd->status ) ==
723 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
724 return CAC_FAILURE;
726 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
727 hnd->status = NT_STATUS_INVALID_HANDLE;
728 return CAC_FAILURE;
731 if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
732 hnd->status = NT_STATUS_INVALID_PARAMETER;
733 return CAC_FAILURE;
736 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
737 if ( !pipe_hnd ) {
738 hnd->status = NT_STATUS_INVALID_HANDLE;
739 return CAC_FAILURE;
742 /*we need to assume that the max number of values will be enumerated */
743 if (op->in.max_values) {
744 types_out =
745 ( uint32 * ) TALLOC_ARRAY( mem_ctx, int, op->in.max_values );
746 if ( !types_out ) {
747 hnd->status = NT_STATUS_NO_MEMORY;
748 return CAC_FAILURE;
751 values_out =
752 TALLOC_ARRAY( mem_ctx, REG_VALUE_DATA *, op->in.max_values );
753 if ( !values_out ) {
754 TALLOC_FREE( types_out );
755 hnd->status = NT_STATUS_NO_MEMORY;
756 return CAC_FAILURE;
759 val_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_values );
760 if ( !val_names_out ) {
761 TALLOC_FREE( types_out );
762 TALLOC_FREE( values_out );
763 hnd->status = NT_STATUS_NO_MEMORY;
764 return CAC_FAILURE;
766 } else {
767 types_out = NULL;
768 values_out = NULL;
769 val_names_out = NULL;
772 resume_idx = op->out.resume_idx;
773 do {
774 ZERO_STRUCT( val_buf );
776 err = rpccli_reg_enum_val( pipe_hnd, mem_ctx, op->in.key,
777 resume_idx, val_name_buf,
778 &types_out[num_values_out],
779 &val_buf );
780 hnd->status = werror_to_ntstatus( err );
782 if ( !NT_STATUS_IS_OK( hnd->status ) )
783 break;
785 values_out[num_values_out] =
786 cac_MakeRegValueData( mem_ctx,
787 types_out[num_values_out],
788 val_buf );
789 val_names_out[num_values_out] =
790 talloc_strdup( mem_ctx, val_name_buf );
792 if ( !val_names_out[num_values_out]
793 || !values_out[num_values_out] ) {
794 hnd->status = NT_STATUS_NO_MEMORY;
795 break;
798 num_values_out++;
799 resume_idx++;
800 } while ( num_values_out < op->in.max_values );
802 if ( CAC_OP_FAILED( hnd->status ) )
803 return CAC_FAILURE;
805 op->out.types = types_out;
806 op->out.num_values = num_values_out;
807 op->out.value_names = val_names_out;
808 op->out.values = values_out;
809 op->out.resume_idx = resume_idx;
811 return CAC_SUCCESS;
814 int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
815 struct RegSetValue *op )
817 struct rpc_pipe_client *pipe_hnd = NULL;
818 WERROR err;
820 RPC_DATA_BLOB *buffer;
822 if ( !hnd )
823 return CAC_FAILURE;
825 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
826 hnd->status = NT_STATUS_INVALID_HANDLE;
827 return CAC_FAILURE;
830 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
831 hnd->status = NT_STATUS_INVALID_PARAMETER;
832 return CAC_FAILURE;
835 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
836 if ( !pipe_hnd ) {
837 hnd->status = NT_STATUS_INVALID_HANDLE;
838 return CAC_FAILURE;
841 buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
843 if ( !buffer ) {
844 if ( errno == ENOMEM )
845 hnd->status = NT_STATUS_NO_MEMORY;
846 else
847 hnd->status = NT_STATUS_INVALID_PARAMETER;
849 return CAC_FAILURE;
852 err = rpccli_reg_set_val( pipe_hnd, mem_ctx, op->in.key,
853 op->in.val_name, op->in.type, buffer );
854 hnd->status = werror_to_ntstatus( err );
856 if ( !NT_STATUS_IS_OK( hnd->status ) )
857 return CAC_FAILURE;
859 /*flush */
860 err = rpccli_reg_flush_key( pipe_hnd, mem_ctx, op->in.key );
861 hnd->status = werror_to_ntstatus( err );
863 if ( !NT_STATUS_IS_OK( hnd->status ) )
864 return CAC_FAILURE;
866 return CAC_SUCCESS;
871 int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
872 struct RegGetVersion *op )
874 struct rpc_pipe_client *pipe_hnd = NULL;
875 WERROR err;
877 uint32 version_out;
879 if ( !hnd )
880 return CAC_FAILURE;
882 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
883 hnd->status = NT_STATUS_INVALID_HANDLE;
884 return CAC_FAILURE;
887 if ( !op || !op->in.key || !mem_ctx ) {
888 hnd->status = NT_STATUS_INVALID_PARAMETER;
889 return CAC_FAILURE;
892 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
893 if ( !pipe_hnd ) {
894 hnd->status = NT_STATUS_INVALID_HANDLE;
895 return CAC_FAILURE;
898 err = rpccli_reg_getversion( pipe_hnd, mem_ctx, op->in.key,
899 &version_out );
900 hnd->status = werror_to_ntstatus( err );
902 if ( !NT_STATUS_IS_OK( hnd->status ) )
903 return CAC_FAILURE;
905 op->out.version = version_out;
907 return CAC_SUCCESS;
910 int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
911 struct RegGetKeySecurity *op )
913 struct rpc_pipe_client *pipe_hnd = NULL;
914 WERROR err;
916 uint32 buf_size;
917 SEC_DESC_BUF buf;
919 ZERO_STRUCT( buf );
921 if ( !hnd )
922 return CAC_FAILURE;
924 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
925 hnd->status = NT_STATUS_INVALID_HANDLE;
926 return CAC_FAILURE;
929 if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
930 hnd->status = NT_STATUS_INVALID_PARAMETER;
931 return CAC_FAILURE;
934 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
935 if ( !pipe_hnd ) {
936 hnd->status = NT_STATUS_INVALID_HANDLE;
937 return CAC_FAILURE;
940 err = rpccli_reg_get_key_sec( pipe_hnd, mem_ctx, op->in.key,
941 op->in.info_type, &buf_size, &buf );
942 hnd->status = werror_to_ntstatus( err );
945 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
946 return CAC_FAILURE;
949 op->out.size = buf.len;
950 op->out.descriptor = dup_sec_desc( mem_ctx, buf.sec );
952 if ( op->out.descriptor == NULL ) {
953 return CAC_FAILURE;
956 return CAC_SUCCESS;
959 int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
960 struct RegSetKeySecurity *op )
962 struct rpc_pipe_client *pipe_hnd = NULL;
963 WERROR err;
965 if ( !hnd )
966 return CAC_FAILURE;
968 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
969 hnd->status = NT_STATUS_INVALID_HANDLE;
970 return CAC_FAILURE;
973 if ( !op || !op->in.key || op->in.info_type == 0 || op->in.size == 0
974 || !op->in.descriptor || !mem_ctx ) {
975 hnd->status = NT_STATUS_INVALID_PARAMETER;
976 return CAC_FAILURE;
979 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
980 if ( !pipe_hnd ) {
981 hnd->status = NT_STATUS_INVALID_HANDLE;
982 return CAC_FAILURE;
985 err = rpccli_reg_set_key_sec( pipe_hnd, mem_ctx, op->in.key,
986 op->in.info_type, op->in.size,
987 op->in.descriptor );
988 hnd->status = werror_to_ntstatus( err );
991 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
992 return CAC_FAILURE;
995 return CAC_SUCCESS;
998 int cac_RegSaveKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
999 struct RegSaveKey *op )
1001 struct rpc_pipe_client *pipe_hnd = NULL;
1002 WERROR err;
1004 if ( !hnd )
1005 return CAC_FAILURE;
1007 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1008 hnd->status = NT_STATUS_INVALID_HANDLE;
1009 return CAC_FAILURE;
1012 if ( !op || !op->in.key || !op->in.filename || !mem_ctx ) {
1013 hnd->status = NT_STATUS_INVALID_PARAMETER;
1014 return CAC_FAILURE;
1017 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1018 if ( !pipe_hnd ) {
1019 hnd->status = NT_STATUS_INVALID_HANDLE;
1020 return CAC_FAILURE;
1023 err = rpccli_reg_save_key( pipe_hnd, mem_ctx, op->in.key,
1024 op->in.filename );
1025 hnd->status = werror_to_ntstatus( err );
1028 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1029 return CAC_FAILURE;
1032 return CAC_SUCCESS;
1035 int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1036 struct Shutdown *op )
1038 SMBCSRV *srv = NULL;
1039 struct rpc_pipe_client *pipe_hnd = NULL;
1041 char *msg;
1043 if ( !hnd )
1044 return CAC_FAILURE;
1046 if ( !hnd->_internal.ctx ) {
1047 hnd->status = NT_STATUS_INVALID_HANDLE;
1048 return CAC_FAILURE;
1051 if ( !op || !mem_ctx ) {
1052 hnd->status = NT_STATUS_INVALID_PARAMETER;
1053 return CAC_FAILURE;
1056 srv = cac_GetServer( hnd );
1057 if ( !srv ) {
1058 hnd->status = NT_STATUS_INVALID_HANDLE;
1059 return CAC_FAILURE;
1062 /*initialize for winreg pipe if we have to */
1063 if ( !hnd->_internal.pipes[PI_SHUTDOWN] ) {
1064 if ( !
1065 ( pipe_hnd =
1066 cli_rpc_pipe_open_noauth( srv->cli, PI_SHUTDOWN,
1067 &( hnd->status ) ) ) ) {
1068 return CAC_FAILURE;
1071 hnd->_internal.pipes[PI_SHUTDOWN] = True;
1074 pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
1075 if ( !pipe_hnd ) {
1076 hnd->status = NT_STATUS_INVALID_HANDLE;
1077 return CAC_FAILURE;
1080 msg = ( op->in.message !=
1081 NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
1083 hnd->status = NT_STATUS_OK;
1085 if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
1086 hnd->status =
1087 rpccli_shutdown_init_ex( pipe_hnd, mem_ctx, msg,
1088 op->in.timeout,
1089 op->in.reboot, op->in.force,
1090 op->in.reason );
1093 if ( hnd->_internal.srv_level < SRV_WIN_2K
1094 || !NT_STATUS_IS_OK( hnd->status ) ) {
1095 hnd->status =
1096 rpccli_shutdown_init( pipe_hnd, mem_ctx, msg,
1097 op->in.timeout, op->in.reboot,
1098 op->in.force );
1100 hnd->_internal.srv_level = SRV_WIN_NT4;
1103 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1104 return CAC_FAILURE;
1107 return CAC_SUCCESS;
1110 int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
1112 struct rpc_pipe_client *pipe_hnd = NULL;
1114 if ( !hnd )
1115 return CAC_FAILURE;
1117 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN] ) {
1118 hnd->status = NT_STATUS_INVALID_HANDLE;
1119 return CAC_FAILURE;
1122 pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
1123 if ( !pipe_hnd ) {
1124 hnd->status = NT_STATUS_INVALID_HANDLE;
1125 return CAC_FAILURE;
1128 hnd->status = rpccli_shutdown_abort( pipe_hnd, mem_ctx );
1130 if ( !NT_STATUS_IS_OK( hnd->status ) )
1131 return CAC_FAILURE;
1133 return CAC_SUCCESS;