/src/samba/source3/registry/reg_dispatcher.c
Line | Count | Source |
1 | | /* |
2 | | * Unix SMB/CIFS implementation. |
3 | | * Virtual Windows Registry Layer |
4 | | * Copyright (C) Gerald Carter 2002-2005 |
5 | | * Copyright (C) Michael Adam 2006-2008 |
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, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | /* |
22 | | * Implementation of registry frontend view functions. |
23 | | * Functions moved from reg_frontend.c to minimize linker deps. |
24 | | */ |
25 | | |
26 | | #include "includes.h" |
27 | | #include "system/passwd.h" /* uid_wrapper */ |
28 | | #include "registry.h" |
29 | | #include "reg_dispatcher.h" |
30 | | #include "../libcli/security/security.h" |
31 | | |
32 | | #undef DBGC_CLASS |
33 | 0 | #define DBGC_CLASS DBGC_REGISTRY |
34 | | |
35 | | static const struct generic_mapping reg_generic_map = |
36 | | { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL }; |
37 | | |
38 | | /******************************************************************** |
39 | | ********************************************************************/ |
40 | | |
41 | | static WERROR construct_registry_sd(TALLOC_CTX *ctx, struct security_descriptor **psd) |
42 | 0 | { |
43 | 0 | struct security_ace ace[3] = {}; |
44 | 0 | size_t i = 0; |
45 | 0 | struct security_descriptor *sd; |
46 | 0 | struct security_acl *theacl; |
47 | 0 | size_t sd_size; |
48 | | |
49 | | /* basic access for Everyone */ |
50 | |
|
51 | 0 | init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, |
52 | 0 | REG_KEY_READ, 0); |
53 | | |
54 | | /* Full Access 'BUILTIN\Administrators' */ |
55 | |
|
56 | 0 | init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, |
57 | 0 | SEC_ACE_TYPE_ACCESS_ALLOWED, REG_KEY_ALL, 0); |
58 | | |
59 | | /* Full Access 'NT Authority\System' */ |
60 | |
|
61 | 0 | init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED, |
62 | 0 | REG_KEY_ALL, 0); |
63 | | |
64 | | /* create the security descriptor */ |
65 | |
|
66 | 0 | theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace); |
67 | 0 | if (theacl == NULL) { |
68 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
69 | 0 | } |
70 | | |
71 | 0 | sd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE, |
72 | 0 | &global_sid_Builtin_Administrators, |
73 | 0 | &global_sid_System, NULL, theacl, |
74 | 0 | &sd_size); |
75 | 0 | if (sd == NULL) { |
76 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
77 | 0 | } |
78 | | |
79 | 0 | *psd = sd; |
80 | 0 | return WERR_OK; |
81 | 0 | } |
82 | | |
83 | | /*********************************************************************** |
84 | | High level wrapper function for storing registry subkeys |
85 | | ***********************************************************************/ |
86 | | |
87 | | bool store_reg_keys(struct registry_key_handle *key, |
88 | | struct regsubkey_ctr *subkeys) |
89 | 0 | { |
90 | 0 | if (key->ops && key->ops->store_subkeys) |
91 | 0 | return key->ops->store_subkeys(key->name, subkeys); |
92 | | |
93 | 0 | return false; |
94 | 0 | } |
95 | | |
96 | | /*********************************************************************** |
97 | | High level wrapper function for storing registry values |
98 | | ***********************************************************************/ |
99 | | |
100 | | bool store_reg_values(struct registry_key_handle *key, struct regval_ctr *val) |
101 | 0 | { |
102 | 0 | if (key->ops && key->ops->store_values) |
103 | 0 | return key->ops->store_values(key->name, val); |
104 | | |
105 | 0 | return false; |
106 | 0 | } |
107 | | |
108 | | WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey) |
109 | 0 | { |
110 | 0 | if (key->ops && key->ops->create_subkey) { |
111 | 0 | return key->ops->create_subkey(key->name, subkey); |
112 | 0 | } |
113 | | |
114 | 0 | return WERR_NOT_SUPPORTED; |
115 | 0 | } |
116 | | |
117 | | WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy) |
118 | 0 | { |
119 | 0 | if (key->ops && key->ops->delete_subkey) { |
120 | 0 | return key->ops->delete_subkey(key->name, subkey, lazy); |
121 | 0 | } |
122 | | |
123 | 0 | return WERR_NOT_SUPPORTED; |
124 | 0 | } |
125 | | |
126 | | /*********************************************************************** |
127 | | High level wrapper function for enumerating registry subkeys |
128 | | Initialize the TALLOC_CTX if necessary |
129 | | ***********************************************************************/ |
130 | | |
131 | | int fetch_reg_keys(struct registry_key_handle *key, |
132 | | struct regsubkey_ctr *subkey_ctr) |
133 | 0 | { |
134 | 0 | int result = -1; |
135 | |
|
136 | 0 | if (key->ops && key->ops->fetch_subkeys) |
137 | 0 | result = key->ops->fetch_subkeys(key->name, subkey_ctr); |
138 | |
|
139 | 0 | return result; |
140 | 0 | } |
141 | | |
142 | | /*********************************************************************** |
143 | | High level wrapper function for enumerating registry values |
144 | | ***********************************************************************/ |
145 | | |
146 | | int fetch_reg_values(struct registry_key_handle *key, struct regval_ctr *val) |
147 | 0 | { |
148 | 0 | int result = -1; |
149 | |
|
150 | 0 | DEBUG(10, ("fetch_reg_values called for key '%s' (ops %p)\n", key->name, |
151 | 0 | (key->ops) ? (void *)key->ops : NULL)); |
152 | |
|
153 | 0 | if (key->ops && key->ops->fetch_values) |
154 | 0 | result = key->ops->fetch_values(key->name, val); |
155 | |
|
156 | 0 | return result; |
157 | 0 | } |
158 | | |
159 | | /*********************************************************************** |
160 | | High level access check for passing the required access mask to the |
161 | | underlying registry backend |
162 | | ***********************************************************************/ |
163 | | |
164 | | bool regkey_access_check(struct registry_key_handle *key, uint32_t requested, |
165 | | uint32_t *granted, |
166 | | const struct security_token *token ) |
167 | 0 | { |
168 | 0 | struct security_descriptor *sec_desc; |
169 | 0 | NTSTATUS status; |
170 | 0 | WERROR err; |
171 | | |
172 | | /* root free-pass, like we have on all other pipes like samr, lsa, etc. */ |
173 | 0 | if (root_mode()) { |
174 | 0 | *granted = REG_KEY_ALL; |
175 | 0 | return true; |
176 | 0 | } |
177 | | |
178 | | /* use the default security check if the backend has not defined its |
179 | | * own */ |
180 | | |
181 | 0 | if (key->ops && key->ops->reg_access_check) { |
182 | 0 | return key->ops->reg_access_check(key->name, requested, |
183 | 0 | granted, token); |
184 | 0 | } |
185 | | |
186 | 0 | err = regkey_get_secdesc(talloc_tos(), key, &sec_desc); |
187 | |
|
188 | 0 | if (!W_ERROR_IS_OK(err)) { |
189 | 0 | return false; |
190 | 0 | } |
191 | | |
192 | 0 | se_map_generic( &requested, ®_generic_map ); |
193 | |
|
194 | 0 | status =se_access_check(sec_desc, token, requested, granted); |
195 | 0 | TALLOC_FREE(sec_desc); |
196 | 0 | if (!NT_STATUS_IS_OK(status)) { |
197 | 0 | return false; |
198 | 0 | } |
199 | | |
200 | 0 | return NT_STATUS_IS_OK(status); |
201 | 0 | } |
202 | | |
203 | | WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, struct registry_key_handle *key, |
204 | | struct security_descriptor **psecdesc) |
205 | 0 | { |
206 | 0 | struct security_descriptor *secdesc; |
207 | 0 | WERROR werr; |
208 | |
|
209 | 0 | if (key->ops && key->ops->get_secdesc) { |
210 | 0 | werr = key->ops->get_secdesc(mem_ctx, key->name, psecdesc); |
211 | 0 | if (W_ERROR_IS_OK(werr)) { |
212 | 0 | return WERR_OK; |
213 | 0 | } |
214 | 0 | } |
215 | | |
216 | 0 | werr = construct_registry_sd(mem_ctx, &secdesc); |
217 | 0 | if (!W_ERROR_IS_OK(werr)) { |
218 | 0 | return werr; |
219 | 0 | } |
220 | | |
221 | 0 | *psecdesc = secdesc; |
222 | 0 | return WERR_OK; |
223 | 0 | } |
224 | | |
225 | | WERROR regkey_set_secdesc(struct registry_key_handle *key, |
226 | | struct security_descriptor *psecdesc) |
227 | 0 | { |
228 | 0 | if (key->ops && key->ops->set_secdesc) { |
229 | 0 | return key->ops->set_secdesc(key->name, psecdesc); |
230 | 0 | } |
231 | | |
232 | 0 | return WERR_ACCESS_DENIED; |
233 | 0 | } |
234 | | |
235 | | /** |
236 | | * Check whether the in-memory version of the subkyes of a |
237 | | * registry key needs update from disk. |
238 | | */ |
239 | | bool reg_subkeys_need_update(struct registry_key_handle *key, |
240 | | struct regsubkey_ctr *subkeys) |
241 | 0 | { |
242 | 0 | if (key->ops && key->ops->subkeys_need_update) |
243 | 0 | { |
244 | 0 | return key->ops->subkeys_need_update(subkeys); |
245 | 0 | } |
246 | | |
247 | 0 | return true; |
248 | 0 | } |
249 | | |
250 | | /** |
251 | | * Check whether the in-memory version of the values of a |
252 | | * registry key needs update from disk. |
253 | | */ |
254 | | bool reg_values_need_update(struct registry_key_handle *key, |
255 | | struct regval_ctr *values) |
256 | 0 | { |
257 | 0 | if (key->ops && key->ops->values_need_update) |
258 | 0 | { |
259 | 0 | return key->ops->values_need_update(values); |
260 | 0 | } |
261 | | |
262 | 0 | return true; |
263 | 0 | } |
264 | | |