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