registry/reg_frontend.c

説明を見る。
00001 /* 
00002  *  Unix SMB/CIFS implementation.
00003  *  Virtual Windows Registry Layer
00004  *  Copyright (C) Gerald Carter                     2002-2005
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *  
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *  
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 /* Implementation of registry frontend view functions. */
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;          /* these are the default */
00032 
00033 /* array of REGISTRY_HOOK's which are read into a tree for easy access */
00034 /* #define REG_TDB_ONLY         1 */
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, &reg_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         /* basic access for Everyone */
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         /* Full Access 'BUILTIN\Administrators' */
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         /* create the security descriptor */
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  Open the registry database and initialize the REGISTRY_HOOK cache
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         /* build the cache tree of registry hooks */
00119         
00120         reghook_cache_init();
00121         
00122         for ( i=0; reg_hooks[i].keyname; i++ ) {
00123                 if ( !reghook_cache_add(&reg_hooks[i]) )
00124                         return False;
00125         }
00126 
00127         if ( DEBUGLEVEL >= 20 )
00128                 reghook_dump_cache(20);
00129 
00130         /* add any keys for other services */
00131 
00132         svcctl_init_keys();
00133         eventlog_init_keys();
00134         perfcount_init_keys();
00135 
00136         /* close and let each smbd open up as necessary */
00137 
00138         regdb_close();
00139 
00140         return True;
00141 }
00142 
00143 /***********************************************************************
00144  High level wrapper function for storing registry subkeys
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  High level wrapper function for storing registry values
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  High level wrapper function for enumerating registry subkeys
00174  Initialize the TALLOC_CTX if necessary
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  retreive a specific subkey specified by index.  Caller is 
00189  responsible for freeing memory
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         /* simple caching for performance; very basic heuristic */
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         /* clear the cache when key_index == 0 or the path has changed */
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  High level wrapper function for enumerating registry values
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         /* if the backend lookup returned no data, try the dynamic overlay */
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  retreive a specific subkey specified by index.  Caller is 
00269  responsible for freeing memory
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         /* simple caching for performance; very basic heuristic */
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         /* clear the cache when val_index == 0 or the path has changed */
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  High level access check for passing the required access mask to the 
00323  underlying registry backend
00324  ***********************************************************************/
00325 
00326 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, NT_USER_TOKEN *token )
00327 {
00328         /* use the default security check if the backend has not defined its own */
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         /* initialization */
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         /* Tag this as a Performance Counter Key */
00377 
00378         if( StrnCaseCmp(path, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
00379                 keyinfo->type = REG_KEY_HKPD;
00380         
00381         /* Look up the table of registry I/O operations */
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         /* check if the path really exists; failed is indicated by -1 */
00391         /* if the subkey count failed, bail out */
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 }

Sambaに対してSat Aug 29 21:23:15 2009に生成されました。  doxygen 1.4.7