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