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