r7995: * privileges are local except when they're *not*
[tprouty/samba.git] / source / 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   { KEY_EVENTLOG,               &eventlog_ops }, 
42   { KEY_SHARES,                 &shares_reg_ops },
43 #endif
44   { NULL, NULL }
45 };
46
47
48 /***********************************************************************
49  Open the registry database and initialize the REGISTRY_HOOK cache
50  ***********************************************************************/
51  
52 BOOL init_registry( void )
53 {
54         int i;
55         
56         if ( !init_registry_db() ) {
57                 DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
58                 return False;
59         }
60                 
61         /* build the cache tree of registry hooks */
62         
63         reghook_cache_init();
64         
65         for ( i=0; reg_hooks[i].keyname; i++ ) {
66                 if ( !reghook_cache_add(&reg_hooks[i]) )
67                         return False;
68         }
69
70         if ( DEBUGLEVEL >= 20 )
71                 reghook_dump_cache(20);
72
73         return True;
74 }
75
76 /***********************************************************************
77  High level wrapper function for storing registry subkeys
78  ***********************************************************************/
79  
80 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
81 {
82         if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
83                 return key->hook->ops->store_subkeys( key->name, subkeys );
84                 
85         return False;
86
87 }
88
89 /***********************************************************************
90  High level wrapper function for storing registry values
91  ***********************************************************************/
92  
93 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
94 {
95         if ( check_dynamic_reg_values( key ) )
96                 return False;
97
98         if ( key->hook && key->hook->ops && key->hook->ops->store_values )
99                 return key->hook->ops->store_values( key->name, val );
100
101         return False;
102 }
103
104
105 /***********************************************************************
106  High level wrapper function for enumerating registry subkeys
107  Initialize the TALLOC_CTX if necessary
108  ***********************************************************************/
109
110 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
111 {
112         int result = -1;
113         
114         if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
115                 result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
116
117         return result;
118 }
119
120 /***********************************************************************
121  retreive a specific subkey specified by index.  Caller is 
122  responsible for freeing memory
123  ***********************************************************************/
124
125 BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index )
126 {
127         static REGSUBKEY_CTR ctr;
128         static pstring save_path;
129         static BOOL ctr_init = False;
130         char *s;
131         
132         *subkey = NULL;
133         
134         /* simple caching for performance; very basic heuristic */
135
136         DEBUG(8,("fetch_reg_keys_specific: Looking for key [%d] of  [%s]\n", key_index, key->name));
137         
138         if ( !ctr_init ) {
139                 DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
140                 regsubkey_ctr_init( &ctr );
141                 
142                 pstrcpy( save_path, key->name );
143                 
144                 if ( fetch_reg_keys( key, &ctr) == -1 )
145                         return False;
146                         
147                 ctr_init = True;
148         }
149         /* clear the cache when key_index == 0 or the path has changed */
150         else if ( !key_index || StrCaseCmp( save_path, key->name) ) {
151
152                 DEBUG(8,("fetch_reg_keys_specific: Updating cache of subkeys for [%s]\n", key->name));
153                 
154                 regsubkey_ctr_destroy( &ctr );  
155                 regsubkey_ctr_init( &ctr );
156                 
157                 pstrcpy( save_path, key->name );
158                 
159                 if ( fetch_reg_keys( key, &ctr) == -1 )
160                         return False;
161         }
162         
163         if ( !(s = regsubkey_ctr_specific_key( &ctr, key_index )) )
164                 return False;
165
166         *subkey = SMB_STRDUP( s );
167
168         return True;
169 }
170
171 /***********************************************************************
172  High level wrapper function for enumerating registry values
173  ***********************************************************************/
174
175 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
176 {
177         int result = -1;
178         
179         if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
180                 result = key->hook->ops->fetch_values( key->name, val );
181         
182         /* if the backend lookup returned no data, try the dynamic overlay */
183         
184         if ( result == 0 ) {
185                 result = fetch_dynamic_reg_values( key, val );
186
187                 return ( result != -1 ) ? result : 0;
188         }
189         
190         return result;
191 }
192
193
194 /***********************************************************************
195  retreive a specific subkey specified by index.  Caller is 
196  responsible for freeing memory
197  ***********************************************************************/
198
199 BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
200 {
201         static REGVAL_CTR       ctr;
202         static pstring          save_path;
203         static BOOL             ctr_init = False;
204         REGISTRY_VALUE          *v;
205         
206         *val = NULL;
207         
208         /* simple caching for performance; very basic heuristic */
209         
210         if ( !ctr_init ) {
211                 DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
212
213                 regval_ctr_init( &ctr );
214                 
215                 pstrcpy( save_path, key->name );
216                 
217                 if ( fetch_reg_values( key, &ctr) == -1 )
218                         return False;
219                         
220                 ctr_init = True;
221         }
222         /* clear the cache when val_index == 0 or the path has changed */
223         else if ( !val_index || !strequal(save_path, key->name) ) {
224
225                 DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));         
226                 
227                 regval_ctr_destroy( &ctr );     
228                 regval_ctr_init( &ctr );
229                 
230                 pstrcpy( save_path, key->name );
231                 
232                 if ( fetch_reg_values( key, &ctr) == -1 )
233                         return False;
234         }
235         
236         if ( !(v = regval_ctr_specific_value( &ctr, val_index )) )
237                 return False;
238
239         *val = dup_registry_value( v );
240
241         return True;
242 }
243
244 /***********************************************************************
245  High level access check for passing the required access mask to the 
246  underlying registry backend
247  ***********************************************************************/
248
249 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, NT_USER_TOKEN *token )
250 {
251         /* use the default security check if the backend has not defined its own */
252         
253         if ( !(key->hook && key->hook->ops && key->hook->ops->reg_access_check) ) {
254                 SEC_DESC *sec_desc;
255                 NTSTATUS status;
256                 
257                 if ( !(sec_desc = construct_registry_sd( get_talloc_ctx() )) )
258                         return False;
259                 
260                 status = registry_access_check( sec_desc, token, requested, granted );          
261                 
262                 return NT_STATUS_IS_OK(status);
263         }
264         
265         return key->hook->ops->reg_access_check( key->name, requested, granted, token );
266 }
267
268