r23779: Change from v2 or later to v3 or later.
[kai/samba.git] / source / registry / reg_frontend_hilvl.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *  Copyright (C) Michael Adam 2006
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /* 
23  * Implementation of registry frontend view functions. 
24  * Functions moved from reg_frontend.c to minimize linker deps.
25  */
26
27 #include "includes.h"
28
29
30 static struct generic_mapping reg_generic_map = 
31         { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
32
33 /********************************************************************
34 ********************************************************************/
35
36 static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
37 {
38         SEC_ACE ace[2]; 
39         SEC_ACCESS mask;
40         size_t i = 0;
41         SEC_DESC *sd;
42         SEC_ACL *acl;
43         size_t sd_size;
44
45         /* basic access for Everyone */
46         
47         init_sec_access(&mask, REG_KEY_READ );
48         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
49         
50         /* Full Access 'BUILTIN\Administrators' */
51         
52         init_sec_access(&mask, REG_KEY_ALL );
53         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
54         
55         
56         /* create the security descriptor */
57         
58         if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
59                 return NULL;
60
61         if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
62                 return NULL;
63
64         return sd;
65 }
66
67 /***********************************************************************
68  High level wrapper function for storing registry subkeys
69  ***********************************************************************/
70  
71 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
72 {
73         if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
74                 return key->hook->ops->store_subkeys( key->name, subkeys );
75                 
76         return False;
77
78 }
79
80 /***********************************************************************
81  High level wrapper function for storing registry values
82  ***********************************************************************/
83  
84 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
85 {
86         if ( check_dynamic_reg_values( key ) )
87                 return False;
88
89         if ( key->hook && key->hook->ops && key->hook->ops->store_values )
90                 return key->hook->ops->store_values( key->name, val );
91
92         return False;
93 }
94
95 /***********************************************************************
96  High level wrapper function for enumerating registry subkeys
97  Initialize the TALLOC_CTX if necessary
98  ***********************************************************************/
99
100 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
101 {
102         int result = -1;
103         
104         if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
105                 result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
106
107         return result;
108 }
109
110 /***********************************************************************
111  High level wrapper function for enumerating registry values
112  ***********************************************************************/
113
114 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
115 {
116         int result = -1;
117         
118         if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
119                 result = key->hook->ops->fetch_values( key->name, val );
120         
121         /* if the backend lookup returned no data, try the dynamic overlay */
122         
123         if ( result == 0 ) {
124                 result = fetch_dynamic_reg_values( key, val );
125
126                 return ( result != -1 ) ? result : 0;
127         }
128         
129         return result;
130 }
131
132 /***********************************************************************
133  High level access check for passing the required access mask to the 
134  underlying registry backend
135  ***********************************************************************/
136
137 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
138                           const struct nt_user_token *token )
139 {
140         SEC_DESC *sec_desc;
141         NTSTATUS status;
142         WERROR err;
143         TALLOC_CTX *mem_ctx;
144
145         /* use the default security check if the backend has not defined its
146          * own */
147
148         if (key->hook && key->hook->ops && key->hook->ops->reg_access_check) {
149                 return key->hook->ops->reg_access_check( key->name, requested,
150                                                          granted, token );
151         }
152
153         /*
154          * The secdesc routines can't yet cope with a NULL talloc ctx sanely.
155          */
156
157         if (!(mem_ctx = talloc_init("regkey_access_check"))) {
158                 return False;
159         }
160
161         err = regkey_get_secdesc(mem_ctx, key, &sec_desc);
162
163         if (!W_ERROR_IS_OK(err)) {
164                 TALLOC_FREE(mem_ctx);
165                 return False;
166         }
167
168         se_map_generic( &requested, &reg_generic_map );
169
170         if (!se_access_check(sec_desc, token, requested, granted, &status)) {
171                 TALLOC_FREE(mem_ctx);
172                 return False;
173         }
174
175         TALLOC_FREE(mem_ctx);
176         return NT_STATUS_IS_OK(status);
177 }
178
179 WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
180                           struct security_descriptor **psecdesc)
181 {
182         struct security_descriptor *secdesc;
183
184         if (key->hook && key->hook->ops && key->hook->ops->get_secdesc) {
185                 WERROR err;
186
187                 err = key->hook->ops->get_secdesc(mem_ctx, key->name,
188                                                   psecdesc);
189                 if (W_ERROR_IS_OK(err)) {
190                         return WERR_OK;
191                 }
192         }
193
194         if (!(secdesc = construct_registry_sd(mem_ctx))) {
195                 return WERR_NOMEM;
196         }
197
198         *psecdesc = secdesc;
199         return WERR_OK;
200 }