• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/libnet/
1/*
2   Unix SMB/CIFS implementation.
3
4   Copyright (C) Stefan Metzmacher  2004
5   Copyright (C) Rafal Szczesniak   2005
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
21#include "includes.h"
22#include "libnet/libnet.h"
23#include "libcli/libcli.h"
24#include "libcli/composite/composite.h"
25#include "librpc/rpc/dcerpc.h"
26#include "librpc/rpc/dcerpc_proto.h"
27#include "librpc/gen_ndr/ndr_lsa_c.h"
28#include "librpc/gen_ndr/ndr_samr.h"
29
30
31struct rpc_connect_srv_state {
32	struct libnet_context *ctx;
33	struct libnet_RpcConnect r;
34	const char *binding;
35
36	/* information about the progress */
37	void (*monitor_fn)(struct monitor_msg*);
38};
39
40
41static void continue_pipe_connect(struct composite_context *ctx);
42
43
44/**
45 * Initiates connection to rpc pipe on remote server
46 *
47 * @param ctx initialised libnet context
48 * @param mem_ctx memory context of this call
49 * @param r data structure containing necessary parameters and return values
50 * @return composite context of this call
51 **/
52
53static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx,
54							   TALLOC_CTX *mem_ctx,
55							   struct libnet_RpcConnect *r,
56							   void (*monitor)(struct monitor_msg*))
57{
58	struct composite_context *c;
59	struct rpc_connect_srv_state *s;
60	struct dcerpc_binding *b;
61	struct composite_context *pipe_connect_req;
62
63	/* composite context allocation and setup */
64	c = composite_create(ctx, ctx->event_ctx);
65	if (c == NULL) return c;
66
67	s = talloc_zero(c, struct rpc_connect_srv_state);
68	if (composite_nomem(s, c)) return c;
69
70	c->private_data = s;
71	s->monitor_fn   = monitor;
72
73	s->ctx = ctx;
74	s->r = *r;
75	ZERO_STRUCT(s->r.out);
76
77	/* prepare binding string */
78	switch (r->level) {
79	case LIBNET_RPC_CONNECT_SERVER:
80		s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
81		break;
82	case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
83		s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address);
84		break;
85
86	case LIBNET_RPC_CONNECT_BINDING:
87		s->binding = talloc_strdup(s, r->in.binding);
88		break;
89
90	case LIBNET_RPC_CONNECT_DC:
91	case LIBNET_RPC_CONNECT_PDC:
92		/* this should never happen - DC and PDC level has a separate
93		   composite function */
94	case LIBNET_RPC_CONNECT_DC_INFO:
95		/* this should never happen - DC_INFO level has a separate
96		   composite function */
97		composite_error(c, NT_STATUS_INVALID_LEVEL);
98		return c;
99	}
100
101	/* parse binding string to the structure */
102	c->status = dcerpc_parse_binding(c, s->binding, &b);
103	if (!NT_STATUS_IS_OK(c->status)) {
104		DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding));
105		composite_error(c, c->status);
106		return c;
107	}
108
109	switch (r->level) {
110	case LIBNET_RPC_CONNECT_SERVER:
111	case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
112		b->flags = r->in.dcerpc_flags;
113	}
114
115	if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
116		b->target_hostname = talloc_strdup(b, r->in.name);
117		if (composite_nomem(b->target_hostname, c)) {
118			return c;
119		}
120	}
121
122	/* connect to remote dcerpc pipe */
123	pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
124						      ctx->cred, c->event_ctx,
125						      ctx->lp_ctx);
126	if (composite_nomem(pipe_connect_req, c)) return c;
127
128	composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
129	return c;
130}
131
132
133/*
134  Step 2 of RpcConnectSrv - get rpc connection
135*/
136static void continue_pipe_connect(struct composite_context *ctx)
137{
138	struct composite_context *c;
139	struct rpc_connect_srv_state *s;
140
141	c = talloc_get_type(ctx->async.private_data, struct composite_context);
142	s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
143
144	/* receive result of rpc pipe connection */
145	c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
146
147	/* post monitor message */
148	if (s->monitor_fn) {
149		struct monitor_msg msg;
150		struct msg_net_rpc_connect data;
151		struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
152
153		/* prepare monitor message and post it */
154		data.host        = binding->host;
155		data.endpoint    = binding->endpoint;
156		data.transport   = binding->transport;
157		data.domain_name = binding->target_hostname;
158
159		msg.type      = mon_NetRpcConnect;
160		msg.data      = (void*)&data;
161		msg.data_size = sizeof(data);
162		s->monitor_fn(&msg);
163	}
164
165	composite_done(c);
166}
167
168
169/**
170 * Receives result of connection to rpc pipe on remote server
171 *
172 * @param c composite context
173 * @param ctx initialised libnet context
174 * @param mem_ctx memory context of this call
175 * @param r data structure containing necessary parameters and return values
176 * @return nt status of rpc connection
177 **/
178
179static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
180					  struct libnet_context *ctx,
181					  TALLOC_CTX *mem_ctx,
182					  struct libnet_RpcConnect *r)
183{
184	NTSTATUS status;
185	struct rpc_connect_srv_state *s = talloc_get_type(c->private_data,
186					  struct rpc_connect_srv_state);
187
188	status = composite_wait(c);
189	if (NT_STATUS_IS_OK(status)) {
190		/* move the returned rpc pipe between memory contexts */
191		s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
192		r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
193
194		/* reference created pipe structure to long-term libnet_context
195		   so that it can be used by other api functions even after short-term
196		   mem_ctx is freed */
197		if (r->in.dcerpc_iface == &ndr_table_samr) {
198			ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
199
200		} else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
201			ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
202		}
203
204		r->out.error_string = talloc_strdup(mem_ctx, "Success");
205
206	} else {
207		r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
208	}
209
210	talloc_free(c);
211	return status;
212}
213
214
215struct rpc_connect_dc_state {
216	struct libnet_context *ctx;
217	struct libnet_RpcConnect r;
218	struct libnet_RpcConnect r2;
219	struct libnet_LookupDCs f;
220	const char *connect_name;
221
222	/* information about the progress */
223	void (*monitor_fn)(struct monitor_msg *);
224};
225
226
227static void continue_lookup_dc(struct composite_context *ctx);
228static void continue_rpc_connect(struct composite_context *ctx);
229
230
231/**
232 * Initiates connection to rpc pipe on domain pdc
233 *
234 * @param ctx initialised libnet context
235 * @param mem_ctx memory context of this call
236 * @param r data structure containing necessary parameters and return values
237 * @return composite context of this call
238 **/
239
240static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
241							  TALLOC_CTX *mem_ctx,
242							  struct libnet_RpcConnect *r,
243							  void (*monitor)(struct monitor_msg *msg))
244{
245	struct composite_context *c;
246	struct rpc_connect_dc_state *s;
247	struct composite_context *lookup_dc_req;
248
249	/* composite context allocation and setup */
250	c = composite_create(ctx, ctx->event_ctx);
251	if (c == NULL) return c;
252
253	s = talloc_zero(c, struct rpc_connect_dc_state);
254	if (composite_nomem(s, c)) return c;
255
256	c->private_data = s;
257	s->monitor_fn   = monitor;
258
259	s->ctx = ctx;
260	s->r   = *r;
261	ZERO_STRUCT(s->r.out);
262
263	switch (r->level) {
264	case LIBNET_RPC_CONNECT_PDC:
265		s->f.in.name_type = NBT_NAME_PDC;
266		break;
267
268	case LIBNET_RPC_CONNECT_DC:
269		s->f.in.name_type = NBT_NAME_LOGON;
270		break;
271
272	default:
273		break;
274	}
275
276	s->f.in.domain_name = r->in.name;
277	s->f.out.num_dcs    = 0;
278	s->f.out.dcs        = NULL;
279
280	/* find the domain pdc first */
281	lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
282	if (composite_nomem(lookup_dc_req, c)) return c;
283
284	composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
285	return c;
286}
287
288
289/*
290  Step 2 of RpcConnectDC: get domain controller name and
291  initiate RpcConnect to it
292*/
293static void continue_lookup_dc(struct composite_context *ctx)
294{
295	struct composite_context *c;
296	struct rpc_connect_dc_state *s;
297	struct composite_context *rpc_connect_req;
298	struct monitor_msg msg;
299	struct msg_net_lookup_dc data;
300
301	c = talloc_get_type(ctx->async.private_data, struct composite_context);
302	s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
303
304	/* receive result of domain controller lookup */
305	c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
306	if (!composite_is_ok(c)) return;
307
308	/* decide on preferred address type depending on DC type */
309	s->connect_name = s->f.out.dcs[0].name;
310
311	/* post monitor message */
312	if (s->monitor_fn) {
313		/* prepare a monitor message and post it */
314		data.domain_name = s->f.in.domain_name;
315		data.hostname    = s->f.out.dcs[0].name;
316		data.address     = s->f.out.dcs[0].address;
317
318		msg.type         = mon_NetLookupDc;
319		msg.data         = &data;
320		msg.data_size    = sizeof(data);
321		s->monitor_fn(&msg);
322	}
323
324	/* ok, pdc has been found so do attempt to rpc connect */
325	s->r2.level	       = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
326
327	/* this will cause yet another name resolution, but at least
328	 * we pass the right name down the stack now */
329	s->r2.in.name          = talloc_strdup(s, s->connect_name);
330	s->r2.in.address       = talloc_steal(s, s->f.out.dcs[0].address);
331	s->r2.in.dcerpc_iface  = s->r.in.dcerpc_iface;
332	s->r2.in.dcerpc_flags  = s->r.in.dcerpc_flags;
333
334	/* send rpc connect request to the server */
335	rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
336	if (composite_nomem(rpc_connect_req, c)) return;
337
338	composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
339}
340
341
342/*
343  Step 3 of RpcConnectDC: get rpc connection to the server
344*/
345static void continue_rpc_connect(struct composite_context *ctx)
346{
347	struct composite_context *c;
348	struct rpc_connect_dc_state *s;
349
350	c = talloc_get_type(ctx->async.private_data, struct composite_context);
351	s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
352
353	c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
354
355	/* error string is to be passed anyway */
356	s->r.out.error_string  = s->r2.out.error_string;
357	if (!composite_is_ok(c)) return;
358
359	s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
360
361	/* post monitor message */
362	if (s->monitor_fn) {
363		struct monitor_msg msg;
364		struct msg_net_rpc_connect data;
365		struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
366
367		data.host        = binding->host;
368		data.endpoint    = binding->endpoint;
369		data.transport   = binding->transport;
370		data.domain_name = binding->target_hostname;
371
372		msg.type      = mon_NetRpcConnect;
373		msg.data      = (void*)&data;
374		msg.data_size = sizeof(data);
375		s->monitor_fn(&msg);
376	}
377
378	composite_done(c);
379}
380
381
382/**
383 * Receives result of connection to rpc pipe on domain pdc
384 *
385 * @param c composite context
386 * @param ctx initialised libnet context
387 * @param mem_ctx memory context of this call
388 * @param r data structure containing necessary parameters and return values
389 * @return nt status of rpc connection
390 **/
391
392static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
393					 struct libnet_context *ctx,
394					 TALLOC_CTX *mem_ctx,
395					 struct libnet_RpcConnect *r)
396{
397	NTSTATUS status;
398	struct rpc_connect_dc_state *s = talloc_get_type(c->private_data,
399					 struct rpc_connect_dc_state);
400
401	status = composite_wait(c);
402	if (NT_STATUS_IS_OK(status)) {
403		/* move connected rpc pipe between memory contexts
404
405		   The use of talloc_reparent(talloc_parent(), ...) is
406		   bizarre, but it is needed because of the absolutely
407		   atrocious use of talloc in this code. We need to
408		   force the original parent to change, but finding
409		   the original parent is well nigh impossible at this
410		   point in the code (yes, I tried).
411		 */
412		r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe),
413						     mem_ctx, s->r.out.dcerpc_pipe);
414
415		/* reference created pipe structure to long-term libnet_context
416		   so that it can be used by other api functions even after short-term
417		   mem_ctx is freed */
418		if (r->in.dcerpc_iface == &ndr_table_samr) {
419			ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
420
421		} else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
422			ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
423		}
424
425	} else {
426		r->out.error_string = talloc_asprintf(mem_ctx,
427						      "Failed to rpc connect: %s",
428						      nt_errstr(status));
429	}
430
431	talloc_free(c);
432	return status;
433}
434
435
436
437struct rpc_connect_dci_state {
438	struct libnet_context *ctx;
439	struct libnet_RpcConnect r;
440	struct libnet_RpcConnect rpc_conn;
441	struct policy_handle lsa_handle;
442	struct lsa_QosInfo qos;
443	struct lsa_ObjectAttribute attr;
444	struct lsa_OpenPolicy2 lsa_open_policy;
445	struct dcerpc_pipe *lsa_pipe;
446	struct lsa_QueryInfoPolicy2 lsa_query_info2;
447	struct lsa_QueryInfoPolicy lsa_query_info;
448	struct dcerpc_binding *final_binding;
449	struct dcerpc_pipe *final_pipe;
450
451	/* information about the progress */
452	void (*monitor_fn)(struct monitor_msg*);
453};
454
455
456static void continue_dci_rpc_connect(struct composite_context *ctx);
457static void continue_lsa_policy(struct rpc_request *req);
458static void continue_lsa_query_info(struct rpc_request *req);
459static void continue_lsa_query_info2(struct rpc_request *req);
460static void continue_epm_map_binding(struct composite_context *ctx);
461static void continue_secondary_conn(struct composite_context *ctx);
462static void continue_epm_map_binding_send(struct composite_context *c);
463
464
465/**
466 * Initiates connection to rpc pipe on remote server or pdc. Received result
467 * contains info on the domain name, domain sid and realm.
468 *
469 * @param ctx initialised libnet context
470 * @param mem_ctx memory context of this call
471 * @param r data structure containing necessary parameters and return values. Must be a talloc context
472 * @return composite context of this call
473 **/
474
475static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
476							      TALLOC_CTX *mem_ctx,
477							      struct libnet_RpcConnect *r,
478							      void (*monitor)(struct monitor_msg*))
479{
480	struct composite_context *c, *conn_req;
481	struct rpc_connect_dci_state *s;
482
483	/* composite context allocation and setup */
484	c = composite_create(ctx, ctx->event_ctx);
485	if (c == NULL) return c;
486
487	s = talloc_zero(c, struct rpc_connect_dci_state);
488	if (composite_nomem(s, c)) return c;
489
490	c->private_data = s;
491	s->monitor_fn   = monitor;
492
493	s->ctx = ctx;
494	s->r   = *r;
495	ZERO_STRUCT(s->r.out);
496
497
498	/* proceed to pure rpc connection if the binding string is provided,
499	   otherwise try to connect domain controller */
500	if (r->in.binding == NULL) {
501		/* Pass on any binding flags (such as anonymous fallback) that have been set */
502		s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
503
504		s->rpc_conn.in.name         = r->in.name;
505		s->rpc_conn.level           = LIBNET_RPC_CONNECT_DC;
506	} else {
507		s->rpc_conn.in.binding      = r->in.binding;
508		s->rpc_conn.level           = LIBNET_RPC_CONNECT_BINDING;
509	}
510
511	/* we need to query information on lsarpc interface first */
512	s->rpc_conn.in.dcerpc_iface    = &ndr_table_lsarpc;
513
514	/* request connection to the lsa pipe on the pdc */
515	conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
516	if (composite_nomem(c, conn_req)) return c;
517
518	composite_continue(c, conn_req, continue_dci_rpc_connect, c);
519	return c;
520}
521
522
523/*
524  Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
525  lsa policy handle
526*/
527static void continue_dci_rpc_connect(struct composite_context *ctx)
528{
529	struct composite_context *c;
530	struct rpc_connect_dci_state *s;
531	struct rpc_request *open_pol_req;
532
533	c = talloc_get_type(ctx->async.private_data, struct composite_context);
534	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
535
536	c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn);
537	if (!NT_STATUS_IS_OK(c->status)) {
538		composite_error(c, c->status);
539		return;
540	}
541
542	/* post monitor message */
543	if (s->monitor_fn) {
544		struct monitor_msg msg;
545		struct msg_net_rpc_connect data;
546		struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
547
548		data.host        = binding->host;
549		data.endpoint    = binding->endpoint;
550		data.transport   = binding->transport;
551		data.domain_name = binding->target_hostname;
552
553		msg.type      = mon_NetRpcConnect;
554		msg.data      = (void*)&data;
555		msg.data_size = sizeof(data);
556		s->monitor_fn(&msg);
557	}
558
559	/* prepare to open a policy handle on lsa pipe */
560	s->lsa_pipe = s->ctx->lsa.pipe;
561
562	s->qos.len                 = 0;
563	s->qos.impersonation_level = 2;
564	s->qos.context_mode        = 1;
565	s->qos.effective_only      = 0;
566
567	s->attr.sec_qos = &s->qos;
568
569	s->lsa_open_policy.in.attr        = &s->attr;
570	s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\");
571	if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return;
572
573	s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
574	s->lsa_open_policy.out.handle     = &s->lsa_handle;
575
576	open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy);
577	if (composite_nomem(open_pol_req, c)) return;
578
579	composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c);
580}
581
582
583/*
584  Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
585  for kerberos realm (dns name) and guid. The query may fail.
586*/
587static void continue_lsa_policy(struct rpc_request *req)
588{
589	struct composite_context *c;
590	struct rpc_connect_dci_state *s;
591	struct rpc_request *query_info_req;
592
593	c = talloc_get_type(req->async.private_data, struct composite_context);
594	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
595
596	c->status = dcerpc_ndr_request_recv(req);
597	if (!NT_STATUS_IS_OK(c->status)) {
598		composite_error(c, c->status);
599		return;
600	}
601
602	if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
603		s->r.out.realm = NULL;
604		s->r.out.guid  = NULL;
605		s->r.out.domain_name = NULL;
606		s->r.out.domain_sid  = NULL;
607
608		/* Skip to the creating the actual connection, no info available on this transport */
609		continue_epm_map_binding_send(c);
610		return;
611
612	} else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
613		composite_error(c, s->lsa_open_policy.out.result);
614		return;
615	}
616
617	/* post monitor message */
618	if (s->monitor_fn) {
619		struct monitor_msg msg;
620
621		msg.type      = mon_LsaOpenPolicy;
622		msg.data      = NULL;
623		msg.data_size = 0;
624		s->monitor_fn(&msg);
625	}
626
627	/* query lsa info for dns domain name and guid */
628	s->lsa_query_info2.in.handle = &s->lsa_handle;
629	s->lsa_query_info2.in.level  = LSA_POLICY_INFO_DNS;
630	s->lsa_query_info2.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
631	if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
632
633	query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2);
634	if (composite_nomem(query_info_req, c)) return;
635
636	composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c);
637}
638
639
640/*
641  Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
642  may result in failure) and query lsa info for domain name and sid.
643*/
644static void continue_lsa_query_info2(struct rpc_request *req)
645{
646	struct composite_context *c;
647	struct rpc_connect_dci_state *s;
648	struct rpc_request *query_info_req;
649
650	c = talloc_get_type(req->async.private_data, struct composite_context);
651	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
652
653	c->status = dcerpc_ndr_request_recv(req);
654
655	/* In case of error just null the realm and guid and proceed
656	   to the next step. After all, it doesn't have to be AD domain
657	   controller we talking to - NT-style PDC also counts */
658
659	if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) {
660		s->r.out.realm = NULL;
661		s->r.out.guid  = NULL;
662
663	} else {
664		if (!NT_STATUS_IS_OK(c->status)) {
665			s->r.out.error_string = talloc_asprintf(c,
666								"lsa_QueryInfoPolicy2 failed: %s",
667								nt_errstr(c->status));
668			composite_error(c, c->status);
669			return;
670		}
671
672		if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) {
673			s->r.out.error_string = talloc_asprintf(c,
674								"lsa_QueryInfoPolicy2 failed: %s",
675								nt_errstr(s->lsa_query_info2.out.result));
676			composite_error(c, s->lsa_query_info2.out.result);
677			return;
678		}
679
680		/* Copy the dns domain name and guid from the query result */
681
682		/* this should actually be a conversion from lsa_StringLarge */
683		s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
684		s->r.out.guid  = talloc(c, struct GUID);
685		if (composite_nomem(s->r.out.guid, c)) {
686			s->r.out.error_string = NULL;
687			return;
688		}
689		*s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
690	}
691
692	/* post monitor message */
693	if (s->monitor_fn) {
694		struct monitor_msg msg;
695
696		msg.type      = mon_LsaQueryPolicy;
697		msg.data      = NULL;
698		msg.data_size = 0;
699		s->monitor_fn(&msg);
700	}
701
702	/* query lsa info for domain name and sid */
703	s->lsa_query_info.in.handle = &s->lsa_handle;
704	s->lsa_query_info.in.level  = LSA_POLICY_INFO_DOMAIN;
705	s->lsa_query_info.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
706	if (composite_nomem(s->lsa_query_info.out.info, c)) return;
707
708	query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info);
709	if (composite_nomem(query_info_req, c)) return;
710
711	composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c);
712}
713
714
715/*
716  Step 5 of RpcConnectDCInfo: Get domain name and sid
717*/
718static void continue_lsa_query_info(struct rpc_request *req)
719{
720	struct composite_context *c;
721	struct rpc_connect_dci_state *s;
722
723	c = talloc_get_type(req->async.private_data, struct composite_context);
724	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
725
726	c->status = dcerpc_ndr_request_recv(req);
727	if (!NT_STATUS_IS_OK(c->status)) {
728		s->r.out.error_string = talloc_asprintf(c,
729							"lsa_QueryInfoPolicy failed: %s",
730							nt_errstr(c->status));
731		composite_error(c, c->status);
732		return;
733	}
734
735	/* post monitor message */
736	if (s->monitor_fn) {
737		struct monitor_msg msg;
738
739		msg.type      = mon_LsaQueryPolicy;
740		msg.data      = NULL;
741		msg.data_size = 0;
742		s->monitor_fn(&msg);
743	}
744
745	/* Copy the domain name and sid from the query result */
746	s->r.out.domain_sid  = (*s->lsa_query_info.out.info)->domain.sid;
747	s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
748
749	continue_epm_map_binding_send(c);
750}
751
752/*
753   Step 5 (continued) of RpcConnectDCInfo: request endpoint
754   map binding.
755
756   We may short-cut to this step if we don't support LSA OpenPolicy on this transport
757*/
758static void continue_epm_map_binding_send(struct composite_context *c)
759{
760	struct rpc_connect_dci_state *s;
761	struct composite_context *epm_map_req;
762	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
763
764	/* prepare to get endpoint mapping for the requested interface */
765	s->final_binding = talloc(s, struct dcerpc_binding);
766	if (composite_nomem(s->final_binding, c)) return;
767
768	*s->final_binding = *s->lsa_pipe->binding;
769	/* Ensure we keep hold of the member elements */
770	if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
771
772	epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
773						  s->lsa_pipe->conn->event_ctx, s->ctx->lp_ctx);
774	if (composite_nomem(epm_map_req, c)) return;
775
776	composite_continue(c, epm_map_req, continue_epm_map_binding, c);
777}
778
779/*
780  Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
781  rpc connection derived from already used pipe but connected to the requested
782  one (as specified in libnet_RpcConnect structure)
783*/
784static void continue_epm_map_binding(struct composite_context *ctx)
785{
786	struct composite_context *c, *sec_conn_req;
787	struct rpc_connect_dci_state *s;
788
789	c = talloc_get_type(ctx->async.private_data, struct composite_context);
790	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
791
792	c->status = dcerpc_epm_map_binding_recv(ctx);
793	if (!NT_STATUS_IS_OK(c->status)) {
794		s->r.out.error_string = talloc_asprintf(c,
795							"failed to map pipe with endpoint mapper - %s",
796							nt_errstr(c->status));
797		composite_error(c, c->status);
798		return;
799	}
800
801	/* create secondary connection derived from lsa pipe */
802	sec_conn_req = dcerpc_secondary_connection_send(s->lsa_pipe, s->final_binding);
803	if (composite_nomem(sec_conn_req, c)) return;
804
805	composite_continue(c, sec_conn_req, continue_secondary_conn, c);
806}
807
808
809/*
810  Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
811  and complete this composite call
812*/
813static void continue_secondary_conn(struct composite_context *ctx)
814{
815	struct composite_context *c;
816	struct rpc_connect_dci_state *s;
817
818	c = talloc_get_type(ctx->async.private_data, struct composite_context);
819	s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
820
821	c->status = dcerpc_secondary_connection_recv(ctx, &s->final_pipe);
822	if (!NT_STATUS_IS_OK(c->status)) {
823		s->r.out.error_string = talloc_asprintf(c,
824							"secondary connection failed: %s",
825							nt_errstr(c->status));
826
827		composite_error(c, c->status);
828		return;
829	}
830
831	s->r.out.dcerpc_pipe = s->final_pipe;
832
833	/* post monitor message */
834	if (s->monitor_fn) {
835		struct monitor_msg msg;
836		struct msg_net_rpc_connect data;
837		struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
838
839		/* prepare monitor message and post it */
840		data.host        = binding->host;
841		data.endpoint    = binding->endpoint;
842		data.transport   = binding->transport;
843		data.domain_name = binding->target_hostname;
844
845		msg.type      = mon_NetRpcConnect;
846		msg.data      = (void*)&data;
847		msg.data_size = sizeof(data);
848		s->monitor_fn(&msg);
849	}
850
851	composite_done(c);
852}
853
854
855/**
856 * Receives result of connection to rpc pipe and gets basic
857 * domain info (name, sid, realm, guid)
858 *
859 * @param c composite context
860 * @param ctx initialised libnet context
861 * @param mem_ctx memory context of this call
862 * @param r data structure containing return values
863 * @return nt status of rpc connection
864 **/
865
866static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx,
867					     TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
868{
869	NTSTATUS status;
870	struct rpc_connect_dci_state *s = talloc_get_type(c->private_data,
871					  struct rpc_connect_dci_state);
872
873	status = composite_wait(c);
874	if (NT_STATUS_IS_OK(status)) {
875		r->out.realm        = talloc_steal(mem_ctx, s->r.out.realm);
876		r->out.guid         = talloc_steal(mem_ctx, s->r.out.guid);
877		r->out.domain_name  = talloc_steal(mem_ctx, s->r.out.domain_name);
878		r->out.domain_sid   = talloc_steal(mem_ctx, s->r.out.domain_sid);
879
880		r->out.dcerpc_pipe  = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
881
882		/* reference created pipe structure to long-term libnet_context
883		   so that it can be used by other api functions even after short-term
884		   mem_ctx is freed */
885		if (r->in.dcerpc_iface == &ndr_table_samr) {
886			ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
887
888		} else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
889			ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
890		}
891
892	} else {
893		if (s->r.out.error_string) {
894			r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
895		} else if (r->in.binding == NULL) {
896			r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
897		} else {
898			r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s",
899							      r->in.binding, nt_errstr(status));
900		}
901	}
902
903	talloc_free(c);
904	return status;
905}
906
907
908/**
909 * Initiates connection to rpc pipe on remote server or pdc, optionally
910 * providing domain info
911 *
912 * @param ctx initialised libnet context
913 * @param mem_ctx memory context of this call
914 * @param r data structure containing necessary parameters and return values
915 * @return composite context of this call
916 **/
917
918struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
919						 TALLOC_CTX *mem_ctx,
920						 struct libnet_RpcConnect *r,
921						 void (*monitor)(struct monitor_msg*))
922{
923	struct composite_context *c;
924
925	switch (r->level) {
926	case LIBNET_RPC_CONNECT_SERVER:
927	case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
928	case LIBNET_RPC_CONNECT_BINDING:
929		c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
930		break;
931
932	case LIBNET_RPC_CONNECT_PDC:
933	case LIBNET_RPC_CONNECT_DC:
934		c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
935		break;
936
937	case LIBNET_RPC_CONNECT_DC_INFO:
938		c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
939		break;
940
941	default:
942		c = talloc_zero(mem_ctx, struct composite_context);
943		composite_error(c, NT_STATUS_INVALID_LEVEL);
944	}
945
946	return c;
947}
948
949
950/**
951 * Receives result of connection to rpc pipe on remote server or pdc
952 *
953 * @param c composite context
954 * @param ctx initialised libnet context
955 * @param mem_ctx memory context of this call
956 * @param r data structure containing necessary parameters and return values
957 * @return nt status of rpc connection
958 **/
959
960NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx,
961				TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
962{
963	switch (r->level) {
964	case LIBNET_RPC_CONNECT_SERVER:
965	case LIBNET_RPC_CONNECT_BINDING:
966		return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r);
967
968	case LIBNET_RPC_CONNECT_PDC:
969	case LIBNET_RPC_CONNECT_DC:
970		return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r);
971
972	case LIBNET_RPC_CONNECT_DC_INFO:
973		return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r);
974
975	default:
976		ZERO_STRUCT(r->out);
977		return NT_STATUS_INVALID_LEVEL;
978	}
979}
980
981
982/**
983 * Connect to a rpc pipe on a remote server - sync version
984 *
985 * @param ctx initialised libnet context
986 * @param mem_ctx memory context of this call
987 * @param r data structure containing necessary parameters and return values
988 * @return nt status of rpc connection
989 **/
990
991NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
992			   struct libnet_RpcConnect *r)
993{
994	struct composite_context *c;
995
996	c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
997	return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);
998}
999