2 Samba Unix/Linux SMB implementation
3 RPC backend for the registry library
4 Copyright (C) 2003-2007 Jelmer Vernooij, jelmer@samba.org
5 Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "librpc/gen_ndr/ndr_winreg_c.h"
24 #define MAX_NAMESIZE 512
25 #define MAX_VALSIZE 32768
28 struct registry_key key
;
29 struct policy_handle pol
;
30 struct dcerpc_pipe
*pipe
;
32 const char* classname
;
34 uint32_t max_subkeylen
;
35 uint32_t max_classlen
;
37 uint32_t max_valnamelen
;
38 uint32_t max_valbufsize
;
40 NTTIME last_changed_time
;
43 struct rpc_registry_context
{
44 struct registry_context context
;
45 struct dcerpc_pipe
*pipe
;
48 static struct registry_operations reg_backend_rpc
;
51 * This is the RPC backend for the registry library.
54 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
56 struct winreg_Open ## u r; \
60 r.in.system_name = NULL; \
61 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
64 status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
66 if (!NT_STATUS_IS_OK(status)) { \
67 DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \
68 return ntstatus_to_werror(status); \
84 WERROR (*open
) (struct dcerpc_pipe
*p
, TALLOC_CTX
*,
85 struct policy_handle
*h
);
87 { HKEY_LOCAL_MACHINE
, open_HKLM
},
88 { HKEY_CURRENT_USER
, open_HKCU
},
89 { HKEY_CLASSES_ROOT
, open_HKCR
},
90 { HKEY_PERFORMANCE_DATA
, open_HKPD
},
91 { HKEY_USERS
, open_HKU
},
92 { HKEY_DYN_DATA
, open_HKDD
},
93 { HKEY_CURRENT_CONFIG
, open_HKCC
},
97 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
);
99 static WERROR
rpc_get_predefined_key(struct registry_context
*ctx
,
101 struct registry_key
**k
)
104 struct rpc_key
*mykeydata
;
105 struct rpc_registry_context
*rctx
= talloc_get_type(ctx
, struct rpc_registry_context
);
109 for(n
= 0; known_hives
[n
].hkey
; n
++) {
110 if(known_hives
[n
].hkey
== hkey_type
)
114 if (known_hives
[n
].open
== NULL
) {
115 DEBUG(1, ("No such hive %d\n", hkey_type
));
116 return WERR_NO_MORE_ITEMS
;
119 mykeydata
= talloc_zero(ctx
, struct rpc_key
);
120 mykeydata
->key
.context
= ctx
;
121 mykeydata
->pipe
= talloc_reference(mykeydata
, rctx
->pipe
);
122 mykeydata
->num_values
= -1;
123 mykeydata
->num_subkeys
= -1;
124 *k
= (struct registry_key
*)mykeydata
;
125 return known_hives
[n
].open(mykeydata
->pipe
, mykeydata
, &(mykeydata
->pol
));
129 static WERROR
rpc_key_put_rpc_data(TALLOC_CTX
*mem_ctx
, struct registry_key
*k
)
131 struct winreg_OpenKey r
;
132 struct rpc_key_data
*mykeydata
;
134 k
->backend_data
= mykeydata
= talloc_zero(mem_ctx
, struct rpc_key_data
);
135 mykeydata
->num_values
= -1;
136 mykeydata
->num_subkeys
= -1;
138 /* Then, open the handle using the hive */
141 r
.in
.handle
= &(((struct rpc_key_data
*)k
->hive
->root
->backend_data
)->pol
);
142 r
.in
.keyname
.name
= k
->path
;
143 r
.in
.unknown
= 0x00000000;
144 r
.in
.access_mask
= 0x02000000;
145 r
.out
.handle
= &mykeydata
->pol
;
147 dcerpc_winreg_OpenKey((struct dcerpc_pipe
*)k
->hive
->backend_data
,
154 static WERROR
rpc_open_key(TALLOC_CTX
*mem_ctx
, struct registry_key
*h
,
155 const char *name
, struct registry_key
**key
)
157 struct rpc_key
*parentkeydata
= talloc_get_type(h
, struct rpc_key
),
159 struct winreg_OpenKey r
;
162 mykeydata
= talloc_zero(mem_ctx
, struct rpc_key
);
163 mykeydata
->key
.context
= parentkeydata
->key
.context
;
164 mykeydata
->pipe
= talloc_reference(mykeydata
, parentkeydata
->pipe
);
165 mykeydata
->num_values
= -1;
166 mykeydata
->num_subkeys
= -1;
167 *key
= (struct registry_key
*)mykeydata
;
169 /* Then, open the handle using the hive */
171 r
.in
.parent_handle
= &parentkeydata
->pol
;
172 r
.in
.keyname
.name
= name
;
173 r
.in
.unknown
= 0x00000000;
174 r
.in
.access_mask
= 0x02000000;
175 r
.out
.handle
= &mykeydata
->pol
;
177 status
= dcerpc_winreg_OpenKey(mykeydata
->pipe
, mem_ctx
, &r
);
179 if (!NT_STATUS_IS_OK(status
)) {
180 DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status
)));
181 return ntstatus_to_werror(status
);
187 static WERROR
rpc_get_value_by_index(TALLOC_CTX
*mem_ctx
,
188 const struct registry_key
*parent
,
190 const char **value_name
,
194 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
195 struct winreg_EnumValue r
;
196 struct winreg_ValNameBuf name
;
198 uint32_t val_size
= MAX_VALSIZE
;
203 if (mykeydata
->num_values
== -1) {
204 error
= rpc_query_key(mem_ctx
, parent
);
205 if(!W_ERROR_IS_OK(error
)) return error
;
209 name
.size
= MAX_NAMESIZE
;
212 r
.in
.handle
= &mykeydata
->pol
;
217 r
.in
.size
= &val_size
;
221 r
.out
.value
= &value
;
222 r
.out
.size
= &val_size
;
223 r
.out
.length
= &zero
;
225 status
= dcerpc_winreg_EnumValue(mykeydata
->pipe
, mem_ctx
, &r
);
227 if (!NT_STATUS_IS_OK(status
)) {
228 DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status
)));
229 return ntstatus_to_werror(status
);
232 *value_name
= talloc_reference(mem_ctx
, r
.out
.name
->name
);
233 *type
= *(r
.out
.type
);
234 *data
= data_blob_talloc(mem_ctx
, r
.out
.value
, *r
.out
.length
);
239 static WERROR
rpc_get_value_by_name(TALLOC_CTX
*mem_ctx
,
240 const struct registry_key
*parent
,
241 const char *value_name
,
245 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
246 struct winreg_QueryValue r
;
247 struct winreg_String name
;
249 uint32_t val_size
= MAX_VALSIZE
;
254 if (mykeydata
->num_values
== -1) {
255 error
= rpc_query_key(mem_ctx
, parent
);
256 if(!W_ERROR_IS_OK(error
)) return error
;
259 name
.name
= value_name
;
262 r
.in
.handle
= &mykeydata
->pol
;
263 r
.in
.value_name
= &name
;
266 r
.in
.data_size
= &val_size
;
267 r
.in
.data_length
= &zero
;
270 r
.out
.data_size
= &val_size
;
271 r
.out
.data_length
= &zero
;
273 status
= dcerpc_winreg_QueryValue(mykeydata
->pipe
, mem_ctx
, &r
);
275 if (!NT_STATUS_IS_OK(status
)) {
276 DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status
)));
277 return ntstatus_to_werror(status
);
280 *type
= *(r
.out
.type
);
281 *data
= data_blob_talloc(mem_ctx
, r
.out
.data
, *r
.out
.data_length
);
286 static WERROR
rpc_get_subkey_by_index(TALLOC_CTX
*mem_ctx
,
287 const struct registry_key
*parent
,
290 const char **keyclass
,
291 NTTIME
*last_changed_time
)
293 struct winreg_EnumKey r
;
294 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
295 struct winreg_StringBuf namebuf
, classbuf
;
296 NTTIME change_time
= 0;
300 namebuf
.size
= MAX_NAMESIZE
;
301 classbuf
.name
= NULL
;
305 r
.in
.handle
= &mykeydata
->pol
;
307 r
.in
.name
= &namebuf
;
308 r
.in
.keyclass
= &classbuf
;
309 r
.in
.last_changed_time
= &change_time
;
310 r
.out
.name
= &namebuf
;
311 r
.out
.keyclass
= &classbuf
;
312 r
.out
.last_changed_time
= &change_time
;
314 status
= dcerpc_winreg_EnumKey(mykeydata
->pipe
, mem_ctx
, &r
);
316 if (!NT_STATUS_IS_OK(status
)) {
317 DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status
)));
318 return ntstatus_to_werror(status
);
322 *name
= talloc_reference(mem_ctx
, r
.out
.name
->name
);
323 if (keyclass
!= NULL
)
324 *keyclass
= talloc_reference(mem_ctx
, r
.out
.keyclass
->name
);
325 if (last_changed_time
!= NULL
)
326 *last_changed_time
= *(r
.out
.last_changed_time
);
331 static WERROR
rpc_add_key(TALLOC_CTX
*mem_ctx
,
332 struct registry_key
*parent
, const char *name
,
333 const char *key_class
,
334 struct security_descriptor
*sec
,
335 struct registry_key
**key
)
337 struct winreg_CreateKey r
;
338 struct rpc_key
*parentkd
= talloc_get_type(parent
, struct rpc_key
);
339 struct rpc_key
*rpck
= talloc(mem_ctx
, struct rpc_key
);
344 r
.in
.handle
= &parentkd
->pol
;
345 r
.in
.name
.name
= name
;
346 r
.in
.keyclass
.name
= NULL
;
348 r
.in
.access_mask
= 0x02000000;
350 r
.in
.action_taken
= NULL
;
351 r
.out
.new_handle
= &rpck
->pol
;
352 r
.out
.action_taken
= NULL
;
354 status
= dcerpc_winreg_CreateKey(parentkd
->pipe
, mem_ctx
, &r
);
356 if (!NT_STATUS_IS_OK(status
)) {
358 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status
)));
359 return ntstatus_to_werror(status
);
362 rpck
->pipe
= talloc_reference(rpck
, parentkd
->pipe
);
363 *key
= (struct registry_key
*)rpck
;
368 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
)
370 struct winreg_QueryInfoKey r
;
371 struct rpc_key
*mykeydata
= talloc_get_type(k
, struct rpc_key
);
372 struct winreg_String classname
;
375 classname
.name
= NULL
;
378 r
.in
.handle
= &mykeydata
->pol
;
379 r
.in
.classname
= &classname
;
380 r
.out
.classname
= &classname
;
381 r
.out
.num_subkeys
= &mykeydata
->num_subkeys
;
382 r
.out
.max_subkeylen
= &mykeydata
->max_subkeylen
;
383 r
.out
.max_classlen
= &mykeydata
->max_classlen
;
384 r
.out
.num_values
= &mykeydata
->num_values
;
385 r
.out
.max_valnamelen
= &mykeydata
->max_valnamelen
;
386 r
.out
.max_valbufsize
= &mykeydata
->max_valbufsize
;
387 r
.out
.secdescsize
= &mykeydata
->secdescsize
;
388 r
.out
.last_changed_time
= &mykeydata
->last_changed_time
;
390 status
= dcerpc_winreg_QueryInfoKey(mykeydata
->pipe
, mem_ctx
, &r
);
392 if (!NT_STATUS_IS_OK(status
)) {
393 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status
)));
394 return ntstatus_to_werror(status
);
397 mykeydata
->classname
= talloc_reference(mem_ctx
, r
.out
.classname
->name
);
402 static WERROR
rpc_del_key(struct registry_key
*parent
, const char *name
)
405 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
406 struct winreg_DeleteKey r
;
407 TALLOC_CTX
*mem_ctx
= talloc_init("del_key");
410 r
.in
.handle
= &mykeydata
->pol
;
411 r
.in
.key
.name
= name
;
413 status
= dcerpc_winreg_DeleteKey(mykeydata
->pipe
, mem_ctx
, &r
);
415 talloc_free(mem_ctx
);
417 if (!NT_STATUS_IS_OK(status
)) {
418 DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status
)));
419 return ntstatus_to_werror(status
);
425 static WERROR
rpc_get_info(TALLOC_CTX
*mem_ctx
, const struct registry_key
*key
,
426 const char **classname
,
427 uint32_t *num_subkeys
,
428 uint32_t *num_values
,
429 NTTIME
*last_changed_time
,
430 uint32_t *max_subkeylen
,
431 uint32_t *max_valnamelen
,
432 uint32_t *max_valbufsize
)
434 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
437 if (mykeydata
->num_values
== -1) {
438 error
= rpc_query_key(mem_ctx
, key
);
439 if(!W_ERROR_IS_OK(error
)) return error
;
442 if (classname
!= NULL
)
443 *classname
= mykeydata
->classname
;
445 if (num_subkeys
!= NULL
)
446 *num_subkeys
= mykeydata
->num_subkeys
;
448 if (num_values
!= NULL
)
449 *num_values
= mykeydata
->num_values
;
451 if (last_changed_time
!= NULL
)
452 *last_changed_time
= mykeydata
->last_changed_time
;
454 if (max_subkeylen
!= NULL
)
455 *max_subkeylen
= mykeydata
->max_subkeylen
;
457 if (max_valnamelen
!= NULL
)
458 *max_valnamelen
= mykeydata
->max_valnamelen
;
460 if (max_valbufsize
!= NULL
)
461 *max_valbufsize
= mykeydata
->max_valbufsize
;
466 static struct registry_operations reg_backend_rpc
= {
468 .open_key
= rpc_open_key
,
469 .get_predefined_key
= rpc_get_predefined_key
,
470 .enum_key
= rpc_get_subkey_by_index
,
471 .enum_value
= rpc_get_value_by_index
,
472 .get_value
= rpc_get_value_by_name
,
473 .create_key
= rpc_add_key
,
474 .delete_key
= rpc_del_key
,
475 .get_key_info
= rpc_get_info
,
476 .get_predefined_key
= rpc_get_predefined_key
,
479 _PUBLIC_ WERROR
reg_open_remote(struct registry_context
**ctx
,
480 struct auth_session_info
*session_info
,
481 struct cli_credentials
*credentials
,
482 struct loadparm_context
*lp_ctx
,
483 const char *location
, struct tevent_context
*ev
)
486 struct dcerpc_pipe
*p
;
487 struct rpc_registry_context
*rctx
;
491 rctx
= talloc(NULL
, struct rpc_registry_context
);
493 /* Default to local smbd if no connection is specified */
495 location
= talloc_strdup(rctx
, "ncalrpc:");
498 status
= dcerpc_pipe_connect(rctx
/* TALLOC_CTX */,
501 credentials
, ev
, lp_ctx
);
504 if(NT_STATUS_IS_ERR(status
)) {
505 DEBUG(1, ("Unable to open '%s': %s\n", location
,
509 return ntstatus_to_werror(status
);
512 *ctx
= (struct registry_context
*)rctx
;
513 (*ctx
)->ops
= ®_backend_rpc
;