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