Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2004
5 : Copyright (C) Rafal Szczesniak 2005
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
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"
28 : #include "auth/credentials/credentials.h"
29 :
30 : struct rpc_connect_srv_state {
31 : struct libnet_context *ctx;
32 : struct libnet_RpcConnect r;
33 : const char *binding;
34 :
35 : /* information about the progress */
36 : void (*monitor_fn)(struct monitor_msg*);
37 : };
38 :
39 :
40 : static void continue_pipe_connect(struct composite_context *ctx);
41 :
42 :
43 : /**
44 : * Initiates connection to rpc pipe on remote server
45 : *
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 : **/
51 :
52 787 : 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*))
56 : {
57 626 : struct composite_context *c;
58 626 : struct rpc_connect_srv_state *s;
59 626 : struct dcerpc_binding *b;
60 626 : struct composite_context *pipe_connect_req;
61 :
62 : /* composite context allocation and setup */
63 787 : c = composite_create(ctx, ctx->event_ctx);
64 948 : if (c == NULL) return c;
65 :
66 787 : s = talloc_zero(c, struct rpc_connect_srv_state);
67 787 : if (composite_nomem(s, c)) return c;
68 :
69 787 : c->private_data = s;
70 787 : s->monitor_fn = monitor;
71 :
72 787 : s->ctx = ctx;
73 787 : s->r = *r;
74 787 : ZERO_STRUCT(s->r.out);
75 :
76 : /* prepare binding string */
77 787 : switch (r->level) {
78 27 : case LIBNET_RPC_CONNECT_SERVER:
79 27 : s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
80 787 : break;
81 209 : case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
82 209 : s->binding = talloc_asprintf(s, "ncacn_np:%s[target_hostname=%s]",
83 : r->in.address, r->in.name);
84 209 : break;
85 :
86 551 : case LIBNET_RPC_CONNECT_BINDING:
87 551 : s->binding = talloc_strdup(s, r->in.binding);
88 551 : break;
89 :
90 0 : case LIBNET_RPC_CONNECT_DC:
91 : case LIBNET_RPC_CONNECT_PDC:
92 : /* this should never happen - DC and PDC level has a separate
93 : composite function */
94 : case LIBNET_RPC_CONNECT_DC_INFO:
95 : /* this should never happen - DC_INFO level has a separate
96 : composite function */
97 0 : composite_error(c, NT_STATUS_INVALID_LEVEL);
98 0 : return c;
99 : }
100 :
101 : /* parse binding string to the structure */
102 787 : c->status = dcerpc_parse_binding(c, s->binding, &b);
103 787 : if (!NT_STATUS_IS_OK(c->status)) {
104 0 : DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding));
105 0 : composite_error(c, c->status);
106 0 : return c;
107 : }
108 :
109 787 : switch (r->level) {
110 236 : case LIBNET_RPC_CONNECT_SERVER:
111 : case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
112 236 : c->status = dcerpc_binding_set_flags(b, r->in.dcerpc_flags, 0);
113 236 : if (!composite_is_ok(c)) return c;
114 62 : break;
115 99 : default:
116 : /* other types have already been checked before */
117 99 : break;
118 : }
119 :
120 787 : if (DEBUGLEVEL >= 10) {
121 0 : c->status = dcerpc_binding_set_flags(b, DCERPC_DEBUG_PRINT_BOTH, 0);
122 0 : if (!composite_is_ok(c)) return c;
123 : }
124 :
125 : /* connect to remote dcerpc pipe */
126 787 : pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
127 : ctx->cred, c->event_ctx,
128 : ctx->lp_ctx);
129 787 : if (composite_nomem(pipe_connect_req, c)) return c;
130 :
131 787 : composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
132 787 : return c;
133 : }
134 :
135 :
136 : /*
137 : Step 2 of RpcConnectSrv - get rpc connection
138 : */
139 787 : static void continue_pipe_connect(struct composite_context *ctx)
140 : {
141 626 : struct composite_context *c;
142 626 : struct rpc_connect_srv_state *s;
143 :
144 787 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
145 787 : s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
146 :
147 : /* receive result of rpc pipe connection */
148 787 : c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
149 :
150 : /* post monitor message */
151 787 : if (s->monitor_fn) {
152 0 : struct monitor_msg msg;
153 0 : struct msg_net_rpc_connect data;
154 0 : const struct dcerpc_binding *b = s->r.out.dcerpc_pipe->binding;
155 :
156 : /* prepare monitor message and post it */
157 0 : data.host = dcerpc_binding_get_string_option(b, "host");
158 0 : data.endpoint = dcerpc_binding_get_string_option(b, "endpoint");
159 0 : data.transport = dcerpc_binding_get_transport(b);
160 0 : data.domain_name = dcerpc_binding_get_string_option(b, "target_hostname");
161 :
162 0 : msg.type = mon_NetRpcConnect;
163 0 : msg.data = (void*)&data;
164 0 : msg.data_size = sizeof(data);
165 0 : s->monitor_fn(&msg);
166 : }
167 :
168 787 : composite_done(c);
169 787 : }
170 :
171 :
172 : /**
173 : * Receives result of connection to rpc pipe on remote server
174 : *
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
180 : **/
181 :
182 787 : static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
183 : struct libnet_context *ctx,
184 : TALLOC_CTX *mem_ctx,
185 : struct libnet_RpcConnect *r)
186 : {
187 626 : NTSTATUS status;
188 :
189 787 : status = composite_wait(c);
190 787 : if (NT_STATUS_IS_OK(status)) {
191 614 : struct rpc_connect_srv_state *s;
192 :
193 : /* move the returned rpc pipe between memory contexts */
194 774 : s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
195 774 : r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
196 :
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
199 : mem_ctx is freed */
200 774 : if (r->in.dcerpc_iface == &ndr_table_samr) {
201 182 : ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
202 182 : ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
203 :
204 592 : } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
205 568 : ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
206 568 : ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
207 : }
208 :
209 774 : r->out.error_string = talloc_strdup(mem_ctx, "Success");
210 :
211 : } else {
212 13 : r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
213 : }
214 :
215 787 : talloc_free(c);
216 787 : return status;
217 : }
218 :
219 :
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;
226 :
227 : /* information about the progress */
228 : void (*monitor_fn)(struct monitor_msg *);
229 : };
230 :
231 :
232 : static void continue_lookup_dc(struct tevent_req *req);
233 : static void continue_rpc_connect(struct composite_context *ctx);
234 :
235 :
236 : /**
237 : * Initiates connection to rpc pipe on domain pdc
238 : *
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
243 : **/
244 :
245 209 : static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
246 : TALLOC_CTX *mem_ctx,
247 : struct libnet_RpcConnect *r,
248 : void (*monitor)(struct monitor_msg *msg))
249 : {
250 153 : struct composite_context *c;
251 153 : struct rpc_connect_dc_state *s;
252 153 : struct tevent_req *lookup_dc_req;
253 :
254 : /* composite context allocation and setup */
255 209 : c = composite_create(ctx, ctx->event_ctx);
256 209 : if (c == NULL) return c;
257 :
258 209 : s = talloc_zero(c, struct rpc_connect_dc_state);
259 209 : if (composite_nomem(s, c)) return c;
260 :
261 209 : c->private_data = s;
262 209 : s->monitor_fn = monitor;
263 :
264 209 : s->ctx = ctx;
265 209 : s->r = *r;
266 209 : ZERO_STRUCT(s->r.out);
267 :
268 209 : switch (r->level) {
269 178 : case LIBNET_RPC_CONNECT_PDC:
270 178 : s->f.in.name_type = NBT_NAME_PDC;
271 178 : break;
272 :
273 31 : case LIBNET_RPC_CONNECT_DC:
274 31 : s->f.in.name_type = NBT_NAME_LOGON;
275 31 : break;
276 :
277 0 : default:
278 0 : break;
279 : }
280 :
281 209 : s->f.in.domain_name = r->in.name;
282 209 : s->f.out.num_dcs = 0;
283 209 : s->f.out.dcs = NULL;
284 :
285 : /* find the domain pdc first */
286 209 : lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
287 209 : if (composite_nomem(lookup_dc_req, c)) return c;
288 :
289 209 : tevent_req_set_callback(lookup_dc_req, continue_lookup_dc, c);
290 209 : return c;
291 : }
292 :
293 :
294 : /*
295 : Step 2 of RpcConnectDC: get domain controller name and
296 : initiate RpcConnect to it
297 : */
298 209 : static void continue_lookup_dc(struct tevent_req *req)
299 : {
300 153 : struct composite_context *c;
301 153 : struct rpc_connect_dc_state *s;
302 153 : struct composite_context *rpc_connect_req;
303 153 : struct monitor_msg msg;
304 153 : struct msg_net_lookup_dc data;
305 :
306 209 : c = tevent_req_callback_data(req, struct composite_context);
307 209 : s = talloc_get_type_abort(c->private_data, struct rpc_connect_dc_state);
308 :
309 : /* receive result of domain controller lookup */
310 209 : c->status = libnet_LookupDCs_recv(req, c, &s->f);
311 209 : if (!composite_is_ok(c)) return;
312 :
313 : /* decide on preferred address type depending on DC type */
314 209 : s->connect_name = s->f.out.dcs[0].name;
315 :
316 : /* post monitor message */
317 209 : if (s->monitor_fn) {
318 : /* prepare a monitor message and post it */
319 0 : data.domain_name = s->f.in.domain_name;
320 0 : data.hostname = s->f.out.dcs[0].name;
321 0 : data.address = s->f.out.dcs[0].address;
322 :
323 0 : msg.type = mon_NetLookupDc;
324 0 : msg.data = &data;
325 0 : msg.data_size = sizeof(data);
326 0 : s->monitor_fn(&msg);
327 : }
328 :
329 : /* ok, pdc has been found so do attempt to rpc connect */
330 209 : s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
331 :
332 : /* this will cause yet another name resolution, but at least
333 : * we pass the right name down the stack now */
334 209 : s->r2.in.name = talloc_strdup(s, s->connect_name);
335 209 : s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address);
336 209 : s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface;
337 209 : s->r2.in.dcerpc_flags = s->r.in.dcerpc_flags;
338 :
339 : /* send rpc connect request to the server */
340 209 : rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
341 209 : if (composite_nomem(rpc_connect_req, c)) return;
342 :
343 209 : composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
344 : }
345 :
346 :
347 : /*
348 : Step 3 of RpcConnectDC: get rpc connection to the server
349 : */
350 209 : static void continue_rpc_connect(struct composite_context *ctx)
351 : {
352 153 : struct composite_context *c;
353 153 : struct rpc_connect_dc_state *s;
354 :
355 209 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
356 209 : s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
357 :
358 209 : c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
359 :
360 : /* error string is to be passed anyway */
361 209 : s->r.out.error_string = s->r2.out.error_string;
362 209 : if (!composite_is_ok(c)) return;
363 :
364 201 : s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
365 :
366 : /* post monitor message */
367 201 : if (s->monitor_fn) {
368 0 : struct monitor_msg msg;
369 0 : struct msg_net_rpc_connect data;
370 0 : const struct dcerpc_binding *b = s->r.out.dcerpc_pipe->binding;
371 :
372 0 : data.host = dcerpc_binding_get_string_option(b, "host");
373 0 : data.endpoint = dcerpc_binding_get_string_option(b, "endpoint");
374 0 : data.transport = dcerpc_binding_get_transport(b);
375 0 : data.domain_name = dcerpc_binding_get_string_option(b, "target_hostname");
376 :
377 0 : msg.type = mon_NetRpcConnect;
378 0 : msg.data = (void*)&data;
379 0 : msg.data_size = sizeof(data);
380 0 : s->monitor_fn(&msg);
381 : }
382 :
383 201 : composite_done(c);
384 : }
385 :
386 :
387 : /**
388 : * Receives result of connection to rpc pipe on domain pdc
389 : *
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
395 : **/
396 :
397 209 : static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
398 : struct libnet_context *ctx,
399 : TALLOC_CTX *mem_ctx,
400 : struct libnet_RpcConnect *r)
401 : {
402 153 : NTSTATUS status;
403 209 : struct rpc_connect_dc_state *s = talloc_get_type(c->private_data,
404 : struct rpc_connect_dc_state);
405 :
406 209 : status = composite_wait(c);
407 209 : if (NT_STATUS_IS_OK(status)) {
408 : /* move connected rpc pipe between memory contexts
409 :
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).
416 : */
417 201 : r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe),
418 201 : mem_ctx, s->r.out.dcerpc_pipe);
419 :
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
422 : mem_ctx is freed */
423 201 : if (r->in.dcerpc_iface == &ndr_table_samr) {
424 179 : ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
425 179 : ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
426 22 : } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
427 20 : ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
428 20 : ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
429 : }
430 :
431 : } else {
432 8 : r->out.error_string = talloc_asprintf(mem_ctx,
433 : "Failed to rpc connect: %s",
434 : nt_errstr(status));
435 : }
436 :
437 209 : talloc_free(c);
438 209 : return status;
439 : }
440 :
441 :
442 :
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;
456 :
457 : /* information about the progress */
458 : void (*monitor_fn)(struct monitor_msg*);
459 : };
460 :
461 :
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);
469 :
470 :
471 : /**
472 : * Initiates connection to rpc pipe on remote server or pdc. Received result
473 : * contains info on the domain name, domain sid and realm.
474 : *
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
479 : **/
480 :
481 564 : static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
482 : TALLOC_CTX *mem_ctx,
483 : struct libnet_RpcConnect *r,
484 : void (*monitor)(struct monitor_msg*))
485 : {
486 459 : struct composite_context *c, *conn_req;
487 459 : struct rpc_connect_dci_state *s;
488 :
489 : /* composite context allocation and setup */
490 564 : c = composite_create(ctx, ctx->event_ctx);
491 564 : if (c == NULL) return c;
492 :
493 564 : s = talloc_zero(c, struct rpc_connect_dci_state);
494 564 : if (composite_nomem(s, c)) return c;
495 :
496 564 : c->private_data = s;
497 564 : s->monitor_fn = monitor;
498 :
499 564 : s->ctx = ctx;
500 564 : s->r = *r;
501 564 : ZERO_STRUCT(s->r.out);
502 :
503 :
504 : /* proceed to pure rpc connection if the binding string is provided,
505 : otherwise try to connect domain controller */
506 564 : if (r->in.binding == NULL) {
507 : /* Pass on any binding flags (such as anonymous fallback) that have been set */
508 18 : s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
509 :
510 18 : s->rpc_conn.in.name = r->in.name;
511 18 : s->rpc_conn.level = LIBNET_RPC_CONNECT_DC;
512 : } else {
513 546 : s->rpc_conn.in.binding = r->in.binding;
514 546 : s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
515 : }
516 :
517 : /* we need to query information on lsarpc interface first */
518 564 : s->rpc_conn.in.dcerpc_iface = &ndr_table_lsarpc;
519 :
520 : /* request connection to the lsa pipe on the pdc */
521 564 : conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
522 564 : if (composite_nomem(c, conn_req)) return c;
523 :
524 564 : composite_continue(c, conn_req, continue_dci_rpc_connect, c);
525 564 : return c;
526 : }
527 :
528 :
529 : /*
530 : Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
531 : lsa policy handle
532 : */
533 564 : static void continue_dci_rpc_connect(struct composite_context *ctx)
534 : {
535 459 : struct composite_context *c;
536 459 : struct rpc_connect_dci_state *s;
537 459 : struct tevent_req *subreq;
538 459 : enum dcerpc_transport_t transport;
539 :
540 564 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
541 564 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
542 :
543 564 : c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn);
544 564 : if (!NT_STATUS_IS_OK(c->status)) {
545 4 : composite_error(c, c->status);
546 4 : return;
547 : }
548 :
549 : /* post monitor message */
550 560 : if (s->monitor_fn) {
551 0 : struct monitor_msg msg;
552 0 : struct msg_net_rpc_connect data;
553 0 : const struct dcerpc_binding *b = s->r.out.dcerpc_pipe->binding;
554 :
555 0 : data.host = dcerpc_binding_get_string_option(b, "host");
556 0 : data.endpoint = dcerpc_binding_get_string_option(b, "endpoint");
557 0 : data.transport = dcerpc_binding_get_transport(b);
558 0 : data.domain_name = dcerpc_binding_get_string_option(b, "target_hostname");
559 :
560 0 : msg.type = mon_NetRpcConnect;
561 0 : msg.data = (void*)&data;
562 0 : msg.data_size = sizeof(data);
563 0 : s->monitor_fn(&msg);
564 : }
565 :
566 : /* prepare to open a policy handle on lsa pipe */
567 560 : s->lsa_pipe = s->ctx->lsa.pipe;
568 :
569 560 : s->qos.len = 0;
570 560 : s->qos.impersonation_level = 2;
571 560 : s->qos.context_mode = 1;
572 560 : s->qos.effective_only = 0;
573 :
574 560 : s->attr.sec_qos = &s->qos;
575 :
576 560 : transport = dcerpc_binding_get_transport(s->lsa_pipe->binding);
577 560 : if (transport == NCACN_IP_TCP) {
578 : /*
579 : * Skip to creating the actual connection. We can't open a
580 : * policy handle over tcpip.
581 : */
582 0 : continue_epm_map_binding_send(c);
583 0 : return;
584 : }
585 :
586 560 : s->lsa_open_policy.in.attr = &s->attr;
587 560 : s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\");
588 560 : if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return;
589 :
590 560 : s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
591 560 : s->lsa_open_policy.out.handle = &s->lsa_handle;
592 :
593 1120 : subreq = dcerpc_lsa_OpenPolicy2_r_send(s, c->event_ctx,
594 560 : s->lsa_pipe->binding_handle,
595 : &s->lsa_open_policy);
596 560 : if (composite_nomem(subreq, c)) return;
597 :
598 560 : tevent_req_set_callback(subreq, continue_lsa_policy, c);
599 : }
600 :
601 :
602 : /*
603 : Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
604 : for kerberos realm (dns name) and guid. The query may fail.
605 : */
606 560 : static void continue_lsa_policy(struct tevent_req *subreq)
607 : {
608 456 : struct composite_context *c;
609 456 : struct rpc_connect_dci_state *s;
610 :
611 560 : c = tevent_req_callback_data(subreq, struct composite_context);
612 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
613 :
614 560 : c->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, s);
615 560 : TALLOC_FREE(subreq);
616 560 : if (!NT_STATUS_IS_OK(c->status)) {
617 0 : composite_error(c, c->status);
618 0 : return;
619 : }
620 :
621 560 : if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
622 0 : s->r.out.realm = NULL;
623 0 : s->r.out.guid = NULL;
624 0 : s->r.out.domain_name = NULL;
625 0 : s->r.out.domain_sid = NULL;
626 :
627 : /* Skip to the creating the actual connection, no info available on this transport */
628 0 : continue_epm_map_binding_send(c);
629 0 : return;
630 :
631 560 : } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
632 0 : composite_error(c, s->lsa_open_policy.out.result);
633 0 : return;
634 : }
635 :
636 : /* post monitor message */
637 560 : if (s->monitor_fn) {
638 0 : struct monitor_msg msg;
639 :
640 0 : msg.type = mon_LsaOpenPolicy;
641 0 : msg.data = NULL;
642 0 : msg.data_size = 0;
643 0 : s->monitor_fn(&msg);
644 : }
645 :
646 : /* query lsa info for dns domain name and guid */
647 560 : s->lsa_query_info2.in.handle = &s->lsa_handle;
648 560 : s->lsa_query_info2.in.level = LSA_POLICY_INFO_DNS;
649 560 : s->lsa_query_info2.out.info = talloc_zero(c, union lsa_PolicyInformation *);
650 560 : if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
651 :
652 1120 : subreq = dcerpc_lsa_QueryInfoPolicy2_r_send(s, c->event_ctx,
653 560 : s->lsa_pipe->binding_handle,
654 : &s->lsa_query_info2);
655 560 : if (composite_nomem(subreq, c)) return;
656 :
657 560 : tevent_req_set_callback(subreq, continue_lsa_query_info2, c);
658 : }
659 :
660 :
661 : /*
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.
664 : */
665 560 : static void continue_lsa_query_info2(struct tevent_req *subreq)
666 : {
667 456 : struct composite_context *c;
668 456 : struct rpc_connect_dci_state *s;
669 :
670 560 : c = tevent_req_callback_data(subreq, struct composite_context);
671 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
672 :
673 560 : c->status = dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq, s);
674 560 : TALLOC_FREE(subreq);
675 :
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 */
679 :
680 560 : if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
681 50 : s->r.out.realm = NULL;
682 50 : s->r.out.guid = NULL;
683 :
684 : } else {
685 510 : if (!NT_STATUS_IS_OK(c->status)) {
686 0 : s->r.out.error_string = talloc_asprintf(c,
687 : "lsa_QueryInfoPolicy2 failed: %s",
688 : nt_errstr(c->status));
689 0 : composite_error(c, c->status);
690 0 : return;
691 : }
692 :
693 510 : if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) {
694 0 : s->r.out.error_string = talloc_asprintf(c,
695 : "lsa_QueryInfoPolicy2 failed: %s",
696 : nt_errstr(s->lsa_query_info2.out.result));
697 0 : composite_error(c, s->lsa_query_info2.out.result);
698 0 : return;
699 : }
700 :
701 : /* Copy the dns domain name and guid from the query result */
702 :
703 : /* this should actually be a conversion from lsa_StringLarge */
704 510 : s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
705 510 : s->r.out.guid = talloc(c, struct GUID);
706 510 : if (composite_nomem(s->r.out.guid, c)) {
707 0 : s->r.out.error_string = NULL;
708 0 : return;
709 : }
710 510 : *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
711 : }
712 :
713 : /* post monitor message */
714 560 : if (s->monitor_fn) {
715 0 : struct monitor_msg msg;
716 :
717 0 : msg.type = mon_LsaQueryPolicy;
718 0 : msg.data = NULL;
719 0 : msg.data_size = 0;
720 0 : s->monitor_fn(&msg);
721 : }
722 :
723 : /* query lsa info for domain name and sid */
724 560 : s->lsa_query_info.in.handle = &s->lsa_handle;
725 560 : s->lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN;
726 560 : s->lsa_query_info.out.info = talloc_zero(c, union lsa_PolicyInformation *);
727 560 : if (composite_nomem(s->lsa_query_info.out.info, c)) return;
728 :
729 1120 : subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
730 560 : s->lsa_pipe->binding_handle,
731 : &s->lsa_query_info);
732 560 : if (composite_nomem(subreq, c)) return;
733 :
734 560 : tevent_req_set_callback(subreq, continue_lsa_query_info, c);
735 : }
736 :
737 :
738 : /*
739 : Step 5 of RpcConnectDCInfo: Get domain name and sid
740 : */
741 560 : static void continue_lsa_query_info(struct tevent_req *subreq)
742 : {
743 456 : struct composite_context *c;
744 456 : struct rpc_connect_dci_state *s;
745 :
746 560 : c = tevent_req_callback_data(subreq, struct composite_context);
747 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
748 :
749 560 : c->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, s);
750 560 : TALLOC_FREE(subreq);
751 560 : if (!NT_STATUS_IS_OK(c->status)) {
752 0 : s->r.out.error_string = talloc_asprintf(c,
753 : "lsa_QueryInfoPolicy failed: %s",
754 : nt_errstr(c->status));
755 0 : composite_error(c, c->status);
756 0 : return;
757 : }
758 :
759 : /* post monitor message */
760 560 : if (s->monitor_fn) {
761 0 : struct monitor_msg msg;
762 :
763 0 : msg.type = mon_LsaQueryPolicy;
764 0 : msg.data = NULL;
765 0 : msg.data_size = 0;
766 0 : s->monitor_fn(&msg);
767 : }
768 :
769 : /* Copy the domain name and sid from the query result */
770 560 : s->r.out.domain_sid = (*s->lsa_query_info.out.info)->domain.sid;
771 560 : s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
772 :
773 560 : continue_epm_map_binding_send(c);
774 : }
775 :
776 : /*
777 : Step 5 (continued) of RpcConnectDCInfo: request endpoint
778 : map binding.
779 :
780 : We may short-cut to this step if we don't support LSA OpenPolicy on this transport
781 : */
782 560 : static void continue_epm_map_binding_send(struct composite_context *c)
783 : {
784 456 : struct rpc_connect_dci_state *s;
785 456 : struct composite_context *epm_map_req;
786 560 : struct cli_credentials *epm_creds = NULL;
787 :
788 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
789 :
790 : /* prepare to get endpoint mapping for the requested interface */
791 560 : s->final_binding = dcerpc_binding_dup(s, s->lsa_pipe->binding);
792 560 : if (composite_nomem(s->final_binding, c)) return;
793 :
794 : /*
795 : * We don't want to inherit the assoc_group_id from the
796 : * lsa_pipe here!
797 : */
798 560 : dcerpc_binding_set_assoc_group_id(s->final_binding, 0);
799 :
800 560 : epm_creds = cli_credentials_init_anon(s);
801 560 : if (composite_nomem(epm_creds, c)) return;
802 :
803 1120 : epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
804 : epm_creds,
805 560 : s->ctx->event_ctx, s->ctx->lp_ctx);
806 560 : if (composite_nomem(epm_map_req, c)) return;
807 :
808 560 : composite_continue(c, epm_map_req, continue_epm_map_binding, c);
809 : }
810 :
811 : /*
812 : Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
813 : rpc connection derived from already used pipe but connected to the requested
814 : one (as specified in libnet_RpcConnect structure)
815 : */
816 560 : static void continue_epm_map_binding(struct composite_context *ctx)
817 : {
818 456 : struct composite_context *c, *sec_conn_req;
819 456 : struct rpc_connect_dci_state *s;
820 :
821 560 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
822 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
823 :
824 560 : c->status = dcerpc_epm_map_binding_recv(ctx);
825 560 : if (!NT_STATUS_IS_OK(c->status)) {
826 0 : s->r.out.error_string = talloc_asprintf(c,
827 : "failed to map pipe with endpoint mapper - %s",
828 : nt_errstr(c->status));
829 0 : composite_error(c, c->status);
830 0 : return;
831 : }
832 :
833 : /* create secondary connection derived from lsa pipe */
834 1120 : sec_conn_req = dcerpc_secondary_auth_connection_send(s->lsa_pipe,
835 560 : s->final_binding,
836 : s->r.in.dcerpc_iface,
837 104 : s->ctx->cred,
838 560 : s->ctx->lp_ctx);
839 560 : if (composite_nomem(sec_conn_req, c)) return;
840 :
841 560 : composite_continue(c, sec_conn_req, continue_secondary_conn, c);
842 : }
843 :
844 :
845 : /*
846 : Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
847 : and complete this composite call
848 : */
849 560 : static void continue_secondary_conn(struct composite_context *ctx)
850 : {
851 456 : struct composite_context *c;
852 456 : struct rpc_connect_dci_state *s;
853 :
854 560 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
855 560 : s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
856 :
857 560 : c->status = dcerpc_secondary_auth_connection_recv(ctx, s->lsa_pipe,
858 : &s->final_pipe);
859 560 : if (!NT_STATUS_IS_OK(c->status)) {
860 0 : s->r.out.error_string = talloc_asprintf(c,
861 : "secondary connection failed: %s",
862 : nt_errstr(c->status));
863 :
864 0 : composite_error(c, c->status);
865 0 : return;
866 : }
867 :
868 560 : s->r.out.dcerpc_pipe = s->final_pipe;
869 :
870 : /* post monitor message */
871 560 : if (s->monitor_fn) {
872 0 : struct monitor_msg msg;
873 0 : struct msg_net_rpc_connect data;
874 0 : const struct dcerpc_binding *b = s->r.out.dcerpc_pipe->binding;
875 :
876 : /* prepare monitor message and post it */
877 0 : data.host = dcerpc_binding_get_string_option(b, "host");
878 0 : data.endpoint = dcerpc_binding_get_string_option(b, "endpoint");
879 0 : data.transport = dcerpc_binding_get_transport(b);
880 0 : data.domain_name = dcerpc_binding_get_string_option(b, "target_hostname");
881 :
882 0 : msg.type = mon_NetRpcConnect;
883 0 : msg.data = (void*)&data;
884 0 : msg.data_size = sizeof(data);
885 0 : s->monitor_fn(&msg);
886 : }
887 :
888 560 : composite_done(c);
889 : }
890 :
891 :
892 : /**
893 : * Receives result of connection to rpc pipe and gets basic
894 : * domain info (name, sid, realm, guid)
895 : *
896 : * @param c composite context
897 : * @param ctx initialised libnet context
898 : * @param mem_ctx memory context of this call
899 : * @param r data structure containing return values
900 : * @return nt status of rpc connection
901 : **/
902 :
903 564 : static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx,
904 : TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
905 : {
906 459 : NTSTATUS status;
907 564 : struct rpc_connect_dci_state *s = talloc_get_type(c->private_data,
908 : struct rpc_connect_dci_state);
909 :
910 564 : status = composite_wait(c);
911 564 : if (NT_STATUS_IS_OK(status)) {
912 560 : r->out.realm = talloc_steal(mem_ctx, s->r.out.realm);
913 560 : r->out.guid = talloc_steal(mem_ctx, s->r.out.guid);
914 560 : r->out.domain_name = talloc_steal(mem_ctx, s->r.out.domain_name);
915 560 : r->out.domain_sid = talloc_steal(mem_ctx, s->r.out.domain_sid);
916 :
917 560 : r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
918 :
919 : /* reference created pipe structure to long-term libnet_context
920 : so that it can be used by other api functions even after short-term
921 : mem_ctx is freed */
922 560 : if (r->in.dcerpc_iface == &ndr_table_samr) {
923 558 : ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
924 558 : ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
925 :
926 2 : } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
927 1 : ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
928 1 : ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
929 : }
930 :
931 : } else {
932 4 : if (s->r.out.error_string) {
933 0 : r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
934 4 : } else if (r->in.binding == NULL) {
935 4 : r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
936 : } else {
937 0 : r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s",
938 : r->in.binding, nt_errstr(status));
939 : }
940 : }
941 :
942 564 : talloc_free(c);
943 564 : return status;
944 : }
945 :
946 :
947 : /**
948 : * Initiates connection to rpc pipe on remote server or pdc, optionally
949 : * providing domain info
950 : *
951 : * @param ctx initialised libnet context
952 : * @param mem_ctx memory context of this call
953 : * @param r data structure containing necessary parameters and return values
954 : * @return composite context of this call
955 : **/
956 :
957 1351 : struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
958 : TALLOC_CTX *mem_ctx,
959 : struct libnet_RpcConnect *r,
960 : void (*monitor)(struct monitor_msg*))
961 : {
962 1085 : struct composite_context *c;
963 :
964 1351 : switch (r->level) {
965 578 : case LIBNET_RPC_CONNECT_SERVER:
966 : case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
967 : case LIBNET_RPC_CONNECT_BINDING:
968 578 : c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
969 1824 : break;
970 :
971 209 : case LIBNET_RPC_CONNECT_PDC:
972 : case LIBNET_RPC_CONNECT_DC:
973 209 : c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
974 209 : break;
975 :
976 564 : case LIBNET_RPC_CONNECT_DC_INFO:
977 564 : c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
978 564 : break;
979 :
980 0 : default:
981 0 : c = talloc_zero(mem_ctx, struct composite_context);
982 0 : composite_error(c, NT_STATUS_INVALID_LEVEL);
983 : }
984 :
985 1351 : return c;
986 : }
987 :
988 :
989 : /**
990 : * Receives result of connection to rpc pipe on remote server or pdc
991 : *
992 : * @param c composite context
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
997 : **/
998 :
999 1351 : NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx,
1000 : TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
1001 : {
1002 1351 : switch (r->level) {
1003 578 : case LIBNET_RPC_CONNECT_SERVER:
1004 : case LIBNET_RPC_CONNECT_BINDING:
1005 844 : return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r);
1006 :
1007 209 : case LIBNET_RPC_CONNECT_PDC:
1008 : case LIBNET_RPC_CONNECT_DC:
1009 209 : return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r);
1010 :
1011 564 : case LIBNET_RPC_CONNECT_DC_INFO:
1012 564 : return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r);
1013 :
1014 0 : default:
1015 0 : ZERO_STRUCT(r->out);
1016 0 : return NT_STATUS_INVALID_LEVEL;
1017 : }
1018 : }
1019 :
1020 :
1021 : /**
1022 : * Connect to a rpc pipe on a remote server - sync version
1023 : *
1024 : * @param ctx initialised libnet context
1025 : * @param mem_ctx memory context of this call
1026 : * @param r data structure containing necessary parameters and return values
1027 : * @return nt status of rpc connection
1028 : **/
1029 :
1030 778 : NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
1031 : struct libnet_RpcConnect *r)
1032 : {
1033 617 : struct composite_context *c;
1034 :
1035 778 : c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
1036 778 : return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);
1037 : }
|