s3: Fix Coverity ID 242726 Uninitialized scalar variable
[Samba/gebeck_regimport.git] / source3 / rpc_client / cli_pipe.c
blob5f5f99201de8e0380837b6a96b87c3ebfb628594
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/rpc/dcerpc.h"
33 #include "rpc_dce.h"
34 #include "cli_pipe.h"
35 #include "libsmb/libsmb.h"
36 #include "auth/gensec/gensec.h"
37 #include "auth/credentials/credentials.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 get_rpc_call_id(void)
61 static uint32 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 event_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 event_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 event_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 event_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 event_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 event_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);
287 * Ensure we have frag_len bytes of data.
289 if (received < state->frag_len) {
290 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
291 status = NT_STATUS_NO_MEMORY;
292 goto post_status;
294 subreq = rpc_read_send(state, state->ev,
295 state->cli->transport,
296 pdu->data + received,
297 state->frag_len - received);
298 if (subreq == NULL) {
299 status = NT_STATUS_NO_MEMORY;
300 goto post_status;
302 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
303 req);
304 return req;
307 status = NT_STATUS_OK;
308 post_status:
309 if (NT_STATUS_IS_OK(status)) {
310 tevent_req_done(req);
311 } else {
312 tevent_req_nterror(req, status);
314 return tevent_req_post(req, ev);
317 static void get_complete_frag_got_header(struct tevent_req *subreq)
319 struct tevent_req *req = tevent_req_callback_data(
320 subreq, struct tevent_req);
321 struct get_complete_frag_state *state = tevent_req_data(
322 req, struct get_complete_frag_state);
323 NTSTATUS status;
325 status = rpc_read_recv(subreq);
326 TALLOC_FREE(subreq);
327 if (!NT_STATUS_IS_OK(status)) {
328 tevent_req_nterror(req, status);
329 return;
332 state->frag_len = dcerpc_get_frag_length(state->pdu);
334 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
335 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
336 return;
340 * We're here in this piece of code because we've read exactly
341 * RPC_HEADER_LEN bytes into state->pdu.
344 subreq = rpc_read_send(state, state->ev, state->cli->transport,
345 state->pdu->data + RPC_HEADER_LEN,
346 state->frag_len - RPC_HEADER_LEN);
347 if (tevent_req_nomem(subreq, req)) {
348 return;
350 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
353 static void get_complete_frag_got_rest(struct tevent_req *subreq)
355 struct tevent_req *req = tevent_req_callback_data(
356 subreq, struct tevent_req);
357 NTSTATUS status;
359 status = rpc_read_recv(subreq);
360 TALLOC_FREE(subreq);
361 if (!NT_STATUS_IS_OK(status)) {
362 tevent_req_nterror(req, status);
363 return;
365 tevent_req_done(req);
368 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
370 return tevent_req_simple_recv_ntstatus(req);
373 /****************************************************************************
374 Do basic authentication checks on an incoming pdu.
375 ****************************************************************************/
377 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
378 struct rpc_pipe_client *cli,
379 struct ncacn_packet *pkt,
380 DATA_BLOB *pdu,
381 uint8_t expected_pkt_type,
382 DATA_BLOB *rdata,
383 DATA_BLOB *reply_pdu)
385 struct dcerpc_response *r;
386 NTSTATUS ret = NT_STATUS_OK;
387 size_t pad_len = 0;
390 * Point the return values at the real data including the RPC
391 * header. Just in case the caller wants it.
393 *rdata = *pdu;
395 /* Ensure we have the correct type. */
396 switch (pkt->ptype) {
397 case DCERPC_PKT_ALTER_RESP:
398 case DCERPC_PKT_BIND_ACK:
400 /* Client code never receives this kind of packets */
401 break;
404 case DCERPC_PKT_RESPONSE:
406 r = &pkt->u.response;
408 /* Here's where we deal with incoming sign/seal. */
409 ret = dcerpc_check_auth(cli->auth, pkt,
410 &r->stub_and_verifier,
411 DCERPC_RESPONSE_LENGTH,
412 pdu, &pad_len);
413 if (!NT_STATUS_IS_OK(ret)) {
414 return ret;
417 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
418 return NT_STATUS_BUFFER_TOO_SMALL;
421 /* Point the return values at the NDR data. */
422 rdata->data = r->stub_and_verifier.data;
424 if (pkt->auth_length) {
425 /* We've already done integer wrap tests in
426 * dcerpc_check_auth(). */
427 rdata->length = r->stub_and_verifier.length
428 - pad_len
429 - DCERPC_AUTH_TRAILER_LENGTH
430 - pkt->auth_length;
431 } else {
432 rdata->length = r->stub_and_verifier.length;
435 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
436 (long unsigned int)pdu->length,
437 (long unsigned int)rdata->length,
438 (unsigned int)pad_len));
441 * If this is the first reply, and the allocation hint is
442 * reasonable, try and set up the reply_pdu DATA_BLOB to the
443 * correct size.
446 if ((reply_pdu->length == 0) &&
447 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
448 if (!data_blob_realloc(mem_ctx, reply_pdu,
449 r->alloc_hint)) {
450 DEBUG(0, ("reply alloc hint %d too "
451 "large to allocate\n",
452 (int)r->alloc_hint));
453 return NT_STATUS_NO_MEMORY;
457 break;
459 case DCERPC_PKT_BIND_NAK:
460 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
461 rpccli_pipe_txt(talloc_tos(), cli)));
462 /* Use this for now... */
463 return NT_STATUS_NETWORK_ACCESS_DENIED;
465 case DCERPC_PKT_FAULT:
467 DEBUG(1, (__location__ ": RPC fault code %s received "
468 "from %s!\n",
469 dcerpc_errstr(talloc_tos(),
470 pkt->u.fault.status),
471 rpccli_pipe_txt(talloc_tos(), cli)));
473 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
475 default:
476 DEBUG(0, (__location__ "Unknown packet type %u received "
477 "from %s!\n",
478 (unsigned int)pkt->ptype,
479 rpccli_pipe_txt(talloc_tos(), cli)));
480 return NT_STATUS_INVALID_INFO_CLASS;
483 if (pkt->ptype != expected_pkt_type) {
484 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
485 "RPC packet type - %u, not %u\n",
486 rpccli_pipe_txt(talloc_tos(), cli),
487 pkt->ptype, expected_pkt_type));
488 return NT_STATUS_INVALID_INFO_CLASS;
491 /* Do this just before return - we don't want to modify any rpc header
492 data before now as we may have needed to do cryptographic actions on
493 it before. */
495 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
496 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
497 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
498 "fragment first/last ON.\n"));
499 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
502 return NT_STATUS_OK;
505 /****************************************************************************
506 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
507 ****************************************************************************/
509 struct cli_api_pipe_state {
510 struct event_context *ev;
511 struct rpc_cli_transport *transport;
512 uint8_t *rdata;
513 uint32_t rdata_len;
516 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
517 static void cli_api_pipe_write_done(struct tevent_req *subreq);
518 static void cli_api_pipe_read_done(struct tevent_req *subreq);
520 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
521 struct event_context *ev,
522 struct rpc_cli_transport *transport,
523 uint8_t *data, size_t data_len,
524 uint32_t max_rdata_len)
526 struct tevent_req *req, *subreq;
527 struct cli_api_pipe_state *state;
528 NTSTATUS status;
530 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
531 if (req == NULL) {
532 return NULL;
534 state->ev = ev;
535 state->transport = transport;
537 if (max_rdata_len < RPC_HEADER_LEN) {
539 * For a RPC reply we always need at least RPC_HEADER_LEN
540 * bytes. We check this here because we will receive
541 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
543 status = NT_STATUS_INVALID_PARAMETER;
544 goto post_status;
547 if (transport->trans_send != NULL) {
548 subreq = transport->trans_send(state, ev, data, data_len,
549 max_rdata_len, transport->priv);
550 if (subreq == NULL) {
551 goto fail;
553 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
554 return req;
558 * If the transport does not provide a "trans" routine, i.e. for
559 * example the ncacn_ip_tcp transport, do the write/read step here.
562 subreq = rpc_write_send(state, ev, transport, data, data_len);
563 if (subreq == NULL) {
564 goto fail;
566 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
567 return req;
569 post_status:
570 tevent_req_nterror(req, status);
571 return tevent_req_post(req, ev);
572 fail:
573 TALLOC_FREE(req);
574 return NULL;
577 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
579 struct tevent_req *req = tevent_req_callback_data(
580 subreq, struct tevent_req);
581 struct cli_api_pipe_state *state = tevent_req_data(
582 req, struct cli_api_pipe_state);
583 NTSTATUS status;
585 status = state->transport->trans_recv(subreq, state, &state->rdata,
586 &state->rdata_len);
587 TALLOC_FREE(subreq);
588 if (!NT_STATUS_IS_OK(status)) {
589 tevent_req_nterror(req, status);
590 return;
592 tevent_req_done(req);
595 static void cli_api_pipe_write_done(struct tevent_req *subreq)
597 struct tevent_req *req = tevent_req_callback_data(
598 subreq, struct tevent_req);
599 struct cli_api_pipe_state *state = tevent_req_data(
600 req, struct cli_api_pipe_state);
601 NTSTATUS status;
603 status = rpc_write_recv(subreq);
604 TALLOC_FREE(subreq);
605 if (!NT_STATUS_IS_OK(status)) {
606 tevent_req_nterror(req, status);
607 return;
610 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
611 if (tevent_req_nomem(state->rdata, req)) {
612 return;
616 * We don't need to use rpc_read_send here, the upper layer will cope
617 * with a short read, transport->trans_send could also return less
618 * than state->max_rdata_len.
620 subreq = state->transport->read_send(state, state->ev, state->rdata,
621 RPC_HEADER_LEN,
622 state->transport->priv);
623 if (tevent_req_nomem(subreq, req)) {
624 return;
626 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
629 static void cli_api_pipe_read_done(struct tevent_req *subreq)
631 struct tevent_req *req = tevent_req_callback_data(
632 subreq, struct tevent_req);
633 struct cli_api_pipe_state *state = tevent_req_data(
634 req, struct cli_api_pipe_state);
635 NTSTATUS status;
636 ssize_t received;
638 status = state->transport->read_recv(subreq, &received);
639 TALLOC_FREE(subreq);
640 if (!NT_STATUS_IS_OK(status)) {
641 tevent_req_nterror(req, status);
642 return;
644 state->rdata_len = received;
645 tevent_req_done(req);
648 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
649 uint8_t **prdata, uint32_t *prdata_len)
651 struct cli_api_pipe_state *state = tevent_req_data(
652 req, struct cli_api_pipe_state);
653 NTSTATUS status;
655 if (tevent_req_is_nterror(req, &status)) {
656 return status;
659 *prdata = talloc_move(mem_ctx, &state->rdata);
660 *prdata_len = state->rdata_len;
661 return NT_STATUS_OK;
664 /****************************************************************************
665 Send data on an rpc pipe via trans. The data must be the last
666 pdu fragment of an NDR data stream.
668 Receive response data from an rpc pipe, which may be large...
670 Read the first fragment: unfortunately have to use SMBtrans for the first
671 bit, then SMBreadX for subsequent bits.
673 If first fragment received also wasn't the last fragment, continue
674 getting fragments until we _do_ receive the last fragment.
676 Request/Response PDU's look like the following...
678 |<------------------PDU len----------------------------------------------->|
679 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
681 +------------+-----------------+-------------+---------------+-------------+
682 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
683 +------------+-----------------+-------------+---------------+-------------+
685 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
686 signing & sealing being negotiated.
688 ****************************************************************************/
690 struct rpc_api_pipe_state {
691 struct event_context *ev;
692 struct rpc_pipe_client *cli;
693 uint8_t expected_pkt_type;
695 DATA_BLOB incoming_frag;
696 struct ncacn_packet *pkt;
698 /* Incoming reply */
699 DATA_BLOB reply_pdu;
700 size_t reply_pdu_offset;
701 uint8_t endianess;
704 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
705 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
706 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
708 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
709 struct event_context *ev,
710 struct rpc_pipe_client *cli,
711 DATA_BLOB *data, /* Outgoing PDU */
712 uint8_t expected_pkt_type)
714 struct tevent_req *req, *subreq;
715 struct rpc_api_pipe_state *state;
716 uint16_t max_recv_frag;
717 NTSTATUS status;
719 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
720 if (req == NULL) {
721 return NULL;
723 state->ev = ev;
724 state->cli = cli;
725 state->expected_pkt_type = expected_pkt_type;
726 state->incoming_frag = data_blob_null;
727 state->reply_pdu = data_blob_null;
728 state->reply_pdu_offset = 0;
729 state->endianess = DCERPC_DREP_LE;
732 * Ensure we're not sending too much.
734 if (data->length > cli->max_xmit_frag) {
735 status = NT_STATUS_INVALID_PARAMETER;
736 goto post_status;
739 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
741 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
742 subreq = rpc_write_send(state, ev, cli->transport,
743 data->data, data->length);
744 if (subreq == NULL) {
745 goto fail;
747 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
748 return req;
751 /* get the header first, then fetch the rest once we have
752 * the frag_length available */
753 max_recv_frag = RPC_HEADER_LEN;
755 subreq = cli_api_pipe_send(state, ev, cli->transport,
756 data->data, data->length, max_recv_frag);
757 if (subreq == NULL) {
758 goto fail;
760 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
761 return req;
763 post_status:
764 tevent_req_nterror(req, status);
765 return tevent_req_post(req, ev);
766 fail:
767 TALLOC_FREE(req);
768 return NULL;
771 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
773 struct tevent_req *req =
774 tevent_req_callback_data(subreq,
775 struct tevent_req);
776 NTSTATUS status;
778 status = rpc_write_recv(subreq);
779 TALLOC_FREE(subreq);
780 if (!NT_STATUS_IS_OK(status)) {
781 tevent_req_nterror(req, status);
782 return;
785 tevent_req_done(req);
788 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
790 struct tevent_req *req = tevent_req_callback_data(
791 subreq, struct tevent_req);
792 struct rpc_api_pipe_state *state = tevent_req_data(
793 req, struct rpc_api_pipe_state);
794 NTSTATUS status;
795 uint8_t *rdata = NULL;
796 uint32_t rdata_len = 0;
798 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
799 TALLOC_FREE(subreq);
800 if (!NT_STATUS_IS_OK(status)) {
801 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
802 tevent_req_nterror(req, status);
803 return;
806 if (rdata == NULL) {
807 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
808 rpccli_pipe_txt(talloc_tos(), state->cli)));
809 tevent_req_done(req);
810 return;
814 * Move data on state->incoming_frag.
816 state->incoming_frag.data = talloc_move(state, &rdata);
817 state->incoming_frag.length = rdata_len;
818 if (!state->incoming_frag.data) {
819 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
820 return;
823 /* Ensure we have enough data for a pdu. */
824 subreq = get_complete_frag_send(state, state->ev, state->cli,
825 &state->incoming_frag);
826 if (tevent_req_nomem(subreq, req)) {
827 return;
829 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
832 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
834 struct tevent_req *req = tevent_req_callback_data(
835 subreq, struct tevent_req);
836 struct rpc_api_pipe_state *state = tevent_req_data(
837 req, struct rpc_api_pipe_state);
838 NTSTATUS status;
839 DATA_BLOB rdata = data_blob_null;
841 status = get_complete_frag_recv(subreq);
842 TALLOC_FREE(subreq);
843 if (!NT_STATUS_IS_OK(status)) {
844 DEBUG(5, ("get_complete_frag failed: %s\n",
845 nt_errstr(status)));
846 tevent_req_nterror(req, status);
847 return;
850 state->pkt = talloc(state, struct ncacn_packet);
851 if (!state->pkt) {
852 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
853 return;
856 status = dcerpc_pull_ncacn_packet(state->pkt,
857 &state->incoming_frag,
858 state->pkt,
859 !state->endianess);
860 if (!NT_STATUS_IS_OK(status)) {
861 tevent_req_nterror(req, status);
862 return;
865 if (state->incoming_frag.length != state->pkt->frag_length) {
866 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
867 (unsigned int)state->incoming_frag.length,
868 (unsigned int)state->pkt->frag_length));
869 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
870 return;
873 status = cli_pipe_validate_current_pdu(state,
874 state->cli, state->pkt,
875 &state->incoming_frag,
876 state->expected_pkt_type,
877 &rdata,
878 &state->reply_pdu);
880 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
881 (unsigned)state->incoming_frag.length,
882 (unsigned)state->reply_pdu_offset,
883 nt_errstr(status)));
885 if (!NT_STATUS_IS_OK(status)) {
886 tevent_req_nterror(req, status);
887 return;
890 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
891 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
893 * Set the data type correctly for big-endian data on the
894 * first packet.
896 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
897 "big-endian.\n",
898 rpccli_pipe_txt(talloc_tos(), state->cli)));
899 state->endianess = 0x00; /* BIG ENDIAN */
902 * Check endianness on subsequent packets.
904 if (state->endianess != state->pkt->drep[0]) {
905 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
906 "%s\n",
907 state->endianess?"little":"big",
908 state->pkt->drep[0]?"little":"big"));
909 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 return;
913 /* Now copy the data portion out of the pdu into rbuf. */
914 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
915 if (!data_blob_realloc(NULL, &state->reply_pdu,
916 state->reply_pdu_offset + rdata.length)) {
917 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
918 return;
922 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
923 rdata.data, rdata.length);
924 state->reply_pdu_offset += rdata.length;
926 /* reset state->incoming_frag, there is no need to free it,
927 * it will be reallocated to the right size the next time
928 * it is used */
929 state->incoming_frag.length = 0;
931 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
932 /* make sure the pdu length is right now that we
933 * have all the data available (alloc hint may
934 * have allocated more than was actually used) */
935 state->reply_pdu.length = state->reply_pdu_offset;
936 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
937 rpccli_pipe_txt(talloc_tos(), state->cli),
938 (unsigned)state->reply_pdu.length));
939 tevent_req_done(req);
940 return;
943 subreq = get_complete_frag_send(state, state->ev, state->cli,
944 &state->incoming_frag);
945 if (tevent_req_nomem(subreq, req)) {
946 return;
948 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
951 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
952 struct ncacn_packet **pkt,
953 DATA_BLOB *reply_pdu)
955 struct rpc_api_pipe_state *state = tevent_req_data(
956 req, struct rpc_api_pipe_state);
957 NTSTATUS status;
959 if (tevent_req_is_nterror(req, &status)) {
960 return status;
963 /* return data to caller and assign it ownership of memory */
964 if (reply_pdu) {
965 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
966 reply_pdu->length = state->reply_pdu.length;
967 state->reply_pdu.length = 0;
968 } else {
969 data_blob_free(&state->reply_pdu);
972 if (pkt) {
973 *pkt = talloc_steal(mem_ctx, state->pkt);
976 return NT_STATUS_OK;
979 /*******************************************************************
980 Creates NTLMSSP auth bind.
981 ********************************************************************/
983 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
984 TALLOC_CTX *mem_ctx,
985 DATA_BLOB *auth_token)
987 struct gensec_security *gensec_security;
988 DATA_BLOB null_blob = data_blob_null;
990 gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
991 struct gensec_security);
993 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
994 return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
997 /*******************************************************************
998 Creates schannel auth bind.
999 ********************************************************************/
1001 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1002 DATA_BLOB *auth_token)
1004 NTSTATUS status;
1005 struct NL_AUTH_MESSAGE r;
1007 /* Use lp_workgroup() if domain not specified */
1009 if (!cli->auth->domain || !cli->auth->domain[0]) {
1010 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1011 if (cli->auth->domain == NULL) {
1012 return NT_STATUS_NO_MEMORY;
1017 * Now marshall the data into the auth parse_struct.
1020 r.MessageType = NL_NEGOTIATE_REQUEST;
1021 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1022 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1023 r.oem_netbios_domain.a = cli->auth->domain;
1024 r.oem_netbios_computer.a = lp_netbios_name();
1026 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 return status;
1031 return NT_STATUS_OK;
1034 /*******************************************************************
1035 Creates the internals of a DCE/RPC bind request or alter context PDU.
1036 ********************************************************************/
1038 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1039 enum dcerpc_pkt_type ptype,
1040 uint32 rpc_call_id,
1041 const struct ndr_syntax_id *abstract,
1042 const struct ndr_syntax_id *transfer,
1043 const DATA_BLOB *auth_info,
1044 DATA_BLOB *blob)
1046 uint16 auth_len = auth_info->length;
1047 NTSTATUS status;
1048 union dcerpc_payload u;
1049 struct dcerpc_ctx_list ctx_list;
1051 if (auth_len) {
1052 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1055 ctx_list.context_id = 0;
1056 ctx_list.num_transfer_syntaxes = 1;
1057 ctx_list.abstract_syntax = *abstract;
1058 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1060 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1061 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1062 u.bind.assoc_group_id = 0x0;
1063 u.bind.num_contexts = 1;
1064 u.bind.ctx_list = &ctx_list;
1065 u.bind.auth_info = *auth_info;
1067 status = dcerpc_push_ncacn_packet(mem_ctx,
1068 ptype,
1069 DCERPC_PFC_FLAG_FIRST |
1070 DCERPC_PFC_FLAG_LAST,
1071 auth_len,
1072 rpc_call_id,
1074 blob);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1077 return status;
1080 return NT_STATUS_OK;
1083 /*******************************************************************
1084 Creates a DCE/RPC bind request.
1085 ********************************************************************/
1087 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1088 struct rpc_pipe_client *cli,
1089 struct pipe_auth_data *auth,
1090 uint32 rpc_call_id,
1091 const struct ndr_syntax_id *abstract,
1092 const struct ndr_syntax_id *transfer,
1093 DATA_BLOB *rpc_out)
1095 DATA_BLOB auth_token = data_blob_null;
1096 DATA_BLOB auth_info = data_blob_null;
1097 NTSTATUS ret = NT_STATUS_OK;
1099 switch (auth->auth_type) {
1100 case DCERPC_AUTH_TYPE_SCHANNEL:
1101 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1102 if (!NT_STATUS_IS_OK(ret)) {
1103 return ret;
1105 break;
1107 case DCERPC_AUTH_TYPE_NTLMSSP:
1108 case DCERPC_AUTH_TYPE_KRB5:
1109 case DCERPC_AUTH_TYPE_SPNEGO:
1110 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token);
1112 if (!NT_STATUS_IS_OK(ret) &&
1113 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1114 return ret;
1116 break;
1118 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1119 auth_token = data_blob_talloc(mem_ctx,
1120 "NCALRPC_AUTH_TOKEN",
1121 18);
1122 break;
1124 case DCERPC_AUTH_TYPE_NONE:
1125 break;
1127 default:
1128 /* "Can't" happen. */
1129 return NT_STATUS_INVALID_INFO_CLASS;
1132 if (auth_token.length != 0) {
1133 ret = dcerpc_push_dcerpc_auth(cli,
1134 auth->auth_type,
1135 auth->auth_level,
1136 0, /* auth_pad_length */
1137 1, /* auth_context_id */
1138 &auth_token,
1139 &auth_info);
1140 if (!NT_STATUS_IS_OK(ret)) {
1141 return ret;
1143 data_blob_free(&auth_token);
1146 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1147 DCERPC_PKT_BIND,
1148 rpc_call_id,
1149 abstract,
1150 transfer,
1151 &auth_info,
1152 rpc_out);
1153 return ret;
1156 /*******************************************************************
1157 External interface.
1158 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1159 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1160 and deals with signing/sealing details.
1161 ********************************************************************/
1163 struct rpc_api_pipe_req_state {
1164 struct event_context *ev;
1165 struct rpc_pipe_client *cli;
1166 uint8_t op_num;
1167 uint32_t call_id;
1168 DATA_BLOB *req_data;
1169 uint32_t req_data_sent;
1170 DATA_BLOB rpc_out;
1171 DATA_BLOB reply_pdu;
1174 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1175 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1176 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1177 bool *is_last_frag);
1179 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1180 struct event_context *ev,
1181 struct rpc_pipe_client *cli,
1182 uint8_t op_num,
1183 DATA_BLOB *req_data)
1185 struct tevent_req *req, *subreq;
1186 struct rpc_api_pipe_req_state *state;
1187 NTSTATUS status;
1188 bool is_last_frag;
1190 req = tevent_req_create(mem_ctx, &state,
1191 struct rpc_api_pipe_req_state);
1192 if (req == NULL) {
1193 return NULL;
1195 state->ev = ev;
1196 state->cli = cli;
1197 state->op_num = op_num;
1198 state->req_data = req_data;
1199 state->req_data_sent = 0;
1200 state->call_id = get_rpc_call_id();
1201 state->reply_pdu = data_blob_null;
1202 state->rpc_out = data_blob_null;
1204 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1205 + RPC_MAX_SIGN_SIZE) {
1206 /* Server is screwed up ! */
1207 status = NT_STATUS_INVALID_PARAMETER;
1208 goto post_status;
1211 status = prepare_next_frag(state, &is_last_frag);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 goto post_status;
1216 if (is_last_frag) {
1217 subreq = rpc_api_pipe_send(state, ev, state->cli,
1218 &state->rpc_out,
1219 DCERPC_PKT_RESPONSE);
1220 if (subreq == NULL) {
1221 goto fail;
1223 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1224 } else {
1225 subreq = rpc_write_send(state, ev, cli->transport,
1226 state->rpc_out.data,
1227 state->rpc_out.length);
1228 if (subreq == NULL) {
1229 goto fail;
1231 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1232 req);
1234 return req;
1236 post_status:
1237 tevent_req_nterror(req, status);
1238 return tevent_req_post(req, ev);
1239 fail:
1240 TALLOC_FREE(req);
1241 return NULL;
1244 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1245 bool *is_last_frag)
1247 size_t data_sent_thistime;
1248 size_t auth_len;
1249 size_t frag_len;
1250 uint8_t flags = 0;
1251 size_t pad_len;
1252 size_t data_left;
1253 NTSTATUS status;
1254 union dcerpc_payload u;
1256 data_left = state->req_data->length - state->req_data_sent;
1258 status = dcerpc_guess_sizes(state->cli->auth,
1259 DCERPC_REQUEST_LENGTH, data_left,
1260 state->cli->max_xmit_frag,
1261 CLIENT_NDR_PADDING_SIZE,
1262 &data_sent_thistime,
1263 &frag_len, &auth_len, &pad_len);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 return status;
1268 if (state->req_data_sent == 0) {
1269 flags = DCERPC_PFC_FLAG_FIRST;
1272 if (data_sent_thistime == data_left) {
1273 flags |= DCERPC_PFC_FLAG_LAST;
1276 data_blob_free(&state->rpc_out);
1278 ZERO_STRUCT(u.request);
1280 u.request.alloc_hint = state->req_data->length;
1281 u.request.context_id = 0;
1282 u.request.opnum = state->op_num;
1284 status = dcerpc_push_ncacn_packet(state,
1285 DCERPC_PKT_REQUEST,
1286 flags,
1287 auth_len,
1288 state->call_id,
1290 &state->rpc_out);
1291 if (!NT_STATUS_IS_OK(status)) {
1292 return status;
1295 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1296 * compute it right for requests because the auth trailer is missing
1297 * at this stage */
1298 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1300 /* Copy in the data. */
1301 if (!data_blob_append(NULL, &state->rpc_out,
1302 state->req_data->data + state->req_data_sent,
1303 data_sent_thistime)) {
1304 return NT_STATUS_NO_MEMORY;
1307 switch (state->cli->auth->auth_level) {
1308 case DCERPC_AUTH_LEVEL_NONE:
1309 case DCERPC_AUTH_LEVEL_CONNECT:
1310 case DCERPC_AUTH_LEVEL_PACKET:
1311 break;
1312 case DCERPC_AUTH_LEVEL_INTEGRITY:
1313 case DCERPC_AUTH_LEVEL_PRIVACY:
1314 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1315 &state->rpc_out);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 return status;
1319 break;
1320 default:
1321 return NT_STATUS_INVALID_PARAMETER;
1324 state->req_data_sent += data_sent_thistime;
1325 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1327 return status;
1330 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1332 struct tevent_req *req = tevent_req_callback_data(
1333 subreq, struct tevent_req);
1334 struct rpc_api_pipe_req_state *state = tevent_req_data(
1335 req, struct rpc_api_pipe_req_state);
1336 NTSTATUS status;
1337 bool is_last_frag;
1339 status = rpc_write_recv(subreq);
1340 TALLOC_FREE(subreq);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 tevent_req_nterror(req, status);
1343 return;
1346 status = prepare_next_frag(state, &is_last_frag);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 tevent_req_nterror(req, status);
1349 return;
1352 if (is_last_frag) {
1353 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1354 &state->rpc_out,
1355 DCERPC_PKT_RESPONSE);
1356 if (tevent_req_nomem(subreq, req)) {
1357 return;
1359 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1360 } else {
1361 subreq = rpc_write_send(state, state->ev,
1362 state->cli->transport,
1363 state->rpc_out.data,
1364 state->rpc_out.length);
1365 if (tevent_req_nomem(subreq, req)) {
1366 return;
1368 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1369 req);
1373 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1375 struct tevent_req *req = tevent_req_callback_data(
1376 subreq, struct tevent_req);
1377 struct rpc_api_pipe_req_state *state = tevent_req_data(
1378 req, struct rpc_api_pipe_req_state);
1379 NTSTATUS status;
1381 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1382 TALLOC_FREE(subreq);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 tevent_req_nterror(req, status);
1385 return;
1387 tevent_req_done(req);
1390 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1391 DATA_BLOB *reply_pdu)
1393 struct rpc_api_pipe_req_state *state = tevent_req_data(
1394 req, struct rpc_api_pipe_req_state);
1395 NTSTATUS status;
1397 if (tevent_req_is_nterror(req, &status)) {
1399 * We always have to initialize to reply pdu, even if there is
1400 * none. The rpccli_* caller routines expect this.
1402 *reply_pdu = data_blob_null;
1403 return status;
1406 /* return data to caller and assign it ownership of memory */
1407 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1408 reply_pdu->length = state->reply_pdu.length;
1409 state->reply_pdu.length = 0;
1411 return NT_STATUS_OK;
1414 /****************************************************************************
1415 Check the rpc bind acknowledge response.
1416 ****************************************************************************/
1418 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1419 const struct ndr_syntax_id *transfer)
1421 struct dcerpc_ack_ctx ctx;
1423 if (r->secondary_address_size == 0) {
1424 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1427 if (r->num_results < 1 || !r->ctx_list) {
1428 return false;
1431 ctx = r->ctx_list[0];
1433 /* check the transfer syntax */
1434 if ((ctx.syntax.if_version != transfer->if_version) ||
1435 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1436 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1437 return False;
1440 if (r->num_results != 0x1 || ctx.result != 0) {
1441 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1442 r->num_results, ctx.reason));
1445 DEBUG(5,("check_bind_response: accepted!\n"));
1446 return True;
1449 /*******************************************************************
1450 Creates a DCE/RPC bind authentication response.
1451 This is the packet that is sent back to the server once we
1452 have received a BIND-ACK, to finish the third leg of
1453 the authentication handshake.
1454 ********************************************************************/
1456 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1457 struct rpc_pipe_client *cli,
1458 uint32 rpc_call_id,
1459 enum dcerpc_AuthType auth_type,
1460 enum dcerpc_AuthLevel auth_level,
1461 DATA_BLOB *pauth_blob,
1462 DATA_BLOB *rpc_out)
1464 NTSTATUS status;
1465 union dcerpc_payload u;
1467 u.auth3._pad = 0;
1469 status = dcerpc_push_dcerpc_auth(mem_ctx,
1470 auth_type,
1471 auth_level,
1472 0, /* auth_pad_length */
1473 1, /* auth_context_id */
1474 pauth_blob,
1475 &u.auth3.auth_info);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 return status;
1480 status = dcerpc_push_ncacn_packet(mem_ctx,
1481 DCERPC_PKT_AUTH3,
1482 DCERPC_PFC_FLAG_FIRST |
1483 DCERPC_PFC_FLAG_LAST,
1484 pauth_blob->length,
1485 rpc_call_id,
1487 rpc_out);
1488 data_blob_free(&u.auth3.auth_info);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1491 return status;
1494 return NT_STATUS_OK;
1497 /*******************************************************************
1498 Creates a DCE/RPC bind alter context authentication request which
1499 may contain a spnego auth blobl
1500 ********************************************************************/
1502 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1503 enum dcerpc_AuthType auth_type,
1504 enum dcerpc_AuthLevel auth_level,
1505 uint32 rpc_call_id,
1506 const struct ndr_syntax_id *abstract,
1507 const struct ndr_syntax_id *transfer,
1508 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1509 DATA_BLOB *rpc_out)
1511 DATA_BLOB auth_info;
1512 NTSTATUS status;
1514 status = dcerpc_push_dcerpc_auth(mem_ctx,
1515 auth_type,
1516 auth_level,
1517 0, /* auth_pad_length */
1518 1, /* auth_context_id */
1519 pauth_blob,
1520 &auth_info);
1521 if (!NT_STATUS_IS_OK(status)) {
1522 return status;
1525 status = create_bind_or_alt_ctx_internal(mem_ctx,
1526 DCERPC_PKT_ALTER,
1527 rpc_call_id,
1528 abstract,
1529 transfer,
1530 &auth_info,
1531 rpc_out);
1532 data_blob_free(&auth_info);
1533 return status;
1536 /****************************************************************************
1537 Do an rpc bind.
1538 ****************************************************************************/
1540 struct rpc_pipe_bind_state {
1541 struct event_context *ev;
1542 struct rpc_pipe_client *cli;
1543 DATA_BLOB rpc_out;
1544 bool auth3;
1545 uint32_t rpc_call_id;
1548 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1549 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1550 struct rpc_pipe_bind_state *state,
1551 DATA_BLOB *credentials);
1552 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1553 struct rpc_pipe_bind_state *state,
1554 DATA_BLOB *credentials);
1556 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1557 struct event_context *ev,
1558 struct rpc_pipe_client *cli,
1559 struct pipe_auth_data *auth)
1561 struct tevent_req *req, *subreq;
1562 struct rpc_pipe_bind_state *state;
1563 NTSTATUS status;
1565 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1566 if (req == NULL) {
1567 return NULL;
1570 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1571 rpccli_pipe_txt(talloc_tos(), cli),
1572 (unsigned int)auth->auth_type,
1573 (unsigned int)auth->auth_level ));
1575 state->ev = ev;
1576 state->cli = cli;
1577 state->rpc_call_id = get_rpc_call_id();
1579 cli->auth = talloc_move(cli, &auth);
1581 /* Marshall the outgoing data. */
1582 status = create_rpc_bind_req(state, cli,
1583 cli->auth,
1584 state->rpc_call_id,
1585 &cli->abstract_syntax,
1586 &cli->transfer_syntax,
1587 &state->rpc_out);
1589 if (!NT_STATUS_IS_OK(status) &&
1590 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1591 goto post_status;
1594 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1595 DCERPC_PKT_BIND_ACK);
1596 if (subreq == NULL) {
1597 goto fail;
1599 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1600 return req;
1602 post_status:
1603 tevent_req_nterror(req, status);
1604 return tevent_req_post(req, ev);
1605 fail:
1606 TALLOC_FREE(req);
1607 return NULL;
1610 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1612 struct tevent_req *req = tevent_req_callback_data(
1613 subreq, struct tevent_req);
1614 struct rpc_pipe_bind_state *state = tevent_req_data(
1615 req, struct rpc_pipe_bind_state);
1616 struct pipe_auth_data *pauth = state->cli->auth;
1617 struct gensec_security *gensec_security;
1618 struct ncacn_packet *pkt = NULL;
1619 struct dcerpc_auth auth;
1620 DATA_BLOB auth_token = data_blob_null;
1621 NTSTATUS status;
1623 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1624 TALLOC_FREE(subreq);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1627 rpccli_pipe_txt(talloc_tos(), state->cli),
1628 nt_errstr(status)));
1629 tevent_req_nterror(req, status);
1630 return;
1633 if (state->auth3) {
1634 tevent_req_done(req);
1635 return;
1638 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1639 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1640 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1641 return;
1644 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1645 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1647 switch(pauth->auth_type) {
1649 case DCERPC_AUTH_TYPE_NONE:
1650 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1651 case DCERPC_AUTH_TYPE_SCHANNEL:
1652 /* Bind complete. */
1653 tevent_req_done(req);
1654 return;
1656 case DCERPC_AUTH_TYPE_NTLMSSP:
1657 case DCERPC_AUTH_TYPE_SPNEGO:
1658 case DCERPC_AUTH_TYPE_KRB5:
1659 /* Paranoid lenght checks */
1660 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1661 + pkt->auth_length) {
1662 tevent_req_nterror(req,
1663 NT_STATUS_INFO_LENGTH_MISMATCH);
1664 return;
1666 /* get auth credentials */
1667 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1668 &pkt->u.bind_ack.auth_info,
1669 &auth, false);
1670 if (!NT_STATUS_IS_OK(status)) {
1671 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1672 nt_errstr(status)));
1673 tevent_req_nterror(req, status);
1674 return;
1676 break;
1678 default:
1679 goto err_out;
1683 * For authenticated binds we may need to do 3 or 4 leg binds.
1686 switch(pauth->auth_type) {
1688 case DCERPC_AUTH_TYPE_NONE:
1689 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1690 case DCERPC_AUTH_TYPE_SCHANNEL:
1691 /* Bind complete. */
1692 tevent_req_done(req);
1693 return;
1695 case DCERPC_AUTH_TYPE_NTLMSSP:
1696 case DCERPC_AUTH_TYPE_KRB5:
1697 case DCERPC_AUTH_TYPE_SPNEGO:
1698 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1699 struct gensec_security);
1700 status = gensec_update(gensec_security, state, NULL,
1701 auth.credentials, &auth_token);
1702 if (NT_STATUS_EQUAL(status,
1703 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1704 status = rpc_bind_next_send(req, state,
1705 &auth_token);
1706 } else if (NT_STATUS_IS_OK(status)) {
1707 if (auth_token.length == 0) {
1708 /* Bind complete. */
1709 tevent_req_done(req);
1710 return;
1712 status = rpc_bind_finish_send(req, state,
1713 &auth_token);
1715 break;
1717 default:
1718 goto err_out;
1721 if (!NT_STATUS_IS_OK(status)) {
1722 tevent_req_nterror(req, status);
1724 return;
1726 err_out:
1727 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1728 (unsigned int)state->cli->auth->auth_type));
1729 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1732 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1733 struct rpc_pipe_bind_state *state,
1734 DATA_BLOB *auth_token)
1736 struct pipe_auth_data *auth = state->cli->auth;
1737 struct tevent_req *subreq;
1738 NTSTATUS status;
1740 /* Now prepare the alter context pdu. */
1741 data_blob_free(&state->rpc_out);
1743 status = create_rpc_alter_context(state,
1744 auth->auth_type,
1745 auth->auth_level,
1746 state->rpc_call_id,
1747 &state->cli->abstract_syntax,
1748 &state->cli->transfer_syntax,
1749 auth_token,
1750 &state->rpc_out);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 return status;
1755 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1756 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1757 if (subreq == NULL) {
1758 return NT_STATUS_NO_MEMORY;
1760 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1761 return NT_STATUS_OK;
1764 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1765 struct rpc_pipe_bind_state *state,
1766 DATA_BLOB *auth_token)
1768 struct pipe_auth_data *auth = state->cli->auth;
1769 struct tevent_req *subreq;
1770 NTSTATUS status;
1772 state->auth3 = true;
1774 /* Now prepare the auth3 context pdu. */
1775 data_blob_free(&state->rpc_out);
1777 status = create_rpc_bind_auth3(state, state->cli,
1778 state->rpc_call_id,
1779 auth->auth_type,
1780 auth->auth_level,
1781 auth_token,
1782 &state->rpc_out);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 return status;
1787 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1788 &state->rpc_out, DCERPC_PKT_AUTH3);
1789 if (subreq == NULL) {
1790 return NT_STATUS_NO_MEMORY;
1792 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1793 return NT_STATUS_OK;
1796 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1798 return tevent_req_simple_recv_ntstatus(req);
1801 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1802 struct pipe_auth_data *auth)
1804 TALLOC_CTX *frame = talloc_stackframe();
1805 struct event_context *ev;
1806 struct tevent_req *req;
1807 NTSTATUS status = NT_STATUS_OK;
1809 ev = event_context_init(frame);
1810 if (ev == NULL) {
1811 status = NT_STATUS_NO_MEMORY;
1812 goto fail;
1815 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1816 if (req == NULL) {
1817 status = NT_STATUS_NO_MEMORY;
1818 goto fail;
1821 if (!tevent_req_poll(req, ev)) {
1822 status = map_nt_error_from_unix(errno);
1823 goto fail;
1826 status = rpc_pipe_bind_recv(req);
1827 fail:
1828 TALLOC_FREE(frame);
1829 return status;
1832 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1834 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1835 unsigned int timeout)
1837 unsigned int old;
1839 if (rpc_cli->transport == NULL) {
1840 return RPCCLI_DEFAULT_TIMEOUT;
1843 if (rpc_cli->transport->set_timeout == NULL) {
1844 return RPCCLI_DEFAULT_TIMEOUT;
1847 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
1848 if (old == 0) {
1849 return RPCCLI_DEFAULT_TIMEOUT;
1852 return old;
1855 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
1857 if (rpc_cli == NULL) {
1858 return false;
1861 if (rpc_cli->transport == NULL) {
1862 return false;
1865 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
1868 struct rpccli_bh_state {
1869 struct rpc_pipe_client *rpc_cli;
1872 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
1874 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1875 struct rpccli_bh_state);
1877 return rpccli_is_connected(hs->rpc_cli);
1880 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
1881 uint32_t timeout)
1883 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1884 struct rpccli_bh_state);
1886 return rpccli_set_timeout(hs->rpc_cli, timeout);
1889 struct rpccli_bh_raw_call_state {
1890 DATA_BLOB in_data;
1891 DATA_BLOB out_data;
1892 uint32_t out_flags;
1895 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
1897 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
1898 struct tevent_context *ev,
1899 struct dcerpc_binding_handle *h,
1900 const struct GUID *object,
1901 uint32_t opnum,
1902 uint32_t in_flags,
1903 const uint8_t *in_data,
1904 size_t in_length)
1906 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1907 struct rpccli_bh_state);
1908 struct tevent_req *req;
1909 struct rpccli_bh_raw_call_state *state;
1910 bool ok;
1911 struct tevent_req *subreq;
1913 req = tevent_req_create(mem_ctx, &state,
1914 struct rpccli_bh_raw_call_state);
1915 if (req == NULL) {
1916 return NULL;
1918 state->in_data.data = discard_const_p(uint8_t, in_data);
1919 state->in_data.length = in_length;
1921 ok = rpccli_bh_is_connected(h);
1922 if (!ok) {
1923 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1924 return tevent_req_post(req, ev);
1927 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
1928 opnum, &state->in_data);
1929 if (tevent_req_nomem(subreq, req)) {
1930 return tevent_req_post(req, ev);
1932 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
1934 return req;
1937 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
1939 struct tevent_req *req =
1940 tevent_req_callback_data(subreq,
1941 struct tevent_req);
1942 struct rpccli_bh_raw_call_state *state =
1943 tevent_req_data(req,
1944 struct rpccli_bh_raw_call_state);
1945 NTSTATUS status;
1947 state->out_flags = 0;
1949 /* TODO: support bigendian responses */
1951 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
1952 TALLOC_FREE(subreq);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 tevent_req_nterror(req, status);
1955 return;
1958 tevent_req_done(req);
1961 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
1962 TALLOC_CTX *mem_ctx,
1963 uint8_t **out_data,
1964 size_t *out_length,
1965 uint32_t *out_flags)
1967 struct rpccli_bh_raw_call_state *state =
1968 tevent_req_data(req,
1969 struct rpccli_bh_raw_call_state);
1970 NTSTATUS status;
1972 if (tevent_req_is_nterror(req, &status)) {
1973 tevent_req_received(req);
1974 return status;
1977 *out_data = talloc_move(mem_ctx, &state->out_data.data);
1978 *out_length = state->out_data.length;
1979 *out_flags = state->out_flags;
1980 tevent_req_received(req);
1981 return NT_STATUS_OK;
1984 struct rpccli_bh_disconnect_state {
1985 uint8_t _dummy;
1988 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
1989 struct tevent_context *ev,
1990 struct dcerpc_binding_handle *h)
1992 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1993 struct rpccli_bh_state);
1994 struct tevent_req *req;
1995 struct rpccli_bh_disconnect_state *state;
1996 bool ok;
1998 req = tevent_req_create(mem_ctx, &state,
1999 struct rpccli_bh_disconnect_state);
2000 if (req == NULL) {
2001 return NULL;
2004 ok = rpccli_bh_is_connected(h);
2005 if (!ok) {
2006 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2007 return tevent_req_post(req, ev);
2011 * TODO: do a real async disconnect ...
2013 * For now the caller needs to free rpc_cli
2015 hs->rpc_cli = NULL;
2017 tevent_req_done(req);
2018 return tevent_req_post(req, ev);
2021 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2023 NTSTATUS status;
2025 if (tevent_req_is_nterror(req, &status)) {
2026 tevent_req_received(req);
2027 return status;
2030 tevent_req_received(req);
2031 return NT_STATUS_OK;
2034 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2036 return true;
2039 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2040 int ndr_flags,
2041 const void *_struct_ptr,
2042 const struct ndr_interface_call *call)
2044 void *struct_ptr = discard_const(_struct_ptr);
2046 if (DEBUGLEVEL < 10) {
2047 return;
2050 if (ndr_flags & NDR_IN) {
2051 ndr_print_function_debug(call->ndr_print,
2052 call->name,
2053 ndr_flags,
2054 struct_ptr);
2056 if (ndr_flags & NDR_OUT) {
2057 ndr_print_function_debug(call->ndr_print,
2058 call->name,
2059 ndr_flags,
2060 struct_ptr);
2064 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2065 .name = "rpccli",
2066 .is_connected = rpccli_bh_is_connected,
2067 .set_timeout = rpccli_bh_set_timeout,
2068 .raw_call_send = rpccli_bh_raw_call_send,
2069 .raw_call_recv = rpccli_bh_raw_call_recv,
2070 .disconnect_send = rpccli_bh_disconnect_send,
2071 .disconnect_recv = rpccli_bh_disconnect_recv,
2073 .ref_alloc = rpccli_bh_ref_alloc,
2074 .do_ndr_print = rpccli_bh_do_ndr_print,
2077 /* initialise a rpc_pipe_client binding handle */
2078 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2080 struct dcerpc_binding_handle *h;
2081 struct rpccli_bh_state *hs;
2083 h = dcerpc_binding_handle_create(c,
2084 &rpccli_bh_ops,
2085 NULL,
2086 NULL, /* TODO */
2087 &hs,
2088 struct rpccli_bh_state,
2089 __location__);
2090 if (h == NULL) {
2091 return NULL;
2093 hs->rpc_cli = c;
2095 return h;
2098 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2099 struct pipe_auth_data **presult)
2101 struct pipe_auth_data *result;
2103 result = talloc(mem_ctx, struct pipe_auth_data);
2104 if (result == NULL) {
2105 return NT_STATUS_NO_MEMORY;
2108 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2109 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2111 result->user_name = talloc_strdup(result, "");
2112 result->domain = talloc_strdup(result, "");
2113 if ((result->user_name == NULL) || (result->domain == NULL)) {
2114 TALLOC_FREE(result);
2115 return NT_STATUS_NO_MEMORY;
2118 *presult = result;
2119 return NT_STATUS_OK;
2122 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2123 struct pipe_auth_data **presult)
2125 struct pipe_auth_data *result;
2127 result = talloc(mem_ctx, struct pipe_auth_data);
2128 if (result == NULL) {
2129 return NT_STATUS_NO_MEMORY;
2132 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2133 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2135 result->user_name = talloc_strdup(result, "");
2136 result->domain = talloc_strdup(result, "");
2137 if ((result->user_name == NULL) || (result->domain == NULL)) {
2138 TALLOC_FREE(result);
2139 return NT_STATUS_NO_MEMORY;
2142 *presult = result;
2143 return NT_STATUS_OK;
2146 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2147 enum dcerpc_AuthType auth_type,
2148 enum dcerpc_AuthLevel auth_level,
2149 const char *server,
2150 const char *target_service,
2151 const char *domain,
2152 const char *username,
2153 const char *password,
2154 enum credentials_use_kerberos use_kerberos,
2155 struct pipe_auth_data **presult)
2157 struct auth_generic_state *auth_generic_ctx;
2158 struct pipe_auth_data *result;
2159 NTSTATUS status;
2161 result = talloc(mem_ctx, struct pipe_auth_data);
2162 if (result == NULL) {
2163 return NT_STATUS_NO_MEMORY;
2166 result->auth_type = auth_type;
2167 result->auth_level = auth_level;
2169 result->user_name = talloc_strdup(result, username);
2170 result->domain = talloc_strdup(result, domain);
2171 if ((result->user_name == NULL) || (result->domain == NULL)) {
2172 status = NT_STATUS_NO_MEMORY;
2173 goto fail;
2176 status = auth_generic_client_prepare(result,
2177 &auth_generic_ctx);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 goto fail;
2182 status = auth_generic_set_username(auth_generic_ctx, username);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 goto fail;
2187 status = auth_generic_set_domain(auth_generic_ctx, domain);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 goto fail;
2192 status = auth_generic_set_password(auth_generic_ctx, password);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 goto fail;
2197 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 goto fail;
2202 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2203 if (!NT_STATUS_IS_OK(status)) {
2204 goto fail;
2207 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2209 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2210 if (!NT_STATUS_IS_OK(status)) {
2211 goto fail;
2214 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2215 talloc_free(auth_generic_ctx);
2216 *presult = result;
2217 return NT_STATUS_OK;
2219 fail:
2220 TALLOC_FREE(result);
2221 return status;
2224 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2225 enum dcerpc_AuthLevel auth_level,
2226 struct netlogon_creds_CredentialState *creds,
2227 struct pipe_auth_data **presult)
2229 struct schannel_state *schannel_auth;
2230 struct pipe_auth_data *result;
2232 result = talloc(mem_ctx, struct pipe_auth_data);
2233 if (result == NULL) {
2234 return NT_STATUS_NO_MEMORY;
2237 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2238 result->auth_level = auth_level;
2240 result->user_name = talloc_strdup(result, "");
2241 result->domain = talloc_strdup(result, domain);
2242 if ((result->user_name == NULL) || (result->domain == NULL)) {
2243 goto fail;
2246 schannel_auth = talloc_zero(result, struct schannel_state);
2247 if (schannel_auth == NULL) {
2248 goto fail;
2251 schannel_auth->state = SCHANNEL_STATE_START;
2252 schannel_auth->initiator = true;
2253 schannel_auth->creds = netlogon_creds_copy(result, creds);
2255 result->auth_ctx = schannel_auth;
2256 *presult = result;
2257 return NT_STATUS_OK;
2259 fail:
2260 TALLOC_FREE(result);
2261 return NT_STATUS_NO_MEMORY;
2265 * Create an rpc pipe client struct, connecting to a tcp port.
2267 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2268 uint16_t port,
2269 const struct ndr_syntax_id *abstract_syntax,
2270 struct rpc_pipe_client **presult)
2272 struct rpc_pipe_client *result;
2273 struct sockaddr_storage addr;
2274 NTSTATUS status;
2275 int fd;
2277 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2278 if (result == NULL) {
2279 return NT_STATUS_NO_MEMORY;
2282 result->abstract_syntax = *abstract_syntax;
2283 result->transfer_syntax = ndr_transfer_syntax_ndr;
2285 result->desthost = talloc_strdup(result, host);
2286 result->srv_name_slash = talloc_asprintf_strupper_m(
2287 result, "\\\\%s", result->desthost);
2288 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2289 status = NT_STATUS_NO_MEMORY;
2290 goto fail;
2293 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2294 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2296 if (!resolve_name(host, &addr, 0, false)) {
2297 status = NT_STATUS_NOT_FOUND;
2298 goto fail;
2301 status = open_socket_out(&addr, port, 60*1000, &fd);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 goto fail;
2305 set_socket_options(fd, lp_socket_options());
2307 status = rpc_transport_sock_init(result, fd, &result->transport);
2308 if (!NT_STATUS_IS_OK(status)) {
2309 close(fd);
2310 goto fail;
2313 result->transport->transport = NCACN_IP_TCP;
2315 result->binding_handle = rpccli_bh_create(result);
2316 if (result->binding_handle == NULL) {
2317 TALLOC_FREE(result);
2318 return NT_STATUS_NO_MEMORY;
2321 *presult = result;
2322 return NT_STATUS_OK;
2324 fail:
2325 TALLOC_FREE(result);
2326 return status;
2330 * Determine the tcp port on which a dcerpc interface is listening
2331 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2332 * target host.
2334 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2335 const struct ndr_syntax_id *abstract_syntax,
2336 uint16_t *pport)
2338 NTSTATUS status;
2339 struct rpc_pipe_client *epm_pipe = NULL;
2340 struct dcerpc_binding_handle *epm_handle = NULL;
2341 struct pipe_auth_data *auth = NULL;
2342 struct dcerpc_binding *map_binding = NULL;
2343 struct dcerpc_binding *res_binding = NULL;
2344 struct epm_twr_t *map_tower = NULL;
2345 struct epm_twr_t *res_towers = NULL;
2346 struct policy_handle *entry_handle = NULL;
2347 uint32_t num_towers = 0;
2348 uint32_t max_towers = 1;
2349 struct epm_twr_p_t towers;
2350 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2351 uint32_t result = 0;
2353 if (pport == NULL) {
2354 status = NT_STATUS_INVALID_PARAMETER;
2355 goto done;
2358 if (ndr_syntax_id_equal(abstract_syntax,
2359 &ndr_table_epmapper.syntax_id)) {
2360 *pport = 135;
2361 return NT_STATUS_OK;
2364 /* open the connection to the endpoint mapper */
2365 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2366 &ndr_table_epmapper.syntax_id,
2367 &epm_pipe);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 goto done;
2372 epm_handle = epm_pipe->binding_handle;
2374 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 goto done;
2379 status = rpc_pipe_bind(epm_pipe, auth);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 goto done;
2384 /* create tower for asking the epmapper */
2386 map_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
2387 if (map_binding == NULL) {
2388 status = NT_STATUS_NO_MEMORY;
2389 goto done;
2392 map_binding->transport = NCACN_IP_TCP;
2393 map_binding->object = *abstract_syntax;
2394 map_binding->host = host; /* needed? */
2395 map_binding->endpoint = "0"; /* correct? needed? */
2397 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2398 if (map_tower == NULL) {
2399 status = NT_STATUS_NO_MEMORY;
2400 goto done;
2403 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2404 &(map_tower->tower));
2405 if (!NT_STATUS_IS_OK(status)) {
2406 goto done;
2409 /* allocate further parameters for the epm_Map call */
2411 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2412 if (res_towers == NULL) {
2413 status = NT_STATUS_NO_MEMORY;
2414 goto done;
2416 towers.twr = res_towers;
2418 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2419 if (entry_handle == NULL) {
2420 status = NT_STATUS_NO_MEMORY;
2421 goto done;
2424 /* ask the endpoint mapper for the port */
2426 status = dcerpc_epm_Map(epm_handle,
2427 tmp_ctx,
2428 discard_const_p(struct GUID,
2429 &(abstract_syntax->uuid)),
2430 map_tower,
2431 entry_handle,
2432 max_towers,
2433 &num_towers,
2434 &towers,
2435 &result);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 goto done;
2441 if (result != EPMAPPER_STATUS_OK) {
2442 status = NT_STATUS_UNSUCCESSFUL;
2443 goto done;
2446 if (num_towers != 1) {
2447 status = NT_STATUS_UNSUCCESSFUL;
2448 goto done;
2451 /* extract the port from the answer */
2453 status = dcerpc_binding_from_tower(tmp_ctx,
2454 &(towers.twr->tower),
2455 &res_binding);
2456 if (!NT_STATUS_IS_OK(status)) {
2457 goto done;
2460 /* are further checks here necessary? */
2461 if (res_binding->transport != NCACN_IP_TCP) {
2462 status = NT_STATUS_UNSUCCESSFUL;
2463 goto done;
2466 *pport = (uint16_t)atoi(res_binding->endpoint);
2468 done:
2469 TALLOC_FREE(tmp_ctx);
2470 return status;
2474 * Create a rpc pipe client struct, connecting to a host via tcp.
2475 * The port is determined by asking the endpoint mapper on the given
2476 * host.
2478 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2479 const struct ndr_syntax_id *abstract_syntax,
2480 struct rpc_pipe_client **presult)
2482 NTSTATUS status;
2483 uint16_t port = 0;
2485 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 return status;
2490 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2491 abstract_syntax, presult);
2494 /********************************************************************
2495 Create a rpc pipe client struct, connecting to a unix domain socket
2496 ********************************************************************/
2497 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2498 const struct ndr_syntax_id *abstract_syntax,
2499 struct rpc_pipe_client **presult)
2501 struct rpc_pipe_client *result;
2502 struct sockaddr_un addr;
2503 NTSTATUS status;
2504 int fd;
2505 socklen_t salen;
2507 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2508 if (result == NULL) {
2509 return NT_STATUS_NO_MEMORY;
2512 result->abstract_syntax = *abstract_syntax;
2513 result->transfer_syntax = ndr_transfer_syntax_ndr;
2515 result->desthost = get_myname(result);
2516 result->srv_name_slash = talloc_asprintf_strupper_m(
2517 result, "\\\\%s", result->desthost);
2518 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2519 status = NT_STATUS_NO_MEMORY;
2520 goto fail;
2523 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2524 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2526 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2527 if (fd == -1) {
2528 status = map_nt_error_from_unix(errno);
2529 goto fail;
2532 ZERO_STRUCT(addr);
2533 addr.sun_family = AF_UNIX;
2534 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2535 salen = sizeof(struct sockaddr_un);
2537 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2538 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2539 strerror(errno)));
2540 close(fd);
2541 return map_nt_error_from_unix(errno);
2544 status = rpc_transport_sock_init(result, fd, &result->transport);
2545 if (!NT_STATUS_IS_OK(status)) {
2546 close(fd);
2547 goto fail;
2550 result->transport->transport = NCALRPC;
2552 result->binding_handle = rpccli_bh_create(result);
2553 if (result->binding_handle == NULL) {
2554 TALLOC_FREE(result);
2555 return NT_STATUS_NO_MEMORY;
2558 *presult = result;
2559 return NT_STATUS_OK;
2561 fail:
2562 TALLOC_FREE(result);
2563 return status;
2566 struct rpc_pipe_client_np_ref {
2567 struct cli_state *cli;
2568 struct rpc_pipe_client *pipe;
2571 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2573 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2574 return 0;
2577 /****************************************************************************
2578 Open a named pipe over SMB to a remote server.
2580 * CAVEAT CALLER OF THIS FUNCTION:
2581 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2582 * so be sure that this function is called AFTER any structure (vs pointer)
2583 * assignment of the cli. In particular, libsmbclient does structure
2584 * assignments of cli, which invalidates the data in the returned
2585 * rpc_pipe_client if this function is called before the structure assignment
2586 * of cli.
2588 ****************************************************************************/
2590 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2591 const struct ndr_syntax_id *abstract_syntax,
2592 struct rpc_pipe_client **presult)
2594 struct rpc_pipe_client *result;
2595 NTSTATUS status;
2596 struct rpc_pipe_client_np_ref *np_ref;
2598 /* sanity check to protect against crashes */
2600 if ( !cli ) {
2601 return NT_STATUS_INVALID_HANDLE;
2604 result = talloc_zero(NULL, struct rpc_pipe_client);
2605 if (result == NULL) {
2606 return NT_STATUS_NO_MEMORY;
2609 result->abstract_syntax = *abstract_syntax;
2610 result->transfer_syntax = ndr_transfer_syntax_ndr;
2611 result->desthost = talloc_strdup(result, cli_state_remote_name(cli));
2612 result->srv_name_slash = talloc_asprintf_strupper_m(
2613 result, "\\\\%s", result->desthost);
2615 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2616 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2618 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2619 TALLOC_FREE(result);
2620 return NT_STATUS_NO_MEMORY;
2623 status = rpc_transport_np_init(result, cli, abstract_syntax,
2624 &result->transport);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 TALLOC_FREE(result);
2627 return status;
2630 result->transport->transport = NCACN_NP;
2632 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2633 if (np_ref == NULL) {
2634 TALLOC_FREE(result);
2635 return NT_STATUS_NO_MEMORY;
2637 np_ref->cli = cli;
2638 np_ref->pipe = result;
2640 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2641 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2643 result->binding_handle = rpccli_bh_create(result);
2644 if (result->binding_handle == NULL) {
2645 TALLOC_FREE(result);
2646 return NT_STATUS_NO_MEMORY;
2649 *presult = result;
2650 return NT_STATUS_OK;
2653 /****************************************************************************
2654 Open a pipe to a remote server.
2655 ****************************************************************************/
2657 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2658 enum dcerpc_transport_t transport,
2659 const struct ndr_syntax_id *interface,
2660 struct rpc_pipe_client **presult)
2662 switch (transport) {
2663 case NCACN_IP_TCP:
2664 return rpc_pipe_open_tcp(NULL, cli_state_remote_name(cli),
2665 interface, presult);
2666 case NCACN_NP:
2667 return rpc_pipe_open_np(cli, interface, presult);
2668 default:
2669 return NT_STATUS_NOT_IMPLEMENTED;
2673 /****************************************************************************
2674 Open a named pipe to an SMB server and bind anonymously.
2675 ****************************************************************************/
2677 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2678 enum dcerpc_transport_t transport,
2679 const struct ndr_syntax_id *interface,
2680 struct rpc_pipe_client **presult)
2682 struct rpc_pipe_client *result;
2683 struct pipe_auth_data *auth;
2684 NTSTATUS status;
2686 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2687 if (!NT_STATUS_IS_OK(status)) {
2688 return status;
2691 status = rpccli_anon_bind_data(result, &auth);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2694 nt_errstr(status)));
2695 TALLOC_FREE(result);
2696 return status;
2700 * This is a bit of an abstraction violation due to the fact that an
2701 * anonymous bind on an authenticated SMB inherits the user/domain
2702 * from the enclosing SMB creds
2705 TALLOC_FREE(auth->user_name);
2706 TALLOC_FREE(auth->domain);
2708 auth->user_name = talloc_strdup(auth, cli->user_name);
2709 auth->domain = talloc_strdup(auth, cli->domain);
2710 auth->user_session_key = data_blob_talloc(auth,
2711 cli->user_session_key.data,
2712 cli->user_session_key.length);
2714 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2715 TALLOC_FREE(result);
2716 return NT_STATUS_NO_MEMORY;
2719 status = rpc_pipe_bind(result, auth);
2720 if (!NT_STATUS_IS_OK(status)) {
2721 int lvl = 0;
2722 if (ndr_syntax_id_equal(interface,
2723 &ndr_table_dssetup.syntax_id)) {
2724 /* non AD domains just don't have this pipe, avoid
2725 * level 0 statement in that case - gd */
2726 lvl = 3;
2728 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2729 "%s failed with error %s\n",
2730 get_pipe_name_from_syntax(talloc_tos(), interface),
2731 nt_errstr(status) ));
2732 TALLOC_FREE(result);
2733 return status;
2736 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2737 "%s and bound anonymously.\n",
2738 get_pipe_name_from_syntax(talloc_tos(), interface),
2739 result->desthost));
2741 *presult = result;
2742 return NT_STATUS_OK;
2745 /****************************************************************************
2746 ****************************************************************************/
2748 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2749 const struct ndr_syntax_id *interface,
2750 struct rpc_pipe_client **presult)
2752 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2753 interface, presult);
2756 /****************************************************************************
2757 Open a named pipe to an SMB server and bind using the mech specified
2758 ****************************************************************************/
2760 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2761 const struct ndr_interface_table *table,
2762 enum dcerpc_transport_t transport,
2763 enum dcerpc_AuthType auth_type,
2764 enum dcerpc_AuthLevel auth_level,
2765 const char *server,
2766 const char *domain,
2767 const char *username,
2768 const char *password,
2769 struct rpc_pipe_client **presult)
2771 struct rpc_pipe_client *result;
2772 struct pipe_auth_data *auth = NULL;
2773 const char *target_service = table->authservices->names[0];
2775 NTSTATUS status;
2777 status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 return status;
2782 status = rpccli_generic_bind_data(result,
2783 auth_type, auth_level,
2784 server, target_service,
2785 domain, username, password,
2786 CRED_AUTO_USE_KERBEROS,
2787 &auth);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2790 nt_errstr(status)));
2791 goto err;
2794 status = rpc_pipe_bind(result, auth);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
2797 nt_errstr(status) ));
2798 goto err;
2801 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
2802 "machine %s and bound as user %s\\%s.\n", table->name,
2803 result->desthost, domain, username));
2805 *presult = result;
2806 return NT_STATUS_OK;
2808 err:
2810 TALLOC_FREE(result);
2811 return status;
2814 /****************************************************************************
2815 External interface.
2816 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2817 using session_key. sign and seal.
2819 The *pdc will be stolen onto this new pipe
2820 ****************************************************************************/
2822 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2823 const struct ndr_syntax_id *interface,
2824 enum dcerpc_transport_t transport,
2825 enum dcerpc_AuthLevel auth_level,
2826 const char *domain,
2827 struct netlogon_creds_CredentialState **pdc,
2828 struct rpc_pipe_client **presult)
2830 struct rpc_pipe_client *result;
2831 struct pipe_auth_data *auth;
2832 NTSTATUS status;
2834 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 return status;
2839 status = rpccli_schannel_bind_data(result, domain, auth_level,
2840 *pdc, &auth);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
2843 nt_errstr(status)));
2844 TALLOC_FREE(result);
2845 return status;
2848 status = rpc_pipe_bind(result, auth);
2849 if (!NT_STATUS_IS_OK(status)) {
2850 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
2851 "cli_rpc_pipe_bind failed with error %s\n",
2852 nt_errstr(status) ));
2853 TALLOC_FREE(result);
2854 return status;
2858 * The credentials on a new netlogon pipe are the ones we are passed
2859 * in - copy them over
2861 result->dc = netlogon_creds_copy(result, *pdc);
2862 if (result->dc == NULL) {
2863 TALLOC_FREE(result);
2864 return NT_STATUS_NO_MEMORY;
2867 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2868 "for domain %s and bound using schannel.\n",
2869 get_pipe_name_from_syntax(talloc_tos(), interface),
2870 result->desthost, domain));
2872 *presult = result;
2873 return NT_STATUS_OK;
2876 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
2877 const struct ndr_interface_table *table,
2878 enum dcerpc_transport_t transport,
2879 const char *oid,
2880 enum dcerpc_AuthLevel auth_level,
2881 const char *server,
2882 const char *domain,
2883 const char *username,
2884 const char *password,
2885 struct rpc_pipe_client **presult)
2887 struct rpc_pipe_client *result;
2888 struct pipe_auth_data *auth = NULL;
2889 const char *target_service = table->authservices->names[0];
2891 NTSTATUS status;
2892 enum credentials_use_kerberos use_kerberos;
2894 if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
2895 use_kerberos = CRED_MUST_USE_KERBEROS;
2896 } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
2897 use_kerberos = CRED_DONT_USE_KERBEROS;
2898 } else {
2899 return NT_STATUS_INVALID_PARAMETER;
2902 status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
2903 if (!NT_STATUS_IS_OK(status)) {
2904 return status;
2907 status = rpccli_generic_bind_data(result,
2908 DCERPC_AUTH_TYPE_SPNEGO, auth_level,
2909 server, target_service,
2910 domain, username, password,
2911 use_kerberos,
2912 &auth);
2913 if (!NT_STATUS_IS_OK(status)) {
2914 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2915 nt_errstr(status)));
2916 goto err;
2919 status = rpc_pipe_bind(result, auth);
2920 if (!NT_STATUS_IS_OK(status)) {
2921 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
2922 nt_errstr(status) ));
2923 goto err;
2926 DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
2927 "machine %s.\n", table->name,
2928 result->desthost));
2930 *presult = result;
2931 return NT_STATUS_OK;
2933 err:
2935 TALLOC_FREE(result);
2936 return status;
2939 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
2940 struct rpc_pipe_client *cli,
2941 DATA_BLOB *session_key)
2943 NTSTATUS status;
2944 struct pipe_auth_data *a;
2945 struct schannel_state *schannel_auth;
2946 struct gensec_security *gensec_security;
2947 DATA_BLOB sk = data_blob_null;
2948 bool make_dup = false;
2950 if (!session_key || !cli) {
2951 return NT_STATUS_INVALID_PARAMETER;
2954 a = cli->auth;
2956 if (a == NULL) {
2957 return NT_STATUS_INVALID_PARAMETER;
2960 switch (cli->auth->auth_type) {
2961 case DCERPC_AUTH_TYPE_SCHANNEL:
2962 schannel_auth = talloc_get_type_abort(a->auth_ctx,
2963 struct schannel_state);
2964 sk = data_blob_const(schannel_auth->creds->session_key, 16);
2965 make_dup = true;
2966 break;
2967 case DCERPC_AUTH_TYPE_SPNEGO:
2968 case DCERPC_AUTH_TYPE_NTLMSSP:
2969 case DCERPC_AUTH_TYPE_KRB5:
2970 gensec_security = talloc_get_type_abort(a->auth_ctx,
2971 struct gensec_security);
2972 status = gensec_session_key(gensec_security, mem_ctx, &sk);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 return status;
2976 make_dup = false;
2977 break;
2978 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
2979 case DCERPC_AUTH_TYPE_NONE:
2980 sk = data_blob_const(a->user_session_key.data,
2981 a->user_session_key.length);
2982 make_dup = true;
2983 break;
2984 default:
2985 break;
2988 if (!sk.data) {
2989 return NT_STATUS_NO_USER_SESSION_KEY;
2992 if (make_dup) {
2993 *session_key = data_blob_dup_talloc(mem_ctx, sk);
2994 } else {
2995 *session_key = sk;
2998 return NT_STATUS_OK;