r665: merge over the new build system from my tmp branch
[gd/samba-autobuild/.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 /**
24  * This is the RPC backend for the registry library.
25  *
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.
28  */
29
30 static void init_winreg_String(struct winreg_String *name, const char *s)
31 {
32     name->name = s;
33     if (s) {
34         name->name_len = 2 * (strlen_m(s) + 1);
35         name->name_size = name->name_len;
36     } else {
37         name->name_len = 0;
38         name->name_size = 0;
39     }
40 }
41
42
43 #define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \
44 { \
45         struct winreg_Open ## u r; \
46         struct winreg_OpenUnknown unknown; \
47         struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
48         \
49         unknown.unknown0 = 0x84e0; \
50         unknown.unknown1 = 0x0000; \
51         r.in.unknown = &unknown; \
52         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
53         r.out.handle = hnd;\
54         \
55         if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\
56                 DEBUG(0,("Error executing open\n"));\
57                 return NULL;\
58         }\
59 \
60         return hnd;\
61 }
62
63 openhive(HKLM)
64 openhive(HKCU)
65 openhive(HKPD)
66 openhive(HKU)
67 openhive(HKCR)
68
69 struct rpc_data {
70         struct dcerpc_pipe *pipe;
71         struct policy_handle *hives[10];
72 };
73
74 struct rpc_key_data {
75         struct policy_handle pol;
76         int num_subkeys;
77         int num_values;
78         int max_valnamelen;
79         int max_valdatalen;
80 };
81
82 struct {
83         const char *name;
84         struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
85 } known_hives[] = {
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 },
91 { NULL, NULL }
92 };
93
94 static WERROR rpc_query_key(REG_KEY *k);
95
96 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
97 {
98         struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
99         char *binding = strdup(location);
100         NTSTATUS status;
101         char *user, *pass;
102
103         if(!credentials || !location) return WERR_INVALID_PARAM;
104
105         user = talloc_strdup(h->mem_ctx, credentials);
106         pass = strchr(user, '%');
107         *pass = '\0'; pass++;
108
109         ZERO_STRUCTP(mydata);
110         
111         status = dcerpc_pipe_connect(&mydata->pipe, binding, 
112                     DCERPC_WINREG_UUID,
113                     DCERPC_WINREG_VERSION,
114                      lp_workgroup(),
115                      user, pass);
116
117         h->backend_data = mydata;
118         
119         return ntstatus_to_werror(status);
120 }
121
122 static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
123 {
124         /* There's not really a 'root' key here */
125         *k = reg_key_new_abs("\\", h, h->backend_data);
126         return WERR_OK;
127 }
128
129 static WERROR rpc_close_registry(REG_HANDLE *h)
130 {
131         dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
132         return WERR_OK;
133 }
134
135 static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
136 {
137         struct policy_handle *hive = NULL;
138     struct winreg_OpenKey r;
139         int i;
140         struct rpc_data *mydata = k->handle->backend_data;
141         struct rpc_key_data *mykeydata;
142         char *realkeyname, *hivename;
143
144         if(k->backend_data) { 
145                 *data = k->backend_data; 
146                 return WERR_OK;
147         }
148
149         k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
150         *data = mykeydata;
151         mykeydata->num_values = -1;
152         mykeydata->num_subkeys = -1;
153
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);
158
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];
163                         break;
164                 }
165         }
166         
167         if(!hive) {
168                 DEBUG(0, ("No such hive: %s\n", hivename));
169                 return WERR_FOOBAR;
170         }
171
172         if(realkeyname && realkeyname[0] == '\\')realkeyname++;
173
174         if(!realkeyname || !(*realkeyname)) { 
175                 mykeydata->pol = *hive;
176                 return WERR_OK;
177         }
178
179         /* Then, open the handle using the hive */
180
181         memset(&r, 0, sizeof(struct winreg_OpenKey));
182     r.in.handle = hive;
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;
187
188     dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
189
190         return r.out.result;
191 }
192
193 static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
194 {
195         struct rpc_key_data *mykeydata;
196         *key = reg_key_new_abs(name, h, NULL);
197         return rpc_key_put_rpc_data(*key, &mykeydata);
198 }
199
200 static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)  
201 {
202         struct winreg_EnumValue r;
203         struct winreg_Uint8buf vb;
204         struct rpc_data *mydata = parent->handle->backend_data;
205         struct winreg_EnumValueName vn;
206         NTSTATUS status;
207         struct rpc_key_data *mykeydata;
208         uint32 type = 0x0, requested_len = 0, returned_len = 0;
209         WERROR error;
210
211         error = rpc_key_put_rpc_data(parent, &mykeydata);
212         if(!W_ERROR_IS_OK(error)) return error;
213
214         /* Root is a special case */
215         if(parent->backend_data == parent->handle->backend_data) {
216                 return WERR_NO_MORE_ITEMS;
217         }
218
219         if(mykeydata->num_values == -1) {
220                 error = rpc_query_key(parent);
221                 if(!W_ERROR_IS_OK(error)) return error;
222         }
223
224         requested_len = mykeydata->max_valdatalen;
225
226         r.in.handle = &mykeydata->pol;
227         r.in.enum_index = n;
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;
232         vn.len = 0;
233         vn.buf = NULL;
234         if(vn.max_len > 0) {
235                 vn.len = 0;
236                 vn.max_len = mykeydata->max_valnamelen*2;
237                 /* FIXME: we should not point a 'char *' to a const buffer!!! --metze*/
238                 vn.buf = "";
239         }
240         r.in.name = r.out.name = &vn;
241         vb.max_len = mykeydata->max_valdatalen;
242         vb.offset = 0x0;
243         vb.len = 0x0;
244         vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
245         r.in.value = r.out.value = &vb;
246
247         status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
248         if(NT_STATUS_IS_ERR(status)) {
249                 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
250         }
251         
252         if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
253                 *value = reg_val_new(parent, NULL);
254                 (*value)->name = r.out.name->buf;
255                 (*value)->data_type = type;
256                 (*value)->data_len = r.out.value->len;
257                 (*value)->data_blk = r.out.value->buffer;
258                 exit(1);
259                 return WERR_OK;
260         }
261         
262         return r.out.result;
263 }
264
265 static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) 
266 {
267         struct winreg_EnumKey r;
268         struct winreg_EnumKeyNameRequest keyname;
269         struct winreg_String classname;
270         struct winreg_Time tm;
271         struct rpc_data *mydata = parent->handle->backend_data;
272         struct rpc_key_data *mykeydata = parent->backend_data;
273         WERROR error;
274         NTSTATUS status;
275
276         /* If parent is the root key, list the hives */
277         if(parent->backend_data == mydata) { 
278                 if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
279                 *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL);
280                 return rpc_key_put_rpc_data(*subkey, &mykeydata);
281         }
282
283         error = rpc_key_put_rpc_data(parent, &mykeydata);
284         if(!W_ERROR_IS_OK(error)) return error;
285
286         r.in.handle = &mykeydata->pol;
287         keyname.unknown = 0x0000020a;
288         init_winreg_String(&keyname.key_name, NULL);
289         init_winreg_String(&classname, NULL);
290         r.in.in_name = &keyname;
291         r.in.class = &classname;
292         tm.low = tm.high = 0x7fffffff;
293         r.in.last_changed_time = &tm;
294         r.out.result.v = 0;
295
296         r.in.enum_index = n;
297         r.in.unknown = r.out.unknown = 0x0414;
298         r.in.key_name_len = r.out.key_name_len = 0;
299         status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
300         if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
301                 *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL);
302         }
303
304         return r.out.result;
305 }
306
307 static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key)
308 {
309         struct rpc_key_data *mykeydata;
310         WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
311         if(!W_ERROR_IS_OK(error)) return error;
312
313         /* FIXME */
314         return WERR_NOT_SUPPORTED;
315 }
316
317 static WERROR rpc_query_key(REG_KEY *k)
318 {
319     NTSTATUS status;
320     struct winreg_QueryInfoKey r;
321     struct rpc_data *mydata = k->handle->backend_data;
322     struct rpc_key_data *mykeydata;                                                                                                       
323     r.in.handle = &mykeydata->pol;
324     init_winreg_String(&r.in.class, NULL);
325                                                                                                        
326     status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
327                                                                                                        
328     if (!NT_STATUS_IS_OK(status)) {
329         printf("QueryInfoKey failed - %s\n", nt_errstr(status));
330         return ntstatus_to_werror(status);
331     }
332                                                                                                        
333     if (W_ERROR_IS_OK(r.out.result)) {
334                 mykeydata->num_subkeys = r.out.num_subkeys;
335                 mykeydata->num_values = r.out.num_values;
336                 mykeydata->max_valnamelen = r.out.max_valnamelen;
337                 mykeydata->max_valdatalen = r.out.max_valbufsize;
338         } 
339
340         return r.out.result;
341 }
342
343 static WERROR rpc_del_key(REG_KEY *k)
344 {
345         NTSTATUS status;
346         struct rpc_data *mydata = k->handle->backend_data;
347         struct rpc_key_data *mykeydata;
348         struct winreg_DeleteKey r;
349         REG_KEY *parent;
350         WERROR error;
351         
352         error = reg_key_get_parent(k, &parent);
353         if(!W_ERROR_IS_OK(error)) return error;
354         
355         error = rpc_key_put_rpc_data(parent, &mykeydata);
356         if(!W_ERROR_IS_OK(error)) return error;
357
358     r.in.handle = &mykeydata->pol;
359     init_winreg_String(&r.in.key, k->name);
360  
361     status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
362
363         return r.out.result;
364 }
365
366 static void rpc_close_key(REG_KEY *k)
367 {
368         reg_key_free(k);
369 }
370
371 static WERROR rpc_num_values(REG_KEY *key, int *count) {
372         struct rpc_key_data *mykeydata;
373         WERROR error;
374                 
375         /* Root is a special case */
376         if(key->backend_data == key->handle->backend_data) {
377                 *count = 0;
378                 return WERR_OK;
379         }
380                 
381         error = rpc_key_put_rpc_data(key, &mykeydata);
382         if(!W_ERROR_IS_OK(error)) return error;
383
384         if(mykeydata->num_values == -1) {
385                 error = rpc_query_key(key);
386                 if(!W_ERROR_IS_OK(error)) return error;
387         }
388                         
389         *count = mykeydata->num_values;
390         return WERR_OK;
391 }
392
393 static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
394         struct rpc_key_data *mykeydata;
395         WERROR error;
396         
397         /* Root is a special case */
398         if(key->backend_data == key->handle->backend_data) {
399                 int i;
400                 for(i = 0; known_hives[i].name; i++);
401                 *count = i;
402                 return WERR_OK;
403         }
404         
405         error = rpc_key_put_rpc_data(key, &mykeydata);
406         if(!W_ERROR_IS_OK(error)) return error;
407
408         if(mykeydata->num_subkeys == -1) {
409                 error = rpc_query_key(key);
410                 if(!W_ERROR_IS_OK(error)) return error;
411         }
412                         
413         *count = mykeydata->num_subkeys;
414         return WERR_OK;
415 }
416
417 static struct registry_ops reg_backend_rpc = {
418         .name = "rpc",
419         .open_registry = rpc_open_registry,
420         .close_registry = rpc_close_registry,
421         .open_root_key = rpc_open_root,
422         .open_key = rpc_open_key,
423         .get_subkey_by_index = rpc_get_subkey_by_index,
424         .get_value_by_index = rpc_get_value_by_index,
425         .add_key = rpc_add_key,
426         .del_key = rpc_del_key,
427         .free_key_backend_data = rpc_close_key,
428         .num_subkeys = rpc_num_subkeys,
429         .num_values = rpc_num_values,
430 };
431
432 NTSTATUS registry_rpc_init(void)
433 {
434         return register_backend("registry", &reg_backend_rpc);
435 }