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 | local_key->hive_key = talloc_steal(local_key, hive);
|
---|
61 | local_key->global.context = talloc_reference(local_key, ctx);
|
---|
62 | local_key->path = parent_path;
|
---|
63 |
|
---|
64 | return (struct registry_key *)local_key;
|
---|
65 | }
|
---|
66 |
|
---|
67 |
|
---|
68 | static WERROR local_open_key(TALLOC_CTX *mem_ctx,
|
---|
69 | struct registry_key *parent,
|
---|
70 | const char *path,
|
---|
71 | struct registry_key **result)
|
---|
72 | {
|
---|
73 | char *orig = talloc_strdup(mem_ctx, path),
|
---|
74 | *curbegin = orig,
|
---|
75 | *curend = strchr(orig, '\\');
|
---|
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 (local_parent->path.elements != NULL) {
|
---|
84 | elements = talloc_array(mem_ctx, const char *,
|
---|
85 | str_list_length(local_parent->path.elements) + 1);
|
---|
86 | for (el = 0; local_parent->path.elements[el] != NULL; el++) {
|
---|
87 | elements[el] = talloc_reference(elements,
|
---|
88 | local_parent->path.elements[el]);
|
---|
89 | }
|
---|
90 | elements[el] = NULL;
|
---|
91 | } else {
|
---|
92 | elements = NULL;
|
---|
93 | el = 0;
|
---|
94 | }
|
---|
95 |
|
---|
96 | while (curbegin != NULL && *curbegin) {
|
---|
97 | if (curend != NULL)
|
---|
98 | *curend = '\0';
|
---|
99 | elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
|
---|
100 | elements[el] = talloc_strdup(elements, curbegin);
|
---|
101 | el++;
|
---|
102 | elements[el] = NULL;
|
---|
103 | error = hive_get_key_by_name(mem_ctx, curkey,
|
---|
104 | curbegin, &curkey);
|
---|
105 | if (!W_ERROR_IS_OK(error)) {
|
---|
106 | DEBUG(2, ("Opening key %s failed: %s\n", curbegin,
|
---|
107 | win_errstr(error)));
|
---|
108 | talloc_free(orig);
|
---|
109 | return error;
|
---|
110 | }
|
---|
111 | if (curend == NULL)
|
---|
112 | break;
|
---|
113 | curbegin = curend + 1;
|
---|
114 | curend = strchr(curbegin, '\\');
|
---|
115 | }
|
---|
116 | talloc_free(orig);
|
---|
117 |
|
---|
118 | *result = reg_import_hive_key(local_parent->global.context, curkey,
|
---|
119 | local_parent->path.predefined_key,
|
---|
120 | talloc_steal(curkey, elements));
|
---|
121 |
|
---|
122 | return WERR_OK;
|
---|
123 | }
|
---|
124 |
|
---|
125 | WERROR local_get_predefined_key(struct registry_context *ctx,
|
---|
126 | uint32_t key_id, struct registry_key **key)
|
---|
127 | {
|
---|
128 | struct registry_local *rctx = talloc_get_type(ctx,
|
---|
129 | struct registry_local);
|
---|
130 | struct mountpoint *mp;
|
---|
131 |
|
---|
132 | for (mp = rctx->mountpoints; mp != NULL; mp = mp->next) {
|
---|
133 | if (mp->path.predefined_key == key_id &&
|
---|
134 | mp->path.elements == NULL)
|
---|
135 | break;
|
---|
136 | }
|
---|
137 |
|
---|
138 | if (mp == NULL)
|
---|
139 | return WERR_BADFILE;
|
---|
140 |
|
---|
141 | *key = reg_import_hive_key(ctx, mp->key,
|
---|
142 | mp->path.predefined_key,
|
---|
143 | mp->path.elements);
|
---|
144 |
|
---|
145 | return WERR_OK;
|
---|
146 | }
|
---|
147 |
|
---|
148 | static WERROR local_enum_key(TALLOC_CTX *mem_ctx,
|
---|
149 | const struct registry_key *key, uint32_t idx,
|
---|
150 | const char **name,
|
---|
151 | const char **keyclass,
|
---|
152 | NTTIME *last_changed_time)
|
---|
153 | {
|
---|
154 | const struct local_key *local = (const struct local_key *)key;
|
---|
155 |
|
---|
156 | return hive_enum_key(mem_ctx, local->hive_key, idx, name, keyclass,
|
---|
157 | last_changed_time);
|
---|
158 | }
|
---|
159 |
|
---|
160 | static WERROR local_create_key(TALLOC_CTX *mem_ctx,
|
---|
161 | struct registry_key *parent_key,
|
---|
162 | const char *name,
|
---|
163 | const char *key_class,
|
---|
164 | struct security_descriptor *security,
|
---|
165 | struct registry_key **key)
|
---|
166 | {
|
---|
167 | struct local_key *local_parent;
|
---|
168 | struct hive_key *hivekey;
|
---|
169 | const char **elements;
|
---|
170 | int i;
|
---|
171 | const char *last_part;
|
---|
172 |
|
---|
173 | last_part = strrchr(name, '\\');
|
---|
174 | if (last_part == NULL) {
|
---|
175 | last_part = name;
|
---|
176 | local_parent = (struct local_key *)parent_key;
|
---|
177 | } else {
|
---|
178 | W_ERROR_NOT_OK_RETURN(reg_open_key(mem_ctx, parent_key,
|
---|
179 | talloc_strndup(mem_ctx, name, last_part-name),
|
---|
180 | (struct registry_key **)&local_parent));
|
---|
181 | last_part++;
|
---|
182 | }
|
---|
183 |
|
---|
184 | W_ERROR_NOT_OK_RETURN(hive_key_add_name(mem_ctx, local_parent->hive_key,
|
---|
185 | last_part, key_class, security,
|
---|
186 | &hivekey));
|
---|
187 |
|
---|
188 | if (local_parent->path.elements != NULL) {
|
---|
189 | elements = talloc_array(hivekey, const char *,
|
---|
190 | str_list_length(local_parent->path.elements)+2);
|
---|
191 | for (i = 0; local_parent->path.elements[i] != NULL; i++) {
|
---|
192 | elements[i] = talloc_reference(elements,
|
---|
193 | local_parent->path.elements[i]);
|
---|
194 | }
|
---|
195 | } else {
|
---|
196 | elements = talloc_array(hivekey, const char *, 2);
|
---|
197 | i = 0;
|
---|
198 | }
|
---|
199 |
|
---|
200 | elements[i] = talloc_strdup(elements, name);
|
---|
201 | elements[i+1] = NULL;
|
---|
202 |
|
---|
203 | *key = reg_import_hive_key(local_parent->global.context, hivekey,
|
---|
204 | local_parent->path.predefined_key,
|
---|
205 | elements);
|
---|
206 |
|
---|
207 | return WERR_OK;
|
---|
208 | }
|
---|
209 |
|
---|
210 | static WERROR local_set_value(struct registry_key *key, const char *name,
|
---|
211 | uint32_t type, const DATA_BLOB data)
|
---|
212 | {
|
---|
213 | struct local_key *local = (struct local_key *)key;
|
---|
214 |
|
---|
215 | return hive_key_set_value(local->hive_key, name, type, data);
|
---|
216 | }
|
---|
217 |
|
---|
218 | static WERROR local_get_value(TALLOC_CTX *mem_ctx,
|
---|
219 | const struct registry_key *key,
|
---|
220 | const char *name, uint32_t *type, DATA_BLOB *data)
|
---|
221 | {
|
---|
222 | const struct local_key *local = (const struct local_key *)key;
|
---|
223 |
|
---|
224 | return hive_get_value(mem_ctx, local->hive_key, name, type, data);
|
---|
225 | }
|
---|
226 |
|
---|
227 | static WERROR local_enum_value(TALLOC_CTX *mem_ctx,
|
---|
228 | const struct registry_key *key, uint32_t idx,
|
---|
229 | const char **name,
|
---|
230 | uint32_t *type,
|
---|
231 | DATA_BLOB *data)
|
---|
232 | {
|
---|
233 | const struct local_key *local = (const struct local_key *)key;
|
---|
234 |
|
---|
235 | return hive_get_value_by_index(mem_ctx, local->hive_key, idx,
|
---|
236 | name, type, data);
|
---|
237 | }
|
---|
238 |
|
---|
239 | static WERROR local_delete_key(struct registry_key *key, const char *name)
|
---|
240 | {
|
---|
241 | const struct local_key *local = (const struct local_key *)key;
|
---|
242 |
|
---|
243 | return hive_key_del(local->hive_key, name);
|
---|
244 | }
|
---|
245 |
|
---|
246 | static WERROR local_delete_value(struct registry_key *key, const char *name)
|
---|
247 | {
|
---|
248 | const struct local_key *local = (const struct local_key *)key;
|
---|
249 |
|
---|
250 | return hive_key_del_value(local->hive_key, name);
|
---|
251 | }
|
---|
252 |
|
---|
253 | static WERROR local_flush_key(struct registry_key *key)
|
---|
254 | {
|
---|
255 | const struct local_key *local = (const struct local_key *)key;
|
---|
256 |
|
---|
257 | return hive_key_flush(local->hive_key);
|
---|
258 | }
|
---|
259 |
|
---|
260 | static WERROR local_get_key_info(TALLOC_CTX *mem_ctx,
|
---|
261 | const struct registry_key *key,
|
---|
262 | const char **classname,
|
---|
263 | uint32_t *num_subkeys,
|
---|
264 | uint32_t *num_values,
|
---|
265 | NTTIME *last_change_time,
|
---|
266 | uint32_t *max_subkeynamelen,
|
---|
267 | uint32_t *max_valnamelen,
|
---|
268 | uint32_t *max_valbufsize)
|
---|
269 | {
|
---|
270 | const struct local_key *local = (const struct local_key *)key;
|
---|
271 |
|
---|
272 | return hive_key_get_info(mem_ctx, local->hive_key,
|
---|
273 | classname, num_subkeys, num_values,
|
---|
274 | last_change_time, max_subkeynamelen,
|
---|
275 | max_valnamelen, max_valbufsize);
|
---|
276 | }
|
---|
277 | static WERROR local_get_sec_desc(TALLOC_CTX *mem_ctx,
|
---|
278 | const struct registry_key *key,
|
---|
279 | struct security_descriptor **security)
|
---|
280 | {
|
---|
281 | const struct local_key *local = (const struct local_key *)key;
|
---|
282 |
|
---|
283 | return hive_get_sec_desc(mem_ctx, local->hive_key, security);
|
---|
284 | }
|
---|
285 | static WERROR local_set_sec_desc(struct registry_key *key,
|
---|
286 | const struct security_descriptor *security)
|
---|
287 | {
|
---|
288 | const struct local_key *local = (const struct local_key *)key;
|
---|
289 |
|
---|
290 | return hive_set_sec_desc(local->hive_key, security);
|
---|
291 | }
|
---|
292 | const static struct registry_operations local_ops = {
|
---|
293 | .name = "local",
|
---|
294 | .open_key = local_open_key,
|
---|
295 | .get_predefined_key = local_get_predefined_key,
|
---|
296 | .enum_key = local_enum_key,
|
---|
297 | .create_key = local_create_key,
|
---|
298 | .set_value = local_set_value,
|
---|
299 | .get_value = local_get_value,
|
---|
300 | .enum_value = local_enum_value,
|
---|
301 | .delete_key = local_delete_key,
|
---|
302 | .delete_value = local_delete_value,
|
---|
303 | .flush_key = local_flush_key,
|
---|
304 | .get_key_info = local_get_key_info,
|
---|
305 | .get_sec_desc = local_get_sec_desc,
|
---|
306 | .set_sec_desc = local_set_sec_desc,
|
---|
307 | };
|
---|
308 |
|
---|
309 | WERROR reg_open_local(TALLOC_CTX *mem_ctx, struct registry_context **ctx)
|
---|
310 | {
|
---|
311 | struct registry_local *ret = talloc_zero(mem_ctx,
|
---|
312 | struct registry_local);
|
---|
313 |
|
---|
314 | W_ERROR_HAVE_NO_MEMORY(ret);
|
---|
315 |
|
---|
316 | ret->ops = &local_ops;
|
---|
317 |
|
---|
318 | *ctx = (struct registry_context *)ret;
|
---|
319 |
|
---|
320 | return WERR_OK;
|
---|
321 | }
|
---|
322 |
|
---|
323 | WERROR reg_mount_hive(struct registry_context *rctx,
|
---|
324 | struct hive_key *hive_key,
|
---|
325 | uint32_t key_id,
|
---|
326 | const char **elements)
|
---|
327 | {
|
---|
328 | struct registry_local *reg_local = talloc_get_type(rctx,
|
---|
329 | struct registry_local);
|
---|
330 | struct mountpoint *mp = talloc(rctx, struct mountpoint);
|
---|
331 | int i = 0;
|
---|
332 |
|
---|
333 | mp->path.predefined_key = key_id;
|
---|
334 | mp->prev = mp->next = NULL;
|
---|
335 | mp->key = hive_key;
|
---|
336 | if (elements != NULL && str_list_length(elements) != 0) {
|
---|
337 | mp->path.elements = talloc_array(mp, const char *,
|
---|
338 | str_list_length(elements));
|
---|
339 | for (i = 0; elements[i] != NULL; i++) {
|
---|
340 | mp->path.elements[i] = talloc_reference(mp->path.elements,
|
---|
341 | elements[i]);
|
---|
342 | }
|
---|
343 | mp->path.elements[i] = NULL;
|
---|
344 | } else {
|
---|
345 | mp->path.elements = NULL;
|
---|
346 | }
|
---|
347 |
|
---|
348 | DLIST_ADD(reg_local->mountpoints, mp);
|
---|
349 |
|
---|
350 | return WERR_OK;
|
---|
351 | }
|
---|