s3-ntsvcs: Use struct pipes_struct.
[Samba/gbeck.git] / source3 / rpc_client / cli_pipe.c
blob6de2e80b457624f4f1688e179eab6d8ed19769ee
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
22 #include "../librpc/gen_ndr/ndr_schannel.h"
23 #include "../librpc/gen_ndr/ndr_dssetup.h"
24 #include "../librpc/gen_ndr/ndr_netlogon.h"
25 #include "../libcli/auth/schannel.h"
26 #include "../libcli/auth/spnego.h"
27 #include "smb_krb5.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "rpc_client/cli_netlogon.h"
31 #include "librpc/gen_ndr/ndr_dcerpc.h"
32 #include "librpc/rpc/dcerpc.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_RPC_CLI
37 /********************************************************************
38 Pipe description for a DEBUG
39 ********************************************************************/
40 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
41 struct rpc_pipe_client *cli)
43 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
44 if (result == NULL) {
45 return "pipe";
47 return result;
50 /********************************************************************
51 Rpc pipe call id.
52 ********************************************************************/
54 static uint32 get_rpc_call_id(void)
56 static uint32 call_id = 0;
57 return ++call_id;
60 /*******************************************************************
61 Use SMBreadX to get rest of one fragment's worth of rpc data.
62 Reads the whole size or give an error message
63 ********************************************************************/
65 struct rpc_read_state {
66 struct event_context *ev;
67 struct rpc_cli_transport *transport;
68 uint8_t *data;
69 size_t size;
70 size_t num_read;
73 static void rpc_read_done(struct tevent_req *subreq);
75 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
76 struct event_context *ev,
77 struct rpc_cli_transport *transport,
78 uint8_t *data, size_t size)
80 struct tevent_req *req, *subreq;
81 struct rpc_read_state *state;
83 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
84 if (req == NULL) {
85 return NULL;
87 state->ev = ev;
88 state->transport = transport;
89 state->data = data;
90 state->size = size;
91 state->num_read = 0;
93 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
95 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
96 transport->priv);
97 if (subreq == NULL) {
98 goto fail;
100 tevent_req_set_callback(subreq, rpc_read_done, req);
101 return req;
103 fail:
104 TALLOC_FREE(req);
105 return NULL;
108 static void rpc_read_done(struct tevent_req *subreq)
110 struct tevent_req *req = tevent_req_callback_data(
111 subreq, struct tevent_req);
112 struct rpc_read_state *state = tevent_req_data(
113 req, struct rpc_read_state);
114 NTSTATUS status;
115 ssize_t received;
117 status = state->transport->read_recv(subreq, &received);
118 TALLOC_FREE(subreq);
119 if (!NT_STATUS_IS_OK(status)) {
120 tevent_req_nterror(req, status);
121 return;
124 state->num_read += received;
125 if (state->num_read == state->size) {
126 tevent_req_done(req);
127 return;
130 subreq = state->transport->read_send(state, state->ev,
131 state->data + state->num_read,
132 state->size - state->num_read,
133 state->transport->priv);
134 if (tevent_req_nomem(subreq, req)) {
135 return;
137 tevent_req_set_callback(subreq, rpc_read_done, req);
140 static NTSTATUS rpc_read_recv(struct tevent_req *req)
142 return tevent_req_simple_recv_ntstatus(req);
145 struct rpc_write_state {
146 struct event_context *ev;
147 struct rpc_cli_transport *transport;
148 const uint8_t *data;
149 size_t size;
150 size_t num_written;
153 static void rpc_write_done(struct tevent_req *subreq);
155 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
156 struct event_context *ev,
157 struct rpc_cli_transport *transport,
158 const uint8_t *data, size_t size)
160 struct tevent_req *req, *subreq;
161 struct rpc_write_state *state;
163 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
164 if (req == NULL) {
165 return NULL;
167 state->ev = ev;
168 state->transport = transport;
169 state->data = data;
170 state->size = size;
171 state->num_written = 0;
173 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
175 subreq = transport->write_send(state, ev, data, size, transport->priv);
176 if (subreq == NULL) {
177 goto fail;
179 tevent_req_set_callback(subreq, rpc_write_done, req);
180 return req;
181 fail:
182 TALLOC_FREE(req);
183 return NULL;
186 static void rpc_write_done(struct tevent_req *subreq)
188 struct tevent_req *req = tevent_req_callback_data(
189 subreq, struct tevent_req);
190 struct rpc_write_state *state = tevent_req_data(
191 req, struct rpc_write_state);
192 NTSTATUS status;
193 ssize_t written;
195 status = state->transport->write_recv(subreq, &written);
196 TALLOC_FREE(subreq);
197 if (!NT_STATUS_IS_OK(status)) {
198 tevent_req_nterror(req, status);
199 return;
202 state->num_written += written;
204 if (state->num_written == state->size) {
205 tevent_req_done(req);
206 return;
209 subreq = state->transport->write_send(state, state->ev,
210 state->data + state->num_written,
211 state->size - state->num_written,
212 state->transport->priv);
213 if (tevent_req_nomem(subreq, req)) {
214 return;
216 tevent_req_set_callback(subreq, rpc_write_done, req);
219 static NTSTATUS rpc_write_recv(struct tevent_req *req)
221 return tevent_req_simple_recv_ntstatus(req);
225 /****************************************************************************
226 Try and get a PDU's worth of data from current_pdu. If not, then read more
227 from the wire.
228 ****************************************************************************/
230 struct get_complete_frag_state {
231 struct event_context *ev;
232 struct rpc_pipe_client *cli;
233 uint16_t frag_len;
234 DATA_BLOB *pdu;
237 static void get_complete_frag_got_header(struct tevent_req *subreq);
238 static void get_complete_frag_got_rest(struct tevent_req *subreq);
240 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
241 struct event_context *ev,
242 struct rpc_pipe_client *cli,
243 DATA_BLOB *pdu)
245 struct tevent_req *req, *subreq;
246 struct get_complete_frag_state *state;
247 size_t received;
248 NTSTATUS status;
250 req = tevent_req_create(mem_ctx, &state,
251 struct get_complete_frag_state);
252 if (req == NULL) {
253 return NULL;
255 state->ev = ev;
256 state->cli = cli;
257 state->frag_len = RPC_HEADER_LEN;
258 state->pdu = pdu;
260 received = pdu->length;
261 if (received < RPC_HEADER_LEN) {
262 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
263 status = NT_STATUS_NO_MEMORY;
264 goto post_status;
266 subreq = rpc_read_send(state, state->ev,
267 state->cli->transport,
268 pdu->data + received,
269 RPC_HEADER_LEN - received);
270 if (subreq == NULL) {
271 status = NT_STATUS_NO_MEMORY;
272 goto post_status;
274 tevent_req_set_callback(subreq, get_complete_frag_got_header,
275 req);
276 return req;
279 state->frag_len = dcerpc_get_frag_length(pdu);
282 * Ensure we have frag_len bytes of data.
284 if (received < state->frag_len) {
285 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
286 status = NT_STATUS_NO_MEMORY;
287 goto post_status;
289 subreq = rpc_read_send(state, state->ev,
290 state->cli->transport,
291 pdu->data + received,
292 state->frag_len - received);
293 if (subreq == NULL) {
294 status = NT_STATUS_NO_MEMORY;
295 goto post_status;
297 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
298 req);
299 return req;
302 status = NT_STATUS_OK;
303 post_status:
304 if (NT_STATUS_IS_OK(status)) {
305 tevent_req_done(req);
306 } else {
307 tevent_req_nterror(req, status);
309 return tevent_req_post(req, ev);
312 static void get_complete_frag_got_header(struct tevent_req *subreq)
314 struct tevent_req *req = tevent_req_callback_data(
315 subreq, struct tevent_req);
316 struct get_complete_frag_state *state = tevent_req_data(
317 req, struct get_complete_frag_state);
318 NTSTATUS status;
320 status = rpc_read_recv(subreq);
321 TALLOC_FREE(subreq);
322 if (!NT_STATUS_IS_OK(status)) {
323 tevent_req_nterror(req, status);
324 return;
327 state->frag_len = dcerpc_get_frag_length(state->pdu);
329 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
330 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
331 return;
335 * We're here in this piece of code because we've read exactly
336 * RPC_HEADER_LEN bytes into state->pdu.
339 subreq = rpc_read_send(state, state->ev, state->cli->transport,
340 state->pdu->data + RPC_HEADER_LEN,
341 state->frag_len - RPC_HEADER_LEN);
342 if (tevent_req_nomem(subreq, req)) {
343 return;
345 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
348 static void get_complete_frag_got_rest(struct tevent_req *subreq)
350 struct tevent_req *req = tevent_req_callback_data(
351 subreq, struct tevent_req);
352 NTSTATUS status;
354 status = rpc_read_recv(subreq);
355 TALLOC_FREE(subreq);
356 if (!NT_STATUS_IS_OK(status)) {
357 tevent_req_nterror(req, status);
358 return;
360 tevent_req_done(req);
363 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
365 return tevent_req_simple_recv_ntstatus(req);
368 /****************************************************************************
369 NTLMSSP specific sign/seal.
370 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
371 In fact I should probably abstract these into identical pieces of code... JRA.
372 ****************************************************************************/
374 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli,
375 struct ncacn_packet *pkt,
376 DATA_BLOB *pdu,
377 uint8 *p_ss_padding_len)
379 struct dcerpc_auth auth_info;
380 DATA_BLOB blob;
381 NTSTATUS status;
383 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
384 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
385 return NT_STATUS_OK;
388 if (!cli->auth->a_u.auth_ntlmssp_state) {
389 return NT_STATUS_INVALID_PARAMETER;
392 /* Ensure there's enough data for an authenticated response. */
393 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
394 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
395 + DCERPC_AUTH_TRAILER_LENGTH
396 + pkt->auth_length)) {
397 DEBUG(0, ("auth_len %u is too long.\n",
398 (unsigned int)pkt->auth_length));
399 return NT_STATUS_BUFFER_TOO_SMALL;
402 /* get the auth blob at the end of the packet */
403 blob = data_blob_const(pdu->data + pkt->frag_length
404 - DCERPC_AUTH_TRAILER_LENGTH
405 - pkt->auth_length,
406 DCERPC_AUTH_TRAILER_LENGTH
407 + pkt->auth_length);
409 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
410 if (!NT_STATUS_IS_OK(status)) {
411 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
412 return status;
415 /* Ensure auth_pad_len fits into the packet. */
416 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
417 + auth_info.auth_pad_length
418 + DCERPC_AUTH_TRAILER_LENGTH
419 + pkt->auth_length) {
420 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
421 "too large (%u), auth_len (%u), frag_len = (%u).\n",
422 (unsigned int)auth_info.auth_pad_length,
423 (unsigned int)pkt->auth_length,
424 (unsigned int)pkt->frag_length));
425 return NT_STATUS_BUFFER_TOO_SMALL;
429 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
430 * after the RPC header.
431 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
432 * functions as NTLMv2 checks the rpc headers also.
435 switch (cli->auth->auth_level) {
436 case DCERPC_AUTH_LEVEL_PRIVACY:
437 /* Data is encrypted. */
438 status = auth_ntlmssp_unseal_packet(
439 cli->auth->a_u.auth_ntlmssp_state,
440 pdu->data + DCERPC_RESPONSE_LENGTH,
441 pkt->frag_length
442 - DCERPC_RESPONSE_LENGTH
443 - DCERPC_AUTH_TRAILER_LENGTH
444 - pkt->auth_length,
445 pdu->data,
446 pkt->frag_length - pkt->auth_length,
447 &auth_info.credentials);
448 if (!NT_STATUS_IS_OK(status)) {
449 DEBUG(0, ("failed to unseal packet from %s."
450 " Error was %s.\n",
451 rpccli_pipe_txt(talloc_tos(), cli),
452 nt_errstr(status)));
453 return status;
455 break;
457 case DCERPC_AUTH_LEVEL_INTEGRITY:
458 /* Data is signed. */
459 status = auth_ntlmssp_check_packet(
460 cli->auth->a_u.auth_ntlmssp_state,
461 pdu->data + DCERPC_RESPONSE_LENGTH,
462 pkt->frag_length
463 - DCERPC_RESPONSE_LENGTH
464 - DCERPC_AUTH_TRAILER_LENGTH
465 - pkt->auth_length,
466 pdu->data,
467 pkt->frag_length - pkt->auth_length,
468 &auth_info.credentials);
469 if (!NT_STATUS_IS_OK(status)) {
470 DEBUG(0, ("check signing failed on packet from %s."
471 " Error was %s.\n",
472 rpccli_pipe_txt(talloc_tos(), cli),
473 nt_errstr(status)));
474 return status;
476 break;
478 default:
479 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
480 "auth level %d\n", cli->auth->auth_level));
481 return NT_STATUS_INVALID_INFO_CLASS;
485 * Remember the padding length. We must remove it from the real data
486 * stream once the sign/seal is done.
489 *p_ss_padding_len = auth_info.auth_pad_length;
491 return NT_STATUS_OK;
494 /****************************************************************************
495 schannel specific sign/seal.
496 ****************************************************************************/
498 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli,
499 struct ncacn_packet *pkt,
500 DATA_BLOB *pdu,
501 uint8 *p_ss_padding_len)
503 struct dcerpc_auth auth_info;
504 DATA_BLOB blob;
505 NTSTATUS status;
507 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
508 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
509 return NT_STATUS_OK;
512 if (pkt->auth_length < NL_AUTH_SIGNATURE_SIZE) {
513 DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length));
514 return NT_STATUS_INVALID_PARAMETER;
517 if (!cli->auth->a_u.schannel_auth) {
518 return NT_STATUS_INVALID_PARAMETER;
521 /* Ensure there's enough data for an authenticated response. */
522 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
523 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
524 + DCERPC_AUTH_TRAILER_LENGTH
525 + pkt->auth_length)) {
526 DEBUG(0, ("auth_len %u is too long.\n",
527 (unsigned int)pkt->auth_length));
528 return NT_STATUS_INVALID_PARAMETER;
531 /* get the auth blob at the end of the packet */
532 blob = data_blob_const(pdu->data + pkt->frag_length
533 - DCERPC_AUTH_TRAILER_LENGTH
534 - pkt->auth_length,
535 DCERPC_AUTH_TRAILER_LENGTH
536 + pkt->auth_length);
539 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
540 if (!NT_STATUS_IS_OK(status)) {
541 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
542 return status;
545 /* Ensure auth_pad_len fits into the packet. */
546 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
547 + auth_info.auth_pad_length
548 + DCERPC_AUTH_TRAILER_LENGTH
549 + pkt->auth_length) {
550 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
551 "too large (%u), auth_len (%u), frag_len = (%u).\n",
552 (unsigned int)auth_info.auth_pad_length,
553 (unsigned int)pkt->auth_length,
554 (unsigned int)pkt->frag_length));
555 return NT_STATUS_BUFFER_TOO_SMALL;
558 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
559 DEBUG(0, ("Invalid auth info %d on schannel\n",
560 auth_info.auth_type));
561 return NT_STATUS_BUFFER_TOO_SMALL;
564 if (DEBUGLEVEL >= 10) {
565 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_info.credentials);
568 switch (cli->auth->auth_level) {
569 case DCERPC_AUTH_LEVEL_PRIVACY:
570 status = netsec_incoming_packet(
571 cli->auth->a_u.schannel_auth,
572 talloc_tos(),
573 true,
574 pdu->data + DCERPC_RESPONSE_LENGTH,
575 pkt->frag_length
576 - DCERPC_RESPONSE_LENGTH
577 - DCERPC_AUTH_TRAILER_LENGTH
578 - pkt->auth_length,
579 &auth_info.credentials);
580 break;
581 case DCERPC_AUTH_LEVEL_INTEGRITY:
582 status = netsec_incoming_packet(
583 cli->auth->a_u.schannel_auth,
584 talloc_tos(),
585 false,
586 pdu->data + DCERPC_RESPONSE_LENGTH,
587 pkt->frag_length
588 - DCERPC_RESPONSE_LENGTH
589 - DCERPC_AUTH_TRAILER_LENGTH
590 - pkt->auth_length,
591 &auth_info.credentials);
592 break;
593 default:
594 status = NT_STATUS_INTERNAL_ERROR;
595 break;
598 if (!NT_STATUS_IS_OK(status)) {
599 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
600 "Connection to %s (%s).\n",
601 rpccli_pipe_txt(talloc_tos(), cli),
602 nt_errstr(status)));
603 return NT_STATUS_INVALID_PARAMETER;
607 * Remember the padding length. We must remove it from the real data
608 * stream once the sign/seal is done.
611 *p_ss_padding_len = auth_info.auth_pad_length;
613 return NT_STATUS_OK;
616 /****************************************************************************
617 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
618 ****************************************************************************/
620 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli,
621 struct ncacn_packet *pkt,
622 DATA_BLOB *pdu,
623 uint8 *p_ss_padding_len)
625 NTSTATUS ret = NT_STATUS_OK;
627 /* Paranioa checks for auth_len. */
628 if (pkt->auth_length) {
629 if (pkt->auth_length > pkt->frag_length) {
630 return NT_STATUS_INVALID_PARAMETER;
633 if ((pkt->auth_length
634 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
635 < pkt->auth_length) ||
636 (pkt->auth_length
637 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
638 < (unsigned int)DCERPC_AUTH_TRAILER_LENGTH)) {
639 /* Integer wrap attempt. */
640 return NT_STATUS_INVALID_PARAMETER;
645 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
648 switch(cli->auth->auth_type) {
649 case PIPE_AUTH_TYPE_NONE:
650 if (pkt->auth_length) {
651 DEBUG(3, ("cli_pipe_validate_rpc_response: "
652 "Connection to %s - got non-zero "
653 "auth len %u.\n",
654 rpccli_pipe_txt(talloc_tos(), cli),
655 (unsigned int)pkt->auth_length));
656 return NT_STATUS_INVALID_PARAMETER;
658 break;
660 case PIPE_AUTH_TYPE_NTLMSSP:
661 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
662 ret = cli_pipe_verify_ntlmssp(cli, pkt, pdu,
663 p_ss_padding_len);
664 if (!NT_STATUS_IS_OK(ret)) {
665 return ret;
667 break;
669 case PIPE_AUTH_TYPE_SCHANNEL:
670 ret = cli_pipe_verify_schannel(cli, pkt, pdu,
671 p_ss_padding_len);
672 if (!NT_STATUS_IS_OK(ret)) {
673 return ret;
675 break;
677 case PIPE_AUTH_TYPE_KRB5:
678 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
679 default:
680 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
681 "to %s - unknown internal auth type %u.\n",
682 rpccli_pipe_txt(talloc_tos(), cli),
683 cli->auth->auth_type ));
684 return NT_STATUS_INVALID_INFO_CLASS;
687 return NT_STATUS_OK;
690 /****************************************************************************
691 Do basic authentication checks on an incoming pdu.
692 ****************************************************************************/
694 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
695 struct rpc_pipe_client *cli,
696 struct ncacn_packet *pkt,
697 DATA_BLOB *pdu,
698 uint8_t expected_pkt_type,
699 DATA_BLOB *rdata,
700 DATA_BLOB *reply_pdu)
702 NTSTATUS ret = NT_STATUS_OK;
703 uint8 ss_padding_len = 0;
705 ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false);
706 if (!NT_STATUS_IS_OK(ret)) {
707 return ret;
710 if (pdu->length != pkt->frag_length) {
711 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
712 (unsigned int)pdu->length,
713 (unsigned int)pkt->frag_length));
714 return NT_STATUS_INVALID_PARAMETER;
718 * Point the return values at the real data including the RPC
719 * header. Just in case the caller wants it.
721 *rdata = *pdu;
723 /* Ensure we have the correct type. */
724 switch (pkt->ptype) {
725 case DCERPC_PKT_ALTER_RESP:
726 case DCERPC_PKT_BIND_ACK:
728 /* Alter context and bind ack share the same packet definitions. */
729 break;
732 case DCERPC_PKT_RESPONSE:
734 /* Here's where we deal with incoming sign/seal. */
735 ret = cli_pipe_validate_rpc_response(cli, pkt, pdu,
736 &ss_padding_len);
737 if (!NT_STATUS_IS_OK(ret)) {
738 return ret;
741 /* Point the return values at the NDR data.
742 * Remember to remove any ss padding. */
743 rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
745 if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
746 return NT_STATUS_BUFFER_TOO_SMALL;
749 rdata->length = pdu->length
750 - DCERPC_RESPONSE_LENGTH
751 - ss_padding_len;
753 /* Remember to remove the auth footer. */
754 if (pkt->auth_length) {
755 /* We've already done integer wrap tests on auth_len in
756 cli_pipe_validate_rpc_response(). */
757 if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH
758 + pkt->auth_length) {
759 return NT_STATUS_BUFFER_TOO_SMALL;
761 rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH
762 + pkt->auth_length);
765 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
766 (long unsigned int)pdu->length,
767 (long unsigned int)rdata->length,
768 (unsigned int)ss_padding_len));
771 * If this is the first reply, and the allocation hint is
772 * reasonable, try and set up the reply_pdu DATA_BLOB to the
773 * correct size.
776 if ((reply_pdu->length == 0) &&
777 pkt->u.response.alloc_hint &&
778 (pkt->u.response.alloc_hint < 15*1024*1024)) {
779 if (!data_blob_realloc(mem_ctx, reply_pdu,
780 pkt->u.response.alloc_hint)) {
781 DEBUG(0, ("reply alloc hint %d too "
782 "large to allocate\n",
783 (int)pkt->u.response.alloc_hint));
784 return NT_STATUS_NO_MEMORY;
788 break;
790 case DCERPC_PKT_BIND_NAK:
791 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
792 "received from %s!\n",
793 rpccli_pipe_txt(talloc_tos(), cli)));
794 /* Use this for now... */
795 return NT_STATUS_NETWORK_ACCESS_DENIED;
797 case DCERPC_PKT_FAULT:
799 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
800 "code %s received from %s!\n",
801 dcerpc_errstr(talloc_tos(),
802 pkt->u.fault.status),
803 rpccli_pipe_txt(talloc_tos(), cli)));
805 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
806 return NT_STATUS_UNSUCCESSFUL;
807 } else {
808 return NT_STATUS(pkt->u.fault.status);
811 default:
812 DEBUG(0, ("Unknown packet type %u received from %s!\n",
813 (unsigned int)pkt->ptype,
814 rpccli_pipe_txt(talloc_tos(), cli)));
815 return NT_STATUS_INVALID_INFO_CLASS;
818 if (pkt->ptype != expected_pkt_type) {
819 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
820 "got an unexpected RPC packet type - %u, not %u\n",
821 rpccli_pipe_txt(talloc_tos(), cli),
822 pkt->ptype,
823 expected_pkt_type));
824 return NT_STATUS_INVALID_INFO_CLASS;
827 /* Do this just before return - we don't want to modify any rpc header
828 data before now as we may have needed to do cryptographic actions on
829 it before. */
831 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
832 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
833 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
834 "setting fragment first/last ON.\n"));
835 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
836 DCERPC_PFC_FLAG_LAST;
839 return NT_STATUS_OK;
842 /****************************************************************************
843 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
844 ****************************************************************************/
846 struct cli_api_pipe_state {
847 struct event_context *ev;
848 struct rpc_cli_transport *transport;
849 uint8_t *rdata;
850 uint32_t rdata_len;
853 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
854 static void cli_api_pipe_write_done(struct tevent_req *subreq);
855 static void cli_api_pipe_read_done(struct tevent_req *subreq);
857 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
858 struct event_context *ev,
859 struct rpc_cli_transport *transport,
860 uint8_t *data, size_t data_len,
861 uint32_t max_rdata_len)
863 struct tevent_req *req, *subreq;
864 struct cli_api_pipe_state *state;
865 NTSTATUS status;
867 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
868 if (req == NULL) {
869 return NULL;
871 state->ev = ev;
872 state->transport = transport;
874 if (max_rdata_len < RPC_HEADER_LEN) {
876 * For a RPC reply we always need at least RPC_HEADER_LEN
877 * bytes. We check this here because we will receive
878 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
880 status = NT_STATUS_INVALID_PARAMETER;
881 goto post_status;
884 if (transport->trans_send != NULL) {
885 subreq = transport->trans_send(state, ev, data, data_len,
886 max_rdata_len, transport->priv);
887 if (subreq == NULL) {
888 goto fail;
890 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
891 return req;
895 * If the transport does not provide a "trans" routine, i.e. for
896 * example the ncacn_ip_tcp transport, do the write/read step here.
899 subreq = rpc_write_send(state, ev, transport, data, data_len);
900 if (subreq == NULL) {
901 goto fail;
903 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
904 return req;
906 post_status:
907 tevent_req_nterror(req, status);
908 return tevent_req_post(req, ev);
909 fail:
910 TALLOC_FREE(req);
911 return NULL;
914 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
916 struct tevent_req *req = tevent_req_callback_data(
917 subreq, struct tevent_req);
918 struct cli_api_pipe_state *state = tevent_req_data(
919 req, struct cli_api_pipe_state);
920 NTSTATUS status;
922 status = state->transport->trans_recv(subreq, state, &state->rdata,
923 &state->rdata_len);
924 TALLOC_FREE(subreq);
925 if (!NT_STATUS_IS_OK(status)) {
926 tevent_req_nterror(req, status);
927 return;
929 tevent_req_done(req);
932 static void cli_api_pipe_write_done(struct tevent_req *subreq)
934 struct tevent_req *req = tevent_req_callback_data(
935 subreq, struct tevent_req);
936 struct cli_api_pipe_state *state = tevent_req_data(
937 req, struct cli_api_pipe_state);
938 NTSTATUS status;
940 status = rpc_write_recv(subreq);
941 TALLOC_FREE(subreq);
942 if (!NT_STATUS_IS_OK(status)) {
943 tevent_req_nterror(req, status);
944 return;
947 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
948 if (tevent_req_nomem(state->rdata, req)) {
949 return;
953 * We don't need to use rpc_read_send here, the upper layer will cope
954 * with a short read, transport->trans_send could also return less
955 * than state->max_rdata_len.
957 subreq = state->transport->read_send(state, state->ev, state->rdata,
958 RPC_HEADER_LEN,
959 state->transport->priv);
960 if (tevent_req_nomem(subreq, req)) {
961 return;
963 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
966 static void cli_api_pipe_read_done(struct tevent_req *subreq)
968 struct tevent_req *req = tevent_req_callback_data(
969 subreq, struct tevent_req);
970 struct cli_api_pipe_state *state = tevent_req_data(
971 req, struct cli_api_pipe_state);
972 NTSTATUS status;
973 ssize_t received;
975 status = state->transport->read_recv(subreq, &received);
976 TALLOC_FREE(subreq);
977 if (!NT_STATUS_IS_OK(status)) {
978 tevent_req_nterror(req, status);
979 return;
981 state->rdata_len = received;
982 tevent_req_done(req);
985 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
986 uint8_t **prdata, uint32_t *prdata_len)
988 struct cli_api_pipe_state *state = tevent_req_data(
989 req, struct cli_api_pipe_state);
990 NTSTATUS status;
992 if (tevent_req_is_nterror(req, &status)) {
993 return status;
996 *prdata = talloc_move(mem_ctx, &state->rdata);
997 *prdata_len = state->rdata_len;
998 return NT_STATUS_OK;
1001 /****************************************************************************
1002 Send data on an rpc pipe via trans. The data must be the last
1003 pdu fragment of an NDR data stream.
1005 Receive response data from an rpc pipe, which may be large...
1007 Read the first fragment: unfortunately have to use SMBtrans for the first
1008 bit, then SMBreadX for subsequent bits.
1010 If first fragment received also wasn't the last fragment, continue
1011 getting fragments until we _do_ receive the last fragment.
1013 Request/Response PDU's look like the following...
1015 |<------------------PDU len----------------------------------------------->|
1016 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1018 +------------+-----------------+-------------+---------------+-------------+
1019 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1020 +------------+-----------------+-------------+---------------+-------------+
1022 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1023 signing & sealing being negotiated.
1025 ****************************************************************************/
1027 struct rpc_api_pipe_state {
1028 struct event_context *ev;
1029 struct rpc_pipe_client *cli;
1030 uint8_t expected_pkt_type;
1032 DATA_BLOB incoming_frag;
1033 struct ncacn_packet *pkt;
1035 /* Incoming reply */
1036 DATA_BLOB reply_pdu;
1037 size_t reply_pdu_offset;
1038 uint8_t endianess;
1041 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1042 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1044 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1045 struct event_context *ev,
1046 struct rpc_pipe_client *cli,
1047 DATA_BLOB *data, /* Outgoing PDU */
1048 uint8_t expected_pkt_type)
1050 struct tevent_req *req, *subreq;
1051 struct rpc_api_pipe_state *state;
1052 uint16_t max_recv_frag;
1053 NTSTATUS status;
1055 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1056 if (req == NULL) {
1057 return NULL;
1059 state->ev = ev;
1060 state->cli = cli;
1061 state->expected_pkt_type = expected_pkt_type;
1062 state->incoming_frag = data_blob_null;
1063 state->reply_pdu = data_blob_null;
1064 state->reply_pdu_offset = 0;
1065 state->endianess = DCERPC_DREP_LE;
1068 * Ensure we're not sending too much.
1070 if (data->length > cli->max_xmit_frag) {
1071 status = NT_STATUS_INVALID_PARAMETER;
1072 goto post_status;
1075 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1077 /* get the header first, then fetch the rest once we have
1078 * the frag_length available */
1079 max_recv_frag = RPC_HEADER_LEN;
1081 subreq = cli_api_pipe_send(state, ev, cli->transport,
1082 data->data, data->length, max_recv_frag);
1083 if (subreq == NULL) {
1084 goto fail;
1086 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1087 return req;
1089 post_status:
1090 tevent_req_nterror(req, status);
1091 return tevent_req_post(req, ev);
1092 fail:
1093 TALLOC_FREE(req);
1094 return NULL;
1097 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1099 struct tevent_req *req = tevent_req_callback_data(
1100 subreq, struct tevent_req);
1101 struct rpc_api_pipe_state *state = tevent_req_data(
1102 req, struct rpc_api_pipe_state);
1103 NTSTATUS status;
1104 uint8_t *rdata = NULL;
1105 uint32_t rdata_len = 0;
1107 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1108 TALLOC_FREE(subreq);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1111 tevent_req_nterror(req, status);
1112 return;
1115 if (rdata == NULL) {
1116 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1117 rpccli_pipe_txt(talloc_tos(), state->cli)));
1118 tevent_req_done(req);
1119 return;
1123 * Move data on state->incoming_frag.
1125 state->incoming_frag.data = talloc_move(state, &rdata);
1126 state->incoming_frag.length = rdata_len;
1127 if (!state->incoming_frag.data) {
1128 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1129 return;
1132 /* Ensure we have enough data for a pdu. */
1133 subreq = get_complete_frag_send(state, state->ev, state->cli,
1134 &state->incoming_frag);
1135 if (tevent_req_nomem(subreq, req)) {
1136 return;
1138 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1141 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1143 struct tevent_req *req = tevent_req_callback_data(
1144 subreq, struct tevent_req);
1145 struct rpc_api_pipe_state *state = tevent_req_data(
1146 req, struct rpc_api_pipe_state);
1147 NTSTATUS status;
1148 DATA_BLOB rdata = data_blob_null;
1150 status = get_complete_frag_recv(subreq);
1151 TALLOC_FREE(subreq);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 DEBUG(5, ("get_complete_frag failed: %s\n",
1154 nt_errstr(status)));
1155 tevent_req_nterror(req, status);
1156 return;
1159 state->pkt = talloc(state, struct ncacn_packet);
1160 if (!state->pkt) {
1161 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1162 return;
1165 status = cli_pipe_validate_current_pdu(state,
1166 state->cli, state->pkt,
1167 &state->incoming_frag,
1168 state->expected_pkt_type,
1169 &rdata,
1170 &state->reply_pdu);
1172 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1173 (unsigned)state->incoming_frag.length,
1174 (unsigned)state->reply_pdu_offset,
1175 nt_errstr(status)));
1177 if (!NT_STATUS_IS_OK(status)) {
1178 tevent_req_nterror(req, status);
1179 return;
1182 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1183 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1185 * Set the data type correctly for big-endian data on the
1186 * first packet.
1188 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1189 "big-endian.\n",
1190 rpccli_pipe_txt(talloc_tos(), state->cli)));
1191 state->endianess = 0x00; /* BIG ENDIAN */
1194 * Check endianness on subsequent packets.
1196 if (state->endianess != state->pkt->drep[0]) {
1197 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1198 "%s\n",
1199 state->endianess?"little":"big",
1200 state->pkt->drep[0]?"little":"big"));
1201 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 return;
1205 /* Now copy the data portion out of the pdu into rbuf. */
1206 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1207 if (!data_blob_realloc(NULL, &state->reply_pdu,
1208 state->reply_pdu_offset + rdata.length)) {
1209 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1210 return;
1214 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1215 rdata.data, rdata.length);
1216 state->reply_pdu_offset += rdata.length;
1218 /* reset state->incoming_frag, there is no need to free it,
1219 * it will be reallocated to the right size the next time
1220 * it is used */
1221 state->incoming_frag.length = 0;
1223 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1224 /* make sure the pdu length is right now that we
1225 * have all the data available (alloc hint may
1226 * have allocated more than was actually used) */
1227 state->reply_pdu.length = state->reply_pdu_offset;
1228 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1229 rpccli_pipe_txt(talloc_tos(), state->cli),
1230 (unsigned)state->reply_pdu.length));
1231 tevent_req_done(req);
1232 return;
1235 subreq = get_complete_frag_send(state, state->ev, state->cli,
1236 &state->incoming_frag);
1237 if (tevent_req_nomem(subreq, req)) {
1238 return;
1240 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1243 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1244 struct ncacn_packet **pkt,
1245 DATA_BLOB *reply_pdu)
1247 struct rpc_api_pipe_state *state = tevent_req_data(
1248 req, struct rpc_api_pipe_state);
1249 NTSTATUS status;
1251 if (tevent_req_is_nterror(req, &status)) {
1252 return status;
1255 /* return data to caller and assign it ownership of memory */
1256 if (reply_pdu) {
1257 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1258 reply_pdu->length = state->reply_pdu.length;
1259 state->reply_pdu.length = 0;
1260 } else {
1261 data_blob_free(&state->reply_pdu);
1264 if (pkt) {
1265 *pkt = talloc_steal(mem_ctx, state->pkt);
1268 return NT_STATUS_OK;
1271 /*******************************************************************
1272 Creates krb5 auth bind.
1273 ********************************************************************/
1275 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1276 enum dcerpc_AuthLevel auth_level,
1277 DATA_BLOB *auth_info)
1279 #ifdef HAVE_KRB5
1280 int ret;
1281 NTSTATUS status;
1282 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1283 DATA_BLOB tkt = data_blob_null;
1284 DATA_BLOB tkt_wrapped = data_blob_null;
1286 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1287 a->service_principal ));
1289 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1291 ret = cli_krb5_get_ticket(a, a->service_principal, 0,
1292 &tkt, &a->session_key,
1293 AP_OPTS_MUTUAL_REQUIRED, NULL,
1294 NULL, NULL);
1296 if (ret) {
1297 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1298 "failed with %s\n",
1299 a->service_principal,
1300 error_message(ret) ));
1302 data_blob_free(&tkt);
1303 return NT_STATUS_INVALID_PARAMETER;
1306 /* wrap that up in a nice GSS-API wrapping */
1307 tkt_wrapped = spnego_gen_krb5_wrap(talloc_tos(), tkt, TOK_ID_KRB_AP_REQ);
1309 data_blob_free(&tkt);
1311 status = dcerpc_push_dcerpc_auth(cli,
1312 DCERPC_AUTH_TYPE_KRB5,
1313 auth_level,
1314 0, /* auth_pad_length */
1315 1, /* auth_context_id */
1316 &tkt_wrapped,
1317 auth_info);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 data_blob_free(&tkt_wrapped);
1320 return status;
1323 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1324 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1326 return NT_STATUS_OK;
1327 #else
1328 return NT_STATUS_INVALID_PARAMETER;
1329 #endif
1332 /*******************************************************************
1333 Creates SPNEGO NTLMSSP auth bind.
1334 ********************************************************************/
1336 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1337 enum dcerpc_AuthLevel auth_level,
1338 DATA_BLOB *auth_info)
1340 NTSTATUS status;
1341 DATA_BLOB null_blob = data_blob_null;
1342 DATA_BLOB request = data_blob_null;
1343 DATA_BLOB spnego_msg = data_blob_null;
1344 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1346 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1347 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1348 null_blob,
1349 &request);
1351 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1352 data_blob_free(&request);
1353 return status;
1356 /* Wrap this in SPNEGO. */
1357 spnego_msg = spnego_gen_negTokenInit(talloc_tos(), OIDs_ntlm, &request, NULL);
1359 data_blob_free(&request);
1361 status = dcerpc_push_dcerpc_auth(cli,
1362 DCERPC_AUTH_TYPE_SPNEGO,
1363 auth_level,
1364 0, /* auth_pad_length */
1365 1, /* auth_context_id */
1366 &spnego_msg,
1367 auth_info);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 data_blob_free(&spnego_msg);
1371 return status;
1374 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1375 dump_data(5, spnego_msg.data, spnego_msg.length);
1376 data_blob_free(&spnego_msg);
1378 return NT_STATUS_OK;
1381 /*******************************************************************
1382 Creates NTLMSSP auth bind.
1383 ********************************************************************/
1385 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1386 enum dcerpc_AuthLevel auth_level,
1387 DATA_BLOB *auth_info)
1389 NTSTATUS status;
1390 DATA_BLOB null_blob = data_blob_null;
1391 DATA_BLOB request = data_blob_null;
1393 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1394 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1395 null_blob,
1396 &request);
1398 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1399 data_blob_free(&request);
1400 return status;
1403 status = dcerpc_push_dcerpc_auth(cli,
1404 DCERPC_AUTH_TYPE_NTLMSSP,
1405 auth_level,
1406 0, /* auth_pad_length */
1407 1, /* auth_context_id */
1408 &request,
1409 auth_info);
1410 if (!NT_STATUS_IS_OK(status)) {
1411 data_blob_free(&request);
1412 return status;
1415 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1416 dump_data(5, request.data, request.length);
1418 return NT_STATUS_OK;
1421 /*******************************************************************
1422 Creates schannel auth bind.
1423 ********************************************************************/
1425 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1426 enum dcerpc_AuthLevel auth_level,
1427 DATA_BLOB *auth_info)
1429 NTSTATUS status;
1430 struct NL_AUTH_MESSAGE r;
1431 DATA_BLOB schannel_blob;
1433 /* Use lp_workgroup() if domain not specified */
1435 if (!cli->auth->domain || !cli->auth->domain[0]) {
1436 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1437 if (cli->auth->domain == NULL) {
1438 return NT_STATUS_NO_MEMORY;
1443 * Now marshall the data into the auth parse_struct.
1446 r.MessageType = NL_NEGOTIATE_REQUEST;
1447 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1448 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1449 r.oem_netbios_domain.a = cli->auth->domain;
1450 r.oem_netbios_computer.a = global_myname();
1452 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1453 if (!NT_STATUS_IS_OK(status)) {
1454 return status;
1457 status = dcerpc_push_dcerpc_auth(cli,
1458 DCERPC_AUTH_TYPE_SCHANNEL,
1459 auth_level,
1460 0, /* auth_pad_length */
1461 1, /* auth_context_id */
1462 &schannel_blob,
1463 auth_info);
1464 if (!NT_STATUS_IS_OK(status)) {
1465 return status;
1468 return NT_STATUS_OK;
1471 /*******************************************************************
1472 Creates the internals of a DCE/RPC bind request or alter context PDU.
1473 ********************************************************************/
1475 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1476 enum dcerpc_pkt_type ptype,
1477 uint32 rpc_call_id,
1478 const struct ndr_syntax_id *abstract,
1479 const struct ndr_syntax_id *transfer,
1480 const DATA_BLOB *auth_info,
1481 DATA_BLOB *blob)
1483 uint16 auth_len = auth_info->length;
1484 NTSTATUS status;
1485 union dcerpc_payload u;
1486 struct dcerpc_ctx_list ctx_list;
1488 if (auth_len) {
1489 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1492 ctx_list.context_id = 0;
1493 ctx_list.num_transfer_syntaxes = 1;
1494 ctx_list.abstract_syntax = *abstract;
1495 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1497 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1498 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1499 u.bind.assoc_group_id = 0x0;
1500 u.bind.num_contexts = 1;
1501 u.bind.ctx_list = &ctx_list;
1502 u.bind.auth_info = *auth_info;
1504 status = dcerpc_push_ncacn_packet(mem_ctx,
1505 ptype,
1506 DCERPC_PFC_FLAG_FIRST |
1507 DCERPC_PFC_FLAG_LAST,
1508 auth_len,
1509 rpc_call_id,
1511 blob);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1514 return status;
1517 return NT_STATUS_OK;
1520 /*******************************************************************
1521 Creates a DCE/RPC bind request.
1522 ********************************************************************/
1524 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1525 struct rpc_pipe_client *cli,
1526 uint32 rpc_call_id,
1527 const struct ndr_syntax_id *abstract,
1528 const struct ndr_syntax_id *transfer,
1529 enum pipe_auth_type auth_type,
1530 enum dcerpc_AuthLevel auth_level,
1531 DATA_BLOB *rpc_out)
1533 DATA_BLOB auth_info = data_blob_null;
1534 NTSTATUS ret = NT_STATUS_OK;
1536 switch (auth_type) {
1537 case PIPE_AUTH_TYPE_SCHANNEL:
1538 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1539 if (!NT_STATUS_IS_OK(ret)) {
1540 return ret;
1542 break;
1544 case PIPE_AUTH_TYPE_NTLMSSP:
1545 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1546 if (!NT_STATUS_IS_OK(ret)) {
1547 return ret;
1549 break;
1551 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1552 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1553 if (!NT_STATUS_IS_OK(ret)) {
1554 return ret;
1556 break;
1558 case PIPE_AUTH_TYPE_KRB5:
1559 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1560 if (!NT_STATUS_IS_OK(ret)) {
1561 return ret;
1563 break;
1565 case PIPE_AUTH_TYPE_NONE:
1566 break;
1568 default:
1569 /* "Can't" happen. */
1570 return NT_STATUS_INVALID_INFO_CLASS;
1573 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1574 DCERPC_PKT_BIND,
1575 rpc_call_id,
1576 abstract,
1577 transfer,
1578 &auth_info,
1579 rpc_out);
1580 return ret;
1583 /*******************************************************************
1584 Create and add the NTLMSSP sign/seal auth header and data.
1585 ********************************************************************/
1587 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1588 uint32 ss_padding_len,
1589 DATA_BLOB *rpc_out)
1591 DATA_BLOB auth_info;
1592 NTSTATUS status;
1593 DATA_BLOB auth_blob = data_blob_null;
1594 uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
1596 if (!cli->auth->a_u.auth_ntlmssp_state) {
1597 return NT_STATUS_INVALID_PARAMETER;
1600 /* marshall the dcerpc_auth with an actually empty auth_blob.
1601 * this is needed because the ntmlssp signature includes the
1602 * auth header */
1603 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1604 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1605 cli->auth->auth_level,
1606 ss_padding_len,
1607 1 /* context id. */,
1608 &auth_blob,
1609 &auth_info);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return status;
1614 /* append the header */
1615 if (!data_blob_append(NULL, rpc_out,
1616 auth_info.data, auth_info.length)) {
1617 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1618 (unsigned int)auth_info.length));
1619 return NT_STATUS_NO_MEMORY;
1621 data_blob_free(&auth_info);
1623 switch (cli->auth->auth_level) {
1624 case DCERPC_AUTH_LEVEL_PRIVACY:
1625 /* Data portion is encrypted. */
1626 status = auth_ntlmssp_seal_packet(cli->auth->a_u.auth_ntlmssp_state,
1627 rpc_out->data,
1628 rpc_out->data
1629 + DCERPC_RESPONSE_LENGTH,
1630 data_and_pad_len,
1631 rpc_out->data,
1632 rpc_out->length,
1633 &auth_blob);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 return status;
1637 break;
1639 case DCERPC_AUTH_LEVEL_INTEGRITY:
1640 /* Data is signed. */
1641 status = auth_ntlmssp_sign_packet(cli->auth->a_u.auth_ntlmssp_state,
1642 rpc_out->data,
1643 rpc_out->data
1644 + DCERPC_RESPONSE_LENGTH,
1645 data_and_pad_len,
1646 rpc_out->data,
1647 rpc_out->length,
1648 &auth_blob);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 return status;
1652 break;
1654 default:
1655 /* Can't happen. */
1656 smb_panic("bad auth level");
1657 /* Notreached. */
1658 return NT_STATUS_INVALID_PARAMETER;
1661 /* Finally attach the blob. */
1662 if (!data_blob_append(NULL, rpc_out,
1663 auth_blob.data, auth_blob.length)) {
1664 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1665 (unsigned int)auth_info.length));
1666 return NT_STATUS_NO_MEMORY;
1668 data_blob_free(&auth_blob);
1670 return NT_STATUS_OK;
1673 /*******************************************************************
1674 Create and add the schannel sign/seal auth header and data.
1675 ********************************************************************/
1677 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1678 uint32 ss_padding_len,
1679 DATA_BLOB *rpc_out)
1681 DATA_BLOB auth_info;
1682 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1683 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
1684 size_t data_and_pad_len = rpc_out->length
1685 - DCERPC_RESPONSE_LENGTH;
1686 DATA_BLOB blob;
1687 NTSTATUS status;
1689 if (!sas) {
1690 return NT_STATUS_INVALID_PARAMETER;
1693 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1694 sas->seq_num));
1696 switch (cli->auth->auth_level) {
1697 case DCERPC_AUTH_LEVEL_PRIVACY:
1698 status = netsec_outgoing_packet(sas,
1699 rpc_out->data,
1700 true,
1701 data_p,
1702 data_and_pad_len,
1703 &blob);
1704 break;
1705 case DCERPC_AUTH_LEVEL_INTEGRITY:
1706 status = netsec_outgoing_packet(sas,
1707 rpc_out->data,
1708 false,
1709 data_p,
1710 data_and_pad_len,
1711 &blob);
1712 break;
1713 default:
1714 status = NT_STATUS_INTERNAL_ERROR;
1715 break;
1718 if (!NT_STATUS_IS_OK(status)) {
1719 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1720 nt_errstr(status)));
1721 return status;
1724 if (DEBUGLEVEL >= 10) {
1725 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1728 /* Finally marshall the blob. */
1729 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1730 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1731 cli->auth->auth_level,
1732 ss_padding_len,
1733 1 /* context id. */,
1734 &blob,
1735 &auth_info);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 return status;
1739 data_blob_free(&blob);
1741 if (!data_blob_append(NULL, rpc_out,
1742 auth_info.data, auth_info.length)) {
1743 return NT_STATUS_NO_MEMORY;
1745 data_blob_free(&auth_info);
1747 return NT_STATUS_OK;
1750 /*******************************************************************
1751 Calculate how much data we're going to send in this packet, also
1752 work out any sign/seal padding length.
1753 ********************************************************************/
1755 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1756 uint32 data_left,
1757 uint16 *p_frag_len,
1758 uint16 *p_auth_len,
1759 uint32 *p_ss_padding)
1761 uint32 data_space, data_len;
1763 #if 0
1764 if ((data_left > 0) && (sys_random() % 2)) {
1765 data_left = MAX(data_left/2, 1);
1767 #endif
1769 switch (cli->auth->auth_level) {
1770 case DCERPC_AUTH_LEVEL_NONE:
1771 case DCERPC_AUTH_LEVEL_CONNECT:
1772 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1773 data_len = MIN(data_space, data_left);
1774 *p_ss_padding = 0;
1775 *p_auth_len = 0;
1776 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1777 return data_len;
1779 case DCERPC_AUTH_LEVEL_INTEGRITY:
1780 case DCERPC_AUTH_LEVEL_PRIVACY:
1781 /* Treat the same for all authenticated rpc requests. */
1782 switch(cli->auth->auth_type) {
1783 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1784 case PIPE_AUTH_TYPE_NTLMSSP:
1785 *p_auth_len = NTLMSSP_SIG_SIZE;
1786 break;
1787 case PIPE_AUTH_TYPE_SCHANNEL:
1788 *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1789 break;
1790 default:
1791 smb_panic("bad auth type");
1792 break;
1795 data_space = cli->max_xmit_frag
1796 - DCERPC_REQUEST_LENGTH
1797 - DCERPC_AUTH_TRAILER_LENGTH
1798 - *p_auth_len;
1800 data_len = MIN(data_space, data_left);
1801 *p_ss_padding = 0;
1802 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1803 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1805 *p_frag_len = DCERPC_REQUEST_LENGTH
1806 + data_len + *p_ss_padding
1807 + DCERPC_AUTH_TRAILER_LENGTH
1808 + *p_auth_len;
1809 return data_len;
1811 default:
1812 smb_panic("bad auth level");
1813 /* Notreached. */
1814 return 0;
1818 /*******************************************************************
1819 External interface.
1820 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1821 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1822 and deals with signing/sealing details.
1823 ********************************************************************/
1825 struct rpc_api_pipe_req_state {
1826 struct event_context *ev;
1827 struct rpc_pipe_client *cli;
1828 uint8_t op_num;
1829 uint32_t call_id;
1830 DATA_BLOB *req_data;
1831 uint32_t req_data_sent;
1832 DATA_BLOB rpc_out;
1833 DATA_BLOB reply_pdu;
1836 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1837 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1838 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1839 bool *is_last_frag);
1841 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1842 struct event_context *ev,
1843 struct rpc_pipe_client *cli,
1844 uint8_t op_num,
1845 DATA_BLOB *req_data)
1847 struct tevent_req *req, *subreq;
1848 struct rpc_api_pipe_req_state *state;
1849 NTSTATUS status;
1850 bool is_last_frag;
1852 req = tevent_req_create(mem_ctx, &state,
1853 struct rpc_api_pipe_req_state);
1854 if (req == NULL) {
1855 return NULL;
1857 state->ev = ev;
1858 state->cli = cli;
1859 state->op_num = op_num;
1860 state->req_data = req_data;
1861 state->req_data_sent = 0;
1862 state->call_id = get_rpc_call_id();
1863 state->reply_pdu = data_blob_null;
1864 state->rpc_out = data_blob_null;
1866 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1867 + RPC_MAX_SIGN_SIZE) {
1868 /* Server is screwed up ! */
1869 status = NT_STATUS_INVALID_PARAMETER;
1870 goto post_status;
1873 status = prepare_next_frag(state, &is_last_frag);
1874 if (!NT_STATUS_IS_OK(status)) {
1875 goto post_status;
1878 if (is_last_frag) {
1879 subreq = rpc_api_pipe_send(state, ev, state->cli,
1880 &state->rpc_out,
1881 DCERPC_PKT_RESPONSE);
1882 if (subreq == NULL) {
1883 goto fail;
1885 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1886 } else {
1887 subreq = rpc_write_send(state, ev, cli->transport,
1888 state->rpc_out.data,
1889 state->rpc_out.length);
1890 if (subreq == NULL) {
1891 goto fail;
1893 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1894 req);
1896 return req;
1898 post_status:
1899 tevent_req_nterror(req, status);
1900 return tevent_req_post(req, ev);
1901 fail:
1902 TALLOC_FREE(req);
1903 return NULL;
1906 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1907 bool *is_last_frag)
1909 uint32_t data_sent_thistime;
1910 uint16_t auth_len;
1911 uint16_t frag_len;
1912 uint8_t flags = 0;
1913 uint32_t ss_padding;
1914 uint32_t data_left;
1915 char pad[8] = { 0, };
1916 NTSTATUS status;
1917 union dcerpc_payload u;
1919 data_left = state->req_data->length - state->req_data_sent;
1921 data_sent_thistime = calculate_data_len_tosend(
1922 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
1924 if (state->req_data_sent == 0) {
1925 flags = DCERPC_PFC_FLAG_FIRST;
1928 if (data_sent_thistime == data_left) {
1929 flags |= DCERPC_PFC_FLAG_LAST;
1932 data_blob_free(&state->rpc_out);
1934 ZERO_STRUCT(u.request);
1936 u.request.alloc_hint = state->req_data->length;
1937 u.request.context_id = 0;
1938 u.request.opnum = state->op_num;
1940 status = dcerpc_push_ncacn_packet(state,
1941 DCERPC_PKT_REQUEST,
1942 flags,
1943 auth_len,
1944 state->call_id,
1946 &state->rpc_out);
1947 if (!NT_STATUS_IS_OK(status)) {
1948 return status;
1951 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1952 * compute it right for requests */
1953 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1955 /* Copy in the data, plus any ss padding. */
1956 if (!data_blob_append(NULL, &state->rpc_out,
1957 state->req_data->data + state->req_data_sent,
1958 data_sent_thistime)) {
1959 return NT_STATUS_NO_MEMORY;
1962 if (ss_padding) {
1963 /* Copy the sign/seal padding data. */
1964 if (!data_blob_append(NULL, &state->rpc_out,
1965 pad, ss_padding)) {
1966 return NT_STATUS_NO_MEMORY;
1970 /* Generate any auth sign/seal and add the auth footer. */
1971 switch (state->cli->auth->auth_type) {
1972 case PIPE_AUTH_TYPE_NONE:
1973 status = NT_STATUS_OK;
1974 break;
1975 case PIPE_AUTH_TYPE_NTLMSSP:
1976 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1977 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
1978 &state->rpc_out);
1979 break;
1980 case PIPE_AUTH_TYPE_SCHANNEL:
1981 status = add_schannel_auth_footer(state->cli, ss_padding,
1982 &state->rpc_out);
1983 break;
1984 default:
1985 status = NT_STATUS_INVALID_PARAMETER;
1986 break;
1989 state->req_data_sent += data_sent_thistime;
1990 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1992 return status;
1995 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1997 struct tevent_req *req = tevent_req_callback_data(
1998 subreq, struct tevent_req);
1999 struct rpc_api_pipe_req_state *state = tevent_req_data(
2000 req, struct rpc_api_pipe_req_state);
2001 NTSTATUS status;
2002 bool is_last_frag;
2004 status = rpc_write_recv(subreq);
2005 TALLOC_FREE(subreq);
2006 if (!NT_STATUS_IS_OK(status)) {
2007 tevent_req_nterror(req, status);
2008 return;
2011 status = prepare_next_frag(state, &is_last_frag);
2012 if (!NT_STATUS_IS_OK(status)) {
2013 tevent_req_nterror(req, status);
2014 return;
2017 if (is_last_frag) {
2018 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2019 &state->rpc_out,
2020 DCERPC_PKT_RESPONSE);
2021 if (tevent_req_nomem(subreq, req)) {
2022 return;
2024 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2025 } else {
2026 subreq = rpc_write_send(state, state->ev,
2027 state->cli->transport,
2028 state->rpc_out.data,
2029 state->rpc_out.length);
2030 if (tevent_req_nomem(subreq, req)) {
2031 return;
2033 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2034 req);
2038 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2040 struct tevent_req *req = tevent_req_callback_data(
2041 subreq, struct tevent_req);
2042 struct rpc_api_pipe_req_state *state = tevent_req_data(
2043 req, struct rpc_api_pipe_req_state);
2044 NTSTATUS status;
2046 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2047 TALLOC_FREE(subreq);
2048 if (!NT_STATUS_IS_OK(status)) {
2049 tevent_req_nterror(req, status);
2050 return;
2052 tevent_req_done(req);
2055 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2056 DATA_BLOB *reply_pdu)
2058 struct rpc_api_pipe_req_state *state = tevent_req_data(
2059 req, struct rpc_api_pipe_req_state);
2060 NTSTATUS status;
2062 if (tevent_req_is_nterror(req, &status)) {
2064 * We always have to initialize to reply pdu, even if there is
2065 * none. The rpccli_* caller routines expect this.
2067 *reply_pdu = data_blob_null;
2068 return status;
2071 /* return data to caller and assign it ownership of memory */
2072 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2073 reply_pdu->length = state->reply_pdu.length;
2074 state->reply_pdu.length = 0;
2076 return NT_STATUS_OK;
2079 #if 0
2080 /****************************************************************************
2081 Set the handle state.
2082 ****************************************************************************/
2084 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2085 const char *pipe_name, uint16 device_state)
2087 bool state_set = False;
2088 char param[2];
2089 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2090 char *rparam = NULL;
2091 char *rdata = NULL;
2092 uint32 rparam_len, rdata_len;
2094 if (pipe_name == NULL)
2095 return False;
2097 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2098 cli->fnum, pipe_name, device_state));
2100 /* create parameters: device state */
2101 SSVAL(param, 0, device_state);
2103 /* create setup parameters. */
2104 setup[0] = 0x0001;
2105 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2107 /* send the data on \PIPE\ */
2108 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2109 setup, 2, 0, /* setup, length, max */
2110 param, 2, 0, /* param, length, max */
2111 NULL, 0, 1024, /* data, length, max */
2112 &rparam, &rparam_len, /* return param, length */
2113 &rdata, &rdata_len)) /* return data, length */
2115 DEBUG(5, ("Set Handle state: return OK\n"));
2116 state_set = True;
2119 SAFE_FREE(rparam);
2120 SAFE_FREE(rdata);
2122 return state_set;
2124 #endif
2126 /****************************************************************************
2127 Check the rpc bind acknowledge response.
2128 ****************************************************************************/
2130 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2131 const struct ndr_syntax_id *transfer)
2133 struct dcerpc_ack_ctx ctx;
2135 if (r->secondary_address_size == 0) {
2136 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2139 if (r->num_results < 1 || !r->ctx_list) {
2140 return false;
2143 ctx = r->ctx_list[0];
2145 /* check the transfer syntax */
2146 if ((ctx.syntax.if_version != transfer->if_version) ||
2147 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2148 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2149 return False;
2152 if (r->num_results != 0x1 || ctx.result != 0) {
2153 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2154 r->num_results, ctx.reason));
2157 DEBUG(5,("check_bind_response: accepted!\n"));
2158 return True;
2161 /*******************************************************************
2162 Creates a DCE/RPC bind authentication response.
2163 This is the packet that is sent back to the server once we
2164 have received a BIND-ACK, to finish the third leg of
2165 the authentication handshake.
2166 ********************************************************************/
2168 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
2169 struct rpc_pipe_client *cli,
2170 uint32 rpc_call_id,
2171 enum pipe_auth_type auth_type,
2172 enum dcerpc_AuthLevel auth_level,
2173 DATA_BLOB *pauth_blob,
2174 DATA_BLOB *rpc_out)
2176 NTSTATUS status;
2177 union dcerpc_payload u;
2179 u.auth3._pad = 0;
2181 status = dcerpc_push_dcerpc_auth(mem_ctx,
2182 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2183 auth_level,
2184 0, /* auth_pad_length */
2185 1, /* auth_context_id */
2186 pauth_blob,
2187 &u.auth3.auth_info);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 return status;
2192 status = dcerpc_push_ncacn_packet(mem_ctx,
2193 DCERPC_PKT_AUTH3,
2194 DCERPC_PFC_FLAG_FIRST |
2195 DCERPC_PFC_FLAG_LAST,
2196 pauth_blob->length,
2197 rpc_call_id,
2199 rpc_out);
2200 data_blob_free(&u.auth3.auth_info);
2201 if (!NT_STATUS_IS_OK(status)) {
2202 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2203 return status;
2206 return NT_STATUS_OK;
2209 /*******************************************************************
2210 Creates a DCE/RPC bind alter context authentication request which
2211 may contain a spnego auth blobl
2212 ********************************************************************/
2214 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2215 uint32 rpc_call_id,
2216 const struct ndr_syntax_id *abstract,
2217 const struct ndr_syntax_id *transfer,
2218 enum dcerpc_AuthLevel auth_level,
2219 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2220 DATA_BLOB *rpc_out)
2222 DATA_BLOB auth_info;
2223 NTSTATUS status;
2225 status = dcerpc_push_dcerpc_auth(mem_ctx,
2226 DCERPC_AUTH_TYPE_SPNEGO,
2227 auth_level,
2228 0, /* auth_pad_length */
2229 1, /* auth_context_id */
2230 pauth_blob,
2231 &auth_info);
2232 if (!NT_STATUS_IS_OK(status)) {
2233 return status;
2236 status = create_bind_or_alt_ctx_internal(mem_ctx,
2237 DCERPC_PKT_ALTER,
2238 rpc_call_id,
2239 abstract,
2240 transfer,
2241 &auth_info,
2242 rpc_out);
2243 data_blob_free(&auth_info);
2244 return status;
2247 /****************************************************************************
2248 Do an rpc bind.
2249 ****************************************************************************/
2251 struct rpc_pipe_bind_state {
2252 struct event_context *ev;
2253 struct rpc_pipe_client *cli;
2254 DATA_BLOB rpc_out;
2255 uint32_t rpc_call_id;
2258 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2259 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2260 struct rpc_pipe_bind_state *state,
2261 struct ncacn_packet *r);
2262 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2263 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2264 struct rpc_pipe_bind_state *state,
2265 struct ncacn_packet *r,
2266 DATA_BLOB *reply_pdu);
2267 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2269 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2270 struct event_context *ev,
2271 struct rpc_pipe_client *cli,
2272 struct pipe_auth_data *auth)
2274 struct tevent_req *req, *subreq;
2275 struct rpc_pipe_bind_state *state;
2276 NTSTATUS status;
2278 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2279 if (req == NULL) {
2280 return NULL;
2283 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2284 rpccli_pipe_txt(talloc_tos(), cli),
2285 (unsigned int)auth->auth_type,
2286 (unsigned int)auth->auth_level ));
2288 state->ev = ev;
2289 state->cli = cli;
2290 state->rpc_call_id = get_rpc_call_id();
2291 state->rpc_out = data_blob_null;
2293 cli->auth = talloc_move(cli, &auth);
2295 /* Marshall the outgoing data. */
2296 status = create_rpc_bind_req(state, cli,
2297 state->rpc_call_id,
2298 &cli->abstract_syntax,
2299 &cli->transfer_syntax,
2300 cli->auth->auth_type,
2301 cli->auth->auth_level,
2302 &state->rpc_out);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 goto post_status;
2308 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2309 DCERPC_PKT_BIND_ACK);
2310 if (subreq == NULL) {
2311 goto fail;
2313 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2314 return req;
2316 post_status:
2317 tevent_req_nterror(req, status);
2318 return tevent_req_post(req, ev);
2319 fail:
2320 TALLOC_FREE(req);
2321 return NULL;
2324 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2326 struct tevent_req *req = tevent_req_callback_data(
2327 subreq, struct tevent_req);
2328 struct rpc_pipe_bind_state *state = tevent_req_data(
2329 req, struct rpc_pipe_bind_state);
2330 DATA_BLOB reply_pdu;
2331 struct ncacn_packet *pkt;
2332 NTSTATUS status;
2334 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2335 TALLOC_FREE(subreq);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2338 rpccli_pipe_txt(talloc_tos(), state->cli),
2339 nt_errstr(status)));
2340 tevent_req_nterror(req, status);
2341 return;
2344 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2345 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2346 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2347 return;
2350 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2351 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2354 * For authenticated binds we may need to do 3 or 4 leg binds.
2357 switch(state->cli->auth->auth_type) {
2359 case PIPE_AUTH_TYPE_NONE:
2360 case PIPE_AUTH_TYPE_SCHANNEL:
2361 /* Bind complete. */
2362 tevent_req_done(req);
2363 break;
2365 case PIPE_AUTH_TYPE_NTLMSSP:
2366 /* Need to send AUTH3 packet - no reply. */
2367 status = rpc_finish_auth3_bind_send(req, state, pkt);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 tevent_req_nterror(req, status);
2371 break;
2373 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2374 /* Need to send alter context request and reply. */
2375 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2376 &reply_pdu);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 tevent_req_nterror(req, status);
2380 break;
2382 case PIPE_AUTH_TYPE_KRB5:
2383 /* */
2385 default:
2386 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2387 (unsigned int)state->cli->auth->auth_type));
2388 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2392 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2393 struct rpc_pipe_bind_state *state,
2394 struct ncacn_packet *r)
2396 DATA_BLOB client_reply = data_blob_null;
2397 struct dcerpc_auth auth;
2398 struct tevent_req *subreq;
2399 NTSTATUS status;
2401 if ((r->auth_length == 0)
2402 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2403 + r->auth_length)) {
2404 return NT_STATUS_INVALID_PARAMETER;
2407 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2408 &r->u.bind_ack.auth_info,
2409 &auth, false);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2412 nt_errstr(status)));
2413 return status;
2416 /* TODO - check auth_type/auth_level match. */
2418 status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
2419 auth.credentials, &client_reply);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2423 "blob failed: %s.\n", nt_errstr(status)));
2424 return status;
2427 data_blob_free(&state->rpc_out);
2429 status = create_rpc_bind_auth3(state,
2430 state->cli, state->rpc_call_id,
2431 state->cli->auth->auth_type,
2432 state->cli->auth->auth_level,
2433 &client_reply, &state->rpc_out);
2434 data_blob_free(&client_reply);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 return status;
2440 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2441 state->rpc_out.data, state->rpc_out.length);
2442 if (subreq == NULL) {
2443 return NT_STATUS_NO_MEMORY;
2445 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2446 return NT_STATUS_OK;
2449 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2451 struct tevent_req *req = tevent_req_callback_data(
2452 subreq, struct tevent_req);
2453 NTSTATUS status;
2455 status = rpc_write_recv(subreq);
2456 TALLOC_FREE(subreq);
2457 if (!NT_STATUS_IS_OK(status)) {
2458 tevent_req_nterror(req, status);
2459 return;
2461 tevent_req_done(req);
2464 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2465 struct rpc_pipe_bind_state *state,
2466 struct ncacn_packet *r,
2467 DATA_BLOB *reply_pdu)
2469 DATA_BLOB server_ntlm_response = data_blob_null;
2470 DATA_BLOB client_reply = data_blob_null;
2471 DATA_BLOB tmp_blob = data_blob_null;
2472 struct dcerpc_auth auth_info;
2473 DATA_BLOB auth_blob;
2474 struct tevent_req *subreq;
2475 NTSTATUS status;
2477 if ((r->auth_length == 0)
2478 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2479 + r->auth_length)) {
2480 return NT_STATUS_INVALID_PARAMETER;
2483 /* Process the returned NTLMSSP blob first. */
2484 auth_blob = data_blob_const(reply_pdu->data
2485 + r->frag_length
2486 - DCERPC_AUTH_TRAILER_LENGTH
2487 - r->auth_length,
2488 DCERPC_AUTH_TRAILER_LENGTH
2489 + r->auth_length);
2491 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2494 return status;
2498 * The server might give us back two challenges - tmp_blob is for the
2499 * second.
2501 if (!spnego_parse_challenge(state, auth_info.credentials,
2502 &server_ntlm_response, &tmp_blob)) {
2503 data_blob_free(&server_ntlm_response);
2504 data_blob_free(&tmp_blob);
2505 return NT_STATUS_INVALID_PARAMETER;
2508 /* We're finished with the server spnego response and the tmp_blob. */
2509 data_blob_free(&tmp_blob);
2511 status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
2512 server_ntlm_response, &client_reply);
2514 /* Finished with the server_ntlm response */
2515 data_blob_free(&server_ntlm_response);
2517 if (!NT_STATUS_IS_OK(status)) {
2518 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2519 "using server blob failed.\n"));
2520 data_blob_free(&client_reply);
2521 return status;
2524 /* SPNEGO wrap the client reply. */
2525 tmp_blob = spnego_gen_auth(state, client_reply);
2526 data_blob_free(&client_reply);
2527 client_reply = tmp_blob;
2528 tmp_blob = data_blob_null;
2530 /* Now prepare the alter context pdu. */
2531 data_blob_free(&state->rpc_out);
2533 status = create_rpc_alter_context(state,
2534 state->rpc_call_id,
2535 &state->cli->abstract_syntax,
2536 &state->cli->transfer_syntax,
2537 state->cli->auth->auth_level,
2538 &client_reply,
2539 &state->rpc_out);
2540 data_blob_free(&client_reply);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 return status;
2546 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2547 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2548 if (subreq == NULL) {
2549 return NT_STATUS_NO_MEMORY;
2551 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2552 return NT_STATUS_OK;
2555 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2557 struct tevent_req *req = tevent_req_callback_data(
2558 subreq, struct tevent_req);
2559 struct rpc_pipe_bind_state *state = tevent_req_data(
2560 req, struct rpc_pipe_bind_state);
2561 DATA_BLOB tmp_blob = data_blob_null;
2562 struct ncacn_packet *pkt;
2563 struct dcerpc_auth auth;
2564 NTSTATUS status;
2566 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2567 TALLOC_FREE(subreq);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 tevent_req_nterror(req, status);
2570 return;
2573 status = dcerpc_pull_dcerpc_auth(pkt,
2574 &pkt->u.alter_resp.auth_info,
2575 &auth, false);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 tevent_req_nterror(req, status);
2578 return;
2581 /* Check we got a valid auth response. */
2582 if (!spnego_parse_auth_response(talloc_tos(), auth.credentials,
2583 NT_STATUS_OK,
2584 OID_NTLMSSP, &tmp_blob)) {
2585 data_blob_free(&tmp_blob);
2586 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2587 return;
2590 data_blob_free(&tmp_blob);
2592 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2593 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2594 tevent_req_done(req);
2597 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2599 return tevent_req_simple_recv_ntstatus(req);
2602 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2603 struct pipe_auth_data *auth)
2605 TALLOC_CTX *frame = talloc_stackframe();
2606 struct event_context *ev;
2607 struct tevent_req *req;
2608 NTSTATUS status = NT_STATUS_OK;
2610 ev = event_context_init(frame);
2611 if (ev == NULL) {
2612 status = NT_STATUS_NO_MEMORY;
2613 goto fail;
2616 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2617 if (req == NULL) {
2618 status = NT_STATUS_NO_MEMORY;
2619 goto fail;
2622 if (!tevent_req_poll(req, ev)) {
2623 status = map_nt_error_from_unix(errno);
2624 goto fail;
2627 status = rpc_pipe_bind_recv(req);
2628 fail:
2629 TALLOC_FREE(frame);
2630 return status;
2633 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2635 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2636 unsigned int timeout)
2638 unsigned int old;
2640 if (rpc_cli->transport == NULL) {
2641 return RPCCLI_DEFAULT_TIMEOUT;
2644 if (rpc_cli->transport->set_timeout == NULL) {
2645 return RPCCLI_DEFAULT_TIMEOUT;
2648 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2649 if (old == 0) {
2650 return RPCCLI_DEFAULT_TIMEOUT;
2653 return old;
2656 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2658 if (rpc_cli == NULL) {
2659 return false;
2662 if (rpc_cli->transport == NULL) {
2663 return false;
2666 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2669 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2671 struct cli_state *cli;
2673 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2674 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2675 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(rpc_cli->auth->a_u.auth_ntlmssp_state), 16);
2676 return true;
2679 cli = rpc_pipe_np_smb_conn(rpc_cli);
2680 if (cli == NULL) {
2681 return false;
2683 E_md4hash(cli->password ? cli->password : "", nt_hash);
2684 return true;
2687 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2688 struct pipe_auth_data **presult)
2690 struct pipe_auth_data *result;
2692 result = talloc(mem_ctx, struct pipe_auth_data);
2693 if (result == NULL) {
2694 return NT_STATUS_NO_MEMORY;
2697 result->auth_type = PIPE_AUTH_TYPE_NONE;
2698 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2700 result->user_name = talloc_strdup(result, "");
2701 result->domain = talloc_strdup(result, "");
2702 if ((result->user_name == NULL) || (result->domain == NULL)) {
2703 TALLOC_FREE(result);
2704 return NT_STATUS_NO_MEMORY;
2707 *presult = result;
2708 return NT_STATUS_OK;
2711 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2713 TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2714 return 0;
2717 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2718 enum pipe_auth_type auth_type,
2719 enum dcerpc_AuthLevel auth_level,
2720 const char *domain,
2721 const char *username,
2722 const char *password,
2723 struct pipe_auth_data **presult)
2725 struct pipe_auth_data *result;
2726 NTSTATUS status;
2728 result = talloc(mem_ctx, struct pipe_auth_data);
2729 if (result == NULL) {
2730 return NT_STATUS_NO_MEMORY;
2733 result->auth_type = auth_type;
2734 result->auth_level = auth_level;
2736 result->user_name = talloc_strdup(result, username);
2737 result->domain = talloc_strdup(result, domain);
2738 if ((result->user_name == NULL) || (result->domain == NULL)) {
2739 status = NT_STATUS_NO_MEMORY;
2740 goto fail;
2743 status = auth_ntlmssp_client_start(NULL,
2744 global_myname(),
2745 lp_workgroup(),
2746 lp_client_ntlmv2_auth(),
2747 &result->a_u.auth_ntlmssp_state);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 goto fail;
2752 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2754 status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2755 username);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 goto fail;
2760 status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2761 domain);
2762 if (!NT_STATUS_IS_OK(status)) {
2763 goto fail;
2766 status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2767 password);
2768 if (!NT_STATUS_IS_OK(status)) {
2769 goto fail;
2773 * Turn off sign+seal to allow selected auth level to turn it back on.
2775 auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2776 ~(NTLMSSP_NEGOTIATE_SIGN |
2777 NTLMSSP_NEGOTIATE_SEAL));
2779 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2780 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2781 NTLMSSP_NEGOTIATE_SIGN);
2782 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2783 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2784 NTLMSSP_NEGOTIATE_SEAL |
2785 NTLMSSP_NEGOTIATE_SIGN);
2788 *presult = result;
2789 return NT_STATUS_OK;
2791 fail:
2792 TALLOC_FREE(result);
2793 return status;
2796 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2797 enum dcerpc_AuthLevel auth_level,
2798 struct netlogon_creds_CredentialState *creds,
2799 struct pipe_auth_data **presult)
2801 struct pipe_auth_data *result;
2803 result = talloc(mem_ctx, struct pipe_auth_data);
2804 if (result == NULL) {
2805 return NT_STATUS_NO_MEMORY;
2808 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2809 result->auth_level = auth_level;
2811 result->user_name = talloc_strdup(result, "");
2812 result->domain = talloc_strdup(result, domain);
2813 if ((result->user_name == NULL) || (result->domain == NULL)) {
2814 goto fail;
2817 result->a_u.schannel_auth = talloc(result, struct schannel_state);
2818 if (result->a_u.schannel_auth == NULL) {
2819 goto fail;
2822 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2823 result->a_u.schannel_auth->seq_num = 0;
2824 result->a_u.schannel_auth->initiator = true;
2825 result->a_u.schannel_auth->creds = creds;
2827 *presult = result;
2828 return NT_STATUS_OK;
2830 fail:
2831 TALLOC_FREE(result);
2832 return NT_STATUS_NO_MEMORY;
2835 #ifdef HAVE_KRB5
2836 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2838 data_blob_free(&auth->session_key);
2839 return 0;
2841 #endif
2843 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2844 enum dcerpc_AuthLevel auth_level,
2845 const char *service_princ,
2846 const char *username,
2847 const char *password,
2848 struct pipe_auth_data **presult)
2850 #ifdef HAVE_KRB5
2851 struct pipe_auth_data *result;
2853 if ((username != NULL) && (password != NULL)) {
2854 int ret = kerberos_kinit_password(username, password, 0, NULL);
2855 if (ret != 0) {
2856 return NT_STATUS_ACCESS_DENIED;
2860 result = talloc(mem_ctx, struct pipe_auth_data);
2861 if (result == NULL) {
2862 return NT_STATUS_NO_MEMORY;
2865 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2866 result->auth_level = auth_level;
2869 * Username / domain need fixing!
2871 result->user_name = talloc_strdup(result, "");
2872 result->domain = talloc_strdup(result, "");
2873 if ((result->user_name == NULL) || (result->domain == NULL)) {
2874 goto fail;
2877 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2878 result, struct kerberos_auth_struct);
2879 if (result->a_u.kerberos_auth == NULL) {
2880 goto fail;
2882 talloc_set_destructor(result->a_u.kerberos_auth,
2883 cli_auth_kerberos_data_destructor);
2885 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2886 result, service_princ);
2887 if (result->a_u.kerberos_auth->service_principal == NULL) {
2888 goto fail;
2891 *presult = result;
2892 return NT_STATUS_OK;
2894 fail:
2895 TALLOC_FREE(result);
2896 return NT_STATUS_NO_MEMORY;
2897 #else
2898 return NT_STATUS_NOT_SUPPORTED;
2899 #endif
2903 * Create an rpc pipe client struct, connecting to a tcp port.
2905 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2906 uint16_t port,
2907 const struct ndr_syntax_id *abstract_syntax,
2908 struct rpc_pipe_client **presult)
2910 struct rpc_pipe_client *result;
2911 struct sockaddr_storage addr;
2912 NTSTATUS status;
2913 int fd;
2915 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2916 if (result == NULL) {
2917 return NT_STATUS_NO_MEMORY;
2920 result->abstract_syntax = *abstract_syntax;
2921 result->transfer_syntax = ndr_transfer_syntax;
2922 result->dispatch = cli_do_rpc_ndr;
2923 result->dispatch_send = cli_do_rpc_ndr_send;
2924 result->dispatch_recv = cli_do_rpc_ndr_recv;
2926 result->desthost = talloc_strdup(result, host);
2927 result->srv_name_slash = talloc_asprintf_strupper_m(
2928 result, "\\\\%s", result->desthost);
2929 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2930 status = NT_STATUS_NO_MEMORY;
2931 goto fail;
2934 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2935 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2937 if (!resolve_name(host, &addr, 0, false)) {
2938 status = NT_STATUS_NOT_FOUND;
2939 goto fail;
2942 status = open_socket_out(&addr, port, 60, &fd);
2943 if (!NT_STATUS_IS_OK(status)) {
2944 goto fail;
2946 set_socket_options(fd, lp_socket_options());
2948 status = rpc_transport_sock_init(result, fd, &result->transport);
2949 if (!NT_STATUS_IS_OK(status)) {
2950 close(fd);
2951 goto fail;
2954 result->transport->transport = NCACN_IP_TCP;
2956 *presult = result;
2957 return NT_STATUS_OK;
2959 fail:
2960 TALLOC_FREE(result);
2961 return status;
2965 * Determine the tcp port on which a dcerpc interface is listening
2966 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2967 * target host.
2969 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2970 const struct ndr_syntax_id *abstract_syntax,
2971 uint16_t *pport)
2973 NTSTATUS status;
2974 struct rpc_pipe_client *epm_pipe = NULL;
2975 struct pipe_auth_data *auth = NULL;
2976 struct dcerpc_binding *map_binding = NULL;
2977 struct dcerpc_binding *res_binding = NULL;
2978 struct epm_twr_t *map_tower = NULL;
2979 struct epm_twr_t *res_towers = NULL;
2980 struct policy_handle *entry_handle = NULL;
2981 uint32_t num_towers = 0;
2982 uint32_t max_towers = 1;
2983 struct epm_twr_p_t towers;
2984 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2986 if (pport == NULL) {
2987 status = NT_STATUS_INVALID_PARAMETER;
2988 goto done;
2991 /* open the connection to the endpoint mapper */
2992 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2993 &ndr_table_epmapper.syntax_id,
2994 &epm_pipe);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 goto done;
3000 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 goto done;
3005 status = rpc_pipe_bind(epm_pipe, auth);
3006 if (!NT_STATUS_IS_OK(status)) {
3007 goto done;
3010 /* create tower for asking the epmapper */
3012 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3013 if (map_binding == NULL) {
3014 status = NT_STATUS_NO_MEMORY;
3015 goto done;
3018 map_binding->transport = NCACN_IP_TCP;
3019 map_binding->object = *abstract_syntax;
3020 map_binding->host = host; /* needed? */
3021 map_binding->endpoint = "0"; /* correct? needed? */
3023 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3024 if (map_tower == NULL) {
3025 status = NT_STATUS_NO_MEMORY;
3026 goto done;
3029 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3030 &(map_tower->tower));
3031 if (!NT_STATUS_IS_OK(status)) {
3032 goto done;
3035 /* allocate further parameters for the epm_Map call */
3037 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3038 if (res_towers == NULL) {
3039 status = NT_STATUS_NO_MEMORY;
3040 goto done;
3042 towers.twr = res_towers;
3044 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3045 if (entry_handle == NULL) {
3046 status = NT_STATUS_NO_MEMORY;
3047 goto done;
3050 /* ask the endpoint mapper for the port */
3052 status = rpccli_epm_Map(epm_pipe,
3053 tmp_ctx,
3054 CONST_DISCARD(struct GUID *,
3055 &(abstract_syntax->uuid)),
3056 map_tower,
3057 entry_handle,
3058 max_towers,
3059 &num_towers,
3060 &towers);
3062 if (!NT_STATUS_IS_OK(status)) {
3063 goto done;
3066 if (num_towers != 1) {
3067 status = NT_STATUS_UNSUCCESSFUL;
3068 goto done;
3071 /* extract the port from the answer */
3073 status = dcerpc_binding_from_tower(tmp_ctx,
3074 &(towers.twr->tower),
3075 &res_binding);
3076 if (!NT_STATUS_IS_OK(status)) {
3077 goto done;
3080 /* are further checks here necessary? */
3081 if (res_binding->transport != NCACN_IP_TCP) {
3082 status = NT_STATUS_UNSUCCESSFUL;
3083 goto done;
3086 *pport = (uint16_t)atoi(res_binding->endpoint);
3088 done:
3089 TALLOC_FREE(tmp_ctx);
3090 return status;
3094 * Create a rpc pipe client struct, connecting to a host via tcp.
3095 * The port is determined by asking the endpoint mapper on the given
3096 * host.
3098 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3099 const struct ndr_syntax_id *abstract_syntax,
3100 struct rpc_pipe_client **presult)
3102 NTSTATUS status;
3103 uint16_t port = 0;
3105 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 return status;
3110 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3111 abstract_syntax, presult);
3114 /********************************************************************
3115 Create a rpc pipe client struct, connecting to a unix domain socket
3116 ********************************************************************/
3117 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3118 const struct ndr_syntax_id *abstract_syntax,
3119 struct rpc_pipe_client **presult)
3121 struct rpc_pipe_client *result;
3122 struct sockaddr_un addr;
3123 NTSTATUS status;
3124 int fd;
3126 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3127 if (result == NULL) {
3128 return NT_STATUS_NO_MEMORY;
3131 result->abstract_syntax = *abstract_syntax;
3132 result->transfer_syntax = ndr_transfer_syntax;
3133 result->dispatch = cli_do_rpc_ndr;
3134 result->dispatch_send = cli_do_rpc_ndr_send;
3135 result->dispatch_recv = cli_do_rpc_ndr_recv;
3137 result->desthost = get_myname(result);
3138 result->srv_name_slash = talloc_asprintf_strupper_m(
3139 result, "\\\\%s", result->desthost);
3140 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3141 status = NT_STATUS_NO_MEMORY;
3142 goto fail;
3145 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3146 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3148 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3149 if (fd == -1) {
3150 status = map_nt_error_from_unix(errno);
3151 goto fail;
3154 ZERO_STRUCT(addr);
3155 addr.sun_family = AF_UNIX;
3156 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3158 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3159 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3160 strerror(errno)));
3161 close(fd);
3162 return map_nt_error_from_unix(errno);
3165 status = rpc_transport_sock_init(result, fd, &result->transport);
3166 if (!NT_STATUS_IS_OK(status)) {
3167 close(fd);
3168 goto fail;
3171 result->transport->transport = NCALRPC;
3173 *presult = result;
3174 return NT_STATUS_OK;
3176 fail:
3177 TALLOC_FREE(result);
3178 return status;
3181 struct rpc_pipe_client_np_ref {
3182 struct cli_state *cli;
3183 struct rpc_pipe_client *pipe;
3186 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3188 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3189 return 0;
3192 /****************************************************************************
3193 Open a named pipe over SMB to a remote server.
3195 * CAVEAT CALLER OF THIS FUNCTION:
3196 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3197 * so be sure that this function is called AFTER any structure (vs pointer)
3198 * assignment of the cli. In particular, libsmbclient does structure
3199 * assignments of cli, which invalidates the data in the returned
3200 * rpc_pipe_client if this function is called before the structure assignment
3201 * of cli.
3203 ****************************************************************************/
3205 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3206 const struct ndr_syntax_id *abstract_syntax,
3207 struct rpc_pipe_client **presult)
3209 struct rpc_pipe_client *result;
3210 NTSTATUS status;
3211 struct rpc_pipe_client_np_ref *np_ref;
3213 /* sanity check to protect against crashes */
3215 if ( !cli ) {
3216 return NT_STATUS_INVALID_HANDLE;
3219 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3220 if (result == NULL) {
3221 return NT_STATUS_NO_MEMORY;
3224 result->abstract_syntax = *abstract_syntax;
3225 result->transfer_syntax = ndr_transfer_syntax;
3226 result->dispatch = cli_do_rpc_ndr;
3227 result->dispatch_send = cli_do_rpc_ndr_send;
3228 result->dispatch_recv = cli_do_rpc_ndr_recv;
3229 result->desthost = talloc_strdup(result, cli->desthost);
3230 result->srv_name_slash = talloc_asprintf_strupper_m(
3231 result, "\\\\%s", result->desthost);
3233 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3234 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3236 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3237 TALLOC_FREE(result);
3238 return NT_STATUS_NO_MEMORY;
3241 status = rpc_transport_np_init(result, cli, abstract_syntax,
3242 &result->transport);
3243 if (!NT_STATUS_IS_OK(status)) {
3244 TALLOC_FREE(result);
3245 return status;
3248 result->transport->transport = NCACN_NP;
3250 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3251 if (np_ref == NULL) {
3252 TALLOC_FREE(result);
3253 return NT_STATUS_NO_MEMORY;
3255 np_ref->cli = cli;
3256 np_ref->pipe = result;
3258 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3259 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3261 *presult = result;
3262 return NT_STATUS_OK;
3265 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3266 struct rpc_cli_smbd_conn *conn,
3267 const struct ndr_syntax_id *syntax,
3268 struct rpc_pipe_client **presult)
3270 struct rpc_pipe_client *result;
3271 struct pipe_auth_data *auth;
3272 NTSTATUS status;
3274 result = talloc(mem_ctx, struct rpc_pipe_client);
3275 if (result == NULL) {
3276 return NT_STATUS_NO_MEMORY;
3278 result->abstract_syntax = *syntax;
3279 result->transfer_syntax = ndr_transfer_syntax;
3280 result->dispatch = cli_do_rpc_ndr;
3281 result->dispatch_send = cli_do_rpc_ndr_send;
3282 result->dispatch_recv = cli_do_rpc_ndr_recv;
3283 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3284 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3286 result->desthost = talloc_strdup(result, global_myname());
3287 result->srv_name_slash = talloc_asprintf_strupper_m(
3288 result, "\\\\%s", global_myname());
3289 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3290 TALLOC_FREE(result);
3291 return NT_STATUS_NO_MEMORY;
3294 status = rpc_transport_smbd_init(result, conn, syntax,
3295 &result->transport);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3298 nt_errstr(status)));
3299 TALLOC_FREE(result);
3300 return status;
3303 status = rpccli_anon_bind_data(result, &auth);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3306 nt_errstr(status)));
3307 TALLOC_FREE(result);
3308 return status;
3311 status = rpc_pipe_bind(result, auth);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3314 TALLOC_FREE(result);
3315 return status;
3318 result->transport->transport = NCACN_INTERNAL;
3320 *presult = result;
3321 return NT_STATUS_OK;
3324 /****************************************************************************
3325 Open a pipe to a remote server.
3326 ****************************************************************************/
3328 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3329 enum dcerpc_transport_t transport,
3330 const struct ndr_syntax_id *interface,
3331 struct rpc_pipe_client **presult)
3333 switch (transport) {
3334 case NCACN_IP_TCP:
3335 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3336 presult);
3337 case NCACN_NP:
3338 return rpc_pipe_open_np(cli, interface, presult);
3339 default:
3340 return NT_STATUS_NOT_IMPLEMENTED;
3344 /****************************************************************************
3345 Open a named pipe to an SMB server and bind anonymously.
3346 ****************************************************************************/
3348 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3349 enum dcerpc_transport_t transport,
3350 const struct ndr_syntax_id *interface,
3351 struct rpc_pipe_client **presult)
3353 struct rpc_pipe_client *result;
3354 struct pipe_auth_data *auth;
3355 NTSTATUS status;
3357 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3358 if (!NT_STATUS_IS_OK(status)) {
3359 return status;
3362 status = rpccli_anon_bind_data(result, &auth);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3365 nt_errstr(status)));
3366 TALLOC_FREE(result);
3367 return status;
3371 * This is a bit of an abstraction violation due to the fact that an
3372 * anonymous bind on an authenticated SMB inherits the user/domain
3373 * from the enclosing SMB creds
3376 TALLOC_FREE(auth->user_name);
3377 TALLOC_FREE(auth->domain);
3379 auth->user_name = talloc_strdup(auth, cli->user_name);
3380 auth->domain = talloc_strdup(auth, cli->domain);
3381 auth->user_session_key = data_blob_talloc(auth,
3382 cli->user_session_key.data,
3383 cli->user_session_key.length);
3385 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3386 TALLOC_FREE(result);
3387 return NT_STATUS_NO_MEMORY;
3390 status = rpc_pipe_bind(result, auth);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 int lvl = 0;
3393 if (ndr_syntax_id_equal(interface,
3394 &ndr_table_dssetup.syntax_id)) {
3395 /* non AD domains just don't have this pipe, avoid
3396 * level 0 statement in that case - gd */
3397 lvl = 3;
3399 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3400 "%s failed with error %s\n",
3401 get_pipe_name_from_syntax(talloc_tos(), interface),
3402 nt_errstr(status) ));
3403 TALLOC_FREE(result);
3404 return status;
3407 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3408 "%s and bound anonymously.\n",
3409 get_pipe_name_from_syntax(talloc_tos(), interface),
3410 cli->desthost));
3412 *presult = result;
3413 return NT_STATUS_OK;
3416 /****************************************************************************
3417 ****************************************************************************/
3419 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3420 const struct ndr_syntax_id *interface,
3421 struct rpc_pipe_client **presult)
3423 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3424 interface, presult);
3427 /****************************************************************************
3428 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3429 ****************************************************************************/
3431 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3432 const struct ndr_syntax_id *interface,
3433 enum dcerpc_transport_t transport,
3434 enum pipe_auth_type auth_type,
3435 enum dcerpc_AuthLevel auth_level,
3436 const char *domain,
3437 const char *username,
3438 const char *password,
3439 struct rpc_pipe_client **presult)
3441 struct rpc_pipe_client *result;
3442 struct pipe_auth_data *auth;
3443 NTSTATUS status;
3445 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3446 if (!NT_STATUS_IS_OK(status)) {
3447 return status;
3450 status = rpccli_ntlmssp_bind_data(
3451 result, auth_type, auth_level, domain, username,
3452 password, &auth);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3455 nt_errstr(status)));
3456 goto err;
3459 status = rpc_pipe_bind(result, auth);
3460 if (!NT_STATUS_IS_OK(status)) {
3461 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3462 nt_errstr(status) ));
3463 goto err;
3466 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3467 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3468 get_pipe_name_from_syntax(talloc_tos(), interface),
3469 cli->desthost, domain, username ));
3471 *presult = result;
3472 return NT_STATUS_OK;
3474 err:
3476 TALLOC_FREE(result);
3477 return status;
3480 /****************************************************************************
3481 External interface.
3482 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3483 ****************************************************************************/
3485 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3486 const struct ndr_syntax_id *interface,
3487 enum dcerpc_transport_t transport,
3488 enum dcerpc_AuthLevel auth_level,
3489 const char *domain,
3490 const char *username,
3491 const char *password,
3492 struct rpc_pipe_client **presult)
3494 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3495 interface,
3496 transport,
3497 PIPE_AUTH_TYPE_NTLMSSP,
3498 auth_level,
3499 domain,
3500 username,
3501 password,
3502 presult);
3505 /****************************************************************************
3506 External interface.
3507 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3508 ****************************************************************************/
3510 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3511 const struct ndr_syntax_id *interface,
3512 enum dcerpc_transport_t transport,
3513 enum dcerpc_AuthLevel auth_level,
3514 const char *domain,
3515 const char *username,
3516 const char *password,
3517 struct rpc_pipe_client **presult)
3519 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3520 interface,
3521 transport,
3522 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3523 auth_level,
3524 domain,
3525 username,
3526 password,
3527 presult);
3530 /****************************************************************************
3531 Get a the schannel session key out of an already opened netlogon pipe.
3532 ****************************************************************************/
3533 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3534 struct cli_state *cli,
3535 const char *domain,
3536 uint32 *pneg_flags)
3538 enum netr_SchannelType sec_chan_type = 0;
3539 unsigned char machine_pwd[16];
3540 const char *machine_account;
3541 NTSTATUS status;
3543 /* Get the machine account credentials from secrets.tdb. */
3544 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3545 &sec_chan_type))
3547 DEBUG(0, ("get_schannel_session_key: could not fetch "
3548 "trust account password for domain '%s'\n",
3549 domain));
3550 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3553 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3554 cli->desthost, /* server name */
3555 domain, /* domain */
3556 global_myname(), /* client name */
3557 machine_account, /* machine account name */
3558 machine_pwd,
3559 sec_chan_type,
3560 pneg_flags);
3562 if (!NT_STATUS_IS_OK(status)) {
3563 DEBUG(3, ("get_schannel_session_key_common: "
3564 "rpccli_netlogon_setup_creds failed with result %s "
3565 "to server %s, domain %s, machine account %s.\n",
3566 nt_errstr(status), cli->desthost, domain,
3567 machine_account ));
3568 return status;
3571 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3572 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3573 cli->desthost));
3574 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3577 return NT_STATUS_OK;;
3580 /****************************************************************************
3581 Open a netlogon pipe and get the schannel session key.
3582 Now exposed to external callers.
3583 ****************************************************************************/
3586 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3587 const char *domain,
3588 uint32 *pneg_flags,
3589 struct rpc_pipe_client **presult)
3591 struct rpc_pipe_client *netlogon_pipe = NULL;
3592 NTSTATUS status;
3594 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3595 &netlogon_pipe);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 return status;
3600 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3601 pneg_flags);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 TALLOC_FREE(netlogon_pipe);
3604 return status;
3607 *presult = netlogon_pipe;
3608 return NT_STATUS_OK;
3611 /****************************************************************************
3612 External interface.
3613 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3614 using session_key. sign and seal.
3616 The *pdc will be stolen onto this new pipe
3617 ****************************************************************************/
3619 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3620 const struct ndr_syntax_id *interface,
3621 enum dcerpc_transport_t transport,
3622 enum dcerpc_AuthLevel auth_level,
3623 const char *domain,
3624 struct netlogon_creds_CredentialState **pdc,
3625 struct rpc_pipe_client **presult)
3627 struct rpc_pipe_client *result;
3628 struct pipe_auth_data *auth;
3629 NTSTATUS status;
3631 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 return status;
3636 status = rpccli_schannel_bind_data(result, domain, auth_level,
3637 *pdc, &auth);
3638 if (!NT_STATUS_IS_OK(status)) {
3639 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3640 nt_errstr(status)));
3641 TALLOC_FREE(result);
3642 return status;
3645 status = rpc_pipe_bind(result, auth);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3648 "cli_rpc_pipe_bind failed with error %s\n",
3649 nt_errstr(status) ));
3650 TALLOC_FREE(result);
3651 return status;
3655 * The credentials on a new netlogon pipe are the ones we are passed
3656 * in - reference them in
3658 result->dc = talloc_move(result, pdc);
3660 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3661 "for domain %s and bound using schannel.\n",
3662 get_pipe_name_from_syntax(talloc_tos(), interface),
3663 cli->desthost, domain ));
3665 *presult = result;
3666 return NT_STATUS_OK;
3669 /****************************************************************************
3670 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3671 Fetch the session key ourselves using a temporary netlogon pipe. This
3672 version uses an ntlmssp auth bound netlogon pipe to get the key.
3673 ****************************************************************************/
3675 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3676 const char *domain,
3677 const char *username,
3678 const char *password,
3679 uint32 *pneg_flags,
3680 struct rpc_pipe_client **presult)
3682 struct rpc_pipe_client *netlogon_pipe = NULL;
3683 NTSTATUS status;
3685 status = cli_rpc_pipe_open_spnego_ntlmssp(
3686 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3687 DCERPC_AUTH_LEVEL_PRIVACY,
3688 domain, username, password, &netlogon_pipe);
3689 if (!NT_STATUS_IS_OK(status)) {
3690 return status;
3693 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3694 pneg_flags);
3695 if (!NT_STATUS_IS_OK(status)) {
3696 TALLOC_FREE(netlogon_pipe);
3697 return status;
3700 *presult = netlogon_pipe;
3701 return NT_STATUS_OK;
3704 /****************************************************************************
3705 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3706 Fetch the session key ourselves using a temporary netlogon pipe. This version
3707 uses an ntlmssp bind to get the session key.
3708 ****************************************************************************/
3710 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3711 const struct ndr_syntax_id *interface,
3712 enum dcerpc_transport_t transport,
3713 enum dcerpc_AuthLevel auth_level,
3714 const char *domain,
3715 const char *username,
3716 const char *password,
3717 struct rpc_pipe_client **presult)
3719 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3720 struct rpc_pipe_client *netlogon_pipe = NULL;
3721 struct rpc_pipe_client *result = NULL;
3722 NTSTATUS status;
3724 status = get_schannel_session_key_auth_ntlmssp(
3725 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3728 "key from server %s for domain %s.\n",
3729 cli->desthost, domain ));
3730 return status;
3733 status = cli_rpc_pipe_open_schannel_with_key(
3734 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3735 &result);
3737 /* Now we've bound using the session key we can close the netlog pipe. */
3738 TALLOC_FREE(netlogon_pipe);
3740 if (NT_STATUS_IS_OK(status)) {
3741 *presult = result;
3743 return status;
3746 /****************************************************************************
3747 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3748 Fetch the session key ourselves using a temporary netlogon pipe.
3749 ****************************************************************************/
3751 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3752 const struct ndr_syntax_id *interface,
3753 enum dcerpc_transport_t transport,
3754 enum dcerpc_AuthLevel auth_level,
3755 const char *domain,
3756 struct rpc_pipe_client **presult)
3758 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3759 struct rpc_pipe_client *netlogon_pipe = NULL;
3760 struct rpc_pipe_client *result = NULL;
3761 NTSTATUS status;
3763 status = get_schannel_session_key(cli, domain, &neg_flags,
3764 &netlogon_pipe);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3767 "key from server %s for domain %s.\n",
3768 cli->desthost, domain ));
3769 return status;
3772 status = cli_rpc_pipe_open_schannel_with_key(
3773 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3774 &result);
3776 /* Now we've bound using the session key we can close the netlog pipe. */
3777 TALLOC_FREE(netlogon_pipe);
3779 if (NT_STATUS_IS_OK(status)) {
3780 *presult = result;
3783 return status;
3786 /****************************************************************************
3787 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3788 The idea is this can be called with service_princ, username and password all
3789 NULL so long as the caller has a TGT.
3790 ****************************************************************************/
3792 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3793 const struct ndr_syntax_id *interface,
3794 enum dcerpc_AuthLevel auth_level,
3795 const char *service_princ,
3796 const char *username,
3797 const char *password,
3798 struct rpc_pipe_client **presult)
3800 #ifdef HAVE_KRB5
3801 struct rpc_pipe_client *result;
3802 struct pipe_auth_data *auth;
3803 NTSTATUS status;
3805 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
3806 if (!NT_STATUS_IS_OK(status)) {
3807 return status;
3810 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3811 username, password, &auth);
3812 if (!NT_STATUS_IS_OK(status)) {
3813 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3814 nt_errstr(status)));
3815 TALLOC_FREE(result);
3816 return status;
3819 status = rpc_pipe_bind(result, auth);
3820 if (!NT_STATUS_IS_OK(status)) {
3821 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3822 "with error %s\n", nt_errstr(status)));
3823 TALLOC_FREE(result);
3824 return status;
3827 *presult = result;
3828 return NT_STATUS_OK;
3829 #else
3830 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3831 return NT_STATUS_NOT_IMPLEMENTED;
3832 #endif
3835 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3836 struct rpc_pipe_client *cli,
3837 DATA_BLOB *session_key)
3839 struct pipe_auth_data *a = cli->auth;
3840 DATA_BLOB sk;
3842 if (!session_key || !cli) {
3843 return NT_STATUS_INVALID_PARAMETER;
3846 if (!cli->auth) {
3847 return NT_STATUS_INVALID_PARAMETER;
3850 switch (cli->auth->auth_type) {
3851 case PIPE_AUTH_TYPE_SCHANNEL:
3852 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3853 16);
3854 break;
3855 case PIPE_AUTH_TYPE_NTLMSSP:
3856 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3857 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3858 break;
3859 case PIPE_AUTH_TYPE_KRB5:
3860 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3861 sk = data_blob_const(a->a_u.kerberos_auth->session_key.data,
3862 a->a_u.kerberos_auth->session_key.length);
3863 break;
3864 case PIPE_AUTH_TYPE_NONE:
3865 sk = data_blob_const(a->user_session_key.data,
3866 a->user_session_key.length);
3867 break;
3868 default:
3869 return NT_STATUS_NO_USER_SESSION_KEY;
3872 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3873 return NT_STATUS_OK;