2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
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/>.
21 #include "librpc/gen_ndr/cli_epmapper.h"
22 #include "../librpc/gen_ndr/ndr_schannel.h"
23 #include "../librpc/gen_ndr/ndr_lsa.h"
24 #include "../librpc/gen_ndr/ndr_dssetup.h"
25 #include "../librpc/gen_ndr/ndr_samr.h"
26 #include "../librpc/gen_ndr/ndr_netlogon.h"
27 #include "../librpc/gen_ndr/ndr_srvsvc.h"
28 #include "../librpc/gen_ndr/ndr_wkssvc.h"
29 #include "../librpc/gen_ndr/ndr_winreg.h"
30 #include "../librpc/gen_ndr/ndr_spoolss.h"
31 #include "../librpc/gen_ndr/ndr_dfs.h"
32 #include "../librpc/gen_ndr/ndr_echo.h"
33 #include "../librpc/gen_ndr/ndr_initshutdown.h"
34 #include "../librpc/gen_ndr/ndr_svcctl.h"
35 #include "../librpc/gen_ndr/ndr_eventlog.h"
36 #include "../librpc/gen_ndr/ndr_ntsvcs.h"
37 #include "../librpc/gen_ndr/ndr_epmapper.h"
38 #include "../librpc/gen_ndr/ndr_drsuapi.h"
39 #include "../libcli/auth/schannel.h"
40 #include "../libcli/auth/spnego.h"
42 #include "../libcli/auth/ntlmssp.h"
43 #include "rpc_client/cli_netlogon.h"
44 #include "librpc/gen_ndr/ndr_dcerpc.h"
45 #include "librpc/rpc/dcerpc.h"
48 #define DBGC_CLASS DBGC_RPC_CLI
50 static const char *get_pipe_name_from_iface(
51 TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
54 const struct ndr_interface_string_array *ep = interface->endpoints;
57 for (i=0; i<ep->count; i++) {
58 if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
67 * extract the pipe name without \\pipe from for example
68 * ncacn_np:[\\pipe\\epmapper]
70 p = strchr(ep->names[i]+15, ']');
74 return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
77 static const struct ndr_interface_table **interfaces;
79 bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
81 int num_interfaces = talloc_array_length(interfaces);
82 const struct ndr_interface_table **tmp;
85 for (i=0; i<num_interfaces; i++) {
86 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
87 &interface->syntax_id)) {
92 tmp = talloc_realloc(NULL, interfaces,
93 const struct ndr_interface_table *,
96 DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
100 interfaces[num_interfaces] = interface;
104 static bool initialize_interfaces(void)
106 if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
109 if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
112 if (!smb_register_ndr_interface(&ndr_table_samr)) {
115 if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
118 if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
121 if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
124 if (!smb_register_ndr_interface(&ndr_table_winreg)) {
127 if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
130 if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
133 if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
136 if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
139 if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
142 if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
145 if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
148 if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
151 if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
157 const struct ndr_interface_table *get_iface_from_syntax(
158 const struct ndr_syntax_id *syntax)
163 if (interfaces == NULL) {
164 if (!initialize_interfaces()) {
168 num_interfaces = talloc_array_length(interfaces);
170 for (i=0; i<num_interfaces; i++) {
171 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
172 return interfaces[i];
179 /****************************************************************************
180 Return the pipe name from the interface.
181 ****************************************************************************/
183 const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
184 const struct ndr_syntax_id *syntax)
186 const struct ndr_interface_table *interface;
190 interface = get_iface_from_syntax(syntax);
191 if (interface != NULL) {
192 result = get_pipe_name_from_iface(mem_ctx, interface);
193 if (result != NULL) {
199 * Here we should ask \\epmapper, but for now our code is only
200 * interested in the known pipes mentioned in pipe_names[]
203 guid_str = GUID_string(talloc_tos(), &syntax->uuid);
204 if (guid_str == NULL) {
207 result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
208 (int)syntax->if_version);
209 TALLOC_FREE(guid_str);
211 if (result == NULL) {
217 /********************************************************************
218 Map internal value to wire value.
219 ********************************************************************/
221 enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
225 case PIPE_AUTH_TYPE_NONE:
226 return DCERPC_AUTH_TYPE_NONE;
228 case PIPE_AUTH_TYPE_NTLMSSP:
229 return DCERPC_AUTH_TYPE_NTLMSSP;
231 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
232 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
233 return DCERPC_AUTH_TYPE_SPNEGO;
235 case PIPE_AUTH_TYPE_SCHANNEL:
236 return DCERPC_AUTH_TYPE_SCHANNEL;
238 case PIPE_AUTH_TYPE_KRB5:
239 return DCERPC_AUTH_TYPE_KRB5;
242 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
244 (unsigned int)auth_type ));
250 /********************************************************************
251 Pipe description for a DEBUG
252 ********************************************************************/
253 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
254 struct rpc_pipe_client *cli)
256 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
257 if (result == NULL) {
263 /********************************************************************
265 ********************************************************************/
267 static uint32 get_rpc_call_id(void)
269 static uint32 call_id = 0;
273 /*******************************************************************
274 Use SMBreadX to get rest of one fragment's worth of rpc data.
275 Reads the whole size or give an error message
276 ********************************************************************/
278 struct rpc_read_state {
279 struct event_context *ev;
280 struct rpc_cli_transport *transport;
286 static void rpc_read_done(struct tevent_req *subreq);
288 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
289 struct event_context *ev,
290 struct rpc_cli_transport *transport,
291 uint8_t *data, size_t size)
293 struct tevent_req *req, *subreq;
294 struct rpc_read_state *state;
296 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
301 state->transport = transport;
306 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
308 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
310 if (subreq == NULL) {
313 tevent_req_set_callback(subreq, rpc_read_done, req);
321 static void rpc_read_done(struct tevent_req *subreq)
323 struct tevent_req *req = tevent_req_callback_data(
324 subreq, struct tevent_req);
325 struct rpc_read_state *state = tevent_req_data(
326 req, struct rpc_read_state);
330 status = state->transport->read_recv(subreq, &received);
332 if (!NT_STATUS_IS_OK(status)) {
333 tevent_req_nterror(req, status);
337 state->num_read += received;
338 if (state->num_read == state->size) {
339 tevent_req_done(req);
343 subreq = state->transport->read_send(state, state->ev,
344 state->data + state->num_read,
345 state->size - state->num_read,
346 state->transport->priv);
347 if (tevent_req_nomem(subreq, req)) {
350 tevent_req_set_callback(subreq, rpc_read_done, req);
353 static NTSTATUS rpc_read_recv(struct tevent_req *req)
355 return tevent_req_simple_recv_ntstatus(req);
358 struct rpc_write_state {
359 struct event_context *ev;
360 struct rpc_cli_transport *transport;
366 static void rpc_write_done(struct tevent_req *subreq);
368 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
369 struct event_context *ev,
370 struct rpc_cli_transport *transport,
371 const uint8_t *data, size_t size)
373 struct tevent_req *req, *subreq;
374 struct rpc_write_state *state;
376 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
381 state->transport = transport;
384 state->num_written = 0;
386 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
388 subreq = transport->write_send(state, ev, data, size, transport->priv);
389 if (subreq == NULL) {
392 tevent_req_set_callback(subreq, rpc_write_done, req);
399 static void rpc_write_done(struct tevent_req *subreq)
401 struct tevent_req *req = tevent_req_callback_data(
402 subreq, struct tevent_req);
403 struct rpc_write_state *state = tevent_req_data(
404 req, struct rpc_write_state);
408 status = state->transport->write_recv(subreq, &written);
410 if (!NT_STATUS_IS_OK(status)) {
411 tevent_req_nterror(req, status);
415 state->num_written += written;
417 if (state->num_written == state->size) {
418 tevent_req_done(req);
422 subreq = state->transport->write_send(state, state->ev,
423 state->data + state->num_written,
424 state->size - state->num_written,
425 state->transport->priv);
426 if (tevent_req_nomem(subreq, req)) {
429 tevent_req_set_callback(subreq, rpc_write_done, req);
432 static NTSTATUS rpc_write_recv(struct tevent_req *req)
434 return tevent_req_simple_recv_ntstatus(req);
438 /****************************************************************************
439 Try and get a PDU's worth of data from current_pdu. If not, then read more
441 ****************************************************************************/
443 struct get_complete_frag_state {
444 struct event_context *ev;
445 struct rpc_pipe_client *cli;
450 static void get_complete_frag_got_header(struct tevent_req *subreq);
451 static void get_complete_frag_got_rest(struct tevent_req *subreq);
453 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
454 struct event_context *ev,
455 struct rpc_pipe_client *cli,
458 struct tevent_req *req, *subreq;
459 struct get_complete_frag_state *state;
463 req = tevent_req_create(mem_ctx, &state,
464 struct get_complete_frag_state);
470 state->frag_len = RPC_HEADER_LEN;
473 received = pdu->length;
474 if (received < RPC_HEADER_LEN) {
475 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
476 status = NT_STATUS_NO_MEMORY;
479 subreq = rpc_read_send(state, state->ev,
480 state->cli->transport,
481 pdu->data + received,
482 RPC_HEADER_LEN - received);
483 if (subreq == NULL) {
484 status = NT_STATUS_NO_MEMORY;
487 tevent_req_set_callback(subreq, get_complete_frag_got_header,
492 state->frag_len = dcerpc_get_frag_length(pdu);
495 * Ensure we have frag_len bytes of data.
497 if (received < state->frag_len) {
498 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
499 status = NT_STATUS_NO_MEMORY;
502 subreq = rpc_read_send(state, state->ev,
503 state->cli->transport,
504 pdu->data + received,
505 state->frag_len - received);
506 if (subreq == NULL) {
507 status = NT_STATUS_NO_MEMORY;
510 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
515 status = NT_STATUS_OK;
517 if (NT_STATUS_IS_OK(status)) {
518 tevent_req_done(req);
520 tevent_req_nterror(req, status);
522 return tevent_req_post(req, ev);
525 static void get_complete_frag_got_header(struct tevent_req *subreq)
527 struct tevent_req *req = tevent_req_callback_data(
528 subreq, struct tevent_req);
529 struct get_complete_frag_state *state = tevent_req_data(
530 req, struct get_complete_frag_state);
533 status = rpc_read_recv(subreq);
535 if (!NT_STATUS_IS_OK(status)) {
536 tevent_req_nterror(req, status);
540 state->frag_len = dcerpc_get_frag_length(state->pdu);
542 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
543 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
548 * We're here in this piece of code because we've read exactly
549 * RPC_HEADER_LEN bytes into state->pdu.
552 subreq = rpc_read_send(state, state->ev, state->cli->transport,
553 state->pdu->data + RPC_HEADER_LEN,
554 state->frag_len - RPC_HEADER_LEN);
555 if (tevent_req_nomem(subreq, req)) {
558 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
561 static void get_complete_frag_got_rest(struct tevent_req *subreq)
563 struct tevent_req *req = tevent_req_callback_data(
564 subreq, struct tevent_req);
567 status = rpc_read_recv(subreq);
569 if (!NT_STATUS_IS_OK(status)) {
570 tevent_req_nterror(req, status);
573 tevent_req_done(req);
576 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
578 return tevent_req_simple_recv_ntstatus(req);
581 /****************************************************************************
582 NTLMSSP specific sign/seal.
583 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
584 In fact I should probably abstract these into identical pieces of code... JRA.
585 ****************************************************************************/
587 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli,
588 struct ncacn_packet *pkt,
590 uint8 *p_ss_padding_len)
592 struct dcerpc_auth auth_info;
596 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
597 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
601 if (!cli->auth->a_u.ntlmssp_state) {
602 return NT_STATUS_INVALID_PARAMETER;
605 /* Ensure there's enough data for an authenticated response. */
606 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
607 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
608 + DCERPC_AUTH_TRAILER_LENGTH
609 + pkt->auth_length)) {
610 DEBUG(0, ("auth_len %u is too long.\n",
611 (unsigned int)pkt->auth_length));
612 return NT_STATUS_BUFFER_TOO_SMALL;
615 /* get the auth blob at the end of the packet */
616 blob = data_blob_const(pdu->data + pkt->frag_length
617 - DCERPC_AUTH_TRAILER_LENGTH
619 DCERPC_AUTH_TRAILER_LENGTH
622 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
623 if (!NT_STATUS_IS_OK(status)) {
624 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
628 /* Ensure auth_pad_len fits into the packet. */
629 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
630 + auth_info.auth_pad_length
631 + DCERPC_AUTH_TRAILER_LENGTH
632 + pkt->auth_length) {
633 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
634 "too large (%u), auth_len (%u), frag_len = (%u).\n",
635 (unsigned int)auth_info.auth_pad_length,
636 (unsigned int)pkt->auth_length,
637 (unsigned int)pkt->frag_length));
638 return NT_STATUS_BUFFER_TOO_SMALL;
642 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
643 * after the RPC header.
644 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
645 * functions as NTLMv2 checks the rpc headers also.
648 switch (cli->auth->auth_level) {
649 case DCERPC_AUTH_LEVEL_PRIVACY:
650 /* Data is encrypted. */
651 status = ntlmssp_unseal_packet(
652 cli->auth->a_u.ntlmssp_state,
653 pdu->data + DCERPC_RESPONSE_LENGTH,
655 - DCERPC_RESPONSE_LENGTH
656 - DCERPC_AUTH_TRAILER_LENGTH
659 pkt->frag_length - pkt->auth_length,
660 &auth_info.credentials);
661 if (!NT_STATUS_IS_OK(status)) {
662 DEBUG(0, ("failed to unseal packet from %s."
664 rpccli_pipe_txt(talloc_tos(), cli),
670 case DCERPC_AUTH_LEVEL_INTEGRITY:
671 /* Data is signed. */
672 status = ntlmssp_check_packet(
673 cli->auth->a_u.ntlmssp_state,
674 pdu->data + DCERPC_RESPONSE_LENGTH,
676 - DCERPC_RESPONSE_LENGTH
677 - DCERPC_AUTH_TRAILER_LENGTH
680 pkt->frag_length - pkt->auth_length,
681 &auth_info.credentials);
682 if (!NT_STATUS_IS_OK(status)) {
683 DEBUG(0, ("check signing failed on packet from %s."
685 rpccli_pipe_txt(talloc_tos(), cli),
692 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
693 "auth level %d\n", cli->auth->auth_level));
694 return NT_STATUS_INVALID_INFO_CLASS;
698 * Remember the padding length. We must remove it from the real data
699 * stream once the sign/seal is done.
702 *p_ss_padding_len = auth_info.auth_pad_length;
707 /****************************************************************************
708 schannel specific sign/seal.
709 ****************************************************************************/
711 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli,
712 struct ncacn_packet *pkt,
714 uint8 *p_ss_padding_len)
716 struct dcerpc_auth auth_info;
720 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
721 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
725 if (pkt->auth_length < NL_AUTH_SIGNATURE_SIZE) {
726 DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length));
727 return NT_STATUS_INVALID_PARAMETER;
730 if (!cli->auth->a_u.schannel_auth) {
731 return NT_STATUS_INVALID_PARAMETER;
734 /* Ensure there's enough data for an authenticated response. */
735 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
736 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
737 + DCERPC_AUTH_TRAILER_LENGTH
738 + pkt->auth_length)) {
739 DEBUG(0, ("auth_len %u is too long.\n",
740 (unsigned int)pkt->auth_length));
741 return NT_STATUS_INVALID_PARAMETER;
744 /* get the auth blob at the end of the packet */
745 blob = data_blob_const(pdu->data + pkt->frag_length
746 - DCERPC_AUTH_TRAILER_LENGTH
748 DCERPC_AUTH_TRAILER_LENGTH
752 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
753 if (!NT_STATUS_IS_OK(status)) {
754 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
758 /* Ensure auth_pad_len fits into the packet. */
759 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
760 + auth_info.auth_pad_length
761 + DCERPC_AUTH_TRAILER_LENGTH
762 + pkt->auth_length) {
763 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
764 "too large (%u), auth_len (%u), frag_len = (%u).\n",
765 (unsigned int)auth_info.auth_pad_length,
766 (unsigned int)pkt->auth_length,
767 (unsigned int)pkt->frag_length));
768 return NT_STATUS_BUFFER_TOO_SMALL;
771 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
772 DEBUG(0, ("Invalid auth info %d on schannel\n",
773 auth_info.auth_type));
774 return NT_STATUS_BUFFER_TOO_SMALL;
777 if (DEBUGLEVEL >= 10) {
778 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_info.credentials);
781 switch (cli->auth->auth_level) {
782 case DCERPC_AUTH_LEVEL_PRIVACY:
783 status = netsec_incoming_packet(
784 cli->auth->a_u.schannel_auth,
787 pdu->data + DCERPC_RESPONSE_LENGTH,
789 - DCERPC_RESPONSE_LENGTH
790 - DCERPC_AUTH_TRAILER_LENGTH
792 &auth_info.credentials);
794 case DCERPC_AUTH_LEVEL_INTEGRITY:
795 status = netsec_incoming_packet(
796 cli->auth->a_u.schannel_auth,
799 pdu->data + DCERPC_RESPONSE_LENGTH,
801 - DCERPC_RESPONSE_LENGTH
802 - DCERPC_AUTH_TRAILER_LENGTH
804 &auth_info.credentials);
807 status = NT_STATUS_INTERNAL_ERROR;
811 if (!NT_STATUS_IS_OK(status)) {
812 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
813 "Connection to %s (%s).\n",
814 rpccli_pipe_txt(talloc_tos(), cli),
816 return NT_STATUS_INVALID_PARAMETER;
820 * Remember the padding length. We must remove it from the real data
821 * stream once the sign/seal is done.
824 *p_ss_padding_len = auth_info.auth_pad_length;
829 /****************************************************************************
830 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
831 ****************************************************************************/
833 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli,
834 struct ncacn_packet *pkt,
836 uint8 *p_ss_padding_len)
838 NTSTATUS ret = NT_STATUS_OK;
840 /* Paranioa checks for auth_len. */
841 if (pkt->auth_length) {
842 if (pkt->auth_length > pkt->frag_length) {
843 return NT_STATUS_INVALID_PARAMETER;
846 if ((pkt->auth_length
847 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
848 < pkt->auth_length) ||
850 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
851 < (unsigned int)DCERPC_AUTH_TRAILER_LENGTH)) {
852 /* Integer wrap attempt. */
853 return NT_STATUS_INVALID_PARAMETER;
858 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
861 switch(cli->auth->auth_type) {
862 case PIPE_AUTH_TYPE_NONE:
863 if (pkt->auth_length) {
864 DEBUG(3, ("cli_pipe_validate_rpc_response: "
865 "Connection to %s - got non-zero "
867 rpccli_pipe_txt(talloc_tos(), cli),
868 (unsigned int)pkt->auth_length));
869 return NT_STATUS_INVALID_PARAMETER;
873 case PIPE_AUTH_TYPE_NTLMSSP:
874 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
875 ret = cli_pipe_verify_ntlmssp(cli, pkt, pdu,
877 if (!NT_STATUS_IS_OK(ret)) {
882 case PIPE_AUTH_TYPE_SCHANNEL:
883 ret = cli_pipe_verify_schannel(cli, pkt, pdu,
885 if (!NT_STATUS_IS_OK(ret)) {
890 case PIPE_AUTH_TYPE_KRB5:
891 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
893 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
894 "to %s - unknown internal auth type %u.\n",
895 rpccli_pipe_txt(talloc_tos(), cli),
896 cli->auth->auth_type ));
897 return NT_STATUS_INVALID_INFO_CLASS;
903 /****************************************************************************
904 Do basic authentication checks on an incoming pdu.
905 ****************************************************************************/
907 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
908 struct rpc_pipe_client *cli,
909 struct ncacn_packet *pkt,
911 uint8_t expected_pkt_type,
913 DATA_BLOB *reply_pdu)
915 NTSTATUS ret = NT_STATUS_OK;
916 uint8 ss_padding_len = 0;
918 ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false);
919 if (!NT_STATUS_IS_OK(ret)) {
923 if (pdu->length != pkt->frag_length) {
924 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
925 (unsigned int)pdu->length,
926 (unsigned int)pkt->frag_length));
927 return NT_STATUS_INVALID_PARAMETER;
931 * Point the return values at the real data including the RPC
932 * header. Just in case the caller wants it.
936 /* Ensure we have the correct type. */
937 switch (pkt->ptype) {
938 case DCERPC_PKT_ALTER_RESP:
939 case DCERPC_PKT_BIND_ACK:
941 /* Alter context and bind ack share the same packet definitions. */
945 case DCERPC_PKT_RESPONSE:
947 /* Here's where we deal with incoming sign/seal. */
948 ret = cli_pipe_validate_rpc_response(cli, pkt, pdu,
950 if (!NT_STATUS_IS_OK(ret)) {
954 /* Point the return values at the NDR data.
955 * Remember to remove any ss padding. */
956 rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
958 if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
959 return NT_STATUS_BUFFER_TOO_SMALL;
962 rdata->length = pdu->length
963 - DCERPC_RESPONSE_LENGTH
966 /* Remember to remove the auth footer. */
967 if (pkt->auth_length) {
968 /* We've already done integer wrap tests on auth_len in
969 cli_pipe_validate_rpc_response(). */
970 if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH
971 + pkt->auth_length) {
972 return NT_STATUS_BUFFER_TOO_SMALL;
974 rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH
978 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
979 pdu->length, rdata->length, ss_padding_len));
982 * If this is the first reply, and the allocation hint is
983 * reasonable, try and set up the reply_pdu DATA_BLOB to the
987 if ((reply_pdu->length == 0) &&
988 pkt->u.response.alloc_hint &&
989 (pkt->u.response.alloc_hint < 15*1024*1024)) {
990 if (!data_blob_realloc(mem_ctx, reply_pdu,
991 pkt->u.response.alloc_hint)) {
992 DEBUG(0, ("reply alloc hint %d too "
993 "large to allocate\n",
994 (int)pkt->u.response.alloc_hint));
995 return NT_STATUS_NO_MEMORY;
1001 case DCERPC_PKT_BIND_NAK:
1002 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1003 "received from %s!\n",
1004 rpccli_pipe_txt(talloc_tos(), cli)));
1005 /* Use this for now... */
1006 return NT_STATUS_NETWORK_ACCESS_DENIED;
1008 case DCERPC_PKT_FAULT:
1010 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1011 "code %s received from %s!\n",
1012 dcerpc_errstr(talloc_tos(),
1013 pkt->u.fault.status),
1014 rpccli_pipe_txt(talloc_tos(), cli)));
1016 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
1017 return NT_STATUS_UNSUCCESSFUL;
1019 return NT_STATUS(pkt->u.fault.status);
1023 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1024 (unsigned int)pkt->ptype,
1025 rpccli_pipe_txt(talloc_tos(), cli)));
1026 return NT_STATUS_INVALID_INFO_CLASS;
1029 if (pkt->ptype != expected_pkt_type) {
1030 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1031 "got an unexpected RPC packet type - %u, not %u\n",
1032 rpccli_pipe_txt(talloc_tos(), cli),
1034 expected_pkt_type));
1035 return NT_STATUS_INVALID_INFO_CLASS;
1038 /* Do this just before return - we don't want to modify any rpc header
1039 data before now as we may have needed to do cryptographic actions on
1042 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
1043 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1044 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1045 "setting fragment first/last ON.\n"));
1046 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
1047 DCERPC_PFC_FLAG_LAST;
1050 return NT_STATUS_OK;
1053 /****************************************************************************
1054 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1055 ****************************************************************************/
1057 struct cli_api_pipe_state {
1058 struct event_context *ev;
1059 struct rpc_cli_transport *transport;
1064 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1065 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1066 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1068 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1069 struct event_context *ev,
1070 struct rpc_cli_transport *transport,
1071 uint8_t *data, size_t data_len,
1072 uint32_t max_rdata_len)
1074 struct tevent_req *req, *subreq;
1075 struct cli_api_pipe_state *state;
1078 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1083 state->transport = transport;
1085 if (max_rdata_len < RPC_HEADER_LEN) {
1087 * For a RPC reply we always need at least RPC_HEADER_LEN
1088 * bytes. We check this here because we will receive
1089 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1091 status = NT_STATUS_INVALID_PARAMETER;
1095 if (transport->trans_send != NULL) {
1096 subreq = transport->trans_send(state, ev, data, data_len,
1097 max_rdata_len, transport->priv);
1098 if (subreq == NULL) {
1101 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1106 * If the transport does not provide a "trans" routine, i.e. for
1107 * example the ncacn_ip_tcp transport, do the write/read step here.
1110 subreq = rpc_write_send(state, ev, transport, data, data_len);
1111 if (subreq == NULL) {
1114 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1118 tevent_req_nterror(req, status);
1119 return tevent_req_post(req, ev);
1125 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1127 struct tevent_req *req = tevent_req_callback_data(
1128 subreq, struct tevent_req);
1129 struct cli_api_pipe_state *state = tevent_req_data(
1130 req, struct cli_api_pipe_state);
1133 status = state->transport->trans_recv(subreq, state, &state->rdata,
1135 TALLOC_FREE(subreq);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 tevent_req_nterror(req, status);
1140 tevent_req_done(req);
1143 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1145 struct tevent_req *req = tevent_req_callback_data(
1146 subreq, struct tevent_req);
1147 struct cli_api_pipe_state *state = tevent_req_data(
1148 req, struct cli_api_pipe_state);
1151 status = rpc_write_recv(subreq);
1152 TALLOC_FREE(subreq);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 tevent_req_nterror(req, status);
1158 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1159 if (tevent_req_nomem(state->rdata, req)) {
1164 * We don't need to use rpc_read_send here, the upper layer will cope
1165 * with a short read, transport->trans_send could also return less
1166 * than state->max_rdata_len.
1168 subreq = state->transport->read_send(state, state->ev, state->rdata,
1170 state->transport->priv);
1171 if (tevent_req_nomem(subreq, req)) {
1174 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1177 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1179 struct tevent_req *req = tevent_req_callback_data(
1180 subreq, struct tevent_req);
1181 struct cli_api_pipe_state *state = tevent_req_data(
1182 req, struct cli_api_pipe_state);
1186 status = state->transport->read_recv(subreq, &received);
1187 TALLOC_FREE(subreq);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 tevent_req_nterror(req, status);
1192 state->rdata_len = received;
1193 tevent_req_done(req);
1196 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1197 uint8_t **prdata, uint32_t *prdata_len)
1199 struct cli_api_pipe_state *state = tevent_req_data(
1200 req, struct cli_api_pipe_state);
1203 if (tevent_req_is_nterror(req, &status)) {
1207 *prdata = talloc_move(mem_ctx, &state->rdata);
1208 *prdata_len = state->rdata_len;
1209 return NT_STATUS_OK;
1212 /****************************************************************************
1213 Send data on an rpc pipe via trans. The data must be the last
1214 pdu fragment of an NDR data stream.
1216 Receive response data from an rpc pipe, which may be large...
1218 Read the first fragment: unfortunately have to use SMBtrans for the first
1219 bit, then SMBreadX for subsequent bits.
1221 If first fragment received also wasn't the last fragment, continue
1222 getting fragments until we _do_ receive the last fragment.
1224 Request/Response PDU's look like the following...
1226 |<------------------PDU len----------------------------------------------->|
1227 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1229 +------------+-----------------+-------------+---------------+-------------+
1230 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1231 +------------+-----------------+-------------+---------------+-------------+
1233 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1234 signing & sealing being negotiated.
1236 ****************************************************************************/
1238 struct rpc_api_pipe_state {
1239 struct event_context *ev;
1240 struct rpc_pipe_client *cli;
1241 uint8_t expected_pkt_type;
1243 DATA_BLOB incoming_frag;
1244 struct ncacn_packet *pkt;
1246 /* Incoming reply */
1247 DATA_BLOB reply_pdu;
1248 size_t reply_pdu_offset;
1252 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1253 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1255 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1256 struct event_context *ev,
1257 struct rpc_pipe_client *cli,
1258 DATA_BLOB *data, /* Outgoing PDU */
1259 uint8_t expected_pkt_type)
1261 struct tevent_req *req, *subreq;
1262 struct rpc_api_pipe_state *state;
1263 uint16_t max_recv_frag;
1266 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1272 state->expected_pkt_type = expected_pkt_type;
1273 state->incoming_frag = data_blob_null;
1274 state->reply_pdu = data_blob_null;
1275 state->reply_pdu_offset = 0;
1276 state->endianess = DCERPC_DREP_LE;
1279 * Ensure we're not sending too much.
1281 if (data->length > cli->max_xmit_frag) {
1282 status = NT_STATUS_INVALID_PARAMETER;
1286 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1288 /* get the header first, then fetch the rest once we have
1289 * the frag_length available */
1290 max_recv_frag = RPC_HEADER_LEN;
1292 subreq = cli_api_pipe_send(state, ev, cli->transport,
1293 data->data, data->length, max_recv_frag);
1294 if (subreq == NULL) {
1297 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1301 tevent_req_nterror(req, status);
1302 return tevent_req_post(req, ev);
1308 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1310 struct tevent_req *req = tevent_req_callback_data(
1311 subreq, struct tevent_req);
1312 struct rpc_api_pipe_state *state = tevent_req_data(
1313 req, struct rpc_api_pipe_state);
1315 uint8_t *rdata = NULL;
1316 uint32_t rdata_len = 0;
1318 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1319 TALLOC_FREE(subreq);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1322 tevent_req_nterror(req, status);
1326 if (rdata == NULL) {
1327 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1328 rpccli_pipe_txt(talloc_tos(), state->cli)));
1329 tevent_req_done(req);
1334 * Move data on state->incoming_frag.
1336 state->incoming_frag.data = talloc_move(state, &rdata);
1337 state->incoming_frag.length = rdata_len;
1338 if (!state->incoming_frag.data) {
1339 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1343 /* Ensure we have enough data for a pdu. */
1344 subreq = get_complete_frag_send(state, state->ev, state->cli,
1345 &state->incoming_frag);
1346 if (tevent_req_nomem(subreq, req)) {
1349 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1352 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1354 struct tevent_req *req = tevent_req_callback_data(
1355 subreq, struct tevent_req);
1356 struct rpc_api_pipe_state *state = tevent_req_data(
1357 req, struct rpc_api_pipe_state);
1359 DATA_BLOB rdata = data_blob_null;
1361 status = get_complete_frag_recv(subreq);
1362 TALLOC_FREE(subreq);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 DEBUG(5, ("get_complete_frag failed: %s\n",
1365 nt_errstr(status)));
1366 tevent_req_nterror(req, status);
1370 state->pkt = talloc(state, struct ncacn_packet);
1372 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1376 status = cli_pipe_validate_current_pdu(state,
1377 state->cli, state->pkt,
1378 &state->incoming_frag,
1379 state->expected_pkt_type,
1383 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1384 (unsigned)state->incoming_frag.length,
1385 (unsigned)state->reply_pdu_offset,
1386 nt_errstr(status)));
1388 if (!NT_STATUS_IS_OK(status)) {
1389 tevent_req_nterror(req, status);
1393 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1394 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1396 * Set the data type correctly for big-endian data on the
1399 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1401 rpccli_pipe_txt(talloc_tos(), state->cli)));
1402 state->endianess = 0x00; /* BIG ENDIAN */
1405 * Check endianness on subsequent packets.
1407 if (state->endianess != state->pkt->drep[0]) {
1408 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1410 state->endianess?"little":"big",
1411 state->pkt->drep[0]?"little":"big"));
1412 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1416 /* Now copy the data portion out of the pdu into rbuf. */
1417 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1418 if (!data_blob_realloc(NULL, &state->reply_pdu,
1419 state->reply_pdu_offset + rdata.length)) {
1420 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1425 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1426 rdata.data, rdata.length);
1427 state->reply_pdu_offset += rdata.length;
1429 /* reset state->incoming_frag, there is no need to free it,
1430 * it will be reallocated to the right size the next time
1432 state->incoming_frag.length = 0;
1434 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1435 /* make sure the pdu length is right now that we
1436 * have all the data available (alloc hint may
1437 * have allocated more than was actually used) */
1438 state->reply_pdu.length = state->reply_pdu_offset;
1439 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1440 rpccli_pipe_txt(talloc_tos(), state->cli),
1441 (unsigned)state->reply_pdu.length));
1442 tevent_req_done(req);
1446 subreq = get_complete_frag_send(state, state->ev, state->cli,
1447 &state->incoming_frag);
1448 if (tevent_req_nomem(subreq, req)) {
1451 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1454 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1455 struct ncacn_packet **pkt,
1456 DATA_BLOB *reply_pdu)
1458 struct rpc_api_pipe_state *state = tevent_req_data(
1459 req, struct rpc_api_pipe_state);
1462 if (tevent_req_is_nterror(req, &status)) {
1466 /* return data to caller and assign it ownership of memory */
1468 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1469 reply_pdu->length = state->reply_pdu.length;
1470 state->reply_pdu.length = 0;
1472 data_blob_free(&state->reply_pdu);
1476 *pkt = talloc_steal(mem_ctx, state->pkt);
1479 return NT_STATUS_OK;
1482 /*******************************************************************
1483 Creates krb5 auth bind.
1484 ********************************************************************/
1486 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1487 enum dcerpc_AuthLevel auth_level,
1488 DATA_BLOB *auth_info)
1493 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1494 DATA_BLOB tkt = data_blob_null;
1495 DATA_BLOB tkt_wrapped = data_blob_null;
1497 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1498 a->service_principal ));
1500 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1502 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1503 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1506 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1508 a->service_principal,
1509 error_message(ret) ));
1511 data_blob_free(&tkt);
1512 return NT_STATUS_INVALID_PARAMETER;
1515 /* wrap that up in a nice GSS-API wrapping */
1516 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1518 data_blob_free(&tkt);
1520 status = dcerpc_push_dcerpc_auth(cli,
1521 DCERPC_AUTH_TYPE_KRB5,
1523 0, /* auth_pad_length */
1524 1, /* auth_context_id */
1527 if (!NT_STATUS_IS_OK(status)) {
1528 data_blob_free(&tkt_wrapped);
1532 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1533 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1535 return NT_STATUS_OK;
1537 return NT_STATUS_INVALID_PARAMETER;
1541 /*******************************************************************
1542 Creates SPNEGO NTLMSSP auth bind.
1543 ********************************************************************/
1545 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1546 enum dcerpc_AuthLevel auth_level,
1547 DATA_BLOB *auth_info)
1550 DATA_BLOB null_blob = data_blob_null;
1551 DATA_BLOB request = data_blob_null;
1552 DATA_BLOB spnego_msg = data_blob_null;
1554 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1555 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1559 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1560 data_blob_free(&request);
1564 /* Wrap this in SPNEGO. */
1565 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1567 data_blob_free(&request);
1569 status = dcerpc_push_dcerpc_auth(cli,
1570 DCERPC_AUTH_TYPE_SPNEGO,
1572 0, /* auth_pad_length */
1573 1, /* auth_context_id */
1576 if (!NT_STATUS_IS_OK(status)) {
1577 data_blob_free(&spnego_msg);
1581 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1582 dump_data(5, spnego_msg.data, spnego_msg.length);
1584 return NT_STATUS_OK;
1587 /*******************************************************************
1588 Creates NTLMSSP auth bind.
1589 ********************************************************************/
1591 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1592 enum dcerpc_AuthLevel auth_level,
1593 DATA_BLOB *auth_info)
1596 DATA_BLOB null_blob = data_blob_null;
1597 DATA_BLOB request = data_blob_null;
1599 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1600 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1604 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1605 data_blob_free(&request);
1609 status = dcerpc_push_dcerpc_auth(cli,
1610 DCERPC_AUTH_TYPE_NTLMSSP,
1612 0, /* auth_pad_length */
1613 1, /* auth_context_id */
1616 if (!NT_STATUS_IS_OK(status)) {
1617 data_blob_free(&request);
1621 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1622 dump_data(5, request.data, request.length);
1624 return NT_STATUS_OK;
1627 /*******************************************************************
1628 Creates schannel auth bind.
1629 ********************************************************************/
1631 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1632 enum dcerpc_AuthLevel auth_level,
1633 DATA_BLOB *auth_info)
1636 struct NL_AUTH_MESSAGE r;
1637 DATA_BLOB schannel_blob;
1639 /* Use lp_workgroup() if domain not specified */
1641 if (!cli->auth->domain || !cli->auth->domain[0]) {
1642 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1643 if (cli->auth->domain == NULL) {
1644 return NT_STATUS_NO_MEMORY;
1649 * Now marshall the data into the auth parse_struct.
1652 r.MessageType = NL_NEGOTIATE_REQUEST;
1653 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1654 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1655 r.oem_netbios_domain.a = cli->auth->domain;
1656 r.oem_netbios_computer.a = global_myname();
1658 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1659 if (!NT_STATUS_IS_OK(status)) {
1663 status = dcerpc_push_dcerpc_auth(cli,
1664 DCERPC_AUTH_TYPE_SCHANNEL,
1666 0, /* auth_pad_length */
1667 1, /* auth_context_id */
1670 if (!NT_STATUS_IS_OK(status)) {
1674 return NT_STATUS_OK;
1677 /*******************************************************************
1678 Creates the internals of a DCE/RPC bind request or alter context PDU.
1679 ********************************************************************/
1681 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1682 enum dcerpc_pkt_type ptype,
1684 const struct ndr_syntax_id *abstract,
1685 const struct ndr_syntax_id *transfer,
1686 const DATA_BLOB *auth_info,
1689 uint16 auth_len = auth_info->length;
1691 union dcerpc_payload u;
1692 struct dcerpc_ctx_list ctx_list;
1695 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1698 ctx_list.context_id = 0;
1699 ctx_list.num_transfer_syntaxes = 1;
1700 ctx_list.abstract_syntax = *abstract;
1701 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1703 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1704 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1705 u.bind.assoc_group_id = 0x0;
1706 u.bind.num_contexts = 1;
1707 u.bind.ctx_list = &ctx_list;
1708 u.bind.auth_info = *auth_info;
1710 status = dcerpc_push_ncacn_packet(mem_ctx,
1712 DCERPC_PFC_FLAG_FIRST |
1713 DCERPC_PFC_FLAG_LAST,
1718 if (!NT_STATUS_IS_OK(status)) {
1719 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1723 return NT_STATUS_OK;
1726 /*******************************************************************
1727 Creates a DCE/RPC bind request.
1728 ********************************************************************/
1730 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1731 struct rpc_pipe_client *cli,
1733 const struct ndr_syntax_id *abstract,
1734 const struct ndr_syntax_id *transfer,
1735 enum pipe_auth_type auth_type,
1736 enum dcerpc_AuthLevel auth_level,
1739 DATA_BLOB auth_info = data_blob_null;
1740 NTSTATUS ret = NT_STATUS_OK;
1742 switch (auth_type) {
1743 case PIPE_AUTH_TYPE_SCHANNEL:
1744 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1745 if (!NT_STATUS_IS_OK(ret)) {
1750 case PIPE_AUTH_TYPE_NTLMSSP:
1751 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1752 if (!NT_STATUS_IS_OK(ret)) {
1757 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1758 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1759 if (!NT_STATUS_IS_OK(ret)) {
1764 case PIPE_AUTH_TYPE_KRB5:
1765 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1766 if (!NT_STATUS_IS_OK(ret)) {
1771 case PIPE_AUTH_TYPE_NONE:
1775 /* "Can't" happen. */
1776 return NT_STATUS_INVALID_INFO_CLASS;
1779 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1789 /*******************************************************************
1790 Create and add the NTLMSSP sign/seal auth header and data.
1791 ********************************************************************/
1793 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1794 uint32 ss_padding_len,
1797 DATA_BLOB auth_info;
1799 DATA_BLOB auth_blob = data_blob_null;
1800 uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
1802 if (!cli->auth->a_u.ntlmssp_state) {
1803 return NT_STATUS_INVALID_PARAMETER;
1806 /* marshall the dcerpc_auth with an actually empty auth_blob.
1807 * this is needed because the ntmlssp signature includes the
1809 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1810 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1811 cli->auth->auth_level,
1813 1 /* context id. */,
1816 if (!NT_STATUS_IS_OK(status)) {
1820 /* append the header */
1821 if (!data_blob_append(NULL, rpc_out,
1822 auth_info.data, auth_info.length)) {
1823 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1824 (unsigned int)auth_info.length));
1825 return NT_STATUS_NO_MEMORY;
1827 data_blob_free(&auth_info);
1829 switch (cli->auth->auth_level) {
1830 case DCERPC_AUTH_LEVEL_PRIVACY:
1831 /* Data portion is encrypted. */
1832 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1835 + DCERPC_RESPONSE_LENGTH,
1840 if (!NT_STATUS_IS_OK(status)) {
1845 case DCERPC_AUTH_LEVEL_INTEGRITY:
1846 /* Data is signed. */
1847 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1850 + DCERPC_RESPONSE_LENGTH,
1855 if (!NT_STATUS_IS_OK(status)) {
1862 smb_panic("bad auth level");
1864 return NT_STATUS_INVALID_PARAMETER;
1867 /* Finally attach the blob. */
1868 if (!data_blob_append(NULL, rpc_out,
1869 auth_blob.data, auth_blob.length)) {
1870 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1871 (unsigned int)auth_info.length));
1872 return NT_STATUS_NO_MEMORY;
1874 data_blob_free(&auth_blob);
1876 return NT_STATUS_OK;
1879 /*******************************************************************
1880 Create and add the schannel sign/seal auth header and data.
1881 ********************************************************************/
1883 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1884 uint32 ss_padding_len,
1887 DATA_BLOB auth_info;
1888 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1889 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
1890 size_t data_and_pad_len = rpc_out->length
1891 - DCERPC_RESPONSE_LENGTH;
1896 return NT_STATUS_INVALID_PARAMETER;
1899 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1902 switch (cli->auth->auth_level) {
1903 case DCERPC_AUTH_LEVEL_PRIVACY:
1904 status = netsec_outgoing_packet(sas,
1911 case DCERPC_AUTH_LEVEL_INTEGRITY:
1912 status = netsec_outgoing_packet(sas,
1920 status = NT_STATUS_INTERNAL_ERROR;
1924 if (!NT_STATUS_IS_OK(status)) {
1925 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1926 nt_errstr(status)));
1930 if (DEBUGLEVEL >= 10) {
1931 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1934 /* Finally marshall the blob. */
1935 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1936 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1937 cli->auth->auth_level,
1939 1 /* context id. */,
1942 if (!NT_STATUS_IS_OK(status)) {
1945 data_blob_free(&blob);
1947 if (!data_blob_append(NULL, rpc_out,
1948 auth_info.data, auth_info.length)) {
1949 return NT_STATUS_NO_MEMORY;
1951 data_blob_free(&auth_info);
1953 return NT_STATUS_OK;
1956 /*******************************************************************
1957 Calculate how much data we're going to send in this packet, also
1958 work out any sign/seal padding length.
1959 ********************************************************************/
1961 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1965 uint32 *p_ss_padding)
1967 uint32 data_space, data_len;
1970 if ((data_left > 0) && (sys_random() % 2)) {
1971 data_left = MAX(data_left/2, 1);
1975 switch (cli->auth->auth_level) {
1976 case DCERPC_AUTH_LEVEL_NONE:
1977 case DCERPC_AUTH_LEVEL_CONNECT:
1978 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1979 data_len = MIN(data_space, data_left);
1982 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1985 case DCERPC_AUTH_LEVEL_INTEGRITY:
1986 case DCERPC_AUTH_LEVEL_PRIVACY:
1987 /* Treat the same for all authenticated rpc requests. */
1988 switch(cli->auth->auth_type) {
1989 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1990 case PIPE_AUTH_TYPE_NTLMSSP:
1991 *p_auth_len = NTLMSSP_SIG_SIZE;
1993 case PIPE_AUTH_TYPE_SCHANNEL:
1994 *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1997 smb_panic("bad auth type");
2001 data_space = cli->max_xmit_frag
2002 - DCERPC_REQUEST_LENGTH
2003 - DCERPC_AUTH_TRAILER_LENGTH
2006 data_len = MIN(data_space, data_left);
2008 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2009 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2011 *p_frag_len = DCERPC_REQUEST_LENGTH
2012 + data_len + *p_ss_padding
2013 + DCERPC_AUTH_TRAILER_LENGTH
2018 smb_panic("bad auth level");
2024 /*******************************************************************
2026 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2027 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2028 and deals with signing/sealing details.
2029 ********************************************************************/
2031 struct rpc_api_pipe_req_state {
2032 struct event_context *ev;
2033 struct rpc_pipe_client *cli;
2036 DATA_BLOB *req_data;
2037 uint32_t req_data_sent;
2039 DATA_BLOB reply_pdu;
2042 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2043 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2044 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2045 bool *is_last_frag);
2047 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2048 struct event_context *ev,
2049 struct rpc_pipe_client *cli,
2051 DATA_BLOB *req_data)
2053 struct tevent_req *req, *subreq;
2054 struct rpc_api_pipe_req_state *state;
2058 req = tevent_req_create(mem_ctx, &state,
2059 struct rpc_api_pipe_req_state);
2065 state->op_num = op_num;
2066 state->req_data = req_data;
2067 state->req_data_sent = 0;
2068 state->call_id = get_rpc_call_id();
2069 state->reply_pdu = data_blob_null;
2070 state->rpc_out = data_blob_null;
2072 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2073 + RPC_MAX_SIGN_SIZE) {
2074 /* Server is screwed up ! */
2075 status = NT_STATUS_INVALID_PARAMETER;
2079 status = prepare_next_frag(state, &is_last_frag);
2080 if (!NT_STATUS_IS_OK(status)) {
2085 subreq = rpc_api_pipe_send(state, ev, state->cli,
2087 DCERPC_PKT_RESPONSE);
2088 if (subreq == NULL) {
2091 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2093 subreq = rpc_write_send(state, ev, cli->transport,
2094 state->rpc_out.data,
2095 state->rpc_out.length);
2096 if (subreq == NULL) {
2099 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2105 tevent_req_nterror(req, status);
2106 return tevent_req_post(req, ev);
2112 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2115 uint32_t data_sent_thistime;
2119 uint32_t ss_padding;
2121 char pad[8] = { 0, };
2123 union dcerpc_payload u;
2125 data_left = state->req_data->length - state->req_data_sent;
2127 data_sent_thistime = calculate_data_len_tosend(
2128 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2130 if (state->req_data_sent == 0) {
2131 flags = DCERPC_PFC_FLAG_FIRST;
2134 if (data_sent_thistime == data_left) {
2135 flags |= DCERPC_PFC_FLAG_LAST;
2138 data_blob_free(&state->rpc_out);
2140 ZERO_STRUCT(u.request);
2142 u.request.alloc_hint = state->req_data->length;
2143 u.request.context_id = 0;
2144 u.request.opnum = state->op_num;
2146 status = dcerpc_push_ncacn_packet(state,
2153 if (!NT_STATUS_IS_OK(status)) {
2157 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2158 * compute it right for requests */
2159 dcerpc_set_frag_length(&state->rpc_out, frag_len);
2161 /* Copy in the data, plus any ss padding. */
2162 if (!data_blob_append(NULL, &state->rpc_out,
2163 state->req_data->data + state->req_data_sent,
2164 data_sent_thistime)) {
2165 return NT_STATUS_NO_MEMORY;
2169 /* Copy the sign/seal padding data. */
2170 if (!data_blob_append(NULL, &state->rpc_out,
2172 return NT_STATUS_NO_MEMORY;
2176 /* Generate any auth sign/seal and add the auth footer. */
2177 switch (state->cli->auth->auth_type) {
2178 case PIPE_AUTH_TYPE_NONE:
2179 status = NT_STATUS_OK;
2181 case PIPE_AUTH_TYPE_NTLMSSP:
2182 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2183 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2186 case PIPE_AUTH_TYPE_SCHANNEL:
2187 status = add_schannel_auth_footer(state->cli, ss_padding,
2191 status = NT_STATUS_INVALID_PARAMETER;
2195 state->req_data_sent += data_sent_thistime;
2196 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2201 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2203 struct tevent_req *req = tevent_req_callback_data(
2204 subreq, struct tevent_req);
2205 struct rpc_api_pipe_req_state *state = tevent_req_data(
2206 req, struct rpc_api_pipe_req_state);
2210 status = rpc_write_recv(subreq);
2211 TALLOC_FREE(subreq);
2212 if (!NT_STATUS_IS_OK(status)) {
2213 tevent_req_nterror(req, status);
2217 status = prepare_next_frag(state, &is_last_frag);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 tevent_req_nterror(req, status);
2224 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2226 DCERPC_PKT_RESPONSE);
2227 if (tevent_req_nomem(subreq, req)) {
2230 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2232 subreq = rpc_write_send(state, state->ev,
2233 state->cli->transport,
2234 state->rpc_out.data,
2235 state->rpc_out.length);
2236 if (tevent_req_nomem(subreq, req)) {
2239 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2244 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2246 struct tevent_req *req = tevent_req_callback_data(
2247 subreq, struct tevent_req);
2248 struct rpc_api_pipe_req_state *state = tevent_req_data(
2249 req, struct rpc_api_pipe_req_state);
2252 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2253 TALLOC_FREE(subreq);
2254 if (!NT_STATUS_IS_OK(status)) {
2255 tevent_req_nterror(req, status);
2258 tevent_req_done(req);
2261 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2262 DATA_BLOB *reply_pdu)
2264 struct rpc_api_pipe_req_state *state = tevent_req_data(
2265 req, struct rpc_api_pipe_req_state);
2268 if (tevent_req_is_nterror(req, &status)) {
2270 * We always have to initialize to reply pdu, even if there is
2271 * none. The rpccli_* caller routines expect this.
2273 *reply_pdu = data_blob_null;
2277 /* return data to caller and assign it ownership of memory */
2278 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2279 reply_pdu->length = state->reply_pdu.length;
2280 state->reply_pdu.length = 0;
2282 return NT_STATUS_OK;
2286 /****************************************************************************
2287 Set the handle state.
2288 ****************************************************************************/
2290 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2291 const char *pipe_name, uint16 device_state)
2293 bool state_set = False;
2295 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2296 char *rparam = NULL;
2298 uint32 rparam_len, rdata_len;
2300 if (pipe_name == NULL)
2303 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2304 cli->fnum, pipe_name, device_state));
2306 /* create parameters: device state */
2307 SSVAL(param, 0, device_state);
2309 /* create setup parameters. */
2311 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2313 /* send the data on \PIPE\ */
2314 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2315 setup, 2, 0, /* setup, length, max */
2316 param, 2, 0, /* param, length, max */
2317 NULL, 0, 1024, /* data, length, max */
2318 &rparam, &rparam_len, /* return param, length */
2319 &rdata, &rdata_len)) /* return data, length */
2321 DEBUG(5, ("Set Handle state: return OK\n"));
2332 /****************************************************************************
2333 Check the rpc bind acknowledge response.
2334 ****************************************************************************/
2336 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2337 const struct ndr_syntax_id *transfer)
2339 struct dcerpc_ack_ctx ctx;
2341 if (r->secondary_address_size == 0) {
2342 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2345 if (r->num_results < 1 || !r->ctx_list) {
2349 ctx = r->ctx_list[0];
2351 /* check the transfer syntax */
2352 if ((ctx.syntax.if_version != transfer->if_version) ||
2353 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2354 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2358 if (r->num_results != 0x1 || ctx.result != 0) {
2359 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2360 r->num_results, ctx.reason));
2363 DEBUG(5,("check_bind_response: accepted!\n"));
2367 /*******************************************************************
2368 Creates a DCE/RPC bind authentication response.
2369 This is the packet that is sent back to the server once we
2370 have received a BIND-ACK, to finish the third leg of
2371 the authentication handshake.
2372 ********************************************************************/
2374 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
2375 struct rpc_pipe_client *cli,
2377 enum pipe_auth_type auth_type,
2378 enum dcerpc_AuthLevel auth_level,
2379 DATA_BLOB *pauth_blob,
2383 union dcerpc_payload u;
2387 status = dcerpc_push_dcerpc_auth(mem_ctx,
2388 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2390 0, /* auth_pad_length */
2391 1, /* auth_context_id */
2393 &u.auth3.auth_info);
2394 if (!NT_STATUS_IS_OK(status)) {
2398 status = dcerpc_push_ncacn_packet(mem_ctx,
2400 DCERPC_PFC_FLAG_FIRST |
2401 DCERPC_PFC_FLAG_LAST,
2406 data_blob_free(&u.auth3.auth_info);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2412 return NT_STATUS_OK;
2415 /*******************************************************************
2416 Creates a DCE/RPC bind alter context authentication request which
2417 may contain a spnego auth blobl
2418 ********************************************************************/
2420 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2422 const struct ndr_syntax_id *abstract,
2423 const struct ndr_syntax_id *transfer,
2424 enum dcerpc_AuthLevel auth_level,
2425 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2428 DATA_BLOB auth_info;
2431 status = dcerpc_push_dcerpc_auth(mem_ctx,
2432 DCERPC_AUTH_TYPE_SPNEGO,
2434 0, /* auth_pad_length */
2435 1, /* auth_context_id */
2438 if (!NT_STATUS_IS_OK(status)) {
2442 status = create_bind_or_alt_ctx_internal(mem_ctx,
2449 data_blob_free(&auth_info);
2453 /****************************************************************************
2455 ****************************************************************************/
2457 struct rpc_pipe_bind_state {
2458 struct event_context *ev;
2459 struct rpc_pipe_client *cli;
2461 uint32_t rpc_call_id;
2464 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2465 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2466 struct rpc_pipe_bind_state *state,
2467 struct ncacn_packet *r);
2468 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2469 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2470 struct rpc_pipe_bind_state *state,
2471 struct ncacn_packet *r,
2472 DATA_BLOB *reply_pdu);
2473 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2475 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2476 struct event_context *ev,
2477 struct rpc_pipe_client *cli,
2478 struct cli_pipe_auth_data *auth)
2480 struct tevent_req *req, *subreq;
2481 struct rpc_pipe_bind_state *state;
2484 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2489 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2490 rpccli_pipe_txt(talloc_tos(), cli),
2491 (unsigned int)auth->auth_type,
2492 (unsigned int)auth->auth_level ));
2496 state->rpc_call_id = get_rpc_call_id();
2497 state->rpc_out = data_blob_null;
2499 cli->auth = talloc_move(cli, &auth);
2501 /* Marshall the outgoing data. */
2502 status = create_rpc_bind_req(state, cli,
2504 &cli->abstract_syntax,
2505 &cli->transfer_syntax,
2506 cli->auth->auth_type,
2507 cli->auth->auth_level,
2510 if (!NT_STATUS_IS_OK(status)) {
2514 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2515 DCERPC_PKT_BIND_ACK);
2516 if (subreq == NULL) {
2519 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2523 tevent_req_nterror(req, status);
2524 return tevent_req_post(req, ev);
2530 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2532 struct tevent_req *req = tevent_req_callback_data(
2533 subreq, struct tevent_req);
2534 struct rpc_pipe_bind_state *state = tevent_req_data(
2535 req, struct rpc_pipe_bind_state);
2536 DATA_BLOB reply_pdu;
2537 struct ncacn_packet *pkt;
2540 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2541 TALLOC_FREE(subreq);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2544 rpccli_pipe_txt(talloc_tos(), state->cli),
2545 nt_errstr(status)));
2546 tevent_req_nterror(req, status);
2550 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2551 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2552 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2556 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2557 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2560 * For authenticated binds we may need to do 3 or 4 leg binds.
2563 switch(state->cli->auth->auth_type) {
2565 case PIPE_AUTH_TYPE_NONE:
2566 case PIPE_AUTH_TYPE_SCHANNEL:
2567 /* Bind complete. */
2568 tevent_req_done(req);
2571 case PIPE_AUTH_TYPE_NTLMSSP:
2572 /* Need to send AUTH3 packet - no reply. */
2573 status = rpc_finish_auth3_bind_send(req, state, pkt);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 tevent_req_nterror(req, status);
2579 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2580 /* Need to send alter context request and reply. */
2581 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2583 if (!NT_STATUS_IS_OK(status)) {
2584 tevent_req_nterror(req, status);
2588 case PIPE_AUTH_TYPE_KRB5:
2592 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2593 (unsigned int)state->cli->auth->auth_type));
2594 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2598 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2599 struct rpc_pipe_bind_state *state,
2600 struct ncacn_packet *r)
2602 DATA_BLOB client_reply = data_blob_null;
2603 struct dcerpc_auth auth;
2604 struct tevent_req *subreq;
2607 if ((r->auth_length == 0)
2608 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2609 + r->auth_length)) {
2610 return NT_STATUS_INVALID_PARAMETER;
2613 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2614 &r->u.bind_ack.auth_info,
2616 if (!NT_STATUS_IS_OK(status)) {
2617 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2618 nt_errstr(status)));
2622 /* TODO - check auth_type/auth_level match. */
2624 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2625 auth.credentials, &client_reply);
2627 if (!NT_STATUS_IS_OK(status)) {
2628 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2629 "blob failed: %s.\n", nt_errstr(status)));
2633 data_blob_free(&state->rpc_out);
2635 status = create_rpc_bind_auth3(state,
2636 state->cli, state->rpc_call_id,
2637 state->cli->auth->auth_type,
2638 state->cli->auth->auth_level,
2639 &client_reply, &state->rpc_out);
2640 data_blob_free(&client_reply);
2642 if (!NT_STATUS_IS_OK(status)) {
2646 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2647 state->rpc_out.data, state->rpc_out.length);
2648 if (subreq == NULL) {
2649 return NT_STATUS_NO_MEMORY;
2651 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2652 return NT_STATUS_OK;
2655 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2657 struct tevent_req *req = tevent_req_callback_data(
2658 subreq, struct tevent_req);
2661 status = rpc_write_recv(subreq);
2662 TALLOC_FREE(subreq);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 tevent_req_nterror(req, status);
2667 tevent_req_done(req);
2670 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2671 struct rpc_pipe_bind_state *state,
2672 struct ncacn_packet *r,
2673 DATA_BLOB *reply_pdu)
2675 DATA_BLOB server_ntlm_response = data_blob_null;
2676 DATA_BLOB client_reply = data_blob_null;
2677 DATA_BLOB tmp_blob = data_blob_null;
2678 struct dcerpc_auth auth_info;
2679 DATA_BLOB auth_blob;
2680 struct tevent_req *subreq;
2683 if ((r->auth_length == 0)
2684 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2685 + r->auth_length)) {
2686 return NT_STATUS_INVALID_PARAMETER;
2689 /* Process the returned NTLMSSP blob first. */
2690 auth_blob = data_blob_const(reply_pdu->data
2692 - DCERPC_AUTH_TRAILER_LENGTH
2694 DCERPC_AUTH_TRAILER_LENGTH
2697 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2704 * The server might give us back two challenges - tmp_blob is for the
2707 if (!spnego_parse_challenge(auth_info.credentials,
2708 &server_ntlm_response, &tmp_blob)) {
2709 data_blob_free(&server_ntlm_response);
2710 data_blob_free(&tmp_blob);
2711 return NT_STATUS_INVALID_PARAMETER;
2714 /* We're finished with the server spnego response and the tmp_blob. */
2715 data_blob_free(&tmp_blob);
2717 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2718 server_ntlm_response, &client_reply);
2720 /* Finished with the server_ntlm response */
2721 data_blob_free(&server_ntlm_response);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2725 "using server blob failed.\n"));
2726 data_blob_free(&client_reply);
2730 /* SPNEGO wrap the client reply. */
2731 tmp_blob = spnego_gen_auth(client_reply);
2732 data_blob_free(&client_reply);
2733 client_reply = tmp_blob;
2734 tmp_blob = data_blob_null;
2736 /* Now prepare the alter context pdu. */
2737 data_blob_free(&state->rpc_out);
2739 status = create_rpc_alter_context(state,
2741 &state->cli->abstract_syntax,
2742 &state->cli->transfer_syntax,
2743 state->cli->auth->auth_level,
2746 data_blob_free(&client_reply);
2748 if (!NT_STATUS_IS_OK(status)) {
2752 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2753 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2754 if (subreq == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2757 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2758 return NT_STATUS_OK;
2761 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2763 struct tevent_req *req = tevent_req_callback_data(
2764 subreq, struct tevent_req);
2765 struct rpc_pipe_bind_state *state = tevent_req_data(
2766 req, struct rpc_pipe_bind_state);
2767 DATA_BLOB tmp_blob = data_blob_null;
2768 struct ncacn_packet *pkt;
2769 struct dcerpc_auth auth;
2772 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2773 TALLOC_FREE(subreq);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 tevent_req_nterror(req, status);
2779 status = dcerpc_pull_dcerpc_auth(pkt,
2780 &pkt->u.alter_resp.auth_info,
2782 if (!NT_STATUS_IS_OK(status)) {
2783 tevent_req_nterror(req, status);
2787 /* Check we got a valid auth response. */
2788 if (!spnego_parse_auth_response(auth.credentials,
2790 OID_NTLMSSP, &tmp_blob)) {
2791 data_blob_free(&tmp_blob);
2792 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2796 data_blob_free(&tmp_blob);
2798 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2799 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2800 tevent_req_done(req);
2803 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2805 return tevent_req_simple_recv_ntstatus(req);
2808 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2809 struct cli_pipe_auth_data *auth)
2811 TALLOC_CTX *frame = talloc_stackframe();
2812 struct event_context *ev;
2813 struct tevent_req *req;
2814 NTSTATUS status = NT_STATUS_OK;
2816 ev = event_context_init(frame);
2818 status = NT_STATUS_NO_MEMORY;
2822 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2824 status = NT_STATUS_NO_MEMORY;
2828 if (!tevent_req_poll(req, ev)) {
2829 status = map_nt_error_from_unix(errno);
2833 status = rpc_pipe_bind_recv(req);
2839 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2841 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2842 unsigned int timeout)
2846 if (rpc_cli->transport == NULL) {
2847 return RPCCLI_DEFAULT_TIMEOUT;
2850 if (rpc_cli->transport->set_timeout == NULL) {
2851 return RPCCLI_DEFAULT_TIMEOUT;
2854 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2856 return RPCCLI_DEFAULT_TIMEOUT;
2862 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2864 if (rpc_cli == NULL) {
2868 if (rpc_cli->transport == NULL) {
2872 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2875 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2877 struct cli_state *cli;
2879 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2880 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2881 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2885 cli = rpc_pipe_np_smb_conn(rpc_cli);
2889 E_md4hash(cli->password ? cli->password : "", nt_hash);
2893 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2894 struct cli_pipe_auth_data **presult)
2896 struct cli_pipe_auth_data *result;
2898 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2899 if (result == NULL) {
2900 return NT_STATUS_NO_MEMORY;
2903 result->auth_type = PIPE_AUTH_TYPE_NONE;
2904 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2906 result->user_name = talloc_strdup(result, "");
2907 result->domain = talloc_strdup(result, "");
2908 if ((result->user_name == NULL) || (result->domain == NULL)) {
2909 TALLOC_FREE(result);
2910 return NT_STATUS_NO_MEMORY;
2914 return NT_STATUS_OK;
2917 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2919 ntlmssp_end(&auth->a_u.ntlmssp_state);
2923 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2924 enum pipe_auth_type auth_type,
2925 enum dcerpc_AuthLevel auth_level,
2927 const char *username,
2928 const char *password,
2929 struct cli_pipe_auth_data **presult)
2931 struct cli_pipe_auth_data *result;
2934 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2935 if (result == NULL) {
2936 return NT_STATUS_NO_MEMORY;
2939 result->auth_type = auth_type;
2940 result->auth_level = auth_level;
2942 result->user_name = talloc_strdup(result, username);
2943 result->domain = talloc_strdup(result, domain);
2944 if ((result->user_name == NULL) || (result->domain == NULL)) {
2945 status = NT_STATUS_NO_MEMORY;
2949 status = ntlmssp_client_start(NULL,
2952 lp_client_ntlmv2_auth(),
2953 &result->a_u.ntlmssp_state);
2954 if (!NT_STATUS_IS_OK(status)) {
2958 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2960 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2961 if (!NT_STATUS_IS_OK(status)) {
2965 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2966 if (!NT_STATUS_IS_OK(status)) {
2970 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2971 if (!NT_STATUS_IS_OK(status)) {
2976 * Turn off sign+seal to allow selected auth level to turn it back on.
2978 result->a_u.ntlmssp_state->neg_flags &=
2979 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2981 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2982 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2983 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2984 result->a_u.ntlmssp_state->neg_flags
2985 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2989 return NT_STATUS_OK;
2992 TALLOC_FREE(result);
2996 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2997 enum dcerpc_AuthLevel auth_level,
2998 struct netlogon_creds_CredentialState *creds,
2999 struct cli_pipe_auth_data **presult)
3001 struct cli_pipe_auth_data *result;
3003 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3004 if (result == NULL) {
3005 return NT_STATUS_NO_MEMORY;
3008 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3009 result->auth_level = auth_level;
3011 result->user_name = talloc_strdup(result, "");
3012 result->domain = talloc_strdup(result, domain);
3013 if ((result->user_name == NULL) || (result->domain == NULL)) {
3017 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3018 if (result->a_u.schannel_auth == NULL) {
3022 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3023 result->a_u.schannel_auth->seq_num = 0;
3024 result->a_u.schannel_auth->initiator = true;
3025 result->a_u.schannel_auth->creds = creds;
3028 return NT_STATUS_OK;
3031 TALLOC_FREE(result);
3032 return NT_STATUS_NO_MEMORY;
3036 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3038 data_blob_free(&auth->session_key);
3043 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3044 enum dcerpc_AuthLevel auth_level,
3045 const char *service_princ,
3046 const char *username,
3047 const char *password,
3048 struct cli_pipe_auth_data **presult)
3051 struct cli_pipe_auth_data *result;
3053 if ((username != NULL) && (password != NULL)) {
3054 int ret = kerberos_kinit_password(username, password, 0, NULL);
3056 return NT_STATUS_ACCESS_DENIED;
3060 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3061 if (result == NULL) {
3062 return NT_STATUS_NO_MEMORY;
3065 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3066 result->auth_level = auth_level;
3069 * Username / domain need fixing!
3071 result->user_name = talloc_strdup(result, "");
3072 result->domain = talloc_strdup(result, "");
3073 if ((result->user_name == NULL) || (result->domain == NULL)) {
3077 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3078 result, struct kerberos_auth_struct);
3079 if (result->a_u.kerberos_auth == NULL) {
3082 talloc_set_destructor(result->a_u.kerberos_auth,
3083 cli_auth_kerberos_data_destructor);
3085 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3086 result, service_princ);
3087 if (result->a_u.kerberos_auth->service_principal == NULL) {
3092 return NT_STATUS_OK;
3095 TALLOC_FREE(result);
3096 return NT_STATUS_NO_MEMORY;
3098 return NT_STATUS_NOT_SUPPORTED;
3103 * Create an rpc pipe client struct, connecting to a tcp port.
3105 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3107 const struct ndr_syntax_id *abstract_syntax,
3108 struct rpc_pipe_client **presult)
3110 struct rpc_pipe_client *result;
3111 struct sockaddr_storage addr;
3115 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3116 if (result == NULL) {
3117 return NT_STATUS_NO_MEMORY;
3120 result->abstract_syntax = *abstract_syntax;
3121 result->transfer_syntax = ndr_transfer_syntax;
3122 result->dispatch = cli_do_rpc_ndr;
3123 result->dispatch_send = cli_do_rpc_ndr_send;
3124 result->dispatch_recv = cli_do_rpc_ndr_recv;
3126 result->desthost = talloc_strdup(result, host);
3127 result->srv_name_slash = talloc_asprintf_strupper_m(
3128 result, "\\\\%s", result->desthost);
3129 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3130 status = NT_STATUS_NO_MEMORY;
3134 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3135 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3137 if (!resolve_name(host, &addr, 0, false)) {
3138 status = NT_STATUS_NOT_FOUND;
3142 status = open_socket_out(&addr, port, 60, &fd);
3143 if (!NT_STATUS_IS_OK(status)) {
3146 set_socket_options(fd, lp_socket_options());
3148 status = rpc_transport_sock_init(result, fd, &result->transport);
3149 if (!NT_STATUS_IS_OK(status)) {
3154 result->transport->transport = NCACN_IP_TCP;
3157 return NT_STATUS_OK;
3160 TALLOC_FREE(result);
3165 * Determine the tcp port on which a dcerpc interface is listening
3166 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3169 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3170 const struct ndr_syntax_id *abstract_syntax,
3174 struct rpc_pipe_client *epm_pipe = NULL;
3175 struct cli_pipe_auth_data *auth = NULL;
3176 struct dcerpc_binding *map_binding = NULL;
3177 struct dcerpc_binding *res_binding = NULL;
3178 struct epm_twr_t *map_tower = NULL;
3179 struct epm_twr_t *res_towers = NULL;
3180 struct policy_handle *entry_handle = NULL;
3181 uint32_t num_towers = 0;
3182 uint32_t max_towers = 1;
3183 struct epm_twr_p_t towers;
3184 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3186 if (pport == NULL) {
3187 status = NT_STATUS_INVALID_PARAMETER;
3191 /* open the connection to the endpoint mapper */
3192 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3193 &ndr_table_epmapper.syntax_id,
3196 if (!NT_STATUS_IS_OK(status)) {
3200 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3201 if (!NT_STATUS_IS_OK(status)) {
3205 status = rpc_pipe_bind(epm_pipe, auth);
3206 if (!NT_STATUS_IS_OK(status)) {
3210 /* create tower for asking the epmapper */
3212 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3213 if (map_binding == NULL) {
3214 status = NT_STATUS_NO_MEMORY;
3218 map_binding->transport = NCACN_IP_TCP;
3219 map_binding->object = *abstract_syntax;
3220 map_binding->host = host; /* needed? */
3221 map_binding->endpoint = "0"; /* correct? needed? */
3223 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3224 if (map_tower == NULL) {
3225 status = NT_STATUS_NO_MEMORY;
3229 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3230 &(map_tower->tower));
3231 if (!NT_STATUS_IS_OK(status)) {
3235 /* allocate further parameters for the epm_Map call */
3237 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3238 if (res_towers == NULL) {
3239 status = NT_STATUS_NO_MEMORY;
3242 towers.twr = res_towers;
3244 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3245 if (entry_handle == NULL) {
3246 status = NT_STATUS_NO_MEMORY;
3250 /* ask the endpoint mapper for the port */
3252 status = rpccli_epm_Map(epm_pipe,
3254 CONST_DISCARD(struct GUID *,
3255 &(abstract_syntax->uuid)),
3262 if (!NT_STATUS_IS_OK(status)) {
3266 if (num_towers != 1) {
3267 status = NT_STATUS_UNSUCCESSFUL;
3271 /* extract the port from the answer */
3273 status = dcerpc_binding_from_tower(tmp_ctx,
3274 &(towers.twr->tower),
3276 if (!NT_STATUS_IS_OK(status)) {
3280 /* are further checks here necessary? */
3281 if (res_binding->transport != NCACN_IP_TCP) {
3282 status = NT_STATUS_UNSUCCESSFUL;
3286 *pport = (uint16_t)atoi(res_binding->endpoint);
3289 TALLOC_FREE(tmp_ctx);
3294 * Create a rpc pipe client struct, connecting to a host via tcp.
3295 * The port is determined by asking the endpoint mapper on the given
3298 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3299 const struct ndr_syntax_id *abstract_syntax,
3300 struct rpc_pipe_client **presult)
3305 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3306 if (!NT_STATUS_IS_OK(status)) {
3310 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3311 abstract_syntax, presult);
3314 /********************************************************************
3315 Create a rpc pipe client struct, connecting to a unix domain socket
3316 ********************************************************************/
3317 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3318 const struct ndr_syntax_id *abstract_syntax,
3319 struct rpc_pipe_client **presult)
3321 struct rpc_pipe_client *result;
3322 struct sockaddr_un addr;
3326 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3327 if (result == NULL) {
3328 return NT_STATUS_NO_MEMORY;
3331 result->abstract_syntax = *abstract_syntax;
3332 result->transfer_syntax = ndr_transfer_syntax;
3333 result->dispatch = cli_do_rpc_ndr;
3334 result->dispatch_send = cli_do_rpc_ndr_send;
3335 result->dispatch_recv = cli_do_rpc_ndr_recv;
3337 result->desthost = get_myname(result);
3338 result->srv_name_slash = talloc_asprintf_strupper_m(
3339 result, "\\\\%s", result->desthost);
3340 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3341 status = NT_STATUS_NO_MEMORY;
3345 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3346 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3348 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3350 status = map_nt_error_from_unix(errno);
3355 addr.sun_family = AF_UNIX;
3356 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3358 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3359 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3362 return map_nt_error_from_unix(errno);
3365 status = rpc_transport_sock_init(result, fd, &result->transport);
3366 if (!NT_STATUS_IS_OK(status)) {
3371 result->transport->transport = NCALRPC;
3374 return NT_STATUS_OK;
3377 TALLOC_FREE(result);
3381 struct rpc_pipe_client_np_ref {
3382 struct cli_state *cli;
3383 struct rpc_pipe_client *pipe;
3386 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3388 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3392 /****************************************************************************
3393 Open a named pipe over SMB to a remote server.
3395 * CAVEAT CALLER OF THIS FUNCTION:
3396 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3397 * so be sure that this function is called AFTER any structure (vs pointer)
3398 * assignment of the cli. In particular, libsmbclient does structure
3399 * assignments of cli, which invalidates the data in the returned
3400 * rpc_pipe_client if this function is called before the structure assignment
3403 ****************************************************************************/
3405 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3406 const struct ndr_syntax_id *abstract_syntax,
3407 struct rpc_pipe_client **presult)
3409 struct rpc_pipe_client *result;
3411 struct rpc_pipe_client_np_ref *np_ref;
3413 /* sanity check to protect against crashes */
3416 return NT_STATUS_INVALID_HANDLE;
3419 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3420 if (result == NULL) {
3421 return NT_STATUS_NO_MEMORY;
3424 result->abstract_syntax = *abstract_syntax;
3425 result->transfer_syntax = ndr_transfer_syntax;
3426 result->dispatch = cli_do_rpc_ndr;
3427 result->dispatch_send = cli_do_rpc_ndr_send;
3428 result->dispatch_recv = cli_do_rpc_ndr_recv;
3429 result->desthost = talloc_strdup(result, cli->desthost);
3430 result->srv_name_slash = talloc_asprintf_strupper_m(
3431 result, "\\\\%s", result->desthost);
3433 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3434 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3436 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3437 TALLOC_FREE(result);
3438 return NT_STATUS_NO_MEMORY;
3441 status = rpc_transport_np_init(result, cli, abstract_syntax,
3442 &result->transport);
3443 if (!NT_STATUS_IS_OK(status)) {
3444 TALLOC_FREE(result);
3448 result->transport->transport = NCACN_NP;
3450 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3451 if (np_ref == NULL) {
3452 TALLOC_FREE(result);
3453 return NT_STATUS_NO_MEMORY;
3456 np_ref->pipe = result;
3458 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3459 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3462 return NT_STATUS_OK;
3465 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3466 struct rpc_cli_smbd_conn *conn,
3467 const struct ndr_syntax_id *syntax,
3468 struct rpc_pipe_client **presult)
3470 struct rpc_pipe_client *result;
3471 struct cli_pipe_auth_data *auth;
3474 result = talloc(mem_ctx, struct rpc_pipe_client);
3475 if (result == NULL) {
3476 return NT_STATUS_NO_MEMORY;
3478 result->abstract_syntax = *syntax;
3479 result->transfer_syntax = ndr_transfer_syntax;
3480 result->dispatch = cli_do_rpc_ndr;
3481 result->dispatch_send = cli_do_rpc_ndr_send;
3482 result->dispatch_recv = cli_do_rpc_ndr_recv;
3483 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3484 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3486 result->desthost = talloc_strdup(result, global_myname());
3487 result->srv_name_slash = talloc_asprintf_strupper_m(
3488 result, "\\\\%s", global_myname());
3489 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3490 TALLOC_FREE(result);
3491 return NT_STATUS_NO_MEMORY;
3494 status = rpc_transport_smbd_init(result, conn, syntax,
3495 &result->transport);
3496 if (!NT_STATUS_IS_OK(status)) {
3497 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3498 nt_errstr(status)));
3499 TALLOC_FREE(result);
3503 status = rpccli_anon_bind_data(result, &auth);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3506 nt_errstr(status)));
3507 TALLOC_FREE(result);
3511 status = rpc_pipe_bind(result, auth);
3512 if (!NT_STATUS_IS_OK(status)) {
3513 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3514 TALLOC_FREE(result);
3518 result->transport->transport = NCACN_INTERNAL;
3521 return NT_STATUS_OK;
3524 /****************************************************************************
3525 Open a pipe to a remote server.
3526 ****************************************************************************/
3528 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3529 enum dcerpc_transport_t transport,
3530 const struct ndr_syntax_id *interface,
3531 struct rpc_pipe_client **presult)
3533 switch (transport) {
3535 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3538 return rpc_pipe_open_np(cli, interface, presult);
3540 return NT_STATUS_NOT_IMPLEMENTED;
3544 /****************************************************************************
3545 Open a named pipe to an SMB server and bind anonymously.
3546 ****************************************************************************/
3548 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3549 enum dcerpc_transport_t transport,
3550 const struct ndr_syntax_id *interface,
3551 struct rpc_pipe_client **presult)
3553 struct rpc_pipe_client *result;
3554 struct cli_pipe_auth_data *auth;
3557 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3558 if (!NT_STATUS_IS_OK(status)) {
3562 status = rpccli_anon_bind_data(result, &auth);
3563 if (!NT_STATUS_IS_OK(status)) {
3564 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3565 nt_errstr(status)));
3566 TALLOC_FREE(result);
3571 * This is a bit of an abstraction violation due to the fact that an
3572 * anonymous bind on an authenticated SMB inherits the user/domain
3573 * from the enclosing SMB creds
3576 TALLOC_FREE(auth->user_name);
3577 TALLOC_FREE(auth->domain);
3579 auth->user_name = talloc_strdup(auth, cli->user_name);
3580 auth->domain = talloc_strdup(auth, cli->domain);
3581 auth->user_session_key = data_blob_talloc(auth,
3582 cli->user_session_key.data,
3583 cli->user_session_key.length);
3585 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3586 TALLOC_FREE(result);
3587 return NT_STATUS_NO_MEMORY;
3590 status = rpc_pipe_bind(result, auth);
3591 if (!NT_STATUS_IS_OK(status)) {
3593 if (ndr_syntax_id_equal(interface,
3594 &ndr_table_dssetup.syntax_id)) {
3595 /* non AD domains just don't have this pipe, avoid
3596 * level 0 statement in that case - gd */
3599 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3600 "%s failed with error %s\n",
3601 get_pipe_name_from_syntax(talloc_tos(), interface),
3602 nt_errstr(status) ));
3603 TALLOC_FREE(result);
3607 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3608 "%s and bound anonymously.\n",
3609 get_pipe_name_from_syntax(talloc_tos(), interface),
3613 return NT_STATUS_OK;
3616 /****************************************************************************
3617 ****************************************************************************/
3619 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3620 const struct ndr_syntax_id *interface,
3621 struct rpc_pipe_client **presult)
3623 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3624 interface, presult);
3627 /****************************************************************************
3628 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3629 ****************************************************************************/
3631 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3632 const struct ndr_syntax_id *interface,
3633 enum dcerpc_transport_t transport,
3634 enum pipe_auth_type auth_type,
3635 enum dcerpc_AuthLevel auth_level,
3637 const char *username,
3638 const char *password,
3639 struct rpc_pipe_client **presult)
3641 struct rpc_pipe_client *result;
3642 struct cli_pipe_auth_data *auth;
3645 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3646 if (!NT_STATUS_IS_OK(status)) {
3650 status = rpccli_ntlmssp_bind_data(
3651 result, auth_type, auth_level, domain, username,
3653 if (!NT_STATUS_IS_OK(status)) {
3654 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3655 nt_errstr(status)));
3659 status = rpc_pipe_bind(result, auth);
3660 if (!NT_STATUS_IS_OK(status)) {
3661 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3662 nt_errstr(status) ));
3666 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3667 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3668 get_pipe_name_from_syntax(talloc_tos(), interface),
3669 cli->desthost, domain, username ));
3672 return NT_STATUS_OK;
3676 TALLOC_FREE(result);
3680 /****************************************************************************
3682 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3683 ****************************************************************************/
3685 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3686 const struct ndr_syntax_id *interface,
3687 enum dcerpc_transport_t transport,
3688 enum dcerpc_AuthLevel auth_level,
3690 const char *username,
3691 const char *password,
3692 struct rpc_pipe_client **presult)
3694 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3697 PIPE_AUTH_TYPE_NTLMSSP,
3705 /****************************************************************************
3707 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3708 ****************************************************************************/
3710 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3711 const struct ndr_syntax_id *interface,
3712 enum dcerpc_transport_t transport,
3713 enum dcerpc_AuthLevel auth_level,
3715 const char *username,
3716 const char *password,
3717 struct rpc_pipe_client **presult)
3719 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3722 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3730 /****************************************************************************
3731 Get a the schannel session key out of an already opened netlogon pipe.
3732 ****************************************************************************/
3733 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3734 struct cli_state *cli,
3738 enum netr_SchannelType sec_chan_type = 0;
3739 unsigned char machine_pwd[16];
3740 const char *machine_account;
3743 /* Get the machine account credentials from secrets.tdb. */
3744 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3747 DEBUG(0, ("get_schannel_session_key: could not fetch "
3748 "trust account password for domain '%s'\n",
3750 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3753 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3754 cli->desthost, /* server name */
3755 domain, /* domain */
3756 global_myname(), /* client name */
3757 machine_account, /* machine account name */
3762 if (!NT_STATUS_IS_OK(status)) {
3763 DEBUG(3, ("get_schannel_session_key_common: "
3764 "rpccli_netlogon_setup_creds failed with result %s "
3765 "to server %s, domain %s, machine account %s.\n",
3766 nt_errstr(status), cli->desthost, domain,
3771 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3772 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3774 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3777 return NT_STATUS_OK;;
3780 /****************************************************************************
3781 Open a netlogon pipe and get the schannel session key.
3782 Now exposed to external callers.
3783 ****************************************************************************/
3786 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3789 struct rpc_pipe_client **presult)
3791 struct rpc_pipe_client *netlogon_pipe = NULL;
3794 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3796 if (!NT_STATUS_IS_OK(status)) {
3800 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3802 if (!NT_STATUS_IS_OK(status)) {
3803 TALLOC_FREE(netlogon_pipe);
3807 *presult = netlogon_pipe;
3808 return NT_STATUS_OK;
3811 /****************************************************************************
3813 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3814 using session_key. sign and seal.
3816 The *pdc will be stolen onto this new pipe
3817 ****************************************************************************/
3819 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3820 const struct ndr_syntax_id *interface,
3821 enum dcerpc_transport_t transport,
3822 enum dcerpc_AuthLevel auth_level,
3824 struct netlogon_creds_CredentialState **pdc,
3825 struct rpc_pipe_client **presult)
3827 struct rpc_pipe_client *result;
3828 struct cli_pipe_auth_data *auth;
3831 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3832 if (!NT_STATUS_IS_OK(status)) {
3836 status = rpccli_schannel_bind_data(result, domain, auth_level,
3838 if (!NT_STATUS_IS_OK(status)) {
3839 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3840 nt_errstr(status)));
3841 TALLOC_FREE(result);
3845 status = rpc_pipe_bind(result, auth);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3848 "cli_rpc_pipe_bind failed with error %s\n",
3849 nt_errstr(status) ));
3850 TALLOC_FREE(result);
3855 * The credentials on a new netlogon pipe are the ones we are passed
3856 * in - reference them in
3858 result->dc = talloc_move(result, pdc);
3860 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3861 "for domain %s and bound using schannel.\n",
3862 get_pipe_name_from_syntax(talloc_tos(), interface),
3863 cli->desthost, domain ));
3866 return NT_STATUS_OK;
3869 /****************************************************************************
3870 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3871 Fetch the session key ourselves using a temporary netlogon pipe. This
3872 version uses an ntlmssp auth bound netlogon pipe to get the key.
3873 ****************************************************************************/
3875 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3877 const char *username,
3878 const char *password,
3880 struct rpc_pipe_client **presult)
3882 struct rpc_pipe_client *netlogon_pipe = NULL;
3885 status = cli_rpc_pipe_open_spnego_ntlmssp(
3886 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3887 DCERPC_AUTH_LEVEL_PRIVACY,
3888 domain, username, password, &netlogon_pipe);
3889 if (!NT_STATUS_IS_OK(status)) {
3893 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3895 if (!NT_STATUS_IS_OK(status)) {
3896 TALLOC_FREE(netlogon_pipe);
3900 *presult = netlogon_pipe;
3901 return NT_STATUS_OK;
3904 /****************************************************************************
3905 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3906 Fetch the session key ourselves using a temporary netlogon pipe. This version
3907 uses an ntlmssp bind to get the session key.
3908 ****************************************************************************/
3910 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3911 const struct ndr_syntax_id *interface,
3912 enum dcerpc_transport_t transport,
3913 enum dcerpc_AuthLevel auth_level,
3915 const char *username,
3916 const char *password,
3917 struct rpc_pipe_client **presult)
3919 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3920 struct rpc_pipe_client *netlogon_pipe = NULL;
3921 struct rpc_pipe_client *result = NULL;
3924 status = get_schannel_session_key_auth_ntlmssp(
3925 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3928 "key from server %s for domain %s.\n",
3929 cli->desthost, domain ));
3933 status = cli_rpc_pipe_open_schannel_with_key(
3934 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3937 /* Now we've bound using the session key we can close the netlog pipe. */
3938 TALLOC_FREE(netlogon_pipe);
3940 if (NT_STATUS_IS_OK(status)) {
3946 /****************************************************************************
3947 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3948 Fetch the session key ourselves using a temporary netlogon pipe.
3949 ****************************************************************************/
3951 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3952 const struct ndr_syntax_id *interface,
3953 enum dcerpc_transport_t transport,
3954 enum dcerpc_AuthLevel auth_level,
3956 struct rpc_pipe_client **presult)
3958 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3959 struct rpc_pipe_client *netlogon_pipe = NULL;
3960 struct rpc_pipe_client *result = NULL;
3963 status = get_schannel_session_key(cli, domain, &neg_flags,
3965 if (!NT_STATUS_IS_OK(status)) {
3966 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3967 "key from server %s for domain %s.\n",
3968 cli->desthost, domain ));
3972 status = cli_rpc_pipe_open_schannel_with_key(
3973 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3976 /* Now we've bound using the session key we can close the netlog pipe. */
3977 TALLOC_FREE(netlogon_pipe);
3979 if (NT_STATUS_IS_OK(status)) {
3986 /****************************************************************************
3987 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3988 The idea is this can be called with service_princ, username and password all
3989 NULL so long as the caller has a TGT.
3990 ****************************************************************************/
3992 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3993 const struct ndr_syntax_id *interface,
3994 enum dcerpc_AuthLevel auth_level,
3995 const char *service_princ,
3996 const char *username,
3997 const char *password,
3998 struct rpc_pipe_client **presult)
4001 struct rpc_pipe_client *result;
4002 struct cli_pipe_auth_data *auth;
4005 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4006 if (!NT_STATUS_IS_OK(status)) {
4010 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4011 username, password, &auth);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4014 nt_errstr(status)));
4015 TALLOC_FREE(result);
4019 status = rpc_pipe_bind(result, auth);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4022 "with error %s\n", nt_errstr(status)));
4023 TALLOC_FREE(result);
4028 return NT_STATUS_OK;
4030 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4031 return NT_STATUS_NOT_IMPLEMENTED;
4035 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4036 struct rpc_pipe_client *cli,
4037 DATA_BLOB *session_key)
4039 if (!session_key || !cli) {
4040 return NT_STATUS_INVALID_PARAMETER;
4044 return NT_STATUS_INVALID_PARAMETER;
4047 switch (cli->auth->auth_type) {
4048 case PIPE_AUTH_TYPE_SCHANNEL:
4049 *session_key = data_blob_talloc(mem_ctx,
4050 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4052 case PIPE_AUTH_TYPE_NTLMSSP:
4053 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4054 *session_key = data_blob_talloc(mem_ctx,
4055 cli->auth->a_u.ntlmssp_state->session_key.data,
4056 cli->auth->a_u.ntlmssp_state->session_key.length);
4058 case PIPE_AUTH_TYPE_KRB5:
4059 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4060 *session_key = data_blob_talloc(mem_ctx,
4061 cli->auth->a_u.kerberos_auth->session_key.data,
4062 cli->auth->a_u.kerberos_auth->session_key.length);
4064 case PIPE_AUTH_TYPE_NONE:
4065 *session_key = data_blob_talloc(mem_ctx,
4066 cli->auth->user_session_key.data,
4067 cli->auth->user_session_key.length);
4070 return NT_STATUS_NO_USER_SESSION_KEY;
4073 return NT_STATUS_OK;