00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025 #undef DBGC_CLASS
00026 #define DBGC_CLASS DBGC_RPC_SRV
00027
00028 extern REGISTRY_OPS printing_ops;
00029 extern REGISTRY_OPS eventlog_ops;
00030 extern REGISTRY_OPS shares_reg_ops;
00031 extern REGISTRY_OPS regdb_ops;
00032
00033
00034
00035
00036 REGISTRY_HOOK reg_hooks[] = {
00037 #ifndef REG_TDB_ONLY
00038 { KEY_PRINTING, &printing_ops },
00039 { KEY_PRINTING_2K, &printing_ops },
00040 { KEY_PRINTING_PORTS, &printing_ops },
00041 { KEY_SHARES, &shares_reg_ops },
00042 #endif
00043 { NULL, NULL }
00044 };
00045
00046
00047 static struct generic_mapping reg_generic_map =
00048 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
00049
00050
00051
00052
00053 static NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
00054 uint32 access_desired, uint32 *access_granted )
00055 {
00056 NTSTATUS result;
00057
00058 if ( geteuid() == sec_initial_uid() ) {
00059 DEBUG(5,("registry_access_check: using root's token\n"));
00060 token = get_root_nt_token();
00061 }
00062
00063 se_map_generic( &access_desired, ®_generic_map );
00064 se_access_check( sec_desc, token, access_desired, access_granted, &result );
00065
00066 return result;
00067 }
00068
00069
00070
00071
00072 static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
00073 {
00074 SEC_ACE ace[2];
00075 SEC_ACCESS mask;
00076 size_t i = 0;
00077 SEC_DESC *sd;
00078 SEC_ACL *acl;
00079 size_t sd_size;
00080
00081
00082
00083 init_sec_access(&mask, REG_KEY_READ );
00084 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00085
00086
00087
00088 init_sec_access(&mask, REG_KEY_ALL );
00089 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00090
00091
00092
00093
00094 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
00095 return NULL;
00096
00097 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
00098 return NULL;
00099
00100 return sd;
00101 }
00102
00103
00104
00105
00106
00107
00108 BOOL init_registry( void )
00109 {
00110 int i;
00111
00112
00113 if ( !regdb_init() ) {
00114 DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
00115 return False;
00116 }
00117
00118
00119
00120 reghook_cache_init();
00121
00122 for ( i=0; reg_hooks[i].keyname; i++ ) {
00123 if ( !reghook_cache_add(®_hooks[i]) )
00124 return False;
00125 }
00126
00127 if ( DEBUGLEVEL >= 20 )
00128 reghook_dump_cache(20);
00129
00130
00131
00132 svcctl_init_keys();
00133 eventlog_init_keys();
00134 perfcount_init_keys();
00135
00136
00137
00138 regdb_close();
00139
00140 return True;
00141 }
00142
00143
00144
00145
00146
00147 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
00148 {
00149 if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
00150 return key->hook->ops->store_subkeys( key->name, subkeys );
00151
00152 return False;
00153
00154 }
00155
00156
00157
00158
00159
00160 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
00161 {
00162 if ( check_dynamic_reg_values( key ) )
00163 return False;
00164
00165 if ( key->hook && key->hook->ops && key->hook->ops->store_values )
00166 return key->hook->ops->store_values( key->name, val );
00167
00168 return False;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
00178 {
00179 int result = -1;
00180
00181 if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
00182 result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
00183
00184 return result;
00185 }
00186
00187
00188
00189
00190
00191
00192 BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index )
00193 {
00194 static REGSUBKEY_CTR *ctr = NULL;
00195 static pstring save_path;
00196 char *s;
00197
00198 *subkey = NULL;
00199
00200
00201
00202 DEBUG(8,("fetch_reg_keys_specific: Looking for key [%d] of [%s]\n", key_index, key->name));
00203
00204 if ( !ctr ) {
00205 DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
00206
00207 if ( !(ctr = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
00208 DEBUG(0,("fetch_reg_keys_specific: talloc() failed!\n"));
00209 return False;
00210 }
00211
00212 pstrcpy( save_path, key->name );
00213
00214 if ( fetch_reg_keys( key, ctr) == -1 )
00215 return False;
00216
00217 }
00218
00219 else if ( !key_index || StrCaseCmp( save_path, key->name) ) {
00220
00221 DEBUG(8,("fetch_reg_keys_specific: Updating cache of subkeys for [%s]\n", key->name));
00222
00223 TALLOC_FREE( ctr );
00224
00225 if ( !(ctr = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
00226 DEBUG(0,("fetch_reg_keys_specific: talloc() failed!\n"));
00227 return False;
00228 }
00229
00230 pstrcpy( save_path, key->name );
00231
00232 if ( fetch_reg_keys( key, ctr) == -1 )
00233 return False;
00234 }
00235
00236 if ( !(s = regsubkey_ctr_specific_key( ctr, key_index )) )
00237 return False;
00238
00239 *subkey = SMB_STRDUP( s );
00240
00241 return True;
00242 }
00243
00244
00245
00246
00247
00248 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
00249 {
00250 int result = -1;
00251
00252 if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
00253 result = key->hook->ops->fetch_values( key->name, val );
00254
00255
00256
00257 if ( result == 0 ) {
00258 result = fetch_dynamic_reg_values( key, val );
00259
00260 return ( result != -1 ) ? result : 0;
00261 }
00262
00263 return result;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272 BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
00273 {
00274 static REGVAL_CTR *ctr = NULL;
00275 static pstring save_path;
00276 REGISTRY_VALUE *v;
00277
00278 *val = NULL;
00279
00280
00281
00282 if ( !ctr ) {
00283 DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
00284
00285 if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
00286 DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
00287 return False;
00288 }
00289
00290 pstrcpy( save_path, key->name );
00291
00292 if ( fetch_reg_values( key, ctr) == -1 )
00293 return False;
00294 }
00295
00296 else if ( !val_index || !strequal(save_path, key->name) ) {
00297
00298 DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));
00299
00300 TALLOC_FREE( ctr );
00301
00302 if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
00303 DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
00304 return False;
00305 }
00306
00307 pstrcpy( save_path, key->name );
00308
00309 if ( fetch_reg_values( key, ctr) == -1 )
00310 return False;
00311 }
00312
00313 if ( !(v = regval_ctr_specific_value( ctr, val_index )) )
00314 return False;
00315
00316 *val = dup_registry_value( v );
00317
00318 return True;
00319 }
00320
00321
00322
00323
00324
00325
00326 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, NT_USER_TOKEN *token )
00327 {
00328
00329
00330 if ( !(key->hook && key->hook->ops && key->hook->ops->reg_access_check) ) {
00331 SEC_DESC *sec_desc;
00332 NTSTATUS status;
00333
00334 if ( !(sec_desc = construct_registry_sd( get_talloc_ctx() )) )
00335 return False;
00336
00337 status = registry_access_check( sec_desc, token, requested, granted );
00338
00339 return NT_STATUS_IS_OK(status);
00340 }
00341
00342 return key->hook->ops->reg_access_check( key->name, requested, granted, token );
00343 }
00344
00345
00346
00347
00348 WERROR regkey_open_internal( REGISTRY_KEY **regkey, const char *path,
00349 NT_USER_TOKEN *token, uint32 access_desired )
00350 {
00351 WERROR result = WERR_OK;
00352 REGISTRY_KEY *keyinfo;
00353 REGSUBKEY_CTR *subkeys = NULL;
00354 uint32 access_granted;
00355
00356 if ( !(W_ERROR_IS_OK(result = regdb_open()) ) )
00357 return result;
00358
00359 DEBUG(7,("regkey_open_internal: name = [%s]\n", path));
00360
00361 if ( !(*regkey = TALLOC_ZERO_P(NULL, REGISTRY_KEY)) ) {
00362 regdb_close();
00363 return WERR_NOMEM;
00364 }
00365
00366 keyinfo = *regkey;
00367
00368
00369
00370 keyinfo->type = REG_KEY_GENERIC;
00371 if (!(keyinfo->name = talloc_strdup(keyinfo, path))) {
00372 result = WERR_NOMEM;
00373 goto done;
00374 }
00375
00376
00377
00378 if( StrnCaseCmp(path, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
00379 keyinfo->type = REG_KEY_HKPD;
00380
00381
00382
00383 if ( !(keyinfo->hook = reghook_cache_find( keyinfo->name )) ) {
00384 DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
00385 keyinfo->name ));
00386 result = WERR_BADFILE;
00387 goto done;
00388 }
00389
00390
00391
00392
00393 if ( !(subkeys = TALLOC_ZERO_P( keyinfo, REGSUBKEY_CTR )) ) {
00394 result = WERR_NOMEM;
00395 goto done;
00396 }
00397
00398 if ( fetch_reg_keys( keyinfo, subkeys ) == -1 ) {
00399 result = WERR_BADFILE;
00400 goto done;
00401 }
00402
00403 TALLOC_FREE( subkeys );
00404
00405 if ( !regkey_access_check( keyinfo, access_desired, &access_granted, token ) ) {
00406 result = WERR_ACCESS_DENIED;
00407 goto done;
00408 }
00409
00410 keyinfo->access_granted = access_granted;
00411
00412 done:
00413 if ( !W_ERROR_IS_OK(result) ) {
00414 regkey_close_internal( *regkey );
00415 }
00416
00417 return result;
00418 }
00419
00420
00421
00422
00423 WERROR regkey_close_internal( REGISTRY_KEY *key )
00424 {
00425 TALLOC_FREE( key );
00426 regdb_close();
00427
00428 return WERR_OK;
00429 }