2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2004
5 Copyright (C) Rafal Szczesniak 2005
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 "libnet/libnet.h"
23 #include "libcli/libcli.h"
24 #include "libcli/composite/composite.h"
25 #include "librpc/rpc/dcerpc.h"
26 #include "librpc/gen_ndr/ndr_lsa_c.h"
27 #include "librpc/gen_ndr/ndr_samr.h"
30 struct rpc_connect_srv_state {
31 struct libnet_context *ctx;
32 struct libnet_RpcConnect r;
35 /* information about the progress */
36 void (*monitor_fn)(struct monitor_msg*);
40 static void continue_pipe_connect(struct composite_context *ctx);
44 * Initiates connection to rpc pipe on remote server
46 * @param ctx initialised libnet context
47 * @param mem_ctx memory context of this call
48 * @param r data structure containing necessary parameters and return values
49 * @return composite context of this call
52 static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx,
54 struct libnet_RpcConnect *r,
55 void (*monitor)(struct monitor_msg*))
57 struct composite_context *c;
58 struct rpc_connect_srv_state *s;
59 struct dcerpc_binding *b;
60 struct composite_context *pipe_connect_req;
62 /* composite context allocation and setup */
63 c = composite_create(ctx, ctx->event_ctx);
64 if (c == NULL) return c;
66 s = talloc_zero(c, struct rpc_connect_srv_state);
67 if (composite_nomem(s, c)) return c;
70 s->monitor_fn = monitor;
74 ZERO_STRUCT(s->r.out);
76 /* prepare binding string */
78 case LIBNET_RPC_CONNECT_SERVER:
79 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
81 case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
82 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address);
85 case LIBNET_RPC_CONNECT_BINDING:
86 s->binding = talloc_strdup(s, r->in.binding);
89 case LIBNET_RPC_CONNECT_DC:
90 case LIBNET_RPC_CONNECT_PDC:
91 /* this should never happen - DC and PDC level has a separate
93 case LIBNET_RPC_CONNECT_DC_INFO:
94 /* this should never happen - DC_INFO level has a separate
96 composite_error(c, NT_STATUS_INVALID_LEVEL);
100 /* parse binding string to the structure */
101 c->status = dcerpc_parse_binding(c, s->binding, &b);
102 if (!NT_STATUS_IS_OK(c->status)) {
103 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding));
104 composite_error(c, c->status);
108 if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
109 b->target_hostname = talloc_reference(b, r->in.name);
110 if (composite_nomem(b->target_hostname, c)) {
115 /* connect to remote dcerpc pipe */
116 pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
117 ctx->cred, c->event_ctx);
118 if (composite_nomem(pipe_connect_req, c)) return c;
120 composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
126 Step 2 of RpcConnectSrv - get rpc connection
128 static void continue_pipe_connect(struct composite_context *ctx)
130 struct composite_context *c;
131 struct rpc_connect_srv_state *s;
133 c = talloc_get_type(ctx->async.private_data, struct composite_context);
134 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
136 /* receive result of rpc pipe connection */
137 c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
139 /* post monitor message */
141 struct monitor_msg msg;
142 struct msg_net_rpc_connect data;
143 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
145 /* prepare monitor message and post it */
146 data.host = binding->host;
147 data.endpoint = binding->endpoint;
148 data.transport = binding->transport;
149 data.domain_name = binding->target_hostname;
151 msg.type = mon_NetRpcConnect;
152 msg.data = (void*)&data;
153 msg.data_size = sizeof(data);
162 * Receives result of connection to rpc pipe on remote server
164 * @param c composite context
165 * @param ctx initialised libnet context
166 * @param mem_ctx memory context of this call
167 * @param r data structure containing necessary parameters and return values
168 * @return nt status of rpc connection
171 static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
172 struct libnet_context *ctx,
174 struct libnet_RpcConnect *r)
177 struct rpc_connect_srv_state *s = talloc_get_type(c->private_data,
178 struct rpc_connect_srv_state);
180 status = composite_wait(c);
181 if (NT_STATUS_IS_OK(status)) {
182 /* move the returned rpc pipe between memory contexts */
183 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
184 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
186 /* reference created pipe structure to long-term libnet_context
187 so that it can be used by other api functions even after short-term
189 if (r->in.dcerpc_iface == &ndr_table_samr) {
190 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
192 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
193 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
196 r->out.error_string = talloc_strdup(mem_ctx, "Success");
199 r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
207 struct rpc_connect_dc_state {
208 struct libnet_context *ctx;
209 struct libnet_RpcConnect r;
210 struct libnet_RpcConnect r2;
211 struct libnet_LookupDCs f;
212 const char *connect_name;
214 /* information about the progress */
215 void (*monitor_fn)(struct monitor_msg *);
219 static void continue_lookup_dc(struct composite_context *ctx);
220 static void continue_rpc_connect(struct composite_context *ctx);
224 * Initiates connection to rpc pipe on domain pdc
226 * @param ctx initialised libnet context
227 * @param mem_ctx memory context of this call
228 * @param r data structure containing necessary parameters and return values
229 * @return composite context of this call
232 static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
234 struct libnet_RpcConnect *r,
235 void (*monitor)(struct monitor_msg *msg))
237 struct composite_context *c;
238 struct rpc_connect_dc_state *s;
239 struct composite_context *lookup_dc_req;
241 /* composite context allocation and setup */
242 c = composite_create(ctx, ctx->event_ctx);
243 if (c == NULL) return c;
245 s = talloc_zero(c, struct rpc_connect_dc_state);
246 if (composite_nomem(s, c)) return c;
249 s->monitor_fn = monitor;
253 ZERO_STRUCT(s->r.out);
256 case LIBNET_RPC_CONNECT_PDC:
257 s->f.in.name_type = NBT_NAME_PDC;
260 case LIBNET_RPC_CONNECT_DC:
261 s->f.in.name_type = NBT_NAME_LOGON;
268 s->f.in.domain_name = r->in.name;
269 s->f.out.num_dcs = 0;
272 /* find the domain pdc first */
273 lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
274 if (composite_nomem(lookup_dc_req, c)) return c;
276 composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
282 Step 2 of RpcConnectDC: get domain controller name and
283 initiate RpcConnect to it
285 static void continue_lookup_dc(struct composite_context *ctx)
287 struct composite_context *c;
288 struct rpc_connect_dc_state *s;
289 struct composite_context *rpc_connect_req;
290 struct monitor_msg msg;
291 struct msg_net_lookup_dc data;
293 c = talloc_get_type(ctx->async.private_data, struct composite_context);
294 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
296 /* receive result of domain controller lookup */
297 c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
298 if (!composite_is_ok(c)) return;
300 /* decide on preferred address type depending on DC type */
301 s->connect_name = s->f.out.dcs[0].name;
303 /* post monitor message */
305 /* prepare a monitor message and post it */
306 data.domain_name = s->f.in.domain_name;
307 data.hostname = s->f.out.dcs[0].name;
308 data.address = s->f.out.dcs[0].address;
310 msg.type = mon_NetLookupDc;
312 msg.data_size = sizeof(data);
316 /* ok, pdc has been found so do attempt to rpc connect */
317 s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
319 /* this will cause yet another name resolution, but at least
320 * we pass the right name down the stack now */
321 s->r2.in.name = talloc_strdup(s, s->connect_name);
322 s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address);
323 s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface;
325 /* send rpc connect request to the server */
326 rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
327 if (composite_nomem(rpc_connect_req, c)) return;
329 composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
334 Step 3 of RpcConnectDC: get rpc connection to the server
336 static void continue_rpc_connect(struct composite_context *ctx)
338 struct composite_context *c;
339 struct rpc_connect_dc_state *s;
341 c = talloc_get_type(ctx->async.private_data, struct composite_context);
342 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
344 c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
346 /* error string is to be passed anyway */
347 s->r.out.error_string = s->r2.out.error_string;
348 if (!composite_is_ok(c)) return;
350 s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
352 /* post monitor message */
354 struct monitor_msg msg;
355 struct msg_net_rpc_connect data;
356 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
358 data.host = binding->host;
359 data.endpoint = binding->endpoint;
360 data.transport = binding->transport;
361 data.domain_name = binding->target_hostname;
363 msg.type = mon_NetRpcConnect;
364 msg.data = (void*)&data;
365 msg.data_size = sizeof(data);
374 * Receives result of connection to rpc pipe on domain pdc
376 * @param c composite context
377 * @param ctx initialised libnet context
378 * @param mem_ctx memory context of this call
379 * @param r data structure containing necessary parameters and return values
380 * @return nt status of rpc connection
383 static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
384 struct libnet_context *ctx,
386 struct libnet_RpcConnect *r)
389 struct rpc_connect_dc_state *s = talloc_get_type(c->private_data,
390 struct rpc_connect_dc_state);
392 status = composite_wait(c);
393 if (NT_STATUS_IS_OK(status)) {
394 /* move connected rpc pipe between memory contexts */
395 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
397 /* reference created pipe structure to long-term libnet_context
398 so that it can be used by other api functions even after short-term
400 if (r->in.dcerpc_iface == &ndr_table_samr) {
401 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
403 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
404 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
408 r->out.error_string = talloc_asprintf(mem_ctx,
409 "Failed to rpc connect: %s",
419 struct rpc_connect_dci_state {
420 struct libnet_context *ctx;
421 struct libnet_RpcConnect r;
422 struct libnet_RpcConnect rpc_conn;
423 struct policy_handle lsa_handle;
424 struct lsa_QosInfo qos;
425 struct lsa_ObjectAttribute attr;
426 struct lsa_OpenPolicy2 lsa_open_policy;
427 struct dcerpc_pipe *lsa_pipe;
428 struct lsa_QueryInfoPolicy2 lsa_query_info2;
429 struct lsa_QueryInfoPolicy lsa_query_info;
430 struct dcerpc_binding *final_binding;
431 struct dcerpc_pipe *final_pipe;
433 /* information about the progress */
434 void (*monitor_fn)(struct monitor_msg*);
438 static void continue_dci_rpc_connect(struct composite_context *ctx);
439 static void continue_lsa_policy(struct rpc_request *req);
440 static void continue_lsa_query_info(struct rpc_request *req);
441 static void continue_lsa_query_info2(struct rpc_request *req);
442 static void continue_epm_map_binding(struct composite_context *ctx);
443 static void continue_secondary_conn(struct composite_context *ctx);
444 static void continue_epm_map_binding_send(struct composite_context *c);
448 * Initiates connection to rpc pipe on remote server or pdc. Received result
449 * contains info on the domain name, domain sid and realm.
451 * @param ctx initialised libnet context
452 * @param mem_ctx memory context of this call
453 * @param r data structure containing necessary parameters and return values. Must be a talloc context
454 * @return composite context of this call
457 static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
459 struct libnet_RpcConnect *r,
460 void (*monitor)(struct monitor_msg*))
462 struct composite_context *c, *conn_req;
463 struct rpc_connect_dci_state *s;
465 /* composite context allocation and setup */
466 c = composite_create(ctx, ctx->event_ctx);
467 if (c == NULL) return c;
469 s = talloc_zero(c, struct rpc_connect_dci_state);
470 if (composite_nomem(s, c)) return c;
473 s->monitor_fn = monitor;
477 ZERO_STRUCT(s->r.out);
479 /* proceed to pure rpc connection if the binding string is provided,
480 otherwise try to connect domain controller */
481 if (r->in.binding == NULL) {
482 s->rpc_conn.in.name = r->in.name;
483 s->rpc_conn.level = LIBNET_RPC_CONNECT_DC;
485 s->rpc_conn.in.binding = r->in.binding;
486 s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
489 /* we need to query information on lsarpc interface first */
490 s->rpc_conn.in.dcerpc_iface = &ndr_table_lsarpc;
492 /* request connection to the lsa pipe on the pdc */
493 conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
494 if (composite_nomem(c, conn_req)) return c;
496 composite_continue(c, conn_req, continue_dci_rpc_connect, c);
502 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
505 static void continue_dci_rpc_connect(struct composite_context *ctx)
507 struct composite_context *c;
508 struct rpc_connect_dci_state *s;
509 struct rpc_request *open_pol_req;
511 c = talloc_get_type(ctx->async.private_data, struct composite_context);
512 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
514 c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn);
515 if (!NT_STATUS_IS_OK(c->status)) {
516 composite_error(c, c->status);
520 /* post monitor message */
522 struct monitor_msg msg;
523 struct msg_net_rpc_connect data;
524 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
526 data.host = binding->host;
527 data.endpoint = binding->endpoint;
528 data.transport = binding->transport;
529 data.domain_name = binding->target_hostname;
531 msg.type = mon_NetRpcConnect;
532 msg.data = (void*)&data;
533 msg.data_size = sizeof(data);
537 /* prepare to open a policy handle on lsa pipe */
538 s->lsa_pipe = s->ctx->lsa.pipe;
541 s->qos.impersonation_level = 2;
542 s->qos.context_mode = 1;
543 s->qos.effective_only = 0;
545 s->attr.sec_qos = &s->qos;
547 s->lsa_open_policy.in.attr = &s->attr;
548 s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\");
549 if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return;
551 s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
552 s->lsa_open_policy.out.handle = &s->lsa_handle;
554 open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy);
555 if (composite_nomem(open_pol_req, c)) return;
557 composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c);
562 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
563 for kerberos realm (dns name) and guid. The query may fail.
565 static void continue_lsa_policy(struct rpc_request *req)
567 struct composite_context *c;
568 struct rpc_connect_dci_state *s;
569 struct rpc_request *query_info_req;
571 c = talloc_get_type(req->async.private_data, struct composite_context);
572 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
574 c->status = dcerpc_ndr_request_recv(req);
575 if (!NT_STATUS_IS_OK(c->status)) {
576 composite_error(c, c->status);
580 if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
581 s->r.out.realm = NULL;
582 s->r.out.guid = NULL;
583 s->r.out.domain_name = NULL;
584 s->r.out.domain_sid = NULL;
586 /* Skip to the creating the actual connection, no info available on this transport */
587 continue_epm_map_binding_send(c);
590 } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
591 composite_error(c, s->lsa_open_policy.out.result);
595 /* post monitor message */
597 struct monitor_msg msg;
599 msg.type = mon_LsaOpenPolicy;
605 /* query lsa info for dns domain name and guid */
606 s->lsa_query_info2.in.handle = &s->lsa_handle;
607 s->lsa_query_info2.in.level = LSA_POLICY_INFO_DNS;
609 query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2);
610 if (composite_nomem(query_info_req, c)) return;
612 composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c);
617 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
618 may result in failure) and query lsa info for domain name and sid.
620 static void continue_lsa_query_info2(struct rpc_request *req)
622 struct composite_context *c;
623 struct rpc_connect_dci_state *s;
624 struct rpc_request *query_info_req;
626 c = talloc_get_type(req->async.private_data, struct composite_context);
627 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
629 c->status = dcerpc_ndr_request_recv(req);
631 /* In case of error just null the realm and guid and proceed
632 to the next step. After all, it doesn't have to be AD domain
633 controller we talking to - NT-style PDC also counts */
635 if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) {
636 s->r.out.realm = NULL;
637 s->r.out.guid = NULL;
640 if (!NT_STATUS_IS_OK(c->status)) {
641 s->r.out.error_string = talloc_asprintf(c,
642 "lsa_QueryInfoPolicy2 failed: %s",
643 nt_errstr(c->status));
644 composite_error(c, c->status);
648 if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) {
649 s->r.out.error_string = talloc_asprintf(c,
650 "lsa_QueryInfoPolicy2 failed: %s",
651 nt_errstr(s->lsa_query_info2.out.result));
652 composite_error(c, s->lsa_query_info2.out.result);
656 /* Copy the dns domain name and guid from the query result */
658 /* this should actually be a conversion from lsa_StringLarge */
659 s->r.out.realm = s->lsa_query_info2.out.info->dns.dns_domain.string;
660 s->r.out.guid = talloc(c, struct GUID);
661 if (composite_nomem(s->r.out.guid, c)) {
662 s->r.out.error_string = NULL;
665 *s->r.out.guid = s->lsa_query_info2.out.info->dns.domain_guid;
668 /* post monitor message */
670 struct monitor_msg msg;
672 msg.type = mon_LsaQueryPolicy;
678 /* query lsa info for domain name and sid */
679 s->lsa_query_info.in.handle = &s->lsa_handle;
680 s->lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN;
682 query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info);
683 if (composite_nomem(query_info_req, c)) return;
685 composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c);
690 Step 5 of RpcConnectDCInfo: Get domain name and sid
692 static void continue_lsa_query_info(struct rpc_request *req)
694 struct composite_context *c;
695 struct rpc_connect_dci_state *s;
697 c = talloc_get_type(req->async.private_data, struct composite_context);
698 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
700 c->status = dcerpc_ndr_request_recv(req);
701 if (!NT_STATUS_IS_OK(c->status)) {
702 s->r.out.error_string = talloc_asprintf(c,
703 "lsa_QueryInfoPolicy failed: %s",
704 nt_errstr(c->status));
705 composite_error(c, c->status);
709 /* post monitor message */
711 struct monitor_msg msg;
713 msg.type = mon_LsaQueryPolicy;
719 /* Copy the domain name and sid from the query result */
720 s->r.out.domain_sid = s->lsa_query_info.out.info->domain.sid;
721 s->r.out.domain_name = s->lsa_query_info.out.info->domain.name.string;
723 continue_epm_map_binding_send(c);
727 Step 5 (continued) of RpcConnectDCInfo: request endpoint
730 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
732 static void continue_epm_map_binding_send(struct composite_context *c)
734 struct rpc_connect_dci_state *s;
735 struct composite_context *epm_map_req;
736 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
738 /* prepare to get endpoint mapping for the requested interface */
739 s->final_binding = talloc(s, struct dcerpc_binding);
740 if (composite_nomem(s->final_binding, c)) return;
742 *s->final_binding = *s->lsa_pipe->binding;
743 /* Ensure we keep hold of the member elements */
744 if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
746 epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
747 s->lsa_pipe->conn->event_ctx);
748 if (composite_nomem(epm_map_req, c)) return;
750 composite_continue(c, epm_map_req, continue_epm_map_binding, c);
754 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
755 rpc connection derived from already used pipe but connected to the requested
756 one (as specified in libnet_RpcConnect structure)
758 static void continue_epm_map_binding(struct composite_context *ctx)
760 struct composite_context *c, *sec_conn_req;
761 struct rpc_connect_dci_state *s;
763 c = talloc_get_type(ctx->async.private_data, struct composite_context);
764 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
766 c->status = dcerpc_epm_map_binding_recv(ctx);
767 if (!NT_STATUS_IS_OK(c->status)) {
768 s->r.out.error_string = talloc_asprintf(c,
769 "failed to map pipe with endpoint mapper - %s",
770 nt_errstr(c->status));
771 composite_error(c, c->status);
775 /* create secondary connection derived from lsa pipe */
776 sec_conn_req = dcerpc_secondary_connection_send(s->lsa_pipe, s->final_binding);
777 if (composite_nomem(sec_conn_req, c)) return;
779 composite_continue(c, sec_conn_req, continue_secondary_conn, c);
784 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
785 and complete this composite call
787 static void continue_secondary_conn(struct composite_context *ctx)
789 struct composite_context *c;
790 struct rpc_connect_dci_state *s;
792 c = talloc_get_type(ctx->async.private_data, struct composite_context);
793 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
795 c->status = dcerpc_secondary_connection_recv(ctx, &s->final_pipe);
796 if (!NT_STATUS_IS_OK(c->status)) {
797 s->r.out.error_string = talloc_asprintf(c,
798 "secondary connection failed: %s",
799 nt_errstr(c->status));
801 composite_error(c, c->status);
805 s->r.out.dcerpc_pipe = s->final_pipe;
807 /* post monitor message */
809 struct monitor_msg msg;
810 struct msg_net_rpc_connect data;
811 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
813 /* prepare monitor message and post it */
814 data.host = binding->host;
815 data.endpoint = binding->endpoint;
816 data.transport = binding->transport;
817 data.domain_name = binding->target_hostname;
819 msg.type = mon_NetRpcConnect;
820 msg.data = (void*)&data;
821 msg.data_size = sizeof(data);
830 * Receives result of connection to rpc pipe and gets basic
831 * domain info (name, sid, realm, guid)
833 * @param c composite context
834 * @param ctx initialised libnet context
835 * @param mem_ctx memory context of this call
836 * @param r data structure containing return values
837 * @return nt status of rpc connection
840 static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx,
841 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
844 struct rpc_connect_dci_state *s = talloc_get_type(c->private_data,
845 struct rpc_connect_dci_state);
847 status = composite_wait(c);
848 if (NT_STATUS_IS_OK(status)) {
849 r->out.realm = talloc_steal(mem_ctx, s->r.out.realm);
850 r->out.guid = talloc_steal(mem_ctx, s->r.out.guid);
851 r->out.domain_name = talloc_steal(mem_ctx, s->r.out.domain_name);
852 r->out.domain_sid = talloc_steal(mem_ctx, s->r.out.domain_sid);
854 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
856 /* reference created pipe structure to long-term libnet_context
857 so that it can be used by other api functions even after short-term
859 if (r->in.dcerpc_iface == &ndr_table_samr) {
860 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
862 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
863 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
867 if (s->r.out.error_string) {
868 r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
870 r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
880 * Initiates connection to rpc pipe on remote server or pdc, optionally
881 * providing domain info
883 * @param ctx initialised libnet context
884 * @param mem_ctx memory context of this call
885 * @param r data structure containing necessary parameters and return values
886 * @return composite context of this call
889 struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
891 struct libnet_RpcConnect *r,
892 void (*monitor)(struct monitor_msg*))
894 struct composite_context *c;
897 case LIBNET_RPC_CONNECT_SERVER:
898 case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
899 case LIBNET_RPC_CONNECT_BINDING:
900 c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
903 case LIBNET_RPC_CONNECT_PDC:
904 case LIBNET_RPC_CONNECT_DC:
905 c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
908 case LIBNET_RPC_CONNECT_DC_INFO:
909 c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
913 c = talloc_zero(mem_ctx, struct composite_context);
914 composite_error(c, NT_STATUS_INVALID_LEVEL);
922 * Receives result of connection to rpc pipe on remote server or pdc
924 * @param c composite context
925 * @param ctx initialised libnet context
926 * @param mem_ctx memory context of this call
927 * @param r data structure containing necessary parameters and return values
928 * @return nt status of rpc connection
931 NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx,
932 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
935 case LIBNET_RPC_CONNECT_SERVER:
936 case LIBNET_RPC_CONNECT_BINDING:
937 return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r);
939 case LIBNET_RPC_CONNECT_PDC:
940 case LIBNET_RPC_CONNECT_DC:
941 return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r);
943 case LIBNET_RPC_CONNECT_DC_INFO:
944 return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r);
948 return NT_STATUS_INVALID_LEVEL;
954 * Connect to a rpc pipe on a remote server - sync version
956 * @param ctx initialised libnet context
957 * @param mem_ctx memory context of this call
958 * @param r data structure containing necessary parameters and return values
959 * @return nt status of rpc connection
962 NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
963 struct libnet_RpcConnect *r)
965 struct composite_context *c;
967 c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
968 return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);