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
);
110 case LIBNET_RPC_CONNECT_SERVER
:
111 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
112 b
->flags
= r
->in
.dcerpc_flags
;
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
)) {
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
,
126 if (composite_nomem(pipe_connect_req
, c
)) return c
;
128 composite_continue(c
, pipe_connect_req
, continue_pipe_connect
, c
);
134 Step 2 of RpcConnectSrv - get rpc connection
136 static void continue_pipe_connect(struct composite_context
*ctx
)
138 struct composite_context
*c
;
139 struct rpc_connect_srv_state
*s
;
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
);
144 /* receive result of rpc pipe connection */
145 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->r
.out
.dcerpc_pipe
);
147 /* post monitor message */
149 struct monitor_msg msg
;
150 struct msg_net_rpc_connect data
;
151 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
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
;
159 msg
.type
= mon_NetRpcConnect
;
160 msg
.data
= (void*)&data
;
161 msg
.data_size
= sizeof(data
);
170 * Receives result of connection to rpc pipe on remote server
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
179 static NTSTATUS
libnet_RpcConnectSrv_recv(struct composite_context
*c
,
180 struct libnet_context
*ctx
,
182 struct libnet_RpcConnect
*r
)
185 struct rpc_connect_srv_state
*s
= talloc_get_type(c
->private_data
,
186 struct rpc_connect_srv_state
);
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
);
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
197 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
198 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
200 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
201 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
204 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
207 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
215 struct 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
;
222 /* information about the progress */
223 void (*monitor_fn
)(struct monitor_msg
*);
227 static void continue_lookup_dc(struct composite_context
*ctx
);
228 static void continue_rpc_connect(struct composite_context
*ctx
);
232 * Initiates connection to rpc pipe on domain pdc
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
240 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
242 struct libnet_RpcConnect
*r
,
243 void (*monitor
)(struct monitor_msg
*msg
))
245 struct composite_context
*c
;
246 struct rpc_connect_dc_state
*s
;
247 struct composite_context
*lookup_dc_req
;
249 /* composite context allocation and setup */
250 c
= composite_create(ctx
, ctx
->event_ctx
);
251 if (c
== NULL
) return c
;
253 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
254 if (composite_nomem(s
, c
)) return c
;
257 s
->monitor_fn
= monitor
;
261 ZERO_STRUCT(s
->r
.out
);
264 case LIBNET_RPC_CONNECT_PDC
:
265 s
->f
.in
.name_type
= NBT_NAME_PDC
;
268 case LIBNET_RPC_CONNECT_DC
:
269 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
276 s
->f
.in
.domain_name
= r
->in
.name
;
277 s
->f
.out
.num_dcs
= 0;
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
;
284 composite_continue(c
, lookup_dc_req
, continue_lookup_dc
, c
);
290 Step 2 of RpcConnectDC: get domain controller name and
291 initiate RpcConnect to it
293 static void continue_lookup_dc(struct composite_context
*ctx
)
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
;
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
);
304 /* receive result of domain controller lookup */
305 c
->status
= libnet_LookupDCs_recv(ctx
, c
, &s
->f
);
306 if (!composite_is_ok(c
)) return;
308 /* decide on preferred address type depending on DC type */
309 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
311 /* post monitor message */
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
;
318 msg
.type
= mon_NetLookupDc
;
320 msg
.data_size
= sizeof(data
);
324 /* ok, pdc has been found so do attempt to rpc connect */
325 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
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
;
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;
338 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
343 Step 3 of RpcConnectDC: get rpc connection to the server
345 static void continue_rpc_connect(struct composite_context
*ctx
)
347 struct composite_context
*c
;
348 struct rpc_connect_dc_state
*s
;
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
);
353 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
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;
359 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
361 /* post monitor message */
363 struct monitor_msg msg
;
364 struct msg_net_rpc_connect data
;
365 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
367 data
.host
= binding
->host
;
368 data
.endpoint
= binding
->endpoint
;
369 data
.transport
= binding
->transport
;
370 data
.domain_name
= binding
->target_hostname
;
372 msg
.type
= mon_NetRpcConnect
;
373 msg
.data
= (void*)&data
;
374 msg
.data_size
= sizeof(data
);
383 * Receives result of connection to rpc pipe on domain pdc
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
392 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
393 struct libnet_context
*ctx
,
395 struct libnet_RpcConnect
*r
)
398 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
399 struct rpc_connect_dc_state
);
401 status
= composite_wait(c
);
402 if (NT_STATUS_IS_OK(status
)) {
403 /* move connected rpc pipe between memory contexts
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).
412 r
->out
.dcerpc_pipe
= talloc_reparent(talloc_parent(s
->r
.out
.dcerpc_pipe
),
413 mem_ctx
, s
->r
.out
.dcerpc_pipe
);
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
418 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
419 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
421 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
422 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
426 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
427 "Failed to rpc connect: %s",
437 struct 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
;
451 /* information about the progress */
452 void (*monitor_fn
)(struct monitor_msg
*);
456 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
457 static void continue_lsa_policy(struct tevent_req
*subreq
);
458 static void continue_lsa_query_info(struct tevent_req
*subreq
);
459 static void continue_lsa_query_info2(struct tevent_req
*subreq
);
460 static void continue_epm_map_binding(struct composite_context
*ctx
);
461 static void continue_secondary_conn(struct composite_context
*ctx
);
462 static void continue_epm_map_binding_send(struct composite_context
*c
);
466 * Initiates connection to rpc pipe on remote server or pdc. Received result
467 * contains info on the domain name, domain sid and realm.
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
475 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
477 struct libnet_RpcConnect
*r
,
478 void (*monitor
)(struct monitor_msg
*))
480 struct composite_context
*c
, *conn_req
;
481 struct rpc_connect_dci_state
*s
;
483 /* composite context allocation and setup */
484 c
= composite_create(ctx
, ctx
->event_ctx
);
485 if (c
== NULL
) return c
;
487 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
488 if (composite_nomem(s
, c
)) return c
;
491 s
->monitor_fn
= monitor
;
495 ZERO_STRUCT(s
->r
.out
);
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
;
504 s
->rpc_conn
.in
.name
= r
->in
.name
;
505 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
507 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
508 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
511 /* we need to query information on lsarpc interface first */
512 s
->rpc_conn
.in
.dcerpc_iface
= &ndr_table_lsarpc
;
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
;
518 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
524 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
527 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
529 struct composite_context
*c
;
530 struct rpc_connect_dci_state
*s
;
531 struct tevent_req
*subreq
;
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
);
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
);
542 /* post monitor message */
544 struct monitor_msg msg
;
545 struct msg_net_rpc_connect data
;
546 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
548 data
.host
= binding
->host
;
549 data
.endpoint
= binding
->endpoint
;
550 data
.transport
= binding
->transport
;
551 data
.domain_name
= binding
->target_hostname
;
553 msg
.type
= mon_NetRpcConnect
;
554 msg
.data
= (void*)&data
;
555 msg
.data_size
= sizeof(data
);
559 /* prepare to open a policy handle on lsa pipe */
560 s
->lsa_pipe
= s
->ctx
->lsa
.pipe
;
563 s
->qos
.impersonation_level
= 2;
564 s
->qos
.context_mode
= 1;
565 s
->qos
.effective_only
= 0;
567 s
->attr
.sec_qos
= &s
->qos
;
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;
573 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
574 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
576 subreq
= dcerpc_lsa_OpenPolicy2_r_send(s
, c
->event_ctx
,
577 s
->lsa_pipe
->binding_handle
,
578 &s
->lsa_open_policy
);
579 if (composite_nomem(subreq
, c
)) return;
581 tevent_req_set_callback(subreq
, continue_lsa_policy
, c
);
586 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
587 for kerberos realm (dns name) and guid. The query may fail.
589 static void continue_lsa_policy(struct tevent_req
*subreq
)
591 struct composite_context
*c
;
592 struct rpc_connect_dci_state
*s
;
594 c
= tevent_req_callback_data(subreq
, struct composite_context
);
595 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
597 c
->status
= dcerpc_lsa_OpenPolicy2_r_recv(subreq
, s
);
599 if (!NT_STATUS_IS_OK(c
->status
)) {
600 composite_error(c
, c
->status
);
604 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
605 s
->r
.out
.realm
= NULL
;
606 s
->r
.out
.guid
= NULL
;
607 s
->r
.out
.domain_name
= NULL
;
608 s
->r
.out
.domain_sid
= NULL
;
610 /* Skip to the creating the actual connection, no info available on this transport */
611 continue_epm_map_binding_send(c
);
614 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
615 composite_error(c
, s
->lsa_open_policy
.out
.result
);
619 /* post monitor message */
621 struct monitor_msg msg
;
623 msg
.type
= mon_LsaOpenPolicy
;
629 /* query lsa info for dns domain name and guid */
630 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
631 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
632 s
->lsa_query_info2
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
633 if (composite_nomem(s
->lsa_query_info2
.out
.info
, c
)) return;
635 subreq
= dcerpc_lsa_QueryInfoPolicy2_r_send(s
, c
->event_ctx
,
636 s
->lsa_pipe
->binding_handle
,
637 &s
->lsa_query_info2
);
638 if (composite_nomem(subreq
, c
)) return;
640 tevent_req_set_callback(subreq
, continue_lsa_query_info2
, c
);
645 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
646 may result in failure) and query lsa info for domain name and sid.
648 static void continue_lsa_query_info2(struct tevent_req
*subreq
)
650 struct composite_context
*c
;
651 struct rpc_connect_dci_state
*s
;
653 c
= tevent_req_callback_data(subreq
, struct composite_context
);
654 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
656 c
->status
= dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq
, s
);
659 /* In case of error just null the realm and guid and proceed
660 to the next step. After all, it doesn't have to be AD domain
661 controller we talking to - NT-style PDC also counts */
663 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_NET_WRITE_FAULT
)) {
664 s
->r
.out
.realm
= NULL
;
665 s
->r
.out
.guid
= NULL
;
668 if (!NT_STATUS_IS_OK(c
->status
)) {
669 s
->r
.out
.error_string
= talloc_asprintf(c
,
670 "lsa_QueryInfoPolicy2 failed: %s",
671 nt_errstr(c
->status
));
672 composite_error(c
, c
->status
);
676 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
677 s
->r
.out
.error_string
= talloc_asprintf(c
,
678 "lsa_QueryInfoPolicy2 failed: %s",
679 nt_errstr(s
->lsa_query_info2
.out
.result
));
680 composite_error(c
, s
->lsa_query_info2
.out
.result
);
684 /* Copy the dns domain name and guid from the query result */
686 /* this should actually be a conversion from lsa_StringLarge */
687 s
->r
.out
.realm
= (*s
->lsa_query_info2
.out
.info
)->dns
.dns_domain
.string
;
688 s
->r
.out
.guid
= talloc(c
, struct GUID
);
689 if (composite_nomem(s
->r
.out
.guid
, c
)) {
690 s
->r
.out
.error_string
= NULL
;
693 *s
->r
.out
.guid
= (*s
->lsa_query_info2
.out
.info
)->dns
.domain_guid
;
696 /* post monitor message */
698 struct monitor_msg msg
;
700 msg
.type
= mon_LsaQueryPolicy
;
706 /* query lsa info for domain name and sid */
707 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
708 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
709 s
->lsa_query_info
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
710 if (composite_nomem(s
->lsa_query_info
.out
.info
, c
)) return;
712 subreq
= dcerpc_lsa_QueryInfoPolicy_r_send(s
, c
->event_ctx
,
713 s
->lsa_pipe
->binding_handle
,
715 if (composite_nomem(subreq
, c
)) return;
717 tevent_req_set_callback(subreq
, continue_lsa_query_info
, c
);
722 Step 5 of RpcConnectDCInfo: Get domain name and sid
724 static void continue_lsa_query_info(struct tevent_req
*subreq
)
726 struct composite_context
*c
;
727 struct rpc_connect_dci_state
*s
;
729 c
= tevent_req_callback_data(subreq
, struct composite_context
);
730 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
732 c
->status
= dcerpc_lsa_QueryInfoPolicy_r_recv(subreq
, s
);
734 if (!NT_STATUS_IS_OK(c
->status
)) {
735 s
->r
.out
.error_string
= talloc_asprintf(c
,
736 "lsa_QueryInfoPolicy failed: %s",
737 nt_errstr(c
->status
));
738 composite_error(c
, c
->status
);
742 /* post monitor message */
744 struct monitor_msg msg
;
746 msg
.type
= mon_LsaQueryPolicy
;
752 /* Copy the domain name and sid from the query result */
753 s
->r
.out
.domain_sid
= (*s
->lsa_query_info
.out
.info
)->domain
.sid
;
754 s
->r
.out
.domain_name
= (*s
->lsa_query_info
.out
.info
)->domain
.name
.string
;
756 continue_epm_map_binding_send(c
);
760 Step 5 (continued) of RpcConnectDCInfo: request endpoint
763 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
765 static void continue_epm_map_binding_send(struct composite_context
*c
)
767 struct rpc_connect_dci_state
*s
;
768 struct composite_context
*epm_map_req
;
769 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
771 /* prepare to get endpoint mapping for the requested interface */
772 s
->final_binding
= talloc(s
, struct dcerpc_binding
);
773 if (composite_nomem(s
->final_binding
, c
)) return;
775 *s
->final_binding
= *s
->lsa_pipe
->binding
;
776 /* Ensure we keep hold of the member elements */
777 if (composite_nomem(talloc_reference(s
->final_binding
, s
->lsa_pipe
->binding
), c
)) return;
779 epm_map_req
= dcerpc_epm_map_binding_send(c
, s
->final_binding
, s
->r
.in
.dcerpc_iface
,
780 s
->lsa_pipe
->conn
->event_ctx
, s
->ctx
->lp_ctx
);
781 if (composite_nomem(epm_map_req
, c
)) return;
783 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
787 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
788 rpc connection derived from already used pipe but connected to the requested
789 one (as specified in libnet_RpcConnect structure)
791 static void continue_epm_map_binding(struct composite_context
*ctx
)
793 struct composite_context
*c
, *sec_conn_req
;
794 struct rpc_connect_dci_state
*s
;
796 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
797 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
799 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
800 if (!NT_STATUS_IS_OK(c
->status
)) {
801 s
->r
.out
.error_string
= talloc_asprintf(c
,
802 "failed to map pipe with endpoint mapper - %s",
803 nt_errstr(c
->status
));
804 composite_error(c
, c
->status
);
808 /* create secondary connection derived from lsa pipe */
809 sec_conn_req
= dcerpc_secondary_connection_send(s
->lsa_pipe
, s
->final_binding
);
810 if (composite_nomem(sec_conn_req
, c
)) return;
812 composite_continue(c
, sec_conn_req
, continue_secondary_conn
, c
);
817 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
818 and complete this composite call
820 static void continue_secondary_conn(struct composite_context
*ctx
)
822 struct composite_context
*c
;
823 struct rpc_connect_dci_state
*s
;
825 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
826 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
828 c
->status
= dcerpc_secondary_connection_recv(ctx
, &s
->final_pipe
);
829 if (!NT_STATUS_IS_OK(c
->status
)) {
830 s
->r
.out
.error_string
= talloc_asprintf(c
,
831 "secondary connection failed: %s",
832 nt_errstr(c
->status
));
834 composite_error(c
, c
->status
);
838 s
->r
.out
.dcerpc_pipe
= s
->final_pipe
;
840 /* post monitor message */
842 struct monitor_msg msg
;
843 struct msg_net_rpc_connect data
;
844 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
846 /* prepare monitor message and post it */
847 data
.host
= binding
->host
;
848 data
.endpoint
= binding
->endpoint
;
849 data
.transport
= binding
->transport
;
850 data
.domain_name
= binding
->target_hostname
;
852 msg
.type
= mon_NetRpcConnect
;
853 msg
.data
= (void*)&data
;
854 msg
.data_size
= sizeof(data
);
863 * Receives result of connection to rpc pipe and gets basic
864 * domain info (name, sid, realm, guid)
866 * @param c composite context
867 * @param ctx initialised libnet context
868 * @param mem_ctx memory context of this call
869 * @param r data structure containing return values
870 * @return nt status of rpc connection
873 static NTSTATUS
libnet_RpcConnectDCInfo_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
874 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
877 struct rpc_connect_dci_state
*s
= talloc_get_type(c
->private_data
,
878 struct rpc_connect_dci_state
);
880 status
= composite_wait(c
);
881 if (NT_STATUS_IS_OK(status
)) {
882 r
->out
.realm
= talloc_steal(mem_ctx
, s
->r
.out
.realm
);
883 r
->out
.guid
= talloc_steal(mem_ctx
, s
->r
.out
.guid
);
884 r
->out
.domain_name
= talloc_steal(mem_ctx
, s
->r
.out
.domain_name
);
885 r
->out
.domain_sid
= talloc_steal(mem_ctx
, s
->r
.out
.domain_sid
);
887 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
889 /* reference created pipe structure to long-term libnet_context
890 so that it can be used by other api functions even after short-term
892 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
893 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
894 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
896 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
897 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
898 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
902 if (s
->r
.out
.error_string
) {
903 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
904 } else if (r
->in
.binding
== NULL
) {
905 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC failed: %s", nt_errstr(status
));
907 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC %s failed: %s",
908 r
->in
.binding
, nt_errstr(status
));
918 * Initiates connection to rpc pipe on remote server or pdc, optionally
919 * providing domain info
921 * @param ctx initialised libnet context
922 * @param mem_ctx memory context of this call
923 * @param r data structure containing necessary parameters and return values
924 * @return composite context of this call
927 struct composite_context
* libnet_RpcConnect_send(struct libnet_context
*ctx
,
929 struct libnet_RpcConnect
*r
,
930 void (*monitor
)(struct monitor_msg
*))
932 struct composite_context
*c
;
935 case LIBNET_RPC_CONNECT_SERVER
:
936 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
937 case LIBNET_RPC_CONNECT_BINDING
:
938 c
= libnet_RpcConnectSrv_send(ctx
, mem_ctx
, r
, monitor
);
941 case LIBNET_RPC_CONNECT_PDC
:
942 case LIBNET_RPC_CONNECT_DC
:
943 c
= libnet_RpcConnectDC_send(ctx
, mem_ctx
, r
, monitor
);
946 case LIBNET_RPC_CONNECT_DC_INFO
:
947 c
= libnet_RpcConnectDCInfo_send(ctx
, mem_ctx
, r
, monitor
);
951 c
= talloc_zero(mem_ctx
, struct composite_context
);
952 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
960 * Receives result of connection to rpc pipe on remote server or pdc
962 * @param c composite context
963 * @param ctx initialised libnet context
964 * @param mem_ctx memory context of this call
965 * @param r data structure containing necessary parameters and return values
966 * @return nt status of rpc connection
969 NTSTATUS
libnet_RpcConnect_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
970 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
973 case LIBNET_RPC_CONNECT_SERVER
:
974 case LIBNET_RPC_CONNECT_BINDING
:
975 return libnet_RpcConnectSrv_recv(c
, ctx
, mem_ctx
, r
);
977 case LIBNET_RPC_CONNECT_PDC
:
978 case LIBNET_RPC_CONNECT_DC
:
979 return libnet_RpcConnectDC_recv(c
, ctx
, mem_ctx
, r
);
981 case LIBNET_RPC_CONNECT_DC_INFO
:
982 return libnet_RpcConnectDCInfo_recv(c
, ctx
, mem_ctx
, r
);
986 return NT_STATUS_INVALID_LEVEL
;
992 * Connect to a rpc pipe on a remote server - sync version
994 * @param ctx initialised libnet context
995 * @param mem_ctx memory context of this call
996 * @param r data structure containing necessary parameters and return values
997 * @return nt status of rpc connection
1000 NTSTATUS
libnet_RpcConnect(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
1001 struct libnet_RpcConnect
*r
)
1003 struct composite_context
*c
;
1005 c
= libnet_RpcConnect_send(ctx
, mem_ctx
, r
, NULL
);
1006 return libnet_RpcConnect_recv(c
, ctx
, mem_ctx
, r
);