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 prs_struct 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 prs_struct *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 (prs_offset(data) > 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 (uint8_t *)prs_data_p(data),
1294 prs_offset(data), max_recv_frag);
1295 if (subreq == NULL) {
1298 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1302 tevent_req_nterror(req, status);
1303 return tevent_req_post(req, ev);
1309 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1311 struct tevent_req *req = tevent_req_callback_data(
1312 subreq, struct tevent_req);
1313 struct rpc_api_pipe_state *state = tevent_req_data(
1314 req, struct rpc_api_pipe_state);
1316 uint8_t *rdata = NULL;
1317 uint32_t rdata_len = 0;
1319 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1320 TALLOC_FREE(subreq);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1323 tevent_req_nterror(req, status);
1327 if (rdata == NULL) {
1328 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1329 rpccli_pipe_txt(talloc_tos(), state->cli)));
1330 tevent_req_done(req);
1335 * Move data on state->incoming_frag.
1337 state->incoming_frag.data = talloc_move(state, &rdata);
1338 state->incoming_frag.length = rdata_len;
1339 if (!state->incoming_frag.data) {
1340 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1344 /* Ensure we have enough data for a pdu. */
1345 subreq = get_complete_frag_send(state, state->ev, state->cli,
1346 &state->incoming_frag);
1347 if (tevent_req_nomem(subreq, req)) {
1350 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1353 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1355 struct tevent_req *req = tevent_req_callback_data(
1356 subreq, struct tevent_req);
1357 struct rpc_api_pipe_state *state = tevent_req_data(
1358 req, struct rpc_api_pipe_state);
1360 DATA_BLOB rdata = data_blob_null;
1362 status = get_complete_frag_recv(subreq);
1363 TALLOC_FREE(subreq);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 DEBUG(5, ("get_complete_frag failed: %s\n",
1366 nt_errstr(status)));
1367 tevent_req_nterror(req, status);
1371 state->pkt = talloc(state, struct ncacn_packet);
1373 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1377 status = cli_pipe_validate_current_pdu(state,
1378 state->cli, state->pkt,
1379 &state->incoming_frag,
1380 state->expected_pkt_type,
1384 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1385 (unsigned)state->incoming_frag.length,
1386 (unsigned)state->reply_pdu_offset,
1387 nt_errstr(status)));
1389 if (!NT_STATUS_IS_OK(status)) {
1390 tevent_req_nterror(req, status);
1394 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1395 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1397 * Set the data type correctly for big-endian data on the
1400 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1402 rpccli_pipe_txt(talloc_tos(), state->cli)));
1403 state->endianess = 0x00; /* BIG ENDIAN */
1406 * Check endianness on subsequent packets.
1408 if (state->endianess != state->pkt->drep[0]) {
1409 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1411 state->endianess?"little":"big",
1412 state->pkt->drep[0]?"little":"big"));
1413 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1417 /* Now copy the data portion out of the pdu into rbuf. */
1418 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1419 if (!data_blob_realloc(NULL, &state->reply_pdu,
1420 state->reply_pdu_offset + rdata.length)) {
1421 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1426 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1427 rdata.data, rdata.length);
1428 state->reply_pdu_offset += rdata.length;
1430 /* reset state->incoming_frag, there is no need to free it,
1431 * it will be reallocated to the right size the next time
1433 state->incoming_frag.length = 0;
1435 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1436 /* make sure the pdu length is right now that we
1437 * have all the data available (alloc hint may
1438 * have allocated more than was actually used) */
1439 state->reply_pdu.length = state->reply_pdu_offset;
1440 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1441 rpccli_pipe_txt(talloc_tos(), state->cli),
1442 (unsigned)state->reply_pdu.length));
1443 tevent_req_done(req);
1447 subreq = get_complete_frag_send(state, state->ev, state->cli,
1448 &state->incoming_frag);
1449 if (tevent_req_nomem(subreq, req)) {
1452 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1455 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1456 struct ncacn_packet **pkt,
1457 DATA_BLOB *reply_pdu)
1459 struct rpc_api_pipe_state *state = tevent_req_data(
1460 req, struct rpc_api_pipe_state);
1463 if (tevent_req_is_nterror(req, &status)) {
1467 /* return data to caller and assign it ownership of memory */
1469 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1470 reply_pdu->length = state->reply_pdu.length;
1471 state->reply_pdu.length = 0;
1473 data_blob_free(&state->reply_pdu);
1477 *pkt = talloc_steal(mem_ctx, state->pkt);
1480 return NT_STATUS_OK;
1483 /*******************************************************************
1484 Creates krb5 auth bind.
1485 ********************************************************************/
1487 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1488 enum dcerpc_AuthLevel auth_level,
1489 DATA_BLOB *auth_info)
1494 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1495 DATA_BLOB tkt = data_blob_null;
1496 DATA_BLOB tkt_wrapped = data_blob_null;
1498 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1499 a->service_principal ));
1501 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1503 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1504 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1507 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1509 a->service_principal,
1510 error_message(ret) ));
1512 data_blob_free(&tkt);
1513 return NT_STATUS_INVALID_PARAMETER;
1516 /* wrap that up in a nice GSS-API wrapping */
1517 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1519 data_blob_free(&tkt);
1521 status = dcerpc_push_dcerpc_auth(cli,
1522 DCERPC_AUTH_TYPE_KRB5,
1524 0, /* auth_pad_length */
1525 1, /* auth_context_id */
1528 if (!NT_STATUS_IS_OK(status)) {
1529 data_blob_free(&tkt_wrapped);
1533 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1534 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1536 return NT_STATUS_OK;
1538 return NT_STATUS_INVALID_PARAMETER;
1542 /*******************************************************************
1543 Creates SPNEGO NTLMSSP auth bind.
1544 ********************************************************************/
1546 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1547 enum dcerpc_AuthLevel auth_level,
1548 DATA_BLOB *auth_info)
1551 DATA_BLOB null_blob = data_blob_null;
1552 DATA_BLOB request = data_blob_null;
1553 DATA_BLOB spnego_msg = data_blob_null;
1555 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1556 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1560 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1561 data_blob_free(&request);
1565 /* Wrap this in SPNEGO. */
1566 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1568 data_blob_free(&request);
1570 status = dcerpc_push_dcerpc_auth(cli,
1571 DCERPC_AUTH_TYPE_SPNEGO,
1573 0, /* auth_pad_length */
1574 1, /* auth_context_id */
1577 if (!NT_STATUS_IS_OK(status)) {
1578 data_blob_free(&spnego_msg);
1582 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1583 dump_data(5, spnego_msg.data, spnego_msg.length);
1585 return NT_STATUS_OK;
1588 /*******************************************************************
1589 Creates NTLMSSP auth bind.
1590 ********************************************************************/
1592 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1593 enum dcerpc_AuthLevel auth_level,
1594 DATA_BLOB *auth_info)
1597 DATA_BLOB null_blob = data_blob_null;
1598 DATA_BLOB request = data_blob_null;
1600 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1601 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1605 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1606 data_blob_free(&request);
1610 status = dcerpc_push_dcerpc_auth(cli,
1611 DCERPC_AUTH_TYPE_NTLMSSP,
1613 0, /* auth_pad_length */
1614 1, /* auth_context_id */
1617 if (!NT_STATUS_IS_OK(status)) {
1618 data_blob_free(&request);
1622 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1623 dump_data(5, request.data, request.length);
1625 return NT_STATUS_OK;
1628 /*******************************************************************
1629 Creates schannel auth bind.
1630 ********************************************************************/
1632 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1633 enum dcerpc_AuthLevel auth_level,
1634 DATA_BLOB *auth_info)
1637 struct NL_AUTH_MESSAGE r;
1638 DATA_BLOB schannel_blob;
1640 /* Use lp_workgroup() if domain not specified */
1642 if (!cli->auth->domain || !cli->auth->domain[0]) {
1643 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1644 if (cli->auth->domain == NULL) {
1645 return NT_STATUS_NO_MEMORY;
1650 * Now marshall the data into the auth parse_struct.
1653 r.MessageType = NL_NEGOTIATE_REQUEST;
1654 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1655 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1656 r.oem_netbios_domain.a = cli->auth->domain;
1657 r.oem_netbios_computer.a = global_myname();
1659 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1660 if (!NT_STATUS_IS_OK(status)) {
1664 status = dcerpc_push_dcerpc_auth(cli,
1665 DCERPC_AUTH_TYPE_SCHANNEL,
1667 0, /* auth_pad_length */
1668 1, /* auth_context_id */
1671 if (!NT_STATUS_IS_OK(status)) {
1675 return NT_STATUS_OK;
1678 /*******************************************************************
1679 ********************************************************************/
1681 static NTSTATUS init_dcerpc_ctx_list(TALLOC_CTX *mem_ctx,
1682 const struct ndr_syntax_id *abstract_syntax,
1683 const struct ndr_syntax_id *transfer_syntax,
1684 struct dcerpc_ctx_list **ctx_list_p)
1686 struct dcerpc_ctx_list *ctx_list;
1688 ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1689 NT_STATUS_HAVE_NO_MEMORY(ctx_list);
1691 ctx_list[0].context_id = 0;
1692 ctx_list[0].num_transfer_syntaxes = 1;
1693 ctx_list[0].abstract_syntax = *abstract_syntax;
1694 ctx_list[0].transfer_syntaxes = talloc_array(ctx_list,
1695 struct ndr_syntax_id,
1696 ctx_list[0].num_transfer_syntaxes);
1697 NT_STATUS_HAVE_NO_MEMORY(ctx_list[0].transfer_syntaxes);
1698 ctx_list[0].transfer_syntaxes[0] = *transfer_syntax;
1700 *ctx_list_p = ctx_list;
1702 return NT_STATUS_OK;
1705 /*******************************************************************
1706 Creates the internals of a DCE/RPC bind request or alter context PDU.
1707 ********************************************************************/
1709 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype,
1710 prs_struct *rpc_out,
1712 const struct ndr_syntax_id *abstract,
1713 const struct ndr_syntax_id *transfer,
1714 const DATA_BLOB *auth_info)
1716 uint16 auth_len = auth_info->length;
1718 union dcerpc_payload u;
1720 struct dcerpc_ctx_list *ctx_list;
1722 status = init_dcerpc_ctx_list(rpc_out->mem_ctx, abstract, transfer,
1724 if (!NT_STATUS_IS_OK(status)) {
1729 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1732 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1733 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1734 u.bind.assoc_group_id = 0x0;
1735 u.bind.num_contexts = 1;
1736 u.bind.ctx_list = ctx_list;
1737 u.bind.auth_info = *auth_info;
1739 status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx,
1741 DCERPC_PFC_FLAG_FIRST |
1742 DCERPC_PFC_FLAG_LAST,
1747 if (!NT_STATUS_IS_OK(status)) {
1748 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1752 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
1753 return NT_STATUS_NO_MEMORY;
1756 return NT_STATUS_OK;
1759 /*******************************************************************
1760 Creates a DCE/RPC bind request.
1761 ********************************************************************/
1763 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1764 prs_struct *rpc_out,
1766 const struct ndr_syntax_id *abstract,
1767 const struct ndr_syntax_id *transfer,
1768 enum pipe_auth_type auth_type,
1769 enum dcerpc_AuthLevel auth_level)
1771 DATA_BLOB auth_info = data_blob_null;
1772 NTSTATUS ret = NT_STATUS_OK;
1774 switch (auth_type) {
1775 case PIPE_AUTH_TYPE_SCHANNEL:
1776 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1777 if (!NT_STATUS_IS_OK(ret)) {
1782 case PIPE_AUTH_TYPE_NTLMSSP:
1783 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1784 if (!NT_STATUS_IS_OK(ret)) {
1789 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1790 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1791 if (!NT_STATUS_IS_OK(ret)) {
1796 case PIPE_AUTH_TYPE_KRB5:
1797 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1798 if (!NT_STATUS_IS_OK(ret)) {
1803 case PIPE_AUTH_TYPE_NONE:
1807 /* "Can't" happen. */
1808 return NT_STATUS_INVALID_INFO_CLASS;
1811 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1820 /*******************************************************************
1821 Create and add the NTLMSSP sign/seal auth header and data.
1822 ********************************************************************/
1824 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1825 uint32 ss_padding_len,
1826 prs_struct *rpc_out)
1828 DATA_BLOB auth_info;
1830 DATA_BLOB auth_blob = data_blob_null;
1831 uint16_t data_and_pad_len = prs_offset(rpc_out)
1832 - DCERPC_RESPONSE_LENGTH;
1834 if (!cli->auth->a_u.ntlmssp_state) {
1835 return NT_STATUS_INVALID_PARAMETER;
1838 /* marshall the dcerpc_auth with an actually empty auth_blob.
1839 * this is needed because the ntmlssp signature includes the
1841 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1842 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1843 cli->auth->auth_level,
1845 1 /* context id. */,
1848 if (!NT_STATUS_IS_OK(status)) {
1852 /* append the header */
1853 if (!prs_copy_data_in(rpc_out,
1854 (char *)auth_info.data,
1855 auth_info.length)) {
1856 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1857 (unsigned int)auth_info.length));
1858 return NT_STATUS_NO_MEMORY;
1861 switch (cli->auth->auth_level) {
1862 case DCERPC_AUTH_LEVEL_PRIVACY:
1863 /* Data portion is encrypted. */
1864 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1865 prs_get_mem_context(rpc_out),
1866 (unsigned char *)prs_data_p(rpc_out)
1867 + DCERPC_RESPONSE_LENGTH,
1869 (unsigned char *)prs_data_p(rpc_out),
1870 (size_t)prs_offset(rpc_out),
1872 if (!NT_STATUS_IS_OK(status)) {
1877 case DCERPC_AUTH_LEVEL_INTEGRITY:
1878 /* Data is signed. */
1879 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1880 prs_get_mem_context(rpc_out),
1881 (unsigned char *)prs_data_p(rpc_out)
1882 + DCERPC_RESPONSE_LENGTH,
1884 (unsigned char *)prs_data_p(rpc_out),
1885 (size_t)prs_offset(rpc_out),
1887 if (!NT_STATUS_IS_OK(status)) {
1894 smb_panic("bad auth level");
1896 return NT_STATUS_INVALID_PARAMETER;
1899 /* Finally attach the blob. */
1900 if (!prs_copy_data_in(rpc_out,
1901 (char *)auth_blob.data,
1902 auth_blob.length)) {
1903 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1904 (unsigned int)auth_info.length));
1905 return NT_STATUS_NO_MEMORY;
1908 return NT_STATUS_OK;
1911 /*******************************************************************
1912 Create and add the schannel sign/seal auth header and data.
1913 ********************************************************************/
1915 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1916 uint32 ss_padding_len,
1917 prs_struct *rpc_out)
1919 DATA_BLOB auth_info;
1920 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1921 char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH;
1922 size_t data_and_pad_len = prs_offset(rpc_out)
1923 - DCERPC_RESPONSE_LENGTH;
1928 return NT_STATUS_INVALID_PARAMETER;
1931 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1934 switch (cli->auth->auth_level) {
1935 case DCERPC_AUTH_LEVEL_PRIVACY:
1936 status = netsec_outgoing_packet(sas,
1943 case DCERPC_AUTH_LEVEL_INTEGRITY:
1944 status = netsec_outgoing_packet(sas,
1952 status = NT_STATUS_INTERNAL_ERROR;
1956 if (!NT_STATUS_IS_OK(status)) {
1957 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1958 nt_errstr(status)));
1962 if (DEBUGLEVEL >= 10) {
1963 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1966 /* Finally marshall the blob. */
1967 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1968 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1969 cli->auth->auth_level,
1971 1 /* context id. */,
1974 if (!NT_STATUS_IS_OK(status)) {
1978 if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
1979 return NT_STATUS_NO_MEMORY;
1982 return NT_STATUS_OK;
1985 /*******************************************************************
1986 Calculate how much data we're going to send in this packet, also
1987 work out any sign/seal padding length.
1988 ********************************************************************/
1990 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1994 uint32 *p_ss_padding)
1996 uint32 data_space, data_len;
1999 if ((data_left > 0) && (sys_random() % 2)) {
2000 data_left = MAX(data_left/2, 1);
2004 switch (cli->auth->auth_level) {
2005 case DCERPC_AUTH_LEVEL_NONE:
2006 case DCERPC_AUTH_LEVEL_CONNECT:
2007 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
2008 data_len = MIN(data_space, data_left);
2011 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
2014 case DCERPC_AUTH_LEVEL_INTEGRITY:
2015 case DCERPC_AUTH_LEVEL_PRIVACY:
2016 /* Treat the same for all authenticated rpc requests. */
2017 switch(cli->auth->auth_type) {
2018 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2019 case PIPE_AUTH_TYPE_NTLMSSP:
2020 *p_auth_len = NTLMSSP_SIG_SIZE;
2022 case PIPE_AUTH_TYPE_SCHANNEL:
2023 *p_auth_len = SCHANNEL_SIG_SIZE;
2026 smb_panic("bad auth type");
2030 data_space = cli->max_xmit_frag
2031 - DCERPC_REQUEST_LENGTH
2032 - DCERPC_AUTH_TRAILER_LENGTH
2035 data_len = MIN(data_space, data_left);
2037 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2038 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2040 *p_frag_len = DCERPC_REQUEST_LENGTH
2041 + data_len + *p_ss_padding
2042 + DCERPC_AUTH_TRAILER_LENGTH
2047 smb_panic("bad auth level");
2053 /*******************************************************************
2055 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2056 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2057 and deals with signing/sealing details.
2058 ********************************************************************/
2060 struct rpc_api_pipe_req_state {
2061 struct event_context *ev;
2062 struct rpc_pipe_client *cli;
2065 prs_struct *req_data;
2066 uint32_t req_data_sent;
2067 prs_struct outgoing_frag;
2068 DATA_BLOB reply_pdu;
2071 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2072 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2073 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2074 bool *is_last_frag);
2076 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2077 struct event_context *ev,
2078 struct rpc_pipe_client *cli,
2080 prs_struct *req_data)
2082 struct tevent_req *req, *subreq;
2083 struct rpc_api_pipe_req_state *state;
2087 req = tevent_req_create(mem_ctx, &state,
2088 struct rpc_api_pipe_req_state);
2094 state->op_num = op_num;
2095 state->req_data = req_data;
2096 state->req_data_sent = 0;
2097 state->call_id = get_rpc_call_id();
2098 state->reply_pdu = data_blob_null;
2100 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2101 + RPC_MAX_SIGN_SIZE) {
2102 /* Server is screwed up ! */
2103 status = NT_STATUS_INVALID_PARAMETER;
2107 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2112 status = prepare_next_frag(state, &is_last_frag);
2113 if (!NT_STATUS_IS_OK(status)) {
2118 subreq = rpc_api_pipe_send(state, ev, state->cli,
2119 &state->outgoing_frag,
2120 DCERPC_PKT_RESPONSE);
2121 if (subreq == NULL) {
2124 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2126 subreq = rpc_write_send(
2127 state, ev, cli->transport,
2128 (uint8_t *)prs_data_p(&state->outgoing_frag),
2129 prs_offset(&state->outgoing_frag));
2130 if (subreq == NULL) {
2133 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2139 tevent_req_nterror(req, status);
2140 return tevent_req_post(req, ev);
2146 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2149 uint32_t data_sent_thistime;
2153 uint32_t ss_padding;
2155 char pad[8] = { 0, };
2157 union dcerpc_payload u;
2160 data_left = prs_offset(state->req_data) - state->req_data_sent;
2162 data_sent_thistime = calculate_data_len_tosend(
2163 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2165 if (state->req_data_sent == 0) {
2166 flags = DCERPC_PFC_FLAG_FIRST;
2169 if (data_sent_thistime == data_left) {
2170 flags |= DCERPC_PFC_FLAG_LAST;
2173 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2174 return NT_STATUS_NO_MEMORY;
2177 ZERO_STRUCT(u.request);
2179 u.request.alloc_hint = prs_offset(state->req_data);
2180 u.request.context_id = 0;
2181 u.request.opnum = state->op_num;
2183 status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
2190 if (!NT_STATUS_IS_OK(status)) {
2194 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2195 * compute it right for requests */
2196 dcerpc_set_frag_length(&blob, frag_len);
2198 if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) {
2199 return NT_STATUS_NO_MEMORY;
2202 /* Copy in the data, plus any ss padding. */
2203 if (!prs_append_some_prs_data(&state->outgoing_frag,
2204 state->req_data, state->req_data_sent,
2205 data_sent_thistime)) {
2206 return NT_STATUS_NO_MEMORY;
2209 /* Copy the sign/seal padding data. */
2210 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2211 return NT_STATUS_NO_MEMORY;
2214 /* Generate any auth sign/seal and add the auth footer. */
2215 switch (state->cli->auth->auth_type) {
2216 case PIPE_AUTH_TYPE_NONE:
2217 status = NT_STATUS_OK;
2219 case PIPE_AUTH_TYPE_NTLMSSP:
2220 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2221 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2222 &state->outgoing_frag);
2224 case PIPE_AUTH_TYPE_SCHANNEL:
2225 status = add_schannel_auth_footer(state->cli, ss_padding,
2226 &state->outgoing_frag);
2229 status = NT_STATUS_INVALID_PARAMETER;
2233 state->req_data_sent += data_sent_thistime;
2234 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2239 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2241 struct tevent_req *req = tevent_req_callback_data(
2242 subreq, struct tevent_req);
2243 struct rpc_api_pipe_req_state *state = tevent_req_data(
2244 req, struct rpc_api_pipe_req_state);
2248 status = rpc_write_recv(subreq);
2249 TALLOC_FREE(subreq);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 tevent_req_nterror(req, status);
2255 status = prepare_next_frag(state, &is_last_frag);
2256 if (!NT_STATUS_IS_OK(status)) {
2257 tevent_req_nterror(req, status);
2262 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2263 &state->outgoing_frag,
2264 DCERPC_PKT_RESPONSE);
2265 if (tevent_req_nomem(subreq, req)) {
2268 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2270 subreq = rpc_write_send(
2272 state->cli->transport,
2273 (uint8_t *)prs_data_p(&state->outgoing_frag),
2274 prs_offset(&state->outgoing_frag));
2275 if (tevent_req_nomem(subreq, req)) {
2278 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2283 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2285 struct tevent_req *req = tevent_req_callback_data(
2286 subreq, struct tevent_req);
2287 struct rpc_api_pipe_req_state *state = tevent_req_data(
2288 req, struct rpc_api_pipe_req_state);
2291 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2292 TALLOC_FREE(subreq);
2293 if (!NT_STATUS_IS_OK(status)) {
2294 tevent_req_nterror(req, status);
2297 tevent_req_done(req);
2300 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2301 DATA_BLOB *reply_pdu)
2303 struct rpc_api_pipe_req_state *state = tevent_req_data(
2304 req, struct rpc_api_pipe_req_state);
2307 if (tevent_req_is_nterror(req, &status)) {
2309 * We always have to initialize to reply pdu, even if there is
2310 * none. The rpccli_* caller routines expect this.
2312 *reply_pdu = data_blob_null;
2316 /* return data to caller and assign it ownership of memory */
2317 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2318 reply_pdu->length = state->reply_pdu.length;
2319 state->reply_pdu.length = 0;
2321 return NT_STATUS_OK;
2325 /****************************************************************************
2326 Set the handle state.
2327 ****************************************************************************/
2329 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2330 const char *pipe_name, uint16 device_state)
2332 bool state_set = False;
2334 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2335 char *rparam = NULL;
2337 uint32 rparam_len, rdata_len;
2339 if (pipe_name == NULL)
2342 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2343 cli->fnum, pipe_name, device_state));
2345 /* create parameters: device state */
2346 SSVAL(param, 0, device_state);
2348 /* create setup parameters. */
2350 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2352 /* send the data on \PIPE\ */
2353 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2354 setup, 2, 0, /* setup, length, max */
2355 param, 2, 0, /* param, length, max */
2356 NULL, 0, 1024, /* data, length, max */
2357 &rparam, &rparam_len, /* return param, length */
2358 &rdata, &rdata_len)) /* return data, length */
2360 DEBUG(5, ("Set Handle state: return OK\n"));
2371 /****************************************************************************
2372 Check the rpc bind acknowledge response.
2373 ****************************************************************************/
2375 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2376 const struct ndr_syntax_id *transfer)
2378 struct dcerpc_ack_ctx ctx;
2380 if (r->secondary_address_size == 0) {
2381 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2384 if (r->num_results < 1 || !r->ctx_list) {
2388 ctx = r->ctx_list[0];
2390 /* check the transfer syntax */
2391 if ((ctx.syntax.if_version != transfer->if_version) ||
2392 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2393 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2397 if (r->num_results != 0x1 || ctx.result != 0) {
2398 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2399 r->num_results, ctx.reason));
2402 DEBUG(5,("check_bind_response: accepted!\n"));
2406 /*******************************************************************
2407 Creates a DCE/RPC bind authentication response.
2408 This is the packet that is sent back to the server once we
2409 have received a BIND-ACK, to finish the third leg of
2410 the authentication handshake.
2411 ********************************************************************/
2413 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2415 enum pipe_auth_type auth_type,
2416 enum dcerpc_AuthLevel auth_level,
2417 DATA_BLOB *pauth_blob,
2418 prs_struct *rpc_out)
2421 union dcerpc_payload u;
2426 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2427 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2429 0, /* auth_pad_length */
2430 1, /* auth_context_id */
2432 &u.auth3.auth_info);
2433 if (!NT_STATUS_IS_OK(status)) {
2437 status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
2439 DCERPC_PFC_FLAG_FIRST |
2440 DCERPC_PFC_FLAG_LAST,
2445 if (!NT_STATUS_IS_OK(status)) {
2446 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2450 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
2451 return NT_STATUS_NO_MEMORY;
2454 return NT_STATUS_OK;
2457 /*******************************************************************
2458 Creates a DCE/RPC bind alter context authentication request which
2459 may contain a spnego auth blobl
2460 ********************************************************************/
2462 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2463 const struct ndr_syntax_id *abstract,
2464 const struct ndr_syntax_id *transfer,
2465 enum dcerpc_AuthLevel auth_level,
2466 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2467 prs_struct *rpc_out)
2469 DATA_BLOB auth_info;
2472 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2473 DCERPC_AUTH_TYPE_SPNEGO,
2475 0, /* auth_pad_length */
2476 1, /* auth_context_id */
2479 if (!NT_STATUS_IS_OK(status)) {
2484 status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2490 if (!NT_STATUS_IS_OK(status)) {
2497 /****************************************************************************
2499 ****************************************************************************/
2501 struct rpc_pipe_bind_state {
2502 struct event_context *ev;
2503 struct rpc_pipe_client *cli;
2505 uint32_t rpc_call_id;
2508 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2509 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2510 struct rpc_pipe_bind_state *state,
2511 struct ncacn_packet *r);
2512 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2513 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2514 struct rpc_pipe_bind_state *state,
2515 struct ncacn_packet *r,
2516 DATA_BLOB *reply_pdu);
2517 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2519 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2520 struct event_context *ev,
2521 struct rpc_pipe_client *cli,
2522 struct cli_pipe_auth_data *auth)
2524 struct tevent_req *req, *subreq;
2525 struct rpc_pipe_bind_state *state;
2528 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2533 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2534 rpccli_pipe_txt(talloc_tos(), cli),
2535 (unsigned int)auth->auth_type,
2536 (unsigned int)auth->auth_level ));
2540 state->rpc_call_id = get_rpc_call_id();
2542 prs_init_empty(&state->rpc_out, state, MARSHALL);
2544 cli->auth = talloc_move(cli, &auth);
2546 /* Marshall the outgoing data. */
2547 status = create_rpc_bind_req(cli, &state->rpc_out,
2549 &cli->abstract_syntax,
2550 &cli->transfer_syntax,
2551 cli->auth->auth_type,
2552 cli->auth->auth_level);
2554 if (!NT_STATUS_IS_OK(status)) {
2558 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2559 DCERPC_PKT_BIND_ACK);
2560 if (subreq == NULL) {
2563 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2567 tevent_req_nterror(req, status);
2568 return tevent_req_post(req, ev);
2574 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2576 struct tevent_req *req = tevent_req_callback_data(
2577 subreq, struct tevent_req);
2578 struct rpc_pipe_bind_state *state = tevent_req_data(
2579 req, struct rpc_pipe_bind_state);
2580 DATA_BLOB reply_pdu;
2581 struct ncacn_packet *pkt;
2584 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2585 TALLOC_FREE(subreq);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2588 rpccli_pipe_txt(talloc_tos(), state->cli),
2589 nt_errstr(status)));
2590 tevent_req_nterror(req, status);
2594 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2595 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2596 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2600 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2601 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2604 * For authenticated binds we may need to do 3 or 4 leg binds.
2607 switch(state->cli->auth->auth_type) {
2609 case PIPE_AUTH_TYPE_NONE:
2610 case PIPE_AUTH_TYPE_SCHANNEL:
2611 /* Bind complete. */
2612 tevent_req_done(req);
2615 case PIPE_AUTH_TYPE_NTLMSSP:
2616 /* Need to send AUTH3 packet - no reply. */
2617 status = rpc_finish_auth3_bind_send(req, state, pkt);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 tevent_req_nterror(req, status);
2623 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2624 /* Need to send alter context request and reply. */
2625 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2627 if (!NT_STATUS_IS_OK(status)) {
2628 tevent_req_nterror(req, status);
2632 case PIPE_AUTH_TYPE_KRB5:
2636 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2637 (unsigned int)state->cli->auth->auth_type));
2638 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2642 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2643 struct rpc_pipe_bind_state *state,
2644 struct ncacn_packet *r)
2646 DATA_BLOB client_reply = data_blob_null;
2647 struct dcerpc_auth auth;
2648 struct tevent_req *subreq;
2651 if ((r->auth_length == 0)
2652 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2653 + r->auth_length)) {
2654 return NT_STATUS_INVALID_PARAMETER;
2657 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2658 &r->u.bind_ack.auth_info,
2660 if (!NT_STATUS_IS_OK(status)) {
2661 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2662 nt_errstr(status)));
2666 /* TODO - check auth_type/auth_level match. */
2668 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2669 auth.credentials, &client_reply);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2673 "blob failed: %s.\n", nt_errstr(status)));
2677 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2679 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2680 state->cli->auth->auth_type,
2681 state->cli->auth->auth_level,
2682 &client_reply, &state->rpc_out);
2683 data_blob_free(&client_reply);
2685 if (!NT_STATUS_IS_OK(status)) {
2689 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2690 (uint8_t *)prs_data_p(&state->rpc_out),
2691 prs_offset(&state->rpc_out));
2692 if (subreq == NULL) {
2693 return NT_STATUS_NO_MEMORY;
2695 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2696 return NT_STATUS_OK;
2699 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2701 struct tevent_req *req = tevent_req_callback_data(
2702 subreq, struct tevent_req);
2705 status = rpc_write_recv(subreq);
2706 TALLOC_FREE(subreq);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 tevent_req_nterror(req, status);
2711 tevent_req_done(req);
2714 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2715 struct rpc_pipe_bind_state *state,
2716 struct ncacn_packet *r,
2717 DATA_BLOB *reply_pdu)
2719 DATA_BLOB server_ntlm_response = data_blob_null;
2720 DATA_BLOB client_reply = data_blob_null;
2721 DATA_BLOB tmp_blob = data_blob_null;
2722 struct dcerpc_auth auth_info;
2723 DATA_BLOB auth_blob;
2724 struct tevent_req *subreq;
2727 if ((r->auth_length == 0)
2728 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2729 + r->auth_length)) {
2730 return NT_STATUS_INVALID_PARAMETER;
2733 /* Process the returned NTLMSSP blob first. */
2734 auth_blob = data_blob_const(reply_pdu->data
2736 - DCERPC_AUTH_TRAILER_LENGTH
2738 DCERPC_AUTH_TRAILER_LENGTH
2741 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2748 * The server might give us back two challenges - tmp_blob is for the
2751 if (!spnego_parse_challenge(auth_info.credentials,
2752 &server_ntlm_response, &tmp_blob)) {
2753 data_blob_free(&server_ntlm_response);
2754 data_blob_free(&tmp_blob);
2755 return NT_STATUS_INVALID_PARAMETER;
2758 /* We're finished with the server spnego response and the tmp_blob. */
2759 data_blob_free(&tmp_blob);
2761 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2762 server_ntlm_response, &client_reply);
2764 /* Finished with the server_ntlm response */
2765 data_blob_free(&server_ntlm_response);
2767 if (!NT_STATUS_IS_OK(status)) {
2768 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2769 "using server blob failed.\n"));
2770 data_blob_free(&client_reply);
2774 /* SPNEGO wrap the client reply. */
2775 tmp_blob = spnego_gen_auth(client_reply);
2776 data_blob_free(&client_reply);
2777 client_reply = tmp_blob;
2778 tmp_blob = data_blob_null;
2780 /* Now prepare the alter context pdu. */
2781 prs_init_empty(&state->rpc_out, state, MARSHALL);
2783 status = create_rpc_alter_context(state->rpc_call_id,
2784 &state->cli->abstract_syntax,
2785 &state->cli->transfer_syntax,
2786 state->cli->auth->auth_level,
2789 data_blob_free(&client_reply);
2791 if (!NT_STATUS_IS_OK(status)) {
2795 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2796 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2797 if (subreq == NULL) {
2798 return NT_STATUS_NO_MEMORY;
2800 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2801 return NT_STATUS_OK;
2804 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2806 struct tevent_req *req = tevent_req_callback_data(
2807 subreq, struct tevent_req);
2808 struct rpc_pipe_bind_state *state = tevent_req_data(
2809 req, struct rpc_pipe_bind_state);
2810 DATA_BLOB tmp_blob = data_blob_null;
2811 struct ncacn_packet *pkt;
2812 struct dcerpc_auth auth;
2815 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2816 TALLOC_FREE(subreq);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 tevent_req_nterror(req, status);
2822 status = dcerpc_pull_dcerpc_auth(pkt,
2823 &pkt->u.alter_resp.auth_info,
2825 if (!NT_STATUS_IS_OK(status)) {
2826 tevent_req_nterror(req, status);
2830 /* Check we got a valid auth response. */
2831 if (!spnego_parse_auth_response(auth.credentials,
2833 OID_NTLMSSP, &tmp_blob)) {
2834 data_blob_free(&tmp_blob);
2835 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2839 data_blob_free(&tmp_blob);
2841 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2842 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2843 tevent_req_done(req);
2846 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2848 return tevent_req_simple_recv_ntstatus(req);
2851 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2852 struct cli_pipe_auth_data *auth)
2854 TALLOC_CTX *frame = talloc_stackframe();
2855 struct event_context *ev;
2856 struct tevent_req *req;
2857 NTSTATUS status = NT_STATUS_OK;
2859 ev = event_context_init(frame);
2861 status = NT_STATUS_NO_MEMORY;
2865 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2867 status = NT_STATUS_NO_MEMORY;
2871 if (!tevent_req_poll(req, ev)) {
2872 status = map_nt_error_from_unix(errno);
2876 status = rpc_pipe_bind_recv(req);
2882 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2884 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2885 unsigned int timeout)
2889 if (rpc_cli->transport == NULL) {
2890 return RPCCLI_DEFAULT_TIMEOUT;
2893 if (rpc_cli->transport->set_timeout == NULL) {
2894 return RPCCLI_DEFAULT_TIMEOUT;
2897 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2899 return RPCCLI_DEFAULT_TIMEOUT;
2905 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2907 if (rpc_cli == NULL) {
2911 if (rpc_cli->transport == NULL) {
2915 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2918 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2920 struct cli_state *cli;
2922 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2923 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2924 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2928 cli = rpc_pipe_np_smb_conn(rpc_cli);
2932 E_md4hash(cli->password ? cli->password : "", nt_hash);
2936 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2937 struct cli_pipe_auth_data **presult)
2939 struct cli_pipe_auth_data *result;
2941 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2942 if (result == NULL) {
2943 return NT_STATUS_NO_MEMORY;
2946 result->auth_type = PIPE_AUTH_TYPE_NONE;
2947 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2949 result->user_name = talloc_strdup(result, "");
2950 result->domain = talloc_strdup(result, "");
2951 if ((result->user_name == NULL) || (result->domain == NULL)) {
2952 TALLOC_FREE(result);
2953 return NT_STATUS_NO_MEMORY;
2957 return NT_STATUS_OK;
2960 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2962 ntlmssp_end(&auth->a_u.ntlmssp_state);
2966 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2967 enum pipe_auth_type auth_type,
2968 enum dcerpc_AuthLevel auth_level,
2970 const char *username,
2971 const char *password,
2972 struct cli_pipe_auth_data **presult)
2974 struct cli_pipe_auth_data *result;
2977 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2978 if (result == NULL) {
2979 return NT_STATUS_NO_MEMORY;
2982 result->auth_type = auth_type;
2983 result->auth_level = auth_level;
2985 result->user_name = talloc_strdup(result, username);
2986 result->domain = talloc_strdup(result, domain);
2987 if ((result->user_name == NULL) || (result->domain == NULL)) {
2988 status = NT_STATUS_NO_MEMORY;
2992 status = ntlmssp_client_start(NULL,
2995 lp_client_ntlmv2_auth(),
2996 &result->a_u.ntlmssp_state);
2997 if (!NT_STATUS_IS_OK(status)) {
3001 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3003 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3004 if (!NT_STATUS_IS_OK(status)) {
3008 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3009 if (!NT_STATUS_IS_OK(status)) {
3013 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3014 if (!NT_STATUS_IS_OK(status)) {
3019 * Turn off sign+seal to allow selected auth level to turn it back on.
3021 result->a_u.ntlmssp_state->neg_flags &=
3022 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3024 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3025 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3026 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3027 result->a_u.ntlmssp_state->neg_flags
3028 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3032 return NT_STATUS_OK;
3035 TALLOC_FREE(result);
3039 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3040 enum dcerpc_AuthLevel auth_level,
3041 struct netlogon_creds_CredentialState *creds,
3042 struct cli_pipe_auth_data **presult)
3044 struct cli_pipe_auth_data *result;
3046 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3047 if (result == NULL) {
3048 return NT_STATUS_NO_MEMORY;
3051 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3052 result->auth_level = auth_level;
3054 result->user_name = talloc_strdup(result, "");
3055 result->domain = talloc_strdup(result, domain);
3056 if ((result->user_name == NULL) || (result->domain == NULL)) {
3060 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3061 if (result->a_u.schannel_auth == NULL) {
3065 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3066 result->a_u.schannel_auth->seq_num = 0;
3067 result->a_u.schannel_auth->initiator = true;
3068 result->a_u.schannel_auth->creds = creds;
3071 return NT_STATUS_OK;
3074 TALLOC_FREE(result);
3075 return NT_STATUS_NO_MEMORY;
3079 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3081 data_blob_free(&auth->session_key);
3086 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3087 enum dcerpc_AuthLevel auth_level,
3088 const char *service_princ,
3089 const char *username,
3090 const char *password,
3091 struct cli_pipe_auth_data **presult)
3094 struct cli_pipe_auth_data *result;
3096 if ((username != NULL) && (password != NULL)) {
3097 int ret = kerberos_kinit_password(username, password, 0, NULL);
3099 return NT_STATUS_ACCESS_DENIED;
3103 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3104 if (result == NULL) {
3105 return NT_STATUS_NO_MEMORY;
3108 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3109 result->auth_level = auth_level;
3112 * Username / domain need fixing!
3114 result->user_name = talloc_strdup(result, "");
3115 result->domain = talloc_strdup(result, "");
3116 if ((result->user_name == NULL) || (result->domain == NULL)) {
3120 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3121 result, struct kerberos_auth_struct);
3122 if (result->a_u.kerberos_auth == NULL) {
3125 talloc_set_destructor(result->a_u.kerberos_auth,
3126 cli_auth_kerberos_data_destructor);
3128 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3129 result, service_princ);
3130 if (result->a_u.kerberos_auth->service_principal == NULL) {
3135 return NT_STATUS_OK;
3138 TALLOC_FREE(result);
3139 return NT_STATUS_NO_MEMORY;
3141 return NT_STATUS_NOT_SUPPORTED;
3146 * Create an rpc pipe client struct, connecting to a tcp port.
3148 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3150 const struct ndr_syntax_id *abstract_syntax,
3151 struct rpc_pipe_client **presult)
3153 struct rpc_pipe_client *result;
3154 struct sockaddr_storage addr;
3158 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3159 if (result == NULL) {
3160 return NT_STATUS_NO_MEMORY;
3163 result->abstract_syntax = *abstract_syntax;
3164 result->transfer_syntax = ndr_transfer_syntax;
3165 result->dispatch = cli_do_rpc_ndr;
3166 result->dispatch_send = cli_do_rpc_ndr_send;
3167 result->dispatch_recv = cli_do_rpc_ndr_recv;
3169 result->desthost = talloc_strdup(result, host);
3170 result->srv_name_slash = talloc_asprintf_strupper_m(
3171 result, "\\\\%s", result->desthost);
3172 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3173 status = NT_STATUS_NO_MEMORY;
3177 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3178 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3180 if (!resolve_name(host, &addr, 0, false)) {
3181 status = NT_STATUS_NOT_FOUND;
3185 status = open_socket_out(&addr, port, 60, &fd);
3186 if (!NT_STATUS_IS_OK(status)) {
3189 set_socket_options(fd, lp_socket_options());
3191 status = rpc_transport_sock_init(result, fd, &result->transport);
3192 if (!NT_STATUS_IS_OK(status)) {
3197 result->transport->transport = NCACN_IP_TCP;
3200 return NT_STATUS_OK;
3203 TALLOC_FREE(result);
3208 * Determine the tcp port on which a dcerpc interface is listening
3209 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3212 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3213 const struct ndr_syntax_id *abstract_syntax,
3217 struct rpc_pipe_client *epm_pipe = NULL;
3218 struct cli_pipe_auth_data *auth = NULL;
3219 struct dcerpc_binding *map_binding = NULL;
3220 struct dcerpc_binding *res_binding = NULL;
3221 struct epm_twr_t *map_tower = NULL;
3222 struct epm_twr_t *res_towers = NULL;
3223 struct policy_handle *entry_handle = NULL;
3224 uint32_t num_towers = 0;
3225 uint32_t max_towers = 1;
3226 struct epm_twr_p_t towers;
3227 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3229 if (pport == NULL) {
3230 status = NT_STATUS_INVALID_PARAMETER;
3234 /* open the connection to the endpoint mapper */
3235 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3236 &ndr_table_epmapper.syntax_id,
3239 if (!NT_STATUS_IS_OK(status)) {
3243 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3244 if (!NT_STATUS_IS_OK(status)) {
3248 status = rpc_pipe_bind(epm_pipe, auth);
3249 if (!NT_STATUS_IS_OK(status)) {
3253 /* create tower for asking the epmapper */
3255 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3256 if (map_binding == NULL) {
3257 status = NT_STATUS_NO_MEMORY;
3261 map_binding->transport = NCACN_IP_TCP;
3262 map_binding->object = *abstract_syntax;
3263 map_binding->host = host; /* needed? */
3264 map_binding->endpoint = "0"; /* correct? needed? */
3266 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3267 if (map_tower == NULL) {
3268 status = NT_STATUS_NO_MEMORY;
3272 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3273 &(map_tower->tower));
3274 if (!NT_STATUS_IS_OK(status)) {
3278 /* allocate further parameters for the epm_Map call */
3280 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3281 if (res_towers == NULL) {
3282 status = NT_STATUS_NO_MEMORY;
3285 towers.twr = res_towers;
3287 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3288 if (entry_handle == NULL) {
3289 status = NT_STATUS_NO_MEMORY;
3293 /* ask the endpoint mapper for the port */
3295 status = rpccli_epm_Map(epm_pipe,
3297 CONST_DISCARD(struct GUID *,
3298 &(abstract_syntax->uuid)),
3305 if (!NT_STATUS_IS_OK(status)) {
3309 if (num_towers != 1) {
3310 status = NT_STATUS_UNSUCCESSFUL;
3314 /* extract the port from the answer */
3316 status = dcerpc_binding_from_tower(tmp_ctx,
3317 &(towers.twr->tower),
3319 if (!NT_STATUS_IS_OK(status)) {
3323 /* are further checks here necessary? */
3324 if (res_binding->transport != NCACN_IP_TCP) {
3325 status = NT_STATUS_UNSUCCESSFUL;
3329 *pport = (uint16_t)atoi(res_binding->endpoint);
3332 TALLOC_FREE(tmp_ctx);
3337 * Create a rpc pipe client struct, connecting to a host via tcp.
3338 * The port is determined by asking the endpoint mapper on the given
3341 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3342 const struct ndr_syntax_id *abstract_syntax,
3343 struct rpc_pipe_client **presult)
3348 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3349 if (!NT_STATUS_IS_OK(status)) {
3353 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3354 abstract_syntax, presult);
3357 /********************************************************************
3358 Create a rpc pipe client struct, connecting to a unix domain socket
3359 ********************************************************************/
3360 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3361 const struct ndr_syntax_id *abstract_syntax,
3362 struct rpc_pipe_client **presult)
3364 struct rpc_pipe_client *result;
3365 struct sockaddr_un addr;
3369 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3370 if (result == NULL) {
3371 return NT_STATUS_NO_MEMORY;
3374 result->abstract_syntax = *abstract_syntax;
3375 result->transfer_syntax = ndr_transfer_syntax;
3376 result->dispatch = cli_do_rpc_ndr;
3377 result->dispatch_send = cli_do_rpc_ndr_send;
3378 result->dispatch_recv = cli_do_rpc_ndr_recv;
3380 result->desthost = get_myname(result);
3381 result->srv_name_slash = talloc_asprintf_strupper_m(
3382 result, "\\\\%s", result->desthost);
3383 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3384 status = NT_STATUS_NO_MEMORY;
3388 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3389 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3391 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3393 status = map_nt_error_from_unix(errno);
3398 addr.sun_family = AF_UNIX;
3399 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3401 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3402 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3405 return map_nt_error_from_unix(errno);
3408 status = rpc_transport_sock_init(result, fd, &result->transport);
3409 if (!NT_STATUS_IS_OK(status)) {
3414 result->transport->transport = NCALRPC;
3417 return NT_STATUS_OK;
3420 TALLOC_FREE(result);
3424 struct rpc_pipe_client_np_ref {
3425 struct cli_state *cli;
3426 struct rpc_pipe_client *pipe;
3429 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3431 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3435 /****************************************************************************
3436 Open a named pipe over SMB to a remote server.
3438 * CAVEAT CALLER OF THIS FUNCTION:
3439 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3440 * so be sure that this function is called AFTER any structure (vs pointer)
3441 * assignment of the cli. In particular, libsmbclient does structure
3442 * assignments of cli, which invalidates the data in the returned
3443 * rpc_pipe_client if this function is called before the structure assignment
3446 ****************************************************************************/
3448 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3449 const struct ndr_syntax_id *abstract_syntax,
3450 struct rpc_pipe_client **presult)
3452 struct rpc_pipe_client *result;
3454 struct rpc_pipe_client_np_ref *np_ref;
3456 /* sanity check to protect against crashes */
3459 return NT_STATUS_INVALID_HANDLE;
3462 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3463 if (result == NULL) {
3464 return NT_STATUS_NO_MEMORY;
3467 result->abstract_syntax = *abstract_syntax;
3468 result->transfer_syntax = ndr_transfer_syntax;
3469 result->dispatch = cli_do_rpc_ndr;
3470 result->dispatch_send = cli_do_rpc_ndr_send;
3471 result->dispatch_recv = cli_do_rpc_ndr_recv;
3472 result->desthost = talloc_strdup(result, cli->desthost);
3473 result->srv_name_slash = talloc_asprintf_strupper_m(
3474 result, "\\\\%s", result->desthost);
3476 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3477 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3479 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3480 TALLOC_FREE(result);
3481 return NT_STATUS_NO_MEMORY;
3484 status = rpc_transport_np_init(result, cli, abstract_syntax,
3485 &result->transport);
3486 if (!NT_STATUS_IS_OK(status)) {
3487 TALLOC_FREE(result);
3491 result->transport->transport = NCACN_NP;
3493 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3494 if (np_ref == NULL) {
3495 TALLOC_FREE(result);
3496 return NT_STATUS_NO_MEMORY;
3499 np_ref->pipe = result;
3501 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3502 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3505 return NT_STATUS_OK;
3508 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3509 struct rpc_cli_smbd_conn *conn,
3510 const struct ndr_syntax_id *syntax,
3511 struct rpc_pipe_client **presult)
3513 struct rpc_pipe_client *result;
3514 struct cli_pipe_auth_data *auth;
3517 result = talloc(mem_ctx, struct rpc_pipe_client);
3518 if (result == NULL) {
3519 return NT_STATUS_NO_MEMORY;
3521 result->abstract_syntax = *syntax;
3522 result->transfer_syntax = ndr_transfer_syntax;
3523 result->dispatch = cli_do_rpc_ndr;
3524 result->dispatch_send = cli_do_rpc_ndr_send;
3525 result->dispatch_recv = cli_do_rpc_ndr_recv;
3526 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3527 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3529 result->desthost = talloc_strdup(result, global_myname());
3530 result->srv_name_slash = talloc_asprintf_strupper_m(
3531 result, "\\\\%s", global_myname());
3532 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3533 TALLOC_FREE(result);
3534 return NT_STATUS_NO_MEMORY;
3537 status = rpc_transport_smbd_init(result, conn, syntax,
3538 &result->transport);
3539 if (!NT_STATUS_IS_OK(status)) {
3540 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3541 nt_errstr(status)));
3542 TALLOC_FREE(result);
3546 status = rpccli_anon_bind_data(result, &auth);
3547 if (!NT_STATUS_IS_OK(status)) {
3548 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3549 nt_errstr(status)));
3550 TALLOC_FREE(result);
3554 status = rpc_pipe_bind(result, auth);
3555 if (!NT_STATUS_IS_OK(status)) {
3556 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3557 TALLOC_FREE(result);
3561 result->transport->transport = NCACN_INTERNAL;
3564 return NT_STATUS_OK;
3567 /****************************************************************************
3568 Open a pipe to a remote server.
3569 ****************************************************************************/
3571 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3572 enum dcerpc_transport_t transport,
3573 const struct ndr_syntax_id *interface,
3574 struct rpc_pipe_client **presult)
3576 switch (transport) {
3578 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3581 return rpc_pipe_open_np(cli, interface, presult);
3583 return NT_STATUS_NOT_IMPLEMENTED;
3587 /****************************************************************************
3588 Open a named pipe to an SMB server and bind anonymously.
3589 ****************************************************************************/
3591 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3592 enum dcerpc_transport_t transport,
3593 const struct ndr_syntax_id *interface,
3594 struct rpc_pipe_client **presult)
3596 struct rpc_pipe_client *result;
3597 struct cli_pipe_auth_data *auth;
3600 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3601 if (!NT_STATUS_IS_OK(status)) {
3605 status = rpccli_anon_bind_data(result, &auth);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3608 nt_errstr(status)));
3609 TALLOC_FREE(result);
3614 * This is a bit of an abstraction violation due to the fact that an
3615 * anonymous bind on an authenticated SMB inherits the user/domain
3616 * from the enclosing SMB creds
3619 TALLOC_FREE(auth->user_name);
3620 TALLOC_FREE(auth->domain);
3622 auth->user_name = talloc_strdup(auth, cli->user_name);
3623 auth->domain = talloc_strdup(auth, cli->domain);
3624 auth->user_session_key = data_blob_talloc(auth,
3625 cli->user_session_key.data,
3626 cli->user_session_key.length);
3628 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3629 TALLOC_FREE(result);
3630 return NT_STATUS_NO_MEMORY;
3633 status = rpc_pipe_bind(result, auth);
3634 if (!NT_STATUS_IS_OK(status)) {
3636 if (ndr_syntax_id_equal(interface,
3637 &ndr_table_dssetup.syntax_id)) {
3638 /* non AD domains just don't have this pipe, avoid
3639 * level 0 statement in that case - gd */
3642 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3643 "%s failed with error %s\n",
3644 get_pipe_name_from_syntax(talloc_tos(), interface),
3645 nt_errstr(status) ));
3646 TALLOC_FREE(result);
3650 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3651 "%s and bound anonymously.\n",
3652 get_pipe_name_from_syntax(talloc_tos(), interface),
3656 return NT_STATUS_OK;
3659 /****************************************************************************
3660 ****************************************************************************/
3662 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3663 const struct ndr_syntax_id *interface,
3664 struct rpc_pipe_client **presult)
3666 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3667 interface, presult);
3670 /****************************************************************************
3671 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3672 ****************************************************************************/
3674 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3675 const struct ndr_syntax_id *interface,
3676 enum dcerpc_transport_t transport,
3677 enum pipe_auth_type auth_type,
3678 enum dcerpc_AuthLevel auth_level,
3680 const char *username,
3681 const char *password,
3682 struct rpc_pipe_client **presult)
3684 struct rpc_pipe_client *result;
3685 struct cli_pipe_auth_data *auth;
3688 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3689 if (!NT_STATUS_IS_OK(status)) {
3693 status = rpccli_ntlmssp_bind_data(
3694 result, auth_type, auth_level, domain, username,
3696 if (!NT_STATUS_IS_OK(status)) {
3697 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3698 nt_errstr(status)));
3702 status = rpc_pipe_bind(result, auth);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3705 nt_errstr(status) ));
3709 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3710 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3711 get_pipe_name_from_syntax(talloc_tos(), interface),
3712 cli->desthost, domain, username ));
3715 return NT_STATUS_OK;
3719 TALLOC_FREE(result);
3723 /****************************************************************************
3725 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3726 ****************************************************************************/
3728 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3729 const struct ndr_syntax_id *interface,
3730 enum dcerpc_transport_t transport,
3731 enum dcerpc_AuthLevel auth_level,
3733 const char *username,
3734 const char *password,
3735 struct rpc_pipe_client **presult)
3737 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3740 PIPE_AUTH_TYPE_NTLMSSP,
3748 /****************************************************************************
3750 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3751 ****************************************************************************/
3753 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3754 const struct ndr_syntax_id *interface,
3755 enum dcerpc_transport_t transport,
3756 enum dcerpc_AuthLevel auth_level,
3758 const char *username,
3759 const char *password,
3760 struct rpc_pipe_client **presult)
3762 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3765 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3773 /****************************************************************************
3774 Get a the schannel session key out of an already opened netlogon pipe.
3775 ****************************************************************************/
3776 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3777 struct cli_state *cli,
3781 enum netr_SchannelType sec_chan_type = 0;
3782 unsigned char machine_pwd[16];
3783 const char *machine_account;
3786 /* Get the machine account credentials from secrets.tdb. */
3787 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3790 DEBUG(0, ("get_schannel_session_key: could not fetch "
3791 "trust account password for domain '%s'\n",
3793 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3796 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3797 cli->desthost, /* server name */
3798 domain, /* domain */
3799 global_myname(), /* client name */
3800 machine_account, /* machine account name */
3805 if (!NT_STATUS_IS_OK(status)) {
3806 DEBUG(3, ("get_schannel_session_key_common: "
3807 "rpccli_netlogon_setup_creds failed with result %s "
3808 "to server %s, domain %s, machine account %s.\n",
3809 nt_errstr(status), cli->desthost, domain,
3814 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3815 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3817 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3820 return NT_STATUS_OK;;
3823 /****************************************************************************
3824 Open a netlogon pipe and get the schannel session key.
3825 Now exposed to external callers.
3826 ****************************************************************************/
3829 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3832 struct rpc_pipe_client **presult)
3834 struct rpc_pipe_client *netlogon_pipe = NULL;
3837 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3839 if (!NT_STATUS_IS_OK(status)) {
3843 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3845 if (!NT_STATUS_IS_OK(status)) {
3846 TALLOC_FREE(netlogon_pipe);
3850 *presult = netlogon_pipe;
3851 return NT_STATUS_OK;
3854 /****************************************************************************
3856 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3857 using session_key. sign and seal.
3859 The *pdc will be stolen onto this new pipe
3860 ****************************************************************************/
3862 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3863 const struct ndr_syntax_id *interface,
3864 enum dcerpc_transport_t transport,
3865 enum dcerpc_AuthLevel auth_level,
3867 struct netlogon_creds_CredentialState **pdc,
3868 struct rpc_pipe_client **presult)
3870 struct rpc_pipe_client *result;
3871 struct cli_pipe_auth_data *auth;
3874 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3875 if (!NT_STATUS_IS_OK(status)) {
3879 status = rpccli_schannel_bind_data(result, domain, auth_level,
3881 if (!NT_STATUS_IS_OK(status)) {
3882 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3883 nt_errstr(status)));
3884 TALLOC_FREE(result);
3888 status = rpc_pipe_bind(result, auth);
3889 if (!NT_STATUS_IS_OK(status)) {
3890 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3891 "cli_rpc_pipe_bind failed with error %s\n",
3892 nt_errstr(status) ));
3893 TALLOC_FREE(result);
3898 * The credentials on a new netlogon pipe are the ones we are passed
3899 * in - reference them in
3901 result->dc = talloc_move(result, pdc);
3903 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3904 "for domain %s and bound using schannel.\n",
3905 get_pipe_name_from_syntax(talloc_tos(), interface),
3906 cli->desthost, domain ));
3909 return NT_STATUS_OK;
3912 /****************************************************************************
3913 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3914 Fetch the session key ourselves using a temporary netlogon pipe. This
3915 version uses an ntlmssp auth bound netlogon pipe to get the key.
3916 ****************************************************************************/
3918 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3920 const char *username,
3921 const char *password,
3923 struct rpc_pipe_client **presult)
3925 struct rpc_pipe_client *netlogon_pipe = NULL;
3928 status = cli_rpc_pipe_open_spnego_ntlmssp(
3929 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3930 DCERPC_AUTH_LEVEL_PRIVACY,
3931 domain, username, password, &netlogon_pipe);
3932 if (!NT_STATUS_IS_OK(status)) {
3936 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3938 if (!NT_STATUS_IS_OK(status)) {
3939 TALLOC_FREE(netlogon_pipe);
3943 *presult = netlogon_pipe;
3944 return NT_STATUS_OK;
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. This version
3950 uses an ntlmssp bind to get the session key.
3951 ****************************************************************************/
3953 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3954 const struct ndr_syntax_id *interface,
3955 enum dcerpc_transport_t transport,
3956 enum dcerpc_AuthLevel auth_level,
3958 const char *username,
3959 const char *password,
3960 struct rpc_pipe_client **presult)
3962 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3963 struct rpc_pipe_client *netlogon_pipe = NULL;
3964 struct rpc_pipe_client *result = NULL;
3967 status = get_schannel_session_key_auth_ntlmssp(
3968 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3971 "key from server %s for domain %s.\n",
3972 cli->desthost, domain ));
3976 status = cli_rpc_pipe_open_schannel_with_key(
3977 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3980 /* Now we've bound using the session key we can close the netlog pipe. */
3981 TALLOC_FREE(netlogon_pipe);
3983 if (NT_STATUS_IS_OK(status)) {
3989 /****************************************************************************
3990 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3991 Fetch the session key ourselves using a temporary netlogon pipe.
3992 ****************************************************************************/
3994 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3995 const struct ndr_syntax_id *interface,
3996 enum dcerpc_transport_t transport,
3997 enum dcerpc_AuthLevel auth_level,
3999 struct rpc_pipe_client **presult)
4001 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4002 struct rpc_pipe_client *netlogon_pipe = NULL;
4003 struct rpc_pipe_client *result = NULL;
4006 status = get_schannel_session_key(cli, domain, &neg_flags,
4008 if (!NT_STATUS_IS_OK(status)) {
4009 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4010 "key from server %s for domain %s.\n",
4011 cli->desthost, domain ));
4015 status = cli_rpc_pipe_open_schannel_with_key(
4016 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4019 /* Now we've bound using the session key we can close the netlog pipe. */
4020 TALLOC_FREE(netlogon_pipe);
4022 if (NT_STATUS_IS_OK(status)) {
4029 /****************************************************************************
4030 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4031 The idea is this can be called with service_princ, username and password all
4032 NULL so long as the caller has a TGT.
4033 ****************************************************************************/
4035 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4036 const struct ndr_syntax_id *interface,
4037 enum dcerpc_AuthLevel auth_level,
4038 const char *service_princ,
4039 const char *username,
4040 const char *password,
4041 struct rpc_pipe_client **presult)
4044 struct rpc_pipe_client *result;
4045 struct cli_pipe_auth_data *auth;
4048 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4049 if (!NT_STATUS_IS_OK(status)) {
4053 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4054 username, password, &auth);
4055 if (!NT_STATUS_IS_OK(status)) {
4056 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4057 nt_errstr(status)));
4058 TALLOC_FREE(result);
4062 status = rpc_pipe_bind(result, auth);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4065 "with error %s\n", nt_errstr(status)));
4066 TALLOC_FREE(result);
4071 return NT_STATUS_OK;
4073 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4074 return NT_STATUS_NOT_IMPLEMENTED;
4078 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4079 struct rpc_pipe_client *cli,
4080 DATA_BLOB *session_key)
4082 if (!session_key || !cli) {
4083 return NT_STATUS_INVALID_PARAMETER;
4087 return NT_STATUS_INVALID_PARAMETER;
4090 switch (cli->auth->auth_type) {
4091 case PIPE_AUTH_TYPE_SCHANNEL:
4092 *session_key = data_blob_talloc(mem_ctx,
4093 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4095 case PIPE_AUTH_TYPE_NTLMSSP:
4096 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4097 *session_key = data_blob_talloc(mem_ctx,
4098 cli->auth->a_u.ntlmssp_state->session_key.data,
4099 cli->auth->a_u.ntlmssp_state->session_key.length);
4101 case PIPE_AUTH_TYPE_KRB5:
4102 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4103 *session_key = data_blob_talloc(mem_ctx,
4104 cli->auth->a_u.kerberos_auth->session_key.data,
4105 cli->auth->a_u.kerberos_auth->session_key.length);
4107 case PIPE_AUTH_TYPE_NONE:
4108 *session_key = data_blob_talloc(mem_ctx,
4109 cli->auth->user_session_key.data,
4110 cli->auth->user_session_key.length);
4113 return NT_STATUS_NO_USER_SESSION_KEY;
4116 return NT_STATUS_OK;