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