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"
28 #include "auth/credentials/credentials.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[target_hostname=%s]",
83 r
->in
.address
, r
->in
.name
);
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 c
->status
= dcerpc_binding_set_flags(b
, r
->in
.dcerpc_flags
, 0);
113 if (!composite_is_ok(c
)) return c
;
116 /* other types have already been checked before */
120 if (DEBUGLEVEL
>= 10) {
121 c
->status
= dcerpc_binding_set_flags(b
, DCERPC_DEBUG_PRINT_BOTH
, 0);
122 if (!composite_is_ok(c
)) return c
;
125 /* connect to remote dcerpc pipe */
126 pipe_connect_req
= dcerpc_pipe_connect_b_send(c
, b
, r
->in
.dcerpc_iface
,
127 ctx
->cred
, c
->event_ctx
,
129 if (composite_nomem(pipe_connect_req
, c
)) return c
;
131 composite_continue(c
, pipe_connect_req
, continue_pipe_connect
, c
);
137 Step 2 of RpcConnectSrv - get rpc connection
139 static void continue_pipe_connect(struct composite_context
*ctx
)
141 struct composite_context
*c
;
142 struct rpc_connect_srv_state
*s
;
144 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
145 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
147 /* receive result of rpc pipe connection */
148 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->r
.out
.dcerpc_pipe
);
150 /* post monitor message */
152 struct monitor_msg msg
;
153 struct msg_net_rpc_connect data
;
154 const struct dcerpc_binding
*b
= s
->r
.out
.dcerpc_pipe
->binding
;
156 /* prepare monitor message and post it */
157 data
.host
= dcerpc_binding_get_string_option(b
, "host");
158 data
.endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
159 data
.transport
= dcerpc_binding_get_transport(b
);
160 data
.domain_name
= dcerpc_binding_get_string_option(b
, "target_hostname");
162 msg
.type
= mon_NetRpcConnect
;
163 msg
.data
= (void*)&data
;
164 msg
.data_size
= sizeof(data
);
173 * Receives result of connection to rpc pipe on remote server
175 * @param c composite context
176 * @param ctx initialised libnet context
177 * @param mem_ctx memory context of this call
178 * @param r data structure containing necessary parameters and return values
179 * @return nt status of rpc connection
182 static NTSTATUS
libnet_RpcConnectSrv_recv(struct composite_context
*c
,
183 struct libnet_context
*ctx
,
185 struct libnet_RpcConnect
*r
)
189 status
= composite_wait(c
);
190 if (NT_STATUS_IS_OK(status
)) {
191 struct rpc_connect_srv_state
*s
;
193 /* move the returned rpc pipe between memory contexts */
194 s
= talloc_get_type(c
->private_data
, struct rpc_connect_srv_state
);
195 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
197 /* reference created pipe structure to long-term libnet_context
198 so that it can be used by other api functions even after short-term
200 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
201 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
202 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
204 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
205 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
206 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
209 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
212 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
220 struct rpc_connect_dc_state
{
221 struct libnet_context
*ctx
;
222 struct libnet_RpcConnect r
;
223 struct libnet_RpcConnect r2
;
224 struct libnet_LookupDCs f
;
225 const char *connect_name
;
227 /* information about the progress */
228 void (*monitor_fn
)(struct monitor_msg
*);
232 static void continue_lookup_dc(struct tevent_req
*req
);
233 static void continue_rpc_connect(struct composite_context
*ctx
);
237 * Initiates connection to rpc pipe on domain pdc
239 * @param ctx initialised libnet context
240 * @param mem_ctx memory context of this call
241 * @param r data structure containing necessary parameters and return values
242 * @return composite context of this call
245 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
247 struct libnet_RpcConnect
*r
,
248 void (*monitor
)(struct monitor_msg
*msg
))
250 struct composite_context
*c
;
251 struct rpc_connect_dc_state
*s
;
252 struct tevent_req
*lookup_dc_req
;
254 /* composite context allocation and setup */
255 c
= composite_create(ctx
, ctx
->event_ctx
);
256 if (c
== NULL
) return c
;
258 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
259 if (composite_nomem(s
, c
)) return c
;
262 s
->monitor_fn
= monitor
;
266 ZERO_STRUCT(s
->r
.out
);
269 case LIBNET_RPC_CONNECT_PDC
:
270 s
->f
.in
.name_type
= NBT_NAME_PDC
;
273 case LIBNET_RPC_CONNECT_DC
:
274 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
281 s
->f
.in
.domain_name
= r
->in
.name
;
282 s
->f
.out
.num_dcs
= 0;
285 /* find the domain pdc first */
286 lookup_dc_req
= libnet_LookupDCs_send(ctx
, c
, &s
->f
);
287 if (composite_nomem(lookup_dc_req
, c
)) return c
;
289 tevent_req_set_callback(lookup_dc_req
, continue_lookup_dc
, c
);
295 Step 2 of RpcConnectDC: get domain controller name and
296 initiate RpcConnect to it
298 static void continue_lookup_dc(struct tevent_req
*req
)
300 struct composite_context
*c
;
301 struct rpc_connect_dc_state
*s
;
302 struct composite_context
*rpc_connect_req
;
303 struct monitor_msg msg
;
304 struct msg_net_lookup_dc data
;
306 c
= tevent_req_callback_data(req
, struct composite_context
);
307 s
= talloc_get_type_abort(c
->private_data
, struct rpc_connect_dc_state
);
309 /* receive result of domain controller lookup */
310 c
->status
= libnet_LookupDCs_recv(req
, c
, &s
->f
);
311 if (!composite_is_ok(c
)) return;
313 /* decide on preferred address type depending on DC type */
314 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
316 /* post monitor message */
318 /* prepare a monitor message and post it */
319 data
.domain_name
= s
->f
.in
.domain_name
;
320 data
.hostname
= s
->f
.out
.dcs
[0].name
;
321 data
.address
= s
->f
.out
.dcs
[0].address
;
323 msg
.type
= mon_NetLookupDc
;
325 msg
.data_size
= sizeof(data
);
329 /* ok, pdc has been found so do attempt to rpc connect */
330 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
332 /* this will cause yet another name resolution, but at least
333 * we pass the right name down the stack now */
334 s
->r2
.in
.name
= talloc_strdup(s
, s
->connect_name
);
335 s
->r2
.in
.address
= talloc_steal(s
, s
->f
.out
.dcs
[0].address
);
336 s
->r2
.in
.dcerpc_iface
= s
->r
.in
.dcerpc_iface
;
337 s
->r2
.in
.dcerpc_flags
= s
->r
.in
.dcerpc_flags
;
339 /* send rpc connect request to the server */
340 rpc_connect_req
= libnet_RpcConnectSrv_send(s
->ctx
, c
, &s
->r2
, s
->monitor_fn
);
341 if (composite_nomem(rpc_connect_req
, c
)) return;
343 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
348 Step 3 of RpcConnectDC: get rpc connection to the server
350 static void continue_rpc_connect(struct composite_context
*ctx
)
352 struct composite_context
*c
;
353 struct rpc_connect_dc_state
*s
;
355 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
356 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
358 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
360 /* error string is to be passed anyway */
361 s
->r
.out
.error_string
= s
->r2
.out
.error_string
;
362 if (!composite_is_ok(c
)) return;
364 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
366 /* post monitor message */
368 struct monitor_msg msg
;
369 struct msg_net_rpc_connect data
;
370 const struct dcerpc_binding
*b
= s
->r
.out
.dcerpc_pipe
->binding
;
372 data
.host
= dcerpc_binding_get_string_option(b
, "host");
373 data
.endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
374 data
.transport
= dcerpc_binding_get_transport(b
);
375 data
.domain_name
= dcerpc_binding_get_string_option(b
, "target_hostname");
377 msg
.type
= mon_NetRpcConnect
;
378 msg
.data
= (void*)&data
;
379 msg
.data_size
= sizeof(data
);
388 * Receives result of connection to rpc pipe on domain pdc
390 * @param c composite context
391 * @param ctx initialised libnet context
392 * @param mem_ctx memory context of this call
393 * @param r data structure containing necessary parameters and return values
394 * @return nt status of rpc connection
397 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
398 struct libnet_context
*ctx
,
400 struct libnet_RpcConnect
*r
)
403 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
404 struct rpc_connect_dc_state
);
406 status
= composite_wait(c
);
407 if (NT_STATUS_IS_OK(status
)) {
408 /* move connected rpc pipe between memory contexts
410 The use of talloc_reparent(talloc_parent(), ...) is
411 bizarre, but it is needed because of the absolutely
412 atrocious use of talloc in this code. We need to
413 force the original parent to change, but finding
414 the original parent is well nigh impossible at this
415 point in the code (yes, I tried).
417 r
->out
.dcerpc_pipe
= talloc_reparent(talloc_parent(s
->r
.out
.dcerpc_pipe
),
418 mem_ctx
, s
->r
.out
.dcerpc_pipe
);
420 /* reference created pipe structure to long-term libnet_context
421 so that it can be used by other api functions even after short-term
423 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
424 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
425 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
426 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
427 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
428 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
432 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
433 "Failed to rpc connect: %s",
443 struct rpc_connect_dci_state
{
444 struct libnet_context
*ctx
;
445 struct libnet_RpcConnect r
;
446 struct libnet_RpcConnect rpc_conn
;
447 struct policy_handle lsa_handle
;
448 struct lsa_QosInfo qos
;
449 struct lsa_ObjectAttribute attr
;
450 struct lsa_OpenPolicy2 lsa_open_policy
;
451 struct dcerpc_pipe
*lsa_pipe
;
452 struct lsa_QueryInfoPolicy2 lsa_query_info2
;
453 struct lsa_QueryInfoPolicy lsa_query_info
;
454 struct dcerpc_binding
*final_binding
;
455 struct dcerpc_pipe
*final_pipe
;
457 /* information about the progress */
458 void (*monitor_fn
)(struct monitor_msg
*);
462 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
463 static void continue_lsa_policy(struct tevent_req
*subreq
);
464 static void continue_lsa_query_info(struct tevent_req
*subreq
);
465 static void continue_lsa_query_info2(struct tevent_req
*subreq
);
466 static void continue_epm_map_binding(struct composite_context
*ctx
);
467 static void continue_secondary_conn(struct composite_context
*ctx
);
468 static void continue_epm_map_binding_send(struct composite_context
*c
);
472 * Initiates connection to rpc pipe on remote server or pdc. Received result
473 * contains info on the domain name, domain sid and realm.
475 * @param ctx initialised libnet context
476 * @param mem_ctx memory context of this call
477 * @param r data structure containing necessary parameters and return values. Must be a talloc context
478 * @return composite context of this call
481 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
483 struct libnet_RpcConnect
*r
,
484 void (*monitor
)(struct monitor_msg
*))
486 struct composite_context
*c
, *conn_req
;
487 struct rpc_connect_dci_state
*s
;
489 /* composite context allocation and setup */
490 c
= composite_create(ctx
, ctx
->event_ctx
);
491 if (c
== NULL
) return c
;
493 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
494 if (composite_nomem(s
, c
)) return c
;
497 s
->monitor_fn
= monitor
;
501 ZERO_STRUCT(s
->r
.out
);
504 /* proceed to pure rpc connection if the binding string is provided,
505 otherwise try to connect domain controller */
506 if (r
->in
.binding
== NULL
) {
507 /* Pass on any binding flags (such as anonymous fallback) that have been set */
508 s
->rpc_conn
.in
.dcerpc_flags
= r
->in
.dcerpc_flags
;
510 s
->rpc_conn
.in
.name
= r
->in
.name
;
511 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
513 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
514 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
517 /* we need to query information on lsarpc interface first */
518 s
->rpc_conn
.in
.dcerpc_iface
= &ndr_table_lsarpc
;
520 /* request connection to the lsa pipe on the pdc */
521 conn_req
= libnet_RpcConnect_send(ctx
, c
, &s
->rpc_conn
, s
->monitor_fn
);
522 if (composite_nomem(c
, conn_req
)) return c
;
524 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
530 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
533 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
535 struct composite_context
*c
;
536 struct rpc_connect_dci_state
*s
;
537 struct tevent_req
*subreq
;
538 enum dcerpc_transport_t transport
;
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 const struct dcerpc_binding
*b
= s
->r
.out
.dcerpc_pipe
->binding
;
555 data
.host
= dcerpc_binding_get_string_option(b
, "host");
556 data
.endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
557 data
.transport
= dcerpc_binding_get_transport(b
);
558 data
.domain_name
= dcerpc_binding_get_string_option(b
, "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 transport
= dcerpc_binding_get_transport(s
->lsa_pipe
->binding
);
577 if (transport
== NCACN_IP_TCP
) {
579 * Skip to creating the actual connection. We can't open a
580 * policy handle over tcpip.
582 continue_epm_map_binding_send(c
);
586 s
->lsa_open_policy
.in
.attr
= &s
->attr
;
587 s
->lsa_open_policy
.in
.system_name
= talloc_asprintf(c
, "\\");
588 if (composite_nomem(s
->lsa_open_policy
.in
.system_name
, c
)) return;
590 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
591 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
593 subreq
= dcerpc_lsa_OpenPolicy2_r_send(s
, c
->event_ctx
,
594 s
->lsa_pipe
->binding_handle
,
595 &s
->lsa_open_policy
);
596 if (composite_nomem(subreq
, c
)) return;
598 tevent_req_set_callback(subreq
, continue_lsa_policy
, c
);
603 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
604 for kerberos realm (dns name) and guid. The query may fail.
606 static void continue_lsa_policy(struct tevent_req
*subreq
)
608 struct composite_context
*c
;
609 struct rpc_connect_dci_state
*s
;
611 c
= tevent_req_callback_data(subreq
, struct composite_context
);
612 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
614 c
->status
= dcerpc_lsa_OpenPolicy2_r_recv(subreq
, s
);
616 if (!NT_STATUS_IS_OK(c
->status
)) {
617 composite_error(c
, c
->status
);
621 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
622 s
->r
.out
.realm
= NULL
;
623 s
->r
.out
.guid
= NULL
;
624 s
->r
.out
.domain_name
= NULL
;
625 s
->r
.out
.domain_sid
= NULL
;
627 /* Skip to the creating the actual connection, no info available on this transport */
628 continue_epm_map_binding_send(c
);
631 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
632 composite_error(c
, s
->lsa_open_policy
.out
.result
);
636 /* post monitor message */
638 struct monitor_msg msg
;
640 msg
.type
= mon_LsaOpenPolicy
;
646 /* query lsa info for dns domain name and guid */
647 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
648 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
649 s
->lsa_query_info2
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
650 if (composite_nomem(s
->lsa_query_info2
.out
.info
, c
)) return;
652 subreq
= dcerpc_lsa_QueryInfoPolicy2_r_send(s
, c
->event_ctx
,
653 s
->lsa_pipe
->binding_handle
,
654 &s
->lsa_query_info2
);
655 if (composite_nomem(subreq
, c
)) return;
657 tevent_req_set_callback(subreq
, continue_lsa_query_info2
, c
);
662 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
663 may result in failure) and query lsa info for domain name and sid.
665 static void continue_lsa_query_info2(struct tevent_req
*subreq
)
667 struct composite_context
*c
;
668 struct rpc_connect_dci_state
*s
;
670 c
= tevent_req_callback_data(subreq
, struct composite_context
);
671 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
673 c
->status
= dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq
, s
);
676 /* In case of error just null the realm and guid and proceed
677 to the next step. After all, it doesn't have to be AD domain
678 controller we talking to - NT-style PDC also counts */
680 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
681 s
->r
.out
.realm
= NULL
;
682 s
->r
.out
.guid
= NULL
;
685 if (!NT_STATUS_IS_OK(c
->status
)) {
686 s
->r
.out
.error_string
= talloc_asprintf(c
,
687 "lsa_QueryInfoPolicy2 failed: %s",
688 nt_errstr(c
->status
));
689 composite_error(c
, c
->status
);
693 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
694 s
->r
.out
.error_string
= talloc_asprintf(c
,
695 "lsa_QueryInfoPolicy2 failed: %s",
696 nt_errstr(s
->lsa_query_info2
.out
.result
));
697 composite_error(c
, s
->lsa_query_info2
.out
.result
);
701 /* Copy the dns domain name and guid from the query result */
703 /* this should actually be a conversion from lsa_StringLarge */
704 s
->r
.out
.realm
= (*s
->lsa_query_info2
.out
.info
)->dns
.dns_domain
.string
;
705 s
->r
.out
.guid
= talloc(c
, struct GUID
);
706 if (composite_nomem(s
->r
.out
.guid
, c
)) {
707 s
->r
.out
.error_string
= NULL
;
710 *s
->r
.out
.guid
= (*s
->lsa_query_info2
.out
.info
)->dns
.domain_guid
;
713 /* post monitor message */
715 struct monitor_msg msg
;
717 msg
.type
= mon_LsaQueryPolicy
;
723 /* query lsa info for domain name and sid */
724 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
725 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
726 s
->lsa_query_info
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
727 if (composite_nomem(s
->lsa_query_info
.out
.info
, c
)) return;
729 subreq
= dcerpc_lsa_QueryInfoPolicy_r_send(s
, c
->event_ctx
,
730 s
->lsa_pipe
->binding_handle
,
732 if (composite_nomem(subreq
, c
)) return;
734 tevent_req_set_callback(subreq
, continue_lsa_query_info
, c
);
739 Step 5 of RpcConnectDCInfo: Get domain name and sid
741 static void continue_lsa_query_info(struct tevent_req
*subreq
)
743 struct composite_context
*c
;
744 struct rpc_connect_dci_state
*s
;
746 c
= tevent_req_callback_data(subreq
, struct composite_context
);
747 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
749 c
->status
= dcerpc_lsa_QueryInfoPolicy_r_recv(subreq
, s
);
751 if (!NT_STATUS_IS_OK(c
->status
)) {
752 s
->r
.out
.error_string
= talloc_asprintf(c
,
753 "lsa_QueryInfoPolicy failed: %s",
754 nt_errstr(c
->status
));
755 composite_error(c
, c
->status
);
759 /* post monitor message */
761 struct monitor_msg msg
;
763 msg
.type
= mon_LsaQueryPolicy
;
769 /* Copy the domain name and sid from the query result */
770 s
->r
.out
.domain_sid
= (*s
->lsa_query_info
.out
.info
)->domain
.sid
;
771 s
->r
.out
.domain_name
= (*s
->lsa_query_info
.out
.info
)->domain
.name
.string
;
773 continue_epm_map_binding_send(c
);
777 Step 5 (continued) of RpcConnectDCInfo: request endpoint
780 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
782 static void continue_epm_map_binding_send(struct composite_context
*c
)
784 struct rpc_connect_dci_state
*s
;
785 struct composite_context
*epm_map_req
;
786 struct cli_credentials
*epm_creds
= NULL
;
788 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
790 /* prepare to get endpoint mapping for the requested interface */
791 s
->final_binding
= dcerpc_binding_dup(s
, s
->lsa_pipe
->binding
);
792 if (composite_nomem(s
->final_binding
, c
)) return;
794 epm_creds
= cli_credentials_init_anon(s
);
795 if (composite_nomem(epm_creds
, c
)) return;
797 epm_map_req
= dcerpc_epm_map_binding_send(c
, s
->final_binding
, s
->r
.in
.dcerpc_iface
,
799 s
->ctx
->event_ctx
, s
->ctx
->lp_ctx
);
800 if (composite_nomem(epm_map_req
, c
)) return;
802 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
806 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
807 rpc connection derived from already used pipe but connected to the requested
808 one (as specified in libnet_RpcConnect structure)
810 static void continue_epm_map_binding(struct composite_context
*ctx
)
812 struct composite_context
*c
, *sec_conn_req
;
813 struct rpc_connect_dci_state
*s
;
815 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
816 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
818 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
819 if (!NT_STATUS_IS_OK(c
->status
)) {
820 s
->r
.out
.error_string
= talloc_asprintf(c
,
821 "failed to map pipe with endpoint mapper - %s",
822 nt_errstr(c
->status
));
823 composite_error(c
, c
->status
);
827 /* create secondary connection derived from lsa pipe */
828 sec_conn_req
= dcerpc_secondary_connection_send(s
->lsa_pipe
, s
->final_binding
);
829 if (composite_nomem(sec_conn_req
, c
)) return;
831 composite_continue(c
, sec_conn_req
, continue_secondary_conn
, c
);
836 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
837 and complete this composite call
839 static void continue_secondary_conn(struct composite_context
*ctx
)
841 struct composite_context
*c
;
842 struct rpc_connect_dci_state
*s
;
844 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
845 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
847 c
->status
= dcerpc_secondary_connection_recv(ctx
, &s
->final_pipe
);
848 if (!NT_STATUS_IS_OK(c
->status
)) {
849 s
->r
.out
.error_string
= talloc_asprintf(c
,
850 "secondary connection failed: %s",
851 nt_errstr(c
->status
));
853 composite_error(c
, c
->status
);
857 s
->r
.out
.dcerpc_pipe
= s
->final_pipe
;
859 /* post monitor message */
861 struct monitor_msg msg
;
862 struct msg_net_rpc_connect data
;
863 const struct dcerpc_binding
*b
= s
->r
.out
.dcerpc_pipe
->binding
;
865 /* prepare monitor message and post it */
866 data
.host
= dcerpc_binding_get_string_option(b
, "host");
867 data
.endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
868 data
.transport
= dcerpc_binding_get_transport(b
);
869 data
.domain_name
= dcerpc_binding_get_string_option(b
, "target_hostname");
871 msg
.type
= mon_NetRpcConnect
;
872 msg
.data
= (void*)&data
;
873 msg
.data_size
= sizeof(data
);
882 * Receives result of connection to rpc pipe and gets basic
883 * domain info (name, sid, realm, guid)
885 * @param c composite context
886 * @param ctx initialised libnet context
887 * @param mem_ctx memory context of this call
888 * @param r data structure containing return values
889 * @return nt status of rpc connection
892 static NTSTATUS
libnet_RpcConnectDCInfo_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
893 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
896 struct rpc_connect_dci_state
*s
= talloc_get_type(c
->private_data
,
897 struct rpc_connect_dci_state
);
899 status
= composite_wait(c
);
900 if (NT_STATUS_IS_OK(status
)) {
901 r
->out
.realm
= talloc_steal(mem_ctx
, s
->r
.out
.realm
);
902 r
->out
.guid
= talloc_steal(mem_ctx
, s
->r
.out
.guid
);
903 r
->out
.domain_name
= talloc_steal(mem_ctx
, s
->r
.out
.domain_name
);
904 r
->out
.domain_sid
= talloc_steal(mem_ctx
, s
->r
.out
.domain_sid
);
906 r
->out
.dcerpc_pipe
= talloc_steal(mem_ctx
, s
->r
.out
.dcerpc_pipe
);
908 /* reference created pipe structure to long-term libnet_context
909 so that it can be used by other api functions even after short-term
911 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
912 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
913 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
915 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
916 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
917 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
921 if (s
->r
.out
.error_string
) {
922 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
923 } else if (r
->in
.binding
== NULL
) {
924 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC failed: %s", nt_errstr(status
));
926 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Connection to DC %s failed: %s",
927 r
->in
.binding
, nt_errstr(status
));
937 * Initiates connection to rpc pipe on remote server or pdc, optionally
938 * providing domain info
940 * @param ctx initialised libnet context
941 * @param mem_ctx memory context of this call
942 * @param r data structure containing necessary parameters and return values
943 * @return composite context of this call
946 struct composite_context
* libnet_RpcConnect_send(struct libnet_context
*ctx
,
948 struct libnet_RpcConnect
*r
,
949 void (*monitor
)(struct monitor_msg
*))
951 struct composite_context
*c
;
954 case LIBNET_RPC_CONNECT_SERVER
:
955 case LIBNET_RPC_CONNECT_SERVER_ADDRESS
:
956 case LIBNET_RPC_CONNECT_BINDING
:
957 c
= libnet_RpcConnectSrv_send(ctx
, mem_ctx
, r
, monitor
);
960 case LIBNET_RPC_CONNECT_PDC
:
961 case LIBNET_RPC_CONNECT_DC
:
962 c
= libnet_RpcConnectDC_send(ctx
, mem_ctx
, r
, monitor
);
965 case LIBNET_RPC_CONNECT_DC_INFO
:
966 c
= libnet_RpcConnectDCInfo_send(ctx
, mem_ctx
, r
, monitor
);
970 c
= talloc_zero(mem_ctx
, struct composite_context
);
971 composite_error(c
, NT_STATUS_INVALID_LEVEL
);
979 * Receives result of connection to rpc pipe on remote server or pdc
981 * @param c composite context
982 * @param ctx initialised libnet context
983 * @param mem_ctx memory context of this call
984 * @param r data structure containing necessary parameters and return values
985 * @return nt status of rpc connection
988 NTSTATUS
libnet_RpcConnect_recv(struct composite_context
*c
, struct libnet_context
*ctx
,
989 TALLOC_CTX
*mem_ctx
, struct libnet_RpcConnect
*r
)
992 case LIBNET_RPC_CONNECT_SERVER
:
993 case LIBNET_RPC_CONNECT_BINDING
:
994 return libnet_RpcConnectSrv_recv(c
, ctx
, mem_ctx
, r
);
996 case LIBNET_RPC_CONNECT_PDC
:
997 case LIBNET_RPC_CONNECT_DC
:
998 return libnet_RpcConnectDC_recv(c
, ctx
, mem_ctx
, r
);
1000 case LIBNET_RPC_CONNECT_DC_INFO
:
1001 return libnet_RpcConnectDCInfo_recv(c
, ctx
, mem_ctx
, r
);
1004 ZERO_STRUCT(r
->out
);
1005 return NT_STATUS_INVALID_LEVEL
;
1011 * Connect to a rpc pipe on a remote server - sync version
1013 * @param ctx initialised libnet context
1014 * @param mem_ctx memory context of this call
1015 * @param r data structure containing necessary parameters and return values
1016 * @return nt status of rpc connection
1019 NTSTATUS
libnet_RpcConnect(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
1020 struct libnet_RpcConnect
*r
)
1022 struct composite_context
*c
;
1024 c
= libnet_RpcConnect_send(ctx
, mem_ctx
, r
, NULL
);
1025 return libnet_RpcConnect_recv(c
, ctx
, mem_ctx
, r
);