Merge branch 'master' of ssh://git.samba.org/data/git/samba into regsrv
[kai/samba-autobuild/.git] / source4 / rpc_server / winreg / rpc_winreg.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the winreg pipe
5
6    Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
7    Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "lib/registry/registry.h"
26 #include "librpc/gen_ndr/ndr_winreg.h"
27 #include "rpc_server/common/common.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "param/param.h"
30 #include "libcli/security/security.h"
31
32 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
33
34 static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call,
35                                    const struct dcesrv_interface *iface)
36 {
37         struct registry_context *ctx;
38         WERROR err;
39
40         err = reg_open_samba(dce_call->context,
41                              &ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info,
42                              NULL);
43
44         if (!W_ERROR_IS_OK(err)) {
45                 DEBUG(0, ("Error opening registry: %s\n", win_errstr(err)));
46                 return NT_STATUS_UNSUCCESSFUL;
47         }
48
49         dce_call->context->private = ctx;
50
51         return NT_STATUS_OK;
52 }
53
54 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
55
56 static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
57                                      TALLOC_CTX *mem_ctx, uint32_t hkey,
58                                      struct policy_handle **outh)
59 {
60         struct registry_context *ctx = dce_call->context->private;
61         struct dcesrv_handle *h;
62         WERROR result;
63
64         h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
65
66         result = reg_get_predefined_key(ctx, hkey,
67                                        (struct registry_key **)&h->data);
68         if (!W_ERROR_IS_OK(result)) {
69                 return result;
70         }
71         *outh = &h->wire_handle;
72
73         return result;
74 }
75
76 #define func_winreg_OpenHive(k,n) static WERROR dcesrv_winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
77 { \
78         return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
79 }
80
81 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
82 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
83 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
84 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
85 func_winreg_OpenHive(HKU,HKEY_USERS)
86 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
87 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
88 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
89 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
90
91 /*
92   winreg_CloseKey
93 */
94 static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
95                                      TALLOC_CTX *mem_ctx,
96                                      struct winreg_CloseKey *r)
97 {
98         struct dcesrv_handle *h;
99
100         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
101
102         talloc_free(h);
103
104         ZERO_STRUCTP(r->out.handle);
105
106         return WERR_OK;
107 }
108
109 /*
110   winreg_CreateKey
111 */
112 static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
113                                       TALLOC_CTX *mem_ctx,
114                                       struct winreg_CreateKey *r)
115 {
116         struct dcesrv_handle *h, *newh;
117         struct security_descriptor sd;
118         struct registry_key *key;
119         WERROR result;
120
121         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
122         key = h->data;
123
124         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
125
126         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
127         {
128         case SECURITY_SYSTEM:
129         case SECURITY_ADMINISTRATOR:
130                 /* the security descriptor is optional */
131                 if (r->in.secdesc != NULL) {
132                         DATA_BLOB sdblob;
133                         enum ndr_err_code ndr_err;
134                         sdblob.data = r->in.secdesc->sd.data;
135                         sdblob.length = r->in.secdesc->sd.len;
136                         if (sdblob.data == NULL) {
137                                 return WERR_INVALID_PARAM;
138                         }
139                         ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
140                                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
141                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
142                                 return WERR_INVALID_PARAM;
143                         }
144                 }
145                 
146                 result = reg_key_add_name(newh, key, r->in.name.name, NULL,
147                         r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data);
148                 if (W_ERROR_IS_OK(result)) {
149                         r->out.new_handle = &newh->wire_handle;
150                 } else {
151                         talloc_free(newh);
152                 }
153                 
154                 return result;
155         default:
156                 return WERR_ACCESS_DENIED;
157         }
158 }
159
160
161 /*
162   winreg_DeleteKey
163 */
164 static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
165                                       TALLOC_CTX *mem_ctx,
166                                       struct winreg_DeleteKey *r)
167 {
168         struct dcesrv_handle *h;
169         struct registry_key *key;
170
171         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
172         key = h->data;
173
174         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
175         {
176         case SECURITY_SYSTEM:
177         case SECURITY_ADMINISTRATOR:
178                 return reg_key_del(key, r->in.key.name);
179         default:
180                 return WERR_ACCESS_DENIED;
181         }
182 }
183
184
185 /*
186   winreg_DeleteValue
187 */
188 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
189                                         TALLOC_CTX *mem_ctx,
190                                         struct winreg_DeleteValue *r)
191 {
192         struct dcesrv_handle *h;
193         struct registry_key *key;
194
195         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
196         key = h->data;
197
198         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
199         {
200         case SECURITY_SYSTEM:
201         case SECURITY_ADMINISTRATOR:
202                 return reg_del_value(key, r->in.value.name);
203         default:
204                 return WERR_ACCESS_DENIED;
205         }
206 }
207
208
209 /*
210   winreg_EnumKey
211 */
212 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
213                                     TALLOC_CTX *mem_ctx,
214                                     struct winreg_EnumKey *r)
215 {
216         struct dcesrv_handle *h;
217         struct registry_key *key;
218         const char *name, *classname;
219         NTTIME last_mod;
220         WERROR result;
221
222         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
223         key = h->data;
224
225         result = reg_key_get_subkey_by_index(mem_ctx, 
226                 key, r->in.enum_index, &name, &classname, &last_mod);
227
228         if (2*strlen_m_term(name) > r->in.name->size) {
229                 return WERR_MORE_DATA;
230         }
231
232         if (name != NULL) {
233                 r->out.name->name = name;
234                 r->out.name->length = 2*strlen_m_term(name);
235         } else {
236                 r->out.name->name = r->in.name->name;
237                 r->out.name->length = r->in.name->length;
238         }
239         r->out.name->size = r->in.name->size;
240
241         r->out.keyclass = r->in.keyclass;
242         if (classname != NULL) {
243                 r->out.keyclass->name = classname;
244                 r->out.keyclass->length = 2*strlen_m_term(classname);
245         } else {
246                 r->out.keyclass->name = r->in.keyclass->name;
247                 r->out.keyclass->length = r->in.keyclass->length;
248         }
249         r->out.keyclass->size = r->in.keyclass->size;
250
251         if (r->in.last_changed_time != NULL)
252                 r->out.last_changed_time = &last_mod;
253
254         return result;
255 }
256
257
258 /*
259   winreg_EnumValue
260 */
261 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
262                                       TALLOC_CTX *mem_ctx,
263                                       struct winreg_EnumValue *r)
264 {
265         struct dcesrv_handle *h;
266         struct registry_key *key;
267         const char *data_name;
268         uint32_t data_type;
269         DATA_BLOB data;
270         WERROR result;
271
272         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
273         key = h->data;
274
275         result = reg_key_get_value_by_index(mem_ctx, key,
276                 r->in.enum_index, &data_name, &data_type, &data);
277
278         if (!W_ERROR_IS_OK(result)) {
279                 /* if the lookup wasn't successful, send client query back */
280                 data_name = r->in.name->name;
281                 data_type = *r->in.type;
282                 data.data = r->in.value;
283                 data.length = *r->in.length;
284         }
285
286         /* check if there is enough room for the name */
287         if (r->in.name->size < 2*strlen_m_term(data_name)) {
288                 return WERR_MORE_DATA;
289         }
290
291         /* "data_name" is NULL when we query the default attribute */
292         if (data_name != NULL) {
293                 r->out.name->name = data_name;
294                 r->out.name->length = 2*strlen_m_term(data_name);
295         } else {
296                 r->out.name->name = r->in.name->name;
297                 r->out.name->length = r->in.name->length;
298         }
299         r->out.name->size = r->in.name->size;
300
301         r->out.type = talloc(mem_ctx, uint32_t);
302         if (!r->out.type) {
303                 return WERR_NOMEM;
304         }
305         *r->out.type = data_type;
306
307         /* check the client has enough room for the value */
308         if (r->in.value != NULL &&
309             r->in.size != NULL &&
310             data.length > *r->in.size) {
311                 return WERR_MORE_DATA;
312         }
313
314         if (r->in.value != NULL) {
315                 r->out.value = data.data;
316         }
317
318         if (r->in.size != NULL) {
319                 r->out.size = talloc(mem_ctx, uint32_t);
320                 *r->out.size = data.length;
321                 r->out.length = r->out.size;
322         }
323
324         return result;
325 }
326
327
328 /*
329   winreg_FlushKey
330 */
331 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
332                                      TALLOC_CTX *mem_ctx,
333                                      struct winreg_FlushKey *r)
334 {
335         struct dcesrv_handle *h;
336         struct registry_key *key;
337
338         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
339         key = h->data;
340
341         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
342         {
343         case SECURITY_SYSTEM:
344         case SECURITY_ADMINISTRATOR:
345                 return reg_key_flush(key);
346         default:
347                 return WERR_ACCESS_DENIED;
348         }
349 }
350
351
352 /*
353   winreg_GetKeySecurity
354 */
355 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
356                                            TALLOC_CTX *mem_ctx,
357                                            struct winreg_GetKeySecurity *r)
358 {
359         struct dcesrv_handle *h;
360
361         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
362
363         return WERR_NOT_SUPPORTED;
364 }
365
366
367 /*
368   winreg_LoadKey
369 */
370 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
371                                     TALLOC_CTX *mem_ctx,
372                                     struct winreg_LoadKey *r)
373 {
374         return WERR_NOT_SUPPORTED;
375 }
376
377
378 /*
379   winreg_NotifyChangeKeyValue
380 */
381 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
382                                                  TALLOC_CTX *mem_ctx,
383                                                  struct winreg_NotifyChangeKeyValue *r)
384 {
385         return WERR_NOT_SUPPORTED;
386 }
387
388
389 /*
390   winreg_OpenKey
391 */
392 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
393                                     TALLOC_CTX *mem_ctx,
394                                     struct winreg_OpenKey *r)
395 {
396         struct dcesrv_handle *h, *newh;
397         struct registry_key *key;
398         WERROR result;
399
400         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
401         key = h->data;
402
403         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
404         {
405         case SECURITY_SYSTEM:
406         case SECURITY_ADMINISTRATOR:
407         case SECURITY_USER:
408                 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
409                         newh = talloc_reference(dce_call->context, h);
410                         result = WERR_OK;
411                 } else {
412                         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
413                         result = reg_open_key(newh, key, r->in.keyname.name,
414                                 (struct registry_key **)&newh->data);
415                 }
416                 
417                 if (W_ERROR_IS_OK(result)) {
418                         r->out.handle = &newh->wire_handle;
419                 } else {
420                         talloc_free(newh);
421                 }
422                 return result;
423         default:
424                 return WERR_ACCESS_DENIED;
425         }
426
427 }
428
429
430 /*
431   winreg_QueryInfoKey
432 */
433 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
434                                          TALLOC_CTX *mem_ctx,
435                                          struct winreg_QueryInfoKey *r)
436 {
437         struct dcesrv_handle *h;
438         struct registry_key *key;
439         const char *classname = NULL;
440         WERROR result;
441
442         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
443         key = h->data;
444
445         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
446         {
447         case SECURITY_SYSTEM:
448         case SECURITY_ADMINISTRATOR:
449         case SECURITY_USER:
450                 result = reg_key_get_info(mem_ctx, key, &classname,
451                         r->out.num_subkeys, r->out.num_values,
452                         r->out.last_changed_time, r->out.max_subkeylen,
453                         r->out.max_valnamelen, r->out.max_valbufsize);
454
455                 if (classname != NULL) {
456                         r->out.classname->name = classname;
457                         r->out.classname->name_len = 2*strlen_m_term(classname);
458                 } else {
459                         r->out.classname->name = r->in.classname->name;
460                         r->out.classname->name_len = r->in.classname->name_len;
461                 }
462                 r->out.classname->name_size = r->in.classname->name_size;
463
464                 return result;
465         default:
466                 return WERR_ACCESS_DENIED;
467         }
468 }
469
470
471 /*
472   winreg_QueryValue
473 */
474 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
475                                        TALLOC_CTX *mem_ctx,
476                                        struct winreg_QueryValue *r)
477 {
478         struct dcesrv_handle *h;
479         struct registry_key *key;
480         uint32_t value_type;
481         DATA_BLOB value_data;
482         WERROR result;
483
484         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
485         key = h->data;
486
487         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
488         {
489         case SECURITY_SYSTEM:
490         case SECURITY_ADMINISTRATOR:
491         case SECURITY_USER:
492                 result = reg_key_get_value_by_name(mem_ctx, key, 
493                          r->in.value_name->name, &value_type, &value_data);
494                 
495                 if (!W_ERROR_IS_OK(result)) {
496                         /* if the lookup wasn't successful, send client query back */
497                         value_type = *r->in.type;
498                         value_data.data = r->in.data;
499                         value_data.length = *r->in.length;
500                 }
501
502                 r->out.type = talloc(mem_ctx, uint32_t);
503                 if (!r->out.type) {
504                         return WERR_NOMEM;
505                 }
506                 *r->out.type = value_type;
507                 r->out.data_length = talloc(mem_ctx, uint32_t);
508                 if (!r->out.data_length) {
509                         return WERR_NOMEM;
510                 }
511                 *r->out.length = value_data.length;
512                 r->out.data_size = talloc(mem_ctx, uint32_t);
513                 if (!r->out.data_size) {
514                         return WERR_NOMEM;
515                 }
516                 *r->out.data_size = value_data.length;
517                 r->out.data = value_data.data;
518
519                 return result;
520         default:
521                 return WERR_ACCESS_DENIED;
522         }
523 }
524
525
526 /*
527   winreg_ReplaceKey
528 */
529 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
530                                        TALLOC_CTX *mem_ctx,
531                                        struct winreg_ReplaceKey *r)
532 {
533         return WERR_NOT_SUPPORTED;
534 }
535
536
537 /*
538   winreg_RestoreKey
539 */
540 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
541                                        TALLOC_CTX *mem_ctx,
542                                        struct winreg_RestoreKey *r)
543 {
544         return WERR_NOT_SUPPORTED;
545 }
546
547
548 /*
549   winreg_SaveKey
550 */
551 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
552                                     TALLOC_CTX *mem_ctx,
553                                     struct winreg_SaveKey *r)
554 {
555         return WERR_NOT_SUPPORTED;
556 }
557
558
559 /*
560   winreg_SetKeySecurity
561 */
562 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
563                                            TALLOC_CTX *mem_ctx,
564                                            struct winreg_SetKeySecurity *r)
565 {
566         return WERR_NOT_SUPPORTED;
567 }
568
569
570 /*
571   winreg_SetValue
572 */
573 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
574                                      TALLOC_CTX *mem_ctx,
575                                      struct winreg_SetValue *r)
576 {
577         struct dcesrv_handle *h;
578         struct registry_key *key;
579         DATA_BLOB data;
580         WERROR result;
581
582         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
583         key = h->data;
584
585         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
586         {
587         case SECURITY_SYSTEM:
588         case SECURITY_ADMINISTRATOR:
589                 data.data = r->in.data;
590                 data.length = r->in.size;
591                 result = reg_val_set(key, r->in.name.name, r->in.type, data);
592                 return result;
593         default:
594                 return WERR_ACCESS_DENIED;
595         }
596 }
597
598
599 /*
600   winreg_UnLoadKey
601 */
602 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
603                                       TALLOC_CTX *mem_ctx,
604                                       struct winreg_UnLoadKey *r)
605 {
606         return WERR_NOT_SUPPORTED;
607 }
608
609
610 /*
611   winreg_InitiateSystemShutdown
612 */
613 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
614                                                    TALLOC_CTX *mem_ctx,
615                                                    struct winreg_InitiateSystemShutdown *r)
616 {
617         return WERR_NOT_SUPPORTED;
618 }
619
620
621 /*
622   winreg_AbortSystemShutdown
623 */
624 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
625                                                 TALLOC_CTX *mem_ctx,
626                                                 struct winreg_AbortSystemShutdown *r)
627 {
628         return WERR_NOT_SUPPORTED;
629 }
630
631
632 /*
633   winreg_GetVersion
634 */
635 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
636                                        TALLOC_CTX *mem_ctx,
637                                        struct winreg_GetVersion *r)
638 {
639         struct dcesrv_handle *h;
640
641         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
642
643         r->out.version = talloc(mem_ctx, uint32_t);
644         W_ERROR_HAVE_NO_MEMORY(r->out.version);
645
646         *r->out.version = 5;
647
648         return WERR_OK;
649 }
650
651
652 /*
653   winreg_QueryMultipleValues
654 */
655 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
656                                                 TALLOC_CTX *mem_ctx,
657                                                 struct winreg_QueryMultipleValues *r)
658 {
659         return WERR_NOT_SUPPORTED;
660 }
661
662
663 /*
664   winreg_InitiateSystemShutdownEx
665 */
666 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
667                                                      TALLOC_CTX *mem_ctx,
668                                                      struct winreg_InitiateSystemShutdownEx *r)
669 {
670         return WERR_NOT_SUPPORTED;
671 }
672
673
674 /*
675   winreg_SaveKeyEx
676 */
677 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
678                                       TALLOC_CTX *mem_ctx,
679                                       struct winreg_SaveKeyEx *r)
680 {
681         return WERR_NOT_SUPPORTED;
682 }
683
684
685 /*
686   winreg_QueryMultipleValues2
687 */
688 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
689                                                  TALLOC_CTX *mem_ctx,
690                                                  struct winreg_QueryMultipleValues2 *r)
691 {
692         return WERR_NOT_SUPPORTED;
693 }
694
695
696 /* include the generated boilerplate */
697 #include "librpc/gen_ndr/ndr_winreg_s.c"