docs: use popt.autohelp in smbtree manpage.
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob13423540ecfc1419f5e1f68221449f6ce7e2b2ce
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client routines
4 * Largely rewritten by Jeremy Allison 2005.
5 * Heavily modified by Simo Sorce 2010.
6 * Copyright Andrew Bartlett 2011.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "auth_generic.h"
28 #include "librpc/gen_ndr/ndr_dcerpc.h"
29 #include "librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "librpc/rpc/dcerpc.h"
31 #include "rpc_dce.h"
32 #include "cli_pipe.h"
33 #include "libsmb/libsmb.h"
34 #include "auth/gensec/gensec.h"
35 #include "auth/credentials/credentials.h"
36 #include "../libcli/smb/smbXcli_base.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_RPC_CLI
41 /********************************************************************
42 Pipe description for a DEBUG
43 ********************************************************************/
44 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
45 struct rpc_pipe_client *cli)
47 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
48 if (result == NULL) {
49 return "pipe";
51 return result;
54 /********************************************************************
55 Rpc pipe call id.
56 ********************************************************************/
58 static uint32 get_rpc_call_id(void)
60 static uint32 call_id = 0;
61 return ++call_id;
64 /*******************************************************************
65 Use SMBreadX to get rest of one fragment's worth of rpc data.
66 Reads the whole size or give an error message
67 ********************************************************************/
69 struct rpc_read_state {
70 struct tevent_context *ev;
71 struct rpc_cli_transport *transport;
72 uint8_t *data;
73 size_t size;
74 size_t num_read;
77 static void rpc_read_done(struct tevent_req *subreq);
79 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
80 struct tevent_context *ev,
81 struct rpc_cli_transport *transport,
82 uint8_t *data, size_t size)
84 struct tevent_req *req, *subreq;
85 struct rpc_read_state *state;
87 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
88 if (req == NULL) {
89 return NULL;
91 state->ev = ev;
92 state->transport = transport;
93 state->data = data;
94 state->size = size;
95 state->num_read = 0;
97 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
99 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
100 transport->priv);
101 if (subreq == NULL) {
102 goto fail;
104 tevent_req_set_callback(subreq, rpc_read_done, req);
105 return req;
107 fail:
108 TALLOC_FREE(req);
109 return NULL;
112 static void rpc_read_done(struct tevent_req *subreq)
114 struct tevent_req *req = tevent_req_callback_data(
115 subreq, struct tevent_req);
116 struct rpc_read_state *state = tevent_req_data(
117 req, struct rpc_read_state);
118 NTSTATUS status;
119 ssize_t received;
121 status = state->transport->read_recv(subreq, &received);
122 TALLOC_FREE(subreq);
123 if (!NT_STATUS_IS_OK(status)) {
124 tevent_req_nterror(req, status);
125 return;
128 state->num_read += received;
129 if (state->num_read == state->size) {
130 tevent_req_done(req);
131 return;
134 subreq = state->transport->read_send(state, state->ev,
135 state->data + state->num_read,
136 state->size - state->num_read,
137 state->transport->priv);
138 if (tevent_req_nomem(subreq, req)) {
139 return;
141 tevent_req_set_callback(subreq, rpc_read_done, req);
144 static NTSTATUS rpc_read_recv(struct tevent_req *req)
146 return tevent_req_simple_recv_ntstatus(req);
149 struct rpc_write_state {
150 struct tevent_context *ev;
151 struct rpc_cli_transport *transport;
152 const uint8_t *data;
153 size_t size;
154 size_t num_written;
157 static void rpc_write_done(struct tevent_req *subreq);
159 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
160 struct tevent_context *ev,
161 struct rpc_cli_transport *transport,
162 const uint8_t *data, size_t size)
164 struct tevent_req *req, *subreq;
165 struct rpc_write_state *state;
167 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
168 if (req == NULL) {
169 return NULL;
171 state->ev = ev;
172 state->transport = transport;
173 state->data = data;
174 state->size = size;
175 state->num_written = 0;
177 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
179 subreq = transport->write_send(state, ev, data, size, transport->priv);
180 if (subreq == NULL) {
181 goto fail;
183 tevent_req_set_callback(subreq, rpc_write_done, req);
184 return req;
185 fail:
186 TALLOC_FREE(req);
187 return NULL;
190 static void rpc_write_done(struct tevent_req *subreq)
192 struct tevent_req *req = tevent_req_callback_data(
193 subreq, struct tevent_req);
194 struct rpc_write_state *state = tevent_req_data(
195 req, struct rpc_write_state);
196 NTSTATUS status;
197 ssize_t written;
199 status = state->transport->write_recv(subreq, &written);
200 TALLOC_FREE(subreq);
201 if (!NT_STATUS_IS_OK(status)) {
202 tevent_req_nterror(req, status);
203 return;
206 state->num_written += written;
208 if (state->num_written == state->size) {
209 tevent_req_done(req);
210 return;
213 subreq = state->transport->write_send(state, state->ev,
214 state->data + state->num_written,
215 state->size - state->num_written,
216 state->transport->priv);
217 if (tevent_req_nomem(subreq, req)) {
218 return;
220 tevent_req_set_callback(subreq, rpc_write_done, req);
223 static NTSTATUS rpc_write_recv(struct tevent_req *req)
225 return tevent_req_simple_recv_ntstatus(req);
229 /****************************************************************************
230 Try and get a PDU's worth of data from current_pdu. If not, then read more
231 from the wire.
232 ****************************************************************************/
234 struct get_complete_frag_state {
235 struct tevent_context *ev;
236 struct rpc_pipe_client *cli;
237 uint16_t frag_len;
238 DATA_BLOB *pdu;
241 static void get_complete_frag_got_header(struct tevent_req *subreq);
242 static void get_complete_frag_got_rest(struct tevent_req *subreq);
244 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
245 struct tevent_context *ev,
246 struct rpc_pipe_client *cli,
247 DATA_BLOB *pdu)
249 struct tevent_req *req, *subreq;
250 struct get_complete_frag_state *state;
251 size_t received;
252 NTSTATUS status;
254 req = tevent_req_create(mem_ctx, &state,
255 struct get_complete_frag_state);
256 if (req == NULL) {
257 return NULL;
259 state->ev = ev;
260 state->cli = cli;
261 state->frag_len = RPC_HEADER_LEN;
262 state->pdu = pdu;
264 received = pdu->length;
265 if (received < RPC_HEADER_LEN) {
266 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
267 status = NT_STATUS_NO_MEMORY;
268 goto post_status;
270 subreq = rpc_read_send(state, state->ev,
271 state->cli->transport,
272 pdu->data + received,
273 RPC_HEADER_LEN - received);
274 if (subreq == NULL) {
275 status = NT_STATUS_NO_MEMORY;
276 goto post_status;
278 tevent_req_set_callback(subreq, get_complete_frag_got_header,
279 req);
280 return req;
283 state->frag_len = dcerpc_get_frag_length(pdu);
286 * Ensure we have frag_len bytes of data.
288 if (received < state->frag_len) {
289 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
290 status = NT_STATUS_NO_MEMORY;
291 goto post_status;
293 subreq = rpc_read_send(state, state->ev,
294 state->cli->transport,
295 pdu->data + received,
296 state->frag_len - received);
297 if (subreq == NULL) {
298 status = NT_STATUS_NO_MEMORY;
299 goto post_status;
301 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
302 req);
303 return req;
306 status = NT_STATUS_OK;
307 post_status:
308 if (NT_STATUS_IS_OK(status)) {
309 tevent_req_done(req);
310 } else {
311 tevent_req_nterror(req, status);
313 return tevent_req_post(req, ev);
316 static void get_complete_frag_got_header(struct tevent_req *subreq)
318 struct tevent_req *req = tevent_req_callback_data(
319 subreq, struct tevent_req);
320 struct get_complete_frag_state *state = tevent_req_data(
321 req, struct get_complete_frag_state);
322 NTSTATUS status;
324 status = rpc_read_recv(subreq);
325 TALLOC_FREE(subreq);
326 if (!NT_STATUS_IS_OK(status)) {
327 tevent_req_nterror(req, status);
328 return;
331 state->frag_len = dcerpc_get_frag_length(state->pdu);
333 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
334 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
335 return;
339 * We're here in this piece of code because we've read exactly
340 * RPC_HEADER_LEN bytes into state->pdu.
343 subreq = rpc_read_send(state, state->ev, state->cli->transport,
344 state->pdu->data + RPC_HEADER_LEN,
345 state->frag_len - RPC_HEADER_LEN);
346 if (tevent_req_nomem(subreq, req)) {
347 return;
349 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
352 static void get_complete_frag_got_rest(struct tevent_req *subreq)
354 struct tevent_req *req = tevent_req_callback_data(
355 subreq, struct tevent_req);
356 NTSTATUS status;
358 status = rpc_read_recv(subreq);
359 TALLOC_FREE(subreq);
360 if (!NT_STATUS_IS_OK(status)) {
361 tevent_req_nterror(req, status);
362 return;
364 tevent_req_done(req);
367 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
369 return tevent_req_simple_recv_ntstatus(req);
372 /****************************************************************************
373 Do basic authentication checks on an incoming pdu.
374 ****************************************************************************/
376 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
377 struct rpc_pipe_client *cli,
378 struct ncacn_packet *pkt,
379 DATA_BLOB *pdu,
380 uint8_t expected_pkt_type,
381 DATA_BLOB *rdata,
382 DATA_BLOB *reply_pdu)
384 struct dcerpc_response *r;
385 NTSTATUS ret = NT_STATUS_OK;
386 size_t pad_len = 0;
389 * Point the return values at the real data including the RPC
390 * header. Just in case the caller wants it.
392 *rdata = *pdu;
394 /* Ensure we have the correct type. */
395 switch (pkt->ptype) {
396 case DCERPC_PKT_ALTER_RESP:
397 case DCERPC_PKT_BIND_ACK:
399 /* Client code never receives this kind of packets */
400 break;
403 case DCERPC_PKT_RESPONSE:
405 r = &pkt->u.response;
407 /* Here's where we deal with incoming sign/seal. */
408 ret = dcerpc_check_auth(cli->auth, pkt,
409 &r->stub_and_verifier,
410 DCERPC_RESPONSE_LENGTH,
411 pdu, &pad_len);
412 if (!NT_STATUS_IS_OK(ret)) {
413 return ret;
416 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
417 return NT_STATUS_BUFFER_TOO_SMALL;
420 /* Point the return values at the NDR data. */
421 rdata->data = r->stub_and_verifier.data;
423 if (pkt->auth_length) {
424 /* We've already done integer wrap tests in
425 * dcerpc_check_auth(). */
426 rdata->length = r->stub_and_verifier.length
427 - pad_len
428 - DCERPC_AUTH_TRAILER_LENGTH
429 - pkt->auth_length;
430 } else {
431 rdata->length = r->stub_and_verifier.length;
434 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
435 (long unsigned int)pdu->length,
436 (long unsigned int)rdata->length,
437 (unsigned int)pad_len));
440 * If this is the first reply, and the allocation hint is
441 * reasonable, try and set up the reply_pdu DATA_BLOB to the
442 * correct size.
445 if ((reply_pdu->length == 0) &&
446 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
447 if (!data_blob_realloc(mem_ctx, reply_pdu,
448 r->alloc_hint)) {
449 DEBUG(0, ("reply alloc hint %d too "
450 "large to allocate\n",
451 (int)r->alloc_hint));
452 return NT_STATUS_NO_MEMORY;
456 break;
458 case DCERPC_PKT_BIND_NAK:
459 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
460 rpccli_pipe_txt(talloc_tos(), cli)));
461 /* Use this for now... */
462 return NT_STATUS_NETWORK_ACCESS_DENIED;
464 case DCERPC_PKT_FAULT:
466 DEBUG(1, (__location__ ": RPC fault code %s received "
467 "from %s!\n",
468 dcerpc_errstr(talloc_tos(),
469 pkt->u.fault.status),
470 rpccli_pipe_txt(talloc_tos(), cli)));
472 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
474 default:
475 DEBUG(0, (__location__ "Unknown packet type %u received "
476 "from %s!\n",
477 (unsigned int)pkt->ptype,
478 rpccli_pipe_txt(talloc_tos(), cli)));
479 return NT_STATUS_INVALID_INFO_CLASS;
482 if (pkt->ptype != expected_pkt_type) {
483 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
484 "RPC packet type - %u, not %u\n",
485 rpccli_pipe_txt(talloc_tos(), cli),
486 pkt->ptype, expected_pkt_type));
487 return NT_STATUS_INVALID_INFO_CLASS;
490 /* Do this just before return - we don't want to modify any rpc header
491 data before now as we may have needed to do cryptographic actions on
492 it before. */
494 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
495 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
496 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
497 "fragment first/last ON.\n"));
498 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
501 return NT_STATUS_OK;
504 /****************************************************************************
505 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
506 ****************************************************************************/
508 struct cli_api_pipe_state {
509 struct tevent_context *ev;
510 struct rpc_cli_transport *transport;
511 uint8_t *rdata;
512 uint32_t rdata_len;
515 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
516 static void cli_api_pipe_write_done(struct tevent_req *subreq);
517 static void cli_api_pipe_read_done(struct tevent_req *subreq);
519 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
520 struct tevent_context *ev,
521 struct rpc_cli_transport *transport,
522 uint8_t *data, size_t data_len,
523 uint32_t max_rdata_len)
525 struct tevent_req *req, *subreq;
526 struct cli_api_pipe_state *state;
527 NTSTATUS status;
529 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
530 if (req == NULL) {
531 return NULL;
533 state->ev = ev;
534 state->transport = transport;
536 if (max_rdata_len < RPC_HEADER_LEN) {
538 * For a RPC reply we always need at least RPC_HEADER_LEN
539 * bytes. We check this here because we will receive
540 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
542 status = NT_STATUS_INVALID_PARAMETER;
543 goto post_status;
546 if (transport->trans_send != NULL) {
547 subreq = transport->trans_send(state, ev, data, data_len,
548 max_rdata_len, transport->priv);
549 if (subreq == NULL) {
550 goto fail;
552 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
553 return req;
557 * If the transport does not provide a "trans" routine, i.e. for
558 * example the ncacn_ip_tcp transport, do the write/read step here.
561 subreq = rpc_write_send(state, ev, transport, data, data_len);
562 if (subreq == NULL) {
563 goto fail;
565 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
566 return req;
568 post_status:
569 tevent_req_nterror(req, status);
570 return tevent_req_post(req, ev);
571 fail:
572 TALLOC_FREE(req);
573 return NULL;
576 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
578 struct tevent_req *req = tevent_req_callback_data(
579 subreq, struct tevent_req);
580 struct cli_api_pipe_state *state = tevent_req_data(
581 req, struct cli_api_pipe_state);
582 NTSTATUS status;
584 status = state->transport->trans_recv(subreq, state, &state->rdata,
585 &state->rdata_len);
586 TALLOC_FREE(subreq);
587 if (!NT_STATUS_IS_OK(status)) {
588 tevent_req_nterror(req, status);
589 return;
591 tevent_req_done(req);
594 static void cli_api_pipe_write_done(struct tevent_req *subreq)
596 struct tevent_req *req = tevent_req_callback_data(
597 subreq, struct tevent_req);
598 struct cli_api_pipe_state *state = tevent_req_data(
599 req, struct cli_api_pipe_state);
600 NTSTATUS status;
602 status = rpc_write_recv(subreq);
603 TALLOC_FREE(subreq);
604 if (!NT_STATUS_IS_OK(status)) {
605 tevent_req_nterror(req, status);
606 return;
609 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
610 if (tevent_req_nomem(state->rdata, req)) {
611 return;
615 * We don't need to use rpc_read_send here, the upper layer will cope
616 * with a short read, transport->trans_send could also return less
617 * than state->max_rdata_len.
619 subreq = state->transport->read_send(state, state->ev, state->rdata,
620 RPC_HEADER_LEN,
621 state->transport->priv);
622 if (tevent_req_nomem(subreq, req)) {
623 return;
625 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
628 static void cli_api_pipe_read_done(struct tevent_req *subreq)
630 struct tevent_req *req = tevent_req_callback_data(
631 subreq, struct tevent_req);
632 struct cli_api_pipe_state *state = tevent_req_data(
633 req, struct cli_api_pipe_state);
634 NTSTATUS status;
635 ssize_t received;
637 status = state->transport->read_recv(subreq, &received);
638 TALLOC_FREE(subreq);
639 if (!NT_STATUS_IS_OK(status)) {
640 tevent_req_nterror(req, status);
641 return;
643 state->rdata_len = received;
644 tevent_req_done(req);
647 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
648 uint8_t **prdata, uint32_t *prdata_len)
650 struct cli_api_pipe_state *state = tevent_req_data(
651 req, struct cli_api_pipe_state);
652 NTSTATUS status;
654 if (tevent_req_is_nterror(req, &status)) {
655 return status;
658 *prdata = talloc_move(mem_ctx, &state->rdata);
659 *prdata_len = state->rdata_len;
660 return NT_STATUS_OK;
663 /****************************************************************************
664 Send data on an rpc pipe via trans. The data must be the last
665 pdu fragment of an NDR data stream.
667 Receive response data from an rpc pipe, which may be large...
669 Read the first fragment: unfortunately have to use SMBtrans for the first
670 bit, then SMBreadX for subsequent bits.
672 If first fragment received also wasn't the last fragment, continue
673 getting fragments until we _do_ receive the last fragment.
675 Request/Response PDU's look like the following...
677 |<------------------PDU len----------------------------------------------->|
678 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
680 +------------+-----------------+-------------+---------------+-------------+
681 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
682 +------------+-----------------+-------------+---------------+-------------+
684 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
685 signing & sealing being negotiated.
687 ****************************************************************************/
689 struct rpc_api_pipe_state {
690 struct tevent_context *ev;
691 struct rpc_pipe_client *cli;
692 uint8_t expected_pkt_type;
694 DATA_BLOB incoming_frag;
695 struct ncacn_packet *pkt;
697 /* Incoming reply */
698 DATA_BLOB reply_pdu;
699 size_t reply_pdu_offset;
700 uint8_t endianess;
703 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
704 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
705 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
707 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
708 struct tevent_context *ev,
709 struct rpc_pipe_client *cli,
710 DATA_BLOB *data, /* Outgoing PDU */
711 uint8_t expected_pkt_type)
713 struct tevent_req *req, *subreq;
714 struct rpc_api_pipe_state *state;
715 uint16_t max_recv_frag;
716 NTSTATUS status;
718 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
719 if (req == NULL) {
720 return NULL;
722 state->ev = ev;
723 state->cli = cli;
724 state->expected_pkt_type = expected_pkt_type;
725 state->endianess = DCERPC_DREP_LE;
728 * Ensure we're not sending too much.
730 if (data->length > cli->max_xmit_frag) {
731 status = NT_STATUS_INVALID_PARAMETER;
732 goto post_status;
735 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
737 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
738 subreq = rpc_write_send(state, ev, cli->transport,
739 data->data, data->length);
740 if (subreq == NULL) {
741 goto fail;
743 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
744 return req;
747 /* get the header first, then fetch the rest once we have
748 * the frag_length available */
749 max_recv_frag = RPC_HEADER_LEN;
751 subreq = cli_api_pipe_send(state, ev, cli->transport,
752 data->data, data->length, max_recv_frag);
753 if (subreq == NULL) {
754 goto fail;
756 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
757 return req;
759 post_status:
760 tevent_req_nterror(req, status);
761 return tevent_req_post(req, ev);
762 fail:
763 TALLOC_FREE(req);
764 return NULL;
767 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
769 struct tevent_req *req =
770 tevent_req_callback_data(subreq,
771 struct tevent_req);
772 NTSTATUS status;
774 status = rpc_write_recv(subreq);
775 TALLOC_FREE(subreq);
776 if (!NT_STATUS_IS_OK(status)) {
777 tevent_req_nterror(req, status);
778 return;
781 tevent_req_done(req);
784 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
786 struct tevent_req *req = tevent_req_callback_data(
787 subreq, struct tevent_req);
788 struct rpc_api_pipe_state *state = tevent_req_data(
789 req, struct rpc_api_pipe_state);
790 NTSTATUS status;
791 uint8_t *rdata = NULL;
792 uint32_t rdata_len = 0;
794 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
795 TALLOC_FREE(subreq);
796 if (!NT_STATUS_IS_OK(status)) {
797 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
798 tevent_req_nterror(req, status);
799 return;
802 if (rdata == NULL) {
803 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
804 rpccli_pipe_txt(talloc_tos(), state->cli)));
805 tevent_req_done(req);
806 return;
810 * Move data on state->incoming_frag.
812 state->incoming_frag.data = talloc_move(state, &rdata);
813 state->incoming_frag.length = rdata_len;
814 if (!state->incoming_frag.data) {
815 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
816 return;
819 /* Ensure we have enough data for a pdu. */
820 subreq = get_complete_frag_send(state, state->ev, state->cli,
821 &state->incoming_frag);
822 if (tevent_req_nomem(subreq, req)) {
823 return;
825 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
828 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
830 struct tevent_req *req = tevent_req_callback_data(
831 subreq, struct tevent_req);
832 struct rpc_api_pipe_state *state = tevent_req_data(
833 req, struct rpc_api_pipe_state);
834 NTSTATUS status;
835 DATA_BLOB rdata = data_blob_null;
837 status = get_complete_frag_recv(subreq);
838 TALLOC_FREE(subreq);
839 if (!NT_STATUS_IS_OK(status)) {
840 DEBUG(5, ("get_complete_frag failed: %s\n",
841 nt_errstr(status)));
842 tevent_req_nterror(req, status);
843 return;
846 state->pkt = talloc(state, struct ncacn_packet);
847 if (!state->pkt) {
848 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
849 return;
852 status = dcerpc_pull_ncacn_packet(state->pkt,
853 &state->incoming_frag,
854 state->pkt,
855 !state->endianess);
856 if (!NT_STATUS_IS_OK(status)) {
857 tevent_req_nterror(req, status);
858 return;
861 if (state->incoming_frag.length != state->pkt->frag_length) {
862 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
863 (unsigned int)state->incoming_frag.length,
864 (unsigned int)state->pkt->frag_length));
865 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
866 return;
869 status = cli_pipe_validate_current_pdu(state,
870 state->cli, state->pkt,
871 &state->incoming_frag,
872 state->expected_pkt_type,
873 &rdata,
874 &state->reply_pdu);
876 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
877 (unsigned)state->incoming_frag.length,
878 (unsigned)state->reply_pdu_offset,
879 nt_errstr(status)));
881 if (!NT_STATUS_IS_OK(status)) {
882 tevent_req_nterror(req, status);
883 return;
886 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
887 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
889 * Set the data type correctly for big-endian data on the
890 * first packet.
892 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
893 "big-endian.\n",
894 rpccli_pipe_txt(talloc_tos(), state->cli)));
895 state->endianess = 0x00; /* BIG ENDIAN */
898 * Check endianness on subsequent packets.
900 if (state->endianess != state->pkt->drep[0]) {
901 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
902 "%s\n",
903 state->endianess?"little":"big",
904 state->pkt->drep[0]?"little":"big"));
905 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
906 return;
909 /* Now copy the data portion out of the pdu into rbuf. */
910 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
911 if (!data_blob_realloc(NULL, &state->reply_pdu,
912 state->reply_pdu_offset + rdata.length)) {
913 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
914 return;
918 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
919 rdata.data, rdata.length);
920 state->reply_pdu_offset += rdata.length;
922 /* reset state->incoming_frag, there is no need to free it,
923 * it will be reallocated to the right size the next time
924 * it is used */
925 state->incoming_frag.length = 0;
927 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
928 /* make sure the pdu length is right now that we
929 * have all the data available (alloc hint may
930 * have allocated more than was actually used) */
931 state->reply_pdu.length = state->reply_pdu_offset;
932 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
933 rpccli_pipe_txt(talloc_tos(), state->cli),
934 (unsigned)state->reply_pdu.length));
935 tevent_req_done(req);
936 return;
939 subreq = get_complete_frag_send(state, state->ev, state->cli,
940 &state->incoming_frag);
941 if (tevent_req_nomem(subreq, req)) {
942 return;
944 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
947 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
948 struct ncacn_packet **pkt,
949 DATA_BLOB *reply_pdu)
951 struct rpc_api_pipe_state *state = tevent_req_data(
952 req, struct rpc_api_pipe_state);
953 NTSTATUS status;
955 if (tevent_req_is_nterror(req, &status)) {
956 return status;
959 /* return data to caller and assign it ownership of memory */
960 if (reply_pdu) {
961 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
962 reply_pdu->length = state->reply_pdu.length;
963 state->reply_pdu.length = 0;
964 } else {
965 data_blob_free(&state->reply_pdu);
968 if (pkt) {
969 *pkt = talloc_steal(mem_ctx, state->pkt);
972 return NT_STATUS_OK;
975 /*******************************************************************
976 Creates NTLMSSP auth bind.
977 ********************************************************************/
979 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
980 TALLOC_CTX *mem_ctx,
981 DATA_BLOB *auth_token)
983 struct gensec_security *gensec_security;
984 DATA_BLOB null_blob = data_blob_null;
986 gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
987 struct gensec_security);
989 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
990 return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
993 /*******************************************************************
994 Creates the internals of a DCE/RPC bind request or alter context PDU.
995 ********************************************************************/
997 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
998 enum dcerpc_pkt_type ptype,
999 uint32 rpc_call_id,
1000 const struct ndr_syntax_id *abstract,
1001 const struct ndr_syntax_id *transfer,
1002 const DATA_BLOB *auth_info,
1003 DATA_BLOB *blob)
1005 uint16 auth_len = auth_info->length;
1006 NTSTATUS status;
1007 union dcerpc_payload u;
1008 struct dcerpc_ctx_list ctx_list;
1010 if (auth_len) {
1011 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1014 ctx_list.context_id = 0;
1015 ctx_list.num_transfer_syntaxes = 1;
1016 ctx_list.abstract_syntax = *abstract;
1017 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1019 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1020 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1021 u.bind.assoc_group_id = 0x0;
1022 u.bind.num_contexts = 1;
1023 u.bind.ctx_list = &ctx_list;
1024 u.bind.auth_info = *auth_info;
1026 status = dcerpc_push_ncacn_packet(mem_ctx,
1027 ptype,
1028 DCERPC_PFC_FLAG_FIRST |
1029 DCERPC_PFC_FLAG_LAST,
1030 auth_len,
1031 rpc_call_id,
1033 blob);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1036 return status;
1039 return NT_STATUS_OK;
1042 /*******************************************************************
1043 Creates a DCE/RPC bind request.
1044 ********************************************************************/
1046 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1047 struct rpc_pipe_client *cli,
1048 struct pipe_auth_data *auth,
1049 uint32 rpc_call_id,
1050 const struct ndr_syntax_id *abstract,
1051 const struct ndr_syntax_id *transfer,
1052 DATA_BLOB *rpc_out)
1054 DATA_BLOB auth_token = data_blob_null;
1055 DATA_BLOB auth_info = data_blob_null;
1056 NTSTATUS ret = NT_STATUS_OK;
1058 switch (auth->auth_type) {
1059 case DCERPC_AUTH_TYPE_SCHANNEL:
1060 case DCERPC_AUTH_TYPE_NTLMSSP:
1061 case DCERPC_AUTH_TYPE_KRB5:
1062 case DCERPC_AUTH_TYPE_SPNEGO:
1063 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token);
1065 if (!NT_STATUS_IS_OK(ret) &&
1066 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1067 return ret;
1069 break;
1071 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1072 auth_token = data_blob_talloc(mem_ctx,
1073 "NCALRPC_AUTH_TOKEN",
1074 18);
1075 break;
1077 case DCERPC_AUTH_TYPE_NONE:
1078 break;
1080 default:
1081 /* "Can't" happen. */
1082 return NT_STATUS_INVALID_INFO_CLASS;
1085 if (auth_token.length != 0) {
1086 ret = dcerpc_push_dcerpc_auth(cli,
1087 auth->auth_type,
1088 auth->auth_level,
1089 0, /* auth_pad_length */
1090 1, /* auth_context_id */
1091 &auth_token,
1092 &auth_info);
1093 if (!NT_STATUS_IS_OK(ret)) {
1094 return ret;
1096 data_blob_free(&auth_token);
1099 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1100 DCERPC_PKT_BIND,
1101 rpc_call_id,
1102 abstract,
1103 transfer,
1104 &auth_info,
1105 rpc_out);
1106 return ret;
1109 /*******************************************************************
1110 External interface.
1111 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1112 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1113 and deals with signing/sealing details.
1114 ********************************************************************/
1116 struct rpc_api_pipe_req_state {
1117 struct tevent_context *ev;
1118 struct rpc_pipe_client *cli;
1119 uint8_t op_num;
1120 uint32_t call_id;
1121 DATA_BLOB *req_data;
1122 uint32_t req_data_sent;
1123 DATA_BLOB rpc_out;
1124 DATA_BLOB reply_pdu;
1127 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1128 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1129 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1130 bool *is_last_frag);
1132 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1133 struct tevent_context *ev,
1134 struct rpc_pipe_client *cli,
1135 uint8_t op_num,
1136 DATA_BLOB *req_data)
1138 struct tevent_req *req, *subreq;
1139 struct rpc_api_pipe_req_state *state;
1140 NTSTATUS status;
1141 bool is_last_frag;
1143 req = tevent_req_create(mem_ctx, &state,
1144 struct rpc_api_pipe_req_state);
1145 if (req == NULL) {
1146 return NULL;
1148 state->ev = ev;
1149 state->cli = cli;
1150 state->op_num = op_num;
1151 state->req_data = req_data;
1152 state->req_data_sent = 0;
1153 state->call_id = get_rpc_call_id();
1154 state->reply_pdu = data_blob_null;
1155 state->rpc_out = data_blob_null;
1157 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1158 + RPC_MAX_SIGN_SIZE) {
1159 /* Server is screwed up ! */
1160 status = NT_STATUS_INVALID_PARAMETER;
1161 goto post_status;
1164 status = prepare_next_frag(state, &is_last_frag);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 goto post_status;
1169 if (is_last_frag) {
1170 subreq = rpc_api_pipe_send(state, ev, state->cli,
1171 &state->rpc_out,
1172 DCERPC_PKT_RESPONSE);
1173 if (subreq == NULL) {
1174 goto fail;
1176 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1177 } else {
1178 subreq = rpc_write_send(state, ev, cli->transport,
1179 state->rpc_out.data,
1180 state->rpc_out.length);
1181 if (subreq == NULL) {
1182 goto fail;
1184 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1185 req);
1187 return req;
1189 post_status:
1190 tevent_req_nterror(req, status);
1191 return tevent_req_post(req, ev);
1192 fail:
1193 TALLOC_FREE(req);
1194 return NULL;
1197 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1198 bool *is_last_frag)
1200 size_t data_sent_thistime;
1201 size_t auth_len;
1202 size_t frag_len;
1203 uint8_t flags = 0;
1204 size_t pad_len;
1205 size_t data_left;
1206 NTSTATUS status;
1207 union dcerpc_payload u;
1209 data_left = state->req_data->length - state->req_data_sent;
1211 status = dcerpc_guess_sizes(state->cli->auth,
1212 DCERPC_REQUEST_LENGTH, data_left,
1213 state->cli->max_xmit_frag,
1214 CLIENT_NDR_PADDING_SIZE,
1215 &data_sent_thistime,
1216 &frag_len, &auth_len, &pad_len);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 return status;
1221 if (state->req_data_sent == 0) {
1222 flags = DCERPC_PFC_FLAG_FIRST;
1225 if (data_sent_thistime == data_left) {
1226 flags |= DCERPC_PFC_FLAG_LAST;
1229 data_blob_free(&state->rpc_out);
1231 ZERO_STRUCT(u.request);
1233 u.request.alloc_hint = state->req_data->length;
1234 u.request.context_id = 0;
1235 u.request.opnum = state->op_num;
1237 status = dcerpc_push_ncacn_packet(state,
1238 DCERPC_PKT_REQUEST,
1239 flags,
1240 auth_len,
1241 state->call_id,
1243 &state->rpc_out);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 return status;
1248 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1249 * compute it right for requests because the auth trailer is missing
1250 * at this stage */
1251 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1253 /* Copy in the data. */
1254 if (!data_blob_append(NULL, &state->rpc_out,
1255 state->req_data->data + state->req_data_sent,
1256 data_sent_thistime)) {
1257 return NT_STATUS_NO_MEMORY;
1260 switch (state->cli->auth->auth_level) {
1261 case DCERPC_AUTH_LEVEL_NONE:
1262 case DCERPC_AUTH_LEVEL_CONNECT:
1263 case DCERPC_AUTH_LEVEL_PACKET:
1264 break;
1265 case DCERPC_AUTH_LEVEL_INTEGRITY:
1266 case DCERPC_AUTH_LEVEL_PRIVACY:
1267 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1268 &state->rpc_out);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 return status;
1272 break;
1273 default:
1274 return NT_STATUS_INVALID_PARAMETER;
1277 state->req_data_sent += data_sent_thistime;
1278 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1280 return status;
1283 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1285 struct tevent_req *req = tevent_req_callback_data(
1286 subreq, struct tevent_req);
1287 struct rpc_api_pipe_req_state *state = tevent_req_data(
1288 req, struct rpc_api_pipe_req_state);
1289 NTSTATUS status;
1290 bool is_last_frag;
1292 status = rpc_write_recv(subreq);
1293 TALLOC_FREE(subreq);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 tevent_req_nterror(req, status);
1296 return;
1299 status = prepare_next_frag(state, &is_last_frag);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 tevent_req_nterror(req, status);
1302 return;
1305 if (is_last_frag) {
1306 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1307 &state->rpc_out,
1308 DCERPC_PKT_RESPONSE);
1309 if (tevent_req_nomem(subreq, req)) {
1310 return;
1312 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1313 } else {
1314 subreq = rpc_write_send(state, state->ev,
1315 state->cli->transport,
1316 state->rpc_out.data,
1317 state->rpc_out.length);
1318 if (tevent_req_nomem(subreq, req)) {
1319 return;
1321 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1322 req);
1326 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1328 struct tevent_req *req = tevent_req_callback_data(
1329 subreq, struct tevent_req);
1330 struct rpc_api_pipe_req_state *state = tevent_req_data(
1331 req, struct rpc_api_pipe_req_state);
1332 NTSTATUS status;
1334 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1335 TALLOC_FREE(subreq);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 tevent_req_nterror(req, status);
1338 return;
1340 tevent_req_done(req);
1343 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1344 DATA_BLOB *reply_pdu)
1346 struct rpc_api_pipe_req_state *state = tevent_req_data(
1347 req, struct rpc_api_pipe_req_state);
1348 NTSTATUS status;
1350 if (tevent_req_is_nterror(req, &status)) {
1352 * We always have to initialize to reply pdu, even if there is
1353 * none. The rpccli_* caller routines expect this.
1355 *reply_pdu = data_blob_null;
1356 return status;
1359 /* return data to caller and assign it ownership of memory */
1360 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1361 reply_pdu->length = state->reply_pdu.length;
1362 state->reply_pdu.length = 0;
1364 return NT_STATUS_OK;
1367 /****************************************************************************
1368 Check the rpc bind acknowledge response.
1369 ****************************************************************************/
1371 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1372 const struct ndr_syntax_id *transfer)
1374 struct dcerpc_ack_ctx ctx;
1376 if (r->secondary_address_size == 0) {
1377 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1380 if (r->num_results < 1 || !r->ctx_list) {
1381 return false;
1384 ctx = r->ctx_list[0];
1386 /* check the transfer syntax */
1387 if ((ctx.syntax.if_version != transfer->if_version) ||
1388 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1389 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1390 return False;
1393 if (r->num_results != 0x1 || ctx.result != 0) {
1394 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1395 r->num_results, ctx.reason));
1398 DEBUG(5,("check_bind_response: accepted!\n"));
1399 return True;
1402 /*******************************************************************
1403 Creates a DCE/RPC bind authentication response.
1404 This is the packet that is sent back to the server once we
1405 have received a BIND-ACK, to finish the third leg of
1406 the authentication handshake.
1407 ********************************************************************/
1409 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1410 struct rpc_pipe_client *cli,
1411 uint32 rpc_call_id,
1412 enum dcerpc_AuthType auth_type,
1413 enum dcerpc_AuthLevel auth_level,
1414 DATA_BLOB *pauth_blob,
1415 DATA_BLOB *rpc_out)
1417 NTSTATUS status;
1418 union dcerpc_payload u;
1420 u.auth3._pad = 0;
1422 status = dcerpc_push_dcerpc_auth(mem_ctx,
1423 auth_type,
1424 auth_level,
1425 0, /* auth_pad_length */
1426 1, /* auth_context_id */
1427 pauth_blob,
1428 &u.auth3.auth_info);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 return status;
1433 status = dcerpc_push_ncacn_packet(mem_ctx,
1434 DCERPC_PKT_AUTH3,
1435 DCERPC_PFC_FLAG_FIRST |
1436 DCERPC_PFC_FLAG_LAST,
1437 pauth_blob->length,
1438 rpc_call_id,
1440 rpc_out);
1441 data_blob_free(&u.auth3.auth_info);
1442 if (!NT_STATUS_IS_OK(status)) {
1443 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1444 return status;
1447 return NT_STATUS_OK;
1450 /*******************************************************************
1451 Creates a DCE/RPC bind alter context authentication request which
1452 may contain a spnego auth blobl
1453 ********************************************************************/
1455 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1456 enum dcerpc_AuthType auth_type,
1457 enum dcerpc_AuthLevel auth_level,
1458 uint32 rpc_call_id,
1459 const struct ndr_syntax_id *abstract,
1460 const struct ndr_syntax_id *transfer,
1461 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1462 DATA_BLOB *rpc_out)
1464 DATA_BLOB auth_info;
1465 NTSTATUS status;
1467 status = dcerpc_push_dcerpc_auth(mem_ctx,
1468 auth_type,
1469 auth_level,
1470 0, /* auth_pad_length */
1471 1, /* auth_context_id */
1472 pauth_blob,
1473 &auth_info);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 return status;
1478 status = create_bind_or_alt_ctx_internal(mem_ctx,
1479 DCERPC_PKT_ALTER,
1480 rpc_call_id,
1481 abstract,
1482 transfer,
1483 &auth_info,
1484 rpc_out);
1485 data_blob_free(&auth_info);
1486 return status;
1489 /****************************************************************************
1490 Do an rpc bind.
1491 ****************************************************************************/
1493 struct rpc_pipe_bind_state {
1494 struct tevent_context *ev;
1495 struct rpc_pipe_client *cli;
1496 DATA_BLOB rpc_out;
1497 bool auth3;
1498 uint32_t rpc_call_id;
1501 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1502 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1503 struct rpc_pipe_bind_state *state,
1504 DATA_BLOB *credentials);
1505 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1506 struct rpc_pipe_bind_state *state,
1507 DATA_BLOB *credentials);
1509 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1510 struct tevent_context *ev,
1511 struct rpc_pipe_client *cli,
1512 struct pipe_auth_data *auth)
1514 struct tevent_req *req, *subreq;
1515 struct rpc_pipe_bind_state *state;
1516 NTSTATUS status;
1518 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1519 if (req == NULL) {
1520 return NULL;
1523 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1524 rpccli_pipe_txt(talloc_tos(), cli),
1525 (unsigned int)auth->auth_type,
1526 (unsigned int)auth->auth_level ));
1528 state->ev = ev;
1529 state->cli = cli;
1530 state->rpc_call_id = get_rpc_call_id();
1532 cli->auth = talloc_move(cli, &auth);
1534 /* Marshall the outgoing data. */
1535 status = create_rpc_bind_req(state, cli,
1536 cli->auth,
1537 state->rpc_call_id,
1538 &cli->abstract_syntax,
1539 &cli->transfer_syntax,
1540 &state->rpc_out);
1542 if (!NT_STATUS_IS_OK(status) &&
1543 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1544 goto post_status;
1547 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1548 DCERPC_PKT_BIND_ACK);
1549 if (subreq == NULL) {
1550 goto fail;
1552 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1553 return req;
1555 post_status:
1556 tevent_req_nterror(req, status);
1557 return tevent_req_post(req, ev);
1558 fail:
1559 TALLOC_FREE(req);
1560 return NULL;
1563 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1565 struct tevent_req *req = tevent_req_callback_data(
1566 subreq, struct tevent_req);
1567 struct rpc_pipe_bind_state *state = tevent_req_data(
1568 req, struct rpc_pipe_bind_state);
1569 struct pipe_auth_data *pauth = state->cli->auth;
1570 struct gensec_security *gensec_security;
1571 struct ncacn_packet *pkt = NULL;
1572 struct dcerpc_auth auth;
1573 DATA_BLOB auth_token = data_blob_null;
1574 NTSTATUS status;
1576 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1577 TALLOC_FREE(subreq);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1580 rpccli_pipe_txt(talloc_tos(), state->cli),
1581 nt_errstr(status)));
1582 tevent_req_nterror(req, status);
1583 return;
1586 if (state->auth3) {
1587 tevent_req_done(req);
1588 return;
1591 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1592 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1593 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1594 return;
1597 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1598 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1600 switch(pauth->auth_type) {
1602 case DCERPC_AUTH_TYPE_NONE:
1603 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1604 case DCERPC_AUTH_TYPE_SCHANNEL:
1605 /* Bind complete. */
1606 tevent_req_done(req);
1607 return;
1609 case DCERPC_AUTH_TYPE_NTLMSSP:
1610 case DCERPC_AUTH_TYPE_SPNEGO:
1611 case DCERPC_AUTH_TYPE_KRB5:
1612 /* Paranoid lenght checks */
1613 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1614 + pkt->auth_length) {
1615 tevent_req_nterror(req,
1616 NT_STATUS_INFO_LENGTH_MISMATCH);
1617 return;
1619 /* get auth credentials */
1620 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1621 &pkt->u.bind_ack.auth_info,
1622 &auth, false);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1625 nt_errstr(status)));
1626 tevent_req_nterror(req, status);
1627 return;
1629 break;
1631 default:
1632 goto err_out;
1636 * For authenticated binds we may need to do 3 or 4 leg binds.
1639 switch(pauth->auth_type) {
1641 case DCERPC_AUTH_TYPE_NONE:
1642 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1643 case DCERPC_AUTH_TYPE_SCHANNEL:
1644 /* Bind complete. */
1645 tevent_req_done(req);
1646 return;
1648 case DCERPC_AUTH_TYPE_NTLMSSP:
1649 case DCERPC_AUTH_TYPE_KRB5:
1650 case DCERPC_AUTH_TYPE_SPNEGO:
1651 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1652 struct gensec_security);
1653 status = gensec_update(gensec_security, state, NULL,
1654 auth.credentials, &auth_token);
1655 if (NT_STATUS_EQUAL(status,
1656 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1657 status = rpc_bind_next_send(req, state,
1658 &auth_token);
1659 } else if (NT_STATUS_IS_OK(status)) {
1660 if (auth_token.length == 0) {
1661 /* Bind complete. */
1662 tevent_req_done(req);
1663 return;
1665 status = rpc_bind_finish_send(req, state,
1666 &auth_token);
1668 break;
1670 default:
1671 goto err_out;
1674 if (!NT_STATUS_IS_OK(status)) {
1675 tevent_req_nterror(req, status);
1677 return;
1679 err_out:
1680 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1681 (unsigned int)state->cli->auth->auth_type));
1682 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1685 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1686 struct rpc_pipe_bind_state *state,
1687 DATA_BLOB *auth_token)
1689 struct pipe_auth_data *auth = state->cli->auth;
1690 struct tevent_req *subreq;
1691 NTSTATUS status;
1693 /* Now prepare the alter context pdu. */
1694 data_blob_free(&state->rpc_out);
1696 status = create_rpc_alter_context(state,
1697 auth->auth_type,
1698 auth->auth_level,
1699 state->rpc_call_id,
1700 &state->cli->abstract_syntax,
1701 &state->cli->transfer_syntax,
1702 auth_token,
1703 &state->rpc_out);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 return status;
1708 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1709 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1710 if (subreq == NULL) {
1711 return NT_STATUS_NO_MEMORY;
1713 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1714 return NT_STATUS_OK;
1717 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1718 struct rpc_pipe_bind_state *state,
1719 DATA_BLOB *auth_token)
1721 struct pipe_auth_data *auth = state->cli->auth;
1722 struct tevent_req *subreq;
1723 NTSTATUS status;
1725 state->auth3 = true;
1727 /* Now prepare the auth3 context pdu. */
1728 data_blob_free(&state->rpc_out);
1730 status = create_rpc_bind_auth3(state, state->cli,
1731 state->rpc_call_id,
1732 auth->auth_type,
1733 auth->auth_level,
1734 auth_token,
1735 &state->rpc_out);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 return status;
1740 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1741 &state->rpc_out, DCERPC_PKT_AUTH3);
1742 if (subreq == NULL) {
1743 return NT_STATUS_NO_MEMORY;
1745 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1746 return NT_STATUS_OK;
1749 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1751 return tevent_req_simple_recv_ntstatus(req);
1754 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1755 struct pipe_auth_data *auth)
1757 TALLOC_CTX *frame = talloc_stackframe();
1758 struct tevent_context *ev;
1759 struct tevent_req *req;
1760 NTSTATUS status = NT_STATUS_OK;
1762 ev = samba_tevent_context_init(frame);
1763 if (ev == NULL) {
1764 status = NT_STATUS_NO_MEMORY;
1765 goto fail;
1768 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1769 if (req == NULL) {
1770 status = NT_STATUS_NO_MEMORY;
1771 goto fail;
1774 if (!tevent_req_poll(req, ev)) {
1775 status = map_nt_error_from_unix(errno);
1776 goto fail;
1779 status = rpc_pipe_bind_recv(req);
1780 fail:
1781 TALLOC_FREE(frame);
1782 return status;
1785 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1787 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1788 unsigned int timeout)
1790 unsigned int old;
1792 if (rpc_cli->transport == NULL) {
1793 return RPCCLI_DEFAULT_TIMEOUT;
1796 if (rpc_cli->transport->set_timeout == NULL) {
1797 return RPCCLI_DEFAULT_TIMEOUT;
1800 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
1801 if (old == 0) {
1802 return RPCCLI_DEFAULT_TIMEOUT;
1805 return old;
1808 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
1810 if (rpc_cli == NULL) {
1811 return false;
1814 if (rpc_cli->transport == NULL) {
1815 return false;
1818 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
1821 struct rpccli_bh_state {
1822 struct rpc_pipe_client *rpc_cli;
1825 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
1827 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1828 struct rpccli_bh_state);
1830 return rpccli_is_connected(hs->rpc_cli);
1833 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
1834 uint32_t timeout)
1836 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1837 struct rpccli_bh_state);
1839 return rpccli_set_timeout(hs->rpc_cli, timeout);
1842 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
1843 enum dcerpc_AuthType *auth_type,
1844 enum dcerpc_AuthLevel *auth_level)
1846 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1847 struct rpccli_bh_state);
1849 if (hs->rpc_cli == NULL) {
1850 return;
1853 if (hs->rpc_cli->auth == NULL) {
1854 return;
1857 *auth_type = hs->rpc_cli->auth->auth_type;
1858 *auth_level = hs->rpc_cli->auth->auth_level;
1861 struct rpccli_bh_raw_call_state {
1862 DATA_BLOB in_data;
1863 DATA_BLOB out_data;
1864 uint32_t out_flags;
1867 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
1869 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
1870 struct tevent_context *ev,
1871 struct dcerpc_binding_handle *h,
1872 const struct GUID *object,
1873 uint32_t opnum,
1874 uint32_t in_flags,
1875 const uint8_t *in_data,
1876 size_t in_length)
1878 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1879 struct rpccli_bh_state);
1880 struct tevent_req *req;
1881 struct rpccli_bh_raw_call_state *state;
1882 bool ok;
1883 struct tevent_req *subreq;
1885 req = tevent_req_create(mem_ctx, &state,
1886 struct rpccli_bh_raw_call_state);
1887 if (req == NULL) {
1888 return NULL;
1890 state->in_data.data = discard_const_p(uint8_t, in_data);
1891 state->in_data.length = in_length;
1893 ok = rpccli_bh_is_connected(h);
1894 if (!ok) {
1895 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1896 return tevent_req_post(req, ev);
1899 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
1900 opnum, &state->in_data);
1901 if (tevent_req_nomem(subreq, req)) {
1902 return tevent_req_post(req, ev);
1904 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
1906 return req;
1909 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
1911 struct tevent_req *req =
1912 tevent_req_callback_data(subreq,
1913 struct tevent_req);
1914 struct rpccli_bh_raw_call_state *state =
1915 tevent_req_data(req,
1916 struct rpccli_bh_raw_call_state);
1917 NTSTATUS status;
1919 state->out_flags = 0;
1921 /* TODO: support bigendian responses */
1923 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
1924 TALLOC_FREE(subreq);
1925 if (!NT_STATUS_IS_OK(status)) {
1926 tevent_req_nterror(req, status);
1927 return;
1930 tevent_req_done(req);
1933 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
1934 TALLOC_CTX *mem_ctx,
1935 uint8_t **out_data,
1936 size_t *out_length,
1937 uint32_t *out_flags)
1939 struct rpccli_bh_raw_call_state *state =
1940 tevent_req_data(req,
1941 struct rpccli_bh_raw_call_state);
1942 NTSTATUS status;
1944 if (tevent_req_is_nterror(req, &status)) {
1945 tevent_req_received(req);
1946 return status;
1949 *out_data = talloc_move(mem_ctx, &state->out_data.data);
1950 *out_length = state->out_data.length;
1951 *out_flags = state->out_flags;
1952 tevent_req_received(req);
1953 return NT_STATUS_OK;
1956 struct rpccli_bh_disconnect_state {
1957 uint8_t _dummy;
1960 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
1961 struct tevent_context *ev,
1962 struct dcerpc_binding_handle *h)
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_disconnect_state *state;
1968 bool ok;
1970 req = tevent_req_create(mem_ctx, &state,
1971 struct rpccli_bh_disconnect_state);
1972 if (req == NULL) {
1973 return NULL;
1976 ok = rpccli_bh_is_connected(h);
1977 if (!ok) {
1978 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1979 return tevent_req_post(req, ev);
1983 * TODO: do a real async disconnect ...
1985 * For now the caller needs to free rpc_cli
1987 hs->rpc_cli = NULL;
1989 tevent_req_done(req);
1990 return tevent_req_post(req, ev);
1993 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
1995 NTSTATUS status;
1997 if (tevent_req_is_nterror(req, &status)) {
1998 tevent_req_received(req);
1999 return status;
2002 tevent_req_received(req);
2003 return NT_STATUS_OK;
2006 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2008 return true;
2011 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2012 int ndr_flags,
2013 const void *_struct_ptr,
2014 const struct ndr_interface_call *call)
2016 void *struct_ptr = discard_const(_struct_ptr);
2018 if (DEBUGLEVEL < 10) {
2019 return;
2022 if (ndr_flags & NDR_IN) {
2023 ndr_print_function_debug(call->ndr_print,
2024 call->name,
2025 ndr_flags,
2026 struct_ptr);
2028 if (ndr_flags & NDR_OUT) {
2029 ndr_print_function_debug(call->ndr_print,
2030 call->name,
2031 ndr_flags,
2032 struct_ptr);
2036 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2037 .name = "rpccli",
2038 .is_connected = rpccli_bh_is_connected,
2039 .set_timeout = rpccli_bh_set_timeout,
2040 .auth_info = rpccli_bh_auth_info,
2041 .raw_call_send = rpccli_bh_raw_call_send,
2042 .raw_call_recv = rpccli_bh_raw_call_recv,
2043 .disconnect_send = rpccli_bh_disconnect_send,
2044 .disconnect_recv = rpccli_bh_disconnect_recv,
2046 .ref_alloc = rpccli_bh_ref_alloc,
2047 .do_ndr_print = rpccli_bh_do_ndr_print,
2050 /* initialise a rpc_pipe_client binding handle */
2051 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2052 const struct GUID *object,
2053 const struct ndr_interface_table *table)
2055 struct dcerpc_binding_handle *h;
2056 struct rpccli_bh_state *hs;
2058 h = dcerpc_binding_handle_create(c,
2059 &rpccli_bh_ops,
2060 object,
2061 table,
2062 &hs,
2063 struct rpccli_bh_state,
2064 __location__);
2065 if (h == NULL) {
2066 return NULL;
2068 hs->rpc_cli = c;
2070 return h;
2073 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2074 struct pipe_auth_data **presult)
2076 struct pipe_auth_data *result;
2078 result = talloc(mem_ctx, struct pipe_auth_data);
2079 if (result == NULL) {
2080 return NT_STATUS_NO_MEMORY;
2083 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2084 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2086 result->user_name = talloc_strdup(result, "");
2087 result->domain = talloc_strdup(result, "");
2088 if ((result->user_name == NULL) || (result->domain == NULL)) {
2089 TALLOC_FREE(result);
2090 return NT_STATUS_NO_MEMORY;
2093 *presult = result;
2094 return NT_STATUS_OK;
2097 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2098 struct pipe_auth_data **presult)
2100 struct pipe_auth_data *result;
2102 result = talloc(mem_ctx, struct pipe_auth_data);
2103 if (result == NULL) {
2104 return NT_STATUS_NO_MEMORY;
2107 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2108 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2110 result->user_name = talloc_strdup(result, "");
2111 result->domain = talloc_strdup(result, "");
2112 if ((result->user_name == NULL) || (result->domain == NULL)) {
2113 TALLOC_FREE(result);
2114 return NT_STATUS_NO_MEMORY;
2117 *presult = result;
2118 return NT_STATUS_OK;
2121 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2122 enum dcerpc_AuthType auth_type,
2123 enum dcerpc_AuthLevel auth_level,
2124 const char *server,
2125 const char *target_service,
2126 const char *domain,
2127 const char *username,
2128 const char *password,
2129 enum credentials_use_kerberos use_kerberos,
2130 struct netlogon_creds_CredentialState *creds,
2131 struct pipe_auth_data **presult)
2133 struct auth_generic_state *auth_generic_ctx;
2134 struct pipe_auth_data *result;
2135 NTSTATUS status;
2137 result = talloc(mem_ctx, struct pipe_auth_data);
2138 if (result == NULL) {
2139 return NT_STATUS_NO_MEMORY;
2142 result->auth_type = auth_type;
2143 result->auth_level = auth_level;
2145 result->user_name = talloc_strdup(result, username);
2146 result->domain = talloc_strdup(result, domain);
2147 if ((result->user_name == NULL) || (result->domain == NULL)) {
2148 status = NT_STATUS_NO_MEMORY;
2149 goto fail;
2152 status = auth_generic_client_prepare(result,
2153 &auth_generic_ctx);
2154 if (!NT_STATUS_IS_OK(status)) {
2155 goto fail;
2158 status = auth_generic_set_username(auth_generic_ctx, username);
2159 if (!NT_STATUS_IS_OK(status)) {
2160 goto fail;
2163 status = auth_generic_set_domain(auth_generic_ctx, domain);
2164 if (!NT_STATUS_IS_OK(status)) {
2165 goto fail;
2168 status = auth_generic_set_password(auth_generic_ctx, password);
2169 if (!NT_STATUS_IS_OK(status)) {
2170 goto fail;
2173 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 goto fail;
2178 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 goto fail;
2183 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2184 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2186 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 goto fail;
2191 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2192 talloc_free(auth_generic_ctx);
2193 *presult = result;
2194 return NT_STATUS_OK;
2196 fail:
2197 TALLOC_FREE(result);
2198 return status;
2202 * Create an rpc pipe client struct, connecting to a tcp port.
2204 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2205 const struct sockaddr_storage *ss_addr,
2206 uint16_t port,
2207 const struct ndr_interface_table *table,
2208 struct rpc_pipe_client **presult)
2210 struct rpc_pipe_client *result;
2211 struct sockaddr_storage addr;
2212 NTSTATUS status;
2213 int fd;
2215 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2216 if (result == NULL) {
2217 return NT_STATUS_NO_MEMORY;
2220 result->abstract_syntax = table->syntax_id;
2221 result->transfer_syntax = ndr_transfer_syntax_ndr;
2223 result->desthost = talloc_strdup(result, host);
2224 result->srv_name_slash = talloc_asprintf_strupper_m(
2225 result, "\\\\%s", result->desthost);
2226 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2227 status = NT_STATUS_NO_MEMORY;
2228 goto fail;
2231 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2232 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2234 if (ss_addr == NULL) {
2235 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2236 status = NT_STATUS_NOT_FOUND;
2237 goto fail;
2239 } else {
2240 addr = *ss_addr;
2243 status = open_socket_out(&addr, port, 60*1000, &fd);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 goto fail;
2247 set_socket_options(fd, lp_socket_options());
2249 status = rpc_transport_sock_init(result, fd, &result->transport);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 close(fd);
2252 goto fail;
2255 result->transport->transport = NCACN_IP_TCP;
2257 result->binding_handle = rpccli_bh_create(result, NULL, table);
2258 if (result->binding_handle == NULL) {
2259 TALLOC_FREE(result);
2260 return NT_STATUS_NO_MEMORY;
2263 *presult = result;
2264 return NT_STATUS_OK;
2266 fail:
2267 TALLOC_FREE(result);
2268 return status;
2272 * Determine the tcp port on which a dcerpc interface is listening
2273 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2274 * target host.
2276 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2277 const struct sockaddr_storage *addr,
2278 const struct ndr_interface_table *table,
2279 uint16_t *pport)
2281 NTSTATUS status;
2282 struct rpc_pipe_client *epm_pipe = NULL;
2283 struct dcerpc_binding_handle *epm_handle = NULL;
2284 struct pipe_auth_data *auth = NULL;
2285 struct dcerpc_binding *map_binding = NULL;
2286 struct dcerpc_binding *res_binding = NULL;
2287 struct epm_twr_t *map_tower = NULL;
2288 struct epm_twr_t *res_towers = NULL;
2289 struct policy_handle *entry_handle = NULL;
2290 uint32_t num_towers = 0;
2291 uint32_t max_towers = 1;
2292 struct epm_twr_p_t towers;
2293 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2294 uint32_t result = 0;
2296 if (pport == NULL) {
2297 status = NT_STATUS_INVALID_PARAMETER;
2298 goto done;
2301 if (ndr_syntax_id_equal(&table->syntax_id,
2302 &ndr_table_epmapper.syntax_id)) {
2303 *pport = 135;
2304 status = NT_STATUS_OK;
2305 goto done;
2308 /* open the connection to the endpoint mapper */
2309 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2310 &ndr_table_epmapper,
2311 &epm_pipe);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 goto done;
2316 epm_handle = epm_pipe->binding_handle;
2318 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 goto done;
2323 status = rpc_pipe_bind(epm_pipe, auth);
2324 if (!NT_STATUS_IS_OK(status)) {
2325 goto done;
2328 /* create tower for asking the epmapper */
2330 map_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
2331 if (map_binding == NULL) {
2332 status = NT_STATUS_NO_MEMORY;
2333 goto done;
2336 map_binding->transport = NCACN_IP_TCP;
2337 map_binding->object = table->syntax_id;
2338 map_binding->host = host; /* needed? */
2339 map_binding->endpoint = "0"; /* correct? needed? */
2341 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2342 if (map_tower == NULL) {
2343 status = NT_STATUS_NO_MEMORY;
2344 goto done;
2347 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2348 &(map_tower->tower));
2349 if (!NT_STATUS_IS_OK(status)) {
2350 goto done;
2353 /* allocate further parameters for the epm_Map call */
2355 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2356 if (res_towers == NULL) {
2357 status = NT_STATUS_NO_MEMORY;
2358 goto done;
2360 towers.twr = res_towers;
2362 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2363 if (entry_handle == NULL) {
2364 status = NT_STATUS_NO_MEMORY;
2365 goto done;
2368 /* ask the endpoint mapper for the port */
2370 status = dcerpc_epm_Map(epm_handle,
2371 tmp_ctx,
2372 discard_const_p(struct GUID,
2373 &(table->syntax_id.uuid)),
2374 map_tower,
2375 entry_handle,
2376 max_towers,
2377 &num_towers,
2378 &towers,
2379 &result);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 goto done;
2385 if (result != EPMAPPER_STATUS_OK) {
2386 status = NT_STATUS_UNSUCCESSFUL;
2387 goto done;
2390 if (num_towers != 1) {
2391 status = NT_STATUS_UNSUCCESSFUL;
2392 goto done;
2395 /* extract the port from the answer */
2397 status = dcerpc_binding_from_tower(tmp_ctx,
2398 &(towers.twr->tower),
2399 &res_binding);
2400 if (!NT_STATUS_IS_OK(status)) {
2401 goto done;
2404 /* are further checks here necessary? */
2405 if (res_binding->transport != NCACN_IP_TCP) {
2406 status = NT_STATUS_UNSUCCESSFUL;
2407 goto done;
2410 *pport = (uint16_t)atoi(res_binding->endpoint);
2412 done:
2413 TALLOC_FREE(tmp_ctx);
2414 return status;
2418 * Create a rpc pipe client struct, connecting to a host via tcp.
2419 * The port is determined by asking the endpoint mapper on the given
2420 * host.
2422 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2423 const struct sockaddr_storage *addr,
2424 const struct ndr_interface_table *table,
2425 struct rpc_pipe_client **presult)
2427 NTSTATUS status;
2428 uint16_t port = 0;
2430 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2431 if (!NT_STATUS_IS_OK(status)) {
2432 return status;
2435 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2436 table, presult);
2439 /********************************************************************
2440 Create a rpc pipe client struct, connecting to a unix domain socket
2441 ********************************************************************/
2442 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2443 const struct ndr_interface_table *table,
2444 struct rpc_pipe_client **presult)
2446 struct rpc_pipe_client *result;
2447 struct sockaddr_un addr;
2448 NTSTATUS status;
2449 int fd;
2450 socklen_t salen;
2452 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2453 if (result == NULL) {
2454 return NT_STATUS_NO_MEMORY;
2457 result->abstract_syntax = table->syntax_id;
2458 result->transfer_syntax = ndr_transfer_syntax_ndr;
2460 result->desthost = get_myname(result);
2461 result->srv_name_slash = talloc_asprintf_strupper_m(
2462 result, "\\\\%s", result->desthost);
2463 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2464 status = NT_STATUS_NO_MEMORY;
2465 goto fail;
2468 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2469 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2471 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2472 if (fd == -1) {
2473 status = map_nt_error_from_unix(errno);
2474 goto fail;
2477 ZERO_STRUCT(addr);
2478 addr.sun_family = AF_UNIX;
2479 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2480 salen = sizeof(struct sockaddr_un);
2482 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2483 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2484 strerror(errno)));
2485 close(fd);
2486 return map_nt_error_from_unix(errno);
2489 status = rpc_transport_sock_init(result, fd, &result->transport);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 close(fd);
2492 goto fail;
2495 result->transport->transport = NCALRPC;
2497 result->binding_handle = rpccli_bh_create(result, NULL, table);
2498 if (result->binding_handle == NULL) {
2499 TALLOC_FREE(result);
2500 return NT_STATUS_NO_MEMORY;
2503 *presult = result;
2504 return NT_STATUS_OK;
2506 fail:
2507 TALLOC_FREE(result);
2508 return status;
2511 struct rpc_pipe_client_np_ref {
2512 struct cli_state *cli;
2513 struct rpc_pipe_client *pipe;
2516 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2518 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2519 return 0;
2522 /****************************************************************************
2523 Open a named pipe over SMB to a remote server.
2525 * CAVEAT CALLER OF THIS FUNCTION:
2526 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2527 * so be sure that this function is called AFTER any structure (vs pointer)
2528 * assignment of the cli. In particular, libsmbclient does structure
2529 * assignments of cli, which invalidates the data in the returned
2530 * rpc_pipe_client if this function is called before the structure assignment
2531 * of cli.
2533 ****************************************************************************/
2535 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2536 const struct ndr_interface_table *table,
2537 struct rpc_pipe_client **presult)
2539 struct rpc_pipe_client *result;
2540 NTSTATUS status;
2541 struct rpc_pipe_client_np_ref *np_ref;
2543 /* sanity check to protect against crashes */
2545 if ( !cli ) {
2546 return NT_STATUS_INVALID_HANDLE;
2549 result = talloc_zero(NULL, struct rpc_pipe_client);
2550 if (result == NULL) {
2551 return NT_STATUS_NO_MEMORY;
2554 result->abstract_syntax = table->syntax_id;
2555 result->transfer_syntax = ndr_transfer_syntax_ndr;
2556 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2557 result->srv_name_slash = talloc_asprintf_strupper_m(
2558 result, "\\\\%s", result->desthost);
2560 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2561 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2563 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2564 TALLOC_FREE(result);
2565 return NT_STATUS_NO_MEMORY;
2568 status = rpc_transport_np_init(result, cli, table,
2569 &result->transport);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 TALLOC_FREE(result);
2572 return status;
2575 result->transport->transport = NCACN_NP;
2577 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2578 if (np_ref == NULL) {
2579 TALLOC_FREE(result);
2580 return NT_STATUS_NO_MEMORY;
2582 np_ref->cli = cli;
2583 np_ref->pipe = result;
2585 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2586 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2588 result->binding_handle = rpccli_bh_create(result, NULL, table);
2589 if (result->binding_handle == NULL) {
2590 TALLOC_FREE(result);
2591 return NT_STATUS_NO_MEMORY;
2594 *presult = result;
2595 return NT_STATUS_OK;
2598 /****************************************************************************
2599 Open a pipe to a remote server.
2600 ****************************************************************************/
2602 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2603 enum dcerpc_transport_t transport,
2604 const struct ndr_interface_table *table,
2605 struct rpc_pipe_client **presult)
2607 switch (transport) {
2608 case NCACN_IP_TCP:
2609 return rpc_pipe_open_tcp(NULL,
2610 smbXcli_conn_remote_name(cli->conn),
2611 smbXcli_conn_remote_sockaddr(cli->conn),
2612 table, presult);
2613 case NCACN_NP:
2614 return rpc_pipe_open_np(cli, table, presult);
2615 default:
2616 return NT_STATUS_NOT_IMPLEMENTED;
2620 /****************************************************************************
2621 Open a named pipe to an SMB server and bind anonymously.
2622 ****************************************************************************/
2624 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2625 enum dcerpc_transport_t transport,
2626 const struct ndr_interface_table *table,
2627 struct rpc_pipe_client **presult)
2629 struct rpc_pipe_client *result;
2630 struct pipe_auth_data *auth;
2631 NTSTATUS status;
2633 status = cli_rpc_pipe_open(cli, transport, table, &result);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 return status;
2638 status = rpccli_anon_bind_data(result, &auth);
2639 if (!NT_STATUS_IS_OK(status)) {
2640 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2641 nt_errstr(status)));
2642 TALLOC_FREE(result);
2643 return status;
2647 * This is a bit of an abstraction violation due to the fact that an
2648 * anonymous bind on an authenticated SMB inherits the user/domain
2649 * from the enclosing SMB creds
2652 TALLOC_FREE(auth->user_name);
2653 TALLOC_FREE(auth->domain);
2655 auth->user_name = talloc_strdup(auth, cli->user_name);
2656 auth->domain = talloc_strdup(auth, cli->domain);
2658 if (transport == NCACN_NP) {
2659 struct smbXcli_session *session;
2661 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2662 session = cli->smb2.session;
2663 } else {
2664 session = cli->smb1.session;
2667 status = smbXcli_session_application_key(session, auth,
2668 &auth->transport_session_key);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 auth->transport_session_key = data_blob_null;
2674 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2675 TALLOC_FREE(result);
2676 return NT_STATUS_NO_MEMORY;
2679 status = rpc_pipe_bind(result, auth);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 int lvl = 0;
2682 if (ndr_syntax_id_equal(&table->syntax_id,
2683 &ndr_table_dssetup.syntax_id)) {
2684 /* non AD domains just don't have this pipe, avoid
2685 * level 0 statement in that case - gd */
2686 lvl = 3;
2688 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2689 "%s failed with error %s\n",
2690 table->name,
2691 nt_errstr(status) ));
2692 TALLOC_FREE(result);
2693 return status;
2696 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2697 "%s and bound anonymously.\n",
2698 table->name,
2699 result->desthost));
2701 *presult = result;
2702 return NT_STATUS_OK;
2705 /****************************************************************************
2706 ****************************************************************************/
2708 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2709 const struct ndr_interface_table *table,
2710 struct rpc_pipe_client **presult)
2712 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2713 table, presult);
2716 /****************************************************************************
2717 Open a named pipe to an SMB server and bind using the mech specified
2718 ****************************************************************************/
2720 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2721 const struct ndr_interface_table *table,
2722 enum dcerpc_transport_t transport,
2723 enum dcerpc_AuthType auth_type,
2724 enum dcerpc_AuthLevel auth_level,
2725 const char *server,
2726 const char *domain,
2727 const char *username,
2728 const char *password,
2729 struct rpc_pipe_client **presult)
2731 struct rpc_pipe_client *result;
2732 struct pipe_auth_data *auth = NULL;
2733 const char *target_service = table->authservices->names[0];
2735 NTSTATUS status;
2737 status = cli_rpc_pipe_open(cli, transport, table, &result);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 return status;
2742 status = rpccli_generic_bind_data(result,
2743 auth_type, auth_level,
2744 server, target_service,
2745 domain, username, password,
2746 CRED_AUTO_USE_KERBEROS,
2747 NULL,
2748 &auth);
2749 if (!NT_STATUS_IS_OK(status)) {
2750 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2751 nt_errstr(status)));
2752 goto err;
2755 status = rpc_pipe_bind(result, auth);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
2758 nt_errstr(status) ));
2759 goto err;
2762 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
2763 "machine %s and bound as user %s\\%s.\n", table->name,
2764 result->desthost, domain, username));
2766 *presult = result;
2767 return NT_STATUS_OK;
2769 err:
2771 TALLOC_FREE(result);
2772 return status;
2775 /****************************************************************************
2776 External interface.
2777 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2778 using session_key. sign and seal.
2780 The *pdc will be stolen onto this new pipe
2781 ****************************************************************************/
2783 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2784 const struct ndr_interface_table *table,
2785 enum dcerpc_transport_t transport,
2786 enum dcerpc_AuthLevel auth_level,
2787 const char *domain,
2788 struct netlogon_creds_CredentialState **pdc,
2789 struct rpc_pipe_client **_rpccli)
2791 struct rpc_pipe_client *rpccli;
2792 struct pipe_auth_data *rpcauth;
2793 NTSTATUS status;
2794 NTSTATUS result;
2795 struct netlogon_creds_CredentialState save_creds;
2796 struct netr_Authenticator auth;
2797 struct netr_Authenticator return_auth;
2798 union netr_Capabilities capabilities;
2799 const char *target_service = table->authservices->names[0];
2801 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 return status;
2806 status = rpccli_generic_bind_data(rpccli,
2807 DCERPC_AUTH_TYPE_SCHANNEL,
2808 auth_level,
2809 NULL,
2810 target_service,
2811 domain,
2812 (*pdc)->computer_name,
2813 NULL,
2814 CRED_AUTO_USE_KERBEROS,
2815 *pdc,
2816 &rpcauth);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2819 nt_errstr(status)));
2820 TALLOC_FREE(rpccli);
2821 return status;
2825 * The credentials on a new netlogon pipe are the ones we are passed
2826 * in - copy them over
2828 * This may get overwritten... in rpc_pipe_bind()...
2830 rpccli->dc = netlogon_creds_copy(rpccli, *pdc);
2831 if (rpccli->dc == NULL) {
2832 TALLOC_FREE(rpccli);
2833 return NT_STATUS_NO_MEMORY;
2836 status = rpc_pipe_bind(rpccli, rpcauth);
2837 if (!NT_STATUS_IS_OK(status)) {
2838 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
2839 "cli_rpc_pipe_bind failed with error %s\n",
2840 nt_errstr(status) ));
2841 TALLOC_FREE(rpccli);
2842 return status;
2845 if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
2846 goto done;
2849 save_creds = *rpccli->dc;
2850 ZERO_STRUCT(return_auth);
2851 ZERO_STRUCT(capabilities);
2853 netlogon_creds_client_authenticator(&save_creds, &auth);
2855 status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle,
2856 talloc_tos(),
2857 rpccli->srv_name_slash,
2858 save_creds.computer_name,
2859 &auth, &return_auth,
2860 1, &capabilities,
2861 &result);
2862 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2863 if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2864 DEBUG(5, ("AES was negotiated and the error was %s - "
2865 "downgrade detected\n",
2866 nt_errstr(status)));
2867 TALLOC_FREE(rpccli);
2868 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2871 /* This is probably an old Samba Version */
2872 DEBUG(5, ("We are checking against an NT or old Samba - %s\n",
2873 nt_errstr(status)));
2874 goto done;
2877 if (!NT_STATUS_IS_OK(status)) {
2878 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
2879 nt_errstr(status)));
2880 TALLOC_FREE(rpccli);
2881 return status;
2884 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
2885 if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2886 /* This means AES isn't supported. */
2887 DEBUG(5, ("AES was negotiated and the result was %s - "
2888 "downgrade detected\n",
2889 nt_errstr(result)));
2890 TALLOC_FREE(rpccli);
2891 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2894 /* This is probably an old Windows version */
2895 DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n",
2896 nt_errstr(result)));
2897 goto done;
2901 * We need to check the credential state here, cause win2k3 and earlier
2902 * returns NT_STATUS_NOT_IMPLEMENTED
2904 if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) {
2906 * Server replied with bad credential. Fail.
2908 DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s "
2909 "replied with bad credential\n",
2910 rpccli->desthost));
2911 TALLOC_FREE(rpccli);
2912 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2914 *rpccli->dc = save_creds;
2916 if (!NT_STATUS_IS_OK(result)) {
2917 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
2918 nt_errstr(result)));
2919 TALLOC_FREE(rpccli);
2920 return result;
2923 if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) {
2924 /* This means AES isn't supported. */
2925 DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities "
2926 "was OK - downgrade detected\n"));
2927 TALLOC_FREE(rpccli);
2928 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2931 if (save_creds.negotiate_flags != capabilities.server_capabilities) {
2932 DEBUG(0, ("The client capabilities don't match the server "
2933 "capabilities: local[0x%08X] remote[0x%08X]\n",
2934 save_creds.negotiate_flags,
2935 capabilities.server_capabilities));
2936 TALLOC_FREE(rpccli);
2937 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2940 done:
2941 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2942 "for domain %s and bound using schannel.\n",
2943 table->name,
2944 rpccli->desthost, domain));
2946 *_rpccli = rpccli;
2947 return NT_STATUS_OK;
2950 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
2951 const struct ndr_interface_table *table,
2952 enum dcerpc_transport_t transport,
2953 const char *oid,
2954 enum dcerpc_AuthLevel auth_level,
2955 const char *server,
2956 const char *domain,
2957 const char *username,
2958 const char *password,
2959 struct rpc_pipe_client **presult)
2961 struct rpc_pipe_client *result;
2962 struct pipe_auth_data *auth = NULL;
2963 const char *target_service = table->authservices->names[0];
2965 NTSTATUS status;
2966 enum credentials_use_kerberos use_kerberos;
2968 if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
2969 use_kerberos = CRED_MUST_USE_KERBEROS;
2970 } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
2971 use_kerberos = CRED_DONT_USE_KERBEROS;
2972 } else {
2973 return NT_STATUS_INVALID_PARAMETER;
2976 status = cli_rpc_pipe_open(cli, transport, table, &result);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 return status;
2981 status = rpccli_generic_bind_data(result,
2982 DCERPC_AUTH_TYPE_SPNEGO, auth_level,
2983 server, target_service,
2984 domain, username, password,
2985 use_kerberos, NULL,
2986 &auth);
2987 if (!NT_STATUS_IS_OK(status)) {
2988 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2989 nt_errstr(status)));
2990 goto err;
2993 status = rpc_pipe_bind(result, auth);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
2996 nt_errstr(status) ));
2997 goto err;
3000 DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
3001 "machine %s.\n", table->name,
3002 result->desthost));
3004 *presult = result;
3005 return NT_STATUS_OK;
3007 err:
3009 TALLOC_FREE(result);
3010 return status;
3013 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3014 struct rpc_pipe_client *cli,
3015 DATA_BLOB *session_key)
3017 NTSTATUS status;
3018 struct pipe_auth_data *a;
3019 struct gensec_security *gensec_security;
3020 DATA_BLOB sk = data_blob_null;
3021 bool make_dup = false;
3023 if (!session_key || !cli) {
3024 return NT_STATUS_INVALID_PARAMETER;
3027 a = cli->auth;
3029 if (a == NULL) {
3030 return NT_STATUS_INVALID_PARAMETER;
3033 switch (cli->auth->auth_type) {
3034 case DCERPC_AUTH_TYPE_SPNEGO:
3035 case DCERPC_AUTH_TYPE_NTLMSSP:
3036 case DCERPC_AUTH_TYPE_KRB5:
3037 gensec_security = talloc_get_type_abort(a->auth_ctx,
3038 struct gensec_security);
3039 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 return status;
3043 make_dup = false;
3044 break;
3045 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3046 case DCERPC_AUTH_TYPE_NONE:
3047 sk = data_blob_const(a->transport_session_key.data,
3048 a->transport_session_key.length);
3049 make_dup = true;
3050 break;
3051 default:
3052 break;
3055 if (!sk.data) {
3056 return NT_STATUS_NO_USER_SESSION_KEY;
3059 if (make_dup) {
3060 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3061 } else {
3062 *session_key = sk;
3065 return NT_STATUS_OK;