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_get_subkey_by_index(TALLOC_CTX
*mem_ctx
,
289 const struct registry_key
*parent
,
292 const char **keyclass
,
293 NTTIME
*last_changed_time
)
295 struct winreg_EnumKey r
;
296 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
297 struct winreg_StringBuf namebuf
, classbuf
;
298 NTTIME change_time
= 0;
302 namebuf
.size
= MAX_NAMESIZE
;
303 classbuf
.name
= NULL
;
307 r
.in
.handle
= &mykeydata
->pol
;
309 r
.in
.name
= &namebuf
;
310 r
.in
.keyclass
= &classbuf
;
311 r
.in
.last_changed_time
= &change_time
;
312 r
.out
.name
= &namebuf
;
313 r
.out
.keyclass
= &classbuf
;
314 r
.out
.last_changed_time
= &change_time
;
316 status
= dcerpc_winreg_EnumKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
318 if (!NT_STATUS_IS_OK(status
)) {
319 DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status
)));
320 return ntstatus_to_werror(status
);
324 *name
= talloc_steal(mem_ctx
, r
.out
.name
->name
);
325 if (keyclass
!= NULL
)
326 *keyclass
= talloc_steal(mem_ctx
, r
.out
.keyclass
->name
);
327 if (last_changed_time
!= NULL
)
328 *last_changed_time
= *(r
.out
.last_changed_time
);
333 static WERROR
rpc_add_key(TALLOC_CTX
*mem_ctx
,
334 struct registry_key
*parent
, const char *path
,
335 const char *key_class
,
336 struct security_descriptor
*sec
,
337 struct registry_key
**key
)
339 struct winreg_CreateKey r
;
340 struct rpc_key
*parentkd
= talloc_get_type(parent
, struct rpc_key
);
341 struct rpc_key
*rpck
= talloc(mem_ctx
, struct rpc_key
);
346 r
.in
.handle
= &parentkd
->pol
;
347 r
.in
.name
.name
= path
;
348 r
.in
.keyclass
.name
= NULL
;
350 r
.in
.access_mask
= 0x02000000;
352 r
.in
.action_taken
= NULL
;
353 r
.out
.new_handle
= &rpck
->pol
;
354 r
.out
.action_taken
= NULL
;
356 status
= dcerpc_winreg_CreateKey_r(parentkd
->binding_handle
, mem_ctx
, &r
);
358 if (!NT_STATUS_IS_OK(status
)) {
360 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status
)));
361 return ntstatus_to_werror(status
);
364 rpck
->binding_handle
= parentkd
->binding_handle
;
365 *key
= (struct registry_key
*)rpck
;
370 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
)
372 struct winreg_QueryInfoKey r
;
373 struct rpc_key
*mykeydata
= talloc_get_type(k
, struct rpc_key
);
374 struct winreg_String classname
;
377 classname
.name
= NULL
;
380 r
.in
.handle
= &mykeydata
->pol
;
381 r
.in
.classname
= &classname
;
382 r
.out
.classname
= &classname
;
383 r
.out
.num_subkeys
= &mykeydata
->num_subkeys
;
384 r
.out
.max_subkeylen
= &mykeydata
->max_subkeylen
;
385 r
.out
.max_classlen
= &mykeydata
->max_classlen
;
386 r
.out
.num_values
= &mykeydata
->num_values
;
387 r
.out
.max_valnamelen
= &mykeydata
->max_valnamelen
;
388 r
.out
.max_valbufsize
= &mykeydata
->max_valbufsize
;
389 r
.out
.secdescsize
= &mykeydata
->secdescsize
;
390 r
.out
.last_changed_time
= &mykeydata
->last_changed_time
;
392 status
= dcerpc_winreg_QueryInfoKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
394 if (!NT_STATUS_IS_OK(status
)) {
395 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status
)));
396 return ntstatus_to_werror(status
);
399 mykeydata
->classname
= talloc_steal(mem_ctx
, r
.out
.classname
->name
);
404 static WERROR
rpc_del_key(TALLOC_CTX
*mem_ctx
, struct registry_key
*parent
,
408 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
409 struct winreg_DeleteKey r
;
412 r
.in
.handle
= &mykeydata
->pol
;
413 r
.in
.key
.name
= name
;
415 status
= dcerpc_winreg_DeleteKey_r(mykeydata
->binding_handle
, mem_ctx
, &r
);
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
,
478 _PUBLIC_ WERROR
reg_open_remote(TALLOC_CTX
*mem_ctx
,
479 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(mem_ctx
, struct rpc_registry_context
);
492 W_ERROR_HAVE_NO_MEMORY(rctx
);
494 /* Default to local smbd if no connection is specified */
496 location
= talloc_strdup(rctx
, "ncalrpc:");
499 status
= dcerpc_pipe_connect(rctx
/* TALLOC_CTX */,
502 credentials
, ev
, lp_ctx
);
503 if(NT_STATUS_IS_ERR(status
)) {
504 DEBUG(1, ("Unable to open '%s': %s\n", location
,
508 return ntstatus_to_werror(status
);
512 rctx
->binding_handle
= p
->binding_handle
;
514 *ctx
= (struct registry_context
*)rctx
;
515 (*ctx
)->ops
= ®_backend_rpc
;