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/rpc/dcerpc_proto.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
;
36 /* information about the progress */
37 void (*monitor_fn
)(struct monitor_msg
*);
41 static void continue_pipe_connect(struct composite_context
*ctx
);
45 * Initiates connection to rpc pipe on remote server
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
53 static struct composite_context
* libnet_RpcConnectSrv_send(struct libnet_context
*ctx
,
55 struct libnet_RpcConnect
*r
,
56 void (*monitor
)(struct monitor_msg
*))
58 struct composite_context
*c
;
59 struct rpc_connect_srv_state
*s
;
60 struct dcerpc_binding
*b
;
61 struct composite_context
*pipe_connect_req
;
63 /* composite context allocation and setup */
64 c
= composite_create(ctx
, ctx
->event_ctx
);
65 if (c
== NULL
) return c
;
67 s
= talloc_zero(c
, struct rpc_connect_srv_state
);
68 if (composite_nomem(s
, c
)) return c
;
71 s
->monitor_fn
= monitor
;
75 ZERO_STRUCT(s
->r
.out
);
77 /* prepare binding string */
79 case LIBNET_RPC_CONNECT_SERVER
:
80 s
->binding
= talloc_asprintf(s
, "ncacn_np:%s", r
->in
.name
);
82 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
83 s
->binding
= talloc_asprintf(s
, "ncacn_np:%s", r
->in
.address
);
86 case LIBNET_RPC_CONNECT_BINDING
:
87 s
->binding
= talloc_strdup(s
, r
->in
.binding
);
90 case LIBNET_RPC_CONNECT_DC
:
91 case LIBNET_RPC_CONNECT_PDC
:
92 /* this should never happen - DC and PDC level has a separate
94 case LIBNET_RPC_CONNECT_DC_INFO
:
95 /* this should never happen - DC_INFO level has a separate
97 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
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
);
109 if (r
->level
== LIBNET_RPC_CONNECT_SERVER_ADDRESS
) {
110 b
->target_hostname
= talloc_reference(b
, r
->in
.name
);
111 if (composite_nomem(b
->target_hostname
, c
)) {
116 /* connect to remote dcerpc pipe */
117 pipe_connect_req
= dcerpc_pipe_connect_b_send(c
, b
, r
->in
.dcerpc_iface
,
118 ctx
->cred
, c
->event_ctx
,
120 if (composite_nomem(pipe_connect_req
, c
)) return c
;
122 composite_continue(c
, pipe_connect_req
, continue_pipe_connect
, c
);
128 Step 2 of RpcConnectSrv - get rpc connection
130 static void continue_pipe_connect(struct composite_context
*ctx
)
132 struct composite_context
*c
;
133 struct rpc_connect_srv_state
*s
;
135 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
136 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
138 /* receive result of rpc pipe connection */
139 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->r
.out
.dcerpc_pipe
);
141 /* post monitor message */
143 struct monitor_msg msg
;
144 struct msg_net_rpc_connect data
;
145 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
147 /* prepare monitor message and post it */
148 data
.host
= binding
->host
;
149 data
.endpoint
= binding
->endpoint
;
150 data
.transport
= binding
->transport
;
151 data
.domain_name
= binding
->target_hostname
;
153 msg
.type
= mon_NetRpcConnect
;
154 msg
.data
= (void*)&data
;
155 msg
.data_size
= sizeof(data
);
164 * Receives result of connection to rpc pipe on remote server
166 * @param c composite context
167 * @param ctx initialised libnet context
168 * @param mem_ctx memory context of this call
169 * @param r data structure containing necessary parameters and return values
170 * @return nt status of rpc connection
173 static NTSTATUS
libnet_RpcConnectSrv_recv(struct composite_context
*c
,
174 struct libnet_context
*ctx
,
176 struct libnet_RpcConnect
*r
)
179 struct rpc_connect_srv_state
*s
= talloc_get_type(c
->private_data
,
180 struct rpc_connect_srv_state
);
182 status
= composite_wait(c
);
183 if (NT_STATUS_IS_OK(status
)) {
184 /* move the returned rpc pipe between memory contexts */
185 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
186 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
188 /* reference created pipe structure to long-term libnet_context
189 so that it can be used by other api functions even after short-term
191 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
192 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
194 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
195 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
198 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
201 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
209 struct rpc_connect_dc_state
{
210 struct libnet_context
*ctx
;
211 struct libnet_RpcConnect r
;
212 struct libnet_RpcConnect r2
;
213 struct libnet_LookupDCs f
;
214 const char *connect_name
;
216 /* information about the progress */
217 void (*monitor_fn
)(struct monitor_msg
*);
221 static void continue_lookup_dc(struct composite_context
*ctx
);
222 static void continue_rpc_connect(struct composite_context
*ctx
);
226 * Initiates connection to rpc pipe on domain pdc
228 * @param ctx initialised libnet context
229 * @param mem_ctx memory context of this call
230 * @param r data structure containing necessary parameters and return values
231 * @return composite context of this call
234 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
236 struct libnet_RpcConnect
*r
,
237 void (*monitor
)(struct monitor_msg
*msg
))
239 struct composite_context
*c
;
240 struct rpc_connect_dc_state
*s
;
241 struct composite_context
*lookup_dc_req
;
243 /* composite context allocation and setup */
244 c
= composite_create(ctx
, ctx
->event_ctx
);
245 if (c
== NULL
) return c
;
247 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
248 if (composite_nomem(s
, c
)) return c
;
251 s
->monitor_fn
= monitor
;
255 ZERO_STRUCT(s
->r
.out
);
258 case LIBNET_RPC_CONNECT_PDC
:
259 s
->f
.in
.name_type
= NBT_NAME_PDC
;
262 case LIBNET_RPC_CONNECT_DC
:
263 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
270 s
->f
.in
.domain_name
= r
->in
.name
;
271 s
->f
.out
.num_dcs
= 0;
274 /* find the domain pdc first */
275 lookup_dc_req
= libnet_LookupDCs_send(ctx
, c
, &s
->f
);
276 if (composite_nomem(lookup_dc_req
, c
)) return c
;
278 composite_continue(c
, lookup_dc_req
, continue_lookup_dc
, c
);
284 Step 2 of RpcConnectDC: get domain controller name and
285 initiate RpcConnect to it
287 static void continue_lookup_dc(struct composite_context
*ctx
)
289 struct composite_context
*c
;
290 struct rpc_connect_dc_state
*s
;
291 struct composite_context
*rpc_connect_req
;
292 struct monitor_msg msg
;
293 struct msg_net_lookup_dc data
;
295 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
296 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
298 /* receive result of domain controller lookup */
299 c
->status
= libnet_LookupDCs_recv(ctx
, c
, &s
->f
);
300 if (!composite_is_ok(c
)) return;
302 /* decide on preferred address type depending on DC type */
303 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
305 /* post monitor message */
307 /* prepare a monitor message and post it */
308 data
.domain_name
= s
->f
.in
.domain_name
;
309 data
.hostname
= s
->f
.out
.dcs
[0].name
;
310 data
.address
= s
->f
.out
.dcs
[0].address
;
312 msg
.type
= mon_NetLookupDc
;
314 msg
.data_size
= sizeof(data
);
318 /* ok, pdc has been found so do attempt to rpc connect */
319 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
321 /* this will cause yet another name resolution, but at least
322 * we pass the right name down the stack now */
323 s
->r2
.in
.name
= talloc_strdup(s
, s
->connect_name
);
324 s
->r2
.in
.address
= talloc_steal(s
, s
->f
.out
.dcs
[0].address
);
325 s
->r2
.in
.dcerpc_iface
= s
->r
.in
.dcerpc_iface
;
327 /* send rpc connect request to the server */
328 rpc_connect_req
= libnet_RpcConnectSrv_send(s
->ctx
, c
, &s
->r2
, s
->monitor_fn
);
329 if (composite_nomem(rpc_connect_req
, c
)) return;
331 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
336 Step 3 of RpcConnectDC: get rpc connection to the server
338 static void continue_rpc_connect(struct composite_context
*ctx
)
340 struct composite_context
*c
;
341 struct rpc_connect_dc_state
*s
;
343 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
344 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
346 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
348 /* error string is to be passed anyway */
349 s
->r
.out
.error_string
= s
->r2
.out
.error_string
;
350 if (!composite_is_ok(c
)) return;
352 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
354 /* post monitor message */
356 struct monitor_msg msg
;
357 struct msg_net_rpc_connect data
;
358 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
360 data
.host
= binding
->host
;
361 data
.endpoint
= binding
->endpoint
;
362 data
.transport
= binding
->transport
;
363 data
.domain_name
= binding
->target_hostname
;
365 msg
.type
= mon_NetRpcConnect
;
366 msg
.data
= (void*)&data
;
367 msg
.data_size
= sizeof(data
);
376 * Receives result of connection to rpc pipe on domain pdc
378 * @param c composite context
379 * @param ctx initialised libnet context
380 * @param mem_ctx memory context of this call
381 * @param r data structure containing necessary parameters and return values
382 * @return nt status of rpc connection
385 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
386 struct libnet_context
*ctx
,
388 struct libnet_RpcConnect
*r
)
391 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
392 struct rpc_connect_dc_state
);
394 status
= composite_wait(c
);
395 if (NT_STATUS_IS_OK(status
)) {
396 /* move connected rpc pipe between memory contexts */
397 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
399 /* reference created pipe structure to long-term libnet_context
400 so that it can be used by other api functions even after short-term
402 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
403 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
405 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
406 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
410 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
411 "Failed to rpc connect: %s",
421 struct rpc_connect_dci_state
{
422 struct libnet_context
*ctx
;
423 struct libnet_RpcConnect r
;
424 struct libnet_RpcConnect rpc_conn
;
425 struct policy_handle lsa_handle
;
426 struct lsa_QosInfo qos
;
427 struct lsa_ObjectAttribute attr
;
428 struct lsa_OpenPolicy2 lsa_open_policy
;
429 struct dcerpc_pipe
*lsa_pipe
;
430 struct lsa_QueryInfoPolicy2 lsa_query_info2
;
431 struct lsa_QueryInfoPolicy lsa_query_info
;
432 struct dcerpc_binding
*final_binding
;
433 struct dcerpc_pipe
*final_pipe
;
435 /* information about the progress */
436 void (*monitor_fn
)(struct monitor_msg
*);
440 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
441 static void continue_lsa_policy(struct rpc_request
*req
);
442 static void continue_lsa_query_info(struct rpc_request
*req
);
443 static void continue_lsa_query_info2(struct rpc_request
*req
);
444 static void continue_epm_map_binding(struct composite_context
*ctx
);
445 static void continue_secondary_conn(struct composite_context
*ctx
);
446 static void continue_epm_map_binding_send(struct composite_context
*c
);
450 * Initiates connection to rpc pipe on remote server or pdc. Received result
451 * contains info on the domain name, domain sid and realm.
453 * @param ctx initialised libnet context
454 * @param mem_ctx memory context of this call
455 * @param r data structure containing necessary parameters and return values. Must be a talloc context
456 * @return composite context of this call
459 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
461 struct libnet_RpcConnect
*r
,
462 void (*monitor
)(struct monitor_msg
*))
464 struct composite_context
*c
, *conn_req
;
465 struct rpc_connect_dci_state
*s
;
467 /* composite context allocation and setup */
468 c
= composite_create(ctx
, ctx
->event_ctx
);
469 if (c
== NULL
) return c
;
471 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
472 if (composite_nomem(s
, c
)) return c
;
475 s
->monitor_fn
= monitor
;
479 ZERO_STRUCT(s
->r
.out
);
481 /* proceed to pure rpc connection if the binding string is provided,
482 otherwise try to connect domain controller */
483 if (r
->in
.binding
== NULL
) {
484 s
->rpc_conn
.in
.name
= r
->in
.name
;
485 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
487 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
488 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
491 /* we need to query information on lsarpc interface first */
492 s
->rpc_conn
.in
.dcerpc_iface
= &ndr_table_lsarpc
;
494 /* request connection to the lsa pipe on the pdc */
495 conn_req
= libnet_RpcConnect_send(ctx
, c
, &s
->rpc_conn
, s
->monitor_fn
);
496 if (composite_nomem(c
, conn_req
)) return c
;
498 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
504 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
507 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
509 struct composite_context
*c
;
510 struct rpc_connect_dci_state
*s
;
511 struct rpc_request
*open_pol_req
;
513 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
514 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
516 c
->status
= libnet_RpcConnect_recv(ctx
, s
->ctx
, c
, &s
->rpc_conn
);
517 if (!NT_STATUS_IS_OK(c
->status
)) {
518 composite_error(c
, c
->status
);
522 /* post monitor message */
524 struct monitor_msg msg
;
525 struct msg_net_rpc_connect data
;
526 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
528 data
.host
= binding
->host
;
529 data
.endpoint
= binding
->endpoint
;
530 data
.transport
= binding
->transport
;
531 data
.domain_name
= binding
->target_hostname
;
533 msg
.type
= mon_NetRpcConnect
;
534 msg
.data
= (void*)&data
;
535 msg
.data_size
= sizeof(data
);
539 /* prepare to open a policy handle on lsa pipe */
540 s
->lsa_pipe
= s
->ctx
->lsa
.pipe
;
543 s
->qos
.impersonation_level
= 2;
544 s
->qos
.context_mode
= 1;
545 s
->qos
.effective_only
= 0;
547 s
->attr
.sec_qos
= &s
->qos
;
549 s
->lsa_open_policy
.in
.attr
= &s
->attr
;
550 s
->lsa_open_policy
.in
.system_name
= talloc_asprintf(c
, "\\");
551 if (composite_nomem(s
->lsa_open_policy
.in
.system_name
, c
)) return;
553 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
554 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
556 open_pol_req
= dcerpc_lsa_OpenPolicy2_send(s
->lsa_pipe
, c
, &s
->lsa_open_policy
);
557 if (composite_nomem(open_pol_req
, c
)) return;
559 composite_continue_rpc(c
, open_pol_req
, continue_lsa_policy
, c
);
564 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
565 for kerberos realm (dns name) and guid. The query may fail.
567 static void continue_lsa_policy(struct rpc_request
*req
)
569 struct composite_context
*c
;
570 struct rpc_connect_dci_state
*s
;
571 struct rpc_request
*query_info_req
;
573 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
574 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
576 c
->status
= dcerpc_ndr_request_recv(req
);
577 if (!NT_STATUS_IS_OK(c
->status
)) {
578 composite_error(c
, c
->status
);
582 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
583 s
->r
.out
.realm
= NULL
;
584 s
->r
.out
.guid
= NULL
;
585 s
->r
.out
.domain_name
= NULL
;
586 s
->r
.out
.domain_sid
= NULL
;
588 /* Skip to the creating the actual connection, no info available on this transport */
589 continue_epm_map_binding_send(c
);
592 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
593 composite_error(c
, s
->lsa_open_policy
.out
.result
);
597 /* post monitor message */
599 struct monitor_msg msg
;
601 msg
.type
= mon_LsaOpenPolicy
;
607 /* query lsa info for dns domain name and guid */
608 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
609 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
610 s
->lsa_query_info2
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
611 if (composite_nomem(s
->lsa_query_info2
.out
.info
, c
)) return;
613 query_info_req
= dcerpc_lsa_QueryInfoPolicy2_send(s
->lsa_pipe
, c
, &s
->lsa_query_info2
);
614 if (composite_nomem(query_info_req
, c
)) return;
616 composite_continue_rpc(c
, query_info_req
, continue_lsa_query_info2
, c
);
621 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
622 may result in failure) and query lsa info for domain name and sid.
624 static void continue_lsa_query_info2(struct rpc_request
*req
)
626 struct composite_context
*c
;
627 struct rpc_connect_dci_state
*s
;
628 struct rpc_request
*query_info_req
;
630 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
631 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
633 c
->status
= dcerpc_ndr_request_recv(req
);
635 /* In case of error just null the realm and guid and proceed
636 to the next step. After all, it doesn't have to be AD domain
637 controller we talking to - NT-style PDC also counts */
639 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_NET_WRITE_FAULT
)) {
640 s
->r
.out
.realm
= NULL
;
641 s
->r
.out
.guid
= NULL
;
644 if (!NT_STATUS_IS_OK(c
->status
)) {
645 s
->r
.out
.error_string
= talloc_asprintf(c
,
646 "lsa_QueryInfoPolicy2 failed: %s",
647 nt_errstr(c
->status
));
648 composite_error(c
, c
->status
);
652 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
653 s
->r
.out
.error_string
= talloc_asprintf(c
,
654 "lsa_QueryInfoPolicy2 failed: %s",
655 nt_errstr(s
->lsa_query_info2
.out
.result
));
656 composite_error(c
, s
->lsa_query_info2
.out
.result
);
660 /* Copy the dns domain name and guid from the query result */
662 /* this should actually be a conversion from lsa_StringLarge */
663 s
->r
.out
.realm
= (*s
->lsa_query_info2
.out
.info
)->dns
.dns_domain
.string
;
664 s
->r
.out
.guid
= talloc(c
, struct GUID
);
665 if (composite_nomem(s
->r
.out
.guid
, c
)) {
666 s
->r
.out
.error_string
= NULL
;
669 *s
->r
.out
.guid
= (*s
->lsa_query_info2
.out
.info
)->dns
.domain_guid
;
672 /* post monitor message */
674 struct monitor_msg msg
;
676 msg
.type
= mon_LsaQueryPolicy
;
682 /* query lsa info for domain name and sid */
683 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
684 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
685 s
->lsa_query_info
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
686 if (composite_nomem(s
->lsa_query_info
.out
.info
, c
)) return;
688 query_info_req
= dcerpc_lsa_QueryInfoPolicy_send(s
->lsa_pipe
, c
, &s
->lsa_query_info
);
689 if (composite_nomem(query_info_req
, c
)) return;
691 composite_continue_rpc(c
, query_info_req
, continue_lsa_query_info
, c
);
696 Step 5 of RpcConnectDCInfo: Get domain name and sid
698 static void continue_lsa_query_info(struct rpc_request
*req
)
700 struct composite_context
*c
;
701 struct rpc_connect_dci_state
*s
;
703 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
704 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
706 c
->status
= dcerpc_ndr_request_recv(req
);
707 if (!NT_STATUS_IS_OK(c
->status
)) {
708 s
->r
.out
.error_string
= talloc_asprintf(c
,
709 "lsa_QueryInfoPolicy failed: %s",
710 nt_errstr(c
->status
));
711 composite_error(c
, c
->status
);
715 /* post monitor message */
717 struct monitor_msg msg
;
719 msg
.type
= mon_LsaQueryPolicy
;
725 /* Copy the domain name and sid from the query result */
726 s
->r
.out
.domain_sid
= (*s
->lsa_query_info
.out
.info
)->domain
.sid
;
727 s
->r
.out
.domain_name
= (*s
->lsa_query_info
.out
.info
)->domain
.name
.string
;
729 continue_epm_map_binding_send(c
);
733 Step 5 (continued) of RpcConnectDCInfo: request endpoint
736 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
738 static void continue_epm_map_binding_send(struct composite_context
*c
)
740 struct rpc_connect_dci_state
*s
;
741 struct composite_context
*epm_map_req
;
742 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
744 /* prepare to get endpoint mapping for the requested interface */
745 s
->final_binding
= talloc(s
, struct dcerpc_binding
);
746 if (composite_nomem(s
->final_binding
, c
)) return;
748 *s
->final_binding
= *s
->lsa_pipe
->binding
;
749 /* Ensure we keep hold of the member elements */
750 if (composite_nomem(talloc_reference(s
->final_binding
, s
->lsa_pipe
->binding
), c
)) return;
752 epm_map_req
= dcerpc_epm_map_binding_send(c
, s
->final_binding
, s
->r
.in
.dcerpc_iface
,
753 s
->lsa_pipe
->conn
->event_ctx
, s
->ctx
->lp_ctx
);
754 if (composite_nomem(epm_map_req
, c
)) return;
756 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
760 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
761 rpc connection derived from already used pipe but connected to the requested
762 one (as specified in libnet_RpcConnect structure)
764 static void continue_epm_map_binding(struct composite_context
*ctx
)
766 struct composite_context
*c
, *sec_conn_req
;
767 struct rpc_connect_dci_state
*s
;
769 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
770 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
772 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
773 if (!NT_STATUS_IS_OK(c
->status
)) {
774 s
->r
.out
.error_string
= talloc_asprintf(c
,
775 "failed to map pipe with endpoint mapper - %s",
776 nt_errstr(c
->status
));
777 composite_error(c
, c
->status
);
781 /* create secondary connection derived from lsa pipe */
782 sec_conn_req
= dcerpc_secondary_connection_send(s
->lsa_pipe
, s
->final_binding
);
783 if (composite_nomem(sec_conn_req
, c
)) return;
785 composite_continue(c
, sec_conn_req
, continue_secondary_conn
, c
);
790 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
791 and complete this composite call
793 static void continue_secondary_conn(struct composite_context
*ctx
)
795 struct composite_context
*c
;
796 struct rpc_connect_dci_state
*s
;
798 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
799 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
801 c
->status
= dcerpc_secondary_connection_recv(ctx
, &s
->final_pipe
);
802 if (!NT_STATUS_IS_OK(c
->status
)) {
803 s
->r
.out
.error_string
= talloc_asprintf(c
,
804 "secondary connection failed: %s",
805 nt_errstr(c
->status
));
807 composite_error(c
, c
->status
);
811 s
->r
.out
.dcerpc_pipe
= s
->final_pipe
;
813 /* post monitor message */
815 struct monitor_msg msg
;
816 struct msg_net_rpc_connect data
;
817 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
819 /* prepare monitor message and post it */
820 data
.host
= binding
->host
;
821 data
.endpoint
= binding
->endpoint
;
822 data
.transport
= binding
->transport
;
823 data
.domain_name
= binding
->target_hostname
;
825 msg
.type
= mon_NetRpcConnect
;
826 msg
.data
= (void*)&data
;
827 msg
.data_size
= sizeof(data
);
836 * Receives result of connection to rpc pipe and gets basic
837 * domain info (name, sid, realm, guid)
839 * @param c composite context
840 * @param ctx initialised libnet context
841 * @param mem_ctx memory context of this call
842 * @param r data structure containing return values
843 * @return nt status of rpc connection
846 static NTSTATUS
libnet_RpcConnectDCInfo_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
847 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
850 struct rpc_connect_dci_state
*s
= talloc_get_type(c
->private_data
,
851 struct rpc_connect_dci_state
);
853 status
= composite_wait(c
);
854 if (NT_STATUS_IS_OK(status
)) {
855 r
->out
.realm
= talloc_steal(mem_ctx
, s
->r
.out
.realm
);
856 r
->out
.guid
= talloc_steal(mem_ctx
, s
->r
.out
.guid
);
857 r
->out
.domain_name
= talloc_steal(mem_ctx
, s
->r
.out
.domain_name
);
858 r
->out
.domain_sid
= talloc_steal(mem_ctx
, s
->r
.out
.domain_sid
);
860 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
862 /* reference created pipe structure to long-term libnet_context
863 so that it can be used by other api functions even after short-term
865 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
866 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
868 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
869 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
873 if (s
->r
.out
.error_string
) {
874 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
875 } else if (r
->in
.binding
== NULL
) {
876 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC failed: %s", nt_errstr(status
));
878 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC %s failed: %s",
879 r
->in
.binding
, nt_errstr(status
));
889 * Initiates connection to rpc pipe on remote server or pdc, optionally
890 * providing domain info
892 * @param ctx initialised libnet context
893 * @param mem_ctx memory context of this call
894 * @param r data structure containing necessary parameters and return values
895 * @return composite context of this call
898 struct composite_context
* libnet_RpcConnect_send(struct libnet_context
*ctx
,
900 struct libnet_RpcConnect
*r
,
901 void (*monitor
)(struct monitor_msg
*))
903 struct composite_context
*c
;
906 case LIBNET_RPC_CONNECT_SERVER
:
907 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
908 case LIBNET_RPC_CONNECT_BINDING
:
909 c
= libnet_RpcConnectSrv_send(ctx
, mem_ctx
, r
, monitor
);
912 case LIBNET_RPC_CONNECT_PDC
:
913 case LIBNET_RPC_CONNECT_DC
:
914 c
= libnet_RpcConnectDC_send(ctx
, mem_ctx
, r
, monitor
);
917 case LIBNET_RPC_CONNECT_DC_INFO
:
918 c
= libnet_RpcConnectDCInfo_send(ctx
, mem_ctx
, r
, monitor
);
922 c
= talloc_zero(mem_ctx
, struct composite_context
);
923 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
931 * Receives result of connection to rpc pipe on remote server or pdc
933 * @param c composite context
934 * @param ctx initialised libnet context
935 * @param mem_ctx memory context of this call
936 * @param r data structure containing necessary parameters and return values
937 * @return nt status of rpc connection
940 NTSTATUS
libnet_RpcConnect_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
941 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
944 case LIBNET_RPC_CONNECT_SERVER
:
945 case LIBNET_RPC_CONNECT_BINDING
:
946 return libnet_RpcConnectSrv_recv(c
, ctx
, mem_ctx
, r
);
948 case LIBNET_RPC_CONNECT_PDC
:
949 case LIBNET_RPC_CONNECT_DC
:
950 return libnet_RpcConnectDC_recv(c
, ctx
, mem_ctx
, r
);
952 case LIBNET_RPC_CONNECT_DC_INFO
:
953 return libnet_RpcConnectDCInfo_recv(c
, ctx
, mem_ctx
, r
);
957 return NT_STATUS_INVALID_LEVEL
;
963 * Connect to a rpc pipe on a remote server - sync version
965 * @param ctx initialised libnet context
966 * @param mem_ctx memory context of this call
967 * @param r data structure containing necessary parameters and return values
968 * @return nt status of rpc connection
971 NTSTATUS
libnet_RpcConnect(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
972 struct libnet_RpcConnect
*r
)
974 struct composite_context
*c
;
976 c
= libnet_RpcConnect_send(ctx
, mem_ctx
, r
, NULL
);
977 return libnet_RpcConnect_recv(c
, ctx
, mem_ctx
, r
);