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