s3-dcerpc: Check data and return appropriate error
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob1bee2f875b8c5e6d605fb19b773821c68c89dacc
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.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "librpc/gen_ndr/cli_epmapper.h"
23 #include "../librpc/gen_ndr/ndr_schannel.h"
24 #include "../librpc/gen_ndr/ndr_dssetup.h"
25 #include "../librpc/gen_ndr/ndr_netlogon.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "ntlmssp_wrap.h"
31 #include "rpc_client/cli_netlogon.h"
32 #include "librpc/gen_ndr/ndr_dcerpc.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "librpc/rpc/dcerpc_gssapi.h"
35 #include "librpc/rpc/dcerpc_spnego.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_RPC_CLI
40 /********************************************************************
41 Pipe description for a DEBUG
42 ********************************************************************/
43 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
44 struct rpc_pipe_client *cli)
46 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
47 if (result == NULL) {
48 return "pipe";
50 return result;
53 /********************************************************************
54 Rpc pipe call id.
55 ********************************************************************/
57 static uint32 get_rpc_call_id(void)
59 static uint32 call_id = 0;
60 return ++call_id;
63 /*******************************************************************
64 Use SMBreadX to get rest of one fragment's worth of rpc data.
65 Reads the whole size or give an error message
66 ********************************************************************/
68 struct rpc_read_state {
69 struct event_context *ev;
70 struct rpc_cli_transport *transport;
71 uint8_t *data;
72 size_t size;
73 size_t num_read;
76 static void rpc_read_done(struct tevent_req *subreq);
78 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
79 struct event_context *ev,
80 struct rpc_cli_transport *transport,
81 uint8_t *data, size_t size)
83 struct tevent_req *req, *subreq;
84 struct rpc_read_state *state;
86 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
87 if (req == NULL) {
88 return NULL;
90 state->ev = ev;
91 state->transport = transport;
92 state->data = data;
93 state->size = size;
94 state->num_read = 0;
96 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
98 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
99 transport->priv);
100 if (subreq == NULL) {
101 goto fail;
103 tevent_req_set_callback(subreq, rpc_read_done, req);
104 return req;
106 fail:
107 TALLOC_FREE(req);
108 return NULL;
111 static void rpc_read_done(struct tevent_req *subreq)
113 struct tevent_req *req = tevent_req_callback_data(
114 subreq, struct tevent_req);
115 struct rpc_read_state *state = tevent_req_data(
116 req, struct rpc_read_state);
117 NTSTATUS status;
118 ssize_t received;
120 status = state->transport->read_recv(subreq, &received);
121 TALLOC_FREE(subreq);
122 if (!NT_STATUS_IS_OK(status)) {
123 tevent_req_nterror(req, status);
124 return;
127 state->num_read += received;
128 if (state->num_read == state->size) {
129 tevent_req_done(req);
130 return;
133 subreq = state->transport->read_send(state, state->ev,
134 state->data + state->num_read,
135 state->size - state->num_read,
136 state->transport->priv);
137 if (tevent_req_nomem(subreq, req)) {
138 return;
140 tevent_req_set_callback(subreq, rpc_read_done, req);
143 static NTSTATUS rpc_read_recv(struct tevent_req *req)
145 return tevent_req_simple_recv_ntstatus(req);
148 struct rpc_write_state {
149 struct event_context *ev;
150 struct rpc_cli_transport *transport;
151 const uint8_t *data;
152 size_t size;
153 size_t num_written;
156 static void rpc_write_done(struct tevent_req *subreq);
158 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
159 struct event_context *ev,
160 struct rpc_cli_transport *transport,
161 const uint8_t *data, size_t size)
163 struct tevent_req *req, *subreq;
164 struct rpc_write_state *state;
166 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
167 if (req == NULL) {
168 return NULL;
170 state->ev = ev;
171 state->transport = transport;
172 state->data = data;
173 state->size = size;
174 state->num_written = 0;
176 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
178 subreq = transport->write_send(state, ev, data, size, transport->priv);
179 if (subreq == NULL) {
180 goto fail;
182 tevent_req_set_callback(subreq, rpc_write_done, req);
183 return req;
184 fail:
185 TALLOC_FREE(req);
186 return NULL;
189 static void rpc_write_done(struct tevent_req *subreq)
191 struct tevent_req *req = tevent_req_callback_data(
192 subreq, struct tevent_req);
193 struct rpc_write_state *state = tevent_req_data(
194 req, struct rpc_write_state);
195 NTSTATUS status;
196 ssize_t written;
198 status = state->transport->write_recv(subreq, &written);
199 TALLOC_FREE(subreq);
200 if (!NT_STATUS_IS_OK(status)) {
201 tevent_req_nterror(req, status);
202 return;
205 state->num_written += written;
207 if (state->num_written == state->size) {
208 tevent_req_done(req);
209 return;
212 subreq = state->transport->write_send(state, state->ev,
213 state->data + state->num_written,
214 state->size - state->num_written,
215 state->transport->priv);
216 if (tevent_req_nomem(subreq, req)) {
217 return;
219 tevent_req_set_callback(subreq, rpc_write_done, req);
222 static NTSTATUS rpc_write_recv(struct tevent_req *req)
224 return tevent_req_simple_recv_ntstatus(req);
228 /****************************************************************************
229 Try and get a PDU's worth of data from current_pdu. If not, then read more
230 from the wire.
231 ****************************************************************************/
233 struct get_complete_frag_state {
234 struct event_context *ev;
235 struct rpc_pipe_client *cli;
236 uint16_t frag_len;
237 DATA_BLOB *pdu;
240 static void get_complete_frag_got_header(struct tevent_req *subreq);
241 static void get_complete_frag_got_rest(struct tevent_req *subreq);
243 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
244 struct event_context *ev,
245 struct rpc_pipe_client *cli,
246 DATA_BLOB *pdu)
248 struct tevent_req *req, *subreq;
249 struct get_complete_frag_state *state;
250 size_t received;
251 NTSTATUS status;
253 req = tevent_req_create(mem_ctx, &state,
254 struct get_complete_frag_state);
255 if (req == NULL) {
256 return NULL;
258 state->ev = ev;
259 state->cli = cli;
260 state->frag_len = RPC_HEADER_LEN;
261 state->pdu = pdu;
263 received = pdu->length;
264 if (received < RPC_HEADER_LEN) {
265 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
266 status = NT_STATUS_NO_MEMORY;
267 goto post_status;
269 subreq = rpc_read_send(state, state->ev,
270 state->cli->transport,
271 pdu->data + received,
272 RPC_HEADER_LEN - received);
273 if (subreq == NULL) {
274 status = NT_STATUS_NO_MEMORY;
275 goto post_status;
277 tevent_req_set_callback(subreq, get_complete_frag_got_header,
278 req);
279 return req;
282 state->frag_len = dcerpc_get_frag_length(pdu);
285 * Ensure we have frag_len bytes of data.
287 if (received < state->frag_len) {
288 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
289 status = NT_STATUS_NO_MEMORY;
290 goto post_status;
292 subreq = rpc_read_send(state, state->ev,
293 state->cli->transport,
294 pdu->data + received,
295 state->frag_len - received);
296 if (subreq == NULL) {
297 status = NT_STATUS_NO_MEMORY;
298 goto post_status;
300 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
301 req);
302 return req;
305 status = NT_STATUS_OK;
306 post_status:
307 if (NT_STATUS_IS_OK(status)) {
308 tevent_req_done(req);
309 } else {
310 tevent_req_nterror(req, status);
312 return tevent_req_post(req, ev);
315 static void get_complete_frag_got_header(struct tevent_req *subreq)
317 struct tevent_req *req = tevent_req_callback_data(
318 subreq, struct tevent_req);
319 struct get_complete_frag_state *state = tevent_req_data(
320 req, struct get_complete_frag_state);
321 NTSTATUS status;
323 status = rpc_read_recv(subreq);
324 TALLOC_FREE(subreq);
325 if (!NT_STATUS_IS_OK(status)) {
326 tevent_req_nterror(req, status);
327 return;
330 state->frag_len = dcerpc_get_frag_length(state->pdu);
332 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
333 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
334 return;
338 * We're here in this piece of code because we've read exactly
339 * RPC_HEADER_LEN bytes into state->pdu.
342 subreq = rpc_read_send(state, state->ev, state->cli->transport,
343 state->pdu->data + RPC_HEADER_LEN,
344 state->frag_len - RPC_HEADER_LEN);
345 if (tevent_req_nomem(subreq, req)) {
346 return;
348 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
351 static void get_complete_frag_got_rest(struct tevent_req *subreq)
353 struct tevent_req *req = tevent_req_callback_data(
354 subreq, struct tevent_req);
355 NTSTATUS status;
357 status = rpc_read_recv(subreq);
358 TALLOC_FREE(subreq);
359 if (!NT_STATUS_IS_OK(status)) {
360 tevent_req_nterror(req, status);
361 return;
363 tevent_req_done(req);
366 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
368 return tevent_req_simple_recv_ntstatus(req);
371 /****************************************************************************
372 Do basic authentication checks on an incoming pdu.
373 ****************************************************************************/
375 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
376 struct rpc_pipe_client *cli,
377 struct ncacn_packet *pkt,
378 DATA_BLOB *pdu,
379 uint8_t expected_pkt_type,
380 DATA_BLOB *rdata,
381 DATA_BLOB *reply_pdu)
383 struct dcerpc_response *r;
384 NTSTATUS ret = NT_STATUS_OK;
385 size_t pad_len = 0;
388 * Point the return values at the real data including the RPC
389 * header. Just in case the caller wants it.
391 *rdata = *pdu;
393 /* Ensure we have the correct type. */
394 switch (pkt->ptype) {
395 case DCERPC_PKT_ALTER_RESP:
396 case DCERPC_PKT_BIND_ACK:
398 /* Client code never receives this kind of packets */
399 break;
402 case DCERPC_PKT_RESPONSE:
404 r = &pkt->u.response;
406 /* Here's where we deal with incoming sign/seal. */
407 ret = dcerpc_check_auth(cli->auth, pkt,
408 &r->stub_and_verifier,
409 DCERPC_RESPONSE_LENGTH,
410 pdu, &pad_len);
411 if (!NT_STATUS_IS_OK(ret)) {
412 return ret;
415 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
416 return NT_STATUS_BUFFER_TOO_SMALL;
419 /* Point the return values at the NDR data. */
420 rdata->data = r->stub_and_verifier.data;
422 if (pkt->auth_length) {
423 /* We've already done integer wrap tests in
424 * dcerpc_check_auth(). */
425 rdata->length = r->stub_and_verifier.length
426 - pad_len
427 - DCERPC_AUTH_TRAILER_LENGTH
428 - pkt->auth_length;
429 } else {
430 rdata->length = r->stub_and_verifier.length;
433 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
434 (long unsigned int)pdu->length,
435 (long unsigned int)rdata->length,
436 (unsigned int)pad_len));
439 * If this is the first reply, and the allocation hint is
440 * reasonable, try and set up the reply_pdu DATA_BLOB to the
441 * correct size.
444 if ((reply_pdu->length == 0) &&
445 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
446 if (!data_blob_realloc(mem_ctx, reply_pdu,
447 r->alloc_hint)) {
448 DEBUG(0, ("reply alloc hint %d too "
449 "large to allocate\n",
450 (int)r->alloc_hint));
451 return NT_STATUS_NO_MEMORY;
455 break;
457 case DCERPC_PKT_BIND_NAK:
458 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
459 rpccli_pipe_txt(talloc_tos(), cli)));
460 /* Use this for now... */
461 return NT_STATUS_NETWORK_ACCESS_DENIED;
463 case DCERPC_PKT_FAULT:
465 DEBUG(1, (__location__ ": RPC fault code %s received "
466 "from %s!\n",
467 dcerpc_errstr(talloc_tos(),
468 pkt->u.fault.status),
469 rpccli_pipe_txt(talloc_tos(), cli)));
471 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
472 return NT_STATUS_UNSUCCESSFUL;
473 } else {
474 return NT_STATUS(pkt->u.fault.status);
477 default:
478 DEBUG(0, (__location__ "Unknown packet type %u received "
479 "from %s!\n",
480 (unsigned int)pkt->ptype,
481 rpccli_pipe_txt(talloc_tos(), cli)));
482 return NT_STATUS_INVALID_INFO_CLASS;
485 if (pkt->ptype != expected_pkt_type) {
486 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
487 "RPC packet type - %u, not %u\n",
488 rpccli_pipe_txt(talloc_tos(), cli),
489 pkt->ptype, expected_pkt_type));
490 return NT_STATUS_INVALID_INFO_CLASS;
493 /* Do this just before return - we don't want to modify any rpc header
494 data before now as we may have needed to do cryptographic actions on
495 it before. */
497 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
498 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
499 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
500 "fragment first/last ON.\n"));
501 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
504 return NT_STATUS_OK;
507 /****************************************************************************
508 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
509 ****************************************************************************/
511 struct cli_api_pipe_state {
512 struct event_context *ev;
513 struct rpc_cli_transport *transport;
514 uint8_t *rdata;
515 uint32_t rdata_len;
518 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
519 static void cli_api_pipe_write_done(struct tevent_req *subreq);
520 static void cli_api_pipe_read_done(struct tevent_req *subreq);
522 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
523 struct event_context *ev,
524 struct rpc_cli_transport *transport,
525 uint8_t *data, size_t data_len,
526 uint32_t max_rdata_len)
528 struct tevent_req *req, *subreq;
529 struct cli_api_pipe_state *state;
530 NTSTATUS status;
532 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
533 if (req == NULL) {
534 return NULL;
536 state->ev = ev;
537 state->transport = transport;
539 if (max_rdata_len < RPC_HEADER_LEN) {
541 * For a RPC reply we always need at least RPC_HEADER_LEN
542 * bytes. We check this here because we will receive
543 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
545 status = NT_STATUS_INVALID_PARAMETER;
546 goto post_status;
549 if (transport->trans_send != NULL) {
550 subreq = transport->trans_send(state, ev, data, data_len,
551 max_rdata_len, transport->priv);
552 if (subreq == NULL) {
553 goto fail;
555 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
556 return req;
560 * If the transport does not provide a "trans" routine, i.e. for
561 * example the ncacn_ip_tcp transport, do the write/read step here.
564 subreq = rpc_write_send(state, ev, transport, data, data_len);
565 if (subreq == NULL) {
566 goto fail;
568 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
569 return req;
571 post_status:
572 tevent_req_nterror(req, status);
573 return tevent_req_post(req, ev);
574 fail:
575 TALLOC_FREE(req);
576 return NULL;
579 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
581 struct tevent_req *req = tevent_req_callback_data(
582 subreq, struct tevent_req);
583 struct cli_api_pipe_state *state = tevent_req_data(
584 req, struct cli_api_pipe_state);
585 NTSTATUS status;
587 status = state->transport->trans_recv(subreq, state, &state->rdata,
588 &state->rdata_len);
589 TALLOC_FREE(subreq);
590 if (!NT_STATUS_IS_OK(status)) {
591 tevent_req_nterror(req, status);
592 return;
594 tevent_req_done(req);
597 static void cli_api_pipe_write_done(struct tevent_req *subreq)
599 struct tevent_req *req = tevent_req_callback_data(
600 subreq, struct tevent_req);
601 struct cli_api_pipe_state *state = tevent_req_data(
602 req, struct cli_api_pipe_state);
603 NTSTATUS status;
605 status = rpc_write_recv(subreq);
606 TALLOC_FREE(subreq);
607 if (!NT_STATUS_IS_OK(status)) {
608 tevent_req_nterror(req, status);
609 return;
612 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
613 if (tevent_req_nomem(state->rdata, req)) {
614 return;
618 * We don't need to use rpc_read_send here, the upper layer will cope
619 * with a short read, transport->trans_send could also return less
620 * than state->max_rdata_len.
622 subreq = state->transport->read_send(state, state->ev, state->rdata,
623 RPC_HEADER_LEN,
624 state->transport->priv);
625 if (tevent_req_nomem(subreq, req)) {
626 return;
628 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
631 static void cli_api_pipe_read_done(struct tevent_req *subreq)
633 struct tevent_req *req = tevent_req_callback_data(
634 subreq, struct tevent_req);
635 struct cli_api_pipe_state *state = tevent_req_data(
636 req, struct cli_api_pipe_state);
637 NTSTATUS status;
638 ssize_t received;
640 status = state->transport->read_recv(subreq, &received);
641 TALLOC_FREE(subreq);
642 if (!NT_STATUS_IS_OK(status)) {
643 tevent_req_nterror(req, status);
644 return;
646 state->rdata_len = received;
647 tevent_req_done(req);
650 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
651 uint8_t **prdata, uint32_t *prdata_len)
653 struct cli_api_pipe_state *state = tevent_req_data(
654 req, struct cli_api_pipe_state);
655 NTSTATUS status;
657 if (tevent_req_is_nterror(req, &status)) {
658 return status;
661 *prdata = talloc_move(mem_ctx, &state->rdata);
662 *prdata_len = state->rdata_len;
663 return NT_STATUS_OK;
666 /****************************************************************************
667 Send data on an rpc pipe via trans. The data must be the last
668 pdu fragment of an NDR data stream.
670 Receive response data from an rpc pipe, which may be large...
672 Read the first fragment: unfortunately have to use SMBtrans for the first
673 bit, then SMBreadX for subsequent bits.
675 If first fragment received also wasn't the last fragment, continue
676 getting fragments until we _do_ receive the last fragment.
678 Request/Response PDU's look like the following...
680 |<------------------PDU len----------------------------------------------->|
681 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
683 +------------+-----------------+-------------+---------------+-------------+
684 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
685 +------------+-----------------+-------------+---------------+-------------+
687 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
688 signing & sealing being negotiated.
690 ****************************************************************************/
692 struct rpc_api_pipe_state {
693 struct event_context *ev;
694 struct rpc_pipe_client *cli;
695 uint8_t expected_pkt_type;
697 DATA_BLOB incoming_frag;
698 struct ncacn_packet *pkt;
700 /* Incoming reply */
701 DATA_BLOB reply_pdu;
702 size_t reply_pdu_offset;
703 uint8_t endianess;
706 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
707 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
709 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
710 struct event_context *ev,
711 struct rpc_pipe_client *cli,
712 DATA_BLOB *data, /* Outgoing PDU */
713 uint8_t expected_pkt_type)
715 struct tevent_req *req, *subreq;
716 struct rpc_api_pipe_state *state;
717 uint16_t max_recv_frag;
718 NTSTATUS status;
720 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
721 if (req == NULL) {
722 return NULL;
724 state->ev = ev;
725 state->cli = cli;
726 state->expected_pkt_type = expected_pkt_type;
727 state->incoming_frag = data_blob_null;
728 state->reply_pdu = data_blob_null;
729 state->reply_pdu_offset = 0;
730 state->endianess = DCERPC_DREP_LE;
733 * Ensure we're not sending too much.
735 if (data->length > cli->max_xmit_frag) {
736 status = NT_STATUS_INVALID_PARAMETER;
737 goto post_status;
740 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
742 /* get the header first, then fetch the rest once we have
743 * the frag_length available */
744 max_recv_frag = RPC_HEADER_LEN;
746 subreq = cli_api_pipe_send(state, ev, cli->transport,
747 data->data, data->length, max_recv_frag);
748 if (subreq == NULL) {
749 goto fail;
751 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
752 return req;
754 post_status:
755 tevent_req_nterror(req, status);
756 return tevent_req_post(req, ev);
757 fail:
758 TALLOC_FREE(req);
759 return NULL;
762 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
764 struct tevent_req *req = tevent_req_callback_data(
765 subreq, struct tevent_req);
766 struct rpc_api_pipe_state *state = tevent_req_data(
767 req, struct rpc_api_pipe_state);
768 NTSTATUS status;
769 uint8_t *rdata = NULL;
770 uint32_t rdata_len = 0;
772 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
773 TALLOC_FREE(subreq);
774 if (!NT_STATUS_IS_OK(status)) {
775 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
776 tevent_req_nterror(req, status);
777 return;
780 if (rdata == NULL) {
781 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
782 rpccli_pipe_txt(talloc_tos(), state->cli)));
783 tevent_req_done(req);
784 return;
788 * Move data on state->incoming_frag.
790 state->incoming_frag.data = talloc_move(state, &rdata);
791 state->incoming_frag.length = rdata_len;
792 if (!state->incoming_frag.data) {
793 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
794 return;
797 /* Ensure we have enough data for a pdu. */
798 subreq = get_complete_frag_send(state, state->ev, state->cli,
799 &state->incoming_frag);
800 if (tevent_req_nomem(subreq, req)) {
801 return;
803 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
806 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
808 struct tevent_req *req = tevent_req_callback_data(
809 subreq, struct tevent_req);
810 struct rpc_api_pipe_state *state = tevent_req_data(
811 req, struct rpc_api_pipe_state);
812 NTSTATUS status;
813 DATA_BLOB rdata = data_blob_null;
815 status = get_complete_frag_recv(subreq);
816 TALLOC_FREE(subreq);
817 if (!NT_STATUS_IS_OK(status)) {
818 DEBUG(5, ("get_complete_frag failed: %s\n",
819 nt_errstr(status)));
820 tevent_req_nterror(req, status);
821 return;
824 state->pkt = talloc(state, struct ncacn_packet);
825 if (!state->pkt) {
826 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
827 return;
830 status = dcerpc_pull_ncacn_packet(state,
831 &state->incoming_frag,
832 state->pkt,
833 !state->endianess);
834 if (!NT_STATUS_IS_OK(status)) {
835 tevent_req_nterror(req, status);
836 return;
839 if (state->incoming_frag.length != state->pkt->frag_length) {
840 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
841 (unsigned int)state->incoming_frag.length,
842 (unsigned int)state->pkt->frag_length));
843 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
844 return;
847 status = cli_pipe_validate_current_pdu(state,
848 state->cli, state->pkt,
849 &state->incoming_frag,
850 state->expected_pkt_type,
851 &rdata,
852 &state->reply_pdu);
854 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
855 (unsigned)state->incoming_frag.length,
856 (unsigned)state->reply_pdu_offset,
857 nt_errstr(status)));
859 if (!NT_STATUS_IS_OK(status)) {
860 tevent_req_nterror(req, status);
861 return;
864 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
865 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
867 * Set the data type correctly for big-endian data on the
868 * first packet.
870 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
871 "big-endian.\n",
872 rpccli_pipe_txt(talloc_tos(), state->cli)));
873 state->endianess = 0x00; /* BIG ENDIAN */
876 * Check endianness on subsequent packets.
878 if (state->endianess != state->pkt->drep[0]) {
879 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
880 "%s\n",
881 state->endianess?"little":"big",
882 state->pkt->drep[0]?"little":"big"));
883 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
884 return;
887 /* Now copy the data portion out of the pdu into rbuf. */
888 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
889 if (!data_blob_realloc(NULL, &state->reply_pdu,
890 state->reply_pdu_offset + rdata.length)) {
891 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
892 return;
896 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
897 rdata.data, rdata.length);
898 state->reply_pdu_offset += rdata.length;
900 /* reset state->incoming_frag, there is no need to free it,
901 * it will be reallocated to the right size the next time
902 * it is used */
903 state->incoming_frag.length = 0;
905 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
906 /* make sure the pdu length is right now that we
907 * have all the data available (alloc hint may
908 * have allocated more than was actually used) */
909 state->reply_pdu.length = state->reply_pdu_offset;
910 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
911 rpccli_pipe_txt(talloc_tos(), state->cli),
912 (unsigned)state->reply_pdu.length));
913 tevent_req_done(req);
914 return;
917 subreq = get_complete_frag_send(state, state->ev, state->cli,
918 &state->incoming_frag);
919 if (tevent_req_nomem(subreq, req)) {
920 return;
922 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
925 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
926 struct ncacn_packet **pkt,
927 DATA_BLOB *reply_pdu)
929 struct rpc_api_pipe_state *state = tevent_req_data(
930 req, struct rpc_api_pipe_state);
931 NTSTATUS status;
933 if (tevent_req_is_nterror(req, &status)) {
934 return status;
937 /* return data to caller and assign it ownership of memory */
938 if (reply_pdu) {
939 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
940 reply_pdu->length = state->reply_pdu.length;
941 state->reply_pdu.length = 0;
942 } else {
943 data_blob_free(&state->reply_pdu);
946 if (pkt) {
947 *pkt = talloc_steal(mem_ctx, state->pkt);
950 return NT_STATUS_OK;
953 /*******************************************************************
954 Creates spnego auth bind.
955 ********************************************************************/
957 static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx,
958 struct pipe_auth_data *auth,
959 DATA_BLOB *auth_token)
961 DATA_BLOB in_token = data_blob_null;
962 NTSTATUS status;
964 /* Negotiate the initial auth token */
965 status = spnego_get_client_auth_token(mem_ctx,
966 auth->a_u.spnego_state,
967 &in_token, auth_token);
968 if (!NT_STATUS_IS_OK(status)) {
969 return status;
972 DEBUG(5, ("Created GSS Authentication Token:\n"));
973 dump_data(5, auth_token->data, auth_token->length);
975 return NT_STATUS_OK;
978 /*******************************************************************
979 Creates krb5 auth bind.
980 ********************************************************************/
982 static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx,
983 struct pipe_auth_data *auth,
984 DATA_BLOB *auth_token)
986 DATA_BLOB in_token = data_blob_null;
987 NTSTATUS status;
989 /* Negotiate the initial auth token */
990 status = gse_get_client_auth_token(mem_ctx,
991 auth->a_u.gssapi_state,
992 &in_token,
993 auth_token);
994 if (!NT_STATUS_IS_OK(status)) {
995 return status;
998 DEBUG(5, ("Created GSS Authentication Token:\n"));
999 dump_data(5, auth_token->data, auth_token->length);
1001 return NT_STATUS_OK;
1004 /*******************************************************************
1005 Creates NTLMSSP auth bind.
1006 ********************************************************************/
1008 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1009 DATA_BLOB *auth_token)
1011 NTSTATUS status;
1012 DATA_BLOB null_blob = data_blob_null;
1014 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1015 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1016 null_blob, auth_token);
1018 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1019 data_blob_free(auth_token);
1020 return status;
1023 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1024 dump_data(5, auth_token->data, auth_token->length);
1026 return NT_STATUS_OK;
1029 /*******************************************************************
1030 Creates schannel auth bind.
1031 ********************************************************************/
1033 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1034 DATA_BLOB *auth_token)
1036 NTSTATUS status;
1037 struct NL_AUTH_MESSAGE r;
1039 /* Use lp_workgroup() if domain not specified */
1041 if (!cli->auth->domain || !cli->auth->domain[0]) {
1042 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1043 if (cli->auth->domain == NULL) {
1044 return NT_STATUS_NO_MEMORY;
1049 * Now marshall the data into the auth parse_struct.
1052 r.MessageType = NL_NEGOTIATE_REQUEST;
1053 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1054 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1055 r.oem_netbios_domain.a = cli->auth->domain;
1056 r.oem_netbios_computer.a = global_myname();
1058 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 return status;
1063 return NT_STATUS_OK;
1066 /*******************************************************************
1067 Creates the internals of a DCE/RPC bind request or alter context PDU.
1068 ********************************************************************/
1070 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1071 enum dcerpc_pkt_type ptype,
1072 uint32 rpc_call_id,
1073 const struct ndr_syntax_id *abstract,
1074 const struct ndr_syntax_id *transfer,
1075 const DATA_BLOB *auth_info,
1076 DATA_BLOB *blob)
1078 uint16 auth_len = auth_info->length;
1079 NTSTATUS status;
1080 union dcerpc_payload u;
1081 struct dcerpc_ctx_list ctx_list;
1083 if (auth_len) {
1084 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1087 ctx_list.context_id = 0;
1088 ctx_list.num_transfer_syntaxes = 1;
1089 ctx_list.abstract_syntax = *abstract;
1090 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1092 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1093 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1094 u.bind.assoc_group_id = 0x0;
1095 u.bind.num_contexts = 1;
1096 u.bind.ctx_list = &ctx_list;
1097 u.bind.auth_info = *auth_info;
1099 status = dcerpc_push_ncacn_packet(mem_ctx,
1100 ptype,
1101 DCERPC_PFC_FLAG_FIRST |
1102 DCERPC_PFC_FLAG_LAST,
1103 auth_len,
1104 rpc_call_id,
1106 blob);
1107 if (!NT_STATUS_IS_OK(status)) {
1108 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1109 return status;
1112 return NT_STATUS_OK;
1115 /*******************************************************************
1116 Creates a DCE/RPC bind request.
1117 ********************************************************************/
1119 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1120 struct rpc_pipe_client *cli,
1121 struct pipe_auth_data *auth,
1122 uint32 rpc_call_id,
1123 const struct ndr_syntax_id *abstract,
1124 const struct ndr_syntax_id *transfer,
1125 DATA_BLOB *rpc_out)
1127 DATA_BLOB auth_token = data_blob_null;
1128 DATA_BLOB auth_info = data_blob_null;
1129 NTSTATUS ret = NT_STATUS_OK;
1131 switch (auth->auth_type) {
1132 case DCERPC_AUTH_TYPE_SCHANNEL:
1133 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1134 if (!NT_STATUS_IS_OK(ret)) {
1135 return ret;
1137 break;
1139 case DCERPC_AUTH_TYPE_NTLMSSP:
1140 ret = create_ntlmssp_auth_rpc_bind_req(cli, &auth_token);
1141 if (!NT_STATUS_IS_OK(ret)) {
1142 return ret;
1144 break;
1146 case DCERPC_AUTH_TYPE_SPNEGO:
1147 ret = create_spnego_auth_bind_req(cli, auth, &auth_token);
1148 if (!NT_STATUS_IS_OK(ret)) {
1149 return ret;
1151 break;
1153 case DCERPC_AUTH_TYPE_KRB5:
1154 ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_token);
1155 if (!NT_STATUS_IS_OK(ret)) {
1156 return ret;
1158 break;
1160 case DCERPC_AUTH_TYPE_NONE:
1161 break;
1163 default:
1164 /* "Can't" happen. */
1165 return NT_STATUS_INVALID_INFO_CLASS;
1168 if (auth_token.length != 0) {
1169 ret = dcerpc_push_dcerpc_auth(cli,
1170 auth->auth_type,
1171 auth->auth_level,
1172 0, /* auth_pad_length */
1173 1, /* auth_context_id */
1174 &auth_token,
1175 &auth_info);
1176 if (!NT_STATUS_IS_OK(ret)) {
1177 return ret;
1179 data_blob_free(&auth_token);
1182 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1183 DCERPC_PKT_BIND,
1184 rpc_call_id,
1185 abstract,
1186 transfer,
1187 &auth_info,
1188 rpc_out);
1189 return ret;
1192 /*******************************************************************
1193 External interface.
1194 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1195 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1196 and deals with signing/sealing details.
1197 ********************************************************************/
1199 struct rpc_api_pipe_req_state {
1200 struct event_context *ev;
1201 struct rpc_pipe_client *cli;
1202 uint8_t op_num;
1203 uint32_t call_id;
1204 DATA_BLOB *req_data;
1205 uint32_t req_data_sent;
1206 DATA_BLOB rpc_out;
1207 DATA_BLOB reply_pdu;
1210 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1211 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1212 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1213 bool *is_last_frag);
1215 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1216 struct event_context *ev,
1217 struct rpc_pipe_client *cli,
1218 uint8_t op_num,
1219 DATA_BLOB *req_data)
1221 struct tevent_req *req, *subreq;
1222 struct rpc_api_pipe_req_state *state;
1223 NTSTATUS status;
1224 bool is_last_frag;
1226 req = tevent_req_create(mem_ctx, &state,
1227 struct rpc_api_pipe_req_state);
1228 if (req == NULL) {
1229 return NULL;
1231 state->ev = ev;
1232 state->cli = cli;
1233 state->op_num = op_num;
1234 state->req_data = req_data;
1235 state->req_data_sent = 0;
1236 state->call_id = get_rpc_call_id();
1237 state->reply_pdu = data_blob_null;
1238 state->rpc_out = data_blob_null;
1240 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1241 + RPC_MAX_SIGN_SIZE) {
1242 /* Server is screwed up ! */
1243 status = NT_STATUS_INVALID_PARAMETER;
1244 goto post_status;
1247 status = prepare_next_frag(state, &is_last_frag);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 goto post_status;
1252 if (is_last_frag) {
1253 subreq = rpc_api_pipe_send(state, ev, state->cli,
1254 &state->rpc_out,
1255 DCERPC_PKT_RESPONSE);
1256 if (subreq == NULL) {
1257 goto fail;
1259 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1260 } else {
1261 subreq = rpc_write_send(state, ev, cli->transport,
1262 state->rpc_out.data,
1263 state->rpc_out.length);
1264 if (subreq == NULL) {
1265 goto fail;
1267 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1268 req);
1270 return req;
1272 post_status:
1273 tevent_req_nterror(req, status);
1274 return tevent_req_post(req, ev);
1275 fail:
1276 TALLOC_FREE(req);
1277 return NULL;
1280 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1281 bool *is_last_frag)
1283 size_t data_sent_thistime;
1284 size_t auth_len;
1285 size_t frag_len;
1286 uint8_t flags = 0;
1287 size_t pad_len;
1288 size_t data_left;
1289 NTSTATUS status;
1290 union dcerpc_payload u;
1292 data_left = state->req_data->length - state->req_data_sent;
1294 status = dcerpc_guess_sizes(state->cli->auth,
1295 DCERPC_REQUEST_LENGTH, data_left,
1296 state->cli->max_xmit_frag,
1297 CLIENT_NDR_PADDING_SIZE,
1298 &data_sent_thistime,
1299 &frag_len, &auth_len, &pad_len);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 return status;
1304 if (state->req_data_sent == 0) {
1305 flags = DCERPC_PFC_FLAG_FIRST;
1308 if (data_sent_thistime == data_left) {
1309 flags |= DCERPC_PFC_FLAG_LAST;
1312 data_blob_free(&state->rpc_out);
1314 ZERO_STRUCT(u.request);
1316 u.request.alloc_hint = state->req_data->length;
1317 u.request.context_id = 0;
1318 u.request.opnum = state->op_num;
1320 status = dcerpc_push_ncacn_packet(state,
1321 DCERPC_PKT_REQUEST,
1322 flags,
1323 auth_len,
1324 state->call_id,
1326 &state->rpc_out);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 return status;
1331 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1332 * compute it right for requests because the auth trailer is missing
1333 * at this stage */
1334 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1336 /* Copy in the data. */
1337 if (!data_blob_append(NULL, &state->rpc_out,
1338 state->req_data->data + state->req_data_sent,
1339 data_sent_thistime)) {
1340 return NT_STATUS_NO_MEMORY;
1343 switch (state->cli->auth->auth_level) {
1344 case DCERPC_AUTH_LEVEL_NONE:
1345 case DCERPC_AUTH_LEVEL_CONNECT:
1346 case DCERPC_AUTH_LEVEL_PACKET:
1347 break;
1348 case DCERPC_AUTH_LEVEL_INTEGRITY:
1349 case DCERPC_AUTH_LEVEL_PRIVACY:
1350 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1351 &state->rpc_out);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 return status;
1355 break;
1356 default:
1357 return NT_STATUS_INVALID_PARAMETER;
1360 state->req_data_sent += data_sent_thistime;
1361 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1363 return status;
1366 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1368 struct tevent_req *req = tevent_req_callback_data(
1369 subreq, struct tevent_req);
1370 struct rpc_api_pipe_req_state *state = tevent_req_data(
1371 req, struct rpc_api_pipe_req_state);
1372 NTSTATUS status;
1373 bool is_last_frag;
1375 status = rpc_write_recv(subreq);
1376 TALLOC_FREE(subreq);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 tevent_req_nterror(req, status);
1379 return;
1382 status = prepare_next_frag(state, &is_last_frag);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 tevent_req_nterror(req, status);
1385 return;
1388 if (is_last_frag) {
1389 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1390 &state->rpc_out,
1391 DCERPC_PKT_RESPONSE);
1392 if (tevent_req_nomem(subreq, req)) {
1393 return;
1395 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1396 } else {
1397 subreq = rpc_write_send(state, state->ev,
1398 state->cli->transport,
1399 state->rpc_out.data,
1400 state->rpc_out.length);
1401 if (tevent_req_nomem(subreq, req)) {
1402 return;
1404 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1405 req);
1409 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1411 struct tevent_req *req = tevent_req_callback_data(
1412 subreq, struct tevent_req);
1413 struct rpc_api_pipe_req_state *state = tevent_req_data(
1414 req, struct rpc_api_pipe_req_state);
1415 NTSTATUS status;
1417 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1418 TALLOC_FREE(subreq);
1419 if (!NT_STATUS_IS_OK(status)) {
1420 tevent_req_nterror(req, status);
1421 return;
1423 tevent_req_done(req);
1426 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1427 DATA_BLOB *reply_pdu)
1429 struct rpc_api_pipe_req_state *state = tevent_req_data(
1430 req, struct rpc_api_pipe_req_state);
1431 NTSTATUS status;
1433 if (tevent_req_is_nterror(req, &status)) {
1435 * We always have to initialize to reply pdu, even if there is
1436 * none. The rpccli_* caller routines expect this.
1438 *reply_pdu = data_blob_null;
1439 return status;
1442 /* return data to caller and assign it ownership of memory */
1443 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1444 reply_pdu->length = state->reply_pdu.length;
1445 state->reply_pdu.length = 0;
1447 return NT_STATUS_OK;
1450 #if 0
1451 /****************************************************************************
1452 Set the handle state.
1453 ****************************************************************************/
1455 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1456 const char *pipe_name, uint16 device_state)
1458 bool state_set = False;
1459 char param[2];
1460 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1461 char *rparam = NULL;
1462 char *rdata = NULL;
1463 uint32 rparam_len, rdata_len;
1465 if (pipe_name == NULL)
1466 return False;
1468 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1469 cli->fnum, pipe_name, device_state));
1471 /* create parameters: device state */
1472 SSVAL(param, 0, device_state);
1474 /* create setup parameters. */
1475 setup[0] = 0x0001;
1476 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1478 /* send the data on \PIPE\ */
1479 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1480 setup, 2, 0, /* setup, length, max */
1481 param, 2, 0, /* param, length, max */
1482 NULL, 0, 1024, /* data, length, max */
1483 &rparam, &rparam_len, /* return param, length */
1484 &rdata, &rdata_len)) /* return data, length */
1486 DEBUG(5, ("Set Handle state: return OK\n"));
1487 state_set = True;
1490 SAFE_FREE(rparam);
1491 SAFE_FREE(rdata);
1493 return state_set;
1495 #endif
1497 /****************************************************************************
1498 Check the rpc bind acknowledge response.
1499 ****************************************************************************/
1501 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1502 const struct ndr_syntax_id *transfer)
1504 struct dcerpc_ack_ctx ctx;
1506 if (r->secondary_address_size == 0) {
1507 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1510 if (r->num_results < 1 || !r->ctx_list) {
1511 return false;
1514 ctx = r->ctx_list[0];
1516 /* check the transfer syntax */
1517 if ((ctx.syntax.if_version != transfer->if_version) ||
1518 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1519 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1520 return False;
1523 if (r->num_results != 0x1 || ctx.result != 0) {
1524 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1525 r->num_results, ctx.reason));
1528 DEBUG(5,("check_bind_response: accepted!\n"));
1529 return True;
1532 /*******************************************************************
1533 Creates a DCE/RPC bind authentication response.
1534 This is the packet that is sent back to the server once we
1535 have received a BIND-ACK, to finish the third leg of
1536 the authentication handshake.
1537 ********************************************************************/
1539 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1540 struct rpc_pipe_client *cli,
1541 uint32 rpc_call_id,
1542 enum dcerpc_AuthType auth_type,
1543 enum dcerpc_AuthLevel auth_level,
1544 DATA_BLOB *pauth_blob,
1545 DATA_BLOB *rpc_out)
1547 NTSTATUS status;
1548 union dcerpc_payload u;
1550 u.auth3._pad = 0;
1552 status = dcerpc_push_dcerpc_auth(mem_ctx,
1553 auth_type,
1554 auth_level,
1555 0, /* auth_pad_length */
1556 1, /* auth_context_id */
1557 pauth_blob,
1558 &u.auth3.auth_info);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 return status;
1563 status = dcerpc_push_ncacn_packet(mem_ctx,
1564 DCERPC_PKT_AUTH3,
1565 DCERPC_PFC_FLAG_FIRST |
1566 DCERPC_PFC_FLAG_LAST,
1567 pauth_blob->length,
1568 rpc_call_id,
1570 rpc_out);
1571 data_blob_free(&u.auth3.auth_info);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1574 return status;
1577 return NT_STATUS_OK;
1580 /*******************************************************************
1581 Creates a DCE/RPC bind alter context authentication request which
1582 may contain a spnego auth blobl
1583 ********************************************************************/
1585 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1586 enum dcerpc_AuthType auth_type,
1587 enum dcerpc_AuthLevel auth_level,
1588 uint32 rpc_call_id,
1589 const struct ndr_syntax_id *abstract,
1590 const struct ndr_syntax_id *transfer,
1591 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1592 DATA_BLOB *rpc_out)
1594 DATA_BLOB auth_info;
1595 NTSTATUS status;
1597 status = dcerpc_push_dcerpc_auth(mem_ctx,
1598 auth_type,
1599 auth_level,
1600 0, /* auth_pad_length */
1601 1, /* auth_context_id */
1602 pauth_blob,
1603 &auth_info);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 return status;
1608 status = create_bind_or_alt_ctx_internal(mem_ctx,
1609 DCERPC_PKT_ALTER,
1610 rpc_call_id,
1611 abstract,
1612 transfer,
1613 &auth_info,
1614 rpc_out);
1615 data_blob_free(&auth_info);
1616 return status;
1619 /****************************************************************************
1620 Do an rpc bind.
1621 ****************************************************************************/
1623 struct rpc_pipe_bind_state {
1624 struct event_context *ev;
1625 struct rpc_pipe_client *cli;
1626 DATA_BLOB rpc_out;
1627 uint32_t rpc_call_id;
1630 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1631 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1632 struct rpc_pipe_bind_state *state,
1633 DATA_BLOB *credentials);
1634 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
1635 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1636 struct rpc_pipe_bind_state *state,
1637 DATA_BLOB *credentials);
1638 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1639 struct rpc_pipe_bind_state *state,
1640 DATA_BLOB *credentials);
1642 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1643 struct event_context *ev,
1644 struct rpc_pipe_client *cli,
1645 struct pipe_auth_data *auth)
1647 struct tevent_req *req, *subreq;
1648 struct rpc_pipe_bind_state *state;
1649 NTSTATUS status;
1651 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1652 if (req == NULL) {
1653 return NULL;
1656 DEBUG(5,("Bind RPC Pipe: %s auth_type %u(%u), auth_level %u\n",
1657 rpccli_pipe_txt(talloc_tos(), cli),
1658 (unsigned int)auth->auth_type,
1659 (unsigned int)auth->spnego_type,
1660 (unsigned int)auth->auth_level ));
1662 state->ev = ev;
1663 state->cli = cli;
1664 state->rpc_call_id = get_rpc_call_id();
1665 state->rpc_out = data_blob_null;
1667 cli->auth = talloc_move(cli, &auth);
1669 /* Marshall the outgoing data. */
1670 status = create_rpc_bind_req(state, cli,
1671 cli->auth,
1672 state->rpc_call_id,
1673 &cli->abstract_syntax,
1674 &cli->transfer_syntax,
1675 &state->rpc_out);
1677 if (!NT_STATUS_IS_OK(status)) {
1678 goto post_status;
1681 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1682 DCERPC_PKT_BIND_ACK);
1683 if (subreq == NULL) {
1684 goto fail;
1686 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1687 return req;
1689 post_status:
1690 tevent_req_nterror(req, status);
1691 return tevent_req_post(req, ev);
1692 fail:
1693 TALLOC_FREE(req);
1694 return NULL;
1697 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1699 struct tevent_req *req = tevent_req_callback_data(
1700 subreq, struct tevent_req);
1701 struct rpc_pipe_bind_state *state = tevent_req_data(
1702 req, struct rpc_pipe_bind_state);
1703 struct pipe_auth_data *pauth = state->cli->auth;
1704 DATA_BLOB reply_pdu;
1705 struct ncacn_packet *pkt;
1706 struct dcerpc_auth auth;
1707 DATA_BLOB auth_token = data_blob_null;
1708 NTSTATUS status;
1710 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
1711 TALLOC_FREE(subreq);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1714 rpccli_pipe_txt(talloc_tos(), state->cli),
1715 nt_errstr(status)));
1716 tevent_req_nterror(req, status);
1717 return;
1720 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1721 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1722 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1723 return;
1726 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1727 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1729 switch(state->cli->auth->auth_type) {
1731 case DCERPC_AUTH_TYPE_NONE:
1732 case DCERPC_AUTH_TYPE_SCHANNEL:
1733 /* Bind complete. */
1734 tevent_req_done(req);
1735 return;
1737 case DCERPC_AUTH_TYPE_NTLMSSP:
1738 case DCERPC_AUTH_TYPE_SPNEGO:
1739 case DCERPC_AUTH_TYPE_KRB5:
1740 /* Paranoid lenght checks */
1741 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1742 + pkt->auth_length) {
1743 tevent_req_nterror(req,
1744 NT_STATUS_INFO_LENGTH_MISMATCH);
1745 return;
1747 /* get auth credentials */
1748 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1749 &pkt->u.bind_ack.auth_info,
1750 &auth, false);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1753 nt_errstr(status)));
1754 tevent_req_nterror(req, status);
1755 return;
1757 break;
1759 default:
1760 goto err_out;
1764 * For authenticated binds we may need to do 3 or 4 leg binds.
1767 switch(state->cli->auth->auth_type) {
1769 case DCERPC_AUTH_TYPE_NONE:
1770 case DCERPC_AUTH_TYPE_SCHANNEL:
1771 /* Bind complete. */
1772 tevent_req_done(req);
1773 return;
1775 case DCERPC_AUTH_TYPE_NTLMSSP:
1776 /* Need to send AUTH3 packet - no reply. */
1777 status = rpc_finish_auth3_bind_send(req, state,
1778 &auth.credentials);
1779 break;
1781 case DCERPC_AUTH_TYPE_SPNEGO:
1782 status = spnego_get_client_auth_token(state,
1783 pauth->a_u.spnego_state,
1784 &auth.credentials,
1785 &auth_token);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 break;
1789 if (auth_token.length == 0) {
1790 /* Bind complete. */
1791 tevent_req_done(req);
1792 return;
1794 if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
1795 status = rpc_bind_next_send(req, state,
1796 &auth_token);
1797 } else {
1798 status = rpc_bind_finish_send(req, state,
1799 &auth_token);
1801 break;
1803 case DCERPC_AUTH_TYPE_KRB5:
1804 status = gse_get_client_auth_token(state,
1805 pauth->a_u.gssapi_state,
1806 &auth.credentials,
1807 &auth_token);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 break;
1812 if (gse_require_more_processing(pauth->a_u.gssapi_state)) {
1813 status = rpc_bind_next_send(req, state, &auth_token);
1814 } else {
1815 status = rpc_bind_finish_send(req, state, &auth_token);
1817 break;
1819 default:
1820 goto err_out;
1823 if (!NT_STATUS_IS_OK(status)) {
1824 tevent_req_nterror(req, status);
1826 return;
1828 err_out:
1829 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u(%u)\n",
1830 (unsigned int)state->cli->auth->auth_type,
1831 (unsigned int)state->cli->auth->spnego_type));
1832 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1835 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1836 struct rpc_pipe_bind_state *state,
1837 DATA_BLOB *credentials)
1839 struct pipe_auth_data *auth = state->cli->auth;
1840 DATA_BLOB client_reply = data_blob_null;
1841 struct tevent_req *subreq;
1842 NTSTATUS status;
1844 /* TODO - check auth_type/auth_level match. */
1846 status = auth_ntlmssp_update(auth->a_u.auth_ntlmssp_state,
1847 *credentials, &client_reply);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
1851 "blob failed: %s.\n", nt_errstr(status)));
1852 return status;
1855 data_blob_free(&state->rpc_out);
1857 status = create_rpc_bind_auth3(state, state->cli,
1858 state->rpc_call_id,
1859 auth->auth_type,
1860 auth->auth_level,
1861 &client_reply,
1862 &state->rpc_out);
1863 data_blob_free(&client_reply);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 return status;
1869 subreq = rpc_write_send(state, state->ev, state->cli->transport,
1870 state->rpc_out.data, state->rpc_out.length);
1871 if (subreq == NULL) {
1872 return NT_STATUS_NO_MEMORY;
1874 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1875 return NT_STATUS_OK;
1878 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
1880 struct tevent_req *req = tevent_req_callback_data(
1881 subreq, struct tevent_req);
1882 NTSTATUS status;
1884 status = rpc_write_recv(subreq);
1885 TALLOC_FREE(subreq);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 tevent_req_nterror(req, status);
1888 return;
1890 tevent_req_done(req);
1893 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1894 struct rpc_pipe_bind_state *state,
1895 DATA_BLOB *auth_token)
1897 struct pipe_auth_data *auth = state->cli->auth;
1898 struct tevent_req *subreq;
1899 NTSTATUS status;
1901 /* Now prepare the alter context pdu. */
1902 data_blob_free(&state->rpc_out);
1904 status = create_rpc_alter_context(state,
1905 auth->auth_type,
1906 auth->auth_level,
1907 state->rpc_call_id,
1908 &state->cli->abstract_syntax,
1909 &state->cli->transfer_syntax,
1910 auth_token,
1911 &state->rpc_out);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 return status;
1916 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1917 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1918 if (subreq == NULL) {
1919 return NT_STATUS_NO_MEMORY;
1921 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1922 return NT_STATUS_OK;
1925 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1926 struct rpc_pipe_bind_state *state,
1927 DATA_BLOB *auth_token)
1929 struct pipe_auth_data *auth = state->cli->auth;
1930 struct tevent_req *subreq;
1931 NTSTATUS status;
1933 /* Now prepare the auth3 context pdu. */
1934 data_blob_free(&state->rpc_out);
1936 status = create_rpc_bind_auth3(state, state->cli,
1937 state->rpc_call_id,
1938 auth->auth_type,
1939 auth->auth_level,
1940 auth_token,
1941 &state->rpc_out);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 return status;
1946 subreq = rpc_write_send(state, state->ev, state->cli->transport,
1947 state->rpc_out.data, state->rpc_out.length);
1948 if (subreq == NULL) {
1949 return NT_STATUS_NO_MEMORY;
1951 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1952 return NT_STATUS_OK;
1955 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1957 return tevent_req_simple_recv_ntstatus(req);
1960 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1961 struct pipe_auth_data *auth)
1963 TALLOC_CTX *frame = talloc_stackframe();
1964 struct event_context *ev;
1965 struct tevent_req *req;
1966 NTSTATUS status = NT_STATUS_OK;
1968 ev = event_context_init(frame);
1969 if (ev == NULL) {
1970 status = NT_STATUS_NO_MEMORY;
1971 goto fail;
1974 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1975 if (req == NULL) {
1976 status = NT_STATUS_NO_MEMORY;
1977 goto fail;
1980 if (!tevent_req_poll(req, ev)) {
1981 status = map_nt_error_from_unix(errno);
1982 goto fail;
1985 status = rpc_pipe_bind_recv(req);
1986 fail:
1987 TALLOC_FREE(frame);
1988 return status;
1991 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1993 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1994 unsigned int timeout)
1996 unsigned int old;
1998 if (rpc_cli->transport == NULL) {
1999 return RPCCLI_DEFAULT_TIMEOUT;
2002 if (rpc_cli->transport->set_timeout == NULL) {
2003 return RPCCLI_DEFAULT_TIMEOUT;
2006 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2007 if (old == 0) {
2008 return RPCCLI_DEFAULT_TIMEOUT;
2011 return old;
2014 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2016 if (rpc_cli == NULL) {
2017 return false;
2020 if (rpc_cli->transport == NULL) {
2021 return false;
2024 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2027 struct rpccli_bh_state {
2028 struct rpc_pipe_client *rpc_cli;
2031 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2033 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2034 struct rpccli_bh_state);
2036 return rpccli_is_connected(hs->rpc_cli);
2039 struct rpccli_bh_raw_call_state {
2040 DATA_BLOB in_data;
2041 DATA_BLOB out_data;
2042 uint32_t out_flags;
2045 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2047 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2048 struct tevent_context *ev,
2049 struct dcerpc_binding_handle *h,
2050 const struct GUID *object,
2051 uint32_t opnum,
2052 uint32_t in_flags,
2053 const uint8_t *in_data,
2054 size_t in_length)
2056 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2057 struct rpccli_bh_state);
2058 struct tevent_req *req;
2059 struct rpccli_bh_raw_call_state *state;
2060 bool ok;
2061 struct tevent_req *subreq;
2063 req = tevent_req_create(mem_ctx, &state,
2064 struct rpccli_bh_raw_call_state);
2065 if (req == NULL) {
2066 return NULL;
2068 state->in_data.data = discard_const_p(uint8_t, in_data);
2069 state->in_data.length = in_length;
2071 ok = rpccli_bh_is_connected(h);
2072 if (!ok) {
2073 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2074 return tevent_req_post(req, ev);
2077 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2078 opnum, &state->in_data);
2079 if (tevent_req_nomem(subreq, req)) {
2080 return tevent_req_post(req, ev);
2082 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2084 return req;
2087 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2089 struct tevent_req *req =
2090 tevent_req_callback_data(subreq,
2091 struct tevent_req);
2092 struct rpccli_bh_raw_call_state *state =
2093 tevent_req_data(req,
2094 struct rpccli_bh_raw_call_state);
2095 NTSTATUS status;
2097 state->out_flags = 0;
2099 /* TODO: support bigendian responses */
2101 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2102 TALLOC_FREE(subreq);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 tevent_req_nterror(req, status);
2105 return;
2108 tevent_req_done(req);
2111 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2112 TALLOC_CTX *mem_ctx,
2113 uint8_t **out_data,
2114 size_t *out_length,
2115 uint32_t *out_flags)
2117 struct rpccli_bh_raw_call_state *state =
2118 tevent_req_data(req,
2119 struct rpccli_bh_raw_call_state);
2120 NTSTATUS status;
2122 if (tevent_req_is_nterror(req, &status)) {
2123 tevent_req_received(req);
2124 return status;
2127 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2128 *out_length = state->out_data.length;
2129 *out_flags = state->out_flags;
2130 tevent_req_received(req);
2131 return NT_STATUS_OK;
2134 struct rpccli_bh_disconnect_state {
2135 uint8_t _dummy;
2138 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2139 struct tevent_context *ev,
2140 struct dcerpc_binding_handle *h)
2142 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2143 struct rpccli_bh_state);
2144 struct tevent_req *req;
2145 struct rpccli_bh_disconnect_state *state;
2146 bool ok;
2148 req = tevent_req_create(mem_ctx, &state,
2149 struct rpccli_bh_disconnect_state);
2150 if (req == NULL) {
2151 return NULL;
2154 ok = rpccli_bh_is_connected(h);
2155 if (!ok) {
2156 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2157 return tevent_req_post(req, ev);
2161 * TODO: do a real async disconnect ...
2163 * For now the caller needs to free rpc_cli
2165 hs->rpc_cli = NULL;
2167 tevent_req_done(req);
2168 return tevent_req_post(req, ev);
2171 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2173 NTSTATUS status;
2175 if (tevent_req_is_nterror(req, &status)) {
2176 tevent_req_received(req);
2177 return status;
2180 tevent_req_received(req);
2181 return NT_STATUS_OK;
2184 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2186 return true;
2189 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2190 int ndr_flags,
2191 const void *_struct_ptr,
2192 const struct ndr_interface_call *call)
2194 void *struct_ptr = discard_const(_struct_ptr);
2196 if (DEBUGLEVEL < 10) {
2197 return;
2200 if (ndr_flags & NDR_IN) {
2201 ndr_print_function_debug(call->ndr_print,
2202 call->name,
2203 ndr_flags,
2204 struct_ptr);
2206 if (ndr_flags & NDR_OUT) {
2207 ndr_print_function_debug(call->ndr_print,
2208 call->name,
2209 ndr_flags,
2210 struct_ptr);
2214 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2215 .name = "rpccli",
2216 .is_connected = rpccli_bh_is_connected,
2217 .raw_call_send = rpccli_bh_raw_call_send,
2218 .raw_call_recv = rpccli_bh_raw_call_recv,
2219 .disconnect_send = rpccli_bh_disconnect_send,
2220 .disconnect_recv = rpccli_bh_disconnect_recv,
2222 .ref_alloc = rpccli_bh_ref_alloc,
2223 .do_ndr_print = rpccli_bh_do_ndr_print,
2226 /* initialise a rpc_pipe_client binding handle */
2227 static struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2229 struct dcerpc_binding_handle *h;
2230 struct rpccli_bh_state *hs;
2232 h = dcerpc_binding_handle_create(c,
2233 &rpccli_bh_ops,
2234 NULL,
2235 NULL, /* TODO */
2236 &hs,
2237 struct rpccli_bh_state,
2238 __location__);
2239 if (h == NULL) {
2240 return NULL;
2242 hs->rpc_cli = c;
2244 return h;
2247 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2249 struct auth_ntlmssp_state *a = NULL;
2250 struct cli_state *cli;
2252 if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2253 a = rpc_cli->auth->a_u.auth_ntlmssp_state;
2254 } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
2255 enum dcerpc_AuthType auth_type;
2256 void *auth_ctx;
2257 NTSTATUS status;
2259 status = spnego_get_negotiated_mech(
2260 rpc_cli->auth->a_u.spnego_state,
2261 &auth_type, &auth_ctx);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 return false;
2266 if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2267 a = talloc_get_type(auth_ctx,
2268 struct auth_ntlmssp_state);
2272 if (a) {
2273 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
2274 return true;
2277 cli = rpc_pipe_np_smb_conn(rpc_cli);
2278 if (cli == NULL) {
2279 return false;
2281 E_md4hash(cli->password ? cli->password : "", nt_hash);
2282 return true;
2285 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2286 struct pipe_auth_data **presult)
2288 struct pipe_auth_data *result;
2290 result = talloc(mem_ctx, struct pipe_auth_data);
2291 if (result == NULL) {
2292 return NT_STATUS_NO_MEMORY;
2295 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2296 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2297 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2299 result->user_name = talloc_strdup(result, "");
2300 result->domain = talloc_strdup(result, "");
2301 if ((result->user_name == NULL) || (result->domain == NULL)) {
2302 TALLOC_FREE(result);
2303 return NT_STATUS_NO_MEMORY;
2306 *presult = result;
2307 return NT_STATUS_OK;
2310 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2312 TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2313 return 0;
2316 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2317 enum dcerpc_AuthType auth_type,
2318 enum dcerpc_AuthLevel auth_level,
2319 const char *domain,
2320 const char *username,
2321 const char *password,
2322 struct pipe_auth_data **presult)
2324 struct pipe_auth_data *result;
2325 NTSTATUS status;
2327 result = talloc(mem_ctx, struct pipe_auth_data);
2328 if (result == NULL) {
2329 return NT_STATUS_NO_MEMORY;
2332 result->auth_type = auth_type;
2333 result->auth_level = auth_level;
2335 result->user_name = talloc_strdup(result, username);
2336 result->domain = talloc_strdup(result, domain);
2337 if ((result->user_name == NULL) || (result->domain == NULL)) {
2338 status = NT_STATUS_NO_MEMORY;
2339 goto fail;
2342 status = auth_ntlmssp_client_start(NULL,
2343 global_myname(),
2344 lp_workgroup(),
2345 lp_client_ntlmv2_auth(),
2346 &result->a_u.auth_ntlmssp_state);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 goto fail;
2351 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2353 status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2354 username);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 goto fail;
2359 status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2360 domain);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 goto fail;
2365 status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2366 password);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 goto fail;
2372 * Turn off sign+seal to allow selected auth level to turn it back on.
2374 auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2375 ~(NTLMSSP_NEGOTIATE_SIGN |
2376 NTLMSSP_NEGOTIATE_SEAL));
2378 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2379 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2380 NTLMSSP_NEGOTIATE_SIGN);
2381 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2382 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2383 NTLMSSP_NEGOTIATE_SEAL |
2384 NTLMSSP_NEGOTIATE_SIGN);
2387 *presult = result;
2388 return NT_STATUS_OK;
2390 fail:
2391 TALLOC_FREE(result);
2392 return status;
2395 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2396 enum dcerpc_AuthLevel auth_level,
2397 struct netlogon_creds_CredentialState *creds,
2398 struct pipe_auth_data **presult)
2400 struct pipe_auth_data *result;
2402 result = talloc(mem_ctx, struct pipe_auth_data);
2403 if (result == NULL) {
2404 return NT_STATUS_NO_MEMORY;
2407 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2408 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2409 result->auth_level = auth_level;
2411 result->user_name = talloc_strdup(result, "");
2412 result->domain = talloc_strdup(result, domain);
2413 if ((result->user_name == NULL) || (result->domain == NULL)) {
2414 goto fail;
2417 result->a_u.schannel_auth = talloc(result, struct schannel_state);
2418 if (result->a_u.schannel_auth == NULL) {
2419 goto fail;
2422 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2423 result->a_u.schannel_auth->seq_num = 0;
2424 result->a_u.schannel_auth->initiator = true;
2425 result->a_u.schannel_auth->creds = creds;
2427 *presult = result;
2428 return NT_STATUS_OK;
2430 fail:
2431 TALLOC_FREE(result);
2432 return NT_STATUS_NO_MEMORY;
2436 * Create an rpc pipe client struct, connecting to a tcp port.
2438 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2439 uint16_t port,
2440 const struct ndr_syntax_id *abstract_syntax,
2441 struct rpc_pipe_client **presult)
2443 struct rpc_pipe_client *result;
2444 struct sockaddr_storage addr;
2445 NTSTATUS status;
2446 int fd;
2448 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2449 if (result == NULL) {
2450 return NT_STATUS_NO_MEMORY;
2453 result->abstract_syntax = *abstract_syntax;
2454 result->transfer_syntax = ndr_transfer_syntax;
2456 result->desthost = talloc_strdup(result, host);
2457 result->srv_name_slash = talloc_asprintf_strupper_m(
2458 result, "\\\\%s", result->desthost);
2459 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2460 status = NT_STATUS_NO_MEMORY;
2461 goto fail;
2464 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2465 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2467 if (!resolve_name(host, &addr, 0, false)) {
2468 status = NT_STATUS_NOT_FOUND;
2469 goto fail;
2472 status = open_socket_out(&addr, port, 60, &fd);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 goto fail;
2476 set_socket_options(fd, lp_socket_options());
2478 status = rpc_transport_sock_init(result, fd, &result->transport);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 close(fd);
2481 goto fail;
2484 result->transport->transport = NCACN_IP_TCP;
2486 result->binding_handle = rpccli_bh_create(result);
2487 if (result->binding_handle == NULL) {
2488 TALLOC_FREE(result);
2489 return NT_STATUS_NO_MEMORY;
2492 *presult = result;
2493 return NT_STATUS_OK;
2495 fail:
2496 TALLOC_FREE(result);
2497 return status;
2501 * Determine the tcp port on which a dcerpc interface is listening
2502 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2503 * target host.
2505 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2506 const struct ndr_syntax_id *abstract_syntax,
2507 uint16_t *pport)
2509 NTSTATUS status;
2510 struct rpc_pipe_client *epm_pipe = NULL;
2511 struct pipe_auth_data *auth = NULL;
2512 struct dcerpc_binding *map_binding = NULL;
2513 struct dcerpc_binding *res_binding = NULL;
2514 struct epm_twr_t *map_tower = NULL;
2515 struct epm_twr_t *res_towers = NULL;
2516 struct policy_handle *entry_handle = NULL;
2517 uint32_t num_towers = 0;
2518 uint32_t max_towers = 1;
2519 struct epm_twr_p_t towers;
2520 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2522 if (pport == NULL) {
2523 status = NT_STATUS_INVALID_PARAMETER;
2524 goto done;
2527 /* open the connection to the endpoint mapper */
2528 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2529 &ndr_table_epmapper.syntax_id,
2530 &epm_pipe);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 goto done;
2536 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 goto done;
2541 status = rpc_pipe_bind(epm_pipe, auth);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 goto done;
2546 /* create tower for asking the epmapper */
2548 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2549 if (map_binding == NULL) {
2550 status = NT_STATUS_NO_MEMORY;
2551 goto done;
2554 map_binding->transport = NCACN_IP_TCP;
2555 map_binding->object = *abstract_syntax;
2556 map_binding->host = host; /* needed? */
2557 map_binding->endpoint = "0"; /* correct? needed? */
2559 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2560 if (map_tower == NULL) {
2561 status = NT_STATUS_NO_MEMORY;
2562 goto done;
2565 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2566 &(map_tower->tower));
2567 if (!NT_STATUS_IS_OK(status)) {
2568 goto done;
2571 /* allocate further parameters for the epm_Map call */
2573 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2574 if (res_towers == NULL) {
2575 status = NT_STATUS_NO_MEMORY;
2576 goto done;
2578 towers.twr = res_towers;
2580 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2581 if (entry_handle == NULL) {
2582 status = NT_STATUS_NO_MEMORY;
2583 goto done;
2586 /* ask the endpoint mapper for the port */
2588 status = rpccli_epm_Map(epm_pipe,
2589 tmp_ctx,
2590 CONST_DISCARD(struct GUID *,
2591 &(abstract_syntax->uuid)),
2592 map_tower,
2593 entry_handle,
2594 max_towers,
2595 &num_towers,
2596 &towers);
2598 if (!NT_STATUS_IS_OK(status)) {
2599 goto done;
2602 if (num_towers != 1) {
2603 status = NT_STATUS_UNSUCCESSFUL;
2604 goto done;
2607 /* extract the port from the answer */
2609 status = dcerpc_binding_from_tower(tmp_ctx,
2610 &(towers.twr->tower),
2611 &res_binding);
2612 if (!NT_STATUS_IS_OK(status)) {
2613 goto done;
2616 /* are further checks here necessary? */
2617 if (res_binding->transport != NCACN_IP_TCP) {
2618 status = NT_STATUS_UNSUCCESSFUL;
2619 goto done;
2622 *pport = (uint16_t)atoi(res_binding->endpoint);
2624 done:
2625 TALLOC_FREE(tmp_ctx);
2626 return status;
2630 * Create a rpc pipe client struct, connecting to a host via tcp.
2631 * The port is determined by asking the endpoint mapper on the given
2632 * host.
2634 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2635 const struct ndr_syntax_id *abstract_syntax,
2636 struct rpc_pipe_client **presult)
2638 NTSTATUS status;
2639 uint16_t port = 0;
2641 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 return status;
2646 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2647 abstract_syntax, presult);
2650 /********************************************************************
2651 Create a rpc pipe client struct, connecting to a unix domain socket
2652 ********************************************************************/
2653 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2654 const struct ndr_syntax_id *abstract_syntax,
2655 struct rpc_pipe_client **presult)
2657 struct rpc_pipe_client *result;
2658 struct sockaddr_un addr;
2659 NTSTATUS status;
2660 int fd;
2662 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2663 if (result == NULL) {
2664 return NT_STATUS_NO_MEMORY;
2667 result->abstract_syntax = *abstract_syntax;
2668 result->transfer_syntax = ndr_transfer_syntax;
2670 result->desthost = get_myname(result);
2671 result->srv_name_slash = talloc_asprintf_strupper_m(
2672 result, "\\\\%s", result->desthost);
2673 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2674 status = NT_STATUS_NO_MEMORY;
2675 goto fail;
2678 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2679 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2681 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2682 if (fd == -1) {
2683 status = map_nt_error_from_unix(errno);
2684 goto fail;
2687 ZERO_STRUCT(addr);
2688 addr.sun_family = AF_UNIX;
2689 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2691 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2692 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2693 strerror(errno)));
2694 close(fd);
2695 return map_nt_error_from_unix(errno);
2698 status = rpc_transport_sock_init(result, fd, &result->transport);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 close(fd);
2701 goto fail;
2704 result->transport->transport = NCALRPC;
2706 result->binding_handle = rpccli_bh_create(result);
2707 if (result->binding_handle == NULL) {
2708 TALLOC_FREE(result);
2709 return NT_STATUS_NO_MEMORY;
2712 *presult = result;
2713 return NT_STATUS_OK;
2715 fail:
2716 TALLOC_FREE(result);
2717 return status;
2720 struct rpc_pipe_client_np_ref {
2721 struct cli_state *cli;
2722 struct rpc_pipe_client *pipe;
2725 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2727 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2728 return 0;
2731 /****************************************************************************
2732 Open a named pipe over SMB to a remote server.
2734 * CAVEAT CALLER OF THIS FUNCTION:
2735 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2736 * so be sure that this function is called AFTER any structure (vs pointer)
2737 * assignment of the cli. In particular, libsmbclient does structure
2738 * assignments of cli, which invalidates the data in the returned
2739 * rpc_pipe_client if this function is called before the structure assignment
2740 * of cli.
2742 ****************************************************************************/
2744 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2745 const struct ndr_syntax_id *abstract_syntax,
2746 struct rpc_pipe_client **presult)
2748 struct rpc_pipe_client *result;
2749 NTSTATUS status;
2750 struct rpc_pipe_client_np_ref *np_ref;
2752 /* sanity check to protect against crashes */
2754 if ( !cli ) {
2755 return NT_STATUS_INVALID_HANDLE;
2758 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2759 if (result == NULL) {
2760 return NT_STATUS_NO_MEMORY;
2763 result->abstract_syntax = *abstract_syntax;
2764 result->transfer_syntax = ndr_transfer_syntax;
2765 result->desthost = talloc_strdup(result, cli->desthost);
2766 result->srv_name_slash = talloc_asprintf_strupper_m(
2767 result, "\\\\%s", result->desthost);
2769 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2770 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2772 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2773 TALLOC_FREE(result);
2774 return NT_STATUS_NO_MEMORY;
2777 status = rpc_transport_np_init(result, cli, abstract_syntax,
2778 &result->transport);
2779 if (!NT_STATUS_IS_OK(status)) {
2780 TALLOC_FREE(result);
2781 return status;
2784 result->transport->transport = NCACN_NP;
2786 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2787 if (np_ref == NULL) {
2788 TALLOC_FREE(result);
2789 return NT_STATUS_NO_MEMORY;
2791 np_ref->cli = cli;
2792 np_ref->pipe = result;
2794 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2795 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2797 result->binding_handle = rpccli_bh_create(result);
2798 if (result->binding_handle == NULL) {
2799 TALLOC_FREE(result);
2800 return NT_STATUS_NO_MEMORY;
2803 *presult = result;
2804 return NT_STATUS_OK;
2807 /****************************************************************************
2808 Open a pipe to a remote server.
2809 ****************************************************************************/
2811 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2812 enum dcerpc_transport_t transport,
2813 const struct ndr_syntax_id *interface,
2814 struct rpc_pipe_client **presult)
2816 switch (transport) {
2817 case NCACN_IP_TCP:
2818 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2819 presult);
2820 case NCACN_NP:
2821 return rpc_pipe_open_np(cli, interface, presult);
2822 default:
2823 return NT_STATUS_NOT_IMPLEMENTED;
2827 /****************************************************************************
2828 Open a named pipe to an SMB server and bind anonymously.
2829 ****************************************************************************/
2831 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2832 enum dcerpc_transport_t transport,
2833 const struct ndr_syntax_id *interface,
2834 struct rpc_pipe_client **presult)
2836 struct rpc_pipe_client *result;
2837 struct pipe_auth_data *auth;
2838 NTSTATUS status;
2840 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 return status;
2845 status = rpccli_anon_bind_data(result, &auth);
2846 if (!NT_STATUS_IS_OK(status)) {
2847 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2848 nt_errstr(status)));
2849 TALLOC_FREE(result);
2850 return status;
2854 * This is a bit of an abstraction violation due to the fact that an
2855 * anonymous bind on an authenticated SMB inherits the user/domain
2856 * from the enclosing SMB creds
2859 TALLOC_FREE(auth->user_name);
2860 TALLOC_FREE(auth->domain);
2862 auth->user_name = talloc_strdup(auth, cli->user_name);
2863 auth->domain = talloc_strdup(auth, cli->domain);
2864 auth->user_session_key = data_blob_talloc(auth,
2865 cli->user_session_key.data,
2866 cli->user_session_key.length);
2868 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2869 TALLOC_FREE(result);
2870 return NT_STATUS_NO_MEMORY;
2873 status = rpc_pipe_bind(result, auth);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 int lvl = 0;
2876 if (ndr_syntax_id_equal(interface,
2877 &ndr_table_dssetup.syntax_id)) {
2878 /* non AD domains just don't have this pipe, avoid
2879 * level 0 statement in that case - gd */
2880 lvl = 3;
2882 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2883 "%s failed with error %s\n",
2884 get_pipe_name_from_syntax(talloc_tos(), interface),
2885 nt_errstr(status) ));
2886 TALLOC_FREE(result);
2887 return status;
2890 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2891 "%s and bound anonymously.\n",
2892 get_pipe_name_from_syntax(talloc_tos(), interface),
2893 cli->desthost));
2895 *presult = result;
2896 return NT_STATUS_OK;
2899 /****************************************************************************
2900 ****************************************************************************/
2902 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2903 const struct ndr_syntax_id *interface,
2904 struct rpc_pipe_client **presult)
2906 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2907 interface, presult);
2910 /****************************************************************************
2911 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2912 ****************************************************************************/
2914 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2915 const struct ndr_syntax_id *interface,
2916 enum dcerpc_transport_t transport,
2917 enum dcerpc_AuthLevel auth_level,
2918 const char *domain,
2919 const char *username,
2920 const char *password,
2921 struct rpc_pipe_client **presult)
2923 struct rpc_pipe_client *result;
2924 struct pipe_auth_data *auth = NULL;
2925 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
2926 NTSTATUS status;
2928 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 return status;
2933 status = rpccli_ntlmssp_bind_data(result,
2934 auth_type, auth_level,
2935 domain, username, password,
2936 &auth);
2937 if (!NT_STATUS_IS_OK(status)) {
2938 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2939 nt_errstr(status)));
2940 goto err;
2943 status = rpc_pipe_bind(result, auth);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2946 nt_errstr(status) ));
2947 goto err;
2950 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2951 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2952 get_pipe_name_from_syntax(talloc_tos(), interface),
2953 cli->desthost, domain, username ));
2955 *presult = result;
2956 return NT_STATUS_OK;
2958 err:
2960 TALLOC_FREE(result);
2961 return status;
2964 /****************************************************************************
2965 Get a the schannel session key out of an already opened netlogon pipe.
2966 ****************************************************************************/
2967 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2968 struct cli_state *cli,
2969 const char *domain,
2970 uint32 *pneg_flags)
2972 enum netr_SchannelType sec_chan_type = 0;
2973 unsigned char machine_pwd[16];
2974 const char *machine_account;
2975 NTSTATUS status;
2977 /* Get the machine account credentials from secrets.tdb. */
2978 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2979 &sec_chan_type))
2981 DEBUG(0, ("get_schannel_session_key: could not fetch "
2982 "trust account password for domain '%s'\n",
2983 domain));
2984 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2987 status = rpccli_netlogon_setup_creds(netlogon_pipe,
2988 cli->desthost, /* server name */
2989 domain, /* domain */
2990 global_myname(), /* client name */
2991 machine_account, /* machine account name */
2992 machine_pwd,
2993 sec_chan_type,
2994 pneg_flags);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 DEBUG(3, ("get_schannel_session_key_common: "
2998 "rpccli_netlogon_setup_creds failed with result %s "
2999 "to server %s, domain %s, machine account %s.\n",
3000 nt_errstr(status), cli->desthost, domain,
3001 machine_account ));
3002 return status;
3005 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3006 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3007 cli->desthost));
3008 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3011 return NT_STATUS_OK;;
3014 /****************************************************************************
3015 Open a netlogon pipe and get the schannel session key.
3016 Now exposed to external callers.
3017 ****************************************************************************/
3020 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3021 const char *domain,
3022 uint32 *pneg_flags,
3023 struct rpc_pipe_client **presult)
3025 struct rpc_pipe_client *netlogon_pipe = NULL;
3026 NTSTATUS status;
3028 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3029 &netlogon_pipe);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 return status;
3034 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3035 pneg_flags);
3036 if (!NT_STATUS_IS_OK(status)) {
3037 TALLOC_FREE(netlogon_pipe);
3038 return status;
3041 *presult = netlogon_pipe;
3042 return NT_STATUS_OK;
3045 /****************************************************************************
3046 External interface.
3047 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3048 using session_key. sign and seal.
3050 The *pdc will be stolen onto this new pipe
3051 ****************************************************************************/
3053 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3054 const struct ndr_syntax_id *interface,
3055 enum dcerpc_transport_t transport,
3056 enum dcerpc_AuthLevel auth_level,
3057 const char *domain,
3058 struct netlogon_creds_CredentialState **pdc,
3059 struct rpc_pipe_client **presult)
3061 struct rpc_pipe_client *result;
3062 struct pipe_auth_data *auth;
3063 NTSTATUS status;
3065 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 return status;
3070 status = rpccli_schannel_bind_data(result, domain, auth_level,
3071 *pdc, &auth);
3072 if (!NT_STATUS_IS_OK(status)) {
3073 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3074 nt_errstr(status)));
3075 TALLOC_FREE(result);
3076 return status;
3079 status = rpc_pipe_bind(result, auth);
3080 if (!NT_STATUS_IS_OK(status)) {
3081 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3082 "cli_rpc_pipe_bind failed with error %s\n",
3083 nt_errstr(status) ));
3084 TALLOC_FREE(result);
3085 return status;
3089 * The credentials on a new netlogon pipe are the ones we are passed
3090 * in - reference them in
3092 result->dc = talloc_move(result, pdc);
3094 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3095 "for domain %s and bound using schannel.\n",
3096 get_pipe_name_from_syntax(talloc_tos(), interface),
3097 cli->desthost, domain ));
3099 *presult = result;
3100 return NT_STATUS_OK;
3103 /****************************************************************************
3104 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3105 Fetch the session key ourselves using a temporary netlogon pipe. This
3106 version uses an ntlmssp auth bound netlogon pipe to get the key.
3107 ****************************************************************************/
3109 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3110 const char *domain,
3111 const char *username,
3112 const char *password,
3113 uint32 *pneg_flags,
3114 struct rpc_pipe_client **presult)
3116 struct rpc_pipe_client *netlogon_pipe = NULL;
3117 NTSTATUS status;
3119 status = cli_rpc_pipe_open_spnego_ntlmssp(
3120 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3121 DCERPC_AUTH_LEVEL_PRIVACY,
3122 domain, username, password, &netlogon_pipe);
3123 if (!NT_STATUS_IS_OK(status)) {
3124 return status;
3127 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3128 pneg_flags);
3129 if (!NT_STATUS_IS_OK(status)) {
3130 TALLOC_FREE(netlogon_pipe);
3131 return status;
3134 *presult = netlogon_pipe;
3135 return NT_STATUS_OK;
3138 /****************************************************************************
3139 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3140 Fetch the session key ourselves using a temporary netlogon pipe. This version
3141 uses an ntlmssp bind to get the session key.
3142 ****************************************************************************/
3144 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3145 const struct ndr_syntax_id *interface,
3146 enum dcerpc_transport_t transport,
3147 enum dcerpc_AuthLevel auth_level,
3148 const char *domain,
3149 const char *username,
3150 const char *password,
3151 struct rpc_pipe_client **presult)
3153 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3154 struct rpc_pipe_client *netlogon_pipe = NULL;
3155 struct rpc_pipe_client *result = NULL;
3156 NTSTATUS status;
3158 status = get_schannel_session_key_auth_ntlmssp(
3159 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3160 if (!NT_STATUS_IS_OK(status)) {
3161 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3162 "key from server %s for domain %s.\n",
3163 cli->desthost, domain ));
3164 return status;
3167 status = cli_rpc_pipe_open_schannel_with_key(
3168 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3169 &result);
3171 /* Now we've bound using the session key we can close the netlog pipe. */
3172 TALLOC_FREE(netlogon_pipe);
3174 if (NT_STATUS_IS_OK(status)) {
3175 *presult = result;
3177 return status;
3180 /****************************************************************************
3181 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3182 Fetch the session key ourselves using a temporary netlogon pipe.
3183 ****************************************************************************/
3185 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3186 const struct ndr_syntax_id *interface,
3187 enum dcerpc_transport_t transport,
3188 enum dcerpc_AuthLevel auth_level,
3189 const char *domain,
3190 struct rpc_pipe_client **presult)
3192 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3193 struct rpc_pipe_client *netlogon_pipe = NULL;
3194 struct rpc_pipe_client *result = NULL;
3195 NTSTATUS status;
3197 status = get_schannel_session_key(cli, domain, &neg_flags,
3198 &netlogon_pipe);
3199 if (!NT_STATUS_IS_OK(status)) {
3200 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3201 "key from server %s for domain %s.\n",
3202 cli->desthost, domain ));
3203 return status;
3206 status = cli_rpc_pipe_open_schannel_with_key(
3207 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3208 &result);
3210 /* Now we've bound using the session key we can close the netlog pipe. */
3211 TALLOC_FREE(netlogon_pipe);
3213 if (NT_STATUS_IS_OK(status)) {
3214 *presult = result;
3217 return status;
3220 /****************************************************************************
3221 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3222 The idea is this can be called with service_princ, username and password all
3223 NULL so long as the caller has a TGT.
3224 ****************************************************************************/
3226 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3227 const struct ndr_syntax_id *interface,
3228 enum dcerpc_transport_t transport,
3229 enum dcerpc_AuthLevel auth_level,
3230 const char *server,
3231 const char *username,
3232 const char *password,
3233 struct rpc_pipe_client **presult)
3235 struct rpc_pipe_client *result;
3236 struct pipe_auth_data *auth;
3237 NTSTATUS status;
3239 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 return status;
3244 auth = talloc(result, struct pipe_auth_data);
3245 if (auth == NULL) {
3246 status = NT_STATUS_NO_MEMORY;
3247 goto err_out;
3249 auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
3250 auth->auth_level = auth_level;
3252 if (!username) {
3253 username = "";
3255 auth->user_name = talloc_strdup(auth, username);
3256 if (!auth->user_name) {
3257 status = NT_STATUS_NO_MEMORY;
3258 goto err_out;
3261 /* Fixme, should we fetch/set the Realm ? */
3262 auth->domain = talloc_strdup(auth, "");
3263 if (!auth->domain) {
3264 status = NT_STATUS_NO_MEMORY;
3265 goto err_out;
3268 status = gse_init_client(auth, auth->auth_type, auth->auth_level,
3269 NULL, server, "cifs", username, password,
3270 GSS_C_DCE_STYLE, &auth->a_u.gssapi_state);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 DEBUG(0, ("gse_init_client returned %s\n",
3274 nt_errstr(status)));
3275 goto err_out;
3278 status = rpc_pipe_bind(result, auth);
3279 if (!NT_STATUS_IS_OK(status)) {
3280 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3281 nt_errstr(status)));
3282 goto err_out;
3285 *presult = result;
3286 return NT_STATUS_OK;
3288 err_out:
3289 TALLOC_FREE(result);
3290 return status;
3293 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
3294 const struct ndr_syntax_id *interface,
3295 enum dcerpc_transport_t transport,
3296 enum dcerpc_AuthLevel auth_level,
3297 const char *server,
3298 const char *username,
3299 const char *password,
3300 struct rpc_pipe_client **presult)
3302 struct rpc_pipe_client *result;
3303 struct pipe_auth_data *auth;
3304 NTSTATUS status;
3306 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3307 if (!NT_STATUS_IS_OK(status)) {
3308 return status;
3311 auth = talloc(result, struct pipe_auth_data);
3312 if (auth == NULL) {
3313 status = NT_STATUS_NO_MEMORY;
3314 goto err_out;
3316 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3317 auth->auth_level = auth_level;
3318 /* compat */
3319 auth->spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
3321 if (!username) {
3322 username = "";
3324 auth->user_name = talloc_strdup(auth, username);
3325 if (!auth->user_name) {
3326 status = NT_STATUS_NO_MEMORY;
3327 goto err_out;
3330 /* Fixme, should we fetch/set the Realm ? */
3331 auth->domain = talloc_strdup(auth, "");
3332 if (!auth->domain) {
3333 status = NT_STATUS_NO_MEMORY;
3334 goto err_out;
3337 status = spnego_gssapi_init_client(auth, auth->auth_level,
3338 NULL, server, "cifs",
3339 username, password,
3340 GSS_C_DCE_STYLE,
3341 &auth->a_u.spnego_state);
3342 if (!NT_STATUS_IS_OK(status)) {
3343 DEBUG(0, ("spnego_init_client returned %s\n",
3344 nt_errstr(status)));
3345 goto err_out;
3348 status = rpc_pipe_bind(result, auth);
3349 if (!NT_STATUS_IS_OK(status)) {
3350 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3351 nt_errstr(status)));
3352 goto err_out;
3355 *presult = result;
3356 return NT_STATUS_OK;
3358 err_out:
3359 TALLOC_FREE(result);
3360 return status;
3363 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3364 const struct ndr_syntax_id *interface,
3365 enum dcerpc_transport_t transport,
3366 enum dcerpc_AuthLevel auth_level,
3367 const char *domain,
3368 const char *username,
3369 const char *password,
3370 struct rpc_pipe_client **presult)
3372 struct rpc_pipe_client *result;
3373 struct pipe_auth_data *auth;
3374 NTSTATUS status;
3376 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3377 if (!NT_STATUS_IS_OK(status)) {
3378 return status;
3381 auth = talloc(result, struct pipe_auth_data);
3382 if (auth == NULL) {
3383 status = NT_STATUS_NO_MEMORY;
3384 goto err_out;
3386 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3387 auth->auth_level = auth_level;
3389 if (!username) {
3390 username = "";
3392 auth->user_name = talloc_strdup(auth, username);
3393 if (!auth->user_name) {
3394 status = NT_STATUS_NO_MEMORY;
3395 goto err_out;
3398 if (!domain) {
3399 domain = "";
3401 auth->domain = talloc_strdup(auth, domain);
3402 if (!auth->domain) {
3403 status = NT_STATUS_NO_MEMORY;
3404 goto err_out;
3407 status = spnego_ntlmssp_init_client(auth, auth->auth_level,
3408 domain, username, password,
3409 &auth->a_u.spnego_state);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 DEBUG(0, ("spnego_init_client returned %s\n",
3412 nt_errstr(status)));
3413 goto err_out;
3416 status = rpc_pipe_bind(result, auth);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3419 nt_errstr(status)));
3420 goto err_out;
3423 *presult = result;
3424 return NT_STATUS_OK;
3426 err_out:
3427 TALLOC_FREE(result);
3428 return status;
3431 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3432 struct rpc_pipe_client *cli,
3433 DATA_BLOB *session_key)
3435 struct pipe_auth_data *a = cli->auth;
3436 DATA_BLOB sk = data_blob_null;
3437 bool make_dup;
3439 if (!session_key || !cli) {
3440 return NT_STATUS_INVALID_PARAMETER;
3443 if (!cli->auth) {
3444 return NT_STATUS_INVALID_PARAMETER;
3447 switch (cli->auth->auth_type) {
3448 case DCERPC_AUTH_TYPE_SCHANNEL:
3449 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3450 16);
3451 make_dup = true;
3452 break;
3453 case DCERPC_AUTH_TYPE_SPNEGO:
3454 sk = spnego_get_session_key(a->a_u.spnego_state);
3455 if (sk.length == 0) {
3456 return NT_STATUS_NO_USER_SESSION_KEY;
3458 make_dup = true;
3459 break;
3460 case DCERPC_AUTH_TYPE_NTLMSSP:
3461 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3462 make_dup = true;
3463 break;
3464 case DCERPC_AUTH_TYPE_KRB5:
3465 sk = gse_get_session_key(a->a_u.gssapi_state);
3466 make_dup = true;
3467 break;
3468 case DCERPC_AUTH_TYPE_NONE:
3469 sk = data_blob_const(a->user_session_key.data,
3470 a->user_session_key.length);
3471 make_dup = true;
3472 break;
3473 default:
3474 break;
3477 if (!sk.data) {
3478 return NT_STATUS_NO_USER_SESSION_KEY;
3481 if (make_dup) {
3482 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3483 } else {
3484 *session_key = sk;
3487 return NT_STATUS_OK;