1 /*
2    Samba Unix/Linux SMB implementation
3    RPC backend for the registry library
4    Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19 
20 #include "includes.h"
21 #include "registry.h"
22 #include "librpc/gen_ndr/ndr_winreg_c.h"
23 
24 static struct hive_operations reg_backend_rpc;
25 
26 /**
27  * This is the RPC backend for the registry library.
28  */
29 
init_winreg_String(struct winreg_String * name,const char * s)30 static void init_winreg_String(struct winreg_String *name, const char *s)
31 {
32 	name->name = s;
33 }
34 
35 
36 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
37 { \
38 	struct winreg_Open ## u r; \
39 	NTSTATUS status; \
40 	\
41 	r.in.system_name = NULL; \
42 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
43 	r.out.handle = hnd;\
44 	\
45 	status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
46 	if (NT_STATUS_IS_ERR(status)) {\
47 		DEBUG(0,("Error executing open\n"));\
48 		return ntstatus_to_werror(status);\
49 	}\
50 \
51 	return r.out.result;\
52 }
53 
54 openhive(HKLM)
55 openhive(HKCU)
56 openhive(HKPD)
57 openhive(HKU)
58 openhive(HKCR)
59 openhive(HKDD)
60 openhive(HKCC)
61 
62 struct rpc_key_data {
63 	struct policy_handle pol;
64 	int num_subkeys;
65 	int num_values;
66 	int max_valnamelen;
67 	int max_valdatalen;
68 };
69 
70 static struct {
71 	uint32_t hkey;
72 	WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h);
73 } known_hives[] = {
74 { HKEY_LOCAL_MACHINE, open_HKLM },
75 { HKEY_CURRENT_USER, open_HKCU },
76 { HKEY_CLASSES_ROOT, open_HKCR },
77 { HKEY_PERFORMANCE_DATA, open_HKPD },
78 { HKEY_USERS, open_HKU },
79 { HKEY_DYN_DATA, open_HKDD },
80 { HKEY_CURRENT_CONFIG, open_HKCC },
81 { 0, NULL }
82 };
83 
84 static WERROR rpc_query_key(const struct registry_key *k);
85 
rpc_get_predefined_key(struct registry_context * ctx,uint32_t hkey_type,struct registry_key ** k)86 static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hkey_type, struct registry_key **k)
87 {
88 	int n;
89 	struct registry_hive *h;
90 	struct rpc_key_data *mykeydata;
91 
92 	for(n = 0; known_hives[n].hkey; n++)
93 	{
94 		if(known_hives[n].hkey == hkey_type) break;
95 	}
96 
97 	if(!known_hives[n].open)  {
98 		DEBUG(1, ("No such hive %d\n", hkey_type));
99 		return WERR_NO_MORE_ITEMS;
100 	}
101 
102 	h = talloc(ctx, struct registry_hive);
103 	h->functions = &reg_backend_rpc;
104 	h->location = NULL;
105 	h->backend_data = ctx->backend_data;
106 
107 	(*k) = h->root = talloc(h, struct registry_key);
108 	(*k)->hive = h;
109 	(*k)->backend_data = mykeydata = talloc(*k, struct rpc_key_data);
110 	mykeydata->num_values = -1;
111 	mykeydata->num_subkeys = -1;
112 	return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol));
113 }
114 
115 #if 0
116 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
117 {
118     struct winreg_OpenKey r;
119 	struct rpc_key_data *mykeydata;
120 
121 	k->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
122 	mykeydata->num_values = -1;
123 	mykeydata->num_subkeys = -1;
124 
125 	/* Then, open the handle using the hive */
126 
127 	memset(&r, 0, sizeof(struct winreg_OpenKey));
128     r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
129     init_winreg_String(&r.in.keyname, k->path);
130     r.in.unknown = 0x00000000;
131     r.in.access_mask = 0x02000000;
132     r.out.handle = &mykeydata->pol;
133 
134     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
135 
136 	return r.out.result;
137 }
138 #endif
139 
rpc_open_key(TALLOC_CTX * mem_ctx,const struct registry_key * h,const char * name,struct registry_key ** key)140 static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
141 {
142 	struct rpc_key_data *mykeydata;
143     struct winreg_OpenKey r;
144 
145 	*key = talloc(mem_ctx, struct registry_key);
146 	(*key)->name = talloc_strdup(mem_ctx, name);
147 
148 	(*key)->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
149 	mykeydata->num_values = -1;
150 	mykeydata->num_subkeys = -1;
151 
152 	/* Then, open the handle using the hive */
153 
154 	memset(&r, 0, sizeof(struct winreg_OpenKey));
155     r.in.parent_handle = &(((struct rpc_key_data *)h->backend_data)->pol);
156     init_winreg_String(&r.in.keyname, name);
157     r.in.unknown = 0x00000000;
158     r.in.access_mask = 0x02000000;
159     r.out.handle = &mykeydata->pol;
160 
161     dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r);
162 
163 	return r.out.result;
164 }
165 
rpc_get_value_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * parent,int n,struct registry_value ** value)166 static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_value **value)
167 {
168 	struct rpc_key_data *mykeydata = parent->backend_data;
169 	WERROR error;
170 	struct winreg_EnumValue r;
171 	uint32_t len1, zero = 0;
172 	enum winreg_Type type;
173 	NTSTATUS status;
174 	struct winreg_StringBuf name;
175 	uint8_t u8;
176 
177 	if(mykeydata->num_values == -1) {
178 		error = rpc_query_key(parent);
179 		if(!W_ERROR_IS_OK(error)) return error;
180 	}
181 
182 	len1 = mykeydata->max_valdatalen;
183 
184 	name.length = 0;
185 	name.size   = mykeydata->max_valnamelen * 2;
186 	name.name   = "";
187 
188 	r.in.handle = &mykeydata->pol;
189 	r.in.enum_index = n;
190 	r.in.name = &name;
191 	r.in.type = &type;
192 	r.in.value = &u8;
193 	r.in.length = &zero;
194 	r.in.size = &len1;
195 	r.out.name = &name;
196 
197 	status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
198 	if(NT_STATUS_IS_ERR(status)) {
199 		DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
200 		return WERR_GENERAL_FAILURE;
201 	}
202 
203 	if(NT_STATUS_IS_OK(status) &&
204 	   W_ERROR_IS_OK(r.out.result) && r.out.length) {
205 		*value = talloc(mem_ctx, struct registry_value);
206 		(*value)->name = talloc_strdup(mem_ctx, r.out.name->name);
207 		(*value)->data_type = type;
208 		(*value)->data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
209 		return WERR_OK;
210 	}
211 
212 	return r.out.result;
213 }
214 
rpc_get_subkey_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * parent,int n,struct registry_key ** subkey)215 static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **subkey)
216 {
217 	struct winreg_EnumKey r;
218 	struct rpc_key_data *mykeydata = parent->backend_data;
219 	NTSTATUS status;
220 	struct winreg_StringBuf namebuf, classbuf;
221 	NTTIME change_time = 0;
222 
223 	namebuf.length = 0;
224 	namebuf.size   = 1024;
225 	namebuf.name   = NULL;
226 	classbuf.length = 0;
227 	classbuf.size   = 0;
228 	classbuf.name   = NULL;
229 
230 	r.in.handle = &mykeydata->pol;
231 	r.in.enum_index = n;
232 	r.in.name = &namebuf;
233 	r.in.keyclass = &classbuf;
234 	r.in.last_changed_time = &change_time;
235 	r.out.name = &namebuf;
236 
237 	status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
238 	if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
239 		char *name = talloc_strdup(mem_ctx, r.out.name->name);
240 		return rpc_open_key(mem_ctx, parent, name, subkey);
241 	}
242 
243 	return r.out.result;
244 }
245 
rpc_add_key(TALLOC_CTX * mem_ctx,const struct registry_key * parent,const char * name,uint32_t access_mask,struct security_descriptor * sec,struct registry_key ** key)246 static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key)
247 {
248 	NTSTATUS status;
249 	struct winreg_CreateKey r;
250 
251 	init_winreg_String(&r.in.name, name);
252 	init_winreg_String(&r.in.keyclass, NULL);
253 
254 	r.in.handle = parent->backend_data;
255 	r.out.new_handle = talloc(mem_ctx, struct policy_handle);
256 	r.in.options = 0;
257 	r.in.access_mask = access_mask;
258 	r.in.secdesc = NULL;
259 
260 	status = dcerpc_winreg_CreateKey((struct dcerpc_pipe *)(parent->hive->backend_data), mem_ctx, &r);
261 
262     if (!NT_STATUS_IS_OK(status)) {
263         DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
264         return ntstatus_to_werror(status);
265     }
266 
267 	if (W_ERROR_IS_OK(r.out.result)) {
268 		*key = talloc(mem_ctx, struct registry_key);
269 		(*key)->name = talloc_strdup(*key, name);
270 		(*key)->backend_data = r.out.new_handle;
271 	}
272 
273 	return r.out.result;
274 }
275 
rpc_query_key(const struct registry_key * k)276 static WERROR rpc_query_key(const struct registry_key *k)
277 {
278     NTSTATUS status;
279     struct winreg_QueryInfoKey r;
280     struct rpc_key_data *mykeydata = k->backend_data;
281 	TALLOC_CTX *mem_ctx = talloc_init("query_key");
282 
283     init_winreg_String(&r.in.class_in, NULL);
284     r.in.handle = &mykeydata->pol;
285 
286     status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r);
287 	talloc_free(mem_ctx);
288 
289     if (!NT_STATUS_IS_OK(status)) {
290         DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
291         return ntstatus_to_werror(status);
292     }
293 
294     if (W_ERROR_IS_OK(r.out.result)) {
295 		mykeydata->num_subkeys = *r.out.num_subkeys;
296 		mykeydata->num_values = *r.out.num_values;
297 		mykeydata->max_valnamelen = *r.out.max_valnamelen;
298 		mykeydata->max_valdatalen = *r.out.max_valbufsize;
299 	}
300 
301 	return r.out.result;
302 }
303 
rpc_del_key(const struct registry_key * parent,const char * name)304 static WERROR rpc_del_key(const struct registry_key *parent, const char *name)
305 {
306 	NTSTATUS status;
307 	struct rpc_key_data *mykeydata = parent->backend_data;
308 	struct winreg_DeleteKey r;
309 	TALLOC_CTX *mem_ctx = talloc_init("del_key");
310 
311     r.in.handle = &mykeydata->pol;
312     init_winreg_String(&r.in.key, name);
313 
314     status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
315 
316 	talloc_free(mem_ctx);
317 
318 	return r.out.result;
319 }
320 
rpc_num_values(const struct registry_key * key,uint32_t * count)321 static WERROR rpc_num_values(const struct registry_key *key, uint32_t *count)
322 {
323 	struct rpc_key_data *mykeydata = key->backend_data;
324 	WERROR error;
325 
326 	if(mykeydata->num_values == -1) {
327 		error = rpc_query_key(key);
328 		if(!W_ERROR_IS_OK(error)) return error;
329 	}
330 
331 	*count = mykeydata->num_values;
332 	return WERR_OK;
333 }
334 
rpc_num_subkeys(const struct registry_key * key,uint32_t * count)335 static WERROR rpc_num_subkeys(const struct registry_key *key, uint32_t *count)
336 {
337 	struct rpc_key_data *mykeydata = key->backend_data;
338 	WERROR error;
339 
340 	if(mykeydata->num_subkeys == -1) {
341 		error = rpc_query_key(key);
342 		if(!W_ERROR_IS_OK(error)) return error;
343 	}
344 
345 	*count = mykeydata->num_subkeys;
346 	return WERR_OK;
347 }
348 
349 static struct hive_operations reg_backend_rpc = {
350 	.name = "rpc",
351 	.open_key = rpc_open_key,
352 	.get_subkey_by_index = rpc_get_subkey_by_index,
353 	.get_value_by_index = rpc_get_value_by_index,
354 	.add_key = rpc_add_key,
355 	.del_key = rpc_del_key,
356 	.num_subkeys = rpc_num_subkeys,
357 	.num_values = rpc_num_values,
358 };
359 
reg_open_remote(struct registry_context ** ctx,struct auth_session_info * session_info,struct cli_credentials * credentials,const char * location,struct event_context * ev)360 _PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, struct auth_session_info *session_info, struct cli_credentials *credentials,
361 		       const char *location, struct event_context *ev)
362 {
363 	NTSTATUS status;
364 	struct dcerpc_pipe *p;
365 
366 	*ctx = talloc(NULL, struct registry_context);
367 
368 	/* Default to local smbd if no connection is specified */
369 	if (!location) {
370 		location = talloc_strdup(ctx, "ncalrpc:");
371 	}
372 
373 	status = dcerpc_pipe_connect(*ctx /* TALLOC_CTX */,
374 				     &p, location,
375 					 &dcerpc_table_winreg,
376 				     credentials, ev);
377 	(*ctx)->backend_data = p;
378 
379 	if(NT_STATUS_IS_ERR(status)) {
380 		DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status)));
381 		talloc_free(*ctx);
382 		*ctx = NULL;
383 		return ntstatus_to_werror(status);
384 	}
385 
386 	(*ctx)->get_predefined_key = rpc_get_predefined_key;
387 
388 	return WERR_OK;
389 }
390 
registry_rpc_init(void)391 NTSTATUS registry_rpc_init(void)
392 {
393 	dcerpc_init();
394 	return registry_register(&reg_backend_rpc);
395 }
396