r164: Viewing remote registries with gregedit works now
[kai/samba.git] / source4 / lib / registry / reg_backend_rpc / reg_backend_rpc.c
1 /*
2    Samba Unix/Linux SMB implementation
3    RPC backend for the registry library
4    Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org
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 2 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 #include "includes.h"
21 #include "lib/registry/common/registry.h"
22
23 static void init_winreg_String(struct winreg_String *name, const char *s)
24 {
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;
32     }
33 }
34
35
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)); \
42         \
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;\
48         \
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;\
52         }\
53 \
54         return hnd;\
55 }
56
57 openhive(HKLM)
58 openhive(HKCU)
59 openhive(HKPD)
60 openhive(HKU)
61 openhive(HKCR)
62
63 struct rpc_data {
64         struct dcerpc_pipe *pipe;
65         struct policy_handle *hives[10];
66 };
67
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 }
78 };
79
80 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
81 {
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;
86
87         if(!credentials || !location) return WERR_INVALID_PARAM;
88
89         user = talloc_strdup(h->mem_ctx, credentials);
90         pass = strchr(user, '%');
91         *pass = '\0'; pass++;
92
93         ZERO_STRUCTP(mydata);
94         
95         status = dcerpc_pipe_connect(&mydata->pipe, binding, 
96                     DCERPC_WINREG_UUID,
97                     DCERPC_WINREG_VERSION,
98                      lp_workgroup(),
99                      user, pass);
100
101
102         h->backend_data = mydata;
103         
104         return ntstatus_to_werror(status);
105 }
106
107 static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
108 {
109         /* There's not really a 'root' key here */
110         *k = reg_key_new_abs("\\", h, h->backend_data);
111         return WERR_OK;
112 }
113
114 static WERROR rpc_close_registry(REG_HANDLE *h)
115 {
116         dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
117         free(h->backend_data);
118         return WERR_OK;
119 }
120
121 static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
122 {
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;
132  
133         if(end) hivename = strndup(path+1, end-path-1);
134         else hivename = strdup(path+1);
135
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];
140                 }
141         }
142         
143         if(!hive) {
144                 DEBUG(0, ("No such hive: %s\n", hivename));
145                 return NULL;
146         }
147
148         DEBUG(2, ("Opening %s, hive: %s\n", path, hivename));
149
150         if(!end || !(*end) || !(*(end+1))) return hive;
151
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;
158                         
159         mem_ctx = talloc_init("openkey");
160     status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r);
161         talloc_destroy(mem_ctx);
162                                                                                                                                
163     if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
164         return NULL;
165     }
166
167         return key_handle;
168 }
169
170 static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
171 {
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;
176 }
177
178 static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) 
179 {
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;
189
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));
196                 }
197
198                 *subkeys = ar;
199
200                 return WERR_OK;
201         }
202
203         if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
204
205         if(!parent->backend_data) return WERR_GENERAL_FAILURE;
206
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;
217
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 *));
227                 }
228         }
229
230         *subkeys = ar;
231         return r.out.result;
232 }
233
234 static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) 
235 {
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 *));
244
245         (*count) = 0;
246
247         /* Root */
248         if(parent->backend_data == parent->handle->backend_data) {
249                 *values = ar;
250                 return WERR_OK;
251         }
252         
253         if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
254
255         if(!parent->backend_data) return WERR_GENERAL_FAILURE;
256
257         r.in.handle = parent->backend_data;
258         r.in.enum_index = 0;
259
260         init_winreg_String(&valuename, NULL);
261         r.in.name = r.out.name = &valuename;
262
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;
269
270         r.in.value = r.out.value = &value;
271
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;
277
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;
291         } 
292         
293         *values = ar;
294
295         return r.out.result;
296 }
297
298 static WERROR rpc_add_key(REG_KEY *parent, const char *name)
299 {
300         /* FIXME */
301         return WERR_NOT_SUPPORTED;
302 }
303
304 static struct policy_handle*get_hive(REG_KEY *k)
305 {
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];
311         }
312         return NULL;
313 }
314
315 static WERROR rpc_del_key(REG_KEY *k)
316 {
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);
322
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);
327         
328     r.in.handle = hive;
329     init_winreg_String(&r.in.key, hivepath+1);
330  
331     status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
332
333         return r.out.result;
334 }
335
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,
346 };
347
348 NTSTATUS reg_rpc_init(void)
349 {
350         return register_backend("registry", &reg_backend_rpc);
351 }