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