Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client routines
4 : * Largely rewritten by Jeremy Allison 2005.
5 : * Heavily modified by Simo Sorce 2010.
6 : * Copyright Andrew Bartlett 2011.
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 3 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "libsmb/namequery.h"
24 : #include "../lib/util/tevent_ntstatus.h"
25 : #include "librpc/gen_ndr/ndr_epmapper_c.h"
26 : #include "../librpc/gen_ndr/ndr_dssetup.h"
27 : #include "../libcli/auth/schannel.h"
28 : #include "../libcli/auth/netlogon_creds_cli.h"
29 : #include "auth_generic.h"
30 : #include "librpc/gen_ndr/ndr_dcerpc.h"
31 : #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 : #include "librpc/gen_ndr/auth.h"
33 : #include "librpc/rpc/dcerpc.h"
34 : #include "librpc/rpc/dcerpc_util.h"
35 : #include "rpc_dce.h"
36 : #include "cli_pipe.h"
37 : #include "libsmb/libsmb.h"
38 : #include "auth/gensec/gensec.h"
39 : #include "auth/credentials/credentials.h"
40 : #include "auth/auth_util.h"
41 : #include "../libcli/smb/smbXcli_base.h"
42 : #include "lib/tsocket/tsocket.h"
43 : #include "libcli/named_pipe_auth/npa_tstream.h"
44 : #include "librpc/gen_ndr/ndr_winreg.h"
45 : #include "local_np.h"
46 :
47 : #undef DBGC_CLASS
48 : #define DBGC_CLASS DBGC_RPC_CLI
49 :
50 : /********************************************************************
51 : Pipe description for a DEBUG
52 : ********************************************************************/
53 328 : static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
54 : struct rpc_pipe_client *cli)
55 : {
56 328 : char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
57 328 : if (result == NULL) {
58 0 : return "pipe";
59 : }
60 328 : return result;
61 : }
62 :
63 : /********************************************************************
64 : Rpc pipe call id.
65 : ********************************************************************/
66 :
67 590274 : static uint32_t get_rpc_call_id(void)
68 : {
69 0 : static uint32_t call_id = 0;
70 590274 : return ++call_id;
71 : }
72 :
73 : /*******************************************************************
74 : Use SMBreadX to get rest of one fragment's worth of rpc data.
75 : Reads the whole size or give an error message
76 : ********************************************************************/
77 :
78 : struct rpc_read_state {
79 : struct tevent_context *ev;
80 : struct rpc_cli_transport *transport;
81 : uint8_t *data;
82 : size_t size;
83 : size_t num_read;
84 : };
85 :
86 : static void rpc_read_done(struct tevent_req *subreq);
87 :
88 591205 : static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
89 : struct tevent_context *ev,
90 : struct rpc_cli_transport *transport,
91 : uint8_t *data, size_t size)
92 : {
93 0 : struct tevent_req *req, *subreq;
94 0 : struct rpc_read_state *state;
95 :
96 591205 : req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
97 591205 : if (req == NULL) {
98 0 : return NULL;
99 : }
100 591205 : state->ev = ev;
101 591205 : state->transport = transport;
102 591205 : state->data = data;
103 591205 : state->size = size;
104 591205 : state->num_read = 0;
105 :
106 591205 : DBG_INFO("data_to_read: %zu\n", size);
107 :
108 591205 : subreq = transport->read_send(state, ev, (uint8_t *)data, size,
109 : transport->priv);
110 591205 : if (subreq == NULL) {
111 0 : goto fail;
112 : }
113 591205 : tevent_req_set_callback(subreq, rpc_read_done, req);
114 591205 : return req;
115 :
116 0 : fail:
117 0 : TALLOC_FREE(req);
118 0 : return NULL;
119 : }
120 :
121 591205 : static void rpc_read_done(struct tevent_req *subreq)
122 : {
123 591205 : struct tevent_req *req = tevent_req_callback_data(
124 : subreq, struct tevent_req);
125 591205 : struct rpc_read_state *state = tevent_req_data(
126 : req, struct rpc_read_state);
127 0 : NTSTATUS status;
128 0 : ssize_t received;
129 :
130 591205 : status = state->transport->read_recv(subreq, &received);
131 591205 : TALLOC_FREE(subreq);
132 591205 : if (tevent_req_nterror(req, status)) {
133 591205 : return;
134 : }
135 :
136 591205 : state->num_read += received;
137 591205 : if (state->num_read == state->size) {
138 591205 : tevent_req_done(req);
139 591205 : return;
140 : }
141 :
142 0 : subreq = state->transport->read_send(state, state->ev,
143 0 : state->data + state->num_read,
144 0 : state->size - state->num_read,
145 0 : state->transport->priv);
146 0 : if (tevent_req_nomem(subreq, req)) {
147 0 : return;
148 : }
149 0 : tevent_req_set_callback(subreq, rpc_read_done, req);
150 : }
151 :
152 591205 : static NTSTATUS rpc_read_recv(struct tevent_req *req)
153 : {
154 591205 : return tevent_req_simple_recv_ntstatus(req);
155 : }
156 :
157 : struct rpc_write_state {
158 : struct tevent_context *ev;
159 : struct rpc_cli_transport *transport;
160 : const uint8_t *data;
161 : size_t size;
162 : size_t num_written;
163 : };
164 :
165 : static void rpc_write_done(struct tevent_req *subreq);
166 :
167 475014 : static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
168 : struct tevent_context *ev,
169 : struct rpc_cli_transport *transport,
170 : const uint8_t *data, size_t size)
171 : {
172 0 : struct tevent_req *req, *subreq;
173 0 : struct rpc_write_state *state;
174 :
175 475014 : req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
176 475014 : if (req == NULL) {
177 0 : return NULL;
178 : }
179 475014 : state->ev = ev;
180 475014 : state->transport = transport;
181 475014 : state->data = data;
182 475014 : state->size = size;
183 475014 : state->num_written = 0;
184 :
185 475014 : DBG_INFO("data_to_write: %zu\n", size);
186 :
187 475014 : subreq = transport->write_send(state, ev, data, size, transport->priv);
188 475014 : if (tevent_req_nomem(subreq, req)) {
189 0 : return tevent_req_post(req, ev);
190 : }
191 475014 : tevent_req_set_callback(subreq, rpc_write_done, req);
192 475014 : return req;
193 : }
194 :
195 475014 : static void rpc_write_done(struct tevent_req *subreq)
196 : {
197 475014 : struct tevent_req *req = tevent_req_callback_data(
198 : subreq, struct tevent_req);
199 475014 : struct rpc_write_state *state = tevent_req_data(
200 : req, struct rpc_write_state);
201 0 : NTSTATUS status;
202 0 : ssize_t written;
203 :
204 475014 : status = state->transport->write_recv(subreq, &written);
205 475014 : TALLOC_FREE(subreq);
206 475014 : if (tevent_req_nterror(req, status)) {
207 475014 : return;
208 : }
209 :
210 475014 : state->num_written += written;
211 :
212 475014 : if (state->num_written == state->size) {
213 475014 : tevent_req_done(req);
214 475014 : return;
215 : }
216 :
217 0 : subreq = state->transport->write_send(state, state->ev,
218 0 : state->data + state->num_written,
219 0 : state->size - state->num_written,
220 0 : state->transport->priv);
221 0 : if (tevent_req_nomem(subreq, req)) {
222 0 : return;
223 : }
224 0 : tevent_req_set_callback(subreq, rpc_write_done, req);
225 : }
226 :
227 475014 : static NTSTATUS rpc_write_recv(struct tevent_req *req)
228 : {
229 475014 : return tevent_req_simple_recv_ntstatus(req);
230 : }
231 :
232 :
233 : /****************************************************************************
234 : Try and get a PDU's worth of data from current_pdu. If not, then read more
235 : from the wire.
236 : ****************************************************************************/
237 :
238 : struct get_complete_frag_state {
239 : struct tevent_context *ev;
240 : struct rpc_pipe_client *cli;
241 : uint16_t frag_len;
242 : DATA_BLOB *pdu;
243 : };
244 :
245 : static void get_complete_frag_got_header(struct tevent_req *subreq);
246 : static void get_complete_frag_got_rest(struct tevent_req *subreq);
247 :
248 590819 : static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
249 : struct tevent_context *ev,
250 : struct rpc_pipe_client *cli,
251 : DATA_BLOB *pdu)
252 : {
253 0 : struct tevent_req *req, *subreq;
254 0 : struct get_complete_frag_state *state;
255 0 : size_t received;
256 :
257 590819 : req = tevent_req_create(mem_ctx, &state,
258 : struct get_complete_frag_state);
259 590819 : if (req == NULL) {
260 0 : return NULL;
261 : }
262 590819 : state->ev = ev;
263 590819 : state->cli = cli;
264 590819 : state->frag_len = RPC_HEADER_LEN;
265 590819 : state->pdu = pdu;
266 :
267 590819 : received = pdu->length;
268 590819 : if (received < RPC_HEADER_LEN) {
269 386 : if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
270 0 : tevent_req_oom(req);
271 0 : return tevent_req_post(req, ev);
272 : }
273 386 : subreq = rpc_read_send(state, state->ev,
274 386 : state->cli->transport,
275 386 : pdu->data + received,
276 : RPC_HEADER_LEN - received);
277 386 : if (tevent_req_nomem(subreq, req)) {
278 0 : return tevent_req_post(req, ev);
279 : }
280 386 : tevent_req_set_callback(subreq, get_complete_frag_got_header,
281 : req);
282 386 : return req;
283 : }
284 :
285 590433 : state->frag_len = dcerpc_get_frag_length(pdu);
286 590433 : if (state->frag_len < RPC_HEADER_LEN) {
287 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
288 0 : return tevent_req_post(req, ev);
289 : }
290 :
291 590433 : if (received >= state->frag_len) {
292 : /*
293 : * Got the whole fragment
294 : */
295 0 : tevent_req_done(req);
296 0 : return tevent_req_post(req, ev);
297 : }
298 :
299 590433 : if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
300 0 : tevent_req_oom(req);
301 0 : return tevent_req_post(req, ev);
302 : }
303 :
304 590433 : subreq = rpc_read_send(
305 : state,
306 590433 : state->ev,
307 590433 : state->cli->transport,
308 590433 : pdu->data + received,
309 590433 : state->frag_len - received);
310 590433 : if (tevent_req_nomem(subreq, req)) {
311 0 : return tevent_req_post(req, ev);
312 : }
313 590433 : tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
314 590433 : return req;
315 : }
316 :
317 386 : static void get_complete_frag_got_header(struct tevent_req *subreq)
318 : {
319 386 : struct tevent_req *req = tevent_req_callback_data(
320 : subreq, struct tevent_req);
321 386 : struct get_complete_frag_state *state = tevent_req_data(
322 : req, struct get_complete_frag_state);
323 0 : NTSTATUS status;
324 :
325 386 : status = rpc_read_recv(subreq);
326 386 : TALLOC_FREE(subreq);
327 386 : if (tevent_req_nterror(req, status)) {
328 0 : return;
329 : }
330 :
331 386 : state->frag_len = dcerpc_get_frag_length(state->pdu);
332 386 : if (state->frag_len < RPC_HEADER_LEN) {
333 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
334 0 : return;
335 : }
336 :
337 386 : if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
338 0 : tevent_req_oom(req);
339 0 : return;
340 : }
341 :
342 : /*
343 : * We're here in this piece of code because we've read exactly
344 : * RPC_HEADER_LEN bytes into state->pdu.
345 : */
346 :
347 386 : subreq = rpc_read_send(state, state->ev, state->cli->transport,
348 386 : state->pdu->data + RPC_HEADER_LEN,
349 386 : state->frag_len - RPC_HEADER_LEN);
350 386 : if (tevent_req_nomem(subreq, req)) {
351 0 : return;
352 : }
353 386 : tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
354 : }
355 :
356 590819 : static void get_complete_frag_got_rest(struct tevent_req *subreq)
357 : {
358 590819 : NTSTATUS status = rpc_read_recv(subreq);
359 590819 : return tevent_req_simple_finish_ntstatus(subreq, status);
360 : }
361 :
362 590819 : static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
363 : {
364 590819 : return tevent_req_simple_recv_ntstatus(req);
365 : }
366 :
367 : /****************************************************************************
368 : Do basic authentication checks on an incoming pdu.
369 : ****************************************************************************/
370 :
371 590819 : static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
372 : struct rpc_pipe_client *cli,
373 : struct ncacn_packet *pkt,
374 : DATA_BLOB *pdu,
375 : uint8_t expected_pkt_type,
376 : uint32_t call_id,
377 : DATA_BLOB *rdata,
378 : DATA_BLOB *reply_pdu)
379 : {
380 590819 : const struct dcerpc_response *r = NULL;
381 590819 : DATA_BLOB tmp_stub = { .data = NULL };
382 0 : NTSTATUS ret;
383 :
384 : /*
385 : * Point the return values at the real data including the RPC
386 : * header. Just in case the caller wants it.
387 : */
388 590819 : *rdata = *pdu;
389 :
390 590819 : if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
391 41679 : !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
392 : /*
393 : * TODO: do we still need this hack which was introduced
394 : * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
395 : *
396 : * I don't even know what AS/U might be...
397 : */
398 0 : DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
399 : "fragment first/last ON.\n"));
400 0 : pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
401 : }
402 :
403 : /* Ensure we have the correct type. */
404 590819 : switch (pkt->ptype) {
405 0 : case DCERPC_PKT_BIND_NAK:
406 0 : DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
407 : rpccli_pipe_txt(talloc_tos(), cli)));
408 :
409 0 : ret = dcerpc_verify_ncacn_packet_header(pkt,
410 : DCERPC_PKT_BIND_NAK,
411 : 0, /* max_auth_info */
412 : DCERPC_PFC_FLAG_FIRST |
413 : DCERPC_PFC_FLAG_LAST,
414 : 0); /* optional flags */
415 0 : if (!NT_STATUS_IS_OK(ret)) {
416 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
417 : "RPC packet type - %u, expected %u: %s\n",
418 : rpccli_pipe_txt(talloc_tos(), cli),
419 : pkt->ptype, expected_pkt_type,
420 : nt_errstr(ret)));
421 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
422 222 : return ret;
423 : }
424 :
425 : /* Use this for now... */
426 0 : return NT_STATUS_NETWORK_ACCESS_DENIED;
427 :
428 41679 : case DCERPC_PKT_BIND_ACK:
429 41679 : ret = dcerpc_verify_ncacn_packet_header(pkt,
430 : expected_pkt_type,
431 : pkt->u.bind_ack.auth_info.length,
432 : DCERPC_PFC_FLAG_FIRST |
433 : DCERPC_PFC_FLAG_LAST,
434 : DCERPC_PFC_FLAG_CONC_MPX |
435 : DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
436 41679 : if (!NT_STATUS_IS_OK(ret)) {
437 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
438 : "RPC packet type - %u, expected %u: %s\n",
439 : rpccli_pipe_txt(talloc_tos(), cli),
440 : pkt->ptype, expected_pkt_type,
441 : nt_errstr(ret)));
442 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
443 0 : return ret;
444 : }
445 :
446 41679 : break;
447 :
448 159 : case DCERPC_PKT_ALTER_RESP:
449 159 : ret = dcerpc_verify_ncacn_packet_header(pkt,
450 : expected_pkt_type,
451 : pkt->u.alter_resp.auth_info.length,
452 : DCERPC_PFC_FLAG_FIRST |
453 : DCERPC_PFC_FLAG_LAST,
454 : DCERPC_PFC_FLAG_CONC_MPX |
455 : DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
456 159 : if (!NT_STATUS_IS_OK(ret)) {
457 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
458 : "RPC packet type - %u, expected %u: %s\n",
459 : rpccli_pipe_txt(talloc_tos(), cli),
460 : pkt->ptype, expected_pkt_type,
461 : nt_errstr(ret)));
462 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
463 0 : return ret;
464 : }
465 :
466 159 : break;
467 :
468 548759 : case DCERPC_PKT_RESPONSE:
469 :
470 548759 : r = &pkt->u.response;
471 :
472 548759 : ret = dcerpc_verify_ncacn_packet_header(pkt,
473 : expected_pkt_type,
474 548759 : r->stub_and_verifier.length,
475 : 0, /* required_flags */
476 : DCERPC_PFC_FLAG_FIRST |
477 : DCERPC_PFC_FLAG_LAST);
478 548759 : if (!NT_STATUS_IS_OK(ret)) {
479 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
480 : "RPC packet type - %u, expected %u: %s\n",
481 : rpccli_pipe_txt(talloc_tos(), cli),
482 : pkt->ptype, expected_pkt_type,
483 : nt_errstr(ret)));
484 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
485 0 : return ret;
486 : }
487 :
488 548759 : tmp_stub.data = r->stub_and_verifier.data;
489 548759 : tmp_stub.length = r->stub_and_verifier.length;
490 :
491 : /* Here's where we deal with incoming sign/seal. */
492 548759 : ret = dcerpc_check_auth(cli->auth, pkt,
493 : &tmp_stub,
494 : DCERPC_RESPONSE_LENGTH,
495 : pdu);
496 548759 : if (!NT_STATUS_IS_OK(ret)) {
497 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
498 : "RPC packet type - %u, expected %u: %s\n",
499 : rpccli_pipe_txt(talloc_tos(), cli),
500 : pkt->ptype, expected_pkt_type,
501 : nt_errstr(ret)));
502 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
503 0 : return ret;
504 : }
505 :
506 : /* Point the return values at the NDR data. */
507 548759 : *rdata = tmp_stub;
508 :
509 548759 : DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
510 : (long unsigned int)pdu->length,
511 : (long unsigned int)rdata->length));
512 :
513 : /*
514 : * If this is the first reply, and the allocation hint is
515 : * reasonable, try and set up the reply_pdu DATA_BLOB to the
516 : * correct size.
517 : */
518 :
519 548759 : if ((reply_pdu->length == 0) &&
520 548373 : r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
521 548373 : if (!data_blob_realloc(mem_ctx, reply_pdu,
522 548373 : r->alloc_hint)) {
523 0 : DEBUG(0, ("reply alloc hint %d too "
524 : "large to allocate\n",
525 : (int)r->alloc_hint));
526 0 : return NT_STATUS_NO_MEMORY;
527 : }
528 : }
529 :
530 548759 : break;
531 :
532 222 : case DCERPC_PKT_FAULT:
533 :
534 222 : ret = dcerpc_verify_ncacn_packet_header(pkt,
535 : DCERPC_PKT_FAULT,
536 : 0, /* max_auth_info */
537 : DCERPC_PFC_FLAG_FIRST |
538 : DCERPC_PFC_FLAG_LAST,
539 : DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
540 222 : if (!NT_STATUS_IS_OK(ret)) {
541 0 : DEBUG(1, (__location__ ": Connection to %s got an unexpected "
542 : "RPC packet type - %u, expected %u: %s\n",
543 : rpccli_pipe_txt(talloc_tos(), cli),
544 : pkt->ptype, expected_pkt_type,
545 : nt_errstr(ret)));
546 0 : NDR_PRINT_DEBUG(ncacn_packet, pkt);
547 0 : return ret;
548 : }
549 :
550 222 : DEBUG(1, (__location__ ": RPC fault code %s received "
551 : "from %s!\n",
552 : dcerpc_errstr(talloc_tos(),
553 : pkt->u.fault.status),
554 : rpccli_pipe_txt(talloc_tos(), cli)));
555 :
556 222 : return dcerpc_fault_to_nt_status(pkt->u.fault.status);
557 :
558 0 : default:
559 0 : DEBUG(0, (__location__ "Unknown packet type %u received "
560 : "from %s!\n",
561 : (unsigned int)pkt->ptype,
562 : rpccli_pipe_txt(talloc_tos(), cli)));
563 0 : return NT_STATUS_RPC_PROTOCOL_ERROR;
564 : }
565 :
566 :
567 590597 : if (pkt->call_id != call_id) {
568 0 : DEBUG(3, (__location__ ": Connection to %s got an unexpected "
569 : "RPC call_id - %u, not %u\n",
570 : rpccli_pipe_txt(talloc_tos(), cli),
571 : pkt->call_id, call_id));
572 0 : return NT_STATUS_RPC_PROTOCOL_ERROR;
573 : }
574 :
575 590597 : return NT_STATUS_OK;
576 : }
577 :
578 : /****************************************************************************
579 : Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
580 : ****************************************************************************/
581 :
582 : struct cli_api_pipe_state {
583 : struct tevent_context *ev;
584 : struct rpc_cli_transport *transport;
585 : uint8_t *rdata;
586 : uint32_t rdata_len;
587 : };
588 :
589 : static void cli_api_pipe_trans_done(struct tevent_req *subreq);
590 : static void cli_api_pipe_write_done(struct tevent_req *subreq);
591 : static void cli_api_pipe_read_done(struct tevent_req *subreq);
592 :
593 590433 : static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
594 : struct tevent_context *ev,
595 : struct rpc_cli_transport *transport,
596 : uint8_t *data, size_t data_len,
597 : uint32_t max_rdata_len)
598 : {
599 0 : struct tevent_req *req, *subreq;
600 0 : struct cli_api_pipe_state *state;
601 :
602 590433 : req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
603 590433 : if (req == NULL) {
604 0 : return NULL;
605 : }
606 590433 : state->ev = ev;
607 590433 : state->transport = transport;
608 :
609 590433 : if (max_rdata_len < RPC_HEADER_LEN) {
610 : /*
611 : * For a RPC reply we always need at least RPC_HEADER_LEN
612 : * bytes. We check this here because we will receive
613 : * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
614 : */
615 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
616 0 : return tevent_req_post(req, ev);
617 : }
618 :
619 590433 : if (transport->trans_send != NULL) {
620 115493 : subreq = transport->trans_send(state, ev, data, data_len,
621 : max_rdata_len, transport->priv);
622 115493 : if (tevent_req_nomem(subreq, req)) {
623 0 : return tevent_req_post(req, ev);
624 : }
625 115493 : tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
626 115493 : return req;
627 : }
628 :
629 : /*
630 : * If the transport does not provide a "trans" routine, i.e. for
631 : * example the ncacn_ip_tcp transport, do the write/read step here.
632 : */
633 :
634 474940 : subreq = rpc_write_send(state, ev, transport, data, data_len);
635 474940 : if (tevent_req_nomem(subreq, req)) {
636 0 : return tevent_req_post(req, ev);
637 : }
638 474940 : tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
639 474940 : return req;
640 : }
641 :
642 115493 : static void cli_api_pipe_trans_done(struct tevent_req *subreq)
643 : {
644 115493 : struct tevent_req *req = tevent_req_callback_data(
645 : subreq, struct tevent_req);
646 115493 : struct cli_api_pipe_state *state = tevent_req_data(
647 : req, struct cli_api_pipe_state);
648 0 : NTSTATUS status;
649 :
650 115493 : status = state->transport->trans_recv(subreq, state, &state->rdata,
651 : &state->rdata_len);
652 115493 : TALLOC_FREE(subreq);
653 115493 : if (tevent_req_nterror(req, status)) {
654 0 : return;
655 : }
656 115493 : tevent_req_done(req);
657 : }
658 :
659 474940 : static void cli_api_pipe_write_done(struct tevent_req *subreq)
660 : {
661 474940 : struct tevent_req *req = tevent_req_callback_data(
662 : subreq, struct tevent_req);
663 474940 : struct cli_api_pipe_state *state = tevent_req_data(
664 : req, struct cli_api_pipe_state);
665 0 : NTSTATUS status;
666 :
667 474940 : status = rpc_write_recv(subreq);
668 474940 : TALLOC_FREE(subreq);
669 474940 : if (tevent_req_nterror(req, status)) {
670 0 : return;
671 : }
672 :
673 474940 : state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
674 474940 : if (tevent_req_nomem(state->rdata, req)) {
675 0 : return;
676 : }
677 :
678 : /*
679 : * We don't need to use rpc_read_send here, the upper layer will cope
680 : * with a short read, transport->trans_send could also return less
681 : * than state->max_rdata_len.
682 : */
683 474940 : subreq = state->transport->read_send(state, state->ev, state->rdata,
684 : RPC_HEADER_LEN,
685 474940 : state->transport->priv);
686 474940 : if (tevent_req_nomem(subreq, req)) {
687 0 : return;
688 : }
689 474940 : tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
690 : }
691 :
692 474940 : static void cli_api_pipe_read_done(struct tevent_req *subreq)
693 : {
694 474940 : struct tevent_req *req = tevent_req_callback_data(
695 : subreq, struct tevent_req);
696 474940 : struct cli_api_pipe_state *state = tevent_req_data(
697 : req, struct cli_api_pipe_state);
698 0 : NTSTATUS status;
699 0 : ssize_t received;
700 :
701 474940 : status = state->transport->read_recv(subreq, &received);
702 474940 : TALLOC_FREE(subreq);
703 474940 : if (tevent_req_nterror(req, status)) {
704 0 : return;
705 : }
706 474940 : state->rdata_len = received;
707 474940 : tevent_req_done(req);
708 : }
709 :
710 590433 : static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
711 : uint8_t **prdata, uint32_t *prdata_len)
712 : {
713 590433 : struct cli_api_pipe_state *state = tevent_req_data(
714 : req, struct cli_api_pipe_state);
715 0 : NTSTATUS status;
716 :
717 590433 : if (tevent_req_is_nterror(req, &status)) {
718 0 : return status;
719 : }
720 :
721 590433 : *prdata = talloc_move(mem_ctx, &state->rdata);
722 590433 : *prdata_len = state->rdata_len;
723 590433 : return NT_STATUS_OK;
724 : }
725 :
726 : /****************************************************************************
727 : Send data on an rpc pipe via trans. The data must be the last
728 : pdu fragment of an NDR data stream.
729 :
730 : Receive response data from an rpc pipe, which may be large...
731 :
732 : Read the first fragment: unfortunately have to use SMBtrans for the first
733 : bit, then SMBreadX for subsequent bits.
734 :
735 : If first fragment received also wasn't the last fragment, continue
736 : getting fragments until we _do_ receive the last fragment.
737 :
738 : Request/Response PDU's look like the following...
739 :
740 : |<------------------PDU len----------------------------------------------->|
741 : |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
742 :
743 : +------------+-----------------+-------------+---------------+-------------+
744 : | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
745 : +------------+-----------------+-------------+---------------+-------------+
746 :
747 : Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
748 : signing & sealing being negotiated.
749 :
750 : ****************************************************************************/
751 :
752 : struct rpc_api_pipe_state {
753 : struct tevent_context *ev;
754 : struct rpc_pipe_client *cli;
755 : uint8_t expected_pkt_type;
756 : uint32_t call_id;
757 :
758 : DATA_BLOB incoming_frag;
759 : struct ncacn_packet *pkt;
760 :
761 : /* Incoming reply */
762 : DATA_BLOB reply_pdu;
763 : size_t reply_pdu_offset;
764 : uint8_t endianness;
765 : };
766 :
767 : static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
768 : static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
769 : static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
770 :
771 590507 : static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
772 : struct tevent_context *ev,
773 : struct rpc_pipe_client *cli,
774 : DATA_BLOB *data, /* Outgoing PDU */
775 : uint8_t expected_pkt_type,
776 : uint32_t call_id)
777 : {
778 0 : struct tevent_req *req, *subreq;
779 0 : struct rpc_api_pipe_state *state;
780 0 : uint16_t max_recv_frag;
781 :
782 590507 : req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
783 590507 : if (req == NULL) {
784 0 : return NULL;
785 : }
786 590507 : state->ev = ev;
787 590507 : state->cli = cli;
788 590507 : state->expected_pkt_type = expected_pkt_type;
789 590507 : state->call_id = call_id;
790 590507 : state->endianness = DCERPC_DREP_LE;
791 :
792 : /*
793 : * Ensure we're not sending too much.
794 : */
795 590507 : if (data->length > cli->max_xmit_frag) {
796 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
797 0 : return tevent_req_post(req, ev);
798 : }
799 :
800 590507 : DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
801 :
802 590507 : if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
803 74 : subreq = rpc_write_send(state, ev, cli->transport,
804 74 : data->data, data->length);
805 74 : if (tevent_req_nomem(subreq, req)) {
806 0 : return tevent_req_post(req, ev);
807 : }
808 74 : tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
809 74 : return req;
810 : }
811 :
812 : /* get the header first, then fetch the rest once we have
813 : * the frag_length available */
814 590433 : max_recv_frag = RPC_HEADER_LEN;
815 :
816 590433 : subreq = cli_api_pipe_send(state, ev, cli->transport,
817 : data->data, data->length, max_recv_frag);
818 590433 : if (tevent_req_nomem(subreq, req)) {
819 0 : return tevent_req_post(req, ev);
820 : }
821 590433 : tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
822 590433 : return req;
823 : }
824 :
825 74 : static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
826 : {
827 74 : NTSTATUS status = rpc_write_recv(subreq);
828 74 : return tevent_req_simple_finish_ntstatus(subreq, status);
829 : }
830 :
831 590433 : static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
832 : {
833 590433 : struct tevent_req *req = tevent_req_callback_data(
834 : subreq, struct tevent_req);
835 590433 : struct rpc_api_pipe_state *state = tevent_req_data(
836 : req, struct rpc_api_pipe_state);
837 0 : NTSTATUS status;
838 590433 : uint8_t *rdata = NULL;
839 590433 : uint32_t rdata_len = 0;
840 :
841 590433 : status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
842 590433 : TALLOC_FREE(subreq);
843 590433 : if (tevent_req_nterror(req, status)) {;
844 0 : DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
845 0 : return;
846 : }
847 :
848 590433 : if (rdata == NULL) {
849 0 : DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
850 : rpccli_pipe_txt(talloc_tos(), state->cli)));
851 0 : tevent_req_done(req);
852 0 : return;
853 : }
854 :
855 : /*
856 : * Move data on state->incoming_frag.
857 : */
858 590433 : state->incoming_frag.data = talloc_move(state, &rdata);
859 590433 : state->incoming_frag.length = rdata_len;
860 590433 : if (!state->incoming_frag.data) {
861 0 : tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
862 0 : return;
863 : }
864 :
865 : /* Ensure we have enough data for a pdu. */
866 590433 : subreq = get_complete_frag_send(state, state->ev, state->cli,
867 : &state->incoming_frag);
868 590433 : if (tevent_req_nomem(subreq, req)) {
869 0 : return;
870 : }
871 590433 : tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
872 : }
873 :
874 590819 : static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
875 : {
876 590819 : struct tevent_req *req = tevent_req_callback_data(
877 : subreq, struct tevent_req);
878 590819 : struct rpc_api_pipe_state *state = tevent_req_data(
879 : req, struct rpc_api_pipe_state);
880 0 : NTSTATUS status;
881 590819 : DATA_BLOB rdata = { .data = NULL };
882 :
883 590819 : status = get_complete_frag_recv(subreq);
884 590819 : TALLOC_FREE(subreq);
885 590819 : if (tevent_req_nterror(req, status)) {
886 0 : DEBUG(5, ("get_complete_frag failed: %s\n",
887 : nt_errstr(status)));
888 590433 : return;
889 : }
890 :
891 590819 : state->pkt = talloc(state, struct ncacn_packet);
892 590819 : if (!state->pkt) {
893 : /*
894 : * TODO: do a real async disconnect ...
895 : *
896 : * For now do it sync...
897 : */
898 0 : TALLOC_FREE(state->cli->transport);
899 0 : tevent_req_oom(req);
900 0 : return;
901 : }
902 :
903 590819 : status = dcerpc_pull_ncacn_packet(state->pkt,
904 590819 : &state->incoming_frag,
905 : state->pkt);
906 590819 : if (tevent_req_nterror(req, status)) {
907 : /*
908 : * TODO: do a real async disconnect ...
909 : *
910 : * For now do it sync...
911 : */
912 0 : TALLOC_FREE(state->cli->transport);
913 0 : return;
914 : }
915 :
916 590819 : if (DEBUGLEVEL >= 10) {
917 98 : NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
918 : }
919 :
920 590819 : status = cli_pipe_validate_current_pdu(state,
921 : state->cli, state->pkt,
922 : &state->incoming_frag,
923 590819 : state->expected_pkt_type,
924 : state->call_id,
925 : &rdata,
926 : &state->reply_pdu);
927 :
928 590819 : DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
929 : state->incoming_frag.length,
930 : state->reply_pdu_offset,
931 : nt_errstr(status));
932 :
933 590819 : if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
934 : /*
935 : * TODO: do a real async disconnect ...
936 : *
937 : * For now do it sync...
938 : */
939 0 : TALLOC_FREE(state->cli->transport);
940 590819 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
941 : /*
942 : * TODO: do a real async disconnect ...
943 : *
944 : * For now do it sync...
945 : */
946 0 : TALLOC_FREE(state->cli->transport);
947 590819 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
948 : /*
949 : * TODO: do a real async disconnect ...
950 : *
951 : * For now do it sync...
952 : */
953 0 : TALLOC_FREE(state->cli->transport);
954 : }
955 590819 : if (tevent_req_nterror(req, status)) {
956 222 : return;
957 : }
958 :
959 590597 : if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
960 590211 : && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
961 : /*
962 : * Set the data type correctly for big-endian data on the
963 : * first packet.
964 : */
965 0 : DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
966 : "big-endian.\n",
967 : rpccli_pipe_txt(talloc_tos(), state->cli)));
968 0 : state->endianness = 0x00; /* BIG ENDIAN */
969 : }
970 : /*
971 : * Check endianness on subsequent packets.
972 : */
973 590597 : if (state->endianness != state->pkt->drep[0]) {
974 0 : DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
975 : "%s\n",
976 : state->endianness?"little":"big",
977 : state->pkt->drep[0]?"little":"big"));
978 : /*
979 : * TODO: do a real async disconnect ...
980 : *
981 : * For now do it sync...
982 : */
983 0 : TALLOC_FREE(state->cli->transport);
984 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
985 0 : return;
986 : }
987 :
988 590597 : if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
989 : /*
990 : * TODO: do a real async disconnect ...
991 : *
992 : * For now do it sync...
993 : */
994 0 : TALLOC_FREE(state->cli->transport);
995 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
996 0 : return;
997 : }
998 :
999 : /* Now copy the data portion out of the pdu into rbuf. */
1000 590597 : if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1001 41838 : if (!data_blob_realloc(NULL, &state->reply_pdu,
1002 41838 : state->reply_pdu_offset + rdata.length)) {
1003 : /*
1004 : * TODO: do a real async disconnect ...
1005 : *
1006 : * For now do it sync...
1007 : */
1008 0 : TALLOC_FREE(state->cli->transport);
1009 0 : tevent_req_oom(req);
1010 0 : return;
1011 : }
1012 : }
1013 :
1014 590597 : memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1015 590597 : rdata.data, rdata.length);
1016 590597 : state->reply_pdu_offset += rdata.length;
1017 :
1018 : /* reset state->incoming_frag, there is no need to free it,
1019 : * it will be reallocated to the right size the next time
1020 : * it is used */
1021 590597 : state->incoming_frag.length = 0;
1022 :
1023 590597 : if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1024 : /* make sure the pdu length is right now that we
1025 : * have all the data available (alloc hint may
1026 : * have allocated more than was actually used) */
1027 590211 : state->reply_pdu.length = state->reply_pdu_offset;
1028 590211 : DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1029 : rpccli_pipe_txt(talloc_tos(), state->cli),
1030 : (unsigned)state->reply_pdu.length));
1031 590211 : tevent_req_done(req);
1032 590211 : return;
1033 : }
1034 :
1035 386 : subreq = get_complete_frag_send(state, state->ev, state->cli,
1036 : &state->incoming_frag);
1037 386 : if (subreq == NULL) {
1038 : /*
1039 : * TODO: do a real async disconnect ...
1040 : *
1041 : * For now do it sync...
1042 : */
1043 0 : TALLOC_FREE(state->cli->transport);
1044 : }
1045 386 : if (tevent_req_nomem(subreq, req)) {
1046 0 : return;
1047 : }
1048 386 : tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1049 : }
1050 :
1051 590507 : static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1052 : struct ncacn_packet **pkt,
1053 : DATA_BLOB *reply_pdu)
1054 : {
1055 590507 : struct rpc_api_pipe_state *state = tevent_req_data(
1056 : req, struct rpc_api_pipe_state);
1057 0 : NTSTATUS status;
1058 :
1059 590507 : if (tevent_req_is_nterror(req, &status)) {
1060 222 : return status;
1061 : }
1062 :
1063 : /* return data to caller and assign it ownership of memory */
1064 590285 : if (reply_pdu) {
1065 548373 : reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1066 548373 : reply_pdu->length = state->reply_pdu.length;
1067 548373 : state->reply_pdu.length = 0;
1068 : } else {
1069 41912 : data_blob_free(&state->reply_pdu);
1070 : }
1071 :
1072 590285 : if (pkt) {
1073 41912 : *pkt = talloc_steal(mem_ctx, state->pkt);
1074 : }
1075 :
1076 590285 : return NT_STATUS_OK;
1077 : }
1078 :
1079 : /*******************************************************************
1080 : Creates NTLMSSP auth bind.
1081 : ********************************************************************/
1082 :
1083 476 : static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1084 : TALLOC_CTX *mem_ctx,
1085 : DATA_BLOB *auth_token,
1086 : bool *client_hdr_signing)
1087 : {
1088 0 : struct gensec_security *gensec_security;
1089 476 : DATA_BLOB null_blob = { .data = NULL };
1090 0 : NTSTATUS status;
1091 :
1092 476 : gensec_security = cli->auth->auth_ctx;
1093 :
1094 476 : DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1095 476 : status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1096 :
1097 476 : if (!NT_STATUS_IS_OK(status) &&
1098 476 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1099 : {
1100 0 : return status;
1101 : }
1102 :
1103 476 : if (client_hdr_signing == NULL) {
1104 0 : return status;
1105 : }
1106 :
1107 476 : if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1108 166 : *client_hdr_signing = false;
1109 166 : return status;
1110 : }
1111 :
1112 310 : *client_hdr_signing = gensec_have_feature(gensec_security,
1113 : GENSEC_FEATURE_SIGN_PKT_HEADER);
1114 :
1115 310 : return status;
1116 : }
1117 :
1118 : /*******************************************************************
1119 : Creates the internals of a DCE/RPC bind request or alter context PDU.
1120 : ********************************************************************/
1121 :
1122 41838 : static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1123 : enum dcerpc_pkt_type ptype,
1124 : uint32_t rpc_call_id,
1125 : const struct ndr_syntax_id *abstract,
1126 : const struct ndr_syntax_id *transfer,
1127 : const DATA_BLOB *auth_info,
1128 : bool client_hdr_signing,
1129 : DATA_BLOB *blob)
1130 : {
1131 41838 : uint16_t auth_len = auth_info->length;
1132 0 : NTSTATUS status;
1133 41838 : struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
1134 : DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
1135 : DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
1136 41838 : struct dcerpc_ctx_list ctx_list[2] = {
1137 : [0] = {
1138 : .context_id = 0,
1139 : .num_transfer_syntaxes = 1,
1140 : .abstract_syntax = *abstract,
1141 : .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
1142 : },
1143 : [1] = {
1144 : .context_id = 1,
1145 : .num_transfer_syntaxes = 1,
1146 : .abstract_syntax = *abstract,
1147 : .transfer_syntaxes = &bind_time_features,
1148 : },
1149 : };
1150 41838 : union dcerpc_payload u = {
1151 : .bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN,
1152 : .bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN,
1153 : .bind.num_contexts = ptype == DCERPC_PKT_BIND ? 2 : 1,
1154 : .bind.ctx_list = ctx_list,
1155 : .bind.auth_info = *auth_info,
1156 : };
1157 41838 : uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1158 :
1159 41838 : if (auth_len) {
1160 635 : auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1161 : }
1162 :
1163 41838 : if (client_hdr_signing) {
1164 310 : pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1165 : }
1166 :
1167 41838 : status = dcerpc_push_ncacn_packet(mem_ctx,
1168 : ptype, pfc_flags,
1169 : auth_len,
1170 : rpc_call_id,
1171 : &u,
1172 : blob);
1173 41838 : if (!NT_STATUS_IS_OK(status)) {
1174 0 : DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1175 0 : return status;
1176 : }
1177 :
1178 41838 : return NT_STATUS_OK;
1179 : }
1180 :
1181 : /*******************************************************************
1182 : Creates a DCE/RPC bind request.
1183 : ********************************************************************/
1184 :
1185 41679 : static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1186 : struct rpc_pipe_client *cli,
1187 : struct pipe_auth_data *auth,
1188 : uint32_t rpc_call_id,
1189 : const struct ndr_syntax_id *abstract,
1190 : const struct ndr_syntax_id *transfer,
1191 : DATA_BLOB *rpc_out)
1192 : {
1193 41679 : DATA_BLOB auth_token = { .data = NULL };
1194 41679 : DATA_BLOB auth_info = { .data = NULL };
1195 0 : NTSTATUS ret;
1196 :
1197 41679 : if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
1198 476 : ret = create_generic_auth_rpc_bind_req(
1199 : cli, mem_ctx, &auth_token, &auth->client_hdr_signing);
1200 :
1201 476 : if (!NT_STATUS_IS_OK(ret) &&
1202 476 : !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1203 0 : return ret;
1204 : }
1205 : }
1206 :
1207 41679 : if (auth_token.length != 0) {
1208 476 : ret = dcerpc_push_dcerpc_auth(cli,
1209 : auth->auth_type,
1210 : auth->auth_level,
1211 : 0, /* auth_pad_length */
1212 : auth->auth_context_id,
1213 : &auth_token,
1214 : &auth_info);
1215 476 : if (!NT_STATUS_IS_OK(ret)) {
1216 0 : return ret;
1217 : }
1218 476 : data_blob_free(&auth_token);
1219 : }
1220 :
1221 41679 : ret = create_bind_or_alt_ctx_internal(mem_ctx,
1222 : DCERPC_PKT_BIND,
1223 : rpc_call_id,
1224 : abstract,
1225 : transfer,
1226 : &auth_info,
1227 41679 : auth->client_hdr_signing,
1228 : rpc_out);
1229 41679 : data_blob_free(&auth_info);
1230 :
1231 41679 : return ret;
1232 : }
1233 :
1234 : /*******************************************************************
1235 : External interface.
1236 : Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1237 : Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1238 : and deals with signing/sealing details.
1239 : ********************************************************************/
1240 :
1241 : struct rpc_api_pipe_req_state {
1242 : struct tevent_context *ev;
1243 : struct rpc_pipe_client *cli;
1244 : uint8_t op_num;
1245 : uint32_t call_id;
1246 : const DATA_BLOB *req_data;
1247 : const struct GUID *object_uuid;
1248 : uint32_t req_data_sent;
1249 : DATA_BLOB req_trailer;
1250 : uint32_t req_trailer_sent;
1251 : bool verify_bitmask1;
1252 : bool verify_pcontext;
1253 : DATA_BLOB rpc_out;
1254 : DATA_BLOB reply_pdu;
1255 : };
1256 :
1257 : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1258 : static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1259 : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1260 : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1261 : bool *is_last_frag);
1262 :
1263 548595 : static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1264 : struct tevent_context *ev,
1265 : struct rpc_pipe_client *cli,
1266 : uint8_t op_num,
1267 : const struct GUID *object_uuid,
1268 : const DATA_BLOB *req_data)
1269 : {
1270 0 : struct tevent_req *req, *subreq;
1271 0 : struct rpc_api_pipe_req_state *state;
1272 0 : NTSTATUS status;
1273 0 : bool is_last_frag;
1274 :
1275 548595 : req = tevent_req_create(mem_ctx, &state,
1276 : struct rpc_api_pipe_req_state);
1277 548595 : if (req == NULL) {
1278 0 : return NULL;
1279 : }
1280 548595 : state->ev = ev;
1281 548595 : state->cli = cli;
1282 548595 : state->op_num = op_num;
1283 548595 : state->object_uuid = object_uuid;
1284 548595 : state->req_data = req_data;
1285 548595 : state->call_id = get_rpc_call_id();
1286 :
1287 548595 : if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1288 : + RPC_MAX_SIGN_SIZE) {
1289 : /* Server is screwed up ! */
1290 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1291 0 : return tevent_req_post(req, ev);
1292 : }
1293 :
1294 548595 : status = prepare_verification_trailer(state);
1295 548595 : if (tevent_req_nterror(req, status)) {
1296 0 : return tevent_req_post(req, ev);
1297 : }
1298 :
1299 548595 : status = prepare_next_frag(state, &is_last_frag);
1300 548595 : if (tevent_req_nterror(req, status)) {
1301 0 : return tevent_req_post(req, ev);
1302 : }
1303 :
1304 548595 : if (is_last_frag) {
1305 548595 : subreq = rpc_api_pipe_send(state, ev, state->cli,
1306 548595 : &state->rpc_out,
1307 : DCERPC_PKT_RESPONSE,
1308 548595 : state->call_id);
1309 548595 : if (tevent_req_nomem(subreq, req)) {
1310 0 : return tevent_req_post(req, ev);
1311 : }
1312 548595 : tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1313 : } else {
1314 0 : subreq = rpc_write_send(state, ev, cli->transport,
1315 0 : state->rpc_out.data,
1316 0 : state->rpc_out.length);
1317 0 : if (tevent_req_nomem(subreq, req)) {
1318 0 : return tevent_req_post(req, ev);
1319 : }
1320 0 : tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1321 : req);
1322 : }
1323 548595 : return req;
1324 : }
1325 :
1326 548595 : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1327 : {
1328 548595 : struct pipe_auth_data *a = state->cli->auth;
1329 0 : struct dcerpc_sec_verification_trailer *t;
1330 548595 : struct ndr_push *ndr = NULL;
1331 0 : enum ndr_err_code ndr_err;
1332 548595 : size_t align = 0;
1333 548595 : size_t pad = 0;
1334 :
1335 548595 : if (a == NULL) {
1336 0 : return NT_STATUS_OK;
1337 : }
1338 :
1339 548595 : if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1340 548229 : return NT_STATUS_OK;
1341 : }
1342 :
1343 366 : t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1344 366 : if (t == NULL) {
1345 0 : return NT_STATUS_NO_MEMORY;
1346 : }
1347 :
1348 366 : if (!a->verified_bitmask1) {
1349 310 : t->commands = talloc_realloc(t, t->commands,
1350 : struct dcerpc_sec_vt,
1351 : t->count.count + 1);
1352 310 : if (t->commands == NULL) {
1353 0 : return NT_STATUS_NO_MEMORY;
1354 : }
1355 310 : t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1356 : .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
1357 310 : .u.bitmask1 = (a->client_hdr_signing) ?
1358 310 : DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
1359 : 0,
1360 : };
1361 310 : state->verify_bitmask1 = true;
1362 : }
1363 :
1364 366 : if (!state->cli->verified_pcontext) {
1365 310 : t->commands = talloc_realloc(t, t->commands,
1366 : struct dcerpc_sec_vt,
1367 : t->count.count + 1);
1368 310 : if (t->commands == NULL) {
1369 0 : return NT_STATUS_NO_MEMORY;
1370 : }
1371 310 : t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1372 : .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
1373 : .u.pcontext.abstract_syntax =
1374 310 : state->cli->abstract_syntax,
1375 : .u.pcontext.transfer_syntax =
1376 310 : state->cli->transfer_syntax,
1377 : };
1378 310 : state->verify_pcontext = true;
1379 : }
1380 :
1381 366 : if (!a->hdr_signing) {
1382 0 : t->commands = talloc_realloc(t, t->commands,
1383 : struct dcerpc_sec_vt,
1384 : t->count.count + 1);
1385 0 : if (t->commands == NULL) {
1386 0 : return NT_STATUS_NO_MEMORY;
1387 : }
1388 0 : t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1389 : .command = DCERPC_SEC_VT_COMMAND_HEADER2,
1390 : .u.header2.ptype = DCERPC_PKT_REQUEST,
1391 : .u.header2.drep[0] = DCERPC_DREP_LE,
1392 0 : .u.header2.call_id = state->call_id,
1393 : .u.header2.context_id = 0,
1394 0 : .u.header2.opnum = state->op_num,
1395 : };
1396 : }
1397 :
1398 366 : if (t->count.count == 0) {
1399 56 : TALLOC_FREE(t);
1400 56 : return NT_STATUS_OK;
1401 : }
1402 :
1403 310 : t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
1404 :
1405 310 : if (DEBUGLEVEL >= 10) {
1406 0 : NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1407 : }
1408 :
1409 310 : ndr = ndr_push_init_ctx(state);
1410 310 : if (ndr == NULL) {
1411 0 : return NT_STATUS_NO_MEMORY;
1412 : }
1413 :
1414 310 : ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1415 : NDR_SCALARS | NDR_BUFFERS,
1416 : t);
1417 310 : TALLOC_FREE(t);
1418 310 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1419 0 : return ndr_map_error2ntstatus(ndr_err);
1420 : }
1421 310 : state->req_trailer = ndr_push_blob(ndr);
1422 :
1423 310 : align = state->req_data->length & 0x3;
1424 310 : if (align > 0) {
1425 0 : pad = 4 - align;
1426 : }
1427 310 : if (pad > 0) {
1428 0 : bool ok;
1429 0 : uint8_t *p;
1430 0 : const uint8_t zeros[4] = { 0, };
1431 :
1432 0 : ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1433 0 : if (!ok) {
1434 0 : return NT_STATUS_NO_MEMORY;
1435 : }
1436 :
1437 : /* move the padding to the start */
1438 0 : p = state->req_trailer.data;
1439 0 : memmove(p + pad, p, state->req_trailer.length - pad);
1440 0 : memset(p, 0, pad);
1441 : }
1442 :
1443 310 : return NT_STATUS_OK;
1444 : }
1445 :
1446 548595 : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1447 : bool *is_last_frag)
1448 : {
1449 0 : size_t auth_len;
1450 0 : size_t frag_len;
1451 548595 : uint8_t flags = 0;
1452 0 : size_t pad_len;
1453 0 : size_t data_left;
1454 0 : size_t data_thistime;
1455 0 : size_t trailer_left;
1456 548595 : size_t trailer_thistime = 0;
1457 0 : size_t total_left;
1458 0 : size_t total_thistime;
1459 0 : NTSTATUS status;
1460 0 : bool ok;
1461 0 : union dcerpc_payload u;
1462 :
1463 548595 : data_left = state->req_data->length - state->req_data_sent;
1464 548595 : trailer_left = state->req_trailer.length - state->req_trailer_sent;
1465 548595 : total_left = data_left + trailer_left;
1466 548595 : if ((total_left < data_left) || (total_left < trailer_left)) {
1467 : /*
1468 : * overflow
1469 : */
1470 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1471 : }
1472 :
1473 548595 : status = dcerpc_guess_sizes(state->cli->auth,
1474 : DCERPC_REQUEST_LENGTH, total_left,
1475 548595 : state->cli->max_xmit_frag,
1476 : &total_thistime,
1477 : &frag_len, &auth_len, &pad_len);
1478 548595 : if (!NT_STATUS_IS_OK(status)) {
1479 0 : return status;
1480 : }
1481 :
1482 548595 : if (state->req_data_sent == 0) {
1483 548595 : flags = DCERPC_PFC_FLAG_FIRST;
1484 : }
1485 :
1486 548595 : if (total_thistime == total_left) {
1487 548595 : flags |= DCERPC_PFC_FLAG_LAST;
1488 : }
1489 :
1490 548595 : data_thistime = MIN(total_thistime, data_left);
1491 548595 : if (data_thistime < total_thistime) {
1492 310 : trailer_thistime = total_thistime - data_thistime;
1493 : }
1494 :
1495 548595 : data_blob_free(&state->rpc_out);
1496 :
1497 548595 : u = (union dcerpc_payload) {
1498 : .request.alloc_hint = total_left,
1499 : .request.context_id = 0,
1500 548595 : .request.opnum = state->op_num,
1501 : };
1502 :
1503 548595 : if (state->object_uuid) {
1504 0 : flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1505 0 : u.request.object.object = *state->object_uuid;
1506 0 : frag_len += ndr_size_GUID(state->object_uuid, 0);
1507 : }
1508 :
1509 548595 : status = dcerpc_push_ncacn_packet(state,
1510 : DCERPC_PKT_REQUEST,
1511 : flags,
1512 : auth_len,
1513 : state->call_id,
1514 : &u,
1515 : &state->rpc_out);
1516 548595 : if (!NT_STATUS_IS_OK(status)) {
1517 0 : return status;
1518 : }
1519 :
1520 : /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1521 : * compute it right for requests because the auth trailer is missing
1522 : * at this stage */
1523 548595 : dcerpc_set_frag_length(&state->rpc_out, frag_len);
1524 :
1525 548595 : if (data_thistime > 0) {
1526 : /* Copy in the data. */
1527 548593 : ok = data_blob_append(NULL, &state->rpc_out,
1528 548593 : state->req_data->data + state->req_data_sent,
1529 : data_thistime);
1530 548593 : if (!ok) {
1531 0 : return NT_STATUS_NO_MEMORY;
1532 : }
1533 548593 : state->req_data_sent += data_thistime;
1534 : }
1535 :
1536 548595 : if (trailer_thistime > 0) {
1537 : /* Copy in the verification trailer. */
1538 310 : ok = data_blob_append(NULL, &state->rpc_out,
1539 310 : state->req_trailer.data + state->req_trailer_sent,
1540 : trailer_thistime);
1541 310 : if (!ok) {
1542 0 : return NT_STATUS_NO_MEMORY;
1543 : }
1544 310 : state->req_trailer_sent += trailer_thistime;
1545 : }
1546 :
1547 548595 : switch (state->cli->auth->auth_level) {
1548 548229 : case DCERPC_AUTH_LEVEL_NONE:
1549 : case DCERPC_AUTH_LEVEL_CONNECT:
1550 548229 : break;
1551 366 : case DCERPC_AUTH_LEVEL_PACKET:
1552 : case DCERPC_AUTH_LEVEL_INTEGRITY:
1553 : case DCERPC_AUTH_LEVEL_PRIVACY:
1554 366 : status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1555 : &state->rpc_out);
1556 366 : if (!NT_STATUS_IS_OK(status)) {
1557 0 : return status;
1558 : }
1559 366 : break;
1560 0 : default:
1561 0 : return NT_STATUS_INVALID_PARAMETER;
1562 : }
1563 :
1564 548595 : *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1565 :
1566 548595 : return status;
1567 : }
1568 :
1569 0 : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1570 : {
1571 0 : struct tevent_req *req = tevent_req_callback_data(
1572 : subreq, struct tevent_req);
1573 0 : struct rpc_api_pipe_req_state *state = tevent_req_data(
1574 : req, struct rpc_api_pipe_req_state);
1575 0 : NTSTATUS status;
1576 0 : bool is_last_frag;
1577 :
1578 0 : status = rpc_write_recv(subreq);
1579 0 : TALLOC_FREE(subreq);
1580 0 : if (tevent_req_nterror(req, status)) {
1581 0 : return;
1582 : }
1583 :
1584 0 : status = prepare_next_frag(state, &is_last_frag);
1585 0 : if (tevent_req_nterror(req, status)) {
1586 0 : return;
1587 : }
1588 :
1589 0 : if (is_last_frag) {
1590 0 : subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1591 : &state->rpc_out,
1592 : DCERPC_PKT_RESPONSE,
1593 : state->call_id);
1594 0 : if (tevent_req_nomem(subreq, req)) {
1595 0 : return;
1596 : }
1597 0 : tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1598 : } else {
1599 0 : subreq = rpc_write_send(state, state->ev,
1600 0 : state->cli->transport,
1601 0 : state->rpc_out.data,
1602 : state->rpc_out.length);
1603 0 : if (tevent_req_nomem(subreq, req)) {
1604 0 : return;
1605 : }
1606 0 : tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1607 : req);
1608 : }
1609 : }
1610 :
1611 548595 : static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1612 : {
1613 548595 : struct tevent_req *req = tevent_req_callback_data(
1614 : subreq, struct tevent_req);
1615 548595 : struct rpc_api_pipe_req_state *state = tevent_req_data(
1616 : req, struct rpc_api_pipe_req_state);
1617 0 : NTSTATUS status;
1618 :
1619 548595 : status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1620 548595 : TALLOC_FREE(subreq);
1621 548595 : if (tevent_req_nterror(req, status)) {
1622 222 : return;
1623 : }
1624 :
1625 548373 : if (state->cli->auth == NULL) {
1626 0 : tevent_req_done(req);
1627 0 : return;
1628 : }
1629 :
1630 548373 : if (state->verify_bitmask1) {
1631 310 : state->cli->auth->verified_bitmask1 = true;
1632 : }
1633 :
1634 548373 : if (state->verify_pcontext) {
1635 310 : state->cli->verified_pcontext = true;
1636 : }
1637 :
1638 548373 : tevent_req_done(req);
1639 : }
1640 :
1641 548595 : static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1642 : DATA_BLOB *reply_pdu)
1643 : {
1644 548595 : struct rpc_api_pipe_req_state *state = tevent_req_data(
1645 : req, struct rpc_api_pipe_req_state);
1646 0 : NTSTATUS status;
1647 :
1648 548595 : if (tevent_req_is_nterror(req, &status)) {
1649 : /*
1650 : * We always have to initialize to reply pdu, even if there is
1651 : * none. The rpccli_* caller routines expect this.
1652 : */
1653 222 : *reply_pdu = data_blob_null;
1654 222 : return status;
1655 : }
1656 :
1657 : /* return data to caller and assign it ownership of memory */
1658 548373 : reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1659 548373 : reply_pdu->length = state->reply_pdu.length;
1660 548373 : state->reply_pdu.length = 0;
1661 :
1662 548373 : return NT_STATUS_OK;
1663 : }
1664 :
1665 : /****************************************************************************
1666 : Check the rpc bind acknowledge response.
1667 : ****************************************************************************/
1668 :
1669 41838 : static bool check_bind_response(const struct dcerpc_bind_ack *r,
1670 : struct rpc_pipe_client *cli)
1671 : {
1672 41838 : const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
1673 0 : struct dcerpc_ack_ctx ctx;
1674 0 : bool equal;
1675 :
1676 41838 : if (r->secondary_address_size == 0) {
1677 159 : DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
1678 : }
1679 :
1680 41838 : if (r->num_results < 1 || !r->ctx_list) {
1681 0 : return false;
1682 : }
1683 :
1684 41838 : ctx = r->ctx_list[0];
1685 :
1686 : /* check the transfer syntax */
1687 41838 : equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
1688 41838 : if (!equal) {
1689 0 : DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1690 0 : return False;
1691 : }
1692 :
1693 41838 : if (ctx.result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1694 0 : DBG_NOTICE("bind denied result: %d reason: %x\n",
1695 : ctx.result, ctx.reason.value);
1696 0 : return false;
1697 : }
1698 :
1699 41838 : if (r->num_results >= 2) {
1700 41679 : const struct dcerpc_ack_ctx *neg = &r->ctx_list[1];
1701 :
1702 41679 : if (neg->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1703 41679 : cli->bind_time_features = neg->reason.negotiate;
1704 : } else {
1705 0 : DBG_DEBUG("bind_time_feature failed - "
1706 : "result: %d reason %x\n",
1707 : neg->result, neg->reason.value);
1708 : }
1709 : }
1710 :
1711 41838 : DEBUG(5,("check_bind_response: accepted!\n"));
1712 41838 : return True;
1713 : }
1714 :
1715 : /*******************************************************************
1716 : Creates a DCE/RPC bind authentication response.
1717 : This is the packet that is sent back to the server once we
1718 : have received a BIND-ACK, to finish the third leg of
1719 : the authentication handshake.
1720 : ********************************************************************/
1721 :
1722 74 : static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1723 : struct rpc_pipe_client *cli,
1724 : struct pipe_auth_data *auth,
1725 : uint32_t rpc_call_id,
1726 : DATA_BLOB *pauth_blob,
1727 : DATA_BLOB *rpc_out)
1728 : {
1729 0 : NTSTATUS status;
1730 74 : union dcerpc_payload u = { .auth3._pad = 0, };
1731 :
1732 74 : status = dcerpc_push_dcerpc_auth(mem_ctx,
1733 : auth->auth_type,
1734 : auth->auth_level,
1735 : 0, /* auth_pad_length */
1736 : auth->auth_context_id,
1737 : pauth_blob,
1738 : &u.auth3.auth_info);
1739 74 : if (!NT_STATUS_IS_OK(status)) {
1740 0 : return status;
1741 : }
1742 :
1743 74 : status = dcerpc_push_ncacn_packet(mem_ctx,
1744 : DCERPC_PKT_AUTH3,
1745 : DCERPC_PFC_FLAG_FIRST |
1746 : DCERPC_PFC_FLAG_LAST,
1747 74 : pauth_blob->length,
1748 : rpc_call_id,
1749 : &u,
1750 : rpc_out);
1751 74 : data_blob_free(&u.auth3.auth_info);
1752 74 : if (!NT_STATUS_IS_OK(status)) {
1753 0 : DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1754 0 : return status;
1755 : }
1756 :
1757 74 : return NT_STATUS_OK;
1758 : }
1759 :
1760 : /*******************************************************************
1761 : Creates a DCE/RPC bind alter context authentication request which
1762 : may contain a spnego auth blob
1763 : ********************************************************************/
1764 :
1765 159 : static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1766 : struct pipe_auth_data *auth,
1767 : uint32_t rpc_call_id,
1768 : const struct ndr_syntax_id *abstract,
1769 : const struct ndr_syntax_id *transfer,
1770 : const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1771 : DATA_BLOB *rpc_out)
1772 : {
1773 0 : DATA_BLOB auth_info;
1774 0 : NTSTATUS status;
1775 :
1776 159 : status = dcerpc_push_dcerpc_auth(mem_ctx,
1777 : auth->auth_type,
1778 : auth->auth_level,
1779 : 0, /* auth_pad_length */
1780 : auth->auth_context_id,
1781 : pauth_blob,
1782 : &auth_info);
1783 159 : if (!NT_STATUS_IS_OK(status)) {
1784 0 : return status;
1785 : }
1786 :
1787 159 : status = create_bind_or_alt_ctx_internal(mem_ctx,
1788 : DCERPC_PKT_ALTER,
1789 : rpc_call_id,
1790 : abstract,
1791 : transfer,
1792 : &auth_info,
1793 : false, /* client_hdr_signing */
1794 : rpc_out);
1795 159 : data_blob_free(&auth_info);
1796 159 : return status;
1797 : }
1798 :
1799 : /****************************************************************************
1800 : Do an rpc bind.
1801 : ****************************************************************************/
1802 :
1803 : struct rpc_pipe_bind_state {
1804 : struct tevent_context *ev;
1805 : struct rpc_pipe_client *cli;
1806 : DATA_BLOB rpc_out;
1807 : bool auth3;
1808 : uint32_t rpc_call_id;
1809 : };
1810 :
1811 : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1812 : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1813 : struct rpc_pipe_bind_state *state,
1814 : DATA_BLOB *credentials);
1815 : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1816 : struct rpc_pipe_bind_state *state,
1817 : DATA_BLOB *credentials);
1818 :
1819 41679 : struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1820 : struct tevent_context *ev,
1821 : struct rpc_pipe_client *cli,
1822 : struct pipe_auth_data *auth)
1823 : {
1824 0 : struct tevent_req *req, *subreq;
1825 0 : struct rpc_pipe_bind_state *state;
1826 0 : NTSTATUS status;
1827 :
1828 41679 : req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1829 41679 : if (req == NULL) {
1830 0 : return NULL;
1831 : }
1832 :
1833 41679 : DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1834 : rpccli_pipe_txt(talloc_tos(), cli),
1835 : (unsigned int)auth->auth_type,
1836 : (unsigned int)auth->auth_level ));
1837 :
1838 41679 : state->ev = ev;
1839 41679 : state->cli = cli;
1840 41679 : state->rpc_call_id = get_rpc_call_id();
1841 :
1842 41679 : cli->auth = talloc_move(cli, &auth);
1843 :
1844 : /* Marshall the outgoing data. */
1845 41679 : status = create_rpc_bind_req(state, cli,
1846 : cli->auth,
1847 41679 : state->rpc_call_id,
1848 41679 : &cli->abstract_syntax,
1849 41679 : &cli->transfer_syntax,
1850 41679 : &state->rpc_out);
1851 :
1852 41679 : if (!NT_STATUS_IS_OK(status) &&
1853 0 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1854 0 : tevent_req_nterror(req, status);
1855 0 : return tevent_req_post(req, ev);
1856 : }
1857 :
1858 41679 : subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1859 41679 : DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1860 41679 : if (tevent_req_nomem(subreq, req)) {
1861 0 : return tevent_req_post(req, ev);
1862 : }
1863 41679 : tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1864 41679 : return req;
1865 : }
1866 :
1867 41912 : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1868 : {
1869 41912 : struct tevent_req *req = tevent_req_callback_data(
1870 : subreq, struct tevent_req);
1871 41912 : struct rpc_pipe_bind_state *state = tevent_req_data(
1872 : req, struct rpc_pipe_bind_state);
1873 41912 : struct pipe_auth_data *pauth = state->cli->auth;
1874 0 : struct gensec_security *gensec_security;
1875 41912 : struct ncacn_packet *pkt = NULL;
1876 0 : struct dcerpc_auth auth;
1877 41912 : DATA_BLOB auth_token = { .data = NULL };
1878 0 : NTSTATUS status;
1879 :
1880 41912 : status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1881 41912 : TALLOC_FREE(subreq);
1882 41912 : if (tevent_req_nterror(req, status)) {
1883 0 : DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1884 : rpccli_pipe_txt(talloc_tos(), state->cli),
1885 : nt_errstr(status)));
1886 0 : return;
1887 : }
1888 :
1889 41912 : if (state->auth3) {
1890 74 : tevent_req_done(req);
1891 74 : return;
1892 : }
1893 :
1894 41838 : if (!check_bind_response(&pkt->u.bind_ack, state->cli)) {
1895 0 : DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1896 0 : tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1897 0 : return;
1898 : }
1899 :
1900 41838 : if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1901 41679 : if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1902 310 : if (pauth->client_hdr_signing) {
1903 310 : pauth->hdr_signing = true;
1904 : }
1905 : }
1906 : }
1907 :
1908 41838 : state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1909 :
1910 41838 : if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1911 : /* Bind complete. */
1912 41203 : tevent_req_done(req);
1913 41203 : return;
1914 : }
1915 :
1916 635 : if (pkt->auth_length == 0) {
1917 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1918 0 : return;
1919 : }
1920 :
1921 : /* get auth credentials */
1922 635 : status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1923 635 : &pkt->u.bind_ack.auth_info,
1924 : &auth, NULL, true);
1925 635 : if (tevent_req_nterror(req, status)) {
1926 0 : DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1927 : nt_errstr(status)));
1928 0 : return;
1929 : }
1930 :
1931 635 : if (auth.auth_type != pauth->auth_type) {
1932 0 : DBG_ERR("Auth type %u mismatch expected %u.\n",
1933 : auth.auth_type, pauth->auth_type);
1934 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1935 0 : return;
1936 : }
1937 :
1938 635 : if (auth.auth_level != pauth->auth_level) {
1939 0 : DBG_ERR("Auth level %u mismatch expected %u.\n",
1940 : auth.auth_level, pauth->auth_level);
1941 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1942 0 : return;
1943 : }
1944 :
1945 635 : if (auth.auth_context_id != pauth->auth_context_id) {
1946 0 : DBG_ERR("Auth context id %"PRIu32" mismatch "
1947 : "expected %"PRIu32".\n",
1948 : auth.auth_context_id,
1949 : pauth->auth_context_id);
1950 0 : tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1951 0 : return;
1952 : }
1953 :
1954 : /*
1955 : * For authenticated binds we may need to do 3 or 4 leg binds.
1956 : */
1957 :
1958 635 : if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1959 : /* Bind complete. */
1960 0 : tevent_req_done(req);
1961 0 : return;
1962 : }
1963 :
1964 635 : gensec_security = pauth->auth_ctx;
1965 :
1966 635 : status = gensec_update(gensec_security, state,
1967 : auth.credentials, &auth_token);
1968 635 : if (NT_STATUS_EQUAL(status,
1969 : NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1970 159 : status = rpc_bind_next_send(req, state,
1971 : &auth_token);
1972 476 : } else if (NT_STATUS_IS_OK(status)) {
1973 476 : if (pauth->hdr_signing) {
1974 310 : gensec_want_feature(gensec_security,
1975 : GENSEC_FEATURE_SIGN_PKT_HEADER);
1976 : }
1977 :
1978 476 : if (auth_token.length == 0) {
1979 : /* Bind complete. */
1980 402 : tevent_req_done(req);
1981 402 : return;
1982 : }
1983 74 : status = rpc_bind_finish_send(req, state,
1984 : &auth_token);
1985 : }
1986 :
1987 233 : if (!NT_STATUS_IS_OK(status)) {
1988 0 : tevent_req_nterror(req, status);
1989 : }
1990 233 : return;
1991 : }
1992 :
1993 159 : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1994 : struct rpc_pipe_bind_state *state,
1995 : DATA_BLOB *auth_token)
1996 : {
1997 159 : struct pipe_auth_data *auth = state->cli->auth;
1998 0 : struct tevent_req *subreq;
1999 0 : NTSTATUS status;
2000 :
2001 : /* Now prepare the alter context pdu. */
2002 159 : data_blob_free(&state->rpc_out);
2003 :
2004 159 : status = create_rpc_alter_context(state, auth,
2005 : state->rpc_call_id,
2006 159 : &state->cli->abstract_syntax,
2007 159 : &state->cli->transfer_syntax,
2008 : auth_token,
2009 : &state->rpc_out);
2010 159 : if (!NT_STATUS_IS_OK(status)) {
2011 0 : return status;
2012 : }
2013 :
2014 159 : subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2015 : &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2016 : state->rpc_call_id);
2017 159 : if (subreq == NULL) {
2018 0 : return NT_STATUS_NO_MEMORY;
2019 : }
2020 159 : tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2021 159 : return NT_STATUS_OK;
2022 : }
2023 :
2024 74 : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2025 : struct rpc_pipe_bind_state *state,
2026 : DATA_BLOB *auth_token)
2027 : {
2028 74 : struct pipe_auth_data *auth = state->cli->auth;
2029 0 : struct tevent_req *subreq;
2030 0 : NTSTATUS status;
2031 :
2032 74 : state->auth3 = true;
2033 :
2034 : /* Now prepare the auth3 context pdu. */
2035 74 : data_blob_free(&state->rpc_out);
2036 :
2037 74 : status = create_rpc_bind_auth3(state, state->cli, auth,
2038 : state->rpc_call_id,
2039 : auth_token,
2040 : &state->rpc_out);
2041 74 : if (!NT_STATUS_IS_OK(status)) {
2042 0 : return status;
2043 : }
2044 :
2045 74 : subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2046 : &state->rpc_out, DCERPC_PKT_AUTH3,
2047 : state->rpc_call_id);
2048 74 : if (subreq == NULL) {
2049 0 : return NT_STATUS_NO_MEMORY;
2050 : }
2051 74 : tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2052 74 : return NT_STATUS_OK;
2053 : }
2054 :
2055 41679 : NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2056 : {
2057 41679 : return tevent_req_simple_recv_ntstatus(req);
2058 : }
2059 :
2060 41679 : NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2061 : struct pipe_auth_data *auth)
2062 : {
2063 41679 : TALLOC_CTX *frame = talloc_stackframe();
2064 0 : struct tevent_context *ev;
2065 0 : struct tevent_req *req;
2066 41679 : NTSTATUS status = NT_STATUS_OK;
2067 :
2068 41679 : ev = samba_tevent_context_init(frame);
2069 41679 : if (ev == NULL) {
2070 0 : status = NT_STATUS_NO_MEMORY;
2071 0 : goto fail;
2072 : }
2073 :
2074 41679 : req = rpc_pipe_bind_send(frame, ev, cli, auth);
2075 41679 : if (req == NULL) {
2076 0 : status = NT_STATUS_NO_MEMORY;
2077 0 : goto fail;
2078 : }
2079 :
2080 41679 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2081 0 : goto fail;
2082 : }
2083 :
2084 41679 : status = rpc_pipe_bind_recv(req);
2085 41679 : fail:
2086 41679 : TALLOC_FREE(frame);
2087 41679 : return status;
2088 : }
2089 :
2090 : #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2091 :
2092 700 : unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2093 : unsigned int timeout)
2094 : {
2095 700 : if (rpc_cli == NULL) {
2096 0 : return RPCCLI_DEFAULT_TIMEOUT;
2097 : }
2098 :
2099 700 : if (rpc_cli->binding_handle == NULL) {
2100 0 : return RPCCLI_DEFAULT_TIMEOUT;
2101 : }
2102 :
2103 700 : return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2104 : timeout);
2105 : }
2106 :
2107 169 : bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2108 : {
2109 169 : if (rpc_cli == NULL) {
2110 84 : return false;
2111 : }
2112 :
2113 85 : if (rpc_cli->binding_handle == NULL) {
2114 0 : return false;
2115 : }
2116 :
2117 85 : return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2118 : }
2119 :
2120 : struct rpccli_bh_state {
2121 : struct rpc_pipe_client *rpc_cli;
2122 : };
2123 :
2124 548680 : static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2125 : {
2126 548680 : struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2127 : struct rpccli_bh_state);
2128 548680 : struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2129 :
2130 548680 : if (transport == NULL) {
2131 0 : return false;
2132 : }
2133 :
2134 548680 : if (transport->is_connected == NULL) {
2135 0 : return false;
2136 : }
2137 :
2138 548680 : return transport->is_connected(transport->priv);
2139 : }
2140 :
2141 716 : static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2142 : uint32_t timeout)
2143 : {
2144 716 : struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2145 : struct rpccli_bh_state);
2146 716 : struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2147 0 : unsigned int old;
2148 :
2149 716 : if (transport == NULL) {
2150 0 : return RPCCLI_DEFAULT_TIMEOUT;
2151 : }
2152 :
2153 716 : if (transport->set_timeout == NULL) {
2154 0 : return RPCCLI_DEFAULT_TIMEOUT;
2155 : }
2156 :
2157 716 : old = transport->set_timeout(transport->priv, timeout);
2158 716 : if (old == 0) {
2159 0 : return RPCCLI_DEFAULT_TIMEOUT;
2160 : }
2161 :
2162 716 : return old;
2163 : }
2164 :
2165 171 : static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2166 : enum dcerpc_AuthType *auth_type,
2167 : enum dcerpc_AuthLevel *auth_level)
2168 : {
2169 171 : struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2170 : struct rpccli_bh_state);
2171 :
2172 171 : if (hs->rpc_cli == NULL) {
2173 0 : return;
2174 : }
2175 :
2176 171 : if (hs->rpc_cli->auth == NULL) {
2177 0 : return;
2178 : }
2179 :
2180 171 : *auth_type = hs->rpc_cli->auth->auth_type;
2181 171 : *auth_level = hs->rpc_cli->auth->auth_level;
2182 : }
2183 :
2184 : struct rpccli_bh_raw_call_state {
2185 : DATA_BLOB in_data;
2186 : DATA_BLOB out_data;
2187 : uint32_t out_flags;
2188 : };
2189 :
2190 : static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2191 :
2192 548595 : static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2193 : struct tevent_context *ev,
2194 : struct dcerpc_binding_handle *h,
2195 : const struct GUID *object,
2196 : uint32_t opnum,
2197 : uint32_t in_flags,
2198 : const uint8_t *in_data,
2199 : size_t in_length)
2200 : {
2201 548595 : struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2202 : struct rpccli_bh_state);
2203 0 : struct tevent_req *req;
2204 0 : struct rpccli_bh_raw_call_state *state;
2205 0 : bool ok;
2206 0 : struct tevent_req *subreq;
2207 :
2208 548595 : req = tevent_req_create(mem_ctx, &state,
2209 : struct rpccli_bh_raw_call_state);
2210 548595 : if (req == NULL) {
2211 0 : return NULL;
2212 : }
2213 548595 : state->in_data.data = discard_const_p(uint8_t, in_data);
2214 548595 : state->in_data.length = in_length;
2215 :
2216 548595 : ok = rpccli_bh_is_connected(h);
2217 548595 : if (!ok) {
2218 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2219 0 : return tevent_req_post(req, ev);
2220 : }
2221 :
2222 548595 : subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2223 548595 : opnum, object, &state->in_data);
2224 548595 : if (tevent_req_nomem(subreq, req)) {
2225 0 : return tevent_req_post(req, ev);
2226 : }
2227 548595 : tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2228 :
2229 548595 : return req;
2230 : }
2231 :
2232 548595 : static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2233 : {
2234 0 : struct tevent_req *req =
2235 548595 : tevent_req_callback_data(subreq,
2236 : struct tevent_req);
2237 0 : struct rpccli_bh_raw_call_state *state =
2238 548595 : tevent_req_data(req,
2239 : struct rpccli_bh_raw_call_state);
2240 0 : NTSTATUS status;
2241 :
2242 548595 : state->out_flags = 0;
2243 :
2244 : /* TODO: support bigendian responses */
2245 :
2246 548595 : status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2247 548595 : TALLOC_FREE(subreq);
2248 548595 : if (tevent_req_nterror(req, status)) {
2249 222 : return;
2250 : }
2251 :
2252 548373 : tevent_req_done(req);
2253 : }
2254 :
2255 548595 : static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2256 : TALLOC_CTX *mem_ctx,
2257 : uint8_t **out_data,
2258 : size_t *out_length,
2259 : uint32_t *out_flags)
2260 : {
2261 0 : struct rpccli_bh_raw_call_state *state =
2262 548595 : tevent_req_data(req,
2263 : struct rpccli_bh_raw_call_state);
2264 0 : NTSTATUS status;
2265 :
2266 548595 : if (tevent_req_is_nterror(req, &status)) {
2267 222 : tevent_req_received(req);
2268 222 : return status;
2269 : }
2270 :
2271 548373 : *out_data = talloc_move(mem_ctx, &state->out_data.data);
2272 548373 : *out_length = state->out_data.length;
2273 548373 : *out_flags = state->out_flags;
2274 548373 : tevent_req_received(req);
2275 548373 : return NT_STATUS_OK;
2276 : }
2277 :
2278 : struct rpccli_bh_disconnect_state {
2279 : uint8_t _dummy;
2280 : };
2281 :
2282 0 : static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2283 : struct tevent_context *ev,
2284 : struct dcerpc_binding_handle *h)
2285 : {
2286 0 : struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2287 : struct rpccli_bh_state);
2288 0 : struct tevent_req *req;
2289 0 : struct rpccli_bh_disconnect_state *state;
2290 0 : bool ok;
2291 :
2292 0 : req = tevent_req_create(mem_ctx, &state,
2293 : struct rpccli_bh_disconnect_state);
2294 0 : if (req == NULL) {
2295 0 : return NULL;
2296 : }
2297 :
2298 0 : ok = rpccli_bh_is_connected(h);
2299 0 : if (!ok) {
2300 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2301 0 : return tevent_req_post(req, ev);
2302 : }
2303 :
2304 : /*
2305 : * TODO: do a real async disconnect ...
2306 : *
2307 : * For now we do it sync...
2308 : */
2309 0 : TALLOC_FREE(hs->rpc_cli->transport);
2310 0 : hs->rpc_cli = NULL;
2311 :
2312 0 : tevent_req_done(req);
2313 0 : return tevent_req_post(req, ev);
2314 : }
2315 :
2316 0 : static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2317 : {
2318 0 : return tevent_req_simple_recv_ntstatus(req);
2319 : }
2320 :
2321 548595 : static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2322 : {
2323 548595 : return true;
2324 : }
2325 :
2326 1096968 : static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2327 : ndr_flags_type ndr_flags,
2328 : const void *_struct_ptr,
2329 : const struct ndr_interface_call *call)
2330 : {
2331 1096968 : void *struct_ptr = discard_const(_struct_ptr);
2332 :
2333 1096968 : if (DEBUGLEVEL < 10) {
2334 1096780 : return;
2335 : }
2336 :
2337 188 : if (ndr_flags & NDR_IN) {
2338 94 : ndr_print_function_debug(call->ndr_print,
2339 94 : call->name,
2340 : ndr_flags,
2341 : struct_ptr);
2342 : }
2343 188 : if (ndr_flags & NDR_OUT) {
2344 94 : ndr_print_function_debug(call->ndr_print,
2345 94 : call->name,
2346 : ndr_flags,
2347 : struct_ptr);
2348 : }
2349 : }
2350 :
2351 : static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2352 : .name = "rpccli",
2353 : .is_connected = rpccli_bh_is_connected,
2354 : .set_timeout = rpccli_bh_set_timeout,
2355 : .auth_info = rpccli_bh_auth_info,
2356 : .raw_call_send = rpccli_bh_raw_call_send,
2357 : .raw_call_recv = rpccli_bh_raw_call_recv,
2358 : .disconnect_send = rpccli_bh_disconnect_send,
2359 : .disconnect_recv = rpccli_bh_disconnect_recv,
2360 :
2361 : .ref_alloc = rpccli_bh_ref_alloc,
2362 : .do_ndr_print = rpccli_bh_do_ndr_print,
2363 : };
2364 :
2365 : /* initialise a rpc_pipe_client binding handle */
2366 41679 : struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2367 : const struct GUID *object,
2368 : const struct ndr_interface_table *table)
2369 : {
2370 0 : struct dcerpc_binding_handle *h;
2371 0 : struct rpccli_bh_state *hs;
2372 :
2373 41679 : h = dcerpc_binding_handle_create(c,
2374 : &rpccli_bh_ops,
2375 : object,
2376 : table,
2377 : &hs,
2378 : struct rpccli_bh_state,
2379 : __location__);
2380 41679 : if (h == NULL) {
2381 0 : return NULL;
2382 : }
2383 41679 : hs->rpc_cli = c;
2384 :
2385 41679 : return h;
2386 : }
2387 :
2388 41203 : NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2389 : struct pipe_auth_data **presult)
2390 : {
2391 0 : struct pipe_auth_data *result;
2392 0 : struct auth_generic_state *auth_generic_ctx;
2393 0 : NTSTATUS status;
2394 :
2395 41203 : result = talloc_zero(mem_ctx, struct pipe_auth_data);
2396 41203 : if (result == NULL) {
2397 0 : return NT_STATUS_NO_MEMORY;
2398 : }
2399 :
2400 41203 : result->auth_type = DCERPC_AUTH_TYPE_NONE;
2401 41203 : result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2402 41203 : result->auth_context_id = 0;
2403 :
2404 41203 : status = auth_generic_client_prepare(result,
2405 : &auth_generic_ctx);
2406 41203 : if (!NT_STATUS_IS_OK(status)) {
2407 0 : DEBUG(1, ("Failed to create auth_generic context: %s\n",
2408 : nt_errstr(status)));
2409 : }
2410 :
2411 41203 : status = auth_generic_set_username(auth_generic_ctx, "");
2412 41203 : if (!NT_STATUS_IS_OK(status)) {
2413 0 : DEBUG(1, ("Failed to set username: %s\n",
2414 : nt_errstr(status)));
2415 : }
2416 :
2417 41203 : status = auth_generic_set_domain(auth_generic_ctx, "");
2418 41203 : if (!NT_STATUS_IS_OK(status)) {
2419 0 : DEBUG(1, ("Failed to set domain: %s\n",
2420 : nt_errstr(status)));
2421 0 : return status;
2422 : }
2423 :
2424 41203 : status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2425 41203 : auth_generic_ctx->credentials);
2426 41203 : if (!NT_STATUS_IS_OK(status)) {
2427 0 : DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2428 : nt_errstr(status)));
2429 0 : return status;
2430 : }
2431 41203 : talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2432 41203 : auth_generic_ctx->credentials = NULL;
2433 :
2434 41203 : result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2435 41203 : talloc_free(auth_generic_ctx);
2436 41203 : *presult = result;
2437 41203 : return NT_STATUS_OK;
2438 : }
2439 :
2440 136 : static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2441 : enum dcerpc_AuthType auth_type,
2442 : enum dcerpc_AuthLevel auth_level,
2443 : const char *server,
2444 : const char *target_service,
2445 : const char *domain,
2446 : const char *username,
2447 : const char *password,
2448 : enum credentials_use_kerberos use_kerberos,
2449 : struct netlogon_creds_CredentialState *creds,
2450 : struct pipe_auth_data **presult)
2451 : {
2452 0 : struct auth_generic_state *auth_generic_ctx;
2453 0 : struct pipe_auth_data *result;
2454 0 : NTSTATUS status;
2455 :
2456 136 : result = talloc_zero(mem_ctx, struct pipe_auth_data);
2457 136 : if (result == NULL) {
2458 0 : return NT_STATUS_NO_MEMORY;
2459 : }
2460 :
2461 136 : result->auth_type = auth_type;
2462 136 : result->auth_level = auth_level;
2463 136 : result->auth_context_id = 1;
2464 :
2465 136 : status = auth_generic_client_prepare(result,
2466 : &auth_generic_ctx);
2467 136 : if (!NT_STATUS_IS_OK(status)) {
2468 0 : goto fail;
2469 : }
2470 :
2471 136 : status = auth_generic_set_username(auth_generic_ctx, username);
2472 136 : if (!NT_STATUS_IS_OK(status)) {
2473 0 : goto fail;
2474 : }
2475 :
2476 136 : status = auth_generic_set_domain(auth_generic_ctx, domain);
2477 136 : if (!NT_STATUS_IS_OK(status)) {
2478 0 : goto fail;
2479 : }
2480 :
2481 136 : status = auth_generic_set_password(auth_generic_ctx, password);
2482 136 : if (!NT_STATUS_IS_OK(status)) {
2483 0 : goto fail;
2484 : }
2485 :
2486 136 : status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2487 136 : if (!NT_STATUS_IS_OK(status)) {
2488 0 : goto fail;
2489 : }
2490 :
2491 136 : status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2492 136 : if (!NT_STATUS_IS_OK(status)) {
2493 0 : goto fail;
2494 : }
2495 :
2496 136 : cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
2497 : use_kerberos,
2498 : CRED_SPECIFIED);
2499 136 : cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2500 :
2501 136 : status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2502 136 : if (!NT_STATUS_IS_OK(status)) {
2503 0 : goto fail;
2504 : }
2505 :
2506 136 : result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2507 136 : talloc_free(auth_generic_ctx);
2508 136 : *presult = result;
2509 136 : return NT_STATUS_OK;
2510 :
2511 0 : fail:
2512 0 : TALLOC_FREE(result);
2513 0 : return status;
2514 : }
2515 :
2516 : /* This routine steals the creds pointer that is passed in */
2517 340 : static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2518 : enum dcerpc_AuthType auth_type,
2519 : enum dcerpc_AuthLevel auth_level,
2520 : const char *server,
2521 : const char *target_service,
2522 : struct cli_credentials *creds,
2523 : struct pipe_auth_data **presult)
2524 : {
2525 0 : struct auth_generic_state *auth_generic_ctx;
2526 0 : struct pipe_auth_data *result;
2527 0 : NTSTATUS status;
2528 :
2529 340 : result = talloc_zero(mem_ctx, struct pipe_auth_data);
2530 340 : if (result == NULL) {
2531 0 : return NT_STATUS_NO_MEMORY;
2532 : }
2533 :
2534 340 : result->auth_type = auth_type;
2535 340 : result->auth_level = auth_level;
2536 340 : result->auth_context_id = 1;
2537 :
2538 340 : status = auth_generic_client_prepare(result,
2539 : &auth_generic_ctx);
2540 340 : if (!NT_STATUS_IS_OK(status)) {
2541 0 : goto fail;
2542 : }
2543 :
2544 340 : status = auth_generic_set_creds(auth_generic_ctx, creds);
2545 340 : if (!NT_STATUS_IS_OK(status)) {
2546 0 : goto fail;
2547 : }
2548 :
2549 340 : status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2550 340 : if (!NT_STATUS_IS_OK(status)) {
2551 0 : goto fail;
2552 : }
2553 :
2554 340 : status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2555 340 : if (!NT_STATUS_IS_OK(status)) {
2556 0 : goto fail;
2557 : }
2558 :
2559 340 : status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2560 340 : if (!NT_STATUS_IS_OK(status)) {
2561 0 : goto fail;
2562 : }
2563 :
2564 340 : result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2565 340 : talloc_free(auth_generic_ctx);
2566 340 : *presult = result;
2567 340 : return NT_STATUS_OK;
2568 :
2569 0 : fail:
2570 0 : TALLOC_FREE(result);
2571 0 : return status;
2572 : }
2573 :
2574 136 : NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2575 : struct pipe_auth_data **presult)
2576 : {
2577 136 : return rpccli_generic_bind_data(mem_ctx,
2578 : DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2579 : DCERPC_AUTH_LEVEL_CONNECT,
2580 : NULL, /* server */
2581 : "host", /* target_service */
2582 : NAME_NT_AUTHORITY, /* domain */
2583 : "SYSTEM",
2584 : NULL, /* password */
2585 : CRED_USE_KERBEROS_DISABLED,
2586 : NULL, /* netlogon_creds_CredentialState */
2587 : presult);
2588 : }
2589 :
2590 : /**
2591 : * Create an rpc pipe client struct, connecting to a tcp port.
2592 : */
2593 100 : static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2594 : const struct sockaddr_storage *ss_addr,
2595 : uint16_t port,
2596 : const struct ndr_interface_table *table,
2597 : struct rpc_pipe_client **presult)
2598 : {
2599 0 : struct rpc_pipe_client *result;
2600 0 : struct sockaddr_storage addr;
2601 0 : NTSTATUS status;
2602 0 : int fd;
2603 :
2604 100 : result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2605 100 : if (result == NULL) {
2606 0 : return NT_STATUS_NO_MEMORY;
2607 : }
2608 :
2609 100 : result->abstract_syntax = table->syntax_id;
2610 100 : result->transfer_syntax = ndr_transfer_syntax_ndr;
2611 :
2612 100 : result->desthost = talloc_strdup(result, host);
2613 100 : if (result->desthost == NULL) {
2614 0 : status = NT_STATUS_NO_MEMORY;
2615 0 : goto fail;
2616 : }
2617 :
2618 100 : result->srv_name_slash = talloc_asprintf_strupper_m(
2619 : result, "\\\\%s", result->desthost);
2620 100 : if (result->srv_name_slash == NULL) {
2621 0 : status = NT_STATUS_NO_MEMORY;
2622 0 : goto fail;
2623 : }
2624 :
2625 100 : result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2626 :
2627 100 : if (ss_addr == NULL) {
2628 0 : if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2629 0 : status = NT_STATUS_NOT_FOUND;
2630 0 : goto fail;
2631 : }
2632 : } else {
2633 100 : addr = *ss_addr;
2634 : }
2635 :
2636 100 : status = open_socket_out(&addr, port, 60*1000, &fd);
2637 100 : if (!NT_STATUS_IS_OK(status)) {
2638 0 : goto fail;
2639 : }
2640 100 : set_socket_options(fd, lp_socket_options());
2641 :
2642 100 : status = rpc_transport_sock_init(result, fd, &result->transport);
2643 100 : if (!NT_STATUS_IS_OK(status)) {
2644 0 : close(fd);
2645 0 : goto fail;
2646 : }
2647 :
2648 100 : result->transport->transport = NCACN_IP_TCP;
2649 :
2650 100 : result->binding_handle = rpccli_bh_create(result, NULL, table);
2651 100 : if (result->binding_handle == NULL) {
2652 0 : TALLOC_FREE(result);
2653 0 : return NT_STATUS_NO_MEMORY;
2654 : }
2655 :
2656 100 : *presult = result;
2657 100 : return NT_STATUS_OK;
2658 :
2659 0 : fail:
2660 0 : TALLOC_FREE(result);
2661 0 : return status;
2662 : }
2663 :
2664 2 : static NTSTATUS rpccli_epm_map_binding(
2665 : struct dcerpc_binding_handle *epm_connection,
2666 : struct dcerpc_binding *binding,
2667 : TALLOC_CTX *mem_ctx,
2668 : char **pendpoint)
2669 : {
2670 2 : TALLOC_CTX *frame = talloc_stackframe();
2671 0 : enum dcerpc_transport_t transport =
2672 2 : dcerpc_binding_get_transport(binding);
2673 0 : enum dcerpc_transport_t res_transport;
2674 2 : struct dcerpc_binding *res_binding = NULL;
2675 2 : struct epm_twr_t *map_tower = NULL;
2676 2 : struct epm_twr_p_t res_towers = { .twr = NULL };
2677 2 : struct policy_handle *entry_handle = NULL;
2678 2 : uint32_t num_towers = 0;
2679 2 : const uint32_t max_towers = 1;
2680 2 : const char *endpoint = NULL;
2681 2 : char *tmp = NULL;
2682 0 : uint32_t result;
2683 0 : NTSTATUS status;
2684 :
2685 2 : map_tower = talloc_zero(frame, struct epm_twr_t);
2686 2 : if (map_tower == NULL) {
2687 0 : goto nomem;
2688 : }
2689 :
2690 2 : status = dcerpc_binding_build_tower(
2691 : frame, binding, &(map_tower->tower));
2692 2 : if (!NT_STATUS_IS_OK(status)) {
2693 0 : DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
2694 : nt_errstr(status));
2695 0 : goto done;
2696 : }
2697 :
2698 2 : res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
2699 2 : if (res_towers.twr == NULL) {
2700 0 : goto nomem;
2701 : }
2702 :
2703 2 : entry_handle = talloc_zero(frame, struct policy_handle);
2704 2 : if (entry_handle == NULL) {
2705 0 : goto nomem;
2706 : }
2707 :
2708 2 : status = dcerpc_epm_Map(
2709 : epm_connection,
2710 : frame,
2711 : NULL,
2712 : map_tower,
2713 : entry_handle,
2714 : max_towers,
2715 : &num_towers,
2716 : &res_towers,
2717 : &result);
2718 :
2719 2 : if (!NT_STATUS_IS_OK(status)) {
2720 0 : DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
2721 0 : goto done;
2722 : }
2723 :
2724 2 : if (result != EPMAPPER_STATUS_OK) {
2725 0 : DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
2726 0 : status = NT_STATUS_NOT_FOUND;
2727 0 : goto done;
2728 : }
2729 :
2730 2 : if (num_towers != 1) {
2731 0 : DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
2732 : num_towers);
2733 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2734 0 : goto done;
2735 : }
2736 :
2737 2 : status = dcerpc_binding_from_tower(
2738 2 : frame, &(res_towers.twr->tower), &res_binding);
2739 2 : if (!NT_STATUS_IS_OK(status)) {
2740 0 : DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
2741 : nt_errstr(status));
2742 0 : goto done;
2743 : }
2744 :
2745 2 : res_transport = dcerpc_binding_get_transport(res_binding);
2746 2 : if (res_transport != transport) {
2747 0 : DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
2748 : "expected %d\n",
2749 : (int)res_transport,
2750 : (int)transport);
2751 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2752 0 : goto done;
2753 : }
2754 :
2755 2 : endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2756 2 : if (endpoint == NULL) {
2757 0 : DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
2758 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2759 0 : goto done;
2760 : }
2761 :
2762 2 : tmp = talloc_strdup(mem_ctx, endpoint);
2763 2 : if (tmp == NULL) {
2764 0 : goto nomem;
2765 : }
2766 2 : *pendpoint = tmp;
2767 :
2768 2 : status = NT_STATUS_OK;
2769 2 : goto done;
2770 :
2771 0 : nomem:
2772 0 : status = NT_STATUS_NO_MEMORY;
2773 2 : done:
2774 2 : TALLOC_FREE(frame);
2775 2 : return status;
2776 : }
2777 :
2778 2 : static NTSTATUS rpccli_epm_map_interface(
2779 : struct dcerpc_binding_handle *epm_connection,
2780 : enum dcerpc_transport_t transport,
2781 : const struct ndr_syntax_id *iface,
2782 : TALLOC_CTX *mem_ctx,
2783 : char **pendpoint)
2784 : {
2785 2 : struct dcerpc_binding *binding = NULL;
2786 2 : char *endpoint = NULL;
2787 0 : NTSTATUS status;
2788 :
2789 2 : status = dcerpc_parse_binding(mem_ctx, "", &binding);
2790 2 : if (!NT_STATUS_IS_OK(status)) {
2791 0 : DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
2792 : nt_errstr(status));
2793 0 : goto done;
2794 : }
2795 :
2796 2 : status = dcerpc_binding_set_transport(binding, transport);
2797 2 : if (!NT_STATUS_IS_OK(status)) {
2798 0 : DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
2799 : nt_errstr(status));
2800 0 : goto done;
2801 : }
2802 :
2803 2 : status = dcerpc_binding_set_abstract_syntax(binding, iface);
2804 2 : if (!NT_STATUS_IS_OK(status)) {
2805 0 : DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
2806 : nt_errstr(status));
2807 0 : goto done;
2808 : }
2809 :
2810 2 : status = rpccli_epm_map_binding(
2811 : epm_connection, binding, mem_ctx, &endpoint);
2812 2 : if (!NT_STATUS_IS_OK(status)) {
2813 0 : DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
2814 : nt_errstr(status));
2815 0 : goto done;
2816 : }
2817 2 : *pendpoint = endpoint;
2818 :
2819 2 : done:
2820 2 : TALLOC_FREE(binding);
2821 2 : return status;
2822 : }
2823 :
2824 : /**
2825 : * Determine the tcp port on which a dcerpc interface is listening
2826 : * for the ncacn_ip_tcp transport via the endpoint mapper of the
2827 : * target host.
2828 : */
2829 98 : static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2830 : const struct sockaddr_storage *addr,
2831 : const struct ndr_interface_table *table,
2832 : uint16_t *pport)
2833 : {
2834 0 : NTSTATUS status;
2835 98 : struct rpc_pipe_client *epm_pipe = NULL;
2836 98 : struct pipe_auth_data *auth = NULL;
2837 98 : char *endpoint = NULL;
2838 98 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2839 :
2840 98 : if (pport == NULL) {
2841 0 : status = NT_STATUS_INVALID_PARAMETER;
2842 0 : goto done;
2843 : }
2844 :
2845 98 : if (ndr_syntax_id_equal(&table->syntax_id,
2846 : &ndr_table_epmapper.syntax_id)) {
2847 96 : *pport = 135;
2848 96 : status = NT_STATUS_OK;
2849 96 : goto done;
2850 : }
2851 :
2852 : /* open the connection to the endpoint mapper */
2853 2 : status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2854 : &ndr_table_epmapper,
2855 : &epm_pipe);
2856 :
2857 2 : if (!NT_STATUS_IS_OK(status)) {
2858 0 : goto done;
2859 : }
2860 :
2861 2 : status = rpccli_anon_bind_data(tmp_ctx, &auth);
2862 2 : if (!NT_STATUS_IS_OK(status)) {
2863 0 : goto done;
2864 : }
2865 :
2866 2 : status = rpc_pipe_bind(epm_pipe, auth);
2867 2 : if (!NT_STATUS_IS_OK(status)) {
2868 0 : goto done;
2869 : }
2870 :
2871 2 : status = rpccli_epm_map_interface(
2872 2 : epm_pipe->binding_handle,
2873 : NCACN_IP_TCP,
2874 : &table->syntax_id,
2875 : tmp_ctx,
2876 : &endpoint);
2877 2 : if (!NT_STATUS_IS_OK(status)) {
2878 0 : DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2879 : nt_errstr(status));
2880 0 : goto done;
2881 : }
2882 :
2883 2 : *pport = (uint16_t)atoi(endpoint);
2884 :
2885 98 : done:
2886 98 : TALLOC_FREE(tmp_ctx);
2887 98 : return status;
2888 : }
2889 :
2890 : /**
2891 : * Create a rpc pipe client struct, connecting to a host via tcp.
2892 : * The port is determined by asking the endpoint mapper on the given
2893 : * host.
2894 : */
2895 98 : static NTSTATUS rpc_pipe_open_tcp(
2896 : TALLOC_CTX *mem_ctx,
2897 : const char *host,
2898 : const struct sockaddr_storage *addr,
2899 : const struct ndr_interface_table *table,
2900 : struct rpc_pipe_client **presult)
2901 : {
2902 0 : NTSTATUS status;
2903 98 : uint16_t port = 0;
2904 :
2905 98 : status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2906 98 : if (!NT_STATUS_IS_OK(status)) {
2907 0 : return status;
2908 : }
2909 :
2910 98 : return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2911 : table, presult);
2912 : }
2913 :
2914 152 : static NTSTATUS rpc_pipe_get_ncalrpc_name(
2915 : const struct ndr_syntax_id *iface,
2916 : TALLOC_CTX *mem_ctx,
2917 : char **psocket_name)
2918 : {
2919 152 : TALLOC_CTX *frame = talloc_stackframe();
2920 152 : struct rpc_pipe_client *epm_pipe = NULL;
2921 152 : struct pipe_auth_data *auth = NULL;
2922 152 : NTSTATUS status = NT_STATUS_OK;
2923 0 : bool is_epm;
2924 :
2925 152 : is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
2926 152 : if (is_epm) {
2927 152 : char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
2928 152 : if (endpoint == NULL) {
2929 0 : status = NT_STATUS_NO_MEMORY;
2930 0 : goto done;
2931 : }
2932 152 : *psocket_name = endpoint;
2933 152 : goto done;
2934 : }
2935 :
2936 0 : status = rpc_pipe_open_ncalrpc(
2937 : frame, &ndr_table_epmapper, &epm_pipe);
2938 0 : if (!NT_STATUS_IS_OK(status)) {
2939 0 : DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
2940 : nt_errstr(status));
2941 0 : goto done;
2942 : }
2943 :
2944 0 : status = rpccli_anon_bind_data(epm_pipe, &auth);
2945 0 : if (!NT_STATUS_IS_OK(status)) {
2946 0 : DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
2947 : nt_errstr(status));
2948 0 : goto done;
2949 : }
2950 :
2951 0 : status = rpc_pipe_bind(epm_pipe, auth);
2952 0 : if (!NT_STATUS_IS_OK(status)) {
2953 0 : DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
2954 0 : goto done;
2955 : }
2956 :
2957 0 : status = rpccli_epm_map_interface(
2958 0 : epm_pipe->binding_handle,
2959 : NCALRPC,
2960 : iface,
2961 : mem_ctx,
2962 : psocket_name);
2963 0 : if (!NT_STATUS_IS_OK(status)) {
2964 0 : DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2965 : nt_errstr(status));
2966 : }
2967 :
2968 0 : done:
2969 152 : TALLOC_FREE(frame);
2970 152 : return status;
2971 : }
2972 :
2973 : /********************************************************************
2974 : Create a rpc pipe client struct, connecting to a unix domain socket
2975 : ********************************************************************/
2976 152 : NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
2977 : const struct ndr_interface_table *table,
2978 : struct rpc_pipe_client **presult)
2979 : {
2980 152 : char *socket_name = NULL;
2981 0 : struct rpc_pipe_client *result;
2982 152 : struct sockaddr_un addr = { .sun_family = AF_UNIX };
2983 152 : socklen_t salen = sizeof(addr);
2984 0 : int pathlen;
2985 0 : NTSTATUS status;
2986 152 : int fd = -1;
2987 :
2988 152 : result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2989 152 : if (result == NULL) {
2990 0 : return NT_STATUS_NO_MEMORY;
2991 : }
2992 :
2993 152 : status = rpc_pipe_get_ncalrpc_name(
2994 : &table->syntax_id, result, &socket_name);
2995 152 : if (!NT_STATUS_IS_OK(status)) {
2996 0 : DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
2997 : nt_errstr(status));
2998 0 : goto fail;
2999 : }
3000 :
3001 152 : pathlen = snprintf(
3002 : addr.sun_path,
3003 : sizeof(addr.sun_path),
3004 : "%s/%s",
3005 : lp_ncalrpc_dir(),
3006 : socket_name);
3007 152 : if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
3008 0 : DBG_DEBUG("socket_path for %s too long\n", socket_name);
3009 0 : status = NT_STATUS_NAME_TOO_LONG;
3010 0 : goto fail;
3011 : }
3012 152 : TALLOC_FREE(socket_name);
3013 :
3014 152 : result->abstract_syntax = table->syntax_id;
3015 152 : result->transfer_syntax = ndr_transfer_syntax_ndr;
3016 :
3017 152 : result->desthost = get_myname(result);
3018 152 : if (result->desthost == NULL) {
3019 0 : status = NT_STATUS_NO_MEMORY;
3020 0 : goto fail;
3021 : }
3022 :
3023 152 : result->srv_name_slash = talloc_asprintf_strupper_m(
3024 : result, "\\\\%s", result->desthost);
3025 152 : if (result->srv_name_slash == NULL) {
3026 0 : status = NT_STATUS_NO_MEMORY;
3027 0 : goto fail;
3028 : }
3029 :
3030 152 : result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3031 :
3032 152 : fd = socket(AF_UNIX, SOCK_STREAM, 0);
3033 152 : if (fd == -1) {
3034 0 : status = map_nt_error_from_unix(errno);
3035 0 : goto fail;
3036 : }
3037 :
3038 152 : if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
3039 16 : DBG_WARNING("connect(%s) failed: %s\n",
3040 : addr.sun_path,
3041 : strerror(errno));
3042 16 : status = map_nt_error_from_unix(errno);
3043 16 : goto fail;
3044 : }
3045 :
3046 136 : status = rpc_transport_sock_init(result, fd, &result->transport);
3047 136 : if (!NT_STATUS_IS_OK(status)) {
3048 0 : goto fail;
3049 : }
3050 136 : fd = -1;
3051 :
3052 136 : result->transport->transport = NCALRPC;
3053 :
3054 136 : result->binding_handle = rpccli_bh_create(result, NULL, table);
3055 136 : if (result->binding_handle == NULL) {
3056 0 : status = NT_STATUS_NO_MEMORY;
3057 0 : goto fail;
3058 : }
3059 :
3060 136 : *presult = result;
3061 136 : return NT_STATUS_OK;
3062 :
3063 16 : fail:
3064 16 : if (fd != -1) {
3065 16 : close(fd);
3066 : }
3067 16 : TALLOC_FREE(result);
3068 16 : return status;
3069 : }
3070 :
3071 30671 : NTSTATUS rpc_pipe_open_local_np(
3072 : TALLOC_CTX *mem_ctx,
3073 : const struct ndr_interface_table *table,
3074 : const char *remote_client_name,
3075 : const struct tsocket_address *remote_client_addr,
3076 : const char *local_server_name,
3077 : const struct tsocket_address *local_server_addr,
3078 : const struct auth_session_info *session_info,
3079 : struct rpc_pipe_client **presult)
3080 : {
3081 30671 : struct rpc_pipe_client *result = NULL;
3082 30671 : struct pipe_auth_data *auth = NULL;
3083 30671 : const char *pipe_name = NULL;
3084 30671 : struct tstream_context *npa_stream = NULL;
3085 30671 : NTSTATUS status = NT_STATUS_NO_MEMORY;
3086 0 : int ret;
3087 :
3088 30671 : result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3089 30671 : if (result == NULL) {
3090 0 : goto fail;
3091 : }
3092 30671 : result->abstract_syntax = table->syntax_id;
3093 30671 : result->transfer_syntax = ndr_transfer_syntax_ndr;
3094 30671 : result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3095 :
3096 30671 : pipe_name = dcerpc_default_transport_endpoint(
3097 : result, NCACN_NP, table);
3098 30671 : if (pipe_name == NULL) {
3099 0 : DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
3100 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3101 0 : goto fail;
3102 : }
3103 :
3104 30671 : if (local_server_name == NULL) {
3105 30671 : result->desthost = get_myname(result);
3106 : } else {
3107 0 : result->desthost = talloc_strdup(result, local_server_name);
3108 : }
3109 30671 : if (result->desthost == NULL) {
3110 0 : goto fail;
3111 : }
3112 30671 : result->srv_name_slash = talloc_asprintf_strupper_m(
3113 : result, "\\\\%s", result->desthost);
3114 30671 : if (result->srv_name_slash == NULL) {
3115 0 : goto fail;
3116 : }
3117 :
3118 30671 : ret = local_np_connect(
3119 : pipe_name,
3120 : NCALRPC,
3121 : remote_client_name,
3122 : remote_client_addr,
3123 : local_server_name,
3124 : local_server_addr,
3125 : session_info,
3126 : true,
3127 : result,
3128 : &npa_stream);
3129 30671 : if (ret != 0) {
3130 0 : DBG_DEBUG("local_np_connect for %s and "
3131 : "user %s\\%s failed: %s\n",
3132 : pipe_name,
3133 : session_info->info->domain_name,
3134 : session_info->info->account_name,
3135 : strerror(ret));
3136 0 : status = map_nt_error_from_unix(ret);
3137 0 : goto fail;
3138 : }
3139 :
3140 30671 : status = rpc_transport_tstream_init(
3141 : result, &npa_stream, &result->transport);
3142 30671 : if (!NT_STATUS_IS_OK(status)) {
3143 0 : DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
3144 : nt_errstr(status));
3145 0 : goto fail;
3146 : }
3147 :
3148 30671 : result->binding_handle = rpccli_bh_create(result, NULL, table);
3149 30671 : if (result->binding_handle == NULL) {
3150 0 : status = NT_STATUS_NO_MEMORY;
3151 0 : DBG_DEBUG("Failed to create binding handle.\n");
3152 0 : goto fail;
3153 : }
3154 :
3155 30671 : status = rpccli_anon_bind_data(result, &auth);
3156 30671 : if (!NT_STATUS_IS_OK(status)) {
3157 0 : DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3158 : nt_errstr(status));
3159 0 : goto fail;
3160 : }
3161 :
3162 30671 : status = rpc_pipe_bind(result, auth);
3163 30671 : if (!NT_STATUS_IS_OK(status)) {
3164 0 : DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3165 0 : goto fail;
3166 : }
3167 :
3168 30671 : *presult = result;
3169 30671 : return NT_STATUS_OK;
3170 :
3171 0 : fail:
3172 0 : TALLOC_FREE(result);
3173 0 : return status;
3174 : }
3175 :
3176 : struct rpc_pipe_client_np_ref {
3177 : struct cli_state *cli;
3178 : struct rpc_pipe_client *pipe;
3179 : };
3180 :
3181 10754 : static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3182 : {
3183 10754 : DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3184 10754 : return 0;
3185 : }
3186 :
3187 : /****************************************************************************
3188 : Open a named pipe over SMB to a remote server.
3189 : *
3190 : * CAVEAT CALLER OF THIS FUNCTION:
3191 : * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3192 : * so be sure that this function is called AFTER any structure (vs pointer)
3193 : * assignment of the cli. In particular, libsmbclient does structure
3194 : * assignments of cli, which invalidates the data in the returned
3195 : * rpc_pipe_client if this function is called before the structure assignment
3196 : * of cli.
3197 : *
3198 : ****************************************************************************/
3199 :
3200 : struct rpc_pipe_open_np_state {
3201 : struct cli_state *cli;
3202 : const struct ndr_interface_table *table;
3203 : struct rpc_pipe_client *result;
3204 : };
3205 :
3206 : static void rpc_pipe_open_np_done(struct tevent_req *subreq);
3207 :
3208 10772 : struct tevent_req *rpc_pipe_open_np_send(
3209 : TALLOC_CTX *mem_ctx,
3210 : struct tevent_context *ev,
3211 : struct cli_state *cli,
3212 : const struct ndr_interface_table *table)
3213 : {
3214 10772 : struct tevent_req *req = NULL, *subreq = NULL;
3215 10772 : struct rpc_pipe_open_np_state *state = NULL;
3216 10772 : struct rpc_pipe_client *result = NULL;
3217 :
3218 10772 : req = tevent_req_create(
3219 : mem_ctx, &state, struct rpc_pipe_open_np_state);
3220 10772 : if (req == NULL) {
3221 0 : return NULL;
3222 : }
3223 10772 : state->cli = cli;
3224 10772 : state->table = table;
3225 :
3226 10772 : state->result = talloc_zero(state, struct rpc_pipe_client);
3227 10772 : if (tevent_req_nomem(state->result, req)) {
3228 0 : return tevent_req_post(req, ev);
3229 : }
3230 10772 : result = state->result;
3231 :
3232 10772 : result->abstract_syntax = table->syntax_id;
3233 10772 : result->transfer_syntax = ndr_transfer_syntax_ndr;
3234 :
3235 10772 : result->desthost = talloc_strdup(
3236 : result, smbXcli_conn_remote_name(cli->conn));
3237 10772 : if (tevent_req_nomem(result->desthost, req)) {
3238 0 : return tevent_req_post(req, ev);
3239 : }
3240 :
3241 10772 : result->srv_name_slash = talloc_asprintf_strupper_m(
3242 : result, "\\\\%s", result->desthost);
3243 10772 : if (tevent_req_nomem(result->srv_name_slash, req)) {
3244 0 : return tevent_req_post(req, ev);
3245 : }
3246 :
3247 10772 : result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3248 :
3249 10772 : subreq = rpc_transport_np_init_send(state, ev, cli, table);
3250 10772 : if (tevent_req_nomem(subreq, req)) {
3251 0 : return tevent_req_post(req, ev);
3252 : }
3253 10772 : tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
3254 10772 : return req;
3255 : }
3256 :
3257 10772 : static void rpc_pipe_open_np_done(struct tevent_req *subreq)
3258 : {
3259 10772 : struct tevent_req *req = tevent_req_callback_data(
3260 : subreq, struct tevent_req);
3261 10772 : struct rpc_pipe_open_np_state *state = tevent_req_data(
3262 : req, struct rpc_pipe_open_np_state);
3263 10772 : struct rpc_pipe_client *result = state->result;
3264 10772 : struct rpc_pipe_client_np_ref *np_ref = NULL;
3265 0 : NTSTATUS status;
3266 :
3267 10772 : status = rpc_transport_np_init_recv(
3268 : subreq, result, &result->transport);
3269 10772 : TALLOC_FREE(subreq);
3270 10772 : if (tevent_req_nterror(req, status)) {
3271 0 : return;
3272 : }
3273 :
3274 10772 : result->transport->transport = NCACN_NP;
3275 :
3276 10772 : np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3277 10772 : if (tevent_req_nomem(np_ref, req)) {
3278 0 : return;
3279 : }
3280 10772 : np_ref->cli = state->cli;
3281 10772 : np_ref->pipe = result;
3282 :
3283 10772 : DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3284 10772 : talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3285 :
3286 10772 : result->binding_handle = rpccli_bh_create(result, NULL, state->table);
3287 10772 : if (tevent_req_nomem(result->binding_handle, req)) {
3288 0 : return;
3289 : }
3290 :
3291 10772 : tevent_req_done(req);
3292 : }
3293 :
3294 10772 : NTSTATUS rpc_pipe_open_np_recv(
3295 : struct tevent_req *req,
3296 : TALLOC_CTX *mem_ctx,
3297 : struct rpc_pipe_client **_result)
3298 : {
3299 10772 : struct rpc_pipe_open_np_state *state = tevent_req_data(
3300 : req, struct rpc_pipe_open_np_state);
3301 0 : NTSTATUS status;
3302 :
3303 10772 : if (tevent_req_is_nterror(req, &status)) {
3304 0 : return status;
3305 : }
3306 10772 : *_result = talloc_move(mem_ctx, &state->result);
3307 10772 : return NT_STATUS_OK;
3308 : }
3309 :
3310 10772 : NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3311 : const struct ndr_interface_table *table,
3312 : struct rpc_pipe_client **presult)
3313 : {
3314 10772 : struct tevent_context *ev = NULL;
3315 10772 : struct tevent_req *req = NULL;
3316 10772 : NTSTATUS status = NT_STATUS_NO_MEMORY;
3317 :
3318 10772 : ev = samba_tevent_context_init(cli);
3319 10772 : if (ev == NULL) {
3320 0 : goto fail;
3321 : }
3322 10772 : req = rpc_pipe_open_np_send(ev, ev, cli, table);
3323 10772 : if (req == NULL) {
3324 0 : goto fail;
3325 : }
3326 10772 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3327 0 : goto fail;
3328 : }
3329 10772 : status = rpc_pipe_open_np_recv(req, NULL, presult);
3330 10772 : fail:
3331 10772 : TALLOC_FREE(req);
3332 10772 : TALLOC_FREE(ev);
3333 10772 : return status;
3334 : }
3335 :
3336 : /****************************************************************************
3337 : Open a pipe to a remote server.
3338 : ****************************************************************************/
3339 :
3340 10870 : static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3341 : enum dcerpc_transport_t transport,
3342 : const struct ndr_interface_table *table,
3343 : const char *remote_name,
3344 : const struct sockaddr_storage *remote_sockaddr,
3345 : struct rpc_pipe_client **presult)
3346 : {
3347 10870 : switch (transport) {
3348 98 : case NCACN_IP_TCP:
3349 98 : return rpc_pipe_open_tcp(NULL,
3350 : remote_name,
3351 : remote_sockaddr,
3352 : table, presult);
3353 10772 : case NCACN_NP:
3354 10772 : return rpc_pipe_open_np(cli, table, presult);
3355 0 : default:
3356 0 : return NT_STATUS_NOT_IMPLEMENTED;
3357 : }
3358 : }
3359 :
3360 : /****************************************************************************
3361 : Open a named pipe to an SMB server and bind anonymously.
3362 : ****************************************************************************/
3363 :
3364 10530 : NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3365 : enum dcerpc_transport_t transport,
3366 : const struct ndr_interface_table *table,
3367 : const char *remote_name,
3368 : const struct sockaddr_storage *remote_sockaddr,
3369 : struct rpc_pipe_client **presult)
3370 : {
3371 0 : struct rpc_pipe_client *result;
3372 0 : struct pipe_auth_data *auth;
3373 0 : NTSTATUS status;
3374 :
3375 10530 : status = cli_rpc_pipe_open(cli,
3376 : transport,
3377 : table,
3378 : remote_name,
3379 : remote_sockaddr,
3380 : &result);
3381 10530 : if (!NT_STATUS_IS_OK(status)) {
3382 0 : return status;
3383 : }
3384 :
3385 10530 : status = rpccli_anon_bind_data(result, &auth);
3386 10530 : if (!NT_STATUS_IS_OK(status)) {
3387 0 : DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3388 : nt_errstr(status)));
3389 0 : TALLOC_FREE(result);
3390 0 : return status;
3391 : }
3392 :
3393 : /*
3394 : * This is a bit of an abstraction violation due to the fact that an
3395 : * anonymous bind on an authenticated SMB inherits the user/domain
3396 : * from the enclosing SMB creds
3397 : */
3398 :
3399 10530 : if (transport == NCACN_NP) {
3400 0 : struct smbXcli_session *session;
3401 :
3402 10522 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3403 10378 : session = cli->smb2.session;
3404 : } else {
3405 144 : session = cli->smb1.session;
3406 : }
3407 :
3408 10522 : status = smbXcli_session_application_key(session, auth,
3409 10522 : &auth->transport_session_key);
3410 10522 : if (!NT_STATUS_IS_OK(status)) {
3411 167 : auth->transport_session_key = data_blob_null;
3412 : }
3413 : }
3414 :
3415 10530 : status = rpc_pipe_bind(result, auth);
3416 10530 : if (!NT_STATUS_IS_OK(status)) {
3417 0 : int lvl = 0;
3418 0 : if (ndr_syntax_id_equal(&table->syntax_id,
3419 : &ndr_table_dssetup.syntax_id)) {
3420 : /* non AD domains just don't have this pipe, avoid
3421 : * level 0 statement in that case - gd */
3422 0 : lvl = 3;
3423 : }
3424 0 : DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3425 : "%s failed with error %s\n",
3426 : table->name,
3427 : nt_errstr(status) ));
3428 0 : TALLOC_FREE(result);
3429 0 : return status;
3430 : }
3431 :
3432 10530 : DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3433 : "%s and bound anonymously.\n",
3434 : table->name,
3435 : result->desthost));
3436 :
3437 10530 : *presult = result;
3438 10530 : return NT_STATUS_OK;
3439 : }
3440 :
3441 : /****************************************************************************
3442 : ****************************************************************************/
3443 :
3444 10136 : NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3445 : const struct ndr_interface_table *table,
3446 : struct rpc_pipe_client **presult)
3447 : {
3448 10136 : const char *remote_name = smbXcli_conn_remote_name(cli->conn);
3449 0 : const struct sockaddr_storage *remote_sockaddr =
3450 10136 : smbXcli_conn_remote_sockaddr(cli->conn);
3451 :
3452 10136 : return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3453 : table,
3454 : remote_name,
3455 : remote_sockaddr,
3456 : presult);
3457 : }
3458 :
3459 : /****************************************************************************
3460 : Open a named pipe to an SMB server and bind using the mech specified
3461 :
3462 : This routine references the creds pointer that is passed in
3463 : ****************************************************************************/
3464 :
3465 233 : NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3466 : const struct ndr_interface_table *table,
3467 : enum dcerpc_transport_t transport,
3468 : enum dcerpc_AuthType auth_type,
3469 : enum dcerpc_AuthLevel auth_level,
3470 : const char *server,
3471 : const struct sockaddr_storage *remote_sockaddr,
3472 : struct cli_credentials *creds,
3473 : struct rpc_pipe_client **presult)
3474 : {
3475 0 : struct rpc_pipe_client *result;
3476 233 : struct pipe_auth_data *auth = NULL;
3477 233 : const char *target_service = table->authservices->names[0];
3478 0 : NTSTATUS status;
3479 :
3480 233 : status = cli_rpc_pipe_open(cli,
3481 : transport,
3482 : table,
3483 : server,
3484 : remote_sockaddr,
3485 : &result);
3486 233 : if (!NT_STATUS_IS_OK(status)) {
3487 0 : return status;
3488 : }
3489 :
3490 233 : status = rpccli_generic_bind_data_from_creds(result,
3491 : auth_type, auth_level,
3492 : server, target_service,
3493 : creds,
3494 : &auth);
3495 233 : if (!NT_STATUS_IS_OK(status)) {
3496 0 : DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3497 : nt_errstr(status));
3498 0 : goto err;
3499 : }
3500 :
3501 233 : status = rpc_pipe_bind(result, auth);
3502 233 : if (!NT_STATUS_IS_OK(status)) {
3503 0 : DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3504 : nt_errstr(status));
3505 0 : goto err;
3506 : }
3507 :
3508 233 : DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3509 : table->name,
3510 : result->desthost,
3511 : cli_credentials_get_unparsed_name(creds, talloc_tos()));
3512 :
3513 233 : *presult = result;
3514 233 : return NT_STATUS_OK;
3515 :
3516 0 : err:
3517 :
3518 0 : TALLOC_FREE(result);
3519 0 : return status;
3520 : }
3521 :
3522 107 : NTSTATUS cli_rpc_pipe_open_bind_schannel(
3523 : struct cli_state *cli,
3524 : const struct ndr_interface_table *table,
3525 : enum dcerpc_transport_t transport,
3526 : struct netlogon_creds_cli_context *netlogon_creds,
3527 : const char *remote_name,
3528 : const struct sockaddr_storage *remote_sockaddr,
3529 : struct rpc_pipe_client **_rpccli)
3530 : {
3531 0 : struct rpc_pipe_client *rpccli;
3532 0 : struct pipe_auth_data *rpcauth;
3533 107 : const char *target_service = table->authservices->names[0];
3534 0 : struct cli_credentials *cli_creds;
3535 0 : enum dcerpc_AuthLevel auth_level;
3536 0 : NTSTATUS status;
3537 :
3538 107 : status = cli_rpc_pipe_open(cli,
3539 : transport,
3540 : table,
3541 : remote_name,
3542 : remote_sockaddr,
3543 : &rpccli);
3544 107 : if (!NT_STATUS_IS_OK(status)) {
3545 0 : return status;
3546 : }
3547 :
3548 107 : auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3549 :
3550 107 : status = netlogon_creds_bind_cli_credentials(
3551 : netlogon_creds, rpccli, &cli_creds);
3552 107 : if (!NT_STATUS_IS_OK(status)) {
3553 0 : DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3554 : nt_errstr(status));
3555 0 : TALLOC_FREE(rpccli);
3556 0 : return status;
3557 : }
3558 :
3559 107 : status = rpccli_generic_bind_data_from_creds(rpccli,
3560 : DCERPC_AUTH_TYPE_SCHANNEL,
3561 : auth_level,
3562 107 : rpccli->desthost,
3563 : target_service,
3564 : cli_creds,
3565 : &rpcauth);
3566 107 : if (!NT_STATUS_IS_OK(status)) {
3567 0 : DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3568 : nt_errstr(status)));
3569 0 : TALLOC_FREE(rpccli);
3570 0 : return status;
3571 : }
3572 :
3573 107 : status = rpc_pipe_bind(rpccli, rpcauth);
3574 :
3575 : /* No TALLOC_FREE, gensec takes references */
3576 107 : talloc_unlink(rpccli, cli_creds);
3577 107 : cli_creds = NULL;
3578 :
3579 107 : if (!NT_STATUS_IS_OK(status)) {
3580 0 : DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3581 : nt_errstr(status));
3582 0 : TALLOC_FREE(rpccli);
3583 0 : return status;
3584 : }
3585 :
3586 107 : *_rpccli = rpccli;
3587 :
3588 107 : return NT_STATUS_OK;
3589 : }
3590 :
3591 107 : NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3592 : const struct ndr_interface_table *table,
3593 : enum dcerpc_transport_t transport,
3594 : struct netlogon_creds_cli_context *netlogon_creds,
3595 : const char *remote_name,
3596 : const struct sockaddr_storage *remote_sockaddr,
3597 : struct rpc_pipe_client **_rpccli)
3598 : {
3599 107 : TALLOC_CTX *frame = talloc_stackframe();
3600 0 : struct rpc_pipe_client *rpccli;
3601 0 : struct netlogon_creds_cli_lck *lck;
3602 0 : NTSTATUS status;
3603 :
3604 107 : status = netlogon_creds_cli_lck(
3605 : netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3606 : frame, &lck);
3607 107 : if (!NT_STATUS_IS_OK(status)) {
3608 0 : DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3609 : nt_errstr(status));
3610 0 : TALLOC_FREE(frame);
3611 0 : return status;
3612 : }
3613 :
3614 107 : status = cli_rpc_pipe_open_bind_schannel(cli,
3615 : table,
3616 : transport,
3617 : netlogon_creds,
3618 : remote_name,
3619 : remote_sockaddr,
3620 : &rpccli);
3621 107 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3622 0 : netlogon_creds_cli_delete_lck(netlogon_creds);
3623 : }
3624 107 : if (!NT_STATUS_IS_OK(status)) {
3625 0 : DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3626 : nt_errstr(status));
3627 0 : TALLOC_FREE(frame);
3628 0 : return status;
3629 : }
3630 :
3631 107 : if (ndr_syntax_id_equal(&table->syntax_id,
3632 : &ndr_table_netlogon.syntax_id)) {
3633 103 : status = netlogon_creds_cli_check(netlogon_creds,
3634 103 : rpccli->binding_handle,
3635 : NULL);
3636 103 : if (!NT_STATUS_IS_OK(status)) {
3637 0 : DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3638 : nt_errstr(status)));
3639 0 : TALLOC_FREE(frame);
3640 0 : return status;
3641 : }
3642 : }
3643 :
3644 107 : DBG_DEBUG("opened pipe %s to machine %s with key %s "
3645 : "and bound using schannel.\n",
3646 : table->name, rpccli->desthost,
3647 : netlogon_creds_cli_debug_string(netlogon_creds, lck));
3648 :
3649 107 : TALLOC_FREE(frame);
3650 :
3651 107 : *_rpccli = rpccli;
3652 107 : return NT_STATUS_OK;
3653 : }
3654 :
3655 21 : NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3656 : struct rpc_pipe_client *cli,
3657 : DATA_BLOB *session_key)
3658 : {
3659 0 : NTSTATUS status;
3660 0 : struct pipe_auth_data *a;
3661 0 : struct gensec_security *gensec_security;
3662 21 : DATA_BLOB sk = { .data = NULL };
3663 21 : bool make_dup = false;
3664 :
3665 21 : if (!session_key || !cli) {
3666 0 : return NT_STATUS_INVALID_PARAMETER;
3667 : }
3668 :
3669 21 : a = cli->auth;
3670 :
3671 21 : if (a == NULL) {
3672 0 : return NT_STATUS_INVALID_PARAMETER;
3673 : }
3674 :
3675 21 : switch (cli->auth->auth_type) {
3676 21 : case DCERPC_AUTH_TYPE_NONE:
3677 21 : sk = data_blob_const(a->transport_session_key.data,
3678 : a->transport_session_key.length);
3679 21 : make_dup = true;
3680 21 : break;
3681 0 : default:
3682 0 : gensec_security = a->auth_ctx;
3683 0 : status = gensec_session_key(gensec_security, mem_ctx, &sk);
3684 0 : if (!NT_STATUS_IS_OK(status)) {
3685 0 : return status;
3686 : }
3687 0 : make_dup = false;
3688 0 : break;
3689 : }
3690 :
3691 21 : if (!sk.data) {
3692 0 : return NT_STATUS_NO_USER_SESSION_KEY;
3693 : }
3694 :
3695 21 : if (make_dup) {
3696 21 : *session_key = data_blob_dup_talloc(mem_ctx, sk);
3697 : } else {
3698 0 : *session_key = sk;
3699 : }
3700 :
3701 21 : return NT_STATUS_OK;
3702 : }
|