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_subkeysize
;
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.
55 * Converts a SAMBA string into a WINREG string
57 static void chars_to_winreg_String(TALLOC_CTX
*mem_ctx
, struct winreg_String
58 *winregStr
, const char *str
)
60 winregStr
->name
= NULL
;
61 winregStr
->name_len
= 0;
63 winregStr
->name
= talloc_strdup(mem_ctx
, str
);
64 winregStr
->name_len
= strlen(str
);
66 winregStr
->name_size
= winregStr
->name_len
;
70 * Converts a WINREG string into a SAMBA string
72 static void winreg_String_to_chars(TALLOC_CTX
*mem_ctx
, const char **str
,
73 struct winreg_String
*winregStr
)
76 if (winregStr
->name
!= NULL
)
77 *str
= talloc_strdup(mem_ctx
, winregStr
->name
);
81 * Converts a SAMBA string into a WINREG string buffer
83 static void chars_to_winreg_StringBuf(TALLOC_CTX
*mem_ctx
, struct winreg_StringBuf
84 *winregStrBuf
, const char *str
, uint16_t size
)
86 winregStrBuf
->name
= NULL
;
87 winregStrBuf
->length
= 0;
89 winregStrBuf
->name
= talloc_strdup(mem_ctx
, str
);
90 winregStrBuf
->length
= strlen(str
);
92 winregStrBuf
->size
= size
;
96 * Converts a WINREG string buffer into a SAMBA string
98 static void winreg_StringBuf_to_chars(TALLOC_CTX
*mem_ctx
, const char **str
,
99 struct winreg_StringBuf
*winregStrBuf
)
102 if (winregStrBuf
->name
!= NULL
)
103 *str
= talloc_strdup(mem_ctx
, winregStrBuf
->name
);
106 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
108 struct winreg_Open ## u r; \
112 r.in.system_name = NULL; \
113 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
116 status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
118 if (!NT_STATUS_IS_OK(status)) { \
119 DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \
120 return ntstatus_to_werror(status); \
123 return r.out.result;\
136 WERROR (*open
) (struct dcerpc_pipe
*p
, TALLOC_CTX
*,
137 struct policy_handle
*h
);
139 { HKEY_LOCAL_MACHINE
, open_HKLM
},
140 { HKEY_CURRENT_USER
, open_HKCU
},
141 { HKEY_CLASSES_ROOT
, open_HKCR
},
142 { HKEY_PERFORMANCE_DATA
, open_HKPD
},
143 { HKEY_USERS
, open_HKU
},
144 { HKEY_DYN_DATA
, open_HKDD
},
145 { HKEY_CURRENT_CONFIG
, open_HKCC
},
149 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
);
151 static WERROR
rpc_get_predefined_key(struct registry_context
*ctx
,
153 struct registry_key
**k
)
156 struct rpc_key
*mykeydata
;
157 struct rpc_registry_context
*rctx
= talloc_get_type(ctx
, struct rpc_registry_context
);
161 for(n
= 0; known_hives
[n
].hkey
; n
++) {
162 if(known_hives
[n
].hkey
== hkey_type
)
166 if (known_hives
[n
].open
== NULL
) {
167 DEBUG(1, ("No such hive %d\n", hkey_type
));
168 return WERR_NO_MORE_ITEMS
;
171 mykeydata
= talloc_zero(ctx
, struct rpc_key
);
172 mykeydata
->key
.context
= ctx
;
173 mykeydata
->pipe
= talloc_reference(mykeydata
, rctx
->pipe
);
174 mykeydata
->num_values
= -1;
175 mykeydata
->num_subkeys
= -1;
176 *k
= (struct registry_key
*)mykeydata
;
177 return known_hives
[n
].open(mykeydata
->pipe
, mykeydata
, &(mykeydata
->pol
));
181 static WERROR
rpc_key_put_rpc_data(TALLOC_CTX
*mem_ctx
, struct registry_key
*k
)
183 struct winreg_OpenKey r
;
184 struct rpc_key_data
*mykeydata
;
186 k
->backend_data
= mykeydata
= talloc(mem_ctx
, struct rpc_key_data
);
187 mykeydata
->num_values
= -1;
188 mykeydata
->num_subkeys
= -1;
190 /* Then, open the handle using the hive */
193 r
.in
.handle
= &(((struct rpc_key_data
*)k
->hive
->root
->backend_data
)->pol
);
194 chars_to_winreg_String(mem_ctx
, &r
.in
.keyname
, k
->path
);
195 r
.in
.unknown
= 0x00000000;
196 r
.in
.access_mask
= 0x02000000;
197 r
.out
.handle
= &mykeydata
->pol
;
199 dcerpc_winreg_OpenKey((struct dcerpc_pipe
*)k
->hive
->backend_data
,
206 static WERROR
rpc_open_key(TALLOC_CTX
*mem_ctx
, struct registry_key
*h
,
207 const char *name
, struct registry_key
**key
)
209 struct rpc_key
*parentkeydata
= talloc_get_type(h
, struct rpc_key
),
211 struct winreg_OpenKey r
;
214 mykeydata
= talloc(mem_ctx
, struct rpc_key
);
216 mykeydata
->key
.context
= parentkeydata
->key
.context
;
217 mykeydata
->pipe
= talloc_reference(mykeydata
, parentkeydata
->pipe
);
218 mykeydata
->num_values
= -1;
219 mykeydata
->num_subkeys
= -1;
220 *key
= (struct registry_key
*)mykeydata
;
222 /* Then, open the handle using the hive */
224 r
.in
.parent_handle
= &parentkeydata
->pol
;
225 chars_to_winreg_String(mem_ctx
, &r
.in
.keyname
, name
);
226 r
.in
.unknown
= 0x00000000;
227 r
.in
.access_mask
= 0x02000000;
228 r
.out
.handle
= &mykeydata
->pol
;
230 status
= dcerpc_winreg_OpenKey(mykeydata
->pipe
, mem_ctx
, &r
);
232 if (!NT_STATUS_IS_OK(status
)) {
233 DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status
)));
234 return ntstatus_to_werror(status
);
240 static WERROR
rpc_get_value_by_index(TALLOC_CTX
*mem_ctx
,
241 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_EnumValue r
;
249 struct winreg_StringBuf 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 chars_to_winreg_StringBuf(mem_ctx
, &name
, "", MAX_NAMESIZE
);
264 r
.in
.handle
= &mykeydata
->pol
;
269 r
.in
.size
= &val_size
;
273 r
.out
.value
= &value
;
274 r
.out
.size
= &val_size
;
275 r
.out
.length
= &zero
;
277 status
= dcerpc_winreg_EnumValue(mykeydata
->pipe
, mem_ctx
, &r
);
279 if (!NT_STATUS_IS_OK(status
)) {
280 DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status
)));
281 return ntstatus_to_werror(status
);
284 winreg_StringBuf_to_chars(mem_ctx
, value_name
, r
.out
.name
);
285 *type
= *(r
.out
.type
);
286 *data
= data_blob_talloc(mem_ctx
, r
.out
.value
, *r
.out
.length
);
291 static WERROR
rpc_get_subkey_by_index(TALLOC_CTX
*mem_ctx
,
292 const struct registry_key
*parent
,
295 const char **keyclass
,
296 NTTIME
*last_changed_time
)
298 struct winreg_EnumKey r
;
299 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
300 struct winreg_StringBuf namebuf
, classbuf
;
301 NTTIME change_time
= 0;
304 chars_to_winreg_StringBuf(mem_ctx
, &namebuf
, " ", MAX_NAMESIZE
);
305 chars_to_winreg_StringBuf(mem_ctx
, &classbuf
, NULL
, 0);
308 r
.in
.handle
= &mykeydata
->pol
;
310 r
.in
.name
= &namebuf
;
311 r
.in
.keyclass
= &classbuf
;
312 r
.in
.last_changed_time
= &change_time
;
313 r
.out
.name
= &namebuf
;
314 r
.out
.keyclass
= &classbuf
;
315 r
.out
.last_changed_time
= &change_time
;
317 status
= dcerpc_winreg_EnumKey(mykeydata
->pipe
, mem_ctx
, &r
);
319 if (!NT_STATUS_IS_OK(status
)) {
320 DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status
)));
321 return ntstatus_to_werror(status
);
325 winreg_StringBuf_to_chars(mem_ctx
, name
, r
.out
.name
);
326 if (keyclass
!= NULL
)
327 winreg_StringBuf_to_chars(mem_ctx
, keyclass
, r
.out
.keyclass
);
328 if (last_changed_time
!= NULL
)
329 *last_changed_time
= *(r
.out
.last_changed_time
);
334 static WERROR
rpc_add_key(TALLOC_CTX
*mem_ctx
,
335 struct registry_key
*parent
, const char *name
,
336 const char *key_class
,
337 struct security_descriptor
*sec
,
338 struct registry_key
**key
)
340 struct winreg_CreateKey r
;
341 struct rpc_key
*parentkd
= talloc_get_type(parent
, struct rpc_key
);
342 struct rpc_key
*rpck
= talloc(mem_ctx
, struct rpc_key
);
347 r
.in
.handle
= &parentkd
->pol
;
348 chars_to_winreg_String(mem_ctx
, &r
.in
.name
, name
);
349 chars_to_winreg_String(mem_ctx
, &r
.in
.keyclass
, NULL
);
351 r
.in
.access_mask
= SEC_STD_ALL
;
353 r
.in
.action_taken
= NULL
;
354 r
.out
.new_handle
= &rpck
->pol
;
355 r
.out
.action_taken
= NULL
;
357 status
= dcerpc_winreg_CreateKey(parentkd
->pipe
, mem_ctx
, &r
);
359 if (!NT_STATUS_IS_OK(status
)) {
361 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status
)));
362 return ntstatus_to_werror(status
);
365 rpck
->pipe
= talloc_reference(rpck
, parentkd
->pipe
);
366 *key
= (struct registry_key
*)rpck
;
371 static WERROR
rpc_query_key(TALLOC_CTX
*mem_ctx
, const struct registry_key
*k
)
373 struct winreg_QueryInfoKey r
;
374 struct rpc_key
*mykeydata
= talloc_get_type(k
, struct rpc_key
);
375 struct winreg_String classname
;
378 chars_to_winreg_String(mem_ctx
, &classname
, NULL
);
381 r
.in
.handle
= &mykeydata
->pol
;
382 r
.in
.classname
= &classname
;
383 r
.out
.classname
= &classname
;
384 r
.out
.num_subkeys
= &mykeydata
->num_subkeys
;
385 r
.out
.max_subkeylen
= &mykeydata
->max_subkeylen
;
386 r
.out
.max_subkeysize
= &mykeydata
->max_subkeysize
;
387 r
.out
.num_values
= &mykeydata
->num_values
;
388 r
.out
.max_valnamelen
= &mykeydata
->max_valnamelen
;
389 r
.out
.max_valbufsize
= &mykeydata
->max_valbufsize
;
390 r
.out
.secdescsize
= &mykeydata
->secdescsize
;
391 r
.out
.last_changed_time
= &mykeydata
->last_changed_time
;
393 status
= dcerpc_winreg_QueryInfoKey(mykeydata
->pipe
, mem_ctx
, &r
);
395 if (!NT_STATUS_IS_OK(status
)) {
396 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status
)));
397 return ntstatus_to_werror(status
);
400 winreg_String_to_chars(mem_ctx
, &mykeydata
->classname
, r
.out
.classname
);
405 static WERROR
rpc_del_key(struct registry_key
*parent
, const char *name
)
408 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
409 struct winreg_DeleteKey r
;
410 TALLOC_CTX
*mem_ctx
= talloc_init("del_key");
413 r
.in
.handle
= &mykeydata
->pol
;
414 chars_to_winreg_String(mem_ctx
, &r
.in
.key
, name
);
416 status
= dcerpc_winreg_DeleteKey(mykeydata
->pipe
, mem_ctx
, &r
);
418 talloc_free(mem_ctx
);
420 if (!NT_STATUS_IS_OK(status
)) {
421 DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status
)));
422 return ntstatus_to_werror(status
);
428 static WERROR
rpc_get_info(TALLOC_CTX
*mem_ctx
, const struct registry_key
*key
,
429 const char **classname
,
430 uint32_t *num_subkeys
,
431 uint32_t *num_values
,
432 NTTIME
*last_changed_time
,
433 uint32_t *max_subkeylen
,
434 uint32_t *max_valnamelen
,
435 uint32_t *max_valbufsize
)
437 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
440 if (mykeydata
->num_values
== -1) {
441 error
= rpc_query_key(mem_ctx
, key
);
442 if(!W_ERROR_IS_OK(error
)) return error
;
445 if (classname
!= NULL
)
446 *classname
= mykeydata
->classname
;
448 if (num_subkeys
!= NULL
)
449 *num_subkeys
= mykeydata
->num_subkeys
;
451 if (num_values
!= NULL
)
452 *num_values
= mykeydata
->num_values
;
454 if (last_changed_time
!= NULL
)
455 *last_changed_time
= mykeydata
->last_changed_time
;
457 if (max_subkeylen
!= NULL
)
458 *max_subkeylen
= mykeydata
->max_subkeylen
;
460 if (max_valnamelen
!= NULL
)
461 *max_valnamelen
= mykeydata
->max_valnamelen
;
463 if (max_valbufsize
!= NULL
)
464 *max_valbufsize
= mykeydata
->max_valbufsize
;
469 static struct registry_operations reg_backend_rpc
= {
471 .open_key
= rpc_open_key
,
472 .get_predefined_key
= rpc_get_predefined_key
,
473 .enum_key
= rpc_get_subkey_by_index
,
474 .enum_value
= rpc_get_value_by_index
,
475 .create_key
= rpc_add_key
,
476 .delete_key
= rpc_del_key
,
477 .get_key_info
= rpc_get_info
,
478 .get_predefined_key
= rpc_get_predefined_key
,
481 _PUBLIC_ WERROR
reg_open_remote(struct registry_context
**ctx
,
482 struct auth_session_info
*session_info
,
483 struct cli_credentials
*credentials
,
484 struct loadparm_context
*lp_ctx
,
485 const char *location
, struct event_context
*ev
)
488 struct dcerpc_pipe
*p
;
489 struct rpc_registry_context
*rctx
;
493 rctx
= talloc(NULL
, struct rpc_registry_context
);
495 /* Default to local smbd if no connection is specified */
497 location
= talloc_strdup(rctx
, "ncalrpc:");
500 status
= dcerpc_pipe_connect(rctx
/* TALLOC_CTX */,
503 credentials
, ev
, lp_ctx
);
506 if(NT_STATUS_IS_ERR(status
)) {
507 DEBUG(1, ("Unable to open '%s': %s\n", location
,
511 return ntstatus_to_werror(status
);
514 *ctx
= (struct registry_context
*)rctx
;
515 (*ctx
)->ops
= ®_backend_rpc
;