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.
26 * This backend is a little special. The root key is 'virtual'. All
27 * of its subkeys are the hives available on the remote server.
30 static void init_winreg_String(struct winreg_String *name, const char *s)
34 name->name_len = 2 * (strlen_m(s) + 1);
35 name->name_size = name->name_len;
43 #define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \
45 struct winreg_Open ## u r; \
46 struct winreg_OpenUnknown unknown; \
47 struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
49 unknown.unknown0 = 0x84e0; \
50 unknown.unknown1 = 0x0000; \
51 r.in.unknown = &unknown; \
52 r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
55 if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\
56 DEBUG(0,("Error executing open\n"));\
70 struct dcerpc_pipe *pipe;
71 struct policy_handle *hives[10];
75 struct policy_handle pol;
84 struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
86 { "HKEY_LOCAL_MACHINE", open_HKLM },
87 { "HKEY_CURRENT_USER", open_HKCU },
88 { "HKEY_CLASSES_ROOT", open_HKCR },
89 { "HKEY_PERFORMANCE_DATA", open_HKPD },
90 { "HKEY_USERS", open_HKU },
94 static WERROR rpc_query_key(REG_KEY *k);
96 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
98 struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
99 char *binding = strdup(location);
103 if(!credentials || !location) return WERR_INVALID_PARAM;
105 user = talloc_strdup(h->mem_ctx, credentials);
106 pass = strchr(user, '%');
107 *pass = '\0'; pass++;
109 ZERO_STRUCTP(mydata);
111 status = dcerpc_pipe_connect(&mydata->pipe, binding,
113 DCERPC_WINREG_VERSION,
117 h->backend_data = mydata;
119 return ntstatus_to_werror(status);
122 static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
124 /* There's not really a 'root' key here */
125 *k = reg_key_new_abs("\\", h, h->backend_data);
129 static WERROR rpc_close_registry(REG_HANDLE *h)
131 dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
135 static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
137 struct policy_handle *hive = NULL;
138 struct winreg_OpenKey r;
140 struct rpc_data *mydata = k->handle->backend_data;
141 struct rpc_key_data *mykeydata;
142 char *realkeyname, *hivename;
144 if(k->backend_data) {
145 *data = k->backend_data;
149 k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
151 mykeydata->num_values = -1;
152 mykeydata->num_subkeys = -1;
154 /* First, ensure the handle to the hive is opened */
155 realkeyname = strchr(k->path+1, '\\');
156 if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1);
157 else hivename = strdup(k->path+1);
159 for(i = 0; known_hives[i].name; i++) {
160 if(!strcmp(hivename, known_hives[i].name)) {
161 if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, k->handle);
162 hive = mydata->hives[i];
168 DEBUG(0, ("No such hive: %s\n", hivename));
172 if(realkeyname && realkeyname[0] == '\\')realkeyname++;
174 if(!realkeyname || !(*realkeyname)) {
175 mykeydata->pol = *hive;
179 /* Then, open the handle using the hive */
181 memset(&r, 0, sizeof(struct winreg_OpenKey));
183 init_winreg_String(&r.in.keyname, realkeyname);
184 r.in.unknown = 0x00000000;
185 r.in.access_mask = 0x02000000;
186 r.out.handle = &mykeydata->pol;
188 dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
193 static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
195 struct rpc_key_data *mykeydata;
196 *key = reg_key_new_abs(name, h, NULL);
197 return rpc_key_put_rpc_data(*key, &mykeydata);
200 static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
202 struct winreg_EnumValue r;
203 struct winreg_Uint8buf vb;
204 struct rpc_data *mydata = parent->handle->backend_data;
205 struct winreg_EnumValueName vn;
207 struct rpc_key_data *mykeydata;
208 uint32 type = 0x0, requested_len = 0, returned_len = 0;
211 error = rpc_key_put_rpc_data(parent, &mykeydata);
212 if(!W_ERROR_IS_OK(error)) return error;
214 /* Root is a special case */
215 if(parent->backend_data == parent->handle->backend_data) {
216 return WERR_NO_MORE_ITEMS;
219 if(mykeydata->num_values == -1) {
220 error = rpc_query_key(parent);
221 if(!W_ERROR_IS_OK(error)) return error;
224 requested_len = mykeydata->max_valdatalen;
226 r.in.handle = &mykeydata->pol;
228 r.in.type = r.out.type = &type;
229 r.in.requested_len = r.out.requested_len = &requested_len;
230 r.in.returned_len = r.out.returned_len = &returned_len;
231 vn.max_len = mykeydata->max_valnamelen * 2;
236 vn.max_len = mykeydata->max_valnamelen*2;
239 r.in.name = r.out.name = &vn;
240 vb.max_len = mykeydata->max_valdatalen;
243 vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
244 r.in.value = r.out.value = &vb;
246 status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
247 if(NT_STATUS_IS_ERR(status)) {
248 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
251 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
252 *value = reg_val_new(parent, NULL);
253 (*value)->name = r.out.name->buf;
254 (*value)->data_type = type;
255 (*value)->data_len = r.out.value->len;
256 (*value)->data_blk = r.out.value->buffer;
264 static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
266 struct winreg_EnumKey r;
267 struct winreg_EnumKeyNameRequest keyname;
268 struct winreg_String classname;
269 struct winreg_Time tm;
270 struct rpc_data *mydata = parent->handle->backend_data;
271 struct rpc_key_data *mykeydata = parent->backend_data;
275 /* If parent is the root key, list the hives */
276 if(parent->backend_data == mydata) {
277 if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
278 *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL);
279 return rpc_key_put_rpc_data(*subkey, &mykeydata);
282 error = rpc_key_put_rpc_data(parent, &mykeydata);
283 if(!W_ERROR_IS_OK(error)) return error;
285 r.in.handle = &mykeydata->pol;
286 keyname.unknown = 0x0000020a;
287 init_winreg_String(&keyname.key_name, NULL);
288 init_winreg_String(&classname, NULL);
289 r.in.in_name = &keyname;
290 r.in.class = &classname;
291 tm.low = tm.high = 0x7fffffff;
292 r.in.last_changed_time = &tm;
296 r.in.unknown = r.out.unknown = 0x0414;
297 r.in.key_name_len = r.out.key_name_len = 0;
298 status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
299 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
300 *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL);
306 static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key)
308 struct rpc_key_data *mykeydata;
309 WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
310 if(!W_ERROR_IS_OK(error)) return error;
313 return WERR_NOT_SUPPORTED;
316 static WERROR rpc_query_key(REG_KEY *k)
319 struct winreg_QueryInfoKey r;
320 struct rpc_data *mydata = k->handle->backend_data;
321 struct rpc_key_data *mykeydata;
322 r.in.handle = &mykeydata->pol;
323 init_winreg_String(&r.in.class, NULL);
325 status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
327 if (!NT_STATUS_IS_OK(status)) {
328 printf("QueryInfoKey failed - %s\n", nt_errstr(status));
329 return ntstatus_to_werror(status);
332 if (W_ERROR_IS_OK(r.out.result)) {
333 mykeydata->num_subkeys = r.out.num_subkeys;
334 mykeydata->num_values = r.out.num_values;
335 mykeydata->max_valnamelen = r.out.max_valnamelen;
336 mykeydata->max_valdatalen = r.out.max_valbufsize;
342 static WERROR rpc_del_key(REG_KEY *k)
345 struct rpc_data *mydata = k->handle->backend_data;
346 struct rpc_key_data *mykeydata;
347 struct winreg_DeleteKey r;
351 error = reg_key_get_parent(k, &parent);
352 if(!W_ERROR_IS_OK(error)) return error;
354 error = rpc_key_put_rpc_data(parent, &mykeydata);
355 if(!W_ERROR_IS_OK(error)) return error;
357 r.in.handle = &mykeydata->pol;
358 init_winreg_String(&r.in.key, k->name);
360 status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
365 static void rpc_close_key(REG_KEY *k)
370 static WERROR rpc_num_values(REG_KEY *key, int *count) {
371 struct rpc_key_data *mykeydata;
374 /* Root is a special case */
375 if(key->backend_data == key->handle->backend_data) {
380 error = rpc_key_put_rpc_data(key, &mykeydata);
381 if(!W_ERROR_IS_OK(error)) return error;
383 if(mykeydata->num_values == -1) {
384 error = rpc_query_key(key);
385 if(!W_ERROR_IS_OK(error)) return error;
388 *count = mykeydata->num_values;
392 static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
393 struct rpc_key_data *mykeydata;
396 /* Root is a special case */
397 if(key->backend_data == key->handle->backend_data) {
399 for(i = 0; known_hives[i].name; i++);
404 error = rpc_key_put_rpc_data(key, &mykeydata);
405 if(!W_ERROR_IS_OK(error)) return error;
407 if(mykeydata->num_subkeys == -1) {
408 error = rpc_query_key(key);
409 if(!W_ERROR_IS_OK(error)) return error;
412 *count = mykeydata->num_subkeys;
416 static struct registry_ops reg_backend_rpc = {
418 .open_registry = rpc_open_registry,
419 .close_registry = rpc_close_registry,
420 .open_root_key = rpc_open_root,
421 .open_key = rpc_open_key,
422 .get_subkey_by_index = rpc_get_subkey_by_index,
423 .get_value_by_index = rpc_get_value_by_index,
424 .add_key = rpc_add_key,
425 .del_key = rpc_del_key,
426 .free_key_backend_data = rpc_close_key,
427 .num_subkeys = rpc_num_subkeys,
428 .num_values = rpc_num_values,
431 NTSTATUS reg_rpc_init(void)
433 return register_backend("registry", ®_backend_rpc);