charset/tests: add more str[n]casecmp_m() tests to demonstrate the bug
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob63b6cf4b458343205379b79b398049f5303a8ed3
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.
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.
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.
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/>.
22 #include "includes.h"
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/netlogon_creds_cli.h"
28 #include "auth_generic.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "rpc_dce.h"
33 #include "cli_pipe.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/credentials/credentials.h"
37 #include "../libcli/smb/smbXcli_base.h"
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_RPC_CLI
42 /********************************************************************
43 Pipe description for a DEBUG
44 ********************************************************************/
45 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
46 struct rpc_pipe_client *cli)
48 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
49 if (result == NULL) {
50 return "pipe";
52 return result;
55 /********************************************************************
56 Rpc pipe call id.
57 ********************************************************************/
59 static uint32_t get_rpc_call_id(void)
61 static uint32_t call_id = 0;
62 return ++call_id;
65 /*******************************************************************
66 Use SMBreadX to get rest of one fragment's worth of rpc data.
67 Reads the whole size or give an error message
68 ********************************************************************/
70 struct rpc_read_state {
71 struct tevent_context *ev;
72 struct rpc_cli_transport *transport;
73 uint8_t *data;
74 size_t size;
75 size_t num_read;
78 static void rpc_read_done(struct tevent_req *subreq);
80 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
81 struct tevent_context *ev,
82 struct rpc_cli_transport *transport,
83 uint8_t *data, size_t size)
85 struct tevent_req *req, *subreq;
86 struct rpc_read_state *state;
88 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
89 if (req == NULL) {
90 return NULL;
92 state->ev = ev;
93 state->transport = transport;
94 state->data = data;
95 state->size = size;
96 state->num_read = 0;
98 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
100 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
101 transport->priv);
102 if (subreq == NULL) {
103 goto fail;
105 tevent_req_set_callback(subreq, rpc_read_done, req);
106 return req;
108 fail:
109 TALLOC_FREE(req);
110 return NULL;
113 static void rpc_read_done(struct tevent_req *subreq)
115 struct tevent_req *req = tevent_req_callback_data(
116 subreq, struct tevent_req);
117 struct rpc_read_state *state = tevent_req_data(
118 req, struct rpc_read_state);
119 NTSTATUS status;
120 ssize_t received;
122 status = state->transport->read_recv(subreq, &received);
123 TALLOC_FREE(subreq);
124 if (!NT_STATUS_IS_OK(status)) {
125 tevent_req_nterror(req, status);
126 return;
129 state->num_read += received;
130 if (state->num_read == state->size) {
131 tevent_req_done(req);
132 return;
135 subreq = state->transport->read_send(state, state->ev,
136 state->data + state->num_read,
137 state->size - state->num_read,
138 state->transport->priv);
139 if (tevent_req_nomem(subreq, req)) {
140 return;
142 tevent_req_set_callback(subreq, rpc_read_done, req);
145 static NTSTATUS rpc_read_recv(struct tevent_req *req)
147 return tevent_req_simple_recv_ntstatus(req);
150 struct rpc_write_state {
151 struct tevent_context *ev;
152 struct rpc_cli_transport *transport;
153 const uint8_t *data;
154 size_t size;
155 size_t num_written;
158 static void rpc_write_done(struct tevent_req *subreq);
160 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
161 struct tevent_context *ev,
162 struct rpc_cli_transport *transport,
163 const uint8_t *data, size_t size)
165 struct tevent_req *req, *subreq;
166 struct rpc_write_state *state;
168 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
169 if (req == NULL) {
170 return NULL;
172 state->ev = ev;
173 state->transport = transport;
174 state->data = data;
175 state->size = size;
176 state->num_written = 0;
178 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
180 subreq = transport->write_send(state, ev, data, size, transport->priv);
181 if (subreq == NULL) {
182 goto fail;
184 tevent_req_set_callback(subreq, rpc_write_done, req);
185 return req;
186 fail:
187 TALLOC_FREE(req);
188 return NULL;
191 static void rpc_write_done(struct tevent_req *subreq)
193 struct tevent_req *req = tevent_req_callback_data(
194 subreq, struct tevent_req);
195 struct rpc_write_state *state = tevent_req_data(
196 req, struct rpc_write_state);
197 NTSTATUS status;
198 ssize_t written;
200 status = state->transport->write_recv(subreq, &written);
201 TALLOC_FREE(subreq);
202 if (!NT_STATUS_IS_OK(status)) {
203 tevent_req_nterror(req, status);
204 return;
207 state->num_written += written;
209 if (state->num_written == state->size) {
210 tevent_req_done(req);
211 return;
214 subreq = state->transport->write_send(state, state->ev,
215 state->data + state->num_written,
216 state->size - state->num_written,
217 state->transport->priv);
218 if (tevent_req_nomem(subreq, req)) {
219 return;
221 tevent_req_set_callback(subreq, rpc_write_done, req);
224 static NTSTATUS rpc_write_recv(struct tevent_req *req)
226 return tevent_req_simple_recv_ntstatus(req);
230 /****************************************************************************
231 Try and get a PDU's worth of data from current_pdu. If not, then read more
232 from the wire.
233 ****************************************************************************/
235 struct get_complete_frag_state {
236 struct tevent_context *ev;
237 struct rpc_pipe_client *cli;
238 uint16_t frag_len;
239 DATA_BLOB *pdu;
242 static void get_complete_frag_got_header(struct tevent_req *subreq);
243 static void get_complete_frag_got_rest(struct tevent_req *subreq);
245 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
246 struct tevent_context *ev,
247 struct rpc_pipe_client *cli,
248 DATA_BLOB *pdu)
250 struct tevent_req *req, *subreq;
251 struct get_complete_frag_state *state;
252 size_t received;
253 NTSTATUS status;
255 req = tevent_req_create(mem_ctx, &state,
256 struct get_complete_frag_state);
257 if (req == NULL) {
258 return NULL;
260 state->ev = ev;
261 state->cli = cli;
262 state->frag_len = RPC_HEADER_LEN;
263 state->pdu = pdu;
265 received = pdu->length;
266 if (received < RPC_HEADER_LEN) {
267 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
268 status = NT_STATUS_NO_MEMORY;
269 goto post_status;
271 subreq = rpc_read_send(state, state->ev,
272 state->cli->transport,
273 pdu->data + received,
274 RPC_HEADER_LEN - received);
275 if (subreq == NULL) {
276 status = NT_STATUS_NO_MEMORY;
277 goto post_status;
279 tevent_req_set_callback(subreq, get_complete_frag_got_header,
280 req);
281 return req;
284 state->frag_len = dcerpc_get_frag_length(pdu);
285 if (state->frag_len < RPC_HEADER_LEN) {
286 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
287 return tevent_req_post(req, ev);
291 * Ensure we have frag_len bytes of data.
293 if (received < state->frag_len) {
294 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
295 status = NT_STATUS_NO_MEMORY;
296 goto post_status;
298 subreq = rpc_read_send(state, state->ev,
299 state->cli->transport,
300 pdu->data + received,
301 state->frag_len - received);
302 if (subreq == NULL) {
303 status = NT_STATUS_NO_MEMORY;
304 goto post_status;
306 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
307 req);
308 return req;
311 status = NT_STATUS_OK;
312 post_status:
313 if (NT_STATUS_IS_OK(status)) {
314 tevent_req_done(req);
315 } else {
316 tevent_req_nterror(req, status);
318 return tevent_req_post(req, ev);
321 static void get_complete_frag_got_header(struct tevent_req *subreq)
323 struct tevent_req *req = tevent_req_callback_data(
324 subreq, struct tevent_req);
325 struct get_complete_frag_state *state = tevent_req_data(
326 req, struct get_complete_frag_state);
327 NTSTATUS status;
329 status = rpc_read_recv(subreq);
330 TALLOC_FREE(subreq);
331 if (!NT_STATUS_IS_OK(status)) {
332 tevent_req_nterror(req, status);
333 return;
336 state->frag_len = dcerpc_get_frag_length(state->pdu);
337 if (state->frag_len < RPC_HEADER_LEN) {
338 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
339 return;
342 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
343 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
344 return;
348 * We're here in this piece of code because we've read exactly
349 * RPC_HEADER_LEN bytes into state->pdu.
352 subreq = rpc_read_send(state, state->ev, state->cli->transport,
353 state->pdu->data + RPC_HEADER_LEN,
354 state->frag_len - RPC_HEADER_LEN);
355 if (tevent_req_nomem(subreq, req)) {
356 return;
358 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
361 static void get_complete_frag_got_rest(struct tevent_req *subreq)
363 struct tevent_req *req = tevent_req_callback_data(
364 subreq, struct tevent_req);
365 NTSTATUS status;
367 status = rpc_read_recv(subreq);
368 TALLOC_FREE(subreq);
369 if (!NT_STATUS_IS_OK(status)) {
370 tevent_req_nterror(req, status);
371 return;
373 tevent_req_done(req);
376 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
378 return tevent_req_simple_recv_ntstatus(req);
381 /****************************************************************************
382 Do basic authentication checks on an incoming pdu.
383 ****************************************************************************/
385 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
386 struct rpc_pipe_client *cli,
387 struct ncacn_packet *pkt,
388 DATA_BLOB *pdu,
389 uint8_t expected_pkt_type,
390 uint32_t call_id,
391 DATA_BLOB *rdata,
392 DATA_BLOB *reply_pdu)
394 const struct dcerpc_response *r = NULL;
395 DATA_BLOB tmp_stub = data_blob_null;
396 NTSTATUS ret = NT_STATUS_OK;
399 * Point the return values at the real data including the RPC
400 * header. Just in case the caller wants it.
402 *rdata = *pdu;
404 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
405 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
407 * TODO: do we still need this hack which was introduced
408 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
410 * I don't even know what AS/U might be...
412 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
413 "fragment first/last ON.\n"));
414 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
417 /* Ensure we have the correct type. */
418 switch (pkt->ptype) {
419 case DCERPC_PKT_BIND_NAK:
420 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
421 rpccli_pipe_txt(talloc_tos(), cli)));
423 ret = dcerpc_verify_ncacn_packet_header(pkt,
424 DCERPC_PKT_BIND_NAK,
425 0, /* max_auth_info */
426 DCERPC_PFC_FLAG_FIRST |
427 DCERPC_PFC_FLAG_LAST,
428 0); /* optional flags */
429 if (!NT_STATUS_IS_OK(ret)) {
430 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
431 "RPC packet type - %u, expected %u: %s\n",
432 rpccli_pipe_txt(talloc_tos(), cli),
433 pkt->ptype, expected_pkt_type,
434 nt_errstr(ret)));
435 NDR_PRINT_DEBUG(ncacn_packet, pkt);
436 return ret;
439 /* Use this for now... */
440 return NT_STATUS_NETWORK_ACCESS_DENIED;
442 case DCERPC_PKT_BIND_ACK:
443 ret = dcerpc_verify_ncacn_packet_header(pkt,
444 expected_pkt_type,
445 pkt->u.bind_ack.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 if (!NT_STATUS_IS_OK(ret)) {
451 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 NDR_PRINT_DEBUG(ncacn_packet, pkt);
457 return ret;
460 break;
462 case DCERPC_PKT_ALTER_RESP:
463 ret = dcerpc_verify_ncacn_packet_header(pkt,
464 expected_pkt_type,
465 pkt->u.alter_resp.auth_info.length,
466 DCERPC_PFC_FLAG_FIRST |
467 DCERPC_PFC_FLAG_LAST,
468 DCERPC_PFC_FLAG_CONC_MPX |
469 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
470 if (!NT_STATUS_IS_OK(ret)) {
471 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
472 "RPC packet type - %u, expected %u: %s\n",
473 rpccli_pipe_txt(talloc_tos(), cli),
474 pkt->ptype, expected_pkt_type,
475 nt_errstr(ret)));
476 NDR_PRINT_DEBUG(ncacn_packet, pkt);
477 return ret;
480 break;
482 case DCERPC_PKT_RESPONSE:
484 r = &pkt->u.response;
486 ret = dcerpc_verify_ncacn_packet_header(pkt,
487 expected_pkt_type,
488 r->stub_and_verifier.length,
489 0, /* required_flags */
490 DCERPC_PFC_FLAG_FIRST |
491 DCERPC_PFC_FLAG_LAST);
492 if (!NT_STATUS_IS_OK(ret)) {
493 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
494 "RPC packet type - %u, expected %u: %s\n",
495 rpccli_pipe_txt(talloc_tos(), cli),
496 pkt->ptype, expected_pkt_type,
497 nt_errstr(ret)));
498 NDR_PRINT_DEBUG(ncacn_packet, pkt);
499 return ret;
502 tmp_stub.data = r->stub_and_verifier.data;
503 tmp_stub.length = r->stub_and_verifier.length;
505 /* Here's where we deal with incoming sign/seal. */
506 ret = dcerpc_check_auth(cli->auth, pkt,
507 &tmp_stub,
508 DCERPC_RESPONSE_LENGTH,
509 pdu);
510 if (!NT_STATUS_IS_OK(ret)) {
511 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
512 "RPC packet type - %u, expected %u: %s\n",
513 rpccli_pipe_txt(talloc_tos(), cli),
514 pkt->ptype, expected_pkt_type,
515 nt_errstr(ret)));
516 NDR_PRINT_DEBUG(ncacn_packet, pkt);
517 return ret;
520 /* Point the return values at the NDR data. */
521 *rdata = tmp_stub;
523 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
524 (long unsigned int)pdu->length,
525 (long unsigned int)rdata->length));
528 * If this is the first reply, and the allocation hint is
529 * reasonable, try and set up the reply_pdu DATA_BLOB to the
530 * correct size.
533 if ((reply_pdu->length == 0) &&
534 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
535 if (!data_blob_realloc(mem_ctx, reply_pdu,
536 r->alloc_hint)) {
537 DEBUG(0, ("reply alloc hint %d too "
538 "large to allocate\n",
539 (int)r->alloc_hint));
540 return NT_STATUS_NO_MEMORY;
544 break;
546 case DCERPC_PKT_FAULT:
548 ret = dcerpc_verify_ncacn_packet_header(pkt,
549 DCERPC_PKT_FAULT,
550 0, /* max_auth_info */
551 DCERPC_PFC_FLAG_FIRST |
552 DCERPC_PFC_FLAG_LAST,
553 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
554 if (!NT_STATUS_IS_OK(ret)) {
555 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
556 "RPC packet type - %u, expected %u: %s\n",
557 rpccli_pipe_txt(talloc_tos(), cli),
558 pkt->ptype, expected_pkt_type,
559 nt_errstr(ret)));
560 NDR_PRINT_DEBUG(ncacn_packet, pkt);
561 return ret;
564 DEBUG(1, (__location__ ": RPC fault code %s received "
565 "from %s!\n",
566 dcerpc_errstr(talloc_tos(),
567 pkt->u.fault.status),
568 rpccli_pipe_txt(talloc_tos(), cli)));
570 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
572 default:
573 DEBUG(0, (__location__ "Unknown packet type %u received "
574 "from %s!\n",
575 (unsigned int)pkt->ptype,
576 rpccli_pipe_txt(talloc_tos(), cli)));
577 return NT_STATUS_RPC_PROTOCOL_ERROR;
581 if (pkt->call_id != call_id) {
582 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
583 "RPC call_id - %u, not %u\n",
584 rpccli_pipe_txt(talloc_tos(), cli),
585 pkt->call_id, call_id));
586 return NT_STATUS_RPC_PROTOCOL_ERROR;
589 return NT_STATUS_OK;
592 /****************************************************************************
593 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
594 ****************************************************************************/
596 struct cli_api_pipe_state {
597 struct tevent_context *ev;
598 struct rpc_cli_transport *transport;
599 uint8_t *rdata;
600 uint32_t rdata_len;
603 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
604 static void cli_api_pipe_write_done(struct tevent_req *subreq);
605 static void cli_api_pipe_read_done(struct tevent_req *subreq);
607 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
608 struct tevent_context *ev,
609 struct rpc_cli_transport *transport,
610 uint8_t *data, size_t data_len,
611 uint32_t max_rdata_len)
613 struct tevent_req *req, *subreq;
614 struct cli_api_pipe_state *state;
615 NTSTATUS status;
617 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
618 if (req == NULL) {
619 return NULL;
621 state->ev = ev;
622 state->transport = transport;
624 if (max_rdata_len < RPC_HEADER_LEN) {
626 * For a RPC reply we always need at least RPC_HEADER_LEN
627 * bytes. We check this here because we will receive
628 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
630 status = NT_STATUS_INVALID_PARAMETER;
631 goto post_status;
634 if (transport->trans_send != NULL) {
635 subreq = transport->trans_send(state, ev, data, data_len,
636 max_rdata_len, transport->priv);
637 if (subreq == NULL) {
638 goto fail;
640 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
641 return req;
645 * If the transport does not provide a "trans" routine, i.e. for
646 * example the ncacn_ip_tcp transport, do the write/read step here.
649 subreq = rpc_write_send(state, ev, transport, data, data_len);
650 if (subreq == NULL) {
651 goto fail;
653 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
654 return req;
656 post_status:
657 tevent_req_nterror(req, status);
658 return tevent_req_post(req, ev);
659 fail:
660 TALLOC_FREE(req);
661 return NULL;
664 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
666 struct tevent_req *req = tevent_req_callback_data(
667 subreq, struct tevent_req);
668 struct cli_api_pipe_state *state = tevent_req_data(
669 req, struct cli_api_pipe_state);
670 NTSTATUS status;
672 status = state->transport->trans_recv(subreq, state, &state->rdata,
673 &state->rdata_len);
674 TALLOC_FREE(subreq);
675 if (!NT_STATUS_IS_OK(status)) {
676 tevent_req_nterror(req, status);
677 return;
679 tevent_req_done(req);
682 static void cli_api_pipe_write_done(struct tevent_req *subreq)
684 struct tevent_req *req = tevent_req_callback_data(
685 subreq, struct tevent_req);
686 struct cli_api_pipe_state *state = tevent_req_data(
687 req, struct cli_api_pipe_state);
688 NTSTATUS status;
690 status = rpc_write_recv(subreq);
691 TALLOC_FREE(subreq);
692 if (!NT_STATUS_IS_OK(status)) {
693 tevent_req_nterror(req, status);
694 return;
697 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
698 if (tevent_req_nomem(state->rdata, req)) {
699 return;
703 * We don't need to use rpc_read_send here, the upper layer will cope
704 * with a short read, transport->trans_send could also return less
705 * than state->max_rdata_len.
707 subreq = state->transport->read_send(state, state->ev, state->rdata,
708 RPC_HEADER_LEN,
709 state->transport->priv);
710 if (tevent_req_nomem(subreq, req)) {
711 return;
713 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
716 static void cli_api_pipe_read_done(struct tevent_req *subreq)
718 struct tevent_req *req = tevent_req_callback_data(
719 subreq, struct tevent_req);
720 struct cli_api_pipe_state *state = tevent_req_data(
721 req, struct cli_api_pipe_state);
722 NTSTATUS status;
723 ssize_t received;
725 status = state->transport->read_recv(subreq, &received);
726 TALLOC_FREE(subreq);
727 if (!NT_STATUS_IS_OK(status)) {
728 tevent_req_nterror(req, status);
729 return;
731 state->rdata_len = received;
732 tevent_req_done(req);
735 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
736 uint8_t **prdata, uint32_t *prdata_len)
738 struct cli_api_pipe_state *state = tevent_req_data(
739 req, struct cli_api_pipe_state);
740 NTSTATUS status;
742 if (tevent_req_is_nterror(req, &status)) {
743 return status;
746 *prdata = talloc_move(mem_ctx, &state->rdata);
747 *prdata_len = state->rdata_len;
748 return NT_STATUS_OK;
751 /****************************************************************************
752 Send data on an rpc pipe via trans. The data must be the last
753 pdu fragment of an NDR data stream.
755 Receive response data from an rpc pipe, which may be large...
757 Read the first fragment: unfortunately have to use SMBtrans for the first
758 bit, then SMBreadX for subsequent bits.
760 If first fragment received also wasn't the last fragment, continue
761 getting fragments until we _do_ receive the last fragment.
763 Request/Response PDU's look like the following...
765 |<------------------PDU len----------------------------------------------->|
766 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
768 +------------+-----------------+-------------+---------------+-------------+
769 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
770 +------------+-----------------+-------------+---------------+-------------+
772 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
773 signing & sealing being negotiated.
775 ****************************************************************************/
777 struct rpc_api_pipe_state {
778 struct tevent_context *ev;
779 struct rpc_pipe_client *cli;
780 uint8_t expected_pkt_type;
781 uint32_t call_id;
783 DATA_BLOB incoming_frag;
784 struct ncacn_packet *pkt;
786 /* Incoming reply */
787 DATA_BLOB reply_pdu;
788 size_t reply_pdu_offset;
789 uint8_t endianess;
792 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
793 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
794 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
796 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
797 struct tevent_context *ev,
798 struct rpc_pipe_client *cli,
799 DATA_BLOB *data, /* Outgoing PDU */
800 uint8_t expected_pkt_type,
801 uint32_t call_id)
803 struct tevent_req *req, *subreq;
804 struct rpc_api_pipe_state *state;
805 uint16_t max_recv_frag;
806 NTSTATUS status;
808 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
809 if (req == NULL) {
810 return NULL;
812 state->ev = ev;
813 state->cli = cli;
814 state->expected_pkt_type = expected_pkt_type;
815 state->call_id = call_id;
816 state->endianess = DCERPC_DREP_LE;
819 * Ensure we're not sending too much.
821 if (data->length > cli->max_xmit_frag) {
822 status = NT_STATUS_INVALID_PARAMETER;
823 goto post_status;
826 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
828 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
829 subreq = rpc_write_send(state, ev, cli->transport,
830 data->data, data->length);
831 if (subreq == NULL) {
832 goto fail;
834 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
835 return req;
838 /* get the header first, then fetch the rest once we have
839 * the frag_length available */
840 max_recv_frag = RPC_HEADER_LEN;
842 subreq = cli_api_pipe_send(state, ev, cli->transport,
843 data->data, data->length, max_recv_frag);
844 if (subreq == NULL) {
845 goto fail;
847 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
848 return req;
850 post_status:
851 tevent_req_nterror(req, status);
852 return tevent_req_post(req, ev);
853 fail:
854 TALLOC_FREE(req);
855 return NULL;
858 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
860 struct tevent_req *req =
861 tevent_req_callback_data(subreq,
862 struct tevent_req);
863 NTSTATUS status;
865 status = rpc_write_recv(subreq);
866 TALLOC_FREE(subreq);
867 if (!NT_STATUS_IS_OK(status)) {
868 tevent_req_nterror(req, status);
869 return;
872 tevent_req_done(req);
875 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
877 struct tevent_req *req = tevent_req_callback_data(
878 subreq, struct tevent_req);
879 struct rpc_api_pipe_state *state = tevent_req_data(
880 req, struct rpc_api_pipe_state);
881 NTSTATUS status;
882 uint8_t *rdata = NULL;
883 uint32_t rdata_len = 0;
885 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
886 TALLOC_FREE(subreq);
887 if (!NT_STATUS_IS_OK(status)) {
888 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
889 tevent_req_nterror(req, status);
890 return;
893 if (rdata == NULL) {
894 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
895 rpccli_pipe_txt(talloc_tos(), state->cli)));
896 tevent_req_done(req);
897 return;
901 * Move data on state->incoming_frag.
903 state->incoming_frag.data = talloc_move(state, &rdata);
904 state->incoming_frag.length = rdata_len;
905 if (!state->incoming_frag.data) {
906 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
907 return;
910 /* Ensure we have enough data for a pdu. */
911 subreq = get_complete_frag_send(state, state->ev, state->cli,
912 &state->incoming_frag);
913 if (tevent_req_nomem(subreq, req)) {
914 return;
916 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
919 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
921 struct tevent_req *req = tevent_req_callback_data(
922 subreq, struct tevent_req);
923 struct rpc_api_pipe_state *state = tevent_req_data(
924 req, struct rpc_api_pipe_state);
925 NTSTATUS status;
926 DATA_BLOB rdata = data_blob_null;
928 status = get_complete_frag_recv(subreq);
929 TALLOC_FREE(subreq);
930 if (!NT_STATUS_IS_OK(status)) {
931 DEBUG(5, ("get_complete_frag failed: %s\n",
932 nt_errstr(status)));
933 tevent_req_nterror(req, status);
934 return;
937 state->pkt = talloc(state, struct ncacn_packet);
938 if (!state->pkt) {
940 * TODO: do a real async disconnect ...
942 * For now do it sync...
944 TALLOC_FREE(state->cli->transport);
945 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
946 return;
949 status = dcerpc_pull_ncacn_packet(state->pkt,
950 &state->incoming_frag,
951 state->pkt);
952 if (!NT_STATUS_IS_OK(status)) {
954 * TODO: do a real async disconnect ...
956 * For now do it sync...
958 TALLOC_FREE(state->cli->transport);
959 tevent_req_nterror(req, status);
960 return;
963 if (DEBUGLEVEL >= 10) {
964 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
967 status = cli_pipe_validate_current_pdu(state,
968 state->cli, state->pkt,
969 &state->incoming_frag,
970 state->expected_pkt_type,
971 state->call_id,
972 &rdata,
973 &state->reply_pdu);
975 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
976 (unsigned)state->incoming_frag.length,
977 (unsigned)state->reply_pdu_offset,
978 nt_errstr(status)));
980 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
982 * TODO: do a real async disconnect ...
984 * For now do it sync...
986 TALLOC_FREE(state->cli->transport);
987 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
989 * TODO: do a real async disconnect ...
991 * For now do it sync...
993 TALLOC_FREE(state->cli->transport);
994 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
996 * TODO: do a real async disconnect ...
998 * For now do it sync...
1000 TALLOC_FREE(state->cli->transport);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 tevent_req_nterror(req, status);
1004 return;
1007 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1008 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1010 * Set the data type correctly for big-endian data on the
1011 * first packet.
1013 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1014 "big-endian.\n",
1015 rpccli_pipe_txt(talloc_tos(), state->cli)));
1016 state->endianess = 0x00; /* BIG ENDIAN */
1019 * Check endianness on subsequent packets.
1021 if (state->endianess != state->pkt->drep[0]) {
1022 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1023 "%s\n",
1024 state->endianess?"little":"big",
1025 state->pkt->drep[0]?"little":"big"));
1027 * TODO: do a real async disconnect ...
1029 * For now do it sync...
1031 TALLOC_FREE(state->cli->transport);
1032 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1033 return;
1036 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1038 * TODO: do a real async disconnect ...
1040 * For now do it sync...
1042 TALLOC_FREE(state->cli->transport);
1043 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1044 return;
1047 /* Now copy the data portion out of the pdu into rbuf. */
1048 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1049 if (!data_blob_realloc(NULL, &state->reply_pdu,
1050 state->reply_pdu_offset + rdata.length)) {
1052 * TODO: do a real async disconnect ...
1054 * For now do it sync...
1056 TALLOC_FREE(state->cli->transport);
1057 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1058 return;
1062 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1063 rdata.data, rdata.length);
1064 state->reply_pdu_offset += rdata.length;
1066 /* reset state->incoming_frag, there is no need to free it,
1067 * it will be reallocated to the right size the next time
1068 * it is used */
1069 state->incoming_frag.length = 0;
1071 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1072 /* make sure the pdu length is right now that we
1073 * have all the data available (alloc hint may
1074 * have allocated more than was actually used) */
1075 state->reply_pdu.length = state->reply_pdu_offset;
1076 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1077 rpccli_pipe_txt(talloc_tos(), state->cli),
1078 (unsigned)state->reply_pdu.length));
1079 tevent_req_done(req);
1080 return;
1083 subreq = get_complete_frag_send(state, state->ev, state->cli,
1084 &state->incoming_frag);
1085 if (subreq == NULL) {
1087 * TODO: do a real async disconnect ...
1089 * For now do it sync...
1091 TALLOC_FREE(state->cli->transport);
1093 if (tevent_req_nomem(subreq, req)) {
1094 return;
1096 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1099 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1100 struct ncacn_packet **pkt,
1101 DATA_BLOB *reply_pdu)
1103 struct rpc_api_pipe_state *state = tevent_req_data(
1104 req, struct rpc_api_pipe_state);
1105 NTSTATUS status;
1107 if (tevent_req_is_nterror(req, &status)) {
1108 return status;
1111 /* return data to caller and assign it ownership of memory */
1112 if (reply_pdu) {
1113 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1114 reply_pdu->length = state->reply_pdu.length;
1115 state->reply_pdu.length = 0;
1116 } else {
1117 data_blob_free(&state->reply_pdu);
1120 if (pkt) {
1121 *pkt = talloc_steal(mem_ctx, state->pkt);
1124 return NT_STATUS_OK;
1127 /*******************************************************************
1128 Creates NTLMSSP auth bind.
1129 ********************************************************************/
1131 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1132 TALLOC_CTX *mem_ctx,
1133 DATA_BLOB *auth_token,
1134 bool *client_hdr_signing)
1136 struct gensec_security *gensec_security;
1137 DATA_BLOB null_blob = data_blob_null;
1138 NTSTATUS status;
1140 gensec_security = cli->auth->auth_ctx;
1142 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1143 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1145 if (!NT_STATUS_IS_OK(status) &&
1146 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1148 return status;
1151 if (client_hdr_signing == NULL) {
1152 return status;
1155 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1156 *client_hdr_signing = false;
1157 return status;
1160 *client_hdr_signing = gensec_have_feature(gensec_security,
1161 GENSEC_FEATURE_SIGN_PKT_HEADER);
1163 return status;
1166 /*******************************************************************
1167 Creates the internals of a DCE/RPC bind request or alter context PDU.
1168 ********************************************************************/
1170 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1171 enum dcerpc_pkt_type ptype,
1172 uint32_t rpc_call_id,
1173 const struct ndr_syntax_id *abstract,
1174 const struct ndr_syntax_id *transfer,
1175 const DATA_BLOB *auth_info,
1176 bool client_hdr_signing,
1177 DATA_BLOB *blob)
1179 uint16_t auth_len = auth_info->length;
1180 NTSTATUS status;
1181 union dcerpc_payload u;
1182 struct dcerpc_ctx_list ctx_list;
1183 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1185 if (auth_len) {
1186 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1189 if (client_hdr_signing) {
1190 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1193 ctx_list.context_id = 0;
1194 ctx_list.num_transfer_syntaxes = 1;
1195 ctx_list.abstract_syntax = *abstract;
1196 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1198 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1199 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1200 u.bind.assoc_group_id = 0x0;
1201 u.bind.num_contexts = 1;
1202 u.bind.ctx_list = &ctx_list;
1203 u.bind.auth_info = *auth_info;
1205 status = dcerpc_push_ncacn_packet(mem_ctx,
1206 ptype, pfc_flags,
1207 auth_len,
1208 rpc_call_id,
1210 blob);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1213 return status;
1216 return NT_STATUS_OK;
1219 /*******************************************************************
1220 Creates a DCE/RPC bind request.
1221 ********************************************************************/
1223 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1224 struct rpc_pipe_client *cli,
1225 struct pipe_auth_data *auth,
1226 uint32_t rpc_call_id,
1227 const struct ndr_syntax_id *abstract,
1228 const struct ndr_syntax_id *transfer,
1229 DATA_BLOB *rpc_out)
1231 DATA_BLOB auth_token = data_blob_null;
1232 DATA_BLOB auth_info = data_blob_null;
1233 NTSTATUS ret = NT_STATUS_OK;
1235 switch (auth->auth_type) {
1236 case DCERPC_AUTH_TYPE_NONE:
1237 break;
1239 default:
1240 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1241 &auth_token,
1242 &auth->client_hdr_signing);
1244 if (!NT_STATUS_IS_OK(ret) &&
1245 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1246 return ret;
1248 break;
1251 if (auth_token.length != 0) {
1252 ret = dcerpc_push_dcerpc_auth(cli,
1253 auth->auth_type,
1254 auth->auth_level,
1255 0, /* auth_pad_length */
1256 auth->auth_context_id,
1257 &auth_token,
1258 &auth_info);
1259 if (!NT_STATUS_IS_OK(ret)) {
1260 return ret;
1262 data_blob_free(&auth_token);
1265 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1266 DCERPC_PKT_BIND,
1267 rpc_call_id,
1268 abstract,
1269 transfer,
1270 &auth_info,
1271 auth->client_hdr_signing,
1272 rpc_out);
1273 return ret;
1276 /*******************************************************************
1277 External interface.
1278 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1279 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1280 and deals with signing/sealing details.
1281 ********************************************************************/
1283 struct rpc_api_pipe_req_state {
1284 struct tevent_context *ev;
1285 struct rpc_pipe_client *cli;
1286 uint8_t op_num;
1287 uint32_t call_id;
1288 const DATA_BLOB *req_data;
1289 const struct GUID *object_uuid;
1290 uint32_t req_data_sent;
1291 DATA_BLOB req_trailer;
1292 uint32_t req_trailer_sent;
1293 bool verify_bitmask1;
1294 bool verify_pcontext;
1295 DATA_BLOB rpc_out;
1296 DATA_BLOB reply_pdu;
1299 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1300 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1301 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1302 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1303 bool *is_last_frag);
1305 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1306 struct tevent_context *ev,
1307 struct rpc_pipe_client *cli,
1308 uint8_t op_num,
1309 const struct GUID *object_uuid,
1310 const DATA_BLOB *req_data)
1312 struct tevent_req *req, *subreq;
1313 struct rpc_api_pipe_req_state *state;
1314 NTSTATUS status;
1315 bool is_last_frag;
1317 req = tevent_req_create(mem_ctx, &state,
1318 struct rpc_api_pipe_req_state);
1319 if (req == NULL) {
1320 return NULL;
1322 state->ev = ev;
1323 state->cli = cli;
1324 state->op_num = op_num;
1325 state->object_uuid = object_uuid;
1326 state->req_data = req_data;
1327 state->req_data_sent = 0;
1328 state->call_id = get_rpc_call_id();
1329 state->reply_pdu = data_blob_null;
1330 state->rpc_out = data_blob_null;
1332 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1333 + RPC_MAX_SIGN_SIZE) {
1334 /* Server is screwed up ! */
1335 status = NT_STATUS_INVALID_PARAMETER;
1336 goto post_status;
1339 status = prepare_verification_trailer(state);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 goto post_status;
1344 status = prepare_next_frag(state, &is_last_frag);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 goto post_status;
1349 if (is_last_frag) {
1350 subreq = rpc_api_pipe_send(state, ev, state->cli,
1351 &state->rpc_out,
1352 DCERPC_PKT_RESPONSE,
1353 state->call_id);
1354 if (subreq == NULL) {
1355 goto fail;
1357 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1358 } else {
1359 subreq = rpc_write_send(state, ev, cli->transport,
1360 state->rpc_out.data,
1361 state->rpc_out.length);
1362 if (subreq == NULL) {
1363 goto fail;
1365 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1366 req);
1368 return req;
1370 post_status:
1371 tevent_req_nterror(req, status);
1372 return tevent_req_post(req, ev);
1373 fail:
1374 TALLOC_FREE(req);
1375 return NULL;
1378 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1380 struct pipe_auth_data *a = state->cli->auth;
1381 struct dcerpc_sec_verification_trailer *t;
1382 struct dcerpc_sec_vt *c = NULL;
1383 struct ndr_push *ndr = NULL;
1384 enum ndr_err_code ndr_err;
1385 size_t align = 0;
1386 size_t pad = 0;
1388 if (a == NULL) {
1389 return NT_STATUS_OK;
1392 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1393 return NT_STATUS_OK;
1396 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1397 if (t == NULL) {
1398 return NT_STATUS_NO_MEMORY;
1401 if (!a->verified_bitmask1) {
1402 t->commands = talloc_realloc(t, t->commands,
1403 struct dcerpc_sec_vt,
1404 t->count.count + 1);
1405 if (t->commands == NULL) {
1406 return NT_STATUS_NO_MEMORY;
1408 c = &t->commands[t->count.count++];
1409 ZERO_STRUCTP(c);
1411 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1412 if (a->client_hdr_signing) {
1413 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1415 state->verify_bitmask1 = true;
1418 if (!state->cli->verified_pcontext) {
1419 t->commands = talloc_realloc(t, t->commands,
1420 struct dcerpc_sec_vt,
1421 t->count.count + 1);
1422 if (t->commands == NULL) {
1423 return NT_STATUS_NO_MEMORY;
1425 c = &t->commands[t->count.count++];
1426 ZERO_STRUCTP(c);
1428 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1429 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1430 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1432 state->verify_pcontext = true;
1435 if (!a->hdr_signing) {
1436 t->commands = talloc_realloc(t, t->commands,
1437 struct dcerpc_sec_vt,
1438 t->count.count + 1);
1439 if (t->commands == NULL) {
1440 return NT_STATUS_NO_MEMORY;
1442 c = &t->commands[t->count.count++];
1443 ZERO_STRUCTP(c);
1445 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1446 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1447 c->u.header2.drep[0] = DCERPC_DREP_LE;
1448 c->u.header2.drep[1] = 0;
1449 c->u.header2.drep[2] = 0;
1450 c->u.header2.drep[3] = 0;
1451 c->u.header2.call_id = state->call_id;
1452 c->u.header2.context_id = 0;
1453 c->u.header2.opnum = state->op_num;
1456 if (t->count.count == 0) {
1457 TALLOC_FREE(t);
1458 return NT_STATUS_OK;
1461 c = &t->commands[t->count.count - 1];
1462 c->command |= DCERPC_SEC_VT_COMMAND_END;
1464 if (DEBUGLEVEL >= 10) {
1465 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1468 ndr = ndr_push_init_ctx(state);
1469 if (ndr == NULL) {
1470 return NT_STATUS_NO_MEMORY;
1473 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1474 NDR_SCALARS | NDR_BUFFERS,
1476 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1477 return ndr_map_error2ntstatus(ndr_err);
1479 state->req_trailer = ndr_push_blob(ndr);
1481 align = state->req_data->length & 0x3;
1482 if (align > 0) {
1483 pad = 4 - align;
1485 if (pad > 0) {
1486 bool ok;
1487 uint8_t *p;
1488 const uint8_t zeros[4] = { 0, };
1490 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1491 if (!ok) {
1492 return NT_STATUS_NO_MEMORY;
1495 /* move the padding to the start */
1496 p = state->req_trailer.data;
1497 memmove(p + pad, p, state->req_trailer.length - pad);
1498 memset(p, 0, pad);
1501 return NT_STATUS_OK;
1504 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1505 bool *is_last_frag)
1507 size_t auth_len;
1508 size_t frag_len;
1509 uint8_t flags = 0;
1510 size_t pad_len;
1511 size_t data_left;
1512 size_t data_thistime;
1513 size_t trailer_left;
1514 size_t trailer_thistime = 0;
1515 size_t total_left;
1516 size_t total_thistime;
1517 NTSTATUS status;
1518 bool ok;
1519 union dcerpc_payload u;
1521 data_left = state->req_data->length - state->req_data_sent;
1522 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1523 total_left = data_left + trailer_left;
1524 if ((total_left < data_left) || (total_left < trailer_left)) {
1526 * overflow
1528 return NT_STATUS_INVALID_PARAMETER_MIX;
1531 status = dcerpc_guess_sizes(state->cli->auth,
1532 DCERPC_REQUEST_LENGTH, total_left,
1533 state->cli->max_xmit_frag,
1534 &total_thistime,
1535 &frag_len, &auth_len, &pad_len);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 return status;
1540 if (state->req_data_sent == 0) {
1541 flags = DCERPC_PFC_FLAG_FIRST;
1544 if (total_thistime == total_left) {
1545 flags |= DCERPC_PFC_FLAG_LAST;
1548 data_thistime = MIN(total_thistime, data_left);
1549 if (data_thistime < total_thistime) {
1550 trailer_thistime = total_thistime - data_thistime;
1553 data_blob_free(&state->rpc_out);
1555 ZERO_STRUCT(u.request);
1557 u.request.alloc_hint = total_left;
1558 u.request.context_id = 0;
1559 u.request.opnum = state->op_num;
1561 if (state->object_uuid) {
1562 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1563 u.request.object.object = *state->object_uuid;
1564 frag_len += ndr_size_GUID(state->object_uuid, 0);
1567 status = dcerpc_push_ncacn_packet(state,
1568 DCERPC_PKT_REQUEST,
1569 flags,
1570 auth_len,
1571 state->call_id,
1573 &state->rpc_out);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return status;
1578 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1579 * compute it right for requests because the auth trailer is missing
1580 * at this stage */
1581 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1583 if (data_thistime > 0) {
1584 /* Copy in the data. */
1585 ok = data_blob_append(NULL, &state->rpc_out,
1586 state->req_data->data + state->req_data_sent,
1587 data_thistime);
1588 if (!ok) {
1589 return NT_STATUS_NO_MEMORY;
1591 state->req_data_sent += data_thistime;
1594 if (trailer_thistime > 0) {
1595 /* Copy in the verification trailer. */
1596 ok = data_blob_append(NULL, &state->rpc_out,
1597 state->req_trailer.data + state->req_trailer_sent,
1598 trailer_thistime);
1599 if (!ok) {
1600 return NT_STATUS_NO_MEMORY;
1602 state->req_trailer_sent += trailer_thistime;
1605 switch (state->cli->auth->auth_level) {
1606 case DCERPC_AUTH_LEVEL_NONE:
1607 case DCERPC_AUTH_LEVEL_CONNECT:
1608 break;
1609 case DCERPC_AUTH_LEVEL_PACKET:
1610 case DCERPC_AUTH_LEVEL_INTEGRITY:
1611 case DCERPC_AUTH_LEVEL_PRIVACY:
1612 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1613 &state->rpc_out);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 return status;
1617 break;
1618 default:
1619 return NT_STATUS_INVALID_PARAMETER;
1622 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1624 return status;
1627 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1629 struct tevent_req *req = tevent_req_callback_data(
1630 subreq, struct tevent_req);
1631 struct rpc_api_pipe_req_state *state = tevent_req_data(
1632 req, struct rpc_api_pipe_req_state);
1633 NTSTATUS status;
1634 bool is_last_frag;
1636 status = rpc_write_recv(subreq);
1637 TALLOC_FREE(subreq);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 tevent_req_nterror(req, status);
1640 return;
1643 status = prepare_next_frag(state, &is_last_frag);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 tevent_req_nterror(req, status);
1646 return;
1649 if (is_last_frag) {
1650 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1651 &state->rpc_out,
1652 DCERPC_PKT_RESPONSE,
1653 state->call_id);
1654 if (tevent_req_nomem(subreq, req)) {
1655 return;
1657 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1658 } else {
1659 subreq = rpc_write_send(state, state->ev,
1660 state->cli->transport,
1661 state->rpc_out.data,
1662 state->rpc_out.length);
1663 if (tevent_req_nomem(subreq, req)) {
1664 return;
1666 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1667 req);
1671 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1673 struct tevent_req *req = tevent_req_callback_data(
1674 subreq, struct tevent_req);
1675 struct rpc_api_pipe_req_state *state = tevent_req_data(
1676 req, struct rpc_api_pipe_req_state);
1677 NTSTATUS status;
1679 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1680 TALLOC_FREE(subreq);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 tevent_req_nterror(req, status);
1683 return;
1686 if (state->cli->auth == NULL) {
1687 tevent_req_done(req);
1688 return;
1691 if (state->verify_bitmask1) {
1692 state->cli->auth->verified_bitmask1 = true;
1695 if (state->verify_pcontext) {
1696 state->cli->verified_pcontext = true;
1699 tevent_req_done(req);
1702 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1703 DATA_BLOB *reply_pdu)
1705 struct rpc_api_pipe_req_state *state = tevent_req_data(
1706 req, struct rpc_api_pipe_req_state);
1707 NTSTATUS status;
1709 if (tevent_req_is_nterror(req, &status)) {
1711 * We always have to initialize to reply pdu, even if there is
1712 * none. The rpccli_* caller routines expect this.
1714 *reply_pdu = data_blob_null;
1715 return status;
1718 /* return data to caller and assign it ownership of memory */
1719 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1720 reply_pdu->length = state->reply_pdu.length;
1721 state->reply_pdu.length = 0;
1723 return NT_STATUS_OK;
1726 /****************************************************************************
1727 Check the rpc bind acknowledge response.
1728 ****************************************************************************/
1730 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1731 const struct ndr_syntax_id *transfer)
1733 struct dcerpc_ack_ctx ctx;
1735 if (r->secondary_address_size == 0) {
1736 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1739 if (r->num_results < 1 || !r->ctx_list) {
1740 return false;
1743 ctx = r->ctx_list[0];
1745 /* check the transfer syntax */
1746 if ((ctx.syntax.if_version != transfer->if_version) ||
1747 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1748 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1749 return False;
1752 if (r->num_results != 0x1 || ctx.result != 0) {
1753 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1754 r->num_results, ctx.reason.value));
1757 DEBUG(5,("check_bind_response: accepted!\n"));
1758 return True;
1761 /*******************************************************************
1762 Creates a DCE/RPC bind authentication response.
1763 This is the packet that is sent back to the server once we
1764 have received a BIND-ACK, to finish the third leg of
1765 the authentication handshake.
1766 ********************************************************************/
1768 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1769 struct rpc_pipe_client *cli,
1770 struct pipe_auth_data *auth,
1771 uint32_t rpc_call_id,
1772 DATA_BLOB *pauth_blob,
1773 DATA_BLOB *rpc_out)
1775 NTSTATUS status;
1776 union dcerpc_payload u;
1778 u.auth3._pad = 0;
1780 status = dcerpc_push_dcerpc_auth(mem_ctx,
1781 auth->auth_type,
1782 auth->auth_level,
1783 0, /* auth_pad_length */
1784 auth->auth_context_id,
1785 pauth_blob,
1786 &u.auth3.auth_info);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 return status;
1791 status = dcerpc_push_ncacn_packet(mem_ctx,
1792 DCERPC_PKT_AUTH3,
1793 DCERPC_PFC_FLAG_FIRST |
1794 DCERPC_PFC_FLAG_LAST,
1795 pauth_blob->length,
1796 rpc_call_id,
1798 rpc_out);
1799 data_blob_free(&u.auth3.auth_info);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1802 return status;
1805 return NT_STATUS_OK;
1808 /*******************************************************************
1809 Creates a DCE/RPC bind alter context authentication request which
1810 may contain a spnego auth blobl
1811 ********************************************************************/
1813 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1814 struct pipe_auth_data *auth,
1815 uint32_t rpc_call_id,
1816 const struct ndr_syntax_id *abstract,
1817 const struct ndr_syntax_id *transfer,
1818 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1819 DATA_BLOB *rpc_out)
1821 DATA_BLOB auth_info;
1822 NTSTATUS status;
1824 status = dcerpc_push_dcerpc_auth(mem_ctx,
1825 auth->auth_type,
1826 auth->auth_level,
1827 0, /* auth_pad_length */
1828 auth->auth_context_id,
1829 pauth_blob,
1830 &auth_info);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 return status;
1835 status = create_bind_or_alt_ctx_internal(mem_ctx,
1836 DCERPC_PKT_ALTER,
1837 rpc_call_id,
1838 abstract,
1839 transfer,
1840 &auth_info,
1841 false, /* client_hdr_signing */
1842 rpc_out);
1843 data_blob_free(&auth_info);
1844 return status;
1847 /****************************************************************************
1848 Do an rpc bind.
1849 ****************************************************************************/
1851 struct rpc_pipe_bind_state {
1852 struct tevent_context *ev;
1853 struct rpc_pipe_client *cli;
1854 DATA_BLOB rpc_out;
1855 bool auth3;
1856 uint32_t rpc_call_id;
1859 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1860 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1861 struct rpc_pipe_bind_state *state,
1862 DATA_BLOB *credentials);
1863 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1864 struct rpc_pipe_bind_state *state,
1865 DATA_BLOB *credentials);
1867 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1868 struct tevent_context *ev,
1869 struct rpc_pipe_client *cli,
1870 struct pipe_auth_data *auth)
1872 struct tevent_req *req, *subreq;
1873 struct rpc_pipe_bind_state *state;
1874 NTSTATUS status;
1876 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1877 if (req == NULL) {
1878 return NULL;
1881 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1882 rpccli_pipe_txt(talloc_tos(), cli),
1883 (unsigned int)auth->auth_type,
1884 (unsigned int)auth->auth_level ));
1886 state->ev = ev;
1887 state->cli = cli;
1888 state->rpc_call_id = get_rpc_call_id();
1890 cli->auth = talloc_move(cli, &auth);
1892 /* Marshall the outgoing data. */
1893 status = create_rpc_bind_req(state, cli,
1894 cli->auth,
1895 state->rpc_call_id,
1896 &cli->abstract_syntax,
1897 &cli->transfer_syntax,
1898 &state->rpc_out);
1900 if (!NT_STATUS_IS_OK(status) &&
1901 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1902 goto post_status;
1905 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1906 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1907 if (subreq == NULL) {
1908 goto fail;
1910 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1911 return req;
1913 post_status:
1914 tevent_req_nterror(req, status);
1915 return tevent_req_post(req, ev);
1916 fail:
1917 TALLOC_FREE(req);
1918 return NULL;
1921 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1923 struct tevent_req *req = tevent_req_callback_data(
1924 subreq, struct tevent_req);
1925 struct rpc_pipe_bind_state *state = tevent_req_data(
1926 req, struct rpc_pipe_bind_state);
1927 struct pipe_auth_data *pauth = state->cli->auth;
1928 struct gensec_security *gensec_security;
1929 struct ncacn_packet *pkt = NULL;
1930 struct dcerpc_auth auth;
1931 DATA_BLOB auth_token = data_blob_null;
1932 NTSTATUS status;
1934 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1935 TALLOC_FREE(subreq);
1936 if (!NT_STATUS_IS_OK(status)) {
1937 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1938 rpccli_pipe_txt(talloc_tos(), state->cli),
1939 nt_errstr(status)));
1940 tevent_req_nterror(req, status);
1941 return;
1944 if (state->auth3) {
1945 tevent_req_done(req);
1946 return;
1949 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1950 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1951 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1952 return;
1955 if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1956 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1957 if (pauth->client_hdr_signing) {
1958 pauth->hdr_signing = true;
1963 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1965 switch(pauth->auth_type) {
1967 case DCERPC_AUTH_TYPE_NONE:
1968 /* Bind complete. */
1969 tevent_req_done(req);
1970 return;
1972 default:
1973 if (pkt->auth_length == 0) {
1974 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1975 return;
1978 /* get auth credentials */
1979 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1980 &pkt->u.bind_ack.auth_info,
1981 &auth, NULL, true);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1984 nt_errstr(status)));
1985 tevent_req_nterror(req, status);
1986 return;
1989 if (auth.auth_type != pauth->auth_type) {
1990 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1991 auth.auth_type, pauth->auth_type));
1992 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1993 return;
1996 if (auth.auth_level != pauth->auth_level) {
1997 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1998 auth.auth_level, pauth->auth_level));
1999 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2000 return;
2003 if (auth.auth_context_id != pauth->auth_context_id) {
2004 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
2005 (unsigned)auth.auth_context_id,
2006 (unsigned)pauth->auth_context_id));
2007 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2008 return;
2011 break;
2015 * For authenticated binds we may need to do 3 or 4 leg binds.
2018 switch(pauth->auth_type) {
2020 case DCERPC_AUTH_TYPE_NONE:
2021 /* Bind complete. */
2022 tevent_req_done(req);
2023 return;
2025 default:
2026 gensec_security = pauth->auth_ctx;
2029 status = gensec_update(gensec_security, state,
2030 auth.credentials, &auth_token);
2031 if (NT_STATUS_EQUAL(status,
2032 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2033 status = rpc_bind_next_send(req, state,
2034 &auth_token);
2035 } else if (NT_STATUS_IS_OK(status)) {
2036 if (pauth->hdr_signing) {
2037 gensec_want_feature(gensec_security,
2038 GENSEC_FEATURE_SIGN_PKT_HEADER);
2041 if (auth_token.length == 0) {
2042 /* Bind complete. */
2043 tevent_req_done(req);
2044 return;
2046 status = rpc_bind_finish_send(req, state,
2047 &auth_token);
2049 break;
2052 if (!NT_STATUS_IS_OK(status)) {
2053 tevent_req_nterror(req, status);
2055 return;
2058 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2059 struct rpc_pipe_bind_state *state,
2060 DATA_BLOB *auth_token)
2062 struct pipe_auth_data *auth = state->cli->auth;
2063 struct tevent_req *subreq;
2064 NTSTATUS status;
2066 /* Now prepare the alter context pdu. */
2067 data_blob_free(&state->rpc_out);
2069 status = create_rpc_alter_context(state, auth,
2070 state->rpc_call_id,
2071 &state->cli->abstract_syntax,
2072 &state->cli->transfer_syntax,
2073 auth_token,
2074 &state->rpc_out);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 return status;
2079 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2080 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2081 state->rpc_call_id);
2082 if (subreq == NULL) {
2083 return NT_STATUS_NO_MEMORY;
2085 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2086 return NT_STATUS_OK;
2089 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2090 struct rpc_pipe_bind_state *state,
2091 DATA_BLOB *auth_token)
2093 struct pipe_auth_data *auth = state->cli->auth;
2094 struct tevent_req *subreq;
2095 NTSTATUS status;
2097 state->auth3 = true;
2099 /* Now prepare the auth3 context pdu. */
2100 data_blob_free(&state->rpc_out);
2102 status = create_rpc_bind_auth3(state, state->cli, auth,
2103 state->rpc_call_id,
2104 auth_token,
2105 &state->rpc_out);
2106 if (!NT_STATUS_IS_OK(status)) {
2107 return status;
2110 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2111 &state->rpc_out, DCERPC_PKT_AUTH3,
2112 state->rpc_call_id);
2113 if (subreq == NULL) {
2114 return NT_STATUS_NO_MEMORY;
2116 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2117 return NT_STATUS_OK;
2120 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2122 return tevent_req_simple_recv_ntstatus(req);
2125 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2126 struct pipe_auth_data *auth)
2128 TALLOC_CTX *frame = talloc_stackframe();
2129 struct tevent_context *ev;
2130 struct tevent_req *req;
2131 NTSTATUS status = NT_STATUS_OK;
2133 ev = samba_tevent_context_init(frame);
2134 if (ev == NULL) {
2135 status = NT_STATUS_NO_MEMORY;
2136 goto fail;
2139 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2140 if (req == NULL) {
2141 status = NT_STATUS_NO_MEMORY;
2142 goto fail;
2145 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2146 goto fail;
2149 status = rpc_pipe_bind_recv(req);
2150 fail:
2151 TALLOC_FREE(frame);
2152 return status;
2155 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2157 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2158 unsigned int timeout)
2160 unsigned int old;
2162 if (rpc_cli->transport == NULL) {
2163 return RPCCLI_DEFAULT_TIMEOUT;
2166 if (rpc_cli->transport->set_timeout == NULL) {
2167 return RPCCLI_DEFAULT_TIMEOUT;
2170 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2171 if (old == 0) {
2172 return RPCCLI_DEFAULT_TIMEOUT;
2175 return old;
2178 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2180 if (rpc_cli == NULL) {
2181 return false;
2184 if (rpc_cli->transport == NULL) {
2185 return false;
2188 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2191 struct rpccli_bh_state {
2192 struct rpc_pipe_client *rpc_cli;
2195 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2197 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2198 struct rpccli_bh_state);
2200 return rpccli_is_connected(hs->rpc_cli);
2203 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2204 uint32_t timeout)
2206 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2207 struct rpccli_bh_state);
2209 return rpccli_set_timeout(hs->rpc_cli, timeout);
2212 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2213 enum dcerpc_AuthType *auth_type,
2214 enum dcerpc_AuthLevel *auth_level)
2216 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2217 struct rpccli_bh_state);
2219 if (hs->rpc_cli == NULL) {
2220 return;
2223 if (hs->rpc_cli->auth == NULL) {
2224 return;
2227 *auth_type = hs->rpc_cli->auth->auth_type;
2228 *auth_level = hs->rpc_cli->auth->auth_level;
2231 struct rpccli_bh_raw_call_state {
2232 DATA_BLOB in_data;
2233 DATA_BLOB out_data;
2234 uint32_t out_flags;
2237 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2239 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2240 struct tevent_context *ev,
2241 struct dcerpc_binding_handle *h,
2242 const struct GUID *object,
2243 uint32_t opnum,
2244 uint32_t in_flags,
2245 const uint8_t *in_data,
2246 size_t in_length)
2248 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2249 struct rpccli_bh_state);
2250 struct tevent_req *req;
2251 struct rpccli_bh_raw_call_state *state;
2252 bool ok;
2253 struct tevent_req *subreq;
2255 req = tevent_req_create(mem_ctx, &state,
2256 struct rpccli_bh_raw_call_state);
2257 if (req == NULL) {
2258 return NULL;
2260 state->in_data.data = discard_const_p(uint8_t, in_data);
2261 state->in_data.length = in_length;
2263 ok = rpccli_bh_is_connected(h);
2264 if (!ok) {
2265 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2266 return tevent_req_post(req, ev);
2269 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2270 opnum, object, &state->in_data);
2271 if (tevent_req_nomem(subreq, req)) {
2272 return tevent_req_post(req, ev);
2274 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2276 return req;
2279 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2281 struct tevent_req *req =
2282 tevent_req_callback_data(subreq,
2283 struct tevent_req);
2284 struct rpccli_bh_raw_call_state *state =
2285 tevent_req_data(req,
2286 struct rpccli_bh_raw_call_state);
2287 NTSTATUS status;
2289 state->out_flags = 0;
2291 /* TODO: support bigendian responses */
2293 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2294 TALLOC_FREE(subreq);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 tevent_req_nterror(req, status);
2297 return;
2300 tevent_req_done(req);
2303 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2304 TALLOC_CTX *mem_ctx,
2305 uint8_t **out_data,
2306 size_t *out_length,
2307 uint32_t *out_flags)
2309 struct rpccli_bh_raw_call_state *state =
2310 tevent_req_data(req,
2311 struct rpccli_bh_raw_call_state);
2312 NTSTATUS status;
2314 if (tevent_req_is_nterror(req, &status)) {
2315 tevent_req_received(req);
2316 return status;
2319 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2320 *out_length = state->out_data.length;
2321 *out_flags = state->out_flags;
2322 tevent_req_received(req);
2323 return NT_STATUS_OK;
2326 struct rpccli_bh_disconnect_state {
2327 uint8_t _dummy;
2330 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2331 struct tevent_context *ev,
2332 struct dcerpc_binding_handle *h)
2334 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2335 struct rpccli_bh_state);
2336 struct tevent_req *req;
2337 struct rpccli_bh_disconnect_state *state;
2338 bool ok;
2340 req = tevent_req_create(mem_ctx, &state,
2341 struct rpccli_bh_disconnect_state);
2342 if (req == NULL) {
2343 return NULL;
2346 ok = rpccli_bh_is_connected(h);
2347 if (!ok) {
2348 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2349 return tevent_req_post(req, ev);
2353 * TODO: do a real async disconnect ...
2355 * For now we do it sync...
2357 TALLOC_FREE(hs->rpc_cli->transport);
2358 hs->rpc_cli = NULL;
2360 tevent_req_done(req);
2361 return tevent_req_post(req, ev);
2364 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2366 NTSTATUS status;
2368 if (tevent_req_is_nterror(req, &status)) {
2369 tevent_req_received(req);
2370 return status;
2373 tevent_req_received(req);
2374 return NT_STATUS_OK;
2377 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2379 return true;
2382 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2383 int ndr_flags,
2384 const void *_struct_ptr,
2385 const struct ndr_interface_call *call)
2387 void *struct_ptr = discard_const(_struct_ptr);
2389 if (DEBUGLEVEL < 10) {
2390 return;
2393 if (ndr_flags & NDR_IN) {
2394 ndr_print_function_debug(call->ndr_print,
2395 call->name,
2396 ndr_flags,
2397 struct_ptr);
2399 if (ndr_flags & NDR_OUT) {
2400 ndr_print_function_debug(call->ndr_print,
2401 call->name,
2402 ndr_flags,
2403 struct_ptr);
2407 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2408 .name = "rpccli",
2409 .is_connected = rpccli_bh_is_connected,
2410 .set_timeout = rpccli_bh_set_timeout,
2411 .auth_info = rpccli_bh_auth_info,
2412 .raw_call_send = rpccli_bh_raw_call_send,
2413 .raw_call_recv = rpccli_bh_raw_call_recv,
2414 .disconnect_send = rpccli_bh_disconnect_send,
2415 .disconnect_recv = rpccli_bh_disconnect_recv,
2417 .ref_alloc = rpccli_bh_ref_alloc,
2418 .do_ndr_print = rpccli_bh_do_ndr_print,
2421 /* initialise a rpc_pipe_client binding handle */
2422 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2423 const struct GUID *object,
2424 const struct ndr_interface_table *table)
2426 struct dcerpc_binding_handle *h;
2427 struct rpccli_bh_state *hs;
2429 h = dcerpc_binding_handle_create(c,
2430 &rpccli_bh_ops,
2431 object,
2432 table,
2433 &hs,
2434 struct rpccli_bh_state,
2435 __location__);
2436 if (h == NULL) {
2437 return NULL;
2439 hs->rpc_cli = c;
2441 return h;
2444 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2445 struct pipe_auth_data **presult)
2447 struct pipe_auth_data *result;
2448 struct auth_generic_state *auth_generic_ctx;
2449 NTSTATUS status;
2451 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2452 if (result == NULL) {
2453 return NT_STATUS_NO_MEMORY;
2456 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2457 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2458 result->auth_context_id = 0;
2460 status = auth_generic_client_prepare(result,
2461 &auth_generic_ctx);
2462 if (!NT_STATUS_IS_OK(status)) {
2463 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2464 nt_errstr(status)));
2467 status = auth_generic_set_username(auth_generic_ctx, "");
2468 if (!NT_STATUS_IS_OK(status)) {
2469 DEBUG(1, ("Failed to set username: %s\n",
2470 nt_errstr(status)));
2473 status = auth_generic_set_domain(auth_generic_ctx, "");
2474 if (!NT_STATUS_IS_OK(status)) {
2475 DEBUG(1, ("Failed to set domain: %s\n",
2476 nt_errstr(status)));
2477 return status;
2480 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2481 auth_generic_ctx->credentials);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2484 nt_errstr(status)));
2485 return status;
2487 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2488 auth_generic_ctx->credentials = NULL;
2490 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2491 talloc_free(auth_generic_ctx);
2492 *presult = result;
2493 return NT_STATUS_OK;
2496 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2497 enum dcerpc_AuthType auth_type,
2498 enum dcerpc_AuthLevel auth_level,
2499 const char *server,
2500 const char *target_service,
2501 const char *domain,
2502 const char *username,
2503 const char *password,
2504 enum credentials_use_kerberos use_kerberos,
2505 struct netlogon_creds_CredentialState *creds,
2506 struct pipe_auth_data **presult)
2508 struct auth_generic_state *auth_generic_ctx;
2509 struct pipe_auth_data *result;
2510 NTSTATUS status;
2512 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2513 if (result == NULL) {
2514 return NT_STATUS_NO_MEMORY;
2517 result->auth_type = auth_type;
2518 result->auth_level = auth_level;
2519 result->auth_context_id = 1;
2521 status = auth_generic_client_prepare(result,
2522 &auth_generic_ctx);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 goto fail;
2527 status = auth_generic_set_username(auth_generic_ctx, username);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 goto fail;
2532 status = auth_generic_set_domain(auth_generic_ctx, domain);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 goto fail;
2537 status = auth_generic_set_password(auth_generic_ctx, password);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 goto fail;
2542 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 goto fail;
2547 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 goto fail;
2552 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2553 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2555 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 goto fail;
2560 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2561 talloc_free(auth_generic_ctx);
2562 *presult = result;
2563 return NT_STATUS_OK;
2565 fail:
2566 TALLOC_FREE(result);
2567 return status;
2570 /* This routine steals the creds pointer that is passed in */
2571 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2572 enum dcerpc_AuthType auth_type,
2573 enum dcerpc_AuthLevel auth_level,
2574 const char *server,
2575 const char *target_service,
2576 struct cli_credentials *creds,
2577 struct pipe_auth_data **presult)
2579 struct auth_generic_state *auth_generic_ctx;
2580 struct pipe_auth_data *result;
2581 NTSTATUS status;
2583 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2584 if (result == NULL) {
2585 return NT_STATUS_NO_MEMORY;
2588 result->auth_type = auth_type;
2589 result->auth_level = auth_level;
2590 result->auth_context_id = 1;
2592 status = auth_generic_client_prepare(result,
2593 &auth_generic_ctx);
2594 if (!NT_STATUS_IS_OK(status)) {
2595 goto fail;
2598 status = auth_generic_set_creds(auth_generic_ctx, creds);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 goto fail;
2603 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 goto fail;
2608 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 goto fail;
2613 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 goto fail;
2618 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2619 talloc_free(auth_generic_ctx);
2620 *presult = result;
2621 return NT_STATUS_OK;
2623 fail:
2624 TALLOC_FREE(result);
2625 return status;
2628 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2629 struct pipe_auth_data **presult)
2631 return rpccli_generic_bind_data(mem_ctx,
2632 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2633 DCERPC_AUTH_LEVEL_CONNECT,
2634 NULL, /* server */
2635 "host", /* target_service */
2636 NAME_NT_AUTHORITY, /* domain */
2637 "SYSTEM",
2638 NULL, /* password */
2639 CRED_DONT_USE_KERBEROS,
2640 NULL, /* netlogon_creds_CredentialState */
2641 presult);
2645 * Create an rpc pipe client struct, connecting to a tcp port.
2647 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2648 const struct sockaddr_storage *ss_addr,
2649 uint16_t port,
2650 const struct ndr_interface_table *table,
2651 struct rpc_pipe_client **presult)
2653 struct rpc_pipe_client *result;
2654 struct sockaddr_storage addr;
2655 NTSTATUS status;
2656 int fd;
2658 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2659 if (result == NULL) {
2660 return NT_STATUS_NO_MEMORY;
2663 result->abstract_syntax = table->syntax_id;
2664 result->transfer_syntax = ndr_transfer_syntax_ndr;
2666 result->desthost = talloc_strdup(result, host);
2667 result->srv_name_slash = talloc_asprintf_strupper_m(
2668 result, "\\\\%s", result->desthost);
2669 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2670 status = NT_STATUS_NO_MEMORY;
2671 goto fail;
2674 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2676 if (ss_addr == NULL) {
2677 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2678 status = NT_STATUS_NOT_FOUND;
2679 goto fail;
2681 } else {
2682 addr = *ss_addr;
2685 status = open_socket_out(&addr, port, 60*1000, &fd);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 goto fail;
2689 set_socket_options(fd, lp_socket_options());
2691 status = rpc_transport_sock_init(result, fd, &result->transport);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 close(fd);
2694 goto fail;
2697 result->transport->transport = NCACN_IP_TCP;
2699 result->binding_handle = rpccli_bh_create(result, NULL, table);
2700 if (result->binding_handle == NULL) {
2701 TALLOC_FREE(result);
2702 return NT_STATUS_NO_MEMORY;
2705 *presult = result;
2706 return NT_STATUS_OK;
2708 fail:
2709 TALLOC_FREE(result);
2710 return status;
2714 * Determine the tcp port on which a dcerpc interface is listening
2715 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2716 * target host.
2718 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2719 const struct sockaddr_storage *addr,
2720 const struct ndr_interface_table *table,
2721 uint16_t *pport)
2723 NTSTATUS status;
2724 struct rpc_pipe_client *epm_pipe = NULL;
2725 struct dcerpc_binding_handle *epm_handle = NULL;
2726 struct pipe_auth_data *auth = NULL;
2727 struct dcerpc_binding *map_binding = NULL;
2728 struct dcerpc_binding *res_binding = NULL;
2729 enum dcerpc_transport_t transport;
2730 const char *endpoint = NULL;
2731 struct epm_twr_t *map_tower = NULL;
2732 struct epm_twr_t *res_towers = NULL;
2733 struct policy_handle *entry_handle = NULL;
2734 uint32_t num_towers = 0;
2735 uint32_t max_towers = 1;
2736 struct epm_twr_p_t towers;
2737 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2738 uint32_t result = 0;
2740 if (pport == NULL) {
2741 status = NT_STATUS_INVALID_PARAMETER;
2742 goto done;
2745 if (ndr_syntax_id_equal(&table->syntax_id,
2746 &ndr_table_epmapper.syntax_id)) {
2747 *pport = 135;
2748 status = NT_STATUS_OK;
2749 goto done;
2752 /* open the connection to the endpoint mapper */
2753 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2754 &ndr_table_epmapper,
2755 &epm_pipe);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 goto done;
2760 epm_handle = epm_pipe->binding_handle;
2762 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 goto done;
2767 status = rpc_pipe_bind(epm_pipe, auth);
2768 if (!NT_STATUS_IS_OK(status)) {
2769 goto done;
2772 /* create tower for asking the epmapper */
2774 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2775 &map_binding);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 goto done;
2780 status = dcerpc_binding_set_abstract_syntax(map_binding,
2781 &table->syntax_id);
2782 if (!NT_STATUS_IS_OK(status)) {
2783 goto done;
2786 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2787 if (map_tower == NULL) {
2788 status = NT_STATUS_NO_MEMORY;
2789 goto done;
2792 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2793 &(map_tower->tower));
2794 if (!NT_STATUS_IS_OK(status)) {
2795 goto done;
2798 /* allocate further parameters for the epm_Map call */
2800 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2801 if (res_towers == NULL) {
2802 status = NT_STATUS_NO_MEMORY;
2803 goto done;
2805 towers.twr = res_towers;
2807 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2808 if (entry_handle == NULL) {
2809 status = NT_STATUS_NO_MEMORY;
2810 goto done;
2813 /* ask the endpoint mapper for the port */
2815 status = dcerpc_epm_Map(epm_handle,
2816 tmp_ctx,
2817 discard_const_p(struct GUID,
2818 &(table->syntax_id.uuid)),
2819 map_tower,
2820 entry_handle,
2821 max_towers,
2822 &num_towers,
2823 &towers,
2824 &result);
2826 if (!NT_STATUS_IS_OK(status)) {
2827 goto done;
2830 if (result != EPMAPPER_STATUS_OK) {
2831 status = NT_STATUS_UNSUCCESSFUL;
2832 goto done;
2835 if (num_towers != 1) {
2836 status = NT_STATUS_UNSUCCESSFUL;
2837 goto done;
2840 /* extract the port from the answer */
2842 status = dcerpc_binding_from_tower(tmp_ctx,
2843 &(towers.twr->tower),
2844 &res_binding);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 goto done;
2849 transport = dcerpc_binding_get_transport(res_binding);
2850 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2852 /* are further checks here necessary? */
2853 if (transport != NCACN_IP_TCP) {
2854 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2855 goto done;
2858 if (endpoint == NULL) {
2859 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2860 goto done;
2863 *pport = (uint16_t)atoi(endpoint);
2865 done:
2866 TALLOC_FREE(tmp_ctx);
2867 return status;
2871 * Create a rpc pipe client struct, connecting to a host via tcp.
2872 * The port is determined by asking the endpoint mapper on the given
2873 * host.
2875 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2876 const struct sockaddr_storage *addr,
2877 const struct ndr_interface_table *table,
2878 struct rpc_pipe_client **presult)
2880 NTSTATUS status;
2881 uint16_t port = 0;
2883 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 return status;
2888 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2889 table, presult);
2892 /********************************************************************
2893 Create a rpc pipe client struct, connecting to a unix domain socket
2894 ********************************************************************/
2895 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2896 const struct ndr_interface_table *table,
2897 struct rpc_pipe_client **presult)
2899 struct rpc_pipe_client *result;
2900 struct sockaddr_un addr;
2901 NTSTATUS status;
2902 int fd;
2903 socklen_t salen;
2905 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2906 if (result == NULL) {
2907 return NT_STATUS_NO_MEMORY;
2910 result->abstract_syntax = table->syntax_id;
2911 result->transfer_syntax = ndr_transfer_syntax_ndr;
2913 result->desthost = get_myname(result);
2914 result->srv_name_slash = talloc_asprintf_strupper_m(
2915 result, "\\\\%s", result->desthost);
2916 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2917 status = NT_STATUS_NO_MEMORY;
2918 goto fail;
2921 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2923 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2924 if (fd == -1) {
2925 status = map_nt_error_from_unix(errno);
2926 goto fail;
2929 ZERO_STRUCT(addr);
2930 addr.sun_family = AF_UNIX;
2931 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2932 salen = sizeof(struct sockaddr_un);
2934 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2935 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2936 strerror(errno)));
2937 close(fd);
2938 return map_nt_error_from_unix(errno);
2941 status = rpc_transport_sock_init(result, fd, &result->transport);
2942 if (!NT_STATUS_IS_OK(status)) {
2943 close(fd);
2944 goto fail;
2947 result->transport->transport = NCALRPC;
2949 result->binding_handle = rpccli_bh_create(result, NULL, table);
2950 if (result->binding_handle == NULL) {
2951 TALLOC_FREE(result);
2952 return NT_STATUS_NO_MEMORY;
2955 *presult = result;
2956 return NT_STATUS_OK;
2958 fail:
2959 TALLOC_FREE(result);
2960 return status;
2963 struct rpc_pipe_client_np_ref {
2964 struct cli_state *cli;
2965 struct rpc_pipe_client *pipe;
2968 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2970 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2971 return 0;
2974 /****************************************************************************
2975 Open a named pipe over SMB to a remote server.
2977 * CAVEAT CALLER OF THIS FUNCTION:
2978 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2979 * so be sure that this function is called AFTER any structure (vs pointer)
2980 * assignment of the cli. In particular, libsmbclient does structure
2981 * assignments of cli, which invalidates the data in the returned
2982 * rpc_pipe_client if this function is called before the structure assignment
2983 * of cli.
2985 ****************************************************************************/
2987 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2988 const struct ndr_interface_table *table,
2989 struct rpc_pipe_client **presult)
2991 struct rpc_pipe_client *result;
2992 NTSTATUS status;
2993 struct rpc_pipe_client_np_ref *np_ref;
2995 /* sanity check to protect against crashes */
2997 if ( !cli ) {
2998 return NT_STATUS_INVALID_HANDLE;
3001 result = talloc_zero(NULL, struct rpc_pipe_client);
3002 if (result == NULL) {
3003 return NT_STATUS_NO_MEMORY;
3006 result->abstract_syntax = table->syntax_id;
3007 result->transfer_syntax = ndr_transfer_syntax_ndr;
3008 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
3009 result->srv_name_slash = talloc_asprintf_strupper_m(
3010 result, "\\\\%s", result->desthost);
3012 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3014 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3015 TALLOC_FREE(result);
3016 return NT_STATUS_NO_MEMORY;
3019 status = rpc_transport_np_init(result, cli, table,
3020 &result->transport);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 TALLOC_FREE(result);
3023 return status;
3026 result->transport->transport = NCACN_NP;
3028 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3029 if (np_ref == NULL) {
3030 TALLOC_FREE(result);
3031 return NT_STATUS_NO_MEMORY;
3033 np_ref->cli = cli;
3034 np_ref->pipe = result;
3036 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3037 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3039 result->binding_handle = rpccli_bh_create(result, NULL, table);
3040 if (result->binding_handle == NULL) {
3041 TALLOC_FREE(result);
3042 return NT_STATUS_NO_MEMORY;
3045 *presult = result;
3046 return NT_STATUS_OK;
3049 /****************************************************************************
3050 Open a pipe to a remote server.
3051 ****************************************************************************/
3053 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3054 enum dcerpc_transport_t transport,
3055 const struct ndr_interface_table *table,
3056 struct rpc_pipe_client **presult)
3058 switch (transport) {
3059 case NCACN_IP_TCP:
3060 return rpc_pipe_open_tcp(NULL,
3061 smbXcli_conn_remote_name(cli->conn),
3062 smbXcli_conn_remote_sockaddr(cli->conn),
3063 table, presult);
3064 case NCACN_NP:
3065 return rpc_pipe_open_np(cli, table, presult);
3066 default:
3067 return NT_STATUS_NOT_IMPLEMENTED;
3071 /****************************************************************************
3072 Open a named pipe to an SMB server and bind anonymously.
3073 ****************************************************************************/
3075 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3076 enum dcerpc_transport_t transport,
3077 const struct ndr_interface_table *table,
3078 struct rpc_pipe_client **presult)
3080 struct rpc_pipe_client *result;
3081 struct pipe_auth_data *auth;
3082 NTSTATUS status;
3084 status = cli_rpc_pipe_open(cli, transport, table, &result);
3085 if (!NT_STATUS_IS_OK(status)) {
3086 return status;
3089 status = rpccli_anon_bind_data(result, &auth);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3092 nt_errstr(status)));
3093 TALLOC_FREE(result);
3094 return status;
3098 * This is a bit of an abstraction violation due to the fact that an
3099 * anonymous bind on an authenticated SMB inherits the user/domain
3100 * from the enclosing SMB creds
3103 if (transport == NCACN_NP) {
3104 struct smbXcli_session *session;
3106 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3107 session = cli->smb2.session;
3108 } else {
3109 session = cli->smb1.session;
3112 status = smbXcli_session_application_key(session, auth,
3113 &auth->transport_session_key);
3114 if (!NT_STATUS_IS_OK(status)) {
3115 auth->transport_session_key = data_blob_null;
3119 status = rpc_pipe_bind(result, auth);
3120 if (!NT_STATUS_IS_OK(status)) {
3121 int lvl = 0;
3122 if (ndr_syntax_id_equal(&table->syntax_id,
3123 &ndr_table_dssetup.syntax_id)) {
3124 /* non AD domains just don't have this pipe, avoid
3125 * level 0 statement in that case - gd */
3126 lvl = 3;
3128 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3129 "%s failed with error %s\n",
3130 table->name,
3131 nt_errstr(status) ));
3132 TALLOC_FREE(result);
3133 return status;
3136 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3137 "%s and bound anonymously.\n",
3138 table->name,
3139 result->desthost));
3141 *presult = result;
3142 return NT_STATUS_OK;
3145 /****************************************************************************
3146 ****************************************************************************/
3148 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3149 const struct ndr_interface_table *table,
3150 struct rpc_pipe_client **presult)
3152 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3153 table, presult);
3156 /****************************************************************************
3157 Open a named pipe to an SMB server and bind using the mech specified
3159 This routine references the creds pointer that is passed in
3160 ****************************************************************************/
3162 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3163 const struct ndr_interface_table *table,
3164 enum dcerpc_transport_t transport,
3165 enum dcerpc_AuthType auth_type,
3166 enum dcerpc_AuthLevel auth_level,
3167 const char *server,
3168 struct cli_credentials *creds,
3169 struct rpc_pipe_client **presult)
3171 struct rpc_pipe_client *result;
3172 struct pipe_auth_data *auth = NULL;
3173 const char *target_service = table->authservices->names[0];
3175 NTSTATUS status;
3177 status = cli_rpc_pipe_open(cli, transport, table, &result);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 return status;
3182 status = rpccli_generic_bind_data_from_creds(result,
3183 auth_type, auth_level,
3184 server, target_service,
3185 creds,
3186 &auth);
3187 if (!NT_STATUS_IS_OK(status)) {
3188 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3189 nt_errstr(status)));
3190 goto err;
3193 status = rpc_pipe_bind(result, auth);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3196 nt_errstr(status) ));
3197 goto err;
3200 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3201 "machine %s and bound as user %s.\n", table->name,
3202 result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3204 *presult = result;
3205 return NT_STATUS_OK;
3207 err:
3209 TALLOC_FREE(result);
3210 return status;
3213 /****************************************************************************
3214 Open a named pipe to an SMB server and bind using the mech specified
3216 This routine steals the creds pointer that is passed in
3217 ****************************************************************************/
3219 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3220 const struct ndr_interface_table *table,
3221 enum dcerpc_transport_t transport,
3222 enum credentials_use_kerberos use_kerberos,
3223 enum dcerpc_AuthType auth_type,
3224 enum dcerpc_AuthLevel auth_level,
3225 const char *server,
3226 const char *domain,
3227 const char *username,
3228 const char *password,
3229 struct rpc_pipe_client **presult)
3231 struct rpc_pipe_client *result;
3232 struct pipe_auth_data *auth = NULL;
3233 const char *target_service = table->authservices->names[0];
3235 NTSTATUS status;
3237 status = cli_rpc_pipe_open(cli, transport, table, &result);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 return status;
3242 status = rpccli_generic_bind_data(result,
3243 auth_type, auth_level,
3244 server, target_service,
3245 domain, username, password,
3246 CRED_AUTO_USE_KERBEROS,
3247 NULL,
3248 &auth);
3249 if (!NT_STATUS_IS_OK(status)) {
3250 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3251 nt_errstr(status)));
3252 goto err;
3255 status = rpc_pipe_bind(result, auth);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3258 nt_errstr(status) ));
3259 goto err;
3262 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3263 "machine %s and bound as user %s\\%s.\n", table->name,
3264 result->desthost, domain, username));
3266 *presult = result;
3267 return NT_STATUS_OK;
3269 err:
3271 TALLOC_FREE(result);
3272 return status;
3275 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3276 const struct ndr_interface_table *table,
3277 enum dcerpc_transport_t transport,
3278 struct cli_credentials *cli_creds,
3279 struct netlogon_creds_cli_context *netlogon_creds,
3280 struct rpc_pipe_client **_rpccli)
3282 struct rpc_pipe_client *rpccli;
3283 struct pipe_auth_data *rpcauth;
3284 const char *target_service = table->authservices->names[0];
3285 struct netlogon_creds_CredentialState *ncreds = NULL;
3286 enum dcerpc_AuthLevel auth_level;
3287 NTSTATUS status;
3288 int rpc_pipe_bind_dbglvl = 0;
3290 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3291 if (!NT_STATUS_IS_OK(status)) {
3292 return status;
3295 status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3298 nt_errstr(status)));
3299 TALLOC_FREE(rpccli);
3300 return status;
3303 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3305 cli_credentials_set_netlogon_creds(cli_creds, ncreds);
3307 status = rpccli_generic_bind_data_from_creds(rpccli,
3308 DCERPC_AUTH_TYPE_SCHANNEL,
3309 auth_level,
3310 rpccli->desthost,
3311 target_service,
3312 cli_creds,
3313 &rpcauth);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3316 nt_errstr(status)));
3317 TALLOC_FREE(rpccli);
3318 return status;
3321 status = rpc_pipe_bind(rpccli, rpcauth);
3322 cli_credentials_set_netlogon_creds(cli_creds, NULL);
3323 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3324 rpc_pipe_bind_dbglvl = 1;
3325 netlogon_creds_cli_delete(netlogon_creds, &ncreds);
3327 if (!NT_STATUS_IS_OK(status)) {
3328 DEBUG(rpc_pipe_bind_dbglvl,
3329 ("%s: rpc_pipe_bind failed with error %s\n",
3330 __func__, nt_errstr(status)));
3331 TALLOC_FREE(rpccli);
3332 return status;
3335 TALLOC_FREE(ncreds);
3337 if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3338 goto done;
3341 status = netlogon_creds_cli_check(netlogon_creds,
3342 rpccli->binding_handle);
3343 if (!NT_STATUS_IS_OK(status)) {
3344 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3345 nt_errstr(status)));
3346 TALLOC_FREE(rpccli);
3347 return status;
3351 done:
3352 DEBUG(10,("%s: opened pipe %s to machine %s "
3353 "for domain %s and bound using schannel.\n",
3354 __func__, table->name,
3355 rpccli->desthost, cli_credentials_get_domain(cli_creds)));
3357 *_rpccli = rpccli;
3358 return NT_STATUS_OK;
3361 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3362 struct rpc_pipe_client *cli,
3363 DATA_BLOB *session_key)
3365 NTSTATUS status;
3366 struct pipe_auth_data *a;
3367 struct gensec_security *gensec_security;
3368 DATA_BLOB sk = data_blob_null;
3369 bool make_dup = false;
3371 if (!session_key || !cli) {
3372 return NT_STATUS_INVALID_PARAMETER;
3375 a = cli->auth;
3377 if (a == NULL) {
3378 return NT_STATUS_INVALID_PARAMETER;
3381 switch (cli->auth->auth_type) {
3382 case DCERPC_AUTH_TYPE_NONE:
3383 sk = data_blob_const(a->transport_session_key.data,
3384 a->transport_session_key.length);
3385 make_dup = true;
3386 break;
3387 default:
3388 gensec_security = a->auth_ctx;
3389 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3390 if (!NT_STATUS_IS_OK(status)) {
3391 return status;
3393 make_dup = false;
3394 break;
3397 if (!sk.data) {
3398 return NT_STATUS_NO_USER_SESSION_KEY;
3401 if (make_dup) {
3402 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3403 } else {
3404 *session_key = sk;
3407 return NT_STATUS_OK;