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/>.
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"
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"
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);
53 /********************************************************************
55 ********************************************************************/
57 static uint32 get_rpc_call_id(void)
59 static uint32 call_id = 0;
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;
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);
91 state->transport = transport;
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,
100 if (subreq == NULL) {
103 tevent_req_set_callback(subreq, rpc_read_done, req);
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);
120 status = state->transport->read_recv(subreq, &received);
122 if (!NT_STATUS_IS_OK(status)) {
123 tevent_req_nterror(req, status);
127 state->num_read += received;
128 if (state->num_read == state->size) {
129 tevent_req_done(req);
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)) {
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;
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);
171 state->transport = transport;
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) {
182 tevent_req_set_callback(subreq, rpc_write_done, req);
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);
198 status = state->transport->write_recv(subreq, &written);
200 if (!NT_STATUS_IS_OK(status)) {
201 tevent_req_nterror(req, status);
205 state->num_written += written;
207 if (state->num_written == state->size) {
208 tevent_req_done(req);
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)) {
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
231 ****************************************************************************/
233 struct get_complete_frag_state {
234 struct event_context *ev;
235 struct rpc_pipe_client *cli;
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,
248 struct tevent_req *req, *subreq;
249 struct get_complete_frag_state *state;
253 req = tevent_req_create(mem_ctx, &state,
254 struct get_complete_frag_state);
260 state->frag_len = RPC_HEADER_LEN;
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;
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;
277 tevent_req_set_callback(subreq, get_complete_frag_got_header,
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;
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;
300 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
305 status = NT_STATUS_OK;
307 if (NT_STATUS_IS_OK(status)) {
308 tevent_req_done(req);
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);
323 status = rpc_read_recv(subreq);
325 if (!NT_STATUS_IS_OK(status)) {
326 tevent_req_nterror(req, status);
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);
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)) {
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);
357 status = rpc_read_recv(subreq);
359 if (!NT_STATUS_IS_OK(status)) {
360 tevent_req_nterror(req, status);
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,
379 uint8_t expected_pkt_type,
381 DATA_BLOB *reply_pdu)
383 NTSTATUS ret = NT_STATUS_OK;
386 ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false);
387 if (!NT_STATUS_IS_OK(ret)) {
391 if (pdu->length != pkt->frag_length) {
392 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
393 (unsigned int)pdu->length,
394 (unsigned int)pkt->frag_length));
395 return NT_STATUS_INVALID_PARAMETER;
399 * Point the return values at the real data including the RPC
400 * header. Just in case the caller wants it.
404 /* Ensure we have the correct type. */
405 switch (pkt->ptype) {
406 case DCERPC_PKT_ALTER_RESP:
407 case DCERPC_PKT_BIND_ACK:
409 /* Alter context and bind ack share the same packet definitions. */
413 case DCERPC_PKT_RESPONSE:
415 /* Here's where we deal with incoming sign/seal. */
416 ret = dcerpc_check_auth(cli->auth, pkt,
417 &pkt->u.response.stub_and_verifier,
418 DCERPC_RESPONSE_LENGTH,
420 if (!NT_STATUS_IS_OK(ret)) {
424 if (pdu->length < DCERPC_RESPONSE_LENGTH + pad_len) {
425 return NT_STATUS_BUFFER_TOO_SMALL;
428 /* Point the return values at the NDR data. */
429 rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
431 if (pkt->auth_length) {
432 /* We've already done integer wrap tests in
433 * dcerpc_check_auth(). */
434 rdata->length = pdu->length
435 - DCERPC_RESPONSE_LENGTH
437 - DCERPC_AUTH_TRAILER_LENGTH
440 rdata->length = pdu->length - DCERPC_RESPONSE_LENGTH;
443 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
444 (long unsigned int)pdu->length,
445 (long unsigned int)rdata->length,
446 (unsigned int)pad_len));
449 * If this is the first reply, and the allocation hint is
450 * reasonable, try and set up the reply_pdu DATA_BLOB to the
454 if ((reply_pdu->length == 0) &&
455 pkt->u.response.alloc_hint &&
456 (pkt->u.response.alloc_hint < 15*1024*1024)) {
457 if (!data_blob_realloc(mem_ctx, reply_pdu,
458 pkt->u.response.alloc_hint)) {
459 DEBUG(0, ("reply alloc hint %d too "
460 "large to allocate\n",
461 (int)pkt->u.response.alloc_hint));
462 return NT_STATUS_NO_MEMORY;
468 case DCERPC_PKT_BIND_NAK:
469 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
470 "received from %s!\n",
471 rpccli_pipe_txt(talloc_tos(), cli)));
472 /* Use this for now... */
473 return NT_STATUS_NETWORK_ACCESS_DENIED;
475 case DCERPC_PKT_FAULT:
477 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
478 "code %s received from %s!\n",
479 dcerpc_errstr(talloc_tos(),
480 pkt->u.fault.status),
481 rpccli_pipe_txt(talloc_tos(), cli)));
483 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
484 return NT_STATUS_UNSUCCESSFUL;
486 return NT_STATUS(pkt->u.fault.status);
490 DEBUG(0, ("Unknown packet type %u received from %s!\n",
491 (unsigned int)pkt->ptype,
492 rpccli_pipe_txt(talloc_tos(), cli)));
493 return NT_STATUS_INVALID_INFO_CLASS;
496 if (pkt->ptype != expected_pkt_type) {
497 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
498 "got an unexpected RPC packet type - %u, not %u\n",
499 rpccli_pipe_txt(talloc_tos(), cli),
502 return NT_STATUS_INVALID_INFO_CLASS;
505 /* Do this just before return - we don't want to modify any rpc header
506 data before now as we may have needed to do cryptographic actions on
509 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
510 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
511 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
512 "setting fragment first/last ON.\n"));
513 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
514 DCERPC_PFC_FLAG_LAST;
520 /****************************************************************************
521 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
522 ****************************************************************************/
524 struct cli_api_pipe_state {
525 struct event_context *ev;
526 struct rpc_cli_transport *transport;
531 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
532 static void cli_api_pipe_write_done(struct tevent_req *subreq);
533 static void cli_api_pipe_read_done(struct tevent_req *subreq);
535 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
536 struct event_context *ev,
537 struct rpc_cli_transport *transport,
538 uint8_t *data, size_t data_len,
539 uint32_t max_rdata_len)
541 struct tevent_req *req, *subreq;
542 struct cli_api_pipe_state *state;
545 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
550 state->transport = transport;
552 if (max_rdata_len < RPC_HEADER_LEN) {
554 * For a RPC reply we always need at least RPC_HEADER_LEN
555 * bytes. We check this here because we will receive
556 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
558 status = NT_STATUS_INVALID_PARAMETER;
562 if (transport->trans_send != NULL) {
563 subreq = transport->trans_send(state, ev, data, data_len,
564 max_rdata_len, transport->priv);
565 if (subreq == NULL) {
568 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
573 * If the transport does not provide a "trans" routine, i.e. for
574 * example the ncacn_ip_tcp transport, do the write/read step here.
577 subreq = rpc_write_send(state, ev, transport, data, data_len);
578 if (subreq == NULL) {
581 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
585 tevent_req_nterror(req, status);
586 return tevent_req_post(req, ev);
592 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
594 struct tevent_req *req = tevent_req_callback_data(
595 subreq, struct tevent_req);
596 struct cli_api_pipe_state *state = tevent_req_data(
597 req, struct cli_api_pipe_state);
600 status = state->transport->trans_recv(subreq, state, &state->rdata,
603 if (!NT_STATUS_IS_OK(status)) {
604 tevent_req_nterror(req, status);
607 tevent_req_done(req);
610 static void cli_api_pipe_write_done(struct tevent_req *subreq)
612 struct tevent_req *req = tevent_req_callback_data(
613 subreq, struct tevent_req);
614 struct cli_api_pipe_state *state = tevent_req_data(
615 req, struct cli_api_pipe_state);
618 status = rpc_write_recv(subreq);
620 if (!NT_STATUS_IS_OK(status)) {
621 tevent_req_nterror(req, status);
625 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
626 if (tevent_req_nomem(state->rdata, req)) {
631 * We don't need to use rpc_read_send here, the upper layer will cope
632 * with a short read, transport->trans_send could also return less
633 * than state->max_rdata_len.
635 subreq = state->transport->read_send(state, state->ev, state->rdata,
637 state->transport->priv);
638 if (tevent_req_nomem(subreq, req)) {
641 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
644 static void cli_api_pipe_read_done(struct tevent_req *subreq)
646 struct tevent_req *req = tevent_req_callback_data(
647 subreq, struct tevent_req);
648 struct cli_api_pipe_state *state = tevent_req_data(
649 req, struct cli_api_pipe_state);
653 status = state->transport->read_recv(subreq, &received);
655 if (!NT_STATUS_IS_OK(status)) {
656 tevent_req_nterror(req, status);
659 state->rdata_len = received;
660 tevent_req_done(req);
663 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
664 uint8_t **prdata, uint32_t *prdata_len)
666 struct cli_api_pipe_state *state = tevent_req_data(
667 req, struct cli_api_pipe_state);
670 if (tevent_req_is_nterror(req, &status)) {
674 *prdata = talloc_move(mem_ctx, &state->rdata);
675 *prdata_len = state->rdata_len;
679 /****************************************************************************
680 Send data on an rpc pipe via trans. The data must be the last
681 pdu fragment of an NDR data stream.
683 Receive response data from an rpc pipe, which may be large...
685 Read the first fragment: unfortunately have to use SMBtrans for the first
686 bit, then SMBreadX for subsequent bits.
688 If first fragment received also wasn't the last fragment, continue
689 getting fragments until we _do_ receive the last fragment.
691 Request/Response PDU's look like the following...
693 |<------------------PDU len----------------------------------------------->|
694 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
696 +------------+-----------------+-------------+---------------+-------------+
697 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
698 +------------+-----------------+-------------+---------------+-------------+
700 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
701 signing & sealing being negotiated.
703 ****************************************************************************/
705 struct rpc_api_pipe_state {
706 struct event_context *ev;
707 struct rpc_pipe_client *cli;
708 uint8_t expected_pkt_type;
710 DATA_BLOB incoming_frag;
711 struct ncacn_packet *pkt;
715 size_t reply_pdu_offset;
719 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
720 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
722 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
723 struct event_context *ev,
724 struct rpc_pipe_client *cli,
725 DATA_BLOB *data, /* Outgoing PDU */
726 uint8_t expected_pkt_type)
728 struct tevent_req *req, *subreq;
729 struct rpc_api_pipe_state *state;
730 uint16_t max_recv_frag;
733 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
739 state->expected_pkt_type = expected_pkt_type;
740 state->incoming_frag = data_blob_null;
741 state->reply_pdu = data_blob_null;
742 state->reply_pdu_offset = 0;
743 state->endianess = DCERPC_DREP_LE;
746 * Ensure we're not sending too much.
748 if (data->length > cli->max_xmit_frag) {
749 status = NT_STATUS_INVALID_PARAMETER;
753 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
755 /* get the header first, then fetch the rest once we have
756 * the frag_length available */
757 max_recv_frag = RPC_HEADER_LEN;
759 subreq = cli_api_pipe_send(state, ev, cli->transport,
760 data->data, data->length, max_recv_frag);
761 if (subreq == NULL) {
764 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
768 tevent_req_nterror(req, status);
769 return tevent_req_post(req, ev);
775 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
777 struct tevent_req *req = tevent_req_callback_data(
778 subreq, struct tevent_req);
779 struct rpc_api_pipe_state *state = tevent_req_data(
780 req, struct rpc_api_pipe_state);
782 uint8_t *rdata = NULL;
783 uint32_t rdata_len = 0;
785 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
787 if (!NT_STATUS_IS_OK(status)) {
788 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
789 tevent_req_nterror(req, status);
794 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
795 rpccli_pipe_txt(talloc_tos(), state->cli)));
796 tevent_req_done(req);
801 * Move data on state->incoming_frag.
803 state->incoming_frag.data = talloc_move(state, &rdata);
804 state->incoming_frag.length = rdata_len;
805 if (!state->incoming_frag.data) {
806 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
810 /* Ensure we have enough data for a pdu. */
811 subreq = get_complete_frag_send(state, state->ev, state->cli,
812 &state->incoming_frag);
813 if (tevent_req_nomem(subreq, req)) {
816 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
819 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
821 struct tevent_req *req = tevent_req_callback_data(
822 subreq, struct tevent_req);
823 struct rpc_api_pipe_state *state = tevent_req_data(
824 req, struct rpc_api_pipe_state);
826 DATA_BLOB rdata = data_blob_null;
828 status = get_complete_frag_recv(subreq);
830 if (!NT_STATUS_IS_OK(status)) {
831 DEBUG(5, ("get_complete_frag failed: %s\n",
833 tevent_req_nterror(req, status);
837 state->pkt = talloc(state, struct ncacn_packet);
839 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
843 status = cli_pipe_validate_current_pdu(state,
844 state->cli, state->pkt,
845 &state->incoming_frag,
846 state->expected_pkt_type,
850 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
851 (unsigned)state->incoming_frag.length,
852 (unsigned)state->reply_pdu_offset,
855 if (!NT_STATUS_IS_OK(status)) {
856 tevent_req_nterror(req, status);
860 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
861 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
863 * Set the data type correctly for big-endian data on the
866 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
868 rpccli_pipe_txt(talloc_tos(), state->cli)));
869 state->endianess = 0x00; /* BIG ENDIAN */
872 * Check endianness on subsequent packets.
874 if (state->endianess != state->pkt->drep[0]) {
875 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
877 state->endianess?"little":"big",
878 state->pkt->drep[0]?"little":"big"));
879 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
883 /* Now copy the data portion out of the pdu into rbuf. */
884 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
885 if (!data_blob_realloc(NULL, &state->reply_pdu,
886 state->reply_pdu_offset + rdata.length)) {
887 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
892 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
893 rdata.data, rdata.length);
894 state->reply_pdu_offset += rdata.length;
896 /* reset state->incoming_frag, there is no need to free it,
897 * it will be reallocated to the right size the next time
899 state->incoming_frag.length = 0;
901 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
902 /* make sure the pdu length is right now that we
903 * have all the data available (alloc hint may
904 * have allocated more than was actually used) */
905 state->reply_pdu.length = state->reply_pdu_offset;
906 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
907 rpccli_pipe_txt(talloc_tos(), state->cli),
908 (unsigned)state->reply_pdu.length));
909 tevent_req_done(req);
913 subreq = get_complete_frag_send(state, state->ev, state->cli,
914 &state->incoming_frag);
915 if (tevent_req_nomem(subreq, req)) {
918 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
921 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
922 struct ncacn_packet **pkt,
923 DATA_BLOB *reply_pdu)
925 struct rpc_api_pipe_state *state = tevent_req_data(
926 req, struct rpc_api_pipe_state);
929 if (tevent_req_is_nterror(req, &status)) {
933 /* return data to caller and assign it ownership of memory */
935 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
936 reply_pdu->length = state->reply_pdu.length;
937 state->reply_pdu.length = 0;
939 data_blob_free(&state->reply_pdu);
943 *pkt = talloc_steal(mem_ctx, state->pkt);
949 /*******************************************************************
950 Creates spnego auth bind.
951 ********************************************************************/
953 static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx,
954 struct pipe_auth_data *auth,
955 DATA_BLOB *auth_token)
957 DATA_BLOB in_token = data_blob_null;
960 /* Negotiate the initial auth token */
961 status = spnego_get_client_auth_token(mem_ctx,
962 auth->a_u.spnego_state,
963 &in_token, auth_token);
964 if (!NT_STATUS_IS_OK(status)) {
968 DEBUG(5, ("Created GSS Authentication Token:\n"));
969 dump_data(5, auth_token->data, auth_token->length);
974 /*******************************************************************
975 Creates krb5 auth bind.
976 ********************************************************************/
978 static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx,
979 struct pipe_auth_data *auth,
980 DATA_BLOB *auth_token)
982 DATA_BLOB in_token = data_blob_null;
985 /* Negotiate the initial auth token */
986 status = gse_get_client_auth_token(mem_ctx,
987 auth->a_u.gssapi_state,
990 if (!NT_STATUS_IS_OK(status)) {
994 DEBUG(5, ("Created GSS Authentication Token:\n"));
995 dump_data(5, auth_token->data, auth_token->length);
1000 /*******************************************************************
1001 Creates NTLMSSP auth bind.
1002 ********************************************************************/
1004 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1005 DATA_BLOB *auth_token)
1008 DATA_BLOB null_blob = data_blob_null;
1010 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1011 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1012 null_blob, auth_token);
1014 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1015 data_blob_free(auth_token);
1019 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1020 dump_data(5, auth_token->data, auth_token->length);
1022 return NT_STATUS_OK;
1025 /*******************************************************************
1026 Creates schannel auth bind.
1027 ********************************************************************/
1029 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1030 DATA_BLOB *auth_token)
1033 struct NL_AUTH_MESSAGE r;
1035 /* Use lp_workgroup() if domain not specified */
1037 if (!cli->auth->domain || !cli->auth->domain[0]) {
1038 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1039 if (cli->auth->domain == NULL) {
1040 return NT_STATUS_NO_MEMORY;
1045 * Now marshall the data into the auth parse_struct.
1048 r.MessageType = NL_NEGOTIATE_REQUEST;
1049 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1050 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1051 r.oem_netbios_domain.a = cli->auth->domain;
1052 r.oem_netbios_computer.a = global_myname();
1054 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1055 if (!NT_STATUS_IS_OK(status)) {
1059 return NT_STATUS_OK;
1062 /*******************************************************************
1063 Creates the internals of a DCE/RPC bind request or alter context PDU.
1064 ********************************************************************/
1066 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1067 enum dcerpc_pkt_type ptype,
1069 const struct ndr_syntax_id *abstract,
1070 const struct ndr_syntax_id *transfer,
1071 const DATA_BLOB *auth_info,
1074 uint16 auth_len = auth_info->length;
1076 union dcerpc_payload u;
1077 struct dcerpc_ctx_list ctx_list;
1080 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1083 ctx_list.context_id = 0;
1084 ctx_list.num_transfer_syntaxes = 1;
1085 ctx_list.abstract_syntax = *abstract;
1086 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1088 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1089 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1090 u.bind.assoc_group_id = 0x0;
1091 u.bind.num_contexts = 1;
1092 u.bind.ctx_list = &ctx_list;
1093 u.bind.auth_info = *auth_info;
1095 status = dcerpc_push_ncacn_packet(mem_ctx,
1097 DCERPC_PFC_FLAG_FIRST |
1098 DCERPC_PFC_FLAG_LAST,
1103 if (!NT_STATUS_IS_OK(status)) {
1104 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1108 return NT_STATUS_OK;
1111 /*******************************************************************
1112 Creates a DCE/RPC bind request.
1113 ********************************************************************/
1115 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1116 struct rpc_pipe_client *cli,
1117 struct pipe_auth_data *auth,
1119 const struct ndr_syntax_id *abstract,
1120 const struct ndr_syntax_id *transfer,
1123 DATA_BLOB auth_token = data_blob_null;
1124 DATA_BLOB auth_info = data_blob_null;
1125 NTSTATUS ret = NT_STATUS_OK;
1127 switch (auth->auth_type) {
1128 case DCERPC_AUTH_TYPE_SCHANNEL:
1129 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1130 if (!NT_STATUS_IS_OK(ret)) {
1135 case DCERPC_AUTH_TYPE_NTLMSSP:
1136 ret = create_ntlmssp_auth_rpc_bind_req(cli, &auth_token);
1137 if (!NT_STATUS_IS_OK(ret)) {
1142 case DCERPC_AUTH_TYPE_SPNEGO:
1143 ret = create_spnego_auth_bind_req(cli, auth, &auth_token);
1144 if (!NT_STATUS_IS_OK(ret)) {
1149 case DCERPC_AUTH_TYPE_KRB5:
1150 ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_token);
1151 if (!NT_STATUS_IS_OK(ret)) {
1156 case DCERPC_AUTH_TYPE_NONE:
1160 /* "Can't" happen. */
1161 return NT_STATUS_INVALID_INFO_CLASS;
1164 if (auth_token.length != 0) {
1165 ret = dcerpc_push_dcerpc_auth(cli,
1168 0, /* auth_pad_length */
1169 1, /* auth_context_id */
1172 if (!NT_STATUS_IS_OK(ret)) {
1175 data_blob_free(&auth_token);
1178 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1188 /*******************************************************************
1190 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1191 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1192 and deals with signing/sealing details.
1193 ********************************************************************/
1195 struct rpc_api_pipe_req_state {
1196 struct event_context *ev;
1197 struct rpc_pipe_client *cli;
1200 DATA_BLOB *req_data;
1201 uint32_t req_data_sent;
1203 DATA_BLOB reply_pdu;
1206 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1207 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1208 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1209 bool *is_last_frag);
1211 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1212 struct event_context *ev,
1213 struct rpc_pipe_client *cli,
1215 DATA_BLOB *req_data)
1217 struct tevent_req *req, *subreq;
1218 struct rpc_api_pipe_req_state *state;
1222 req = tevent_req_create(mem_ctx, &state,
1223 struct rpc_api_pipe_req_state);
1229 state->op_num = op_num;
1230 state->req_data = req_data;
1231 state->req_data_sent = 0;
1232 state->call_id = get_rpc_call_id();
1233 state->reply_pdu = data_blob_null;
1234 state->rpc_out = data_blob_null;
1236 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1237 + RPC_MAX_SIGN_SIZE) {
1238 /* Server is screwed up ! */
1239 status = NT_STATUS_INVALID_PARAMETER;
1243 status = prepare_next_frag(state, &is_last_frag);
1244 if (!NT_STATUS_IS_OK(status)) {
1249 subreq = rpc_api_pipe_send(state, ev, state->cli,
1251 DCERPC_PKT_RESPONSE);
1252 if (subreq == NULL) {
1255 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1257 subreq = rpc_write_send(state, ev, cli->transport,
1258 state->rpc_out.data,
1259 state->rpc_out.length);
1260 if (subreq == NULL) {
1263 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1269 tevent_req_nterror(req, status);
1270 return tevent_req_post(req, ev);
1276 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1279 size_t data_sent_thistime;
1286 union dcerpc_payload u;
1288 data_left = state->req_data->length - state->req_data_sent;
1290 status = dcerpc_guess_sizes(state->cli->auth,
1291 DCERPC_REQUEST_LENGTH, data_left,
1292 state->cli->max_xmit_frag,
1293 CLIENT_NDR_PADDING_SIZE,
1294 &data_sent_thistime,
1295 &frag_len, &auth_len, &pad_len);
1296 if (!NT_STATUS_IS_OK(status)) {
1300 if (state->req_data_sent == 0) {
1301 flags = DCERPC_PFC_FLAG_FIRST;
1304 if (data_sent_thistime == data_left) {
1305 flags |= DCERPC_PFC_FLAG_LAST;
1308 data_blob_free(&state->rpc_out);
1310 ZERO_STRUCT(u.request);
1312 u.request.alloc_hint = state->req_data->length;
1313 u.request.context_id = 0;
1314 u.request.opnum = state->op_num;
1316 status = dcerpc_push_ncacn_packet(state,
1323 if (!NT_STATUS_IS_OK(status)) {
1327 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1328 * compute it right for requests because the auth trailer is missing
1330 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1332 /* Copy in the data. */
1333 if (!data_blob_append(NULL, &state->rpc_out,
1334 state->req_data->data + state->req_data_sent,
1335 data_sent_thistime)) {
1336 return NT_STATUS_NO_MEMORY;
1339 switch (state->cli->auth->auth_level) {
1340 case DCERPC_AUTH_LEVEL_NONE:
1341 case DCERPC_AUTH_LEVEL_CONNECT:
1342 case DCERPC_AUTH_LEVEL_PACKET:
1344 case DCERPC_AUTH_LEVEL_INTEGRITY:
1345 case DCERPC_AUTH_LEVEL_PRIVACY:
1346 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1348 if (!NT_STATUS_IS_OK(status)) {
1353 return NT_STATUS_INVALID_PARAMETER;
1356 state->req_data_sent += data_sent_thistime;
1357 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1362 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1364 struct tevent_req *req = tevent_req_callback_data(
1365 subreq, struct tevent_req);
1366 struct rpc_api_pipe_req_state *state = tevent_req_data(
1367 req, struct rpc_api_pipe_req_state);
1371 status = rpc_write_recv(subreq);
1372 TALLOC_FREE(subreq);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 tevent_req_nterror(req, status);
1378 status = prepare_next_frag(state, &is_last_frag);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 tevent_req_nterror(req, status);
1385 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1387 DCERPC_PKT_RESPONSE);
1388 if (tevent_req_nomem(subreq, req)) {
1391 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1393 subreq = rpc_write_send(state, state->ev,
1394 state->cli->transport,
1395 state->rpc_out.data,
1396 state->rpc_out.length);
1397 if (tevent_req_nomem(subreq, req)) {
1400 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1405 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1407 struct tevent_req *req = tevent_req_callback_data(
1408 subreq, struct tevent_req);
1409 struct rpc_api_pipe_req_state *state = tevent_req_data(
1410 req, struct rpc_api_pipe_req_state);
1413 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1414 TALLOC_FREE(subreq);
1415 if (!NT_STATUS_IS_OK(status)) {
1416 tevent_req_nterror(req, status);
1419 tevent_req_done(req);
1422 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1423 DATA_BLOB *reply_pdu)
1425 struct rpc_api_pipe_req_state *state = tevent_req_data(
1426 req, struct rpc_api_pipe_req_state);
1429 if (tevent_req_is_nterror(req, &status)) {
1431 * We always have to initialize to reply pdu, even if there is
1432 * none. The rpccli_* caller routines expect this.
1434 *reply_pdu = data_blob_null;
1438 /* return data to caller and assign it ownership of memory */
1439 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1440 reply_pdu->length = state->reply_pdu.length;
1441 state->reply_pdu.length = 0;
1443 return NT_STATUS_OK;
1447 /****************************************************************************
1448 Set the handle state.
1449 ****************************************************************************/
1451 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1452 const char *pipe_name, uint16 device_state)
1454 bool state_set = False;
1456 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1457 char *rparam = NULL;
1459 uint32 rparam_len, rdata_len;
1461 if (pipe_name == NULL)
1464 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1465 cli->fnum, pipe_name, device_state));
1467 /* create parameters: device state */
1468 SSVAL(param, 0, device_state);
1470 /* create setup parameters. */
1472 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1474 /* send the data on \PIPE\ */
1475 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1476 setup, 2, 0, /* setup, length, max */
1477 param, 2, 0, /* param, length, max */
1478 NULL, 0, 1024, /* data, length, max */
1479 &rparam, &rparam_len, /* return param, length */
1480 &rdata, &rdata_len)) /* return data, length */
1482 DEBUG(5, ("Set Handle state: return OK\n"));
1493 /****************************************************************************
1494 Check the rpc bind acknowledge response.
1495 ****************************************************************************/
1497 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1498 const struct ndr_syntax_id *transfer)
1500 struct dcerpc_ack_ctx ctx;
1502 if (r->secondary_address_size == 0) {
1503 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1506 if (r->num_results < 1 || !r->ctx_list) {
1510 ctx = r->ctx_list[0];
1512 /* check the transfer syntax */
1513 if ((ctx.syntax.if_version != transfer->if_version) ||
1514 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1515 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1519 if (r->num_results != 0x1 || ctx.result != 0) {
1520 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1521 r->num_results, ctx.reason));
1524 DEBUG(5,("check_bind_response: accepted!\n"));
1528 /*******************************************************************
1529 Creates a DCE/RPC bind authentication response.
1530 This is the packet that is sent back to the server once we
1531 have received a BIND-ACK, to finish the third leg of
1532 the authentication handshake.
1533 ********************************************************************/
1535 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1536 struct rpc_pipe_client *cli,
1538 enum dcerpc_AuthType auth_type,
1539 enum dcerpc_AuthLevel auth_level,
1540 DATA_BLOB *pauth_blob,
1544 union dcerpc_payload u;
1548 status = dcerpc_push_dcerpc_auth(mem_ctx,
1551 0, /* auth_pad_length */
1552 1, /* auth_context_id */
1554 &u.auth3.auth_info);
1555 if (!NT_STATUS_IS_OK(status)) {
1559 status = dcerpc_push_ncacn_packet(mem_ctx,
1561 DCERPC_PFC_FLAG_FIRST |
1562 DCERPC_PFC_FLAG_LAST,
1567 data_blob_free(&u.auth3.auth_info);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1573 return NT_STATUS_OK;
1576 /*******************************************************************
1577 Creates a DCE/RPC bind alter context authentication request which
1578 may contain a spnego auth blobl
1579 ********************************************************************/
1581 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1582 enum dcerpc_AuthType auth_type,
1583 enum dcerpc_AuthLevel auth_level,
1585 const struct ndr_syntax_id *abstract,
1586 const struct ndr_syntax_id *transfer,
1587 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1590 DATA_BLOB auth_info;
1593 status = dcerpc_push_dcerpc_auth(mem_ctx,
1596 0, /* auth_pad_length */
1597 1, /* auth_context_id */
1600 if (!NT_STATUS_IS_OK(status)) {
1604 status = create_bind_or_alt_ctx_internal(mem_ctx,
1611 data_blob_free(&auth_info);
1615 /****************************************************************************
1617 ****************************************************************************/
1619 struct rpc_pipe_bind_state {
1620 struct event_context *ev;
1621 struct rpc_pipe_client *cli;
1623 uint32_t rpc_call_id;
1626 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1627 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1628 struct rpc_pipe_bind_state *state,
1629 DATA_BLOB *credentials);
1630 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
1631 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1632 struct rpc_pipe_bind_state *state,
1633 DATA_BLOB *credentials);
1634 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1635 struct rpc_pipe_bind_state *state,
1636 DATA_BLOB *credentials);
1638 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1639 struct event_context *ev,
1640 struct rpc_pipe_client *cli,
1641 struct pipe_auth_data *auth)
1643 struct tevent_req *req, *subreq;
1644 struct rpc_pipe_bind_state *state;
1647 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1652 DEBUG(5,("Bind RPC Pipe: %s auth_type %u(%u), auth_level %u\n",
1653 rpccli_pipe_txt(talloc_tos(), cli),
1654 (unsigned int)auth->auth_type,
1655 (unsigned int)auth->spnego_type,
1656 (unsigned int)auth->auth_level ));
1660 state->rpc_call_id = get_rpc_call_id();
1661 state->rpc_out = data_blob_null;
1663 cli->auth = talloc_move(cli, &auth);
1665 /* Marshall the outgoing data. */
1666 status = create_rpc_bind_req(state, cli,
1669 &cli->abstract_syntax,
1670 &cli->transfer_syntax,
1673 if (!NT_STATUS_IS_OK(status)) {
1677 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1678 DCERPC_PKT_BIND_ACK);
1679 if (subreq == NULL) {
1682 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1686 tevent_req_nterror(req, status);
1687 return tevent_req_post(req, ev);
1693 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1695 struct tevent_req *req = tevent_req_callback_data(
1696 subreq, struct tevent_req);
1697 struct rpc_pipe_bind_state *state = tevent_req_data(
1698 req, struct rpc_pipe_bind_state);
1699 struct pipe_auth_data *pauth = state->cli->auth;
1700 DATA_BLOB reply_pdu;
1701 struct ncacn_packet *pkt;
1702 struct dcerpc_auth auth;
1703 DATA_BLOB auth_token = data_blob_null;
1706 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
1707 TALLOC_FREE(subreq);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1710 rpccli_pipe_txt(talloc_tos(), state->cli),
1711 nt_errstr(status)));
1712 tevent_req_nterror(req, status);
1716 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1717 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1718 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1722 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1723 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1725 switch(state->cli->auth->auth_type) {
1727 case DCERPC_AUTH_TYPE_NONE:
1728 case DCERPC_AUTH_TYPE_SCHANNEL:
1729 /* Bind complete. */
1730 tevent_req_done(req);
1733 case DCERPC_AUTH_TYPE_NTLMSSP:
1734 case DCERPC_AUTH_TYPE_SPNEGO:
1735 case DCERPC_AUTH_TYPE_KRB5:
1736 /* Paranoid lenght checks */
1737 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1738 + pkt->auth_length) {
1739 tevent_req_nterror(req,
1740 NT_STATUS_INFO_LENGTH_MISMATCH);
1743 /* get auth credentials */
1744 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1745 &pkt->u.bind_ack.auth_info,
1747 if (!NT_STATUS_IS_OK(status)) {
1748 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1749 nt_errstr(status)));
1750 tevent_req_nterror(req, status);
1760 * For authenticated binds we may need to do 3 or 4 leg binds.
1763 switch(state->cli->auth->auth_type) {
1765 case DCERPC_AUTH_TYPE_NONE:
1766 case DCERPC_AUTH_TYPE_SCHANNEL:
1767 /* Bind complete. */
1768 tevent_req_done(req);
1771 case DCERPC_AUTH_TYPE_NTLMSSP:
1772 /* Need to send AUTH3 packet - no reply. */
1773 status = rpc_finish_auth3_bind_send(req, state,
1777 case DCERPC_AUTH_TYPE_SPNEGO:
1778 status = spnego_get_client_auth_token(state,
1779 pauth->a_u.spnego_state,
1782 if (!NT_STATUS_IS_OK(status)) {
1785 if (auth_token.length == 0) {
1786 /* Bind complete. */
1787 tevent_req_done(req);
1790 if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
1791 status = rpc_bind_next_send(req, state,
1794 status = rpc_bind_finish_send(req, state,
1799 case DCERPC_AUTH_TYPE_KRB5:
1800 status = gse_get_client_auth_token(state,
1801 pauth->a_u.gssapi_state,
1804 if (!NT_STATUS_IS_OK(status)) {
1808 if (gse_require_more_processing(pauth->a_u.gssapi_state)) {
1809 status = rpc_bind_next_send(req, state, &auth_token);
1811 status = rpc_bind_finish_send(req, state, &auth_token);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 tevent_req_nterror(req, status);
1825 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u(%u)\n",
1826 (unsigned int)state->cli->auth->auth_type,
1827 (unsigned int)state->cli->auth->spnego_type));
1828 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1831 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1832 struct rpc_pipe_bind_state *state,
1833 DATA_BLOB *credentials)
1835 struct pipe_auth_data *auth = state->cli->auth;
1836 DATA_BLOB client_reply = data_blob_null;
1837 struct tevent_req *subreq;
1840 /* TODO - check auth_type/auth_level match. */
1842 status = auth_ntlmssp_update(auth->a_u.auth_ntlmssp_state,
1843 *credentials, &client_reply);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
1847 "blob failed: %s.\n", nt_errstr(status)));
1851 data_blob_free(&state->rpc_out);
1853 status = create_rpc_bind_auth3(state, state->cli,
1859 data_blob_free(&client_reply);
1861 if (!NT_STATUS_IS_OK(status)) {
1865 subreq = rpc_write_send(state, state->ev, state->cli->transport,
1866 state->rpc_out.data, state->rpc_out.length);
1867 if (subreq == NULL) {
1868 return NT_STATUS_NO_MEMORY;
1870 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1871 return NT_STATUS_OK;
1874 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
1876 struct tevent_req *req = tevent_req_callback_data(
1877 subreq, struct tevent_req);
1880 status = rpc_write_recv(subreq);
1881 TALLOC_FREE(subreq);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 tevent_req_nterror(req, status);
1886 tevent_req_done(req);
1889 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1890 struct rpc_pipe_bind_state *state,
1891 DATA_BLOB *auth_token)
1893 struct pipe_auth_data *auth = state->cli->auth;
1894 struct tevent_req *subreq;
1897 /* Now prepare the alter context pdu. */
1898 data_blob_free(&state->rpc_out);
1900 status = create_rpc_alter_context(state,
1904 &state->cli->abstract_syntax,
1905 &state->cli->transfer_syntax,
1908 if (!NT_STATUS_IS_OK(status)) {
1912 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1913 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1914 if (subreq == NULL) {
1915 return NT_STATUS_NO_MEMORY;
1917 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1918 return NT_STATUS_OK;
1921 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1922 struct rpc_pipe_bind_state *state,
1923 DATA_BLOB *auth_token)
1925 struct pipe_auth_data *auth = state->cli->auth;
1926 struct tevent_req *subreq;
1929 /* Now prepare the auth3 context pdu. */
1930 data_blob_free(&state->rpc_out);
1932 status = create_rpc_bind_auth3(state, state->cli,
1938 if (!NT_STATUS_IS_OK(status)) {
1942 subreq = rpc_write_send(state, state->ev, state->cli->transport,
1943 state->rpc_out.data, state->rpc_out.length);
1944 if (subreq == NULL) {
1945 return NT_STATUS_NO_MEMORY;
1947 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1948 return NT_STATUS_OK;
1951 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1953 return tevent_req_simple_recv_ntstatus(req);
1956 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1957 struct pipe_auth_data *auth)
1959 TALLOC_CTX *frame = talloc_stackframe();
1960 struct event_context *ev;
1961 struct tevent_req *req;
1962 NTSTATUS status = NT_STATUS_OK;
1964 ev = event_context_init(frame);
1966 status = NT_STATUS_NO_MEMORY;
1970 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1972 status = NT_STATUS_NO_MEMORY;
1976 if (!tevent_req_poll(req, ev)) {
1977 status = map_nt_error_from_unix(errno);
1981 status = rpc_pipe_bind_recv(req);
1987 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1989 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1990 unsigned int timeout)
1994 if (rpc_cli->transport == NULL) {
1995 return RPCCLI_DEFAULT_TIMEOUT;
1998 if (rpc_cli->transport->set_timeout == NULL) {
1999 return RPCCLI_DEFAULT_TIMEOUT;
2002 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2004 return RPCCLI_DEFAULT_TIMEOUT;
2010 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2012 if (rpc_cli == NULL) {
2016 if (rpc_cli->transport == NULL) {
2020 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2023 struct rpccli_bh_state {
2024 struct rpc_pipe_client *rpc_cli;
2027 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2029 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2030 struct rpccli_bh_state);
2032 return rpccli_is_connected(hs->rpc_cli);
2035 struct rpccli_bh_raw_call_state {
2041 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2043 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2044 struct tevent_context *ev,
2045 struct dcerpc_binding_handle *h,
2046 const struct GUID *object,
2049 const uint8_t *in_data,
2052 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2053 struct rpccli_bh_state);
2054 struct tevent_req *req;
2055 struct rpccli_bh_raw_call_state *state;
2057 struct tevent_req *subreq;
2059 req = tevent_req_create(mem_ctx, &state,
2060 struct rpccli_bh_raw_call_state);
2064 state->in_data.data = discard_const_p(uint8_t, in_data);
2065 state->in_data.length = in_length;
2067 ok = rpccli_bh_is_connected(h);
2069 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2070 return tevent_req_post(req, ev);
2073 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2074 opnum, &state->in_data);
2075 if (tevent_req_nomem(subreq, req)) {
2076 return tevent_req_post(req, ev);
2078 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2083 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2085 struct tevent_req *req =
2086 tevent_req_callback_data(subreq,
2088 struct rpccli_bh_raw_call_state *state =
2089 tevent_req_data(req,
2090 struct rpccli_bh_raw_call_state);
2093 state->out_flags = 0;
2095 /* TODO: support bigendian responses */
2097 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2098 TALLOC_FREE(subreq);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 tevent_req_nterror(req, status);
2104 tevent_req_done(req);
2107 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2108 TALLOC_CTX *mem_ctx,
2111 uint32_t *out_flags)
2113 struct rpccli_bh_raw_call_state *state =
2114 tevent_req_data(req,
2115 struct rpccli_bh_raw_call_state);
2118 if (tevent_req_is_nterror(req, &status)) {
2119 tevent_req_received(req);
2123 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2124 *out_length = state->out_data.length;
2125 *out_flags = state->out_flags;
2126 tevent_req_received(req);
2127 return NT_STATUS_OK;
2130 struct rpccli_bh_disconnect_state {
2134 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2135 struct tevent_context *ev,
2136 struct dcerpc_binding_handle *h)
2138 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2139 struct rpccli_bh_state);
2140 struct tevent_req *req;
2141 struct rpccli_bh_disconnect_state *state;
2144 req = tevent_req_create(mem_ctx, &state,
2145 struct rpccli_bh_disconnect_state);
2150 ok = rpccli_bh_is_connected(h);
2152 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2153 return tevent_req_post(req, ev);
2157 * TODO: do a real async disconnect ...
2159 * For now the caller needs to free rpc_cli
2163 tevent_req_done(req);
2164 return tevent_req_post(req, ev);
2167 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2171 if (tevent_req_is_nterror(req, &status)) {
2172 tevent_req_received(req);
2176 tevent_req_received(req);
2177 return NT_STATUS_OK;
2180 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2185 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2187 const void *_struct_ptr,
2188 const struct ndr_interface_call *call)
2190 void *struct_ptr = discard_const(_struct_ptr);
2192 if (DEBUGLEVEL < 10) {
2196 if (ndr_flags & NDR_IN) {
2197 ndr_print_function_debug(call->ndr_print,
2202 if (ndr_flags & NDR_OUT) {
2203 ndr_print_function_debug(call->ndr_print,
2210 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2212 .is_connected = rpccli_bh_is_connected,
2213 .raw_call_send = rpccli_bh_raw_call_send,
2214 .raw_call_recv = rpccli_bh_raw_call_recv,
2215 .disconnect_send = rpccli_bh_disconnect_send,
2216 .disconnect_recv = rpccli_bh_disconnect_recv,
2218 .ref_alloc = rpccli_bh_ref_alloc,
2219 .do_ndr_print = rpccli_bh_do_ndr_print,
2222 /* initialise a rpc_pipe_client binding handle */
2223 static struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2225 struct dcerpc_binding_handle *h;
2226 struct rpccli_bh_state *hs;
2228 h = dcerpc_binding_handle_create(c,
2233 struct rpccli_bh_state,
2243 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2245 struct auth_ntlmssp_state *a = NULL;
2246 struct cli_state *cli;
2248 if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2249 a = rpc_cli->auth->a_u.auth_ntlmssp_state;
2250 } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
2251 enum dcerpc_AuthType auth_type;
2255 status = spnego_get_negotiated_mech(
2256 rpc_cli->auth->a_u.spnego_state,
2257 &auth_type, &auth_ctx);
2258 if (!NT_STATUS_IS_OK(status)) {
2262 if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2263 a = talloc_get_type(auth_ctx,
2264 struct auth_ntlmssp_state);
2269 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
2273 cli = rpc_pipe_np_smb_conn(rpc_cli);
2277 E_md4hash(cli->password ? cli->password : "", nt_hash);
2281 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2282 struct pipe_auth_data **presult)
2284 struct pipe_auth_data *result;
2286 result = talloc(mem_ctx, struct pipe_auth_data);
2287 if (result == NULL) {
2288 return NT_STATUS_NO_MEMORY;
2291 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2292 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2293 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2295 result->user_name = talloc_strdup(result, "");
2296 result->domain = talloc_strdup(result, "");
2297 if ((result->user_name == NULL) || (result->domain == NULL)) {
2298 TALLOC_FREE(result);
2299 return NT_STATUS_NO_MEMORY;
2303 return NT_STATUS_OK;
2306 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2308 TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2312 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2313 enum dcerpc_AuthType auth_type,
2314 enum dcerpc_AuthLevel auth_level,
2316 const char *username,
2317 const char *password,
2318 struct pipe_auth_data **presult)
2320 struct pipe_auth_data *result;
2323 result = talloc(mem_ctx, struct pipe_auth_data);
2324 if (result == NULL) {
2325 return NT_STATUS_NO_MEMORY;
2328 result->auth_type = auth_type;
2329 result->auth_level = auth_level;
2331 result->user_name = talloc_strdup(result, username);
2332 result->domain = talloc_strdup(result, domain);
2333 if ((result->user_name == NULL) || (result->domain == NULL)) {
2334 status = NT_STATUS_NO_MEMORY;
2338 status = auth_ntlmssp_client_start(NULL,
2341 lp_client_ntlmv2_auth(),
2342 &result->a_u.auth_ntlmssp_state);
2343 if (!NT_STATUS_IS_OK(status)) {
2347 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2349 status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2351 if (!NT_STATUS_IS_OK(status)) {
2355 status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2357 if (!NT_STATUS_IS_OK(status)) {
2361 status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2363 if (!NT_STATUS_IS_OK(status)) {
2368 * Turn off sign+seal to allow selected auth level to turn it back on.
2370 auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2371 ~(NTLMSSP_NEGOTIATE_SIGN |
2372 NTLMSSP_NEGOTIATE_SEAL));
2374 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2375 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2376 NTLMSSP_NEGOTIATE_SIGN);
2377 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2378 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2379 NTLMSSP_NEGOTIATE_SEAL |
2380 NTLMSSP_NEGOTIATE_SIGN);
2384 return NT_STATUS_OK;
2387 TALLOC_FREE(result);
2391 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2392 enum dcerpc_AuthLevel auth_level,
2393 struct netlogon_creds_CredentialState *creds,
2394 struct pipe_auth_data **presult)
2396 struct pipe_auth_data *result;
2398 result = talloc(mem_ctx, struct pipe_auth_data);
2399 if (result == NULL) {
2400 return NT_STATUS_NO_MEMORY;
2403 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2404 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2405 result->auth_level = auth_level;
2407 result->user_name = talloc_strdup(result, "");
2408 result->domain = talloc_strdup(result, domain);
2409 if ((result->user_name == NULL) || (result->domain == NULL)) {
2413 result->a_u.schannel_auth = talloc(result, struct schannel_state);
2414 if (result->a_u.schannel_auth == NULL) {
2418 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2419 result->a_u.schannel_auth->seq_num = 0;
2420 result->a_u.schannel_auth->initiator = true;
2421 result->a_u.schannel_auth->creds = creds;
2424 return NT_STATUS_OK;
2427 TALLOC_FREE(result);
2428 return NT_STATUS_NO_MEMORY;
2432 * Create an rpc pipe client struct, connecting to a tcp port.
2434 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2436 const struct ndr_syntax_id *abstract_syntax,
2437 struct rpc_pipe_client **presult)
2439 struct rpc_pipe_client *result;
2440 struct sockaddr_storage addr;
2444 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2445 if (result == NULL) {
2446 return NT_STATUS_NO_MEMORY;
2449 result->abstract_syntax = *abstract_syntax;
2450 result->transfer_syntax = ndr_transfer_syntax;
2452 result->desthost = talloc_strdup(result, host);
2453 result->srv_name_slash = talloc_asprintf_strupper_m(
2454 result, "\\\\%s", result->desthost);
2455 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2456 status = NT_STATUS_NO_MEMORY;
2460 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2461 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2463 if (!resolve_name(host, &addr, 0, false)) {
2464 status = NT_STATUS_NOT_FOUND;
2468 status = open_socket_out(&addr, port, 60, &fd);
2469 if (!NT_STATUS_IS_OK(status)) {
2472 set_socket_options(fd, lp_socket_options());
2474 status = rpc_transport_sock_init(result, fd, &result->transport);
2475 if (!NT_STATUS_IS_OK(status)) {
2480 result->transport->transport = NCACN_IP_TCP;
2482 result->binding_handle = rpccli_bh_create(result);
2483 if (result->binding_handle == NULL) {
2484 TALLOC_FREE(result);
2485 return NT_STATUS_NO_MEMORY;
2489 return NT_STATUS_OK;
2492 TALLOC_FREE(result);
2497 * Determine the tcp port on which a dcerpc interface is listening
2498 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2501 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2502 const struct ndr_syntax_id *abstract_syntax,
2506 struct rpc_pipe_client *epm_pipe = NULL;
2507 struct pipe_auth_data *auth = NULL;
2508 struct dcerpc_binding *map_binding = NULL;
2509 struct dcerpc_binding *res_binding = NULL;
2510 struct epm_twr_t *map_tower = NULL;
2511 struct epm_twr_t *res_towers = NULL;
2512 struct policy_handle *entry_handle = NULL;
2513 uint32_t num_towers = 0;
2514 uint32_t max_towers = 1;
2515 struct epm_twr_p_t towers;
2516 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2518 if (pport == NULL) {
2519 status = NT_STATUS_INVALID_PARAMETER;
2523 /* open the connection to the endpoint mapper */
2524 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2525 &ndr_table_epmapper.syntax_id,
2528 if (!NT_STATUS_IS_OK(status)) {
2532 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2533 if (!NT_STATUS_IS_OK(status)) {
2537 status = rpc_pipe_bind(epm_pipe, auth);
2538 if (!NT_STATUS_IS_OK(status)) {
2542 /* create tower for asking the epmapper */
2544 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2545 if (map_binding == NULL) {
2546 status = NT_STATUS_NO_MEMORY;
2550 map_binding->transport = NCACN_IP_TCP;
2551 map_binding->object = *abstract_syntax;
2552 map_binding->host = host; /* needed? */
2553 map_binding->endpoint = "0"; /* correct? needed? */
2555 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2556 if (map_tower == NULL) {
2557 status = NT_STATUS_NO_MEMORY;
2561 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2562 &(map_tower->tower));
2563 if (!NT_STATUS_IS_OK(status)) {
2567 /* allocate further parameters for the epm_Map call */
2569 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2570 if (res_towers == NULL) {
2571 status = NT_STATUS_NO_MEMORY;
2574 towers.twr = res_towers;
2576 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2577 if (entry_handle == NULL) {
2578 status = NT_STATUS_NO_MEMORY;
2582 /* ask the endpoint mapper for the port */
2584 status = rpccli_epm_Map(epm_pipe,
2586 CONST_DISCARD(struct GUID *,
2587 &(abstract_syntax->uuid)),
2594 if (!NT_STATUS_IS_OK(status)) {
2598 if (num_towers != 1) {
2599 status = NT_STATUS_UNSUCCESSFUL;
2603 /* extract the port from the answer */
2605 status = dcerpc_binding_from_tower(tmp_ctx,
2606 &(towers.twr->tower),
2608 if (!NT_STATUS_IS_OK(status)) {
2612 /* are further checks here necessary? */
2613 if (res_binding->transport != NCACN_IP_TCP) {
2614 status = NT_STATUS_UNSUCCESSFUL;
2618 *pport = (uint16_t)atoi(res_binding->endpoint);
2621 TALLOC_FREE(tmp_ctx);
2626 * Create a rpc pipe client struct, connecting to a host via tcp.
2627 * The port is determined by asking the endpoint mapper on the given
2630 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2631 const struct ndr_syntax_id *abstract_syntax,
2632 struct rpc_pipe_client **presult)
2637 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2638 if (!NT_STATUS_IS_OK(status)) {
2642 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2643 abstract_syntax, presult);
2646 /********************************************************************
2647 Create a rpc pipe client struct, connecting to a unix domain socket
2648 ********************************************************************/
2649 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2650 const struct ndr_syntax_id *abstract_syntax,
2651 struct rpc_pipe_client **presult)
2653 struct rpc_pipe_client *result;
2654 struct sockaddr_un addr;
2658 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2659 if (result == NULL) {
2660 return NT_STATUS_NO_MEMORY;
2663 result->abstract_syntax = *abstract_syntax;
2664 result->transfer_syntax = ndr_transfer_syntax;
2666 result->desthost = get_myname(result);
2667 result->srv_name_slash = talloc_asprintf_strupper_m(
2668 result, "\\\\%s", result->desthost);
2669 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2670 status = NT_STATUS_NO_MEMORY;
2674 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2675 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2677 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2679 status = map_nt_error_from_unix(errno);
2684 addr.sun_family = AF_UNIX;
2685 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2687 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2688 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2691 return map_nt_error_from_unix(errno);
2694 status = rpc_transport_sock_init(result, fd, &result->transport);
2695 if (!NT_STATUS_IS_OK(status)) {
2700 result->transport->transport = NCALRPC;
2702 result->binding_handle = rpccli_bh_create(result);
2703 if (result->binding_handle == NULL) {
2704 TALLOC_FREE(result);
2705 return NT_STATUS_NO_MEMORY;
2709 return NT_STATUS_OK;
2712 TALLOC_FREE(result);
2716 struct rpc_pipe_client_np_ref {
2717 struct cli_state *cli;
2718 struct rpc_pipe_client *pipe;
2721 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2723 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2727 /****************************************************************************
2728 Open a named pipe over SMB to a remote server.
2730 * CAVEAT CALLER OF THIS FUNCTION:
2731 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2732 * so be sure that this function is called AFTER any structure (vs pointer)
2733 * assignment of the cli. In particular, libsmbclient does structure
2734 * assignments of cli, which invalidates the data in the returned
2735 * rpc_pipe_client if this function is called before the structure assignment
2738 ****************************************************************************/
2740 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2741 const struct ndr_syntax_id *abstract_syntax,
2742 struct rpc_pipe_client **presult)
2744 struct rpc_pipe_client *result;
2746 struct rpc_pipe_client_np_ref *np_ref;
2748 /* sanity check to protect against crashes */
2751 return NT_STATUS_INVALID_HANDLE;
2754 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2755 if (result == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2759 result->abstract_syntax = *abstract_syntax;
2760 result->transfer_syntax = ndr_transfer_syntax;
2761 result->desthost = talloc_strdup(result, cli->desthost);
2762 result->srv_name_slash = talloc_asprintf_strupper_m(
2763 result, "\\\\%s", result->desthost);
2765 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2766 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2768 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2769 TALLOC_FREE(result);
2770 return NT_STATUS_NO_MEMORY;
2773 status = rpc_transport_np_init(result, cli, abstract_syntax,
2774 &result->transport);
2775 if (!NT_STATUS_IS_OK(status)) {
2776 TALLOC_FREE(result);
2780 result->transport->transport = NCACN_NP;
2782 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2783 if (np_ref == NULL) {
2784 TALLOC_FREE(result);
2785 return NT_STATUS_NO_MEMORY;
2788 np_ref->pipe = result;
2790 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2791 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2793 result->binding_handle = rpccli_bh_create(result);
2794 if (result->binding_handle == NULL) {
2795 TALLOC_FREE(result);
2796 return NT_STATUS_NO_MEMORY;
2800 return NT_STATUS_OK;
2803 /****************************************************************************
2804 Open a pipe to a remote server.
2805 ****************************************************************************/
2807 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2808 enum dcerpc_transport_t transport,
2809 const struct ndr_syntax_id *interface,
2810 struct rpc_pipe_client **presult)
2812 switch (transport) {
2814 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2817 return rpc_pipe_open_np(cli, interface, presult);
2819 return NT_STATUS_NOT_IMPLEMENTED;
2823 /****************************************************************************
2824 Open a named pipe to an SMB server and bind anonymously.
2825 ****************************************************************************/
2827 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2828 enum dcerpc_transport_t transport,
2829 const struct ndr_syntax_id *interface,
2830 struct rpc_pipe_client **presult)
2832 struct rpc_pipe_client *result;
2833 struct pipe_auth_data *auth;
2836 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2837 if (!NT_STATUS_IS_OK(status)) {
2841 status = rpccli_anon_bind_data(result, &auth);
2842 if (!NT_STATUS_IS_OK(status)) {
2843 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2844 nt_errstr(status)));
2845 TALLOC_FREE(result);
2850 * This is a bit of an abstraction violation due to the fact that an
2851 * anonymous bind on an authenticated SMB inherits the user/domain
2852 * from the enclosing SMB creds
2855 TALLOC_FREE(auth->user_name);
2856 TALLOC_FREE(auth->domain);
2858 auth->user_name = talloc_strdup(auth, cli->user_name);
2859 auth->domain = talloc_strdup(auth, cli->domain);
2860 auth->user_session_key = data_blob_talloc(auth,
2861 cli->user_session_key.data,
2862 cli->user_session_key.length);
2864 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2865 TALLOC_FREE(result);
2866 return NT_STATUS_NO_MEMORY;
2869 status = rpc_pipe_bind(result, auth);
2870 if (!NT_STATUS_IS_OK(status)) {
2872 if (ndr_syntax_id_equal(interface,
2873 &ndr_table_dssetup.syntax_id)) {
2874 /* non AD domains just don't have this pipe, avoid
2875 * level 0 statement in that case - gd */
2878 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2879 "%s failed with error %s\n",
2880 get_pipe_name_from_syntax(talloc_tos(), interface),
2881 nt_errstr(status) ));
2882 TALLOC_FREE(result);
2886 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2887 "%s and bound anonymously.\n",
2888 get_pipe_name_from_syntax(talloc_tos(), interface),
2892 return NT_STATUS_OK;
2895 /****************************************************************************
2896 ****************************************************************************/
2898 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2899 const struct ndr_syntax_id *interface,
2900 struct rpc_pipe_client **presult)
2902 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2903 interface, presult);
2906 /****************************************************************************
2907 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2908 ****************************************************************************/
2910 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2911 const struct ndr_syntax_id *interface,
2912 enum dcerpc_transport_t transport,
2913 enum dcerpc_AuthLevel auth_level,
2915 const char *username,
2916 const char *password,
2917 struct rpc_pipe_client **presult)
2919 struct rpc_pipe_client *result;
2920 struct pipe_auth_data *auth = NULL;
2921 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
2924 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2925 if (!NT_STATUS_IS_OK(status)) {
2929 status = rpccli_ntlmssp_bind_data(result,
2930 auth_type, auth_level,
2931 domain, username, password,
2933 if (!NT_STATUS_IS_OK(status)) {
2934 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2935 nt_errstr(status)));
2939 status = rpc_pipe_bind(result, auth);
2940 if (!NT_STATUS_IS_OK(status)) {
2941 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2942 nt_errstr(status) ));
2946 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2947 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2948 get_pipe_name_from_syntax(talloc_tos(), interface),
2949 cli->desthost, domain, username ));
2952 return NT_STATUS_OK;
2956 TALLOC_FREE(result);
2960 /****************************************************************************
2961 Get a the schannel session key out of an already opened netlogon pipe.
2962 ****************************************************************************/
2963 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2964 struct cli_state *cli,
2968 enum netr_SchannelType sec_chan_type = 0;
2969 unsigned char machine_pwd[16];
2970 const char *machine_account;
2973 /* Get the machine account credentials from secrets.tdb. */
2974 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2977 DEBUG(0, ("get_schannel_session_key: could not fetch "
2978 "trust account password for domain '%s'\n",
2980 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2983 status = rpccli_netlogon_setup_creds(netlogon_pipe,
2984 cli->desthost, /* server name */
2985 domain, /* domain */
2986 global_myname(), /* client name */
2987 machine_account, /* machine account name */
2992 if (!NT_STATUS_IS_OK(status)) {
2993 DEBUG(3, ("get_schannel_session_key_common: "
2994 "rpccli_netlogon_setup_creds failed with result %s "
2995 "to server %s, domain %s, machine account %s.\n",
2996 nt_errstr(status), cli->desthost, domain,
3001 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3002 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3004 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3007 return NT_STATUS_OK;;
3010 /****************************************************************************
3011 Open a netlogon pipe and get the schannel session key.
3012 Now exposed to external callers.
3013 ****************************************************************************/
3016 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3019 struct rpc_pipe_client **presult)
3021 struct rpc_pipe_client *netlogon_pipe = NULL;
3024 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3026 if (!NT_STATUS_IS_OK(status)) {
3030 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3032 if (!NT_STATUS_IS_OK(status)) {
3033 TALLOC_FREE(netlogon_pipe);
3037 *presult = netlogon_pipe;
3038 return NT_STATUS_OK;
3041 /****************************************************************************
3043 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3044 using session_key. sign and seal.
3046 The *pdc will be stolen onto this new pipe
3047 ****************************************************************************/
3049 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3050 const struct ndr_syntax_id *interface,
3051 enum dcerpc_transport_t transport,
3052 enum dcerpc_AuthLevel auth_level,
3054 struct netlogon_creds_CredentialState **pdc,
3055 struct rpc_pipe_client **presult)
3057 struct rpc_pipe_client *result;
3058 struct pipe_auth_data *auth;
3061 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3062 if (!NT_STATUS_IS_OK(status)) {
3066 status = rpccli_schannel_bind_data(result, domain, auth_level,
3068 if (!NT_STATUS_IS_OK(status)) {
3069 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3070 nt_errstr(status)));
3071 TALLOC_FREE(result);
3075 status = rpc_pipe_bind(result, auth);
3076 if (!NT_STATUS_IS_OK(status)) {
3077 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3078 "cli_rpc_pipe_bind failed with error %s\n",
3079 nt_errstr(status) ));
3080 TALLOC_FREE(result);
3085 * The credentials on a new netlogon pipe are the ones we are passed
3086 * in - reference them in
3088 result->dc = talloc_move(result, pdc);
3090 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3091 "for domain %s and bound using schannel.\n",
3092 get_pipe_name_from_syntax(talloc_tos(), interface),
3093 cli->desthost, domain ));
3096 return NT_STATUS_OK;
3099 /****************************************************************************
3100 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3101 Fetch the session key ourselves using a temporary netlogon pipe. This
3102 version uses an ntlmssp auth bound netlogon pipe to get the key.
3103 ****************************************************************************/
3105 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3107 const char *username,
3108 const char *password,
3110 struct rpc_pipe_client **presult)
3112 struct rpc_pipe_client *netlogon_pipe = NULL;
3115 status = cli_rpc_pipe_open_spnego_ntlmssp(
3116 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3117 DCERPC_AUTH_LEVEL_PRIVACY,
3118 domain, username, password, &netlogon_pipe);
3119 if (!NT_STATUS_IS_OK(status)) {
3123 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3125 if (!NT_STATUS_IS_OK(status)) {
3126 TALLOC_FREE(netlogon_pipe);
3130 *presult = netlogon_pipe;
3131 return NT_STATUS_OK;
3134 /****************************************************************************
3135 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3136 Fetch the session key ourselves using a temporary netlogon pipe. This version
3137 uses an ntlmssp bind to get the session key.
3138 ****************************************************************************/
3140 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3141 const struct ndr_syntax_id *interface,
3142 enum dcerpc_transport_t transport,
3143 enum dcerpc_AuthLevel auth_level,
3145 const char *username,
3146 const char *password,
3147 struct rpc_pipe_client **presult)
3149 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3150 struct rpc_pipe_client *netlogon_pipe = NULL;
3151 struct rpc_pipe_client *result = NULL;
3154 status = get_schannel_session_key_auth_ntlmssp(
3155 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3156 if (!NT_STATUS_IS_OK(status)) {
3157 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3158 "key from server %s for domain %s.\n",
3159 cli->desthost, domain ));
3163 status = cli_rpc_pipe_open_schannel_with_key(
3164 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3167 /* Now we've bound using the session key we can close the netlog pipe. */
3168 TALLOC_FREE(netlogon_pipe);
3170 if (NT_STATUS_IS_OK(status)) {
3176 /****************************************************************************
3177 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3178 Fetch the session key ourselves using a temporary netlogon pipe.
3179 ****************************************************************************/
3181 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3182 const struct ndr_syntax_id *interface,
3183 enum dcerpc_transport_t transport,
3184 enum dcerpc_AuthLevel auth_level,
3186 struct rpc_pipe_client **presult)
3188 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3189 struct rpc_pipe_client *netlogon_pipe = NULL;
3190 struct rpc_pipe_client *result = NULL;
3193 status = get_schannel_session_key(cli, domain, &neg_flags,
3195 if (!NT_STATUS_IS_OK(status)) {
3196 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3197 "key from server %s for domain %s.\n",
3198 cli->desthost, domain ));
3202 status = cli_rpc_pipe_open_schannel_with_key(
3203 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3206 /* Now we've bound using the session key we can close the netlog pipe. */
3207 TALLOC_FREE(netlogon_pipe);
3209 if (NT_STATUS_IS_OK(status)) {
3216 /****************************************************************************
3217 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3218 The idea is this can be called with service_princ, username and password all
3219 NULL so long as the caller has a TGT.
3220 ****************************************************************************/
3222 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3223 const struct ndr_syntax_id *interface,
3224 enum dcerpc_transport_t transport,
3225 enum dcerpc_AuthLevel auth_level,
3227 const char *username,
3228 const char *password,
3229 struct rpc_pipe_client **presult)
3231 struct rpc_pipe_client *result;
3232 struct pipe_auth_data *auth;
3235 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3236 if (!NT_STATUS_IS_OK(status)) {
3240 auth = talloc(result, struct pipe_auth_data);
3242 status = NT_STATUS_NO_MEMORY;
3245 auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
3246 auth->auth_level = auth_level;
3251 auth->user_name = talloc_strdup(auth, username);
3252 if (!auth->user_name) {
3253 status = NT_STATUS_NO_MEMORY;
3257 /* Fixme, should we fetch/set the Realm ? */
3258 auth->domain = talloc_strdup(auth, "");
3259 if (!auth->domain) {
3260 status = NT_STATUS_NO_MEMORY;
3264 status = gse_init_client(auth, auth->auth_type, auth->auth_level,
3265 NULL, server, "cifs", username, password,
3266 GSS_C_DCE_STYLE, &auth->a_u.gssapi_state);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 DEBUG(0, ("gse_init_client returned %s\n",
3270 nt_errstr(status)));
3274 status = rpc_pipe_bind(result, auth);
3275 if (!NT_STATUS_IS_OK(status)) {
3276 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3277 nt_errstr(status)));
3282 return NT_STATUS_OK;
3285 TALLOC_FREE(result);
3289 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
3290 const struct ndr_syntax_id *interface,
3291 enum dcerpc_transport_t transport,
3292 enum dcerpc_AuthLevel auth_level,
3294 const char *username,
3295 const char *password,
3296 struct rpc_pipe_client **presult)
3298 struct rpc_pipe_client *result;
3299 struct pipe_auth_data *auth;
3302 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3303 if (!NT_STATUS_IS_OK(status)) {
3307 auth = talloc(result, struct pipe_auth_data);
3309 status = NT_STATUS_NO_MEMORY;
3312 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3313 auth->auth_level = auth_level;
3315 auth->spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
3320 auth->user_name = talloc_strdup(auth, username);
3321 if (!auth->user_name) {
3322 status = NT_STATUS_NO_MEMORY;
3326 /* Fixme, should we fetch/set the Realm ? */
3327 auth->domain = talloc_strdup(auth, "");
3328 if (!auth->domain) {
3329 status = NT_STATUS_NO_MEMORY;
3333 status = spnego_gssapi_init_client(auth, auth->auth_level,
3334 NULL, server, "cifs",
3337 &auth->a_u.spnego_state);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 DEBUG(0, ("spnego_init_client returned %s\n",
3340 nt_errstr(status)));
3344 status = rpc_pipe_bind(result, auth);
3345 if (!NT_STATUS_IS_OK(status)) {
3346 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3347 nt_errstr(status)));
3352 return NT_STATUS_OK;
3355 TALLOC_FREE(result);
3359 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3360 const struct ndr_syntax_id *interface,
3361 enum dcerpc_transport_t transport,
3362 enum dcerpc_AuthLevel auth_level,
3364 const char *username,
3365 const char *password,
3366 struct rpc_pipe_client **presult)
3368 struct rpc_pipe_client *result;
3369 struct pipe_auth_data *auth;
3372 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3373 if (!NT_STATUS_IS_OK(status)) {
3377 auth = talloc(result, struct pipe_auth_data);
3379 status = NT_STATUS_NO_MEMORY;
3382 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3383 auth->auth_level = auth_level;
3388 auth->user_name = talloc_strdup(auth, username);
3389 if (!auth->user_name) {
3390 status = NT_STATUS_NO_MEMORY;
3397 auth->domain = talloc_strdup(auth, domain);
3398 if (!auth->domain) {
3399 status = NT_STATUS_NO_MEMORY;
3403 status = spnego_ntlmssp_init_client(auth, auth->auth_level,
3404 domain, username, password,
3405 &auth->a_u.spnego_state);
3406 if (!NT_STATUS_IS_OK(status)) {
3407 DEBUG(0, ("spnego_init_client returned %s\n",
3408 nt_errstr(status)));
3412 status = rpc_pipe_bind(result, auth);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3415 nt_errstr(status)));
3420 return NT_STATUS_OK;
3423 TALLOC_FREE(result);
3427 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3428 struct rpc_pipe_client *cli,
3429 DATA_BLOB *session_key)
3431 struct pipe_auth_data *a = cli->auth;
3434 if (!session_key || !cli) {
3435 return NT_STATUS_INVALID_PARAMETER;
3439 return NT_STATUS_INVALID_PARAMETER;
3442 switch (cli->auth->auth_type) {
3443 case DCERPC_AUTH_TYPE_SCHANNEL:
3444 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3447 case DCERPC_AUTH_TYPE_SPNEGO:
3448 sk = spnego_get_session_key(a->a_u.spnego_state);
3449 if (sk.length == 0) {
3450 return NT_STATUS_NO_USER_SESSION_KEY;
3453 case DCERPC_AUTH_TYPE_NTLMSSP:
3454 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3456 case DCERPC_AUTH_TYPE_KRB5:
3457 sk = gse_get_session_key(a->a_u.gssapi_state);
3459 case DCERPC_AUTH_TYPE_NONE:
3460 sk = data_blob_const(a->user_session_key.data,
3461 a->user_session_key.length);
3464 return NT_STATUS_NO_USER_SESSION_KEY;
3467 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3468 return NT_STATUS_OK;