source: trunk-3.0/source/libmsrpc/cac_winreg.c@ 102

Last change on this file since 102 was 39, checked in by Paul Smedley, 18 years ago

Upgrade source to 3.0.25a

File size: 27.1 KB
Line 
1
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.
11 *
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.
16 *
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.
20 */
21
22#include "libmsrpc.h"
23#include "libmsrpc_internal.h"
24
25WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
26 TALLOC_CTX * mem_ctx, POLICY_HND * key );
27
28int cac_RegConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
29 struct RegConnect *op )
30{
31 SMBCSRV *srv = NULL;
32 struct rpc_pipe_client *pipe_hnd = NULL;
33 POLICY_HND *key = NULL;
34 WERROR err;
35
36 if ( !hnd )
37 return CAC_FAILURE;
38
39 if ( !hnd->_internal.ctx ) {
40 hnd->status = NT_STATUS_INVALID_HANDLE;
41 return CAC_FAILURE;
42 }
43
44 if ( !op || !op->in.root || !mem_ctx ) {
45 hnd->status = NT_STATUS_INVALID_PARAMETER;
46 return CAC_FAILURE;
47 }
48
49 srv = cac_GetServer( hnd );
50 if ( !srv ) {
51 hnd->status = NT_STATUS_INVALID_CONNECTION;
52 return CAC_FAILURE;
53 }
54
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;
62 }
63
64 hnd->_internal.pipes[PI_WINREG] = True;
65 }
66
67 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
68 if ( !pipe_hnd ) {
69 hnd->status = NT_STATUS_INVALID_HANDLE;
70 return CAC_FAILURE;
71 }
72
73 key = talloc( mem_ctx, POLICY_HND );
74 if ( !key ) {
75 hnd->status = NT_STATUS_NO_MEMORY;
76 return CAC_FAILURE;
77 }
78
79 err = rpccli_reg_connect( pipe_hnd, mem_ctx, op->in.root,
80 op->in.access, key );
81 hnd->status = werror_to_ntstatus( err );
82
83 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
84 return CAC_FAILURE;
85 }
86
87 op->out.key = key;
88
89 return CAC_SUCCESS;
90}
91
92int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
93 POLICY_HND * key )
94{
95 struct rpc_pipe_client *pipe_hnd = NULL;
96 WERROR err;
97
98 if ( !hnd )
99 return CAC_FAILURE;
100
101 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
102 hnd->status = NT_STATUS_INVALID_HANDLE;
103 return CAC_FAILURE;
104 }
105
106 if ( !key || !mem_ctx ) {
107 hnd->status = NT_STATUS_INVALID_PARAMETER;
108 return CAC_FAILURE;
109 }
110
111 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
112 if ( !pipe_hnd ) {
113 hnd->status = NT_STATUS_INVALID_HANDLE;
114 return CAC_FAILURE;
115 }
116
117 err = rpccli_reg_close( pipe_hnd, mem_ctx, key );
118 hnd->status = werror_to_ntstatus( err );
119
120 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
121 return CAC_FAILURE;
122 }
123
124 return CAC_SUCCESS;
125}
126
127int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
128 struct RegOpenKey *op )
129{
130 struct rpc_pipe_client *pipe_hnd = NULL;
131 WERROR err;
132
133 POLICY_HND *key_out;
134 POLICY_HND *parent_key;
135
136 char *key_name = NULL;
137 uint32 reg_type = 0;
138
139 struct RegConnect rc;
140
141 if ( !hnd )
142 return CAC_FAILURE;
143
144 if ( !hnd->_internal.ctx ) {
145 hnd->status = NT_STATUS_INVALID_HANDLE;
146 return CAC_FAILURE;
147 }
148
149 if ( !op || !op->in.name || !mem_ctx ) {
150 hnd->status = NT_STATUS_INVALID_PARAMETER;
151 return CAC_FAILURE;
152 }
153
154
155 key_out = talloc( mem_ctx, POLICY_HND );
156 if ( !key_out ) {
157 hnd->status = NT_STATUS_NO_MEMORY;
158 return CAC_FAILURE;
159 }
160
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;
166 }
167
168 /*use cac_RegConnect because it handles the session setup */
169 ZERO_STRUCT( rc );
170
171 rc.in.access = op->in.access;
172 rc.in.root = reg_type;
173
174 if ( !cac_RegConnect( hnd, mem_ctx, &rc ) ) {
175 return CAC_FAILURE;
176 }
177
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;
182 }
183
184 parent_key = rc.out.key;
185 } else {
186 parent_key = op->in.parent_key;
187 key_name = op->in.name;
188 }
189
190 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
191 if ( !pipe_hnd ) {
192 hnd->status = NT_STATUS_INVALID_HANDLE;
193 return CAC_FAILURE;
194 }
195
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 );
199
200 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
201 return CAC_FAILURE;
202 }
203
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 );
208
209 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
210 return CAC_FAILURE;
211 }
212 }
213
214 op->out.key = key_out;
215
216 return CAC_SUCCESS;
217}
218
219int cac_RegEnumKeys( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
220 struct RegEnumKeys *op )
221{
222 struct rpc_pipe_client *pipe_hnd = NULL;
223 WERROR err;
224
225 /*buffers for rpccli_reg_enum_key call */
226 fstring key_name_in;
227 fstring class_name_in;
228
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;
235
236 if ( !hnd )
237 return CAC_FAILURE;
238
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;
243
244 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
245 hnd->status = NT_STATUS_INVALID_HANDLE;
246 return CAC_FAILURE;
247 }
248
249 if ( !op || op->in.max_keys == 0 || !mem_ctx ) {
250 hnd->status = NT_STATUS_INVALID_PARAMETER;
251 return CAC_FAILURE;
252 }
253
254 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
255 if ( !pipe_hnd ) {
256 hnd->status = NT_STATUS_INVALID_HANDLE;
257 return CAC_FAILURE;
258 }
259
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;
266 }
267
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;
273 }
274
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 );
280
281 return CAC_FAILURE;
282 }
283 } else {
284 key_names_out = NULL;
285 class_names_out = NULL;
286 mod_times_out = NULL;
287 }
288
289 resume_idx = op->out.resume_idx;
290
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 );
297
298 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
299 /*don't increment any values */
300 break;
301 }
302
303 key_names_out[num_keys_out] =
304 talloc_strdup( mem_ctx, key_name_in );
305
306 class_names_out[num_keys_out] =
307 talloc_strdup( mem_ctx, class_name_in );
308
309 if ( !key_names_out[num_keys_out]
310 || !class_names_out[num_keys_out] ) {
311 hnd->status = NT_STATUS_NO_MEMORY;
312 break;
313 }
314
315 resume_idx++;
316 num_keys_out++;
317 } while ( num_keys_out < op->in.max_keys );
318
319 if ( CAC_OP_FAILED( hnd->status ) ) {
320 op->out.num_keys = 0;
321 return CAC_FAILURE;
322 }
323
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;
329
330 return CAC_SUCCESS;
331}
332
333int cac_RegCreateKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
334 struct RegCreateKey *op )
335{
336 struct rpc_pipe_client *pipe_hnd = NULL;
337 WERROR err;
338
339 POLICY_HND *key_out;
340
341 struct RegOpenKey rok;
342
343 if ( !hnd )
344 return CAC_FAILURE;
345
346 if ( !hnd->_internal.ctx ) {
347 hnd->status = NT_STATUS_INVALID_HANDLE;
348 return CAC_FAILURE;
349 }
350
351 if ( !op || !op->in.parent_key || !op->in.key_name || !mem_ctx ) {
352 hnd->status = NT_STATUS_INVALID_PARAMETER;
353 return CAC_FAILURE;
354 }
355
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 );
358
359 rok.in.name = op->in.key_name;
360 rok.in.access = op->in.access;
361 rok.in.parent_key = op->in.parent_key;
362
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;
367 }
368
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;
374 }
375
376 key_out = talloc( mem_ctx, POLICY_HND );
377 if ( !key_out ) {
378 hnd->status = NT_STATUS_NO_MEMORY;
379 return CAC_FAILURE;
380 }
381
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 );
386
387 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
388 return CAC_FAILURE;
389 }
390
391 op->out.key = key_out;
392
393 return CAC_SUCCESS;
394
395}
396
397WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
398 TALLOC_CTX * mem_ctx, POLICY_HND * key )
399{
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*/
402
403 WERROR err = WERR_OK;
404
405 POLICY_HND subkey;
406 fstring subkey_name;
407 fstring class_buf;
408 time_t mod_time_buf;
409
410 int cur_key = 0;
411
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 );
416
417 if ( !W_ERROR_IS_OK( err ) )
418 break;
419
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 );
424
425 if ( !W_ERROR_IS_OK( err ) )
426 break;
427
428 err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
429 &subkey );
430
431 if ( !W_ERROR_EQUAL( err, WERR_NO_MORE_ITEMS )
432 && !W_ERROR_IS_OK( err ) )
433 break;
434
435 /*flush the key just to be safe */
436 rpccli_reg_flush_key( pipe_hnd, mem_ctx, key );
437
438 /*close the key that we opened */
439 rpccli_reg_close( pipe_hnd, mem_ctx, &subkey );
440
441 /*now we delete the subkey */
442 err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, key,
443 subkey_name );
444
445
446 cur_key++;
447 }
448
449
450 return err;
451}
452
453
454
455int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
456 struct RegDeleteKey *op )
457{
458 struct rpc_pipe_client *pipe_hnd = NULL;
459 WERROR err;
460
461 if ( !hnd )
462 return CAC_FAILURE;
463
464 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
465 hnd->status = NT_STATUS_INVALID_HANDLE;
466 return CAC_FAILURE;
467 }
468
469 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
470 hnd->status = NT_STATUS_INVALID_PARAMETER;
471 return CAC_FAILURE;
472 }
473
474 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
475 if ( !pipe_hnd ) {
476 hnd->status = NT_STATUS_INVALID_HANDLE;
477 return CAC_FAILURE;
478 }
479
480 if ( op->in.recursive ) {
481 /*first open the key, and then delete all of it's subkeys recursively */
482 struct RegOpenKey rok;
483
484 ZERO_STRUCT( rok );
485
486 rok.in.parent_key = op->in.parent_key;
487 rok.in.name = op->in.name;
488 rok.in.access = REG_KEY_ALL;
489
490 if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
491 return CAC_FAILURE;
492
493 err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
494 rok.out.key );
495
496 /*close the key that we opened */
497 cac_RegClose( hnd, mem_ctx, rok.out.key );
498
499 hnd->status = werror_to_ntstatus( err );
500
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;
505
506 /*now go on to actually delete the key */
507 }
508
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 );
512
513 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
514 return CAC_FAILURE;
515 }
516
517 return CAC_SUCCESS;
518}
519
520int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
521 struct RegDeleteValue *op )
522{
523 struct rpc_pipe_client *pipe_hnd = NULL;
524 WERROR err;
525
526 if ( !hnd )
527 return CAC_FAILURE;
528
529 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
530 hnd->status = NT_STATUS_INVALID_HANDLE;
531 return CAC_FAILURE;
532 }
533
534 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
535 hnd->status = NT_STATUS_INVALID_PARAMETER;
536 return CAC_FAILURE;
537 }
538
539 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
540 if ( !pipe_hnd ) {
541 hnd->status = NT_STATUS_INVALID_HANDLE;
542 return CAC_FAILURE;
543 }
544
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 );
548
549 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
550 return CAC_FAILURE;
551 }
552
553 return CAC_SUCCESS;
554}
555
556#if 0
557
558/* JRA - disabled until fix. */
559
560/* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
561 cleanly and resubmit the query. */
562
563int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
564 struct RegQueryKeyInfo *op )
565{
566 struct rpc_pipe_client *pipe_hnd = NULL;
567 WERROR err;
568
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;
579
580 if ( !hnd )
581 return CAC_FAILURE;
582
583 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
584 hnd->status = NT_STATUS_INVALID_HANDLE;
585 return CAC_FAILURE;
586 }
587
588 if ( !op || !op->in.key || !mem_ctx ) {
589 hnd->status = NT_STATUS_INVALID_PARAMETER;
590 return CAC_FAILURE;
591 }
592
593 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
594 if ( !pipe_hnd ) {
595 hnd->status = NT_STATUS_INVALID_HANDLE;
596 return CAC_FAILURE;
597 }
598
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 );
609
610 hnd->status = werror_to_ntstatus( err );
611
612 if ( !NT_STATUS_IS_OK( hnd->status ) )
613 return CAC_FAILURE;
614
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 ) );
622
623 memcpy( op->out.class_name, class_name_out, class_len );
624
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 );
628 }
629
630 if ( !op->out.class_name ) {
631 hnd->status = NT_STATUS_NO_MEMORY;
632 return CAC_FAILURE;
633 }
634
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 );
643
644 return CAC_FAILURE;
645}
646#endif
647
648int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
649 struct RegQueryValue *op )
650{
651 struct rpc_pipe_client *pipe_hnd = NULL;
652 WERROR err;
653
654 uint32 val_type;
655 REGVAL_BUFFER buffer;
656 REG_VALUE_DATA *data_out = NULL;
657
658 if ( !hnd )
659 return CAC_FAILURE;
660
661 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
662 hnd->status = NT_STATUS_INVALID_HANDLE;
663 return CAC_FAILURE;
664 }
665
666 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
667 hnd->status = NT_STATUS_INVALID_PARAMETER;
668 return CAC_FAILURE;
669 }
670
671 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
672 if ( !pipe_hnd ) {
673 hnd->status = NT_STATUS_INVALID_HANDLE;
674 return CAC_FAILURE;
675 }
676
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 );
680
681 if ( !NT_STATUS_IS_OK( hnd->status ) )
682 return CAC_FAILURE;
683
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;
690
691 return CAC_FAILURE;
692 }
693
694 op->out.type = val_type;
695 op->out.data = data_out;
696
697 return CAC_SUCCESS;
698}
699
700
701int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
702 struct RegEnumValues *op )
703{
704 struct rpc_pipe_client *pipe_hnd = NULL;
705 WERROR err;
706
707 /*buffers for rpccli_reg_enum_key call */
708 fstring val_name_buf;
709 REGVAL_BUFFER val_buf;
710
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;
717
718 if ( !hnd )
719 return CAC_FAILURE;
720
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;
725
726 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
727 hnd->status = NT_STATUS_INVALID_HANDLE;
728 return CAC_FAILURE;
729 }
730
731 if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
732 hnd->status = NT_STATUS_INVALID_PARAMETER;
733 return CAC_FAILURE;
734 }
735
736 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
737 if ( !pipe_hnd ) {
738 hnd->status = NT_STATUS_INVALID_HANDLE;
739 return CAC_FAILURE;
740 }
741
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;
749 }
750
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;
757 }
758
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;
765 }
766 } else {
767 types_out = NULL;
768 values_out = NULL;
769 val_names_out = NULL;
770 }
771
772 resume_idx = op->out.resume_idx;
773 do {
774 ZERO_STRUCT( val_buf );
775
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 );
781
782 if ( !NT_STATUS_IS_OK( hnd->status ) )
783 break;
784
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 );
791
792 if ( !val_names_out[num_values_out]
793 || !values_out[num_values_out] ) {
794 hnd->status = NT_STATUS_NO_MEMORY;
795 break;
796 }
797
798 num_values_out++;
799 resume_idx++;
800 } while ( num_values_out < op->in.max_values );
801
802 if ( CAC_OP_FAILED( hnd->status ) )
803 return CAC_FAILURE;
804
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;
810
811 return CAC_SUCCESS;
812}
813
814int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
815 struct RegSetValue *op )
816{
817 struct rpc_pipe_client *pipe_hnd = NULL;
818 WERROR err;
819
820 RPC_DATA_BLOB *buffer;
821
822 if ( !hnd )
823 return CAC_FAILURE;
824
825 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
826 hnd->status = NT_STATUS_INVALID_HANDLE;
827 return CAC_FAILURE;
828 }
829
830 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
831 hnd->status = NT_STATUS_INVALID_PARAMETER;
832 return CAC_FAILURE;
833 }
834
835 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
836 if ( !pipe_hnd ) {
837 hnd->status = NT_STATUS_INVALID_HANDLE;
838 return CAC_FAILURE;
839 }
840
841 buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
842
843 if ( !buffer ) {
844 if ( errno == ENOMEM )
845 hnd->status = NT_STATUS_NO_MEMORY;
846 else
847 hnd->status = NT_STATUS_INVALID_PARAMETER;
848
849 return CAC_FAILURE;
850 }
851
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 );
855
856 if ( !NT_STATUS_IS_OK( hnd->status ) )
857 return CAC_FAILURE;
858
859 /*flush */
860 err = rpccli_reg_flush_key( pipe_hnd, mem_ctx, op->in.key );
861 hnd->status = werror_to_ntstatus( err );
862
863 if ( !NT_STATUS_IS_OK( hnd->status ) )
864 return CAC_FAILURE;
865
866 return CAC_SUCCESS;
867}
868
869
870
871int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
872 struct RegGetVersion *op )
873{
874 struct rpc_pipe_client *pipe_hnd = NULL;
875 WERROR err;
876
877 uint32 version_out;
878
879 if ( !hnd )
880 return CAC_FAILURE;
881
882 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
883 hnd->status = NT_STATUS_INVALID_HANDLE;
884 return CAC_FAILURE;
885 }
886
887 if ( !op || !op->in.key || !mem_ctx ) {
888 hnd->status = NT_STATUS_INVALID_PARAMETER;
889 return CAC_FAILURE;
890 }
891
892 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
893 if ( !pipe_hnd ) {
894 hnd->status = NT_STATUS_INVALID_HANDLE;
895 return CAC_FAILURE;
896 }
897
898 err = rpccli_reg_getversion( pipe_hnd, mem_ctx, op->in.key,
899 &version_out );
900 hnd->status = werror_to_ntstatus( err );
901
902 if ( !NT_STATUS_IS_OK( hnd->status ) )
903 return CAC_FAILURE;
904
905 op->out.version = version_out;
906
907 return CAC_SUCCESS;
908}
909
910int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
911 struct RegGetKeySecurity *op )
912{
913 struct rpc_pipe_client *pipe_hnd = NULL;
914 WERROR err;
915
916 uint32 buf_size;
917 SEC_DESC_BUF buf;
918
919 ZERO_STRUCT( buf );
920
921 if ( !hnd )
922 return CAC_FAILURE;
923
924 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
925 hnd->status = NT_STATUS_INVALID_HANDLE;
926 return CAC_FAILURE;
927 }
928
929 if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
930 hnd->status = NT_STATUS_INVALID_PARAMETER;
931 return CAC_FAILURE;
932 }
933
934 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
935 if ( !pipe_hnd ) {
936 hnd->status = NT_STATUS_INVALID_HANDLE;
937 return CAC_FAILURE;
938 }
939
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 );
943
944
945 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
946 return CAC_FAILURE;
947 }
948
949 op->out.size = buf.len;
950 op->out.descriptor = dup_sec_desc( mem_ctx, buf.sec );
951
952 if ( op->out.descriptor == NULL ) {
953 return CAC_FAILURE;
954 }
955
956 return CAC_SUCCESS;
957}
958
959int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
960 struct RegSetKeySecurity *op )
961{
962 struct rpc_pipe_client *pipe_hnd = NULL;
963 WERROR err;
964
965 if ( !hnd )
966 return CAC_FAILURE;
967
968 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
969 hnd->status = NT_STATUS_INVALID_HANDLE;
970 return CAC_FAILURE;
971 }
972
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;
977 }
978
979 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
980 if ( !pipe_hnd ) {
981 hnd->status = NT_STATUS_INVALID_HANDLE;
982 return CAC_FAILURE;
983 }
984
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 );
989
990
991 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
992 return CAC_FAILURE;
993 }
994
995 return CAC_SUCCESS;
996}
997
998int cac_RegSaveKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
999 struct RegSaveKey *op )
1000{
1001 struct rpc_pipe_client *pipe_hnd = NULL;
1002 WERROR err;
1003
1004 if ( !hnd )
1005 return CAC_FAILURE;
1006
1007 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1008 hnd->status = NT_STATUS_INVALID_HANDLE;
1009 return CAC_FAILURE;
1010 }
1011
1012 if ( !op || !op->in.key || !op->in.filename || !mem_ctx ) {
1013 hnd->status = NT_STATUS_INVALID_PARAMETER;
1014 return CAC_FAILURE;
1015 }
1016
1017 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1018 if ( !pipe_hnd ) {
1019 hnd->status = NT_STATUS_INVALID_HANDLE;
1020 return CAC_FAILURE;
1021 }
1022
1023 err = rpccli_reg_save_key( pipe_hnd, mem_ctx, op->in.key,
1024 op->in.filename );
1025 hnd->status = werror_to_ntstatus( err );
1026
1027
1028 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1029 return CAC_FAILURE;
1030 }
1031
1032 return CAC_SUCCESS;
1033}
1034
1035int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1036 struct Shutdown *op )
1037{
1038 SMBCSRV *srv = NULL;
1039 struct rpc_pipe_client *pipe_hnd = NULL;
1040
1041 char *msg;
1042
1043 if ( !hnd )
1044 return CAC_FAILURE;
1045
1046 if ( !hnd->_internal.ctx ) {
1047 hnd->status = NT_STATUS_INVALID_HANDLE;
1048 return CAC_FAILURE;
1049 }
1050
1051 if ( !op || !mem_ctx ) {
1052 hnd->status = NT_STATUS_INVALID_PARAMETER;
1053 return CAC_FAILURE;
1054 }
1055
1056 srv = cac_GetServer( hnd );
1057 if ( !srv ) {
1058 hnd->status = NT_STATUS_INVALID_HANDLE;
1059 return CAC_FAILURE;
1060 }
1061
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;
1069 }
1070
1071 hnd->_internal.pipes[PI_SHUTDOWN] = True;
1072 }
1073
1074 pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
1075 if ( !pipe_hnd ) {
1076 hnd->status = NT_STATUS_INVALID_HANDLE;
1077 return CAC_FAILURE;
1078 }
1079
1080 msg = ( op->in.message !=
1081 NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
1082
1083 hnd->status = NT_STATUS_OK;
1084
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 );
1091 }
1092
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 );
1099
1100 hnd->_internal.srv_level = SRV_WIN_NT4;
1101 }
1102
1103 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1104 return CAC_FAILURE;
1105 }
1106
1107 return CAC_SUCCESS;
1108}
1109
1110int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
1111{
1112 struct rpc_pipe_client *pipe_hnd = NULL;
1113
1114 if ( !hnd )
1115 return CAC_FAILURE;
1116
1117 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN] ) {
1118 hnd->status = NT_STATUS_INVALID_HANDLE;
1119 return CAC_FAILURE;
1120 }
1121
1122 pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
1123 if ( !pipe_hnd ) {
1124 hnd->status = NT_STATUS_INVALID_HANDLE;
1125 return CAC_FAILURE;
1126 }
1127
1128 hnd->status = rpccli_shutdown_abort( pipe_hnd, mem_ctx );
1129
1130 if ( !NT_STATUS_IS_OK( hnd->status ) )
1131 return CAC_FAILURE;
1132
1133 return CAC_SUCCESS;
1134}
Note: See TracBrowser for help on using the repository browser.