00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028 #include "regfio.h"
00029
00030 #undef DBGC_CLASS
00031 #define DBGC_CLASS DBGC_RPC_SRV
00032
00033 static struct generic_mapping reg_generic_map =
00034 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
00035
00036
00037
00038
00039
00040
00041 static void free_regkey_info(void *ptr)
00042 {
00043 regkey_close_internal( (REGISTRY_KEY*)ptr );
00044 }
00045
00046
00047
00048
00049
00050 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
00051 {
00052 REGISTRY_KEY *regkey = NULL;
00053
00054 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
00055 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
00056 return NULL;
00057 }
00058
00059 return regkey;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
00072 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
00073 const char *subkeyname, uint32 access_desired )
00074 {
00075 pstring keypath;
00076 int path_len;
00077 WERROR result = WERR_OK;
00078
00079
00080
00081
00082 pstr_sprintf( keypath, "%s%s%s",
00083 parent ? parent->name : "",
00084 parent ? "\\" : "",
00085 subkeyname );
00086
00087 path_len = strlen( keypath );
00088 if ( path_len && keypath[path_len-1] == '\\' )
00089 keypath[path_len-1] = '\0';
00090
00091
00092
00093 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
00094 if ( !W_ERROR_IS_OK(result) )
00095 return result;
00096
00097 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
00098 result = WERR_BADFILE;
00099 regkey_close_internal( *keyinfo );
00100 }
00101
00102 return result;
00103 }
00104
00105
00106
00107
00108
00109
00110 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
00111 {
00112 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
00113
00114 if ( !regkey ) {
00115 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
00116 return False;
00117 }
00118
00119 close_policy_hnd(p, hnd);
00120
00121 return True;
00122 }
00123
00124
00125
00126
00127
00128 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
00129 {
00130 int num_subkeys, i;
00131 uint32 max_len;
00132 REGSUBKEY_CTR *subkeys;
00133 uint32 len;
00134
00135 if ( !key )
00136 return False;
00137
00138 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
00139 return False;
00140
00141 if ( fetch_reg_keys( key, subkeys ) == -1 )
00142 return False;
00143
00144
00145
00146 max_len = 0;
00147 num_subkeys = regsubkey_ctr_numkeys( subkeys );
00148
00149 for ( i=0; i<num_subkeys; i++ ) {
00150 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
00151 max_len = MAX(max_len, len);
00152 }
00153
00154 *maxnum = num_subkeys;
00155 *maxlen = max_len*2;
00156
00157 TALLOC_FREE( subkeys );
00158
00159 return True;
00160 }
00161
00162
00163
00164
00165
00166 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
00167 uint32 *maxlen, uint32 *maxsize )
00168 {
00169 REGVAL_CTR *values;
00170 REGISTRY_VALUE *val;
00171 uint32 sizemax, lenmax;
00172 int i, num_values;
00173
00174 if ( !key )
00175 return False;
00176
00177 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
00178 return False;
00179
00180 if ( fetch_reg_values( key, values ) == -1 )
00181 return False;
00182
00183 lenmax = sizemax = 0;
00184 num_values = regval_ctr_numvals( values );
00185
00186 val = regval_ctr_specific_value( values, 0 );
00187
00188 for ( i=0; i<num_values && val; i++ )
00189 {
00190 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
00191 sizemax = MAX(sizemax, val->size );
00192
00193 val = regval_ctr_specific_value( values, i );
00194 }
00195
00196 *maxnum = num_values;
00197 *maxlen = lenmax;
00198 *maxsize = sizemax;
00199
00200 TALLOC_FREE( values );
00201
00202 return True;
00203 }
00204
00205
00206
00207
00208
00209
00210 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
00211 {
00212
00213
00214 if (!close_registry_key(p, &q_u->pol))
00215 return WERR_BADFID;
00216
00217 return WERR_OK;
00218 }
00219
00220
00221
00222
00223 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
00224 {
00225 REGISTRY_KEY *keyinfo;
00226
00227 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
00228 }
00229
00230
00231
00232
00233 WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
00234 {
00235 REGISTRY_KEY *keyinfo;
00236
00237 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
00238 }
00239
00240
00241
00242
00243 WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
00244 {
00245 REGISTRY_KEY *keyinfo;
00246
00247 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
00248 }
00249
00250
00251
00252
00253 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
00254 {
00255 REGISTRY_KEY *keyinfo;
00256
00257 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
00258 }
00259
00260
00261
00262
00263 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
00264 {
00265 REGISTRY_KEY *keyinfo;
00266
00267 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
00268 }
00269
00270
00271
00272
00273
00274 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
00275 {
00276 fstring name;
00277 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
00278 REGISTRY_KEY *newkey = NULL;
00279 uint32 check_rights;
00280
00281 if ( !parent )
00282 return WERR_BADFID;
00283
00284 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
00285
00286
00287
00288 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
00289 SEC_RIGHTS_CREATE_SUBKEY|
00290 SEC_RIGHTS_QUERY_VALUE|
00291 SEC_RIGHTS_SET_VALUE);
00292
00293 if ( !(parent->access_granted & check_rights) ) {
00294 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
00295 return WERR_ACCESS_DENIED;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
00306 }
00307
00308
00309
00310
00311
00312 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
00313 {
00314 WERROR status = WERR_BADFILE;
00315 fstring name;
00316 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00317 REGISTRY_VALUE *val = NULL;
00318 REGVAL_CTR *regvals;
00319 int i;
00320
00321 if ( !regkey )
00322 return WERR_BADFID;
00323
00324 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
00325 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
00326
00327 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
00328
00329 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
00330
00331 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
00332 return WERR_NOMEM;
00333
00334
00335 if(regkey->type == REG_KEY_HKPD)
00336 {
00337 if(strequal(name, "Global"))
00338 {
00339 uint32 outbuf_len;
00340 prs_struct prs_hkpd;
00341 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
00342 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
00343 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
00344 prs_hkpd.data_p, outbuf_len);
00345 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
00346 prs_mem_free(&prs_hkpd);
00347 }
00348 else if(strequal(name, "Counter 009"))
00349 {
00350 uint32 base_index;
00351 uint32 buffer_size;
00352 char *buffer;
00353
00354 buffer = NULL;
00355 base_index = reg_perfcount_get_base_index();
00356 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
00357 regval_ctr_addvalue(regvals, "Counter 009",
00358 REG_MULTI_SZ, buffer, buffer_size);
00359
00360 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
00361
00362 if(buffer_size > 0)
00363 {
00364 SAFE_FREE(buffer);
00365 status = WERR_OK;
00366 }
00367 }
00368 else if(strequal(name, "Explain 009"))
00369 {
00370 uint32 base_index;
00371 uint32 buffer_size;
00372 char *buffer;
00373
00374 buffer = NULL;
00375 base_index = reg_perfcount_get_base_index();
00376 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
00377 regval_ctr_addvalue(regvals, "Explain 009",
00378 REG_MULTI_SZ, buffer, buffer_size);
00379
00380 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
00381
00382 if(buffer_size > 0)
00383 {
00384 SAFE_FREE(buffer);
00385 status = WERR_OK;
00386 }
00387 }
00388 else if(isdigit(name[0]))
00389 {
00390
00391 uint32 outbuf_len;
00392 prs_struct prs_hkpd;
00393 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
00394 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
00395 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
00396 prs_hkpd.data_p, outbuf_len);
00397
00398 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
00399 prs_mem_free(&prs_hkpd);
00400 }
00401 else
00402 {
00403 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
00404 return WERR_BADFILE;
00405 }
00406 }
00407
00408 else
00409 {
00410 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
00411 {
00412 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
00413 if ( strequal( val->valuename, name ) ) {
00414 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
00415 status = WERR_OK;
00416 break;
00417 }
00418
00419 free_registry_value( val );
00420 }
00421 }
00422
00423 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
00424
00425 TALLOC_FREE( regvals );
00426 free_registry_value( val );
00427
00428 return status;
00429 }
00430
00431
00432
00433
00434
00435 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
00436 {
00437 WERROR status = WERR_OK;
00438 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00439
00440 if ( !regkey )
00441 return WERR_BADFID;
00442
00443 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
00444 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
00445 return WERR_ACCESS_DENIED;
00446 }
00447
00448 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
00449 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
00450 return WERR_ACCESS_DENIED;
00451 }
00452
00453
00454 r_u->sec_desc = 0x00000078;
00455
00456
00457
00458
00459 ZERO_STRUCT(r_u->mod_time);
00460
00461 return status;
00462 }
00463
00464
00465
00466
00467
00468
00469 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
00470 {
00471 WERROR status = WERR_OK;
00472 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00473
00474 if ( !regkey )
00475 return WERR_BADFID;
00476
00477 r_u->win_version = 0x00000005;
00478
00479 return status;
00480 }
00481
00482
00483
00484
00485
00486
00487 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
00488 {
00489 WERROR status = WERR_OK;
00490 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00491 char *subkey = NULL;
00492
00493
00494 if ( !regkey )
00495 return WERR_BADFID;
00496
00497 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
00498
00499 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
00500 {
00501 status = WERR_NO_MORE_ITEMS;
00502 goto done;
00503 }
00504
00505 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
00506
00507
00508
00509 init_reg_r_enum_key( r_u, subkey );
00510
00511 done:
00512 SAFE_FREE( subkey );
00513 return status;
00514 }
00515
00516
00517
00518
00519
00520 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
00521 {
00522 WERROR status = WERR_OK;
00523 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00524 REGISTRY_VALUE *val;
00525
00526
00527 if ( !regkey )
00528 return WERR_BADFID;
00529
00530 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
00531
00532 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
00533 status = WERR_NO_MORE_ITEMS;
00534 goto done;
00535 }
00536
00537 #if 0
00538 if ( val->type == REG_MULTI_SZ ) {
00539 char **str;
00540 int num_strings = regval_convert_multi_sz( (uint16*)regval_data_p(val), regval_size(val), &str );
00541 uint16 *buffer;
00542 size_t buf_size;
00543
00544
00545 if ( num_strings )
00546 buf_size = regval_build_multi_sz( str, &buffer );
00547
00548 TALLOC_FREE( str );
00549 TALLOC_FREE( buffer );
00550 }
00551 #endif
00552
00553 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
00554
00555
00556
00557 init_reg_r_enum_val( r_u, val );
00558
00559 done:
00560 free_registry_value( val );
00561
00562 return status;
00563 }
00564
00565
00566
00567
00568
00569
00570 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
00571 {
00572 REG_Q_SHUTDOWN_EX q_u_ex;
00573 REG_R_SHUTDOWN_EX r_u_ex;
00574
00575
00576
00577 q_u_ex.server = q_u->server;
00578 q_u_ex.message = q_u->message;
00579 q_u_ex.timeout = q_u->timeout;
00580 q_u_ex.force = q_u->force;
00581 q_u_ex.reboot = q_u->reboot;
00582 q_u_ex.reason = 0x0;
00583
00584
00585
00586 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
00587 }
00588
00589
00590
00591
00592
00593 #define SHUTDOWN_R_STRING "-r"
00594 #define SHUTDOWN_F_STRING "-f"
00595
00596
00597 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
00598 {
00599 pstring shutdown_script;
00600 pstring message;
00601 pstring chkmsg;
00602 fstring timeout;
00603 fstring reason;
00604 fstring r;
00605 fstring f;
00606 int ret;
00607 BOOL can_shutdown;
00608
00609
00610 pstrcpy(shutdown_script, lp_shutdown_script());
00611
00612 if ( !*shutdown_script )
00613 return WERR_ACCESS_DENIED;
00614
00615
00616
00617 pstrcpy( message, "" );
00618 if ( q_u->message ) {
00619 UNISTR2 *msg_string = q_u->message->string;
00620
00621 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
00622 }
00623 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
00624
00625 fstr_sprintf(timeout, "%d", q_u->timeout);
00626 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
00627 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
00628 fstr_sprintf( reason, "%d", q_u->reason );
00629
00630 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
00631 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
00632 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
00633 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
00634 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
00635
00636 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
00637
00638
00639
00640
00641
00642
00643 if ( can_shutdown )
00644 become_root();
00645
00646 ret = smbrun( shutdown_script, NULL );
00647
00648 if ( can_shutdown )
00649 unbecome_root();
00650
00651
00652
00653 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
00654 shutdown_script, ret));
00655
00656
00657 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
00668 {
00669 pstring abort_shutdown_script;
00670 int ret;
00671 BOOL can_shutdown;
00672
00673 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
00674
00675 if ( !*abort_shutdown_script )
00676 return WERR_ACCESS_DENIED;
00677
00678 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
00679
00680
00681
00682 if ( can_shutdown )
00683 become_root();
00684
00685 ret = smbrun( abort_shutdown_script, NULL );
00686
00687 if ( can_shutdown )
00688 unbecome_root();
00689
00690
00691
00692 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
00693 abort_shutdown_script, ret));
00694
00695
00696 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
00697 }
00698
00699
00700
00701
00702 static int validate_reg_filename( pstring fname )
00703 {
00704 char *p;
00705 int num_services = lp_numservices();
00706 int snum;
00707 pstring share_path;
00708 pstring unix_fname;
00709
00710
00711
00712 if ( !(p = valid_share_pathname( fname ) ))
00713 return -1;
00714
00715
00716
00717 for ( snum=0; snum<num_services; snum++ ) {
00718
00719 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
00720 continue;
00721
00722 pstrcpy( share_path, lp_pathname(snum) );
00723
00724
00725
00726 if ( strlen( share_path ) == 0 )
00727 continue;
00728
00729 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
00730 break;
00731 }
00732
00733
00734
00735 pstrcpy( unix_fname, p );
00736 pstrcpy( fname, unix_fname );
00737
00738 return (snum < num_services) ? snum : -1;
00739 }
00740
00741
00742
00743
00744
00745
00746 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
00747 REGF_NK_REC *key )
00748 {
00749 REGF_NK_REC *subkey;
00750 REGISTRY_KEY registry_key;
00751 REGVAL_CTR *values;
00752 REGSUBKEY_CTR *subkeys;
00753 int i;
00754 pstring path;
00755 WERROR result = WERR_OK;
00756
00757
00758
00759 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
00760 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
00761 topkeypath ));
00762 return WERR_BADFILE;
00763 }
00764 pstrcpy( registry_key.name, topkeypath );
00765
00766
00767
00768 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
00769 return WERR_NOMEM;
00770
00771 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
00772 return WERR_NOMEM;
00773
00774
00775
00776 for ( i=0; i<key->num_values; i++ ) {
00777 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
00778 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
00779 }
00780
00781
00782
00783 key->subkey_index = 0;
00784 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
00785 regsubkey_ctr_addkey( subkeys, subkey->keyname );
00786 }
00787
00788
00789
00790 if ( !store_reg_values( ®istry_key, values )
00791 || !store_reg_keys( ®istry_key, subkeys ) )
00792 {
00793 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
00794 result = WERR_REG_IO_FAILURE;
00795 }
00796
00797 TALLOC_FREE( subkeys );
00798
00799 if ( !W_ERROR_IS_OK(result) )
00800 return result;
00801
00802
00803
00804 key->subkey_index = 0;
00805 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
00806 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
00807 result = reg_load_tree( regfile, path, subkey );
00808 if ( !W_ERROR_IS_OK(result) )
00809 break;
00810 }
00811
00812 return result;
00813 }
00814
00815
00816
00817
00818 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
00819 {
00820 REGF_FILE *regfile;
00821 REGF_NK_REC *rootkey;
00822 WERROR result;
00823
00824
00825
00826 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
00827 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
00828 fname, strerror(errno) ));
00829 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
00830 }
00831
00832
00833
00834
00835 if ( !(rootkey = regfio_rootkey( regfile )) ) {
00836 regfio_close( regfile );
00837 return WERR_REG_FILE_INVALID;
00838 }
00839
00840 result = reg_load_tree( regfile, krecord->name, rootkey );
00841
00842
00843
00844 regfio_close( regfile );
00845
00846 return result;
00847 }
00848
00849
00850
00851
00852 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
00853 {
00854 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
00855 pstring filename;
00856 int snum;
00857
00858 if ( !regkey )
00859 return WERR_BADFID;
00860
00861 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
00862
00863 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
00864
00865 if ( (snum = validate_reg_filename( filename )) == -1 )
00866 return WERR_OBJECT_PATH_INVALID;
00867
00868
00869
00870 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
00871 return WERR_ACCESS_DENIED;
00872
00873 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
00874
00875 return restore_registry_key( regkey, filename );
00876 }
00877
00878
00879
00880
00881 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
00882 REGF_NK_REC *parent, SEC_DESC *sec_desc )
00883 {
00884 REGF_NK_REC *key;
00885 REGVAL_CTR *values;
00886 REGSUBKEY_CTR *subkeys;
00887 int i, num_subkeys;
00888 pstring key_tmp;
00889 char *keyname, *parentpath;
00890 pstring subkeypath;
00891 char *subkeyname;
00892 REGISTRY_KEY registry_key;
00893 WERROR result = WERR_OK;
00894
00895 if ( !regfile )
00896 return WERR_GENERAL_FAILURE;
00897
00898 if ( !keypath )
00899 return WERR_OBJECT_PATH_INVALID;
00900
00901
00902
00903 pstrcpy( key_tmp, keypath );
00904 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
00905 return WERR_OBJECT_PATH_INVALID;
00906
00907 if ( !keyname )
00908 keyname = parentpath;
00909
00910
00911
00912 ZERO_STRUCT( registry_key );
00913 pstrcpy( registry_key.name, keypath );
00914 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
00915 return WERR_BADFILE;
00916
00917
00918
00919
00920 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
00921 return WERR_NOMEM;
00922
00923 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
00924 return WERR_NOMEM;
00925
00926 fetch_reg_keys( ®istry_key, subkeys );
00927 fetch_reg_values( ®istry_key, values );
00928
00929
00930
00931 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
00932 result = WERR_CAN_NOT_COMPLETE;
00933 goto done;
00934 }
00935
00936
00937
00938 num_subkeys = regsubkey_ctr_numkeys( subkeys );
00939 for ( i=0; i<num_subkeys; i++ ) {
00940 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
00941 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
00942 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
00943 if ( !W_ERROR_IS_OK(result) )
00944 goto done;
00945 }
00946
00947 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
00948
00949 done:
00950 TALLOC_FREE( subkeys );
00951
00952 return result;
00953 }
00954
00955
00956
00957
00958 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
00959 {
00960 DOM_SID adm_sid, owner_sid;
00961 SEC_ACE ace[2];
00962 SEC_ACCESS mask;
00963 SEC_ACL *psa = NULL;
00964 size_t sd_size;
00965
00966
00967
00968 sid_copy(&owner_sid, &global_sid_Builtin);
00969 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
00970
00971
00972
00973
00974 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
00975 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00976
00977
00978
00979 init_sec_access(&mask, reg_generic_map.generic_all);
00980 sid_copy(&adm_sid, &global_sid_Builtin);
00981 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
00982 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00983
00984
00985
00986 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
00987 return WERR_NOMEM;
00988
00989 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
00990 return WERR_NOMEM;
00991
00992 return WERR_OK;
00993 }
00994
00995
00996
00997
00998 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
00999 {
01000 REGF_FILE *regfile;
01001 WERROR result;
01002 SEC_DESC *sd = NULL;
01003
01004
01005
01006 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
01007 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
01008 fname, strerror(errno) ));
01009 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
01010 }
01011
01012 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
01013 regfio_close( regfile );
01014 return result;
01015 }
01016
01017
01018
01019 result = reg_write_tree( regfile, krecord->name, NULL, sd );
01020
01021
01022
01023 regfio_close( regfile );
01024
01025 return result;
01026 }
01027
01028
01029
01030
01031 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
01032 {
01033 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
01034 pstring filename;
01035 int snum;
01036
01037 if ( !regkey )
01038 return WERR_BADFID;
01039
01040 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
01041
01042 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
01043
01044 if ( (snum = validate_reg_filename( filename )) == -1 )
01045 return WERR_OBJECT_PATH_INVALID;
01046
01047 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
01048
01049 return backup_registry_key( regkey, filename );
01050 }
01051
01052
01053
01054
01055 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
01056 {
01057 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
01058 REGISTRY_KEY *newparentinfo, *keyinfo;
01059 POLICY_HND newparent_handle;
01060 REGSUBKEY_CTR *subkeys;
01061 BOOL write_result;
01062 pstring name;
01063 WERROR result;
01064
01065 if ( !parent )
01066 return WERR_BADFID;
01067
01068 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
01069
01070
01071
01072 if ( strrchr( name, '\\' ) ) {
01073 pstring newkeyname;
01074 char *ptr;
01075
01076
01077
01078
01079
01080 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
01081 return WERR_ACCESS_DENIED;
01082
01083 pstrcpy( newkeyname, name );
01084 ptr = strrchr( newkeyname, '\\' );
01085 *ptr = '\0';
01086
01087 result = open_registry_key( p, &newparent_handle, &newparentinfo,
01088 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
01089
01090 if ( !W_ERROR_IS_OK(result) )
01091 return result;
01092
01093
01094
01095 pstrcpy( name, ptr+1 );
01096 }
01097 else {
01098
01099 newparentinfo = parent;
01100 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
01101 }
01102
01103
01104
01105 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
01106 result = WERR_ACCESS_DENIED;
01107 goto done;
01108 }
01109
01110 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
01111 result = WERR_NOMEM;
01112 goto done;
01113 }
01114
01115
01116
01117 fetch_reg_keys( newparentinfo, subkeys );
01118 regsubkey_ctr_addkey( subkeys, name );
01119
01120
01121
01122 write_result = store_reg_keys( newparentinfo, subkeys );
01123
01124 TALLOC_FREE( subkeys );
01125
01126 if ( !write_result )
01127 return WERR_REG_IO_FAILURE;
01128
01129
01130
01131
01132 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
01133 keyinfo->access_granted = REG_KEY_ALL;
01134
01135 done:
01136
01137
01138 if ( newparentinfo != parent )
01139 close_registry_key( p, &newparent_handle );
01140
01141 return result;
01142 }
01143
01144
01145
01146
01147
01148 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
01149 {
01150 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
01151 REGVAL_CTR *values;
01152 BOOL write_result;
01153 fstring valuename;
01154
01155 if ( !key )
01156 return WERR_BADFID;
01157
01158
01159
01160 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
01161 return WERR_ACCESS_DENIED;
01162
01163 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
01164
01165
01166
01167 if ( !*valuename )
01168 return WERR_INVALID_PARAM;
01169
01170 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
01171
01172 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
01173 return WERR_NOMEM;
01174
01175
01176
01177 fetch_reg_values( key, values );
01178
01179 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
01180
01181
01182
01183 write_result = store_reg_values( key, values );
01184
01185 TALLOC_FREE( values );
01186
01187 if ( !write_result )
01188 return WERR_REG_IO_FAILURE;
01189
01190 return WERR_OK;
01191 }
01192
01193
01194
01195
01196 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
01197 {
01198 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
01199 REGISTRY_KEY *newparentinfo = NULL;
01200 POLICY_HND newparent_handle;
01201 REGSUBKEY_CTR *subkeys;
01202 BOOL write_result;
01203 pstring name;
01204 WERROR result;
01205
01206 if ( !parent )
01207 return WERR_BADFID;
01208
01209
01210
01211
01212
01213 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
01214 result = WERR_ACCESS_DENIED;
01215 goto done;
01216 }
01217
01218 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
01219
01220
01221
01222 if ( strrchr( name, '\\' ) ) {
01223 pstring newkeyname;
01224 char *ptr;
01225
01226
01227
01228
01229 pstrcpy( newkeyname, name );
01230 ptr = strrchr( newkeyname, '\\' );
01231 *ptr = '\0';
01232 pstrcpy( name, ptr+1 );
01233
01234 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
01235 if ( !W_ERROR_IS_OK(result) )
01236 return result;
01237 }
01238 else {
01239
01240 newparentinfo = parent;
01241 }
01242
01243 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
01244 result = WERR_NOMEM;
01245 goto done;
01246 }
01247
01248
01249
01250 fetch_reg_keys( newparentinfo, subkeys );
01251
01252 regsubkey_ctr_delkey( subkeys, name );
01253
01254
01255
01256 write_result = store_reg_keys( newparentinfo, subkeys );
01257
01258 TALLOC_FREE( subkeys );
01259
01260 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
01261
01262 done:
01263
01264
01265 if ( newparentinfo != parent )
01266 close_registry_key( p, &newparent_handle );
01267
01268 return result;
01269 }
01270
01271
01272
01273
01274
01275 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
01276 {
01277 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
01278 REGVAL_CTR *values;
01279 BOOL write_result;
01280 fstring valuename;
01281
01282 if ( !key )
01283 return WERR_BADFID;
01284
01285
01286
01287 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
01288 return WERR_ACCESS_DENIED;
01289
01290 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
01291
01292 if ( !*valuename )
01293 return WERR_INVALID_PARAM;
01294
01295 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
01296
01297 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
01298 return WERR_NOMEM;
01299
01300
01301
01302 fetch_reg_values( key, values );
01303
01304 regval_ctr_delvalue( values, valuename );
01305
01306
01307
01308 write_result = store_reg_values( key, values );
01309
01310 TALLOC_FREE( values );
01311
01312 if ( !write_result )
01313 return WERR_REG_IO_FAILURE;
01314
01315 return WERR_OK;
01316 }
01317
01318
01319
01320
01321 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
01322 {
01323 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
01324
01325 if ( !key )
01326 return WERR_BADFID;
01327
01328
01329
01330 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
01331 return WERR_ACCESS_DENIED;
01332
01333 return WERR_ACCESS_DENIED;
01334 }
01335
01336
01337
01338
01339 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
01340 {
01341 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
01342
01343 if ( !key )
01344 return WERR_BADFID;
01345
01346
01347
01348 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
01349 return WERR_ACCESS_DENIED;
01350
01351 return WERR_ACCESS_DENIED;
01352 }