s3-librpc Call GSSAPI via the auth_generic layer and gensec
[Samba/gebeck_regimport.git] / source3 / rpc_client / cli_pipe.c
blobce8ab819c53843d04b59a4b98e5c0723c7558703
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 "librpc/crypto/spnego.h"
34 #include "rpc_dce.h"
35 #include "cli_pipe.h"
36 #include "libsmb/libsmb.h"
37 #include "auth/gensec/gensec.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 spnego auth bind.
981 ********************************************************************/
983 static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx,
984 struct pipe_auth_data *auth,
985 DATA_BLOB *auth_token)
987 struct spnego_context *spnego_ctx;
988 DATA_BLOB in_token = data_blob_null;
989 NTSTATUS status;
991 spnego_ctx = talloc_get_type_abort(auth->auth_ctx,
992 struct spnego_context);
994 /* Negotiate the initial auth token */
995 status = spnego_get_client_auth_token(mem_ctx, spnego_ctx,
996 &in_token, auth_token);
997 if (!NT_STATUS_IS_OK(status)) {
998 return status;
1001 DEBUG(5, ("Created GSS Authentication Token:\n"));
1002 dump_data(5, auth_token->data, auth_token->length);
1004 return NT_STATUS_OK;
1007 /*******************************************************************
1008 Creates NTLMSSP auth bind.
1009 ********************************************************************/
1011 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1012 TALLOC_CTX *mem_ctx,
1013 DATA_BLOB *auth_token)
1015 struct gensec_security *gensec_security;
1016 DATA_BLOB null_blob = data_blob_null;
1017 NTSTATUS status;
1019 gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
1020 struct gensec_security);
1022 DEBUG(5, ("create_generic_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1023 status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
1025 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1026 data_blob_free(auth_token);
1027 return status;
1030 return NT_STATUS_OK;
1033 /*******************************************************************
1034 Creates schannel auth bind.
1035 ********************************************************************/
1037 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1038 DATA_BLOB *auth_token)
1040 NTSTATUS status;
1041 struct NL_AUTH_MESSAGE r;
1043 /* Use lp_workgroup() if domain not specified */
1045 if (!cli->auth->domain || !cli->auth->domain[0]) {
1046 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1047 if (cli->auth->domain == NULL) {
1048 return NT_STATUS_NO_MEMORY;
1053 * Now marshall the data into the auth parse_struct.
1056 r.MessageType = NL_NEGOTIATE_REQUEST;
1057 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1058 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1059 r.oem_netbios_domain.a = cli->auth->domain;
1060 r.oem_netbios_computer.a = lp_netbios_name();
1062 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 return status;
1067 return NT_STATUS_OK;
1070 /*******************************************************************
1071 Creates the internals of a DCE/RPC bind request or alter context PDU.
1072 ********************************************************************/
1074 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1075 enum dcerpc_pkt_type ptype,
1076 uint32 rpc_call_id,
1077 const struct ndr_syntax_id *abstract,
1078 const struct ndr_syntax_id *transfer,
1079 const DATA_BLOB *auth_info,
1080 DATA_BLOB *blob)
1082 uint16 auth_len = auth_info->length;
1083 NTSTATUS status;
1084 union dcerpc_payload u;
1085 struct dcerpc_ctx_list ctx_list;
1087 if (auth_len) {
1088 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1091 ctx_list.context_id = 0;
1092 ctx_list.num_transfer_syntaxes = 1;
1093 ctx_list.abstract_syntax = *abstract;
1094 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1096 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1097 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1098 u.bind.assoc_group_id = 0x0;
1099 u.bind.num_contexts = 1;
1100 u.bind.ctx_list = &ctx_list;
1101 u.bind.auth_info = *auth_info;
1103 status = dcerpc_push_ncacn_packet(mem_ctx,
1104 ptype,
1105 DCERPC_PFC_FLAG_FIRST |
1106 DCERPC_PFC_FLAG_LAST,
1107 auth_len,
1108 rpc_call_id,
1110 blob);
1111 if (!NT_STATUS_IS_OK(status)) {
1112 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1113 return status;
1116 return NT_STATUS_OK;
1119 /*******************************************************************
1120 Creates a DCE/RPC bind request.
1121 ********************************************************************/
1123 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1124 struct rpc_pipe_client *cli,
1125 struct pipe_auth_data *auth,
1126 uint32 rpc_call_id,
1127 const struct ndr_syntax_id *abstract,
1128 const struct ndr_syntax_id *transfer,
1129 DATA_BLOB *rpc_out)
1131 DATA_BLOB auth_token = data_blob_null;
1132 DATA_BLOB auth_info = data_blob_null;
1133 NTSTATUS ret = NT_STATUS_OK;
1135 switch (auth->auth_type) {
1136 case DCERPC_AUTH_TYPE_SCHANNEL:
1137 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1138 if (!NT_STATUS_IS_OK(ret)) {
1139 return ret;
1141 break;
1143 case DCERPC_AUTH_TYPE_NTLMSSP:
1144 case DCERPC_AUTH_TYPE_KRB5:
1145 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token);
1146 if (!NT_STATUS_IS_OK(ret)) {
1147 return ret;
1149 break;
1151 case DCERPC_AUTH_TYPE_SPNEGO:
1152 ret = create_spnego_auth_bind_req(cli, auth, &auth_token);
1153 if (!NT_STATUS_IS_OK(ret)) {
1154 return ret;
1156 break;
1158 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1159 auth_token = data_blob_talloc(mem_ctx,
1160 "NCALRPC_AUTH_TOKEN",
1161 18);
1162 break;
1164 case DCERPC_AUTH_TYPE_NONE:
1165 break;
1167 default:
1168 /* "Can't" happen. */
1169 return NT_STATUS_INVALID_INFO_CLASS;
1172 if (auth_token.length != 0) {
1173 ret = dcerpc_push_dcerpc_auth(cli,
1174 auth->auth_type,
1175 auth->auth_level,
1176 0, /* auth_pad_length */
1177 1, /* auth_context_id */
1178 &auth_token,
1179 &auth_info);
1180 if (!NT_STATUS_IS_OK(ret)) {
1181 return ret;
1183 data_blob_free(&auth_token);
1186 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1187 DCERPC_PKT_BIND,
1188 rpc_call_id,
1189 abstract,
1190 transfer,
1191 &auth_info,
1192 rpc_out);
1193 return ret;
1196 /*******************************************************************
1197 External interface.
1198 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1199 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1200 and deals with signing/sealing details.
1201 ********************************************************************/
1203 struct rpc_api_pipe_req_state {
1204 struct event_context *ev;
1205 struct rpc_pipe_client *cli;
1206 uint8_t op_num;
1207 uint32_t call_id;
1208 DATA_BLOB *req_data;
1209 uint32_t req_data_sent;
1210 DATA_BLOB rpc_out;
1211 DATA_BLOB reply_pdu;
1214 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1215 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1216 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1217 bool *is_last_frag);
1219 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1220 struct event_context *ev,
1221 struct rpc_pipe_client *cli,
1222 uint8_t op_num,
1223 DATA_BLOB *req_data)
1225 struct tevent_req *req, *subreq;
1226 struct rpc_api_pipe_req_state *state;
1227 NTSTATUS status;
1228 bool is_last_frag;
1230 req = tevent_req_create(mem_ctx, &state,
1231 struct rpc_api_pipe_req_state);
1232 if (req == NULL) {
1233 return NULL;
1235 state->ev = ev;
1236 state->cli = cli;
1237 state->op_num = op_num;
1238 state->req_data = req_data;
1239 state->req_data_sent = 0;
1240 state->call_id = get_rpc_call_id();
1241 state->reply_pdu = data_blob_null;
1242 state->rpc_out = data_blob_null;
1244 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1245 + RPC_MAX_SIGN_SIZE) {
1246 /* Server is screwed up ! */
1247 status = NT_STATUS_INVALID_PARAMETER;
1248 goto post_status;
1251 status = prepare_next_frag(state, &is_last_frag);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 goto post_status;
1256 if (is_last_frag) {
1257 subreq = rpc_api_pipe_send(state, ev, state->cli,
1258 &state->rpc_out,
1259 DCERPC_PKT_RESPONSE);
1260 if (subreq == NULL) {
1261 goto fail;
1263 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1264 } else {
1265 subreq = rpc_write_send(state, ev, cli->transport,
1266 state->rpc_out.data,
1267 state->rpc_out.length);
1268 if (subreq == NULL) {
1269 goto fail;
1271 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1272 req);
1274 return req;
1276 post_status:
1277 tevent_req_nterror(req, status);
1278 return tevent_req_post(req, ev);
1279 fail:
1280 TALLOC_FREE(req);
1281 return NULL;
1284 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1285 bool *is_last_frag)
1287 size_t data_sent_thistime;
1288 size_t auth_len;
1289 size_t frag_len;
1290 uint8_t flags = 0;
1291 size_t pad_len;
1292 size_t data_left;
1293 NTSTATUS status;
1294 union dcerpc_payload u;
1296 data_left = state->req_data->length - state->req_data_sent;
1298 status = dcerpc_guess_sizes(state->cli->auth,
1299 DCERPC_REQUEST_LENGTH, data_left,
1300 state->cli->max_xmit_frag,
1301 CLIENT_NDR_PADDING_SIZE,
1302 &data_sent_thistime,
1303 &frag_len, &auth_len, &pad_len);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 return status;
1308 if (state->req_data_sent == 0) {
1309 flags = DCERPC_PFC_FLAG_FIRST;
1312 if (data_sent_thistime == data_left) {
1313 flags |= DCERPC_PFC_FLAG_LAST;
1316 data_blob_free(&state->rpc_out);
1318 ZERO_STRUCT(u.request);
1320 u.request.alloc_hint = state->req_data->length;
1321 u.request.context_id = 0;
1322 u.request.opnum = state->op_num;
1324 status = dcerpc_push_ncacn_packet(state,
1325 DCERPC_PKT_REQUEST,
1326 flags,
1327 auth_len,
1328 state->call_id,
1330 &state->rpc_out);
1331 if (!NT_STATUS_IS_OK(status)) {
1332 return status;
1335 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1336 * compute it right for requests because the auth trailer is missing
1337 * at this stage */
1338 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1340 /* Copy in the data. */
1341 if (!data_blob_append(NULL, &state->rpc_out,
1342 state->req_data->data + state->req_data_sent,
1343 data_sent_thistime)) {
1344 return NT_STATUS_NO_MEMORY;
1347 switch (state->cli->auth->auth_level) {
1348 case DCERPC_AUTH_LEVEL_NONE:
1349 case DCERPC_AUTH_LEVEL_CONNECT:
1350 case DCERPC_AUTH_LEVEL_PACKET:
1351 break;
1352 case DCERPC_AUTH_LEVEL_INTEGRITY:
1353 case DCERPC_AUTH_LEVEL_PRIVACY:
1354 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1355 &state->rpc_out);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 return status;
1359 break;
1360 default:
1361 return NT_STATUS_INVALID_PARAMETER;
1364 state->req_data_sent += data_sent_thistime;
1365 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1367 return status;
1370 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1372 struct tevent_req *req = tevent_req_callback_data(
1373 subreq, struct tevent_req);
1374 struct rpc_api_pipe_req_state *state = tevent_req_data(
1375 req, struct rpc_api_pipe_req_state);
1376 NTSTATUS status;
1377 bool is_last_frag;
1379 status = rpc_write_recv(subreq);
1380 TALLOC_FREE(subreq);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 tevent_req_nterror(req, status);
1383 return;
1386 status = prepare_next_frag(state, &is_last_frag);
1387 if (!NT_STATUS_IS_OK(status)) {
1388 tevent_req_nterror(req, status);
1389 return;
1392 if (is_last_frag) {
1393 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1394 &state->rpc_out,
1395 DCERPC_PKT_RESPONSE);
1396 if (tevent_req_nomem(subreq, req)) {
1397 return;
1399 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1400 } else {
1401 subreq = rpc_write_send(state, state->ev,
1402 state->cli->transport,
1403 state->rpc_out.data,
1404 state->rpc_out.length);
1405 if (tevent_req_nomem(subreq, req)) {
1406 return;
1408 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1409 req);
1413 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1415 struct tevent_req *req = tevent_req_callback_data(
1416 subreq, struct tevent_req);
1417 struct rpc_api_pipe_req_state *state = tevent_req_data(
1418 req, struct rpc_api_pipe_req_state);
1419 NTSTATUS status;
1421 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1422 TALLOC_FREE(subreq);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 tevent_req_nterror(req, status);
1425 return;
1427 tevent_req_done(req);
1430 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1431 DATA_BLOB *reply_pdu)
1433 struct rpc_api_pipe_req_state *state = tevent_req_data(
1434 req, struct rpc_api_pipe_req_state);
1435 NTSTATUS status;
1437 if (tevent_req_is_nterror(req, &status)) {
1439 * We always have to initialize to reply pdu, even if there is
1440 * none. The rpccli_* caller routines expect this.
1442 *reply_pdu = data_blob_null;
1443 return status;
1446 /* return data to caller and assign it ownership of memory */
1447 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1448 reply_pdu->length = state->reply_pdu.length;
1449 state->reply_pdu.length = 0;
1451 return NT_STATUS_OK;
1454 /****************************************************************************
1455 Check the rpc bind acknowledge response.
1456 ****************************************************************************/
1458 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1459 const struct ndr_syntax_id *transfer)
1461 struct dcerpc_ack_ctx ctx;
1463 if (r->secondary_address_size == 0) {
1464 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1467 if (r->num_results < 1 || !r->ctx_list) {
1468 return false;
1471 ctx = r->ctx_list[0];
1473 /* check the transfer syntax */
1474 if ((ctx.syntax.if_version != transfer->if_version) ||
1475 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1476 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1477 return False;
1480 if (r->num_results != 0x1 || ctx.result != 0) {
1481 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1482 r->num_results, ctx.reason));
1485 DEBUG(5,("check_bind_response: accepted!\n"));
1486 return True;
1489 /*******************************************************************
1490 Creates a DCE/RPC bind authentication response.
1491 This is the packet that is sent back to the server once we
1492 have received a BIND-ACK, to finish the third leg of
1493 the authentication handshake.
1494 ********************************************************************/
1496 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1497 struct rpc_pipe_client *cli,
1498 uint32 rpc_call_id,
1499 enum dcerpc_AuthType auth_type,
1500 enum dcerpc_AuthLevel auth_level,
1501 DATA_BLOB *pauth_blob,
1502 DATA_BLOB *rpc_out)
1504 NTSTATUS status;
1505 union dcerpc_payload u;
1507 u.auth3._pad = 0;
1509 status = dcerpc_push_dcerpc_auth(mem_ctx,
1510 auth_type,
1511 auth_level,
1512 0, /* auth_pad_length */
1513 1, /* auth_context_id */
1514 pauth_blob,
1515 &u.auth3.auth_info);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 return status;
1520 status = dcerpc_push_ncacn_packet(mem_ctx,
1521 DCERPC_PKT_AUTH3,
1522 DCERPC_PFC_FLAG_FIRST |
1523 DCERPC_PFC_FLAG_LAST,
1524 pauth_blob->length,
1525 rpc_call_id,
1527 rpc_out);
1528 data_blob_free(&u.auth3.auth_info);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1531 return status;
1534 return NT_STATUS_OK;
1537 /*******************************************************************
1538 Creates a DCE/RPC bind alter context authentication request which
1539 may contain a spnego auth blobl
1540 ********************************************************************/
1542 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1543 enum dcerpc_AuthType auth_type,
1544 enum dcerpc_AuthLevel auth_level,
1545 uint32 rpc_call_id,
1546 const struct ndr_syntax_id *abstract,
1547 const struct ndr_syntax_id *transfer,
1548 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1549 DATA_BLOB *rpc_out)
1551 DATA_BLOB auth_info;
1552 NTSTATUS status;
1554 status = dcerpc_push_dcerpc_auth(mem_ctx,
1555 auth_type,
1556 auth_level,
1557 0, /* auth_pad_length */
1558 1, /* auth_context_id */
1559 pauth_blob,
1560 &auth_info);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 return status;
1565 status = create_bind_or_alt_ctx_internal(mem_ctx,
1566 DCERPC_PKT_ALTER,
1567 rpc_call_id,
1568 abstract,
1569 transfer,
1570 &auth_info,
1571 rpc_out);
1572 data_blob_free(&auth_info);
1573 return status;
1576 /****************************************************************************
1577 Do an rpc bind.
1578 ****************************************************************************/
1580 struct rpc_pipe_bind_state {
1581 struct event_context *ev;
1582 struct rpc_pipe_client *cli;
1583 DATA_BLOB rpc_out;
1584 bool auth3;
1585 uint32_t rpc_call_id;
1588 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1589 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1590 struct rpc_pipe_bind_state *state,
1591 DATA_BLOB *credentials);
1592 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1593 struct rpc_pipe_bind_state *state,
1594 DATA_BLOB *credentials);
1596 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1597 struct event_context *ev,
1598 struct rpc_pipe_client *cli,
1599 struct pipe_auth_data *auth)
1601 struct tevent_req *req, *subreq;
1602 struct rpc_pipe_bind_state *state;
1603 NTSTATUS status;
1605 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1606 if (req == NULL) {
1607 return NULL;
1610 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1611 rpccli_pipe_txt(talloc_tos(), cli),
1612 (unsigned int)auth->auth_type,
1613 (unsigned int)auth->auth_level ));
1615 state->ev = ev;
1616 state->cli = cli;
1617 state->rpc_call_id = get_rpc_call_id();
1619 cli->auth = talloc_move(cli, &auth);
1621 /* Marshall the outgoing data. */
1622 status = create_rpc_bind_req(state, cli,
1623 cli->auth,
1624 state->rpc_call_id,
1625 &cli->abstract_syntax,
1626 &cli->transfer_syntax,
1627 &state->rpc_out);
1629 if (!NT_STATUS_IS_OK(status)) {
1630 goto post_status;
1633 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1634 DCERPC_PKT_BIND_ACK);
1635 if (subreq == NULL) {
1636 goto fail;
1638 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1639 return req;
1641 post_status:
1642 tevent_req_nterror(req, status);
1643 return tevent_req_post(req, ev);
1644 fail:
1645 TALLOC_FREE(req);
1646 return NULL;
1649 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1651 struct tevent_req *req = tevent_req_callback_data(
1652 subreq, struct tevent_req);
1653 struct rpc_pipe_bind_state *state = tevent_req_data(
1654 req, struct rpc_pipe_bind_state);
1655 struct pipe_auth_data *pauth = state->cli->auth;
1656 struct gensec_security *gensec_security;
1657 struct spnego_context *spnego_ctx;
1658 struct ncacn_packet *pkt = NULL;
1659 struct dcerpc_auth auth;
1660 DATA_BLOB auth_token = data_blob_null;
1661 NTSTATUS status;
1663 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1664 TALLOC_FREE(subreq);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1667 rpccli_pipe_txt(talloc_tos(), state->cli),
1668 nt_errstr(status)));
1669 tevent_req_nterror(req, status);
1670 return;
1673 if (state->auth3) {
1674 tevent_req_done(req);
1675 return;
1678 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1679 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1680 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1681 return;
1684 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1685 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1687 switch(pauth->auth_type) {
1689 case DCERPC_AUTH_TYPE_NONE:
1690 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1691 case DCERPC_AUTH_TYPE_SCHANNEL:
1692 /* Bind complete. */
1693 tevent_req_done(req);
1694 return;
1696 case DCERPC_AUTH_TYPE_NTLMSSP:
1697 case DCERPC_AUTH_TYPE_SPNEGO:
1698 case DCERPC_AUTH_TYPE_KRB5:
1699 /* Paranoid lenght checks */
1700 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1701 + pkt->auth_length) {
1702 tevent_req_nterror(req,
1703 NT_STATUS_INFO_LENGTH_MISMATCH);
1704 return;
1706 /* get auth credentials */
1707 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1708 &pkt->u.bind_ack.auth_info,
1709 &auth, false);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1712 nt_errstr(status)));
1713 tevent_req_nterror(req, status);
1714 return;
1716 break;
1718 default:
1719 goto err_out;
1723 * For authenticated binds we may need to do 3 or 4 leg binds.
1726 switch(pauth->auth_type) {
1728 case DCERPC_AUTH_TYPE_NONE:
1729 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1730 case DCERPC_AUTH_TYPE_SCHANNEL:
1731 /* Bind complete. */
1732 tevent_req_done(req);
1733 return;
1735 case DCERPC_AUTH_TYPE_NTLMSSP:
1736 case DCERPC_AUTH_TYPE_KRB5:
1737 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1738 struct gensec_security);
1739 status = gensec_update(gensec_security, state, NULL,
1740 auth.credentials, &auth_token);
1741 if (NT_STATUS_EQUAL(status,
1742 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1743 status = rpc_bind_next_send(req, state,
1744 &auth_token);
1745 } else if (NT_STATUS_IS_OK(status)) {
1746 status = rpc_bind_finish_send(req, state,
1747 &auth_token);
1749 break;
1751 case DCERPC_AUTH_TYPE_SPNEGO:
1752 spnego_ctx = talloc_get_type_abort(pauth->auth_ctx,
1753 struct spnego_context);
1754 status = spnego_get_client_auth_token(state,
1755 spnego_ctx,
1756 &auth.credentials,
1757 &auth_token);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 break;
1761 if (auth_token.length == 0) {
1762 /* Bind complete. */
1763 tevent_req_done(req);
1764 return;
1766 if (spnego_require_more_processing(spnego_ctx)) {
1767 status = rpc_bind_next_send(req, state,
1768 &auth_token);
1769 } else {
1770 status = rpc_bind_finish_send(req, state,
1771 &auth_token);
1773 break;
1775 default:
1776 goto err_out;
1779 if (!NT_STATUS_IS_OK(status)) {
1780 tevent_req_nterror(req, status);
1782 return;
1784 err_out:
1785 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1786 (unsigned int)state->cli->auth->auth_type));
1787 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1790 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1791 struct rpc_pipe_bind_state *state,
1792 DATA_BLOB *auth_token)
1794 struct pipe_auth_data *auth = state->cli->auth;
1795 struct tevent_req *subreq;
1796 NTSTATUS status;
1798 /* Now prepare the alter context pdu. */
1799 data_blob_free(&state->rpc_out);
1801 status = create_rpc_alter_context(state,
1802 auth->auth_type,
1803 auth->auth_level,
1804 state->rpc_call_id,
1805 &state->cli->abstract_syntax,
1806 &state->cli->transfer_syntax,
1807 auth_token,
1808 &state->rpc_out);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 return status;
1813 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1814 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1815 if (subreq == NULL) {
1816 return NT_STATUS_NO_MEMORY;
1818 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1819 return NT_STATUS_OK;
1822 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1823 struct rpc_pipe_bind_state *state,
1824 DATA_BLOB *auth_token)
1826 struct pipe_auth_data *auth = state->cli->auth;
1827 struct tevent_req *subreq;
1828 NTSTATUS status;
1830 state->auth3 = true;
1832 /* Now prepare the auth3 context pdu. */
1833 data_blob_free(&state->rpc_out);
1835 status = create_rpc_bind_auth3(state, state->cli,
1836 state->rpc_call_id,
1837 auth->auth_type,
1838 auth->auth_level,
1839 auth_token,
1840 &state->rpc_out);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 return status;
1845 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1846 &state->rpc_out, DCERPC_PKT_AUTH3);
1847 if (subreq == NULL) {
1848 return NT_STATUS_NO_MEMORY;
1850 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1851 return NT_STATUS_OK;
1854 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1856 return tevent_req_simple_recv_ntstatus(req);
1859 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1860 struct pipe_auth_data *auth)
1862 TALLOC_CTX *frame = talloc_stackframe();
1863 struct event_context *ev;
1864 struct tevent_req *req;
1865 NTSTATUS status = NT_STATUS_OK;
1867 ev = event_context_init(frame);
1868 if (ev == NULL) {
1869 status = NT_STATUS_NO_MEMORY;
1870 goto fail;
1873 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1874 if (req == NULL) {
1875 status = NT_STATUS_NO_MEMORY;
1876 goto fail;
1879 if (!tevent_req_poll(req, ev)) {
1880 status = map_nt_error_from_unix(errno);
1881 goto fail;
1884 status = rpc_pipe_bind_recv(req);
1885 fail:
1886 TALLOC_FREE(frame);
1887 return status;
1890 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1892 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1893 unsigned int timeout)
1895 unsigned int old;
1897 if (rpc_cli->transport == NULL) {
1898 return RPCCLI_DEFAULT_TIMEOUT;
1901 if (rpc_cli->transport->set_timeout == NULL) {
1902 return RPCCLI_DEFAULT_TIMEOUT;
1905 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
1906 if (old == 0) {
1907 return RPCCLI_DEFAULT_TIMEOUT;
1910 return old;
1913 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
1915 if (rpc_cli == NULL) {
1916 return false;
1919 if (rpc_cli->transport == NULL) {
1920 return false;
1923 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
1926 struct rpccli_bh_state {
1927 struct rpc_pipe_client *rpc_cli;
1930 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
1932 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1933 struct rpccli_bh_state);
1935 return rpccli_is_connected(hs->rpc_cli);
1938 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
1939 uint32_t timeout)
1941 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1942 struct rpccli_bh_state);
1944 return rpccli_set_timeout(hs->rpc_cli, timeout);
1947 struct rpccli_bh_raw_call_state {
1948 DATA_BLOB in_data;
1949 DATA_BLOB out_data;
1950 uint32_t out_flags;
1953 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
1955 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
1956 struct tevent_context *ev,
1957 struct dcerpc_binding_handle *h,
1958 const struct GUID *object,
1959 uint32_t opnum,
1960 uint32_t in_flags,
1961 const uint8_t *in_data,
1962 size_t in_length)
1964 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1965 struct rpccli_bh_state);
1966 struct tevent_req *req;
1967 struct rpccli_bh_raw_call_state *state;
1968 bool ok;
1969 struct tevent_req *subreq;
1971 req = tevent_req_create(mem_ctx, &state,
1972 struct rpccli_bh_raw_call_state);
1973 if (req == NULL) {
1974 return NULL;
1976 state->in_data.data = discard_const_p(uint8_t, in_data);
1977 state->in_data.length = in_length;
1979 ok = rpccli_bh_is_connected(h);
1980 if (!ok) {
1981 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1982 return tevent_req_post(req, ev);
1985 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
1986 opnum, &state->in_data);
1987 if (tevent_req_nomem(subreq, req)) {
1988 return tevent_req_post(req, ev);
1990 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
1992 return req;
1995 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
1997 struct tevent_req *req =
1998 tevent_req_callback_data(subreq,
1999 struct tevent_req);
2000 struct rpccli_bh_raw_call_state *state =
2001 tevent_req_data(req,
2002 struct rpccli_bh_raw_call_state);
2003 NTSTATUS status;
2005 state->out_flags = 0;
2007 /* TODO: support bigendian responses */
2009 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2010 TALLOC_FREE(subreq);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 tevent_req_nterror(req, status);
2013 return;
2016 tevent_req_done(req);
2019 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2020 TALLOC_CTX *mem_ctx,
2021 uint8_t **out_data,
2022 size_t *out_length,
2023 uint32_t *out_flags)
2025 struct rpccli_bh_raw_call_state *state =
2026 tevent_req_data(req,
2027 struct rpccli_bh_raw_call_state);
2028 NTSTATUS status;
2030 if (tevent_req_is_nterror(req, &status)) {
2031 tevent_req_received(req);
2032 return status;
2035 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2036 *out_length = state->out_data.length;
2037 *out_flags = state->out_flags;
2038 tevent_req_received(req);
2039 return NT_STATUS_OK;
2042 struct rpccli_bh_disconnect_state {
2043 uint8_t _dummy;
2046 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2047 struct tevent_context *ev,
2048 struct dcerpc_binding_handle *h)
2050 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2051 struct rpccli_bh_state);
2052 struct tevent_req *req;
2053 struct rpccli_bh_disconnect_state *state;
2054 bool ok;
2056 req = tevent_req_create(mem_ctx, &state,
2057 struct rpccli_bh_disconnect_state);
2058 if (req == NULL) {
2059 return NULL;
2062 ok = rpccli_bh_is_connected(h);
2063 if (!ok) {
2064 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2065 return tevent_req_post(req, ev);
2069 * TODO: do a real async disconnect ...
2071 * For now the caller needs to free rpc_cli
2073 hs->rpc_cli = NULL;
2075 tevent_req_done(req);
2076 return tevent_req_post(req, ev);
2079 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2081 NTSTATUS status;
2083 if (tevent_req_is_nterror(req, &status)) {
2084 tevent_req_received(req);
2085 return status;
2088 tevent_req_received(req);
2089 return NT_STATUS_OK;
2092 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2094 return true;
2097 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2098 int ndr_flags,
2099 const void *_struct_ptr,
2100 const struct ndr_interface_call *call)
2102 void *struct_ptr = discard_const(_struct_ptr);
2104 if (DEBUGLEVEL < 10) {
2105 return;
2108 if (ndr_flags & NDR_IN) {
2109 ndr_print_function_debug(call->ndr_print,
2110 call->name,
2111 ndr_flags,
2112 struct_ptr);
2114 if (ndr_flags & NDR_OUT) {
2115 ndr_print_function_debug(call->ndr_print,
2116 call->name,
2117 ndr_flags,
2118 struct_ptr);
2122 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2123 .name = "rpccli",
2124 .is_connected = rpccli_bh_is_connected,
2125 .set_timeout = rpccli_bh_set_timeout,
2126 .raw_call_send = rpccli_bh_raw_call_send,
2127 .raw_call_recv = rpccli_bh_raw_call_recv,
2128 .disconnect_send = rpccli_bh_disconnect_send,
2129 .disconnect_recv = rpccli_bh_disconnect_recv,
2131 .ref_alloc = rpccli_bh_ref_alloc,
2132 .do_ndr_print = rpccli_bh_do_ndr_print,
2135 /* initialise a rpc_pipe_client binding handle */
2136 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2138 struct dcerpc_binding_handle *h;
2139 struct rpccli_bh_state *hs;
2141 h = dcerpc_binding_handle_create(c,
2142 &rpccli_bh_ops,
2143 NULL,
2144 NULL, /* TODO */
2145 &hs,
2146 struct rpccli_bh_state,
2147 __location__);
2148 if (h == NULL) {
2149 return NULL;
2151 hs->rpc_cli = c;
2153 return h;
2156 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2157 struct pipe_auth_data **presult)
2159 struct pipe_auth_data *result;
2161 result = talloc(mem_ctx, struct pipe_auth_data);
2162 if (result == NULL) {
2163 return NT_STATUS_NO_MEMORY;
2166 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2167 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2169 result->user_name = talloc_strdup(result, "");
2170 result->domain = talloc_strdup(result, "");
2171 if ((result->user_name == NULL) || (result->domain == NULL)) {
2172 TALLOC_FREE(result);
2173 return NT_STATUS_NO_MEMORY;
2176 *presult = result;
2177 return NT_STATUS_OK;
2180 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2181 struct pipe_auth_data **presult)
2183 struct pipe_auth_data *result;
2185 result = talloc(mem_ctx, struct pipe_auth_data);
2186 if (result == NULL) {
2187 return NT_STATUS_NO_MEMORY;
2190 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2191 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2193 result->user_name = talloc_strdup(result, "");
2194 result->domain = talloc_strdup(result, "");
2195 if ((result->user_name == NULL) || (result->domain == NULL)) {
2196 TALLOC_FREE(result);
2197 return NT_STATUS_NO_MEMORY;
2200 *presult = result;
2201 return NT_STATUS_OK;
2204 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2205 enum dcerpc_AuthType auth_type,
2206 enum dcerpc_AuthLevel auth_level,
2207 const char *server,
2208 const char *target_service,
2209 const char *domain,
2210 const char *username,
2211 const char *password,
2212 struct pipe_auth_data **presult)
2214 struct auth_generic_state *auth_generic_ctx;
2215 struct pipe_auth_data *result;
2216 NTSTATUS status;
2218 result = talloc(mem_ctx, struct pipe_auth_data);
2219 if (result == NULL) {
2220 return NT_STATUS_NO_MEMORY;
2223 result->auth_type = auth_type;
2224 result->auth_level = auth_level;
2226 result->user_name = talloc_strdup(result, username);
2227 result->domain = talloc_strdup(result, domain);
2228 if ((result->user_name == NULL) || (result->domain == NULL)) {
2229 status = NT_STATUS_NO_MEMORY;
2230 goto fail;
2233 status = auth_generic_client_prepare(result,
2234 &auth_generic_ctx);
2235 if (!NT_STATUS_IS_OK(status)) {
2236 goto fail;
2239 status = auth_generic_set_username(auth_generic_ctx, username);
2240 if (!NT_STATUS_IS_OK(status)) {
2241 goto fail;
2244 status = auth_generic_set_domain(auth_generic_ctx, domain);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 goto fail;
2249 status = auth_generic_set_password(auth_generic_ctx, password);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 goto fail;
2254 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 goto fail;
2259 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 goto fail;
2264 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2265 if (!NT_STATUS_IS_OK(status)) {
2266 goto fail;
2269 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2270 talloc_free(auth_generic_ctx);
2271 *presult = result;
2272 return NT_STATUS_OK;
2274 fail:
2275 TALLOC_FREE(result);
2276 return status;
2279 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2280 enum dcerpc_AuthLevel auth_level,
2281 struct netlogon_creds_CredentialState *creds,
2282 struct pipe_auth_data **presult)
2284 struct schannel_state *schannel_auth;
2285 struct pipe_auth_data *result;
2287 result = talloc(mem_ctx, struct pipe_auth_data);
2288 if (result == NULL) {
2289 return NT_STATUS_NO_MEMORY;
2292 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2293 result->auth_level = auth_level;
2295 result->user_name = talloc_strdup(result, "");
2296 result->domain = talloc_strdup(result, domain);
2297 if ((result->user_name == NULL) || (result->domain == NULL)) {
2298 goto fail;
2301 schannel_auth = talloc(result, struct schannel_state);
2302 if (schannel_auth == NULL) {
2303 goto fail;
2306 schannel_auth->state = SCHANNEL_STATE_START;
2307 schannel_auth->seq_num = 0;
2308 schannel_auth->initiator = true;
2309 schannel_auth->creds = netlogon_creds_copy(result, creds);
2311 result->auth_ctx = schannel_auth;
2312 *presult = result;
2313 return NT_STATUS_OK;
2315 fail:
2316 TALLOC_FREE(result);
2317 return NT_STATUS_NO_MEMORY;
2321 * Create an rpc pipe client struct, connecting to a tcp port.
2323 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2324 uint16_t port,
2325 const struct ndr_syntax_id *abstract_syntax,
2326 struct rpc_pipe_client **presult)
2328 struct rpc_pipe_client *result;
2329 struct sockaddr_storage addr;
2330 NTSTATUS status;
2331 int fd;
2333 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2334 if (result == NULL) {
2335 return NT_STATUS_NO_MEMORY;
2338 result->abstract_syntax = *abstract_syntax;
2339 result->transfer_syntax = ndr_transfer_syntax;
2341 result->desthost = talloc_strdup(result, host);
2342 result->srv_name_slash = talloc_asprintf_strupper_m(
2343 result, "\\\\%s", result->desthost);
2344 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2345 status = NT_STATUS_NO_MEMORY;
2346 goto fail;
2349 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2350 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2352 if (!resolve_name(host, &addr, 0, false)) {
2353 status = NT_STATUS_NOT_FOUND;
2354 goto fail;
2357 status = open_socket_out(&addr, port, 60*1000, &fd);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 goto fail;
2361 set_socket_options(fd, lp_socket_options());
2363 status = rpc_transport_sock_init(result, fd, &result->transport);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 close(fd);
2366 goto fail;
2369 result->transport->transport = NCACN_IP_TCP;
2371 result->binding_handle = rpccli_bh_create(result);
2372 if (result->binding_handle == NULL) {
2373 TALLOC_FREE(result);
2374 return NT_STATUS_NO_MEMORY;
2377 *presult = result;
2378 return NT_STATUS_OK;
2380 fail:
2381 TALLOC_FREE(result);
2382 return status;
2386 * Determine the tcp port on which a dcerpc interface is listening
2387 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2388 * target host.
2390 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2391 const struct ndr_syntax_id *abstract_syntax,
2392 uint16_t *pport)
2394 NTSTATUS status;
2395 struct rpc_pipe_client *epm_pipe = NULL;
2396 struct dcerpc_binding_handle *epm_handle = NULL;
2397 struct pipe_auth_data *auth = NULL;
2398 struct dcerpc_binding *map_binding = NULL;
2399 struct dcerpc_binding *res_binding = NULL;
2400 struct epm_twr_t *map_tower = NULL;
2401 struct epm_twr_t *res_towers = NULL;
2402 struct policy_handle *entry_handle = NULL;
2403 uint32_t num_towers = 0;
2404 uint32_t max_towers = 1;
2405 struct epm_twr_p_t towers;
2406 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2407 uint32_t result = 0;
2409 if (pport == NULL) {
2410 status = NT_STATUS_INVALID_PARAMETER;
2411 goto done;
2414 if (ndr_syntax_id_equal(abstract_syntax,
2415 &ndr_table_epmapper.syntax_id)) {
2416 *pport = 135;
2417 return NT_STATUS_OK;
2420 /* open the connection to the endpoint mapper */
2421 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2422 &ndr_table_epmapper.syntax_id,
2423 &epm_pipe);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 goto done;
2428 epm_handle = epm_pipe->binding_handle;
2430 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2431 if (!NT_STATUS_IS_OK(status)) {
2432 goto done;
2435 status = rpc_pipe_bind(epm_pipe, auth);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 goto done;
2440 /* create tower for asking the epmapper */
2442 map_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
2443 if (map_binding == NULL) {
2444 status = NT_STATUS_NO_MEMORY;
2445 goto done;
2448 map_binding->transport = NCACN_IP_TCP;
2449 map_binding->object = *abstract_syntax;
2450 map_binding->host = host; /* needed? */
2451 map_binding->endpoint = "0"; /* correct? needed? */
2453 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2454 if (map_tower == NULL) {
2455 status = NT_STATUS_NO_MEMORY;
2456 goto done;
2459 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2460 &(map_tower->tower));
2461 if (!NT_STATUS_IS_OK(status)) {
2462 goto done;
2465 /* allocate further parameters for the epm_Map call */
2467 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2468 if (res_towers == NULL) {
2469 status = NT_STATUS_NO_MEMORY;
2470 goto done;
2472 towers.twr = res_towers;
2474 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2475 if (entry_handle == NULL) {
2476 status = NT_STATUS_NO_MEMORY;
2477 goto done;
2480 /* ask the endpoint mapper for the port */
2482 status = dcerpc_epm_Map(epm_handle,
2483 tmp_ctx,
2484 discard_const_p(struct GUID,
2485 &(abstract_syntax->uuid)),
2486 map_tower,
2487 entry_handle,
2488 max_towers,
2489 &num_towers,
2490 &towers,
2491 &result);
2493 if (!NT_STATUS_IS_OK(status)) {
2494 goto done;
2497 if (result != EPMAPPER_STATUS_OK) {
2498 status = NT_STATUS_UNSUCCESSFUL;
2499 goto done;
2502 if (num_towers != 1) {
2503 status = NT_STATUS_UNSUCCESSFUL;
2504 goto done;
2507 /* extract the port from the answer */
2509 status = dcerpc_binding_from_tower(tmp_ctx,
2510 &(towers.twr->tower),
2511 &res_binding);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 goto done;
2516 /* are further checks here necessary? */
2517 if (res_binding->transport != NCACN_IP_TCP) {
2518 status = NT_STATUS_UNSUCCESSFUL;
2519 goto done;
2522 *pport = (uint16_t)atoi(res_binding->endpoint);
2524 done:
2525 TALLOC_FREE(tmp_ctx);
2526 return status;
2530 * Create a rpc pipe client struct, connecting to a host via tcp.
2531 * The port is determined by asking the endpoint mapper on the given
2532 * host.
2534 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2535 const struct ndr_syntax_id *abstract_syntax,
2536 struct rpc_pipe_client **presult)
2538 NTSTATUS status;
2539 uint16_t port = 0;
2541 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 return status;
2546 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2547 abstract_syntax, presult);
2550 /********************************************************************
2551 Create a rpc pipe client struct, connecting to a unix domain socket
2552 ********************************************************************/
2553 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2554 const struct ndr_syntax_id *abstract_syntax,
2555 struct rpc_pipe_client **presult)
2557 struct rpc_pipe_client *result;
2558 struct sockaddr_un addr;
2559 NTSTATUS status;
2560 int fd;
2562 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2563 if (result == NULL) {
2564 return NT_STATUS_NO_MEMORY;
2567 result->abstract_syntax = *abstract_syntax;
2568 result->transfer_syntax = ndr_transfer_syntax;
2570 result->desthost = get_myname(result);
2571 result->srv_name_slash = talloc_asprintf_strupper_m(
2572 result, "\\\\%s", result->desthost);
2573 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2574 status = NT_STATUS_NO_MEMORY;
2575 goto fail;
2578 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2579 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2581 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2582 if (fd == -1) {
2583 status = map_nt_error_from_unix(errno);
2584 goto fail;
2587 ZERO_STRUCT(addr);
2588 addr.sun_family = AF_UNIX;
2589 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2591 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2592 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2593 strerror(errno)));
2594 close(fd);
2595 return map_nt_error_from_unix(errno);
2598 status = rpc_transport_sock_init(result, fd, &result->transport);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 close(fd);
2601 goto fail;
2604 result->transport->transport = NCALRPC;
2606 result->binding_handle = rpccli_bh_create(result);
2607 if (result->binding_handle == NULL) {
2608 TALLOC_FREE(result);
2609 return NT_STATUS_NO_MEMORY;
2612 *presult = result;
2613 return NT_STATUS_OK;
2615 fail:
2616 TALLOC_FREE(result);
2617 return status;
2620 struct rpc_pipe_client_np_ref {
2621 struct cli_state *cli;
2622 struct rpc_pipe_client *pipe;
2625 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2627 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2628 return 0;
2631 /****************************************************************************
2632 Open a named pipe over SMB to a remote server.
2634 * CAVEAT CALLER OF THIS FUNCTION:
2635 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2636 * so be sure that this function is called AFTER any structure (vs pointer)
2637 * assignment of the cli. In particular, libsmbclient does structure
2638 * assignments of cli, which invalidates the data in the returned
2639 * rpc_pipe_client if this function is called before the structure assignment
2640 * of cli.
2642 ****************************************************************************/
2644 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2645 const struct ndr_syntax_id *abstract_syntax,
2646 struct rpc_pipe_client **presult)
2648 struct rpc_pipe_client *result;
2649 NTSTATUS status;
2650 struct rpc_pipe_client_np_ref *np_ref;
2652 /* sanity check to protect against crashes */
2654 if ( !cli ) {
2655 return NT_STATUS_INVALID_HANDLE;
2658 result = talloc_zero(NULL, struct rpc_pipe_client);
2659 if (result == NULL) {
2660 return NT_STATUS_NO_MEMORY;
2663 result->abstract_syntax = *abstract_syntax;
2664 result->transfer_syntax = ndr_transfer_syntax;
2665 result->desthost = talloc_strdup(result, cli_state_remote_name(cli));
2666 result->srv_name_slash = talloc_asprintf_strupper_m(
2667 result, "\\\\%s", result->desthost);
2669 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2670 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2672 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2673 TALLOC_FREE(result);
2674 return NT_STATUS_NO_MEMORY;
2677 status = rpc_transport_np_init(result, cli, abstract_syntax,
2678 &result->transport);
2679 if (!NT_STATUS_IS_OK(status)) {
2680 TALLOC_FREE(result);
2681 return status;
2684 result->transport->transport = NCACN_NP;
2686 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2687 if (np_ref == NULL) {
2688 TALLOC_FREE(result);
2689 return NT_STATUS_NO_MEMORY;
2691 np_ref->cli = cli;
2692 np_ref->pipe = result;
2694 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2695 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2697 result->binding_handle = rpccli_bh_create(result);
2698 if (result->binding_handle == NULL) {
2699 TALLOC_FREE(result);
2700 return NT_STATUS_NO_MEMORY;
2703 *presult = result;
2704 return NT_STATUS_OK;
2707 /****************************************************************************
2708 Open a pipe to a remote server.
2709 ****************************************************************************/
2711 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2712 enum dcerpc_transport_t transport,
2713 const struct ndr_syntax_id *interface,
2714 struct rpc_pipe_client **presult)
2716 switch (transport) {
2717 case NCACN_IP_TCP:
2718 return rpc_pipe_open_tcp(NULL, cli_state_remote_name(cli),
2719 interface, presult);
2720 case NCACN_NP:
2721 return rpc_pipe_open_np(cli, interface, presult);
2722 default:
2723 return NT_STATUS_NOT_IMPLEMENTED;
2727 /****************************************************************************
2728 Open a named pipe to an SMB server and bind anonymously.
2729 ****************************************************************************/
2731 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2732 enum dcerpc_transport_t transport,
2733 const struct ndr_syntax_id *interface,
2734 struct rpc_pipe_client **presult)
2736 struct rpc_pipe_client *result;
2737 struct pipe_auth_data *auth;
2738 NTSTATUS status;
2740 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 return status;
2745 status = rpccli_anon_bind_data(result, &auth);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2748 nt_errstr(status)));
2749 TALLOC_FREE(result);
2750 return status;
2754 * This is a bit of an abstraction violation due to the fact that an
2755 * anonymous bind on an authenticated SMB inherits the user/domain
2756 * from the enclosing SMB creds
2759 TALLOC_FREE(auth->user_name);
2760 TALLOC_FREE(auth->domain);
2762 auth->user_name = talloc_strdup(auth, cli->user_name);
2763 auth->domain = talloc_strdup(auth, cli->domain);
2764 auth->user_session_key = data_blob_talloc(auth,
2765 cli->user_session_key.data,
2766 cli->user_session_key.length);
2768 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2769 TALLOC_FREE(result);
2770 return NT_STATUS_NO_MEMORY;
2773 status = rpc_pipe_bind(result, auth);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 int lvl = 0;
2776 if (ndr_syntax_id_equal(interface,
2777 &ndr_table_dssetup.syntax_id)) {
2778 /* non AD domains just don't have this pipe, avoid
2779 * level 0 statement in that case - gd */
2780 lvl = 3;
2782 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2783 "%s failed with error %s\n",
2784 get_pipe_name_from_syntax(talloc_tos(), interface),
2785 nt_errstr(status) ));
2786 TALLOC_FREE(result);
2787 return status;
2790 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2791 "%s and bound anonymously.\n",
2792 get_pipe_name_from_syntax(talloc_tos(), interface),
2793 result->desthost));
2795 *presult = result;
2796 return NT_STATUS_OK;
2799 /****************************************************************************
2800 ****************************************************************************/
2802 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2803 const struct ndr_syntax_id *interface,
2804 struct rpc_pipe_client **presult)
2806 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2807 interface, presult);
2810 /****************************************************************************
2811 Open a named pipe to an SMB server and bind using the mech specified
2812 ****************************************************************************/
2814 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2815 const struct ndr_syntax_id *interface,
2816 enum dcerpc_transport_t transport,
2817 enum dcerpc_AuthType auth_type,
2818 enum dcerpc_AuthLevel auth_level,
2819 const char *server,
2820 const char *domain,
2821 const char *username,
2822 const char *password,
2823 struct rpc_pipe_client **presult)
2825 struct rpc_pipe_client *result;
2826 struct pipe_auth_data *auth = NULL;
2827 const char *target_service = "cifs"; /* TODO: Determine target service from the bindings or interface table */
2828 NTSTATUS status;
2830 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 return status;
2835 status = rpccli_generic_bind_data(result,
2836 auth_type, auth_level,
2837 server, target_service,
2838 domain, username, password,
2839 &auth);
2840 if (!NT_STATUS_IS_OK(status)) {
2841 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2842 nt_errstr(status)));
2843 goto err;
2846 status = rpc_pipe_bind(result, auth);
2847 if (!NT_STATUS_IS_OK(status)) {
2848 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
2849 nt_errstr(status) ));
2850 goto err;
2853 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
2854 "machine %s and bound as user %s\\%s.\n",
2855 get_pipe_name_from_syntax(talloc_tos(), interface),
2856 result->desthost, domain, username));
2858 *presult = result;
2859 return NT_STATUS_OK;
2861 err:
2863 TALLOC_FREE(result);
2864 return status;
2867 /****************************************************************************
2868 External interface.
2869 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2870 using session_key. sign and seal.
2872 The *pdc will be stolen onto this new pipe
2873 ****************************************************************************/
2875 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2876 const struct ndr_syntax_id *interface,
2877 enum dcerpc_transport_t transport,
2878 enum dcerpc_AuthLevel auth_level,
2879 const char *domain,
2880 struct netlogon_creds_CredentialState **pdc,
2881 struct rpc_pipe_client **presult)
2883 struct rpc_pipe_client *result;
2884 struct pipe_auth_data *auth;
2885 NTSTATUS status;
2887 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2888 if (!NT_STATUS_IS_OK(status)) {
2889 return status;
2892 status = rpccli_schannel_bind_data(result, domain, auth_level,
2893 *pdc, &auth);
2894 if (!NT_STATUS_IS_OK(status)) {
2895 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
2896 nt_errstr(status)));
2897 TALLOC_FREE(result);
2898 return status;
2901 status = rpc_pipe_bind(result, auth);
2902 if (!NT_STATUS_IS_OK(status)) {
2903 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
2904 "cli_rpc_pipe_bind failed with error %s\n",
2905 nt_errstr(status) ));
2906 TALLOC_FREE(result);
2907 return status;
2911 * The credentials on a new netlogon pipe are the ones we are passed
2912 * in - copy them over
2914 result->dc = netlogon_creds_copy(result, *pdc);
2915 if (result->dc == NULL) {
2916 TALLOC_FREE(result);
2917 return NT_STATUS_NO_MEMORY;
2920 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2921 "for domain %s and bound using schannel.\n",
2922 get_pipe_name_from_syntax(talloc_tos(), interface),
2923 result->desthost, domain));
2925 *presult = result;
2926 return NT_STATUS_OK;
2929 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
2930 const struct ndr_syntax_id *interface,
2931 enum dcerpc_transport_t transport,
2932 enum dcerpc_AuthLevel auth_level,
2933 const char *server,
2934 const char *username,
2935 const char *password,
2936 struct rpc_pipe_client **presult)
2938 struct rpc_pipe_client *result;
2939 struct pipe_auth_data *auth;
2940 struct spnego_context *spnego_ctx;
2941 NTSTATUS status;
2943 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 return status;
2948 auth = talloc(result, struct pipe_auth_data);
2949 if (auth == NULL) {
2950 status = NT_STATUS_NO_MEMORY;
2951 goto err_out;
2953 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
2954 auth->auth_level = auth_level;
2956 if (!username) {
2957 username = "";
2959 auth->user_name = talloc_strdup(auth, username);
2960 if (!auth->user_name) {
2961 status = NT_STATUS_NO_MEMORY;
2962 goto err_out;
2965 /* Fixme, should we fetch/set the Realm ? */
2966 auth->domain = talloc_strdup(auth, "");
2967 if (!auth->domain) {
2968 status = NT_STATUS_NO_MEMORY;
2969 goto err_out;
2972 status = spnego_gssapi_init_client(auth,
2973 (auth->auth_level ==
2974 DCERPC_AUTH_LEVEL_INTEGRITY),
2975 (auth->auth_level ==
2976 DCERPC_AUTH_LEVEL_PRIVACY),
2977 true,
2978 NULL, server, "cifs",
2979 username, password,
2980 &spnego_ctx);
2981 if (!NT_STATUS_IS_OK(status)) {
2982 DEBUG(0, ("spnego_init_client returned %s\n",
2983 nt_errstr(status)));
2984 goto err_out;
2986 auth->auth_ctx = spnego_ctx;
2988 status = rpc_pipe_bind(result, auth);
2989 if (!NT_STATUS_IS_OK(status)) {
2990 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
2991 nt_errstr(status)));
2992 goto err_out;
2995 *presult = result;
2996 return NT_STATUS_OK;
2998 err_out:
2999 TALLOC_FREE(result);
3000 return status;
3003 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3004 const struct ndr_syntax_id *interface,
3005 enum dcerpc_transport_t transport,
3006 enum dcerpc_AuthLevel auth_level,
3007 const char *domain,
3008 const char *username,
3009 const char *password,
3010 struct rpc_pipe_client **presult)
3012 struct rpc_pipe_client *result;
3013 struct pipe_auth_data *auth;
3014 struct spnego_context *spnego_ctx;
3015 NTSTATUS status;
3016 const char *server = NULL;
3017 const char *target_service = "cifs"; /* TODO: Determine target service from the bindings or interface table */
3019 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3020 if (!NT_STATUS_IS_OK(status)) {
3021 return status;
3024 auth = talloc(result, struct pipe_auth_data);
3025 if (auth == NULL) {
3026 status = NT_STATUS_NO_MEMORY;
3027 goto err_out;
3029 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3030 auth->auth_level = auth_level;
3032 if (!username) {
3033 username = "";
3035 auth->user_name = talloc_strdup(auth, username);
3036 if (!auth->user_name) {
3037 status = NT_STATUS_NO_MEMORY;
3038 goto err_out;
3041 if (!domain) {
3042 domain = "";
3044 auth->domain = talloc_strdup(auth, domain);
3045 if (!auth->domain) {
3046 status = NT_STATUS_NO_MEMORY;
3047 goto err_out;
3050 status = spnego_generic_init_client(auth,
3051 GENSEC_OID_NTLMSSP,
3052 (auth->auth_level ==
3053 DCERPC_AUTH_LEVEL_INTEGRITY),
3054 (auth->auth_level ==
3055 DCERPC_AUTH_LEVEL_PRIVACY),
3056 true,
3057 server, target_service,
3058 domain, username, password,
3059 &spnego_ctx);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 DEBUG(0, ("spnego_init_client returned %s\n",
3062 nt_errstr(status)));
3063 goto err_out;
3065 auth->auth_ctx = spnego_ctx;
3067 status = rpc_pipe_bind(result, auth);
3068 if (!NT_STATUS_IS_OK(status)) {
3069 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3070 nt_errstr(status)));
3071 goto err_out;
3074 *presult = result;
3075 return NT_STATUS_OK;
3077 err_out:
3078 TALLOC_FREE(result);
3079 return status;
3082 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3083 struct rpc_pipe_client *cli,
3084 DATA_BLOB *session_key)
3086 NTSTATUS status;
3087 struct pipe_auth_data *a;
3088 struct schannel_state *schannel_auth;
3089 struct gensec_security *gensec_security;
3090 struct spnego_context *spnego_ctx;
3091 DATA_BLOB sk = data_blob_null;
3092 bool make_dup = false;
3094 if (!session_key || !cli) {
3095 return NT_STATUS_INVALID_PARAMETER;
3098 a = cli->auth;
3100 if (a == NULL) {
3101 return NT_STATUS_INVALID_PARAMETER;
3104 switch (cli->auth->auth_type) {
3105 case DCERPC_AUTH_TYPE_SCHANNEL:
3106 schannel_auth = talloc_get_type_abort(a->auth_ctx,
3107 struct schannel_state);
3108 sk = data_blob_const(schannel_auth->creds->session_key, 16);
3109 make_dup = true;
3110 break;
3111 case DCERPC_AUTH_TYPE_SPNEGO:
3112 spnego_ctx = talloc_get_type_abort(a->auth_ctx,
3113 struct spnego_context);
3114 sk = spnego_get_session_key(mem_ctx, spnego_ctx);
3115 make_dup = false;
3116 break;
3117 case DCERPC_AUTH_TYPE_NTLMSSP:
3118 case DCERPC_AUTH_TYPE_KRB5:
3119 gensec_security = talloc_get_type_abort(a->auth_ctx,
3120 struct gensec_security);
3121 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3122 if (!NT_STATUS_IS_OK(status)) {
3123 return status;
3125 make_dup = false;
3126 break;
3127 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3128 case DCERPC_AUTH_TYPE_NONE:
3129 sk = data_blob_const(a->user_session_key.data,
3130 a->user_session_key.length);
3131 make_dup = true;
3132 break;
3133 default:
3134 break;
3137 if (!sk.data) {
3138 return NT_STATUS_NO_USER_SESSION_KEY;
3141 if (make_dup) {
3142 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3143 } else {
3144 *session_key = sk;
3147 return NT_STATUS_OK;