ad4d537f9b1456d437ac21a1be53b8951fb55aa9
[ira/wip.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                 printf("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 BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full)
81 {
82         BOOL res = True;
83         struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
84         char *binding = strdup(location);
85         NTSTATUS status;
86         
87         ZERO_STRUCTP(mydata);
88         
89         status = dcerpc_pipe_connect(&mydata->pipe, binding, 
90                     DCERPC_WINREG_UUID,
91                     DCERPC_WINREG_VERSION,
92                      lp_workgroup(),
93                      "tridge", "samba");
94
95         if(!NT_STATUS_IS_OK(status)) return False;
96
97         h->backend_data = mydata;
98         
99         return True;
100 }
101
102 static REG_KEY *rpc_open_root(REG_HANDLE *h)
103 {
104         /* There's not really a 'root' key here */
105         return reg_key_new_abs("\\", h, h->backend_data);
106 }
107
108 static BOOL rpc_close_registry(REG_HANDLE *h)
109 {
110         dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
111         free(h->backend_data);
112         return True;
113 }
114
115 static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
116 {
117         char *hivename;
118         int i = 0;
119         struct rpc_data *mydata = h->backend_data;
120         struct policy_handle *hive = NULL;
121         char *end = strchr(path+1, '\\');
122     NTSTATUS status;
123     struct winreg_OpenKey r;
124         struct policy_handle *key_handle = talloc(h->mem_ctx, sizeof(struct policy_handle));
125         TALLOC_CTX *mem_ctx;
126  
127         if(end) hivename = strndup(path+1, end-path-1);
128         else hivename = strdup(path+1);
129
130         for(i = 0; known_hives[i].name; i++) {
131                 if(!strcmp(hivename, known_hives[i].name)) {
132                 if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, h);
133                         hive = mydata->hives[i];
134                 }
135         }
136         
137         if(!hive) {
138                 DEBUG(0, ("No such hive: %s\n", hivename));
139                 return NULL;
140         }
141
142         DEBUG(2, ("Opening %s, hive: %s\n", path, hivename));
143
144         if(!end || !(*end) || !(*(end+1))) return hive;
145
146         memset(&r, 0, sizeof(struct winreg_OpenKey));
147     r.in.handle = hive;
148     init_winreg_String(&r.in.keyname, end+1);
149     r.in.unknown = 0x00000000;
150     r.in.access_mask = 0x02000000;
151     r.out.handle = key_handle;
152                         
153         mem_ctx = talloc_init("openkey");
154     status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r);
155         talloc_destroy(mem_ctx);
156                                                                                                                                
157     if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
158         return NULL;
159     }
160
161         return key_handle;
162 }
163
164 static REG_KEY *rpc_open_key(REG_HANDLE *h, const char *name)
165 {
166         return reg_key_new_abs(name, h, rpc_get_key_handle(h, name));
167 }
168
169 static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) 
170 {
171         struct winreg_EnumKey r;
172         struct winreg_EnumKeyNameRequest keyname;
173         struct winreg_String classname;
174         struct winreg_Time tm;
175         struct rpc_data *mydata = parent->handle->backend_data;
176         int i;
177         REG_KEY **ar = talloc(parent->mem_ctx, sizeof(REG_KEY *));
178         NTSTATUS status = NT_STATUS_OK;
179         TALLOC_CTX *mem_ctx;
180
181         /* List the hives */
182         if(parent->backend_data == parent->handle->backend_data) { 
183                 for(i = 0; known_hives[i].name; i++) {
184                         ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL);
185                         (*count)++;
186                         ar = talloc_realloc(parent->mem_ctx, ar, sizeof(REG_KEY *) * ((*count)+1));
187                 }
188
189                 *subkeys = ar;
190
191                 return True;
192         }
193
194         if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
195
196         if(!parent->backend_data) return False;
197
198         (*count) = 0;
199         r.in.handle = parent->backend_data;
200         keyname.unknown = 0x0000020a;
201         init_winreg_String(&keyname.key_name, NULL);
202         init_winreg_String(&classname, NULL);
203         r.in.in_name = &keyname;
204         r.in.class = &classname;
205         tm.low = tm.high = 0x7fffffff;
206         r.in.last_changed_time = &tm;
207         r.out.result.v = 0;
208
209         for(i = 0; NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result); i++) {
210                 r.in.enum_index = i;
211                 r.in.unknown = r.out.unknown = 0x0414;
212                 r.in.key_name_len = r.out.key_name_len = 0;
213                 status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
214                 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
215                         ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL);
216                         (*count)++;
217                         ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_KEY *));
218                 }
219         }
220
221         *subkeys = ar;
222         return True;
223 }
224
225 static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) 
226 {
227         struct winreg_EnumValue r;
228         struct winreg_Uint8buf value;
229         struct winreg_String valuename;
230         struct rpc_data *mydata = parent->handle->backend_data;
231         TALLOC_CTX *mem_ctx;
232         uint32 type, requested_len, returned_len;
233         NTSTATUS status = NT_STATUS_OK;
234         REG_VAL **ar = malloc(sizeof(REG_VAL *));
235
236         (*count) = 0;
237
238         /* Root */
239         if(parent->backend_data == parent->handle->backend_data) {
240                 *values = ar;
241                 return True;
242         }
243         
244         if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
245
246         if(!parent->backend_data) return False;
247
248         r.in.handle = parent->backend_data;
249         r.in.enum_index = 0;
250
251         init_winreg_String(&valuename, NULL);
252         r.in.name = r.out.name = &valuename;
253
254         type = 0;
255         r.in.type = r.out.type = &type;
256         value.max_len = 0x7fff;
257         value.offset = 0;
258         value.len = 0;
259         value.buffer = NULL;
260
261         r.in.value = r.out.value = &value;
262
263         requested_len = value.max_len;
264         r.in.requested_len = &requested_len;
265         returned_len = 0;
266         r.in.returned_len = &returned_len;
267         r.out.result.v = 0;
268
269         while(1) {
270                 status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
271                 if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
272                         r.in.enum_index++;
273                         ar[(*count)] = reg_val_new(parent, NULL);
274                         ar[(*count)]->name = talloc_strdup(ar[*count]->mem_ctx, r.out.name->name);
275                         ar[(*count)]->data_type = *r.out.type;
276                         ar[(*count)]->data_len = value.len;
277                         ar[(*count)]->data_blk = talloc(ar[*count]->mem_ctx, value.len);
278                         memcpy(ar[(*count)]->data_blk, value.buffer, value.len);
279                         (*count)++;
280                         ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_VAL *));
281                 } else break;
282         } 
283         
284         *values = ar;
285
286         return True;
287 }
288
289 static BOOL rpc_add_key(REG_KEY *parent, const char *name)
290 {
291         /* FIXME */
292         return False;   
293 }
294
295 static BOOL rpc_del_key(REG_KEY *k)
296 {
297         /* FIXME */
298         return False;
299 }
300
301 static REG_OPS reg_backend_rpc = {
302         .name = "rpc",
303         .open_registry = rpc_open_registry,
304         .close_registry = rpc_close_registry,
305         .open_root_key = rpc_open_root,
306         .open_key = rpc_open_key,
307         .fetch_subkeys = rpc_fetch_subkeys,
308         .fetch_values = rpc_fetch_values,
309         .add_key = rpc_add_key,
310         .del_key = rpc_del_key,
311 };
312
313 NTSTATUS reg_rpc_init(void)
314 {
315         return register_backend("registry", &reg_backend_rpc);
316 }