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_binding_handle
*binding_handle
;
31 const char* classname
;
33 uint32_t max_subkeylen
;
34 uint32_t max_classlen
;
36 uint32_t max_valnamelen
;
37 uint32_t max_valbufsize
;
39 NTTIME last_changed_time
;
42 struct rpc_registry_context
{
43 struct registry_context context
;
44 struct dcerpc_pipe
*pipe
;
45 struct dcerpc_binding_handle
*binding_handle
;
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_binding_handle *b, 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 ## _r(b, 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_binding_handle
*b
, 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 W_ERROR_HAVE_NO_MEMORY(mykeydata
);
121 mykeydata
->key
.context
= ctx
;
122 mykeydata
->binding_handle
= rctx
->binding_handle
;
123 mykeydata
->num_values
= -1;
124 mykeydata
->num_subkeys
= -1;
125 *k
= (struct registry_key
*)mykeydata
;
126 return known_hives
[n
].open(mykeydata
->binding_handle
, mykeydata
, &mykeydata
->pol
);
130 static WERROR
rpc_key_put_rpc_data(TALLOC_CTX
*mem_ctx
, struct registry_key
*k
)
132 struct winreg_OpenKey r
;
133 struct rpc_key_data
*mykeydata
;
135 k
->backend_data
= mykeydata
= talloc_zero(mem_ctx
, struct rpc_key_data
);
136 mykeydata
->num_values
= -1;
137 mykeydata
->num_subkeys
= -1;
139 /* Then, open the handle using the hive */
142 r
.in
.handle
= &(((struct rpc_key_data
*)k
->hive
->root
->backend_data
)->pol
);
143 r
.in
.keyname
.name
= k
->path
;
144 r
.in
.unknown
= 0x00000000;
145 r
.in
.access_mask
= 0x02000000;
146 r
.out
.handle
= &mykeydata
->pol
;
148 dcerpc_winreg_OpenKey((struct dcerpc_pipe
*)k
->hive
->backend_data
,
155 static WERROR
rpc_open_key(TALLOC_CTX
*mem_ctx
, struct registry_key
*h
,
156 const char *name
, struct registry_key
**key
)
158 struct rpc_key
*parentkeydata
= talloc_get_type(h
, struct rpc_key
),
160 struct winreg_OpenKey r
;
163 mykeydata
= talloc_zero(mem_ctx
, struct rpc_key
);
164 W_ERROR_HAVE_NO_MEMORY(mykeydata
);
165 mykeydata
->key
.context
= parentkeydata
->key
.context
;
166 mykeydata
->binding_handle
= parentkeydata
->binding_handle
;
167 mykeydata
->num_values
= -1;
168 mykeydata
->num_subkeys
= -1;
169 *key
= (struct registry_key
*)mykeydata
;
171 /* Then, open the handle using the hive */
173 r
.in
.parent_handle
= &parentkeydata
->pol
;
174 r
.in
.keyname
.name
= name
;
175 r
.in
.options
= 0x00000000;
176 r
.in
.access_mask
= 0x02000000;
177 r
.out
.handle
= &mykeydata
->pol
;
179 status
= dcerpc_winreg_OpenKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
181 if (!NT_STATUS_IS_OK(status
)) {
182 DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status
)));
183 return ntstatus_to_werror(status
);
189 static WERROR
rpc_get_value_by_index(TALLOC_CTX
*mem_ctx
,
190 const struct registry_key
*parent
,
192 const char **value_name
,
196 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
197 struct winreg_EnumValue r
;
198 struct winreg_ValNameBuf name
;
200 uint32_t val_size
= MAX_VALSIZE
;
205 if (mykeydata
->num_values
== -1) {
206 error
= rpc_query_key(mem_ctx
, parent
);
207 if(!W_ERROR_IS_OK(error
)) return error
;
211 name
.size
= MAX_NAMESIZE
;
214 r
.in
.handle
= &mykeydata
->pol
;
217 r
.in
.type
= (enum winreg_Type
*) type
;
219 r
.in
.size
= &val_size
;
222 r
.out
.type
= (enum winreg_Type
*) type
;
223 r
.out
.value
= &value
;
224 r
.out
.size
= &val_size
;
225 r
.out
.length
= &zero
;
227 status
= dcerpc_winreg_EnumValue_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
229 if (!NT_STATUS_IS_OK(status
)) {
230 DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status
)));
231 return ntstatus_to_werror(status
);
234 *value_name
= talloc_steal(mem_ctx
, r
.out
.name
->name
);
235 *type
= *(r
.out
.type
);
236 *data
= data_blob_talloc(mem_ctx
, r
.out
.value
, *r
.out
.length
);
241 static WERROR
rpc_get_value_by_name(TALLOC_CTX
*mem_ctx
,
242 const struct registry_key
*parent
,
243 const char *value_name
,
247 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
248 struct winreg_QueryValue r
;
249 struct winreg_String name
;
251 uint32_t val_size
= MAX_VALSIZE
;
256 if (mykeydata
->num_values
== -1) {
257 error
= rpc_query_key(mem_ctx
, parent
);
258 if(!W_ERROR_IS_OK(error
)) return error
;
261 name
.name
= value_name
;
264 r
.in
.handle
= &mykeydata
->pol
;
265 r
.in
.value_name
= &name
;
266 r
.in
.type
= (enum winreg_Type
*) type
;
268 r
.in
.data_size
= &val_size
;
269 r
.in
.data_length
= &zero
;
270 r
.out
.type
= (enum winreg_Type
*) type
;
272 r
.out
.data_size
= &val_size
;
273 r
.out
.data_length
= &zero
;
275 status
= dcerpc_winreg_QueryValue_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
277 if (!NT_STATUS_IS_OK(status
)) {
278 DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status
)));
279 return ntstatus_to_werror(status
);
282 *type
= *(r
.out
.type
);
283 *data
= data_blob_talloc(mem_ctx
, r
.out
.data
, *r
.out
.data_length
);
288 static WERROR
rpc_set_value(struct registry_key
*key
, const char *value_name
,
289 uint32_t type
, const DATA_BLOB data
)
291 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
292 struct winreg_SetValue r
;
293 struct winreg_String name
;
296 name
= (struct winreg_String
) { .name
= value_name
};
299 r
.in
.handle
= &mykeydata
->pol
;
301 r
.in
.type
= (enum winreg_Type
)type
;
302 r
.in
.data
= data
.data
;
303 r
.in
.size
= data
.length
;
305 status
= dcerpc_winreg_SetValue_r(mykeydata
->binding_handle
, key
, &r
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 DEBUG(1, ("SetValue failed - %s\n", nt_errstr(status
)));
308 return ntstatus_to_werror(status
);
314 static WERROR
rpc_del_value(TALLOC_CTX
*mem_ctx
, struct registry_key
*key
,
315 const char *value_name
)
317 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
318 struct winreg_DeleteValue r
;
319 struct winreg_String name
;
322 name
= (struct winreg_String
) { .name
= value_name
};
325 r
.in
.handle
= &mykeydata
->pol
;
328 status
= dcerpc_winreg_DeleteValue_r(mykeydata
->binding_handle
,
330 if (!NT_STATUS_IS_OK(status
)) {
331 DEBUG(1, ("DeleteValue failed - %s\n", nt_errstr(status
)));
332 return ntstatus_to_werror(status
);
338 static WERROR
rpc_get_subkey_by_index(TALLOC_CTX
*mem_ctx
,
339 const struct registry_key
*parent
,
342 const char **keyclass
,
343 NTTIME
*last_changed_time
)
345 struct winreg_EnumKey r
;
346 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
347 struct winreg_StringBuf namebuf
, classbuf
;
348 NTTIME change_time
= 0;
352 namebuf
.size
= MAX_NAMESIZE
;
353 classbuf
.name
= NULL
;
357 r
.in
.handle
= &mykeydata
->pol
;
359 r
.in
.name
= &namebuf
;
360 r
.in
.keyclass
= &classbuf
;
361 r
.in
.last_changed_time
= &change_time
;
362 r
.out
.name
= &namebuf
;
363 r
.out
.keyclass
= &classbuf
;
364 r
.out
.last_changed_time
= &change_time
;
366 status
= dcerpc_winreg_EnumKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
368 if (!NT_STATUS_IS_OK(status
)) {
369 DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status
)));
370 return ntstatus_to_werror(status
);
374 *name
= talloc_steal(mem_ctx
, r
.out
.name
->name
);
375 if (keyclass
!= NULL
)
376 *keyclass
= talloc_steal(mem_ctx
, r
.out
.keyclass
->name
);
377 if (last_changed_time
!= NULL
)
378 *last_changed_time
= *(r
.out
.last_changed_time
);
383 static WERROR
rpc_add_key(TALLOC_CTX
*mem_ctx
,
384 struct registry_key
*parent
, const char *path
,
385 const char *key_class
,
386 struct security_descriptor
*sec
,
387 struct registry_key
**key
)
389 struct winreg_CreateKey r
;
390 struct rpc_key
*parentkd
= talloc_get_type(parent
, struct rpc_key
);
391 struct rpc_key
*rpck
= talloc_zero(mem_ctx
, struct rpc_key
);
396 return WERR_NOT_ENOUGH_MEMORY
;
399 rpck
->key
.context
= parentkd
->key
.context
;
400 rpck
->binding_handle
= parentkd
->binding_handle
;
401 rpck
->num_values
= -1;
402 rpck
->num_subkeys
= -1;
405 r
.in
.handle
= &parentkd
->pol
;
406 r
.in
.name
.name
= path
;
407 r
.in
.keyclass
.name
= NULL
;
409 r
.in
.access_mask
= 0x02000000;
411 r
.in
.action_taken
= NULL
;
412 r
.out
.new_handle
= &rpck
->pol
;
413 r
.out
.action_taken
= NULL
;
415 status
= dcerpc_winreg_CreateKey_r(parentkd
->binding_handle
, mem_ctx
, &r
);
417 if (!NT_STATUS_IS_OK(status
)) {
419 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status
)));
420 return ntstatus_to_werror(status
);
423 rpck
->binding_handle
= parentkd
->binding_handle
;
424 *key
= (struct registry_key
*)rpck
;
429 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
)
431 struct winreg_QueryInfoKey r
;
432 struct rpc_key
*mykeydata
= talloc_get_type(k
, struct rpc_key
);
433 struct winreg_String classname
;
436 classname
.name
= NULL
;
439 r
.in
.handle
= &mykeydata
->pol
;
440 r
.in
.classname
= &classname
;
441 r
.out
.classname
= &classname
;
442 r
.out
.num_subkeys
= &mykeydata
->num_subkeys
;
443 r
.out
.max_subkeylen
= &mykeydata
->max_subkeylen
;
444 r
.out
.max_classlen
= &mykeydata
->max_classlen
;
445 r
.out
.num_values
= &mykeydata
->num_values
;
446 r
.out
.max_valnamelen
= &mykeydata
->max_valnamelen
;
447 r
.out
.max_valbufsize
= &mykeydata
->max_valbufsize
;
448 r
.out
.secdescsize
= &mykeydata
->secdescsize
;
449 r
.out
.last_changed_time
= &mykeydata
->last_changed_time
;
451 status
= dcerpc_winreg_QueryInfoKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
453 if (!NT_STATUS_IS_OK(status
)) {
454 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status
)));
455 return ntstatus_to_werror(status
);
458 mykeydata
->classname
= talloc_steal(mem_ctx
, r
.out
.classname
->name
);
463 static WERROR
rpc_del_key(TALLOC_CTX
*mem_ctx
, struct registry_key
*parent
,
467 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
468 struct winreg_DeleteKey r
;
471 r
.in
.handle
= &mykeydata
->pol
;
472 r
.in
.key
.name
= name
;
474 status
= dcerpc_winreg_DeleteKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
476 if (!NT_STATUS_IS_OK(status
)) {
477 DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status
)));
478 return ntstatus_to_werror(status
);
484 static WERROR
rpc_get_info(TALLOC_CTX
*mem_ctx
, const struct registry_key
*key
,
485 const char **classname
,
486 uint32_t *num_subkeys
,
487 uint32_t *num_values
,
488 NTTIME
*last_changed_time
,
489 uint32_t *max_subkeylen
,
490 uint32_t *max_valnamelen
,
491 uint32_t *max_valbufsize
)
493 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
496 if (mykeydata
->num_values
== -1) {
497 error
= rpc_query_key(mem_ctx
, key
);
498 if(!W_ERROR_IS_OK(error
)) return error
;
501 if (classname
!= NULL
)
502 *classname
= mykeydata
->classname
;
504 if (num_subkeys
!= NULL
)
505 *num_subkeys
= mykeydata
->num_subkeys
;
507 if (num_values
!= NULL
)
508 *num_values
= mykeydata
->num_values
;
510 if (last_changed_time
!= NULL
)
511 *last_changed_time
= mykeydata
->last_changed_time
;
513 if (max_subkeylen
!= NULL
)
514 *max_subkeylen
= mykeydata
->max_subkeylen
;
516 if (max_valnamelen
!= NULL
)
517 *max_valnamelen
= mykeydata
->max_valnamelen
;
519 if (max_valbufsize
!= NULL
)
520 *max_valbufsize
= mykeydata
->max_valbufsize
;
525 static struct registry_operations reg_backend_rpc
= {
527 .open_key
= rpc_open_key
,
528 .get_predefined_key
= rpc_get_predefined_key
,
529 .enum_key
= rpc_get_subkey_by_index
,
530 .enum_value
= rpc_get_value_by_index
,
531 .get_value
= rpc_get_value_by_name
,
532 .set_value
= rpc_set_value
,
533 .delete_value
= rpc_del_value
,
534 .create_key
= rpc_add_key
,
535 .delete_key
= rpc_del_key
,
536 .get_key_info
= rpc_get_info
,
539 _PUBLIC_ WERROR
reg_open_remote(TALLOC_CTX
*mem_ctx
,
540 struct registry_context
**ctx
,
541 struct cli_credentials
*credentials
,
542 struct loadparm_context
*lp_ctx
,
543 const char *location
, struct tevent_context
*ev
)
546 struct dcerpc_pipe
*p
;
547 struct rpc_registry_context
*rctx
;
551 rctx
= talloc(mem_ctx
, struct rpc_registry_context
);
552 W_ERROR_HAVE_NO_MEMORY(rctx
);
554 /* Default to local smbd if no connection is specified */
556 location
= talloc_strdup(rctx
, "ncalrpc:");
559 status
= dcerpc_pipe_connect(rctx
/* TALLOC_CTX */,
562 credentials
, ev
, lp_ctx
);
563 if(NT_STATUS_IS_ERR(status
)) {
564 DEBUG(1, ("Unable to open '%s': %s\n", location
,
568 return ntstatus_to_werror(status
);
572 rctx
->binding_handle
= p
->binding_handle
;
574 *ctx
= (struct registry_context
*)rctx
;
575 (*ctx
)->ops
= ®_backend_rpc
;