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