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);
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 < SCHANNEL_SIG_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);
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);
919 if (!NT_STATUS_IS_OK(ret)) {
923 if (pdu->length != pkt->frag_length) {
924 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
925 (unsigned int)pdu->length,
926 (unsigned int)pkt->frag_length));
927 return NT_STATUS_INVALID_PARAMETER;
931 * Point the return values at the real data including the RPC
932 * header. Just in case the caller wants it.
936 /* Ensure we have the correct type. */
937 switch (pkt->ptype) {
938 case DCERPC_PKT_ALTER_RESP:
939 case DCERPC_PKT_BIND_ACK:
941 /* Alter context and bind ack share the same packet definitions. */
945 case DCERPC_PKT_RESPONSE:
947 /* Here's where we deal with incoming sign/seal. */
948 ret = cli_pipe_validate_rpc_response(cli, pkt, pdu,
950 if (!NT_STATUS_IS_OK(ret)) {
954 /* Point the return values at the NDR data.
955 * Remember to remove any ss padding. */
956 rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
958 if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
959 return NT_STATUS_BUFFER_TOO_SMALL;
962 rdata->length = pdu->length
963 - DCERPC_RESPONSE_LENGTH
966 /* Remember to remove the auth footer. */
967 if (pkt->auth_length) {
968 /* We've already done integer wrap tests on auth_len in
969 cli_pipe_validate_rpc_response(). */
970 if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH
971 + pkt->auth_length) {
972 return NT_STATUS_BUFFER_TOO_SMALL;
974 rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH
978 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
979 pdu->length, rdata->length, ss_padding_len));
982 * If this is the first reply, and the allocation hint is
983 * reasonable, try and set up the reply_pdu DATA_BLOB to the
987 if ((reply_pdu->length == 0) &&
988 pkt->u.response.alloc_hint &&
989 (pkt->u.response.alloc_hint < 15*1024*1024)) {
990 if (!data_blob_realloc(mem_ctx, reply_pdu,
991 pkt->u.response.alloc_hint)) {
992 DEBUG(0, ("reply alloc hint %d too "
993 "large to allocate\n",
994 (int)pkt->u.response.alloc_hint));
995 return NT_STATUS_NO_MEMORY;
1001 case DCERPC_PKT_BIND_NAK:
1002 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1003 "received from %s!\n",
1004 rpccli_pipe_txt(talloc_tos(), cli)));
1005 /* Use this for now... */
1006 return NT_STATUS_NETWORK_ACCESS_DENIED;
1008 case DCERPC_PKT_FAULT:
1010 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1011 "code %s received from %s!\n",
1012 dcerpc_errstr(talloc_tos(),
1013 pkt->u.fault.status),
1014 rpccli_pipe_txt(talloc_tos(), cli)));
1016 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
1017 return NT_STATUS_UNSUCCESSFUL;
1019 return NT_STATUS(pkt->u.fault.status);
1023 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1024 (unsigned int)pkt->ptype,
1025 rpccli_pipe_txt(talloc_tos(), cli)));
1026 return NT_STATUS_INVALID_INFO_CLASS;
1029 if (pkt->ptype != expected_pkt_type) {
1030 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1031 "got an unexpected RPC packet type - %u, not %u\n",
1032 rpccli_pipe_txt(talloc_tos(), cli),
1034 expected_pkt_type));
1035 return NT_STATUS_INVALID_INFO_CLASS;
1038 /* Do this just before return - we don't want to modify any rpc header
1039 data before now as we may have needed to do cryptographic actions on
1042 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
1043 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1044 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1045 "setting fragment first/last ON.\n"));
1046 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
1047 DCERPC_PFC_FLAG_LAST;
1050 return NT_STATUS_OK;
1053 /****************************************************************************
1054 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1055 ****************************************************************************/
1057 struct cli_api_pipe_state {
1058 struct event_context *ev;
1059 struct rpc_cli_transport *transport;
1064 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1065 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1066 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1068 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1069 struct event_context *ev,
1070 struct rpc_cli_transport *transport,
1071 uint8_t *data, size_t data_len,
1072 uint32_t max_rdata_len)
1074 struct tevent_req *req, *subreq;
1075 struct cli_api_pipe_state *state;
1078 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1083 state->transport = transport;
1085 if (max_rdata_len < RPC_HEADER_LEN) {
1087 * For a RPC reply we always need at least RPC_HEADER_LEN
1088 * bytes. We check this here because we will receive
1089 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1091 status = NT_STATUS_INVALID_PARAMETER;
1095 if (transport->trans_send != NULL) {
1096 subreq = transport->trans_send(state, ev, data, data_len,
1097 max_rdata_len, transport->priv);
1098 if (subreq == NULL) {
1101 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1106 * If the transport does not provide a "trans" routine, i.e. for
1107 * example the ncacn_ip_tcp transport, do the write/read step here.
1110 subreq = rpc_write_send(state, ev, transport, data, data_len);
1111 if (subreq == NULL) {
1114 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1118 tevent_req_nterror(req, status);
1119 return tevent_req_post(req, ev);
1125 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1127 struct tevent_req *req = tevent_req_callback_data(
1128 subreq, struct tevent_req);
1129 struct cli_api_pipe_state *state = tevent_req_data(
1130 req, struct cli_api_pipe_state);
1133 status = state->transport->trans_recv(subreq, state, &state->rdata,
1135 TALLOC_FREE(subreq);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 tevent_req_nterror(req, status);
1140 tevent_req_done(req);
1143 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1145 struct tevent_req *req = tevent_req_callback_data(
1146 subreq, struct tevent_req);
1147 struct cli_api_pipe_state *state = tevent_req_data(
1148 req, struct cli_api_pipe_state);
1151 status = rpc_write_recv(subreq);
1152 TALLOC_FREE(subreq);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 tevent_req_nterror(req, status);
1158 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1159 if (tevent_req_nomem(state->rdata, req)) {
1164 * We don't need to use rpc_read_send here, the upper layer will cope
1165 * with a short read, transport->trans_send could also return less
1166 * than state->max_rdata_len.
1168 subreq = state->transport->read_send(state, state->ev, state->rdata,
1170 state->transport->priv);
1171 if (tevent_req_nomem(subreq, req)) {
1174 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1177 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1179 struct tevent_req *req = tevent_req_callback_data(
1180 subreq, struct tevent_req);
1181 struct cli_api_pipe_state *state = tevent_req_data(
1182 req, struct cli_api_pipe_state);
1186 status = state->transport->read_recv(subreq, &received);
1187 TALLOC_FREE(subreq);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 tevent_req_nterror(req, status);
1192 state->rdata_len = received;
1193 tevent_req_done(req);
1196 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1197 uint8_t **prdata, uint32_t *prdata_len)
1199 struct cli_api_pipe_state *state = tevent_req_data(
1200 req, struct cli_api_pipe_state);
1203 if (tevent_req_is_nterror(req, &status)) {
1207 *prdata = talloc_move(mem_ctx, &state->rdata);
1208 *prdata_len = state->rdata_len;
1209 return NT_STATUS_OK;
1212 /****************************************************************************
1213 Send data on an rpc pipe via trans. The data must be the last
1214 pdu fragment of an NDR data stream.
1216 Receive response data from an rpc pipe, which may be large...
1218 Read the first fragment: unfortunately have to use SMBtrans for the first
1219 bit, then SMBreadX for subsequent bits.
1221 If first fragment received also wasn't the last fragment, continue
1222 getting fragments until we _do_ receive the last fragment.
1224 Request/Response PDU's look like the following...
1226 |<------------------PDU len----------------------------------------------->|
1227 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1229 +------------+-----------------+-------------+---------------+-------------+
1230 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1231 +------------+-----------------+-------------+---------------+-------------+
1233 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1234 signing & sealing being negotiated.
1236 ****************************************************************************/
1238 struct rpc_api_pipe_state {
1239 struct event_context *ev;
1240 struct rpc_pipe_client *cli;
1241 uint8_t expected_pkt_type;
1243 DATA_BLOB incoming_frag;
1244 struct ncacn_packet *pkt;
1246 /* Incoming reply */
1247 DATA_BLOB reply_pdu;
1248 size_t reply_pdu_offset;
1252 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1253 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1255 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1256 struct event_context *ev,
1257 struct rpc_pipe_client *cli,
1258 DATA_BLOB *data, /* Outgoing PDU */
1259 uint8_t expected_pkt_type)
1261 struct tevent_req *req, *subreq;
1262 struct rpc_api_pipe_state *state;
1263 uint16_t max_recv_frag;
1266 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1272 state->expected_pkt_type = expected_pkt_type;
1273 state->incoming_frag = data_blob_null;
1274 state->reply_pdu = data_blob_null;
1275 state->reply_pdu_offset = 0;
1276 state->endianess = DCERPC_DREP_LE;
1279 * Ensure we're not sending too much.
1281 if (data->length > cli->max_xmit_frag) {
1282 status = NT_STATUS_INVALID_PARAMETER;
1286 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1288 /* get the header first, then fetch the rest once we have
1289 * the frag_length available */
1290 max_recv_frag = RPC_HEADER_LEN;
1292 subreq = cli_api_pipe_send(state, ev, cli->transport,
1293 data->data, data->length, max_recv_frag);
1294 if (subreq == NULL) {
1297 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1301 tevent_req_nterror(req, status);
1302 return tevent_req_post(req, ev);
1308 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1310 struct tevent_req *req = tevent_req_callback_data(
1311 subreq, struct tevent_req);
1312 struct rpc_api_pipe_state *state = tevent_req_data(
1313 req, struct rpc_api_pipe_state);
1315 uint8_t *rdata = NULL;
1316 uint32_t rdata_len = 0;
1318 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1319 TALLOC_FREE(subreq);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1322 tevent_req_nterror(req, status);
1326 if (rdata == NULL) {
1327 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1328 rpccli_pipe_txt(talloc_tos(), state->cli)));
1329 tevent_req_done(req);
1334 * Move data on state->incoming_frag.
1336 state->incoming_frag.data = talloc_move(state, &rdata);
1337 state->incoming_frag.length = rdata_len;
1338 if (!state->incoming_frag.data) {
1339 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1343 /* Ensure we have enough data for a pdu. */
1344 subreq = get_complete_frag_send(state, state->ev, state->cli,
1345 &state->incoming_frag);
1346 if (tevent_req_nomem(subreq, req)) {
1349 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1352 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1354 struct tevent_req *req = tevent_req_callback_data(
1355 subreq, struct tevent_req);
1356 struct rpc_api_pipe_state *state = tevent_req_data(
1357 req, struct rpc_api_pipe_state);
1359 DATA_BLOB rdata = data_blob_null;
1361 status = get_complete_frag_recv(subreq);
1362 TALLOC_FREE(subreq);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 DEBUG(5, ("get_complete_frag failed: %s\n",
1365 nt_errstr(status)));
1366 tevent_req_nterror(req, status);
1370 state->pkt = talloc(state, struct ncacn_packet);
1372 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1376 status = cli_pipe_validate_current_pdu(state,
1377 state->cli, state->pkt,
1378 &state->incoming_frag,
1379 state->expected_pkt_type,
1383 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1384 (unsigned)state->incoming_frag.length,
1385 (unsigned)state->reply_pdu_offset,
1386 nt_errstr(status)));
1388 if (!NT_STATUS_IS_OK(status)) {
1389 tevent_req_nterror(req, status);
1393 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1394 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1396 * Set the data type correctly for big-endian data on the
1399 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1401 rpccli_pipe_txt(talloc_tos(), state->cli)));
1402 state->endianess = 0x00; /* BIG ENDIAN */
1405 * Check endianness on subsequent packets.
1407 if (state->endianess != state->pkt->drep[0]) {
1408 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1410 state->endianess?"little":"big",
1411 state->pkt->drep[0]?"little":"big"));
1412 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1416 /* Now copy the data portion out of the pdu into rbuf. */
1417 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1418 if (!data_blob_realloc(NULL, &state->reply_pdu,
1419 state->reply_pdu_offset + rdata.length)) {
1420 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1425 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1426 rdata.data, rdata.length);
1427 state->reply_pdu_offset += rdata.length;
1429 /* reset state->incoming_frag, there is no need to free it,
1430 * it will be reallocated to the right size the next time
1432 state->incoming_frag.length = 0;
1434 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1435 /* make sure the pdu length is right now that we
1436 * have all the data available (alloc hint may
1437 * have allocated more than was actually used) */
1438 state->reply_pdu.length = state->reply_pdu_offset;
1439 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1440 rpccli_pipe_txt(talloc_tos(), state->cli),
1441 (unsigned)state->reply_pdu.length));
1442 tevent_req_done(req);
1446 subreq = get_complete_frag_send(state, state->ev, state->cli,
1447 &state->incoming_frag);
1448 if (tevent_req_nomem(subreq, req)) {
1451 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1454 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1455 struct ncacn_packet **pkt,
1456 DATA_BLOB *reply_pdu)
1458 struct rpc_api_pipe_state *state = tevent_req_data(
1459 req, struct rpc_api_pipe_state);
1462 if (tevent_req_is_nterror(req, &status)) {
1466 /* return data to caller and assign it ownership of memory */
1468 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1469 reply_pdu->length = state->reply_pdu.length;
1470 state->reply_pdu.length = 0;
1472 data_blob_free(&state->reply_pdu);
1476 *pkt = talloc_steal(mem_ctx, state->pkt);
1479 return NT_STATUS_OK;
1482 /*******************************************************************
1483 Creates krb5 auth bind.
1484 ********************************************************************/
1486 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1487 enum dcerpc_AuthLevel auth_level,
1488 DATA_BLOB *auth_info)
1493 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1494 DATA_BLOB tkt = data_blob_null;
1495 DATA_BLOB tkt_wrapped = data_blob_null;
1497 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1498 a->service_principal ));
1500 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1502 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1503 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1506 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1508 a->service_principal,
1509 error_message(ret) ));
1511 data_blob_free(&tkt);
1512 return NT_STATUS_INVALID_PARAMETER;
1515 /* wrap that up in a nice GSS-API wrapping */
1516 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1518 data_blob_free(&tkt);
1520 status = dcerpc_push_dcerpc_auth(cli,
1521 DCERPC_AUTH_TYPE_KRB5,
1523 0, /* auth_pad_length */
1524 1, /* auth_context_id */
1527 if (!NT_STATUS_IS_OK(status)) {
1528 data_blob_free(&tkt_wrapped);
1532 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1533 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1535 return NT_STATUS_OK;
1537 return NT_STATUS_INVALID_PARAMETER;
1541 /*******************************************************************
1542 Creates SPNEGO NTLMSSP auth bind.
1543 ********************************************************************/
1545 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1546 enum dcerpc_AuthLevel auth_level,
1547 DATA_BLOB *auth_info)
1550 DATA_BLOB null_blob = data_blob_null;
1551 DATA_BLOB request = data_blob_null;
1552 DATA_BLOB spnego_msg = data_blob_null;
1554 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1555 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1559 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1560 data_blob_free(&request);
1564 /* Wrap this in SPNEGO. */
1565 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1567 data_blob_free(&request);
1569 status = dcerpc_push_dcerpc_auth(cli,
1570 DCERPC_AUTH_TYPE_SPNEGO,
1572 0, /* auth_pad_length */
1573 1, /* auth_context_id */
1576 if (!NT_STATUS_IS_OK(status)) {
1577 data_blob_free(&spnego_msg);
1581 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1582 dump_data(5, spnego_msg.data, spnego_msg.length);
1584 return NT_STATUS_OK;
1587 /*******************************************************************
1588 Creates NTLMSSP auth bind.
1589 ********************************************************************/
1591 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1592 enum dcerpc_AuthLevel auth_level,
1593 DATA_BLOB *auth_info)
1596 DATA_BLOB null_blob = data_blob_null;
1597 DATA_BLOB request = data_blob_null;
1599 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1600 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1604 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1605 data_blob_free(&request);
1609 status = dcerpc_push_dcerpc_auth(cli,
1610 DCERPC_AUTH_TYPE_NTLMSSP,
1612 0, /* auth_pad_length */
1613 1, /* auth_context_id */
1616 if (!NT_STATUS_IS_OK(status)) {
1617 data_blob_free(&request);
1621 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1622 dump_data(5, request.data, request.length);
1624 return NT_STATUS_OK;
1627 /*******************************************************************
1628 Creates schannel auth bind.
1629 ********************************************************************/
1631 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1632 enum dcerpc_AuthLevel auth_level,
1633 DATA_BLOB *auth_info)
1636 struct NL_AUTH_MESSAGE r;
1637 DATA_BLOB schannel_blob;
1639 /* Use lp_workgroup() if domain not specified */
1641 if (!cli->auth->domain || !cli->auth->domain[0]) {
1642 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1643 if (cli->auth->domain == NULL) {
1644 return NT_STATUS_NO_MEMORY;
1649 * Now marshall the data into the auth parse_struct.
1652 r.MessageType = NL_NEGOTIATE_REQUEST;
1653 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1654 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1655 r.oem_netbios_domain.a = cli->auth->domain;
1656 r.oem_netbios_computer.a = global_myname();
1658 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1659 if (!NT_STATUS_IS_OK(status)) {
1663 status = dcerpc_push_dcerpc_auth(cli,
1664 DCERPC_AUTH_TYPE_SCHANNEL,
1666 0, /* auth_pad_length */
1667 1, /* auth_context_id */
1670 if (!NT_STATUS_IS_OK(status)) {
1674 return NT_STATUS_OK;
1677 /*******************************************************************
1678 Creates the internals of a DCE/RPC bind request or alter context PDU.
1679 ********************************************************************/
1681 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1682 enum dcerpc_pkt_type ptype,
1684 const struct ndr_syntax_id *abstract,
1685 const struct ndr_syntax_id *transfer,
1686 const DATA_BLOB *auth_info,
1689 uint16 auth_len = auth_info->length;
1691 union dcerpc_payload u;
1692 struct dcerpc_ctx_list ctx_list;
1695 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1698 ctx_list.context_id = 0;
1699 ctx_list.num_transfer_syntaxes = 1;
1700 ctx_list.abstract_syntax = *abstract;
1701 ctx_list.transfer_syntaxes = discard_const(transfer);
1703 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1704 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1705 u.bind.assoc_group_id = 0x0;
1706 u.bind.num_contexts = 1;
1707 u.bind.ctx_list = &ctx_list;
1708 u.bind.auth_info = *auth_info;
1710 status = dcerpc_push_ncacn_packet(mem_ctx,
1712 DCERPC_PFC_FLAG_FIRST |
1713 DCERPC_PFC_FLAG_LAST,
1718 if (!NT_STATUS_IS_OK(status)) {
1719 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1723 return NT_STATUS_OK;
1726 /*******************************************************************
1727 Creates a DCE/RPC bind request.
1728 ********************************************************************/
1730 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1731 struct rpc_pipe_client *cli,
1733 const struct ndr_syntax_id *abstract,
1734 const struct ndr_syntax_id *transfer,
1735 enum pipe_auth_type auth_type,
1736 enum dcerpc_AuthLevel auth_level,
1739 DATA_BLOB auth_info = data_blob_null;
1740 NTSTATUS ret = NT_STATUS_OK;
1742 switch (auth_type) {
1743 case PIPE_AUTH_TYPE_SCHANNEL:
1744 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1745 if (!NT_STATUS_IS_OK(ret)) {
1750 case PIPE_AUTH_TYPE_NTLMSSP:
1751 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1752 if (!NT_STATUS_IS_OK(ret)) {
1757 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1758 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1759 if (!NT_STATUS_IS_OK(ret)) {
1764 case PIPE_AUTH_TYPE_KRB5:
1765 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1766 if (!NT_STATUS_IS_OK(ret)) {
1771 case PIPE_AUTH_TYPE_NONE:
1775 /* "Can't" happen. */
1776 return NT_STATUS_INVALID_INFO_CLASS;
1779 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1789 /*******************************************************************
1790 Create and add the NTLMSSP sign/seal auth header and data.
1791 ********************************************************************/
1793 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1794 uint32 ss_padding_len,
1797 DATA_BLOB auth_info;
1799 DATA_BLOB auth_blob = data_blob_null;
1800 uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
1802 if (!cli->auth->a_u.ntlmssp_state) {
1803 return NT_STATUS_INVALID_PARAMETER;
1806 /* marshall the dcerpc_auth with an actually empty auth_blob.
1807 * this is needed because the ntmlssp signature includes the
1809 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1810 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1811 cli->auth->auth_level,
1813 1 /* context id. */,
1816 if (!NT_STATUS_IS_OK(status)) {
1820 /* append the header */
1821 if (!data_blob_append(NULL, rpc_out,
1822 auth_info.data, auth_info.length)) {
1823 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1824 (unsigned int)auth_info.length));
1825 return NT_STATUS_NO_MEMORY;
1827 data_blob_free(&auth_info);
1829 switch (cli->auth->auth_level) {
1830 case DCERPC_AUTH_LEVEL_PRIVACY:
1831 /* Data portion is encrypted. */
1832 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1835 + DCERPC_RESPONSE_LENGTH,
1840 if (!NT_STATUS_IS_OK(status)) {
1845 case DCERPC_AUTH_LEVEL_INTEGRITY:
1846 /* Data is signed. */
1847 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1850 + DCERPC_RESPONSE_LENGTH,
1855 if (!NT_STATUS_IS_OK(status)) {
1862 smb_panic("bad auth level");
1864 return NT_STATUS_INVALID_PARAMETER;
1867 /* Finally attach the blob. */
1868 if (!data_blob_append(NULL, rpc_out,
1869 auth_blob.data, auth_blob.length)) {
1870 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1871 (unsigned int)auth_info.length));
1872 return NT_STATUS_NO_MEMORY;
1874 data_blob_free(&auth_blob);
1876 return NT_STATUS_OK;
1879 /*******************************************************************
1880 Create and add the schannel sign/seal auth header and data.
1881 ********************************************************************/
1883 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1884 uint32 ss_padding_len,
1887 DATA_BLOB auth_info;
1888 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1889 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
1890 size_t data_and_pad_len = rpc_out->length
1891 - DCERPC_RESPONSE_LENGTH;
1896 return NT_STATUS_INVALID_PARAMETER;
1899 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1902 switch (cli->auth->auth_level) {
1903 case DCERPC_AUTH_LEVEL_PRIVACY:
1904 status = netsec_outgoing_packet(sas,
1911 case DCERPC_AUTH_LEVEL_INTEGRITY:
1912 status = netsec_outgoing_packet(sas,
1920 status = NT_STATUS_INTERNAL_ERROR;
1924 if (!NT_STATUS_IS_OK(status)) {
1925 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1926 nt_errstr(status)));
1930 if (DEBUGLEVEL >= 10) {
1931 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1934 /* Finally marshall the blob. */
1935 status = dcerpc_push_dcerpc_auth(rpc_out->data,
1936 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1937 cli->auth->auth_level,
1939 1 /* context id. */,
1942 if (!NT_STATUS_IS_OK(status)) {
1945 data_blob_free(&blob);
1947 if (!data_blob_append(NULL, rpc_out,
1948 auth_info.data, auth_info.length)) {
1949 return NT_STATUS_NO_MEMORY;
1951 data_blob_free(&auth_info);
1953 return NT_STATUS_OK;
1956 /*******************************************************************
1957 Calculate how much data we're going to send in this packet, also
1958 work out any sign/seal padding length.
1959 ********************************************************************/
1961 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1965 uint32 *p_ss_padding)
1967 uint32 data_space, data_len;
1970 if ((data_left > 0) && (sys_random() % 2)) {
1971 data_left = MAX(data_left/2, 1);
1975 switch (cli->auth->auth_level) {
1976 case DCERPC_AUTH_LEVEL_NONE:
1977 case DCERPC_AUTH_LEVEL_CONNECT:
1978 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1979 data_len = MIN(data_space, data_left);
1982 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1985 case DCERPC_AUTH_LEVEL_INTEGRITY:
1986 case DCERPC_AUTH_LEVEL_PRIVACY:
1987 /* Treat the same for all authenticated rpc requests. */
1988 switch(cli->auth->auth_type) {
1989 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1990 case PIPE_AUTH_TYPE_NTLMSSP:
1991 *p_auth_len = NTLMSSP_SIG_SIZE;
1993 case PIPE_AUTH_TYPE_SCHANNEL:
1994 *p_auth_len = SCHANNEL_SIG_SIZE;
1997 smb_panic("bad auth type");
2001 data_space = cli->max_xmit_frag
2002 - DCERPC_REQUEST_LENGTH
2003 - DCERPC_AUTH_TRAILER_LENGTH
2006 data_len = MIN(data_space, data_left);
2008 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2009 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2011 *p_frag_len = DCERPC_REQUEST_LENGTH
2012 + data_len + *p_ss_padding
2013 + DCERPC_AUTH_TRAILER_LENGTH
2018 smb_panic("bad auth level");
2024 /*******************************************************************
2026 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2027 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2028 and deals with signing/sealing details.
2029 ********************************************************************/
2031 struct rpc_api_pipe_req_state {
2032 struct event_context *ev;
2033 struct rpc_pipe_client *cli;
2036 prs_struct *req_data;
2037 uint32_t req_data_sent;
2039 DATA_BLOB reply_pdu;
2042 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2043 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2044 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2045 bool *is_last_frag);
2047 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2048 struct event_context *ev,
2049 struct rpc_pipe_client *cli,
2051 prs_struct *req_data)
2053 struct tevent_req *req, *subreq;
2054 struct rpc_api_pipe_req_state *state;
2058 req = tevent_req_create(mem_ctx, &state,
2059 struct rpc_api_pipe_req_state);
2065 state->op_num = op_num;
2066 state->req_data = req_data;
2067 state->req_data_sent = 0;
2068 state->call_id = get_rpc_call_id();
2069 state->reply_pdu = data_blob_null;
2070 state->rpc_out = data_blob_null;
2072 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2073 + RPC_MAX_SIGN_SIZE) {
2074 /* Server is screwed up ! */
2075 status = NT_STATUS_INVALID_PARAMETER;
2079 status = prepare_next_frag(state, &is_last_frag);
2080 if (!NT_STATUS_IS_OK(status)) {
2085 subreq = rpc_api_pipe_send(state, ev, state->cli,
2087 DCERPC_PKT_RESPONSE);
2088 if (subreq == NULL) {
2091 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2093 subreq = rpc_write_send(state, ev, cli->transport,
2094 state->rpc_out.data,
2095 state->rpc_out.length);
2096 if (subreq == NULL) {
2099 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2105 tevent_req_nterror(req, status);
2106 return tevent_req_post(req, ev);
2112 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2115 uint32_t data_sent_thistime;
2119 uint32_t ss_padding;
2121 char pad[8] = { 0, };
2123 union dcerpc_payload u;
2125 data_left = prs_offset(state->req_data) - state->req_data_sent;
2127 data_sent_thistime = calculate_data_len_tosend(
2128 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2130 if (state->req_data_sent == 0) {
2131 flags = DCERPC_PFC_FLAG_FIRST;
2134 if (data_sent_thistime == data_left) {
2135 flags |= DCERPC_PFC_FLAG_LAST;
2138 data_blob_free(&state->rpc_out);
2140 ZERO_STRUCT(u.request);
2142 u.request.alloc_hint = prs_offset(state->req_data);
2143 u.request.context_id = 0;
2144 u.request.opnum = state->op_num;
2146 status = dcerpc_push_ncacn_packet(state,
2153 if (!NT_STATUS_IS_OK(status)) {
2157 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2158 * compute it right for requests */
2159 dcerpc_set_frag_length(&state->rpc_out, frag_len);
2161 /* Copy in the data, plus any ss padding. */
2162 if (!data_blob_append(NULL, &state->rpc_out,
2163 prs_data_p(state->req_data)
2164 + state->req_data_sent,
2165 data_sent_thistime)) {
2166 return NT_STATUS_NO_MEMORY;
2170 /* Copy the sign/seal padding data. */
2171 if (!data_blob_append(NULL, &state->rpc_out,
2173 return NT_STATUS_NO_MEMORY;
2177 /* Generate any auth sign/seal and add the auth footer. */
2178 switch (state->cli->auth->auth_type) {
2179 case PIPE_AUTH_TYPE_NONE:
2180 status = NT_STATUS_OK;
2182 case PIPE_AUTH_TYPE_NTLMSSP:
2183 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2184 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2187 case PIPE_AUTH_TYPE_SCHANNEL:
2188 status = add_schannel_auth_footer(state->cli, ss_padding,
2192 status = NT_STATUS_INVALID_PARAMETER;
2196 state->req_data_sent += data_sent_thistime;
2197 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2202 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2204 struct tevent_req *req = tevent_req_callback_data(
2205 subreq, struct tevent_req);
2206 struct rpc_api_pipe_req_state *state = tevent_req_data(
2207 req, struct rpc_api_pipe_req_state);
2211 status = rpc_write_recv(subreq);
2212 TALLOC_FREE(subreq);
2213 if (!NT_STATUS_IS_OK(status)) {
2214 tevent_req_nterror(req, status);
2218 status = prepare_next_frag(state, &is_last_frag);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 tevent_req_nterror(req, status);
2225 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2227 DCERPC_PKT_RESPONSE);
2228 if (tevent_req_nomem(subreq, req)) {
2231 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2233 subreq = rpc_write_send(state, state->ev,
2234 state->cli->transport,
2235 state->rpc_out.data,
2236 state->rpc_out.length);
2237 if (tevent_req_nomem(subreq, req)) {
2240 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2245 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2247 struct tevent_req *req = tevent_req_callback_data(
2248 subreq, struct tevent_req);
2249 struct rpc_api_pipe_req_state *state = tevent_req_data(
2250 req, struct rpc_api_pipe_req_state);
2253 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2254 TALLOC_FREE(subreq);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 tevent_req_nterror(req, status);
2259 tevent_req_done(req);
2262 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2263 DATA_BLOB *reply_pdu)
2265 struct rpc_api_pipe_req_state *state = tevent_req_data(
2266 req, struct rpc_api_pipe_req_state);
2269 if (tevent_req_is_nterror(req, &status)) {
2271 * We always have to initialize to reply pdu, even if there is
2272 * none. The rpccli_* caller routines expect this.
2274 *reply_pdu = data_blob_null;
2278 /* return data to caller and assign it ownership of memory */
2279 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2280 reply_pdu->length = state->reply_pdu.length;
2281 state->reply_pdu.length = 0;
2283 return NT_STATUS_OK;
2287 /****************************************************************************
2288 Set the handle state.
2289 ****************************************************************************/
2291 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2292 const char *pipe_name, uint16 device_state)
2294 bool state_set = False;
2296 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2297 char *rparam = NULL;
2299 uint32 rparam_len, rdata_len;
2301 if (pipe_name == NULL)
2304 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2305 cli->fnum, pipe_name, device_state));
2307 /* create parameters: device state */
2308 SSVAL(param, 0, device_state);
2310 /* create setup parameters. */
2312 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2314 /* send the data on \PIPE\ */
2315 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2316 setup, 2, 0, /* setup, length, max */
2317 param, 2, 0, /* param, length, max */
2318 NULL, 0, 1024, /* data, length, max */
2319 &rparam, &rparam_len, /* return param, length */
2320 &rdata, &rdata_len)) /* return data, length */
2322 DEBUG(5, ("Set Handle state: return OK\n"));
2333 /****************************************************************************
2334 Check the rpc bind acknowledge response.
2335 ****************************************************************************/
2337 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2338 const struct ndr_syntax_id *transfer)
2340 struct dcerpc_ack_ctx ctx;
2342 if (r->secondary_address_size == 0) {
2343 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2346 if (r->num_results < 1 || !r->ctx_list) {
2350 ctx = r->ctx_list[0];
2352 /* check the transfer syntax */
2353 if ((ctx.syntax.if_version != transfer->if_version) ||
2354 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2355 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2359 if (r->num_results != 0x1 || ctx.result != 0) {
2360 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2361 r->num_results, ctx.reason));
2364 DEBUG(5,("check_bind_response: accepted!\n"));
2368 /*******************************************************************
2369 Creates a DCE/RPC bind authentication response.
2370 This is the packet that is sent back to the server once we
2371 have received a BIND-ACK, to finish the third leg of
2372 the authentication handshake.
2373 ********************************************************************/
2375 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
2376 struct rpc_pipe_client *cli,
2378 enum pipe_auth_type auth_type,
2379 enum dcerpc_AuthLevel auth_level,
2380 DATA_BLOB *pauth_blob,
2384 union dcerpc_payload u;
2388 status = dcerpc_push_dcerpc_auth(mem_ctx,
2389 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2391 0, /* auth_pad_length */
2392 1, /* auth_context_id */
2394 &u.auth3.auth_info);
2395 if (!NT_STATUS_IS_OK(status)) {
2399 status = dcerpc_push_ncacn_packet(mem_ctx,
2401 DCERPC_PFC_FLAG_FIRST |
2402 DCERPC_PFC_FLAG_LAST,
2407 data_blob_free(&u.auth3.auth_info);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2413 return NT_STATUS_OK;
2416 /*******************************************************************
2417 Creates a DCE/RPC bind alter context authentication request which
2418 may contain a spnego auth blobl
2419 ********************************************************************/
2421 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2423 const struct ndr_syntax_id *abstract,
2424 const struct ndr_syntax_id *transfer,
2425 enum dcerpc_AuthLevel auth_level,
2426 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2429 DATA_BLOB auth_info;
2432 status = dcerpc_push_dcerpc_auth(mem_ctx,
2433 DCERPC_AUTH_TYPE_SPNEGO,
2435 0, /* auth_pad_length */
2436 1, /* auth_context_id */
2439 if (!NT_STATUS_IS_OK(status)) {
2443 status = create_bind_or_alt_ctx_internal(mem_ctx,
2450 data_blob_free(&auth_info);
2454 /****************************************************************************
2456 ****************************************************************************/
2458 struct rpc_pipe_bind_state {
2459 struct event_context *ev;
2460 struct rpc_pipe_client *cli;
2462 uint32_t rpc_call_id;
2465 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2466 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2467 struct rpc_pipe_bind_state *state,
2468 struct ncacn_packet *r);
2469 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2470 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2471 struct rpc_pipe_bind_state *state,
2472 struct ncacn_packet *r,
2473 DATA_BLOB *reply_pdu);
2474 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2476 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2477 struct event_context *ev,
2478 struct rpc_pipe_client *cli,
2479 struct cli_pipe_auth_data *auth)
2481 struct tevent_req *req, *subreq;
2482 struct rpc_pipe_bind_state *state;
2485 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2490 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2491 rpccli_pipe_txt(talloc_tos(), cli),
2492 (unsigned int)auth->auth_type,
2493 (unsigned int)auth->auth_level ));
2497 state->rpc_call_id = get_rpc_call_id();
2498 state->rpc_out = data_blob_null;
2500 cli->auth = talloc_move(cli, &auth);
2502 /* Marshall the outgoing data. */
2503 status = create_rpc_bind_req(state, cli,
2505 &cli->abstract_syntax,
2506 &cli->transfer_syntax,
2507 cli->auth->auth_type,
2508 cli->auth->auth_level,
2511 if (!NT_STATUS_IS_OK(status)) {
2515 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2516 DCERPC_PKT_BIND_ACK);
2517 if (subreq == NULL) {
2520 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2524 tevent_req_nterror(req, status);
2525 return tevent_req_post(req, ev);
2531 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2533 struct tevent_req *req = tevent_req_callback_data(
2534 subreq, struct tevent_req);
2535 struct rpc_pipe_bind_state *state = tevent_req_data(
2536 req, struct rpc_pipe_bind_state);
2537 DATA_BLOB reply_pdu;
2538 struct ncacn_packet *pkt;
2541 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2542 TALLOC_FREE(subreq);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2545 rpccli_pipe_txt(talloc_tos(), state->cli),
2546 nt_errstr(status)));
2547 tevent_req_nterror(req, status);
2551 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2552 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2553 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2557 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2558 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2561 * For authenticated binds we may need to do 3 or 4 leg binds.
2564 switch(state->cli->auth->auth_type) {
2566 case PIPE_AUTH_TYPE_NONE:
2567 case PIPE_AUTH_TYPE_SCHANNEL:
2568 /* Bind complete. */
2569 tevent_req_done(req);
2572 case PIPE_AUTH_TYPE_NTLMSSP:
2573 /* Need to send AUTH3 packet - no reply. */
2574 status = rpc_finish_auth3_bind_send(req, state, pkt);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 tevent_req_nterror(req, status);
2580 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2581 /* Need to send alter context request and reply. */
2582 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2584 if (!NT_STATUS_IS_OK(status)) {
2585 tevent_req_nterror(req, status);
2589 case PIPE_AUTH_TYPE_KRB5:
2593 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2594 (unsigned int)state->cli->auth->auth_type));
2595 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2599 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2600 struct rpc_pipe_bind_state *state,
2601 struct ncacn_packet *r)
2603 DATA_BLOB client_reply = data_blob_null;
2604 struct dcerpc_auth auth;
2605 struct tevent_req *subreq;
2608 if ((r->auth_length == 0)
2609 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2610 + r->auth_length)) {
2611 return NT_STATUS_INVALID_PARAMETER;
2614 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2615 &r->u.bind_ack.auth_info,
2617 if (!NT_STATUS_IS_OK(status)) {
2618 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2619 nt_errstr(status)));
2623 /* TODO - check auth_type/auth_level match. */
2625 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2626 auth.credentials, &client_reply);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2630 "blob failed: %s.\n", nt_errstr(status)));
2634 data_blob_free(&state->rpc_out);
2636 status = create_rpc_bind_auth3(state,
2637 state->cli, state->rpc_call_id,
2638 state->cli->auth->auth_type,
2639 state->cli->auth->auth_level,
2640 &client_reply, &state->rpc_out);
2641 data_blob_free(&client_reply);
2643 if (!NT_STATUS_IS_OK(status)) {
2647 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2648 state->rpc_out.data, state->rpc_out.length);
2649 if (subreq == NULL) {
2650 return NT_STATUS_NO_MEMORY;
2652 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2653 return NT_STATUS_OK;
2656 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2658 struct tevent_req *req = tevent_req_callback_data(
2659 subreq, struct tevent_req);
2662 status = rpc_write_recv(subreq);
2663 TALLOC_FREE(subreq);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 tevent_req_nterror(req, status);
2668 tevent_req_done(req);
2671 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2672 struct rpc_pipe_bind_state *state,
2673 struct ncacn_packet *r,
2674 DATA_BLOB *reply_pdu)
2676 DATA_BLOB server_ntlm_response = data_blob_null;
2677 DATA_BLOB client_reply = data_blob_null;
2678 DATA_BLOB tmp_blob = data_blob_null;
2679 struct dcerpc_auth auth_info;
2680 DATA_BLOB auth_blob;
2681 struct tevent_req *subreq;
2684 if ((r->auth_length == 0)
2685 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2686 + r->auth_length)) {
2687 return NT_STATUS_INVALID_PARAMETER;
2690 /* Process the returned NTLMSSP blob first. */
2691 auth_blob = data_blob_const(reply_pdu->data
2693 - DCERPC_AUTH_TRAILER_LENGTH
2695 DCERPC_AUTH_TRAILER_LENGTH
2698 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2705 * The server might give us back two challenges - tmp_blob is for the
2708 if (!spnego_parse_challenge(auth_info.credentials,
2709 &server_ntlm_response, &tmp_blob)) {
2710 data_blob_free(&server_ntlm_response);
2711 data_blob_free(&tmp_blob);
2712 return NT_STATUS_INVALID_PARAMETER;
2715 /* We're finished with the server spnego response and the tmp_blob. */
2716 data_blob_free(&tmp_blob);
2718 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2719 server_ntlm_response, &client_reply);
2721 /* Finished with the server_ntlm response */
2722 data_blob_free(&server_ntlm_response);
2724 if (!NT_STATUS_IS_OK(status)) {
2725 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2726 "using server blob failed.\n"));
2727 data_blob_free(&client_reply);
2731 /* SPNEGO wrap the client reply. */
2732 tmp_blob = spnego_gen_auth(client_reply);
2733 data_blob_free(&client_reply);
2734 client_reply = tmp_blob;
2735 tmp_blob = data_blob_null;
2737 /* Now prepare the alter context pdu. */
2738 data_blob_free(&state->rpc_out);
2740 status = create_rpc_alter_context(state,
2742 &state->cli->abstract_syntax,
2743 &state->cli->transfer_syntax,
2744 state->cli->auth->auth_level,
2747 data_blob_free(&client_reply);
2749 if (!NT_STATUS_IS_OK(status)) {
2753 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2754 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2755 if (subreq == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2758 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2759 return NT_STATUS_OK;
2762 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2764 struct tevent_req *req = tevent_req_callback_data(
2765 subreq, struct tevent_req);
2766 struct rpc_pipe_bind_state *state = tevent_req_data(
2767 req, struct rpc_pipe_bind_state);
2768 DATA_BLOB tmp_blob = data_blob_null;
2769 struct ncacn_packet *pkt;
2770 struct dcerpc_auth auth;
2773 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2774 TALLOC_FREE(subreq);
2775 if (!NT_STATUS_IS_OK(status)) {
2776 tevent_req_nterror(req, status);
2780 status = dcerpc_pull_dcerpc_auth(pkt,
2781 &pkt->u.alter_resp.auth_info,
2783 if (!NT_STATUS_IS_OK(status)) {
2784 tevent_req_nterror(req, status);
2788 /* Check we got a valid auth response. */
2789 if (!spnego_parse_auth_response(auth.credentials,
2791 OID_NTLMSSP, &tmp_blob)) {
2792 data_blob_free(&tmp_blob);
2793 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2797 data_blob_free(&tmp_blob);
2799 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2800 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2801 tevent_req_done(req);
2804 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2806 return tevent_req_simple_recv_ntstatus(req);
2809 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2810 struct cli_pipe_auth_data *auth)
2812 TALLOC_CTX *frame = talloc_stackframe();
2813 struct event_context *ev;
2814 struct tevent_req *req;
2815 NTSTATUS status = NT_STATUS_OK;
2817 ev = event_context_init(frame);
2819 status = NT_STATUS_NO_MEMORY;
2823 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2825 status = NT_STATUS_NO_MEMORY;
2829 if (!tevent_req_poll(req, ev)) {
2830 status = map_nt_error_from_unix(errno);
2834 status = rpc_pipe_bind_recv(req);
2840 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2842 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2843 unsigned int timeout)
2847 if (rpc_cli->transport == NULL) {
2848 return RPCCLI_DEFAULT_TIMEOUT;
2851 if (rpc_cli->transport->set_timeout == NULL) {
2852 return RPCCLI_DEFAULT_TIMEOUT;
2855 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2857 return RPCCLI_DEFAULT_TIMEOUT;
2863 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2865 if (rpc_cli == NULL) {
2869 if (rpc_cli->transport == NULL) {
2873 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2876 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2878 struct cli_state *cli;
2880 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2881 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2882 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2886 cli = rpc_pipe_np_smb_conn(rpc_cli);
2890 E_md4hash(cli->password ? cli->password : "", nt_hash);
2894 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2895 struct cli_pipe_auth_data **presult)
2897 struct cli_pipe_auth_data *result;
2899 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2900 if (result == NULL) {
2901 return NT_STATUS_NO_MEMORY;
2904 result->auth_type = PIPE_AUTH_TYPE_NONE;
2905 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2907 result->user_name = talloc_strdup(result, "");
2908 result->domain = talloc_strdup(result, "");
2909 if ((result->user_name == NULL) || (result->domain == NULL)) {
2910 TALLOC_FREE(result);
2911 return NT_STATUS_NO_MEMORY;
2915 return NT_STATUS_OK;
2918 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2920 ntlmssp_end(&auth->a_u.ntlmssp_state);
2924 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2925 enum pipe_auth_type auth_type,
2926 enum dcerpc_AuthLevel auth_level,
2928 const char *username,
2929 const char *password,
2930 struct cli_pipe_auth_data **presult)
2932 struct cli_pipe_auth_data *result;
2935 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2936 if (result == NULL) {
2937 return NT_STATUS_NO_MEMORY;
2940 result->auth_type = auth_type;
2941 result->auth_level = auth_level;
2943 result->user_name = talloc_strdup(result, username);
2944 result->domain = talloc_strdup(result, domain);
2945 if ((result->user_name == NULL) || (result->domain == NULL)) {
2946 status = NT_STATUS_NO_MEMORY;
2950 status = ntlmssp_client_start(NULL,
2953 lp_client_ntlmv2_auth(),
2954 &result->a_u.ntlmssp_state);
2955 if (!NT_STATUS_IS_OK(status)) {
2959 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2961 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2962 if (!NT_STATUS_IS_OK(status)) {
2966 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2967 if (!NT_STATUS_IS_OK(status)) {
2971 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2972 if (!NT_STATUS_IS_OK(status)) {
2977 * Turn off sign+seal to allow selected auth level to turn it back on.
2979 result->a_u.ntlmssp_state->neg_flags &=
2980 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2982 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2983 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2984 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2985 result->a_u.ntlmssp_state->neg_flags
2986 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2990 return NT_STATUS_OK;
2993 TALLOC_FREE(result);
2997 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2998 enum dcerpc_AuthLevel auth_level,
2999 struct netlogon_creds_CredentialState *creds,
3000 struct cli_pipe_auth_data **presult)
3002 struct cli_pipe_auth_data *result;
3004 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3005 if (result == NULL) {
3006 return NT_STATUS_NO_MEMORY;
3009 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3010 result->auth_level = auth_level;
3012 result->user_name = talloc_strdup(result, "");
3013 result->domain = talloc_strdup(result, domain);
3014 if ((result->user_name == NULL) || (result->domain == NULL)) {
3018 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3019 if (result->a_u.schannel_auth == NULL) {
3023 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3024 result->a_u.schannel_auth->seq_num = 0;
3025 result->a_u.schannel_auth->initiator = true;
3026 result->a_u.schannel_auth->creds = creds;
3029 return NT_STATUS_OK;
3032 TALLOC_FREE(result);
3033 return NT_STATUS_NO_MEMORY;
3037 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3039 data_blob_free(&auth->session_key);
3044 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3045 enum dcerpc_AuthLevel auth_level,
3046 const char *service_princ,
3047 const char *username,
3048 const char *password,
3049 struct cli_pipe_auth_data **presult)
3052 struct cli_pipe_auth_data *result;
3054 if ((username != NULL) && (password != NULL)) {
3055 int ret = kerberos_kinit_password(username, password, 0, NULL);
3057 return NT_STATUS_ACCESS_DENIED;
3061 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3062 if (result == NULL) {
3063 return NT_STATUS_NO_MEMORY;
3066 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3067 result->auth_level = auth_level;
3070 * Username / domain need fixing!
3072 result->user_name = talloc_strdup(result, "");
3073 result->domain = talloc_strdup(result, "");
3074 if ((result->user_name == NULL) || (result->domain == NULL)) {
3078 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3079 result, struct kerberos_auth_struct);
3080 if (result->a_u.kerberos_auth == NULL) {
3083 talloc_set_destructor(result->a_u.kerberos_auth,
3084 cli_auth_kerberos_data_destructor);
3086 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3087 result, service_princ);
3088 if (result->a_u.kerberos_auth->service_principal == NULL) {
3093 return NT_STATUS_OK;
3096 TALLOC_FREE(result);
3097 return NT_STATUS_NO_MEMORY;
3099 return NT_STATUS_NOT_SUPPORTED;
3104 * Create an rpc pipe client struct, connecting to a tcp port.
3106 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3108 const struct ndr_syntax_id *abstract_syntax,
3109 struct rpc_pipe_client **presult)
3111 struct rpc_pipe_client *result;
3112 struct sockaddr_storage addr;
3116 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3117 if (result == NULL) {
3118 return NT_STATUS_NO_MEMORY;
3121 result->abstract_syntax = *abstract_syntax;
3122 result->transfer_syntax = ndr_transfer_syntax;
3123 result->dispatch = cli_do_rpc_ndr;
3124 result->dispatch_send = cli_do_rpc_ndr_send;
3125 result->dispatch_recv = cli_do_rpc_ndr_recv;
3127 result->desthost = talloc_strdup(result, host);
3128 result->srv_name_slash = talloc_asprintf_strupper_m(
3129 result, "\\\\%s", result->desthost);
3130 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3131 status = NT_STATUS_NO_MEMORY;
3135 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3136 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3138 if (!resolve_name(host, &addr, 0, false)) {
3139 status = NT_STATUS_NOT_FOUND;
3143 status = open_socket_out(&addr, port, 60, &fd);
3144 if (!NT_STATUS_IS_OK(status)) {
3147 set_socket_options(fd, lp_socket_options());
3149 status = rpc_transport_sock_init(result, fd, &result->transport);
3150 if (!NT_STATUS_IS_OK(status)) {
3155 result->transport->transport = NCACN_IP_TCP;
3158 return NT_STATUS_OK;
3161 TALLOC_FREE(result);
3166 * Determine the tcp port on which a dcerpc interface is listening
3167 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3170 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3171 const struct ndr_syntax_id *abstract_syntax,
3175 struct rpc_pipe_client *epm_pipe = NULL;
3176 struct cli_pipe_auth_data *auth = NULL;
3177 struct dcerpc_binding *map_binding = NULL;
3178 struct dcerpc_binding *res_binding = NULL;
3179 struct epm_twr_t *map_tower = NULL;
3180 struct epm_twr_t *res_towers = NULL;
3181 struct policy_handle *entry_handle = NULL;
3182 uint32_t num_towers = 0;
3183 uint32_t max_towers = 1;
3184 struct epm_twr_p_t towers;
3185 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3187 if (pport == NULL) {
3188 status = NT_STATUS_INVALID_PARAMETER;
3192 /* open the connection to the endpoint mapper */
3193 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3194 &ndr_table_epmapper.syntax_id,
3197 if (!NT_STATUS_IS_OK(status)) {
3201 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3202 if (!NT_STATUS_IS_OK(status)) {
3206 status = rpc_pipe_bind(epm_pipe, auth);
3207 if (!NT_STATUS_IS_OK(status)) {
3211 /* create tower for asking the epmapper */
3213 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3214 if (map_binding == NULL) {
3215 status = NT_STATUS_NO_MEMORY;
3219 map_binding->transport = NCACN_IP_TCP;
3220 map_binding->object = *abstract_syntax;
3221 map_binding->host = host; /* needed? */
3222 map_binding->endpoint = "0"; /* correct? needed? */
3224 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3225 if (map_tower == NULL) {
3226 status = NT_STATUS_NO_MEMORY;
3230 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3231 &(map_tower->tower));
3232 if (!NT_STATUS_IS_OK(status)) {
3236 /* allocate further parameters for the epm_Map call */
3238 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3239 if (res_towers == NULL) {
3240 status = NT_STATUS_NO_MEMORY;
3243 towers.twr = res_towers;
3245 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3246 if (entry_handle == NULL) {
3247 status = NT_STATUS_NO_MEMORY;
3251 /* ask the endpoint mapper for the port */
3253 status = rpccli_epm_Map(epm_pipe,
3255 CONST_DISCARD(struct GUID *,
3256 &(abstract_syntax->uuid)),
3263 if (!NT_STATUS_IS_OK(status)) {
3267 if (num_towers != 1) {
3268 status = NT_STATUS_UNSUCCESSFUL;
3272 /* extract the port from the answer */
3274 status = dcerpc_binding_from_tower(tmp_ctx,
3275 &(towers.twr->tower),
3277 if (!NT_STATUS_IS_OK(status)) {
3281 /* are further checks here necessary? */
3282 if (res_binding->transport != NCACN_IP_TCP) {
3283 status = NT_STATUS_UNSUCCESSFUL;
3287 *pport = (uint16_t)atoi(res_binding->endpoint);
3290 TALLOC_FREE(tmp_ctx);
3295 * Create a rpc pipe client struct, connecting to a host via tcp.
3296 * The port is determined by asking the endpoint mapper on the given
3299 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3300 const struct ndr_syntax_id *abstract_syntax,
3301 struct rpc_pipe_client **presult)
3306 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3307 if (!NT_STATUS_IS_OK(status)) {
3311 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3312 abstract_syntax, presult);
3315 /********************************************************************
3316 Create a rpc pipe client struct, connecting to a unix domain socket
3317 ********************************************************************/
3318 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3319 const struct ndr_syntax_id *abstract_syntax,
3320 struct rpc_pipe_client **presult)
3322 struct rpc_pipe_client *result;
3323 struct sockaddr_un addr;
3327 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3328 if (result == NULL) {
3329 return NT_STATUS_NO_MEMORY;
3332 result->abstract_syntax = *abstract_syntax;
3333 result->transfer_syntax = ndr_transfer_syntax;
3334 result->dispatch = cli_do_rpc_ndr;
3335 result->dispatch_send = cli_do_rpc_ndr_send;
3336 result->dispatch_recv = cli_do_rpc_ndr_recv;
3338 result->desthost = get_myname(result);
3339 result->srv_name_slash = talloc_asprintf_strupper_m(
3340 result, "\\\\%s", result->desthost);
3341 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3342 status = NT_STATUS_NO_MEMORY;
3346 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3347 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3349 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3351 status = map_nt_error_from_unix(errno);
3356 addr.sun_family = AF_UNIX;
3357 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3359 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3360 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3363 return map_nt_error_from_unix(errno);
3366 status = rpc_transport_sock_init(result, fd, &result->transport);
3367 if (!NT_STATUS_IS_OK(status)) {
3372 result->transport->transport = NCALRPC;
3375 return NT_STATUS_OK;
3378 TALLOC_FREE(result);
3382 struct rpc_pipe_client_np_ref {
3383 struct cli_state *cli;
3384 struct rpc_pipe_client *pipe;
3387 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3389 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3393 /****************************************************************************
3394 Open a named pipe over SMB to a remote server.
3396 * CAVEAT CALLER OF THIS FUNCTION:
3397 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3398 * so be sure that this function is called AFTER any structure (vs pointer)
3399 * assignment of the cli. In particular, libsmbclient does structure
3400 * assignments of cli, which invalidates the data in the returned
3401 * rpc_pipe_client if this function is called before the structure assignment
3404 ****************************************************************************/
3406 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3407 const struct ndr_syntax_id *abstract_syntax,
3408 struct rpc_pipe_client **presult)
3410 struct rpc_pipe_client *result;
3412 struct rpc_pipe_client_np_ref *np_ref;
3414 /* sanity check to protect against crashes */
3417 return NT_STATUS_INVALID_HANDLE;
3420 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3421 if (result == NULL) {
3422 return NT_STATUS_NO_MEMORY;
3425 result->abstract_syntax = *abstract_syntax;
3426 result->transfer_syntax = ndr_transfer_syntax;
3427 result->dispatch = cli_do_rpc_ndr;
3428 result->dispatch_send = cli_do_rpc_ndr_send;
3429 result->dispatch_recv = cli_do_rpc_ndr_recv;
3430 result->desthost = talloc_strdup(result, cli->desthost);
3431 result->srv_name_slash = talloc_asprintf_strupper_m(
3432 result, "\\\\%s", result->desthost);
3434 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3435 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3437 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3438 TALLOC_FREE(result);
3439 return NT_STATUS_NO_MEMORY;
3442 status = rpc_transport_np_init(result, cli, abstract_syntax,
3443 &result->transport);
3444 if (!NT_STATUS_IS_OK(status)) {
3445 TALLOC_FREE(result);
3449 result->transport->transport = NCACN_NP;
3451 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3452 if (np_ref == NULL) {
3453 TALLOC_FREE(result);
3454 return NT_STATUS_NO_MEMORY;
3457 np_ref->pipe = result;
3459 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3460 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3463 return NT_STATUS_OK;
3466 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3467 struct rpc_cli_smbd_conn *conn,
3468 const struct ndr_syntax_id *syntax,
3469 struct rpc_pipe_client **presult)
3471 struct rpc_pipe_client *result;
3472 struct cli_pipe_auth_data *auth;
3475 result = talloc(mem_ctx, struct rpc_pipe_client);
3476 if (result == NULL) {
3477 return NT_STATUS_NO_MEMORY;
3479 result->abstract_syntax = *syntax;
3480 result->transfer_syntax = ndr_transfer_syntax;
3481 result->dispatch = cli_do_rpc_ndr;
3482 result->dispatch_send = cli_do_rpc_ndr_send;
3483 result->dispatch_recv = cli_do_rpc_ndr_recv;
3484 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3485 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3487 result->desthost = talloc_strdup(result, global_myname());
3488 result->srv_name_slash = talloc_asprintf_strupper_m(
3489 result, "\\\\%s", global_myname());
3490 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3491 TALLOC_FREE(result);
3492 return NT_STATUS_NO_MEMORY;
3495 status = rpc_transport_smbd_init(result, conn, syntax,
3496 &result->transport);
3497 if (!NT_STATUS_IS_OK(status)) {
3498 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3499 nt_errstr(status)));
3500 TALLOC_FREE(result);
3504 status = rpccli_anon_bind_data(result, &auth);
3505 if (!NT_STATUS_IS_OK(status)) {
3506 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3507 nt_errstr(status)));
3508 TALLOC_FREE(result);
3512 status = rpc_pipe_bind(result, auth);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3515 TALLOC_FREE(result);
3519 result->transport->transport = NCACN_INTERNAL;
3522 return NT_STATUS_OK;
3525 /****************************************************************************
3526 Open a pipe to a remote server.
3527 ****************************************************************************/
3529 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3530 enum dcerpc_transport_t transport,
3531 const struct ndr_syntax_id *interface,
3532 struct rpc_pipe_client **presult)
3534 switch (transport) {
3536 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3539 return rpc_pipe_open_np(cli, interface, presult);
3541 return NT_STATUS_NOT_IMPLEMENTED;
3545 /****************************************************************************
3546 Open a named pipe to an SMB server and bind anonymously.
3547 ****************************************************************************/
3549 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3550 enum dcerpc_transport_t transport,
3551 const struct ndr_syntax_id *interface,
3552 struct rpc_pipe_client **presult)
3554 struct rpc_pipe_client *result;
3555 struct cli_pipe_auth_data *auth;
3558 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3559 if (!NT_STATUS_IS_OK(status)) {
3563 status = rpccli_anon_bind_data(result, &auth);
3564 if (!NT_STATUS_IS_OK(status)) {
3565 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3566 nt_errstr(status)));
3567 TALLOC_FREE(result);
3572 * This is a bit of an abstraction violation due to the fact that an
3573 * anonymous bind on an authenticated SMB inherits the user/domain
3574 * from the enclosing SMB creds
3577 TALLOC_FREE(auth->user_name);
3578 TALLOC_FREE(auth->domain);
3580 auth->user_name = talloc_strdup(auth, cli->user_name);
3581 auth->domain = talloc_strdup(auth, cli->domain);
3582 auth->user_session_key = data_blob_talloc(auth,
3583 cli->user_session_key.data,
3584 cli->user_session_key.length);
3586 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3587 TALLOC_FREE(result);
3588 return NT_STATUS_NO_MEMORY;
3591 status = rpc_pipe_bind(result, auth);
3592 if (!NT_STATUS_IS_OK(status)) {
3594 if (ndr_syntax_id_equal(interface,
3595 &ndr_table_dssetup.syntax_id)) {
3596 /* non AD domains just don't have this pipe, avoid
3597 * level 0 statement in that case - gd */
3600 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3601 "%s failed with error %s\n",
3602 get_pipe_name_from_syntax(talloc_tos(), interface),
3603 nt_errstr(status) ));
3604 TALLOC_FREE(result);
3608 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3609 "%s and bound anonymously.\n",
3610 get_pipe_name_from_syntax(talloc_tos(), interface),
3614 return NT_STATUS_OK;
3617 /****************************************************************************
3618 ****************************************************************************/
3620 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3621 const struct ndr_syntax_id *interface,
3622 struct rpc_pipe_client **presult)
3624 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3625 interface, presult);
3628 /****************************************************************************
3629 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3630 ****************************************************************************/
3632 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3633 const struct ndr_syntax_id *interface,
3634 enum dcerpc_transport_t transport,
3635 enum pipe_auth_type auth_type,
3636 enum dcerpc_AuthLevel auth_level,
3638 const char *username,
3639 const char *password,
3640 struct rpc_pipe_client **presult)
3642 struct rpc_pipe_client *result;
3643 struct cli_pipe_auth_data *auth;
3646 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3647 if (!NT_STATUS_IS_OK(status)) {
3651 status = rpccli_ntlmssp_bind_data(
3652 result, auth_type, auth_level, domain, username,
3654 if (!NT_STATUS_IS_OK(status)) {
3655 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3656 nt_errstr(status)));
3660 status = rpc_pipe_bind(result, auth);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3663 nt_errstr(status) ));
3667 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3668 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3669 get_pipe_name_from_syntax(talloc_tos(), interface),
3670 cli->desthost, domain, username ));
3673 return NT_STATUS_OK;
3677 TALLOC_FREE(result);
3681 /****************************************************************************
3683 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3684 ****************************************************************************/
3686 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3687 const struct ndr_syntax_id *interface,
3688 enum dcerpc_transport_t transport,
3689 enum dcerpc_AuthLevel auth_level,
3691 const char *username,
3692 const char *password,
3693 struct rpc_pipe_client **presult)
3695 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3698 PIPE_AUTH_TYPE_NTLMSSP,
3706 /****************************************************************************
3708 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3709 ****************************************************************************/
3711 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3712 const struct ndr_syntax_id *interface,
3713 enum dcerpc_transport_t transport,
3714 enum dcerpc_AuthLevel auth_level,
3716 const char *username,
3717 const char *password,
3718 struct rpc_pipe_client **presult)
3720 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3723 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3731 /****************************************************************************
3732 Get a the schannel session key out of an already opened netlogon pipe.
3733 ****************************************************************************/
3734 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3735 struct cli_state *cli,
3739 enum netr_SchannelType sec_chan_type = 0;
3740 unsigned char machine_pwd[16];
3741 const char *machine_account;
3744 /* Get the machine account credentials from secrets.tdb. */
3745 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3748 DEBUG(0, ("get_schannel_session_key: could not fetch "
3749 "trust account password for domain '%s'\n",
3751 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3754 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3755 cli->desthost, /* server name */
3756 domain, /* domain */
3757 global_myname(), /* client name */
3758 machine_account, /* machine account name */
3763 if (!NT_STATUS_IS_OK(status)) {
3764 DEBUG(3, ("get_schannel_session_key_common: "
3765 "rpccli_netlogon_setup_creds failed with result %s "
3766 "to server %s, domain %s, machine account %s.\n",
3767 nt_errstr(status), cli->desthost, domain,
3772 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3773 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3775 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3778 return NT_STATUS_OK;;
3781 /****************************************************************************
3782 Open a netlogon pipe and get the schannel session key.
3783 Now exposed to external callers.
3784 ****************************************************************************/
3787 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3790 struct rpc_pipe_client **presult)
3792 struct rpc_pipe_client *netlogon_pipe = NULL;
3795 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3797 if (!NT_STATUS_IS_OK(status)) {
3801 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3803 if (!NT_STATUS_IS_OK(status)) {
3804 TALLOC_FREE(netlogon_pipe);
3808 *presult = netlogon_pipe;
3809 return NT_STATUS_OK;
3812 /****************************************************************************
3814 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3815 using session_key. sign and seal.
3817 The *pdc will be stolen onto this new pipe
3818 ****************************************************************************/
3820 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3821 const struct ndr_syntax_id *interface,
3822 enum dcerpc_transport_t transport,
3823 enum dcerpc_AuthLevel auth_level,
3825 struct netlogon_creds_CredentialState **pdc,
3826 struct rpc_pipe_client **presult)
3828 struct rpc_pipe_client *result;
3829 struct cli_pipe_auth_data *auth;
3832 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3833 if (!NT_STATUS_IS_OK(status)) {
3837 status = rpccli_schannel_bind_data(result, domain, auth_level,
3839 if (!NT_STATUS_IS_OK(status)) {
3840 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3841 nt_errstr(status)));
3842 TALLOC_FREE(result);
3846 status = rpc_pipe_bind(result, auth);
3847 if (!NT_STATUS_IS_OK(status)) {
3848 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3849 "cli_rpc_pipe_bind failed with error %s\n",
3850 nt_errstr(status) ));
3851 TALLOC_FREE(result);
3856 * The credentials on a new netlogon pipe are the ones we are passed
3857 * in - reference them in
3859 result->dc = talloc_move(result, pdc);
3861 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3862 "for domain %s and bound using schannel.\n",
3863 get_pipe_name_from_syntax(talloc_tos(), interface),
3864 cli->desthost, domain ));
3867 return NT_STATUS_OK;
3870 /****************************************************************************
3871 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3872 Fetch the session key ourselves using a temporary netlogon pipe. This
3873 version uses an ntlmssp auth bound netlogon pipe to get the key.
3874 ****************************************************************************/
3876 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3878 const char *username,
3879 const char *password,
3881 struct rpc_pipe_client **presult)
3883 struct rpc_pipe_client *netlogon_pipe = NULL;
3886 status = cli_rpc_pipe_open_spnego_ntlmssp(
3887 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3888 DCERPC_AUTH_LEVEL_PRIVACY,
3889 domain, username, password, &netlogon_pipe);
3890 if (!NT_STATUS_IS_OK(status)) {
3894 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3896 if (!NT_STATUS_IS_OK(status)) {
3897 TALLOC_FREE(netlogon_pipe);
3901 *presult = netlogon_pipe;
3902 return NT_STATUS_OK;
3905 /****************************************************************************
3906 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3907 Fetch the session key ourselves using a temporary netlogon pipe. This version
3908 uses an ntlmssp bind to get the session key.
3909 ****************************************************************************/
3911 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3912 const struct ndr_syntax_id *interface,
3913 enum dcerpc_transport_t transport,
3914 enum dcerpc_AuthLevel auth_level,
3916 const char *username,
3917 const char *password,
3918 struct rpc_pipe_client **presult)
3920 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3921 struct rpc_pipe_client *netlogon_pipe = NULL;
3922 struct rpc_pipe_client *result = NULL;
3925 status = get_schannel_session_key_auth_ntlmssp(
3926 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3927 if (!NT_STATUS_IS_OK(status)) {
3928 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3929 "key from server %s for domain %s.\n",
3930 cli->desthost, domain ));
3934 status = cli_rpc_pipe_open_schannel_with_key(
3935 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3938 /* Now we've bound using the session key we can close the netlog pipe. */
3939 TALLOC_FREE(netlogon_pipe);
3941 if (NT_STATUS_IS_OK(status)) {
3947 /****************************************************************************
3948 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3949 Fetch the session key ourselves using a temporary netlogon pipe.
3950 ****************************************************************************/
3952 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3953 const struct ndr_syntax_id *interface,
3954 enum dcerpc_transport_t transport,
3955 enum dcerpc_AuthLevel auth_level,
3957 struct rpc_pipe_client **presult)
3959 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3960 struct rpc_pipe_client *netlogon_pipe = NULL;
3961 struct rpc_pipe_client *result = NULL;
3964 status = get_schannel_session_key(cli, domain, &neg_flags,
3966 if (!NT_STATUS_IS_OK(status)) {
3967 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3968 "key from server %s for domain %s.\n",
3969 cli->desthost, domain ));
3973 status = cli_rpc_pipe_open_schannel_with_key(
3974 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3977 /* Now we've bound using the session key we can close the netlog pipe. */
3978 TALLOC_FREE(netlogon_pipe);
3980 if (NT_STATUS_IS_OK(status)) {
3987 /****************************************************************************
3988 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3989 The idea is this can be called with service_princ, username and password all
3990 NULL so long as the caller has a TGT.
3991 ****************************************************************************/
3993 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3994 const struct ndr_syntax_id *interface,
3995 enum dcerpc_AuthLevel auth_level,
3996 const char *service_princ,
3997 const char *username,
3998 const char *password,
3999 struct rpc_pipe_client **presult)
4002 struct rpc_pipe_client *result;
4003 struct cli_pipe_auth_data *auth;
4006 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4007 if (!NT_STATUS_IS_OK(status)) {
4011 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4012 username, password, &auth);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4015 nt_errstr(status)));
4016 TALLOC_FREE(result);
4020 status = rpc_pipe_bind(result, auth);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4023 "with error %s\n", nt_errstr(status)));
4024 TALLOC_FREE(result);
4029 return NT_STATUS_OK;
4031 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4032 return NT_STATUS_NOT_IMPLEMENTED;
4036 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4037 struct rpc_pipe_client *cli,
4038 DATA_BLOB *session_key)
4040 if (!session_key || !cli) {
4041 return NT_STATUS_INVALID_PARAMETER;
4045 return NT_STATUS_INVALID_PARAMETER;
4048 switch (cli->auth->auth_type) {
4049 case PIPE_AUTH_TYPE_SCHANNEL:
4050 *session_key = data_blob_talloc(mem_ctx,
4051 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4053 case PIPE_AUTH_TYPE_NTLMSSP:
4054 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4055 *session_key = data_blob_talloc(mem_ctx,
4056 cli->auth->a_u.ntlmssp_state->session_key.data,
4057 cli->auth->a_u.ntlmssp_state->session_key.length);
4059 case PIPE_AUTH_TYPE_KRB5:
4060 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4061 *session_key = data_blob_talloc(mem_ctx,
4062 cli->auth->a_u.kerberos_auth->session_key.data,
4063 cli->auth->a_u.kerberos_auth->session_key.length);
4065 case PIPE_AUTH_TYPE_NONE:
4066 *session_key = data_blob_talloc(mem_ctx,
4067 cli->auth->user_session_key.data,
4068 cli->auth->user_session_key.length);
4071 return NT_STATUS_NO_USER_SESSION_KEY;
4074 return NT_STATUS_OK;