CVE-2013-4408:s4:dcerpc_sock: check for invalid frag_len within sock_complete_packet()
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob0bd768f9c2a092179b9f95ae652162b5919a715e
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_schannel.h"
26 #include "../librpc/gen_ndr/ndr_dssetup.h"
27 #include "../libcli/auth/schannel.h"
28 #include "../libcli/auth/spnego.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "auth_generic.h"
31 #include "librpc/gen_ndr/ndr_dcerpc.h"
32 #include "librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "rpc_dce.h"
35 #include "cli_pipe.h"
36 #include "libsmb/libsmb.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/credentials/credentials.h"
39 #include "../libcli/smb/smbXcli_base.h"
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_RPC_CLI
44 /********************************************************************
45 Pipe description for a DEBUG
46 ********************************************************************/
47 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
48 struct rpc_pipe_client *cli)
50 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
51 if (result == NULL) {
52 return "pipe";
54 return result;
57 /********************************************************************
58 Rpc pipe call id.
59 ********************************************************************/
61 static uint32 get_rpc_call_id(void)
63 static uint32 call_id = 0;
64 return ++call_id;
67 /*******************************************************************
68 Use SMBreadX to get rest of one fragment's worth of rpc data.
69 Reads the whole size or give an error message
70 ********************************************************************/
72 struct rpc_read_state {
73 struct event_context *ev;
74 struct rpc_cli_transport *transport;
75 uint8_t *data;
76 size_t size;
77 size_t num_read;
80 static void rpc_read_done(struct tevent_req *subreq);
82 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
83 struct event_context *ev,
84 struct rpc_cli_transport *transport,
85 uint8_t *data, size_t size)
87 struct tevent_req *req, *subreq;
88 struct rpc_read_state *state;
90 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
91 if (req == NULL) {
92 return NULL;
94 state->ev = ev;
95 state->transport = transport;
96 state->data = data;
97 state->size = size;
98 state->num_read = 0;
100 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
102 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
103 transport->priv);
104 if (subreq == NULL) {
105 goto fail;
107 tevent_req_set_callback(subreq, rpc_read_done, req);
108 return req;
110 fail:
111 TALLOC_FREE(req);
112 return NULL;
115 static void rpc_read_done(struct tevent_req *subreq)
117 struct tevent_req *req = tevent_req_callback_data(
118 subreq, struct tevent_req);
119 struct rpc_read_state *state = tevent_req_data(
120 req, struct rpc_read_state);
121 NTSTATUS status;
122 ssize_t received;
124 status = state->transport->read_recv(subreq, &received);
125 TALLOC_FREE(subreq);
126 if (!NT_STATUS_IS_OK(status)) {
127 tevent_req_nterror(req, status);
128 return;
131 state->num_read += received;
132 if (state->num_read == state->size) {
133 tevent_req_done(req);
134 return;
137 subreq = state->transport->read_send(state, state->ev,
138 state->data + state->num_read,
139 state->size - state->num_read,
140 state->transport->priv);
141 if (tevent_req_nomem(subreq, req)) {
142 return;
144 tevent_req_set_callback(subreq, rpc_read_done, req);
147 static NTSTATUS rpc_read_recv(struct tevent_req *req)
149 return tevent_req_simple_recv_ntstatus(req);
152 struct rpc_write_state {
153 struct event_context *ev;
154 struct rpc_cli_transport *transport;
155 const uint8_t *data;
156 size_t size;
157 size_t num_written;
160 static void rpc_write_done(struct tevent_req *subreq);
162 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
163 struct event_context *ev,
164 struct rpc_cli_transport *transport,
165 const uint8_t *data, size_t size)
167 struct tevent_req *req, *subreq;
168 struct rpc_write_state *state;
170 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
171 if (req == NULL) {
172 return NULL;
174 state->ev = ev;
175 state->transport = transport;
176 state->data = data;
177 state->size = size;
178 state->num_written = 0;
180 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
182 subreq = transport->write_send(state, ev, data, size, transport->priv);
183 if (subreq == NULL) {
184 goto fail;
186 tevent_req_set_callback(subreq, rpc_write_done, req);
187 return req;
188 fail:
189 TALLOC_FREE(req);
190 return NULL;
193 static void rpc_write_done(struct tevent_req *subreq)
195 struct tevent_req *req = tevent_req_callback_data(
196 subreq, struct tevent_req);
197 struct rpc_write_state *state = tevent_req_data(
198 req, struct rpc_write_state);
199 NTSTATUS status;
200 ssize_t written;
202 status = state->transport->write_recv(subreq, &written);
203 TALLOC_FREE(subreq);
204 if (!NT_STATUS_IS_OK(status)) {
205 tevent_req_nterror(req, status);
206 return;
209 state->num_written += written;
211 if (state->num_written == state->size) {
212 tevent_req_done(req);
213 return;
216 subreq = state->transport->write_send(state, state->ev,
217 state->data + state->num_written,
218 state->size - state->num_written,
219 state->transport->priv);
220 if (tevent_req_nomem(subreq, req)) {
221 return;
223 tevent_req_set_callback(subreq, rpc_write_done, req);
226 static NTSTATUS rpc_write_recv(struct tevent_req *req)
228 return tevent_req_simple_recv_ntstatus(req);
232 /****************************************************************************
233 Try and get a PDU's worth of data from current_pdu. If not, then read more
234 from the wire.
235 ****************************************************************************/
237 struct get_complete_frag_state {
238 struct event_context *ev;
239 struct rpc_pipe_client *cli;
240 uint16_t frag_len;
241 DATA_BLOB *pdu;
244 static void get_complete_frag_got_header(struct tevent_req *subreq);
245 static void get_complete_frag_got_rest(struct tevent_req *subreq);
247 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
248 struct event_context *ev,
249 struct rpc_pipe_client *cli,
250 DATA_BLOB *pdu)
252 struct tevent_req *req, *subreq;
253 struct get_complete_frag_state *state;
254 size_t received;
255 NTSTATUS status;
257 req = tevent_req_create(mem_ctx, &state,
258 struct get_complete_frag_state);
259 if (req == NULL) {
260 return NULL;
262 state->ev = ev;
263 state->cli = cli;
264 state->frag_len = RPC_HEADER_LEN;
265 state->pdu = pdu;
267 received = pdu->length;
268 if (received < RPC_HEADER_LEN) {
269 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
270 status = NT_STATUS_NO_MEMORY;
271 goto post_status;
273 subreq = rpc_read_send(state, state->ev,
274 state->cli->transport,
275 pdu->data + received,
276 RPC_HEADER_LEN - received);
277 if (subreq == NULL) {
278 status = NT_STATUS_NO_MEMORY;
279 goto post_status;
281 tevent_req_set_callback(subreq, get_complete_frag_got_header,
282 req);
283 return req;
286 state->frag_len = dcerpc_get_frag_length(pdu);
287 if (state->frag_len < RPC_HEADER_LEN) {
288 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
289 return tevent_req_post(req, ev);
293 * Ensure we have frag_len bytes of data.
295 if (received < state->frag_len) {
296 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
297 status = NT_STATUS_NO_MEMORY;
298 goto post_status;
300 subreq = rpc_read_send(state, state->ev,
301 state->cli->transport,
302 pdu->data + received,
303 state->frag_len - received);
304 if (subreq == NULL) {
305 status = NT_STATUS_NO_MEMORY;
306 goto post_status;
308 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
309 req);
310 return req;
313 status = NT_STATUS_OK;
314 post_status:
315 if (NT_STATUS_IS_OK(status)) {
316 tevent_req_done(req);
317 } else {
318 tevent_req_nterror(req, status);
320 return tevent_req_post(req, ev);
323 static void get_complete_frag_got_header(struct tevent_req *subreq)
325 struct tevent_req *req = tevent_req_callback_data(
326 subreq, struct tevent_req);
327 struct get_complete_frag_state *state = tevent_req_data(
328 req, struct get_complete_frag_state);
329 NTSTATUS status;
331 status = rpc_read_recv(subreq);
332 TALLOC_FREE(subreq);
333 if (!NT_STATUS_IS_OK(status)) {
334 tevent_req_nterror(req, status);
335 return;
338 state->frag_len = dcerpc_get_frag_length(state->pdu);
339 if (state->frag_len < RPC_HEADER_LEN) {
340 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
341 return;
344 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
345 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
346 return;
350 * We're here in this piece of code because we've read exactly
351 * RPC_HEADER_LEN bytes into state->pdu.
354 subreq = rpc_read_send(state, state->ev, state->cli->transport,
355 state->pdu->data + RPC_HEADER_LEN,
356 state->frag_len - RPC_HEADER_LEN);
357 if (tevent_req_nomem(subreq, req)) {
358 return;
360 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
363 static void get_complete_frag_got_rest(struct tevent_req *subreq)
365 struct tevent_req *req = tevent_req_callback_data(
366 subreq, struct tevent_req);
367 NTSTATUS status;
369 status = rpc_read_recv(subreq);
370 TALLOC_FREE(subreq);
371 if (!NT_STATUS_IS_OK(status)) {
372 tevent_req_nterror(req, status);
373 return;
375 tevent_req_done(req);
378 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
380 return tevent_req_simple_recv_ntstatus(req);
383 /****************************************************************************
384 Do basic authentication checks on an incoming pdu.
385 ****************************************************************************/
387 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
388 struct rpc_pipe_client *cli,
389 struct ncacn_packet *pkt,
390 DATA_BLOB *pdu,
391 uint8_t expected_pkt_type,
392 DATA_BLOB *rdata,
393 DATA_BLOB *reply_pdu)
395 struct dcerpc_response *r;
396 NTSTATUS ret = NT_STATUS_OK;
397 size_t pad_len = 0;
400 * Point the return values at the real data including the RPC
401 * header. Just in case the caller wants it.
403 *rdata = *pdu;
405 /* Ensure we have the correct type. */
406 switch (pkt->ptype) {
407 case DCERPC_PKT_ALTER_RESP:
408 case DCERPC_PKT_BIND_ACK:
410 /* Client code never receives this kind of packets */
411 break;
414 case DCERPC_PKT_RESPONSE:
416 r = &pkt->u.response;
418 /* Here's where we deal with incoming sign/seal. */
419 ret = dcerpc_check_auth(cli->auth, pkt,
420 &r->stub_and_verifier,
421 DCERPC_RESPONSE_LENGTH,
422 pdu, &pad_len);
423 if (!NT_STATUS_IS_OK(ret)) {
424 return ret;
427 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
428 return NT_STATUS_BUFFER_TOO_SMALL;
431 /* Point the return values at the NDR data. */
432 rdata->data = r->stub_and_verifier.data;
434 if (pkt->auth_length) {
435 /* We've already done integer wrap tests in
436 * dcerpc_check_auth(). */
437 rdata->length = r->stub_and_verifier.length
438 - pad_len
439 - DCERPC_AUTH_TRAILER_LENGTH
440 - pkt->auth_length;
441 } else {
442 rdata->length = r->stub_and_verifier.length;
445 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
446 (long unsigned int)pdu->length,
447 (long unsigned int)rdata->length,
448 (unsigned int)pad_len));
451 * If this is the first reply, and the allocation hint is
452 * reasonable, try and set up the reply_pdu DATA_BLOB to the
453 * correct size.
456 if ((reply_pdu->length == 0) &&
457 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
458 if (!data_blob_realloc(mem_ctx, reply_pdu,
459 r->alloc_hint)) {
460 DEBUG(0, ("reply alloc hint %d too "
461 "large to allocate\n",
462 (int)r->alloc_hint));
463 return NT_STATUS_NO_MEMORY;
467 break;
469 case DCERPC_PKT_BIND_NAK:
470 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
471 rpccli_pipe_txt(talloc_tos(), cli)));
472 /* Use this for now... */
473 return NT_STATUS_NETWORK_ACCESS_DENIED;
475 case DCERPC_PKT_FAULT:
477 DEBUG(1, (__location__ ": RPC fault code %s received "
478 "from %s!\n",
479 dcerpc_errstr(talloc_tos(),
480 pkt->u.fault.status),
481 rpccli_pipe_txt(talloc_tos(), cli)));
483 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
485 default:
486 DEBUG(0, (__location__ "Unknown packet type %u received "
487 "from %s!\n",
488 (unsigned int)pkt->ptype,
489 rpccli_pipe_txt(talloc_tos(), cli)));
490 return NT_STATUS_INVALID_INFO_CLASS;
493 if (pkt->ptype != expected_pkt_type) {
494 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
495 "RPC packet type - %u, not %u\n",
496 rpccli_pipe_txt(talloc_tos(), cli),
497 pkt->ptype, expected_pkt_type));
498 return NT_STATUS_INVALID_INFO_CLASS;
501 /* Do this just before return - we don't want to modify any rpc header
502 data before now as we may have needed to do cryptographic actions on
503 it before. */
505 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
506 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
507 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
508 "fragment first/last ON.\n"));
509 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
512 return NT_STATUS_OK;
515 /****************************************************************************
516 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
517 ****************************************************************************/
519 struct cli_api_pipe_state {
520 struct event_context *ev;
521 struct rpc_cli_transport *transport;
522 uint8_t *rdata;
523 uint32_t rdata_len;
526 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
527 static void cli_api_pipe_write_done(struct tevent_req *subreq);
528 static void cli_api_pipe_read_done(struct tevent_req *subreq);
530 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
531 struct event_context *ev,
532 struct rpc_cli_transport *transport,
533 uint8_t *data, size_t data_len,
534 uint32_t max_rdata_len)
536 struct tevent_req *req, *subreq;
537 struct cli_api_pipe_state *state;
538 NTSTATUS status;
540 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
541 if (req == NULL) {
542 return NULL;
544 state->ev = ev;
545 state->transport = transport;
547 if (max_rdata_len < RPC_HEADER_LEN) {
549 * For a RPC reply we always need at least RPC_HEADER_LEN
550 * bytes. We check this here because we will receive
551 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
553 status = NT_STATUS_INVALID_PARAMETER;
554 goto post_status;
557 if (transport->trans_send != NULL) {
558 subreq = transport->trans_send(state, ev, data, data_len,
559 max_rdata_len, transport->priv);
560 if (subreq == NULL) {
561 goto fail;
563 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
564 return req;
568 * If the transport does not provide a "trans" routine, i.e. for
569 * example the ncacn_ip_tcp transport, do the write/read step here.
572 subreq = rpc_write_send(state, ev, transport, data, data_len);
573 if (subreq == NULL) {
574 goto fail;
576 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
577 return req;
579 post_status:
580 tevent_req_nterror(req, status);
581 return tevent_req_post(req, ev);
582 fail:
583 TALLOC_FREE(req);
584 return NULL;
587 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
589 struct tevent_req *req = tevent_req_callback_data(
590 subreq, struct tevent_req);
591 struct cli_api_pipe_state *state = tevent_req_data(
592 req, struct cli_api_pipe_state);
593 NTSTATUS status;
595 status = state->transport->trans_recv(subreq, state, &state->rdata,
596 &state->rdata_len);
597 TALLOC_FREE(subreq);
598 if (!NT_STATUS_IS_OK(status)) {
599 tevent_req_nterror(req, status);
600 return;
602 tevent_req_done(req);
605 static void cli_api_pipe_write_done(struct tevent_req *subreq)
607 struct tevent_req *req = tevent_req_callback_data(
608 subreq, struct tevent_req);
609 struct cli_api_pipe_state *state = tevent_req_data(
610 req, struct cli_api_pipe_state);
611 NTSTATUS status;
613 status = rpc_write_recv(subreq);
614 TALLOC_FREE(subreq);
615 if (!NT_STATUS_IS_OK(status)) {
616 tevent_req_nterror(req, status);
617 return;
620 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
621 if (tevent_req_nomem(state->rdata, req)) {
622 return;
626 * We don't need to use rpc_read_send here, the upper layer will cope
627 * with a short read, transport->trans_send could also return less
628 * than state->max_rdata_len.
630 subreq = state->transport->read_send(state, state->ev, state->rdata,
631 RPC_HEADER_LEN,
632 state->transport->priv);
633 if (tevent_req_nomem(subreq, req)) {
634 return;
636 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
639 static void cli_api_pipe_read_done(struct tevent_req *subreq)
641 struct tevent_req *req = tevent_req_callback_data(
642 subreq, struct tevent_req);
643 struct cli_api_pipe_state *state = tevent_req_data(
644 req, struct cli_api_pipe_state);
645 NTSTATUS status;
646 ssize_t received;
648 status = state->transport->read_recv(subreq, &received);
649 TALLOC_FREE(subreq);
650 if (!NT_STATUS_IS_OK(status)) {
651 tevent_req_nterror(req, status);
652 return;
654 state->rdata_len = received;
655 tevent_req_done(req);
658 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
659 uint8_t **prdata, uint32_t *prdata_len)
661 struct cli_api_pipe_state *state = tevent_req_data(
662 req, struct cli_api_pipe_state);
663 NTSTATUS status;
665 if (tevent_req_is_nterror(req, &status)) {
666 return status;
669 *prdata = talloc_move(mem_ctx, &state->rdata);
670 *prdata_len = state->rdata_len;
671 return NT_STATUS_OK;
674 /****************************************************************************
675 Send data on an rpc pipe via trans. The data must be the last
676 pdu fragment of an NDR data stream.
678 Receive response data from an rpc pipe, which may be large...
680 Read the first fragment: unfortunately have to use SMBtrans for the first
681 bit, then SMBreadX for subsequent bits.
683 If first fragment received also wasn't the last fragment, continue
684 getting fragments until we _do_ receive the last fragment.
686 Request/Response PDU's look like the following...
688 |<------------------PDU len----------------------------------------------->|
689 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
691 +------------+-----------------+-------------+---------------+-------------+
692 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
693 +------------+-----------------+-------------+---------------+-------------+
695 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
696 signing & sealing being negotiated.
698 ****************************************************************************/
700 struct rpc_api_pipe_state {
701 struct event_context *ev;
702 struct rpc_pipe_client *cli;
703 uint8_t expected_pkt_type;
705 DATA_BLOB incoming_frag;
706 struct ncacn_packet *pkt;
708 /* Incoming reply */
709 DATA_BLOB reply_pdu;
710 size_t reply_pdu_offset;
711 uint8_t endianess;
714 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
715 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
716 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
718 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
719 struct event_context *ev,
720 struct rpc_pipe_client *cli,
721 DATA_BLOB *data, /* Outgoing PDU */
722 uint8_t expected_pkt_type)
724 struct tevent_req *req, *subreq;
725 struct rpc_api_pipe_state *state;
726 uint16_t max_recv_frag;
727 NTSTATUS status;
729 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
730 if (req == NULL) {
731 return NULL;
733 state->ev = ev;
734 state->cli = cli;
735 state->expected_pkt_type = expected_pkt_type;
736 state->incoming_frag = data_blob_null;
737 state->reply_pdu = data_blob_null;
738 state->reply_pdu_offset = 0;
739 state->endianess = DCERPC_DREP_LE;
742 * Ensure we're not sending too much.
744 if (data->length > cli->max_xmit_frag) {
745 status = NT_STATUS_INVALID_PARAMETER;
746 goto post_status;
749 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
751 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
752 subreq = rpc_write_send(state, ev, cli->transport,
753 data->data, data->length);
754 if (subreq == NULL) {
755 goto fail;
757 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
758 return req;
761 /* get the header first, then fetch the rest once we have
762 * the frag_length available */
763 max_recv_frag = RPC_HEADER_LEN;
765 subreq = cli_api_pipe_send(state, ev, cli->transport,
766 data->data, data->length, max_recv_frag);
767 if (subreq == NULL) {
768 goto fail;
770 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
771 return req;
773 post_status:
774 tevent_req_nterror(req, status);
775 return tevent_req_post(req, ev);
776 fail:
777 TALLOC_FREE(req);
778 return NULL;
781 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
783 struct tevent_req *req =
784 tevent_req_callback_data(subreq,
785 struct tevent_req);
786 NTSTATUS status;
788 status = rpc_write_recv(subreq);
789 TALLOC_FREE(subreq);
790 if (!NT_STATUS_IS_OK(status)) {
791 tevent_req_nterror(req, status);
792 return;
795 tevent_req_done(req);
798 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
800 struct tevent_req *req = tevent_req_callback_data(
801 subreq, struct tevent_req);
802 struct rpc_api_pipe_state *state = tevent_req_data(
803 req, struct rpc_api_pipe_state);
804 NTSTATUS status;
805 uint8_t *rdata = NULL;
806 uint32_t rdata_len = 0;
808 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
809 TALLOC_FREE(subreq);
810 if (!NT_STATUS_IS_OK(status)) {
811 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
812 tevent_req_nterror(req, status);
813 return;
816 if (rdata == NULL) {
817 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
818 rpccli_pipe_txt(talloc_tos(), state->cli)));
819 tevent_req_done(req);
820 return;
824 * Move data on state->incoming_frag.
826 state->incoming_frag.data = talloc_move(state, &rdata);
827 state->incoming_frag.length = rdata_len;
828 if (!state->incoming_frag.data) {
829 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
830 return;
833 /* Ensure we have enough data for a pdu. */
834 subreq = get_complete_frag_send(state, state->ev, state->cli,
835 &state->incoming_frag);
836 if (tevent_req_nomem(subreq, req)) {
837 return;
839 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
842 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
844 struct tevent_req *req = tevent_req_callback_data(
845 subreq, struct tevent_req);
846 struct rpc_api_pipe_state *state = tevent_req_data(
847 req, struct rpc_api_pipe_state);
848 NTSTATUS status;
849 DATA_BLOB rdata = data_blob_null;
851 status = get_complete_frag_recv(subreq);
852 TALLOC_FREE(subreq);
853 if (!NT_STATUS_IS_OK(status)) {
854 DEBUG(5, ("get_complete_frag failed: %s\n",
855 nt_errstr(status)));
856 tevent_req_nterror(req, status);
857 return;
860 state->pkt = talloc(state, struct ncacn_packet);
861 if (!state->pkt) {
862 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
863 return;
866 status = dcerpc_pull_ncacn_packet(state->pkt,
867 &state->incoming_frag,
868 state->pkt,
869 !state->endianess);
870 if (!NT_STATUS_IS_OK(status)) {
871 tevent_req_nterror(req, status);
872 return;
875 if (state->incoming_frag.length != state->pkt->frag_length) {
876 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
877 (unsigned int)state->incoming_frag.length,
878 (unsigned int)state->pkt->frag_length));
879 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
880 return;
883 status = cli_pipe_validate_current_pdu(state,
884 state->cli, state->pkt,
885 &state->incoming_frag,
886 state->expected_pkt_type,
887 &rdata,
888 &state->reply_pdu);
890 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
891 (unsigned)state->incoming_frag.length,
892 (unsigned)state->reply_pdu_offset,
893 nt_errstr(status)));
895 if (!NT_STATUS_IS_OK(status)) {
896 tevent_req_nterror(req, status);
897 return;
900 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
901 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
903 * Set the data type correctly for big-endian data on the
904 * first packet.
906 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
907 "big-endian.\n",
908 rpccli_pipe_txt(talloc_tos(), state->cli)));
909 state->endianess = 0x00; /* BIG ENDIAN */
912 * Check endianness on subsequent packets.
914 if (state->endianess != state->pkt->drep[0]) {
915 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
916 "%s\n",
917 state->endianess?"little":"big",
918 state->pkt->drep[0]?"little":"big"));
919 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
920 return;
923 /* Now copy the data portion out of the pdu into rbuf. */
924 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
925 if (!data_blob_realloc(NULL, &state->reply_pdu,
926 state->reply_pdu_offset + rdata.length)) {
927 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
928 return;
932 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
933 rdata.data, rdata.length);
934 state->reply_pdu_offset += rdata.length;
936 /* reset state->incoming_frag, there is no need to free it,
937 * it will be reallocated to the right size the next time
938 * it is used */
939 state->incoming_frag.length = 0;
941 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
942 /* make sure the pdu length is right now that we
943 * have all the data available (alloc hint may
944 * have allocated more than was actually used) */
945 state->reply_pdu.length = state->reply_pdu_offset;
946 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
947 rpccli_pipe_txt(talloc_tos(), state->cli),
948 (unsigned)state->reply_pdu.length));
949 tevent_req_done(req);
950 return;
953 subreq = get_complete_frag_send(state, state->ev, state->cli,
954 &state->incoming_frag);
955 if (tevent_req_nomem(subreq, req)) {
956 return;
958 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
961 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
962 struct ncacn_packet **pkt,
963 DATA_BLOB *reply_pdu)
965 struct rpc_api_pipe_state *state = tevent_req_data(
966 req, struct rpc_api_pipe_state);
967 NTSTATUS status;
969 if (tevent_req_is_nterror(req, &status)) {
970 return status;
973 /* return data to caller and assign it ownership of memory */
974 if (reply_pdu) {
975 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
976 reply_pdu->length = state->reply_pdu.length;
977 state->reply_pdu.length = 0;
978 } else {
979 data_blob_free(&state->reply_pdu);
982 if (pkt) {
983 *pkt = talloc_steal(mem_ctx, state->pkt);
986 return NT_STATUS_OK;
989 /*******************************************************************
990 Creates NTLMSSP auth bind.
991 ********************************************************************/
993 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
994 TALLOC_CTX *mem_ctx,
995 DATA_BLOB *auth_token)
997 struct gensec_security *gensec_security;
998 DATA_BLOB null_blob = data_blob_null;
1000 gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
1001 struct gensec_security);
1003 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1004 return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
1007 /*******************************************************************
1008 Creates schannel auth bind.
1009 ********************************************************************/
1011 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1012 DATA_BLOB *auth_token)
1014 NTSTATUS status;
1015 struct NL_AUTH_MESSAGE r;
1017 /* Use lp_workgroup() if domain not specified */
1019 if (!cli->auth->domain || !cli->auth->domain[0]) {
1020 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1021 if (cli->auth->domain == NULL) {
1022 return NT_STATUS_NO_MEMORY;
1027 * Now marshall the data into the auth parse_struct.
1030 r.MessageType = NL_NEGOTIATE_REQUEST;
1031 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1032 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1033 r.oem_netbios_domain.a = cli->auth->domain;
1034 r.oem_netbios_computer.a = lp_netbios_name();
1036 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1037 if (!NT_STATUS_IS_OK(status)) {
1038 return status;
1041 return NT_STATUS_OK;
1044 /*******************************************************************
1045 Creates the internals of a DCE/RPC bind request or alter context PDU.
1046 ********************************************************************/
1048 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1049 enum dcerpc_pkt_type ptype,
1050 uint32 rpc_call_id,
1051 const struct ndr_syntax_id *abstract,
1052 const struct ndr_syntax_id *transfer,
1053 const DATA_BLOB *auth_info,
1054 DATA_BLOB *blob)
1056 uint16 auth_len = auth_info->length;
1057 NTSTATUS status;
1058 union dcerpc_payload u;
1059 struct dcerpc_ctx_list ctx_list;
1061 if (auth_len) {
1062 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1065 ctx_list.context_id = 0;
1066 ctx_list.num_transfer_syntaxes = 1;
1067 ctx_list.abstract_syntax = *abstract;
1068 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1070 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1071 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1072 u.bind.assoc_group_id = 0x0;
1073 u.bind.num_contexts = 1;
1074 u.bind.ctx_list = &ctx_list;
1075 u.bind.auth_info = *auth_info;
1077 status = dcerpc_push_ncacn_packet(mem_ctx,
1078 ptype,
1079 DCERPC_PFC_FLAG_FIRST |
1080 DCERPC_PFC_FLAG_LAST,
1081 auth_len,
1082 rpc_call_id,
1084 blob);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1087 return status;
1090 return NT_STATUS_OK;
1093 /*******************************************************************
1094 Creates a DCE/RPC bind request.
1095 ********************************************************************/
1097 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1098 struct rpc_pipe_client *cli,
1099 struct pipe_auth_data *auth,
1100 uint32 rpc_call_id,
1101 const struct ndr_syntax_id *abstract,
1102 const struct ndr_syntax_id *transfer,
1103 DATA_BLOB *rpc_out)
1105 DATA_BLOB auth_token = data_blob_null;
1106 DATA_BLOB auth_info = data_blob_null;
1107 NTSTATUS ret = NT_STATUS_OK;
1109 switch (auth->auth_type) {
1110 case DCERPC_AUTH_TYPE_SCHANNEL:
1111 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1112 if (!NT_STATUS_IS_OK(ret)) {
1113 return ret;
1115 break;
1117 case DCERPC_AUTH_TYPE_NTLMSSP:
1118 case DCERPC_AUTH_TYPE_KRB5:
1119 case DCERPC_AUTH_TYPE_SPNEGO:
1120 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token);
1122 if (!NT_STATUS_IS_OK(ret) &&
1123 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1124 return ret;
1126 break;
1128 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1129 auth_token = data_blob_talloc(mem_ctx,
1130 "NCALRPC_AUTH_TOKEN",
1131 18);
1132 break;
1134 case DCERPC_AUTH_TYPE_NONE:
1135 break;
1137 default:
1138 /* "Can't" happen. */
1139 return NT_STATUS_INVALID_INFO_CLASS;
1142 if (auth_token.length != 0) {
1143 ret = dcerpc_push_dcerpc_auth(cli,
1144 auth->auth_type,
1145 auth->auth_level,
1146 0, /* auth_pad_length */
1147 1, /* auth_context_id */
1148 &auth_token,
1149 &auth_info);
1150 if (!NT_STATUS_IS_OK(ret)) {
1151 return ret;
1153 data_blob_free(&auth_token);
1156 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1157 DCERPC_PKT_BIND,
1158 rpc_call_id,
1159 abstract,
1160 transfer,
1161 &auth_info,
1162 rpc_out);
1163 return ret;
1166 /*******************************************************************
1167 External interface.
1168 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1169 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1170 and deals with signing/sealing details.
1171 ********************************************************************/
1173 struct rpc_api_pipe_req_state {
1174 struct event_context *ev;
1175 struct rpc_pipe_client *cli;
1176 uint8_t op_num;
1177 uint32_t call_id;
1178 DATA_BLOB *req_data;
1179 uint32_t req_data_sent;
1180 DATA_BLOB rpc_out;
1181 DATA_BLOB reply_pdu;
1184 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1185 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1186 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1187 bool *is_last_frag);
1189 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1190 struct event_context *ev,
1191 struct rpc_pipe_client *cli,
1192 uint8_t op_num,
1193 DATA_BLOB *req_data)
1195 struct tevent_req *req, *subreq;
1196 struct rpc_api_pipe_req_state *state;
1197 NTSTATUS status;
1198 bool is_last_frag;
1200 req = tevent_req_create(mem_ctx, &state,
1201 struct rpc_api_pipe_req_state);
1202 if (req == NULL) {
1203 return NULL;
1205 state->ev = ev;
1206 state->cli = cli;
1207 state->op_num = op_num;
1208 state->req_data = req_data;
1209 state->req_data_sent = 0;
1210 state->call_id = get_rpc_call_id();
1211 state->reply_pdu = data_blob_null;
1212 state->rpc_out = data_blob_null;
1214 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1215 + RPC_MAX_SIGN_SIZE) {
1216 /* Server is screwed up ! */
1217 status = NT_STATUS_INVALID_PARAMETER;
1218 goto post_status;
1221 status = prepare_next_frag(state, &is_last_frag);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 goto post_status;
1226 if (is_last_frag) {
1227 subreq = rpc_api_pipe_send(state, ev, state->cli,
1228 &state->rpc_out,
1229 DCERPC_PKT_RESPONSE);
1230 if (subreq == NULL) {
1231 goto fail;
1233 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1234 } else {
1235 subreq = rpc_write_send(state, ev, cli->transport,
1236 state->rpc_out.data,
1237 state->rpc_out.length);
1238 if (subreq == NULL) {
1239 goto fail;
1241 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1242 req);
1244 return req;
1246 post_status:
1247 tevent_req_nterror(req, status);
1248 return tevent_req_post(req, ev);
1249 fail:
1250 TALLOC_FREE(req);
1251 return NULL;
1254 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1255 bool *is_last_frag)
1257 size_t data_sent_thistime;
1258 size_t auth_len;
1259 size_t frag_len;
1260 uint8_t flags = 0;
1261 size_t pad_len;
1262 size_t data_left;
1263 NTSTATUS status;
1264 union dcerpc_payload u;
1266 data_left = state->req_data->length - state->req_data_sent;
1268 status = dcerpc_guess_sizes(state->cli->auth,
1269 DCERPC_REQUEST_LENGTH, data_left,
1270 state->cli->max_xmit_frag,
1271 CLIENT_NDR_PADDING_SIZE,
1272 &data_sent_thistime,
1273 &frag_len, &auth_len, &pad_len);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 return status;
1278 if (state->req_data_sent == 0) {
1279 flags = DCERPC_PFC_FLAG_FIRST;
1282 if (data_sent_thistime == data_left) {
1283 flags |= DCERPC_PFC_FLAG_LAST;
1286 data_blob_free(&state->rpc_out);
1288 ZERO_STRUCT(u.request);
1290 u.request.alloc_hint = state->req_data->length;
1291 u.request.context_id = 0;
1292 u.request.opnum = state->op_num;
1294 status = dcerpc_push_ncacn_packet(state,
1295 DCERPC_PKT_REQUEST,
1296 flags,
1297 auth_len,
1298 state->call_id,
1300 &state->rpc_out);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 return status;
1305 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1306 * compute it right for requests because the auth trailer is missing
1307 * at this stage */
1308 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1310 /* Copy in the data. */
1311 if (!data_blob_append(NULL, &state->rpc_out,
1312 state->req_data->data + state->req_data_sent,
1313 data_sent_thistime)) {
1314 return NT_STATUS_NO_MEMORY;
1317 switch (state->cli->auth->auth_level) {
1318 case DCERPC_AUTH_LEVEL_NONE:
1319 case DCERPC_AUTH_LEVEL_CONNECT:
1320 case DCERPC_AUTH_LEVEL_PACKET:
1321 break;
1322 case DCERPC_AUTH_LEVEL_INTEGRITY:
1323 case DCERPC_AUTH_LEVEL_PRIVACY:
1324 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1325 &state->rpc_out);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return status;
1329 break;
1330 default:
1331 return NT_STATUS_INVALID_PARAMETER;
1334 state->req_data_sent += data_sent_thistime;
1335 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1337 return status;
1340 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1342 struct tevent_req *req = tevent_req_callback_data(
1343 subreq, struct tevent_req);
1344 struct rpc_api_pipe_req_state *state = tevent_req_data(
1345 req, struct rpc_api_pipe_req_state);
1346 NTSTATUS status;
1347 bool is_last_frag;
1349 status = rpc_write_recv(subreq);
1350 TALLOC_FREE(subreq);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 tevent_req_nterror(req, status);
1353 return;
1356 status = prepare_next_frag(state, &is_last_frag);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 tevent_req_nterror(req, status);
1359 return;
1362 if (is_last_frag) {
1363 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1364 &state->rpc_out,
1365 DCERPC_PKT_RESPONSE);
1366 if (tevent_req_nomem(subreq, req)) {
1367 return;
1369 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1370 } else {
1371 subreq = rpc_write_send(state, state->ev,
1372 state->cli->transport,
1373 state->rpc_out.data,
1374 state->rpc_out.length);
1375 if (tevent_req_nomem(subreq, req)) {
1376 return;
1378 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1379 req);
1383 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1385 struct tevent_req *req = tevent_req_callback_data(
1386 subreq, struct tevent_req);
1387 struct rpc_api_pipe_req_state *state = tevent_req_data(
1388 req, struct rpc_api_pipe_req_state);
1389 NTSTATUS status;
1391 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1392 TALLOC_FREE(subreq);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 tevent_req_nterror(req, status);
1395 return;
1397 tevent_req_done(req);
1400 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1401 DATA_BLOB *reply_pdu)
1403 struct rpc_api_pipe_req_state *state = tevent_req_data(
1404 req, struct rpc_api_pipe_req_state);
1405 NTSTATUS status;
1407 if (tevent_req_is_nterror(req, &status)) {
1409 * We always have to initialize to reply pdu, even if there is
1410 * none. The rpccli_* caller routines expect this.
1412 *reply_pdu = data_blob_null;
1413 return status;
1416 /* return data to caller and assign it ownership of memory */
1417 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1418 reply_pdu->length = state->reply_pdu.length;
1419 state->reply_pdu.length = 0;
1421 return NT_STATUS_OK;
1424 /****************************************************************************
1425 Check the rpc bind acknowledge response.
1426 ****************************************************************************/
1428 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1429 const struct ndr_syntax_id *transfer)
1431 struct dcerpc_ack_ctx ctx;
1433 if (r->secondary_address_size == 0) {
1434 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1437 if (r->num_results < 1 || !r->ctx_list) {
1438 return false;
1441 ctx = r->ctx_list[0];
1443 /* check the transfer syntax */
1444 if ((ctx.syntax.if_version != transfer->if_version) ||
1445 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1446 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1447 return False;
1450 if (r->num_results != 0x1 || ctx.result != 0) {
1451 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1452 r->num_results, ctx.reason));
1455 DEBUG(5,("check_bind_response: accepted!\n"));
1456 return True;
1459 /*******************************************************************
1460 Creates a DCE/RPC bind authentication response.
1461 This is the packet that is sent back to the server once we
1462 have received a BIND-ACK, to finish the third leg of
1463 the authentication handshake.
1464 ********************************************************************/
1466 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1467 struct rpc_pipe_client *cli,
1468 uint32 rpc_call_id,
1469 enum dcerpc_AuthType auth_type,
1470 enum dcerpc_AuthLevel auth_level,
1471 DATA_BLOB *pauth_blob,
1472 DATA_BLOB *rpc_out)
1474 NTSTATUS status;
1475 union dcerpc_payload u;
1477 u.auth3._pad = 0;
1479 status = dcerpc_push_dcerpc_auth(mem_ctx,
1480 auth_type,
1481 auth_level,
1482 0, /* auth_pad_length */
1483 1, /* auth_context_id */
1484 pauth_blob,
1485 &u.auth3.auth_info);
1486 if (!NT_STATUS_IS_OK(status)) {
1487 return status;
1490 status = dcerpc_push_ncacn_packet(mem_ctx,
1491 DCERPC_PKT_AUTH3,
1492 DCERPC_PFC_FLAG_FIRST |
1493 DCERPC_PFC_FLAG_LAST,
1494 pauth_blob->length,
1495 rpc_call_id,
1497 rpc_out);
1498 data_blob_free(&u.auth3.auth_info);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1501 return status;
1504 return NT_STATUS_OK;
1507 /*******************************************************************
1508 Creates a DCE/RPC bind alter context authentication request which
1509 may contain a spnego auth blobl
1510 ********************************************************************/
1512 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1513 enum dcerpc_AuthType auth_type,
1514 enum dcerpc_AuthLevel auth_level,
1515 uint32 rpc_call_id,
1516 const struct ndr_syntax_id *abstract,
1517 const struct ndr_syntax_id *transfer,
1518 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1519 DATA_BLOB *rpc_out)
1521 DATA_BLOB auth_info;
1522 NTSTATUS status;
1524 status = dcerpc_push_dcerpc_auth(mem_ctx,
1525 auth_type,
1526 auth_level,
1527 0, /* auth_pad_length */
1528 1, /* auth_context_id */
1529 pauth_blob,
1530 &auth_info);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 return status;
1535 status = create_bind_or_alt_ctx_internal(mem_ctx,
1536 DCERPC_PKT_ALTER,
1537 rpc_call_id,
1538 abstract,
1539 transfer,
1540 &auth_info,
1541 rpc_out);
1542 data_blob_free(&auth_info);
1543 return status;
1546 /****************************************************************************
1547 Do an rpc bind.
1548 ****************************************************************************/
1550 struct rpc_pipe_bind_state {
1551 struct event_context *ev;
1552 struct rpc_pipe_client *cli;
1553 DATA_BLOB rpc_out;
1554 bool auth3;
1555 uint32_t rpc_call_id;
1556 struct netr_Authenticator auth;
1557 struct netr_Authenticator return_auth;
1558 struct netlogon_creds_CredentialState *creds;
1559 union netr_Capabilities capabilities;
1560 struct netr_LogonGetCapabilities r;
1563 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1564 static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req);
1565 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1566 struct rpc_pipe_bind_state *state,
1567 DATA_BLOB *credentials);
1568 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1569 struct rpc_pipe_bind_state *state,
1570 DATA_BLOB *credentials);
1572 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1573 struct event_context *ev,
1574 struct rpc_pipe_client *cli,
1575 struct pipe_auth_data *auth)
1577 struct tevent_req *req, *subreq;
1578 struct rpc_pipe_bind_state *state;
1579 NTSTATUS status;
1581 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1582 if (req == NULL) {
1583 return NULL;
1586 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1587 rpccli_pipe_txt(talloc_tos(), cli),
1588 (unsigned int)auth->auth_type,
1589 (unsigned int)auth->auth_level ));
1591 state->ev = ev;
1592 state->cli = cli;
1593 state->rpc_call_id = get_rpc_call_id();
1595 cli->auth = talloc_move(cli, &auth);
1597 /* Marshall the outgoing data. */
1598 status = create_rpc_bind_req(state, cli,
1599 cli->auth,
1600 state->rpc_call_id,
1601 &cli->abstract_syntax,
1602 &cli->transfer_syntax,
1603 &state->rpc_out);
1605 if (!NT_STATUS_IS_OK(status) &&
1606 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1607 goto post_status;
1610 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1611 DCERPC_PKT_BIND_ACK);
1612 if (subreq == NULL) {
1613 goto fail;
1615 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1616 return req;
1618 post_status:
1619 tevent_req_nterror(req, status);
1620 return tevent_req_post(req, ev);
1621 fail:
1622 TALLOC_FREE(req);
1623 return NULL;
1626 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1628 struct tevent_req *req = tevent_req_callback_data(
1629 subreq, struct tevent_req);
1630 struct rpc_pipe_bind_state *state = tevent_req_data(
1631 req, struct rpc_pipe_bind_state);
1632 struct pipe_auth_data *pauth = state->cli->auth;
1633 struct gensec_security *gensec_security;
1634 struct ncacn_packet *pkt = NULL;
1635 struct dcerpc_auth auth;
1636 DATA_BLOB auth_token = data_blob_null;
1637 NTSTATUS status;
1639 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1640 TALLOC_FREE(subreq);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1643 rpccli_pipe_txt(talloc_tos(), state->cli),
1644 nt_errstr(status)));
1645 tevent_req_nterror(req, status);
1646 return;
1649 if (state->auth3) {
1650 tevent_req_done(req);
1651 return;
1654 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1655 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1656 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1657 return;
1660 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1661 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1663 switch(pauth->auth_type) {
1665 case DCERPC_AUTH_TYPE_NONE:
1666 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1667 /* Bind complete. */
1668 tevent_req_done(req);
1669 return;
1671 case DCERPC_AUTH_TYPE_SCHANNEL:
1672 rpc_pipe_bind_step_two_trigger(req);
1673 return;
1675 case DCERPC_AUTH_TYPE_NTLMSSP:
1676 case DCERPC_AUTH_TYPE_SPNEGO:
1677 case DCERPC_AUTH_TYPE_KRB5:
1678 /* Paranoid lenght checks */
1679 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1680 + pkt->auth_length) {
1681 tevent_req_nterror(req,
1682 NT_STATUS_INFO_LENGTH_MISMATCH);
1683 return;
1685 /* get auth credentials */
1686 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1687 &pkt->u.bind_ack.auth_info,
1688 &auth, false);
1689 if (!NT_STATUS_IS_OK(status)) {
1690 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1691 nt_errstr(status)));
1692 tevent_req_nterror(req, status);
1693 return;
1695 break;
1697 default:
1698 goto err_out;
1702 * For authenticated binds we may need to do 3 or 4 leg binds.
1705 switch(pauth->auth_type) {
1707 case DCERPC_AUTH_TYPE_NONE:
1708 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1709 case DCERPC_AUTH_TYPE_SCHANNEL:
1710 /* Bind complete. */
1711 tevent_req_done(req);
1712 return;
1714 case DCERPC_AUTH_TYPE_NTLMSSP:
1715 case DCERPC_AUTH_TYPE_KRB5:
1716 case DCERPC_AUTH_TYPE_SPNEGO:
1717 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1718 struct gensec_security);
1719 status = gensec_update(gensec_security, state, NULL,
1720 auth.credentials, &auth_token);
1721 if (NT_STATUS_EQUAL(status,
1722 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1723 status = rpc_bind_next_send(req, state,
1724 &auth_token);
1725 } else if (NT_STATUS_IS_OK(status)) {
1726 if (auth_token.length == 0) {
1727 /* Bind complete. */
1728 tevent_req_done(req);
1729 return;
1731 status = rpc_bind_finish_send(req, state,
1732 &auth_token);
1734 break;
1736 default:
1737 goto err_out;
1740 if (!NT_STATUS_IS_OK(status)) {
1741 tevent_req_nterror(req, status);
1743 return;
1745 err_out:
1746 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1747 (unsigned int)state->cli->auth->auth_type));
1748 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1751 static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq);
1753 static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req)
1755 struct rpc_pipe_bind_state *state =
1756 tevent_req_data(req,
1757 struct rpc_pipe_bind_state);
1758 struct dcerpc_binding_handle *b = state->cli->binding_handle;
1759 struct schannel_state *schannel_auth =
1760 talloc_get_type_abort(state->cli->auth->auth_ctx,
1761 struct schannel_state);
1762 struct tevent_req *subreq;
1764 if (schannel_auth == NULL ||
1765 !ndr_syntax_id_equal(&state->cli->abstract_syntax,
1766 &ndr_table_netlogon.syntax_id)) {
1767 tevent_req_done(req);
1768 return;
1771 ZERO_STRUCT(state->return_auth);
1773 state->creds = netlogon_creds_copy(state, schannel_auth->creds);
1774 if (state->creds == NULL) {
1775 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1776 return;
1779 netlogon_creds_client_authenticator(state->creds, &state->auth);
1781 state->r.in.server_name = state->cli->srv_name_slash;
1782 state->r.in.computer_name = state->creds->computer_name;
1783 state->r.in.credential = &state->auth;
1784 state->r.in.query_level = 1;
1785 state->r.in.return_authenticator = &state->return_auth;
1787 state->r.out.capabilities = &state->capabilities;
1788 state->r.out.return_authenticator = &state->return_auth;
1790 subreq = dcerpc_netr_LogonGetCapabilities_r_send(talloc_tos(),
1791 state->ev,
1793 &state->r);
1794 if (subreq == NULL) {
1795 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1796 return;
1799 tevent_req_set_callback(subreq, rpc_pipe_bind_step_two_done, req);
1800 return;
1803 static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq)
1805 struct tevent_req *req =
1806 tevent_req_callback_data(subreq,
1807 struct tevent_req);
1808 struct rpc_pipe_bind_state *state =
1809 tevent_req_data(req,
1810 struct rpc_pipe_bind_state);
1811 NTSTATUS status;
1813 status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos());
1814 TALLOC_FREE(subreq);
1815 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1816 if (state->cli->dc && state->cli->dc->negotiate_flags &
1817 NETLOGON_NEG_SUPPORTS_AES) {
1818 DEBUG(5, ("AES is not supported and the error was %s\n",
1819 nt_errstr(status)));
1820 tevent_req_nterror(req,
1821 NT_STATUS_INVALID_NETWORK_RESPONSE);
1822 return;
1825 /* This is probably NT */
1826 DEBUG(5, ("We are checking against an NT - %s\n",
1827 nt_errstr(status)));
1828 tevent_req_done(req);
1829 return;
1830 } else if (!NT_STATUS_IS_OK(status)) {
1831 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n",
1832 nt_errstr(status)));
1833 tevent_req_nterror(req, status);
1834 return;
1837 if (NT_STATUS_EQUAL(state->r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
1838 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1839 /* This means AES isn't supported. */
1840 DEBUG(5, ("AES is not supported and the error was %s\n",
1841 nt_errstr(state->r.out.result)));
1842 tevent_req_nterror(req,
1843 NT_STATUS_INVALID_NETWORK_RESPONSE);
1844 return;
1847 /* This is probably an old Samba version */
1848 DEBUG(5, ("We are checking against an old Samba version - %s\n",
1849 nt_errstr(state->r.out.result)));
1850 tevent_req_done(req);
1851 return;
1854 /* We need to check the credential state here, cause win2k3 and earlier
1855 * returns NT_STATUS_NOT_IMPLEMENTED */
1856 if (!netlogon_creds_client_check(state->creds,
1857 &state->r.out.return_authenticator->cred)) {
1859 * Server replied with bad credential. Fail.
1861 DEBUG(0,("rpc_pipe_bind_step_two_done: server %s "
1862 "replied with bad credential\n",
1863 state->cli->desthost));
1864 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1865 return;
1868 TALLOC_FREE(state->cli->dc);
1869 state->cli->dc = talloc_steal(state->cli, state->creds);
1871 if (!NT_STATUS_IS_OK(state->r.out.result)) {
1872 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n",
1873 nt_errstr(state->r.out.result)));
1874 tevent_req_nterror(req, state->r.out.result);
1875 return;
1878 if (state->creds->negotiate_flags !=
1879 state->r.out.capabilities->server_capabilities) {
1880 DEBUG(0, ("The client capabilities don't match the server "
1881 "capabilities: local[0x%08X] remote[0x%08X]\n",
1882 state->creds->negotiate_flags,
1883 state->capabilities.server_capabilities));
1884 tevent_req_nterror(req,
1885 NT_STATUS_INVALID_NETWORK_RESPONSE);
1886 return;
1889 /* TODO: Add downgrade dectection. */
1891 tevent_req_done(req);
1892 return;
1895 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1896 struct rpc_pipe_bind_state *state,
1897 DATA_BLOB *auth_token)
1899 struct pipe_auth_data *auth = state->cli->auth;
1900 struct tevent_req *subreq;
1901 NTSTATUS status;
1903 /* Now prepare the alter context pdu. */
1904 data_blob_free(&state->rpc_out);
1906 status = create_rpc_alter_context(state,
1907 auth->auth_type,
1908 auth->auth_level,
1909 state->rpc_call_id,
1910 &state->cli->abstract_syntax,
1911 &state->cli->transfer_syntax,
1912 auth_token,
1913 &state->rpc_out);
1914 if (!NT_STATUS_IS_OK(status)) {
1915 return status;
1918 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1919 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1920 if (subreq == NULL) {
1921 return NT_STATUS_NO_MEMORY;
1923 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1924 return NT_STATUS_OK;
1927 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1928 struct rpc_pipe_bind_state *state,
1929 DATA_BLOB *auth_token)
1931 struct pipe_auth_data *auth = state->cli->auth;
1932 struct tevent_req *subreq;
1933 NTSTATUS status;
1935 state->auth3 = true;
1937 /* Now prepare the auth3 context pdu. */
1938 data_blob_free(&state->rpc_out);
1940 status = create_rpc_bind_auth3(state, state->cli,
1941 state->rpc_call_id,
1942 auth->auth_type,
1943 auth->auth_level,
1944 auth_token,
1945 &state->rpc_out);
1946 if (!NT_STATUS_IS_OK(status)) {
1947 return status;
1950 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1951 &state->rpc_out, DCERPC_PKT_AUTH3);
1952 if (subreq == NULL) {
1953 return NT_STATUS_NO_MEMORY;
1955 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1956 return NT_STATUS_OK;
1959 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1961 return tevent_req_simple_recv_ntstatus(req);
1964 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1965 struct pipe_auth_data *auth)
1967 TALLOC_CTX *frame = talloc_stackframe();
1968 struct event_context *ev;
1969 struct tevent_req *req;
1970 NTSTATUS status = NT_STATUS_OK;
1972 ev = event_context_init(frame);
1973 if (ev == NULL) {
1974 status = NT_STATUS_NO_MEMORY;
1975 goto fail;
1978 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1979 if (req == NULL) {
1980 status = NT_STATUS_NO_MEMORY;
1981 goto fail;
1984 if (!tevent_req_poll(req, ev)) {
1985 status = map_nt_error_from_unix(errno);
1986 goto fail;
1989 status = rpc_pipe_bind_recv(req);
1990 fail:
1991 TALLOC_FREE(frame);
1992 return status;
1995 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1997 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1998 unsigned int timeout)
2000 unsigned int old;
2002 if (rpc_cli->transport == NULL) {
2003 return RPCCLI_DEFAULT_TIMEOUT;
2006 if (rpc_cli->transport->set_timeout == NULL) {
2007 return RPCCLI_DEFAULT_TIMEOUT;
2010 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2011 if (old == 0) {
2012 return RPCCLI_DEFAULT_TIMEOUT;
2015 return old;
2018 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2020 if (rpc_cli == NULL) {
2021 return false;
2024 if (rpc_cli->transport == NULL) {
2025 return false;
2028 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2031 struct rpccli_bh_state {
2032 struct rpc_pipe_client *rpc_cli;
2035 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2037 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2038 struct rpccli_bh_state);
2040 return rpccli_is_connected(hs->rpc_cli);
2043 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2044 uint32_t timeout)
2046 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2047 struct rpccli_bh_state);
2049 return rpccli_set_timeout(hs->rpc_cli, timeout);
2052 struct rpccli_bh_raw_call_state {
2053 DATA_BLOB in_data;
2054 DATA_BLOB out_data;
2055 uint32_t out_flags;
2058 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2060 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2061 struct tevent_context *ev,
2062 struct dcerpc_binding_handle *h,
2063 const struct GUID *object,
2064 uint32_t opnum,
2065 uint32_t in_flags,
2066 const uint8_t *in_data,
2067 size_t in_length)
2069 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2070 struct rpccli_bh_state);
2071 struct tevent_req *req;
2072 struct rpccli_bh_raw_call_state *state;
2073 bool ok;
2074 struct tevent_req *subreq;
2076 req = tevent_req_create(mem_ctx, &state,
2077 struct rpccli_bh_raw_call_state);
2078 if (req == NULL) {
2079 return NULL;
2081 state->in_data.data = discard_const_p(uint8_t, in_data);
2082 state->in_data.length = in_length;
2084 ok = rpccli_bh_is_connected(h);
2085 if (!ok) {
2086 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2087 return tevent_req_post(req, ev);
2090 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2091 opnum, &state->in_data);
2092 if (tevent_req_nomem(subreq, req)) {
2093 return tevent_req_post(req, ev);
2095 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2097 return req;
2100 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2102 struct tevent_req *req =
2103 tevent_req_callback_data(subreq,
2104 struct tevent_req);
2105 struct rpccli_bh_raw_call_state *state =
2106 tevent_req_data(req,
2107 struct rpccli_bh_raw_call_state);
2108 NTSTATUS status;
2110 state->out_flags = 0;
2112 /* TODO: support bigendian responses */
2114 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2115 TALLOC_FREE(subreq);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 tevent_req_nterror(req, status);
2118 return;
2121 tevent_req_done(req);
2124 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2125 TALLOC_CTX *mem_ctx,
2126 uint8_t **out_data,
2127 size_t *out_length,
2128 uint32_t *out_flags)
2130 struct rpccli_bh_raw_call_state *state =
2131 tevent_req_data(req,
2132 struct rpccli_bh_raw_call_state);
2133 NTSTATUS status;
2135 if (tevent_req_is_nterror(req, &status)) {
2136 tevent_req_received(req);
2137 return status;
2140 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2141 *out_length = state->out_data.length;
2142 *out_flags = state->out_flags;
2143 tevent_req_received(req);
2144 return NT_STATUS_OK;
2147 struct rpccli_bh_disconnect_state {
2148 uint8_t _dummy;
2151 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2152 struct tevent_context *ev,
2153 struct dcerpc_binding_handle *h)
2155 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2156 struct rpccli_bh_state);
2157 struct tevent_req *req;
2158 struct rpccli_bh_disconnect_state *state;
2159 bool ok;
2161 req = tevent_req_create(mem_ctx, &state,
2162 struct rpccli_bh_disconnect_state);
2163 if (req == NULL) {
2164 return NULL;
2167 ok = rpccli_bh_is_connected(h);
2168 if (!ok) {
2169 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2170 return tevent_req_post(req, ev);
2174 * TODO: do a real async disconnect ...
2176 * For now the caller needs to free rpc_cli
2178 hs->rpc_cli = NULL;
2180 tevent_req_done(req);
2181 return tevent_req_post(req, ev);
2184 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2186 NTSTATUS status;
2188 if (tevent_req_is_nterror(req, &status)) {
2189 tevent_req_received(req);
2190 return status;
2193 tevent_req_received(req);
2194 return NT_STATUS_OK;
2197 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2199 return true;
2202 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2203 int ndr_flags,
2204 const void *_struct_ptr,
2205 const struct ndr_interface_call *call)
2207 void *struct_ptr = discard_const(_struct_ptr);
2209 if (DEBUGLEVEL < 10) {
2210 return;
2213 if (ndr_flags & NDR_IN) {
2214 ndr_print_function_debug(call->ndr_print,
2215 call->name,
2216 ndr_flags,
2217 struct_ptr);
2219 if (ndr_flags & NDR_OUT) {
2220 ndr_print_function_debug(call->ndr_print,
2221 call->name,
2222 ndr_flags,
2223 struct_ptr);
2227 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2228 .name = "rpccli",
2229 .is_connected = rpccli_bh_is_connected,
2230 .set_timeout = rpccli_bh_set_timeout,
2231 .raw_call_send = rpccli_bh_raw_call_send,
2232 .raw_call_recv = rpccli_bh_raw_call_recv,
2233 .disconnect_send = rpccli_bh_disconnect_send,
2234 .disconnect_recv = rpccli_bh_disconnect_recv,
2236 .ref_alloc = rpccli_bh_ref_alloc,
2237 .do_ndr_print = rpccli_bh_do_ndr_print,
2240 /* initialise a rpc_pipe_client binding handle */
2241 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2243 struct dcerpc_binding_handle *h;
2244 struct rpccli_bh_state *hs;
2246 h = dcerpc_binding_handle_create(c,
2247 &rpccli_bh_ops,
2248 NULL,
2249 NULL, /* TODO */
2250 &hs,
2251 struct rpccli_bh_state,
2252 __location__);
2253 if (h == NULL) {
2254 return NULL;
2256 hs->rpc_cli = c;
2258 return h;
2261 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2262 struct pipe_auth_data **presult)
2264 struct pipe_auth_data *result;
2266 result = talloc(mem_ctx, struct pipe_auth_data);
2267 if (result == NULL) {
2268 return NT_STATUS_NO_MEMORY;
2271 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2272 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2274 result->user_name = talloc_strdup(result, "");
2275 result->domain = talloc_strdup(result, "");
2276 if ((result->user_name == NULL) || (result->domain == NULL)) {
2277 TALLOC_FREE(result);
2278 return NT_STATUS_NO_MEMORY;
2281 *presult = result;
2282 return NT_STATUS_OK;
2285 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2286 struct pipe_auth_data **presult)
2288 struct pipe_auth_data *result;
2290 result = talloc(mem_ctx, struct pipe_auth_data);
2291 if (result == NULL) {
2292 return NT_STATUS_NO_MEMORY;
2295 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2296 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2298 result->user_name = talloc_strdup(result, "");
2299 result->domain = talloc_strdup(result, "");
2300 if ((result->user_name == NULL) || (result->domain == NULL)) {
2301 TALLOC_FREE(result);
2302 return NT_STATUS_NO_MEMORY;
2305 *presult = result;
2306 return NT_STATUS_OK;
2309 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2310 enum dcerpc_AuthType auth_type,
2311 enum dcerpc_AuthLevel auth_level,
2312 const char *server,
2313 const char *target_service,
2314 const char *domain,
2315 const char *username,
2316 const char *password,
2317 enum credentials_use_kerberos use_kerberos,
2318 struct pipe_auth_data **presult)
2320 struct auth_generic_state *auth_generic_ctx;
2321 struct pipe_auth_data *result;
2322 NTSTATUS status;
2324 result = talloc(mem_ctx, struct pipe_auth_data);
2325 if (result == NULL) {
2326 return NT_STATUS_NO_MEMORY;
2329 result->auth_type = auth_type;
2330 result->auth_level = auth_level;
2332 result->user_name = talloc_strdup(result, username);
2333 result->domain = talloc_strdup(result, domain);
2334 if ((result->user_name == NULL) || (result->domain == NULL)) {
2335 status = NT_STATUS_NO_MEMORY;
2336 goto fail;
2339 status = auth_generic_client_prepare(result,
2340 &auth_generic_ctx);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 goto fail;
2345 status = auth_generic_set_username(auth_generic_ctx, username);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 goto fail;
2350 status = auth_generic_set_domain(auth_generic_ctx, domain);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 goto fail;
2355 status = auth_generic_set_password(auth_generic_ctx, password);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 goto fail;
2360 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 goto fail;
2365 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 goto fail;
2370 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2372 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2373 if (!NT_STATUS_IS_OK(status)) {
2374 goto fail;
2377 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2378 talloc_free(auth_generic_ctx);
2379 *presult = result;
2380 return NT_STATUS_OK;
2382 fail:
2383 TALLOC_FREE(result);
2384 return status;
2387 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2388 enum dcerpc_AuthLevel auth_level,
2389 struct netlogon_creds_CredentialState *creds,
2390 struct pipe_auth_data **presult)
2392 struct schannel_state *schannel_auth;
2393 struct pipe_auth_data *result;
2395 result = talloc(mem_ctx, struct pipe_auth_data);
2396 if (result == NULL) {
2397 return NT_STATUS_NO_MEMORY;
2400 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2401 result->auth_level = auth_level;
2403 result->user_name = talloc_strdup(result, "");
2404 result->domain = talloc_strdup(result, domain);
2405 if ((result->user_name == NULL) || (result->domain == NULL)) {
2406 goto fail;
2409 schannel_auth = talloc_zero(result, struct schannel_state);
2410 if (schannel_auth == NULL) {
2411 goto fail;
2414 schannel_auth->state = SCHANNEL_STATE_START;
2415 schannel_auth->initiator = true;
2416 schannel_auth->creds = netlogon_creds_copy(result, creds);
2418 result->auth_ctx = schannel_auth;
2419 *presult = result;
2420 return NT_STATUS_OK;
2422 fail:
2423 TALLOC_FREE(result);
2424 return NT_STATUS_NO_MEMORY;
2428 * Create an rpc pipe client struct, connecting to a tcp port.
2430 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2431 const struct sockaddr_storage *ss_addr,
2432 uint16_t port,
2433 const struct ndr_syntax_id *abstract_syntax,
2434 struct rpc_pipe_client **presult)
2436 struct rpc_pipe_client *result;
2437 struct sockaddr_storage addr;
2438 NTSTATUS status;
2439 int fd;
2441 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2442 if (result == NULL) {
2443 return NT_STATUS_NO_MEMORY;
2446 result->abstract_syntax = *abstract_syntax;
2447 result->transfer_syntax = ndr_transfer_syntax_ndr;
2449 result->desthost = talloc_strdup(result, host);
2450 result->srv_name_slash = talloc_asprintf_strupper_m(
2451 result, "\\\\%s", result->desthost);
2452 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2453 status = NT_STATUS_NO_MEMORY;
2454 goto fail;
2457 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2458 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2460 if (ss_addr == NULL) {
2461 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2462 status = NT_STATUS_NOT_FOUND;
2463 goto fail;
2465 } else {
2466 addr = *ss_addr;
2469 status = open_socket_out(&addr, port, 60*1000, &fd);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 goto fail;
2473 set_socket_options(fd, lp_socket_options());
2475 status = rpc_transport_sock_init(result, fd, &result->transport);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 close(fd);
2478 goto fail;
2481 result->transport->transport = NCACN_IP_TCP;
2483 result->binding_handle = rpccli_bh_create(result);
2484 if (result->binding_handle == NULL) {
2485 TALLOC_FREE(result);
2486 return NT_STATUS_NO_MEMORY;
2489 *presult = result;
2490 return NT_STATUS_OK;
2492 fail:
2493 TALLOC_FREE(result);
2494 return status;
2498 * Determine the tcp port on which a dcerpc interface is listening
2499 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2500 * target host.
2502 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2503 const struct sockaddr_storage *addr,
2504 const struct ndr_syntax_id *abstract_syntax,
2505 uint16_t *pport)
2507 NTSTATUS status;
2508 struct rpc_pipe_client *epm_pipe = NULL;
2509 struct dcerpc_binding_handle *epm_handle = NULL;
2510 struct pipe_auth_data *auth = NULL;
2511 struct dcerpc_binding *map_binding = NULL;
2512 struct dcerpc_binding *res_binding = NULL;
2513 struct epm_twr_t *map_tower = NULL;
2514 struct epm_twr_t *res_towers = NULL;
2515 struct policy_handle *entry_handle = NULL;
2516 uint32_t num_towers = 0;
2517 uint32_t max_towers = 1;
2518 struct epm_twr_p_t towers;
2519 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2520 uint32_t result = 0;
2522 if (pport == NULL) {
2523 status = NT_STATUS_INVALID_PARAMETER;
2524 goto done;
2527 if (ndr_syntax_id_equal(abstract_syntax,
2528 &ndr_table_epmapper.syntax_id)) {
2529 *pport = 135;
2530 return NT_STATUS_OK;
2533 /* open the connection to the endpoint mapper */
2534 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2535 &ndr_table_epmapper.syntax_id,
2536 &epm_pipe);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 goto done;
2541 epm_handle = epm_pipe->binding_handle;
2543 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 goto done;
2548 status = rpc_pipe_bind(epm_pipe, auth);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 goto done;
2553 /* create tower for asking the epmapper */
2555 map_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
2556 if (map_binding == NULL) {
2557 status = NT_STATUS_NO_MEMORY;
2558 goto done;
2561 map_binding->transport = NCACN_IP_TCP;
2562 map_binding->object = *abstract_syntax;
2563 map_binding->host = host; /* needed? */
2564 map_binding->endpoint = "0"; /* correct? needed? */
2566 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2567 if (map_tower == NULL) {
2568 status = NT_STATUS_NO_MEMORY;
2569 goto done;
2572 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2573 &(map_tower->tower));
2574 if (!NT_STATUS_IS_OK(status)) {
2575 goto done;
2578 /* allocate further parameters for the epm_Map call */
2580 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2581 if (res_towers == NULL) {
2582 status = NT_STATUS_NO_MEMORY;
2583 goto done;
2585 towers.twr = res_towers;
2587 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2588 if (entry_handle == NULL) {
2589 status = NT_STATUS_NO_MEMORY;
2590 goto done;
2593 /* ask the endpoint mapper for the port */
2595 status = dcerpc_epm_Map(epm_handle,
2596 tmp_ctx,
2597 discard_const_p(struct GUID,
2598 &(abstract_syntax->uuid)),
2599 map_tower,
2600 entry_handle,
2601 max_towers,
2602 &num_towers,
2603 &towers,
2604 &result);
2606 if (!NT_STATUS_IS_OK(status)) {
2607 goto done;
2610 if (result != EPMAPPER_STATUS_OK) {
2611 status = NT_STATUS_UNSUCCESSFUL;
2612 goto done;
2615 if (num_towers != 1) {
2616 status = NT_STATUS_UNSUCCESSFUL;
2617 goto done;
2620 /* extract the port from the answer */
2622 status = dcerpc_binding_from_tower(tmp_ctx,
2623 &(towers.twr->tower),
2624 &res_binding);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 goto done;
2629 /* are further checks here necessary? */
2630 if (res_binding->transport != NCACN_IP_TCP) {
2631 status = NT_STATUS_UNSUCCESSFUL;
2632 goto done;
2635 *pport = (uint16_t)atoi(res_binding->endpoint);
2637 done:
2638 TALLOC_FREE(tmp_ctx);
2639 return status;
2643 * Create a rpc pipe client struct, connecting to a host via tcp.
2644 * The port is determined by asking the endpoint mapper on the given
2645 * host.
2647 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2648 const struct sockaddr_storage *addr,
2649 const struct ndr_syntax_id *abstract_syntax,
2650 struct rpc_pipe_client **presult)
2652 NTSTATUS status;
2653 uint16_t port = 0;
2655 status = rpc_pipe_get_tcp_port(host, addr, abstract_syntax, &port);
2656 if (!NT_STATUS_IS_OK(status)) {
2657 return status;
2660 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2661 abstract_syntax, presult);
2664 /********************************************************************
2665 Create a rpc pipe client struct, connecting to a unix domain socket
2666 ********************************************************************/
2667 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2668 const struct ndr_syntax_id *abstract_syntax,
2669 struct rpc_pipe_client **presult)
2671 struct rpc_pipe_client *result;
2672 struct sockaddr_un addr;
2673 NTSTATUS status;
2674 int fd;
2675 socklen_t salen;
2677 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2678 if (result == NULL) {
2679 return NT_STATUS_NO_MEMORY;
2682 result->abstract_syntax = *abstract_syntax;
2683 result->transfer_syntax = ndr_transfer_syntax_ndr;
2685 result->desthost = get_myname(result);
2686 result->srv_name_slash = talloc_asprintf_strupper_m(
2687 result, "\\\\%s", result->desthost);
2688 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2689 status = NT_STATUS_NO_MEMORY;
2690 goto fail;
2693 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2694 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2696 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2697 if (fd == -1) {
2698 status = map_nt_error_from_unix(errno);
2699 goto fail;
2702 ZERO_STRUCT(addr);
2703 addr.sun_family = AF_UNIX;
2704 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2705 salen = sizeof(struct sockaddr_un);
2707 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2708 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2709 strerror(errno)));
2710 close(fd);
2711 return map_nt_error_from_unix(errno);
2714 status = rpc_transport_sock_init(result, fd, &result->transport);
2715 if (!NT_STATUS_IS_OK(status)) {
2716 close(fd);
2717 goto fail;
2720 result->transport->transport = NCALRPC;
2722 result->binding_handle = rpccli_bh_create(result);
2723 if (result->binding_handle == NULL) {
2724 TALLOC_FREE(result);
2725 return NT_STATUS_NO_MEMORY;
2728 *presult = result;
2729 return NT_STATUS_OK;
2731 fail:
2732 TALLOC_FREE(result);
2733 return status;
2736 struct rpc_pipe_client_np_ref {
2737 struct cli_state *cli;
2738 struct rpc_pipe_client *pipe;
2741 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2743 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2744 return 0;
2747 /****************************************************************************
2748 Open a named pipe over SMB to a remote server.
2750 * CAVEAT CALLER OF THIS FUNCTION:
2751 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2752 * so be sure that this function is called AFTER any structure (vs pointer)
2753 * assignment of the cli. In particular, libsmbclient does structure
2754 * assignments of cli, which invalidates the data in the returned
2755 * rpc_pipe_client if this function is called before the structure assignment
2756 * of cli.
2758 ****************************************************************************/
2760 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2761 const struct ndr_syntax_id *abstract_syntax,
2762 struct rpc_pipe_client **presult)
2764 struct rpc_pipe_client *result;
2765 NTSTATUS status;
2766 struct rpc_pipe_client_np_ref *np_ref;
2768 /* sanity check to protect against crashes */
2770 if ( !cli ) {
2771 return NT_STATUS_INVALID_HANDLE;
2774 result = talloc_zero(NULL, struct rpc_pipe_client);
2775 if (result == NULL) {
2776 return NT_STATUS_NO_MEMORY;
2779 result->abstract_syntax = *abstract_syntax;
2780 result->transfer_syntax = ndr_transfer_syntax_ndr;
2781 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2782 result->srv_name_slash = talloc_asprintf_strupper_m(
2783 result, "\\\\%s", result->desthost);
2785 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2786 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2788 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2789 TALLOC_FREE(result);
2790 return NT_STATUS_NO_MEMORY;
2793 status = rpc_transport_np_init(result, cli, abstract_syntax,
2794 &result->transport);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 TALLOC_FREE(result);
2797 return status;
2800 result->transport->transport = NCACN_NP;
2802 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2803 if (np_ref == NULL) {
2804 TALLOC_FREE(result);
2805 return NT_STATUS_NO_MEMORY;
2807 np_ref->cli = cli;
2808 np_ref->pipe = result;
2810 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2811 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2813 result->binding_handle = rpccli_bh_create(result);
2814 if (result->binding_handle == NULL) {
2815 TALLOC_FREE(result);
2816 return NT_STATUS_NO_MEMORY;
2819 *presult = result;
2820 return NT_STATUS_OK;
2823 /****************************************************************************
2824 Open a pipe to a remote server.
2825 ****************************************************************************/
2827 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2828 enum dcerpc_transport_t transport,
2829 const struct ndr_syntax_id *interface,
2830 struct rpc_pipe_client **presult)
2832 switch (transport) {
2833 case NCACN_IP_TCP:
2834 return rpc_pipe_open_tcp(NULL,
2835 smbXcli_conn_remote_name(cli->conn),
2836 smbXcli_conn_remote_sockaddr(cli->conn),
2837 interface, presult);
2838 case NCACN_NP:
2839 return rpc_pipe_open_np(cli, interface, presult);
2840 default:
2841 return NT_STATUS_NOT_IMPLEMENTED;
2845 /****************************************************************************
2846 Open a named pipe to an SMB server and bind anonymously.
2847 ****************************************************************************/
2849 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2850 enum dcerpc_transport_t transport,
2851 const struct ndr_syntax_id *interface,
2852 struct rpc_pipe_client **presult)
2854 struct rpc_pipe_client *result;
2855 struct pipe_auth_data *auth;
2856 NTSTATUS status;
2858 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2859 if (!NT_STATUS_IS_OK(status)) {
2860 return status;
2863 status = rpccli_anon_bind_data(result, &auth);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2866 nt_errstr(status)));
2867 TALLOC_FREE(result);
2868 return status;
2872 * This is a bit of an abstraction violation due to the fact that an
2873 * anonymous bind on an authenticated SMB inherits the user/domain
2874 * from the enclosing SMB creds
2877 TALLOC_FREE(auth->user_name);
2878 TALLOC_FREE(auth->domain);
2880 auth->user_name = talloc_strdup(auth, cli->user_name);
2881 auth->domain = talloc_strdup(auth, cli->domain);
2883 if (transport == NCACN_NP) {
2884 struct smbXcli_session *session;
2886 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2887 session = cli->smb2.session;
2888 } else {
2889 session = cli->smb1.session;
2892 status = smbXcli_session_application_key(session, auth,
2893 &auth->transport_session_key);
2894 if (!NT_STATUS_IS_OK(status)) {
2895 auth->transport_session_key = data_blob_null;
2899 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2900 TALLOC_FREE(result);
2901 return NT_STATUS_NO_MEMORY;
2904 status = rpc_pipe_bind(result, auth);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 int lvl = 0;
2907 if (ndr_syntax_id_equal(interface,
2908 &ndr_table_dssetup.syntax_id)) {
2909 /* non AD domains just don't have this pipe, avoid
2910 * level 0 statement in that case - gd */
2911 lvl = 3;
2913 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2914 "%s failed with error %s\n",
2915 get_pipe_name_from_syntax(talloc_tos(), interface),
2916 nt_errstr(status) ));
2917 TALLOC_FREE(result);
2918 return status;
2921 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2922 "%s and bound anonymously.\n",
2923 get_pipe_name_from_syntax(talloc_tos(), interface),
2924 result->desthost));
2926 *presult = result;
2927 return NT_STATUS_OK;
2930 /****************************************************************************
2931 ****************************************************************************/
2933 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2934 const struct ndr_syntax_id *interface,
2935 struct rpc_pipe_client **presult)
2937 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2938 interface, presult);
2941 /****************************************************************************
2942 Open a named pipe to an SMB server and bind using the mech specified
2943 ****************************************************************************/
2945 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2946 const struct ndr_interface_table *table,
2947 enum dcerpc_transport_t transport,
2948 enum dcerpc_AuthType auth_type,
2949 enum dcerpc_AuthLevel auth_level,
2950 const char *server,
2951 const char *domain,
2952 const char *username,
2953 const char *password,
2954 struct rpc_pipe_client **presult)
2956 struct rpc_pipe_client *result;
2957 struct pipe_auth_data *auth = NULL;
2958 const char *target_service = table->authservices->names[0];
2960 NTSTATUS status;
2962 status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
2963 if (!NT_STATUS_IS_OK(status)) {
2964 return status;
2967 status = rpccli_generic_bind_data(result,
2968 auth_type, auth_level,
2969 server, target_service,
2970 domain, username, password,
2971 CRED_AUTO_USE_KERBEROS,
2972 &auth);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2975 nt_errstr(status)));
2976 goto err;
2979 status = rpc_pipe_bind(result, auth);
2980 if (!NT_STATUS_IS_OK(status)) {
2981 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
2982 nt_errstr(status) ));
2983 goto err;
2986 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
2987 "machine %s and bound as user %s\\%s.\n", table->name,
2988 result->desthost, domain, username));
2990 *presult = result;
2991 return NT_STATUS_OK;
2993 err:
2995 TALLOC_FREE(result);
2996 return status;
2999 /****************************************************************************
3000 External interface.
3001 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3002 using session_key. sign and seal.
3004 The *pdc will be stolen onto this new pipe
3005 ****************************************************************************/
3007 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3008 const struct ndr_syntax_id *interface,
3009 enum dcerpc_transport_t transport,
3010 enum dcerpc_AuthLevel auth_level,
3011 const char *domain,
3012 struct netlogon_creds_CredentialState **pdc,
3013 struct rpc_pipe_client **presult)
3015 struct rpc_pipe_client *result;
3016 struct pipe_auth_data *auth;
3017 NTSTATUS status;
3019 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3020 if (!NT_STATUS_IS_OK(status)) {
3021 return status;
3024 status = rpccli_schannel_bind_data(result, domain, auth_level,
3025 *pdc, &auth);
3026 if (!NT_STATUS_IS_OK(status)) {
3027 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3028 nt_errstr(status)));
3029 TALLOC_FREE(result);
3030 return status;
3033 status = rpc_pipe_bind(result, auth);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3036 "cli_rpc_pipe_bind failed with error %s\n",
3037 nt_errstr(status) ));
3038 TALLOC_FREE(result);
3039 return status;
3043 * The credentials on a new netlogon pipe are the ones we are passed
3044 * in - copy them over
3046 if (result->dc == NULL) {
3047 result->dc = netlogon_creds_copy(result, *pdc);
3048 if (result->dc == NULL) {
3049 TALLOC_FREE(result);
3050 return NT_STATUS_NO_MEMORY;
3054 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3055 "for domain %s and bound using schannel.\n",
3056 get_pipe_name_from_syntax(talloc_tos(), interface),
3057 result->desthost, domain));
3059 *presult = result;
3060 return NT_STATUS_OK;
3063 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
3064 const struct ndr_interface_table *table,
3065 enum dcerpc_transport_t transport,
3066 const char *oid,
3067 enum dcerpc_AuthLevel auth_level,
3068 const char *server,
3069 const char *domain,
3070 const char *username,
3071 const char *password,
3072 struct rpc_pipe_client **presult)
3074 struct rpc_pipe_client *result;
3075 struct pipe_auth_data *auth = NULL;
3076 const char *target_service = table->authservices->names[0];
3078 NTSTATUS status;
3079 enum credentials_use_kerberos use_kerberos;
3081 if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
3082 use_kerberos = CRED_MUST_USE_KERBEROS;
3083 } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
3084 use_kerberos = CRED_DONT_USE_KERBEROS;
3085 } else {
3086 return NT_STATUS_INVALID_PARAMETER;
3089 status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 return status;
3094 status = rpccli_generic_bind_data(result,
3095 DCERPC_AUTH_TYPE_SPNEGO, auth_level,
3096 server, target_service,
3097 domain, username, password,
3098 use_kerberos,
3099 &auth);
3100 if (!NT_STATUS_IS_OK(status)) {
3101 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3102 nt_errstr(status)));
3103 goto err;
3106 status = rpc_pipe_bind(result, auth);
3107 if (!NT_STATUS_IS_OK(status)) {
3108 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
3109 nt_errstr(status) ));
3110 goto err;
3113 DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
3114 "machine %s.\n", table->name,
3115 result->desthost));
3117 *presult = result;
3118 return NT_STATUS_OK;
3120 err:
3122 TALLOC_FREE(result);
3123 return status;
3126 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3127 struct rpc_pipe_client *cli,
3128 DATA_BLOB *session_key)
3130 NTSTATUS status;
3131 struct pipe_auth_data *a;
3132 struct schannel_state *schannel_auth;
3133 struct gensec_security *gensec_security;
3134 DATA_BLOB sk = data_blob_null;
3135 bool make_dup = false;
3137 if (!session_key || !cli) {
3138 return NT_STATUS_INVALID_PARAMETER;
3141 a = cli->auth;
3143 if (a == NULL) {
3144 return NT_STATUS_INVALID_PARAMETER;
3147 switch (cli->auth->auth_type) {
3148 case DCERPC_AUTH_TYPE_SCHANNEL:
3149 schannel_auth = talloc_get_type_abort(a->auth_ctx,
3150 struct schannel_state);
3151 sk = data_blob_const(schannel_auth->creds->session_key, 16);
3152 make_dup = true;
3153 break;
3154 case DCERPC_AUTH_TYPE_SPNEGO:
3155 case DCERPC_AUTH_TYPE_NTLMSSP:
3156 case DCERPC_AUTH_TYPE_KRB5:
3157 gensec_security = talloc_get_type_abort(a->auth_ctx,
3158 struct gensec_security);
3159 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3160 if (!NT_STATUS_IS_OK(status)) {
3161 return status;
3163 make_dup = false;
3164 break;
3165 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3166 case DCERPC_AUTH_TYPE_NONE:
3167 sk = data_blob_const(a->transport_session_key.data,
3168 a->transport_session_key.length);
3169 make_dup = true;
3170 break;
3171 default:
3172 break;
3175 if (!sk.data) {
3176 return NT_STATUS_NO_USER_SESSION_KEY;
3179 if (make_dup) {
3180 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3181 } else {
3182 *session_key = sk;
3185 return NT_STATUS_OK;