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