source: branches/samba-3.0/source/rpc_server/srv_reg_nt.c@ 403

Last change on this file since 403 was 1, checked in by Paul Smedley, 19 years ago

Initial code import

File size: 37.1 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997.
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
6 * Copyright (C) Paul Ashton 1997.
7 * Copyright (C) Jeremy Allison 2001.
8 * Copyright (C) Gerald Carter 2002-2005.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25/* Implementation of registry functions. */
26
27#include "includes.h"
28#include "regfio.h"
29
30#undef DBGC_CLASS
31#define DBGC_CLASS DBGC_RPC_SRV
32
33static struct generic_mapping reg_generic_map =
34 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
35
36
37/******************************************************************
38 free() function for REGISTRY_KEY
39 *****************************************************************/
40
41static void free_regkey_info(void *ptr)
42{
43 regkey_close_internal( (REGISTRY_KEY*)ptr );
44}
45
46/******************************************************************
47 Find a registry key handle and return a REGISTRY_KEY
48 *****************************************************************/
49
50static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
51{
52 REGISTRY_KEY *regkey = NULL;
53
54 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
55 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
56 return NULL;
57 }
58
59 return regkey;
60}
61
62
63/*******************************************************************
64 Function for open a new registry handle and creating a handle
65 Note that P should be valid & hnd should already have space
66
67 When we open a key, we store the full path to the key as
68 HK[LM|U]\<key>\<key>\...
69 *******************************************************************/
70
71static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
72 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
73 const char *subkeyname, uint32 access_desired )
74{
75 pstring keypath;
76 int path_len;
77 WERROR result = WERR_OK;
78
79 /* create a full registry path and strip any trailing '\'
80 characters */
81
82 pstr_sprintf( keypath, "%s%s%s",
83 parent ? parent->name : "",
84 parent ? "\\" : "",
85 subkeyname );
86
87 path_len = strlen( keypath );
88 if ( path_len && keypath[path_len-1] == '\\' )
89 keypath[path_len-1] = '\0';
90
91 /* now do the internal open */
92
93 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
94 if ( !W_ERROR_IS_OK(result) )
95 return result;
96
97 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
98 result = WERR_BADFILE;
99 regkey_close_internal( *keyinfo );
100 }
101
102 return result;
103}
104
105/*******************************************************************
106 Function for open a new registry handle and creating a handle
107 Note that P should be valid & hnd should already have space
108 *******************************************************************/
109
110static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
111{
112 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
113
114 if ( !regkey ) {
115 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
116 return False;
117 }
118
119 close_policy_hnd(p, hnd);
120
121 return True;
122}
123
124/********************************************************************
125 retrieve information about the subkeys
126 *******************************************************************/
127
128static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
129{
130 int num_subkeys, i;
131 uint32 max_len;
132 REGSUBKEY_CTR *subkeys;
133 uint32 len;
134
135 if ( !key )
136 return False;
137
138 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
139 return False;
140
141 if ( fetch_reg_keys( key, subkeys ) == -1 )
142 return False;
143
144 /* find the longest string */
145
146 max_len = 0;
147 num_subkeys = regsubkey_ctr_numkeys( subkeys );
148
149 for ( i=0; i<num_subkeys; i++ ) {
150 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
151 max_len = MAX(max_len, len);
152 }
153
154 *maxnum = num_subkeys;
155 *maxlen = max_len*2;
156
157 TALLOC_FREE( subkeys );
158
159 return True;
160}
161
162/********************************************************************
163 retrieve information about the values.
164 *******************************************************************/
165
166static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
167 uint32 *maxlen, uint32 *maxsize )
168{
169 REGVAL_CTR *values;
170 REGISTRY_VALUE *val;
171 uint32 sizemax, lenmax;
172 int i, num_values;
173
174 if ( !key )
175 return False;
176
177 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
178 return False;
179
180 if ( fetch_reg_values( key, values ) == -1 )
181 return False;
182
183 lenmax = sizemax = 0;
184 num_values = regval_ctr_numvals( values );
185
186 val = regval_ctr_specific_value( values, 0 );
187
188 for ( i=0; i<num_values && val; i++ )
189 {
190 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
191 sizemax = MAX(sizemax, val->size );
192
193 val = regval_ctr_specific_value( values, i );
194 }
195
196 *maxnum = num_values;
197 *maxlen = lenmax;
198 *maxsize = sizemax;
199
200 TALLOC_FREE( values );
201
202 return True;
203}
204
205
206/********************************************************************
207 reg_close
208 ********************************************************************/
209
210WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
211{
212 /* close the policy handle */
213
214 if (!close_registry_key(p, &q_u->pol))
215 return WERR_BADFID;
216
217 return WERR_OK;
218}
219
220/*******************************************************************
221 ********************************************************************/
222
223WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
224{
225 REGISTRY_KEY *keyinfo;
226
227 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
228}
229
230/*******************************************************************
231 ********************************************************************/
232
233WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
234{
235 REGISTRY_KEY *keyinfo;
236
237 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
238}
239
240/*******************************************************************
241 ********************************************************************/
242
243WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
244{
245 REGISTRY_KEY *keyinfo;
246
247 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
248}
249
250/*******************************************************************
251 ********************************************************************/
252
253WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
254{
255 REGISTRY_KEY *keyinfo;
256
257 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
258}
259
260/*******************************************************************
261 ********************************************************************/
262
263WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
264{
265 REGISTRY_KEY *keyinfo;
266
267 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
268}
269
270/*******************************************************************
271 reg_reply_open_entry
272 ********************************************************************/
273
274WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
275{
276 fstring name;
277 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
278 REGISTRY_KEY *newkey = NULL;
279 uint32 check_rights;
280
281 if ( !parent )
282 return WERR_BADFID;
283
284 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
285
286 /* check granted access first; what is the correct mask here? */
287
288 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
289 SEC_RIGHTS_CREATE_SUBKEY|
290 SEC_RIGHTS_QUERY_VALUE|
291 SEC_RIGHTS_SET_VALUE);
292
293 if ( !(parent->access_granted & check_rights) ) {
294 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
295 return WERR_ACCESS_DENIED;
296 }
297
298 /*
299 * very crazy, but regedit.exe on Win2k will attempt to call
300 * REG_OPEN_ENTRY with a keyname of "". We should return a new
301 * (second) handle here on the key->name. regedt32.exe does
302 * not do this stupidity. --jerry
303 */
304
305 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
306}
307
308/*******************************************************************
309 reg_reply_info
310 ********************************************************************/
311
312WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
313{
314 WERROR status = WERR_BADFILE;
315 fstring name;
316 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
317 REGISTRY_VALUE *val = NULL;
318 REGVAL_CTR *regvals;
319 int i;
320
321 if ( !regkey )
322 return WERR_BADFID;
323
324 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
325 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
326
327 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
328
329 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
330
331 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
332 return WERR_NOMEM;
333
334 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
335 if(regkey->type == REG_KEY_HKPD)
336 {
337 if(strequal(name, "Global"))
338 {
339 uint32 outbuf_len;
340 prs_struct prs_hkpd;
341 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
342 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
343 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
344 prs_hkpd.data_p, outbuf_len);
345 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
346 prs_mem_free(&prs_hkpd);
347 }
348 else if(strequal(name, "Counter 009"))
349 {
350 uint32 base_index;
351 uint32 buffer_size;
352 char *buffer;
353
354 buffer = NULL;
355 base_index = reg_perfcount_get_base_index();
356 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
357 regval_ctr_addvalue(regvals, "Counter 009",
358 REG_MULTI_SZ, buffer, buffer_size);
359
360 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
361
362 if(buffer_size > 0)
363 {
364 SAFE_FREE(buffer);
365 status = WERR_OK;
366 }
367 }
368 else if(strequal(name, "Explain 009"))
369 {
370 uint32 base_index;
371 uint32 buffer_size;
372 char *buffer;
373
374 buffer = NULL;
375 base_index = reg_perfcount_get_base_index();
376 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
377 regval_ctr_addvalue(regvals, "Explain 009",
378 REG_MULTI_SZ, buffer, buffer_size);
379
380 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
381
382 if(buffer_size > 0)
383 {
384 SAFE_FREE(buffer);
385 status = WERR_OK;
386 }
387 }
388 else if(isdigit(name[0]))
389 {
390 /* we probably have a request for a specific object here */
391 uint32 outbuf_len;
392 prs_struct prs_hkpd;
393 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
394 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
395 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
396 prs_hkpd.data_p, outbuf_len);
397
398 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
399 prs_mem_free(&prs_hkpd);
400 }
401 else
402 {
403 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
404 return WERR_BADFILE;
405 }
406 }
407 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
408 else
409 {
410 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
411 {
412 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
413 if ( strequal( val->valuename, name ) ) {
414 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
415 status = WERR_OK;
416 break;
417 }
418
419 free_registry_value( val );
420 }
421 }
422
423 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
424
425 TALLOC_FREE( regvals );
426 free_registry_value( val );
427
428 return status;
429}
430
431/*****************************************************************************
432 Implementation of REG_QUERY_KEY
433 ****************************************************************************/
434
435WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
436{
437 WERROR status = WERR_OK;
438 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
439
440 if ( !regkey )
441 return WERR_BADFID;
442
443 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
444 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
445 return WERR_ACCESS_DENIED;
446 }
447
448 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
449 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
450 return WERR_ACCESS_DENIED;
451 }
452
453
454 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
455
456 /* Win9x set this to 0x0 since it does not keep timestamps.
457 Doing the same here for simplicity --jerry */
458
459 ZERO_STRUCT(r_u->mod_time);
460
461 return status;
462}
463
464
465/*****************************************************************************
466 Implementation of REG_GETVERSION
467 ****************************************************************************/
468
469WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
470{
471 WERROR status = WERR_OK;
472 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
473
474 if ( !regkey )
475 return WERR_BADFID;
476
477 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
478
479 return status;
480}
481
482
483/*****************************************************************************
484 Implementation of REG_ENUM_KEY
485 ****************************************************************************/
486
487WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
488{
489 WERROR status = WERR_OK;
490 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
491 char *subkey = NULL;
492
493
494 if ( !regkey )
495 return WERR_BADFID;
496
497 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
498
499 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
500 {
501 status = WERR_NO_MORE_ITEMS;
502 goto done;
503 }
504
505 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
506
507 /* subkey has the string name now */
508
509 init_reg_r_enum_key( r_u, subkey );
510
511done:
512 SAFE_FREE( subkey );
513 return status;
514}
515
516/*****************************************************************************
517 Implementation of REG_ENUM_VALUE
518 ****************************************************************************/
519
520WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
521{
522 WERROR status = WERR_OK;
523 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
524 REGISTRY_VALUE *val;
525
526
527 if ( !regkey )
528 return WERR_BADFID;
529
530 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
531
532 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
533 status = WERR_NO_MORE_ITEMS;
534 goto done;
535 }
536
537#if 0 /* JERRY TEST CODE */
538 if ( val->type == REG_MULTI_SZ ) {
539 char **str;
540 int num_strings = regval_convert_multi_sz( (uint16*)regval_data_p(val), regval_size(val), &str );
541 uint16 *buffer;
542 size_t buf_size;
543
544
545 if ( num_strings )
546 buf_size = regval_build_multi_sz( str, &buffer );
547
548 TALLOC_FREE( str );
549 TALLOC_FREE( buffer );
550 }
551#endif
552
553 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
554
555 /* subkey has the string name now */
556
557 init_reg_r_enum_val( r_u, val );
558
559done:
560 free_registry_value( val );
561
562 return status;
563}
564
565
566/*******************************************************************
567 reg_shutdwon
568 ********************************************************************/
569
570WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
571{
572 REG_Q_SHUTDOWN_EX q_u_ex;
573 REG_R_SHUTDOWN_EX r_u_ex;
574
575 /* copy fields (including stealing memory) */
576
577 q_u_ex.server = q_u->server;
578 q_u_ex.message = q_u->message;
579 q_u_ex.timeout = q_u->timeout;
580 q_u_ex.force = q_u->force;
581 q_u_ex.reboot = q_u->reboot;
582 q_u_ex.reason = 0x0; /* don't care for now */
583
584 /* thunk down to _reg_shutdown_ex() (just returns a status) */
585
586 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
587}
588
589/*******************************************************************
590 reg_shutdown_ex
591 ********************************************************************/
592
593#define SHUTDOWN_R_STRING "-r"
594#define SHUTDOWN_F_STRING "-f"
595
596
597WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
598{
599 pstring shutdown_script;
600 pstring message;
601 pstring chkmsg;
602 fstring timeout;
603 fstring reason;
604 fstring r;
605 fstring f;
606 int ret;
607 BOOL can_shutdown;
608
609
610 pstrcpy(shutdown_script, lp_shutdown_script());
611
612 if ( !*shutdown_script )
613 return WERR_ACCESS_DENIED;
614
615 /* pull the message string and perform necessary sanity checks on it */
616
617 pstrcpy( message, "" );
618 if ( q_u->message ) {
619 UNISTR2 *msg_string = q_u->message->string;
620
621 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
622 }
623 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
624
625 fstr_sprintf(timeout, "%d", q_u->timeout);
626 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
627 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
628 fstr_sprintf( reason, "%d", q_u->reason );
629
630 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
631 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
632 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
633 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
634 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
635
636 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
637
638 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
639 Take the error return from the script and provide it as the Windows return code. */
640
641 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
642
643 if ( can_shutdown )
644 become_root();
645
646 ret = smbrun( shutdown_script, NULL );
647
648 if ( can_shutdown )
649 unbecome_root();
650
651 /********** END SeRemoteShutdownPrivilege BLOCK **********/
652
653 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
654 shutdown_script, ret));
655
656
657 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
658}
659
660
661
662
663/*******************************************************************
664 reg_abort_shutdwon
665 ********************************************************************/
666
667WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
668{
669 pstring abort_shutdown_script;
670 int ret;
671 BOOL can_shutdown;
672
673 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
674
675 if ( !*abort_shutdown_script )
676 return WERR_ACCESS_DENIED;
677
678 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
679
680 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
681
682 if ( can_shutdown )
683 become_root();
684
685 ret = smbrun( abort_shutdown_script, NULL );
686
687 if ( can_shutdown )
688 unbecome_root();
689
690 /********** END SeRemoteShutdownPrivilege BLOCK **********/
691
692 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
693 abort_shutdown_script, ret));
694
695
696 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
697}
698
699/*******************************************************************
700 ********************************************************************/
701
702static int validate_reg_filename( pstring fname )
703{
704 char *p;
705 int num_services = lp_numservices();
706 int snum;
707 pstring share_path;
708 pstring unix_fname;
709
710 /* convert to a unix path, stripping the C:\ along the way */
711
712 if ( !(p = valid_share_pathname( fname ) ))
713 return -1;
714
715 /* has to exist within a valid file share */
716
717 for ( snum=0; snum<num_services; snum++ ) {
718
719 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
720 continue;
721
722 pstrcpy( share_path, lp_pathname(snum) );
723
724 /* make sure we have a path (e.g. [homes] ) */
725
726 if ( strlen( share_path ) == 0 )
727 continue;
728
729 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
730 break;
731 }
732
733 /* p and fname are overlapping memory so copy out and back in again */
734
735 pstrcpy( unix_fname, p );
736 pstrcpy( fname, unix_fname );
737
738 return (snum < num_services) ? snum : -1;
739}
740
741/*******************************************************************
742 Note: topkeypat is the *full* path that this *key will be
743 loaded into (including the name of the key)
744 ********************************************************************/
745
746static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
747 REGF_NK_REC *key )
748{
749 REGF_NK_REC *subkey;
750 REGISTRY_KEY registry_key;
751 REGVAL_CTR *values;
752 REGSUBKEY_CTR *subkeys;
753 int i;
754 pstring path;
755 WERROR result = WERR_OK;
756
757 /* initialize the REGISTRY_KEY structure */
758
759 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
760 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
761 topkeypath ));
762 return WERR_BADFILE;
763 }
764 pstrcpy( registry_key.name, topkeypath );
765
766 /* now start parsing the values and subkeys */
767
768 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
769 return WERR_NOMEM;
770
771 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
772 return WERR_NOMEM;
773
774 /* copy values into the REGVAL_CTR */
775
776 for ( i=0; i<key->num_values; i++ ) {
777 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
778 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
779 }
780
781 /* copy subkeys into the REGSUBKEY_CTR */
782
783 key->subkey_index = 0;
784 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
785 regsubkey_ctr_addkey( subkeys, subkey->keyname );
786 }
787
788 /* write this key and values out */
789
790 if ( !store_reg_values( &registry_key, values )
791 || !store_reg_keys( &registry_key, subkeys ) )
792 {
793 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
794 result = WERR_REG_IO_FAILURE;
795 }
796
797 TALLOC_FREE( subkeys );
798
799 if ( !W_ERROR_IS_OK(result) )
800 return result;
801
802 /* now continue to load each subkey registry tree */
803
804 key->subkey_index = 0;
805 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
806 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
807 result = reg_load_tree( regfile, path, subkey );
808 if ( !W_ERROR_IS_OK(result) )
809 break;
810 }
811
812 return result;
813}
814
815/*******************************************************************
816 ********************************************************************/
817
818static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
819{
820 REGF_FILE *regfile;
821 REGF_NK_REC *rootkey;
822 WERROR result;
823
824 /* open the registry file....fail if the file already exists */
825
826 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
827 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
828 fname, strerror(errno) ));
829 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
830 }
831
832 /* get the rootkey from the regf file and then load the tree
833 via recursive calls */
834
835 if ( !(rootkey = regfio_rootkey( regfile )) ) {
836 regfio_close( regfile );
837 return WERR_REG_FILE_INVALID;
838 }
839
840 result = reg_load_tree( regfile, krecord->name, rootkey );
841
842 /* cleanup */
843
844 regfio_close( regfile );
845
846 return result;
847}
848
849/*******************************************************************
850 ********************************************************************/
851
852WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
853{
854 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
855 pstring filename;
856 int snum;
857
858 if ( !regkey )
859 return WERR_BADFID;
860
861 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
862
863 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
864
865 if ( (snum = validate_reg_filename( filename )) == -1 )
866 return WERR_OBJECT_PATH_INVALID;
867
868 /* user must posses SeRestorePrivilege for this this proceed */
869
870 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
871 return WERR_ACCESS_DENIED;
872
873 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
874
875 return restore_registry_key( regkey, filename );
876}
877
878/********************************************************************
879********************************************************************/
880
881static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
882 REGF_NK_REC *parent, SEC_DESC *sec_desc )
883{
884 REGF_NK_REC *key;
885 REGVAL_CTR *values;
886 REGSUBKEY_CTR *subkeys;
887 int i, num_subkeys;
888 pstring key_tmp;
889 char *keyname, *parentpath;
890 pstring subkeypath;
891 char *subkeyname;
892 REGISTRY_KEY registry_key;
893 WERROR result = WERR_OK;
894
895 if ( !regfile )
896 return WERR_GENERAL_FAILURE;
897
898 if ( !keypath )
899 return WERR_OBJECT_PATH_INVALID;
900
901 /* split up the registry key path */
902
903 pstrcpy( key_tmp, keypath );
904 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
905 return WERR_OBJECT_PATH_INVALID;
906
907 if ( !keyname )
908 keyname = parentpath;
909
910 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
911
912 ZERO_STRUCT( registry_key );
913 pstrcpy( registry_key.name, keypath );
914 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
915 return WERR_BADFILE;
916
917
918 /* lookup the values and subkeys */
919
920 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
921 return WERR_NOMEM;
922
923 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
924 return WERR_NOMEM;
925
926 fetch_reg_keys( &registry_key, subkeys );
927 fetch_reg_values( &registry_key, values );
928
929 /* write out this key */
930
931 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
932 result = WERR_CAN_NOT_COMPLETE;
933 goto done;
934 }
935
936 /* write each one of the subkeys out */
937
938 num_subkeys = regsubkey_ctr_numkeys( subkeys );
939 for ( i=0; i<num_subkeys; i++ ) {
940 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
941 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
942 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
943 if ( !W_ERROR_IS_OK(result) )
944 goto done;
945 }
946
947 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
948
949done:
950 TALLOC_FREE( subkeys );
951
952 return result;
953}
954
955/*******************************************************************
956 ********************************************************************/
957
958static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
959{
960 DOM_SID adm_sid, owner_sid;
961 SEC_ACE ace[2]; /* at most 2 entries */
962 SEC_ACCESS mask;
963 SEC_ACL *psa = NULL;
964 size_t sd_size;
965
966 /* set the owner to BUILTIN\Administrator */
967
968 sid_copy(&owner_sid, &global_sid_Builtin);
969 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
970
971
972 /* basic access for Everyone */
973
974 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
975 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
976
977 /* add Full Access 'BUILTIN\Administrators' */
978
979 init_sec_access(&mask, reg_generic_map.generic_all);
980 sid_copy(&adm_sid, &global_sid_Builtin);
981 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
982 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
983
984 /* create the security descriptor */
985
986 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
987 return WERR_NOMEM;
988
989 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
990 return WERR_NOMEM;
991
992 return WERR_OK;
993}
994
995/*******************************************************************
996 ********************************************************************/
997
998static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
999{
1000 REGF_FILE *regfile;
1001 WERROR result;
1002 SEC_DESC *sd = NULL;
1003
1004 /* open the registry file....fail if the file already exists */
1005
1006 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1007 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1008 fname, strerror(errno) ));
1009 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1010 }
1011
1012 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1013 regfio_close( regfile );
1014 return result;
1015 }
1016
1017 /* write the registry tree to the file */
1018
1019 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1020
1021 /* cleanup */
1022
1023 regfio_close( regfile );
1024
1025 return result;
1026}
1027
1028/*******************************************************************
1029 ********************************************************************/
1030
1031WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1032{
1033 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1034 pstring filename;
1035 int snum;
1036
1037 if ( !regkey )
1038 return WERR_BADFID;
1039
1040 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1041
1042 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1043
1044 if ( (snum = validate_reg_filename( filename )) == -1 )
1045 return WERR_OBJECT_PATH_INVALID;
1046
1047 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1048
1049 return backup_registry_key( regkey, filename );
1050}
1051
1052/*******************************************************************
1053 ********************************************************************/
1054
1055WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1056{
1057 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1058 REGISTRY_KEY *newparentinfo, *keyinfo;
1059 POLICY_HND newparent_handle;
1060 REGSUBKEY_CTR *subkeys;
1061 BOOL write_result;
1062 pstring name;
1063 WERROR result;
1064
1065 if ( !parent )
1066 return WERR_BADFID;
1067
1068 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1069
1070 /* ok. Here's what we do. */
1071
1072 if ( strrchr( name, '\\' ) ) {
1073 pstring newkeyname;
1074 char *ptr;
1075
1076 /* (1) check for enumerate rights on the parent handle. CLients can try
1077 create things like 'SOFTWARE\Samba' on the HKLM handle.
1078 (2) open the path to the child parent key if necessary */
1079
1080 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1081 return WERR_ACCESS_DENIED;
1082
1083 pstrcpy( newkeyname, name );
1084 ptr = strrchr( newkeyname, '\\' );
1085 *ptr = '\0';
1086
1087 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1088 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1089
1090 if ( !W_ERROR_IS_OK(result) )
1091 return result;
1092
1093 /* copy the new key name (just the lower most keyname) */
1094
1095 pstrcpy( name, ptr+1 );
1096 }
1097 else {
1098 /* use the existing open key information */
1099 newparentinfo = parent;
1100 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1101 }
1102
1103 /* (3) check for create subkey rights on the correct parent */
1104
1105 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1106 result = WERR_ACCESS_DENIED;
1107 goto done;
1108 }
1109
1110 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1111 result = WERR_NOMEM;
1112 goto done;
1113 }
1114
1115 /* (4) lookup the current keys and add the new one */
1116
1117 fetch_reg_keys( newparentinfo, subkeys );
1118 regsubkey_ctr_addkey( subkeys, name );
1119
1120 /* now write to the registry backend */
1121
1122 write_result = store_reg_keys( newparentinfo, subkeys );
1123
1124 TALLOC_FREE( subkeys );
1125
1126 if ( !write_result )
1127 return WERR_REG_IO_FAILURE;
1128
1129 /* (5) open the new key and return the handle. Note that it is probably
1130 not correct to grant full access on this open handle. */
1131
1132 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1133 keyinfo->access_granted = REG_KEY_ALL;
1134
1135done:
1136 /* close any intermediate key handles */
1137
1138 if ( newparentinfo != parent )
1139 close_registry_key( p, &newparent_handle );
1140
1141 return result;
1142}
1143
1144
1145/*******************************************************************
1146 ********************************************************************/
1147
1148WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1149{
1150 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1151 REGVAL_CTR *values;
1152 BOOL write_result;
1153 fstring valuename;
1154
1155 if ( !key )
1156 return WERR_BADFID;
1157
1158 /* access checks first */
1159
1160 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1161 return WERR_ACCESS_DENIED;
1162
1163 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1164
1165 /* verify the name */
1166
1167 if ( !*valuename )
1168 return WERR_INVALID_PARAM;
1169
1170 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1171
1172 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1173 return WERR_NOMEM;
1174
1175 /* lookup the current values and add the new one */
1176
1177 fetch_reg_values( key, values );
1178
1179 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1180
1181 /* now write to the registry backend */
1182
1183 write_result = store_reg_values( key, values );
1184
1185 TALLOC_FREE( values );
1186
1187 if ( !write_result )
1188 return WERR_REG_IO_FAILURE;
1189
1190 return WERR_OK;
1191}
1192
1193/*******************************************************************
1194 ********************************************************************/
1195
1196WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1197{
1198 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1199 REGISTRY_KEY *newparentinfo = NULL;
1200 POLICY_HND newparent_handle;
1201 REGSUBKEY_CTR *subkeys;
1202 BOOL write_result;
1203 pstring name;
1204 WERROR result;
1205
1206 if ( !parent )
1207 return WERR_BADFID;
1208
1209 /* MSDN says parent the handle must have been opened with DELETE access */
1210
1211 /* (1) check for delete rights on the parent */
1212
1213 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1214 result = WERR_ACCESS_DENIED;
1215 goto done;
1216 }
1217
1218 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1219
1220 /* ok. Here's what we do. */
1221
1222 if ( strrchr( name, '\\' ) ) {
1223 pstring newkeyname;
1224 char *ptr;
1225
1226 /* (2) open the path to the child parent key if necessary */
1227 /* split the registry path and save the subkeyname */
1228
1229 pstrcpy( newkeyname, name );
1230 ptr = strrchr( newkeyname, '\\' );
1231 *ptr = '\0';
1232 pstrcpy( name, ptr+1 );
1233
1234 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1235 if ( !W_ERROR_IS_OK(result) )
1236 return result;
1237 }
1238 else {
1239 /* use the existing open key information */
1240 newparentinfo = parent;
1241 }
1242
1243 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1244 result = WERR_NOMEM;
1245 goto done;
1246 }
1247
1248 /* lookup the current keys and delete the new one */
1249
1250 fetch_reg_keys( newparentinfo, subkeys );
1251
1252 regsubkey_ctr_delkey( subkeys, name );
1253
1254 /* now write to the registry backend */
1255
1256 write_result = store_reg_keys( newparentinfo, subkeys );
1257
1258 TALLOC_FREE( subkeys );
1259
1260 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1261
1262done:
1263 /* close any intermediate key handles */
1264
1265 if ( newparentinfo != parent )
1266 close_registry_key( p, &newparent_handle );
1267
1268 return result;
1269}
1270
1271
1272/*******************************************************************
1273 ********************************************************************/
1274
1275WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1276{
1277 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1278 REGVAL_CTR *values;
1279 BOOL write_result;
1280 fstring valuename;
1281
1282 if ( !key )
1283 return WERR_BADFID;
1284
1285 /* access checks first */
1286
1287 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1288 return WERR_ACCESS_DENIED;
1289
1290 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1291
1292 if ( !*valuename )
1293 return WERR_INVALID_PARAM;
1294
1295 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1296
1297 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1298 return WERR_NOMEM;
1299
1300 /* lookup the current values and add the new one */
1301
1302 fetch_reg_values( key, values );
1303
1304 regval_ctr_delvalue( values, valuename );
1305
1306 /* now write to the registry backend */
1307
1308 write_result = store_reg_values( key, values );
1309
1310 TALLOC_FREE( values );
1311
1312 if ( !write_result )
1313 return WERR_REG_IO_FAILURE;
1314
1315 return WERR_OK;
1316}
1317
1318/*******************************************************************
1319 ********************************************************************/
1320
1321WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1322{
1323 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1324
1325 if ( !key )
1326 return WERR_BADFID;
1327
1328 /* access checks first */
1329
1330 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1331 return WERR_ACCESS_DENIED;
1332
1333 return WERR_ACCESS_DENIED;
1334}
1335
1336/*******************************************************************
1337 ********************************************************************/
1338
1339WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1340{
1341 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1342
1343 if ( !key )
1344 return WERR_BADFID;
1345
1346 /* access checks first */
1347
1348 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1349 return WERR_ACCESS_DENIED;
1350
1351 return WERR_ACCESS_DENIED;
1352}
Note: See TracBrowser for help on using the repository browser.