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(struct rpc_pipe_client *cli,
908 struct ncacn_packet *pkt,
910 uint8 expected_pkt_type,
912 prs_struct *return_data)
914 NTSTATUS ret = NT_STATUS_OK;
915 uint8 ss_padding_len = 0;
917 ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt);
918 if (!NT_STATUS_IS_OK(ret)) {
922 if (pdu->length != pkt->frag_length) {
923 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
924 (unsigned int)pdu->length,
925 (unsigned int)pkt->frag_length));
926 return NT_STATUS_INVALID_PARAMETER;
930 * Point the return values at the real data including the RPC
931 * header. Just in case the caller wants it.
935 /* Ensure we have the correct type. */
936 switch (pkt->ptype) {
937 case DCERPC_PKT_ALTER_RESP:
938 case DCERPC_PKT_BIND_ACK:
940 /* Alter context and bind ack share the same packet definitions. */
944 case DCERPC_PKT_RESPONSE:
946 /* Here's where we deal with incoming sign/seal. */
947 ret = cli_pipe_validate_rpc_response(cli, pkt, pdu,
949 if (!NT_STATUS_IS_OK(ret)) {
953 /* Point the return values at the NDR data.
954 * Remember to remove any ss padding. */
955 rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
957 if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
958 return NT_STATUS_BUFFER_TOO_SMALL;
961 rdata->length = pdu->length
962 - DCERPC_RESPONSE_LENGTH
965 /* Remember to remove the auth footer. */
966 if (pkt->auth_length) {
967 /* We've already done integer wrap tests on auth_len in
968 cli_pipe_validate_rpc_response(). */
969 if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH
970 + pkt->auth_length) {
971 return NT_STATUS_BUFFER_TOO_SMALL;
973 rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH
977 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
978 pdu->length, rdata->length, ss_padding_len));
981 * If this is the first reply, and the allocation hint is
982 * reasonable, try and set up the return_data parse_struct to
986 if ((prs_data_size(return_data) == 0) &&
987 pkt->u.response.alloc_hint &&
988 (pkt->u.response.alloc_hint < 15*1024*1024)) {
989 if (!prs_set_buffer_size(return_data,
990 pkt->u.response.alloc_hint)) {
991 DEBUG(0, ("reply alloc hint %d too "
992 "large to allocate\n",
993 (int)pkt->u.response.alloc_hint));
994 return NT_STATUS_NO_MEMORY;
1000 case DCERPC_PKT_BIND_NAK:
1001 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1002 "received from %s!\n",
1003 rpccli_pipe_txt(talloc_tos(), cli)));
1004 /* Use this for now... */
1005 return NT_STATUS_NETWORK_ACCESS_DENIED;
1007 case DCERPC_PKT_FAULT:
1009 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1010 "code %s received from %s!\n",
1011 dcerpc_errstr(talloc_tos(),
1012 pkt->u.fault.status),
1013 rpccli_pipe_txt(talloc_tos(), cli)));
1015 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
1016 return NT_STATUS_UNSUCCESSFUL;
1018 return NT_STATUS(pkt->u.fault.status);
1022 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1023 (unsigned int)pkt->ptype,
1024 rpccli_pipe_txt(talloc_tos(), cli)));
1025 return NT_STATUS_INVALID_INFO_CLASS;
1028 if (pkt->ptype != expected_pkt_type) {
1029 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1030 "got an unexpected RPC packet type - %u, not %u\n",
1031 rpccli_pipe_txt(talloc_tos(), cli),
1033 expected_pkt_type));
1034 return NT_STATUS_INVALID_INFO_CLASS;
1037 /* Do this just before return - we don't want to modify any rpc header
1038 data before now as we may have needed to do cryptographic actions on
1041 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
1042 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1043 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1044 "setting fragment first/last ON.\n"));
1045 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
1046 DCERPC_PFC_FLAG_LAST;
1049 return NT_STATUS_OK;
1052 /****************************************************************************
1053 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1054 ****************************************************************************/
1056 struct cli_api_pipe_state {
1057 struct event_context *ev;
1058 struct rpc_cli_transport *transport;
1063 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1064 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1065 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1067 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1068 struct event_context *ev,
1069 struct rpc_cli_transport *transport,
1070 uint8_t *data, size_t data_len,
1071 uint32_t max_rdata_len)
1073 struct tevent_req *req, *subreq;
1074 struct cli_api_pipe_state *state;
1077 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1082 state->transport = transport;
1084 if (max_rdata_len < RPC_HEADER_LEN) {
1086 * For a RPC reply we always need at least RPC_HEADER_LEN
1087 * bytes. We check this here because we will receive
1088 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1090 status = NT_STATUS_INVALID_PARAMETER;
1094 if (transport->trans_send != NULL) {
1095 subreq = transport->trans_send(state, ev, data, data_len,
1096 max_rdata_len, transport->priv);
1097 if (subreq == NULL) {
1100 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1105 * If the transport does not provide a "trans" routine, i.e. for
1106 * example the ncacn_ip_tcp transport, do the write/read step here.
1109 subreq = rpc_write_send(state, ev, transport, data, data_len);
1110 if (subreq == NULL) {
1113 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1117 tevent_req_nterror(req, status);
1118 return tevent_req_post(req, ev);
1124 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1126 struct tevent_req *req = tevent_req_callback_data(
1127 subreq, struct tevent_req);
1128 struct cli_api_pipe_state *state = tevent_req_data(
1129 req, struct cli_api_pipe_state);
1132 status = state->transport->trans_recv(subreq, state, &state->rdata,
1134 TALLOC_FREE(subreq);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 tevent_req_nterror(req, status);
1139 tevent_req_done(req);
1142 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1144 struct tevent_req *req = tevent_req_callback_data(
1145 subreq, struct tevent_req);
1146 struct cli_api_pipe_state *state = tevent_req_data(
1147 req, struct cli_api_pipe_state);
1150 status = rpc_write_recv(subreq);
1151 TALLOC_FREE(subreq);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 tevent_req_nterror(req, status);
1157 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1158 if (tevent_req_nomem(state->rdata, req)) {
1163 * We don't need to use rpc_read_send here, the upper layer will cope
1164 * with a short read, transport->trans_send could also return less
1165 * than state->max_rdata_len.
1167 subreq = state->transport->read_send(state, state->ev, state->rdata,
1169 state->transport->priv);
1170 if (tevent_req_nomem(subreq, req)) {
1173 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1176 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1178 struct tevent_req *req = tevent_req_callback_data(
1179 subreq, struct tevent_req);
1180 struct cli_api_pipe_state *state = tevent_req_data(
1181 req, struct cli_api_pipe_state);
1185 status = state->transport->read_recv(subreq, &received);
1186 TALLOC_FREE(subreq);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 tevent_req_nterror(req, status);
1191 state->rdata_len = received;
1192 tevent_req_done(req);
1195 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1196 uint8_t **prdata, uint32_t *prdata_len)
1198 struct cli_api_pipe_state *state = tevent_req_data(
1199 req, struct cli_api_pipe_state);
1202 if (tevent_req_is_nterror(req, &status)) {
1206 *prdata = talloc_move(mem_ctx, &state->rdata);
1207 *prdata_len = state->rdata_len;
1208 return NT_STATUS_OK;
1211 /****************************************************************************
1212 Send data on an rpc pipe via trans. The prs_struct data must be the last
1213 pdu fragment of an NDR data stream.
1215 Receive response data from an rpc pipe, which may be large...
1217 Read the first fragment: unfortunately have to use SMBtrans for the first
1218 bit, then SMBreadX for subsequent bits.
1220 If first fragment received also wasn't the last fragment, continue
1221 getting fragments until we _do_ receive the last fragment.
1223 Request/Response PDU's look like the following...
1225 |<------------------PDU len----------------------------------------------->|
1226 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1228 +------------+-----------------+-------------+---------------+-------------+
1229 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1230 +------------+-----------------+-------------+---------------+-------------+
1232 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1233 signing & sealing being negotiated.
1235 ****************************************************************************/
1237 struct rpc_api_pipe_state {
1238 struct event_context *ev;
1239 struct rpc_pipe_client *cli;
1240 uint8_t expected_pkt_type;
1242 DATA_BLOB incoming_frag;
1243 struct ncacn_packet *pkt;
1245 prs_struct incoming_pdu; /* Incoming reply */
1246 uint32_t incoming_pdu_offset;
1249 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1250 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1252 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1253 struct event_context *ev,
1254 struct rpc_pipe_client *cli,
1255 prs_struct *data, /* Outgoing PDU */
1256 uint8_t expected_pkt_type)
1258 struct tevent_req *req, *subreq;
1259 struct rpc_api_pipe_state *state;
1260 uint16_t max_recv_frag;
1263 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1269 state->expected_pkt_type = expected_pkt_type;
1270 state->incoming_pdu_offset = 0;
1271 state->incoming_frag = data_blob_null;
1273 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1274 /* Make incoming_pdu dynamic with no memory. */
1275 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1278 * Ensure we're not sending too much.
1280 if (prs_offset(data) > cli->max_xmit_frag) {
1281 status = NT_STATUS_INVALID_PARAMETER;
1285 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1287 /* get the header first, then fetch the rest once we have
1288 * the frag_length available */
1289 max_recv_frag = RPC_HEADER_LEN;
1291 subreq = cli_api_pipe_send(state, ev, cli->transport,
1292 (uint8_t *)prs_data_p(data),
1293 prs_offset(data), max_recv_frag);
1294 if (subreq == NULL) {
1297 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1301 tevent_req_nterror(req, status);
1302 return tevent_req_post(req, ev);
1308 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1310 struct tevent_req *req = tevent_req_callback_data(
1311 subreq, struct tevent_req);
1312 struct rpc_api_pipe_state *state = tevent_req_data(
1313 req, struct rpc_api_pipe_state);
1315 uint8_t *rdata = NULL;
1316 uint32_t rdata_len = 0;
1318 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1319 TALLOC_FREE(subreq);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1322 tevent_req_nterror(req, status);
1326 if (rdata == NULL) {
1327 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1328 rpccli_pipe_txt(talloc_tos(), state->cli)));
1329 tevent_req_done(req);
1334 * Move data on state->incoming_frag.
1336 state->incoming_frag.data = talloc_move(state, &rdata);
1337 state->incoming_frag.length = rdata_len;
1338 if (!state->incoming_frag.data) {
1339 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1343 /* Ensure we have enough data for a pdu. */
1344 subreq = get_complete_frag_send(state, state->ev, state->cli,
1345 &state->incoming_frag);
1346 if (tevent_req_nomem(subreq, req)) {
1349 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1352 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1354 struct tevent_req *req = tevent_req_callback_data(
1355 subreq, struct tevent_req);
1356 struct rpc_api_pipe_state *state = tevent_req_data(
1357 req, struct rpc_api_pipe_state);
1359 DATA_BLOB rdata = data_blob_null;
1361 status = get_complete_frag_recv(subreq);
1362 TALLOC_FREE(subreq);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 DEBUG(5, ("get_complete_frag failed: %s\n",
1365 nt_errstr(status)));
1366 tevent_req_nterror(req, status);
1370 state->pkt = talloc(state, struct ncacn_packet);
1372 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1376 status = cli_pipe_validate_current_pdu(state->cli, state->pkt,
1377 &state->incoming_frag,
1378 state->expected_pkt_type,
1380 &state->incoming_pdu);
1382 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1383 (unsigned)state->incoming_frag.length,
1384 (unsigned)state->incoming_pdu_offset,
1385 nt_errstr(status)));
1387 if (!NT_STATUS_IS_OK(status)) {
1388 tevent_req_nterror(req, status);
1392 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1393 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1395 * Set the data type correctly for big-endian data on the
1398 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1400 rpccli_pipe_txt(talloc_tos(), state->cli)));
1401 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1404 * Check endianness on subsequent packets.
1406 if (state->incoming_pdu.bigendian_data &&
1407 (state->pkt->drep[0] == DCERPC_DREP_LE)) {
1408 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1410 state->incoming_pdu.bigendian_data?"big":"little",
1411 (state->pkt->drep[0] != DCERPC_DREP_LE)?"big":"little"));
1412 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1416 /* Now copy the data portion out of the pdu into rbuf. */
1417 if (!prs_force_grow(&state->incoming_pdu, rdata.length)) {
1418 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1422 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1423 rdata.data, rdata.length);
1424 state->incoming_pdu_offset += rdata.length;
1426 /* reset state->incoming_frag, there is no need to free it,
1427 * it will be reallocated to the right size the next time
1429 state->incoming_frag.length = 0;
1431 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1432 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1433 rpccli_pipe_txt(talloc_tos(), state->cli),
1434 (unsigned)prs_data_size(&state->incoming_pdu)));
1435 tevent_req_done(req);
1439 subreq = get_complete_frag_send(state, state->ev, state->cli,
1440 &state->incoming_frag);
1441 if (tevent_req_nomem(subreq, req)) {
1444 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1447 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1448 struct ncacn_packet **pkt,
1449 prs_struct *reply_pdu)
1451 struct rpc_api_pipe_state *state = tevent_req_data(
1452 req, struct rpc_api_pipe_state);
1455 if (tevent_req_is_nterror(req, &status)) {
1459 *reply_pdu = state->incoming_pdu;
1460 reply_pdu->mem_ctx = mem_ctx;
1463 * Prevent state->incoming_pdu from being freed
1464 * when state is freed.
1466 talloc_steal(mem_ctx, prs_data_p(reply_pdu));
1467 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1470 *pkt = talloc_steal(mem_ctx, state->pkt);
1473 return NT_STATUS_OK;
1476 /*******************************************************************
1477 Creates krb5 auth bind.
1478 ********************************************************************/
1480 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1481 enum dcerpc_AuthLevel auth_level,
1482 DATA_BLOB *auth_info)
1487 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1488 DATA_BLOB tkt = data_blob_null;
1489 DATA_BLOB tkt_wrapped = data_blob_null;
1491 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1492 a->service_principal ));
1494 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1496 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1497 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1500 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1502 a->service_principal,
1503 error_message(ret) ));
1505 data_blob_free(&tkt);
1506 return NT_STATUS_INVALID_PARAMETER;
1509 /* wrap that up in a nice GSS-API wrapping */
1510 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1512 data_blob_free(&tkt);
1514 status = dcerpc_push_dcerpc_auth(cli,
1515 DCERPC_AUTH_TYPE_KRB5,
1517 0, /* auth_pad_length */
1518 1, /* auth_context_id */
1521 if (!NT_STATUS_IS_OK(status)) {
1522 data_blob_free(&tkt_wrapped);
1526 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1527 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1529 return NT_STATUS_OK;
1531 return NT_STATUS_INVALID_PARAMETER;
1535 /*******************************************************************
1536 Creates SPNEGO NTLMSSP auth bind.
1537 ********************************************************************/
1539 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1540 enum dcerpc_AuthLevel auth_level,
1541 DATA_BLOB *auth_info)
1544 DATA_BLOB null_blob = data_blob_null;
1545 DATA_BLOB request = data_blob_null;
1546 DATA_BLOB spnego_msg = data_blob_null;
1548 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1549 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1553 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1554 data_blob_free(&request);
1558 /* Wrap this in SPNEGO. */
1559 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1561 data_blob_free(&request);
1563 status = dcerpc_push_dcerpc_auth(cli,
1564 DCERPC_AUTH_TYPE_SPNEGO,
1566 0, /* auth_pad_length */
1567 1, /* auth_context_id */
1570 if (!NT_STATUS_IS_OK(status)) {
1571 data_blob_free(&spnego_msg);
1575 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1576 dump_data(5, spnego_msg.data, spnego_msg.length);
1578 return NT_STATUS_OK;
1581 /*******************************************************************
1582 Creates NTLMSSP auth bind.
1583 ********************************************************************/
1585 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1586 enum dcerpc_AuthLevel auth_level,
1587 DATA_BLOB *auth_info)
1590 DATA_BLOB null_blob = data_blob_null;
1591 DATA_BLOB request = data_blob_null;
1593 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1594 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1598 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1599 data_blob_free(&request);
1603 status = dcerpc_push_dcerpc_auth(cli,
1604 DCERPC_AUTH_TYPE_NTLMSSP,
1606 0, /* auth_pad_length */
1607 1, /* auth_context_id */
1610 if (!NT_STATUS_IS_OK(status)) {
1611 data_blob_free(&request);
1615 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1616 dump_data(5, request.data, request.length);
1618 return NT_STATUS_OK;
1621 /*******************************************************************
1622 Creates schannel auth bind.
1623 ********************************************************************/
1625 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1626 enum dcerpc_AuthLevel auth_level,
1627 DATA_BLOB *auth_info)
1630 struct NL_AUTH_MESSAGE r;
1631 DATA_BLOB schannel_blob;
1633 /* Use lp_workgroup() if domain not specified */
1635 if (!cli->auth->domain || !cli->auth->domain[0]) {
1636 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1637 if (cli->auth->domain == NULL) {
1638 return NT_STATUS_NO_MEMORY;
1643 * Now marshall the data into the auth parse_struct.
1646 r.MessageType = NL_NEGOTIATE_REQUEST;
1647 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1648 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1649 r.oem_netbios_domain.a = cli->auth->domain;
1650 r.oem_netbios_computer.a = global_myname();
1652 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1653 if (!NT_STATUS_IS_OK(status)) {
1657 status = dcerpc_push_dcerpc_auth(cli,
1658 DCERPC_AUTH_TYPE_SCHANNEL,
1660 0, /* auth_pad_length */
1661 1, /* auth_context_id */
1664 if (!NT_STATUS_IS_OK(status)) {
1668 return NT_STATUS_OK;
1671 /*******************************************************************
1672 ********************************************************************/
1674 static NTSTATUS init_dcerpc_ctx_list(TALLOC_CTX *mem_ctx,
1675 const struct ndr_syntax_id *abstract_syntax,
1676 const struct ndr_syntax_id *transfer_syntax,
1677 struct dcerpc_ctx_list **ctx_list_p)
1679 struct dcerpc_ctx_list *ctx_list;
1681 ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1682 NT_STATUS_HAVE_NO_MEMORY(ctx_list);
1684 ctx_list[0].context_id = 0;
1685 ctx_list[0].num_transfer_syntaxes = 1;
1686 ctx_list[0].abstract_syntax = *abstract_syntax;
1687 ctx_list[0].transfer_syntaxes = talloc_array(ctx_list,
1688 struct ndr_syntax_id,
1689 ctx_list[0].num_transfer_syntaxes);
1690 NT_STATUS_HAVE_NO_MEMORY(ctx_list[0].transfer_syntaxes);
1691 ctx_list[0].transfer_syntaxes[0] = *transfer_syntax;
1693 *ctx_list_p = ctx_list;
1695 return NT_STATUS_OK;
1698 /*******************************************************************
1699 Creates the internals of a DCE/RPC bind request or alter context PDU.
1700 ********************************************************************/
1702 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype,
1703 prs_struct *rpc_out,
1705 const struct ndr_syntax_id *abstract,
1706 const struct ndr_syntax_id *transfer,
1707 const DATA_BLOB *auth_info)
1709 uint16 auth_len = auth_info->length;
1711 union dcerpc_payload u;
1713 struct dcerpc_ctx_list *ctx_list;
1715 status = init_dcerpc_ctx_list(rpc_out->mem_ctx, abstract, transfer,
1717 if (!NT_STATUS_IS_OK(status)) {
1722 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1725 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1726 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1727 u.bind.assoc_group_id = 0x0;
1728 u.bind.num_contexts = 1;
1729 u.bind.ctx_list = ctx_list;
1730 u.bind.auth_info = *auth_info;
1732 status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx,
1734 DCERPC_PFC_FLAG_FIRST |
1735 DCERPC_PFC_FLAG_LAST,
1740 if (!NT_STATUS_IS_OK(status)) {
1741 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1745 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
1746 return NT_STATUS_NO_MEMORY;
1749 return NT_STATUS_OK;
1752 /*******************************************************************
1753 Creates a DCE/RPC bind request.
1754 ********************************************************************/
1756 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1757 prs_struct *rpc_out,
1759 const struct ndr_syntax_id *abstract,
1760 const struct ndr_syntax_id *transfer,
1761 enum pipe_auth_type auth_type,
1762 enum dcerpc_AuthLevel auth_level)
1764 DATA_BLOB auth_info = data_blob_null;
1765 NTSTATUS ret = NT_STATUS_OK;
1767 switch (auth_type) {
1768 case PIPE_AUTH_TYPE_SCHANNEL:
1769 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1770 if (!NT_STATUS_IS_OK(ret)) {
1775 case PIPE_AUTH_TYPE_NTLMSSP:
1776 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1777 if (!NT_STATUS_IS_OK(ret)) {
1782 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1783 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1784 if (!NT_STATUS_IS_OK(ret)) {
1789 case PIPE_AUTH_TYPE_KRB5:
1790 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1791 if (!NT_STATUS_IS_OK(ret)) {
1796 case PIPE_AUTH_TYPE_NONE:
1800 /* "Can't" happen. */
1801 return NT_STATUS_INVALID_INFO_CLASS;
1804 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1813 /*******************************************************************
1814 Create and add the NTLMSSP sign/seal auth header and data.
1815 ********************************************************************/
1817 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1818 uint32 ss_padding_len,
1819 prs_struct *rpc_out)
1821 DATA_BLOB auth_info;
1823 DATA_BLOB auth_blob = data_blob_null;
1824 uint16_t data_and_pad_len = prs_offset(rpc_out)
1825 - DCERPC_RESPONSE_LENGTH;
1827 if (!cli->auth->a_u.ntlmssp_state) {
1828 return NT_STATUS_INVALID_PARAMETER;
1831 /* marshall the dcerpc_auth with an actually empty auth_blob.
1832 * this is needed because the ntmlssp signature includes the
1834 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1835 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1836 cli->auth->auth_level,
1838 1 /* context id. */,
1841 if (!NT_STATUS_IS_OK(status)) {
1845 /* append the header */
1846 if (!prs_copy_data_in(rpc_out,
1847 (char *)auth_info.data,
1848 auth_info.length)) {
1849 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1850 (unsigned int)auth_info.length));
1851 return NT_STATUS_NO_MEMORY;
1854 switch (cli->auth->auth_level) {
1855 case DCERPC_AUTH_LEVEL_PRIVACY:
1856 /* Data portion is encrypted. */
1857 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1858 prs_get_mem_context(rpc_out),
1859 (unsigned char *)prs_data_p(rpc_out)
1860 + DCERPC_RESPONSE_LENGTH,
1862 (unsigned char *)prs_data_p(rpc_out),
1863 (size_t)prs_offset(rpc_out),
1865 if (!NT_STATUS_IS_OK(status)) {
1870 case DCERPC_AUTH_LEVEL_INTEGRITY:
1871 /* Data is signed. */
1872 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1873 prs_get_mem_context(rpc_out),
1874 (unsigned char *)prs_data_p(rpc_out)
1875 + DCERPC_RESPONSE_LENGTH,
1877 (unsigned char *)prs_data_p(rpc_out),
1878 (size_t)prs_offset(rpc_out),
1880 if (!NT_STATUS_IS_OK(status)) {
1887 smb_panic("bad auth level");
1889 return NT_STATUS_INVALID_PARAMETER;
1892 /* Finally attach the blob. */
1893 if (!prs_copy_data_in(rpc_out,
1894 (char *)auth_blob.data,
1895 auth_blob.length)) {
1896 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1897 (unsigned int)auth_info.length));
1898 return NT_STATUS_NO_MEMORY;
1901 return NT_STATUS_OK;
1904 /*******************************************************************
1905 Create and add the schannel sign/seal auth header and data.
1906 ********************************************************************/
1908 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1909 uint32 ss_padding_len,
1910 prs_struct *rpc_out)
1912 DATA_BLOB auth_info;
1913 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1914 char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH;
1915 size_t data_and_pad_len = prs_offset(rpc_out)
1916 - DCERPC_RESPONSE_LENGTH;
1921 return NT_STATUS_INVALID_PARAMETER;
1924 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1927 switch (cli->auth->auth_level) {
1928 case DCERPC_AUTH_LEVEL_PRIVACY:
1929 status = netsec_outgoing_packet(sas,
1936 case DCERPC_AUTH_LEVEL_INTEGRITY:
1937 status = netsec_outgoing_packet(sas,
1945 status = NT_STATUS_INTERNAL_ERROR;
1949 if (!NT_STATUS_IS_OK(status)) {
1950 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1951 nt_errstr(status)));
1955 if (DEBUGLEVEL >= 10) {
1956 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1959 /* Finally marshall the blob. */
1960 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1961 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1962 cli->auth->auth_level,
1964 1 /* context id. */,
1967 if (!NT_STATUS_IS_OK(status)) {
1971 if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
1972 return NT_STATUS_NO_MEMORY;
1975 return NT_STATUS_OK;
1978 /*******************************************************************
1979 Calculate how much data we're going to send in this packet, also
1980 work out any sign/seal padding length.
1981 ********************************************************************/
1983 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1987 uint32 *p_ss_padding)
1989 uint32 data_space, data_len;
1992 if ((data_left > 0) && (sys_random() % 2)) {
1993 data_left = MAX(data_left/2, 1);
1997 switch (cli->auth->auth_level) {
1998 case DCERPC_AUTH_LEVEL_NONE:
1999 case DCERPC_AUTH_LEVEL_CONNECT:
2000 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
2001 data_len = MIN(data_space, data_left);
2004 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
2007 case DCERPC_AUTH_LEVEL_INTEGRITY:
2008 case DCERPC_AUTH_LEVEL_PRIVACY:
2009 /* Treat the same for all authenticated rpc requests. */
2010 switch(cli->auth->auth_type) {
2011 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2012 case PIPE_AUTH_TYPE_NTLMSSP:
2013 *p_auth_len = NTLMSSP_SIG_SIZE;
2015 case PIPE_AUTH_TYPE_SCHANNEL:
2016 *p_auth_len = SCHANNEL_SIG_SIZE;
2019 smb_panic("bad auth type");
2023 data_space = cli->max_xmit_frag
2024 - DCERPC_REQUEST_LENGTH
2025 - DCERPC_AUTH_TRAILER_LENGTH
2028 data_len = MIN(data_space, data_left);
2030 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2031 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2033 *p_frag_len = DCERPC_REQUEST_LENGTH
2034 + data_len + *p_ss_padding
2035 + DCERPC_AUTH_TRAILER_LENGTH
2040 smb_panic("bad auth level");
2046 /*******************************************************************
2048 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2049 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2050 and deals with signing/sealing details.
2051 ********************************************************************/
2053 struct rpc_api_pipe_req_state {
2054 struct event_context *ev;
2055 struct rpc_pipe_client *cli;
2058 prs_struct *req_data;
2059 uint32_t req_data_sent;
2060 prs_struct outgoing_frag;
2061 prs_struct reply_pdu;
2064 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2065 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2066 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2067 bool *is_last_frag);
2069 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2070 struct event_context *ev,
2071 struct rpc_pipe_client *cli,
2073 prs_struct *req_data)
2075 struct tevent_req *req, *subreq;
2076 struct rpc_api_pipe_req_state *state;
2080 req = tevent_req_create(mem_ctx, &state,
2081 struct rpc_api_pipe_req_state);
2087 state->op_num = op_num;
2088 state->req_data = req_data;
2089 state->req_data_sent = 0;
2090 state->call_id = get_rpc_call_id();
2092 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2093 + RPC_MAX_SIGN_SIZE) {
2094 /* Server is screwed up ! */
2095 status = NT_STATUS_INVALID_PARAMETER;
2099 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2101 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2106 status = prepare_next_frag(state, &is_last_frag);
2107 if (!NT_STATUS_IS_OK(status)) {
2112 subreq = rpc_api_pipe_send(state, ev, state->cli,
2113 &state->outgoing_frag,
2114 DCERPC_PKT_RESPONSE);
2115 if (subreq == NULL) {
2118 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2120 subreq = rpc_write_send(
2121 state, ev, cli->transport,
2122 (uint8_t *)prs_data_p(&state->outgoing_frag),
2123 prs_offset(&state->outgoing_frag));
2124 if (subreq == NULL) {
2127 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2133 tevent_req_nterror(req, status);
2134 return tevent_req_post(req, ev);
2140 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2143 uint32_t data_sent_thistime;
2147 uint32_t ss_padding;
2149 char pad[8] = { 0, };
2151 union dcerpc_payload u;
2154 data_left = prs_offset(state->req_data) - state->req_data_sent;
2156 data_sent_thistime = calculate_data_len_tosend(
2157 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2159 if (state->req_data_sent == 0) {
2160 flags = DCERPC_PFC_FLAG_FIRST;
2163 if (data_sent_thistime == data_left) {
2164 flags |= DCERPC_PFC_FLAG_LAST;
2167 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2168 return NT_STATUS_NO_MEMORY;
2171 ZERO_STRUCT(u.request);
2173 u.request.alloc_hint = prs_offset(state->req_data);
2174 u.request.context_id = 0;
2175 u.request.opnum = state->op_num;
2177 status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
2184 if (!NT_STATUS_IS_OK(status)) {
2188 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2189 * compute it right for requests */
2190 dcerpc_set_frag_length(&blob, frag_len);
2192 if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) {
2193 return NT_STATUS_NO_MEMORY;
2196 /* Copy in the data, plus any ss padding. */
2197 if (!prs_append_some_prs_data(&state->outgoing_frag,
2198 state->req_data, state->req_data_sent,
2199 data_sent_thistime)) {
2200 return NT_STATUS_NO_MEMORY;
2203 /* Copy the sign/seal padding data. */
2204 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2205 return NT_STATUS_NO_MEMORY;
2208 /* Generate any auth sign/seal and add the auth footer. */
2209 switch (state->cli->auth->auth_type) {
2210 case PIPE_AUTH_TYPE_NONE:
2211 status = NT_STATUS_OK;
2213 case PIPE_AUTH_TYPE_NTLMSSP:
2214 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2215 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2216 &state->outgoing_frag);
2218 case PIPE_AUTH_TYPE_SCHANNEL:
2219 status = add_schannel_auth_footer(state->cli, ss_padding,
2220 &state->outgoing_frag);
2223 status = NT_STATUS_INVALID_PARAMETER;
2227 state->req_data_sent += data_sent_thistime;
2228 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2233 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2235 struct tevent_req *req = tevent_req_callback_data(
2236 subreq, struct tevent_req);
2237 struct rpc_api_pipe_req_state *state = tevent_req_data(
2238 req, struct rpc_api_pipe_req_state);
2242 status = rpc_write_recv(subreq);
2243 TALLOC_FREE(subreq);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 tevent_req_nterror(req, status);
2249 status = prepare_next_frag(state, &is_last_frag);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 tevent_req_nterror(req, status);
2256 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2257 &state->outgoing_frag,
2258 DCERPC_PKT_RESPONSE);
2259 if (tevent_req_nomem(subreq, req)) {
2262 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2264 subreq = rpc_write_send(
2266 state->cli->transport,
2267 (uint8_t *)prs_data_p(&state->outgoing_frag),
2268 prs_offset(&state->outgoing_frag));
2269 if (tevent_req_nomem(subreq, req)) {
2272 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2277 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2279 struct tevent_req *req = tevent_req_callback_data(
2280 subreq, struct tevent_req);
2281 struct rpc_api_pipe_req_state *state = tevent_req_data(
2282 req, struct rpc_api_pipe_req_state);
2285 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2286 TALLOC_FREE(subreq);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 tevent_req_nterror(req, status);
2291 tevent_req_done(req);
2294 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2295 prs_struct *reply_pdu)
2297 struct rpc_api_pipe_req_state *state = tevent_req_data(
2298 req, struct rpc_api_pipe_req_state);
2301 if (tevent_req_is_nterror(req, &status)) {
2303 * We always have to initialize to reply pdu, even if there is
2304 * none. The rpccli_* caller routines expect this.
2306 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2310 *reply_pdu = state->reply_pdu;
2311 reply_pdu->mem_ctx = mem_ctx;
2314 * Prevent state->req_pdu from being freed
2315 * when state is freed.
2317 talloc_steal(mem_ctx, prs_data_p(reply_pdu));
2318 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2320 return NT_STATUS_OK;
2324 /****************************************************************************
2325 Set the handle state.
2326 ****************************************************************************/
2328 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2329 const char *pipe_name, uint16 device_state)
2331 bool state_set = False;
2333 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2334 char *rparam = NULL;
2336 uint32 rparam_len, rdata_len;
2338 if (pipe_name == NULL)
2341 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2342 cli->fnum, pipe_name, device_state));
2344 /* create parameters: device state */
2345 SSVAL(param, 0, device_state);
2347 /* create setup parameters. */
2349 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2351 /* send the data on \PIPE\ */
2352 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2353 setup, 2, 0, /* setup, length, max */
2354 param, 2, 0, /* param, length, max */
2355 NULL, 0, 1024, /* data, length, max */
2356 &rparam, &rparam_len, /* return param, length */
2357 &rdata, &rdata_len)) /* return data, length */
2359 DEBUG(5, ("Set Handle state: return OK\n"));
2370 /****************************************************************************
2371 Check the rpc bind acknowledge response.
2372 ****************************************************************************/
2374 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2375 const struct ndr_syntax_id *transfer)
2377 struct dcerpc_ack_ctx ctx;
2379 if (r->secondary_address_size == 0) {
2380 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2383 if (r->num_results < 1 || !r->ctx_list) {
2387 ctx = r->ctx_list[0];
2389 /* check the transfer syntax */
2390 if ((ctx.syntax.if_version != transfer->if_version) ||
2391 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2392 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2396 if (r->num_results != 0x1 || ctx.result != 0) {
2397 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2398 r->num_results, ctx.reason));
2401 DEBUG(5,("check_bind_response: accepted!\n"));
2405 /*******************************************************************
2406 Creates a DCE/RPC bind authentication response.
2407 This is the packet that is sent back to the server once we
2408 have received a BIND-ACK, to finish the third leg of
2409 the authentication handshake.
2410 ********************************************************************/
2412 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2414 enum pipe_auth_type auth_type,
2415 enum dcerpc_AuthLevel auth_level,
2416 DATA_BLOB *pauth_blob,
2417 prs_struct *rpc_out)
2420 union dcerpc_payload u;
2425 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2426 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2428 0, /* auth_pad_length */
2429 1, /* auth_context_id */
2431 &u.auth3.auth_info);
2432 if (!NT_STATUS_IS_OK(status)) {
2436 status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
2438 DCERPC_PFC_FLAG_FIRST |
2439 DCERPC_PFC_FLAG_LAST,
2444 if (!NT_STATUS_IS_OK(status)) {
2445 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2449 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
2450 return NT_STATUS_NO_MEMORY;
2453 return NT_STATUS_OK;
2456 /*******************************************************************
2457 Creates a DCE/RPC bind alter context authentication request which
2458 may contain a spnego auth blobl
2459 ********************************************************************/
2461 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2462 const struct ndr_syntax_id *abstract,
2463 const struct ndr_syntax_id *transfer,
2464 enum dcerpc_AuthLevel auth_level,
2465 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2466 prs_struct *rpc_out)
2468 DATA_BLOB auth_info;
2471 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2472 DCERPC_AUTH_TYPE_SPNEGO,
2474 0, /* auth_pad_length */
2475 1, /* auth_context_id */
2478 if (!NT_STATUS_IS_OK(status)) {
2483 status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2489 if (!NT_STATUS_IS_OK(status)) {
2496 /****************************************************************************
2498 ****************************************************************************/
2500 struct rpc_pipe_bind_state {
2501 struct event_context *ev;
2502 struct rpc_pipe_client *cli;
2504 uint32_t rpc_call_id;
2507 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2508 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2509 struct rpc_pipe_bind_state *state,
2510 struct ncacn_packet *r,
2511 prs_struct *reply_pdu);
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 prs_struct *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 prs_struct 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,
2619 if (!NT_STATUS_IS_OK(status)) {
2620 tevent_req_nterror(req, status);
2624 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2625 /* Need to send alter context request and reply. */
2626 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2628 if (!NT_STATUS_IS_OK(status)) {
2629 tevent_req_nterror(req, status);
2633 case PIPE_AUTH_TYPE_KRB5:
2637 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2638 (unsigned int)state->cli->auth->auth_type));
2639 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2643 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2644 struct rpc_pipe_bind_state *state,
2645 struct ncacn_packet *r,
2646 prs_struct *reply_pdu)
2648 DATA_BLOB client_reply = data_blob_null;
2649 struct dcerpc_auth auth;
2650 struct tevent_req *subreq;
2653 if ((r->auth_length == 0)
2654 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2655 + r->auth_length)) {
2656 return NT_STATUS_INVALID_PARAMETER;
2659 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2660 &r->u.bind_ack.auth_info,
2662 if (!NT_STATUS_IS_OK(status)) {
2663 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2664 nt_errstr(status)));
2668 /* TODO - check auth_type/auth_level match. */
2670 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2671 auth.credentials, &client_reply);
2673 if (!NT_STATUS_IS_OK(status)) {
2674 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2675 "blob failed: %s.\n", nt_errstr(status)));
2679 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2681 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2682 state->cli->auth->auth_type,
2683 state->cli->auth->auth_level,
2684 &client_reply, &state->rpc_out);
2685 data_blob_free(&client_reply);
2687 if (!NT_STATUS_IS_OK(status)) {
2691 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2692 (uint8_t *)prs_data_p(&state->rpc_out),
2693 prs_offset(&state->rpc_out));
2694 if (subreq == NULL) {
2695 return NT_STATUS_NO_MEMORY;
2697 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2698 return NT_STATUS_OK;
2701 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2703 struct tevent_req *req = tevent_req_callback_data(
2704 subreq, struct tevent_req);
2707 status = rpc_write_recv(subreq);
2708 TALLOC_FREE(subreq);
2709 if (!NT_STATUS_IS_OK(status)) {
2710 tevent_req_nterror(req, status);
2713 tevent_req_done(req);
2716 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2717 struct rpc_pipe_bind_state *state,
2718 struct ncacn_packet *r,
2721 DATA_BLOB server_ntlm_response = data_blob_null;
2722 DATA_BLOB client_reply = data_blob_null;
2723 DATA_BLOB tmp_blob = data_blob_null;
2724 struct dcerpc_auth auth_info;
2725 DATA_BLOB auth_blob;
2726 struct tevent_req *subreq;
2729 if ((r->auth_length == 0)
2730 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2731 + r->auth_length)) {
2732 return NT_STATUS_INVALID_PARAMETER;
2735 /* Process the returned NTLMSSP blob first. */
2736 if (!prs_set_offset(rpc_in, r->frag_length
2737 - DCERPC_AUTH_TRAILER_LENGTH
2738 - r->auth_length)) {
2739 return NT_STATUS_INVALID_PARAMETER;
2742 auth_blob = data_blob_const(prs_data_p(rpc_in) + prs_offset(rpc_in),
2743 prs_data_size(rpc_in) - prs_offset(rpc_in));
2745 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2752 * The server might give us back two challenges - tmp_blob is for the
2755 if (!spnego_parse_challenge(auth_info.credentials,
2756 &server_ntlm_response, &tmp_blob)) {
2757 data_blob_free(&server_ntlm_response);
2758 data_blob_free(&tmp_blob);
2759 return NT_STATUS_INVALID_PARAMETER;
2762 /* We're finished with the server spnego response and the tmp_blob. */
2763 data_blob_free(&tmp_blob);
2765 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2766 server_ntlm_response, &client_reply);
2768 /* Finished with the server_ntlm response */
2769 data_blob_free(&server_ntlm_response);
2771 if (!NT_STATUS_IS_OK(status)) {
2772 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2773 "using server blob failed.\n"));
2774 data_blob_free(&client_reply);
2778 /* SPNEGO wrap the client reply. */
2779 tmp_blob = spnego_gen_auth(client_reply);
2780 data_blob_free(&client_reply);
2781 client_reply = tmp_blob;
2782 tmp_blob = data_blob_null;
2784 /* Now prepare the alter context pdu. */
2785 prs_init_empty(&state->rpc_out, state, MARSHALL);
2787 status = create_rpc_alter_context(state->rpc_call_id,
2788 &state->cli->abstract_syntax,
2789 &state->cli->transfer_syntax,
2790 state->cli->auth->auth_level,
2793 data_blob_free(&client_reply);
2795 if (!NT_STATUS_IS_OK(status)) {
2799 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2800 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2801 if (subreq == NULL) {
2802 return NT_STATUS_NO_MEMORY;
2804 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2805 return NT_STATUS_OK;
2808 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2810 struct tevent_req *req = tevent_req_callback_data(
2811 subreq, struct tevent_req);
2812 struct rpc_pipe_bind_state *state = tevent_req_data(
2813 req, struct rpc_pipe_bind_state);
2814 DATA_BLOB tmp_blob = data_blob_null;
2815 struct ncacn_packet *pkt;
2816 struct dcerpc_auth auth;
2817 prs_struct reply_pdu;
2820 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2821 TALLOC_FREE(subreq);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 tevent_req_nterror(req, status);
2827 status = dcerpc_pull_dcerpc_auth(pkt,
2828 &pkt->u.alter_resp.auth_info,
2830 if (!NT_STATUS_IS_OK(status)) {
2831 tevent_req_nterror(req, status);
2835 /* Check we got a valid auth response. */
2836 if (!spnego_parse_auth_response(auth.credentials,
2838 OID_NTLMSSP, &tmp_blob)) {
2839 data_blob_free(&tmp_blob);
2840 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2844 data_blob_free(&tmp_blob);
2846 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2847 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2848 tevent_req_done(req);
2851 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2853 return tevent_req_simple_recv_ntstatus(req);
2856 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2857 struct cli_pipe_auth_data *auth)
2859 TALLOC_CTX *frame = talloc_stackframe();
2860 struct event_context *ev;
2861 struct tevent_req *req;
2862 NTSTATUS status = NT_STATUS_OK;
2864 ev = event_context_init(frame);
2866 status = NT_STATUS_NO_MEMORY;
2870 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2872 status = NT_STATUS_NO_MEMORY;
2876 if (!tevent_req_poll(req, ev)) {
2877 status = map_nt_error_from_unix(errno);
2881 status = rpc_pipe_bind_recv(req);
2887 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2889 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2890 unsigned int timeout)
2894 if (rpc_cli->transport == NULL) {
2895 return RPCCLI_DEFAULT_TIMEOUT;
2898 if (rpc_cli->transport->set_timeout == NULL) {
2899 return RPCCLI_DEFAULT_TIMEOUT;
2902 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2904 return RPCCLI_DEFAULT_TIMEOUT;
2910 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2912 if (rpc_cli == NULL) {
2916 if (rpc_cli->transport == NULL) {
2920 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2923 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2925 struct cli_state *cli;
2927 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2928 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2929 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2933 cli = rpc_pipe_np_smb_conn(rpc_cli);
2937 E_md4hash(cli->password ? cli->password : "", nt_hash);
2941 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2942 struct cli_pipe_auth_data **presult)
2944 struct cli_pipe_auth_data *result;
2946 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2947 if (result == NULL) {
2948 return NT_STATUS_NO_MEMORY;
2951 result->auth_type = PIPE_AUTH_TYPE_NONE;
2952 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2954 result->user_name = talloc_strdup(result, "");
2955 result->domain = talloc_strdup(result, "");
2956 if ((result->user_name == NULL) || (result->domain == NULL)) {
2957 TALLOC_FREE(result);
2958 return NT_STATUS_NO_MEMORY;
2962 return NT_STATUS_OK;
2965 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2967 ntlmssp_end(&auth->a_u.ntlmssp_state);
2971 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2972 enum pipe_auth_type auth_type,
2973 enum dcerpc_AuthLevel auth_level,
2975 const char *username,
2976 const char *password,
2977 struct cli_pipe_auth_data **presult)
2979 struct cli_pipe_auth_data *result;
2982 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2983 if (result == NULL) {
2984 return NT_STATUS_NO_MEMORY;
2987 result->auth_type = auth_type;
2988 result->auth_level = auth_level;
2990 result->user_name = talloc_strdup(result, username);
2991 result->domain = talloc_strdup(result, domain);
2992 if ((result->user_name == NULL) || (result->domain == NULL)) {
2993 status = NT_STATUS_NO_MEMORY;
2997 status = ntlmssp_client_start(NULL,
3000 lp_client_ntlmv2_auth(),
3001 &result->a_u.ntlmssp_state);
3002 if (!NT_STATUS_IS_OK(status)) {
3006 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3008 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3009 if (!NT_STATUS_IS_OK(status)) {
3013 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3014 if (!NT_STATUS_IS_OK(status)) {
3018 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3019 if (!NT_STATUS_IS_OK(status)) {
3024 * Turn off sign+seal to allow selected auth level to turn it back on.
3026 result->a_u.ntlmssp_state->neg_flags &=
3027 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3029 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3030 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3031 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3032 result->a_u.ntlmssp_state->neg_flags
3033 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3037 return NT_STATUS_OK;
3040 TALLOC_FREE(result);
3044 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3045 enum dcerpc_AuthLevel auth_level,
3046 struct netlogon_creds_CredentialState *creds,
3047 struct cli_pipe_auth_data **presult)
3049 struct cli_pipe_auth_data *result;
3051 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3052 if (result == NULL) {
3053 return NT_STATUS_NO_MEMORY;
3056 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3057 result->auth_level = auth_level;
3059 result->user_name = talloc_strdup(result, "");
3060 result->domain = talloc_strdup(result, domain);
3061 if ((result->user_name == NULL) || (result->domain == NULL)) {
3065 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3066 if (result->a_u.schannel_auth == NULL) {
3070 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3071 result->a_u.schannel_auth->seq_num = 0;
3072 result->a_u.schannel_auth->initiator = true;
3073 result->a_u.schannel_auth->creds = creds;
3076 return NT_STATUS_OK;
3079 TALLOC_FREE(result);
3080 return NT_STATUS_NO_MEMORY;
3084 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3086 data_blob_free(&auth->session_key);
3091 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3092 enum dcerpc_AuthLevel auth_level,
3093 const char *service_princ,
3094 const char *username,
3095 const char *password,
3096 struct cli_pipe_auth_data **presult)
3099 struct cli_pipe_auth_data *result;
3101 if ((username != NULL) && (password != NULL)) {
3102 int ret = kerberos_kinit_password(username, password, 0, NULL);
3104 return NT_STATUS_ACCESS_DENIED;
3108 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3109 if (result == NULL) {
3110 return NT_STATUS_NO_MEMORY;
3113 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3114 result->auth_level = auth_level;
3117 * Username / domain need fixing!
3119 result->user_name = talloc_strdup(result, "");
3120 result->domain = talloc_strdup(result, "");
3121 if ((result->user_name == NULL) || (result->domain == NULL)) {
3125 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3126 result, struct kerberos_auth_struct);
3127 if (result->a_u.kerberos_auth == NULL) {
3130 talloc_set_destructor(result->a_u.kerberos_auth,
3131 cli_auth_kerberos_data_destructor);
3133 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3134 result, service_princ);
3135 if (result->a_u.kerberos_auth->service_principal == NULL) {
3140 return NT_STATUS_OK;
3143 TALLOC_FREE(result);
3144 return NT_STATUS_NO_MEMORY;
3146 return NT_STATUS_NOT_SUPPORTED;
3151 * Create an rpc pipe client struct, connecting to a tcp port.
3153 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3155 const struct ndr_syntax_id *abstract_syntax,
3156 struct rpc_pipe_client **presult)
3158 struct rpc_pipe_client *result;
3159 struct sockaddr_storage addr;
3163 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3164 if (result == NULL) {
3165 return NT_STATUS_NO_MEMORY;
3168 result->abstract_syntax = *abstract_syntax;
3169 result->transfer_syntax = ndr_transfer_syntax;
3170 result->dispatch = cli_do_rpc_ndr;
3171 result->dispatch_send = cli_do_rpc_ndr_send;
3172 result->dispatch_recv = cli_do_rpc_ndr_recv;
3174 result->desthost = talloc_strdup(result, host);
3175 result->srv_name_slash = talloc_asprintf_strupper_m(
3176 result, "\\\\%s", result->desthost);
3177 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3178 status = NT_STATUS_NO_MEMORY;
3182 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3183 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3185 if (!resolve_name(host, &addr, 0, false)) {
3186 status = NT_STATUS_NOT_FOUND;
3190 status = open_socket_out(&addr, port, 60, &fd);
3191 if (!NT_STATUS_IS_OK(status)) {
3194 set_socket_options(fd, lp_socket_options());
3196 status = rpc_transport_sock_init(result, fd, &result->transport);
3197 if (!NT_STATUS_IS_OK(status)) {
3202 result->transport->transport = NCACN_IP_TCP;
3205 return NT_STATUS_OK;
3208 TALLOC_FREE(result);
3213 * Determine the tcp port on which a dcerpc interface is listening
3214 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3217 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3218 const struct ndr_syntax_id *abstract_syntax,
3222 struct rpc_pipe_client *epm_pipe = NULL;
3223 struct cli_pipe_auth_data *auth = NULL;
3224 struct dcerpc_binding *map_binding = NULL;
3225 struct dcerpc_binding *res_binding = NULL;
3226 struct epm_twr_t *map_tower = NULL;
3227 struct epm_twr_t *res_towers = NULL;
3228 struct policy_handle *entry_handle = NULL;
3229 uint32_t num_towers = 0;
3230 uint32_t max_towers = 1;
3231 struct epm_twr_p_t towers;
3232 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3234 if (pport == NULL) {
3235 status = NT_STATUS_INVALID_PARAMETER;
3239 /* open the connection to the endpoint mapper */
3240 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3241 &ndr_table_epmapper.syntax_id,
3244 if (!NT_STATUS_IS_OK(status)) {
3248 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3249 if (!NT_STATUS_IS_OK(status)) {
3253 status = rpc_pipe_bind(epm_pipe, auth);
3254 if (!NT_STATUS_IS_OK(status)) {
3258 /* create tower for asking the epmapper */
3260 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3261 if (map_binding == NULL) {
3262 status = NT_STATUS_NO_MEMORY;
3266 map_binding->transport = NCACN_IP_TCP;
3267 map_binding->object = *abstract_syntax;
3268 map_binding->host = host; /* needed? */
3269 map_binding->endpoint = "0"; /* correct? needed? */
3271 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3272 if (map_tower == NULL) {
3273 status = NT_STATUS_NO_MEMORY;
3277 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3278 &(map_tower->tower));
3279 if (!NT_STATUS_IS_OK(status)) {
3283 /* allocate further parameters for the epm_Map call */
3285 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3286 if (res_towers == NULL) {
3287 status = NT_STATUS_NO_MEMORY;
3290 towers.twr = res_towers;
3292 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3293 if (entry_handle == NULL) {
3294 status = NT_STATUS_NO_MEMORY;
3298 /* ask the endpoint mapper for the port */
3300 status = rpccli_epm_Map(epm_pipe,
3302 CONST_DISCARD(struct GUID *,
3303 &(abstract_syntax->uuid)),
3310 if (!NT_STATUS_IS_OK(status)) {
3314 if (num_towers != 1) {
3315 status = NT_STATUS_UNSUCCESSFUL;
3319 /* extract the port from the answer */
3321 status = dcerpc_binding_from_tower(tmp_ctx,
3322 &(towers.twr->tower),
3324 if (!NT_STATUS_IS_OK(status)) {
3328 /* are further checks here necessary? */
3329 if (res_binding->transport != NCACN_IP_TCP) {
3330 status = NT_STATUS_UNSUCCESSFUL;
3334 *pport = (uint16_t)atoi(res_binding->endpoint);
3337 TALLOC_FREE(tmp_ctx);
3342 * Create a rpc pipe client struct, connecting to a host via tcp.
3343 * The port is determined by asking the endpoint mapper on the given
3346 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3347 const struct ndr_syntax_id *abstract_syntax,
3348 struct rpc_pipe_client **presult)
3353 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3354 if (!NT_STATUS_IS_OK(status)) {
3358 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3359 abstract_syntax, presult);
3362 /********************************************************************
3363 Create a rpc pipe client struct, connecting to a unix domain socket
3364 ********************************************************************/
3365 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3366 const struct ndr_syntax_id *abstract_syntax,
3367 struct rpc_pipe_client **presult)
3369 struct rpc_pipe_client *result;
3370 struct sockaddr_un addr;
3374 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3375 if (result == NULL) {
3376 return NT_STATUS_NO_MEMORY;
3379 result->abstract_syntax = *abstract_syntax;
3380 result->transfer_syntax = ndr_transfer_syntax;
3381 result->dispatch = cli_do_rpc_ndr;
3382 result->dispatch_send = cli_do_rpc_ndr_send;
3383 result->dispatch_recv = cli_do_rpc_ndr_recv;
3385 result->desthost = get_myname(result);
3386 result->srv_name_slash = talloc_asprintf_strupper_m(
3387 result, "\\\\%s", result->desthost);
3388 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3389 status = NT_STATUS_NO_MEMORY;
3393 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3394 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3396 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3398 status = map_nt_error_from_unix(errno);
3403 addr.sun_family = AF_UNIX;
3404 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3406 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3407 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3410 return map_nt_error_from_unix(errno);
3413 status = rpc_transport_sock_init(result, fd, &result->transport);
3414 if (!NT_STATUS_IS_OK(status)) {
3419 result->transport->transport = NCALRPC;
3422 return NT_STATUS_OK;
3425 TALLOC_FREE(result);
3429 struct rpc_pipe_client_np_ref {
3430 struct cli_state *cli;
3431 struct rpc_pipe_client *pipe;
3434 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3436 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3440 /****************************************************************************
3441 Open a named pipe over SMB to a remote server.
3443 * CAVEAT CALLER OF THIS FUNCTION:
3444 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3445 * so be sure that this function is called AFTER any structure (vs pointer)
3446 * assignment of the cli. In particular, libsmbclient does structure
3447 * assignments of cli, which invalidates the data in the returned
3448 * rpc_pipe_client if this function is called before the structure assignment
3451 ****************************************************************************/
3453 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3454 const struct ndr_syntax_id *abstract_syntax,
3455 struct rpc_pipe_client **presult)
3457 struct rpc_pipe_client *result;
3459 struct rpc_pipe_client_np_ref *np_ref;
3461 /* sanity check to protect against crashes */
3464 return NT_STATUS_INVALID_HANDLE;
3467 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3468 if (result == NULL) {
3469 return NT_STATUS_NO_MEMORY;
3472 result->abstract_syntax = *abstract_syntax;
3473 result->transfer_syntax = ndr_transfer_syntax;
3474 result->dispatch = cli_do_rpc_ndr;
3475 result->dispatch_send = cli_do_rpc_ndr_send;
3476 result->dispatch_recv = cli_do_rpc_ndr_recv;
3477 result->desthost = talloc_strdup(result, cli->desthost);
3478 result->srv_name_slash = talloc_asprintf_strupper_m(
3479 result, "\\\\%s", result->desthost);
3481 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3482 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3484 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3485 TALLOC_FREE(result);
3486 return NT_STATUS_NO_MEMORY;
3489 status = rpc_transport_np_init(result, cli, abstract_syntax,
3490 &result->transport);
3491 if (!NT_STATUS_IS_OK(status)) {
3492 TALLOC_FREE(result);
3496 result->transport->transport = NCACN_NP;
3498 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3499 if (np_ref == NULL) {
3500 TALLOC_FREE(result);
3501 return NT_STATUS_NO_MEMORY;
3504 np_ref->pipe = result;
3506 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3507 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3510 return NT_STATUS_OK;
3513 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3514 struct rpc_cli_smbd_conn *conn,
3515 const struct ndr_syntax_id *syntax,
3516 struct rpc_pipe_client **presult)
3518 struct rpc_pipe_client *result;
3519 struct cli_pipe_auth_data *auth;
3522 result = talloc(mem_ctx, struct rpc_pipe_client);
3523 if (result == NULL) {
3524 return NT_STATUS_NO_MEMORY;
3526 result->abstract_syntax = *syntax;
3527 result->transfer_syntax = ndr_transfer_syntax;
3528 result->dispatch = cli_do_rpc_ndr;
3529 result->dispatch_send = cli_do_rpc_ndr_send;
3530 result->dispatch_recv = cli_do_rpc_ndr_recv;
3531 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3532 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3534 result->desthost = talloc_strdup(result, global_myname());
3535 result->srv_name_slash = talloc_asprintf_strupper_m(
3536 result, "\\\\%s", global_myname());
3537 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3538 TALLOC_FREE(result);
3539 return NT_STATUS_NO_MEMORY;
3542 status = rpc_transport_smbd_init(result, conn, syntax,
3543 &result->transport);
3544 if (!NT_STATUS_IS_OK(status)) {
3545 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3546 nt_errstr(status)));
3547 TALLOC_FREE(result);
3551 status = rpccli_anon_bind_data(result, &auth);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3554 nt_errstr(status)));
3555 TALLOC_FREE(result);
3559 status = rpc_pipe_bind(result, auth);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3562 TALLOC_FREE(result);
3566 result->transport->transport = NCACN_INTERNAL;
3569 return NT_STATUS_OK;
3572 /****************************************************************************
3573 Open a pipe to a remote server.
3574 ****************************************************************************/
3576 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3577 enum dcerpc_transport_t transport,
3578 const struct ndr_syntax_id *interface,
3579 struct rpc_pipe_client **presult)
3581 switch (transport) {
3583 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3586 return rpc_pipe_open_np(cli, interface, presult);
3588 return NT_STATUS_NOT_IMPLEMENTED;
3592 /****************************************************************************
3593 Open a named pipe to an SMB server and bind anonymously.
3594 ****************************************************************************/
3596 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3597 enum dcerpc_transport_t transport,
3598 const struct ndr_syntax_id *interface,
3599 struct rpc_pipe_client **presult)
3601 struct rpc_pipe_client *result;
3602 struct cli_pipe_auth_data *auth;
3605 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3606 if (!NT_STATUS_IS_OK(status)) {
3610 status = rpccli_anon_bind_data(result, &auth);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3613 nt_errstr(status)));
3614 TALLOC_FREE(result);
3619 * This is a bit of an abstraction violation due to the fact that an
3620 * anonymous bind on an authenticated SMB inherits the user/domain
3621 * from the enclosing SMB creds
3624 TALLOC_FREE(auth->user_name);
3625 TALLOC_FREE(auth->domain);
3627 auth->user_name = talloc_strdup(auth, cli->user_name);
3628 auth->domain = talloc_strdup(auth, cli->domain);
3629 auth->user_session_key = data_blob_talloc(auth,
3630 cli->user_session_key.data,
3631 cli->user_session_key.length);
3633 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3634 TALLOC_FREE(result);
3635 return NT_STATUS_NO_MEMORY;
3638 status = rpc_pipe_bind(result, auth);
3639 if (!NT_STATUS_IS_OK(status)) {
3641 if (ndr_syntax_id_equal(interface,
3642 &ndr_table_dssetup.syntax_id)) {
3643 /* non AD domains just don't have this pipe, avoid
3644 * level 0 statement in that case - gd */
3647 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3648 "%s failed with error %s\n",
3649 get_pipe_name_from_syntax(talloc_tos(), interface),
3650 nt_errstr(status) ));
3651 TALLOC_FREE(result);
3655 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3656 "%s and bound anonymously.\n",
3657 get_pipe_name_from_syntax(talloc_tos(), interface),
3661 return NT_STATUS_OK;
3664 /****************************************************************************
3665 ****************************************************************************/
3667 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3668 const struct ndr_syntax_id *interface,
3669 struct rpc_pipe_client **presult)
3671 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3672 interface, presult);
3675 /****************************************************************************
3676 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3677 ****************************************************************************/
3679 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3680 const struct ndr_syntax_id *interface,
3681 enum dcerpc_transport_t transport,
3682 enum pipe_auth_type auth_type,
3683 enum dcerpc_AuthLevel auth_level,
3685 const char *username,
3686 const char *password,
3687 struct rpc_pipe_client **presult)
3689 struct rpc_pipe_client *result;
3690 struct cli_pipe_auth_data *auth;
3693 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3694 if (!NT_STATUS_IS_OK(status)) {
3698 status = rpccli_ntlmssp_bind_data(
3699 result, auth_type, auth_level, domain, username,
3701 if (!NT_STATUS_IS_OK(status)) {
3702 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3703 nt_errstr(status)));
3707 status = rpc_pipe_bind(result, auth);
3708 if (!NT_STATUS_IS_OK(status)) {
3709 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3710 nt_errstr(status) ));
3714 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3715 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3716 get_pipe_name_from_syntax(talloc_tos(), interface),
3717 cli->desthost, domain, username ));
3720 return NT_STATUS_OK;
3724 TALLOC_FREE(result);
3728 /****************************************************************************
3730 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3731 ****************************************************************************/
3733 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3734 const struct ndr_syntax_id *interface,
3735 enum dcerpc_transport_t transport,
3736 enum dcerpc_AuthLevel auth_level,
3738 const char *username,
3739 const char *password,
3740 struct rpc_pipe_client **presult)
3742 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3745 PIPE_AUTH_TYPE_NTLMSSP,
3753 /****************************************************************************
3755 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3756 ****************************************************************************/
3758 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3759 const struct ndr_syntax_id *interface,
3760 enum dcerpc_transport_t transport,
3761 enum dcerpc_AuthLevel auth_level,
3763 const char *username,
3764 const char *password,
3765 struct rpc_pipe_client **presult)
3767 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3770 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3778 /****************************************************************************
3779 Get a the schannel session key out of an already opened netlogon pipe.
3780 ****************************************************************************/
3781 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3782 struct cli_state *cli,
3786 enum netr_SchannelType sec_chan_type = 0;
3787 unsigned char machine_pwd[16];
3788 const char *machine_account;
3791 /* Get the machine account credentials from secrets.tdb. */
3792 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3795 DEBUG(0, ("get_schannel_session_key: could not fetch "
3796 "trust account password for domain '%s'\n",
3798 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3801 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3802 cli->desthost, /* server name */
3803 domain, /* domain */
3804 global_myname(), /* client name */
3805 machine_account, /* machine account name */
3810 if (!NT_STATUS_IS_OK(status)) {
3811 DEBUG(3, ("get_schannel_session_key_common: "
3812 "rpccli_netlogon_setup_creds failed with result %s "
3813 "to server %s, domain %s, machine account %s.\n",
3814 nt_errstr(status), cli->desthost, domain,
3819 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3820 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3822 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3825 return NT_STATUS_OK;;
3828 /****************************************************************************
3829 Open a netlogon pipe and get the schannel session key.
3830 Now exposed to external callers.
3831 ****************************************************************************/
3834 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3837 struct rpc_pipe_client **presult)
3839 struct rpc_pipe_client *netlogon_pipe = NULL;
3842 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3844 if (!NT_STATUS_IS_OK(status)) {
3848 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3850 if (!NT_STATUS_IS_OK(status)) {
3851 TALLOC_FREE(netlogon_pipe);
3855 *presult = netlogon_pipe;
3856 return NT_STATUS_OK;
3859 /****************************************************************************
3861 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3862 using session_key. sign and seal.
3864 The *pdc will be stolen onto this new pipe
3865 ****************************************************************************/
3867 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3868 const struct ndr_syntax_id *interface,
3869 enum dcerpc_transport_t transport,
3870 enum dcerpc_AuthLevel auth_level,
3872 struct netlogon_creds_CredentialState **pdc,
3873 struct rpc_pipe_client **presult)
3875 struct rpc_pipe_client *result;
3876 struct cli_pipe_auth_data *auth;
3879 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3880 if (!NT_STATUS_IS_OK(status)) {
3884 status = rpccli_schannel_bind_data(result, domain, auth_level,
3886 if (!NT_STATUS_IS_OK(status)) {
3887 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3888 nt_errstr(status)));
3889 TALLOC_FREE(result);
3893 status = rpc_pipe_bind(result, auth);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3896 "cli_rpc_pipe_bind failed with error %s\n",
3897 nt_errstr(status) ));
3898 TALLOC_FREE(result);
3903 * The credentials on a new netlogon pipe are the ones we are passed
3904 * in - reference them in
3906 result->dc = talloc_move(result, pdc);
3908 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3909 "for domain %s and bound using schannel.\n",
3910 get_pipe_name_from_syntax(talloc_tos(), interface),
3911 cli->desthost, domain ));
3914 return NT_STATUS_OK;
3917 /****************************************************************************
3918 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3919 Fetch the session key ourselves using a temporary netlogon pipe. This
3920 version uses an ntlmssp auth bound netlogon pipe to get the key.
3921 ****************************************************************************/
3923 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3925 const char *username,
3926 const char *password,
3928 struct rpc_pipe_client **presult)
3930 struct rpc_pipe_client *netlogon_pipe = NULL;
3933 status = cli_rpc_pipe_open_spnego_ntlmssp(
3934 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3935 DCERPC_AUTH_LEVEL_PRIVACY,
3936 domain, username, password, &netlogon_pipe);
3937 if (!NT_STATUS_IS_OK(status)) {
3941 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3943 if (!NT_STATUS_IS_OK(status)) {
3944 TALLOC_FREE(netlogon_pipe);
3948 *presult = netlogon_pipe;
3949 return NT_STATUS_OK;
3952 /****************************************************************************
3953 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3954 Fetch the session key ourselves using a temporary netlogon pipe. This version
3955 uses an ntlmssp bind to get the session key.
3956 ****************************************************************************/
3958 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3959 const struct ndr_syntax_id *interface,
3960 enum dcerpc_transport_t transport,
3961 enum dcerpc_AuthLevel auth_level,
3963 const char *username,
3964 const char *password,
3965 struct rpc_pipe_client **presult)
3967 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3968 struct rpc_pipe_client *netlogon_pipe = NULL;
3969 struct rpc_pipe_client *result = NULL;
3972 status = get_schannel_session_key_auth_ntlmssp(
3973 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3976 "key from server %s for domain %s.\n",
3977 cli->desthost, domain ));
3981 status = cli_rpc_pipe_open_schannel_with_key(
3982 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3985 /* Now we've bound using the session key we can close the netlog pipe. */
3986 TALLOC_FREE(netlogon_pipe);
3988 if (NT_STATUS_IS_OK(status)) {
3994 /****************************************************************************
3995 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3996 Fetch the session key ourselves using a temporary netlogon pipe.
3997 ****************************************************************************/
3999 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4000 const struct ndr_syntax_id *interface,
4001 enum dcerpc_transport_t transport,
4002 enum dcerpc_AuthLevel auth_level,
4004 struct rpc_pipe_client **presult)
4006 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4007 struct rpc_pipe_client *netlogon_pipe = NULL;
4008 struct rpc_pipe_client *result = NULL;
4011 status = get_schannel_session_key(cli, domain, &neg_flags,
4013 if (!NT_STATUS_IS_OK(status)) {
4014 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4015 "key from server %s for domain %s.\n",
4016 cli->desthost, domain ));
4020 status = cli_rpc_pipe_open_schannel_with_key(
4021 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4024 /* Now we've bound using the session key we can close the netlog pipe. */
4025 TALLOC_FREE(netlogon_pipe);
4027 if (NT_STATUS_IS_OK(status)) {
4034 /****************************************************************************
4035 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4036 The idea is this can be called with service_princ, username and password all
4037 NULL so long as the caller has a TGT.
4038 ****************************************************************************/
4040 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4041 const struct ndr_syntax_id *interface,
4042 enum dcerpc_AuthLevel auth_level,
4043 const char *service_princ,
4044 const char *username,
4045 const char *password,
4046 struct rpc_pipe_client **presult)
4049 struct rpc_pipe_client *result;
4050 struct cli_pipe_auth_data *auth;
4053 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4054 if (!NT_STATUS_IS_OK(status)) {
4058 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4059 username, password, &auth);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4062 nt_errstr(status)));
4063 TALLOC_FREE(result);
4067 status = rpc_pipe_bind(result, auth);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4070 "with error %s\n", nt_errstr(status)));
4071 TALLOC_FREE(result);
4076 return NT_STATUS_OK;
4078 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4079 return NT_STATUS_NOT_IMPLEMENTED;
4083 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4084 struct rpc_pipe_client *cli,
4085 DATA_BLOB *session_key)
4087 if (!session_key || !cli) {
4088 return NT_STATUS_INVALID_PARAMETER;
4092 return NT_STATUS_INVALID_PARAMETER;
4095 switch (cli->auth->auth_type) {
4096 case PIPE_AUTH_TYPE_SCHANNEL:
4097 *session_key = data_blob_talloc(mem_ctx,
4098 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4100 case PIPE_AUTH_TYPE_NTLMSSP:
4101 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4102 *session_key = data_blob_talloc(mem_ctx,
4103 cli->auth->a_u.ntlmssp_state->session_key.data,
4104 cli->auth->a_u.ntlmssp_state->session_key.length);
4106 case PIPE_AUTH_TYPE_KRB5:
4107 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4108 *session_key = data_blob_talloc(mem_ctx,
4109 cli->auth->a_u.kerberos_auth->session_key.data,
4110 cli->auth->a_u.kerberos_auth->session_key.length);
4112 case PIPE_AUTH_TYPE_NONE:
4113 *session_key = data_blob_talloc(mem_ctx,
4114 cli->auth->user_session_key.data,
4115 cli->auth->user_session_key.length);
4118 return NT_STATUS_NO_USER_SESSION_KEY;
4121 return NT_STATUS_OK;