954e7684bbe9cf70d9114f7d62805355928869b2
[jelmer/samba4-debian.git] / source / 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 "registry.h"
22 #include "librpc/gen_ndr/ndr_winreg.h"
23
24 /**
25  * This is the RPC backend for the registry library.
26  */
27
28 static void init_winreg_String(struct winreg_String *name, const char *s)
29 {
30     name->name = s;
31     if (s) {
32         name->name_len = 2 * (strlen_m(s) + 1);
33         name->name_size = name->name_len;
34     } else {
35         name->name_len = 0;
36         name->name_size = 0;
37     }
38 }
39
40
41 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
42 { \
43         struct winreg_Open ## u r; \
44         struct winreg_OpenUnknown unknown; \
45         NTSTATUS status; \
46         \
47         unknown.unknown0 = 0x84e0; \
48         unknown.unknown1 = 0x0000; \
49         r.in.unknown = &unknown; \
50         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
51         r.out.handle = hnd;\
52         \
53         status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
54         if (NT_STATUS_IS_ERR(status)) {\
55                 DEBUG(0,("Error executing open\n"));\
56                 return ntstatus_to_werror(status);\
57         }\
58 \
59         return r.out.result;\
60 }
61
62 openhive(HKLM)
63 openhive(HKCU)
64 openhive(HKPD)
65 openhive(HKU)
66 openhive(HKCR)
67
68 struct rpc_key_data {
69         struct policy_handle pol;
70         int num_subkeys;
71         int num_values;
72         int max_valnamelen;
73         int max_valdatalen;
74 };
75
76 struct {
77         const char *name;
78         WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h);
79 } known_hives[] = {
80 { "HKEY_LOCAL_MACHINE", open_HKLM },
81 { "HKEY_CURRENT_USER", open_HKCU },
82 { "HKEY_CLASSES_ROOT", open_HKCR },
83 { "HKEY_PERFORMANCE_DATA", open_HKPD },
84 { "HKEY_USERS", open_HKU },
85 { NULL, NULL }
86 };
87
88 static WERROR rpc_query_key(struct registry_key *k);
89
90 static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives)
91 {
92         int i = 0;
93         *hives = talloc_p(mem_ctx, char *);
94         for(i = 0; known_hives[i].name; i++) {
95                 *hives = talloc_realloc_p(mem_ctx, *hives, char *, i+2);
96                 (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name);
97         }
98         (*hives)[i] = NULL;
99         return WERR_OK;
100 }
101
102 static WERROR rpc_close_hive (struct registry_hive *h)
103 {
104         dcerpc_pipe_close(h->backend_data);
105         return WERR_OK;
106 }
107
108 static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k)
109 {
110         NTSTATUS status;
111         char *user;
112         char *pass;
113         struct rpc_key_data *mykeydata;
114         struct dcerpc_pipe *p;
115         int n;
116
117         if (!h->credentials) return WERR_INVALID_PARAM;
118
119         /* Default to local smbd if no connection is specified */
120         if (!h->location) {
121                 h->location = talloc_strdup(mem_ctx, "ncalrpc:");
122         }
123
124         user = talloc_strdup(mem_ctx, h->credentials);
125         pass = strchr(user, '%');
126         if (pass) {
127                 *pass = '\0';
128                 pass = strdup(pass+1);
129         } else {
130                 pass = strdup("");
131         }
132
133         status = dcerpc_pipe_connect(&p, h->location, 
134                                      DCERPC_WINREG_UUID,
135                                      DCERPC_WINREG_VERSION,
136                                      lp_workgroup(),
137                                      user, pass);
138         free(pass);
139
140         h->backend_data = p;
141
142         if(NT_STATUS_IS_ERR(status)) {
143                 DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status)));
144                 return ntstatus_to_werror(status);
145         }
146
147         for(n = 0; known_hives[n].name; n++) 
148         {
149                 if(!strcmp(known_hives[n].name, h->backend_hivename)) break;
150         }
151         
152         if(!known_hives[n].name)  {
153                 DEBUG(1, ("No such hive %s\n", known_hives[n].name));
154                 return WERR_NO_MORE_ITEMS;
155         }
156         
157         *k = talloc_p(mem_ctx, struct registry_key);
158         (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
159         mykeydata->num_values = -1;
160         mykeydata->num_subkeys = -1;
161         return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol));
162 }
163
164 #if 0
165 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
166 {
167     struct winreg_OpenKey r;
168         struct rpc_key_data *mykeydata;
169
170         k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
171         mykeydata->num_values = -1;
172         mykeydata->num_subkeys = -1;
173
174         /* Then, open the handle using the hive */
175
176         memset(&r, 0, sizeof(struct winreg_OpenKey));
177     r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
178     init_winreg_String(&r.in.keyname, k->path);
179     r.in.unknown = 0x00000000;
180     r.in.access_mask = 0x02000000;
181     r.out.handle = &mykeydata->pol;
182
183     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
184
185         return r.out.result;
186 }
187 #endif
188
189 static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key)
190 {
191         struct rpc_key_data *mykeydata;
192     struct winreg_OpenKey r;
193
194         *key = talloc_p(mem_ctx, struct registry_key);
195         (*key)->name = talloc_strdup(mem_ctx, name);
196
197         (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
198         mykeydata->num_values = -1;
199         mykeydata->num_subkeys = -1;
200
201         /* Then, open the handle using the hive */
202
203         memset(&r, 0, sizeof(struct winreg_OpenKey));
204     r.in.handle = &(((struct rpc_key_data *)h->backend_data)->pol);
205     init_winreg_String(&r.in.keyname, name);
206     r.in.unknown = 0x00000000;
207     r.in.access_mask = 0x02000000;
208     r.out.handle = &mykeydata->pol;
209
210     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r);
211
212         return r.out.result;
213 }
214
215 static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key)
216 {
217         return rpc_open_rel_key(mem_ctx, h->root, name, key);
218 }
219
220 static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value)  
221 {
222         struct rpc_key_data *mykeydata = parent->backend_data;
223         WERROR error;
224         struct winreg_EnumValue r;
225         uint32 type, len1, len2 = 0;
226         struct EnumValueIn buf_name, buf_val;
227         NTSTATUS status;
228         
229         if(mykeydata->num_values == -1) {
230                 error = rpc_query_key(parent);
231                 if(!W_ERROR_IS_OK(error)) return error;
232         }
233
234         len1 = mykeydata->max_valdatalen;
235         
236         r.in.handle = &mykeydata->pol;
237         r.in.enum_index = n;
238         r.in.name_in.len = 0;
239         r.in.name_in.max_len = mykeydata->max_valnamelen * 2;
240         buf_name.max_len = mykeydata->max_valnamelen;
241         buf_name.offset = 0;
242         buf_name.len = 0;
243         r.in.name_in.buffer = &buf_name;
244         r.in.type = &type;
245         buf_val.max_len = mykeydata->max_valdatalen;
246         buf_val.offset = 0;
247         buf_val.len = 0;
248         r.in.value_in = &buf_val;
249         r.in.value_len1 = &len1;
250         r.in.value_len2 = &len2;
251         r.out.type = &type;
252
253         
254         status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
255         if(NT_STATUS_IS_ERR(status)) {
256                 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
257                 return WERR_GENERAL_FAILURE;
258         }
259         
260         if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
261                 *value = talloc_p(mem_ctx, struct registry_value);
262                 (*value)->parent = parent;
263                 (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name);
264                 (*value)->data_type = type;
265                 (*value)->data_len = r.out.value_out->buffer.length;
266                 (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value_out->buffer.data, r.out.value_out->buffer.length);
267                 return WERR_OK;
268         }
269         
270         return r.out.result;
271 }
272
273 static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) 
274 {
275         struct winreg_EnumKey r;
276         struct winreg_EnumKeyNameRequest keyname;
277         struct winreg_String classname;
278         struct winreg_Time tm;
279         struct rpc_key_data *mykeydata = parent->backend_data;
280         NTSTATUS status;
281
282         r.in.handle = &mykeydata->pol;
283         keyname.unknown = 0x0000020a;
284         init_winreg_String(&keyname.key_name, NULL);
285         init_winreg_String(&classname, NULL);
286         r.in.in_name = &keyname;
287         r.in.class = &classname;
288         tm.low = tm.high = 0x7fffffff;
289         r.in.last_changed_time = &tm;
290
291         r.in.enum_index = n;
292         r.in.unknown = r.out.unknown = 0x0414;
293         r.in.key_name_len = r.out.key_name_len = 0;
294         status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
295         if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
296                         return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey);
297         }
298
299         return r.out.result;
300 }
301
302 static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key)
303 {
304         return WERR_NOT_SUPPORTED;
305 }
306
307 static WERROR rpc_query_key(struct registry_key *k)
308 {
309     NTSTATUS status;
310     struct winreg_QueryInfoKey r;
311     struct rpc_key_data *mykeydata = k->backend_data;
312         TALLOC_CTX *mem_ctx = talloc_init("query_key");
313
314     init_winreg_String(&r.in.class, NULL);
315     r.in.handle = &mykeydata->pol;
316         
317     status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r);
318         talloc_destroy(mem_ctx);
319
320     if (!NT_STATUS_IS_OK(status)) {
321         DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
322         return ntstatus_to_werror(status);
323     }
324                                                                                                        
325     if (W_ERROR_IS_OK(r.out.result)) {
326                 mykeydata->num_subkeys = r.out.num_subkeys;
327                 mykeydata->num_values = r.out.num_values;
328                 mykeydata->max_valnamelen = r.out.max_valnamelen;
329                 mykeydata->max_valdatalen = r.out.max_valbufsize;
330         } 
331
332         return r.out.result;
333 }
334
335 static WERROR rpc_del_key(struct registry_key *k)
336 {
337         NTSTATUS status;
338         struct rpc_key_data *mykeydata = k->backend_data;
339         struct winreg_DeleteKey r;
340         struct registry_key *parent;
341         WERROR error;
342         TALLOC_CTX *mem_ctx = talloc_init("del_key");
343         
344         error = reg_key_get_parent(mem_ctx, k, &parent);
345         if(!W_ERROR_IS_OK(error)) { 
346                 talloc_destroy(mem_ctx); 
347                 return error; 
348         }
349
350         mykeydata = parent->backend_data;
351
352     r.in.handle = &mykeydata->pol;
353     init_winreg_String(&r.in.key, k->name);
354  
355     status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
356
357         talloc_destroy(mem_ctx);
358
359         return r.out.result;
360 }
361
362 static WERROR rpc_num_values(struct registry_key *key, int *count) {
363         struct rpc_key_data *mykeydata = key->backend_data;
364         WERROR error;
365                 
366         if(mykeydata->num_values == -1) {
367                 error = rpc_query_key(key);
368                 if(!W_ERROR_IS_OK(error)) return error;
369         }
370                         
371         *count = mykeydata->num_values;
372         return WERR_OK;
373 }
374
375 static WERROR rpc_num_subkeys(struct registry_key *key, int *count) {
376         struct rpc_key_data *mykeydata = key->backend_data;
377         WERROR error;
378
379         if(mykeydata->num_subkeys == -1) {
380                 error = rpc_query_key(key);
381                 if(!W_ERROR_IS_OK(error)) return error;
382         }
383                         
384         *count = mykeydata->num_subkeys;
385         return WERR_OK;
386 }
387
388 static struct registry_operations reg_backend_rpc = {
389         .name = "rpc",
390         .open_hive = rpc_open_hive,
391         .close_hive = rpc_close_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         .num_subkeys = rpc_num_subkeys,
398         .num_values = rpc_num_values,
399         .list_available_hives = rpc_list_hives,
400 };
401
402 NTSTATUS registry_rpc_init(void)
403 {
404         return register_backend("registry", &reg_backend_rpc);
405 }