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_proto.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
);
109 case LIBNET_RPC_CONNECT_SERVER
:
110 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
111 b
->flags
= r
->in
.dcerpc_flags
;
114 /* other types have already been checked before */
118 if (DEBUGLEVEL
>= 10) {
119 b
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
122 if (r
->level
== LIBNET_RPC_CONNECT_SERVER_ADDRESS
) {
123 b
->target_hostname
= talloc_strdup(b
, r
->in
.name
);
124 if (composite_nomem(b
->target_hostname
, c
)) {
129 /* connect to remote dcerpc pipe */
130 pipe_connect_req
= dcerpc_pipe_connect_b_send(c
, b
, r
->in
.dcerpc_iface
,
131 ctx
->cred
, c
->event_ctx
,
133 if (composite_nomem(pipe_connect_req
, c
)) return c
;
135 composite_continue(c
, pipe_connect_req
, continue_pipe_connect
, c
);
141 Step 2 of RpcConnectSrv - get rpc connection
143 static void continue_pipe_connect(struct composite_context
*ctx
)
145 struct composite_context
*c
;
146 struct rpc_connect_srv_state
*s
;
148 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
149 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
151 /* receive result of rpc pipe connection */
152 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->r
.out
.dcerpc_pipe
);
154 /* post monitor message */
156 struct monitor_msg msg
;
157 struct msg_net_rpc_connect data
;
158 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
160 /* prepare monitor message and post it */
161 data
.host
= binding
->host
;
162 data
.endpoint
= binding
->endpoint
;
163 data
.transport
= binding
->transport
;
164 data
.domain_name
= binding
->target_hostname
;
166 msg
.type
= mon_NetRpcConnect
;
167 msg
.data
= (void*)&data
;
168 msg
.data_size
= sizeof(data
);
177 * Receives result of connection to rpc pipe on remote server
179 * @param c composite context
180 * @param ctx initialised libnet context
181 * @param mem_ctx memory context of this call
182 * @param r data structure containing necessary parameters and return values
183 * @return nt status of rpc connection
186 static NTSTATUS
libnet_RpcConnectSrv_recv(struct composite_context
*c
,
187 struct libnet_context
*ctx
,
189 struct libnet_RpcConnect
*r
)
192 struct rpc_connect_srv_state
*s
= talloc_get_type(c
->private_data
,
193 struct rpc_connect_srv_state
);
195 status
= composite_wait(c
);
196 if (NT_STATUS_IS_OK(status
)) {
197 /* move the returned rpc pipe between memory contexts */
198 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
199 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
201 /* reference created pipe structure to long-term libnet_context
202 so that it can be used by other api functions even after short-term
204 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
205 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
207 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
208 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
211 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
214 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
222 struct rpc_connect_dc_state
{
223 struct libnet_context
*ctx
;
224 struct libnet_RpcConnect r
;
225 struct libnet_RpcConnect r2
;
226 struct libnet_LookupDCs f
;
227 const char *connect_name
;
229 /* information about the progress */
230 void (*monitor_fn
)(struct monitor_msg
*);
234 static void continue_lookup_dc(struct tevent_req
*req
);
235 static void continue_rpc_connect(struct composite_context
*ctx
);
239 * Initiates connection to rpc pipe on domain pdc
241 * @param ctx initialised libnet context
242 * @param mem_ctx memory context of this call
243 * @param r data structure containing necessary parameters and return values
244 * @return composite context of this call
247 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
249 struct libnet_RpcConnect
*r
,
250 void (*monitor
)(struct monitor_msg
*msg
))
252 struct composite_context
*c
;
253 struct rpc_connect_dc_state
*s
;
254 struct tevent_req
*lookup_dc_req
;
256 /* composite context allocation and setup */
257 c
= composite_create(ctx
, ctx
->event_ctx
);
258 if (c
== NULL
) return c
;
260 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
261 if (composite_nomem(s
, c
)) return c
;
264 s
->monitor_fn
= monitor
;
268 ZERO_STRUCT(s
->r
.out
);
271 case LIBNET_RPC_CONNECT_PDC
:
272 s
->f
.in
.name_type
= NBT_NAME_PDC
;
275 case LIBNET_RPC_CONNECT_DC
:
276 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
283 s
->f
.in
.domain_name
= r
->in
.name
;
284 s
->f
.out
.num_dcs
= 0;
287 /* find the domain pdc first */
288 lookup_dc_req
= libnet_LookupDCs_send(ctx
, c
, &s
->f
);
289 if (composite_nomem(lookup_dc_req
, c
)) return c
;
291 tevent_req_set_callback(lookup_dc_req
, continue_lookup_dc
, c
);
297 Step 2 of RpcConnectDC: get domain controller name and
298 initiate RpcConnect to it
300 static void continue_lookup_dc(struct tevent_req
*req
)
302 struct composite_context
*c
;
303 struct rpc_connect_dc_state
*s
;
304 struct composite_context
*rpc_connect_req
;
305 struct monitor_msg msg
;
306 struct msg_net_lookup_dc data
;
308 c
= tevent_req_callback_data(req
, struct composite_context
);
309 s
= talloc_get_type_abort(c
->private_data
, struct rpc_connect_dc_state
);
311 /* receive result of domain controller lookup */
312 c
->status
= libnet_LookupDCs_recv(req
, c
, &s
->f
);
313 if (!composite_is_ok(c
)) return;
315 /* decide on preferred address type depending on DC type */
316 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
318 /* post monitor message */
320 /* prepare a monitor message and post it */
321 data
.domain_name
= s
->f
.in
.domain_name
;
322 data
.hostname
= s
->f
.out
.dcs
[0].name
;
323 data
.address
= s
->f
.out
.dcs
[0].address
;
325 msg
.type
= mon_NetLookupDc
;
327 msg
.data_size
= sizeof(data
);
331 /* ok, pdc has been found so do attempt to rpc connect */
332 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
334 /* this will cause yet another name resolution, but at least
335 * we pass the right name down the stack now */
336 s
->r2
.in
.name
= talloc_strdup(s
, s
->connect_name
);
337 s
->r2
.in
.address
= talloc_steal(s
, s
->f
.out
.dcs
[0].address
);
338 s
->r2
.in
.dcerpc_iface
= s
->r
.in
.dcerpc_iface
;
339 s
->r2
.in
.dcerpc_flags
= s
->r
.in
.dcerpc_flags
;
341 /* send rpc connect request to the server */
342 rpc_connect_req
= libnet_RpcConnectSrv_send(s
->ctx
, c
, &s
->r2
, s
->monitor_fn
);
343 if (composite_nomem(rpc_connect_req
, c
)) return;
345 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
350 Step 3 of RpcConnectDC: get rpc connection to the server
352 static void continue_rpc_connect(struct composite_context
*ctx
)
354 struct composite_context
*c
;
355 struct rpc_connect_dc_state
*s
;
357 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
358 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
360 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
362 /* error string is to be passed anyway */
363 s
->r
.out
.error_string
= s
->r2
.out
.error_string
;
364 if (!composite_is_ok(c
)) return;
366 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
368 /* post monitor message */
370 struct monitor_msg msg
;
371 struct msg_net_rpc_connect data
;
372 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
374 data
.host
= binding
->host
;
375 data
.endpoint
= binding
->endpoint
;
376 data
.transport
= binding
->transport
;
377 data
.domain_name
= binding
->target_hostname
;
379 msg
.type
= mon_NetRpcConnect
;
380 msg
.data
= (void*)&data
;
381 msg
.data_size
= sizeof(data
);
390 * Receives result of connection to rpc pipe on domain pdc
392 * @param c composite context
393 * @param ctx initialised libnet context
394 * @param mem_ctx memory context of this call
395 * @param r data structure containing necessary parameters and return values
396 * @return nt status of rpc connection
399 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
400 struct libnet_context
*ctx
,
402 struct libnet_RpcConnect
*r
)
405 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
406 struct rpc_connect_dc_state
);
408 status
= composite_wait(c
);
409 if (NT_STATUS_IS_OK(status
)) {
410 /* move connected rpc pipe between memory contexts
412 The use of talloc_reparent(talloc_parent(), ...) is
413 bizarre, but it is needed because of the absolutely
414 atrocious use of talloc in this code. We need to
415 force the original parent to change, but finding
416 the original parent is well nigh impossible at this
417 point in the code (yes, I tried).
419 r
->out
.dcerpc_pipe
= talloc_reparent(talloc_parent(s
->r
.out
.dcerpc_pipe
),
420 mem_ctx
, s
->r
.out
.dcerpc_pipe
);
422 /* reference created pipe structure to long-term libnet_context
423 so that it can be used by other api functions even after short-term
425 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
426 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
428 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
429 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
433 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
434 "Failed to rpc connect: %s",
444 struct rpc_connect_dci_state
{
445 struct libnet_context
*ctx
;
446 struct libnet_RpcConnect r
;
447 struct libnet_RpcConnect rpc_conn
;
448 struct policy_handle lsa_handle
;
449 struct lsa_QosInfo qos
;
450 struct lsa_ObjectAttribute attr
;
451 struct lsa_OpenPolicy2 lsa_open_policy
;
452 struct dcerpc_pipe
*lsa_pipe
;
453 struct lsa_QueryInfoPolicy2 lsa_query_info2
;
454 struct lsa_QueryInfoPolicy lsa_query_info
;
455 struct dcerpc_binding
*final_binding
;
456 struct dcerpc_pipe
*final_pipe
;
458 /* information about the progress */
459 void (*monitor_fn
)(struct monitor_msg
*);
463 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
464 static void continue_lsa_policy(struct tevent_req
*subreq
);
465 static void continue_lsa_query_info(struct tevent_req
*subreq
);
466 static void continue_lsa_query_info2(struct tevent_req
*subreq
);
467 static void continue_epm_map_binding(struct composite_context
*ctx
);
468 static void continue_secondary_conn(struct composite_context
*ctx
);
469 static void continue_epm_map_binding_send(struct composite_context
*c
);
473 * Initiates connection to rpc pipe on remote server or pdc. Received result
474 * contains info on the domain name, domain sid and realm.
476 * @param ctx initialised libnet context
477 * @param mem_ctx memory context of this call
478 * @param r data structure containing necessary parameters and return values. Must be a talloc context
479 * @return composite context of this call
482 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
484 struct libnet_RpcConnect
*r
,
485 void (*monitor
)(struct monitor_msg
*))
487 struct composite_context
*c
, *conn_req
;
488 struct rpc_connect_dci_state
*s
;
490 /* composite context allocation and setup */
491 c
= composite_create(ctx
, ctx
->event_ctx
);
492 if (c
== NULL
) return c
;
494 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
495 if (composite_nomem(s
, c
)) return c
;
498 s
->monitor_fn
= monitor
;
502 ZERO_STRUCT(s
->r
.out
);
505 /* proceed to pure rpc connection if the binding string is provided,
506 otherwise try to connect domain controller */
507 if (r
->in
.binding
== NULL
) {
508 /* Pass on any binding flags (such as anonymous fallback) that have been set */
509 s
->rpc_conn
.in
.dcerpc_flags
= r
->in
.dcerpc_flags
;
511 s
->rpc_conn
.in
.name
= r
->in
.name
;
512 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
514 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
515 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
518 /* we need to query information on lsarpc interface first */
519 s
->rpc_conn
.in
.dcerpc_iface
= &ndr_table_lsarpc
;
521 /* request connection to the lsa pipe on the pdc */
522 conn_req
= libnet_RpcConnect_send(ctx
, c
, &s
->rpc_conn
, s
->monitor_fn
);
523 if (composite_nomem(c
, conn_req
)) return c
;
525 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
531 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
534 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
536 struct composite_context
*c
;
537 struct rpc_connect_dci_state
*s
;
538 struct tevent_req
*subreq
;
540 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
541 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
543 c
->status
= libnet_RpcConnect_recv(ctx
, s
->ctx
, c
, &s
->rpc_conn
);
544 if (!NT_STATUS_IS_OK(c
->status
)) {
545 composite_error(c
, c
->status
);
549 /* post monitor message */
551 struct monitor_msg msg
;
552 struct msg_net_rpc_connect data
;
553 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
555 data
.host
= binding
->host
;
556 data
.endpoint
= binding
->endpoint
;
557 data
.transport
= binding
->transport
;
558 data
.domain_name
= binding
->target_hostname
;
560 msg
.type
= mon_NetRpcConnect
;
561 msg
.data
= (void*)&data
;
562 msg
.data_size
= sizeof(data
);
566 /* prepare to open a policy handle on lsa pipe */
567 s
->lsa_pipe
= s
->ctx
->lsa
.pipe
;
570 s
->qos
.impersonation_level
= 2;
571 s
->qos
.context_mode
= 1;
572 s
->qos
.effective_only
= 0;
574 s
->attr
.sec_qos
= &s
->qos
;
576 if (s
->lsa_pipe
->binding
->transport
== NCACN_IP_TCP
) {
578 * Skip to creating the actual connection. We can't open a
579 * policy handle over tcpip.
581 continue_epm_map_binding_send(c
);
585 s
->lsa_open_policy
.in
.attr
= &s
->attr
;
586 s
->lsa_open_policy
.in
.system_name
= talloc_asprintf(c
, "\\");
587 if (composite_nomem(s
->lsa_open_policy
.in
.system_name
, c
)) return;
589 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
590 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
592 subreq
= dcerpc_lsa_OpenPolicy2_r_send(s
, c
->event_ctx
,
593 s
->lsa_pipe
->binding_handle
,
594 &s
->lsa_open_policy
);
595 if (composite_nomem(subreq
, c
)) return;
597 tevent_req_set_callback(subreq
, continue_lsa_policy
, c
);
602 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
603 for kerberos realm (dns name) and guid. The query may fail.
605 static void continue_lsa_policy(struct tevent_req
*subreq
)
607 struct composite_context
*c
;
608 struct rpc_connect_dci_state
*s
;
610 c
= tevent_req_callback_data(subreq
, struct composite_context
);
611 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
613 c
->status
= dcerpc_lsa_OpenPolicy2_r_recv(subreq
, s
);
615 if (!NT_STATUS_IS_OK(c
->status
)) {
616 composite_error(c
, c
->status
);
620 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
621 s
->r
.out
.realm
= NULL
;
622 s
->r
.out
.guid
= NULL
;
623 s
->r
.out
.domain_name
= NULL
;
624 s
->r
.out
.domain_sid
= NULL
;
626 /* Skip to the creating the actual connection, no info available on this transport */
627 continue_epm_map_binding_send(c
);
630 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
631 composite_error(c
, s
->lsa_open_policy
.out
.result
);
635 /* post monitor message */
637 struct monitor_msg msg
;
639 msg
.type
= mon_LsaOpenPolicy
;
645 /* query lsa info for dns domain name and guid */
646 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
647 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
648 s
->lsa_query_info2
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
649 if (composite_nomem(s
->lsa_query_info2
.out
.info
, c
)) return;
651 subreq
= dcerpc_lsa_QueryInfoPolicy2_r_send(s
, c
->event_ctx
,
652 s
->lsa_pipe
->binding_handle
,
653 &s
->lsa_query_info2
);
654 if (composite_nomem(subreq
, c
)) return;
656 tevent_req_set_callback(subreq
, continue_lsa_query_info2
, c
);
661 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
662 may result in failure) and query lsa info for domain name and sid.
664 static void continue_lsa_query_info2(struct tevent_req
*subreq
)
666 struct composite_context
*c
;
667 struct rpc_connect_dci_state
*s
;
669 c
= tevent_req_callback_data(subreq
, struct composite_context
);
670 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
672 c
->status
= dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq
, s
);
675 /* In case of error just null the realm and guid and proceed
676 to the next step. After all, it doesn't have to be AD domain
677 controller we talking to - NT-style PDC also counts */
679 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
680 s
->r
.out
.realm
= NULL
;
681 s
->r
.out
.guid
= NULL
;
684 if (!NT_STATUS_IS_OK(c
->status
)) {
685 s
->r
.out
.error_string
= talloc_asprintf(c
,
686 "lsa_QueryInfoPolicy2 failed: %s",
687 nt_errstr(c
->status
));
688 composite_error(c
, c
->status
);
692 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
693 s
->r
.out
.error_string
= talloc_asprintf(c
,
694 "lsa_QueryInfoPolicy2 failed: %s",
695 nt_errstr(s
->lsa_query_info2
.out
.result
));
696 composite_error(c
, s
->lsa_query_info2
.out
.result
);
700 /* Copy the dns domain name and guid from the query result */
702 /* this should actually be a conversion from lsa_StringLarge */
703 s
->r
.out
.realm
= (*s
->lsa_query_info2
.out
.info
)->dns
.dns_domain
.string
;
704 s
->r
.out
.guid
= talloc(c
, struct GUID
);
705 if (composite_nomem(s
->r
.out
.guid
, c
)) {
706 s
->r
.out
.error_string
= NULL
;
709 *s
->r
.out
.guid
= (*s
->lsa_query_info2
.out
.info
)->dns
.domain_guid
;
712 /* post monitor message */
714 struct monitor_msg msg
;
716 msg
.type
= mon_LsaQueryPolicy
;
722 /* query lsa info for domain name and sid */
723 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
724 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
725 s
->lsa_query_info
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
726 if (composite_nomem(s
->lsa_query_info
.out
.info
, c
)) return;
728 subreq
= dcerpc_lsa_QueryInfoPolicy_r_send(s
, c
->event_ctx
,
729 s
->lsa_pipe
->binding_handle
,
731 if (composite_nomem(subreq
, c
)) return;
733 tevent_req_set_callback(subreq
, continue_lsa_query_info
, c
);
738 Step 5 of RpcConnectDCInfo: Get domain name and sid
740 static void continue_lsa_query_info(struct tevent_req
*subreq
)
742 struct composite_context
*c
;
743 struct rpc_connect_dci_state
*s
;
745 c
= tevent_req_callback_data(subreq
, struct composite_context
);
746 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
748 c
->status
= dcerpc_lsa_QueryInfoPolicy_r_recv(subreq
, s
);
750 if (!NT_STATUS_IS_OK(c
->status
)) {
751 s
->r
.out
.error_string
= talloc_asprintf(c
,
752 "lsa_QueryInfoPolicy failed: %s",
753 nt_errstr(c
->status
));
754 composite_error(c
, c
->status
);
758 /* post monitor message */
760 struct monitor_msg msg
;
762 msg
.type
= mon_LsaQueryPolicy
;
768 /* Copy the domain name and sid from the query result */
769 s
->r
.out
.domain_sid
= (*s
->lsa_query_info
.out
.info
)->domain
.sid
;
770 s
->r
.out
.domain_name
= (*s
->lsa_query_info
.out
.info
)->domain
.name
.string
;
772 continue_epm_map_binding_send(c
);
776 Step 5 (continued) of RpcConnectDCInfo: request endpoint
779 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
781 static void continue_epm_map_binding_send(struct composite_context
*c
)
783 struct rpc_connect_dci_state
*s
;
784 struct composite_context
*epm_map_req
;
785 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
787 /* prepare to get endpoint mapping for the requested interface */
788 s
->final_binding
= talloc_zero(s
, struct dcerpc_binding
);
789 if (composite_nomem(s
->final_binding
, c
)) return;
791 *s
->final_binding
= *s
->lsa_pipe
->binding
;
792 /* Ensure we keep hold of the member elements */
793 if (composite_nomem(talloc_reference(s
->final_binding
, s
->lsa_pipe
->binding
), c
)) return;
795 epm_map_req
= dcerpc_epm_map_binding_send(c
, s
->final_binding
, s
->r
.in
.dcerpc_iface
,
796 s
->lsa_pipe
->conn
->event_ctx
, s
->ctx
->lp_ctx
);
797 if (composite_nomem(epm_map_req
, c
)) return;
799 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
803 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
804 rpc connection derived from already used pipe but connected to the requested
805 one (as specified in libnet_RpcConnect structure)
807 static void continue_epm_map_binding(struct composite_context
*ctx
)
809 struct composite_context
*c
, *sec_conn_req
;
810 struct rpc_connect_dci_state
*s
;
812 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
813 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
815 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
816 if (!NT_STATUS_IS_OK(c
->status
)) {
817 s
->r
.out
.error_string
= talloc_asprintf(c
,
818 "failed to map pipe with endpoint mapper - %s",
819 nt_errstr(c
->status
));
820 composite_error(c
, c
->status
);
824 /* create secondary connection derived from lsa pipe */
825 sec_conn_req
= dcerpc_secondary_connection_send(s
->lsa_pipe
, s
->final_binding
);
826 if (composite_nomem(sec_conn_req
, c
)) return;
828 composite_continue(c
, sec_conn_req
, continue_secondary_conn
, c
);
833 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
834 and complete this composite call
836 static void continue_secondary_conn(struct composite_context
*ctx
)
838 struct composite_context
*c
;
839 struct rpc_connect_dci_state
*s
;
841 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
842 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
844 c
->status
= dcerpc_secondary_connection_recv(ctx
, &s
->final_pipe
);
845 if (!NT_STATUS_IS_OK(c
->status
)) {
846 s
->r
.out
.error_string
= talloc_asprintf(c
,
847 "secondary connection failed: %s",
848 nt_errstr(c
->status
));
850 composite_error(c
, c
->status
);
854 s
->r
.out
.dcerpc_pipe
= s
->final_pipe
;
856 /* post monitor message */
858 struct monitor_msg msg
;
859 struct msg_net_rpc_connect data
;
860 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
862 /* prepare monitor message and post it */
863 data
.host
= binding
->host
;
864 data
.endpoint
= binding
->endpoint
;
865 data
.transport
= binding
->transport
;
866 data
.domain_name
= binding
->target_hostname
;
868 msg
.type
= mon_NetRpcConnect
;
869 msg
.data
= (void*)&data
;
870 msg
.data_size
= sizeof(data
);
879 * Receives result of connection to rpc pipe and gets basic
880 * domain info (name, sid, realm, guid)
882 * @param c composite context
883 * @param ctx initialised libnet context
884 * @param mem_ctx memory context of this call
885 * @param r data structure containing return values
886 * @return nt status of rpc connection
889 static NTSTATUS
libnet_RpcConnectDCInfo_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
890 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
893 struct rpc_connect_dci_state
*s
= talloc_get_type(c
->private_data
,
894 struct rpc_connect_dci_state
);
896 status
= composite_wait(c
);
897 if (NT_STATUS_IS_OK(status
)) {
898 r
->out
.realm
= talloc_steal(mem_ctx
, s
->r
.out
.realm
);
899 r
->out
.guid
= talloc_steal(mem_ctx
, s
->r
.out
.guid
);
900 r
->out
.domain_name
= talloc_steal(mem_ctx
, s
->r
.out
.domain_name
);
901 r
->out
.domain_sid
= talloc_steal(mem_ctx
, s
->r
.out
.domain_sid
);
903 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
905 /* reference created pipe structure to long-term libnet_context
906 so that it can be used by other api functions even after short-term
908 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
909 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
910 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
912 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
913 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
914 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
918 if (s
->r
.out
.error_string
) {
919 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
920 } else if (r
->in
.binding
== NULL
) {
921 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC failed: %s", nt_errstr(status
));
923 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC %s failed: %s",
924 r
->in
.binding
, nt_errstr(status
));
934 * Initiates connection to rpc pipe on remote server or pdc, optionally
935 * providing domain info
937 * @param ctx initialised libnet context
938 * @param mem_ctx memory context of this call
939 * @param r data structure containing necessary parameters and return values
940 * @return composite context of this call
943 struct composite_context
* libnet_RpcConnect_send(struct libnet_context
*ctx
,
945 struct libnet_RpcConnect
*r
,
946 void (*monitor
)(struct monitor_msg
*))
948 struct composite_context
*c
;
951 case LIBNET_RPC_CONNECT_SERVER
:
952 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
953 case LIBNET_RPC_CONNECT_BINDING
:
954 c
= libnet_RpcConnectSrv_send(ctx
, mem_ctx
, r
, monitor
);
957 case LIBNET_RPC_CONNECT_PDC
:
958 case LIBNET_RPC_CONNECT_DC
:
959 c
= libnet_RpcConnectDC_send(ctx
, mem_ctx
, r
, monitor
);
962 case LIBNET_RPC_CONNECT_DC_INFO
:
963 c
= libnet_RpcConnectDCInfo_send(ctx
, mem_ctx
, r
, monitor
);
967 c
= talloc_zero(mem_ctx
, struct composite_context
);
968 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
976 * Receives result of connection to rpc pipe on remote server or pdc
978 * @param c composite context
979 * @param ctx initialised libnet context
980 * @param mem_ctx memory context of this call
981 * @param r data structure containing necessary parameters and return values
982 * @return nt status of rpc connection
985 NTSTATUS
libnet_RpcConnect_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
986 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
989 case LIBNET_RPC_CONNECT_SERVER
:
990 case LIBNET_RPC_CONNECT_BINDING
:
991 return libnet_RpcConnectSrv_recv(c
, ctx
, mem_ctx
, r
);
993 case LIBNET_RPC_CONNECT_PDC
:
994 case LIBNET_RPC_CONNECT_DC
:
995 return libnet_RpcConnectDC_recv(c
, ctx
, mem_ctx
, r
);
997 case LIBNET_RPC_CONNECT_DC_INFO
:
998 return libnet_RpcConnectDCInfo_recv(c
, ctx
, mem_ctx
, r
);
1001 ZERO_STRUCT(r
->out
);
1002 return NT_STATUS_INVALID_LEVEL
;
1008 * Connect to a rpc pipe on a remote server - sync version
1010 * @param ctx initialised libnet context
1011 * @param mem_ctx memory context of this call
1012 * @param r data structure containing necessary parameters and return values
1013 * @return nt status of rpc connection
1016 NTSTATUS
libnet_RpcConnect(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
1017 struct libnet_RpcConnect
*r
)
1019 struct composite_context
*c
;
1021 c
= libnet_RpcConnect_send(ctx
, mem_ctx
, r
, NULL
);
1022 return libnet_RpcConnect_recv(c
, ctx
, mem_ctx
, r
);