Fix one more data_blob -> data_blob_talloc. Move away from implicit NULL context...
[Samba/wip.git] / source3 / rpc_client / cli_pipe.c
blob3ca9271a82044f3f8d87be3e042bf37c94b4527d
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->service_principal, 0, &tkt,
1292 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1294 if (ret) {
1295 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1296 "failed with %s\n",
1297 a->service_principal,
1298 error_message(ret) ));
1300 data_blob_free(&tkt);
1301 return NT_STATUS_INVALID_PARAMETER;
1304 /* wrap that up in a nice GSS-API wrapping */
1305 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1307 data_blob_free(&tkt);
1309 status = dcerpc_push_dcerpc_auth(cli,
1310 DCERPC_AUTH_TYPE_KRB5,
1311 auth_level,
1312 0, /* auth_pad_length */
1313 1, /* auth_context_id */
1314 &tkt_wrapped,
1315 auth_info);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 data_blob_free(&tkt_wrapped);
1318 return status;
1321 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1322 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1324 return NT_STATUS_OK;
1325 #else
1326 return NT_STATUS_INVALID_PARAMETER;
1327 #endif
1330 /*******************************************************************
1331 Creates SPNEGO NTLMSSP auth bind.
1332 ********************************************************************/
1334 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1335 enum dcerpc_AuthLevel auth_level,
1336 DATA_BLOB *auth_info)
1338 NTSTATUS status;
1339 DATA_BLOB null_blob = data_blob_null;
1340 DATA_BLOB request = data_blob_null;
1341 DATA_BLOB spnego_msg = data_blob_null;
1342 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1344 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1345 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1346 null_blob,
1347 &request);
1349 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1350 data_blob_free(&request);
1351 return status;
1354 /* Wrap this in SPNEGO. */
1355 spnego_msg = spnego_gen_negTokenInit(talloc_tos(), OIDs_ntlm, &request, NULL);
1357 data_blob_free(&request);
1359 status = dcerpc_push_dcerpc_auth(cli,
1360 DCERPC_AUTH_TYPE_SPNEGO,
1361 auth_level,
1362 0, /* auth_pad_length */
1363 1, /* auth_context_id */
1364 &spnego_msg,
1365 auth_info);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 data_blob_free(&spnego_msg);
1369 return status;
1372 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1373 dump_data(5, spnego_msg.data, spnego_msg.length);
1374 data_blob_free(&spnego_msg);
1376 return NT_STATUS_OK;
1379 /*******************************************************************
1380 Creates NTLMSSP auth bind.
1381 ********************************************************************/
1383 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1384 enum dcerpc_AuthLevel auth_level,
1385 DATA_BLOB *auth_info)
1387 NTSTATUS status;
1388 DATA_BLOB null_blob = data_blob_null;
1389 DATA_BLOB request = data_blob_null;
1391 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1392 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1393 null_blob,
1394 &request);
1396 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1397 data_blob_free(&request);
1398 return status;
1401 status = dcerpc_push_dcerpc_auth(cli,
1402 DCERPC_AUTH_TYPE_NTLMSSP,
1403 auth_level,
1404 0, /* auth_pad_length */
1405 1, /* auth_context_id */
1406 &request,
1407 auth_info);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 data_blob_free(&request);
1410 return status;
1413 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1414 dump_data(5, request.data, request.length);
1416 return NT_STATUS_OK;
1419 /*******************************************************************
1420 Creates schannel auth bind.
1421 ********************************************************************/
1423 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1424 enum dcerpc_AuthLevel auth_level,
1425 DATA_BLOB *auth_info)
1427 NTSTATUS status;
1428 struct NL_AUTH_MESSAGE r;
1429 DATA_BLOB schannel_blob;
1431 /* Use lp_workgroup() if domain not specified */
1433 if (!cli->auth->domain || !cli->auth->domain[0]) {
1434 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1435 if (cli->auth->domain == NULL) {
1436 return NT_STATUS_NO_MEMORY;
1441 * Now marshall the data into the auth parse_struct.
1444 r.MessageType = NL_NEGOTIATE_REQUEST;
1445 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1446 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1447 r.oem_netbios_domain.a = cli->auth->domain;
1448 r.oem_netbios_computer.a = global_myname();
1450 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return status;
1455 status = dcerpc_push_dcerpc_auth(cli,
1456 DCERPC_AUTH_TYPE_SCHANNEL,
1457 auth_level,
1458 0, /* auth_pad_length */
1459 1, /* auth_context_id */
1460 &schannel_blob,
1461 auth_info);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 return status;
1466 return NT_STATUS_OK;
1469 /*******************************************************************
1470 Creates the internals of a DCE/RPC bind request or alter context PDU.
1471 ********************************************************************/
1473 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1474 enum dcerpc_pkt_type ptype,
1475 uint32 rpc_call_id,
1476 const struct ndr_syntax_id *abstract,
1477 const struct ndr_syntax_id *transfer,
1478 const DATA_BLOB *auth_info,
1479 DATA_BLOB *blob)
1481 uint16 auth_len = auth_info->length;
1482 NTSTATUS status;
1483 union dcerpc_payload u;
1484 struct dcerpc_ctx_list ctx_list;
1486 if (auth_len) {
1487 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1490 ctx_list.context_id = 0;
1491 ctx_list.num_transfer_syntaxes = 1;
1492 ctx_list.abstract_syntax = *abstract;
1493 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1495 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1496 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1497 u.bind.assoc_group_id = 0x0;
1498 u.bind.num_contexts = 1;
1499 u.bind.ctx_list = &ctx_list;
1500 u.bind.auth_info = *auth_info;
1502 status = dcerpc_push_ncacn_packet(mem_ctx,
1503 ptype,
1504 DCERPC_PFC_FLAG_FIRST |
1505 DCERPC_PFC_FLAG_LAST,
1506 auth_len,
1507 rpc_call_id,
1509 blob);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1512 return status;
1515 return NT_STATUS_OK;
1518 /*******************************************************************
1519 Creates a DCE/RPC bind request.
1520 ********************************************************************/
1522 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1523 struct rpc_pipe_client *cli,
1524 uint32 rpc_call_id,
1525 const struct ndr_syntax_id *abstract,
1526 const struct ndr_syntax_id *transfer,
1527 enum pipe_auth_type auth_type,
1528 enum dcerpc_AuthLevel auth_level,
1529 DATA_BLOB *rpc_out)
1531 DATA_BLOB auth_info = data_blob_null;
1532 NTSTATUS ret = NT_STATUS_OK;
1534 switch (auth_type) {
1535 case PIPE_AUTH_TYPE_SCHANNEL:
1536 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1537 if (!NT_STATUS_IS_OK(ret)) {
1538 return ret;
1540 break;
1542 case PIPE_AUTH_TYPE_NTLMSSP:
1543 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1544 if (!NT_STATUS_IS_OK(ret)) {
1545 return ret;
1547 break;
1549 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1550 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1551 if (!NT_STATUS_IS_OK(ret)) {
1552 return ret;
1554 break;
1556 case PIPE_AUTH_TYPE_KRB5:
1557 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1558 if (!NT_STATUS_IS_OK(ret)) {
1559 return ret;
1561 break;
1563 case PIPE_AUTH_TYPE_NONE:
1564 break;
1566 default:
1567 /* "Can't" happen. */
1568 return NT_STATUS_INVALID_INFO_CLASS;
1571 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1572 DCERPC_PKT_BIND,
1573 rpc_call_id,
1574 abstract,
1575 transfer,
1576 &auth_info,
1577 rpc_out);
1578 return ret;
1581 /*******************************************************************
1582 Create and add the NTLMSSP sign/seal auth header and data.
1583 ********************************************************************/
1585 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1586 uint32 ss_padding_len,
1587 DATA_BLOB *rpc_out)
1589 DATA_BLOB auth_info;
1590 NTSTATUS status;
1591 DATA_BLOB auth_blob = data_blob_null;
1592 uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
1594 if (!cli->auth->a_u.auth_ntlmssp_state) {
1595 return NT_STATUS_INVALID_PARAMETER;
1598 /* marshall the dcerpc_auth with an actually empty auth_blob.
1599 * this is needed because the ntmlssp signature includes the
1600 * auth header */
1601 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1602 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1603 cli->auth->auth_level,
1604 ss_padding_len,
1605 1 /* context id. */,
1606 &auth_blob,
1607 &auth_info);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 return status;
1612 /* append the header */
1613 if (!data_blob_append(NULL, rpc_out,
1614 auth_info.data, auth_info.length)) {
1615 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1616 (unsigned int)auth_info.length));
1617 return NT_STATUS_NO_MEMORY;
1619 data_blob_free(&auth_info);
1621 switch (cli->auth->auth_level) {
1622 case DCERPC_AUTH_LEVEL_PRIVACY:
1623 /* Data portion is encrypted. */
1624 status = auth_ntlmssp_seal_packet(cli->auth->a_u.auth_ntlmssp_state,
1625 rpc_out->data,
1626 rpc_out->data
1627 + DCERPC_RESPONSE_LENGTH,
1628 data_and_pad_len,
1629 rpc_out->data,
1630 rpc_out->length,
1631 &auth_blob);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 return status;
1635 break;
1637 case DCERPC_AUTH_LEVEL_INTEGRITY:
1638 /* Data is signed. */
1639 status = auth_ntlmssp_sign_packet(cli->auth->a_u.auth_ntlmssp_state,
1640 rpc_out->data,
1641 rpc_out->data
1642 + DCERPC_RESPONSE_LENGTH,
1643 data_and_pad_len,
1644 rpc_out->data,
1645 rpc_out->length,
1646 &auth_blob);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 return status;
1650 break;
1652 default:
1653 /* Can't happen. */
1654 smb_panic("bad auth level");
1655 /* Notreached. */
1656 return NT_STATUS_INVALID_PARAMETER;
1659 /* Finally attach the blob. */
1660 if (!data_blob_append(NULL, rpc_out,
1661 auth_blob.data, auth_blob.length)) {
1662 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1663 (unsigned int)auth_info.length));
1664 return NT_STATUS_NO_MEMORY;
1666 data_blob_free(&auth_blob);
1668 return NT_STATUS_OK;
1671 /*******************************************************************
1672 Create and add the schannel sign/seal auth header and data.
1673 ********************************************************************/
1675 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1676 uint32 ss_padding_len,
1677 DATA_BLOB *rpc_out)
1679 DATA_BLOB auth_info;
1680 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1681 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
1682 size_t data_and_pad_len = rpc_out->length
1683 - DCERPC_RESPONSE_LENGTH;
1684 DATA_BLOB blob;
1685 NTSTATUS status;
1687 if (!sas) {
1688 return NT_STATUS_INVALID_PARAMETER;
1691 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1692 sas->seq_num));
1694 switch (cli->auth->auth_level) {
1695 case DCERPC_AUTH_LEVEL_PRIVACY:
1696 status = netsec_outgoing_packet(sas,
1697 rpc_out->data,
1698 true,
1699 data_p,
1700 data_and_pad_len,
1701 &blob);
1702 break;
1703 case DCERPC_AUTH_LEVEL_INTEGRITY:
1704 status = netsec_outgoing_packet(sas,
1705 rpc_out->data,
1706 false,
1707 data_p,
1708 data_and_pad_len,
1709 &blob);
1710 break;
1711 default:
1712 status = NT_STATUS_INTERNAL_ERROR;
1713 break;
1716 if (!NT_STATUS_IS_OK(status)) {
1717 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1718 nt_errstr(status)));
1719 return status;
1722 if (DEBUGLEVEL >= 10) {
1723 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1726 /* Finally marshall the blob. */
1727 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1728 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1729 cli->auth->auth_level,
1730 ss_padding_len,
1731 1 /* context id. */,
1732 &blob,
1733 &auth_info);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 return status;
1737 data_blob_free(&blob);
1739 if (!data_blob_append(NULL, rpc_out,
1740 auth_info.data, auth_info.length)) {
1741 return NT_STATUS_NO_MEMORY;
1743 data_blob_free(&auth_info);
1745 return NT_STATUS_OK;
1748 /*******************************************************************
1749 Calculate how much data we're going to send in this packet, also
1750 work out any sign/seal padding length.
1751 ********************************************************************/
1753 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1754 uint32 data_left,
1755 uint16 *p_frag_len,
1756 uint16 *p_auth_len,
1757 uint32 *p_ss_padding)
1759 uint32 data_space, data_len;
1761 #if 0
1762 if ((data_left > 0) && (sys_random() % 2)) {
1763 data_left = MAX(data_left/2, 1);
1765 #endif
1767 switch (cli->auth->auth_level) {
1768 case DCERPC_AUTH_LEVEL_NONE:
1769 case DCERPC_AUTH_LEVEL_CONNECT:
1770 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1771 data_len = MIN(data_space, data_left);
1772 *p_ss_padding = 0;
1773 *p_auth_len = 0;
1774 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1775 return data_len;
1777 case DCERPC_AUTH_LEVEL_INTEGRITY:
1778 case DCERPC_AUTH_LEVEL_PRIVACY:
1779 /* Treat the same for all authenticated rpc requests. */
1780 switch(cli->auth->auth_type) {
1781 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1782 case PIPE_AUTH_TYPE_NTLMSSP:
1783 *p_auth_len = NTLMSSP_SIG_SIZE;
1784 break;
1785 case PIPE_AUTH_TYPE_SCHANNEL:
1786 *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1787 break;
1788 default:
1789 smb_panic("bad auth type");
1790 break;
1793 data_space = cli->max_xmit_frag
1794 - DCERPC_REQUEST_LENGTH
1795 - DCERPC_AUTH_TRAILER_LENGTH
1796 - *p_auth_len;
1798 data_len = MIN(data_space, data_left);
1799 *p_ss_padding = 0;
1800 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1801 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1803 *p_frag_len = DCERPC_REQUEST_LENGTH
1804 + data_len + *p_ss_padding
1805 + DCERPC_AUTH_TRAILER_LENGTH
1806 + *p_auth_len;
1807 return data_len;
1809 default:
1810 smb_panic("bad auth level");
1811 /* Notreached. */
1812 return 0;
1816 /*******************************************************************
1817 External interface.
1818 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1819 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1820 and deals with signing/sealing details.
1821 ********************************************************************/
1823 struct rpc_api_pipe_req_state {
1824 struct event_context *ev;
1825 struct rpc_pipe_client *cli;
1826 uint8_t op_num;
1827 uint32_t call_id;
1828 DATA_BLOB *req_data;
1829 uint32_t req_data_sent;
1830 DATA_BLOB rpc_out;
1831 DATA_BLOB reply_pdu;
1834 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1835 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1836 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1837 bool *is_last_frag);
1839 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1840 struct event_context *ev,
1841 struct rpc_pipe_client *cli,
1842 uint8_t op_num,
1843 DATA_BLOB *req_data)
1845 struct tevent_req *req, *subreq;
1846 struct rpc_api_pipe_req_state *state;
1847 NTSTATUS status;
1848 bool is_last_frag;
1850 req = tevent_req_create(mem_ctx, &state,
1851 struct rpc_api_pipe_req_state);
1852 if (req == NULL) {
1853 return NULL;
1855 state->ev = ev;
1856 state->cli = cli;
1857 state->op_num = op_num;
1858 state->req_data = req_data;
1859 state->req_data_sent = 0;
1860 state->call_id = get_rpc_call_id();
1861 state->reply_pdu = data_blob_null;
1862 state->rpc_out = data_blob_null;
1864 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1865 + RPC_MAX_SIGN_SIZE) {
1866 /* Server is screwed up ! */
1867 status = NT_STATUS_INVALID_PARAMETER;
1868 goto post_status;
1871 status = prepare_next_frag(state, &is_last_frag);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 goto post_status;
1876 if (is_last_frag) {
1877 subreq = rpc_api_pipe_send(state, ev, state->cli,
1878 &state->rpc_out,
1879 DCERPC_PKT_RESPONSE);
1880 if (subreq == NULL) {
1881 goto fail;
1883 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1884 } else {
1885 subreq = rpc_write_send(state, ev, cli->transport,
1886 state->rpc_out.data,
1887 state->rpc_out.length);
1888 if (subreq == NULL) {
1889 goto fail;
1891 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1892 req);
1894 return req;
1896 post_status:
1897 tevent_req_nterror(req, status);
1898 return tevent_req_post(req, ev);
1899 fail:
1900 TALLOC_FREE(req);
1901 return NULL;
1904 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1905 bool *is_last_frag)
1907 uint32_t data_sent_thistime;
1908 uint16_t auth_len;
1909 uint16_t frag_len;
1910 uint8_t flags = 0;
1911 uint32_t ss_padding;
1912 uint32_t data_left;
1913 char pad[8] = { 0, };
1914 NTSTATUS status;
1915 union dcerpc_payload u;
1917 data_left = state->req_data->length - state->req_data_sent;
1919 data_sent_thistime = calculate_data_len_tosend(
1920 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
1922 if (state->req_data_sent == 0) {
1923 flags = DCERPC_PFC_FLAG_FIRST;
1926 if (data_sent_thistime == data_left) {
1927 flags |= DCERPC_PFC_FLAG_LAST;
1930 data_blob_free(&state->rpc_out);
1932 ZERO_STRUCT(u.request);
1934 u.request.alloc_hint = state->req_data->length;
1935 u.request.context_id = 0;
1936 u.request.opnum = state->op_num;
1938 status = dcerpc_push_ncacn_packet(state,
1939 DCERPC_PKT_REQUEST,
1940 flags,
1941 auth_len,
1942 state->call_id,
1944 &state->rpc_out);
1945 if (!NT_STATUS_IS_OK(status)) {
1946 return status;
1949 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1950 * compute it right for requests */
1951 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1953 /* Copy in the data, plus any ss padding. */
1954 if (!data_blob_append(NULL, &state->rpc_out,
1955 state->req_data->data + state->req_data_sent,
1956 data_sent_thistime)) {
1957 return NT_STATUS_NO_MEMORY;
1960 if (ss_padding) {
1961 /* Copy the sign/seal padding data. */
1962 if (!data_blob_append(NULL, &state->rpc_out,
1963 pad, ss_padding)) {
1964 return NT_STATUS_NO_MEMORY;
1968 /* Generate any auth sign/seal and add the auth footer. */
1969 switch (state->cli->auth->auth_type) {
1970 case PIPE_AUTH_TYPE_NONE:
1971 status = NT_STATUS_OK;
1972 break;
1973 case PIPE_AUTH_TYPE_NTLMSSP:
1974 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1975 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
1976 &state->rpc_out);
1977 break;
1978 case PIPE_AUTH_TYPE_SCHANNEL:
1979 status = add_schannel_auth_footer(state->cli, ss_padding,
1980 &state->rpc_out);
1981 break;
1982 default:
1983 status = NT_STATUS_INVALID_PARAMETER;
1984 break;
1987 state->req_data_sent += data_sent_thistime;
1988 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1990 return status;
1993 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1995 struct tevent_req *req = tevent_req_callback_data(
1996 subreq, struct tevent_req);
1997 struct rpc_api_pipe_req_state *state = tevent_req_data(
1998 req, struct rpc_api_pipe_req_state);
1999 NTSTATUS status;
2000 bool is_last_frag;
2002 status = rpc_write_recv(subreq);
2003 TALLOC_FREE(subreq);
2004 if (!NT_STATUS_IS_OK(status)) {
2005 tevent_req_nterror(req, status);
2006 return;
2009 status = prepare_next_frag(state, &is_last_frag);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 tevent_req_nterror(req, status);
2012 return;
2015 if (is_last_frag) {
2016 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2017 &state->rpc_out,
2018 DCERPC_PKT_RESPONSE);
2019 if (tevent_req_nomem(subreq, req)) {
2020 return;
2022 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2023 } else {
2024 subreq = rpc_write_send(state, state->ev,
2025 state->cli->transport,
2026 state->rpc_out.data,
2027 state->rpc_out.length);
2028 if (tevent_req_nomem(subreq, req)) {
2029 return;
2031 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2032 req);
2036 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2038 struct tevent_req *req = tevent_req_callback_data(
2039 subreq, struct tevent_req);
2040 struct rpc_api_pipe_req_state *state = tevent_req_data(
2041 req, struct rpc_api_pipe_req_state);
2042 NTSTATUS status;
2044 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2045 TALLOC_FREE(subreq);
2046 if (!NT_STATUS_IS_OK(status)) {
2047 tevent_req_nterror(req, status);
2048 return;
2050 tevent_req_done(req);
2053 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2054 DATA_BLOB *reply_pdu)
2056 struct rpc_api_pipe_req_state *state = tevent_req_data(
2057 req, struct rpc_api_pipe_req_state);
2058 NTSTATUS status;
2060 if (tevent_req_is_nterror(req, &status)) {
2062 * We always have to initialize to reply pdu, even if there is
2063 * none. The rpccli_* caller routines expect this.
2065 *reply_pdu = data_blob_null;
2066 return status;
2069 /* return data to caller and assign it ownership of memory */
2070 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2071 reply_pdu->length = state->reply_pdu.length;
2072 state->reply_pdu.length = 0;
2074 return NT_STATUS_OK;
2077 #if 0
2078 /****************************************************************************
2079 Set the handle state.
2080 ****************************************************************************/
2082 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2083 const char *pipe_name, uint16 device_state)
2085 bool state_set = False;
2086 char param[2];
2087 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2088 char *rparam = NULL;
2089 char *rdata = NULL;
2090 uint32 rparam_len, rdata_len;
2092 if (pipe_name == NULL)
2093 return False;
2095 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2096 cli->fnum, pipe_name, device_state));
2098 /* create parameters: device state */
2099 SSVAL(param, 0, device_state);
2101 /* create setup parameters. */
2102 setup[0] = 0x0001;
2103 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2105 /* send the data on \PIPE\ */
2106 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2107 setup, 2, 0, /* setup, length, max */
2108 param, 2, 0, /* param, length, max */
2109 NULL, 0, 1024, /* data, length, max */
2110 &rparam, &rparam_len, /* return param, length */
2111 &rdata, &rdata_len)) /* return data, length */
2113 DEBUG(5, ("Set Handle state: return OK\n"));
2114 state_set = True;
2117 SAFE_FREE(rparam);
2118 SAFE_FREE(rdata);
2120 return state_set;
2122 #endif
2124 /****************************************************************************
2125 Check the rpc bind acknowledge response.
2126 ****************************************************************************/
2128 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2129 const struct ndr_syntax_id *transfer)
2131 struct dcerpc_ack_ctx ctx;
2133 if (r->secondary_address_size == 0) {
2134 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2137 if (r->num_results < 1 || !r->ctx_list) {
2138 return false;
2141 ctx = r->ctx_list[0];
2143 /* check the transfer syntax */
2144 if ((ctx.syntax.if_version != transfer->if_version) ||
2145 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2146 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2147 return False;
2150 if (r->num_results != 0x1 || ctx.result != 0) {
2151 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2152 r->num_results, ctx.reason));
2155 DEBUG(5,("check_bind_response: accepted!\n"));
2156 return True;
2159 /*******************************************************************
2160 Creates a DCE/RPC bind authentication response.
2161 This is the packet that is sent back to the server once we
2162 have received a BIND-ACK, to finish the third leg of
2163 the authentication handshake.
2164 ********************************************************************/
2166 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
2167 struct rpc_pipe_client *cli,
2168 uint32 rpc_call_id,
2169 enum pipe_auth_type auth_type,
2170 enum dcerpc_AuthLevel auth_level,
2171 DATA_BLOB *pauth_blob,
2172 DATA_BLOB *rpc_out)
2174 NTSTATUS status;
2175 union dcerpc_payload u;
2177 u.auth3._pad = 0;
2179 status = dcerpc_push_dcerpc_auth(mem_ctx,
2180 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2181 auth_level,
2182 0, /* auth_pad_length */
2183 1, /* auth_context_id */
2184 pauth_blob,
2185 &u.auth3.auth_info);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 return status;
2190 status = dcerpc_push_ncacn_packet(mem_ctx,
2191 DCERPC_PKT_AUTH3,
2192 DCERPC_PFC_FLAG_FIRST |
2193 DCERPC_PFC_FLAG_LAST,
2194 pauth_blob->length,
2195 rpc_call_id,
2197 rpc_out);
2198 data_blob_free(&u.auth3.auth_info);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2201 return status;
2204 return NT_STATUS_OK;
2207 /*******************************************************************
2208 Creates a DCE/RPC bind alter context authentication request which
2209 may contain a spnego auth blobl
2210 ********************************************************************/
2212 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2213 uint32 rpc_call_id,
2214 const struct ndr_syntax_id *abstract,
2215 const struct ndr_syntax_id *transfer,
2216 enum dcerpc_AuthLevel auth_level,
2217 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2218 DATA_BLOB *rpc_out)
2220 DATA_BLOB auth_info;
2221 NTSTATUS status;
2223 status = dcerpc_push_dcerpc_auth(mem_ctx,
2224 DCERPC_AUTH_TYPE_SPNEGO,
2225 auth_level,
2226 0, /* auth_pad_length */
2227 1, /* auth_context_id */
2228 pauth_blob,
2229 &auth_info);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 return status;
2234 status = create_bind_or_alt_ctx_internal(mem_ctx,
2235 DCERPC_PKT_ALTER,
2236 rpc_call_id,
2237 abstract,
2238 transfer,
2239 &auth_info,
2240 rpc_out);
2241 data_blob_free(&auth_info);
2242 return status;
2245 /****************************************************************************
2246 Do an rpc bind.
2247 ****************************************************************************/
2249 struct rpc_pipe_bind_state {
2250 struct event_context *ev;
2251 struct rpc_pipe_client *cli;
2252 DATA_BLOB rpc_out;
2253 uint32_t rpc_call_id;
2256 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2257 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2258 struct rpc_pipe_bind_state *state,
2259 struct ncacn_packet *r);
2260 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2261 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2262 struct rpc_pipe_bind_state *state,
2263 struct ncacn_packet *r,
2264 DATA_BLOB *reply_pdu);
2265 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2267 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2268 struct event_context *ev,
2269 struct rpc_pipe_client *cli,
2270 struct pipe_auth_data *auth)
2272 struct tevent_req *req, *subreq;
2273 struct rpc_pipe_bind_state *state;
2274 NTSTATUS status;
2276 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2277 if (req == NULL) {
2278 return NULL;
2281 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2282 rpccli_pipe_txt(talloc_tos(), cli),
2283 (unsigned int)auth->auth_type,
2284 (unsigned int)auth->auth_level ));
2286 state->ev = ev;
2287 state->cli = cli;
2288 state->rpc_call_id = get_rpc_call_id();
2289 state->rpc_out = data_blob_null;
2291 cli->auth = talloc_move(cli, &auth);
2293 /* Marshall the outgoing data. */
2294 status = create_rpc_bind_req(state, cli,
2295 state->rpc_call_id,
2296 &cli->abstract_syntax,
2297 &cli->transfer_syntax,
2298 cli->auth->auth_type,
2299 cli->auth->auth_level,
2300 &state->rpc_out);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 goto post_status;
2306 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2307 DCERPC_PKT_BIND_ACK);
2308 if (subreq == NULL) {
2309 goto fail;
2311 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2312 return req;
2314 post_status:
2315 tevent_req_nterror(req, status);
2316 return tevent_req_post(req, ev);
2317 fail:
2318 TALLOC_FREE(req);
2319 return NULL;
2322 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2324 struct tevent_req *req = tevent_req_callback_data(
2325 subreq, struct tevent_req);
2326 struct rpc_pipe_bind_state *state = tevent_req_data(
2327 req, struct rpc_pipe_bind_state);
2328 DATA_BLOB reply_pdu;
2329 struct ncacn_packet *pkt;
2330 NTSTATUS status;
2332 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2333 TALLOC_FREE(subreq);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2336 rpccli_pipe_txt(talloc_tos(), state->cli),
2337 nt_errstr(status)));
2338 tevent_req_nterror(req, status);
2339 return;
2342 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2343 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2344 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2345 return;
2348 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2349 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2352 * For authenticated binds we may need to do 3 or 4 leg binds.
2355 switch(state->cli->auth->auth_type) {
2357 case PIPE_AUTH_TYPE_NONE:
2358 case PIPE_AUTH_TYPE_SCHANNEL:
2359 /* Bind complete. */
2360 tevent_req_done(req);
2361 break;
2363 case PIPE_AUTH_TYPE_NTLMSSP:
2364 /* Need to send AUTH3 packet - no reply. */
2365 status = rpc_finish_auth3_bind_send(req, state, pkt);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 tevent_req_nterror(req, status);
2369 break;
2371 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2372 /* Need to send alter context request and reply. */
2373 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2374 &reply_pdu);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 tevent_req_nterror(req, status);
2378 break;
2380 case PIPE_AUTH_TYPE_KRB5:
2381 /* */
2383 default:
2384 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2385 (unsigned int)state->cli->auth->auth_type));
2386 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2390 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2391 struct rpc_pipe_bind_state *state,
2392 struct ncacn_packet *r)
2394 DATA_BLOB client_reply = data_blob_null;
2395 struct dcerpc_auth auth;
2396 struct tevent_req *subreq;
2397 NTSTATUS status;
2399 if ((r->auth_length == 0)
2400 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2401 + r->auth_length)) {
2402 return NT_STATUS_INVALID_PARAMETER;
2405 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2406 &r->u.bind_ack.auth_info,
2407 &auth, false);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2410 nt_errstr(status)));
2411 return status;
2414 /* TODO - check auth_type/auth_level match. */
2416 status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
2417 auth.credentials, &client_reply);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2421 "blob failed: %s.\n", nt_errstr(status)));
2422 return status;
2425 data_blob_free(&state->rpc_out);
2427 status = create_rpc_bind_auth3(state,
2428 state->cli, state->rpc_call_id,
2429 state->cli->auth->auth_type,
2430 state->cli->auth->auth_level,
2431 &client_reply, &state->rpc_out);
2432 data_blob_free(&client_reply);
2434 if (!NT_STATUS_IS_OK(status)) {
2435 return status;
2438 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2439 state->rpc_out.data, state->rpc_out.length);
2440 if (subreq == NULL) {
2441 return NT_STATUS_NO_MEMORY;
2443 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2444 return NT_STATUS_OK;
2447 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2449 struct tevent_req *req = tevent_req_callback_data(
2450 subreq, struct tevent_req);
2451 NTSTATUS status;
2453 status = rpc_write_recv(subreq);
2454 TALLOC_FREE(subreq);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 tevent_req_nterror(req, status);
2457 return;
2459 tevent_req_done(req);
2462 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2463 struct rpc_pipe_bind_state *state,
2464 struct ncacn_packet *r,
2465 DATA_BLOB *reply_pdu)
2467 DATA_BLOB server_ntlm_response = data_blob_null;
2468 DATA_BLOB client_reply = data_blob_null;
2469 DATA_BLOB tmp_blob = data_blob_null;
2470 struct dcerpc_auth auth_info;
2471 DATA_BLOB auth_blob;
2472 struct tevent_req *subreq;
2473 NTSTATUS status;
2475 if ((r->auth_length == 0)
2476 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2477 + r->auth_length)) {
2478 return NT_STATUS_INVALID_PARAMETER;
2481 /* Process the returned NTLMSSP blob first. */
2482 auth_blob = data_blob_const(reply_pdu->data
2483 + r->frag_length
2484 - DCERPC_AUTH_TRAILER_LENGTH
2485 - r->auth_length,
2486 DCERPC_AUTH_TRAILER_LENGTH
2487 + r->auth_length);
2489 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2492 return status;
2496 * The server might give us back two challenges - tmp_blob is for the
2497 * second.
2499 if (!spnego_parse_challenge(auth_info.credentials,
2500 &server_ntlm_response, &tmp_blob)) {
2501 data_blob_free(&server_ntlm_response);
2502 data_blob_free(&tmp_blob);
2503 return NT_STATUS_INVALID_PARAMETER;
2506 /* We're finished with the server spnego response and the tmp_blob. */
2507 data_blob_free(&tmp_blob);
2509 status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
2510 server_ntlm_response, &client_reply);
2512 /* Finished with the server_ntlm response */
2513 data_blob_free(&server_ntlm_response);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2517 "using server blob failed.\n"));
2518 data_blob_free(&client_reply);
2519 return status;
2522 /* SPNEGO wrap the client reply. */
2523 tmp_blob = spnego_gen_auth(client_reply);
2524 data_blob_free(&client_reply);
2525 client_reply = tmp_blob;
2526 tmp_blob = data_blob_null;
2528 /* Now prepare the alter context pdu. */
2529 data_blob_free(&state->rpc_out);
2531 status = create_rpc_alter_context(state,
2532 state->rpc_call_id,
2533 &state->cli->abstract_syntax,
2534 &state->cli->transfer_syntax,
2535 state->cli->auth->auth_level,
2536 &client_reply,
2537 &state->rpc_out);
2538 data_blob_free(&client_reply);
2540 if (!NT_STATUS_IS_OK(status)) {
2541 return status;
2544 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2545 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2546 if (subreq == NULL) {
2547 return NT_STATUS_NO_MEMORY;
2549 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2550 return NT_STATUS_OK;
2553 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2555 struct tevent_req *req = tevent_req_callback_data(
2556 subreq, struct tevent_req);
2557 struct rpc_pipe_bind_state *state = tevent_req_data(
2558 req, struct rpc_pipe_bind_state);
2559 DATA_BLOB tmp_blob = data_blob_null;
2560 struct ncacn_packet *pkt;
2561 struct dcerpc_auth auth;
2562 NTSTATUS status;
2564 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2565 TALLOC_FREE(subreq);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 tevent_req_nterror(req, status);
2568 return;
2571 status = dcerpc_pull_dcerpc_auth(pkt,
2572 &pkt->u.alter_resp.auth_info,
2573 &auth, false);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 tevent_req_nterror(req, status);
2576 return;
2579 /* Check we got a valid auth response. */
2580 if (!spnego_parse_auth_response(auth.credentials,
2581 NT_STATUS_OK,
2582 OID_NTLMSSP, &tmp_blob)) {
2583 data_blob_free(&tmp_blob);
2584 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2585 return;
2588 data_blob_free(&tmp_blob);
2590 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2591 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2592 tevent_req_done(req);
2595 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2597 return tevent_req_simple_recv_ntstatus(req);
2600 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2601 struct pipe_auth_data *auth)
2603 TALLOC_CTX *frame = talloc_stackframe();
2604 struct event_context *ev;
2605 struct tevent_req *req;
2606 NTSTATUS status = NT_STATUS_OK;
2608 ev = event_context_init(frame);
2609 if (ev == NULL) {
2610 status = NT_STATUS_NO_MEMORY;
2611 goto fail;
2614 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2615 if (req == NULL) {
2616 status = NT_STATUS_NO_MEMORY;
2617 goto fail;
2620 if (!tevent_req_poll(req, ev)) {
2621 status = map_nt_error_from_unix(errno);
2622 goto fail;
2625 status = rpc_pipe_bind_recv(req);
2626 fail:
2627 TALLOC_FREE(frame);
2628 return status;
2631 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2633 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2634 unsigned int timeout)
2636 unsigned int old;
2638 if (rpc_cli->transport == NULL) {
2639 return RPCCLI_DEFAULT_TIMEOUT;
2642 if (rpc_cli->transport->set_timeout == NULL) {
2643 return RPCCLI_DEFAULT_TIMEOUT;
2646 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2647 if (old == 0) {
2648 return RPCCLI_DEFAULT_TIMEOUT;
2651 return old;
2654 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2656 if (rpc_cli == NULL) {
2657 return false;
2660 if (rpc_cli->transport == NULL) {
2661 return false;
2664 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2667 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2669 struct cli_state *cli;
2671 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2672 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2673 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(rpc_cli->auth->a_u.auth_ntlmssp_state), 16);
2674 return true;
2677 cli = rpc_pipe_np_smb_conn(rpc_cli);
2678 if (cli == NULL) {
2679 return false;
2681 E_md4hash(cli->password ? cli->password : "", nt_hash);
2682 return true;
2685 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2686 struct pipe_auth_data **presult)
2688 struct pipe_auth_data *result;
2690 result = talloc(mem_ctx, struct pipe_auth_data);
2691 if (result == NULL) {
2692 return NT_STATUS_NO_MEMORY;
2695 result->auth_type = PIPE_AUTH_TYPE_NONE;
2696 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2698 result->user_name = talloc_strdup(result, "");
2699 result->domain = talloc_strdup(result, "");
2700 if ((result->user_name == NULL) || (result->domain == NULL)) {
2701 TALLOC_FREE(result);
2702 return NT_STATUS_NO_MEMORY;
2705 *presult = result;
2706 return NT_STATUS_OK;
2709 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2711 TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2712 return 0;
2715 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2716 enum pipe_auth_type auth_type,
2717 enum dcerpc_AuthLevel auth_level,
2718 const char *domain,
2719 const char *username,
2720 const char *password,
2721 struct pipe_auth_data **presult)
2723 struct pipe_auth_data *result;
2724 NTSTATUS status;
2726 result = talloc(mem_ctx, struct pipe_auth_data);
2727 if (result == NULL) {
2728 return NT_STATUS_NO_MEMORY;
2731 result->auth_type = auth_type;
2732 result->auth_level = auth_level;
2734 result->user_name = talloc_strdup(result, username);
2735 result->domain = talloc_strdup(result, domain);
2736 if ((result->user_name == NULL) || (result->domain == NULL)) {
2737 status = NT_STATUS_NO_MEMORY;
2738 goto fail;
2741 status = auth_ntlmssp_client_start(NULL,
2742 global_myname(),
2743 lp_workgroup(),
2744 lp_client_ntlmv2_auth(),
2745 &result->a_u.auth_ntlmssp_state);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 goto fail;
2750 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2752 status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2753 username);
2754 if (!NT_STATUS_IS_OK(status)) {
2755 goto fail;
2758 status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2759 domain);
2760 if (!NT_STATUS_IS_OK(status)) {
2761 goto fail;
2764 status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2765 password);
2766 if (!NT_STATUS_IS_OK(status)) {
2767 goto fail;
2771 * Turn off sign+seal to allow selected auth level to turn it back on.
2773 auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2774 ~(NTLMSSP_NEGOTIATE_SIGN |
2775 NTLMSSP_NEGOTIATE_SEAL));
2777 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2778 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2779 NTLMSSP_NEGOTIATE_SIGN);
2780 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2781 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2782 NTLMSSP_NEGOTIATE_SEAL |
2783 NTLMSSP_NEGOTIATE_SIGN);
2786 *presult = result;
2787 return NT_STATUS_OK;
2789 fail:
2790 TALLOC_FREE(result);
2791 return status;
2794 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2795 enum dcerpc_AuthLevel auth_level,
2796 struct netlogon_creds_CredentialState *creds,
2797 struct pipe_auth_data **presult)
2799 struct pipe_auth_data *result;
2801 result = talloc(mem_ctx, struct pipe_auth_data);
2802 if (result == NULL) {
2803 return NT_STATUS_NO_MEMORY;
2806 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2807 result->auth_level = auth_level;
2809 result->user_name = talloc_strdup(result, "");
2810 result->domain = talloc_strdup(result, domain);
2811 if ((result->user_name == NULL) || (result->domain == NULL)) {
2812 goto fail;
2815 result->a_u.schannel_auth = talloc(result, struct schannel_state);
2816 if (result->a_u.schannel_auth == NULL) {
2817 goto fail;
2820 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2821 result->a_u.schannel_auth->seq_num = 0;
2822 result->a_u.schannel_auth->initiator = true;
2823 result->a_u.schannel_auth->creds = creds;
2825 *presult = result;
2826 return NT_STATUS_OK;
2828 fail:
2829 TALLOC_FREE(result);
2830 return NT_STATUS_NO_MEMORY;
2833 #ifdef HAVE_KRB5
2834 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2836 data_blob_free(&auth->session_key);
2837 return 0;
2839 #endif
2841 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2842 enum dcerpc_AuthLevel auth_level,
2843 const char *service_princ,
2844 const char *username,
2845 const char *password,
2846 struct pipe_auth_data **presult)
2848 #ifdef HAVE_KRB5
2849 struct pipe_auth_data *result;
2851 if ((username != NULL) && (password != NULL)) {
2852 int ret = kerberos_kinit_password(username, password, 0, NULL);
2853 if (ret != 0) {
2854 return NT_STATUS_ACCESS_DENIED;
2858 result = talloc(mem_ctx, struct pipe_auth_data);
2859 if (result == NULL) {
2860 return NT_STATUS_NO_MEMORY;
2863 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2864 result->auth_level = auth_level;
2867 * Username / domain need fixing!
2869 result->user_name = talloc_strdup(result, "");
2870 result->domain = talloc_strdup(result, "");
2871 if ((result->user_name == NULL) || (result->domain == NULL)) {
2872 goto fail;
2875 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2876 result, struct kerberos_auth_struct);
2877 if (result->a_u.kerberos_auth == NULL) {
2878 goto fail;
2880 talloc_set_destructor(result->a_u.kerberos_auth,
2881 cli_auth_kerberos_data_destructor);
2883 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2884 result, service_princ);
2885 if (result->a_u.kerberos_auth->service_principal == NULL) {
2886 goto fail;
2889 *presult = result;
2890 return NT_STATUS_OK;
2892 fail:
2893 TALLOC_FREE(result);
2894 return NT_STATUS_NO_MEMORY;
2895 #else
2896 return NT_STATUS_NOT_SUPPORTED;
2897 #endif
2901 * Create an rpc pipe client struct, connecting to a tcp port.
2903 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2904 uint16_t port,
2905 const struct ndr_syntax_id *abstract_syntax,
2906 struct rpc_pipe_client **presult)
2908 struct rpc_pipe_client *result;
2909 struct sockaddr_storage addr;
2910 NTSTATUS status;
2911 int fd;
2913 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2914 if (result == NULL) {
2915 return NT_STATUS_NO_MEMORY;
2918 result->abstract_syntax = *abstract_syntax;
2919 result->transfer_syntax = ndr_transfer_syntax;
2920 result->dispatch = cli_do_rpc_ndr;
2921 result->dispatch_send = cli_do_rpc_ndr_send;
2922 result->dispatch_recv = cli_do_rpc_ndr_recv;
2924 result->desthost = talloc_strdup(result, host);
2925 result->srv_name_slash = talloc_asprintf_strupper_m(
2926 result, "\\\\%s", result->desthost);
2927 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2928 status = NT_STATUS_NO_MEMORY;
2929 goto fail;
2932 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2933 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2935 if (!resolve_name(host, &addr, 0, false)) {
2936 status = NT_STATUS_NOT_FOUND;
2937 goto fail;
2940 status = open_socket_out(&addr, port, 60, &fd);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 goto fail;
2944 set_socket_options(fd, lp_socket_options());
2946 status = rpc_transport_sock_init(result, fd, &result->transport);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 close(fd);
2949 goto fail;
2952 result->transport->transport = NCACN_IP_TCP;
2954 *presult = result;
2955 return NT_STATUS_OK;
2957 fail:
2958 TALLOC_FREE(result);
2959 return status;
2963 * Determine the tcp port on which a dcerpc interface is listening
2964 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2965 * target host.
2967 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2968 const struct ndr_syntax_id *abstract_syntax,
2969 uint16_t *pport)
2971 NTSTATUS status;
2972 struct rpc_pipe_client *epm_pipe = NULL;
2973 struct pipe_auth_data *auth = NULL;
2974 struct dcerpc_binding *map_binding = NULL;
2975 struct dcerpc_binding *res_binding = NULL;
2976 struct epm_twr_t *map_tower = NULL;
2977 struct epm_twr_t *res_towers = NULL;
2978 struct policy_handle *entry_handle = NULL;
2979 uint32_t num_towers = 0;
2980 uint32_t max_towers = 1;
2981 struct epm_twr_p_t towers;
2982 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2984 if (pport == NULL) {
2985 status = NT_STATUS_INVALID_PARAMETER;
2986 goto done;
2989 /* open the connection to the endpoint mapper */
2990 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2991 &ndr_table_epmapper.syntax_id,
2992 &epm_pipe);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 goto done;
2998 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 goto done;
3003 status = rpc_pipe_bind(epm_pipe, auth);
3004 if (!NT_STATUS_IS_OK(status)) {
3005 goto done;
3008 /* create tower for asking the epmapper */
3010 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3011 if (map_binding == NULL) {
3012 status = NT_STATUS_NO_MEMORY;
3013 goto done;
3016 map_binding->transport = NCACN_IP_TCP;
3017 map_binding->object = *abstract_syntax;
3018 map_binding->host = host; /* needed? */
3019 map_binding->endpoint = "0"; /* correct? needed? */
3021 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3022 if (map_tower == NULL) {
3023 status = NT_STATUS_NO_MEMORY;
3024 goto done;
3027 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3028 &(map_tower->tower));
3029 if (!NT_STATUS_IS_OK(status)) {
3030 goto done;
3033 /* allocate further parameters for the epm_Map call */
3035 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3036 if (res_towers == NULL) {
3037 status = NT_STATUS_NO_MEMORY;
3038 goto done;
3040 towers.twr = res_towers;
3042 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3043 if (entry_handle == NULL) {
3044 status = NT_STATUS_NO_MEMORY;
3045 goto done;
3048 /* ask the endpoint mapper for the port */
3050 status = rpccli_epm_Map(epm_pipe,
3051 tmp_ctx,
3052 CONST_DISCARD(struct GUID *,
3053 &(abstract_syntax->uuid)),
3054 map_tower,
3055 entry_handle,
3056 max_towers,
3057 &num_towers,
3058 &towers);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 goto done;
3064 if (num_towers != 1) {
3065 status = NT_STATUS_UNSUCCESSFUL;
3066 goto done;
3069 /* extract the port from the answer */
3071 status = dcerpc_binding_from_tower(tmp_ctx,
3072 &(towers.twr->tower),
3073 &res_binding);
3074 if (!NT_STATUS_IS_OK(status)) {
3075 goto done;
3078 /* are further checks here necessary? */
3079 if (res_binding->transport != NCACN_IP_TCP) {
3080 status = NT_STATUS_UNSUCCESSFUL;
3081 goto done;
3084 *pport = (uint16_t)atoi(res_binding->endpoint);
3086 done:
3087 TALLOC_FREE(tmp_ctx);
3088 return status;
3092 * Create a rpc pipe client struct, connecting to a host via tcp.
3093 * The port is determined by asking the endpoint mapper on the given
3094 * host.
3096 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3097 const struct ndr_syntax_id *abstract_syntax,
3098 struct rpc_pipe_client **presult)
3100 NTSTATUS status;
3101 uint16_t port = 0;
3103 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3104 if (!NT_STATUS_IS_OK(status)) {
3105 return status;
3108 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3109 abstract_syntax, presult);
3112 /********************************************************************
3113 Create a rpc pipe client struct, connecting to a unix domain socket
3114 ********************************************************************/
3115 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3116 const struct ndr_syntax_id *abstract_syntax,
3117 struct rpc_pipe_client **presult)
3119 struct rpc_pipe_client *result;
3120 struct sockaddr_un addr;
3121 NTSTATUS status;
3122 int fd;
3124 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3125 if (result == NULL) {
3126 return NT_STATUS_NO_MEMORY;
3129 result->abstract_syntax = *abstract_syntax;
3130 result->transfer_syntax = ndr_transfer_syntax;
3131 result->dispatch = cli_do_rpc_ndr;
3132 result->dispatch_send = cli_do_rpc_ndr_send;
3133 result->dispatch_recv = cli_do_rpc_ndr_recv;
3135 result->desthost = get_myname(result);
3136 result->srv_name_slash = talloc_asprintf_strupper_m(
3137 result, "\\\\%s", result->desthost);
3138 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3139 status = NT_STATUS_NO_MEMORY;
3140 goto fail;
3143 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3144 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3146 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3147 if (fd == -1) {
3148 status = map_nt_error_from_unix(errno);
3149 goto fail;
3152 ZERO_STRUCT(addr);
3153 addr.sun_family = AF_UNIX;
3154 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3156 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3157 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3158 strerror(errno)));
3159 close(fd);
3160 return map_nt_error_from_unix(errno);
3163 status = rpc_transport_sock_init(result, fd, &result->transport);
3164 if (!NT_STATUS_IS_OK(status)) {
3165 close(fd);
3166 goto fail;
3169 result->transport->transport = NCALRPC;
3171 *presult = result;
3172 return NT_STATUS_OK;
3174 fail:
3175 TALLOC_FREE(result);
3176 return status;
3179 struct rpc_pipe_client_np_ref {
3180 struct cli_state *cli;
3181 struct rpc_pipe_client *pipe;
3184 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3186 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3187 return 0;
3190 /****************************************************************************
3191 Open a named pipe over SMB to a remote server.
3193 * CAVEAT CALLER OF THIS FUNCTION:
3194 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3195 * so be sure that this function is called AFTER any structure (vs pointer)
3196 * assignment of the cli. In particular, libsmbclient does structure
3197 * assignments of cli, which invalidates the data in the returned
3198 * rpc_pipe_client if this function is called before the structure assignment
3199 * of cli.
3201 ****************************************************************************/
3203 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3204 const struct ndr_syntax_id *abstract_syntax,
3205 struct rpc_pipe_client **presult)
3207 struct rpc_pipe_client *result;
3208 NTSTATUS status;
3209 struct rpc_pipe_client_np_ref *np_ref;
3211 /* sanity check to protect against crashes */
3213 if ( !cli ) {
3214 return NT_STATUS_INVALID_HANDLE;
3217 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3218 if (result == NULL) {
3219 return NT_STATUS_NO_MEMORY;
3222 result->abstract_syntax = *abstract_syntax;
3223 result->transfer_syntax = ndr_transfer_syntax;
3224 result->dispatch = cli_do_rpc_ndr;
3225 result->dispatch_send = cli_do_rpc_ndr_send;
3226 result->dispatch_recv = cli_do_rpc_ndr_recv;
3227 result->desthost = talloc_strdup(result, cli->desthost);
3228 result->srv_name_slash = talloc_asprintf_strupper_m(
3229 result, "\\\\%s", result->desthost);
3231 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3232 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3234 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3235 TALLOC_FREE(result);
3236 return NT_STATUS_NO_MEMORY;
3239 status = rpc_transport_np_init(result, cli, abstract_syntax,
3240 &result->transport);
3241 if (!NT_STATUS_IS_OK(status)) {
3242 TALLOC_FREE(result);
3243 return status;
3246 result->transport->transport = NCACN_NP;
3248 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3249 if (np_ref == NULL) {
3250 TALLOC_FREE(result);
3251 return NT_STATUS_NO_MEMORY;
3253 np_ref->cli = cli;
3254 np_ref->pipe = result;
3256 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3257 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3259 *presult = result;
3260 return NT_STATUS_OK;
3263 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3264 struct rpc_cli_smbd_conn *conn,
3265 const struct ndr_syntax_id *syntax,
3266 struct rpc_pipe_client **presult)
3268 struct rpc_pipe_client *result;
3269 struct pipe_auth_data *auth;
3270 NTSTATUS status;
3272 result = talloc(mem_ctx, struct rpc_pipe_client);
3273 if (result == NULL) {
3274 return NT_STATUS_NO_MEMORY;
3276 result->abstract_syntax = *syntax;
3277 result->transfer_syntax = ndr_transfer_syntax;
3278 result->dispatch = cli_do_rpc_ndr;
3279 result->dispatch_send = cli_do_rpc_ndr_send;
3280 result->dispatch_recv = cli_do_rpc_ndr_recv;
3281 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3282 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3284 result->desthost = talloc_strdup(result, global_myname());
3285 result->srv_name_slash = talloc_asprintf_strupper_m(
3286 result, "\\\\%s", global_myname());
3287 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3288 TALLOC_FREE(result);
3289 return NT_STATUS_NO_MEMORY;
3292 status = rpc_transport_smbd_init(result, conn, syntax,
3293 &result->transport);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3296 nt_errstr(status)));
3297 TALLOC_FREE(result);
3298 return status;
3301 status = rpccli_anon_bind_data(result, &auth);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3304 nt_errstr(status)));
3305 TALLOC_FREE(result);
3306 return status;
3309 status = rpc_pipe_bind(result, auth);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3312 TALLOC_FREE(result);
3313 return status;
3316 result->transport->transport = NCACN_INTERNAL;
3318 *presult = result;
3319 return NT_STATUS_OK;
3322 /****************************************************************************
3323 Open a pipe to a remote server.
3324 ****************************************************************************/
3326 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3327 enum dcerpc_transport_t transport,
3328 const struct ndr_syntax_id *interface,
3329 struct rpc_pipe_client **presult)
3331 switch (transport) {
3332 case NCACN_IP_TCP:
3333 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3334 presult);
3335 case NCACN_NP:
3336 return rpc_pipe_open_np(cli, interface, presult);
3337 default:
3338 return NT_STATUS_NOT_IMPLEMENTED;
3342 /****************************************************************************
3343 Open a named pipe to an SMB server and bind anonymously.
3344 ****************************************************************************/
3346 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3347 enum dcerpc_transport_t transport,
3348 const struct ndr_syntax_id *interface,
3349 struct rpc_pipe_client **presult)
3351 struct rpc_pipe_client *result;
3352 struct pipe_auth_data *auth;
3353 NTSTATUS status;
3355 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3356 if (!NT_STATUS_IS_OK(status)) {
3357 return status;
3360 status = rpccli_anon_bind_data(result, &auth);
3361 if (!NT_STATUS_IS_OK(status)) {
3362 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3363 nt_errstr(status)));
3364 TALLOC_FREE(result);
3365 return status;
3369 * This is a bit of an abstraction violation due to the fact that an
3370 * anonymous bind on an authenticated SMB inherits the user/domain
3371 * from the enclosing SMB creds
3374 TALLOC_FREE(auth->user_name);
3375 TALLOC_FREE(auth->domain);
3377 auth->user_name = talloc_strdup(auth, cli->user_name);
3378 auth->domain = talloc_strdup(auth, cli->domain);
3379 auth->user_session_key = data_blob_talloc(auth,
3380 cli->user_session_key.data,
3381 cli->user_session_key.length);
3383 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3384 TALLOC_FREE(result);
3385 return NT_STATUS_NO_MEMORY;
3388 status = rpc_pipe_bind(result, auth);
3389 if (!NT_STATUS_IS_OK(status)) {
3390 int lvl = 0;
3391 if (ndr_syntax_id_equal(interface,
3392 &ndr_table_dssetup.syntax_id)) {
3393 /* non AD domains just don't have this pipe, avoid
3394 * level 0 statement in that case - gd */
3395 lvl = 3;
3397 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3398 "%s failed with error %s\n",
3399 get_pipe_name_from_syntax(talloc_tos(), interface),
3400 nt_errstr(status) ));
3401 TALLOC_FREE(result);
3402 return status;
3405 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3406 "%s and bound anonymously.\n",
3407 get_pipe_name_from_syntax(talloc_tos(), interface),
3408 cli->desthost));
3410 *presult = result;
3411 return NT_STATUS_OK;
3414 /****************************************************************************
3415 ****************************************************************************/
3417 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3418 const struct ndr_syntax_id *interface,
3419 struct rpc_pipe_client **presult)
3421 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3422 interface, presult);
3425 /****************************************************************************
3426 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3427 ****************************************************************************/
3429 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3430 const struct ndr_syntax_id *interface,
3431 enum dcerpc_transport_t transport,
3432 enum pipe_auth_type auth_type,
3433 enum dcerpc_AuthLevel auth_level,
3434 const char *domain,
3435 const char *username,
3436 const char *password,
3437 struct rpc_pipe_client **presult)
3439 struct rpc_pipe_client *result;
3440 struct pipe_auth_data *auth;
3441 NTSTATUS status;
3443 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3444 if (!NT_STATUS_IS_OK(status)) {
3445 return status;
3448 status = rpccli_ntlmssp_bind_data(
3449 result, auth_type, auth_level, domain, username,
3450 password, &auth);
3451 if (!NT_STATUS_IS_OK(status)) {
3452 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3453 nt_errstr(status)));
3454 goto err;
3457 status = rpc_pipe_bind(result, auth);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3460 nt_errstr(status) ));
3461 goto err;
3464 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3465 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3466 get_pipe_name_from_syntax(talloc_tos(), interface),
3467 cli->desthost, domain, username ));
3469 *presult = result;
3470 return NT_STATUS_OK;
3472 err:
3474 TALLOC_FREE(result);
3475 return status;
3478 /****************************************************************************
3479 External interface.
3480 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3481 ****************************************************************************/
3483 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3484 const struct ndr_syntax_id *interface,
3485 enum dcerpc_transport_t transport,
3486 enum dcerpc_AuthLevel auth_level,
3487 const char *domain,
3488 const char *username,
3489 const char *password,
3490 struct rpc_pipe_client **presult)
3492 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3493 interface,
3494 transport,
3495 PIPE_AUTH_TYPE_NTLMSSP,
3496 auth_level,
3497 domain,
3498 username,
3499 password,
3500 presult);
3503 /****************************************************************************
3504 External interface.
3505 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3506 ****************************************************************************/
3508 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3509 const struct ndr_syntax_id *interface,
3510 enum dcerpc_transport_t transport,
3511 enum dcerpc_AuthLevel auth_level,
3512 const char *domain,
3513 const char *username,
3514 const char *password,
3515 struct rpc_pipe_client **presult)
3517 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3518 interface,
3519 transport,
3520 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3521 auth_level,
3522 domain,
3523 username,
3524 password,
3525 presult);
3528 /****************************************************************************
3529 Get a the schannel session key out of an already opened netlogon pipe.
3530 ****************************************************************************/
3531 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3532 struct cli_state *cli,
3533 const char *domain,
3534 uint32 *pneg_flags)
3536 enum netr_SchannelType sec_chan_type = 0;
3537 unsigned char machine_pwd[16];
3538 const char *machine_account;
3539 NTSTATUS status;
3541 /* Get the machine account credentials from secrets.tdb. */
3542 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3543 &sec_chan_type))
3545 DEBUG(0, ("get_schannel_session_key: could not fetch "
3546 "trust account password for domain '%s'\n",
3547 domain));
3548 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3551 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3552 cli->desthost, /* server name */
3553 domain, /* domain */
3554 global_myname(), /* client name */
3555 machine_account, /* machine account name */
3556 machine_pwd,
3557 sec_chan_type,
3558 pneg_flags);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 DEBUG(3, ("get_schannel_session_key_common: "
3562 "rpccli_netlogon_setup_creds failed with result %s "
3563 "to server %s, domain %s, machine account %s.\n",
3564 nt_errstr(status), cli->desthost, domain,
3565 machine_account ));
3566 return status;
3569 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3570 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3571 cli->desthost));
3572 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3575 return NT_STATUS_OK;;
3578 /****************************************************************************
3579 Open a netlogon pipe and get the schannel session key.
3580 Now exposed to external callers.
3581 ****************************************************************************/
3584 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3585 const char *domain,
3586 uint32 *pneg_flags,
3587 struct rpc_pipe_client **presult)
3589 struct rpc_pipe_client *netlogon_pipe = NULL;
3590 NTSTATUS status;
3592 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3593 &netlogon_pipe);
3594 if (!NT_STATUS_IS_OK(status)) {
3595 return status;
3598 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3599 pneg_flags);
3600 if (!NT_STATUS_IS_OK(status)) {
3601 TALLOC_FREE(netlogon_pipe);
3602 return status;
3605 *presult = netlogon_pipe;
3606 return NT_STATUS_OK;
3609 /****************************************************************************
3610 External interface.
3611 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3612 using session_key. sign and seal.
3614 The *pdc will be stolen onto this new pipe
3615 ****************************************************************************/
3617 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3618 const struct ndr_syntax_id *interface,
3619 enum dcerpc_transport_t transport,
3620 enum dcerpc_AuthLevel auth_level,
3621 const char *domain,
3622 struct netlogon_creds_CredentialState **pdc,
3623 struct rpc_pipe_client **presult)
3625 struct rpc_pipe_client *result;
3626 struct pipe_auth_data *auth;
3627 NTSTATUS status;
3629 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3630 if (!NT_STATUS_IS_OK(status)) {
3631 return status;
3634 status = rpccli_schannel_bind_data(result, domain, auth_level,
3635 *pdc, &auth);
3636 if (!NT_STATUS_IS_OK(status)) {
3637 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3638 nt_errstr(status)));
3639 TALLOC_FREE(result);
3640 return status;
3643 status = rpc_pipe_bind(result, auth);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3646 "cli_rpc_pipe_bind failed with error %s\n",
3647 nt_errstr(status) ));
3648 TALLOC_FREE(result);
3649 return status;
3653 * The credentials on a new netlogon pipe are the ones we are passed
3654 * in - reference them in
3656 result->dc = talloc_move(result, pdc);
3658 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3659 "for domain %s and bound using schannel.\n",
3660 get_pipe_name_from_syntax(talloc_tos(), interface),
3661 cli->desthost, domain ));
3663 *presult = result;
3664 return NT_STATUS_OK;
3667 /****************************************************************************
3668 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3669 Fetch the session key ourselves using a temporary netlogon pipe. This
3670 version uses an ntlmssp auth bound netlogon pipe to get the key.
3671 ****************************************************************************/
3673 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3674 const char *domain,
3675 const char *username,
3676 const char *password,
3677 uint32 *pneg_flags,
3678 struct rpc_pipe_client **presult)
3680 struct rpc_pipe_client *netlogon_pipe = NULL;
3681 NTSTATUS status;
3683 status = cli_rpc_pipe_open_spnego_ntlmssp(
3684 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3685 DCERPC_AUTH_LEVEL_PRIVACY,
3686 domain, username, password, &netlogon_pipe);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 return status;
3691 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3692 pneg_flags);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 TALLOC_FREE(netlogon_pipe);
3695 return status;
3698 *presult = netlogon_pipe;
3699 return NT_STATUS_OK;
3702 /****************************************************************************
3703 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3704 Fetch the session key ourselves using a temporary netlogon pipe. This version
3705 uses an ntlmssp bind to get the session key.
3706 ****************************************************************************/
3708 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3709 const struct ndr_syntax_id *interface,
3710 enum dcerpc_transport_t transport,
3711 enum dcerpc_AuthLevel auth_level,
3712 const char *domain,
3713 const char *username,
3714 const char *password,
3715 struct rpc_pipe_client **presult)
3717 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3718 struct rpc_pipe_client *netlogon_pipe = NULL;
3719 struct rpc_pipe_client *result = NULL;
3720 NTSTATUS status;
3722 status = get_schannel_session_key_auth_ntlmssp(
3723 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3726 "key from server %s for domain %s.\n",
3727 cli->desthost, domain ));
3728 return status;
3731 status = cli_rpc_pipe_open_schannel_with_key(
3732 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3733 &result);
3735 /* Now we've bound using the session key we can close the netlog pipe. */
3736 TALLOC_FREE(netlogon_pipe);
3738 if (NT_STATUS_IS_OK(status)) {
3739 *presult = result;
3741 return status;
3744 /****************************************************************************
3745 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3746 Fetch the session key ourselves using a temporary netlogon pipe.
3747 ****************************************************************************/
3749 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3750 const struct ndr_syntax_id *interface,
3751 enum dcerpc_transport_t transport,
3752 enum dcerpc_AuthLevel auth_level,
3753 const char *domain,
3754 struct rpc_pipe_client **presult)
3756 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3757 struct rpc_pipe_client *netlogon_pipe = NULL;
3758 struct rpc_pipe_client *result = NULL;
3759 NTSTATUS status;
3761 status = get_schannel_session_key(cli, domain, &neg_flags,
3762 &netlogon_pipe);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3765 "key from server %s for domain %s.\n",
3766 cli->desthost, domain ));
3767 return status;
3770 status = cli_rpc_pipe_open_schannel_with_key(
3771 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3772 &result);
3774 /* Now we've bound using the session key we can close the netlog pipe. */
3775 TALLOC_FREE(netlogon_pipe);
3777 if (NT_STATUS_IS_OK(status)) {
3778 *presult = result;
3781 return status;
3784 /****************************************************************************
3785 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3786 The idea is this can be called with service_princ, username and password all
3787 NULL so long as the caller has a TGT.
3788 ****************************************************************************/
3790 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3791 const struct ndr_syntax_id *interface,
3792 enum dcerpc_AuthLevel auth_level,
3793 const char *service_princ,
3794 const char *username,
3795 const char *password,
3796 struct rpc_pipe_client **presult)
3798 #ifdef HAVE_KRB5
3799 struct rpc_pipe_client *result;
3800 struct pipe_auth_data *auth;
3801 NTSTATUS status;
3803 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 return status;
3808 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3809 username, password, &auth);
3810 if (!NT_STATUS_IS_OK(status)) {
3811 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3812 nt_errstr(status)));
3813 TALLOC_FREE(result);
3814 return status;
3817 status = rpc_pipe_bind(result, auth);
3818 if (!NT_STATUS_IS_OK(status)) {
3819 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3820 "with error %s\n", nt_errstr(status)));
3821 TALLOC_FREE(result);
3822 return status;
3825 *presult = result;
3826 return NT_STATUS_OK;
3827 #else
3828 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3829 return NT_STATUS_NOT_IMPLEMENTED;
3830 #endif
3833 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3834 struct rpc_pipe_client *cli,
3835 DATA_BLOB *session_key)
3837 DATA_BLOB sk;
3839 if (!session_key || !cli) {
3840 return NT_STATUS_INVALID_PARAMETER;
3843 if (!cli->auth) {
3844 return NT_STATUS_INVALID_PARAMETER;
3847 switch (cli->auth->auth_type) {
3848 case PIPE_AUTH_TYPE_SCHANNEL:
3849 *session_key = data_blob_talloc(mem_ctx,
3850 cli->auth->a_u.schannel_auth->creds->session_key, 16);
3851 break;
3852 case PIPE_AUTH_TYPE_NTLMSSP:
3853 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3854 sk = auth_ntlmssp_get_session_key(cli->auth->a_u.auth_ntlmssp_state);
3855 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3856 break;
3857 case PIPE_AUTH_TYPE_KRB5:
3858 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3859 *session_key = data_blob_talloc(mem_ctx,
3860 cli->auth->a_u.kerberos_auth->session_key.data,
3861 cli->auth->a_u.kerberos_auth->session_key.length);
3862 break;
3863 case PIPE_AUTH_TYPE_NONE:
3864 *session_key = data_blob_talloc(mem_ctx,
3865 cli->auth->user_session_key.data,
3866 cli->auth->user_session_key.length);
3867 break;
3868 default:
3869 return NT_STATUS_NO_USER_SESSION_KEY;
3872 return NT_STATUS_OK;