1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | Transparent registry backend handling
|
---|
4 | Copyright (C) Jelmer Vernooij 2003-2007.
|
---|
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 3 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 | #include "includes.h"
|
---|
22 | #include "../lib/util/dlinklist.h"
|
---|
23 | #include "lib/registry/registry.h"
|
---|
24 | #include "system/filesys.h"
|
---|
25 |
|
---|
26 | struct reg_key_path {
|
---|
27 | uint32_t predefined_key;
|
---|
28 | const char **elements;
|
---|
29 | };
|
---|
30 |
|
---|
31 | struct registry_local {
|
---|
32 | const struct registry_operations *ops;
|
---|
33 |
|
---|
34 | struct mountpoint {
|
---|
35 | struct reg_key_path path;
|
---|
36 | struct hive_key *key;
|
---|
37 | struct mountpoint *prev, *next;
|
---|
38 | } *mountpoints;
|
---|
39 | };
|
---|
40 |
|
---|
41 | struct local_key {
|
---|
42 | struct registry_key global;
|
---|
43 | struct reg_key_path path;
|
---|
44 | struct hive_key *hive_key;
|
---|
45 | };
|
---|
46 |
|
---|
47 |
|
---|
48 | struct registry_key *reg_import_hive_key(struct registry_context *ctx,
|
---|
49 | struct hive_key *hive,
|
---|
50 | uint32_t predefined_key,
|
---|
51 | const char **elements)
|
---|
52 | {
|
---|
53 | struct local_key *local_key;
|
---|
54 | struct reg_key_path parent_path;
|
---|
55 |
|
---|
56 | parent_path.predefined_key = predefined_key;
|
---|
57 | parent_path.elements = elements;
|
---|
58 |
|
---|
59 | local_key = talloc(ctx, struct local_key);
|
---|
60 | if (local_key != NULL) {
|
---|
61 | local_key->hive_key = talloc_reference(local_key, hive);
|
---|
62 | local_key->global.context = talloc_reference(local_key, ctx);
|
---|
63 | local_key->path = parent_path;
|
---|
64 | }
|
---|
65 |
|
---|
66 | return (struct registry_key *)local_key;
|
---|
67 | }
|
---|
68 |
|
---|
69 |
|
---|
70 | static WERROR local_open_key(TALLOC_CTX *mem_ctx,
|
---|
71 | struct registry_key *parent,
|
---|
72 | const char *path,
|
---|
73 | struct registry_key **result)
|
---|
74 | {
|
---|
75 | char *orig, *curbegin, *curend;
|
---|
76 | struct local_key *local_parent = talloc_get_type(parent,
|
---|
77 | struct local_key);
|
---|
78 | struct hive_key *curkey = local_parent->hive_key;
|
---|
79 | WERROR error;
|
---|
80 | const char **elements = NULL;
|
---|
81 | int el;
|
---|
82 |
|
---|
83 | if (path == NULL || path[0] == '\0') {
|
---|
84 | return WERR_INVALID_PARAM;
|
---|
85 | }
|
---|
86 |
|
---|
87 | orig = talloc_strdup(mem_ctx, path);
|
---|
88 | W_ERROR_HAVE_NO_MEMORY(orig);
|
---|
89 | curbegin = orig;
|
---|
90 | curend = strchr(orig, '\\');
|
---|
91 |
|
---|
92 | if (local_parent->path.elements != NULL) {
|
---|
93 | elements = talloc_array(mem_ctx, const char *,
|
---|
94 | str_list_length(local_parent->path.elements) + 1);
|
---|
95 | W_ERROR_HAVE_NO_MEMORY(elements);
|
---|
96 | for (el = 0; local_parent->path.elements[el] != NULL; el++) {
|
---|
97 | elements[el] = talloc_reference(elements,
|
---|
98 | local_parent->path.elements[el]);
|
---|
99 | }
|
---|
100 | elements[el] = NULL;
|
---|
101 | } else {
|
---|
102 | elements = NULL;
|
---|
103 | el = 0;
|
---|
104 | }
|
---|
105 |
|
---|
106 | do {
|
---|
107 | if (curend != NULL)
|
---|
108 | *curend = '\0';
|
---|
109 | elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
|
---|
110 | W_ERROR_HAVE_NO_MEMORY(elements);
|
---|
111 | elements[el] = talloc_strdup(elements, curbegin);
|
---|
112 | W_ERROR_HAVE_NO_MEMORY(elements[el]);
|
---|
113 | el++;
|
---|
114 | elements[el] = NULL;
|
---|
115 | error = hive_get_key_by_name(mem_ctx, curkey,
|
---|
116 | curbegin, &curkey);
|
---|
117 | if (!W_ERROR_IS_OK(error)) {
|
---|
118 | DEBUG(2, ("Opening key %s failed: %s\n", curbegin,
|
---|
119 | win_errstr(error)));
|
---|
120 | talloc_free(orig);
|
---|
121 | return error;
|
---|
122 | }
|
---|
123 | if (curend == NULL)
|
---|
124 | break;
|
---|
125 | curbegin = curend + 1;
|
---|
126 | curend = strchr(curbegin, '\\');
|
---|
127 | } while (curbegin[0] != '\0');
|
---|
128 | talloc_free(orig);
|
---|
129 |
|
---|
130 | *result = reg_import_hive_key(local_parent->global.context, curkey,
|
---|
131 | local_parent->path.predefined_key,
|
---|
132 | talloc_steal(curkey, elements));
|
---|
133 |
|
---|
134 | return WERR_OK;
|
---|
135 | }
|
---|
136 |
|
---|
137 | WERROR local_get_predefined_key(struct registry_context *ctx,
|
---|
138 | uint32_t key_id, struct registry_key **key)
|
---|
139 | {
|
---|
140 | struct registry_local *rctx = talloc_get_type(ctx,
|
---|
141 | struct registry_local);
|
---|
142 | struct mountpoint *mp;
|
---|
143 |
|
---|
144 | for (mp = rctx->mountpoints; mp != NULL; mp = mp->next) {
|
---|
145 | if (mp->path.predefined_key == key_id &&
|
---|
146 | mp->path.elements == NULL)
|
---|
147 | break;
|
---|
148 | }
|
---|
149 |
|
---|
150 | if (mp == NULL)
|
---|
151 | return WERR_BADFILE;
|
---|
152 |
|
---|
153 | *key = reg_import_hive_key(ctx, mp->key,
|
---|
154 | mp->path.predefined_key,
|
---|
155 | mp->path.elements);
|
---|
156 |
|
---|
157 | return WERR_OK;
|
---|
158 | }
|
---|
159 |
|
---|
160 | static WERROR local_enum_key(TALLOC_CTX *mem_ctx,
|
---|
161 | const struct registry_key *key, uint32_t idx,
|
---|
162 | const char **name,
|
---|
163 | const char **keyclass,
|
---|
164 | NTTIME *last_changed_time)
|
---|
165 | {
|
---|
166 | const struct local_key *local = (const struct local_key *)key;
|
---|
167 |
|
---|
168 | return hive_enum_key(mem_ctx, local->hive_key, idx, name, keyclass,
|
---|
169 | last_changed_time);
|
---|
170 | }
|
---|
171 |
|
---|
172 | static WERROR local_create_key(TALLOC_CTX *mem_ctx,
|
---|
173 | struct registry_key *parent,
|
---|
174 | const char *path,
|
---|
175 | const char *key_class,
|
---|
176 | struct security_descriptor *security,
|
---|
177 | struct registry_key **result)
|
---|
178 | {
|
---|
179 | char *orig, *curbegin, *curend;
|
---|
180 | struct local_key *local_parent = talloc_get_type(parent,
|
---|
181 | struct local_key);
|
---|
182 | struct hive_key *curkey = local_parent->hive_key;
|
---|
183 | WERROR error;
|
---|
184 | const char **elements = NULL;
|
---|
185 | int el;
|
---|
186 |
|
---|
187 | if (path == NULL || path[0] == '\0') {
|
---|
188 | return WERR_INVALID_PARAM;
|
---|
189 | }
|
---|
190 |
|
---|
191 | orig = talloc_strdup(mem_ctx, path);
|
---|
192 | W_ERROR_HAVE_NO_MEMORY(orig);
|
---|
193 | curbegin = orig;
|
---|
194 | curend = strchr(orig, '\\');
|
---|
195 |
|
---|
196 | if (local_parent->path.elements != NULL) {
|
---|
197 | elements = talloc_array(mem_ctx, const char *,
|
---|
198 | str_list_length(local_parent->path.elements) + 1);
|
---|
199 | W_ERROR_HAVE_NO_MEMORY(elements);
|
---|
200 | for (el = 0; local_parent->path.elements[el] != NULL; el++) {
|
---|
201 | elements[el] = talloc_reference(elements,
|
---|
202 | local_parent->path.elements[el]);
|
---|
203 | }
|
---|
204 | elements[el] = NULL;
|
---|
205 | } else {
|
---|
206 | elements = NULL;
|
---|
207 | el = 0;
|
---|
208 | }
|
---|
209 |
|
---|
210 | do {
|
---|
211 | if (curend != NULL)
|
---|
212 | *curend = '\0';
|
---|
213 | elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
|
---|
214 | W_ERROR_HAVE_NO_MEMORY(elements);
|
---|
215 | elements[el] = talloc_strdup(elements, curbegin);
|
---|
216 | W_ERROR_HAVE_NO_MEMORY(elements[el]);
|
---|
217 | el++;
|
---|
218 | elements[el] = NULL;
|
---|
219 | error = hive_get_key_by_name(mem_ctx, curkey,
|
---|
220 | curbegin, &curkey);
|
---|
221 | if (W_ERROR_EQUAL(error, WERR_BADFILE)) {
|
---|
222 | error = hive_key_add_name(mem_ctx, curkey, curbegin,
|
---|
223 | key_class, security,
|
---|
224 | &curkey);
|
---|
225 | }
|
---|
226 | if (!W_ERROR_IS_OK(error)) {
|
---|
227 | DEBUG(2, ("Open/Creation of key %s failed: %s\n",
|
---|
228 | curbegin, win_errstr(error)));
|
---|
229 | talloc_free(orig);
|
---|
230 | return error;
|
---|
231 | }
|
---|
232 | if (curend == NULL)
|
---|
233 | break;
|
---|
234 | curbegin = curend + 1;
|
---|
235 | curend = strchr(curbegin, '\\');
|
---|
236 | } while (curbegin[0] != '\0');
|
---|
237 | talloc_free(orig);
|
---|
238 |
|
---|
239 | *result = reg_import_hive_key(local_parent->global.context, curkey,
|
---|
240 | local_parent->path.predefined_key,
|
---|
241 | talloc_steal(curkey, elements));
|
---|
242 |
|
---|
243 | return WERR_OK;
|
---|
244 | }
|
---|
245 |
|
---|
246 | static WERROR local_set_value(struct registry_key *key, const char *name,
|
---|
247 | uint32_t type, const DATA_BLOB data)
|
---|
248 | {
|
---|
249 | struct local_key *local = (struct local_key *)key;
|
---|
250 |
|
---|
251 | if (name == NULL) {
|
---|
252 | return WERR_INVALID_PARAM;
|
---|
253 | }
|
---|
254 |
|
---|
255 | return hive_key_set_value(local->hive_key, name, type, data);
|
---|
256 | }
|
---|
257 |
|
---|
258 | static WERROR local_get_value(TALLOC_CTX *mem_ctx,
|
---|
259 | const struct registry_key *key,
|
---|
260 | const char *name, uint32_t *type, DATA_BLOB *data)
|
---|
261 | {
|
---|
262 | const struct local_key *local = (const struct local_key *)key;
|
---|
263 |
|
---|
264 | if (name == NULL) {
|
---|
265 | return WERR_INVALID_PARAM;
|
---|
266 | }
|
---|
267 |
|
---|
268 | return hive_get_value(mem_ctx, local->hive_key, name, type, data);
|
---|
269 | }
|
---|
270 |
|
---|
271 | static WERROR local_enum_value(TALLOC_CTX *mem_ctx,
|
---|
272 | const struct registry_key *key, uint32_t idx,
|
---|
273 | const char **name,
|
---|
274 | uint32_t *type,
|
---|
275 | DATA_BLOB *data)
|
---|
276 | {
|
---|
277 | const struct local_key *local = (const struct local_key *)key;
|
---|
278 |
|
---|
279 | return hive_get_value_by_index(mem_ctx, local->hive_key, idx,
|
---|
280 | name, type, data);
|
---|
281 | }
|
---|
282 |
|
---|
283 | static WERROR local_delete_key(TALLOC_CTX *mem_ctx, struct registry_key *key,
|
---|
284 | const char *name)
|
---|
285 | {
|
---|
286 | const struct local_key *local = (const struct local_key *)key;
|
---|
287 |
|
---|
288 | if (name == NULL) {
|
---|
289 | return WERR_INVALID_PARAM;
|
---|
290 | }
|
---|
291 |
|
---|
292 | return hive_key_del(mem_ctx, local->hive_key, name);
|
---|
293 | }
|
---|
294 |
|
---|
295 | static WERROR local_delete_value(TALLOC_CTX *mem_ctx, struct registry_key *key,
|
---|
296 | const char *name)
|
---|
297 | {
|
---|
298 | const struct local_key *local = (const struct local_key *)key;
|
---|
299 |
|
---|
300 | if (name == NULL) {
|
---|
301 | return WERR_INVALID_PARAM;
|
---|
302 | }
|
---|
303 |
|
---|
304 | return hive_key_del_value(mem_ctx, local->hive_key, name);
|
---|
305 | }
|
---|
306 |
|
---|
307 | static WERROR local_flush_key(struct registry_key *key)
|
---|
308 | {
|
---|
309 | const struct local_key *local = (const struct local_key *)key;
|
---|
310 |
|
---|
311 | return hive_key_flush(local->hive_key);
|
---|
312 | }
|
---|
313 |
|
---|
314 | static WERROR local_get_key_info(TALLOC_CTX *mem_ctx,
|
---|
315 | const struct registry_key *key,
|
---|
316 | const char **classname,
|
---|
317 | uint32_t *num_subkeys,
|
---|
318 | uint32_t *num_values,
|
---|
319 | NTTIME *last_change_time,
|
---|
320 | uint32_t *max_subkeynamelen,
|
---|
321 | uint32_t *max_valnamelen,
|
---|
322 | uint32_t *max_valbufsize)
|
---|
323 | {
|
---|
324 | const struct local_key *local = (const struct local_key *)key;
|
---|
325 |
|
---|
326 | return hive_key_get_info(mem_ctx, local->hive_key,
|
---|
327 | classname, num_subkeys, num_values,
|
---|
328 | last_change_time, max_subkeynamelen,
|
---|
329 | max_valnamelen, max_valbufsize);
|
---|
330 | }
|
---|
331 | static WERROR local_get_sec_desc(TALLOC_CTX *mem_ctx,
|
---|
332 | const struct registry_key *key,
|
---|
333 | struct security_descriptor **security)
|
---|
334 | {
|
---|
335 | const struct local_key *local = (const struct local_key *)key;
|
---|
336 |
|
---|
337 | return hive_get_sec_desc(mem_ctx, local->hive_key, security);
|
---|
338 | }
|
---|
339 | static WERROR local_set_sec_desc(struct registry_key *key,
|
---|
340 | const struct security_descriptor *security)
|
---|
341 | {
|
---|
342 | const struct local_key *local = (const struct local_key *)key;
|
---|
343 |
|
---|
344 | return hive_set_sec_desc(local->hive_key, security);
|
---|
345 | }
|
---|
346 | const static struct registry_operations local_ops = {
|
---|
347 | .name = "local",
|
---|
348 | .open_key = local_open_key,
|
---|
349 | .get_predefined_key = local_get_predefined_key,
|
---|
350 | .enum_key = local_enum_key,
|
---|
351 | .create_key = local_create_key,
|
---|
352 | .set_value = local_set_value,
|
---|
353 | .get_value = local_get_value,
|
---|
354 | .enum_value = local_enum_value,
|
---|
355 | .delete_key = local_delete_key,
|
---|
356 | .delete_value = local_delete_value,
|
---|
357 | .flush_key = local_flush_key,
|
---|
358 | .get_key_info = local_get_key_info,
|
---|
359 | .get_sec_desc = local_get_sec_desc,
|
---|
360 | .set_sec_desc = local_set_sec_desc,
|
---|
361 | };
|
---|
362 |
|
---|
363 | WERROR reg_open_local(TALLOC_CTX *mem_ctx, struct registry_context **ctx)
|
---|
364 | {
|
---|
365 | struct registry_local *ret = talloc_zero(mem_ctx,
|
---|
366 | struct registry_local);
|
---|
367 |
|
---|
368 | W_ERROR_HAVE_NO_MEMORY(ret);
|
---|
369 |
|
---|
370 | ret->ops = &local_ops;
|
---|
371 |
|
---|
372 | *ctx = (struct registry_context *)ret;
|
---|
373 |
|
---|
374 | return WERR_OK;
|
---|
375 | }
|
---|
376 |
|
---|
377 | WERROR reg_mount_hive(struct registry_context *rctx,
|
---|
378 | struct hive_key *hive_key,
|
---|
379 | uint32_t key_id,
|
---|
380 | const char **elements)
|
---|
381 | {
|
---|
382 | struct registry_local *reg_local = talloc_get_type(rctx,
|
---|
383 | struct registry_local);
|
---|
384 | struct mountpoint *mp;
|
---|
385 | unsigned int i = 0;
|
---|
386 |
|
---|
387 | mp = talloc(rctx, struct mountpoint);
|
---|
388 | W_ERROR_HAVE_NO_MEMORY(mp);
|
---|
389 | mp->path.predefined_key = key_id;
|
---|
390 | mp->prev = mp->next = NULL;
|
---|
391 | mp->key = hive_key;
|
---|
392 | if (elements != NULL && str_list_length(elements) != 0) {
|
---|
393 | mp->path.elements = talloc_array(mp, const char *,
|
---|
394 | str_list_length(elements));
|
---|
395 | W_ERROR_HAVE_NO_MEMORY(mp->path.elements);
|
---|
396 | for (i = 0; elements[i] != NULL; i++) {
|
---|
397 | mp->path.elements[i] = talloc_reference(mp->path.elements,
|
---|
398 | elements[i]);
|
---|
399 | }
|
---|
400 | mp->path.elements[i] = NULL;
|
---|
401 | } else {
|
---|
402 | mp->path.elements = NULL;
|
---|
403 | }
|
---|
404 |
|
---|
405 | DLIST_ADD(reg_local->mountpoints, mp);
|
---|
406 |
|
---|
407 | return WERR_OK;
|
---|
408 | }
|
---|