r23792: convert Samba4 to GPLv3
[ira/wip.git] / source / rpc_server / winreg / rpc_winreg.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the winreg pipe
5
6    Copyright (C) Jelmer Vernooij 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "rpc_server/dcerpc_server.h"
24 #include "lib/registry/registry.h"
25 #include "librpc/gen_ndr/ndr_winreg.h"
26 #include "rpc_server/common/common.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28
29 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
30
31 static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
32 {
33         struct registry_context *ctx;
34         WERROR err;
35
36         err = reg_open_local(dce_call->context,
37                              &ctx, dce_call->conn->auth_state.session_info, NULL);
38
39         dce_call->context->private = ctx;
40
41         return NT_STATUS_OK;
42 }
43
44 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
45
46 static WERROR dcesrv_winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t hkey, struct policy_handle **outh)
47 {
48         struct registry_context *ctx = dce_call->context->private;
49         struct dcesrv_handle *h; 
50         WERROR error;
51
52         h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); 
53
54         error = reg_get_predefined_key(ctx, hkey, (struct registry_key **)&h->data);
55         if (!W_ERROR_IS_OK(error)) {
56                 return error;
57         }
58         
59         *outh = &h->wire_handle; 
60
61         return error; 
62 }
63
64 #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) \
65 { \
66         return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
67 }
68
69 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
70 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
71 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
72 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
73 func_winreg_OpenHive(HKU,HKEY_USERS)
74 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
75 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
76 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
77 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
78
79 /* 
80   winreg_CloseKey 
81 */
82 static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
83                               struct winreg_CloseKey *r)
84 {
85         struct dcesrv_handle *h; 
86
87         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
88
89         talloc_free(h);
90
91         ZERO_STRUCTP(r->out.handle);
92
93         return WERR_OK;
94 }
95
96
97 /* 
98   winreg_CreateKey 
99 */
100 static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
101                                struct winreg_CreateKey *r)
102 {
103         struct dcesrv_handle *h, *newh;
104         WERROR error;
105         struct security_descriptor sd;
106
107         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
108         
109         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
110
111         /* the security descriptor is optional */
112         if (r->in.secdesc != NULL) {
113                 DATA_BLOB sdblob;
114                 NTSTATUS status;
115                 sdblob.data = r->in.secdesc->sd.data;
116                 sdblob.length = r->in.secdesc->sd.len;
117                 if (sdblob.data == NULL) {
118                         return WERR_INVALID_PARAM;
119                 }
120                 status = ndr_pull_struct_blob_all(&sdblob, mem_ctx, &sd, 
121                                                   (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
122                 if (!NT_STATUS_IS_OK(status)) {
123                         return WERR_INVALID_PARAM;
124                 }
125         }
126
127         error = reg_key_add_name(newh, (struct registry_key *)h->data, r->in.name.name, 
128                                  r->in.access_mask, 
129                                  r->in.secdesc?&sd:NULL, 
130                                  (struct registry_key **)&newh->data);
131         if (W_ERROR_IS_OK(error)) {
132                 r->out.new_handle = &newh->wire_handle;
133         } else {
134                 talloc_free(newh);
135         }
136
137         return error;
138 }
139
140
141 /* 
142   winreg_DeleteKey 
143 */
144 static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145                        struct winreg_DeleteKey *r)
146 {
147         struct dcesrv_handle *h;
148
149         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
150         
151         return reg_key_del((struct registry_key *)h->data, r->in.key.name);
152 }
153
154
155 /* 
156   winreg_DeleteValue 
157 */
158 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
159                        struct winreg_DeleteValue *r)
160 {
161         struct dcesrv_handle *h;
162         struct registry_key *key;
163
164         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
165
166         key = h->data;
167         
168         return reg_del_value(key, r->in.value.name);
169 }
170
171
172 /* 
173   winreg_EnumKey 
174 */
175 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
176                        struct winreg_EnumKey *r)
177 {
178         struct dcesrv_handle *h;
179         struct registry_key *key;
180
181         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
182
183         r->out.result = reg_key_get_subkey_by_index(mem_ctx, (struct registry_key *)h->data, r->in.enum_index, &key);
184
185         if (W_ERROR_IS_OK(r->out.result)) {
186                 if (2*strlen_m_term(key->name) > r->in.name->size) {
187                         return WERR_MORE_DATA;
188                 }
189                 r->out.name->length = 2*strlen_m_term(key->name);
190                 r->out.name->name = key->name;
191                 r->out.keyclass = talloc_zero(mem_ctx, struct winreg_StringBuf);
192                 if (r->in.last_changed_time) {
193                         r->out.last_changed_time = &key->last_mod;
194                 }
195         }
196         
197         return r->out.result;
198 }
199
200
201 /* 
202   winreg_EnumValue 
203 */
204 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
205                                struct winreg_EnumValue *r)
206 {
207         struct dcesrv_handle *h;
208         struct registry_key *key;
209         struct registry_value *value;
210         WERROR result;
211
212         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
213
214         key = h->data;
215
216         result = reg_key_get_value_by_index(mem_ctx, key, r->in.enum_index, &value);
217         if (!W_ERROR_IS_OK(result)) {
218                 return result;
219         }
220
221         /* the client can optionally pass a NULL for type, meaning they don't
222            want that back */
223         if (r->in.type != NULL) {
224                 r->out.type = talloc(mem_ctx, enum winreg_Type);
225                 *r->out.type = value->data_type;
226         }
227
228         /* check the client has enough room for the value */
229         if (r->in.value != NULL &&
230             r->in.size != NULL && 
231             value->data.length > *r->in.size) {
232                 return WERR_MORE_DATA;
233         }
234         
235         /* and enough room for the name */
236         if (r->in.name->size < 2*strlen_m_term(value->name)) {
237                 return WERR_MORE_DATA;          
238         }
239
240         r->out.name->name = value->name;
241         r->out.name->length = 2*strlen_m_term(value->name);
242         r->out.name->size = 2*strlen_m_term(value->name);
243
244         if (r->in.value) {
245                 r->out.value = value->data.data;
246         }
247
248         if (r->in.size) {
249                 r->out.size = talloc(mem_ctx, uint32_t);
250                 *r->out.size = value->data.length;
251                 r->out.length = r->out.size;
252         }
253         
254         return WERR_OK;
255 }
256
257
258 /* 
259   winreg_FlushKey 
260 */
261 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
262                        struct winreg_FlushKey *r)
263 {
264         struct dcesrv_handle *h;
265
266         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
267
268         return reg_key_flush(h->data);
269 }
270
271
272 /* 
273   winreg_GetKeySecurity 
274 */
275 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
276                        struct winreg_GetKeySecurity *r)
277 {
278         struct dcesrv_handle *h;
279
280         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
281
282         return WERR_NOT_SUPPORTED;
283 }
284
285
286 /* 
287   winreg_LoadKey 
288 */
289 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
290                        struct winreg_LoadKey *r)
291 {
292         return WERR_NOT_SUPPORTED;
293 }
294
295
296 /* 
297   winreg_NotifyChangeKeyValue 
298 */
299 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
300                        struct winreg_NotifyChangeKeyValue *r)
301 {
302         return WERR_NOT_SUPPORTED;
303 }
304
305
306 /* 
307   winreg_OpenKey 
308 */
309 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
310                        struct winreg_OpenKey *r)
311 {
312         struct dcesrv_handle *h, *newh;
313         WERROR result;
314
315         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
316
317         if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
318                 newh = talloc_reference(dce_call->context, h);
319                 result = WERR_OK;
320         } else {
321                 newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
322                 result = reg_open_key(newh, (struct registry_key *)h->data, 
323                                       r->in.keyname.name, (struct registry_key **)&newh->data);
324         }
325         
326         if (W_ERROR_IS_OK(result)) {
327                 r->out.handle = &newh->wire_handle; 
328         } else {
329                 talloc_free(newh);
330         }
331         
332         return result;
333 }
334
335
336 /* 
337   winreg_QueryInfoKey 
338 */
339 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
340                        struct winreg_QueryInfoKey *r)
341 {
342         struct dcesrv_handle *h;
343         struct registry_key *k;
344         WERROR ret;
345
346         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
347
348         k = h->data;
349
350         ret = reg_key_num_subkeys(k, r->out.num_subkeys);
351         if (!W_ERROR_IS_OK(ret)) { 
352                 return ret;
353         }
354
355         ret = reg_key_num_values(k, r->out.num_values);
356         if (!W_ERROR_IS_OK(ret)) { 
357                 return ret;
358         }
359
360         ret = reg_key_subkeysizes(k, r->out.max_subkeysize, r->out.max_subkeylen);
361         if (!W_ERROR_IS_OK(ret)) { 
362                 return ret;
363         }
364
365         ret = reg_key_valuesizes(k, r->out.max_valnamelen, r->out.max_valbufsize);
366         if (!W_ERROR_IS_OK(ret)) { 
367                 return ret;
368         }
369
370         r->out.secdescsize = 0; /* FIXME */
371         ZERO_STRUCT(r->out.last_changed_time); /* FIXME */
372         if (!W_ERROR_IS_OK(ret)) { 
373                 return ret;
374         }
375
376
377         return WERR_OK;
378 }
379
380
381 /* 
382   winreg_QueryValue 
383 */
384 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
385                        struct winreg_QueryValue *r)
386 {
387         struct dcesrv_handle *h;
388         struct registry_key *key;
389         struct registry_value *val;
390         WERROR result;
391
392         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
393
394         key = h->data;
395         
396         result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name, &val);
397
398         if (!W_ERROR_IS_OK(result)) { 
399                 return result;
400         }
401
402         /* Just asking for the size of the buffer */
403         r->out.type = (enum winreg_Type *)&val->data_type;
404         r->out.length = talloc(mem_ctx, uint32_t);
405         if (!r->out.length) {
406                 return WERR_NOMEM;
407         }
408         *r->out.length = val->data.length;
409         if (!r->in.data) {
410                 r->out.size = talloc(mem_ctx, uint32_t);
411                 *r->out.size = val->data.length;
412         } else {
413                 r->out.size = r->in.size;
414                 r->out.data = val->data.data;
415         }
416
417         return WERR_OK;
418 }
419
420
421 /* 
422   winreg_ReplaceKey 
423 */
424 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
425                        struct winreg_ReplaceKey *r)
426 {
427         return WERR_NOT_SUPPORTED;
428 }
429
430
431 /* 
432   winreg_RestoreKey 
433 */
434 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
435                        struct winreg_RestoreKey *r)
436 {
437         return WERR_NOT_SUPPORTED;
438 }
439
440
441 /* 
442   winreg_SaveKey 
443 */
444 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
445                        struct winreg_SaveKey *r)
446 {
447         return WERR_NOT_SUPPORTED;
448 }
449
450
451 /* 
452   winreg_SetKeySecurity 
453 */
454 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
455                        struct winreg_SetKeySecurity *r)
456 {
457         return WERR_NOT_SUPPORTED;
458 }
459
460
461 /* 
462   winreg_SetValue 
463 */
464 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
465                        struct winreg_SetValue *r)
466 {
467         struct dcesrv_handle *h;
468         struct registry_key *key;
469         WERROR result;
470         DATA_BLOB data;
471
472         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
473
474         key = h->data;
475         
476         data.data = r->in.data;
477         data.length = r->in.size;
478         result = reg_val_set(key, r->in.name.name, r->in.type, data);
479
480         if (!W_ERROR_IS_OK(result)) { 
481                 return result;
482         }
483
484         return WERR_OK;
485 }
486
487
488 /* 
489   winreg_UnLoadKey 
490 */
491 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
492                        struct winreg_UnLoadKey *r)
493 {
494         return WERR_NOT_SUPPORTED;
495 }
496
497
498 /* 
499   winreg_InitiateSystemShutdown 
500 */
501 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
502                        struct winreg_InitiateSystemShutdown *r)
503 {
504         return WERR_NOT_SUPPORTED;
505 }
506
507
508 /* 
509   winreg_AbortSystemShutdown 
510 */
511 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
512                        struct winreg_AbortSystemShutdown *r)
513 {
514         return WERR_NOT_SUPPORTED;
515 }
516
517
518 /* 
519   winreg_GetVersion 
520 */
521 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
522                                 struct winreg_GetVersion *r)
523 {
524         struct dcesrv_handle *h;
525
526         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
527
528         r->out.version = talloc(mem_ctx, uint32_t);
529         W_ERROR_HAVE_NO_MEMORY(r->out.version);
530
531         *r->out.version = 5;
532
533         return WERR_OK;
534 }
535
536
537 /* 
538   winreg_QueryMultipleValues 
539 */
540 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
541                        struct winreg_QueryMultipleValues *r)
542 {
543         return WERR_NOT_SUPPORTED;
544 }
545
546
547 /* 
548   winreg_InitiateSystemShutdownEx 
549 */
550 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
551                        struct winreg_InitiateSystemShutdownEx *r)
552 {
553         return WERR_NOT_SUPPORTED;
554 }
555
556
557 /* 
558   winreg_SaveKeyEx 
559 */
560 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
561                        struct winreg_SaveKeyEx *r)
562 {
563         return WERR_NOT_SUPPORTED;
564 }
565
566
567 /* 
568   winreg_QueryMultipleValues2 
569 */
570 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
571                        struct winreg_QueryMultipleValues2 *r)
572 {
573         return WERR_NOT_SUPPORTED;
574 }
575
576
577 /* include the generated boilerplate */
578 #include "librpc/gen_ndr/ndr_winreg_s.c"