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. */
21 #include "lib/registry/common/registry.h"
24 * This is the RPC backend for the registry library.
27 static void init_winreg_String(struct winreg_String *name, const char *s)
31 name->name_len = 2 * (strlen_m(s) + 1);
32 name->name_size = name->name_len;
40 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \
42 struct winreg_Open ## u r; \
43 struct winreg_OpenUnknown unknown; \
46 unknown.unknown0 = 0x84e0; \
47 unknown.unknown1 = 0x0000; \
48 r.in.unknown = &unknown; \
49 r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
52 status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \
53 if (NT_STATUS_IS_ERR(status)) {\
54 DEBUG(0,("Error executing open\n"));\
55 return ntstatus_to_werror(status);\
68 struct policy_handle pol;
77 WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h);
79 { "HKEY_LOCAL_MACHINE", open_HKLM },
80 { "HKEY_CURRENT_USER", open_HKCU },
81 { "HKEY_CLASSES_ROOT", open_HKCR },
82 { "HKEY_PERFORMANCE_DATA", open_HKPD },
83 { "HKEY_USERS", open_HKU },
87 static WERROR rpc_query_key(REG_KEY *k);
89 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
91 char *binding = strdup(location);
95 if(!credentials || !location) return WERR_INVALID_PARAM;
97 user = talloc_strdup(h->mem_ctx, credentials);
98 pass = strchr(user, '%');
101 status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding,
103 DCERPC_WINREG_VERSION,
107 return ntstatus_to_werror(status);
110 static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k)
112 struct rpc_key_data *mykeydata;
114 if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
115 *k = reg_key_new_abs(known_hives[n].name, h, NULL);
116 (*k)->backend_data = mykeydata = talloc_p((*k)->mem_ctx, struct rpc_key_data);
117 mykeydata->num_values = -1;
118 mykeydata->num_subkeys = -1;
119 error = known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &mykeydata->pol);
123 static WERROR rpc_close_registry(REG_HANDLE *h)
125 dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data);
129 static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
131 struct winreg_OpenKey r;
133 struct rpc_data *mydata = k->handle->backend_data;
136 struct rpc_key_data *mykeydata;
138 if(k->backend_data) {
139 *data = k->backend_data;
143 k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
145 mykeydata->num_values = -1;
146 mykeydata->num_subkeys = -1;
148 /* Then, open the handle using the hive */
150 memset(&r, 0, sizeof(struct winreg_OpenKey));
151 error = rpc_get_hive(k->handle, k->hive, &hivekey);
152 if(!W_ERROR_IS_OK(error))return error;
153 r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
154 init_winreg_String(&r.in.keyname, reg_key_get_path(k));
155 r.in.unknown = 0x00000000;
156 r.in.access_mask = 0x02000000;
157 r.out.handle = &mykeydata->pol;
159 dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
164 static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key)
166 struct rpc_key_data *mykeydata;
167 struct winreg_OpenKey r;
171 *key = reg_key_new_abs(name, h, NULL);
173 (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data);
174 mykeydata->num_values = -1;
175 mykeydata->num_subkeys = -1;
177 /* Then, open the handle using the hive */
179 memset(&r, 0, sizeof(struct winreg_OpenKey));
180 error = rpc_get_hive(h, hive, &hivekey);
181 if(!W_ERROR_IS_OK(error))return error;
182 r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
183 init_winreg_String(&r.in.keyname, name);
184 r.in.unknown = 0x00000000;
185 r.in.access_mask = 0x02000000;
186 r.out.handle = &mykeydata->pol;
188 dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r);
193 static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
195 struct winreg_EnumValue r;
196 struct winreg_Uint8buf vb;
197 struct winreg_EnumValueName vn;
199 struct rpc_key_data *mykeydata;
200 uint32_t type = 0x0, requested_len = 0, returned_len = 0;
203 error = rpc_key_put_rpc_data(parent, &mykeydata);
204 if(!W_ERROR_IS_OK(error)) return error;
206 if(mykeydata->num_values == -1) {
207 error = rpc_query_key(parent);
208 if(!W_ERROR_IS_OK(error)) return error;
211 requested_len = mykeydata->max_valdatalen;
213 r.in.handle = &mykeydata->pol;
215 r.in.type = r.out.type = &type;
216 r.in.requested_len = r.out.requested_len = &requested_len;
217 r.in.returned_len = r.out.returned_len = &returned_len;
218 vn.max_len = mykeydata->max_valnamelen * 2;
223 vn.max_len = mykeydata->max_valnamelen*2;
224 /* FIXME: we should not point a 'char *' to a const buffer!!! --metze*/
227 r.in.name = r.out.name = &vn;
228 vb.max_len = mykeydata->max_valdatalen;
231 vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
232 r.in.value = r.out.value = &vb;
234 status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
235 if(NT_STATUS_IS_ERR(status)) {
236 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
239 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
240 *value = reg_val_new(parent, NULL);
241 (*value)->name = r.out.name->buf;
242 (*value)->data_type = type;
243 (*value)->data_len = r.out.value->len;
244 (*value)->data_blk = r.out.value->buffer;
252 static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
254 struct winreg_EnumKey r;
255 struct winreg_EnumKeyNameRequest keyname;
256 struct winreg_String classname;
257 struct winreg_Time tm;
258 struct rpc_data *mydata = parent->handle->backend_data;
259 struct rpc_key_data *mykeydata = parent->backend_data;
263 error = rpc_key_put_rpc_data(parent, &mykeydata);
264 if(!W_ERROR_IS_OK(error)) return error;
266 r.in.handle = &mykeydata->pol;
267 keyname.unknown = 0x0000020a;
268 init_winreg_String(&keyname.key_name, NULL);
269 init_winreg_String(&classname, NULL);
270 r.in.in_name = &keyname;
271 r.in.class = &classname;
272 tm.low = tm.high = 0x7fffffff;
273 r.in.last_changed_time = &tm;
276 r.in.unknown = r.out.unknown = 0x0414;
277 r.in.key_name_len = r.out.key_name_len = 0;
278 status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
279 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
280 *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL);
286 static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **key)
288 struct rpc_key_data *mykeydata;
291 error = rpc_key_put_rpc_data(parent, &mykeydata);
292 if(!W_ERROR_IS_OK(error)) return error;
295 return WERR_NOT_SUPPORTED;
298 static WERROR rpc_query_key(REG_KEY *k)
302 struct winreg_QueryInfoKey r;
303 struct rpc_key_data *mykeydata;
305 error = rpc_key_put_rpc_data(k, &mykeydata);
306 if(!W_ERROR_IS_OK(error)) return error;
308 init_winreg_String(&r.in.class, NULL);
309 r.in.handle = &mykeydata->pol;
311 status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
313 if (!NT_STATUS_IS_OK(status)) {
314 printf("QueryInfoKey failed - %s\n", nt_errstr(status));
315 return ntstatus_to_werror(status);
318 if (W_ERROR_IS_OK(r.out.result)) {
319 mykeydata->num_subkeys = r.out.num_subkeys;
320 mykeydata->num_values = r.out.num_values;
321 mykeydata->max_valnamelen = r.out.max_valnamelen;
322 mykeydata->max_valdatalen = r.out.max_valbufsize;
328 static WERROR rpc_del_key(REG_KEY *k)
331 struct rpc_key_data *mykeydata = k->backend_data;
332 struct winreg_DeleteKey r;
336 error = reg_key_get_parent(k, &parent);
337 if(!W_ERROR_IS_OK(error)) return error;
339 error = rpc_key_put_rpc_data(parent, &mykeydata);
340 if(!W_ERROR_IS_OK(error)) return error;
342 r.in.handle = &mykeydata->pol;
343 init_winreg_String(&r.in.key, k->name);
345 status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
350 static void rpc_close_key(REG_KEY *k)
355 static WERROR rpc_num_values(REG_KEY *key, int *count) {
356 struct rpc_key_data *mykeydata = key->backend_data;
359 error = rpc_key_put_rpc_data(key, &mykeydata);
360 if(!W_ERROR_IS_OK(error)) return error;
362 if(mykeydata->num_values == -1) {
363 error = rpc_query_key(key);
364 if(!W_ERROR_IS_OK(error)) return error;
367 *count = mykeydata->num_values;
371 static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
372 struct rpc_key_data *mykeydata = key->backend_data;
375 error = rpc_key_put_rpc_data(key, &mykeydata);
376 if(!W_ERROR_IS_OK(error)) return error;
378 if(mykeydata->num_subkeys == -1) {
379 error = rpc_query_key(key);
380 if(!W_ERROR_IS_OK(error)) return error;
383 *count = mykeydata->num_subkeys;
387 static struct registry_ops reg_backend_rpc = {
389 .open_registry = rpc_open_registry,
390 .close_registry = rpc_close_registry,
391 .get_hive = rpc_get_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 .free_key_backend_data = rpc_close_key,
398 .num_subkeys = rpc_num_subkeys,
399 .num_values = rpc_num_values,
402 NTSTATUS registry_rpc_init(void)
404 return register_backend("registry", ®_backend_rpc);