s3-security: use shared SECINFO_OWNER define.
[Samba/ekacnet.git] / source4 / libnet / libnet_rpc.c
blob138b9267428c8db0667ec0a11c8d6d9fb78403bd
1 /*
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/>.
21 #include "includes.h"
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;
33 const char *binding;
35 /* information about the progress */
36 void (*monitor_fn)(struct monitor_msg*);
40 static void continue_pipe_connect(struct composite_context *ctx);
43 /**
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
50 **/
52 static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx,
53 TALLOC_CTX *mem_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;
69 c->private_data = s;
70 s->monitor_fn = monitor;
72 s->ctx = ctx;
73 s->r = *r;
74 ZERO_STRUCT(s->r.out);
76 /* prepare binding string */
77 switch (r->level) {
78 case LIBNET_RPC_CONNECT_SERVER:
79 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
80 break;
81 case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
82 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address);
83 break;
85 case LIBNET_RPC_CONNECT_BINDING:
86 s->binding = talloc_strdup(s, r->in.binding);
87 break;
89 case LIBNET_RPC_CONNECT_DC:
90 case LIBNET_RPC_CONNECT_PDC:
91 /* this should never happen - DC and PDC level has a separate
92 composite function */
93 case LIBNET_RPC_CONNECT_DC_INFO:
94 /* this should never happen - DC_INFO level has a separate
95 composite function */
96 composite_error(c, NT_STATUS_INVALID_LEVEL);
97 return c;
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);
105 return c;
108 switch (r->level) {
109 case LIBNET_RPC_CONNECT_SERVER:
110 case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
111 b->flags = r->in.dcerpc_flags;
114 if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
115 b->target_hostname = talloc_strdup(b, r->in.name);
116 if (composite_nomem(b->target_hostname, c)) {
117 return c;
121 /* connect to remote dcerpc pipe */
122 pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
123 ctx->cred, c->event_ctx,
124 ctx->lp_ctx);
125 if (composite_nomem(pipe_connect_req, c)) return c;
127 composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
128 return c;
133 Step 2 of RpcConnectSrv - get rpc connection
135 static void continue_pipe_connect(struct composite_context *ctx)
137 struct composite_context *c;
138 struct rpc_connect_srv_state *s;
140 c = talloc_get_type(ctx->async.private_data, struct composite_context);
141 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
143 /* receive result of rpc pipe connection */
144 c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
146 /* post monitor message */
147 if (s->monitor_fn) {
148 struct monitor_msg msg;
149 struct msg_net_rpc_connect data;
150 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
152 /* prepare monitor message and post it */
153 data.host = binding->host;
154 data.endpoint = binding->endpoint;
155 data.transport = binding->transport;
156 data.domain_name = binding->target_hostname;
158 msg.type = mon_NetRpcConnect;
159 msg.data = (void*)&data;
160 msg.data_size = sizeof(data);
161 s->monitor_fn(&msg);
164 composite_done(c);
169 * Receives result of connection to rpc pipe on remote server
171 * @param c composite context
172 * @param ctx initialised libnet context
173 * @param mem_ctx memory context of this call
174 * @param r data structure containing necessary parameters and return values
175 * @return nt status of rpc connection
178 static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
179 struct libnet_context *ctx,
180 TALLOC_CTX *mem_ctx,
181 struct libnet_RpcConnect *r)
183 NTSTATUS status;
184 struct rpc_connect_srv_state *s = talloc_get_type(c->private_data,
185 struct rpc_connect_srv_state);
187 status = composite_wait(c);
188 if (NT_STATUS_IS_OK(status)) {
189 /* move the returned rpc pipe between memory contexts */
190 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
191 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
193 /* reference created pipe structure to long-term libnet_context
194 so that it can be used by other api functions even after short-term
195 mem_ctx is freed */
196 if (r->in.dcerpc_iface == &ndr_table_samr) {
197 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
199 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
200 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
203 r->out.error_string = talloc_strdup(mem_ctx, "Success");
205 } else {
206 r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
209 talloc_free(c);
210 return status;
214 struct rpc_connect_dc_state {
215 struct libnet_context *ctx;
216 struct libnet_RpcConnect r;
217 struct libnet_RpcConnect r2;
218 struct libnet_LookupDCs f;
219 const char *connect_name;
221 /* information about the progress */
222 void (*monitor_fn)(struct monitor_msg *);
226 static void continue_lookup_dc(struct composite_context *ctx);
227 static void continue_rpc_connect(struct composite_context *ctx);
231 * Initiates connection to rpc pipe on domain pdc
233 * @param ctx initialised libnet context
234 * @param mem_ctx memory context of this call
235 * @param r data structure containing necessary parameters and return values
236 * @return composite context of this call
239 static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
240 TALLOC_CTX *mem_ctx,
241 struct libnet_RpcConnect *r,
242 void (*monitor)(struct monitor_msg *msg))
244 struct composite_context *c;
245 struct rpc_connect_dc_state *s;
246 struct composite_context *lookup_dc_req;
248 /* composite context allocation and setup */
249 c = composite_create(ctx, ctx->event_ctx);
250 if (c == NULL) return c;
252 s = talloc_zero(c, struct rpc_connect_dc_state);
253 if (composite_nomem(s, c)) return c;
255 c->private_data = s;
256 s->monitor_fn = monitor;
258 s->ctx = ctx;
259 s->r = *r;
260 ZERO_STRUCT(s->r.out);
262 switch (r->level) {
263 case LIBNET_RPC_CONNECT_PDC:
264 s->f.in.name_type = NBT_NAME_PDC;
265 break;
267 case LIBNET_RPC_CONNECT_DC:
268 s->f.in.name_type = NBT_NAME_LOGON;
269 break;
271 default:
272 break;
275 s->f.in.domain_name = r->in.name;
276 s->f.out.num_dcs = 0;
277 s->f.out.dcs = NULL;
279 /* find the domain pdc first */
280 lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
281 if (composite_nomem(lookup_dc_req, c)) return c;
283 composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
284 return c;
289 Step 2 of RpcConnectDC: get domain controller name and
290 initiate RpcConnect to it
292 static void continue_lookup_dc(struct composite_context *ctx)
294 struct composite_context *c;
295 struct rpc_connect_dc_state *s;
296 struct composite_context *rpc_connect_req;
297 struct monitor_msg msg;
298 struct msg_net_lookup_dc data;
300 c = talloc_get_type(ctx->async.private_data, struct composite_context);
301 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
303 /* receive result of domain controller lookup */
304 c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
305 if (!composite_is_ok(c)) return;
307 /* decide on preferred address type depending on DC type */
308 s->connect_name = s->f.out.dcs[0].name;
310 /* post monitor message */
311 if (s->monitor_fn) {
312 /* prepare a monitor message and post it */
313 data.domain_name = s->f.in.domain_name;
314 data.hostname = s->f.out.dcs[0].name;
315 data.address = s->f.out.dcs[0].address;
317 msg.type = mon_NetLookupDc;
318 msg.data = &data;
319 msg.data_size = sizeof(data);
320 s->monitor_fn(&msg);
323 /* ok, pdc has been found so do attempt to rpc connect */
324 s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
326 /* this will cause yet another name resolution, but at least
327 * we pass the right name down the stack now */
328 s->r2.in.name = talloc_strdup(s, s->connect_name);
329 s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address);
330 s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface;
331 s->r2.in.dcerpc_flags = s->r.in.dcerpc_flags;
333 /* send rpc connect request to the server */
334 rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
335 if (composite_nomem(rpc_connect_req, c)) return;
337 composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
342 Step 3 of RpcConnectDC: get rpc connection to the server
344 static void continue_rpc_connect(struct composite_context *ctx)
346 struct composite_context *c;
347 struct rpc_connect_dc_state *s;
349 c = talloc_get_type(ctx->async.private_data, struct composite_context);
350 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
352 c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
354 /* error string is to be passed anyway */
355 s->r.out.error_string = s->r2.out.error_string;
356 if (!composite_is_ok(c)) return;
358 s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
360 /* post monitor message */
361 if (s->monitor_fn) {
362 struct monitor_msg msg;
363 struct msg_net_rpc_connect data;
364 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
366 data.host = binding->host;
367 data.endpoint = binding->endpoint;
368 data.transport = binding->transport;
369 data.domain_name = binding->target_hostname;
371 msg.type = mon_NetRpcConnect;
372 msg.data = (void*)&data;
373 msg.data_size = sizeof(data);
374 s->monitor_fn(&msg);
377 composite_done(c);
382 * Receives result of connection to rpc pipe on domain pdc
384 * @param c composite context
385 * @param ctx initialised libnet context
386 * @param mem_ctx memory context of this call
387 * @param r data structure containing necessary parameters and return values
388 * @return nt status of rpc connection
391 static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
392 struct libnet_context *ctx,
393 TALLOC_CTX *mem_ctx,
394 struct libnet_RpcConnect *r)
396 NTSTATUS status;
397 struct rpc_connect_dc_state *s = talloc_get_type(c->private_data,
398 struct rpc_connect_dc_state);
400 status = composite_wait(c);
401 if (NT_STATUS_IS_OK(status)) {
402 /* move connected rpc pipe between memory contexts
404 The use of talloc_reparent(talloc_parent(), ...) is
405 bizarre, but it is needed because of the absolutely
406 atrocious use of talloc in this code. We need to
407 force the original parent to change, but finding
408 the original parent is well nigh impossible at this
409 point in the code (yes, I tried).
411 r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe),
412 mem_ctx, s->r.out.dcerpc_pipe);
414 /* reference created pipe structure to long-term libnet_context
415 so that it can be used by other api functions even after short-term
416 mem_ctx is freed */
417 if (r->in.dcerpc_iface == &ndr_table_samr) {
418 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
420 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
421 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
424 } else {
425 r->out.error_string = talloc_asprintf(mem_ctx,
426 "Failed to rpc connect: %s",
427 nt_errstr(status));
430 talloc_free(c);
431 return status;
436 struct rpc_connect_dci_state {
437 struct libnet_context *ctx;
438 struct libnet_RpcConnect r;
439 struct libnet_RpcConnect rpc_conn;
440 struct policy_handle lsa_handle;
441 struct lsa_QosInfo qos;
442 struct lsa_ObjectAttribute attr;
443 struct lsa_OpenPolicy2 lsa_open_policy;
444 struct dcerpc_pipe *lsa_pipe;
445 struct lsa_QueryInfoPolicy2 lsa_query_info2;
446 struct lsa_QueryInfoPolicy lsa_query_info;
447 struct dcerpc_binding *final_binding;
448 struct dcerpc_pipe *final_pipe;
450 /* information about the progress */
451 void (*monitor_fn)(struct monitor_msg*);
455 static void continue_dci_rpc_connect(struct composite_context *ctx);
456 static void continue_lsa_policy(struct tevent_req *subreq);
457 static void continue_lsa_query_info(struct tevent_req *subreq);
458 static void continue_lsa_query_info2(struct tevent_req *subreq);
459 static void continue_epm_map_binding(struct composite_context *ctx);
460 static void continue_secondary_conn(struct composite_context *ctx);
461 static void continue_epm_map_binding_send(struct composite_context *c);
465 * Initiates connection to rpc pipe on remote server or pdc. Received result
466 * contains info on the domain name, domain sid and realm.
468 * @param ctx initialised libnet context
469 * @param mem_ctx memory context of this call
470 * @param r data structure containing necessary parameters and return values. Must be a talloc context
471 * @return composite context of this call
474 static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
475 TALLOC_CTX *mem_ctx,
476 struct libnet_RpcConnect *r,
477 void (*monitor)(struct monitor_msg*))
479 struct composite_context *c, *conn_req;
480 struct rpc_connect_dci_state *s;
482 /* composite context allocation and setup */
483 c = composite_create(ctx, ctx->event_ctx);
484 if (c == NULL) return c;
486 s = talloc_zero(c, struct rpc_connect_dci_state);
487 if (composite_nomem(s, c)) return c;
489 c->private_data = s;
490 s->monitor_fn = monitor;
492 s->ctx = ctx;
493 s->r = *r;
494 ZERO_STRUCT(s->r.out);
497 /* proceed to pure rpc connection if the binding string is provided,
498 otherwise try to connect domain controller */
499 if (r->in.binding == NULL) {
500 /* Pass on any binding flags (such as anonymous fallback) that have been set */
501 s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
503 s->rpc_conn.in.name = r->in.name;
504 s->rpc_conn.level = LIBNET_RPC_CONNECT_DC;
505 } else {
506 s->rpc_conn.in.binding = r->in.binding;
507 s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
510 /* we need to query information on lsarpc interface first */
511 s->rpc_conn.in.dcerpc_iface = &ndr_table_lsarpc;
513 /* request connection to the lsa pipe on the pdc */
514 conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
515 if (composite_nomem(c, conn_req)) return c;
517 composite_continue(c, conn_req, continue_dci_rpc_connect, c);
518 return c;
523 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
524 lsa policy handle
526 static void continue_dci_rpc_connect(struct composite_context *ctx)
528 struct composite_context *c;
529 struct rpc_connect_dci_state *s;
530 struct tevent_req *subreq;
532 c = talloc_get_type(ctx->async.private_data, struct composite_context);
533 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
535 c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn);
536 if (!NT_STATUS_IS_OK(c->status)) {
537 composite_error(c, c->status);
538 return;
541 /* post monitor message */
542 if (s->monitor_fn) {
543 struct monitor_msg msg;
544 struct msg_net_rpc_connect data;
545 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
547 data.host = binding->host;
548 data.endpoint = binding->endpoint;
549 data.transport = binding->transport;
550 data.domain_name = binding->target_hostname;
552 msg.type = mon_NetRpcConnect;
553 msg.data = (void*)&data;
554 msg.data_size = sizeof(data);
555 s->monitor_fn(&msg);
558 /* prepare to open a policy handle on lsa pipe */
559 s->lsa_pipe = s->ctx->lsa.pipe;
561 s->qos.len = 0;
562 s->qos.impersonation_level = 2;
563 s->qos.context_mode = 1;
564 s->qos.effective_only = 0;
566 s->attr.sec_qos = &s->qos;
568 s->lsa_open_policy.in.attr = &s->attr;
569 s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\");
570 if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return;
572 s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
573 s->lsa_open_policy.out.handle = &s->lsa_handle;
575 subreq = dcerpc_lsa_OpenPolicy2_r_send(s, c->event_ctx,
576 s->lsa_pipe->binding_handle,
577 &s->lsa_open_policy);
578 if (composite_nomem(subreq, c)) return;
580 tevent_req_set_callback(subreq, continue_lsa_policy, c);
585 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
586 for kerberos realm (dns name) and guid. The query may fail.
588 static void continue_lsa_policy(struct tevent_req *subreq)
590 struct composite_context *c;
591 struct rpc_connect_dci_state *s;
593 c = tevent_req_callback_data(subreq, struct composite_context);
594 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
596 c->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, s);
597 TALLOC_FREE(subreq);
598 if (!NT_STATUS_IS_OK(c->status)) {
599 composite_error(c, c->status);
600 return;
603 if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
604 s->r.out.realm = NULL;
605 s->r.out.guid = NULL;
606 s->r.out.domain_name = NULL;
607 s->r.out.domain_sid = NULL;
609 /* Skip to the creating the actual connection, no info available on this transport */
610 continue_epm_map_binding_send(c);
611 return;
613 } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
614 composite_error(c, s->lsa_open_policy.out.result);
615 return;
618 /* post monitor message */
619 if (s->monitor_fn) {
620 struct monitor_msg msg;
622 msg.type = mon_LsaOpenPolicy;
623 msg.data = NULL;
624 msg.data_size = 0;
625 s->monitor_fn(&msg);
628 /* query lsa info for dns domain name and guid */
629 s->lsa_query_info2.in.handle = &s->lsa_handle;
630 s->lsa_query_info2.in.level = LSA_POLICY_INFO_DNS;
631 s->lsa_query_info2.out.info = talloc_zero(c, union lsa_PolicyInformation *);
632 if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
634 subreq = dcerpc_lsa_QueryInfoPolicy2_r_send(s, c->event_ctx,
635 s->lsa_pipe->binding_handle,
636 &s->lsa_query_info2);
637 if (composite_nomem(subreq, c)) return;
639 tevent_req_set_callback(subreq, continue_lsa_query_info2, c);
644 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
645 may result in failure) and query lsa info for domain name and sid.
647 static void continue_lsa_query_info2(struct tevent_req *subreq)
649 struct composite_context *c;
650 struct rpc_connect_dci_state *s;
652 c = tevent_req_callback_data(subreq, struct composite_context);
653 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
655 c->status = dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq, s);
656 TALLOC_FREE(subreq);
658 /* In case of error just null the realm and guid and proceed
659 to the next step. After all, it doesn't have to be AD domain
660 controller we talking to - NT-style PDC also counts */
662 if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
663 s->r.out.realm = NULL;
664 s->r.out.guid = NULL;
666 } else {
667 if (!NT_STATUS_IS_OK(c->status)) {
668 s->r.out.error_string = talloc_asprintf(c,
669 "lsa_QueryInfoPolicy2 failed: %s",
670 nt_errstr(c->status));
671 composite_error(c, c->status);
672 return;
675 if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) {
676 s->r.out.error_string = talloc_asprintf(c,
677 "lsa_QueryInfoPolicy2 failed: %s",
678 nt_errstr(s->lsa_query_info2.out.result));
679 composite_error(c, s->lsa_query_info2.out.result);
680 return;
683 /* Copy the dns domain name and guid from the query result */
685 /* this should actually be a conversion from lsa_StringLarge */
686 s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
687 s->r.out.guid = talloc(c, struct GUID);
688 if (composite_nomem(s->r.out.guid, c)) {
689 s->r.out.error_string = NULL;
690 return;
692 *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
695 /* post monitor message */
696 if (s->monitor_fn) {
697 struct monitor_msg msg;
699 msg.type = mon_LsaQueryPolicy;
700 msg.data = NULL;
701 msg.data_size = 0;
702 s->monitor_fn(&msg);
705 /* query lsa info for domain name and sid */
706 s->lsa_query_info.in.handle = &s->lsa_handle;
707 s->lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN;
708 s->lsa_query_info.out.info = talloc_zero(c, union lsa_PolicyInformation *);
709 if (composite_nomem(s->lsa_query_info.out.info, c)) return;
711 subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
712 s->lsa_pipe->binding_handle,
713 &s->lsa_query_info);
714 if (composite_nomem(subreq, c)) return;
716 tevent_req_set_callback(subreq, continue_lsa_query_info, c);
721 Step 5 of RpcConnectDCInfo: Get domain name and sid
723 static void continue_lsa_query_info(struct tevent_req *subreq)
725 struct composite_context *c;
726 struct rpc_connect_dci_state *s;
728 c = tevent_req_callback_data(subreq, struct composite_context);
729 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
731 c->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, s);
732 TALLOC_FREE(subreq);
733 if (!NT_STATUS_IS_OK(c->status)) {
734 s->r.out.error_string = talloc_asprintf(c,
735 "lsa_QueryInfoPolicy failed: %s",
736 nt_errstr(c->status));
737 composite_error(c, c->status);
738 return;
741 /* post monitor message */
742 if (s->monitor_fn) {
743 struct monitor_msg msg;
745 msg.type = mon_LsaQueryPolicy;
746 msg.data = NULL;
747 msg.data_size = 0;
748 s->monitor_fn(&msg);
751 /* Copy the domain name and sid from the query result */
752 s->r.out.domain_sid = (*s->lsa_query_info.out.info)->domain.sid;
753 s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
755 continue_epm_map_binding_send(c);
759 Step 5 (continued) of RpcConnectDCInfo: request endpoint
760 map binding.
762 We may short-cut to this step if we don't support LSA OpenPolicy on this transport
764 static void continue_epm_map_binding_send(struct composite_context *c)
766 struct rpc_connect_dci_state *s;
767 struct composite_context *epm_map_req;
768 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
770 /* prepare to get endpoint mapping for the requested interface */
771 s->final_binding = talloc(s, struct dcerpc_binding);
772 if (composite_nomem(s->final_binding, c)) return;
774 *s->final_binding = *s->lsa_pipe->binding;
775 /* Ensure we keep hold of the member elements */
776 if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
778 epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
779 s->lsa_pipe->conn->event_ctx, s->ctx->lp_ctx);
780 if (composite_nomem(epm_map_req, c)) return;
782 composite_continue(c, epm_map_req, continue_epm_map_binding, c);
786 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
787 rpc connection derived from already used pipe but connected to the requested
788 one (as specified in libnet_RpcConnect structure)
790 static void continue_epm_map_binding(struct composite_context *ctx)
792 struct composite_context *c, *sec_conn_req;
793 struct rpc_connect_dci_state *s;
795 c = talloc_get_type(ctx->async.private_data, struct composite_context);
796 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
798 c->status = dcerpc_epm_map_binding_recv(ctx);
799 if (!NT_STATUS_IS_OK(c->status)) {
800 s->r.out.error_string = talloc_asprintf(c,
801 "failed to map pipe with endpoint mapper - %s",
802 nt_errstr(c->status));
803 composite_error(c, c->status);
804 return;
807 /* create secondary connection derived from lsa pipe */
808 sec_conn_req = dcerpc_secondary_connection_send(s->lsa_pipe, s->final_binding);
809 if (composite_nomem(sec_conn_req, c)) return;
811 composite_continue(c, sec_conn_req, continue_secondary_conn, c);
816 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
817 and complete this composite call
819 static void continue_secondary_conn(struct composite_context *ctx)
821 struct composite_context *c;
822 struct rpc_connect_dci_state *s;
824 c = talloc_get_type(ctx->async.private_data, struct composite_context);
825 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
827 c->status = dcerpc_secondary_connection_recv(ctx, &s->final_pipe);
828 if (!NT_STATUS_IS_OK(c->status)) {
829 s->r.out.error_string = talloc_asprintf(c,
830 "secondary connection failed: %s",
831 nt_errstr(c->status));
833 composite_error(c, c->status);
834 return;
837 s->r.out.dcerpc_pipe = s->final_pipe;
839 /* post monitor message */
840 if (s->monitor_fn) {
841 struct monitor_msg msg;
842 struct msg_net_rpc_connect data;
843 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
845 /* prepare monitor message and post it */
846 data.host = binding->host;
847 data.endpoint = binding->endpoint;
848 data.transport = binding->transport;
849 data.domain_name = binding->target_hostname;
851 msg.type = mon_NetRpcConnect;
852 msg.data = (void*)&data;
853 msg.data_size = sizeof(data);
854 s->monitor_fn(&msg);
857 composite_done(c);
862 * Receives result of connection to rpc pipe and gets basic
863 * domain info (name, sid, realm, guid)
865 * @param c composite context
866 * @param ctx initialised libnet context
867 * @param mem_ctx memory context of this call
868 * @param r data structure containing return values
869 * @return nt status of rpc connection
872 static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx,
873 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
875 NTSTATUS status;
876 struct rpc_connect_dci_state *s = talloc_get_type(c->private_data,
877 struct rpc_connect_dci_state);
879 status = composite_wait(c);
880 if (NT_STATUS_IS_OK(status)) {
881 r->out.realm = talloc_steal(mem_ctx, s->r.out.realm);
882 r->out.guid = talloc_steal(mem_ctx, s->r.out.guid);
883 r->out.domain_name = talloc_steal(mem_ctx, s->r.out.domain_name);
884 r->out.domain_sid = talloc_steal(mem_ctx, s->r.out.domain_sid);
886 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
888 /* reference created pipe structure to long-term libnet_context
889 so that it can be used by other api functions even after short-term
890 mem_ctx is freed */
891 if (r->in.dcerpc_iface == &ndr_table_samr) {
892 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
893 ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
895 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
896 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
897 ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
900 } else {
901 if (s->r.out.error_string) {
902 r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
903 } else if (r->in.binding == NULL) {
904 r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
905 } else {
906 r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s",
907 r->in.binding, nt_errstr(status));
911 talloc_free(c);
912 return status;
917 * Initiates connection to rpc pipe on remote server or pdc, optionally
918 * providing domain info
920 * @param ctx initialised libnet context
921 * @param mem_ctx memory context of this call
922 * @param r data structure containing necessary parameters and return values
923 * @return composite context of this call
926 struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
927 TALLOC_CTX *mem_ctx,
928 struct libnet_RpcConnect *r,
929 void (*monitor)(struct monitor_msg*))
931 struct composite_context *c;
933 switch (r->level) {
934 case LIBNET_RPC_CONNECT_SERVER:
935 case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
936 case LIBNET_RPC_CONNECT_BINDING:
937 c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
938 break;
940 case LIBNET_RPC_CONNECT_PDC:
941 case LIBNET_RPC_CONNECT_DC:
942 c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
943 break;
945 case LIBNET_RPC_CONNECT_DC_INFO:
946 c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
947 break;
949 default:
950 c = talloc_zero(mem_ctx, struct composite_context);
951 composite_error(c, NT_STATUS_INVALID_LEVEL);
954 return c;
959 * Receives result of connection to rpc pipe on remote server or pdc
961 * @param c composite context
962 * @param ctx initialised libnet context
963 * @param mem_ctx memory context of this call
964 * @param r data structure containing necessary parameters and return values
965 * @return nt status of rpc connection
968 NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx,
969 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
971 switch (r->level) {
972 case LIBNET_RPC_CONNECT_SERVER:
973 case LIBNET_RPC_CONNECT_BINDING:
974 return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r);
976 case LIBNET_RPC_CONNECT_PDC:
977 case LIBNET_RPC_CONNECT_DC:
978 return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r);
980 case LIBNET_RPC_CONNECT_DC_INFO:
981 return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r);
983 default:
984 ZERO_STRUCT(r->out);
985 return NT_STATUS_INVALID_LEVEL;
991 * Connect to a rpc pipe on a remote server - sync version
993 * @param ctx initialised libnet context
994 * @param mem_ctx memory context of this call
995 * @param r data structure containing necessary parameters and return values
996 * @return nt status of rpc connection
999 NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
1000 struct libnet_RpcConnect *r)
1002 struct composite_context *c;
1004 c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
1005 return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);