d6e02884616817f732368d0aee5725f38d4a3043
[ira/wip.git] / source3 / registry / reg_frontend.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /* Implementation of registry frontend view functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 extern REGISTRY_OPS printing_ops;
29 extern REGISTRY_OPS eventlog_ops;
30 extern REGISTRY_OPS shares_reg_ops;
31 extern REGISTRY_OPS regdb_ops;          /* these are the default */
32
33 /* array of REGISTRY_HOOK's which are read into a tree for easy access */
34 /* #define REG_TDB_ONLY         1 */
35
36 REGISTRY_HOOK reg_hooks[] = {
37 #ifndef REG_TDB_ONLY 
38   { KEY_PRINTING,               &printing_ops },
39   { KEY_PRINTING_2K,            &printing_ops },
40   { KEY_PRINTING_PORTS,         &printing_ops },
41 #if 0
42   { KEY_EVENTLOG,               &eventlog_ops }, 
43 #endif
44   { KEY_SHARES,                 &shares_reg_ops },
45 #endif
46   { NULL, NULL }
47 };
48
49
50 /***********************************************************************
51  Open the registry database and initialize the REGISTRY_HOOK cache
52  ***********************************************************************/
53  
54 BOOL init_registry( void )
55 {
56         int i;
57         
58         if ( !init_registry_db() ) {
59                 DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
60                 return False;
61         }
62                 
63         /* build the cache tree of registry hooks */
64         
65         reghook_cache_init();
66         
67         for ( i=0; reg_hooks[i].keyname; i++ ) {
68                 if ( !reghook_cache_add(&reg_hooks[i]) )
69                         return False;
70         }
71
72         if ( DEBUGLEVEL >= 20 )
73                 reghook_dump_cache(20);
74
75         return True;
76 }
77
78 /***********************************************************************
79  High level wrapper function for storing registry subkeys
80  ***********************************************************************/
81  
82 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
83 {
84         if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
85                 return key->hook->ops->store_subkeys( key->name, subkeys );
86                 
87         return False;
88
89 }
90
91 /***********************************************************************
92  High level wrapper function for storing registry values
93  ***********************************************************************/
94  
95 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
96 {
97         if ( check_dynamic_reg_values( key ) )
98                 return False;
99
100         if ( key->hook && key->hook->ops && key->hook->ops->store_values )
101                 return key->hook->ops->store_values( key->name, val );
102
103         return False;
104 }
105
106
107 /***********************************************************************
108  High level wrapper function for enumerating registry subkeys
109  Initialize the TALLOC_CTX if necessary
110  ***********************************************************************/
111
112 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
113 {
114         int result = -1;
115         
116         if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
117                 result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
118
119         return result;
120 }
121
122 /***********************************************************************
123  retreive a specific subkey specified by index.  Caller is 
124  responsible for freeing memory
125  ***********************************************************************/
126
127 BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index )
128 {
129         static REGSUBKEY_CTR *ctr = NULL;
130         static pstring save_path;
131         char *s;
132         
133         *subkey = NULL;
134         
135         /* simple caching for performance; very basic heuristic */
136
137         DEBUG(8,("fetch_reg_keys_specific: Looking for key [%d] of  [%s]\n", key_index, key->name));
138         
139         if ( !ctr ) {
140                 DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
141
142                 if ( !(ctr = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
143                         DEBUG(0,("fetch_reg_keys_specific: talloc() failed!\n"));
144                         return False;
145                 }
146                 
147                 pstrcpy( save_path, key->name );
148                 
149                 if ( fetch_reg_keys( key, ctr) == -1 )
150                         return False;
151                         
152         }
153         /* clear the cache when key_index == 0 or the path has changed */
154         else if ( !key_index || StrCaseCmp( save_path, key->name) ) {
155
156                 DEBUG(8,("fetch_reg_keys_specific: Updating cache of subkeys for [%s]\n", key->name));
157                 
158                 TALLOC_FREE( ctr );
159
160                 if ( !(ctr = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
161                         DEBUG(0,("fetch_reg_keys_specific: talloc() failed!\n"));
162                         return False;
163                 }
164                 
165                 pstrcpy( save_path, key->name );
166                 
167                 if ( fetch_reg_keys( key, ctr) == -1 )
168                         return False;
169         }
170         
171         if ( !(s = regsubkey_ctr_specific_key( ctr, key_index )) )
172                 return False;
173
174         *subkey = SMB_STRDUP( s );
175
176         return True;
177 }
178
179 /***********************************************************************
180  High level wrapper function for enumerating registry values
181  ***********************************************************************/
182
183 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
184 {
185         int result = -1;
186         
187         if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
188                 result = key->hook->ops->fetch_values( key->name, val );
189         
190         /* if the backend lookup returned no data, try the dynamic overlay */
191         
192         if ( result == 0 ) {
193                 result = fetch_dynamic_reg_values( key, val );
194
195                 return ( result != -1 ) ? result : 0;
196         }
197         
198         return result;
199 }
200
201
202 /***********************************************************************
203  retreive a specific subkey specified by index.  Caller is 
204  responsible for freeing memory
205  ***********************************************************************/
206
207 BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
208 {
209         static REGVAL_CTR       *ctr = NULL;
210         static pstring          save_path;
211         REGISTRY_VALUE          *v;
212         
213         *val = NULL;
214         
215         /* simple caching for performance; very basic heuristic */
216         
217         if ( !ctr ) {
218                 DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
219
220                 if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
221                         DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
222                         return False;
223                 }
224
225                 pstrcpy( save_path, key->name );
226                 
227                 if ( fetch_reg_values( key, ctr) == -1 )
228                         return False;
229         }
230         /* clear the cache when val_index == 0 or the path has changed */
231         else if ( !val_index || !strequal(save_path, key->name) ) {
232
233                 DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));         
234                 
235                 TALLOC_FREE( ctr );
236
237                 if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
238                         DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
239                         return False;
240                 }
241
242                 pstrcpy( save_path, key->name );
243                 
244                 if ( fetch_reg_values( key, ctr) == -1 )
245                         return False;
246         }
247         
248         if ( !(v = regval_ctr_specific_value( ctr, val_index )) )
249                 return False;
250
251         *val = dup_registry_value( v );
252
253         return True;
254 }
255
256 /***********************************************************************
257  High level access check for passing the required access mask to the 
258  underlying registry backend
259  ***********************************************************************/
260
261 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, NT_USER_TOKEN *token )
262 {
263         /* use the default security check if the backend has not defined its own */
264         
265         if ( !(key->hook && key->hook->ops && key->hook->ops->reg_access_check) ) {
266                 SEC_DESC *sec_desc;
267                 NTSTATUS status;
268                 
269                 if ( !(sec_desc = construct_registry_sd( get_talloc_ctx() )) )
270                         return False;
271                 
272                 status = registry_access_check( sec_desc, token, requested, granted );          
273                 
274                 return NT_STATUS_IS_OK(status);
275         }
276         
277         return key->hook->ops->reg_access_check( key->name, requested, granted, token );
278 }
279
280