r164: Viewing remote registries with gregedit works now
[Samba/ekacnet.git] / source / lib / registry / reg_backend_rpc / reg_backend_rpc.c
blob7c30302e8423922290ae20928eaa0f8d9a27a855
1 /*
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. */
20 #include "includes.h"
21 #include "lib/registry/common/registry.h"
23 static void init_winreg_String(struct winreg_String *name, const char *s)
25 name->name = s;
26 if (s) {
27 name->name_len = 2 * (strlen_m(s) + 1);
28 name->name_size = name->name_len;
29 } else {
30 name->name_len = 0;
31 name->name_size = 0;
36 #define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \
37 { \
38 NTSTATUS status; \
39 struct winreg_Open ## u r; \
40 struct winreg_OpenUnknown unknown; \
41 struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
43 unknown.unknown0 = 0x84e0; \
44 unknown.unknown1 = 0x0000; \
45 r.in.unknown = &unknown; \
46 r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
47 r.out.handle = hnd;\
49 if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\
50 DEBUG(0,("Error executing open\n"));\
51 return NULL;\
54 return hnd;\
57 openhive(HKLM)
58 openhive(HKCU)
59 openhive(HKPD)
60 openhive(HKU)
61 openhive(HKCR)
63 struct rpc_data {
64 struct dcerpc_pipe *pipe;
65 struct policy_handle *hives[10];
68 struct {
69 char *name;
70 struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
71 } known_hives[] = {
72 { "HKEY_LOCAL_MACHINE", open_HKLM },
73 { "HKEY_CURRENT_USER", open_HKCU },
74 { "HKEY_CLASSES_ROOT", open_HKCR },
75 { "HKEY_PERFORMANCE_DATA", open_HKPD },
76 { "HKEY_USERS", open_HKU },
77 { NULL, NULL }
80 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
82 struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
83 char *binding = strdup(location);
84 NTSTATUS status;
85 char *user, *pass;
87 if(!credentials || !location) return WERR_INVALID_PARAM;
89 user = talloc_strdup(h->mem_ctx, credentials);
90 pass = strchr(user, '%');
91 *pass = '\0'; pass++;
93 ZERO_STRUCTP(mydata);
95 status = dcerpc_pipe_connect(&mydata->pipe, binding,
96 DCERPC_WINREG_UUID,
97 DCERPC_WINREG_VERSION,
98 lp_workgroup(),
99 user, pass);
102 h->backend_data = mydata;
104 return ntstatus_to_werror(status);
107 static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
109 /* There's not really a 'root' key here */
110 *k = reg_key_new_abs("\\", h, h->backend_data);
111 return WERR_OK;
114 static WERROR rpc_close_registry(REG_HANDLE *h)
116 dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
117 free(h->backend_data);
118 return WERR_OK;
121 static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
123 char *hivename;
124 int i = 0;
125 struct rpc_data *mydata = h->backend_data;
126 struct policy_handle *hive = NULL;
127 char *end = strchr(path+1, '\\');
128 NTSTATUS status;
129 struct winreg_OpenKey r;
130 struct policy_handle *key_handle = talloc(h->mem_ctx, sizeof(struct policy_handle));
131 TALLOC_CTX *mem_ctx;
133 if(end) hivename = strndup(path+1, end-path-1);
134 else hivename = strdup(path+1);
136 for(i = 0; known_hives[i].name; i++) {
137 if(!strcmp(hivename, known_hives[i].name)) {
138 if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, h);
139 hive = mydata->hives[i];
143 if(!hive) {
144 DEBUG(0, ("No such hive: %s\n", hivename));
145 return NULL;
148 DEBUG(2, ("Opening %s, hive: %s\n", path, hivename));
150 if(!end || !(*end) || !(*(end+1))) return hive;
152 memset(&r, 0, sizeof(struct winreg_OpenKey));
153 r.in.handle = hive;
154 init_winreg_String(&r.in.keyname, end+1);
155 r.in.unknown = 0x00000000;
156 r.in.access_mask = 0x02000000;
157 r.out.handle = key_handle;
159 mem_ctx = talloc_init("openkey");
160 status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r);
161 talloc_destroy(mem_ctx);
163 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
164 return NULL;
167 return key_handle;
170 static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
172 struct policy_handle *pol = rpc_get_key_handle(h, name);
173 if(!pol) return WERR_DEST_NOT_FOUND;
174 *key = reg_key_new_abs(name, h, pol);
175 return WERR_OK;
178 static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
180 struct winreg_EnumKey r;
181 struct winreg_EnumKeyNameRequest keyname;
182 struct winreg_String classname;
183 struct winreg_Time tm;
184 struct rpc_data *mydata = parent->handle->backend_data;
185 int i;
186 REG_KEY **ar = talloc(parent->mem_ctx, sizeof(REG_KEY *));
187 NTSTATUS status = NT_STATUS_OK;
188 TALLOC_CTX *mem_ctx;
190 /* List the hives */
191 if(parent->backend_data == parent->handle->backend_data) {
192 for(i = 0; known_hives[i].name; i++) {
193 ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL);
194 (*count)++;
195 ar = talloc_realloc(parent->mem_ctx, ar, sizeof(REG_KEY *) * ((*count)+1));
198 *subkeys = ar;
200 return WERR_OK;
203 if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
205 if(!parent->backend_data) return WERR_GENERAL_FAILURE;
207 (*count) = 0;
208 r.in.handle = parent->backend_data;
209 keyname.unknown = 0x0000020a;
210 init_winreg_String(&keyname.key_name, NULL);
211 init_winreg_String(&classname, NULL);
212 r.in.in_name = &keyname;
213 r.in.class = &classname;
214 tm.low = tm.high = 0x7fffffff;
215 r.in.last_changed_time = &tm;
216 r.out.result.v = 0;
218 for(i = 0; NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result); i++) {
219 r.in.enum_index = i;
220 r.in.unknown = r.out.unknown = 0x0414;
221 r.in.key_name_len = r.out.key_name_len = 0;
222 status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
223 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
224 ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL);
225 (*count)++;
226 ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_KEY *));
230 *subkeys = ar;
231 return r.out.result;
234 static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
236 struct winreg_EnumValue r;
237 struct winreg_Uint8buf value;
238 struct winreg_String valuename;
239 struct rpc_data *mydata = parent->handle->backend_data;
240 TALLOC_CTX *mem_ctx;
241 uint32 type, requested_len, returned_len;
242 NTSTATUS status = NT_STATUS_OK;
243 REG_VAL **ar = malloc(sizeof(REG_VAL *));
245 (*count) = 0;
247 /* Root */
248 if(parent->backend_data == parent->handle->backend_data) {
249 *values = ar;
250 return WERR_OK;
253 if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
255 if(!parent->backend_data) return WERR_GENERAL_FAILURE;
257 r.in.handle = parent->backend_data;
258 r.in.enum_index = 0;
260 init_winreg_String(&valuename, NULL);
261 r.in.name = r.out.name = &valuename;
263 type = 0;
264 r.in.type = r.out.type = &type;
265 value.max_len = 0x7fff;
266 value.offset = 0;
267 value.len = 0;
268 value.buffer = NULL;
270 r.in.value = r.out.value = &value;
272 requested_len = value.max_len;
273 r.in.requested_len = &requested_len;
274 returned_len = 0;
275 r.in.returned_len = &returned_len;
276 r.out.result.v = 0;
278 while(1) {
279 status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
280 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
281 r.in.enum_index++;
282 ar[(*count)] = reg_val_new(parent, NULL);
283 ar[(*count)]->name = talloc_strdup(ar[*count]->mem_ctx, r.out.name->name);
284 ar[(*count)]->data_type = *r.out.type;
285 ar[(*count)]->data_len = value.len;
286 ar[(*count)]->data_blk = talloc(ar[*count]->mem_ctx, value.len);
287 memcpy(ar[(*count)]->data_blk, value.buffer, value.len);
288 (*count)++;
289 ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_VAL *));
290 } else break;
293 *values = ar;
295 return r.out.result;
298 static WERROR rpc_add_key(REG_KEY *parent, const char *name)
300 /* FIXME */
301 return WERR_NOT_SUPPORTED;
304 static struct policy_handle*get_hive(REG_KEY *k)
306 int i;
307 struct rpc_data *mydata = k->handle->backend_data;
308 for(i = 0; known_hives[i].name; i++) {
309 if(!strncmp(known_hives[i].name, reg_key_get_path(k)+1, strlen(known_hives[i].name)))
310 return mydata->hives[i];
312 return NULL;
315 static WERROR rpc_del_key(REG_KEY *k)
317 NTSTATUS status;
318 struct rpc_data *mydata = k->handle->backend_data;
319 struct winreg_DeleteKey r;
320 char *hivepath;
321 struct policy_handle *hive = get_hive(k);
323 printf("first: %s\n", reg_key_get_path(k));
324 hivepath = strchr(reg_key_get_path(k), '\\');
325 hivepath = strchr(hivepath+1, '\\');
326 printf("asfter: %s\n", hivepath+1);
328 r.in.handle = hive;
329 init_winreg_String(&r.in.key, hivepath+1);
331 status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
333 return r.out.result;
336 static struct registry_ops reg_backend_rpc = {
337 .name = "rpc",
338 .open_registry = rpc_open_registry,
339 .close_registry = rpc_close_registry,
340 .open_root_key = rpc_open_root,
341 .open_key = rpc_open_key,
342 .fetch_subkeys = rpc_fetch_subkeys,
343 .fetch_values = rpc_fetch_values,
344 .add_key = rpc_add_key,
345 .del_key = rpc_del_key,
348 NTSTATUS reg_rpc_init(void)
350 return register_backend("registry", &reg_backend_rpc);