r14146: Just some typos.
[samba.git] / source3 / utils / net_rpc_registry.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) Gerald (Jerry) Carter          2005
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20 #include "includes.h"
21 #include "utils/net.h"
22 #include "regfio.h"
23 #include "reg_objects.h"
24
25 /********************************************************************
26 ********************************************************************/
27
28 char* dump_regval_type( uint32 type )
29 {
30         static fstring string;
31         
32         switch (type) {
33         case REG_SZ:
34                 fstrcpy( string, "REG_SZ" );
35                 break;
36         case REG_MULTI_SZ:
37                 fstrcpy( string, "REG_MULTI_SZ" );
38                 break;
39         case REG_EXPAND_SZ:
40                 fstrcpy( string, "REG_EXPAND_SZ" );
41                 break;
42         case REG_DWORD:
43                 fstrcpy( string, "REG_DWORD" );
44                 break;
45         case REG_BINARY:
46                 fstrcpy( string, "REG_BINARY" );
47                 break;
48         default:
49                 fstr_sprintf( string, "UNKNOWN [%d]", type );
50         }
51         
52         return string;
53 }
54 /********************************************************************
55 ********************************************************************/
56
57 void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
58 {
59         pstring string;
60         uint32 value;
61         
62         switch (type) {
63         case REG_SZ:
64                 rpcstr_pull( string, buffer->buffer, sizeof(string), -1, STR_TERMINATE );
65                 d_printf("%s\n", string);
66                 break;
67         case REG_MULTI_SZ:
68                 d_printf("\n");
69                 break;
70         case REG_DWORD:
71                 value = IVAL( buffer->buffer, 0 );
72                 d_printf( "0x%x\n", value );
73                 break;
74         case REG_BINARY:
75                 d_printf("\n");
76                 break;
77         
78         
79         default:
80                 d_printf( "\tUnknown type [%d]\n", type );
81         }
82 }
83
84 /********************************************************************
85 ********************************************************************/
86
87 static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
88                                                 const char *domain_name, 
89                                                 struct cli_state *cli,
90                                                 struct rpc_pipe_client *pipe_hnd,
91                                                 TALLOC_CTX *mem_ctx, 
92                                                 int argc,
93                                                 const char **argv )
94 {
95         WERROR result = WERR_GENERAL_FAILURE;
96         uint32 hive;
97         pstring subpath;
98         POLICY_HND pol_hive, pol_key; 
99         uint32 idx;
100         
101         if (argc != 1 ) {
102                 d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
103                 d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
104                 return NT_STATUS_OK;
105         }
106         
107         if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
108                 d_fprintf(stderr, "invalid registry path\n");
109                 return NT_STATUS_OK;
110         }
111         
112         /* open the top level hive and then the registry key */
113         
114         result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
115         if ( !W_ERROR_IS_OK(result) ) {
116                 d_fprintf(stderr, "Unable to connect to remote registry\n");
117                 return werror_to_ntstatus(result);
118         }
119         
120         if ( strlen( subpath ) != 0 ) {
121                 result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
122                 if ( !W_ERROR_IS_OK(result) ) {
123                         d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
124                         return werror_to_ntstatus(result);
125                 }
126         }
127         
128         /* get the subkeys */
129         
130         result = WERR_OK;
131         idx = 0;
132         while ( W_ERROR_IS_OK(result) ) {
133                 time_t modtime;
134                 fstring keyname, classname;
135                 
136                 result = rpccli_reg_enum_key(pipe_hnd, mem_ctx, &pol_key, idx, 
137                         keyname, classname, &modtime );
138                         
139                 if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
140                         result = WERR_OK;
141                         break;
142                 }
143                         
144                 d_printf("Keyname   = %s\n", keyname );
145                 d_printf("Classname = %s\n", classname );
146                 d_printf("Modtime   = %s\n", http_timestring(modtime) );
147                 d_printf("\n" );
148
149                 idx++;
150         }
151
152         if ( !W_ERROR_IS_OK(result) )
153                 goto out;
154         
155         /* get the values */
156         
157         result = WERR_OK;
158         idx = 0;
159         while ( W_ERROR_IS_OK(result) ) {
160                 uint32 type;
161                 fstring name;
162                 REGVAL_BUFFER value;
163                 
164                 fstrcpy( name, "" );
165                 ZERO_STRUCT( value );
166                 
167                 result = rpccli_reg_enum_val(pipe_hnd, mem_ctx, &pol_key, idx, 
168                         name, &type, &value );
169                         
170                 if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
171                         result = WERR_OK;
172                         break;
173                 }
174                         
175                 d_printf("Valuename  = %s\n", name );
176                 d_printf("Type       = %s\n", dump_regval_type(type) );
177                 d_printf("Data       = " );
178                 dump_regval_buffer( type, &value );
179                 d_printf("\n" );
180
181                 idx++;
182         }
183         
184         
185 out:
186         /* cleanup */
187         
188         if ( strlen( subpath ) != 0 )
189                 rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
190         rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
191
192         return werror_to_ntstatus(result);
193 }
194
195 /********************************************************************
196 ********************************************************************/
197
198 static int rpc_registry_enumerate( int argc, const char **argv )
199 {
200         return run_rpc_command( NULL, PI_WINREG, 0, 
201                 rpc_registry_enumerate_internal, argc, argv );
202 }
203
204 /********************************************************************
205 ********************************************************************/
206
207 static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
208                                         const char *domain_name, 
209                                         struct cli_state *cli,
210                                         struct rpc_pipe_client *pipe_hnd,
211                                         TALLOC_CTX *mem_ctx, 
212                                         int argc,
213                                         const char **argv )
214 {
215         WERROR result = WERR_GENERAL_FAILURE;
216         uint32 hive;
217         pstring subpath;
218         POLICY_HND pol_hive, pol_key; 
219         
220         if (argc != 2 ) {
221                 d_printf("Usage:    net rpc backup <path> <file> \n");
222                 return NT_STATUS_OK;
223         }
224         
225         if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
226                 d_fprintf(stderr, "invalid registry path\n");
227                 return NT_STATUS_OK;
228         }
229         
230         /* open the top level hive and then the registry key */
231         
232         result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
233         if ( !W_ERROR_IS_OK(result) ) {
234                 d_fprintf(stderr, "Unable to connect to remote registry\n");
235                 return werror_to_ntstatus(result);
236         }
237         
238         result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
239         if ( !W_ERROR_IS_OK(result) ) {
240                 d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
241                 return werror_to_ntstatus(result);
242         }
243         
244         result = rpccli_reg_save_key(pipe_hnd, mem_ctx, &pol_key, argv[1] );
245         if ( !W_ERROR_IS_OK(result) ) {
246                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
247         }
248         
249         
250         /* cleanup */
251         
252         rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
253         rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
254
255         return werror_to_ntstatus(result);
256 }
257
258 /********************************************************************
259 ********************************************************************/
260
261 static int rpc_registry_save( int argc, const char **argv )
262 {
263         return run_rpc_command( NULL, PI_WINREG, 0, 
264                 rpc_registry_save_internal, argc, argv );
265 }
266
267
268 /********************************************************************
269 ********************************************************************/
270
271 static void dump_values( REGF_NK_REC *nk )
272 {
273         int i, j;
274         pstring data_str;
275         uint32 data_size, data;
276
277         if ( !nk->values )
278                 return;
279
280         for ( i=0; i<nk->num_values; i++ ) {
281                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
282                 d_printf( "(%s) ", dump_regval_type( nk->values[i].type ) );
283
284                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
285                 switch ( nk->values[i].type ) {
286                         case REG_SZ:
287                                 rpcstr_pull( data_str, nk->values[i].data, sizeof(data_str), -1, STR_TERMINATE );
288                                 d_printf( "%s", data_str );
289                                 break;
290                         case REG_MULTI_SZ:
291                         case REG_EXPAND_SZ:
292                                 for ( j=0; j<data_size; j++ ) {
293                                         d_printf( "%c", nk->values[i].data[j] );
294                                 }
295                                 break;
296                         case REG_DWORD:
297                                 data = IVAL( nk->values[i].data, 0 );
298                                 d_printf("0x%x", data );
299                                 break;
300                         case REG_BINARY:
301                                 for ( j=0; j<data_size; j++ ) {
302                                         d_printf( "%x", nk->values[i].data[j] );
303                                 }
304                                 break;
305                         default:
306                                 d_printf("unknown");
307                                 break;
308                 }
309
310                 d_printf( "\n" );
311         }
312
313 }
314
315 /********************************************************************
316 ********************************************************************/
317
318 static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
319 {
320         REGF_NK_REC *key;
321         pstring regpath;
322
323         /* depth first dump of the registry tree */
324
325         while ( (key = regfio_fetch_subkey( file, nk )) ) {
326                 pstr_sprintf( regpath, "%s\\%s", parent, key->keyname );
327                 d_printf("[%s]\n", regpath );
328                 dump_values( key );
329                 d_printf("\n");
330                 dump_registry_tree( file, key, regpath );
331         }
332
333         return True;
334 }
335
336 /********************************************************************
337 ********************************************************************/
338
339 static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
340                                  REGF_NK_REC *parent, REGF_FILE *outfile,
341                                  const char *parentpath )
342 {
343         REGF_NK_REC *key, *subkey;
344         REGVAL_CTR *values;
345         REGSUBKEY_CTR *subkeys;
346         int i;
347         pstring path;
348
349         if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
350                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
351                 return False;
352         }
353
354         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) ) {
355                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
356                 return False;
357         }
358
359         /* copy values into the REGVAL_CTR */
360         
361         for ( i=0; i<nk->num_values; i++ ) {
362                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
363                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
364         }
365
366         /* copy subkeys into the REGSUBKEY_CTR */
367         
368         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
369                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
370         }
371         
372         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
373
374         /* write each one of the subkeys out */
375
376         pstr_sprintf( path, "%s%s%s", parentpath, parent ? "\\" : "", nk->keyname );
377         nk->subkey_index = 0;
378         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
379                 write_registry_tree( infile, subkey, key, outfile, path );
380         }
381
382         TALLOC_FREE( subkeys );
383
384         d_printf("[%s]\n", path );
385         
386         return True;
387 }
388
389 /********************************************************************
390 ********************************************************************/
391
392 static int rpc_registry_dump( int argc, const char **argv )
393 {
394         REGF_FILE   *registry;
395         REGF_NK_REC *nk;
396         
397         if (argc != 1 ) {
398                 d_printf("Usage:    net rpc dump <file> \n");
399                 return 0;
400         }
401         
402         d_printf("Opening %s....", argv[0]);
403         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
404                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
405                 return 1;
406         }
407         d_printf("ok\n");
408         
409         /* get the root of the registry file */
410         
411         nk = regfio_rootkey( registry );
412         d_printf("[%s]\n", nk->keyname);
413         dump_values( nk );
414         d_printf("\n");
415
416         dump_registry_tree( registry, nk, nk->keyname );
417
418 #if 0
419         talloc_report_full( registry->mem_ctx, stderr );
420 #endif  
421         d_printf("Closing registry...");
422         regfio_close( registry );
423         d_printf("ok\n");
424
425         return 0;
426 }
427
428 /********************************************************************
429 ********************************************************************/
430
431 static int rpc_registry_copy( int argc, const char **argv )
432 {
433         REGF_FILE   *infile, *outfile;
434         REGF_NK_REC *nk;
435         int result = 1;
436         
437         if (argc != 2 ) {
438                 d_printf("Usage:    net rpc copy <srcfile> <newfile>\n");
439                 return 0;
440         }
441         
442         d_printf("Opening %s....", argv[0]);
443         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
444                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
445                 return 1;
446         }
447         d_printf("ok\n");
448
449         d_printf("Opening %s....", argv[1]);
450         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
451                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
452                 goto out_close_infile;
453         }
454         d_printf("ok\n");
455         
456         /* get the root of the registry file */
457         
458         nk = regfio_rootkey( infile );
459         d_printf("RootKey: [%s]\n", nk->keyname);
460
461         write_registry_tree( infile, nk, NULL, outfile, "" );
462
463         result = 0;
464
465         d_printf("Closing %s...", argv[1]);
466         regfio_close( outfile );
467         d_printf("ok\n");
468
469 out_close_infile:
470         d_printf("Closing %s...", argv[0]);
471         regfio_close( infile );
472         d_printf("ok\n");
473
474         return( result);
475 }
476
477 /********************************************************************
478 ********************************************************************/
479
480 static int net_help_registry( int argc, const char **argv )
481 {
482         d_printf("net rpc registry enumerate <path> [recurse]  Enumerate the subkeya and values for a given registry path\n");
483         d_printf("net rpc registry save <path> <file>          Backup a registry tree to a file on the server\n");
484         d_printf("net rpc registry dump <file>                 Dump the contents of a registry file to stdout\n");
485         
486         return -1;
487 }
488
489 /********************************************************************
490 ********************************************************************/
491
492 int net_rpc_registry(int argc, const char **argv) 
493 {
494         struct functable func[] = {
495                 {"enumerate", rpc_registry_enumerate},
496                 {"save",      rpc_registry_save},
497                 {"dump",      rpc_registry_dump},
498                 {"copy",      rpc_registry_copy},
499                 {NULL, NULL}
500         };
501         
502         if ( argc )
503                 return net_run_function( argc, argv, func, net_help_registry );
504                 
505         return net_help_registry( argc, argv );
506 }