1 /*
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
6 
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.
11 
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.
16 
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/>.  */
19 
20 #include "includes.h"
21 #include "registry.h"
22 #include "librpc/gen_ndr/ndr_winreg_c.h"
23 
24 #define MAX_NAMESIZE 512
25 #define MAX_VALSIZE 32768
26 
27 struct rpc_key {
28 	struct registry_key key;
29 	struct policy_handle pol;
30 	struct dcerpc_binding_handle *binding_handle;
31 	const char* classname;
32 	uint32_t num_subkeys;
33 	uint32_t max_subkeylen;
34 	uint32_t max_classlen;
35 	uint32_t num_values;
36 	uint32_t max_valnamelen;
37 	uint32_t max_valbufsize;
38 	uint32_t secdescsize;
39 	NTTIME last_changed_time;
40 };
41 
42 struct rpc_registry_context {
43 	struct registry_context context;
44 	struct dcerpc_pipe *pipe;
45 	struct dcerpc_binding_handle *binding_handle;
46 };
47 
48 static struct registry_operations reg_backend_rpc;
49 
50 /**
51  * This is the RPC backend for the registry library.
52  */
53 
54 #define openhive(u) static WERROR open_ ## u(struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
55 { \
56 	struct winreg_Open ## u r; \
57 	NTSTATUS status; \
58 \
59 	ZERO_STRUCT(r); \
60 	r.in.system_name = NULL; \
61 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
62 	r.out.handle = hnd;\
63 \
64 	status = dcerpc_winreg_Open ## u ## _r(b, mem_ctx, &r); \
65 \
66 	if (!NT_STATUS_IS_OK(status)) { \
67 		DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \
68 		return ntstatus_to_werror(status); \
69 	} \
70 \
71 	return r.out.result;\
72 }
73 
74 openhive(HKLM)
75 openhive(HKCU)
76 openhive(HKPD)
77 openhive(HKU)
78 openhive(HKCR)
79 openhive(HKDD)
80 openhive(HKCC)
81 
82 static struct {
83 	uint32_t hkey;
84 	WERROR (*open) (struct dcerpc_binding_handle *b, TALLOC_CTX *,
85 			struct policy_handle *h);
86 } known_hives[] = {
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 },
94 	{ 0, NULL }
95 };
96 
97 static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k);
98 
rpc_get_predefined_key(struct registry_context * ctx,uint32_t hkey_type,struct registry_key ** k)99 static WERROR rpc_get_predefined_key(struct registry_context *ctx,
100 				     uint32_t hkey_type,
101 				     struct registry_key **k)
102 {
103 	int n;
104 	struct rpc_key *mykeydata;
105 	struct rpc_registry_context *rctx = talloc_get_type(ctx, struct rpc_registry_context);
106 
107 	*k = NULL;
108 
109 	for(n = 0; known_hives[n].hkey; n++) {
110 		if(known_hives[n].hkey == hkey_type)
111 			break;
112 	}
113 
114 	if (known_hives[n].open == NULL)  {
115 		DEBUG(1, ("No such hive %d\n", hkey_type));
116 		return WERR_NO_MORE_ITEMS;
117 	}
118 
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);
127 }
128 
129 #if 0
130 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
131 {
132 	struct winreg_OpenKey r;
133 	struct rpc_key_data *mykeydata;
134 
135 	k->backend_data = mykeydata = talloc_zero(mem_ctx, struct rpc_key_data);
136 	mykeydata->num_values = -1;
137 	mykeydata->num_subkeys = -1;
138 
139 	/* Then, open the handle using the hive */
140 
141 	ZERO_STRUCT(r);
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;
147 
148 	dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data,
149 			      mem_ctx, &r);
150 
151 	return r.out.result;
152 }
153 #endif
154 
rpc_open_key(TALLOC_CTX * mem_ctx,struct registry_key * h,const char * name,struct registry_key ** key)155 static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h,
156 			   const char *name, struct registry_key **key)
157 {
158 	struct rpc_key *parentkeydata = talloc_get_type(h, struct rpc_key),
159 						    *mykeydata;
160 	struct winreg_OpenKey r;
161 	NTSTATUS status;
162 
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;
170 
171 	/* Then, open the handle using the hive */
172 	ZERO_STRUCT(r);
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;
178 
179 	status = dcerpc_winreg_OpenKey_r(mykeydata->binding_handle, mem_ctx, &r);
180 
181 	if (!NT_STATUS_IS_OK(status)) {
182 		DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status)));
183 		return ntstatus_to_werror(status);
184 	}
185 
186 	return r.out.result;
187 }
188 
rpc_get_value_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * parent,uint32_t n,const char ** value_name,uint32_t * type,DATA_BLOB * data)189 static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx,
190 				     const struct registry_key *parent,
191 				     uint32_t n,
192 				     const char **value_name,
193 				     uint32_t *type,
194 				     DATA_BLOB *data)
195 {
196 	struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
197 	struct winreg_EnumValue r;
198 	struct winreg_ValNameBuf name;
199 	uint8_t value;
200 	uint32_t val_size = MAX_VALSIZE;
201 	uint32_t zero = 0;
202 	WERROR error;
203 	NTSTATUS status;
204 
205 	if (mykeydata->num_values == -1) {
206 		error = rpc_query_key(mem_ctx, parent);
207 		if(!W_ERROR_IS_OK(error)) return error;
208 	}
209 
210 	name.name = "";
211 	name.size = MAX_NAMESIZE;
212 
213 	ZERO_STRUCT(r);
214 	r.in.handle = &mykeydata->pol;
215 	r.in.enum_index = n;
216 	r.in.name = &name;
217 	r.in.type = (enum winreg_Type *) type;
218 	r.in.value = &value;
219 	r.in.size = &val_size;
220 	r.in.length = &zero;
221 	r.out.name = &name;
222 	r.out.type = (enum winreg_Type *) type;
223 	r.out.value = &value;
224 	r.out.size = &val_size;
225 	r.out.length = &zero;
226 
227 	status = dcerpc_winreg_EnumValue_r(mykeydata->binding_handle, mem_ctx, &r);
228 
229 	if (!NT_STATUS_IS_OK(status)) {
230 		DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status)));
231 		return ntstatus_to_werror(status);
232 	}
233 
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);
237 
238 	return r.out.result;
239 }
240 
rpc_get_value_by_name(TALLOC_CTX * mem_ctx,const struct registry_key * parent,const char * value_name,uint32_t * type,DATA_BLOB * data)241 static WERROR rpc_get_value_by_name(TALLOC_CTX *mem_ctx,
242 				     const struct registry_key *parent,
243 				     const char *value_name,
244 				     uint32_t *type,
245 				     DATA_BLOB *data)
246 {
247 	struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
248 	struct winreg_QueryValue r;
249 	struct winreg_String name;
250 	uint8_t value;
251 	uint32_t val_size = MAX_VALSIZE;
252 	uint32_t zero = 0;
253 	WERROR error;
254 	NTSTATUS status;
255 
256 	if (mykeydata->num_values == -1) {
257 		error = rpc_query_key(mem_ctx, parent);
258 		if(!W_ERROR_IS_OK(error)) return error;
259 	}
260 
261 	name.name = value_name;
262 
263 	ZERO_STRUCT(r);
264 	r.in.handle = &mykeydata->pol;
265 	r.in.value_name = &name;
266 	r.in.type = (enum winreg_Type *) type;
267 	r.in.data = &value;
268 	r.in.data_size = &val_size;
269 	r.in.data_length = &zero;
270 	r.out.type = (enum winreg_Type *) type;
271 	r.out.data = &value;
272 	r.out.data_size = &val_size;
273 	r.out.data_length = &zero;
274 
275 	status = dcerpc_winreg_QueryValue_r(mykeydata->binding_handle, mem_ctx, &r);
276 
277 	if (!NT_STATUS_IS_OK(status)) {
278 		DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status)));
279 		return ntstatus_to_werror(status);
280 	}
281 
282 	*type = *(r.out.type);
283 	*data = data_blob_talloc(mem_ctx, r.out.data, *r.out.data_length);
284 
285 	return r.out.result;
286 }
287 
rpc_set_value(struct registry_key * key,const char * value_name,uint32_t type,const DATA_BLOB data)288 static WERROR rpc_set_value(struct registry_key *key, const char *value_name,
289 			    uint32_t type, const DATA_BLOB data)
290 {
291 	struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
292 	struct winreg_SetValue r;
293 	struct winreg_String name;
294 	NTSTATUS status;
295 
296 	name = (struct winreg_String) { .name = value_name };
297 
298 	ZERO_STRUCT(r);
299 	r.in.handle = &mykeydata->pol;
300 	r.in.name = name;
301 	r.in.type = (enum winreg_Type)type;
302 	r.in.data = data.data;
303 	r.in.size = data.length;
304 
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);
309 	}
310 
311 	return r.out.result;
312 }
313 
rpc_del_value(TALLOC_CTX * mem_ctx,struct registry_key * key,const char * value_name)314 static WERROR rpc_del_value(TALLOC_CTX *mem_ctx, struct registry_key *key,
315 			    const char *value_name)
316 {
317 	struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
318 	struct winreg_DeleteValue r;
319 	struct winreg_String name;
320 	NTSTATUS status;
321 
322 	name = (struct winreg_String) { .name = value_name };
323 
324 	ZERO_STRUCT(r);
325 	r.in.handle = &mykeydata->pol;
326 	r.in.value = name;
327 
328 	status = dcerpc_winreg_DeleteValue_r(mykeydata->binding_handle,
329 					     mem_ctx, &r);
330 	if (!NT_STATUS_IS_OK(status)) {
331 		DEBUG(1, ("DeleteValue failed - %s\n", nt_errstr(status)));
332 		return ntstatus_to_werror(status);
333 	}
334 
335 	return r.out.result;
336 }
337 
rpc_get_subkey_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * parent,uint32_t n,const char ** name,const char ** keyclass,NTTIME * last_changed_time)338 static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx,
339 				      const struct registry_key *parent,
340 				      uint32_t n,
341 				      const char **name,
342 				      const char **keyclass,
343 				      NTTIME *last_changed_time)
344 {
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;
349 	NTSTATUS status;
350 
351 	namebuf.name = "";
352 	namebuf.size = MAX_NAMESIZE;
353 	classbuf.name = NULL;
354 	classbuf.size = 0;
355 
356 	ZERO_STRUCT(r);
357 	r.in.handle = &mykeydata->pol;
358 	r.in.enum_index = n;
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;
365 
366 	status = dcerpc_winreg_EnumKey_r(mykeydata->binding_handle, mem_ctx, &r);
367 
368 	if (!NT_STATUS_IS_OK(status)) {
369 		DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status)));
370 		return ntstatus_to_werror(status);
371 	}
372 
373 	if (name != NULL)
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);
379 
380 	return r.out.result;
381 }
382 
rpc_add_key(TALLOC_CTX * mem_ctx,struct registry_key * parent,const char * path,const char * key_class,struct security_descriptor * sec,struct registry_key ** key)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)
388 {
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);
392 
393 	NTSTATUS status;
394 
395 	if (rpck == NULL) {
396 		return WERR_NOT_ENOUGH_MEMORY;
397 	}
398 
399 	rpck->key.context = parentkd->key.context;
400 	rpck->binding_handle = parentkd->binding_handle;
401 	rpck->num_values = -1;
402 	rpck->num_subkeys = -1;
403 
404 	ZERO_STRUCT(r);
405 	r.in.handle = &parentkd->pol;
406 	r.in.name.name = path;
407 	r.in.keyclass.name = NULL;
408 	r.in.options = 0;
409 	r.in.access_mask = 0x02000000;
410 	r.in.secdesc = NULL;
411 	r.in.action_taken = NULL;
412 	r.out.new_handle = &rpck->pol;
413 	r.out.action_taken = NULL;
414 
415 	status = dcerpc_winreg_CreateKey_r(parentkd->binding_handle, mem_ctx, &r);
416 
417 	if (!NT_STATUS_IS_OK(status)) {
418 		talloc_free(rpck);
419 		DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
420 		return ntstatus_to_werror(status);
421 	}
422 
423 	rpck->binding_handle = parentkd->binding_handle;
424 	*key = (struct registry_key *)rpck;
425 
426 	return r.out.result;
427 }
428 
rpc_query_key(TALLOC_CTX * mem_ctx,const struct registry_key * k)429 static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k)
430 {
431 	struct winreg_QueryInfoKey r;
432 	struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key);
433 	struct winreg_String classname;
434 	NTSTATUS status;
435 
436 	classname.name = NULL;
437 
438 	ZERO_STRUCT(r);
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;
450 
451 	status = dcerpc_winreg_QueryInfoKey_r(mykeydata->binding_handle, mem_ctx, &r);
452 
453 	if (!NT_STATUS_IS_OK(status)) {
454 		DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
455 		return ntstatus_to_werror(status);
456 	}
457 
458 	mykeydata->classname = talloc_steal(mem_ctx, r.out.classname->name);
459 
460 	return r.out.result;
461 }
462 
rpc_del_key(TALLOC_CTX * mem_ctx,struct registry_key * parent,const char * name)463 static WERROR rpc_del_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
464 			  const char *name)
465 {
466 	NTSTATUS status;
467 	struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
468 	struct winreg_DeleteKey r;
469 
470 	ZERO_STRUCT(r);
471 	r.in.handle = &mykeydata->pol;
472 	r.in.key.name = name;
473 
474 	status = dcerpc_winreg_DeleteKey_r(mykeydata->binding_handle, mem_ctx, &r);
475 
476 	if (!NT_STATUS_IS_OK(status)) {
477 		DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status)));
478 		return ntstatus_to_werror(status);
479 	}
480 
481 	return r.out.result;
482 }
483 
rpc_get_info(TALLOC_CTX * mem_ctx,const struct registry_key * key,const char ** classname,uint32_t * num_subkeys,uint32_t * num_values,NTTIME * last_changed_time,uint32_t * max_subkeylen,uint32_t * max_valnamelen,uint32_t * max_valbufsize)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)
492 {
493 	struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
494 	WERROR error;
495 
496 	if (mykeydata->num_values == -1) {
497 		error = rpc_query_key(mem_ctx, key);
498 		if(!W_ERROR_IS_OK(error)) return error;
499 	}
500 
501 	if (classname != NULL)
502 		*classname = mykeydata->classname;
503 
504 	if (num_subkeys != NULL)
505 		*num_subkeys = mykeydata->num_subkeys;
506 
507 	if (num_values != NULL)
508 		*num_values = mykeydata->num_values;
509 
510 	if (last_changed_time != NULL)
511 		*last_changed_time = mykeydata->last_changed_time;
512 
513 	if (max_subkeylen != NULL)
514 		*max_subkeylen = mykeydata->max_subkeylen;
515 
516 	if (max_valnamelen != NULL)
517 		*max_valnamelen = mykeydata->max_valnamelen;
518 
519 	if (max_valbufsize != NULL)
520 		*max_valbufsize = mykeydata->max_valbufsize;
521 
522 	return WERR_OK;
523 }
524 
525 static struct registry_operations reg_backend_rpc = {
526 	.name = "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,
537 };
538 
reg_open_remote(TALLOC_CTX * mem_ctx,struct registry_context ** ctx,struct auth_session_info * session_info,struct cli_credentials * credentials,struct loadparm_context * lp_ctx,const char * location,struct tevent_context * ev)539 _PUBLIC_ WERROR reg_open_remote(TALLOC_CTX *mem_ctx,
540 				struct registry_context **ctx,
541 				struct auth_session_info *session_info,
542 				struct cli_credentials *credentials,
543 				struct loadparm_context *lp_ctx,
544 				const char *location, struct tevent_context *ev)
545 {
546 	NTSTATUS status;
547 	struct dcerpc_pipe *p;
548 	struct rpc_registry_context *rctx;
549 
550 	dcerpc_init();
551 
552 	rctx = talloc(mem_ctx, struct rpc_registry_context);
553 	W_ERROR_HAVE_NO_MEMORY(rctx);
554 
555 	/* Default to local smbd if no connection is specified */
556 	if (!location) {
557 		location = talloc_strdup(rctx, "ncalrpc:");
558 	}
559 
560 	status = dcerpc_pipe_connect(rctx /* TALLOC_CTX */,
561 				     &p, location,
562 				     &ndr_table_winreg,
563 				     credentials, ev, lp_ctx);
564 	if(NT_STATUS_IS_ERR(status)) {
565 		DEBUG(1, ("Unable to open '%s': %s\n", location,
566 			nt_errstr(status)));
567 		talloc_free(rctx);
568 		*ctx = NULL;
569 		return ntstatus_to_werror(status);
570 	}
571 
572 	rctx->pipe = p;
573 	rctx->binding_handle = p->binding_handle;
574 
575 	*ctx = (struct registry_context *)rctx;
576 	(*ctx)->ops = &reg_backend_rpc;
577 
578 	return WERR_OK;
579 }
580