5cabae53a234c918ff17eb89e567fd3fee698859
[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         WERROR result;
119
120         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
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, (struct registry_key *)h->data,
145                                          r->in.name.name, NULL, r->in.secdesc?&sd:NULL,
146                                          (struct registry_key **)&newh->data);
147                 if (W_ERROR_IS_OK(result)) {
148                         r->out.new_handle = &newh->wire_handle;
149                 } else {
150                         talloc_free(newh);
151                 }
152                 
153                 return result;
154         default:
155                 return WERR_ACCESS_DENIED;
156         }
157 }
158
159
160 /*
161   winreg_DeleteKey
162 */
163 static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
164                                       TALLOC_CTX *mem_ctx,
165                                       struct winreg_DeleteKey *r)
166 {
167         struct dcesrv_handle *h;
168
169         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
170
171         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
172         {
173         case SECURITY_SYSTEM:
174         case SECURITY_ADMINISTRATOR:
175                 return reg_key_del((struct registry_key *)h->data, r->in.key.name);
176         default:
177                 return WERR_ACCESS_DENIED;
178         }
179 }
180
181
182 /*
183   winreg_DeleteValue
184 */
185 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
186                                         TALLOC_CTX *mem_ctx,
187                                         struct winreg_DeleteValue *r)
188 {
189         struct dcesrv_handle *h;
190
191         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
192
193         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
194         {
195         case SECURITY_SYSTEM:
196         case SECURITY_ADMINISTRATOR:
197                 return reg_del_value((struct registry_key *)h->data, r->in.value.name);
198         default:
199                 return WERR_ACCESS_DENIED;
200         }
201 }
202
203
204 /*
205   winreg_EnumKey
206 */
207 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
208                                     TALLOC_CTX *mem_ctx,
209                                     struct winreg_EnumKey *r)
210 {
211         struct dcesrv_handle *h;
212         const char *name, *classname;
213         NTTIME last_mod;
214         WERROR result;
215
216         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
217
218         result = reg_key_get_subkey_by_index(mem_ctx, 
219                 (struct registry_key *)h->data, r->in.enum_index,
220                 &name, &classname, &last_mod);
221
222         if (2*strlen_m_term(name) > r->in.name->size) {
223                 return WERR_MORE_DATA;
224         }
225
226         if (name != NULL) {
227                 r->out.name->name = name;
228                 r->out.name->length = 2*strlen_m_term(name);
229         } else {
230                 r->out.name->name = r->in.name->name;
231                 r->out.name->length = r->in.name->length;
232         }
233         r->out.name->size = r->in.name->size;
234
235         r->out.keyclass = r->in.keyclass;
236         if (classname != NULL) {
237                 r->out.keyclass->name = classname;
238                 r->out.keyclass->length = 2*strlen_m_term(classname);
239         } else {
240                 r->out.keyclass->name = r->in.keyclass->name;
241                 r->out.keyclass->length = r->in.keyclass->length;
242         }
243         r->out.keyclass->size = r->in.keyclass->size;
244
245         if (r->in.last_changed_time != NULL)
246                 r->out.last_changed_time = &last_mod;
247
248         return result;
249 }
250
251
252 /*
253   winreg_EnumValue
254 */
255 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
256                                       TALLOC_CTX *mem_ctx,
257                                       struct winreg_EnumValue *r)
258 {
259         struct dcesrv_handle *h;
260         struct registry_key *key;
261         const char *data_name;
262         uint32_t data_type;
263         DATA_BLOB data;
264         WERROR result;
265
266         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
267
268         key = h->data;
269
270         result = reg_key_get_value_by_index(mem_ctx, (struct registry_key *)h->data,
271                 r->in.enum_index, &data_name, &data_type, &data);
272
273         if (!W_ERROR_IS_OK(result)) {
274                 /* if the lookup wasn't successful, send client query back */
275                 data_name = r->in.name->name;
276                 data_type = *r->in.type;
277                 data.data = r->in.value;
278                 data.length = *r->in.length;
279         }
280
281         /* and enough room for the name */
282         if (r->in.name->size < 2*strlen_m_term(data_name)) {
283                 return WERR_MORE_DATA;
284         }
285
286         /* "data_name" is NULL when we query the default attribute */
287         if (data_name != NULL) {
288                 r->out.name->name = data_name;
289                 r->out.name->length = 2*strlen_m_term(data_name);
290         } else {
291                 r->out.name->name = r->in.name->name;
292                 r->out.name->length = r->in.name->length;
293         }
294         r->out.name->size = r->in.name->size;
295
296         *r->out.value = data_type;
297
298         /* check the client has enough room for the value */
299         if (r->in.value != NULL &&
300             r->in.size != NULL &&
301             data.length > *r->in.size) {
302                 return WERR_MORE_DATA;
303         }
304
305         if (r->in.value != NULL) {
306                 r->out.value = data.data;
307         }
308
309         if (r->in.size != NULL) {
310                 r->out.size = talloc(mem_ctx, uint32_t);
311                 *r->out.size = data.length;
312                 r->out.length = r->out.size;
313         }
314
315         return result;
316 }
317
318
319 /*
320   winreg_FlushKey
321 */
322 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
323                                      TALLOC_CTX *mem_ctx,
324                                      struct winreg_FlushKey *r)
325 {
326         struct dcesrv_handle *h;
327
328         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
329
330         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
331         {
332         case SECURITY_SYSTEM:
333         case SECURITY_ADMINISTRATOR:
334                 return reg_key_flush(h->data);
335         default:
336                 return WERR_ACCESS_DENIED;
337         }
338 }
339
340
341 /*
342   winreg_GetKeySecurity
343 */
344 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
345                                            TALLOC_CTX *mem_ctx,
346                                            struct winreg_GetKeySecurity *r)
347 {
348         struct dcesrv_handle *h;
349
350         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
351
352         return WERR_NOT_SUPPORTED;
353 }
354
355
356 /*
357   winreg_LoadKey
358 */
359 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
360                                     TALLOC_CTX *mem_ctx,
361                                     struct winreg_LoadKey *r)
362 {
363         return WERR_NOT_SUPPORTED;
364 }
365
366
367 /*
368   winreg_NotifyChangeKeyValue
369 */
370 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
371                                                  TALLOC_CTX *mem_ctx,
372                                                  struct winreg_NotifyChangeKeyValue *r)
373 {
374         return WERR_NOT_SUPPORTED;
375 }
376
377
378 /*
379   winreg_OpenKey
380 */
381 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
382                                     TALLOC_CTX *mem_ctx,
383                                     struct winreg_OpenKey *r)
384 {
385         struct dcesrv_handle *h, *newh;
386         WERROR result;
387
388         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
389
390         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
391         {
392         case SECURITY_SYSTEM:
393         case SECURITY_ADMINISTRATOR:
394         case SECURITY_USER:
395                 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
396                         newh = talloc_reference(dce_call->context, h);
397                         result = WERR_OK;
398                 } else {
399                         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
400                         result = reg_open_key(newh, (struct registry_key *)h->data,
401                                               r->in.keyname.name,
402                                               (struct registry_key **)&newh->data);
403                 }
404                 
405                 if (W_ERROR_IS_OK(result)) {
406                         r->out.handle = &newh->wire_handle;
407                 } else {
408                         talloc_free(newh);
409                 }
410                 return result;
411         default:
412                 return WERR_ACCESS_DENIED;
413         }
414
415 }
416
417
418 /*
419   winreg_QueryInfoKey
420 */
421 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
422                                          TALLOC_CTX *mem_ctx,
423                                          struct winreg_QueryInfoKey *r)
424 {
425         struct dcesrv_handle *h;
426         const char *classname = NULL;
427         WERROR result;
428
429         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
430
431         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
432         {
433         case SECURITY_SYSTEM:
434         case SECURITY_ADMINISTRATOR:
435         case SECURITY_USER:
436                 result = reg_key_get_info(mem_ctx, (struct registry_key *)h->data,
437                          &classname, r->out.num_subkeys, r->out.num_values,
438                          r->out.last_changed_time, r->out.max_subkeylen,
439                          r->out.max_valnamelen, r->out.max_valbufsize);
440
441                 if (classname != NULL) {
442                         r->out.classname->name = classname;
443                         r->out.classname->name_len = 2*strlen_m_term(classname);
444                 } else {
445                         r->out.classname->name = r->in.classname->name;
446                         r->out.classname->name_len = r->in.classname->name_len;
447                 }
448                 r->out.classname->name_size = r->in.classname->name_size;
449
450                 return result;
451         default:
452                 return WERR_ACCESS_DENIED;
453         }
454 }
455
456
457 /*
458   winreg_QueryValue
459 */
460 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
461                                        TALLOC_CTX *mem_ctx,
462                                        struct winreg_QueryValue *r)
463 {
464         struct dcesrv_handle *h;
465         uint32_t value_type;
466         DATA_BLOB value_data;
467         WERROR result;
468
469         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
470
471         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
472         {
473         case SECURITY_SYSTEM:
474         case SECURITY_ADMINISTRATOR:
475         case SECURITY_USER:
476                 result = reg_key_get_value_by_name(mem_ctx,
477                         (struct registry_key *)h->data, r->in.value_name.name,
478                                                    &value_type, &value_data);
479                 
480                 if (!W_ERROR_IS_OK(result)) {
481                         /* if the lookup wasn't successful, send client query back */
482                         value_type = *r->in.type;
483                         value_data.data = r->in.data;
484                         value_data.length = *r->in.length;
485                 }
486
487                 /* Just asking for the size of the buffer */
488                 r->out.type = talloc(mem_ctx, uint32_t);
489                 if (!r->out.type) {
490                         return WERR_NOMEM;
491                 }
492                 *r->out.type = value_type;
493                 r->out.length = talloc(mem_ctx, uint32_t);
494                 if (!r->out.length) {
495                         return WERR_NOMEM;
496                 }
497                 *r->out.length = value_data.length;
498                 r->out.size = talloc(mem_ctx, uint32_t);
499                 if (!r->out.size) {
500                         return WERR_NOMEM;
501                 }
502                 *r->out.size = value_data.length;
503
504                 r->out.data = value_data.data;
505
506                 return result;
507         default:
508                 return WERR_ACCESS_DENIED;
509         }
510 }
511
512
513 /*
514   winreg_ReplaceKey
515 */
516 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
517                                        TALLOC_CTX *mem_ctx,
518                                        struct winreg_ReplaceKey *r)
519 {
520         return WERR_NOT_SUPPORTED;
521 }
522
523
524 /*
525   winreg_RestoreKey
526 */
527 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
528                                        TALLOC_CTX *mem_ctx,
529                                        struct winreg_RestoreKey *r)
530 {
531         return WERR_NOT_SUPPORTED;
532 }
533
534
535 /*
536   winreg_SaveKey
537 */
538 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
539                                     TALLOC_CTX *mem_ctx,
540                                     struct winreg_SaveKey *r)
541 {
542         return WERR_NOT_SUPPORTED;
543 }
544
545
546 /*
547   winreg_SetKeySecurity
548 */
549 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
550                                            TALLOC_CTX *mem_ctx,
551                                            struct winreg_SetKeySecurity *r)
552 {
553         return WERR_NOT_SUPPORTED;
554 }
555
556
557 /*
558   winreg_SetValue
559 */
560 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
561                                      TALLOC_CTX *mem_ctx,
562                                      struct winreg_SetValue *r)
563 {
564         struct dcesrv_handle *h;
565         DATA_BLOB data;
566         WERROR result;
567
568         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
569
570         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
571         {
572         case SECURITY_SYSTEM:
573         case SECURITY_ADMINISTRATOR:
574                 data.data = r->in.data;
575                 data.length = r->in.size;
576                 result = reg_val_set((struct registry_key *)h->data,
577                         r->in.name.name, r->in.type, data);
578                 return result;
579         default:
580                 return WERR_ACCESS_DENIED;
581         }
582 }
583
584
585 /*
586   winreg_UnLoadKey
587 */
588 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
589                                       TALLOC_CTX *mem_ctx,
590                                       struct winreg_UnLoadKey *r)
591 {
592         return WERR_NOT_SUPPORTED;
593 }
594
595
596 /*
597   winreg_InitiateSystemShutdown
598 */
599 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
600                                                    TALLOC_CTX *mem_ctx,
601                                                    struct winreg_InitiateSystemShutdown *r)
602 {
603         return WERR_NOT_SUPPORTED;
604 }
605
606
607 /*
608   winreg_AbortSystemShutdown
609 */
610 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
611                                                 TALLOC_CTX *mem_ctx,
612                                                 struct winreg_AbortSystemShutdown *r)
613 {
614         return WERR_NOT_SUPPORTED;
615 }
616
617
618 /*
619   winreg_GetVersion
620 */
621 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
622                                        TALLOC_CTX *mem_ctx,
623                                        struct winreg_GetVersion *r)
624 {
625         struct dcesrv_handle *h;
626
627         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
628
629         r->out.version = talloc(mem_ctx, uint32_t);
630         W_ERROR_HAVE_NO_MEMORY(r->out.version);
631
632         *r->out.version = 5;
633
634         return WERR_OK;
635 }
636
637
638 /*
639   winreg_QueryMultipleValues
640 */
641 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
642                                                 TALLOC_CTX *mem_ctx,
643                                                 struct winreg_QueryMultipleValues *r)
644 {
645         return WERR_NOT_SUPPORTED;
646 }
647
648
649 /*
650   winreg_InitiateSystemShutdownEx
651 */
652 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
653                                                      TALLOC_CTX *mem_ctx,
654                                                      struct winreg_InitiateSystemShutdownEx *r)
655 {
656         return WERR_NOT_SUPPORTED;
657 }
658
659
660 /*
661   winreg_SaveKeyEx
662 */
663 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
664                                       TALLOC_CTX *mem_ctx,
665                                       struct winreg_SaveKeyEx *r)
666 {
667         return WERR_NOT_SUPPORTED;
668 }
669
670
671 /*
672   winreg_QueryMultipleValues2
673 */
674 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
675                                                  TALLOC_CTX *mem_ctx,
676                                                  struct winreg_QueryMultipleValues2 *r)
677 {
678         return WERR_NOT_SUPPORTED;
679 }
680
681
682 /* include the generated boilerplate */
683 #include "librpc/gen_ndr/ndr_winreg_s.c"