2 Samba Unix/Linux SMB implementation
3 RPC backend for the registry library
4 Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org
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.
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.
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. */
22 #include "librpc/gen_ndr/ndr_winreg.h"
25 * This is the RPC backend for the registry library.
28 static void init_winreg_String(struct winreg_String *name, const char *s)
32 name->name_len = 2 * (strlen_m(s) + 1);
33 name->name_size = name->name_len;
41 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
43 struct winreg_Open ## u r; \
44 struct winreg_OpenUnknown unknown; \
47 unknown.unknown0 = 0x84e0; \
48 unknown.unknown1 = 0x0000; \
49 r.in.unknown = &unknown; \
50 r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
53 status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
54 if (NT_STATUS_IS_ERR(status)) {\
55 DEBUG(0,("Error executing open\n"));\
56 return ntstatus_to_werror(status);\
69 struct policy_handle pol;
78 WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h);
80 { "HKEY_LOCAL_MACHINE", open_HKLM },
81 { "HKEY_CURRENT_USER", open_HKCU },
82 { "HKEY_CLASSES_ROOT", open_HKCR },
83 { "HKEY_PERFORMANCE_DATA", open_HKPD },
84 { "HKEY_USERS", open_HKU },
88 static WERROR rpc_query_key(struct registry_key *k);
90 static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives)
93 *hives = talloc_p(mem_ctx, char *);
94 for(i = 0; known_hives[i].name; i++) {
95 *hives = talloc_realloc_p(mem_ctx, *hives, char *, i+2);
96 (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name);
102 static WERROR rpc_close_hive (struct registry_hive *h)
104 dcerpc_pipe_close(h->backend_data);
108 static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k)
113 struct rpc_key_data *mykeydata;
114 struct dcerpc_pipe *p;
117 if (!h->credentials) return WERR_INVALID_PARAM;
119 /* Default to local smbd if no connection is specified */
121 h->location = talloc_strdup(mem_ctx, "ncalrpc:");
124 user = talloc_strdup(mem_ctx, h->credentials);
125 pass = strchr(user, '%');
128 pass = strdup(pass+1);
133 status = dcerpc_pipe_connect(&p, h->location,
135 DCERPC_WINREG_VERSION,
142 if(NT_STATUS_IS_ERR(status)) {
143 DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status)));
144 return ntstatus_to_werror(status);
147 for(n = 0; known_hives[n].name; n++)
149 if(!strcmp(known_hives[n].name, h->backend_hivename)) break;
152 if(!known_hives[n].name) {
153 DEBUG(1, ("No such hive %s\n", known_hives[n].name));
154 return WERR_NO_MORE_ITEMS;
157 *k = talloc_p(mem_ctx, struct registry_key);
158 (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
159 mykeydata->num_values = -1;
160 mykeydata->num_subkeys = -1;
161 return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol));
165 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
167 struct winreg_OpenKey r;
168 struct rpc_key_data *mykeydata;
170 k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
171 mykeydata->num_values = -1;
172 mykeydata->num_subkeys = -1;
174 /* Then, open the handle using the hive */
176 memset(&r, 0, sizeof(struct winreg_OpenKey));
177 r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
178 init_winreg_String(&r.in.keyname, k->path);
179 r.in.unknown = 0x00000000;
180 r.in.access_mask = 0x02000000;
181 r.out.handle = &mykeydata->pol;
183 dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
189 static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key)
191 struct rpc_key_data *mykeydata;
192 struct winreg_OpenKey r;
194 *key = talloc_p(mem_ctx, struct registry_key);
195 (*key)->name = talloc_strdup(mem_ctx, name);
197 (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
198 mykeydata->num_values = -1;
199 mykeydata->num_subkeys = -1;
201 /* Then, open the handle using the hive */
203 memset(&r, 0, sizeof(struct winreg_OpenKey));
204 r.in.handle = &(((struct rpc_key_data *)h->backend_data)->pol);
205 init_winreg_String(&r.in.keyname, name);
206 r.in.unknown = 0x00000000;
207 r.in.access_mask = 0x02000000;
208 r.out.handle = &mykeydata->pol;
210 dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r);
215 static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key)
217 return rpc_open_rel_key(mem_ctx, h->root, name, key);
220 static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value)
222 struct rpc_key_data *mykeydata = parent->backend_data;
224 struct winreg_EnumValue r;
225 uint32 type, len1, len2 = 0;
226 struct EnumValueIn buf_name, buf_val;
229 if(mykeydata->num_values == -1) {
230 error = rpc_query_key(parent);
231 if(!W_ERROR_IS_OK(error)) return error;
234 len1 = mykeydata->max_valdatalen;
236 r.in.handle = &mykeydata->pol;
238 r.in.name_in.len = 0;
239 r.in.name_in.max_len = mykeydata->max_valnamelen * 2;
240 buf_name.max_len = mykeydata->max_valnamelen;
243 r.in.name_in.buffer = &buf_name;
245 buf_val.max_len = mykeydata->max_valdatalen;
248 r.in.value_in = &buf_val;
249 r.in.value_len1 = &len1;
250 r.in.value_len2 = &len2;
254 status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
255 if(NT_STATUS_IS_ERR(status)) {
256 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
257 return WERR_GENERAL_FAILURE;
260 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
261 *value = talloc_p(mem_ctx, struct registry_value);
262 (*value)->parent = parent;
263 (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name);
264 (*value)->data_type = type;
265 (*value)->data_len = r.out.value_out->buffer.length;
266 (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value_out->buffer.data, r.out.value_out->buffer.length);
273 static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey)
275 struct winreg_EnumKey r;
276 struct winreg_EnumKeyNameRequest keyname;
277 struct winreg_String classname;
278 struct winreg_Time tm;
279 struct rpc_key_data *mykeydata = parent->backend_data;
282 r.in.handle = &mykeydata->pol;
283 keyname.unknown = 0x0000020a;
284 init_winreg_String(&keyname.key_name, NULL);
285 init_winreg_String(&classname, NULL);
286 r.in.in_name = &keyname;
287 r.in.class = &classname;
288 tm.low = tm.high = 0x7fffffff;
289 r.in.last_changed_time = &tm;
292 r.in.unknown = r.out.unknown = 0x0414;
293 r.in.key_name_len = r.out.key_name_len = 0;
294 status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
295 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
296 return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey);
302 static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key)
304 return WERR_NOT_SUPPORTED;
307 static WERROR rpc_query_key(struct registry_key *k)
310 struct winreg_QueryInfoKey r;
311 struct rpc_key_data *mykeydata = k->backend_data;
312 TALLOC_CTX *mem_ctx = talloc_init("query_key");
314 init_winreg_String(&r.in.class, NULL);
315 r.in.handle = &mykeydata->pol;
317 status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r);
318 talloc_destroy(mem_ctx);
320 if (!NT_STATUS_IS_OK(status)) {
321 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
322 return ntstatus_to_werror(status);
325 if (W_ERROR_IS_OK(r.out.result)) {
326 mykeydata->num_subkeys = r.out.num_subkeys;
327 mykeydata->num_values = r.out.num_values;
328 mykeydata->max_valnamelen = r.out.max_valnamelen;
329 mykeydata->max_valdatalen = r.out.max_valbufsize;
335 static WERROR rpc_del_key(struct registry_key *k)
338 struct rpc_key_data *mykeydata = k->backend_data;
339 struct winreg_DeleteKey r;
340 struct registry_key *parent;
342 TALLOC_CTX *mem_ctx = talloc_init("del_key");
344 error = reg_key_get_parent(mem_ctx, k, &parent);
345 if(!W_ERROR_IS_OK(error)) {
346 talloc_destroy(mem_ctx);
350 mykeydata = parent->backend_data;
352 r.in.handle = &mykeydata->pol;
353 init_winreg_String(&r.in.key, k->name);
355 status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
357 talloc_destroy(mem_ctx);
362 static WERROR rpc_num_values(struct registry_key *key, int *count) {
363 struct rpc_key_data *mykeydata = key->backend_data;
366 if(mykeydata->num_values == -1) {
367 error = rpc_query_key(key);
368 if(!W_ERROR_IS_OK(error)) return error;
371 *count = mykeydata->num_values;
375 static WERROR rpc_num_subkeys(struct registry_key *key, int *count) {
376 struct rpc_key_data *mykeydata = key->backend_data;
379 if(mykeydata->num_subkeys == -1) {
380 error = rpc_query_key(key);
381 if(!W_ERROR_IS_OK(error)) return error;
384 *count = mykeydata->num_subkeys;
388 static struct registry_operations reg_backend_rpc = {
390 .open_hive = rpc_open_hive,
391 .close_hive = rpc_close_hive,
392 .open_key = rpc_open_key,
393 .get_subkey_by_index = rpc_get_subkey_by_index,
394 .get_value_by_index = rpc_get_value_by_index,
395 .add_key = rpc_add_key,
396 .del_key = rpc_del_key,
397 .num_subkeys = rpc_num_subkeys,
398 .num_values = rpc_num_values,
399 .list_available_hives = rpc_list_hives,
402 NTSTATUS registry_rpc_init(void)
404 return register_backend("registry", ®_backend_rpc);