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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "libnet/libnet.h"
24 #include "libcli/libcli.h"
25 #include "libcli/composite/composite.h"
26 #include "librpc/rpc/dcerpc.h"
27 #include "librpc/gen_ndr/ndr_lsa_c.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
31 struct rpc_connect_srv_state
{
32 struct libnet_context
*ctx
;
33 struct libnet_RpcConnect r
;
38 static void continue_pipe_connect(struct composite_context
*ctx
);
42 * Initiates connection to rpc pipe on remote server
44 * @param ctx initialised libnet context
45 * @param mem_ctx memory context of this call
46 * @param r data structure containing necessary parameters and return values
47 * @return composite context of this call
50 static struct composite_context
* libnet_RpcConnectSrv_send(struct libnet_context
*ctx
,
52 struct libnet_RpcConnect
*r
)
54 struct composite_context
*c
;
55 struct rpc_connect_srv_state
*s
;
56 struct dcerpc_binding
*b
;
57 struct composite_context
*pipe_connect_req
;
59 /* composite context allocation and setup */
60 c
= talloc_zero(mem_ctx
, struct composite_context
);
61 if (c
== NULL
) return NULL
;
63 s
= talloc_zero(c
, struct rpc_connect_srv_state
);
64 if (composite_nomem(s
, c
)) return c
;
66 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
68 c
->event_ctx
= ctx
->event_ctx
;
72 ZERO_STRUCT(s
->r
.out
);
74 /* prepare binding string */
76 case LIBNET_RPC_CONNECT_SERVER
:
77 s
->binding
= talloc_asprintf(s
, "ncacn_np:%s", r
->in
.name
);
79 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
80 s
->binding
= talloc_asprintf(s
, "ncacn_np:%s", r
->in
.address
);
83 case LIBNET_RPC_CONNECT_BINDING
:
84 s
->binding
= talloc_strdup(s
, r
->in
.binding
);
87 case LIBNET_RPC_CONNECT_DC
:
88 case LIBNET_RPC_CONNECT_PDC
:
89 /* this should never happen - DC and PDC level has a separate
91 case LIBNET_RPC_CONNECT_DC_INFO
:
92 /* this should never happen - DC_INFO level has a separate
94 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
98 /* parse binding string to the structure */
99 c
->status
= dcerpc_parse_binding(c
, s
->binding
, &b
);
100 if (!NT_STATUS_IS_OK(c
->status
)) {
101 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s
->binding
));
102 composite_error(c
, c
->status
);
106 if (r
->level
== LIBNET_RPC_CONNECT_SERVER_ADDRESS
) {
107 b
->target_hostname
= talloc_reference(b
, r
->in
.name
);
108 if (composite_nomem(b
->target_hostname
, c
)) {
113 /* connect to remote dcerpc pipe */
114 pipe_connect_req
= dcerpc_pipe_connect_b_send(c
, b
, r
->in
.dcerpc_iface
,
115 ctx
->cred
, c
->event_ctx
);
116 if (composite_nomem(pipe_connect_req
, c
)) return c
;
118 composite_continue(c
, pipe_connect_req
, continue_pipe_connect
, c
);
124 Step 2 of RpcConnectSrv - get rpc connection
126 static void continue_pipe_connect(struct composite_context
*ctx
)
128 struct composite_context
*c
;
129 struct rpc_connect_srv_state
*s
;
131 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
132 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
134 /* receive result of rpc pipe connection */
135 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->r
.out
.dcerpc_pipe
);
142 * Receives result of connection to rpc pipe on remote server
144 * @param c composite context
145 * @param ctx initialised libnet context
146 * @param mem_ctx memory context of this call
147 * @param r data structure containing necessary parameters and return values
148 * @return nt status of rpc connection
151 static NTSTATUS
libnet_RpcConnectSrv_recv(struct composite_context
*c
,
152 struct libnet_context
*ctx
,
154 struct libnet_RpcConnect
*r
)
157 struct rpc_connect_srv_state
*s
= talloc_get_type(c
->private_data
,
158 struct rpc_connect_srv_state
);
160 status
= composite_wait(c
);
161 if (NT_STATUS_IS_OK(status
)) {
162 /* move the returned rpc pipe between memory contexts */
163 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
164 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
166 /* reference created pipe structure to long-term libnet_context
167 so that it can be used by other api functions even after short-term
169 if (r
->in
.dcerpc_iface
== &dcerpc_table_samr
) {
170 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
172 } else if (r
->in
.dcerpc_iface
== &dcerpc_table_lsarpc
) {
173 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
176 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
179 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
187 struct rpc_connect_dc_state
{
188 struct libnet_context
*ctx
;
189 struct libnet_RpcConnect r
;
190 struct libnet_RpcConnect r2
;
191 struct libnet_LookupDCs f
;
192 const char *connect_name
;
194 /* information about the progress */
195 void (*monitor_fn
)(struct monitor_msg
*);
199 static void continue_lookup_dc(struct composite_context
*ctx
);
200 static void continue_rpc_connect(struct composite_context
*ctx
);
204 * Initiates connection to rpc pipe on domain pdc
206 * @param ctx initialised libnet context
207 * @param mem_ctx memory context of this call
208 * @param r data structure containing necessary parameters and return values
209 * @return composite context of this call
212 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
214 struct libnet_RpcConnect
*r
)
216 struct composite_context
*c
;
217 struct rpc_connect_dc_state
*s
;
218 struct composite_context
*lookup_dc_req
;
220 /* composite context allocation and setup */
221 c
= talloc_zero(mem_ctx
, struct composite_context
);
222 if (c
== NULL
) return NULL
;
224 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
225 if (composite_nomem(s
, c
)) return c
;
227 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
229 c
->event_ctx
= ctx
->event_ctx
;
233 ZERO_STRUCT(s
->r
.out
);
236 case LIBNET_RPC_CONNECT_PDC
:
237 s
->f
.in
.name_type
= NBT_NAME_PDC
;
240 case LIBNET_RPC_CONNECT_DC
:
241 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
248 s
->f
.in
.domain_name
= r
->in
.name
;
249 s
->f
.out
.num_dcs
= 0;
252 /* find the domain pdc first */
253 lookup_dc_req
= libnet_LookupDCs_send(ctx
, c
, &s
->f
);
254 if (composite_nomem(lookup_dc_req
, c
)) return c
;
256 composite_continue(c
, lookup_dc_req
, continue_lookup_dc
, c
);
262 Step 2 of RpcConnectDC: get domain controller name and
263 initiate RpcConnect to it
265 static void continue_lookup_dc(struct composite_context
*ctx
)
267 struct composite_context
*c
;
268 struct rpc_connect_dc_state
*s
;
269 struct composite_context
*rpc_connect_req
;
270 struct monitor_msg msg
;
271 struct msg_net_lookup_dc data
;
273 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
274 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
276 /* receive result of domain controller lookup */
277 c
->status
= libnet_LookupDCs_recv(ctx
, c
, &s
->f
);
278 if (!composite_is_ok(c
)) return;
280 /* decide on preferred address type depending on DC type */
281 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
283 /* prepare a monitor message and post it */
284 msg
.type
= net_lookup_dc
;
286 msg
.data_size
= sizeof(data
);
288 data
.domain_name
= s
->f
.in
.domain_name
;
289 data
.hostname
= s
->f
.out
.dcs
[0].name
;
290 data
.address
= s
->f
.out
.dcs
[0].address
;
292 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
294 /* ok, pdc has been found so do attempt to rpc connect */
295 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
297 /* this will cause yet another name resolution, but at least
298 * we pass the right name down the stack now */
299 s
->r2
.in
.name
= talloc_strdup(s
, s
->connect_name
);
300 s
->r2
.in
.address
= talloc_steal(s
, s
->f
.out
.dcs
[0].address
);
301 s
->r2
.in
.dcerpc_iface
= s
->r
.in
.dcerpc_iface
;
303 /* send rpc connect request to the server */
304 rpc_connect_req
= libnet_RpcConnectSrv_send(s
->ctx
, c
, &s
->r2
);
305 if (composite_nomem(rpc_connect_req
, c
)) return;
307 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
312 Step 3 of RpcConnectDC: get rpc connection to the server
314 static void continue_rpc_connect(struct composite_context
*ctx
)
316 struct composite_context
*c
;
317 struct rpc_connect_dc_state
*s
;
318 struct monitor_msg msg
;
319 struct msg_net_pipe_connected data
;
321 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
322 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
324 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
326 /* error string is to be passed anyway */
327 s
->r
.out
.error_string
= s
->r2
.out
.error_string
;
328 if (!composite_is_ok(c
)) return;
330 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
332 /* prepare a monitor message and post it */
333 msg
.type
= net_pipe_connected
;
337 data
.host
= s
->r
.out
.dcerpc_pipe
->binding
->host
;
338 data
.endpoint
= s
->r
.out
.dcerpc_pipe
->binding
->endpoint
;
339 data
.transport
= s
->r
.out
.dcerpc_pipe
->binding
->transport
;
341 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
348 * Receives result of connection to rpc pipe on domain pdc
350 * @param c composite context
351 * @param ctx initialised libnet context
352 * @param mem_ctx memory context of this call
353 * @param r data structure containing necessary parameters and return values
354 * @return nt status of rpc connection
357 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
358 struct libnet_context
*ctx
,
360 struct libnet_RpcConnect
*r
)
363 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
364 struct rpc_connect_dc_state
);
366 status
= composite_wait(c
);
367 if (NT_STATUS_IS_OK(status
)) {
368 /* move connected rpc pipe between memory contexts */
369 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
371 /* reference created pipe structure to long-term libnet_context
372 so that it can be used by other api functions even after short-term
374 if (r
->in
.dcerpc_iface
== &dcerpc_table_samr
) {
375 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
377 } else if (r
->in
.dcerpc_iface
== &dcerpc_table_lsarpc
) {
378 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
382 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
383 "Failed to rpc connect: %s",
393 struct rpc_connect_dci_state
{
394 struct libnet_context
*ctx
;
395 struct libnet_RpcConnect r
;
396 struct libnet_RpcConnect rpc_conn
;
397 struct policy_handle lsa_handle
;
398 struct lsa_QosInfo qos
;
399 struct lsa_ObjectAttribute attr
;
400 struct lsa_OpenPolicy2 lsa_open_policy
;
401 struct dcerpc_pipe
*lsa_pipe
;
402 struct lsa_QueryInfoPolicy2 lsa_query_info2
;
403 struct lsa_QueryInfoPolicy lsa_query_info
;
404 struct dcerpc_binding
*final_binding
;
405 struct dcerpc_pipe
*final_pipe
;
409 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
410 static void continue_lsa_policy(struct rpc_request
*req
);
411 static void continue_lsa_query_info(struct rpc_request
*req
);
412 static void continue_lsa_query_info2(struct rpc_request
*req
);
413 static void continue_epm_map_binding(struct composite_context
*ctx
);
414 static void continue_secondary_conn(struct composite_context
*ctx
);
415 static void continue_epm_map_binding_send(struct composite_context
*c
);
419 * Initiates connection to rpc pipe on remote server or pdc. Received result
420 * contains info on the domain name, domain sid and realm.
422 * @param ctx initialised libnet context
423 * @param mem_ctx memory context of this call
424 * @param r data structure containing necessary parameters and return values. Must be a talloc context
425 * @return composite context of this call
428 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
430 struct libnet_RpcConnect
*r
)
432 struct composite_context
*c
, *conn_req
;
433 struct rpc_connect_dci_state
*s
;
435 /* composite context allocation and setup */
436 c
= talloc_zero(mem_ctx
, struct composite_context
);
437 if (c
== NULL
) return NULL
;
439 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
440 if (composite_nomem(s
, c
)) return c
;
442 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
444 c
->event_ctx
= ctx
->event_ctx
;
448 ZERO_STRUCT(s
->r
.out
);
450 /* proceed to pure rpc connection if the binding string is provided,
451 otherwise try to connect domain controller */
452 if (r
->in
.binding
== NULL
) {
453 s
->rpc_conn
.in
.name
= r
->in
.name
;
454 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
456 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
457 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
460 /* we need to query information on lsarpc interface first */
461 s
->rpc_conn
.in
.dcerpc_iface
= &dcerpc_table_lsarpc
;
463 /* request connection to the lsa pipe on the pdc */
464 conn_req
= libnet_RpcConnect_send(ctx
, c
, &s
->rpc_conn
);
465 if (composite_nomem(c
, conn_req
)) return c
;
467 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
473 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
476 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
478 struct composite_context
*c
;
479 struct rpc_connect_dci_state
*s
;
480 struct rpc_request
*open_pol_req
;
482 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
483 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
485 c
->status
= libnet_RpcConnect_recv(ctx
, s
->ctx
, c
, &s
->rpc_conn
);
486 if (!NT_STATUS_IS_OK(c
->status
)) {
487 composite_error(c
, c
->status
);
491 /* prepare to open a policy handle on lsa pipe */
492 s
->lsa_pipe
= s
->ctx
->lsa
.pipe
;
495 s
->qos
.impersonation_level
= 2;
496 s
->qos
.context_mode
= 1;
497 s
->qos
.effective_only
= 0;
499 s
->attr
.sec_qos
= &s
->qos
;
501 s
->lsa_open_policy
.in
.attr
= &s
->attr
;
502 s
->lsa_open_policy
.in
.system_name
= talloc_asprintf(c
, "\\");
503 if (composite_nomem(s
->lsa_open_policy
.in
.system_name
, c
)) return;
505 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
506 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
508 open_pol_req
= dcerpc_lsa_OpenPolicy2_send(s
->lsa_pipe
, c
, &s
->lsa_open_policy
);
509 if (composite_nomem(open_pol_req
, c
)) return;
511 composite_continue_rpc(c
, open_pol_req
, continue_lsa_policy
, c
);
516 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
517 for kerberos realm (dns name) and guid. The query may fail.
519 static void continue_lsa_policy(struct rpc_request
*req
)
521 struct composite_context
*c
;
522 struct rpc_connect_dci_state
*s
;
523 struct rpc_request
*query_info_req
;
525 c
= talloc_get_type(req
->async
.private, struct composite_context
);
526 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
528 c
->status
= dcerpc_ndr_request_recv(req
);
529 if (!NT_STATUS_IS_OK(c
->status
)) {
530 composite_error(c
, c
->status
);
534 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
535 s
->r
.out
.realm
= NULL
;
536 s
->r
.out
.guid
= NULL
;
537 s
->r
.out
.domain_name
= NULL
;
538 s
->r
.out
.domain_sid
= NULL
;
539 /* Skip to the creating the actual connection, no info available on this transport */
540 continue_epm_map_binding_send(c
);
542 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
543 composite_error(c
, s
->lsa_open_policy
.out
.result
);
547 /* query lsa info for dns domain name and guid */
548 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
549 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
551 query_info_req
= dcerpc_lsa_QueryInfoPolicy2_send(s
->lsa_pipe
, c
, &s
->lsa_query_info2
);
552 if (composite_nomem(query_info_req
, c
)) return;
554 composite_continue_rpc(c
, query_info_req
, continue_lsa_query_info2
, c
);
559 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
560 may result in failure) and query lsa info for domain name and sid.
562 static void continue_lsa_query_info2(struct rpc_request
*req
)
564 struct composite_context
*c
;
565 struct rpc_connect_dci_state
*s
;
566 struct rpc_request
*query_info_req
;
568 c
= talloc_get_type(req
->async
.private, struct composite_context
);
569 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
571 c
->status
= dcerpc_ndr_request_recv(req
);
573 /* In case of error just null the realm and guid and proceed
574 to the next step. After all, it doesn't have to be AD domain
575 controller we talking to - NT-style PDC also counts */
577 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_NET_WRITE_FAULT
)) {
578 s
->r
.out
.realm
= NULL
;
579 s
->r
.out
.guid
= NULL
;
582 if (!NT_STATUS_IS_OK(c
->status
)) {
583 s
->r
.out
.error_string
= talloc_asprintf(c
,
584 "lsa_QueryInfoPolicy2 failed: %s",
585 nt_errstr(c
->status
));
586 composite_error(c
, c
->status
);
590 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
591 s
->r
.out
.error_string
= talloc_asprintf(c
,
592 "lsa_QueryInfoPolicy2 failed: %s",
593 nt_errstr(s
->lsa_query_info2
.out
.result
));
594 composite_error(c
, s
->lsa_query_info2
.out
.result
);
598 /* Copy the dns domain name and guid from the query result */
600 /* this should actually be a conversion from lsa_StringLarge */
601 s
->r
.out
.realm
= s
->lsa_query_info2
.out
.info
->dns
.dns_domain
.string
;
602 s
->r
.out
.guid
= talloc(c
, struct GUID
);
603 if (composite_nomem(s
->r
.out
.guid
, c
)) {
604 s
->r
.out
.error_string
= NULL
;
607 *s
->r
.out
.guid
= s
->lsa_query_info2
.out
.info
->dns
.domain_guid
;
610 /* query lsa info for domain name and sid */
611 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
612 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
614 query_info_req
= dcerpc_lsa_QueryInfoPolicy_send(s
->lsa_pipe
, c
, &s
->lsa_query_info
);
615 if (composite_nomem(query_info_req
, c
)) return;
617 composite_continue_rpc(c
, query_info_req
, continue_lsa_query_info
, c
);
622 Step 5 of RpcConnectDCInfo: Get domain name and sid
624 static void continue_lsa_query_info(struct rpc_request
*req
)
626 struct composite_context
*c
;
627 struct rpc_connect_dci_state
*s
;
629 c
= talloc_get_type(req
->async
.private, struct composite_context
);
630 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
632 c
->status
= dcerpc_ndr_request_recv(req
);
633 if (!NT_STATUS_IS_OK(c
->status
)) {
634 s
->r
.out
.error_string
= talloc_asprintf(c
,
635 "lsa_QueryInfoPolicy failed: %s",
636 nt_errstr(c
->status
));
637 composite_error(c
, c
->status
);
641 /* Copy the domain name and sid from the query result */
642 s
->r
.out
.domain_sid
= s
->lsa_query_info
.out
.info
->domain
.sid
;
643 s
->r
.out
.domain_name
= s
->lsa_query_info
.out
.info
->domain
.name
.string
;
645 continue_epm_map_binding_send(c
);
649 Step 5 (continued) of RpcConnectDCInfo: request endpoint
652 We may short-cut to this step if we dont' support LSA OpenPolicy on this transport
654 static void continue_epm_map_binding_send(struct composite_context
*c
)
656 struct rpc_connect_dci_state
*s
;
657 struct composite_context
*epm_map_req
;
658 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
660 /* prepare to get endpoint mapping for the requested interface */
661 s
->final_binding
= talloc(s
, struct dcerpc_binding
);
662 if (composite_nomem(s
->final_binding
, c
)) return;
664 *s
->final_binding
= *s
->lsa_pipe
->binding
;
665 /* Ensure we keep hold of the member elements */
666 if (composite_nomem(talloc_reference(s
->final_binding
, s
->lsa_pipe
->binding
), c
)) return;
668 epm_map_req
= dcerpc_epm_map_binding_send(c
, s
->final_binding
, s
->r
.in
.dcerpc_iface
,
669 s
->lsa_pipe
->conn
->event_ctx
);
670 if (composite_nomem(epm_map_req
, c
)) return;
672 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
676 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
677 rpc connection derived from already used pipe but connected to the requested
678 one (as specified in libnet_RpcConnect structure)
680 static void continue_epm_map_binding(struct composite_context
*ctx
)
682 struct composite_context
*c
, *sec_conn_req
;
683 struct rpc_connect_dci_state
*s
;
685 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
686 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
688 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
689 if (!NT_STATUS_IS_OK(c
->status
)) {
690 s
->r
.out
.error_string
= talloc_asprintf(c
,
691 "failed to map pipe with endpoint mapper - %s",
692 nt_errstr(c
->status
));
693 composite_error(c
, c
->status
);
697 /* create secondary connection derived from lsa pipe */
698 sec_conn_req
= dcerpc_secondary_connection_send(s
->lsa_pipe
, s
->final_binding
);
699 if (composite_nomem(sec_conn_req
, c
)) return;
701 composite_continue(c
, sec_conn_req
, continue_secondary_conn
, c
);
706 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
707 and complete this composite call
709 static void continue_secondary_conn(struct composite_context
*ctx
)
711 struct composite_context
*c
;
712 struct rpc_connect_dci_state
*s
;
714 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
715 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
717 c
->status
= dcerpc_secondary_connection_recv(ctx
, &s
->final_pipe
);
718 if (!NT_STATUS_IS_OK(c
->status
)) {
719 s
->r
.out
.error_string
= talloc_asprintf(c
,
720 "secondary connection failed: %s",
721 nt_errstr(c
->status
));
723 composite_error(c
, c
->status
);
727 s
->r
.out
.dcerpc_pipe
= s
->final_pipe
;
733 * Receives result of connection to rpc pipe and gets basic
734 * domain info (name, sid, realm, guid)
736 * @param c composite context
737 * @param ctx initialised libnet context
738 * @param mem_ctx memory context of this call
739 * @param r data structure containing return values
740 * @return nt status of rpc connection
743 static NTSTATUS
libnet_RpcConnectDCInfo_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
744 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
747 struct rpc_connect_dci_state
*s
= talloc_get_type(c
->private_data
,
748 struct rpc_connect_dci_state
);
750 status
= composite_wait(c
);
751 if (NT_STATUS_IS_OK(status
)) {
752 r
->out
.realm
= talloc_steal(mem_ctx
, s
->r
.out
.realm
);
753 r
->out
.guid
= talloc_steal(mem_ctx
, s
->r
.out
.guid
);
754 r
->out
.domain_name
= talloc_steal(mem_ctx
, s
->r
.out
.domain_name
);
755 r
->out
.domain_sid
= talloc_steal(mem_ctx
, s
->r
.out
.domain_sid
);
757 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
759 /* reference created pipe structure to long-term libnet_context
760 so that it can be used by other api functions even after short-term
762 if (r
->in
.dcerpc_iface
== &dcerpc_table_samr
) {
763 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
765 } else if (r
->in
.dcerpc_iface
== &dcerpc_table_lsarpc
) {
766 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
770 if (s
->r
.out
.error_string
) {
771 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
773 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC failed: %s", nt_errstr(status
));
783 * Initiates connection to rpc pipe on remote server or pdc, optionally
784 * providing domain info
786 * @param ctx initialised libnet context
787 * @param mem_ctx memory context of this call
788 * @param r data structure containing necessary parameters and return values
789 * @return composite context of this call
792 struct composite_context
* libnet_RpcConnect_send(struct libnet_context
*ctx
,
794 struct libnet_RpcConnect
*r
)
796 struct composite_context
*c
;
799 case LIBNET_RPC_CONNECT_SERVER
:
800 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
801 case LIBNET_RPC_CONNECT_BINDING
:
802 c
= libnet_RpcConnectSrv_send(ctx
, mem_ctx
, r
);
805 case LIBNET_RPC_CONNECT_PDC
:
806 case LIBNET_RPC_CONNECT_DC
:
807 c
= libnet_RpcConnectDC_send(ctx
, mem_ctx
, r
);
810 case LIBNET_RPC_CONNECT_DC_INFO
:
811 c
= libnet_RpcConnectDCInfo_send(ctx
, mem_ctx
, r
);
815 c
= talloc_zero(mem_ctx
, struct composite_context
);
816 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
824 * Receives result of connection to rpc pipe on remote server or pdc
826 * @param c composite context
827 * @param ctx initialised libnet context
828 * @param mem_ctx memory context of this call
829 * @param r data structure containing necessary parameters and return values
830 * @return nt status of rpc connection
833 NTSTATUS
libnet_RpcConnect_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
834 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
837 case LIBNET_RPC_CONNECT_SERVER
:
838 case LIBNET_RPC_CONNECT_BINDING
:
839 return libnet_RpcConnectSrv_recv(c
, ctx
, mem_ctx
, r
);
841 case LIBNET_RPC_CONNECT_PDC
:
842 case LIBNET_RPC_CONNECT_DC
:
843 return libnet_RpcConnectDC_recv(c
, ctx
, mem_ctx
, r
);
845 case LIBNET_RPC_CONNECT_DC_INFO
:
846 return libnet_RpcConnectDCInfo_recv(c
, ctx
, mem_ctx
, r
);
850 return NT_STATUS_INVALID_LEVEL
;
856 * Connect to a rpc pipe on a remote server - sync version
858 * @param ctx initialised libnet context
859 * @param mem_ctx memory context of this call
860 * @param r data structure containing necessary parameters and return values
861 * @return nt status of rpc connection
864 NTSTATUS
libnet_RpcConnect(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
865 struct libnet_RpcConnect
*r
)
867 struct composite_context
*c
;
869 c
= libnet_RpcConnect_send(ctx
, mem_ctx
, r
);
870 return libnet_RpcConnect_recv(c
, ctx
, mem_ctx
, r
);