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
)
193 status
= composite_wait(c
);
194 if (NT_STATUS_IS_OK(status
)) {
195 struct rpc_connect_srv_state
*s
;
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
);
206 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
208 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
209 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
210 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
213 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
216 r
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
224 struct rpc_connect_dc_state
{
225 struct libnet_context
*ctx
;
226 struct libnet_RpcConnect r
;
227 struct libnet_RpcConnect r2
;
228 struct libnet_LookupDCs f
;
229 const char *connect_name
;
231 /* information about the progress */
232 void (*monitor_fn
)(struct monitor_msg
*);
236 static void continue_lookup_dc(struct tevent_req
*req
);
237 static void continue_rpc_connect(struct composite_context
*ctx
);
241 * Initiates connection to rpc pipe on domain pdc
243 * @param ctx initialised libnet context
244 * @param mem_ctx memory context of this call
245 * @param r data structure containing necessary parameters and return values
246 * @return composite context of this call
249 static struct composite_context
* libnet_RpcConnectDC_send(struct libnet_context
*ctx
,
251 struct libnet_RpcConnect
*r
,
252 void (*monitor
)(struct monitor_msg
*msg
))
254 struct composite_context
*c
;
255 struct rpc_connect_dc_state
*s
;
256 struct tevent_req
*lookup_dc_req
;
258 /* composite context allocation and setup */
259 c
= composite_create(ctx
, ctx
->event_ctx
);
260 if (c
== NULL
) return c
;
262 s
= talloc_zero(c
, struct rpc_connect_dc_state
);
263 if (composite_nomem(s
, c
)) return c
;
266 s
->monitor_fn
= monitor
;
270 ZERO_STRUCT(s
->r
.out
);
273 case LIBNET_RPC_CONNECT_PDC
:
274 s
->f
.in
.name_type
= NBT_NAME_PDC
;
277 case LIBNET_RPC_CONNECT_DC
:
278 s
->f
.in
.name_type
= NBT_NAME_LOGON
;
285 s
->f
.in
.domain_name
= r
->in
.name
;
286 s
->f
.out
.num_dcs
= 0;
289 /* find the domain pdc first */
290 lookup_dc_req
= libnet_LookupDCs_send(ctx
, c
, &s
->f
);
291 if (composite_nomem(lookup_dc_req
, c
)) return c
;
293 tevent_req_set_callback(lookup_dc_req
, continue_lookup_dc
, c
);
299 Step 2 of RpcConnectDC: get domain controller name and
300 initiate RpcConnect to it
302 static void continue_lookup_dc(struct tevent_req
*req
)
304 struct composite_context
*c
;
305 struct rpc_connect_dc_state
*s
;
306 struct composite_context
*rpc_connect_req
;
307 struct monitor_msg msg
;
308 struct msg_net_lookup_dc data
;
310 c
= tevent_req_callback_data(req
, struct composite_context
);
311 s
= talloc_get_type_abort(c
->private_data
, struct rpc_connect_dc_state
);
313 /* receive result of domain controller lookup */
314 c
->status
= libnet_LookupDCs_recv(req
, c
, &s
->f
);
315 if (!composite_is_ok(c
)) return;
317 /* decide on preferred address type depending on DC type */
318 s
->connect_name
= s
->f
.out
.dcs
[0].name
;
320 /* post monitor message */
322 /* prepare a monitor message and post it */
323 data
.domain_name
= s
->f
.in
.domain_name
;
324 data
.hostname
= s
->f
.out
.dcs
[0].name
;
325 data
.address
= s
->f
.out
.dcs
[0].address
;
327 msg
.type
= mon_NetLookupDc
;
329 msg
.data_size
= sizeof(data
);
333 /* ok, pdc has been found so do attempt to rpc connect */
334 s
->r2
.level
= LIBNET_RPC_CONNECT_SERVER_ADDRESS
;
336 /* this will cause yet another name resolution, but at least
337 * we pass the right name down the stack now */
338 s
->r2
.in
.name
= talloc_strdup(s
, s
->connect_name
);
339 s
->r2
.in
.address
= talloc_steal(s
, s
->f
.out
.dcs
[0].address
);
340 s
->r2
.in
.dcerpc_iface
= s
->r
.in
.dcerpc_iface
;
341 s
->r2
.in
.dcerpc_flags
= s
->r
.in
.dcerpc_flags
;
343 /* send rpc connect request to the server */
344 rpc_connect_req
= libnet_RpcConnectSrv_send(s
->ctx
, c
, &s
->r2
, s
->monitor_fn
);
345 if (composite_nomem(rpc_connect_req
, c
)) return;
347 composite_continue(c
, rpc_connect_req
, continue_rpc_connect
, c
);
352 Step 3 of RpcConnectDC: get rpc connection to the server
354 static void continue_rpc_connect(struct composite_context
*ctx
)
356 struct composite_context
*c
;
357 struct rpc_connect_dc_state
*s
;
359 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
360 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dc_state
);
362 c
->status
= libnet_RpcConnectSrv_recv(ctx
, s
->ctx
, c
, &s
->r2
);
364 /* error string is to be passed anyway */
365 s
->r
.out
.error_string
= s
->r2
.out
.error_string
;
366 if (!composite_is_ok(c
)) return;
368 s
->r
.out
.dcerpc_pipe
= s
->r2
.out
.dcerpc_pipe
;
370 /* post monitor message */
372 struct monitor_msg msg
;
373 struct msg_net_rpc_connect data
;
374 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
376 data
.host
= binding
->host
;
377 data
.endpoint
= binding
->endpoint
;
378 data
.transport
= binding
->transport
;
379 data
.domain_name
= binding
->target_hostname
;
381 msg
.type
= mon_NetRpcConnect
;
382 msg
.data
= (void*)&data
;
383 msg
.data_size
= sizeof(data
);
392 * Receives result of connection to rpc pipe on domain pdc
394 * @param c composite context
395 * @param ctx initialised libnet context
396 * @param mem_ctx memory context of this call
397 * @param r data structure containing necessary parameters and return values
398 * @return nt status of rpc connection
401 static NTSTATUS
libnet_RpcConnectDC_recv(struct composite_context
*c
,
402 struct libnet_context
*ctx
,
404 struct libnet_RpcConnect
*r
)
407 struct rpc_connect_dc_state
*s
= talloc_get_type(c
->private_data
,
408 struct rpc_connect_dc_state
);
410 status
= composite_wait(c
);
411 if (NT_STATUS_IS_OK(status
)) {
412 /* move connected rpc pipe between memory contexts
414 The use of talloc_reparent(talloc_parent(), ...) is
415 bizarre, but it is needed because of the absolutely
416 atrocious use of talloc in this code. We need to
417 force the original parent to change, but finding
418 the original parent is well nigh impossible at this
419 point in the code (yes, I tried).
421 r
->out
.dcerpc_pipe
= talloc_reparent(talloc_parent(s
->r
.out
.dcerpc_pipe
),
422 mem_ctx
, s
->r
.out
.dcerpc_pipe
);
424 /* reference created pipe structure to long-term libnet_context
425 so that it can be used by other api functions even after short-term
427 if (r
->in
.dcerpc_iface
== &ndr_table_samr
) {
428 ctx
->samr
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
429 ctx
->samr
.samr_handle
= ctx
->samr
.pipe
->binding_handle
;
430 } else if (r
->in
.dcerpc_iface
== &ndr_table_lsarpc
) {
431 ctx
->lsa
.pipe
= talloc_reference(ctx
, r
->out
.dcerpc_pipe
);
432 ctx
->lsa
.lsa_handle
= ctx
->lsa
.pipe
->binding_handle
;
436 r
->out
.error_string
= talloc_asprintf(mem_ctx
,
437 "Failed to rpc connect: %s",
447 struct rpc_connect_dci_state
{
448 struct libnet_context
*ctx
;
449 struct libnet_RpcConnect r
;
450 struct libnet_RpcConnect rpc_conn
;
451 struct policy_handle lsa_handle
;
452 struct lsa_QosInfo qos
;
453 struct lsa_ObjectAttribute attr
;
454 struct lsa_OpenPolicy2 lsa_open_policy
;
455 struct dcerpc_pipe
*lsa_pipe
;
456 struct lsa_QueryInfoPolicy2 lsa_query_info2
;
457 struct lsa_QueryInfoPolicy lsa_query_info
;
458 struct dcerpc_binding
*final_binding
;
459 struct dcerpc_pipe
*final_pipe
;
461 /* information about the progress */
462 void (*monitor_fn
)(struct monitor_msg
*);
466 static void continue_dci_rpc_connect(struct composite_context
*ctx
);
467 static void continue_lsa_policy(struct tevent_req
*subreq
);
468 static void continue_lsa_query_info(struct tevent_req
*subreq
);
469 static void continue_lsa_query_info2(struct tevent_req
*subreq
);
470 static void continue_epm_map_binding(struct composite_context
*ctx
);
471 static void continue_secondary_conn(struct composite_context
*ctx
);
472 static void continue_epm_map_binding_send(struct composite_context
*c
);
476 * Initiates connection to rpc pipe on remote server or pdc. Received result
477 * contains info on the domain name, domain sid and realm.
479 * @param ctx initialised libnet context
480 * @param mem_ctx memory context of this call
481 * @param r data structure containing necessary parameters and return values. Must be a talloc context
482 * @return composite context of this call
485 static struct composite_context
* libnet_RpcConnectDCInfo_send(struct libnet_context
*ctx
,
487 struct libnet_RpcConnect
*r
,
488 void (*monitor
)(struct monitor_msg
*))
490 struct composite_context
*c
, *conn_req
;
491 struct rpc_connect_dci_state
*s
;
493 /* composite context allocation and setup */
494 c
= composite_create(ctx
, ctx
->event_ctx
);
495 if (c
== NULL
) return c
;
497 s
= talloc_zero(c
, struct rpc_connect_dci_state
);
498 if (composite_nomem(s
, c
)) return c
;
501 s
->monitor_fn
= monitor
;
505 ZERO_STRUCT(s
->r
.out
);
508 /* proceed to pure rpc connection if the binding string is provided,
509 otherwise try to connect domain controller */
510 if (r
->in
.binding
== NULL
) {
511 /* Pass on any binding flags (such as anonymous fallback) that have been set */
512 s
->rpc_conn
.in
.dcerpc_flags
= r
->in
.dcerpc_flags
;
514 s
->rpc_conn
.in
.name
= r
->in
.name
;
515 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_DC
;
517 s
->rpc_conn
.in
.binding
= r
->in
.binding
;
518 s
->rpc_conn
.level
= LIBNET_RPC_CONNECT_BINDING
;
521 /* we need to query information on lsarpc interface first */
522 s
->rpc_conn
.in
.dcerpc_iface
= &ndr_table_lsarpc
;
524 /* request connection to the lsa pipe on the pdc */
525 conn_req
= libnet_RpcConnect_send(ctx
, c
, &s
->rpc_conn
, s
->monitor_fn
);
526 if (composite_nomem(c
, conn_req
)) return c
;
528 composite_continue(c
, conn_req
, continue_dci_rpc_connect
, c
);
534 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
537 static void continue_dci_rpc_connect(struct composite_context
*ctx
)
539 struct composite_context
*c
;
540 struct rpc_connect_dci_state
*s
;
541 struct tevent_req
*subreq
;
543 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
544 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
546 c
->status
= libnet_RpcConnect_recv(ctx
, s
->ctx
, c
, &s
->rpc_conn
);
547 if (!NT_STATUS_IS_OK(c
->status
)) {
548 composite_error(c
, c
->status
);
552 /* post monitor message */
554 struct monitor_msg msg
;
555 struct msg_net_rpc_connect data
;
556 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
558 data
.host
= binding
->host
;
559 data
.endpoint
= binding
->endpoint
;
560 data
.transport
= binding
->transport
;
561 data
.domain_name
= binding
->target_hostname
;
563 msg
.type
= mon_NetRpcConnect
;
564 msg
.data
= (void*)&data
;
565 msg
.data_size
= sizeof(data
);
569 /* prepare to open a policy handle on lsa pipe */
570 s
->lsa_pipe
= s
->ctx
->lsa
.pipe
;
573 s
->qos
.impersonation_level
= 2;
574 s
->qos
.context_mode
= 1;
575 s
->qos
.effective_only
= 0;
577 s
->attr
.sec_qos
= &s
->qos
;
579 if (s
->lsa_pipe
->binding
->transport
== NCACN_IP_TCP
) {
581 * Skip to creating the actual connection. We can't open a
582 * policy handle over tcpip.
584 continue_epm_map_binding_send(c
);
588 s
->lsa_open_policy
.in
.attr
= &s
->attr
;
589 s
->lsa_open_policy
.in
.system_name
= talloc_asprintf(c
, "\\");
590 if (composite_nomem(s
->lsa_open_policy
.in
.system_name
, c
)) return;
592 s
->lsa_open_policy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
593 s
->lsa_open_policy
.out
.handle
= &s
->lsa_handle
;
595 subreq
= dcerpc_lsa_OpenPolicy2_r_send(s
, c
->event_ctx
,
596 s
->lsa_pipe
->binding_handle
,
597 &s
->lsa_open_policy
);
598 if (composite_nomem(subreq
, c
)) return;
600 tevent_req_set_callback(subreq
, continue_lsa_policy
, c
);
605 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
606 for kerberos realm (dns name) and guid. The query may fail.
608 static void continue_lsa_policy(struct tevent_req
*subreq
)
610 struct composite_context
*c
;
611 struct rpc_connect_dci_state
*s
;
613 c
= tevent_req_callback_data(subreq
, struct composite_context
);
614 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
616 c
->status
= dcerpc_lsa_OpenPolicy2_r_recv(subreq
, s
);
618 if (!NT_STATUS_IS_OK(c
->status
)) {
619 composite_error(c
, c
->status
);
623 if (NT_STATUS_EQUAL(s
->lsa_open_policy
.out
.result
, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED
)) {
624 s
->r
.out
.realm
= NULL
;
625 s
->r
.out
.guid
= NULL
;
626 s
->r
.out
.domain_name
= NULL
;
627 s
->r
.out
.domain_sid
= NULL
;
629 /* Skip to the creating the actual connection, no info available on this transport */
630 continue_epm_map_binding_send(c
);
633 } else if (!NT_STATUS_IS_OK(s
->lsa_open_policy
.out
.result
)) {
634 composite_error(c
, s
->lsa_open_policy
.out
.result
);
638 /* post monitor message */
640 struct monitor_msg msg
;
642 msg
.type
= mon_LsaOpenPolicy
;
648 /* query lsa info for dns domain name and guid */
649 s
->lsa_query_info2
.in
.handle
= &s
->lsa_handle
;
650 s
->lsa_query_info2
.in
.level
= LSA_POLICY_INFO_DNS
;
651 s
->lsa_query_info2
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
652 if (composite_nomem(s
->lsa_query_info2
.out
.info
, c
)) return;
654 subreq
= dcerpc_lsa_QueryInfoPolicy2_r_send(s
, c
->event_ctx
,
655 s
->lsa_pipe
->binding_handle
,
656 &s
->lsa_query_info2
);
657 if (composite_nomem(subreq
, c
)) return;
659 tevent_req_set_callback(subreq
, continue_lsa_query_info2
, c
);
664 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
665 may result in failure) and query lsa info for domain name and sid.
667 static void continue_lsa_query_info2(struct tevent_req
*subreq
)
669 struct composite_context
*c
;
670 struct rpc_connect_dci_state
*s
;
672 c
= tevent_req_callback_data(subreq
, struct composite_context
);
673 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
675 c
->status
= dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq
, s
);
678 /* In case of error just null the realm and guid and proceed
679 to the next step. After all, it doesn't have to be AD domain
680 controller we talking to - NT-style PDC also counts */
682 if (NT_STATUS_EQUAL(c
->status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
683 s
->r
.out
.realm
= NULL
;
684 s
->r
.out
.guid
= NULL
;
687 if (!NT_STATUS_IS_OK(c
->status
)) {
688 s
->r
.out
.error_string
= talloc_asprintf(c
,
689 "lsa_QueryInfoPolicy2 failed: %s",
690 nt_errstr(c
->status
));
691 composite_error(c
, c
->status
);
695 if (!NT_STATUS_IS_OK(s
->lsa_query_info2
.out
.result
)) {
696 s
->r
.out
.error_string
= talloc_asprintf(c
,
697 "lsa_QueryInfoPolicy2 failed: %s",
698 nt_errstr(s
->lsa_query_info2
.out
.result
));
699 composite_error(c
, s
->lsa_query_info2
.out
.result
);
703 /* Copy the dns domain name and guid from the query result */
705 /* this should actually be a conversion from lsa_StringLarge */
706 s
->r
.out
.realm
= (*s
->lsa_query_info2
.out
.info
)->dns
.dns_domain
.string
;
707 s
->r
.out
.guid
= talloc(c
, struct GUID
);
708 if (composite_nomem(s
->r
.out
.guid
, c
)) {
709 s
->r
.out
.error_string
= NULL
;
712 *s
->r
.out
.guid
= (*s
->lsa_query_info2
.out
.info
)->dns
.domain_guid
;
715 /* post monitor message */
717 struct monitor_msg msg
;
719 msg
.type
= mon_LsaQueryPolicy
;
725 /* query lsa info for domain name and sid */
726 s
->lsa_query_info
.in
.handle
= &s
->lsa_handle
;
727 s
->lsa_query_info
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
728 s
->lsa_query_info
.out
.info
= talloc_zero(c
, union lsa_PolicyInformation
*);
729 if (composite_nomem(s
->lsa_query_info
.out
.info
, c
)) return;
731 subreq
= dcerpc_lsa_QueryInfoPolicy_r_send(s
, c
->event_ctx
,
732 s
->lsa_pipe
->binding_handle
,
734 if (composite_nomem(subreq
, c
)) return;
736 tevent_req_set_callback(subreq
, continue_lsa_query_info
, c
);
741 Step 5 of RpcConnectDCInfo: Get domain name and sid
743 static void continue_lsa_query_info(struct tevent_req
*subreq
)
745 struct composite_context
*c
;
746 struct rpc_connect_dci_state
*s
;
748 c
= tevent_req_callback_data(subreq
, struct composite_context
);
749 s
= talloc_get_type(c
->private_data
, struct rpc_connect_dci_state
);
751 c
->status
= dcerpc_lsa_QueryInfoPolicy_r_recv(subreq
, s
);
753 if (!NT_STATUS_IS_OK(c
->status
)) {
754 s
->r
.out
.error_string
= talloc_asprintf(c
,
755 "lsa_QueryInfoPolicy failed: %s",
756 nt_errstr(c
->status
));
757 composite_error(c
, c
->status
);
761 /* post monitor message */
763 struct monitor_msg msg
;
765 msg
.type
= mon_LsaQueryPolicy
;
771 /* Copy the domain name and sid from the query result */
772 s
->r
.out
.domain_sid
= (*s
->lsa_query_info
.out
.info
)->domain
.sid
;
773 s
->r
.out
.domain_name
= (*s
->lsa_query_info
.out
.info
)->domain
.name
.string
;
775 continue_epm_map_binding_send(c
);
779 Step 5 (continued) of RpcConnectDCInfo: request endpoint
782 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
784 static void continue_epm_map_binding_send(struct composite_context
*c
)
786 struct rpc_connect_dci_state
*s
;
787 struct composite_context
*epm_map_req
;
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
= talloc_zero(s
, struct dcerpc_binding
);
792 if (composite_nomem(s
->final_binding
, c
)) return;
794 *s
->final_binding
= *s
->lsa_pipe
->binding
;
795 /* Ensure we keep hold of the member elements */
796 if (composite_nomem(talloc_reference(s
->final_binding
, s
->lsa_pipe
->binding
), c
)) return;
798 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 struct dcerpc_binding
*binding
= s
->r
.out
.dcerpc_pipe
->binding
;
865 /* prepare monitor message and post it */
866 data
.host
= binding
->host
;
867 data
.endpoint
= binding
->endpoint
;
868 data
.transport
= binding
->transport
;
869 data
.domain_name
= binding
->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
);