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