r19790: Check in the PIDL change and the converted unixinfo and winbind pipes without
[tprouty/samba.git] / source3 / utils / net_rpc_registry.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4
5    Copyright (C) Gerald (Jerry) Carter          2005-2006
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 #include "includes.h"
22 #include "utils/net.h"
23 #include "regfio.h"
24 #include "reg_objects.h"
25
26 /********************************************************************
27 ********************************************************************/
28
29 void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
30 {
31         pstring string;
32         uint32 value;
33         
34         switch (type) {
35         case REG_SZ:
36                 rpcstr_pull( string, buffer->buffer, sizeof(string), -1, STR_TERMINATE );
37                 d_printf("%s\n", string);
38                 break;
39         case REG_MULTI_SZ: {
40                 int i, num_values;
41                 char **values;
42
43                 d_printf("\n");
44
45                 if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, buffer->buffer,
46                                                        buffer->buf_len,
47                                                        &num_values,
48                                                        &values))) {
49                         d_printf("reg_pull_multi_sz failed\n");
50                         break;
51                 }
52
53                 for (i=0; i<num_values; i++) {
54                         d_printf("%s\n", values[i]);
55                 }
56                 TALLOC_FREE(values);
57                 break;
58         }
59         case REG_DWORD:
60                 value = IVAL( buffer->buffer, 0 );
61                 d_printf( "0x%x\n", value );
62                 break;
63         case REG_BINARY:
64                 d_printf("\n");
65                 break;
66         
67         
68         default:
69                 d_printf( "\tUnknown type [%d]\n", type );
70         }
71 }
72
73 /********************************************************************
74 ********************************************************************/
75
76 static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
77                                                 const char *domain_name, 
78                                                 struct cli_state *cli,
79                                                 struct rpc_pipe_client *pipe_hnd,
80                                                 TALLOC_CTX *mem_ctx, 
81                                                 int argc,
82                                                 const char **argv )
83 {
84         WERROR result = WERR_GENERAL_FAILURE;
85         uint32 hive;
86         pstring subpath;
87         POLICY_HND pol_hive, pol_key; 
88         uint32 idx;
89         NTSTATUS status;
90         struct winreg_String subkeyname;
91         struct winreg_String classname;
92         uint32 num_subkeys, max_subkeylen, max_classlen;
93         uint32 num_values, max_valnamelen, max_valbufsize;
94         uint32 secdescsize;
95         NTTIME last_changed_time;
96         struct winreg_StringBuf subkey_namebuf;
97         char *name_buffer; 
98         uint8 *value_buffer;
99         
100         if (argc != 1 ) {
101                 d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
102                 d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
103                 return NT_STATUS_OK;
104         }
105         
106         if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
107                 d_fprintf(stderr, "invalid registry path\n");
108                 return NT_STATUS_OK;
109         }
110         
111         /* open the top level hive and then the registry key */
112         
113         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
114         if ( !NT_STATUS_IS_OK(status) ) {
115                 d_fprintf(stderr, "Unable to connect to remote registry: "
116                           "%s\n", nt_errstr(status));
117                 return status;
118         }
119         
120         subkeyname.name = subpath;
121         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, &pol_hive, subkeyname,
122                                        0, MAXIMUM_ALLOWED_ACCESS, &pol_key );
123         if ( !NT_STATUS_IS_OK(status) ) {
124                 d_fprintf(stderr, "Unable to open [%s]: %s\n", argv[0],
125                           nt_errstr(status));
126                 return werror_to_ntstatus(result);
127         }
128
129         classname.name = NULL;
130         status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, &pol_key, 
131                         &classname, &num_subkeys, &max_subkeylen,
132                         &max_classlen, &num_values, &max_valnamelen,
133                         &max_valbufsize, &secdescsize, &last_changed_time );
134
135         if ( !NT_STATUS_IS_OK(status) ) {
136                 d_fprintf(stderr, "Unable to determine subkeys (%s)\n", 
137                         nt_errstr(status));
138                 return status;
139         }
140
141         /* values do not include the terminating NULL */
142
143         max_subkeylen += 2;
144         max_valnamelen += 2;
145
146         if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) {
147                 d_fprintf(stderr, "Memory allocation error.\n");
148                 return NT_STATUS_NO_MEMORY;
149         }
150
151         /* get the subkeys */
152         
153         status = NT_STATUS_OK;
154         idx = 0;
155         while ( NT_STATUS_IS_OK(status) ) {
156                 struct winreg_StringBuf class_namebuf;
157                 struct winreg_StringBuf *p_class_namebuf = &class_namebuf;
158                 fstring kname;
159                 NTTIME modtime;
160                 NTTIME *p_modtime = &modtime;
161
162                 class_namebuf.name = NULL;
163                 class_namebuf.size = 0;
164                 class_namebuf.length = 0;
165
166                 /* zero out each time */
167
168                 subkey_namebuf.length = 0;
169                 subkey_namebuf.size = max_subkeylen;
170                 memset( name_buffer, 0x0, max_subkeylen );
171                 subkey_namebuf.name = name_buffer;
172
173                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, &pol_key,
174                                                idx, &subkey_namebuf,
175                                                &p_class_namebuf, &p_modtime);
176                         
177                 if ( W_ERROR_EQUAL(ntstatus_to_werror(status), WERR_NO_MORE_ITEMS) ) {
178                         status = NT_STATUS_OK;
179                         break;
180                 }
181
182                 if ( !NT_STATUS_IS_OK(status) )
183                         goto out;
184                 
185                 StrnCpy( kname, subkey_namebuf.name, MIN(subkey_namebuf.length,sizeof(kname))-1 );
186                 kname[MIN(subkey_namebuf.length,sizeof(kname))-1] = '\0';
187                 d_printf("Keyname   = %s\n", kname);
188                 d_printf("Modtime   = %s\n", 
189                         http_timestring(nt_time_to_unix(modtime)) );
190                 d_printf("\n" );
191
192                 idx++;
193         }
194
195         if ( !NT_STATUS_IS_OK(status) )
196                 goto out;
197
198         /* TALLOC_FREE( name_buffer ); */
199
200         if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_valnamelen )) == NULL ) {
201                 d_fprintf(stderr, "Memory allocation error.\n");
202                 return NT_STATUS_NO_MEMORY;
203         }
204
205         if ( (value_buffer = TALLOC_ARRAY( mem_ctx, uint8, max_valbufsize )) == NULL ) {
206                 d_fprintf(stderr, "Memory allocation error.\n");
207                 return NT_STATUS_NO_MEMORY;
208         }
209
210         /* get the values */
211         
212         status = NT_STATUS_OK;
213         idx = 0;
214         while ( NT_STATUS_IS_OK(status) ) {
215                 enum winreg_Type type = REG_NONE;
216                 enum winreg_Type *ptype = &type;
217                 fstring name;
218                 uint8 *data;
219                 uint32 data_size, value_length;
220                 uint32 *pdata_size = &data_size;
221                 uint32 *pvalue_length = &value_length;
222                 struct winreg_StringBuf value_namebuf;
223                 REGVAL_BUFFER value;
224                 
225                 fstrcpy( name, "" );
226                 ZERO_STRUCT( value );
227
228                 memset( name_buffer, 0x0, max_valnamelen );
229                 value_namebuf.name = name_buffer;
230                 value_namebuf.length = 0;
231                 value_namebuf.size = max_valnamelen;
232
233                 memset( value_buffer, 0x0, max_valbufsize );
234                 data = value_buffer;
235                 data_size = max_valbufsize;
236                 value_length = 0;
237
238                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, &pol_key,
239                                                  idx, &value_namebuf, &ptype,
240                                                  &data, &pdata_size,
241                                                  &pvalue_length );
242                         
243                 if ( W_ERROR_EQUAL(ntstatus_to_werror(status), WERR_NO_MORE_ITEMS) ) {
244                         status = NT_STATUS_OK;
245                         break;
246                 }
247
248                 if ( !NT_STATUS_IS_OK(status) )
249                         goto out;
250
251                 init_regval_buffer( &value, data, value_length );
252                         
253                 StrnCpy( name, value_namebuf.name, MIN(max_valnamelen, sizeof(name)-1) );
254                 name[MIN(max_valnamelen, sizeof(name)-1)] = '\0';
255
256                 d_printf("Valuename  = %s\n", name );
257                 d_printf("Type       = %s\n", reg_type_lookup(type));
258                 d_printf("Data       = " );
259                 dump_regval_buffer( type, &value );
260                 d_printf("\n" );
261
262                 idx++;
263         }
264         
265 out:
266         /* cleanup */
267         
268         if ( strlen( subpath ) != 0 )
269                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
270         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
271
272         return status;
273 }
274
275 /********************************************************************
276 ********************************************************************/
277
278 static int rpc_registry_enumerate( int argc, const char **argv )
279 {
280         return run_rpc_command( NULL, PI_WINREG, 0, 
281                 rpc_registry_enumerate_internal, argc, argv );
282 }
283
284 /********************************************************************
285 ********************************************************************/
286
287 static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
288                                         const char *domain_name, 
289                                         struct cli_state *cli,
290                                         struct rpc_pipe_client *pipe_hnd,
291                                         TALLOC_CTX *mem_ctx, 
292                                         int argc,
293                                         const char **argv )
294 {
295         WERROR result = WERR_GENERAL_FAILURE;
296         uint32 hive;
297         pstring subpath;
298         POLICY_HND pol_hive, pol_key; 
299         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
300         struct winreg_String subkeyname;
301         struct winreg_String filename;
302         
303         if (argc != 2 ) {
304                 d_printf("Usage:    net rpc backup <path> <file> \n");
305                 return NT_STATUS_OK;
306         }
307         
308         if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
309                 d_fprintf(stderr, "invalid registry path\n");
310                 return NT_STATUS_OK;
311         }
312         
313         /* open the top level hive and then the registry key */
314         
315         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
316         if ( !NT_STATUS_IS_OK(status) ) {
317                 d_fprintf(stderr, "Unable to connect to remote registry\n");
318                 return status;
319         }
320         
321         subkeyname.name = subpath;
322         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, &pol_hive, subkeyname,
323                         0, MAXIMUM_ALLOWED_ACCESS, &pol_key );
324         if ( !NT_STATUS_IS_OK(status) ) {
325                 d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
326                 return werror_to_ntstatus(result);
327         }
328         
329         filename.name = argv[1];
330         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL  );
331         if ( !W_ERROR_IS_OK(result) ) {
332                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
333         }
334         
335         /* cleanup */
336         
337         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
338         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
339
340         return status;
341 }
342
343 /********************************************************************
344 ********************************************************************/
345
346 static int rpc_registry_save( int argc, const char **argv )
347 {
348         return run_rpc_command( NULL, PI_WINREG, 0, 
349                 rpc_registry_save_internal, argc, argv );
350 }
351
352
353 /********************************************************************
354 ********************************************************************/
355
356 static void dump_values( REGF_NK_REC *nk )
357 {
358         int i, j;
359         pstring data_str;
360         uint32 data_size, data;
361
362         if ( !nk->values )
363                 return;
364
365         for ( i=0; i<nk->num_values; i++ ) {
366                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
367                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
368
369                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
370                 switch ( nk->values[i].type ) {
371                         case REG_SZ:
372                                 rpcstr_pull( data_str, nk->values[i].data, sizeof(data_str), -1, STR_TERMINATE );
373                                 d_printf( "%s", data_str );
374                                 break;
375                         case REG_MULTI_SZ:
376                         case REG_EXPAND_SZ:
377                                 for ( j=0; j<data_size; j++ ) {
378                                         d_printf( "%c", nk->values[i].data[j] );
379                                 }
380                                 break;
381                         case REG_DWORD:
382                                 data = IVAL( nk->values[i].data, 0 );
383                                 d_printf("0x%x", data );
384                                 break;
385                         case REG_BINARY:
386                                 for ( j=0; j<data_size; j++ ) {
387                                         d_printf( "%x", nk->values[i].data[j] );
388                                 }
389                                 break;
390                         default:
391                                 d_printf("unknown");
392                                 break;
393                 }
394
395                 d_printf( "\n" );
396         }
397
398 }
399
400 /********************************************************************
401 ********************************************************************/
402
403 static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
404 {
405         REGF_NK_REC *key;
406         pstring regpath;
407
408         /* depth first dump of the registry tree */
409
410         while ( (key = regfio_fetch_subkey( file, nk )) ) {
411                 pstr_sprintf( regpath, "%s\\%s", parent, key->keyname );
412                 d_printf("[%s]\n", regpath );
413                 dump_values( key );
414                 d_printf("\n");
415                 dump_registry_tree( file, key, regpath );
416         }
417
418         return True;
419 }
420
421 /********************************************************************
422 ********************************************************************/
423
424 static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
425                                  REGF_NK_REC *parent, REGF_FILE *outfile,
426                                  const char *parentpath )
427 {
428         REGF_NK_REC *key, *subkey;
429         REGVAL_CTR *values;
430         REGSUBKEY_CTR *subkeys;
431         int i;
432         pstring path;
433
434         if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
435                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
436                 return False;
437         }
438
439         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) ) {
440                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
441                 return False;
442         }
443
444         /* copy values into the REGVAL_CTR */
445         
446         for ( i=0; i<nk->num_values; i++ ) {
447                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
448                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
449         }
450
451         /* copy subkeys into the REGSUBKEY_CTR */
452         
453         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
454                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
455         }
456         
457         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
458
459         /* write each one of the subkeys out */
460
461         pstr_sprintf( path, "%s%s%s", parentpath, parent ? "\\" : "", nk->keyname );
462         nk->subkey_index = 0;
463         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
464                 write_registry_tree( infile, subkey, key, outfile, path );
465         }
466
467         TALLOC_FREE( subkeys );
468
469         d_printf("[%s]\n", path );
470         
471         return True;
472 }
473
474 /********************************************************************
475 ********************************************************************/
476
477 static int rpc_registry_dump( int argc, const char **argv )
478 {
479         REGF_FILE   *registry;
480         REGF_NK_REC *nk;
481         
482         if (argc != 1 ) {
483                 d_printf("Usage:    net rpc dump <file> \n");
484                 return 0;
485         }
486         
487         d_printf("Opening %s....", argv[0]);
488         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
489                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
490                 return 1;
491         }
492         d_printf("ok\n");
493         
494         /* get the root of the registry file */
495         
496         if ((nk = regfio_rootkey( registry )) == NULL) {
497                 d_fprintf(stderr, "Could not get rootkey\n");
498                 regfio_close( registry );
499                 return 1;
500         }
501         d_printf("[%s]\n", nk->keyname);
502         dump_values( nk );
503         d_printf("\n");
504
505         dump_registry_tree( registry, nk, nk->keyname );
506
507 #if 0
508         talloc_report_full( registry->mem_ctx, stderr );
509 #endif  
510         d_printf("Closing registry...");
511         regfio_close( registry );
512         d_printf("ok\n");
513
514         return 0;
515 }
516
517 /********************************************************************
518 ********************************************************************/
519
520 static int rpc_registry_copy( int argc, const char **argv )
521 {
522         REGF_FILE   *infile = NULL, *outfile = NULL;
523         REGF_NK_REC *nk;
524         int result = 1;
525         
526         if (argc != 2 ) {
527                 d_printf("Usage:    net rpc copy <srcfile> <newfile>\n");
528                 return 0;
529         }
530         
531         d_printf("Opening %s....", argv[0]);
532         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
533                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
534                 return 1;
535         }
536         d_printf("ok\n");
537
538         d_printf("Opening %s....", argv[1]);
539         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
540                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
541                 goto out;
542         }
543         d_printf("ok\n");
544         
545         /* get the root of the registry file */
546         
547         if ((nk = regfio_rootkey( infile )) == NULL) {
548                 d_fprintf(stderr, "Could not get rootkey\n");
549                 goto out;
550         }
551         d_printf("RootKey: [%s]\n", nk->keyname);
552
553         write_registry_tree( infile, nk, NULL, outfile, "" );
554
555         result = 0;
556
557 out:
558
559         d_printf("Closing %s...", argv[1]);
560         if (outfile) {
561                 regfio_close( outfile );
562         }
563         d_printf("ok\n");
564
565         d_printf("Closing %s...", argv[0]);
566         if (infile) {
567                 regfio_close( infile );
568         }
569         d_printf("ok\n");
570
571         return( result);
572 }
573
574 /********************************************************************
575 ********************************************************************/
576
577 static int net_help_registry( int argc, const char **argv )
578 {
579         d_printf("net rpc registry enumerate <path> [recurse]  Enumerate the subkeya and values for a given registry path\n");
580         d_printf("net rpc registry save <path> <file>          Backup a registry tree to a file on the server\n");
581         d_printf("net rpc registry dump <file>                 Dump the contents of a registry file to stdout\n");
582         
583         return -1;
584 }
585
586 /********************************************************************
587 ********************************************************************/
588
589 int net_rpc_registry(int argc, const char **argv) 
590 {
591         struct functable func[] = {
592                 {"enumerate", rpc_registry_enumerate},
593                 {"save",      rpc_registry_save},
594                 {"dump",      rpc_registry_dump},
595                 {"copy",      rpc_registry_copy},
596                 {NULL, NULL}
597         };
598         
599         if ( argc )
600                 return net_run_function( argc, argv, func, net_help_registry );
601                 
602         return net_help_registry( argc, argv );
603 }