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 (long unsigned int)pdu->length,
980 (long unsigned int)rdata->length,
981 (long unsigned int)ss_padding_len));
984 * If this is the first reply, and the allocation hint is
985 * reasonable, try and set up the reply_pdu DATA_BLOB to the
989 if ((reply_pdu->length == 0) &&
990 pkt->u.response.alloc_hint &&
991 (pkt->u.response.alloc_hint < 15*1024*1024)) {
992 if (!data_blob_realloc(mem_ctx, reply_pdu,
993 pkt->u.response.alloc_hint)) {
994 DEBUG(0, ("reply alloc hint %d too "
995 "large to allocate\n",
996 (int)pkt->u.response.alloc_hint));
997 return NT_STATUS_NO_MEMORY;
1003 case DCERPC_PKT_BIND_NAK:
1004 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1005 "received from %s!\n",
1006 rpccli_pipe_txt(talloc_tos(), cli)));
1007 /* Use this for now... */
1008 return NT_STATUS_NETWORK_ACCESS_DENIED;
1010 case DCERPC_PKT_FAULT:
1012 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1013 "code %s received from %s!\n",
1014 dcerpc_errstr(talloc_tos(),
1015 pkt->u.fault.status),
1016 rpccli_pipe_txt(talloc_tos(), cli)));
1018 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
1019 return NT_STATUS_UNSUCCESSFUL;
1021 return NT_STATUS(pkt->u.fault.status);
1025 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1026 (unsigned int)pkt->ptype,
1027 rpccli_pipe_txt(talloc_tos(), cli)));
1028 return NT_STATUS_INVALID_INFO_CLASS;
1031 if (pkt->ptype != expected_pkt_type) {
1032 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1033 "got an unexpected RPC packet type - %u, not %u\n",
1034 rpccli_pipe_txt(talloc_tos(), cli),
1036 expected_pkt_type));
1037 return NT_STATUS_INVALID_INFO_CLASS;
1040 /* Do this just before return - we don't want to modify any rpc header
1041 data before now as we may have needed to do cryptographic actions on
1044 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
1045 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1046 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1047 "setting fragment first/last ON.\n"));
1048 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
1049 DCERPC_PFC_FLAG_LAST;
1052 return NT_STATUS_OK;
1055 /****************************************************************************
1056 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1057 ****************************************************************************/
1059 struct cli_api_pipe_state {
1060 struct event_context *ev;
1061 struct rpc_cli_transport *transport;
1066 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1067 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1068 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1070 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1071 struct event_context *ev,
1072 struct rpc_cli_transport *transport,
1073 uint8_t *data, size_t data_len,
1074 uint32_t max_rdata_len)
1076 struct tevent_req *req, *subreq;
1077 struct cli_api_pipe_state *state;
1080 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1085 state->transport = transport;
1087 if (max_rdata_len < RPC_HEADER_LEN) {
1089 * For a RPC reply we always need at least RPC_HEADER_LEN
1090 * bytes. We check this here because we will receive
1091 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1093 status = NT_STATUS_INVALID_PARAMETER;
1097 if (transport->trans_send != NULL) {
1098 subreq = transport->trans_send(state, ev, data, data_len,
1099 max_rdata_len, transport->priv);
1100 if (subreq == NULL) {
1103 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1108 * If the transport does not provide a "trans" routine, i.e. for
1109 * example the ncacn_ip_tcp transport, do the write/read step here.
1112 subreq = rpc_write_send(state, ev, transport, data, data_len);
1113 if (subreq == NULL) {
1116 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1120 tevent_req_nterror(req, status);
1121 return tevent_req_post(req, ev);
1127 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1129 struct tevent_req *req = tevent_req_callback_data(
1130 subreq, struct tevent_req);
1131 struct cli_api_pipe_state *state = tevent_req_data(
1132 req, struct cli_api_pipe_state);
1135 status = state->transport->trans_recv(subreq, state, &state->rdata,
1137 TALLOC_FREE(subreq);
1138 if (!NT_STATUS_IS_OK(status)) {
1139 tevent_req_nterror(req, status);
1142 tevent_req_done(req);
1145 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1147 struct tevent_req *req = tevent_req_callback_data(
1148 subreq, struct tevent_req);
1149 struct cli_api_pipe_state *state = tevent_req_data(
1150 req, struct cli_api_pipe_state);
1153 status = rpc_write_recv(subreq);
1154 TALLOC_FREE(subreq);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 tevent_req_nterror(req, status);
1160 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1161 if (tevent_req_nomem(state->rdata, req)) {
1166 * We don't need to use rpc_read_send here, the upper layer will cope
1167 * with a short read, transport->trans_send could also return less
1168 * than state->max_rdata_len.
1170 subreq = state->transport->read_send(state, state->ev, state->rdata,
1172 state->transport->priv);
1173 if (tevent_req_nomem(subreq, req)) {
1176 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1179 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1181 struct tevent_req *req = tevent_req_callback_data(
1182 subreq, struct tevent_req);
1183 struct cli_api_pipe_state *state = tevent_req_data(
1184 req, struct cli_api_pipe_state);
1188 status = state->transport->read_recv(subreq, &received);
1189 TALLOC_FREE(subreq);
1190 if (!NT_STATUS_IS_OK(status)) {
1191 tevent_req_nterror(req, status);
1194 state->rdata_len = received;
1195 tevent_req_done(req);
1198 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1199 uint8_t **prdata, uint32_t *prdata_len)
1201 struct cli_api_pipe_state *state = tevent_req_data(
1202 req, struct cli_api_pipe_state);
1205 if (tevent_req_is_nterror(req, &status)) {
1209 *prdata = talloc_move(mem_ctx, &state->rdata);
1210 *prdata_len = state->rdata_len;
1211 return NT_STATUS_OK;
1214 /****************************************************************************
1215 Send data on an rpc pipe via trans. The data must be the last
1216 pdu fragment of an NDR data stream.
1218 Receive response data from an rpc pipe, which may be large...
1220 Read the first fragment: unfortunately have to use SMBtrans for the first
1221 bit, then SMBreadX for subsequent bits.
1223 If first fragment received also wasn't the last fragment, continue
1224 getting fragments until we _do_ receive the last fragment.
1226 Request/Response PDU's look like the following...
1228 |<------------------PDU len----------------------------------------------->|
1229 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1231 +------------+-----------------+-------------+---------------+-------------+
1232 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1233 +------------+-----------------+-------------+---------------+-------------+
1235 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1236 signing & sealing being negotiated.
1238 ****************************************************************************/
1240 struct rpc_api_pipe_state {
1241 struct event_context *ev;
1242 struct rpc_pipe_client *cli;
1243 uint8_t expected_pkt_type;
1245 DATA_BLOB incoming_frag;
1246 struct ncacn_packet *pkt;
1248 /* Incoming reply */
1249 DATA_BLOB reply_pdu;
1250 size_t reply_pdu_offset;
1254 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1255 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1257 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1258 struct event_context *ev,
1259 struct rpc_pipe_client *cli,
1260 DATA_BLOB *data, /* Outgoing PDU */
1261 uint8_t expected_pkt_type)
1263 struct tevent_req *req, *subreq;
1264 struct rpc_api_pipe_state *state;
1265 uint16_t max_recv_frag;
1268 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1274 state->expected_pkt_type = expected_pkt_type;
1275 state->incoming_frag = data_blob_null;
1276 state->reply_pdu = data_blob_null;
1277 state->reply_pdu_offset = 0;
1278 state->endianess = DCERPC_DREP_LE;
1281 * Ensure we're not sending too much.
1283 if (data->length > cli->max_xmit_frag) {
1284 status = NT_STATUS_INVALID_PARAMETER;
1288 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1290 /* get the header first, then fetch the rest once we have
1291 * the frag_length available */
1292 max_recv_frag = RPC_HEADER_LEN;
1294 subreq = cli_api_pipe_send(state, ev, cli->transport,
1295 data->data, data->length, max_recv_frag);
1296 if (subreq == NULL) {
1299 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1303 tevent_req_nterror(req, status);
1304 return tevent_req_post(req, ev);
1310 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1312 struct tevent_req *req = tevent_req_callback_data(
1313 subreq, struct tevent_req);
1314 struct rpc_api_pipe_state *state = tevent_req_data(
1315 req, struct rpc_api_pipe_state);
1317 uint8_t *rdata = NULL;
1318 uint32_t rdata_len = 0;
1320 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1321 TALLOC_FREE(subreq);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1324 tevent_req_nterror(req, status);
1328 if (rdata == NULL) {
1329 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1330 rpccli_pipe_txt(talloc_tos(), state->cli)));
1331 tevent_req_done(req);
1336 * Move data on state->incoming_frag.
1338 state->incoming_frag.data = talloc_move(state, &rdata);
1339 state->incoming_frag.length = rdata_len;
1340 if (!state->incoming_frag.data) {
1341 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1345 /* Ensure we have enough data for a pdu. */
1346 subreq = get_complete_frag_send(state, state->ev, state->cli,
1347 &state->incoming_frag);
1348 if (tevent_req_nomem(subreq, req)) {
1351 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1354 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1356 struct tevent_req *req = tevent_req_callback_data(
1357 subreq, struct tevent_req);
1358 struct rpc_api_pipe_state *state = tevent_req_data(
1359 req, struct rpc_api_pipe_state);
1361 DATA_BLOB rdata = data_blob_null;
1363 status = get_complete_frag_recv(subreq);
1364 TALLOC_FREE(subreq);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 DEBUG(5, ("get_complete_frag failed: %s\n",
1367 nt_errstr(status)));
1368 tevent_req_nterror(req, status);
1372 state->pkt = talloc(state, struct ncacn_packet);
1374 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1378 status = cli_pipe_validate_current_pdu(state,
1379 state->cli, state->pkt,
1380 &state->incoming_frag,
1381 state->expected_pkt_type,
1385 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1386 (unsigned)state->incoming_frag.length,
1387 (unsigned)state->reply_pdu_offset,
1388 nt_errstr(status)));
1390 if (!NT_STATUS_IS_OK(status)) {
1391 tevent_req_nterror(req, status);
1395 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1396 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1398 * Set the data type correctly for big-endian data on the
1401 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1403 rpccli_pipe_txt(talloc_tos(), state->cli)));
1404 state->endianess = 0x00; /* BIG ENDIAN */
1407 * Check endianness on subsequent packets.
1409 if (state->endianess != state->pkt->drep[0]) {
1410 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1412 state->endianess?"little":"big",
1413 state->pkt->drep[0]?"little":"big"));
1414 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1418 /* Now copy the data portion out of the pdu into rbuf. */
1419 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1420 if (!data_blob_realloc(NULL, &state->reply_pdu,
1421 state->reply_pdu_offset + rdata.length)) {
1422 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1427 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1428 rdata.data, rdata.length);
1429 state->reply_pdu_offset += rdata.length;
1431 /* reset state->incoming_frag, there is no need to free it,
1432 * it will be reallocated to the right size the next time
1434 state->incoming_frag.length = 0;
1436 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1437 /* make sure the pdu length is right now that we
1438 * have all the data available (alloc hint may
1439 * have allocated more than was actually used) */
1440 state->reply_pdu.length = state->reply_pdu_offset;
1441 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1442 rpccli_pipe_txt(talloc_tos(), state->cli),
1443 (unsigned)state->reply_pdu.length));
1444 tevent_req_done(req);
1448 subreq = get_complete_frag_send(state, state->ev, state->cli,
1449 &state->incoming_frag);
1450 if (tevent_req_nomem(subreq, req)) {
1453 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1456 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1457 struct ncacn_packet **pkt,
1458 DATA_BLOB *reply_pdu)
1460 struct rpc_api_pipe_state *state = tevent_req_data(
1461 req, struct rpc_api_pipe_state);
1464 if (tevent_req_is_nterror(req, &status)) {
1468 /* return data to caller and assign it ownership of memory */
1470 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1471 reply_pdu->length = state->reply_pdu.length;
1472 state->reply_pdu.length = 0;
1474 data_blob_free(&state->reply_pdu);
1478 *pkt = talloc_steal(mem_ctx, state->pkt);
1481 return NT_STATUS_OK;
1484 /*******************************************************************
1485 Creates krb5 auth bind.
1486 ********************************************************************/
1488 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1489 enum dcerpc_AuthLevel auth_level,
1490 DATA_BLOB *auth_info)
1495 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1496 DATA_BLOB tkt = data_blob_null;
1497 DATA_BLOB tkt_wrapped = data_blob_null;
1499 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1500 a->service_principal ));
1502 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1504 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1505 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1508 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1510 a->service_principal,
1511 error_message(ret) ));
1513 data_blob_free(&tkt);
1514 return NT_STATUS_INVALID_PARAMETER;
1517 /* wrap that up in a nice GSS-API wrapping */
1518 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1520 data_blob_free(&tkt);
1522 status = dcerpc_push_dcerpc_auth(cli,
1523 DCERPC_AUTH_TYPE_KRB5,
1525 0, /* auth_pad_length */
1526 1, /* auth_context_id */
1529 if (!NT_STATUS_IS_OK(status)) {
1530 data_blob_free(&tkt_wrapped);
1534 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1535 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1537 return NT_STATUS_OK;
1539 return NT_STATUS_INVALID_PARAMETER;
1543 /*******************************************************************
1544 Creates SPNEGO NTLMSSP auth bind.
1545 ********************************************************************/
1547 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1548 enum dcerpc_AuthLevel auth_level,
1549 DATA_BLOB *auth_info)
1552 DATA_BLOB null_blob = data_blob_null;
1553 DATA_BLOB request = data_blob_null;
1554 DATA_BLOB spnego_msg = data_blob_null;
1556 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1557 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1561 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1562 data_blob_free(&request);
1566 /* Wrap this in SPNEGO. */
1567 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1569 data_blob_free(&request);
1571 status = dcerpc_push_dcerpc_auth(cli,
1572 DCERPC_AUTH_TYPE_SPNEGO,
1574 0, /* auth_pad_length */
1575 1, /* auth_context_id */
1578 if (!NT_STATUS_IS_OK(status)) {
1579 data_blob_free(&spnego_msg);
1583 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1584 dump_data(5, spnego_msg.data, spnego_msg.length);
1586 return NT_STATUS_OK;
1589 /*******************************************************************
1590 Creates NTLMSSP auth bind.
1591 ********************************************************************/
1593 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1594 enum dcerpc_AuthLevel auth_level,
1595 DATA_BLOB *auth_info)
1598 DATA_BLOB null_blob = data_blob_null;
1599 DATA_BLOB request = data_blob_null;
1601 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1602 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1606 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1607 data_blob_free(&request);
1611 status = dcerpc_push_dcerpc_auth(cli,
1612 DCERPC_AUTH_TYPE_NTLMSSP,
1614 0, /* auth_pad_length */
1615 1, /* auth_context_id */
1618 if (!NT_STATUS_IS_OK(status)) {
1619 data_blob_free(&request);
1623 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1624 dump_data(5, request.data, request.length);
1626 return NT_STATUS_OK;
1629 /*******************************************************************
1630 Creates schannel auth bind.
1631 ********************************************************************/
1633 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1634 enum dcerpc_AuthLevel auth_level,
1635 DATA_BLOB *auth_info)
1638 struct NL_AUTH_MESSAGE r;
1639 DATA_BLOB schannel_blob;
1641 /* Use lp_workgroup() if domain not specified */
1643 if (!cli->auth->domain || !cli->auth->domain[0]) {
1644 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1645 if (cli->auth->domain == NULL) {
1646 return NT_STATUS_NO_MEMORY;
1651 * Now marshall the data into the auth parse_struct.
1654 r.MessageType = NL_NEGOTIATE_REQUEST;
1655 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1656 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1657 r.oem_netbios_domain.a = cli->auth->domain;
1658 r.oem_netbios_computer.a = global_myname();
1660 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1661 if (!NT_STATUS_IS_OK(status)) {
1665 status = dcerpc_push_dcerpc_auth(cli,
1666 DCERPC_AUTH_TYPE_SCHANNEL,
1668 0, /* auth_pad_length */
1669 1, /* auth_context_id */
1672 if (!NT_STATUS_IS_OK(status)) {
1676 return NT_STATUS_OK;
1679 /*******************************************************************
1680 Creates the internals of a DCE/RPC bind request or alter context PDU.
1681 ********************************************************************/
1683 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1684 enum dcerpc_pkt_type ptype,
1686 const struct ndr_syntax_id *abstract,
1687 const struct ndr_syntax_id *transfer,
1688 const DATA_BLOB *auth_info,
1691 uint16 auth_len = auth_info->length;
1693 union dcerpc_payload u;
1694 struct dcerpc_ctx_list ctx_list;
1697 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1700 ctx_list.context_id = 0;
1701 ctx_list.num_transfer_syntaxes = 1;
1702 ctx_list.abstract_syntax = *abstract;
1703 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1705 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1706 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1707 u.bind.assoc_group_id = 0x0;
1708 u.bind.num_contexts = 1;
1709 u.bind.ctx_list = &ctx_list;
1710 u.bind.auth_info = *auth_info;
1712 status = dcerpc_push_ncacn_packet(mem_ctx,
1714 DCERPC_PFC_FLAG_FIRST |
1715 DCERPC_PFC_FLAG_LAST,
1720 if (!NT_STATUS_IS_OK(status)) {
1721 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1725 return NT_STATUS_OK;
1728 /*******************************************************************
1729 Creates a DCE/RPC bind request.
1730 ********************************************************************/
1732 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1733 struct rpc_pipe_client *cli,
1735 const struct ndr_syntax_id *abstract,
1736 const struct ndr_syntax_id *transfer,
1737 enum pipe_auth_type auth_type,
1738 enum dcerpc_AuthLevel auth_level,
1741 DATA_BLOB auth_info = data_blob_null;
1742 NTSTATUS ret = NT_STATUS_OK;
1744 switch (auth_type) {
1745 case PIPE_AUTH_TYPE_SCHANNEL:
1746 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1747 if (!NT_STATUS_IS_OK(ret)) {
1752 case PIPE_AUTH_TYPE_NTLMSSP:
1753 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1754 if (!NT_STATUS_IS_OK(ret)) {
1759 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1760 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1761 if (!NT_STATUS_IS_OK(ret)) {
1766 case PIPE_AUTH_TYPE_KRB5:
1767 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1768 if (!NT_STATUS_IS_OK(ret)) {
1773 case PIPE_AUTH_TYPE_NONE:
1777 /* "Can't" happen. */
1778 return NT_STATUS_INVALID_INFO_CLASS;
1781 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1791 /*******************************************************************
1792 Create and add the NTLMSSP sign/seal auth header and data.
1793 ********************************************************************/
1795 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1796 uint32 ss_padding_len,
1799 DATA_BLOB auth_info;
1801 DATA_BLOB auth_blob = data_blob_null;
1802 uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
1804 if (!cli->auth->a_u.ntlmssp_state) {
1805 return NT_STATUS_INVALID_PARAMETER;
1808 /* marshall the dcerpc_auth with an actually empty auth_blob.
1809 * this is needed because the ntmlssp signature includes the
1811 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1812 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1813 cli->auth->auth_level,
1815 1 /* context id. */,
1818 if (!NT_STATUS_IS_OK(status)) {
1822 /* append the header */
1823 if (!data_blob_append(NULL, rpc_out,
1824 auth_info.data, auth_info.length)) {
1825 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1826 (unsigned int)auth_info.length));
1827 return NT_STATUS_NO_MEMORY;
1829 data_blob_free(&auth_info);
1831 switch (cli->auth->auth_level) {
1832 case DCERPC_AUTH_LEVEL_PRIVACY:
1833 /* Data portion is encrypted. */
1834 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1837 + DCERPC_RESPONSE_LENGTH,
1842 if (!NT_STATUS_IS_OK(status)) {
1847 case DCERPC_AUTH_LEVEL_INTEGRITY:
1848 /* Data is signed. */
1849 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1852 + DCERPC_RESPONSE_LENGTH,
1857 if (!NT_STATUS_IS_OK(status)) {
1864 smb_panic("bad auth level");
1866 return NT_STATUS_INVALID_PARAMETER;
1869 /* Finally attach the blob. */
1870 if (!data_blob_append(NULL, rpc_out,
1871 auth_blob.data, auth_blob.length)) {
1872 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1873 (unsigned int)auth_info.length));
1874 return NT_STATUS_NO_MEMORY;
1876 data_blob_free(&auth_blob);
1878 return NT_STATUS_OK;
1881 /*******************************************************************
1882 Create and add the schannel sign/seal auth header and data.
1883 ********************************************************************/
1885 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1886 uint32 ss_padding_len,
1889 DATA_BLOB auth_info;
1890 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1891 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
1892 size_t data_and_pad_len = rpc_out->length
1893 - DCERPC_RESPONSE_LENGTH;
1898 return NT_STATUS_INVALID_PARAMETER;
1901 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1904 switch (cli->auth->auth_level) {
1905 case DCERPC_AUTH_LEVEL_PRIVACY:
1906 status = netsec_outgoing_packet(sas,
1913 case DCERPC_AUTH_LEVEL_INTEGRITY:
1914 status = netsec_outgoing_packet(sas,
1922 status = NT_STATUS_INTERNAL_ERROR;
1926 if (!NT_STATUS_IS_OK(status)) {
1927 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1928 nt_errstr(status)));
1932 if (DEBUGLEVEL >= 10) {
1933 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1936 /* Finally marshall the blob. */
1937 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1938 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1939 cli->auth->auth_level,
1941 1 /* context id. */,
1944 if (!NT_STATUS_IS_OK(status)) {
1947 data_blob_free(&blob);
1949 if (!data_blob_append(NULL, rpc_out,
1950 auth_info.data, auth_info.length)) {
1951 return NT_STATUS_NO_MEMORY;
1953 data_blob_free(&auth_info);
1955 return NT_STATUS_OK;
1958 /*******************************************************************
1959 Calculate how much data we're going to send in this packet, also
1960 work out any sign/seal padding length.
1961 ********************************************************************/
1963 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1967 uint32 *p_ss_padding)
1969 uint32 data_space, data_len;
1972 if ((data_left > 0) && (sys_random() % 2)) {
1973 data_left = MAX(data_left/2, 1);
1977 switch (cli->auth->auth_level) {
1978 case DCERPC_AUTH_LEVEL_NONE:
1979 case DCERPC_AUTH_LEVEL_CONNECT:
1980 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1981 data_len = MIN(data_space, data_left);
1984 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1987 case DCERPC_AUTH_LEVEL_INTEGRITY:
1988 case DCERPC_AUTH_LEVEL_PRIVACY:
1989 /* Treat the same for all authenticated rpc requests. */
1990 switch(cli->auth->auth_type) {
1991 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1992 case PIPE_AUTH_TYPE_NTLMSSP:
1993 *p_auth_len = NTLMSSP_SIG_SIZE;
1995 case PIPE_AUTH_TYPE_SCHANNEL:
1996 *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1999 smb_panic("bad auth type");
2003 data_space = cli->max_xmit_frag
2004 - DCERPC_REQUEST_LENGTH
2005 - DCERPC_AUTH_TRAILER_LENGTH
2008 data_len = MIN(data_space, data_left);
2010 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2011 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2013 *p_frag_len = DCERPC_REQUEST_LENGTH
2014 + data_len + *p_ss_padding
2015 + DCERPC_AUTH_TRAILER_LENGTH
2020 smb_panic("bad auth level");
2026 /*******************************************************************
2028 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2029 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2030 and deals with signing/sealing details.
2031 ********************************************************************/
2033 struct rpc_api_pipe_req_state {
2034 struct event_context *ev;
2035 struct rpc_pipe_client *cli;
2038 DATA_BLOB *req_data;
2039 uint32_t req_data_sent;
2041 DATA_BLOB reply_pdu;
2044 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2045 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2046 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2047 bool *is_last_frag);
2049 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2050 struct event_context *ev,
2051 struct rpc_pipe_client *cli,
2053 DATA_BLOB *req_data)
2055 struct tevent_req *req, *subreq;
2056 struct rpc_api_pipe_req_state *state;
2060 req = tevent_req_create(mem_ctx, &state,
2061 struct rpc_api_pipe_req_state);
2067 state->op_num = op_num;
2068 state->req_data = req_data;
2069 state->req_data_sent = 0;
2070 state->call_id = get_rpc_call_id();
2071 state->reply_pdu = data_blob_null;
2072 state->rpc_out = data_blob_null;
2074 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2075 + RPC_MAX_SIGN_SIZE) {
2076 /* Server is screwed up ! */
2077 status = NT_STATUS_INVALID_PARAMETER;
2081 status = prepare_next_frag(state, &is_last_frag);
2082 if (!NT_STATUS_IS_OK(status)) {
2087 subreq = rpc_api_pipe_send(state, ev, state->cli,
2089 DCERPC_PKT_RESPONSE);
2090 if (subreq == NULL) {
2093 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2095 subreq = rpc_write_send(state, ev, cli->transport,
2096 state->rpc_out.data,
2097 state->rpc_out.length);
2098 if (subreq == NULL) {
2101 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2107 tevent_req_nterror(req, status);
2108 return tevent_req_post(req, ev);
2114 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2117 uint32_t data_sent_thistime;
2121 uint32_t ss_padding;
2123 char pad[8] = { 0, };
2125 union dcerpc_payload u;
2127 data_left = state->req_data->length - state->req_data_sent;
2129 data_sent_thistime = calculate_data_len_tosend(
2130 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2132 if (state->req_data_sent == 0) {
2133 flags = DCERPC_PFC_FLAG_FIRST;
2136 if (data_sent_thistime == data_left) {
2137 flags |= DCERPC_PFC_FLAG_LAST;
2140 data_blob_free(&state->rpc_out);
2142 ZERO_STRUCT(u.request);
2144 u.request.alloc_hint = state->req_data->length;
2145 u.request.context_id = 0;
2146 u.request.opnum = state->op_num;
2148 status = dcerpc_push_ncacn_packet(state,
2155 if (!NT_STATUS_IS_OK(status)) {
2159 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2160 * compute it right for requests */
2161 dcerpc_set_frag_length(&state->rpc_out, frag_len);
2163 /* Copy in the data, plus any ss padding. */
2164 if (!data_blob_append(NULL, &state->rpc_out,
2165 state->req_data->data + state->req_data_sent,
2166 data_sent_thistime)) {
2167 return NT_STATUS_NO_MEMORY;
2171 /* Copy the sign/seal padding data. */
2172 if (!data_blob_append(NULL, &state->rpc_out,
2174 return NT_STATUS_NO_MEMORY;
2178 /* Generate any auth sign/seal and add the auth footer. */
2179 switch (state->cli->auth->auth_type) {
2180 case PIPE_AUTH_TYPE_NONE:
2181 status = NT_STATUS_OK;
2183 case PIPE_AUTH_TYPE_NTLMSSP:
2184 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2185 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2188 case PIPE_AUTH_TYPE_SCHANNEL:
2189 status = add_schannel_auth_footer(state->cli, ss_padding,
2193 status = NT_STATUS_INVALID_PARAMETER;
2197 state->req_data_sent += data_sent_thistime;
2198 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2203 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2205 struct tevent_req *req = tevent_req_callback_data(
2206 subreq, struct tevent_req);
2207 struct rpc_api_pipe_req_state *state = tevent_req_data(
2208 req, struct rpc_api_pipe_req_state);
2212 status = rpc_write_recv(subreq);
2213 TALLOC_FREE(subreq);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 tevent_req_nterror(req, status);
2219 status = prepare_next_frag(state, &is_last_frag);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 tevent_req_nterror(req, status);
2226 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2228 DCERPC_PKT_RESPONSE);
2229 if (tevent_req_nomem(subreq, req)) {
2232 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2234 subreq = rpc_write_send(state, state->ev,
2235 state->cli->transport,
2236 state->rpc_out.data,
2237 state->rpc_out.length);
2238 if (tevent_req_nomem(subreq, req)) {
2241 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2246 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2248 struct tevent_req *req = tevent_req_callback_data(
2249 subreq, struct tevent_req);
2250 struct rpc_api_pipe_req_state *state = tevent_req_data(
2251 req, struct rpc_api_pipe_req_state);
2254 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2255 TALLOC_FREE(subreq);
2256 if (!NT_STATUS_IS_OK(status)) {
2257 tevent_req_nterror(req, status);
2260 tevent_req_done(req);
2263 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2264 DATA_BLOB *reply_pdu)
2266 struct rpc_api_pipe_req_state *state = tevent_req_data(
2267 req, struct rpc_api_pipe_req_state);
2270 if (tevent_req_is_nterror(req, &status)) {
2272 * We always have to initialize to reply pdu, even if there is
2273 * none. The rpccli_* caller routines expect this.
2275 *reply_pdu = data_blob_null;
2279 /* return data to caller and assign it ownership of memory */
2280 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2281 reply_pdu->length = state->reply_pdu.length;
2282 state->reply_pdu.length = 0;
2284 return NT_STATUS_OK;
2288 /****************************************************************************
2289 Set the handle state.
2290 ****************************************************************************/
2292 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2293 const char *pipe_name, uint16 device_state)
2295 bool state_set = False;
2297 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2298 char *rparam = NULL;
2300 uint32 rparam_len, rdata_len;
2302 if (pipe_name == NULL)
2305 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2306 cli->fnum, pipe_name, device_state));
2308 /* create parameters: device state */
2309 SSVAL(param, 0, device_state);
2311 /* create setup parameters. */
2313 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2315 /* send the data on \PIPE\ */
2316 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2317 setup, 2, 0, /* setup, length, max */
2318 param, 2, 0, /* param, length, max */
2319 NULL, 0, 1024, /* data, length, max */
2320 &rparam, &rparam_len, /* return param, length */
2321 &rdata, &rdata_len)) /* return data, length */
2323 DEBUG(5, ("Set Handle state: return OK\n"));
2334 /****************************************************************************
2335 Check the rpc bind acknowledge response.
2336 ****************************************************************************/
2338 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2339 const struct ndr_syntax_id *transfer)
2341 struct dcerpc_ack_ctx ctx;
2343 if (r->secondary_address_size == 0) {
2344 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2347 if (r->num_results < 1 || !r->ctx_list) {
2351 ctx = r->ctx_list[0];
2353 /* check the transfer syntax */
2354 if ((ctx.syntax.if_version != transfer->if_version) ||
2355 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2356 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2360 if (r->num_results != 0x1 || ctx.result != 0) {
2361 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2362 r->num_results, ctx.reason));
2365 DEBUG(5,("check_bind_response: accepted!\n"));
2369 /*******************************************************************
2370 Creates a DCE/RPC bind authentication response.
2371 This is the packet that is sent back to the server once we
2372 have received a BIND-ACK, to finish the third leg of
2373 the authentication handshake.
2374 ********************************************************************/
2376 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
2377 struct rpc_pipe_client *cli,
2379 enum pipe_auth_type auth_type,
2380 enum dcerpc_AuthLevel auth_level,
2381 DATA_BLOB *pauth_blob,
2385 union dcerpc_payload u;
2389 status = dcerpc_push_dcerpc_auth(mem_ctx,
2390 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2392 0, /* auth_pad_length */
2393 1, /* auth_context_id */
2395 &u.auth3.auth_info);
2396 if (!NT_STATUS_IS_OK(status)) {
2400 status = dcerpc_push_ncacn_packet(mem_ctx,
2402 DCERPC_PFC_FLAG_FIRST |
2403 DCERPC_PFC_FLAG_LAST,
2408 data_blob_free(&u.auth3.auth_info);
2409 if (!NT_STATUS_IS_OK(status)) {
2410 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2414 return NT_STATUS_OK;
2417 /*******************************************************************
2418 Creates a DCE/RPC bind alter context authentication request which
2419 may contain a spnego auth blobl
2420 ********************************************************************/
2422 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2424 const struct ndr_syntax_id *abstract,
2425 const struct ndr_syntax_id *transfer,
2426 enum dcerpc_AuthLevel auth_level,
2427 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2430 DATA_BLOB auth_info;
2433 status = dcerpc_push_dcerpc_auth(mem_ctx,
2434 DCERPC_AUTH_TYPE_SPNEGO,
2436 0, /* auth_pad_length */
2437 1, /* auth_context_id */
2440 if (!NT_STATUS_IS_OK(status)) {
2444 status = create_bind_or_alt_ctx_internal(mem_ctx,
2451 data_blob_free(&auth_info);
2455 /****************************************************************************
2457 ****************************************************************************/
2459 struct rpc_pipe_bind_state {
2460 struct event_context *ev;
2461 struct rpc_pipe_client *cli;
2463 uint32_t rpc_call_id;
2466 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2467 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2468 struct rpc_pipe_bind_state *state,
2469 struct ncacn_packet *r);
2470 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2471 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2472 struct rpc_pipe_bind_state *state,
2473 struct ncacn_packet *r,
2474 DATA_BLOB *reply_pdu);
2475 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2477 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2478 struct event_context *ev,
2479 struct rpc_pipe_client *cli,
2480 struct cli_pipe_auth_data *auth)
2482 struct tevent_req *req, *subreq;
2483 struct rpc_pipe_bind_state *state;
2486 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2491 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2492 rpccli_pipe_txt(talloc_tos(), cli),
2493 (unsigned int)auth->auth_type,
2494 (unsigned int)auth->auth_level ));
2498 state->rpc_call_id = get_rpc_call_id();
2499 state->rpc_out = data_blob_null;
2501 cli->auth = talloc_move(cli, &auth);
2503 /* Marshall the outgoing data. */
2504 status = create_rpc_bind_req(state, cli,
2506 &cli->abstract_syntax,
2507 &cli->transfer_syntax,
2508 cli->auth->auth_type,
2509 cli->auth->auth_level,
2512 if (!NT_STATUS_IS_OK(status)) {
2516 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2517 DCERPC_PKT_BIND_ACK);
2518 if (subreq == NULL) {
2521 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2525 tevent_req_nterror(req, status);
2526 return tevent_req_post(req, ev);
2532 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2534 struct tevent_req *req = tevent_req_callback_data(
2535 subreq, struct tevent_req);
2536 struct rpc_pipe_bind_state *state = tevent_req_data(
2537 req, struct rpc_pipe_bind_state);
2538 DATA_BLOB reply_pdu;
2539 struct ncacn_packet *pkt;
2542 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2543 TALLOC_FREE(subreq);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2546 rpccli_pipe_txt(talloc_tos(), state->cli),
2547 nt_errstr(status)));
2548 tevent_req_nterror(req, status);
2552 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2553 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2554 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2558 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2559 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2562 * For authenticated binds we may need to do 3 or 4 leg binds.
2565 switch(state->cli->auth->auth_type) {
2567 case PIPE_AUTH_TYPE_NONE:
2568 case PIPE_AUTH_TYPE_SCHANNEL:
2569 /* Bind complete. */
2570 tevent_req_done(req);
2573 case PIPE_AUTH_TYPE_NTLMSSP:
2574 /* Need to send AUTH3 packet - no reply. */
2575 status = rpc_finish_auth3_bind_send(req, state, pkt);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 tevent_req_nterror(req, status);
2581 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2582 /* Need to send alter context request and reply. */
2583 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2585 if (!NT_STATUS_IS_OK(status)) {
2586 tevent_req_nterror(req, status);
2590 case PIPE_AUTH_TYPE_KRB5:
2594 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2595 (unsigned int)state->cli->auth->auth_type));
2596 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2600 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2601 struct rpc_pipe_bind_state *state,
2602 struct ncacn_packet *r)
2604 DATA_BLOB client_reply = data_blob_null;
2605 struct dcerpc_auth auth;
2606 struct tevent_req *subreq;
2609 if ((r->auth_length == 0)
2610 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2611 + r->auth_length)) {
2612 return NT_STATUS_INVALID_PARAMETER;
2615 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2616 &r->u.bind_ack.auth_info,
2618 if (!NT_STATUS_IS_OK(status)) {
2619 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2620 nt_errstr(status)));
2624 /* TODO - check auth_type/auth_level match. */
2626 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2627 auth.credentials, &client_reply);
2629 if (!NT_STATUS_IS_OK(status)) {
2630 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2631 "blob failed: %s.\n", nt_errstr(status)));
2635 data_blob_free(&state->rpc_out);
2637 status = create_rpc_bind_auth3(state,
2638 state->cli, state->rpc_call_id,
2639 state->cli->auth->auth_type,
2640 state->cli->auth->auth_level,
2641 &client_reply, &state->rpc_out);
2642 data_blob_free(&client_reply);
2644 if (!NT_STATUS_IS_OK(status)) {
2648 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2649 state->rpc_out.data, state->rpc_out.length);
2650 if (subreq == NULL) {
2651 return NT_STATUS_NO_MEMORY;
2653 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2654 return NT_STATUS_OK;
2657 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2659 struct tevent_req *req = tevent_req_callback_data(
2660 subreq, struct tevent_req);
2663 status = rpc_write_recv(subreq);
2664 TALLOC_FREE(subreq);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 tevent_req_nterror(req, status);
2669 tevent_req_done(req);
2672 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2673 struct rpc_pipe_bind_state *state,
2674 struct ncacn_packet *r,
2675 DATA_BLOB *reply_pdu)
2677 DATA_BLOB server_ntlm_response = data_blob_null;
2678 DATA_BLOB client_reply = data_blob_null;
2679 DATA_BLOB tmp_blob = data_blob_null;
2680 struct dcerpc_auth auth_info;
2681 DATA_BLOB auth_blob;
2682 struct tevent_req *subreq;
2685 if ((r->auth_length == 0)
2686 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2687 + r->auth_length)) {
2688 return NT_STATUS_INVALID_PARAMETER;
2691 /* Process the returned NTLMSSP blob first. */
2692 auth_blob = data_blob_const(reply_pdu->data
2694 - DCERPC_AUTH_TRAILER_LENGTH
2696 DCERPC_AUTH_TRAILER_LENGTH
2699 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
2700 if (!NT_STATUS_IS_OK(status)) {
2701 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2706 * The server might give us back two challenges - tmp_blob is for the
2709 if (!spnego_parse_challenge(auth_info.credentials,
2710 &server_ntlm_response, &tmp_blob)) {
2711 data_blob_free(&server_ntlm_response);
2712 data_blob_free(&tmp_blob);
2713 return NT_STATUS_INVALID_PARAMETER;
2716 /* We're finished with the server spnego response and the tmp_blob. */
2717 data_blob_free(&tmp_blob);
2719 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2720 server_ntlm_response, &client_reply);
2722 /* Finished with the server_ntlm response */
2723 data_blob_free(&server_ntlm_response);
2725 if (!NT_STATUS_IS_OK(status)) {
2726 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2727 "using server blob failed.\n"));
2728 data_blob_free(&client_reply);
2732 /* SPNEGO wrap the client reply. */
2733 tmp_blob = spnego_gen_auth(client_reply);
2734 data_blob_free(&client_reply);
2735 client_reply = tmp_blob;
2736 tmp_blob = data_blob_null;
2738 /* Now prepare the alter context pdu. */
2739 data_blob_free(&state->rpc_out);
2741 status = create_rpc_alter_context(state,
2743 &state->cli->abstract_syntax,
2744 &state->cli->transfer_syntax,
2745 state->cli->auth->auth_level,
2748 data_blob_free(&client_reply);
2750 if (!NT_STATUS_IS_OK(status)) {
2754 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2755 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2756 if (subreq == NULL) {
2757 return NT_STATUS_NO_MEMORY;
2759 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2760 return NT_STATUS_OK;
2763 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2765 struct tevent_req *req = tevent_req_callback_data(
2766 subreq, struct tevent_req);
2767 struct rpc_pipe_bind_state *state = tevent_req_data(
2768 req, struct rpc_pipe_bind_state);
2769 DATA_BLOB tmp_blob = data_blob_null;
2770 struct ncacn_packet *pkt;
2771 struct dcerpc_auth auth;
2774 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2775 TALLOC_FREE(subreq);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 tevent_req_nterror(req, status);
2781 status = dcerpc_pull_dcerpc_auth(pkt,
2782 &pkt->u.alter_resp.auth_info,
2784 if (!NT_STATUS_IS_OK(status)) {
2785 tevent_req_nterror(req, status);
2789 /* Check we got a valid auth response. */
2790 if (!spnego_parse_auth_response(auth.credentials,
2792 OID_NTLMSSP, &tmp_blob)) {
2793 data_blob_free(&tmp_blob);
2794 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2798 data_blob_free(&tmp_blob);
2800 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2801 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2802 tevent_req_done(req);
2805 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2807 return tevent_req_simple_recv_ntstatus(req);
2810 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2811 struct cli_pipe_auth_data *auth)
2813 TALLOC_CTX *frame = talloc_stackframe();
2814 struct event_context *ev;
2815 struct tevent_req *req;
2816 NTSTATUS status = NT_STATUS_OK;
2818 ev = event_context_init(frame);
2820 status = NT_STATUS_NO_MEMORY;
2824 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2826 status = NT_STATUS_NO_MEMORY;
2830 if (!tevent_req_poll(req, ev)) {
2831 status = map_nt_error_from_unix(errno);
2835 status = rpc_pipe_bind_recv(req);
2841 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2843 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2844 unsigned int timeout)
2848 if (rpc_cli->transport == NULL) {
2849 return RPCCLI_DEFAULT_TIMEOUT;
2852 if (rpc_cli->transport->set_timeout == NULL) {
2853 return RPCCLI_DEFAULT_TIMEOUT;
2856 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2858 return RPCCLI_DEFAULT_TIMEOUT;
2864 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2866 if (rpc_cli == NULL) {
2870 if (rpc_cli->transport == NULL) {
2874 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2877 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2879 struct cli_state *cli;
2881 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2882 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2883 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2887 cli = rpc_pipe_np_smb_conn(rpc_cli);
2891 E_md4hash(cli->password ? cli->password : "", nt_hash);
2895 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2896 struct cli_pipe_auth_data **presult)
2898 struct cli_pipe_auth_data *result;
2900 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2901 if (result == NULL) {
2902 return NT_STATUS_NO_MEMORY;
2905 result->auth_type = PIPE_AUTH_TYPE_NONE;
2906 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2908 result->user_name = talloc_strdup(result, "");
2909 result->domain = talloc_strdup(result, "");
2910 if ((result->user_name == NULL) || (result->domain == NULL)) {
2911 TALLOC_FREE(result);
2912 return NT_STATUS_NO_MEMORY;
2916 return NT_STATUS_OK;
2919 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2921 ntlmssp_end(&auth->a_u.ntlmssp_state);
2925 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2926 enum pipe_auth_type auth_type,
2927 enum dcerpc_AuthLevel auth_level,
2929 const char *username,
2930 const char *password,
2931 struct cli_pipe_auth_data **presult)
2933 struct cli_pipe_auth_data *result;
2936 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2937 if (result == NULL) {
2938 return NT_STATUS_NO_MEMORY;
2941 result->auth_type = auth_type;
2942 result->auth_level = auth_level;
2944 result->user_name = talloc_strdup(result, username);
2945 result->domain = talloc_strdup(result, domain);
2946 if ((result->user_name == NULL) || (result->domain == NULL)) {
2947 status = NT_STATUS_NO_MEMORY;
2951 status = ntlmssp_client_start(NULL,
2954 lp_client_ntlmv2_auth(),
2955 &result->a_u.ntlmssp_state);
2956 if (!NT_STATUS_IS_OK(status)) {
2960 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2962 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2963 if (!NT_STATUS_IS_OK(status)) {
2967 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2968 if (!NT_STATUS_IS_OK(status)) {
2972 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2973 if (!NT_STATUS_IS_OK(status)) {
2978 * Turn off sign+seal to allow selected auth level to turn it back on.
2980 result->a_u.ntlmssp_state->neg_flags &=
2981 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2983 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2984 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2985 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2986 result->a_u.ntlmssp_state->neg_flags
2987 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2991 return NT_STATUS_OK;
2994 TALLOC_FREE(result);
2998 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2999 enum dcerpc_AuthLevel auth_level,
3000 struct netlogon_creds_CredentialState *creds,
3001 struct cli_pipe_auth_data **presult)
3003 struct cli_pipe_auth_data *result;
3005 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3006 if (result == NULL) {
3007 return NT_STATUS_NO_MEMORY;
3010 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3011 result->auth_level = auth_level;
3013 result->user_name = talloc_strdup(result, "");
3014 result->domain = talloc_strdup(result, domain);
3015 if ((result->user_name == NULL) || (result->domain == NULL)) {
3019 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3020 if (result->a_u.schannel_auth == NULL) {
3024 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3025 result->a_u.schannel_auth->seq_num = 0;
3026 result->a_u.schannel_auth->initiator = true;
3027 result->a_u.schannel_auth->creds = creds;
3030 return NT_STATUS_OK;
3033 TALLOC_FREE(result);
3034 return NT_STATUS_NO_MEMORY;
3038 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3040 data_blob_free(&auth->session_key);
3045 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3046 enum dcerpc_AuthLevel auth_level,
3047 const char *service_princ,
3048 const char *username,
3049 const char *password,
3050 struct cli_pipe_auth_data **presult)
3053 struct cli_pipe_auth_data *result;
3055 if ((username != NULL) && (password != NULL)) {
3056 int ret = kerberos_kinit_password(username, password, 0, NULL);
3058 return NT_STATUS_ACCESS_DENIED;
3062 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3063 if (result == NULL) {
3064 return NT_STATUS_NO_MEMORY;
3067 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3068 result->auth_level = auth_level;
3071 * Username / domain need fixing!
3073 result->user_name = talloc_strdup(result, "");
3074 result->domain = talloc_strdup(result, "");
3075 if ((result->user_name == NULL) || (result->domain == NULL)) {
3079 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3080 result, struct kerberos_auth_struct);
3081 if (result->a_u.kerberos_auth == NULL) {
3084 talloc_set_destructor(result->a_u.kerberos_auth,
3085 cli_auth_kerberos_data_destructor);
3087 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3088 result, service_princ);
3089 if (result->a_u.kerberos_auth->service_principal == NULL) {
3094 return NT_STATUS_OK;
3097 TALLOC_FREE(result);
3098 return NT_STATUS_NO_MEMORY;
3100 return NT_STATUS_NOT_SUPPORTED;
3105 * Create an rpc pipe client struct, connecting to a tcp port.
3107 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3109 const struct ndr_syntax_id *abstract_syntax,
3110 struct rpc_pipe_client **presult)
3112 struct rpc_pipe_client *result;
3113 struct sockaddr_storage addr;
3117 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3118 if (result == NULL) {
3119 return NT_STATUS_NO_MEMORY;
3122 result->abstract_syntax = *abstract_syntax;
3123 result->transfer_syntax = ndr_transfer_syntax;
3124 result->dispatch = cli_do_rpc_ndr;
3125 result->dispatch_send = cli_do_rpc_ndr_send;
3126 result->dispatch_recv = cli_do_rpc_ndr_recv;
3128 result->desthost = talloc_strdup(result, host);
3129 result->srv_name_slash = talloc_asprintf_strupper_m(
3130 result, "\\\\%s", result->desthost);
3131 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3132 status = NT_STATUS_NO_MEMORY;
3136 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3137 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3139 if (!resolve_name(host, &addr, 0, false)) {
3140 status = NT_STATUS_NOT_FOUND;
3144 status = open_socket_out(&addr, port, 60, &fd);
3145 if (!NT_STATUS_IS_OK(status)) {
3148 set_socket_options(fd, lp_socket_options());
3150 status = rpc_transport_sock_init(result, fd, &result->transport);
3151 if (!NT_STATUS_IS_OK(status)) {
3156 result->transport->transport = NCACN_IP_TCP;
3159 return NT_STATUS_OK;
3162 TALLOC_FREE(result);
3167 * Determine the tcp port on which a dcerpc interface is listening
3168 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3171 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3172 const struct ndr_syntax_id *abstract_syntax,
3176 struct rpc_pipe_client *epm_pipe = NULL;
3177 struct cli_pipe_auth_data *auth = NULL;
3178 struct dcerpc_binding *map_binding = NULL;
3179 struct dcerpc_binding *res_binding = NULL;
3180 struct epm_twr_t *map_tower = NULL;
3181 struct epm_twr_t *res_towers = NULL;
3182 struct policy_handle *entry_handle = NULL;
3183 uint32_t num_towers = 0;
3184 uint32_t max_towers = 1;
3185 struct epm_twr_p_t towers;
3186 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3188 if (pport == NULL) {
3189 status = NT_STATUS_INVALID_PARAMETER;
3193 /* open the connection to the endpoint mapper */
3194 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3195 &ndr_table_epmapper.syntax_id,
3198 if (!NT_STATUS_IS_OK(status)) {
3202 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3203 if (!NT_STATUS_IS_OK(status)) {
3207 status = rpc_pipe_bind(epm_pipe, auth);
3208 if (!NT_STATUS_IS_OK(status)) {
3212 /* create tower for asking the epmapper */
3214 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3215 if (map_binding == NULL) {
3216 status = NT_STATUS_NO_MEMORY;
3220 map_binding->transport = NCACN_IP_TCP;
3221 map_binding->object = *abstract_syntax;
3222 map_binding->host = host; /* needed? */
3223 map_binding->endpoint = "0"; /* correct? needed? */
3225 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3226 if (map_tower == NULL) {
3227 status = NT_STATUS_NO_MEMORY;
3231 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3232 &(map_tower->tower));
3233 if (!NT_STATUS_IS_OK(status)) {
3237 /* allocate further parameters for the epm_Map call */
3239 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3240 if (res_towers == NULL) {
3241 status = NT_STATUS_NO_MEMORY;
3244 towers.twr = res_towers;
3246 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3247 if (entry_handle == NULL) {
3248 status = NT_STATUS_NO_MEMORY;
3252 /* ask the endpoint mapper for the port */
3254 status = rpccli_epm_Map(epm_pipe,
3256 CONST_DISCARD(struct GUID *,
3257 &(abstract_syntax->uuid)),
3264 if (!NT_STATUS_IS_OK(status)) {
3268 if (num_towers != 1) {
3269 status = NT_STATUS_UNSUCCESSFUL;
3273 /* extract the port from the answer */
3275 status = dcerpc_binding_from_tower(tmp_ctx,
3276 &(towers.twr->tower),
3278 if (!NT_STATUS_IS_OK(status)) {
3282 /* are further checks here necessary? */
3283 if (res_binding->transport != NCACN_IP_TCP) {
3284 status = NT_STATUS_UNSUCCESSFUL;
3288 *pport = (uint16_t)atoi(res_binding->endpoint);
3291 TALLOC_FREE(tmp_ctx);
3296 * Create a rpc pipe client struct, connecting to a host via tcp.
3297 * The port is determined by asking the endpoint mapper on the given
3300 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3301 const struct ndr_syntax_id *abstract_syntax,
3302 struct rpc_pipe_client **presult)
3307 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3308 if (!NT_STATUS_IS_OK(status)) {
3312 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3313 abstract_syntax, presult);
3316 /********************************************************************
3317 Create a rpc pipe client struct, connecting to a unix domain socket
3318 ********************************************************************/
3319 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3320 const struct ndr_syntax_id *abstract_syntax,
3321 struct rpc_pipe_client **presult)
3323 struct rpc_pipe_client *result;
3324 struct sockaddr_un addr;
3328 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3329 if (result == NULL) {
3330 return NT_STATUS_NO_MEMORY;
3333 result->abstract_syntax = *abstract_syntax;
3334 result->transfer_syntax = ndr_transfer_syntax;
3335 result->dispatch = cli_do_rpc_ndr;
3336 result->dispatch_send = cli_do_rpc_ndr_send;
3337 result->dispatch_recv = cli_do_rpc_ndr_recv;
3339 result->desthost = get_myname(result);
3340 result->srv_name_slash = talloc_asprintf_strupper_m(
3341 result, "\\\\%s", result->desthost);
3342 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3343 status = NT_STATUS_NO_MEMORY;
3347 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3348 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3350 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3352 status = map_nt_error_from_unix(errno);
3357 addr.sun_family = AF_UNIX;
3358 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3360 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3361 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3364 return map_nt_error_from_unix(errno);
3367 status = rpc_transport_sock_init(result, fd, &result->transport);
3368 if (!NT_STATUS_IS_OK(status)) {
3373 result->transport->transport = NCALRPC;
3376 return NT_STATUS_OK;
3379 TALLOC_FREE(result);
3383 struct rpc_pipe_client_np_ref {
3384 struct cli_state *cli;
3385 struct rpc_pipe_client *pipe;
3388 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3390 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3394 /****************************************************************************
3395 Open a named pipe over SMB to a remote server.
3397 * CAVEAT CALLER OF THIS FUNCTION:
3398 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3399 * so be sure that this function is called AFTER any structure (vs pointer)
3400 * assignment of the cli. In particular, libsmbclient does structure
3401 * assignments of cli, which invalidates the data in the returned
3402 * rpc_pipe_client if this function is called before the structure assignment
3405 ****************************************************************************/
3407 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3408 const struct ndr_syntax_id *abstract_syntax,
3409 struct rpc_pipe_client **presult)
3411 struct rpc_pipe_client *result;
3413 struct rpc_pipe_client_np_ref *np_ref;
3415 /* sanity check to protect against crashes */
3418 return NT_STATUS_INVALID_HANDLE;
3421 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3422 if (result == NULL) {
3423 return NT_STATUS_NO_MEMORY;
3426 result->abstract_syntax = *abstract_syntax;
3427 result->transfer_syntax = ndr_transfer_syntax;
3428 result->dispatch = cli_do_rpc_ndr;
3429 result->dispatch_send = cli_do_rpc_ndr_send;
3430 result->dispatch_recv = cli_do_rpc_ndr_recv;
3431 result->desthost = talloc_strdup(result, cli->desthost);
3432 result->srv_name_slash = talloc_asprintf_strupper_m(
3433 result, "\\\\%s", result->desthost);
3435 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3436 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3438 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3439 TALLOC_FREE(result);
3440 return NT_STATUS_NO_MEMORY;
3443 status = rpc_transport_np_init(result, cli, abstract_syntax,
3444 &result->transport);
3445 if (!NT_STATUS_IS_OK(status)) {
3446 TALLOC_FREE(result);
3450 result->transport->transport = NCACN_NP;
3452 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3453 if (np_ref == NULL) {
3454 TALLOC_FREE(result);
3455 return NT_STATUS_NO_MEMORY;
3458 np_ref->pipe = result;
3460 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3461 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3464 return NT_STATUS_OK;
3467 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3468 struct rpc_cli_smbd_conn *conn,
3469 const struct ndr_syntax_id *syntax,
3470 struct rpc_pipe_client **presult)
3472 struct rpc_pipe_client *result;
3473 struct cli_pipe_auth_data *auth;
3476 result = talloc(mem_ctx, struct rpc_pipe_client);
3477 if (result == NULL) {
3478 return NT_STATUS_NO_MEMORY;
3480 result->abstract_syntax = *syntax;
3481 result->transfer_syntax = ndr_transfer_syntax;
3482 result->dispatch = cli_do_rpc_ndr;
3483 result->dispatch_send = cli_do_rpc_ndr_send;
3484 result->dispatch_recv = cli_do_rpc_ndr_recv;
3485 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3486 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3488 result->desthost = talloc_strdup(result, global_myname());
3489 result->srv_name_slash = talloc_asprintf_strupper_m(
3490 result, "\\\\%s", global_myname());
3491 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3492 TALLOC_FREE(result);
3493 return NT_STATUS_NO_MEMORY;
3496 status = rpc_transport_smbd_init(result, conn, syntax,
3497 &result->transport);
3498 if (!NT_STATUS_IS_OK(status)) {
3499 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3500 nt_errstr(status)));
3501 TALLOC_FREE(result);
3505 status = rpccli_anon_bind_data(result, &auth);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3508 nt_errstr(status)));
3509 TALLOC_FREE(result);
3513 status = rpc_pipe_bind(result, auth);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3516 TALLOC_FREE(result);
3520 result->transport->transport = NCACN_INTERNAL;
3523 return NT_STATUS_OK;
3526 /****************************************************************************
3527 Open a pipe to a remote server.
3528 ****************************************************************************/
3530 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3531 enum dcerpc_transport_t transport,
3532 const struct ndr_syntax_id *interface,
3533 struct rpc_pipe_client **presult)
3535 switch (transport) {
3537 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3540 return rpc_pipe_open_np(cli, interface, presult);
3542 return NT_STATUS_NOT_IMPLEMENTED;
3546 /****************************************************************************
3547 Open a named pipe to an SMB server and bind anonymously.
3548 ****************************************************************************/
3550 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3551 enum dcerpc_transport_t transport,
3552 const struct ndr_syntax_id *interface,
3553 struct rpc_pipe_client **presult)
3555 struct rpc_pipe_client *result;
3556 struct cli_pipe_auth_data *auth;
3559 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3560 if (!NT_STATUS_IS_OK(status)) {
3564 status = rpccli_anon_bind_data(result, &auth);
3565 if (!NT_STATUS_IS_OK(status)) {
3566 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3567 nt_errstr(status)));
3568 TALLOC_FREE(result);
3573 * This is a bit of an abstraction violation due to the fact that an
3574 * anonymous bind on an authenticated SMB inherits the user/domain
3575 * from the enclosing SMB creds
3578 TALLOC_FREE(auth->user_name);
3579 TALLOC_FREE(auth->domain);
3581 auth->user_name = talloc_strdup(auth, cli->user_name);
3582 auth->domain = talloc_strdup(auth, cli->domain);
3583 auth->user_session_key = data_blob_talloc(auth,
3584 cli->user_session_key.data,
3585 cli->user_session_key.length);
3587 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3588 TALLOC_FREE(result);
3589 return NT_STATUS_NO_MEMORY;
3592 status = rpc_pipe_bind(result, auth);
3593 if (!NT_STATUS_IS_OK(status)) {
3595 if (ndr_syntax_id_equal(interface,
3596 &ndr_table_dssetup.syntax_id)) {
3597 /* non AD domains just don't have this pipe, avoid
3598 * level 0 statement in that case - gd */
3601 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3602 "%s failed with error %s\n",
3603 get_pipe_name_from_syntax(talloc_tos(), interface),
3604 nt_errstr(status) ));
3605 TALLOC_FREE(result);
3609 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3610 "%s and bound anonymously.\n",
3611 get_pipe_name_from_syntax(talloc_tos(), interface),
3615 return NT_STATUS_OK;
3618 /****************************************************************************
3619 ****************************************************************************/
3621 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3622 const struct ndr_syntax_id *interface,
3623 struct rpc_pipe_client **presult)
3625 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3626 interface, presult);
3629 /****************************************************************************
3630 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3631 ****************************************************************************/
3633 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3634 const struct ndr_syntax_id *interface,
3635 enum dcerpc_transport_t transport,
3636 enum pipe_auth_type auth_type,
3637 enum dcerpc_AuthLevel auth_level,
3639 const char *username,
3640 const char *password,
3641 struct rpc_pipe_client **presult)
3643 struct rpc_pipe_client *result;
3644 struct cli_pipe_auth_data *auth;
3647 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3648 if (!NT_STATUS_IS_OK(status)) {
3652 status = rpccli_ntlmssp_bind_data(
3653 result, auth_type, auth_level, domain, username,
3655 if (!NT_STATUS_IS_OK(status)) {
3656 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3657 nt_errstr(status)));
3661 status = rpc_pipe_bind(result, auth);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3664 nt_errstr(status) ));
3668 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3669 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3670 get_pipe_name_from_syntax(talloc_tos(), interface),
3671 cli->desthost, domain, username ));
3674 return NT_STATUS_OK;
3678 TALLOC_FREE(result);
3682 /****************************************************************************
3684 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3685 ****************************************************************************/
3687 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3688 const struct ndr_syntax_id *interface,
3689 enum dcerpc_transport_t transport,
3690 enum dcerpc_AuthLevel auth_level,
3692 const char *username,
3693 const char *password,
3694 struct rpc_pipe_client **presult)
3696 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3699 PIPE_AUTH_TYPE_NTLMSSP,
3707 /****************************************************************************
3709 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3710 ****************************************************************************/
3712 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3713 const struct ndr_syntax_id *interface,
3714 enum dcerpc_transport_t transport,
3715 enum dcerpc_AuthLevel auth_level,
3717 const char *username,
3718 const char *password,
3719 struct rpc_pipe_client **presult)
3721 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3724 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3732 /****************************************************************************
3733 Get a the schannel session key out of an already opened netlogon pipe.
3734 ****************************************************************************/
3735 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3736 struct cli_state *cli,
3740 enum netr_SchannelType sec_chan_type = 0;
3741 unsigned char machine_pwd[16];
3742 const char *machine_account;
3745 /* Get the machine account credentials from secrets.tdb. */
3746 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3749 DEBUG(0, ("get_schannel_session_key: could not fetch "
3750 "trust account password for domain '%s'\n",
3752 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3755 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3756 cli->desthost, /* server name */
3757 domain, /* domain */
3758 global_myname(), /* client name */
3759 machine_account, /* machine account name */
3764 if (!NT_STATUS_IS_OK(status)) {
3765 DEBUG(3, ("get_schannel_session_key_common: "
3766 "rpccli_netlogon_setup_creds failed with result %s "
3767 "to server %s, domain %s, machine account %s.\n",
3768 nt_errstr(status), cli->desthost, domain,
3773 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3774 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3776 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3779 return NT_STATUS_OK;;
3782 /****************************************************************************
3783 Open a netlogon pipe and get the schannel session key.
3784 Now exposed to external callers.
3785 ****************************************************************************/
3788 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3791 struct rpc_pipe_client **presult)
3793 struct rpc_pipe_client *netlogon_pipe = NULL;
3796 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3798 if (!NT_STATUS_IS_OK(status)) {
3802 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3804 if (!NT_STATUS_IS_OK(status)) {
3805 TALLOC_FREE(netlogon_pipe);
3809 *presult = netlogon_pipe;
3810 return NT_STATUS_OK;
3813 /****************************************************************************
3815 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3816 using session_key. sign and seal.
3818 The *pdc will be stolen onto this new pipe
3819 ****************************************************************************/
3821 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3822 const struct ndr_syntax_id *interface,
3823 enum dcerpc_transport_t transport,
3824 enum dcerpc_AuthLevel auth_level,
3826 struct netlogon_creds_CredentialState **pdc,
3827 struct rpc_pipe_client **presult)
3829 struct rpc_pipe_client *result;
3830 struct cli_pipe_auth_data *auth;
3833 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3834 if (!NT_STATUS_IS_OK(status)) {
3838 status = rpccli_schannel_bind_data(result, domain, auth_level,
3840 if (!NT_STATUS_IS_OK(status)) {
3841 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3842 nt_errstr(status)));
3843 TALLOC_FREE(result);
3847 status = rpc_pipe_bind(result, auth);
3848 if (!NT_STATUS_IS_OK(status)) {
3849 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3850 "cli_rpc_pipe_bind failed with error %s\n",
3851 nt_errstr(status) ));
3852 TALLOC_FREE(result);
3857 * The credentials on a new netlogon pipe are the ones we are passed
3858 * in - reference them in
3860 result->dc = talloc_move(result, pdc);
3862 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3863 "for domain %s and bound using schannel.\n",
3864 get_pipe_name_from_syntax(talloc_tos(), interface),
3865 cli->desthost, domain ));
3868 return NT_STATUS_OK;
3871 /****************************************************************************
3872 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3873 Fetch the session key ourselves using a temporary netlogon pipe. This
3874 version uses an ntlmssp auth bound netlogon pipe to get the key.
3875 ****************************************************************************/
3877 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3879 const char *username,
3880 const char *password,
3882 struct rpc_pipe_client **presult)
3884 struct rpc_pipe_client *netlogon_pipe = NULL;
3887 status = cli_rpc_pipe_open_spnego_ntlmssp(
3888 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3889 DCERPC_AUTH_LEVEL_PRIVACY,
3890 domain, username, password, &netlogon_pipe);
3891 if (!NT_STATUS_IS_OK(status)) {
3895 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3897 if (!NT_STATUS_IS_OK(status)) {
3898 TALLOC_FREE(netlogon_pipe);
3902 *presult = netlogon_pipe;
3903 return NT_STATUS_OK;
3906 /****************************************************************************
3907 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3908 Fetch the session key ourselves using a temporary netlogon pipe. This version
3909 uses an ntlmssp bind to get the session key.
3910 ****************************************************************************/
3912 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3913 const struct ndr_syntax_id *interface,
3914 enum dcerpc_transport_t transport,
3915 enum dcerpc_AuthLevel auth_level,
3917 const char *username,
3918 const char *password,
3919 struct rpc_pipe_client **presult)
3921 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3922 struct rpc_pipe_client *netlogon_pipe = NULL;
3923 struct rpc_pipe_client *result = NULL;
3926 status = get_schannel_session_key_auth_ntlmssp(
3927 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3930 "key from server %s for domain %s.\n",
3931 cli->desthost, domain ));
3935 status = cli_rpc_pipe_open_schannel_with_key(
3936 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3939 /* Now we've bound using the session key we can close the netlog pipe. */
3940 TALLOC_FREE(netlogon_pipe);
3942 if (NT_STATUS_IS_OK(status)) {
3948 /****************************************************************************
3949 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3950 Fetch the session key ourselves using a temporary netlogon pipe.
3951 ****************************************************************************/
3953 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3954 const struct ndr_syntax_id *interface,
3955 enum dcerpc_transport_t transport,
3956 enum dcerpc_AuthLevel auth_level,
3958 struct rpc_pipe_client **presult)
3960 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3961 struct rpc_pipe_client *netlogon_pipe = NULL;
3962 struct rpc_pipe_client *result = NULL;
3965 status = get_schannel_session_key(cli, domain, &neg_flags,
3967 if (!NT_STATUS_IS_OK(status)) {
3968 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3969 "key from server %s for domain %s.\n",
3970 cli->desthost, domain ));
3974 status = cli_rpc_pipe_open_schannel_with_key(
3975 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3978 /* Now we've bound using the session key we can close the netlog pipe. */
3979 TALLOC_FREE(netlogon_pipe);
3981 if (NT_STATUS_IS_OK(status)) {
3988 /****************************************************************************
3989 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3990 The idea is this can be called with service_princ, username and password all
3991 NULL so long as the caller has a TGT.
3992 ****************************************************************************/
3994 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3995 const struct ndr_syntax_id *interface,
3996 enum dcerpc_AuthLevel auth_level,
3997 const char *service_princ,
3998 const char *username,
3999 const char *password,
4000 struct rpc_pipe_client **presult)
4003 struct rpc_pipe_client *result;
4004 struct cli_pipe_auth_data *auth;
4007 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4008 if (!NT_STATUS_IS_OK(status)) {
4012 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4013 username, password, &auth);
4014 if (!NT_STATUS_IS_OK(status)) {
4015 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4016 nt_errstr(status)));
4017 TALLOC_FREE(result);
4021 status = rpc_pipe_bind(result, auth);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4024 "with error %s\n", nt_errstr(status)));
4025 TALLOC_FREE(result);
4030 return NT_STATUS_OK;
4032 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4033 return NT_STATUS_NOT_IMPLEMENTED;
4037 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4038 struct rpc_pipe_client *cli,
4039 DATA_BLOB *session_key)
4041 if (!session_key || !cli) {
4042 return NT_STATUS_INVALID_PARAMETER;
4046 return NT_STATUS_INVALID_PARAMETER;
4049 switch (cli->auth->auth_type) {
4050 case PIPE_AUTH_TYPE_SCHANNEL:
4051 *session_key = data_blob_talloc(mem_ctx,
4052 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4054 case PIPE_AUTH_TYPE_NTLMSSP:
4055 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4056 *session_key = data_blob_talloc(mem_ctx,
4057 cli->auth->a_u.ntlmssp_state->session_key.data,
4058 cli->auth->a_u.ntlmssp_state->session_key.length);
4060 case PIPE_AUTH_TYPE_KRB5:
4061 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4062 *session_key = data_blob_talloc(mem_ctx,
4063 cli->auth->a_u.kerberos_auth->session_key.data,
4064 cli->auth->a_u.kerberos_auth->session_key.length);
4066 case PIPE_AUTH_TYPE_NONE:
4067 *session_key = data_blob_talloc(mem_ctx,
4068 cli->auth->user_session_key.data,
4069 cli->auth->user_session_key.length);
4072 return NT_STATUS_NO_USER_SESSION_KEY;
4075 return NT_STATUS_OK;