Merge commit 'release-4-0-0alpha1' into v4-0-test
[kai/samba.git] / source / lib / registry / rpc.c
1 /*
2    Samba Unix/Linux SMB implementation
3    RPC backend for the registry library
4    Copyright (C) 2003-2007 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 3 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, see <http://www.gnu.org/licenses/>.  */
18
19 #include "includes.h"
20 #include "registry.h"
21 #include "librpc/gen_ndr/ndr_winreg_c.h"
22
23 struct rpc_key {
24         struct registry_key key;
25         struct policy_handle pol;
26         struct dcerpc_pipe *pipe;
27
28         uint32_t num_values;
29         uint32_t num_subkeys;
30         uint32_t max_valnamelen;
31         uint32_t max_valdatalen;
32 };
33
34 struct rpc_registry_context {
35         struct registry_context context;
36         struct dcerpc_pipe *pipe;
37 };
38
39 static struct registry_operations reg_backend_rpc;
40
41 /**
42  * This is the RPC backend for the registry library.
43  */
44
45 static void init_winreg_String(struct winreg_String *name, const char *s)
46 {
47         name->name = s;
48 }
49
50
51 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
52 { \
53         struct winreg_Open ## u r; \
54         NTSTATUS status; \
55         \
56         r.in.system_name = NULL; \
57         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
58         r.out.handle = hnd;\
59         \
60         status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
61         if (NT_STATUS_IS_ERR(status)) {\
62                 DEBUG(0,("Error executing open\n"));\
63                 return ntstatus_to_werror(status);\
64         }\
65 \
66         return r.out.result;\
67 }
68
69 openhive(HKLM)
70 openhive(HKCU)
71 openhive(HKPD)
72 openhive(HKU)
73 openhive(HKCR)
74 openhive(HKDD)
75 openhive(HKCC)
76
77 static struct {
78         uint32_t hkey;
79         WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *,
80                         struct policy_handle *h);
81 } known_hives[] = {
82         { HKEY_LOCAL_MACHINE, open_HKLM },
83         { HKEY_CURRENT_USER, open_HKCU },
84         { HKEY_CLASSES_ROOT, open_HKCR },
85         { HKEY_PERFORMANCE_DATA, open_HKPD },
86         { HKEY_USERS, open_HKU },
87         { HKEY_DYN_DATA, open_HKDD },
88         { HKEY_CURRENT_CONFIG, open_HKCC },
89         { 0, NULL }
90 };
91
92 static WERROR rpc_query_key(const struct registry_key *k);
93
94 static WERROR rpc_get_predefined_key(const struct registry_context *ctx,
95                                      uint32_t hkey_type,
96                                      struct registry_key **k)
97 {
98         int n;
99         struct rpc_registry_context *rctx = talloc_get_type(ctx,
100                                                             struct rpc_registry_context);
101         struct rpc_key *mykeydata;
102
103         for(n = 0; known_hives[n].hkey; n++) {
104                 if(known_hives[n].hkey == hkey_type)
105                         break;
106         }
107
108         if (known_hives[n].open == NULL)  {
109                 DEBUG(1, ("No such hive %d\n", hkey_type));
110                 return WERR_NO_MORE_ITEMS;
111         }
112
113         mykeydata = talloc(ctx, struct rpc_key);
114         mykeydata->pipe = rctx->pipe;
115         mykeydata->num_values = -1;
116         mykeydata->num_subkeys = -1;
117         return known_hives[n].open(mykeydata->pipe, *k, &(mykeydata->pol));
118 }
119
120 #if 0
121 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
122 {
123         struct winreg_OpenKey r;
124         struct rpc_key_data *mykeydata;
125
126         k->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
127         mykeydata->num_values = -1;
128         mykeydata->num_subkeys = -1;
129
130         /* Then, open the handle using the hive */
131
132         memset(&r, 0, sizeof(struct winreg_OpenKey));
133         r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
134         init_winreg_String(&r.in.keyname, k->path);
135         r.in.unknown = 0x00000000;
136         r.in.access_mask = 0x02000000;
137         r.out.handle = &mykeydata->pol;
138
139         dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data,
140                               mem_ctx, &r);
141
142         return r.out.result;
143 }
144 #endif
145
146 static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h,
147                            const char *name, struct registry_key **key)
148 {
149         struct rpc_key *mykeydata = talloc_get_type(h, struct rpc_key),
150                                                     *newkeydata;
151         struct winreg_OpenKey r;
152
153         mykeydata = talloc(mem_ctx, struct rpc_key);
154
155         /* Then, open the handle using the hive */
156         memset(&r, 0, sizeof(struct winreg_OpenKey));
157         r.in.parent_handle = &mykeydata->pol;
158         init_winreg_String(&r.in.keyname, name);
159         r.in.unknown = 0x00000000;
160         r.in.access_mask = 0x02000000;
161         r.out.handle = &newkeydata->pol;
162
163         dcerpc_winreg_OpenKey(mykeydata->pipe, mem_ctx, &r);
164
165         return r.out.result;
166 }
167
168 static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx,
169                                      const struct registry_key *parent,
170                                      uint32_t n,
171                                      const char **value_name,
172                                      uint32_t *type,
173                                      DATA_BLOB *data)
174 {
175         struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
176         WERROR error;
177         struct winreg_EnumValue r;
178         uint32_t len1, zero = 0;
179         NTSTATUS status;
180         struct winreg_StringBuf name;
181         uint8_t u8;
182
183         if (mykeydata->num_values == -1) {
184                 error = rpc_query_key(parent);
185                 if(!W_ERROR_IS_OK(error)) return error;
186         }
187
188         len1 = mykeydata->max_valdatalen;
189
190         name.length = 0;
191         name.size   = mykeydata->max_valnamelen * 2;
192         name.name   = "";
193
194         r.in.handle = &mykeydata->pol;
195         r.in.enum_index = n;
196         r.in.name = &name;
197         r.in.type = type;
198         r.in.value = &u8;
199         r.in.length = &zero;
200         r.in.size = &len1;
201         r.out.name = &name;
202
203         status = dcerpc_winreg_EnumValue(mykeydata->pipe, mem_ctx, &r);
204         if(NT_STATUS_IS_ERR(status)) {
205                 DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
206                 return WERR_GENERAL_FAILURE;
207         }
208
209         if(NT_STATUS_IS_OK(status) &&
210            W_ERROR_IS_OK(r.out.result) && r.out.length) {
211                 *value_name = talloc_strdup(mem_ctx, r.out.name->name);
212                 *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
213                 return WERR_OK;
214         }
215
216         return r.out.result;
217 }
218
219 static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx,
220                                       const struct registry_key *parent,
221                                       uint32_t n,
222                                       const char **name,
223                                       const char **keyclass,
224                                       NTTIME *last_changed_time)
225 {
226         struct winreg_EnumKey r;
227         struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
228         NTSTATUS status;
229         struct winreg_StringBuf namebuf, classbuf;
230         NTTIME change_time = 0;
231
232         namebuf.length = 0;
233         namebuf.size   = 1024;
234         namebuf.name   = NULL;
235         classbuf.length = 0;
236         classbuf.size   = 0;
237         classbuf.name   = NULL;
238
239         r.in.handle = &mykeydata->pol;
240         r.in.enum_index = n;
241         r.in.name = &namebuf;
242         r.in.keyclass = &classbuf;
243         r.in.last_changed_time = &change_time;
244         r.out.name = &namebuf;
245
246         status = dcerpc_winreg_EnumKey(mykeydata->pipe, mem_ctx, &r);
247         if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
248                 *name = talloc_strdup(mem_ctx, r.out.name->name);
249                 *keyclass = talloc_strdup(mem_ctx, r.out.keyclass->name);
250                 *last_changed_time = *r.out.last_changed_time;
251         }
252
253         return r.out.result;
254 }
255
256 static WERROR rpc_add_key(TALLOC_CTX *mem_ctx,
257                           struct registry_key *parent, const char *name,
258                           const char *key_class,
259                           struct security_descriptor *sec,
260                           struct registry_key **key)
261 {
262         NTSTATUS status;
263         struct winreg_CreateKey r;
264         struct rpc_key *parentkd = talloc_get_type(parent, struct rpc_key);
265         struct rpc_key *rpck = talloc(mem_ctx, struct rpc_key);
266
267         init_winreg_String(&r.in.name, name);
268         init_winreg_String(&r.in.keyclass, NULL);
269
270         r.in.handle = &parentkd->pol;
271         r.out.new_handle = &rpck->pol;
272         r.in.options = 0;
273         r.in.access_mask = SEC_STD_ALL;
274         r.in.secdesc = NULL;
275
276         status = dcerpc_winreg_CreateKey(parentkd->pipe, mem_ctx, &r);
277
278         if (!NT_STATUS_IS_OK(status)) {
279                 talloc_free(rpck);
280                 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
281                 return ntstatus_to_werror(status);
282         }
283
284         if (W_ERROR_IS_OK(r.out.result)) {
285                 rpck->pipe = talloc_reference(rpck, parentkd->pipe);
286                 *key = (struct registry_key *)rpck;
287         }
288
289         return r.out.result;
290 }
291
292 static WERROR rpc_query_key(const struct registry_key *k)
293 {
294         NTSTATUS status;
295         struct winreg_QueryInfoKey r;
296         struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key);
297         TALLOC_CTX *mem_ctx = talloc_init("query_key");
298
299         r.in.classname = talloc(mem_ctx, struct winreg_String);
300         init_winreg_String(r.in.classname, NULL);
301         r.in.handle = &mykeydata->pol;
302
303         status = dcerpc_winreg_QueryInfoKey(mykeydata->pipe, mem_ctx, &r);
304         talloc_free(mem_ctx);
305
306         if (!NT_STATUS_IS_OK(status)) {
307                 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
308                 return ntstatus_to_werror(status);
309         }
310
311         if (W_ERROR_IS_OK(r.out.result)) {
312                 mykeydata->num_subkeys = *r.out.num_subkeys;
313                 mykeydata->num_values = *r.out.num_values;
314                 mykeydata->max_valnamelen = *r.out.max_valnamelen;
315                 mykeydata->max_valdatalen = *r.out.max_valbufsize;
316         }
317
318         return r.out.result;
319 }
320
321 static WERROR rpc_del_key(struct registry_key *parent, const char *name)
322 {
323         NTSTATUS status;
324         struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
325         struct winreg_DeleteKey r;
326         TALLOC_CTX *mem_ctx = talloc_init("del_key");
327
328         r.in.handle = &mykeydata->pol;
329         init_winreg_String(&r.in.key, name);
330
331         status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r);
332
333         talloc_free(mem_ctx);
334
335         return r.out.result;
336 }
337
338 static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key,
339                                                    const char **classname,
340                                                    uint32_t *numsubkeys,
341                                                    uint32_t *numvalue,
342                                                    NTTIME *last_changed_time)
343 {
344         struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
345         WERROR error;
346
347         if (mykeydata->num_values == -1) {
348                 error = rpc_query_key(key);
349                 if(!W_ERROR_IS_OK(error)) return error;
350         }
351
352         /* FIXME: *classname = talloc_strdup(mem_ctx, mykeydata->classname); */
353         /* FIXME: *last_changed_time = mykeydata->last_changed_time */
354
355         if (numvalue != NULL)
356                 *numvalue = mykeydata->num_values;
357
358         if (numsubkeys != NULL)
359                 *numsubkeys = mykeydata->num_subkeys;
360
361         return WERR_OK;
362 }
363
364 static struct registry_operations reg_backend_rpc = {
365         .name = "rpc",
366         .open_key = rpc_open_key,
367         .enum_key = rpc_get_subkey_by_index,
368         .enum_value = rpc_get_value_by_index,
369         .create_key = rpc_add_key,
370         .delete_key = rpc_del_key,
371         .get_key_info = rpc_get_info,
372         .get_predefined_key = rpc_get_predefined_key,
373 };
374
375 _PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx,
376                                 struct auth_session_info *session_info,
377                                 struct cli_credentials *credentials,
378                                 const char *location, struct event_context *ev)
379 {
380         NTSTATUS status;
381         struct dcerpc_pipe *p;
382         struct rpc_registry_context *rctx;
383
384         dcerpc_init();
385
386         rctx = talloc(NULL, struct rpc_registry_context);
387
388         /* Default to local smbd if no connection is specified */
389         if (!location) {
390                 location = talloc_strdup(ctx, "ncalrpc:");
391         }
392
393         status = dcerpc_pipe_connect(*ctx /* TALLOC_CTX */,
394                                      &p, location,
395                                          &ndr_table_winreg,
396                                      credentials, ev);
397         rctx->pipe = p;
398
399         if(NT_STATUS_IS_ERR(status)) {
400                 DEBUG(1, ("Unable to open '%s': %s\n", location,
401                         nt_errstr(status)));
402                 talloc_free(*ctx);
403                 *ctx = NULL;
404                 return ntstatus_to_werror(status);
405         }
406
407         *ctx = (struct registry_context *)rctx;
408         (*ctx)->ops = &reg_backend_rpc;
409
410         return WERR_OK;
411 }