2 Unix SMB/CIFS implementation.
4 endpoint server for the winreg pipe
6 Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
7 Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
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.
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.
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/>.
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 #include "param/param.h"
30 #include "libcli/security/security.h"
32 enum handle_types
{ HTYPE_REGVAL
, HTYPE_REGKEY
};
34 static NTSTATUS
dcerpc_winreg_bind(struct dcesrv_call_state
*dce_call
,
35 const struct dcesrv_interface
*iface
)
37 struct registry_context
*ctx
;
40 err
= reg_open_samba(dce_call
->context
,
41 &ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
, dce_call
->conn
->auth_state
.session_info
,
44 if (!W_ERROR_IS_OK(err
)) {
45 DEBUG(0, ("Error opening registry: %s\n", win_errstr(err
)));
46 return NT_STATUS_UNSUCCESSFUL
;
49 dce_call
->context
->private = ctx
;
54 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
56 static WERROR
dcesrv_winreg_openhive(struct dcesrv_call_state
*dce_call
,
57 TALLOC_CTX
*mem_ctx
, uint32_t hkey
,
58 struct policy_handle
**outh
)
60 struct registry_context
*ctx
= dce_call
->context
->private;
61 struct dcesrv_handle
*h
;
64 h
= dcesrv_handle_new(dce_call
->context
, HTYPE_REGKEY
);
66 result
= reg_get_predefined_key(ctx
, hkey
,
67 (struct registry_key
**)&h
->data
);
68 if (!W_ERROR_IS_OK(result
)) {
71 *outh
= &h
->wire_handle
;
76 #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) \
78 return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
81 func_winreg_OpenHive(HKCR
,HKEY_CLASSES_ROOT
)
82 func_winreg_OpenHive(HKCU
,HKEY_CURRENT_USER
)
83 func_winreg_OpenHive(HKLM
,HKEY_LOCAL_MACHINE
)
84 func_winreg_OpenHive(HKPD
,HKEY_PERFORMANCE_DATA
)
85 func_winreg_OpenHive(HKU
,HKEY_USERS
)
86 func_winreg_OpenHive(HKCC
,HKEY_CURRENT_CONFIG
)
87 func_winreg_OpenHive(HKDD
,HKEY_DYN_DATA
)
88 func_winreg_OpenHive(HKPT
,HKEY_PERFORMANCE_TEXT
)
89 func_winreg_OpenHive(HKPN
,HKEY_PERFORMANCE_NLSTEXT
)
94 static WERROR
dcesrv_winreg_CloseKey(struct dcesrv_call_state
*dce_call
,
96 struct winreg_CloseKey
*r
)
98 struct dcesrv_handle
*h
;
100 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
104 ZERO_STRUCTP(r
->out
.handle
);
112 static WERROR
dcesrv_winreg_CreateKey(struct dcesrv_call_state
*dce_call
,
114 struct winreg_CreateKey
*r
)
116 struct dcesrv_handle
*h
, *newh
;
117 struct security_descriptor sd
;
118 struct registry_key
*key
;
121 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
124 newh
= dcesrv_handle_new(dce_call
->context
, HTYPE_REGKEY
);
126 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
128 case SECURITY_SYSTEM
:
129 case SECURITY_ADMINISTRATOR
:
130 /* the security descriptor is optional */
131 if (r
->in
.secdesc
!= NULL
) {
133 enum ndr_err_code ndr_err
;
134 sdblob
.data
= r
->in
.secdesc
->sd
.data
;
135 sdblob
.length
= r
->in
.secdesc
->sd
.len
;
136 if (sdblob
.data
== NULL
) {
137 return WERR_INVALID_PARAM
;
139 ndr_err
= ndr_pull_struct_blob_all(&sdblob
, mem_ctx
, NULL
, &sd
,
140 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
141 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
142 return WERR_INVALID_PARAM
;
146 result
= reg_key_add_name(newh
, key
, r
->in
.name
.name
, NULL
,
147 r
->in
.secdesc
?&sd
:NULL
, (struct registry_key
**)&newh
->data
);
148 if (W_ERROR_IS_OK(result
)) {
149 r
->out
.new_handle
= &newh
->wire_handle
;
156 return WERR_ACCESS_DENIED
;
164 static WERROR
dcesrv_winreg_DeleteKey(struct dcesrv_call_state
*dce_call
,
166 struct winreg_DeleteKey
*r
)
168 struct dcesrv_handle
*h
;
169 struct registry_key
*key
;
171 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
174 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
176 case SECURITY_SYSTEM
:
177 case SECURITY_ADMINISTRATOR
:
178 return reg_key_del(key
, r
->in
.key
.name
);
180 return WERR_ACCESS_DENIED
;
188 static WERROR
dcesrv_winreg_DeleteValue(struct dcesrv_call_state
*dce_call
,
190 struct winreg_DeleteValue
*r
)
192 struct dcesrv_handle
*h
;
193 struct registry_key
*key
;
195 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
198 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
200 case SECURITY_SYSTEM
:
201 case SECURITY_ADMINISTRATOR
:
202 return reg_del_value(key
, r
->in
.value
.name
);
204 return WERR_ACCESS_DENIED
;
212 static WERROR
dcesrv_winreg_EnumKey(struct dcesrv_call_state
*dce_call
,
214 struct winreg_EnumKey
*r
)
216 struct dcesrv_handle
*h
;
217 struct registry_key
*key
;
218 const char *name
, *classname
;
222 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
225 result
= reg_key_get_subkey_by_index(mem_ctx
,
226 key
, r
->in
.enum_index
, &name
, &classname
, &last_mod
);
228 if (2*strlen_m_term(name
) > r
->in
.name
->size
) {
229 return WERR_MORE_DATA
;
233 r
->out
.name
->name
= name
;
234 r
->out
.name
->length
= 2*strlen_m_term(name
);
236 r
->out
.name
->name
= r
->in
.name
->name
;
237 r
->out
.name
->length
= r
->in
.name
->length
;
239 r
->out
.name
->size
= r
->in
.name
->size
;
241 r
->out
.keyclass
= r
->in
.keyclass
;
242 if (classname
!= NULL
) {
243 r
->out
.keyclass
->name
= classname
;
244 r
->out
.keyclass
->length
= 2*strlen_m_term(classname
);
246 r
->out
.keyclass
->name
= r
->in
.keyclass
->name
;
247 r
->out
.keyclass
->length
= r
->in
.keyclass
->length
;
249 r
->out
.keyclass
->size
= r
->in
.keyclass
->size
;
251 if (r
->in
.last_changed_time
!= NULL
)
252 r
->out
.last_changed_time
= &last_mod
;
261 static WERROR
dcesrv_winreg_EnumValue(struct dcesrv_call_state
*dce_call
,
263 struct winreg_EnumValue
*r
)
265 struct dcesrv_handle
*h
;
266 struct registry_key
*key
;
267 const char *data_name
;
272 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
275 result
= reg_key_get_value_by_index(mem_ctx
, key
,
276 r
->in
.enum_index
, &data_name
, &data_type
, &data
);
278 if (!W_ERROR_IS_OK(result
)) {
279 /* if the lookup wasn't successful, send client query back */
280 data_name
= r
->in
.name
->name
;
281 data_type
= *r
->in
.type
;
282 data
.data
= r
->in
.value
;
283 data
.length
= *r
->in
.length
;
286 /* check if there is enough room for the name */
287 if (r
->in
.name
->size
< 2*strlen_m_term(data_name
)) {
288 return WERR_MORE_DATA
;
291 /* "data_name" is NULL when we query the default attribute */
292 if (data_name
!= NULL
) {
293 r
->out
.name
->name
= data_name
;
294 r
->out
.name
->length
= 2*strlen_m_term(data_name
);
296 r
->out
.name
->name
= r
->in
.name
->name
;
297 r
->out
.name
->length
= r
->in
.name
->length
;
299 r
->out
.name
->size
= r
->in
.name
->size
;
301 r
->out
.type
= talloc(mem_ctx
, uint32_t);
305 *r
->out
.type
= data_type
;
307 /* check the client has enough room for the value */
308 if (r
->in
.value
!= NULL
&&
309 r
->in
.size
!= NULL
&&
310 data
.length
> *r
->in
.size
) {
311 return WERR_MORE_DATA
;
314 if (r
->in
.value
!= NULL
) {
315 r
->out
.value
= data
.data
;
318 if (r
->in
.size
!= NULL
) {
319 r
->out
.size
= talloc(mem_ctx
, uint32_t);
320 *r
->out
.size
= data
.length
;
321 r
->out
.length
= r
->out
.size
;
331 static WERROR
dcesrv_winreg_FlushKey(struct dcesrv_call_state
*dce_call
,
333 struct winreg_FlushKey
*r
)
335 struct dcesrv_handle
*h
;
336 struct registry_key
*key
;
338 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
341 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
343 case SECURITY_SYSTEM
:
344 case SECURITY_ADMINISTRATOR
:
345 return reg_key_flush(key
);
347 return WERR_ACCESS_DENIED
;
353 winreg_GetKeySecurity
355 static WERROR
dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state
*dce_call
,
357 struct winreg_GetKeySecurity
*r
)
359 struct dcesrv_handle
*h
;
361 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
363 return WERR_NOT_SUPPORTED
;
370 static WERROR
dcesrv_winreg_LoadKey(struct dcesrv_call_state
*dce_call
,
372 struct winreg_LoadKey
*r
)
374 return WERR_NOT_SUPPORTED
;
379 winreg_NotifyChangeKeyValue
381 static WERROR
dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state
*dce_call
,
383 struct winreg_NotifyChangeKeyValue
*r
)
385 return WERR_NOT_SUPPORTED
;
392 static WERROR
dcesrv_winreg_OpenKey(struct dcesrv_call_state
*dce_call
,
394 struct winreg_OpenKey
*r
)
396 struct dcesrv_handle
*h
, *newh
;
397 struct registry_key
*key
;
400 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.parent_handle
, HTYPE_REGKEY
);
403 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
405 case SECURITY_SYSTEM
:
406 case SECURITY_ADMINISTRATOR
:
408 if (r
->in
.keyname
.name
&& strcmp(r
->in
.keyname
.name
, "") == 0) {
409 newh
= talloc_reference(dce_call
->context
, h
);
412 newh
= dcesrv_handle_new(dce_call
->context
, HTYPE_REGKEY
);
413 result
= reg_open_key(newh
, key
, r
->in
.keyname
.name
,
414 (struct registry_key
**)&newh
->data
);
417 if (W_ERROR_IS_OK(result
)) {
418 r
->out
.handle
= &newh
->wire_handle
;
424 return WERR_ACCESS_DENIED
;
433 static WERROR
dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state
*dce_call
,
435 struct winreg_QueryInfoKey
*r
)
437 struct dcesrv_handle
*h
;
438 struct registry_key
*key
;
439 const char *classname
= NULL
;
442 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
445 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
447 case SECURITY_SYSTEM
:
448 case SECURITY_ADMINISTRATOR
:
450 result
= reg_key_get_info(mem_ctx
, key
, &classname
,
451 r
->out
.num_subkeys
, r
->out
.num_values
,
452 r
->out
.last_changed_time
, r
->out
.max_subkeylen
,
453 r
->out
.max_valnamelen
, r
->out
.max_valbufsize
);
455 if (classname
!= NULL
) {
456 r
->out
.classname
->name
= classname
;
457 r
->out
.classname
->name_len
= 2*strlen_m_term(classname
);
459 r
->out
.classname
->name
= r
->in
.classname
->name
;
460 r
->out
.classname
->name_len
= r
->in
.classname
->name_len
;
462 r
->out
.classname
->name_size
= r
->in
.classname
->name_size
;
466 return WERR_ACCESS_DENIED
;
474 static WERROR
dcesrv_winreg_QueryValue(struct dcesrv_call_state
*dce_call
,
476 struct winreg_QueryValue
*r
)
478 struct dcesrv_handle
*h
;
479 struct registry_key
*key
;
481 DATA_BLOB value_data
;
484 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
487 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
489 case SECURITY_SYSTEM
:
490 case SECURITY_ADMINISTRATOR
:
492 result
= reg_key_get_value_by_name(mem_ctx
, key
,
493 r
->in
.value_name
->name
, &value_type
, &value_data
);
495 if (!W_ERROR_IS_OK(result
)) {
496 /* if the lookup wasn't successful, send client query back */
497 value_type
= *r
->in
.type
;
498 value_data
.data
= r
->in
.data
;
499 value_data
.length
= *r
->in
.data_length
;
502 r
->out
.type
= talloc(mem_ctx
, uint32_t);
506 *r
->out
.type
= value_type
;
507 r
->out
.data_length
= talloc(mem_ctx
, uint32_t);
508 if (!r
->out
.data_length
) {
511 *r
->out
.data_length
= value_data
.length
;
512 r
->out
.data_size
= talloc(mem_ctx
, uint32_t);
513 if (!r
->out
.data_size
) {
516 *r
->out
.data_size
= value_data
.length
;
517 r
->out
.data
= value_data
.data
;
521 return WERR_ACCESS_DENIED
;
529 static WERROR
dcesrv_winreg_ReplaceKey(struct dcesrv_call_state
*dce_call
,
531 struct winreg_ReplaceKey
*r
)
533 return WERR_NOT_SUPPORTED
;
540 static WERROR
dcesrv_winreg_RestoreKey(struct dcesrv_call_state
*dce_call
,
542 struct winreg_RestoreKey
*r
)
544 return WERR_NOT_SUPPORTED
;
551 static WERROR
dcesrv_winreg_SaveKey(struct dcesrv_call_state
*dce_call
,
553 struct winreg_SaveKey
*r
)
555 return WERR_NOT_SUPPORTED
;
560 winreg_SetKeySecurity
562 static WERROR
dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state
*dce_call
,
564 struct winreg_SetKeySecurity
*r
)
566 return WERR_NOT_SUPPORTED
;
573 static WERROR
dcesrv_winreg_SetValue(struct dcesrv_call_state
*dce_call
,
575 struct winreg_SetValue
*r
)
577 struct dcesrv_handle
*h
;
578 struct registry_key
*key
;
582 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
585 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
))
587 case SECURITY_SYSTEM
:
588 case SECURITY_ADMINISTRATOR
:
589 data
.data
= r
->in
.data
;
590 data
.length
= r
->in
.size
;
591 result
= reg_val_set(key
, r
->in
.name
.name
, r
->in
.type
, data
);
594 return WERR_ACCESS_DENIED
;
602 static WERROR
dcesrv_winreg_UnLoadKey(struct dcesrv_call_state
*dce_call
,
604 struct winreg_UnLoadKey
*r
)
606 return WERR_NOT_SUPPORTED
;
611 winreg_InitiateSystemShutdown
613 static WERROR
dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state
*dce_call
,
615 struct winreg_InitiateSystemShutdown
*r
)
617 return WERR_NOT_SUPPORTED
;
622 winreg_AbortSystemShutdown
624 static WERROR
dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state
*dce_call
,
626 struct winreg_AbortSystemShutdown
*r
)
628 return WERR_NOT_SUPPORTED
;
635 static WERROR
dcesrv_winreg_GetVersion(struct dcesrv_call_state
*dce_call
,
637 struct winreg_GetVersion
*r
)
639 struct dcesrv_handle
*h
;
641 DCESRV_PULL_HANDLE_FAULT(h
, r
->in
.handle
, HTYPE_REGKEY
);
643 r
->out
.version
= talloc(mem_ctx
, uint32_t);
644 W_ERROR_HAVE_NO_MEMORY(r
->out
.version
);
653 winreg_QueryMultipleValues
655 static WERROR
dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state
*dce_call
,
657 struct winreg_QueryMultipleValues
*r
)
659 return WERR_NOT_SUPPORTED
;
664 winreg_InitiateSystemShutdownEx
666 static WERROR
dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state
*dce_call
,
668 struct winreg_InitiateSystemShutdownEx
*r
)
670 return WERR_NOT_SUPPORTED
;
677 static WERROR
dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state
*dce_call
,
679 struct winreg_SaveKeyEx
*r
)
681 return WERR_NOT_SUPPORTED
;
686 winreg_QueryMultipleValues2
688 static WERROR
dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state
*dce_call
,
690 struct winreg_QueryMultipleValues2
*r
)
692 return WERR_NOT_SUPPORTED
;
696 /* include the generated boilerplate */
697 #include "librpc/gen_ndr/ndr_winreg_s.c"