s4:WINREG RPC server - Reintroduce the free operation on "CloseKey"
[ira/wip.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,
40                              dce_call->conn->auth_state.session_info,
41                              NULL);
42
43         if (!W_ERROR_IS_OK(err)) {
44                 DEBUG(0, ("Error opening registry: %s\n", win_errstr(err)));
45                 return NT_STATUS_UNSUCCESSFUL;
46         }
47
48         dce_call->context->private_data = ctx;
49
50         return NT_STATUS_OK;
51 }
52
53 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
54
55 static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
56                                      TALLOC_CTX *mem_ctx, uint32_t hkey,
57                                      struct policy_handle **outh)
58 {
59         struct registry_context *ctx = dce_call->context->private_data;
60         struct dcesrv_handle *h;
61         WERROR result;
62
63         h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
64
65         result = reg_get_predefined_key(ctx, hkey,
66                                        (struct registry_key **)&h->data);
67         if (!W_ERROR_IS_OK(result)) {
68                 return result;
69         }
70         *outh = &h->wire_handle;
71
72         return result;
73 }
74
75 #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) \
76 { \
77         return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
78 }
79
80 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
81 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
82 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
83 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
84 func_winreg_OpenHive(HKU,HKEY_USERS)
85 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
86 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
87 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
88 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
89
90 /*
91   winreg_CloseKey
92 */
93 static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
94                                      TALLOC_CTX *mem_ctx,
95                                      struct winreg_CloseKey *r)
96 {
97         struct dcesrv_handle *h;
98
99         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
100
101         talloc_unlink(dce_call->context, h);
102
103         ZERO_STRUCTP(r->out.handle);
104
105         return WERR_OK;
106 }
107
108 /*
109   winreg_CreateKey
110 */
111 static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
112                                       TALLOC_CTX *mem_ctx,
113                                       struct winreg_CreateKey *r)
114 {
115         struct dcesrv_handle *h, *newh;
116         struct security_descriptor sd;
117         struct registry_key *key;
118         WERROR result;
119
120         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
121         key = h->data;
122
123         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
124
125         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
126         {
127         case SECURITY_SYSTEM:
128         case SECURITY_ADMINISTRATOR:
129                 /* the security descriptor is optional */
130                 if (r->in.secdesc != NULL) {
131                         DATA_BLOB sdblob;
132                         enum ndr_err_code ndr_err;
133                         sdblob.data = r->in.secdesc->sd.data;
134                         sdblob.length = r->in.secdesc->sd.len;
135                         if (sdblob.data == NULL) {
136                                 return WERR_INVALID_PARAM;
137                         }
138                         ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
139                                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
140                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
141                                 return WERR_INVALID_PARAM;
142                         }
143                 }
144                 
145                 result = reg_key_add_name(newh, key, r->in.name.name, NULL,
146                         r->in.secdesc?&sd:NULL, (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         struct registry_key *key;
169
170         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
171         key = h->data;
172
173         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
174         {
175         case SECURITY_SYSTEM:
176         case SECURITY_ADMINISTRATOR:
177                 return reg_key_del(key, r->in.key.name);
178         default:
179                 return WERR_ACCESS_DENIED;
180         }
181 }
182
183
184 /*
185   winreg_DeleteValue
186 */
187 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
188                                         TALLOC_CTX *mem_ctx,
189                                         struct winreg_DeleteValue *r)
190 {
191         struct dcesrv_handle *h;
192         struct registry_key *key;
193
194         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
195         key = h->data;
196
197         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
198         {
199         case SECURITY_SYSTEM:
200         case SECURITY_ADMINISTRATOR:
201                 return reg_del_value(key, r->in.value.name);
202         default:
203                 return WERR_ACCESS_DENIED;
204         }
205 }
206
207
208 /*
209   winreg_EnumKey
210 */
211 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
212                                     TALLOC_CTX *mem_ctx,
213                                     struct winreg_EnumKey *r)
214 {
215         struct dcesrv_handle *h;
216         struct registry_key *key;
217         const char *name, *classname;
218         NTTIME last_mod;
219         WERROR result;
220
221         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
222         key = h->data;
223
224         result = reg_key_get_subkey_by_index(mem_ctx, 
225                 key, r->in.enum_index, &name, &classname, &last_mod);
226
227         if (2*strlen_m_term(name) > r->in.name->size) {
228                 return WERR_MORE_DATA;
229         }
230
231         if (name != NULL) {
232                 r->out.name->name = name;
233                 r->out.name->length = 2*strlen_m_term(name);
234         } else {
235                 r->out.name->name = r->in.name->name;
236                 r->out.name->length = r->in.name->length;
237         }
238         r->out.name->size = r->in.name->size;
239
240         r->out.keyclass = r->in.keyclass;
241         if (classname != NULL) {
242                 r->out.keyclass->name = classname;
243                 r->out.keyclass->length = 2*strlen_m_term(classname);
244         } else {
245                 r->out.keyclass->name = r->in.keyclass->name;
246                 r->out.keyclass->length = r->in.keyclass->length;
247         }
248         r->out.keyclass->size = r->in.keyclass->size;
249
250         if (r->in.last_changed_time != NULL)
251                 r->out.last_changed_time = &last_mod;
252
253         return result;
254 }
255
256
257 /*
258   winreg_EnumValue
259 */
260 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
261                                       TALLOC_CTX *mem_ctx,
262                                       struct winreg_EnumValue *r)
263 {
264         struct dcesrv_handle *h;
265         struct registry_key *key;
266         const char *data_name;
267         uint32_t data_type;
268         DATA_BLOB data;
269         WERROR result;
270
271         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
272         key = h->data;
273
274         result = reg_key_get_value_by_index(mem_ctx, key,
275                 r->in.enum_index, &data_name, &data_type, &data);
276
277         if (!W_ERROR_IS_OK(result)) {
278                 /* if the lookup wasn't successful, send client query back */
279                 data_name = r->in.name->name;
280                 data_type = *r->in.type;
281                 data.data = r->in.value;
282                 data.length = *r->in.length;
283         }
284
285         /* check if there is enough room for the name */
286         if (r->in.name->size < 2*strlen_m_term(data_name)) {
287                 return WERR_MORE_DATA;
288         }
289
290         /* "data_name" is NULL when we query the default attribute */
291         if (data_name != NULL) {
292                 r->out.name->name = data_name;
293                 r->out.name->length = 2*strlen_m_term(data_name);
294         } else {
295                 r->out.name->name = r->in.name->name;
296                 r->out.name->length = r->in.name->length;
297         }
298         r->out.name->size = r->in.name->size;
299
300         r->out.type = talloc(mem_ctx, uint32_t);
301         if (!r->out.type) {
302                 return WERR_NOMEM;
303         }
304         *r->out.type = data_type;
305
306         /* check the client has enough room for the value */
307         if (r->in.value != NULL &&
308             r->in.size != NULL &&
309             data.length > *r->in.size) {
310                 return WERR_MORE_DATA;
311         }
312
313         if (r->in.value != NULL) {
314                 r->out.value = data.data;
315         }
316
317         if (r->in.size != NULL) {
318                 r->out.size = talloc(mem_ctx, uint32_t);
319                 *r->out.size = data.length;
320                 r->out.length = r->out.size;
321         }
322
323         return result;
324 }
325
326
327 /*
328   winreg_FlushKey
329 */
330 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
331                                      TALLOC_CTX *mem_ctx,
332                                      struct winreg_FlushKey *r)
333 {
334         struct dcesrv_handle *h;
335         struct registry_key *key;
336
337         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
338         key = h->data;
339
340         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
341         {
342         case SECURITY_SYSTEM:
343         case SECURITY_ADMINISTRATOR:
344                 return reg_key_flush(key);
345         default:
346                 return WERR_ACCESS_DENIED;
347         }
348 }
349
350
351 /*
352   winreg_GetKeySecurity
353 */
354 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
355                                            TALLOC_CTX *mem_ctx,
356                                            struct winreg_GetKeySecurity *r)
357 {
358         struct dcesrv_handle *h;
359
360         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
361
362         return WERR_NOT_SUPPORTED;
363 }
364
365
366 /*
367   winreg_LoadKey
368 */
369 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
370                                     TALLOC_CTX *mem_ctx,
371                                     struct winreg_LoadKey *r)
372 {
373         return WERR_NOT_SUPPORTED;
374 }
375
376
377 /*
378   winreg_NotifyChangeKeyValue
379 */
380 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
381                                                  TALLOC_CTX *mem_ctx,
382                                                  struct winreg_NotifyChangeKeyValue *r)
383 {
384         return WERR_NOT_SUPPORTED;
385 }
386
387
388 /*
389   winreg_OpenKey
390 */
391 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
392                                     TALLOC_CTX *mem_ctx,
393                                     struct winreg_OpenKey *r)
394 {
395         struct dcesrv_handle *h, *newh;
396         struct registry_key *key;
397         WERROR result;
398
399         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
400         key = h->data;
401
402         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
403         {
404         case SECURITY_SYSTEM:
405         case SECURITY_ADMINISTRATOR:
406         case SECURITY_USER:
407                 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
408                         newh = talloc_reference(dce_call->context, h);
409                         result = WERR_OK;
410                 } else {
411                         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
412                         result = reg_open_key(newh, key, r->in.keyname.name,
413                                 (struct registry_key **)&newh->data);
414                 }
415                 
416                 if (W_ERROR_IS_OK(result)) {
417                         r->out.handle = &newh->wire_handle;
418                 } else {
419                         talloc_free(newh);
420                 }
421                 return result;
422         default:
423                 return WERR_ACCESS_DENIED;
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"