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