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_zero(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_zero(mem_ctx
, struct rpc_key
);
215 mykeydata
->key
.context
= parentkeydata
->key
.context
;
216 mykeydata
->pipe
= talloc_reference(mykeydata
, parentkeydata
->pipe
);
217 mykeydata
->num_values
= -1;
218 mykeydata
->num_subkeys
= -1;
219 *key
= (struct registry_key
*)mykeydata
;
221 /* Then, open the handle using the hive */
223 r
.in
.parent_handle
= &parentkeydata
->pol
;
224 chars_to_winreg_String(mem_ctx
, &r
.in
.keyname
, name
);
225 r
.in
.unknown
= 0x00000000;
226 r
.in
.access_mask
= 0x02000000;
227 r
.out
.handle
= &mykeydata
->pol
;
229 status
= dcerpc_winreg_OpenKey(mykeydata
->pipe
, mem_ctx
, &r
);
231 if (!NT_STATUS_IS_OK(status
)) {
232 DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status
)));
233 return ntstatus_to_werror(status
);
239 static WERROR
rpc_get_value_by_index(TALLOC_CTX
*mem_ctx
,
240 const struct registry_key
*parent
,
242 const char **value_name
,
246 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
247 struct winreg_EnumValue r
;
248 struct winreg_StringBuf name
;
250 uint32_t val_size
= MAX_VALSIZE
;
255 if (mykeydata
->num_values
== -1) {
256 error
= rpc_query_key(mem_ctx
, parent
);
257 if(!W_ERROR_IS_OK(error
)) return error
;
260 chars_to_winreg_StringBuf(mem_ctx
, &name
, "", MAX_NAMESIZE
);
263 r
.in
.handle
= &mykeydata
->pol
;
268 r
.in
.size
= &val_size
;
272 r
.out
.value
= &value
;
273 r
.out
.size
= &val_size
;
274 r
.out
.length
= &zero
;
276 status
= dcerpc_winreg_EnumValue(mykeydata
->pipe
, mem_ctx
, &r
);
278 if (!NT_STATUS_IS_OK(status
)) {
279 DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status
)));
280 return ntstatus_to_werror(status
);
283 winreg_StringBuf_to_chars(mem_ctx
, value_name
, r
.out
.name
);
284 *type
= *(r
.out
.type
);
285 *data
= data_blob_talloc(mem_ctx
, r
.out
.value
, *r
.out
.length
);
290 static WERROR
rpc_get_subkey_by_index(TALLOC_CTX
*mem_ctx
,
291 const struct registry_key
*parent
,
294 const char **keyclass
,
295 NTTIME
*last_changed_time
)
297 struct winreg_EnumKey r
;
298 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
299 struct winreg_StringBuf namebuf
, classbuf
;
300 NTTIME change_time
= 0;
303 chars_to_winreg_StringBuf(mem_ctx
, &namebuf
, " ", MAX_NAMESIZE
);
304 chars_to_winreg_StringBuf(mem_ctx
, &classbuf
, NULL
, 0);
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(mykeydata
->pipe
, 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 winreg_StringBuf_to_chars(mem_ctx
, name
, r
.out
.name
);
325 if (keyclass
!= NULL
)
326 winreg_StringBuf_to_chars(mem_ctx
, keyclass
, r
.out
.keyclass
);
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 *name
,
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 chars_to_winreg_String(mem_ctx
, &r
.in
.name
, name
);
348 chars_to_winreg_String(mem_ctx
, &r
.in
.keyclass
, 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(parentkd
->pipe
, 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
->pipe
= talloc_reference(rpck
, parentkd
->pipe
);
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 chars_to_winreg_String(mem_ctx
, &classname
, 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_subkeysize
= &mykeydata
->max_subkeysize
;
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(mykeydata
->pipe
, 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 winreg_String_to_chars(mem_ctx
, &mykeydata
->classname
, r
.out
.classname
);
404 static WERROR
rpc_del_key(struct registry_key
*parent
, const char *name
)
407 struct rpc_key
*mykeydata
= talloc_get_type(parent
, struct rpc_key
);
408 struct winreg_DeleteKey r
;
409 TALLOC_CTX
*mem_ctx
= talloc_init("del_key");
412 r
.in
.handle
= &mykeydata
->pol
;
413 chars_to_winreg_String(mem_ctx
, &r
.in
.key
, name
);
415 status
= dcerpc_winreg_DeleteKey(mykeydata
->pipe
, mem_ctx
, &r
);
417 talloc_free(mem_ctx
);
419 if (!NT_STATUS_IS_OK(status
)) {
420 DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status
)));
421 return ntstatus_to_werror(status
);
427 static WERROR
rpc_get_info(TALLOC_CTX
*mem_ctx
, const struct registry_key
*key
,
428 const char **classname
,
429 uint32_t *num_subkeys
,
430 uint32_t *num_values
,
431 NTTIME
*last_changed_time
,
432 uint32_t *max_subkeylen
,
433 uint32_t *max_valnamelen
,
434 uint32_t *max_valbufsize
)
436 struct rpc_key
*mykeydata
= talloc_get_type(key
, struct rpc_key
);
439 if (mykeydata
->num_values
== -1) {
440 error
= rpc_query_key(mem_ctx
, key
);
441 if(!W_ERROR_IS_OK(error
)) return error
;
444 if (classname
!= NULL
)
445 *classname
= mykeydata
->classname
;
447 if (num_subkeys
!= NULL
)
448 *num_subkeys
= mykeydata
->num_subkeys
;
450 if (num_values
!= NULL
)
451 *num_values
= mykeydata
->num_values
;
453 if (last_changed_time
!= NULL
)
454 *last_changed_time
= mykeydata
->last_changed_time
;
456 if (max_subkeylen
!= NULL
)
457 *max_subkeylen
= mykeydata
->max_subkeylen
;
459 if (max_valnamelen
!= NULL
)
460 *max_valnamelen
= mykeydata
->max_valnamelen
;
462 if (max_valbufsize
!= NULL
)
463 *max_valbufsize
= mykeydata
->max_valbufsize
;
468 static struct registry_operations reg_backend_rpc
= {
470 .open_key
= rpc_open_key
,
471 .get_predefined_key
= rpc_get_predefined_key
,
472 .enum_key
= rpc_get_subkey_by_index
,
473 .enum_value
= rpc_get_value_by_index
,
474 .create_key
= rpc_add_key
,
475 .delete_key
= rpc_del_key
,
476 .get_key_info
= rpc_get_info
,
477 .get_predefined_key
= rpc_get_predefined_key
,
480 _PUBLIC_ WERROR
reg_open_remote(struct registry_context
**ctx
,
481 struct auth_session_info
*session_info
,
482 struct cli_credentials
*credentials
,
483 struct loadparm_context
*lp_ctx
,
484 const char *location
, struct event_context
*ev
)
487 struct dcerpc_pipe
*p
;
488 struct rpc_registry_context
*rctx
;
492 rctx
= talloc(NULL
, struct rpc_registry_context
);
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
);
505 if(NT_STATUS_IS_ERR(status
)) {
506 DEBUG(1, ("Unable to open '%s': %s\n", location
,
510 return ntstatus_to_werror(status
);
513 *ctx
= (struct registry_context
*)rctx
;
514 (*ctx
)->ops
= ®_backend_rpc
;