69631b3a6656d1d276ba25024c9cfc5aed658096
[kai/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 "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         /* check if there is 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.type = talloc(mem_ctx, uint32_t);
297         if (!r->out.type) {
298                 return WERR_NOMEM;
299         }
300         *r->out.type = data_type;
301
302         /* check the client has enough room for the value */
303         if (r->in.value != NULL &&
304             r->in.size != NULL &&
305             data.length > *r->in.size) {
306                 return WERR_MORE_DATA;
307         }
308
309         if (r->in.value != NULL) {
310                 r->out.value = data.data;
311         }
312
313         if (r->in.size != NULL) {
314                 r->out.size = talloc(mem_ctx, uint32_t);
315                 *r->out.size = data.length;
316                 r->out.length = r->out.size;
317         }
318
319         return result;
320 }
321
322
323 /*
324   winreg_FlushKey
325 */
326 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
327                                      TALLOC_CTX *mem_ctx,
328                                      struct winreg_FlushKey *r)
329 {
330         struct dcesrv_handle *h;
331
332         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
333
334         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
335         {
336         case SECURITY_SYSTEM:
337         case SECURITY_ADMINISTRATOR:
338                 return reg_key_flush(h->data);
339         default:
340                 return WERR_ACCESS_DENIED;
341         }
342 }
343
344
345 /*
346   winreg_GetKeySecurity
347 */
348 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
349                                            TALLOC_CTX *mem_ctx,
350                                            struct winreg_GetKeySecurity *r)
351 {
352         struct dcesrv_handle *h;
353
354         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
355
356         return WERR_NOT_SUPPORTED;
357 }
358
359
360 /*
361   winreg_LoadKey
362 */
363 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
364                                     TALLOC_CTX *mem_ctx,
365                                     struct winreg_LoadKey *r)
366 {
367         return WERR_NOT_SUPPORTED;
368 }
369
370
371 /*
372   winreg_NotifyChangeKeyValue
373 */
374 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
375                                                  TALLOC_CTX *mem_ctx,
376                                                  struct winreg_NotifyChangeKeyValue *r)
377 {
378         return WERR_NOT_SUPPORTED;
379 }
380
381
382 /*
383   winreg_OpenKey
384 */
385 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
386                                     TALLOC_CTX *mem_ctx,
387                                     struct winreg_OpenKey *r)
388 {
389         struct dcesrv_handle *h, *newh;
390         WERROR result;
391
392         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
393
394         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
395         {
396         case SECURITY_SYSTEM:
397         case SECURITY_ADMINISTRATOR:
398         case SECURITY_USER:
399                 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
400                         newh = talloc_reference(dce_call->context, h);
401                         result = WERR_OK;
402                 } else {
403                         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
404                         result = reg_open_key(newh, (struct registry_key *)h->data,
405                                               r->in.keyname.name,
406                                               (struct registry_key **)&newh->data);
407                 }
408                 
409                 if (W_ERROR_IS_OK(result)) {
410                         r->out.handle = &newh->wire_handle;
411                 } else {
412                         talloc_free(newh);
413                 }
414                 return result;
415         default:
416                 return WERR_ACCESS_DENIED;
417         }
418
419 }
420
421
422 /*
423   winreg_QueryInfoKey
424 */
425 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
426                                          TALLOC_CTX *mem_ctx,
427                                          struct winreg_QueryInfoKey *r)
428 {
429         struct dcesrv_handle *h;
430         const char *classname = NULL;
431         WERROR result;
432
433         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
434
435         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
436         {
437         case SECURITY_SYSTEM:
438         case SECURITY_ADMINISTRATOR:
439         case SECURITY_USER:
440                 result = reg_key_get_info(mem_ctx, (struct registry_key *)h->data,
441                          &classname, r->out.num_subkeys, r->out.num_values,
442                          r->out.last_changed_time, r->out.max_subkeylen,
443                          r->out.max_valnamelen, r->out.max_valbufsize);
444
445                 if (classname != NULL) {
446                         r->out.classname->name = classname;
447                         r->out.classname->name_len = 2*strlen_m_term(classname);
448                 } else {
449                         r->out.classname->name = r->in.classname->name;
450                         r->out.classname->name_len = r->in.classname->name_len;
451                 }
452                 r->out.classname->name_size = r->in.classname->name_size;
453
454                 return result;
455         default:
456                 return WERR_ACCESS_DENIED;
457         }
458 }
459
460
461 /*
462   winreg_QueryValue
463 */
464 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
465                                        TALLOC_CTX *mem_ctx,
466                                        struct winreg_QueryValue *r)
467 {
468         struct dcesrv_handle *h;
469         uint32_t value_type;
470         DATA_BLOB value_data;
471         WERROR result;
472
473         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
474
475         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
476         {
477         case SECURITY_SYSTEM:
478         case SECURITY_ADMINISTRATOR:
479         case SECURITY_USER:
480                 result = reg_key_get_value_by_name(mem_ctx,
481                         (struct registry_key *)h->data, r->in.value_name.name,
482                                                    &value_type, &value_data);
483                 
484                 if (!W_ERROR_IS_OK(result)) {
485                         /* if the lookup wasn't successful, send client query back */
486                         value_type = *r->in.type;
487                         value_data.data = r->in.data;
488                         value_data.length = *r->in.length;
489                 }
490
491                 r->out.type = talloc(mem_ctx, uint32_t);
492                 if (!r->out.type) {
493                         return WERR_NOMEM;
494                 }
495                 *r->out.type = value_type;
496                 r->out.length = talloc(mem_ctx, uint32_t);
497                 if (!r->out.length) {
498                         return WERR_NOMEM;
499                 }
500                 *r->out.length = value_data.length;
501                 r->out.size = talloc(mem_ctx, uint32_t);
502                 if (!r->out.size) {
503                         return WERR_NOMEM;
504                 }
505                 *r->out.size = value_data.length;
506
507                 r->out.data = value_data.data;
508
509                 return result;
510         default:
511                 return WERR_ACCESS_DENIED;
512         }
513 }
514
515
516 /*
517   winreg_ReplaceKey
518 */
519 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
520                                        TALLOC_CTX *mem_ctx,
521                                        struct winreg_ReplaceKey *r)
522 {
523         return WERR_NOT_SUPPORTED;
524 }
525
526
527 /*
528   winreg_RestoreKey
529 */
530 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
531                                        TALLOC_CTX *mem_ctx,
532                                        struct winreg_RestoreKey *r)
533 {
534         return WERR_NOT_SUPPORTED;
535 }
536
537
538 /*
539   winreg_SaveKey
540 */
541 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
542                                     TALLOC_CTX *mem_ctx,
543                                     struct winreg_SaveKey *r)
544 {
545         return WERR_NOT_SUPPORTED;
546 }
547
548
549 /*
550   winreg_SetKeySecurity
551 */
552 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
553                                            TALLOC_CTX *mem_ctx,
554                                            struct winreg_SetKeySecurity *r)
555 {
556         return WERR_NOT_SUPPORTED;
557 }
558
559
560 /*
561   winreg_SetValue
562 */
563 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
564                                      TALLOC_CTX *mem_ctx,
565                                      struct winreg_SetValue *r)
566 {
567         struct dcesrv_handle *h;
568         DATA_BLOB data;
569         WERROR result;
570
571         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
572
573         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
574         {
575         case SECURITY_SYSTEM:
576         case SECURITY_ADMINISTRATOR:
577                 data.data = r->in.data;
578                 data.length = r->in.size;
579                 result = reg_val_set((struct registry_key *)h->data,
580                         r->in.name.name, r->in.type, data);
581                 return result;
582         default:
583                 return WERR_ACCESS_DENIED;
584         }
585 }
586
587
588 /*
589   winreg_UnLoadKey
590 */
591 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
592                                       TALLOC_CTX *mem_ctx,
593                                       struct winreg_UnLoadKey *r)
594 {
595         return WERR_NOT_SUPPORTED;
596 }
597
598
599 /*
600   winreg_InitiateSystemShutdown
601 */
602 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
603                                                    TALLOC_CTX *mem_ctx,
604                                                    struct winreg_InitiateSystemShutdown *r)
605 {
606         return WERR_NOT_SUPPORTED;
607 }
608
609
610 /*
611   winreg_AbortSystemShutdown
612 */
613 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
614                                                 TALLOC_CTX *mem_ctx,
615                                                 struct winreg_AbortSystemShutdown *r)
616 {
617         return WERR_NOT_SUPPORTED;
618 }
619
620
621 /*
622   winreg_GetVersion
623 */
624 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
625                                        TALLOC_CTX *mem_ctx,
626                                        struct winreg_GetVersion *r)
627 {
628         struct dcesrv_handle *h;
629
630         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
631
632         r->out.version = talloc(mem_ctx, uint32_t);
633         W_ERROR_HAVE_NO_MEMORY(r->out.version);
634
635         *r->out.version = 5;
636
637         return WERR_OK;
638 }
639
640
641 /*
642   winreg_QueryMultipleValues
643 */
644 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
645                                                 TALLOC_CTX *mem_ctx,
646                                                 struct winreg_QueryMultipleValues *r)
647 {
648         return WERR_NOT_SUPPORTED;
649 }
650
651
652 /*
653   winreg_InitiateSystemShutdownEx
654 */
655 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
656                                                      TALLOC_CTX *mem_ctx,
657                                                      struct winreg_InitiateSystemShutdownEx *r)
658 {
659         return WERR_NOT_SUPPORTED;
660 }
661
662
663 /*
664   winreg_SaveKeyEx
665 */
666 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
667                                       TALLOC_CTX *mem_ctx,
668                                       struct winreg_SaveKeyEx *r)
669 {
670         return WERR_NOT_SUPPORTED;
671 }
672
673
674 /*
675   winreg_QueryMultipleValues2
676 */
677 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
678                                                  TALLOC_CTX *mem_ctx,
679                                                  struct winreg_QueryMultipleValues2 *r)
680 {
681         return WERR_NOT_SUPPORTED;
682 }
683
684
685 /* include the generated boilerplate */
686 #include "librpc/gen_ndr/ndr_winreg_s.c"