28e2094bedd41aa1661acc08f4326c6fd7c9b682
[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 /**
24  * This is the RPC backend for the registry library.
25  */
26
27 static void init_winreg_String(struct winreg_String *name, const char *s)
28 {
29     name->name = s;
30     if (s) {
31         name->name_len = 2 * (strlen_m(s) + 1);
32         name->name_size = name->name_len;
33     } else {
34         name->name_len = 0;
35         name->name_size = 0;
36     }
37 }
38
39
40 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \
41 { \
42         struct winreg_Open ## u r; \
43         struct winreg_OpenUnknown unknown; \
44         NTSTATUS status; \
45         \
46         unknown.unknown0 = 0x84e0; \
47         unknown.unknown1 = 0x0000; \
48         r.in.unknown = &unknown; \
49         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
50         r.out.handle = hnd;\
51         \
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);\
56         }\
57 \
58         return r.out.result;\
59 }
60
61 openhive(HKLM)
62 openhive(HKCU)
63 openhive(HKPD)
64 openhive(HKU)
65 openhive(HKCR)
66
67 struct rpc_key_data {
68         struct policy_handle pol;
69         int num_subkeys;
70         int num_values;
71         int max_valnamelen;
72         int max_valdatalen;
73 };
74
75 struct {
76         const char *name;
77         WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h);
78 } known_hives[] = {
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 },
84 { NULL, NULL }
85 };
86
87 static WERROR rpc_query_key(REG_KEY *k);
88
89 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
90 {
91         char *binding = strdup(location);
92         NTSTATUS status;
93         char *user, *pass;
94
95         if(!credentials || !location) return WERR_INVALID_PARAM;
96
97         user = talloc_strdup(h->mem_ctx, credentials);
98         pass = strchr(user, '%');
99         *pass = '\0'; pass++;
100
101         status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding, 
102                     DCERPC_WINREG_UUID,
103                     DCERPC_WINREG_VERSION,
104                      lp_workgroup(),
105                      user, pass);
106         
107         return ntstatus_to_werror(status);
108 }
109
110 static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k)
111 {
112         struct rpc_key_data *mykeydata;
113         WERROR error;
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);
120         return error;
121 }
122
123 static WERROR rpc_close_registry(REG_HANDLE *h)
124 {
125         dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data);
126         return WERR_OK;
127 }
128
129 static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
130 {
131     struct winreg_OpenKey r;
132         int i;
133         struct rpc_data *mydata = k->handle->backend_data;
134         WERROR error;
135         REG_KEY *hivekey;
136         struct rpc_key_data *mykeydata;
137
138         if(k->backend_data) { 
139                 *data = k->backend_data; 
140                 return WERR_OK;
141         }
142
143         k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
144         *data = mykeydata;
145         mykeydata->num_values = -1;
146         mykeydata->num_subkeys = -1;
147
148         /* Then, open the handle using the hive */
149
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;
158
159     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
160
161         return r.out.result;
162 }
163
164 static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key)
165 {
166         struct rpc_key_data *mykeydata;
167     struct winreg_OpenKey r;
168         REG_KEY *hivekey;
169         WERROR error;
170         
171         *key = reg_key_new_abs(name, h, NULL);
172
173         (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data);
174         mykeydata->num_values = -1;
175         mykeydata->num_subkeys = -1;
176
177         /* Then, open the handle using the hive */
178
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;
187
188     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r);
189
190         return r.out.result;
191 }
192
193 static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)  
194 {
195         struct winreg_EnumValue r;
196         struct winreg_Uint8buf vb;
197         struct winreg_EnumValueName vn;
198         NTSTATUS status;
199         struct rpc_key_data *mykeydata;
200         uint32_t type = 0x0, requested_len = 0, returned_len = 0;
201         WERROR error;
202
203         error = rpc_key_put_rpc_data(parent, &mykeydata);
204         if(!W_ERROR_IS_OK(error)) return error;
205
206         if(mykeydata->num_values == -1) {
207                 error = rpc_query_key(parent);
208                 if(!W_ERROR_IS_OK(error)) return error;
209         }
210
211         requested_len = mykeydata->max_valdatalen;
212
213         r.in.handle = &mykeydata->pol;
214         r.in.enum_index = n;
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;
219         vn.len = 0;
220         vn.buf = NULL;
221         if(vn.max_len > 0) {
222                 vn.len = 0;
223                 vn.max_len = mykeydata->max_valnamelen*2;
224                 /* FIXME: we should not point a 'char *' to a const buffer!!! --metze*/
225                 vn.buf = "";
226         }
227         r.in.name = r.out.name = &vn;
228         vb.max_len = mykeydata->max_valdatalen;
229         vb.offset = 0x0;
230         vb.len = 0x0;
231         vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
232         r.in.value = r.out.value = &vb;
233
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)));
237         }
238         
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;
245                 exit(1);
246                 return WERR_OK;
247         }
248         
249         return r.out.result;
250 }
251
252 static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) 
253 {
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;
260         WERROR error;
261         NTSTATUS status;
262
263         error = rpc_key_put_rpc_data(parent, &mykeydata);
264         if(!W_ERROR_IS_OK(error)) return error;
265
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;
274
275         r.in.enum_index = n;
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);
281         }
282
283         return r.out.result;
284 }
285
286 static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **key)
287 {
288         struct rpc_key_data *mykeydata;
289         WERROR error;
290
291         error = rpc_key_put_rpc_data(parent, &mykeydata);
292         if(!W_ERROR_IS_OK(error)) return error;
293
294         /* FIXME */
295         return WERR_NOT_SUPPORTED;
296 }
297
298 static WERROR rpc_query_key(REG_KEY *k)
299 {
300     NTSTATUS status;
301         WERROR error;
302     struct winreg_QueryInfoKey r;
303     struct rpc_key_data *mykeydata;
304
305         error = rpc_key_put_rpc_data(k, &mykeydata);
306         if(!W_ERROR_IS_OK(error)) return error;
307
308     init_winreg_String(&r.in.class, NULL);
309     r.in.handle = &mykeydata->pol;
310         
311     status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
312
313     if (!NT_STATUS_IS_OK(status)) {
314         printf("QueryInfoKey failed - %s\n", nt_errstr(status));
315         return ntstatus_to_werror(status);
316     }
317                                                                                                        
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;
323         } 
324
325         return r.out.result;
326 }
327
328 static WERROR rpc_del_key(REG_KEY *k)
329 {
330         NTSTATUS status;
331         struct rpc_key_data *mykeydata = k->backend_data;
332         struct winreg_DeleteKey r;
333         REG_KEY *parent;
334         WERROR error;
335         
336         error = reg_key_get_parent(k, &parent);
337         if(!W_ERROR_IS_OK(error)) return error;
338
339         error = rpc_key_put_rpc_data(parent, &mykeydata);
340         if(!W_ERROR_IS_OK(error)) return error;
341         
342     r.in.handle = &mykeydata->pol;
343     init_winreg_String(&r.in.key, k->name);
344  
345     status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
346
347         return r.out.result;
348 }
349
350 static void rpc_close_key(REG_KEY *k)
351 {
352         reg_key_free(k);
353 }
354
355 static WERROR rpc_num_values(REG_KEY *key, int *count) {
356         struct rpc_key_data *mykeydata = key->backend_data;
357         WERROR error;
358                 
359         error = rpc_key_put_rpc_data(key, &mykeydata);
360         if(!W_ERROR_IS_OK(error)) return error;
361
362         if(mykeydata->num_values == -1) {
363                 error = rpc_query_key(key);
364                 if(!W_ERROR_IS_OK(error)) return error;
365         }
366                         
367         *count = mykeydata->num_values;
368         return WERR_OK;
369 }
370
371 static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
372         struct rpc_key_data *mykeydata = key->backend_data;
373         WERROR error;
374
375         error = rpc_key_put_rpc_data(key, &mykeydata);
376         if(!W_ERROR_IS_OK(error)) return error;
377         
378         if(mykeydata->num_subkeys == -1) {
379                 error = rpc_query_key(key);
380                 if(!W_ERROR_IS_OK(error)) return error;
381         }
382                         
383         *count = mykeydata->num_subkeys;
384         return WERR_OK;
385 }
386
387 static struct registry_ops reg_backend_rpc = {
388         .name = "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,
400 };
401
402 NTSTATUS registry_rpc_init(void)
403 {
404         return register_backend("registry", &reg_backend_rpc);
405 }