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;
274 * Realloc pdu to have a least "size" bytes
277 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
281 if (prs_data_size(pdu) >= size) {
285 extra_size = size - prs_data_size(pdu);
287 if (!prs_force_grow(pdu, extra_size)) {
288 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
289 "%d bytes.\n", (int)extra_size));
293 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
294 (int)extra_size, prs_data_size(pdu)));
298 /*******************************************************************
299 Use SMBreadX to get rest of one fragment's worth of rpc data.
300 Reads the whole size or give an error message
301 ********************************************************************/
303 struct rpc_read_state {
304 struct event_context *ev;
305 struct rpc_cli_transport *transport;
311 static void rpc_read_done(struct tevent_req *subreq);
313 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
314 struct event_context *ev,
315 struct rpc_cli_transport *transport,
316 uint8_t *data, size_t size)
318 struct tevent_req *req, *subreq;
319 struct rpc_read_state *state;
321 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
326 state->transport = transport;
331 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
333 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
335 if (subreq == NULL) {
338 tevent_req_set_callback(subreq, rpc_read_done, req);
346 static void rpc_read_done(struct tevent_req *subreq)
348 struct tevent_req *req = tevent_req_callback_data(
349 subreq, struct tevent_req);
350 struct rpc_read_state *state = tevent_req_data(
351 req, struct rpc_read_state);
355 status = state->transport->read_recv(subreq, &received);
357 if (!NT_STATUS_IS_OK(status)) {
358 tevent_req_nterror(req, status);
362 state->num_read += received;
363 if (state->num_read == state->size) {
364 tevent_req_done(req);
368 subreq = state->transport->read_send(state, state->ev,
369 state->data + state->num_read,
370 state->size - state->num_read,
371 state->transport->priv);
372 if (tevent_req_nomem(subreq, req)) {
375 tevent_req_set_callback(subreq, rpc_read_done, req);
378 static NTSTATUS rpc_read_recv(struct tevent_req *req)
380 return tevent_req_simple_recv_ntstatus(req);
383 struct rpc_write_state {
384 struct event_context *ev;
385 struct rpc_cli_transport *transport;
391 static void rpc_write_done(struct tevent_req *subreq);
393 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
394 struct event_context *ev,
395 struct rpc_cli_transport *transport,
396 const uint8_t *data, size_t size)
398 struct tevent_req *req, *subreq;
399 struct rpc_write_state *state;
401 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
406 state->transport = transport;
409 state->num_written = 0;
411 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
413 subreq = transport->write_send(state, ev, data, size, transport->priv);
414 if (subreq == NULL) {
417 tevent_req_set_callback(subreq, rpc_write_done, req);
424 static void rpc_write_done(struct tevent_req *subreq)
426 struct tevent_req *req = tevent_req_callback_data(
427 subreq, struct tevent_req);
428 struct rpc_write_state *state = tevent_req_data(
429 req, struct rpc_write_state);
433 status = state->transport->write_recv(subreq, &written);
435 if (!NT_STATUS_IS_OK(status)) {
436 tevent_req_nterror(req, status);
440 state->num_written += written;
442 if (state->num_written == state->size) {
443 tevent_req_done(req);
447 subreq = state->transport->write_send(state, state->ev,
448 state->data + state->num_written,
449 state->size - state->num_written,
450 state->transport->priv);
451 if (tevent_req_nomem(subreq, req)) {
454 tevent_req_set_callback(subreq, rpc_write_done, req);
457 static NTSTATUS rpc_write_recv(struct tevent_req *req)
459 return tevent_req_simple_recv_ntstatus(req);
463 /****************************************************************************
464 Try and get a PDU's worth of data from current_pdu. If not, then read more
466 ****************************************************************************/
468 struct get_complete_frag_state {
469 struct event_context *ev;
470 struct rpc_pipe_client *cli;
475 static void get_complete_frag_got_header(struct tevent_req *subreq);
476 static void get_complete_frag_got_rest(struct tevent_req *subreq);
478 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
479 struct event_context *ev,
480 struct rpc_pipe_client *cli,
483 struct tevent_req *req, *subreq;
484 struct get_complete_frag_state *state;
489 req = tevent_req_create(mem_ctx, &state,
490 struct get_complete_frag_state);
496 state->frag_len = RPC_HEADER_LEN;
499 pdu_len = prs_data_size(pdu);
500 if (pdu_len < RPC_HEADER_LEN) {
501 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
502 status = NT_STATUS_NO_MEMORY;
505 subreq = rpc_read_send(
507 state->cli->transport,
508 (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
509 RPC_HEADER_LEN - pdu_len);
510 if (subreq == NULL) {
511 status = NT_STATUS_NO_MEMORY;
514 tevent_req_set_callback(subreq, get_complete_frag_got_header,
519 blob = data_blob_const(prs_data_p(state->pdu), pdu_len);
520 state->frag_len = dcerpc_get_frag_length(&blob);
523 * Ensure we have frag_len bytes of data.
525 if (pdu_len < state->frag_len) {
526 if (!rpc_grow_buffer(pdu, state->frag_len)) {
527 status = NT_STATUS_NO_MEMORY;
530 subreq = rpc_read_send(state, state->ev,
531 state->cli->transport,
532 (uint8_t *)(prs_data_p(pdu) + pdu_len),
533 state->frag_len - pdu_len);
534 if (subreq == NULL) {
535 status = NT_STATUS_NO_MEMORY;
538 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
543 status = NT_STATUS_OK;
545 if (NT_STATUS_IS_OK(status)) {
546 tevent_req_done(req);
548 tevent_req_nterror(req, status);
550 return tevent_req_post(req, ev);
553 static void get_complete_frag_got_header(struct tevent_req *subreq)
555 struct tevent_req *req = tevent_req_callback_data(
556 subreq, struct tevent_req);
557 struct get_complete_frag_state *state = tevent_req_data(
558 req, struct get_complete_frag_state);
562 status = rpc_read_recv(subreq);
564 if (!NT_STATUS_IS_OK(status)) {
565 tevent_req_nterror(req, status);
569 pdu = data_blob_const(prs_data_p(state->pdu),
570 prs_data_size(state->pdu));
571 state->frag_len = dcerpc_get_frag_length(&pdu);
573 if (!rpc_grow_buffer(state->pdu, state->frag_len)) {
574 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
579 * We're here in this piece of code because we've read exactly
580 * RPC_HEADER_LEN bytes into state->pdu.
583 subreq = rpc_read_send(
584 state, state->ev, state->cli->transport,
585 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
586 state->frag_len - RPC_HEADER_LEN);
587 if (tevent_req_nomem(subreq, req)) {
590 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
593 static void get_complete_frag_got_rest(struct tevent_req *subreq)
595 struct tevent_req *req = tevent_req_callback_data(
596 subreq, struct tevent_req);
599 status = rpc_read_recv(subreq);
601 if (!NT_STATUS_IS_OK(status)) {
602 tevent_req_nterror(req, status);
605 tevent_req_done(req);
608 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
610 return tevent_req_simple_recv_ntstatus(req);
613 /****************************************************************************
614 NTLMSSP specific sign/seal.
615 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
616 In fact I should probably abstract these into identical pieces of code... JRA.
617 ****************************************************************************/
619 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli,
620 struct ncacn_packet *pkt,
621 prs_struct *current_pdu,
622 uint8 *p_ss_padding_len)
624 uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu);
625 struct dcerpc_auth auth_info;
629 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
630 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
634 if (!cli->auth->a_u.ntlmssp_state) {
635 return NT_STATUS_INVALID_PARAMETER;
638 /* Ensure there's enough data for an authenticated response. */
639 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
640 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
641 + DCERPC_AUTH_TRAILER_LENGTH
642 + pkt->auth_length)) {
643 DEBUG(0, ("auth_len %u is too long.\n",
644 (unsigned int)pkt->auth_length));
645 return NT_STATUS_BUFFER_TOO_SMALL;
648 /* get the auth blob at the end of the packet */
649 blob = data_blob_const(frag_data + pkt->frag_length
650 - DCERPC_AUTH_TRAILER_LENGTH
652 DCERPC_AUTH_TRAILER_LENGTH
655 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info);
656 if (!NT_STATUS_IS_OK(status)) {
657 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
661 /* Ensure auth_pad_len fits into the packet. */
662 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
663 + auth_info.auth_pad_length
664 + DCERPC_AUTH_TRAILER_LENGTH
665 + pkt->auth_length) {
666 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
667 "too large (%u), auth_len (%u), frag_len = (%u).\n",
668 (unsigned int)auth_info.auth_pad_length,
669 (unsigned int)pkt->auth_length,
670 (unsigned int)pkt->frag_length));
671 return NT_STATUS_BUFFER_TOO_SMALL;
675 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
676 * after the RPC header.
677 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
678 * functions as NTLMv2 checks the rpc headers also.
681 switch (cli->auth->auth_level) {
682 case DCERPC_AUTH_LEVEL_PRIVACY:
683 /* Data is encrypted. */
684 status = ntlmssp_unseal_packet(
685 cli->auth->a_u.ntlmssp_state,
686 &frag_data[DCERPC_RESPONSE_LENGTH],
688 - DCERPC_RESPONSE_LENGTH
689 - DCERPC_AUTH_TRAILER_LENGTH
692 pkt->frag_length - pkt->auth_length,
693 &auth_info.credentials);
694 if (!NT_STATUS_IS_OK(status)) {
695 DEBUG(0, ("failed to unseal packet from %s."
697 rpccli_pipe_txt(talloc_tos(), cli),
703 case DCERPC_AUTH_LEVEL_INTEGRITY:
704 /* Data is signed. */
705 status = ntlmssp_check_packet(
706 cli->auth->a_u.ntlmssp_state,
707 &frag_data[DCERPC_RESPONSE_LENGTH],
709 - DCERPC_RESPONSE_LENGTH
710 - DCERPC_AUTH_TRAILER_LENGTH
713 pkt->frag_length - pkt->auth_length,
714 &auth_info.credentials);
715 if (!NT_STATUS_IS_OK(status)) {
716 DEBUG(0, ("check signing failed on packet from %s."
718 rpccli_pipe_txt(talloc_tos(), cli),
725 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
726 "auth level %d\n", cli->auth->auth_level));
727 return NT_STATUS_INVALID_INFO_CLASS;
731 * Remember the padding length. We must remove it from the real data
732 * stream once the sign/seal is done.
735 *p_ss_padding_len = auth_info.auth_pad_length;
740 /****************************************************************************
741 schannel specific sign/seal.
742 ****************************************************************************/
744 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli,
745 struct ncacn_packet *pkt,
746 prs_struct *current_pdu,
747 uint8 *p_ss_padding_len)
749 uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu);
750 struct dcerpc_auth auth_info;
754 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
755 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
759 if (pkt->auth_length < SCHANNEL_SIG_SIZE) {
760 DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length));
761 return NT_STATUS_INVALID_PARAMETER;
764 if (!cli->auth->a_u.schannel_auth) {
765 return NT_STATUS_INVALID_PARAMETER;
768 /* Ensure there's enough data for an authenticated response. */
769 if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
770 (pkt->frag_length < DCERPC_RESPONSE_LENGTH
771 + DCERPC_AUTH_TRAILER_LENGTH
772 + pkt->auth_length)) {
773 DEBUG(0, ("auth_len %u is too long.\n",
774 (unsigned int)pkt->auth_length));
775 return NT_STATUS_INVALID_PARAMETER;
778 /* get the auth blob at the end of the packet */
779 blob = data_blob_const(frag_data + pkt->frag_length
780 - DCERPC_AUTH_TRAILER_LENGTH
782 DCERPC_AUTH_TRAILER_LENGTH
786 status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info);
787 if (!NT_STATUS_IS_OK(status)) {
788 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
792 /* Ensure auth_pad_len fits into the packet. */
793 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
794 + auth_info.auth_pad_length
795 + DCERPC_AUTH_TRAILER_LENGTH
796 + pkt->auth_length) {
797 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
798 "too large (%u), auth_len (%u), frag_len = (%u).\n",
799 (unsigned int)auth_info.auth_pad_length,
800 (unsigned int)pkt->auth_length,
801 (unsigned int)pkt->frag_length));
802 return NT_STATUS_BUFFER_TOO_SMALL;
805 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
806 DEBUG(0, ("Invalid auth info %d on schannel\n",
807 auth_info.auth_type));
808 return NT_STATUS_BUFFER_TOO_SMALL;
811 if (DEBUGLEVEL >= 10) {
812 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_info.credentials);
815 switch (cli->auth->auth_level) {
816 case DCERPC_AUTH_LEVEL_PRIVACY:
817 status = netsec_incoming_packet(
818 cli->auth->a_u.schannel_auth,
821 &frag_data[DCERPC_RESPONSE_LENGTH],
823 - DCERPC_RESPONSE_LENGTH
824 - DCERPC_AUTH_TRAILER_LENGTH
826 &auth_info.credentials);
828 case DCERPC_AUTH_LEVEL_INTEGRITY:
829 status = netsec_incoming_packet(
830 cli->auth->a_u.schannel_auth,
833 &frag_data[DCERPC_RESPONSE_LENGTH],
835 - DCERPC_RESPONSE_LENGTH
836 - DCERPC_AUTH_TRAILER_LENGTH
838 &auth_info.credentials);
841 status = NT_STATUS_INTERNAL_ERROR;
845 if (!NT_STATUS_IS_OK(status)) {
846 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
847 "Connection to %s (%s).\n",
848 rpccli_pipe_txt(talloc_tos(), cli),
850 return NT_STATUS_INVALID_PARAMETER;
854 * Remember the padding length. We must remove it from the real data
855 * stream once the sign/seal is done.
858 *p_ss_padding_len = auth_info.auth_pad_length;
863 /****************************************************************************
864 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
865 ****************************************************************************/
867 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli,
868 struct ncacn_packet *pkt,
869 prs_struct *current_pdu,
870 uint8 *p_ss_padding_len)
872 NTSTATUS ret = NT_STATUS_OK;
874 /* Paranioa checks for auth_len. */
875 if (pkt->auth_length) {
876 if (pkt->auth_length > pkt->frag_length) {
877 return NT_STATUS_INVALID_PARAMETER;
880 if ((pkt->auth_length
881 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
882 < pkt->auth_length) ||
884 + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
885 < (unsigned int)DCERPC_AUTH_TRAILER_LENGTH)) {
886 /* Integer wrap attempt. */
887 return NT_STATUS_INVALID_PARAMETER;
892 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
895 switch(cli->auth->auth_type) {
896 case PIPE_AUTH_TYPE_NONE:
897 if (pkt->auth_length) {
898 DEBUG(3, ("cli_pipe_validate_rpc_response: "
899 "Connection to %s - got non-zero "
901 rpccli_pipe_txt(talloc_tos(), cli),
902 (unsigned int)pkt->auth_length));
903 return NT_STATUS_INVALID_PARAMETER;
907 case PIPE_AUTH_TYPE_NTLMSSP:
908 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
909 ret = cli_pipe_verify_ntlmssp(cli, pkt, current_pdu,
911 if (!NT_STATUS_IS_OK(ret)) {
916 case PIPE_AUTH_TYPE_SCHANNEL:
917 ret = cli_pipe_verify_schannel(cli, pkt, current_pdu,
919 if (!NT_STATUS_IS_OK(ret)) {
924 case PIPE_AUTH_TYPE_KRB5:
925 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
927 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
928 "to %s - unknown internal auth type %u.\n",
929 rpccli_pipe_txt(talloc_tos(), cli),
930 cli->auth->auth_type ));
931 return NT_STATUS_INVALID_INFO_CLASS;
937 /****************************************************************************
938 Do basic authentication checks on an incoming pdu.
939 ****************************************************************************/
941 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli,
942 struct ncacn_packet *pkt,
943 prs_struct *current_pdu,
944 uint8 expected_pkt_type,
947 prs_struct *return_data)
949 NTSTATUS ret = NT_STATUS_OK;
950 uint32 current_pdu_len = prs_data_size(current_pdu);
951 DATA_BLOB blob = data_blob_const(prs_data_p(current_pdu),
952 prs_data_size(current_pdu));
953 uint8 ss_padding_len = 0;
955 ret = dcerpc_pull_ncacn_packet(cli, &blob, pkt);
956 if (!NT_STATUS_IS_OK(ret)) {
960 /* FIXME: although we already unmarshalled the whole packet,
961 * set the offset of the pdu to right after the header
962 * until the rest of the code downstream is changed
963 * to always use the already decoded packet and not try
964 * to unmarshall bits of the packet.
966 if (!prs_set_offset(current_pdu,
967 prs_offset(current_pdu) + RPC_HEADER_LEN)) {
968 return NT_STATUS_BUFFER_TOO_SMALL;
971 if (current_pdu_len != pkt->frag_length) {
972 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
973 (unsigned int)current_pdu_len,
974 (unsigned int)pkt->frag_length));
975 return NT_STATUS_INVALID_PARAMETER;
979 * Point the return values at the real data including the RPC
980 * header. Just in case the caller wants it.
982 *ppdata = prs_data_p(current_pdu);
983 *pdata_len = current_pdu_len;
985 /* Ensure we have the correct type. */
986 switch (pkt->ptype) {
987 case DCERPC_PKT_ALTER_RESP:
988 case DCERPC_PKT_BIND_ACK:
990 /* Alter context and bind ack share the same packet definitions. */
994 case DCERPC_PKT_RESPONSE:
996 /* Here's where we deal with incoming sign/seal. */
997 ret = cli_pipe_validate_rpc_response(cli, pkt,
998 current_pdu, &ss_padding_len);
999 if (!NT_STATUS_IS_OK(ret)) {
1003 /* Point the return values at the NDR data.
1004 * Remember to remove any ss padding. */
1005 *ppdata = prs_data_p(current_pdu) + DCERPC_RESPONSE_LENGTH;
1007 if (current_pdu_len < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
1008 return NT_STATUS_BUFFER_TOO_SMALL;
1011 *pdata_len = current_pdu_len - DCERPC_RESPONSE_LENGTH - ss_padding_len;
1013 /* Remember to remove the auth footer. */
1014 if (pkt->auth_length) {
1015 /* We've already done integer wrap tests on auth_len in
1016 cli_pipe_validate_rpc_response(). */
1017 if (*pdata_len < DCERPC_AUTH_TRAILER_LENGTH
1018 + pkt->auth_length) {
1019 return NT_STATUS_BUFFER_TOO_SMALL;
1021 *pdata_len -= (DCERPC_AUTH_TRAILER_LENGTH
1022 + pkt->auth_length);
1025 DEBUG(10, ("Got pdu len %u, data_len %u, ss_len %u\n",
1026 current_pdu_len, *pdata_len, ss_padding_len));
1029 * If this is the first reply, and the allocation hint is
1030 * reasonable, try and set up the return_data parse_struct to
1034 if ((prs_data_size(return_data) == 0) &&
1035 pkt->u.response.alloc_hint &&
1036 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1037 if (!prs_set_buffer_size(return_data,
1038 pkt->u.response.alloc_hint)) {
1039 DEBUG(0, ("reply alloc hint %d too "
1040 "large to allocate\n",
1041 (int)pkt->u.response.alloc_hint));
1042 return NT_STATUS_NO_MEMORY;
1048 case DCERPC_PKT_BIND_NAK:
1049 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1050 "received from %s!\n",
1051 rpccli_pipe_txt(talloc_tos(), cli)));
1052 /* Use this for now... */
1053 return NT_STATUS_NETWORK_ACCESS_DENIED;
1055 case DCERPC_PKT_FAULT:
1057 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1058 "code %s received from %s!\n",
1059 dcerpc_errstr(talloc_tos(),
1060 pkt->u.fault.status),
1061 rpccli_pipe_txt(talloc_tos(), cli)));
1063 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
1064 return NT_STATUS_UNSUCCESSFUL;
1066 return NT_STATUS(pkt->u.fault.status);
1070 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1071 (unsigned int)pkt->ptype,
1072 rpccli_pipe_txt(talloc_tos(), cli)));
1073 return NT_STATUS_INVALID_INFO_CLASS;
1076 if (pkt->ptype != expected_pkt_type) {
1077 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1078 "got an unexpected RPC packet type - %u, not %u\n",
1079 rpccli_pipe_txt(talloc_tos(), cli),
1081 expected_pkt_type));
1082 return NT_STATUS_INVALID_INFO_CLASS;
1085 /* Do this just before return - we don't want to modify any rpc header
1086 data before now as we may have needed to do cryptographic actions on
1089 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
1090 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1091 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1092 "setting fragment first/last ON.\n"));
1093 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
1094 DCERPC_PFC_FLAG_LAST;
1097 return NT_STATUS_OK;
1100 /****************************************************************************
1101 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1102 Normally the frag_len and buffer size will match, but on the first trans
1103 reply there is a theoretical chance that buffer size > frag_len, so we must
1105 ****************************************************************************/
1107 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli,
1108 struct ncacn_packet *pkt,
1109 prs_struct *current_pdu)
1111 uint32 current_pdu_len = prs_data_size(current_pdu);
1113 if (current_pdu_len < pkt->frag_length) {
1114 return NT_STATUS_BUFFER_TOO_SMALL;
1118 if (current_pdu_len == (uint32)pkt->frag_length) {
1119 prs_mem_free(current_pdu);
1120 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1121 /* Make current_pdu dynamic with no memory. */
1122 prs_give_memory(current_pdu, 0, 0, True);
1123 return NT_STATUS_OK;
1127 * Oh no ! More data in buffer than we processed in current pdu.
1128 * This shouldn't happen, we only read exactly pkt->frag_length.
1129 * Something is wrong here, throw an error.
1132 DEBUG(0, ("Data buffer size (%u) and pkt->frag_length (%u) differ\n!",
1133 (unsigned)current_pdu_len, (unsigned)pkt->frag_length));
1134 return NT_STATUS_INVALID_BUFFER_SIZE;
1137 /****************************************************************************
1138 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1139 ****************************************************************************/
1141 struct cli_api_pipe_state {
1142 struct event_context *ev;
1143 struct rpc_cli_transport *transport;
1148 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1149 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1150 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1152 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1153 struct event_context *ev,
1154 struct rpc_cli_transport *transport,
1155 uint8_t *data, size_t data_len,
1156 uint32_t max_rdata_len)
1158 struct tevent_req *req, *subreq;
1159 struct cli_api_pipe_state *state;
1162 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1167 state->transport = transport;
1169 if (max_rdata_len < RPC_HEADER_LEN) {
1171 * For a RPC reply we always need at least RPC_HEADER_LEN
1172 * bytes. We check this here because we will receive
1173 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1175 status = NT_STATUS_INVALID_PARAMETER;
1179 if (transport->trans_send != NULL) {
1180 subreq = transport->trans_send(state, ev, data, data_len,
1181 max_rdata_len, transport->priv);
1182 if (subreq == NULL) {
1185 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1190 * If the transport does not provide a "trans" routine, i.e. for
1191 * example the ncacn_ip_tcp transport, do the write/read step here.
1194 subreq = rpc_write_send(state, ev, transport, data, data_len);
1195 if (subreq == NULL) {
1198 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1202 tevent_req_nterror(req, status);
1203 return tevent_req_post(req, ev);
1209 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1211 struct tevent_req *req = tevent_req_callback_data(
1212 subreq, struct tevent_req);
1213 struct cli_api_pipe_state *state = tevent_req_data(
1214 req, struct cli_api_pipe_state);
1217 status = state->transport->trans_recv(subreq, state, &state->rdata,
1219 TALLOC_FREE(subreq);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 tevent_req_nterror(req, status);
1224 tevent_req_done(req);
1227 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1229 struct tevent_req *req = tevent_req_callback_data(
1230 subreq, struct tevent_req);
1231 struct cli_api_pipe_state *state = tevent_req_data(
1232 req, struct cli_api_pipe_state);
1235 status = rpc_write_recv(subreq);
1236 TALLOC_FREE(subreq);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 tevent_req_nterror(req, status);
1242 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1243 if (tevent_req_nomem(state->rdata, req)) {
1248 * We don't need to use rpc_read_send here, the upper layer will cope
1249 * with a short read, transport->trans_send could also return less
1250 * than state->max_rdata_len.
1252 subreq = state->transport->read_send(state, state->ev, state->rdata,
1254 state->transport->priv);
1255 if (tevent_req_nomem(subreq, req)) {
1258 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1261 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1263 struct tevent_req *req = tevent_req_callback_data(
1264 subreq, struct tevent_req);
1265 struct cli_api_pipe_state *state = tevent_req_data(
1266 req, struct cli_api_pipe_state);
1270 status = state->transport->read_recv(subreq, &received);
1271 TALLOC_FREE(subreq);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 tevent_req_nterror(req, status);
1276 state->rdata_len = received;
1277 tevent_req_done(req);
1280 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1281 uint8_t **prdata, uint32_t *prdata_len)
1283 struct cli_api_pipe_state *state = tevent_req_data(
1284 req, struct cli_api_pipe_state);
1287 if (tevent_req_is_nterror(req, &status)) {
1291 *prdata = talloc_move(mem_ctx, &state->rdata);
1292 *prdata_len = state->rdata_len;
1293 return NT_STATUS_OK;
1296 /****************************************************************************
1297 Send data on an rpc pipe via trans. The prs_struct data must be the last
1298 pdu fragment of an NDR data stream.
1300 Receive response data from an rpc pipe, which may be large...
1302 Read the first fragment: unfortunately have to use SMBtrans for the first
1303 bit, then SMBreadX for subsequent bits.
1305 If first fragment received also wasn't the last fragment, continue
1306 getting fragments until we _do_ receive the last fragment.
1308 Request/Response PDU's look like the following...
1310 |<------------------PDU len----------------------------------------------->|
1311 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1313 +------------+-----------------+-------------+---------------+-------------+
1314 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1315 +------------+-----------------+-------------+---------------+-------------+
1317 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1318 signing & sealing being negotiated.
1320 ****************************************************************************/
1322 struct rpc_api_pipe_state {
1323 struct event_context *ev;
1324 struct rpc_pipe_client *cli;
1325 uint8_t expected_pkt_type;
1327 prs_struct incoming_frag;
1328 struct ncacn_packet *pkt;
1330 prs_struct incoming_pdu; /* Incoming reply */
1331 uint32_t incoming_pdu_offset;
1334 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1335 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1337 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1338 struct event_context *ev,
1339 struct rpc_pipe_client *cli,
1340 prs_struct *data, /* Outgoing PDU */
1341 uint8_t expected_pkt_type)
1343 struct tevent_req *req, *subreq;
1344 struct rpc_api_pipe_state *state;
1345 uint16_t max_recv_frag;
1348 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1354 state->expected_pkt_type = expected_pkt_type;
1355 state->incoming_pdu_offset = 0;
1357 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1359 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1360 /* Make incoming_pdu dynamic with no memory. */
1361 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1364 * Ensure we're not sending too much.
1366 if (prs_offset(data) > cli->max_xmit_frag) {
1367 status = NT_STATUS_INVALID_PARAMETER;
1371 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1373 /* get the header first, then fetch the rest once we have
1374 * the frag_length available */
1375 max_recv_frag = RPC_HEADER_LEN;
1377 subreq = cli_api_pipe_send(state, ev, cli->transport,
1378 (uint8_t *)prs_data_p(data),
1379 prs_offset(data), max_recv_frag);
1380 if (subreq == NULL) {
1383 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1387 tevent_req_nterror(req, status);
1388 return tevent_req_post(req, ev);
1394 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1396 struct tevent_req *req = tevent_req_callback_data(
1397 subreq, struct tevent_req);
1398 struct rpc_api_pipe_state *state = tevent_req_data(
1399 req, struct rpc_api_pipe_state);
1401 uint8_t *rdata = NULL;
1402 uint32_t rdata_len = 0;
1404 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1405 TALLOC_FREE(subreq);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1408 tevent_req_nterror(req, status);
1412 if (rdata == NULL) {
1413 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1414 rpccli_pipe_txt(talloc_tos(), state->cli)));
1415 tevent_req_done(req);
1420 * This is equivalent to a talloc_steal - gives rdata to
1421 * the prs_struct state->incoming_frag.
1423 prs_give_memory(&state->incoming_frag, (char *)rdata, rdata_len, true);
1426 /* Ensure we have enough data for a pdu. */
1427 subreq = get_complete_frag_send(state, state->ev, state->cli,
1428 &state->incoming_frag);
1429 if (tevent_req_nomem(subreq, req)) {
1432 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1435 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1437 struct tevent_req *req = tevent_req_callback_data(
1438 subreq, struct tevent_req);
1439 struct rpc_api_pipe_state *state = tevent_req_data(
1440 req, struct rpc_api_pipe_state);
1443 uint32_t rdata_len = 0;
1445 status = get_complete_frag_recv(subreq);
1446 TALLOC_FREE(subreq);
1447 if (!NT_STATUS_IS_OK(status)) {
1448 DEBUG(5, ("get_complete_frag failed: %s\n",
1449 nt_errstr(status)));
1450 tevent_req_nterror(req, status);
1454 state->pkt = talloc(state, struct ncacn_packet);
1456 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1460 status = cli_pipe_validate_current_pdu(
1461 state->cli, state->pkt, &state->incoming_frag,
1462 state->expected_pkt_type, &rdata, &rdata_len,
1463 &state->incoming_pdu);
1465 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1466 (unsigned)prs_data_size(&state->incoming_frag),
1467 (unsigned)state->incoming_pdu_offset,
1468 nt_errstr(status)));
1470 if (!NT_STATUS_IS_OK(status)) {
1471 tevent_req_nterror(req, status);
1475 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1476 && (state->pkt->drep[0] == 0)) {
1478 * Set the data type correctly for big-endian data on the
1481 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1483 rpccli_pipe_txt(talloc_tos(), state->cli)));
1484 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1487 * Check endianness on subsequent packets.
1489 if (state->incoming_frag.bigendian_data
1490 != state->incoming_pdu.bigendian_data) {
1491 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1493 state->incoming_pdu.bigendian_data?"big":"little",
1494 state->incoming_frag.bigendian_data?"big":"little"));
1495 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1499 /* Now copy the data portion out of the pdu into rbuf. */
1500 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1501 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1505 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1506 rdata, (size_t)rdata_len);
1507 state->incoming_pdu_offset += rdata_len;
1509 status = cli_pipe_reset_current_pdu(state->cli, state->pkt,
1510 &state->incoming_frag);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 tevent_req_nterror(req, status);
1516 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1517 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1518 rpccli_pipe_txt(talloc_tos(), state->cli),
1519 (unsigned)prs_data_size(&state->incoming_pdu)));
1520 tevent_req_done(req);
1524 subreq = get_complete_frag_send(state, state->ev, state->cli,
1525 &state->incoming_frag);
1526 if (tevent_req_nomem(subreq, req)) {
1529 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1532 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1533 struct ncacn_packet **pkt,
1534 prs_struct *reply_pdu)
1536 struct rpc_api_pipe_state *state = tevent_req_data(
1537 req, struct rpc_api_pipe_state);
1540 if (tevent_req_is_nterror(req, &status)) {
1544 *reply_pdu = state->incoming_pdu;
1545 reply_pdu->mem_ctx = mem_ctx;
1548 * Prevent state->incoming_pdu from being freed
1549 * when state is freed.
1551 talloc_steal(mem_ctx, prs_data_p(reply_pdu));
1552 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1555 *pkt = talloc_steal(mem_ctx, state->pkt);
1558 return NT_STATUS_OK;
1561 /*******************************************************************
1562 Creates krb5 auth bind.
1563 ********************************************************************/
1565 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1566 enum dcerpc_AuthLevel auth_level,
1567 DATA_BLOB *auth_info)
1572 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1573 DATA_BLOB tkt = data_blob_null;
1574 DATA_BLOB tkt_wrapped = data_blob_null;
1576 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1577 a->service_principal ));
1579 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1581 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1582 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1585 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1587 a->service_principal,
1588 error_message(ret) ));
1590 data_blob_free(&tkt);
1591 return NT_STATUS_INVALID_PARAMETER;
1594 /* wrap that up in a nice GSS-API wrapping */
1595 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1597 data_blob_free(&tkt);
1599 status = dcerpc_push_dcerpc_auth(cli,
1600 DCERPC_AUTH_TYPE_KRB5,
1602 0, /* auth_pad_length */
1603 1, /* auth_context_id */
1606 if (!NT_STATUS_IS_OK(status)) {
1607 data_blob_free(&tkt_wrapped);
1611 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1612 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1614 return NT_STATUS_OK;
1616 return NT_STATUS_INVALID_PARAMETER;
1620 /*******************************************************************
1621 Creates SPNEGO NTLMSSP auth bind.
1622 ********************************************************************/
1624 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1625 enum dcerpc_AuthLevel auth_level,
1626 DATA_BLOB *auth_info)
1629 DATA_BLOB null_blob = data_blob_null;
1630 DATA_BLOB request = data_blob_null;
1631 DATA_BLOB spnego_msg = data_blob_null;
1633 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1634 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1638 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1639 data_blob_free(&request);
1643 /* Wrap this in SPNEGO. */
1644 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1646 data_blob_free(&request);
1648 status = dcerpc_push_dcerpc_auth(cli,
1649 DCERPC_AUTH_TYPE_SPNEGO,
1651 0, /* auth_pad_length */
1652 1, /* auth_context_id */
1655 if (!NT_STATUS_IS_OK(status)) {
1656 data_blob_free(&spnego_msg);
1660 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1661 dump_data(5, spnego_msg.data, spnego_msg.length);
1663 return NT_STATUS_OK;
1666 /*******************************************************************
1667 Creates NTLMSSP auth bind.
1668 ********************************************************************/
1670 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1671 enum dcerpc_AuthLevel auth_level,
1672 DATA_BLOB *auth_info)
1675 DATA_BLOB null_blob = data_blob_null;
1676 DATA_BLOB request = data_blob_null;
1678 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1679 status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1683 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1684 data_blob_free(&request);
1688 status = dcerpc_push_dcerpc_auth(cli,
1689 DCERPC_AUTH_TYPE_NTLMSSP,
1691 0, /* auth_pad_length */
1692 1, /* auth_context_id */
1695 if (!NT_STATUS_IS_OK(status)) {
1696 data_blob_free(&request);
1700 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1701 dump_data(5, request.data, request.length);
1703 return NT_STATUS_OK;
1706 /*******************************************************************
1707 Creates schannel auth bind.
1708 ********************************************************************/
1710 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1711 enum dcerpc_AuthLevel auth_level,
1712 DATA_BLOB *auth_info)
1715 struct NL_AUTH_MESSAGE r;
1716 DATA_BLOB schannel_blob;
1718 /* Use lp_workgroup() if domain not specified */
1720 if (!cli->auth->domain || !cli->auth->domain[0]) {
1721 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1722 if (cli->auth->domain == NULL) {
1723 return NT_STATUS_NO_MEMORY;
1728 * Now marshall the data into the auth parse_struct.
1731 r.MessageType = NL_NEGOTIATE_REQUEST;
1732 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1733 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1734 r.oem_netbios_domain.a = cli->auth->domain;
1735 r.oem_netbios_computer.a = global_myname();
1737 status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1738 if (!NT_STATUS_IS_OK(status)) {
1742 status = dcerpc_push_dcerpc_auth(cli,
1743 DCERPC_AUTH_TYPE_SCHANNEL,
1745 0, /* auth_pad_length */
1746 1, /* auth_context_id */
1749 if (!NT_STATUS_IS_OK(status)) {
1753 return NT_STATUS_OK;
1756 /*******************************************************************
1757 ********************************************************************/
1759 static NTSTATUS init_dcerpc_ctx_list(TALLOC_CTX *mem_ctx,
1760 const struct ndr_syntax_id *abstract_syntax,
1761 const struct ndr_syntax_id *transfer_syntax,
1762 struct dcerpc_ctx_list **ctx_list_p)
1764 struct dcerpc_ctx_list *ctx_list;
1766 ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1767 NT_STATUS_HAVE_NO_MEMORY(ctx_list);
1769 ctx_list[0].context_id = 0;
1770 ctx_list[0].num_transfer_syntaxes = 1;
1771 ctx_list[0].abstract_syntax = *abstract_syntax;
1772 ctx_list[0].transfer_syntaxes = talloc_array(ctx_list,
1773 struct ndr_syntax_id,
1774 ctx_list[0].num_transfer_syntaxes);
1775 NT_STATUS_HAVE_NO_MEMORY(ctx_list[0].transfer_syntaxes);
1776 ctx_list[0].transfer_syntaxes[0] = *transfer_syntax;
1778 *ctx_list_p = ctx_list;
1780 return NT_STATUS_OK;
1783 /*******************************************************************
1784 Creates the internals of a DCE/RPC bind request or alter context PDU.
1785 ********************************************************************/
1787 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype,
1788 prs_struct *rpc_out,
1790 const struct ndr_syntax_id *abstract,
1791 const struct ndr_syntax_id *transfer,
1792 const DATA_BLOB *auth_info)
1794 uint16 auth_len = auth_info->length;
1796 union dcerpc_payload u;
1798 struct dcerpc_ctx_list *ctx_list;
1800 status = init_dcerpc_ctx_list(rpc_out->mem_ctx, abstract, transfer,
1802 if (!NT_STATUS_IS_OK(status)) {
1807 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1810 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1811 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1812 u.bind.assoc_group_id = 0x0;
1813 u.bind.num_contexts = 1;
1814 u.bind.ctx_list = ctx_list;
1815 u.bind.auth_info = *auth_info;
1817 status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx,
1819 DCERPC_PFC_FLAG_FIRST |
1820 DCERPC_PFC_FLAG_LAST,
1825 if (!NT_STATUS_IS_OK(status)) {
1826 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1830 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
1831 return NT_STATUS_NO_MEMORY;
1834 return NT_STATUS_OK;
1837 /*******************************************************************
1838 Creates a DCE/RPC bind request.
1839 ********************************************************************/
1841 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1842 prs_struct *rpc_out,
1844 const struct ndr_syntax_id *abstract,
1845 const struct ndr_syntax_id *transfer,
1846 enum pipe_auth_type auth_type,
1847 enum dcerpc_AuthLevel auth_level)
1849 DATA_BLOB auth_info = data_blob_null;
1850 NTSTATUS ret = NT_STATUS_OK;
1852 switch (auth_type) {
1853 case PIPE_AUTH_TYPE_SCHANNEL:
1854 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1855 if (!NT_STATUS_IS_OK(ret)) {
1860 case PIPE_AUTH_TYPE_NTLMSSP:
1861 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1862 if (!NT_STATUS_IS_OK(ret)) {
1867 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1868 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1869 if (!NT_STATUS_IS_OK(ret)) {
1874 case PIPE_AUTH_TYPE_KRB5:
1875 ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1876 if (!NT_STATUS_IS_OK(ret)) {
1881 case PIPE_AUTH_TYPE_NONE:
1885 /* "Can't" happen. */
1886 return NT_STATUS_INVALID_INFO_CLASS;
1889 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1898 /*******************************************************************
1899 Create and add the NTLMSSP sign/seal auth header and data.
1900 ********************************************************************/
1902 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1903 uint32 ss_padding_len,
1904 prs_struct *rpc_out)
1906 DATA_BLOB auth_info;
1908 DATA_BLOB auth_blob = data_blob_null;
1909 uint16_t data_and_pad_len = prs_offset(rpc_out)
1910 - DCERPC_RESPONSE_LENGTH;
1912 if (!cli->auth->a_u.ntlmssp_state) {
1913 return NT_STATUS_INVALID_PARAMETER;
1916 /* marshall the dcerpc_auth with an actually empty auth_blob.
1917 * this is needed because the ntmlssp signature includes the
1919 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1920 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1921 cli->auth->auth_level,
1923 1 /* context id. */,
1926 if (!NT_STATUS_IS_OK(status)) {
1930 /* append the header */
1931 if (!prs_copy_data_in(rpc_out,
1932 (char *)auth_info.data,
1933 auth_info.length)) {
1934 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1935 (unsigned int)auth_info.length));
1936 return NT_STATUS_NO_MEMORY;
1939 switch (cli->auth->auth_level) {
1940 case DCERPC_AUTH_LEVEL_PRIVACY:
1941 /* Data portion is encrypted. */
1942 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1943 prs_get_mem_context(rpc_out),
1944 (unsigned char *)prs_data_p(rpc_out)
1945 + DCERPC_RESPONSE_LENGTH,
1947 (unsigned char *)prs_data_p(rpc_out),
1948 (size_t)prs_offset(rpc_out),
1950 if (!NT_STATUS_IS_OK(status)) {
1955 case DCERPC_AUTH_LEVEL_INTEGRITY:
1956 /* Data is signed. */
1957 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1958 prs_get_mem_context(rpc_out),
1959 (unsigned char *)prs_data_p(rpc_out)
1960 + DCERPC_RESPONSE_LENGTH,
1962 (unsigned char *)prs_data_p(rpc_out),
1963 (size_t)prs_offset(rpc_out),
1965 if (!NT_STATUS_IS_OK(status)) {
1972 smb_panic("bad auth level");
1974 return NT_STATUS_INVALID_PARAMETER;
1977 /* Finally attach the blob. */
1978 if (!prs_copy_data_in(rpc_out,
1979 (char *)auth_blob.data,
1980 auth_blob.length)) {
1981 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1982 (unsigned int)auth_info.length));
1983 return NT_STATUS_NO_MEMORY;
1986 return NT_STATUS_OK;
1989 /*******************************************************************
1990 Create and add the schannel sign/seal auth header and data.
1991 ********************************************************************/
1993 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1994 uint32 ss_padding_len,
1995 prs_struct *rpc_out)
1997 DATA_BLOB auth_info;
1998 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1999 char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH;
2000 size_t data_and_pad_len = prs_offset(rpc_out)
2001 - DCERPC_RESPONSE_LENGTH;
2006 return NT_STATUS_INVALID_PARAMETER;
2009 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2012 switch (cli->auth->auth_level) {
2013 case DCERPC_AUTH_LEVEL_PRIVACY:
2014 status = netsec_outgoing_packet(sas,
2021 case DCERPC_AUTH_LEVEL_INTEGRITY:
2022 status = netsec_outgoing_packet(sas,
2030 status = NT_STATUS_INTERNAL_ERROR;
2034 if (!NT_STATUS_IS_OK(status)) {
2035 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2036 nt_errstr(status)));
2040 if (DEBUGLEVEL >= 10) {
2041 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2044 /* Finally marshall the blob. */
2045 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2046 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2047 cli->auth->auth_level,
2049 1 /* context id. */,
2052 if (!NT_STATUS_IS_OK(status)) {
2056 if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
2057 return NT_STATUS_NO_MEMORY;
2060 return NT_STATUS_OK;
2063 /*******************************************************************
2064 Calculate how much data we're going to send in this packet, also
2065 work out any sign/seal padding length.
2066 ********************************************************************/
2068 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2072 uint32 *p_ss_padding)
2074 uint32 data_space, data_len;
2077 if ((data_left > 0) && (sys_random() % 2)) {
2078 data_left = MAX(data_left/2, 1);
2082 switch (cli->auth->auth_level) {
2083 case DCERPC_AUTH_LEVEL_NONE:
2084 case DCERPC_AUTH_LEVEL_CONNECT:
2085 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
2086 data_len = MIN(data_space, data_left);
2089 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
2092 case DCERPC_AUTH_LEVEL_INTEGRITY:
2093 case DCERPC_AUTH_LEVEL_PRIVACY:
2094 /* Treat the same for all authenticated rpc requests. */
2095 switch(cli->auth->auth_type) {
2096 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2097 case PIPE_AUTH_TYPE_NTLMSSP:
2098 *p_auth_len = NTLMSSP_SIG_SIZE;
2100 case PIPE_AUTH_TYPE_SCHANNEL:
2101 *p_auth_len = SCHANNEL_SIG_SIZE;
2104 smb_panic("bad auth type");
2108 data_space = cli->max_xmit_frag
2109 - DCERPC_REQUEST_LENGTH
2110 - DCERPC_AUTH_TRAILER_LENGTH
2113 data_len = MIN(data_space, data_left);
2115 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2116 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2118 *p_frag_len = DCERPC_REQUEST_LENGTH
2119 + data_len + *p_ss_padding
2120 + DCERPC_AUTH_TRAILER_LENGTH
2125 smb_panic("bad auth level");
2131 /*******************************************************************
2133 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2134 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2135 and deals with signing/sealing details.
2136 ********************************************************************/
2138 struct rpc_api_pipe_req_state {
2139 struct event_context *ev;
2140 struct rpc_pipe_client *cli;
2143 prs_struct *req_data;
2144 uint32_t req_data_sent;
2145 prs_struct outgoing_frag;
2146 prs_struct reply_pdu;
2149 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2150 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2151 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2152 bool *is_last_frag);
2154 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2155 struct event_context *ev,
2156 struct rpc_pipe_client *cli,
2158 prs_struct *req_data)
2160 struct tevent_req *req, *subreq;
2161 struct rpc_api_pipe_req_state *state;
2165 req = tevent_req_create(mem_ctx, &state,
2166 struct rpc_api_pipe_req_state);
2172 state->op_num = op_num;
2173 state->req_data = req_data;
2174 state->req_data_sent = 0;
2175 state->call_id = get_rpc_call_id();
2177 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
2178 + RPC_MAX_SIGN_SIZE) {
2179 /* Server is screwed up ! */
2180 status = NT_STATUS_INVALID_PARAMETER;
2184 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2186 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2191 status = prepare_next_frag(state, &is_last_frag);
2192 if (!NT_STATUS_IS_OK(status)) {
2197 subreq = rpc_api_pipe_send(state, ev, state->cli,
2198 &state->outgoing_frag,
2199 DCERPC_PKT_RESPONSE);
2200 if (subreq == NULL) {
2203 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2205 subreq = rpc_write_send(
2206 state, ev, cli->transport,
2207 (uint8_t *)prs_data_p(&state->outgoing_frag),
2208 prs_offset(&state->outgoing_frag));
2209 if (subreq == NULL) {
2212 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2218 tevent_req_nterror(req, status);
2219 return tevent_req_post(req, ev);
2225 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2228 uint32_t data_sent_thistime;
2232 uint32_t ss_padding;
2234 char pad[8] = { 0, };
2236 union dcerpc_payload u;
2239 data_left = prs_offset(state->req_data) - state->req_data_sent;
2241 data_sent_thistime = calculate_data_len_tosend(
2242 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2244 if (state->req_data_sent == 0) {
2245 flags = DCERPC_PFC_FLAG_FIRST;
2248 if (data_sent_thistime == data_left) {
2249 flags |= DCERPC_PFC_FLAG_LAST;
2252 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2253 return NT_STATUS_NO_MEMORY;
2256 ZERO_STRUCT(u.request);
2258 u.request.alloc_hint = prs_offset(state->req_data);
2259 u.request.context_id = 0;
2260 u.request.opnum = state->op_num;
2262 status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
2269 if (!NT_STATUS_IS_OK(status)) {
2273 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2274 * compute it right for requests */
2275 dcerpc_set_frag_length(&blob, frag_len);
2277 if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) {
2278 return NT_STATUS_NO_MEMORY;
2281 /* Copy in the data, plus any ss padding. */
2282 if (!prs_append_some_prs_data(&state->outgoing_frag,
2283 state->req_data, state->req_data_sent,
2284 data_sent_thistime)) {
2285 return NT_STATUS_NO_MEMORY;
2288 /* Copy the sign/seal padding data. */
2289 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2290 return NT_STATUS_NO_MEMORY;
2293 /* Generate any auth sign/seal and add the auth footer. */
2294 switch (state->cli->auth->auth_type) {
2295 case PIPE_AUTH_TYPE_NONE:
2296 status = NT_STATUS_OK;
2298 case PIPE_AUTH_TYPE_NTLMSSP:
2299 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2300 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2301 &state->outgoing_frag);
2303 case PIPE_AUTH_TYPE_SCHANNEL:
2304 status = add_schannel_auth_footer(state->cli, ss_padding,
2305 &state->outgoing_frag);
2308 status = NT_STATUS_INVALID_PARAMETER;
2312 state->req_data_sent += data_sent_thistime;
2313 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2318 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2320 struct tevent_req *req = tevent_req_callback_data(
2321 subreq, struct tevent_req);
2322 struct rpc_api_pipe_req_state *state = tevent_req_data(
2323 req, struct rpc_api_pipe_req_state);
2327 status = rpc_write_recv(subreq);
2328 TALLOC_FREE(subreq);
2329 if (!NT_STATUS_IS_OK(status)) {
2330 tevent_req_nterror(req, status);
2334 status = prepare_next_frag(state, &is_last_frag);
2335 if (!NT_STATUS_IS_OK(status)) {
2336 tevent_req_nterror(req, status);
2341 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2342 &state->outgoing_frag,
2343 DCERPC_PKT_RESPONSE);
2344 if (tevent_req_nomem(subreq, req)) {
2347 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2349 subreq = rpc_write_send(
2351 state->cli->transport,
2352 (uint8_t *)prs_data_p(&state->outgoing_frag),
2353 prs_offset(&state->outgoing_frag));
2354 if (tevent_req_nomem(subreq, req)) {
2357 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2362 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2364 struct tevent_req *req = tevent_req_callback_data(
2365 subreq, struct tevent_req);
2366 struct rpc_api_pipe_req_state *state = tevent_req_data(
2367 req, struct rpc_api_pipe_req_state);
2370 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2371 TALLOC_FREE(subreq);
2372 if (!NT_STATUS_IS_OK(status)) {
2373 tevent_req_nterror(req, status);
2376 tevent_req_done(req);
2379 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2380 prs_struct *reply_pdu)
2382 struct rpc_api_pipe_req_state *state = tevent_req_data(
2383 req, struct rpc_api_pipe_req_state);
2386 if (tevent_req_is_nterror(req, &status)) {
2388 * We always have to initialize to reply pdu, even if there is
2389 * none. The rpccli_* caller routines expect this.
2391 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2395 *reply_pdu = state->reply_pdu;
2396 reply_pdu->mem_ctx = mem_ctx;
2399 * Prevent state->req_pdu from being freed
2400 * when state is freed.
2402 talloc_steal(mem_ctx, prs_data_p(reply_pdu));
2403 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2405 return NT_STATUS_OK;
2409 /****************************************************************************
2410 Set the handle state.
2411 ****************************************************************************/
2413 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2414 const char *pipe_name, uint16 device_state)
2416 bool state_set = False;
2418 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2419 char *rparam = NULL;
2421 uint32 rparam_len, rdata_len;
2423 if (pipe_name == NULL)
2426 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2427 cli->fnum, pipe_name, device_state));
2429 /* create parameters: device state */
2430 SSVAL(param, 0, device_state);
2432 /* create setup parameters. */
2434 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2436 /* send the data on \PIPE\ */
2437 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2438 setup, 2, 0, /* setup, length, max */
2439 param, 2, 0, /* param, length, max */
2440 NULL, 0, 1024, /* data, length, max */
2441 &rparam, &rparam_len, /* return param, length */
2442 &rdata, &rdata_len)) /* return data, length */
2444 DEBUG(5, ("Set Handle state: return OK\n"));
2455 /****************************************************************************
2456 Check the rpc bind acknowledge response.
2457 ****************************************************************************/
2459 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2460 const struct ndr_syntax_id *transfer)
2462 struct dcerpc_ack_ctx ctx;
2464 if (r->secondary_address_size == 0) {
2465 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2468 if (r->num_results < 1 || !r->ctx_list) {
2472 ctx = r->ctx_list[0];
2474 /* check the transfer syntax */
2475 if ((ctx.syntax.if_version != transfer->if_version) ||
2476 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2477 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2481 if (r->num_results != 0x1 || ctx.result != 0) {
2482 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2483 r->num_results, ctx.reason));
2486 DEBUG(5,("check_bind_response: accepted!\n"));
2490 /*******************************************************************
2491 Creates a DCE/RPC bind authentication response.
2492 This is the packet that is sent back to the server once we
2493 have received a BIND-ACK, to finish the third leg of
2494 the authentication handshake.
2495 ********************************************************************/
2497 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2499 enum pipe_auth_type auth_type,
2500 enum dcerpc_AuthLevel auth_level,
2501 DATA_BLOB *pauth_blob,
2502 prs_struct *rpc_out)
2505 union dcerpc_payload u;
2510 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2511 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2513 0, /* auth_pad_length */
2514 1, /* auth_context_id */
2516 &u.auth3.auth_info);
2517 if (!NT_STATUS_IS_OK(status)) {
2521 status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
2523 DCERPC_PFC_FLAG_FIRST |
2524 DCERPC_PFC_FLAG_LAST,
2529 if (!NT_STATUS_IS_OK(status)) {
2530 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2534 if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
2535 return NT_STATUS_NO_MEMORY;
2538 return NT_STATUS_OK;
2541 /*******************************************************************
2542 Creates a DCE/RPC bind alter context authentication request which
2543 may contain a spnego auth blobl
2544 ********************************************************************/
2546 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2547 const struct ndr_syntax_id *abstract,
2548 const struct ndr_syntax_id *transfer,
2549 enum dcerpc_AuthLevel auth_level,
2550 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2551 prs_struct *rpc_out)
2553 DATA_BLOB auth_info;
2556 status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2557 DCERPC_AUTH_TYPE_SPNEGO,
2559 0, /* auth_pad_length */
2560 1, /* auth_context_id */
2563 if (!NT_STATUS_IS_OK(status)) {
2568 status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2574 if (!NT_STATUS_IS_OK(status)) {
2581 /****************************************************************************
2583 ****************************************************************************/
2585 struct rpc_pipe_bind_state {
2586 struct event_context *ev;
2587 struct rpc_pipe_client *cli;
2589 uint32_t rpc_call_id;
2592 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2593 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2594 struct rpc_pipe_bind_state *state,
2595 struct ncacn_packet *r,
2596 prs_struct *reply_pdu);
2597 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2598 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2599 struct rpc_pipe_bind_state *state,
2600 struct ncacn_packet *r,
2601 prs_struct *reply_pdu);
2602 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2604 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2605 struct event_context *ev,
2606 struct rpc_pipe_client *cli,
2607 struct cli_pipe_auth_data *auth)
2609 struct tevent_req *req, *subreq;
2610 struct rpc_pipe_bind_state *state;
2613 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2618 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2619 rpccli_pipe_txt(talloc_tos(), cli),
2620 (unsigned int)auth->auth_type,
2621 (unsigned int)auth->auth_level ));
2625 state->rpc_call_id = get_rpc_call_id();
2627 prs_init_empty(&state->rpc_out, state, MARSHALL);
2629 cli->auth = talloc_move(cli, &auth);
2631 /* Marshall the outgoing data. */
2632 status = create_rpc_bind_req(cli, &state->rpc_out,
2634 &cli->abstract_syntax,
2635 &cli->transfer_syntax,
2636 cli->auth->auth_type,
2637 cli->auth->auth_level);
2639 if (!NT_STATUS_IS_OK(status)) {
2643 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2644 DCERPC_PKT_BIND_ACK);
2645 if (subreq == NULL) {
2648 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2652 tevent_req_nterror(req, status);
2653 return tevent_req_post(req, ev);
2659 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2661 struct tevent_req *req = tevent_req_callback_data(
2662 subreq, struct tevent_req);
2663 struct rpc_pipe_bind_state *state = tevent_req_data(
2664 req, struct rpc_pipe_bind_state);
2665 prs_struct reply_pdu;
2666 struct ncacn_packet *pkt;
2669 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2670 TALLOC_FREE(subreq);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2673 rpccli_pipe_txt(talloc_tos(), state->cli),
2674 nt_errstr(status)));
2675 tevent_req_nterror(req, status);
2679 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2680 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2681 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2685 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2686 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2689 * For authenticated binds we may need to do 3 or 4 leg binds.
2692 switch(state->cli->auth->auth_type) {
2694 case PIPE_AUTH_TYPE_NONE:
2695 case PIPE_AUTH_TYPE_SCHANNEL:
2696 /* Bind complete. */
2697 tevent_req_done(req);
2700 case PIPE_AUTH_TYPE_NTLMSSP:
2701 /* Need to send AUTH3 packet - no reply. */
2702 status = rpc_finish_auth3_bind_send(req, state, pkt,
2704 if (!NT_STATUS_IS_OK(status)) {
2705 tevent_req_nterror(req, status);
2709 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2710 /* Need to send alter context request and reply. */
2711 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2713 if (!NT_STATUS_IS_OK(status)) {
2714 tevent_req_nterror(req, status);
2718 case PIPE_AUTH_TYPE_KRB5:
2722 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2723 (unsigned int)state->cli->auth->auth_type));
2724 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2728 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2729 struct rpc_pipe_bind_state *state,
2730 struct ncacn_packet *r,
2731 prs_struct *reply_pdu)
2733 DATA_BLOB client_reply = data_blob_null;
2734 struct dcerpc_auth auth;
2735 struct tevent_req *subreq;
2738 if ((r->auth_length == 0)
2739 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2740 + r->auth_length)) {
2741 return NT_STATUS_INVALID_PARAMETER;
2744 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2745 &r->u.bind_ack.auth_info,
2747 if (!NT_STATUS_IS_OK(status)) {
2748 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2749 nt_errstr(status)));
2753 /* TODO - check auth_type/auth_level match. */
2755 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2756 auth.credentials, &client_reply);
2758 if (!NT_STATUS_IS_OK(status)) {
2759 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2760 "blob failed: %s.\n", nt_errstr(status)));
2764 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2766 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2767 state->cli->auth->auth_type,
2768 state->cli->auth->auth_level,
2769 &client_reply, &state->rpc_out);
2770 data_blob_free(&client_reply);
2772 if (!NT_STATUS_IS_OK(status)) {
2776 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2777 (uint8_t *)prs_data_p(&state->rpc_out),
2778 prs_offset(&state->rpc_out));
2779 if (subreq == NULL) {
2780 return NT_STATUS_NO_MEMORY;
2782 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2783 return NT_STATUS_OK;
2786 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2788 struct tevent_req *req = tevent_req_callback_data(
2789 subreq, struct tevent_req);
2792 status = rpc_write_recv(subreq);
2793 TALLOC_FREE(subreq);
2794 if (!NT_STATUS_IS_OK(status)) {
2795 tevent_req_nterror(req, status);
2798 tevent_req_done(req);
2801 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2802 struct rpc_pipe_bind_state *state,
2803 struct ncacn_packet *r,
2806 DATA_BLOB server_ntlm_response = data_blob_null;
2807 DATA_BLOB client_reply = data_blob_null;
2808 DATA_BLOB tmp_blob = data_blob_null;
2809 struct dcerpc_auth auth_info;
2810 DATA_BLOB auth_blob;
2811 struct tevent_req *subreq;
2814 if ((r->auth_length == 0)
2815 || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2816 + r->auth_length)) {
2817 return NT_STATUS_INVALID_PARAMETER;
2820 /* Process the returned NTLMSSP blob first. */
2821 if (!prs_set_offset(rpc_in, r->frag_length
2822 - DCERPC_AUTH_TRAILER_LENGTH
2823 - r->auth_length)) {
2824 return NT_STATUS_INVALID_PARAMETER;
2827 auth_blob = data_blob_const(prs_data_p(rpc_in) + prs_offset(rpc_in),
2828 prs_data_size(rpc_in) - prs_offset(rpc_in));
2830 status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2837 * The server might give us back two challenges - tmp_blob is for the
2840 if (!spnego_parse_challenge(auth_info.credentials,
2841 &server_ntlm_response, &tmp_blob)) {
2842 data_blob_free(&server_ntlm_response);
2843 data_blob_free(&tmp_blob);
2844 return NT_STATUS_INVALID_PARAMETER;
2847 /* We're finished with the server spnego response and the tmp_blob. */
2848 data_blob_free(&tmp_blob);
2850 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2851 server_ntlm_response, &client_reply);
2853 /* Finished with the server_ntlm response */
2854 data_blob_free(&server_ntlm_response);
2856 if (!NT_STATUS_IS_OK(status)) {
2857 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2858 "using server blob failed.\n"));
2859 data_blob_free(&client_reply);
2863 /* SPNEGO wrap the client reply. */
2864 tmp_blob = spnego_gen_auth(client_reply);
2865 data_blob_free(&client_reply);
2866 client_reply = tmp_blob;
2867 tmp_blob = data_blob_null;
2869 /* Now prepare the alter context pdu. */
2870 prs_init_empty(&state->rpc_out, state, MARSHALL);
2872 status = create_rpc_alter_context(state->rpc_call_id,
2873 &state->cli->abstract_syntax,
2874 &state->cli->transfer_syntax,
2875 state->cli->auth->auth_level,
2878 data_blob_free(&client_reply);
2880 if (!NT_STATUS_IS_OK(status)) {
2884 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2885 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2886 if (subreq == NULL) {
2887 return NT_STATUS_NO_MEMORY;
2889 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2890 return NT_STATUS_OK;
2893 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2895 struct tevent_req *req = tevent_req_callback_data(
2896 subreq, struct tevent_req);
2897 struct rpc_pipe_bind_state *state = tevent_req_data(
2898 req, struct rpc_pipe_bind_state);
2899 DATA_BLOB tmp_blob = data_blob_null;
2900 struct ncacn_packet *pkt;
2901 struct dcerpc_auth auth;
2902 prs_struct reply_pdu;
2905 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2906 TALLOC_FREE(subreq);
2907 if (!NT_STATUS_IS_OK(status)) {
2908 tevent_req_nterror(req, status);
2912 status = dcerpc_pull_dcerpc_auth(pkt,
2913 &pkt->u.alter_resp.auth_info,
2915 if (!NT_STATUS_IS_OK(status)) {
2916 tevent_req_nterror(req, status);
2920 /* Check we got a valid auth response. */
2921 if (!spnego_parse_auth_response(auth.credentials,
2923 OID_NTLMSSP, &tmp_blob)) {
2924 data_blob_free(&tmp_blob);
2925 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2929 data_blob_free(&tmp_blob);
2931 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2932 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2933 tevent_req_done(req);
2936 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2938 return tevent_req_simple_recv_ntstatus(req);
2941 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2942 struct cli_pipe_auth_data *auth)
2944 TALLOC_CTX *frame = talloc_stackframe();
2945 struct event_context *ev;
2946 struct tevent_req *req;
2947 NTSTATUS status = NT_STATUS_OK;
2949 ev = event_context_init(frame);
2951 status = NT_STATUS_NO_MEMORY;
2955 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2957 status = NT_STATUS_NO_MEMORY;
2961 if (!tevent_req_poll(req, ev)) {
2962 status = map_nt_error_from_unix(errno);
2966 status = rpc_pipe_bind_recv(req);
2972 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2974 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2975 unsigned int timeout)
2979 if (rpc_cli->transport == NULL) {
2980 return RPCCLI_DEFAULT_TIMEOUT;
2983 if (rpc_cli->transport->set_timeout == NULL) {
2984 return RPCCLI_DEFAULT_TIMEOUT;
2987 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2989 return RPCCLI_DEFAULT_TIMEOUT;
2995 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2997 if (rpc_cli == NULL) {
3001 if (rpc_cli->transport == NULL) {
3005 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
3008 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3010 struct cli_state *cli;
3012 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3013 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3014 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3018 cli = rpc_pipe_np_smb_conn(rpc_cli);
3022 E_md4hash(cli->password ? cli->password : "", nt_hash);
3026 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3027 struct cli_pipe_auth_data **presult)
3029 struct cli_pipe_auth_data *result;
3031 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3032 if (result == NULL) {
3033 return NT_STATUS_NO_MEMORY;
3036 result->auth_type = PIPE_AUTH_TYPE_NONE;
3037 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3039 result->user_name = talloc_strdup(result, "");
3040 result->domain = talloc_strdup(result, "");
3041 if ((result->user_name == NULL) || (result->domain == NULL)) {
3042 TALLOC_FREE(result);
3043 return NT_STATUS_NO_MEMORY;
3047 return NT_STATUS_OK;
3050 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3052 ntlmssp_end(&auth->a_u.ntlmssp_state);
3056 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3057 enum pipe_auth_type auth_type,
3058 enum dcerpc_AuthLevel auth_level,
3060 const char *username,
3061 const char *password,
3062 struct cli_pipe_auth_data **presult)
3064 struct cli_pipe_auth_data *result;
3067 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3068 if (result == NULL) {
3069 return NT_STATUS_NO_MEMORY;
3072 result->auth_type = auth_type;
3073 result->auth_level = auth_level;
3075 result->user_name = talloc_strdup(result, username);
3076 result->domain = talloc_strdup(result, domain);
3077 if ((result->user_name == NULL) || (result->domain == NULL)) {
3078 status = NT_STATUS_NO_MEMORY;
3082 status = ntlmssp_client_start(NULL,
3085 lp_client_ntlmv2_auth(),
3086 &result->a_u.ntlmssp_state);
3087 if (!NT_STATUS_IS_OK(status)) {
3091 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3093 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3094 if (!NT_STATUS_IS_OK(status)) {
3098 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3099 if (!NT_STATUS_IS_OK(status)) {
3103 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3104 if (!NT_STATUS_IS_OK(status)) {
3109 * Turn off sign+seal to allow selected auth level to turn it back on.
3111 result->a_u.ntlmssp_state->neg_flags &=
3112 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3114 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3115 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3116 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3117 result->a_u.ntlmssp_state->neg_flags
3118 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3122 return NT_STATUS_OK;
3125 TALLOC_FREE(result);
3129 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3130 enum dcerpc_AuthLevel auth_level,
3131 struct netlogon_creds_CredentialState *creds,
3132 struct cli_pipe_auth_data **presult)
3134 struct cli_pipe_auth_data *result;
3136 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3137 if (result == NULL) {
3138 return NT_STATUS_NO_MEMORY;
3141 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3142 result->auth_level = auth_level;
3144 result->user_name = talloc_strdup(result, "");
3145 result->domain = talloc_strdup(result, domain);
3146 if ((result->user_name == NULL) || (result->domain == NULL)) {
3150 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3151 if (result->a_u.schannel_auth == NULL) {
3155 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3156 result->a_u.schannel_auth->seq_num = 0;
3157 result->a_u.schannel_auth->initiator = true;
3158 result->a_u.schannel_auth->creds = creds;
3161 return NT_STATUS_OK;
3164 TALLOC_FREE(result);
3165 return NT_STATUS_NO_MEMORY;
3169 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3171 data_blob_free(&auth->session_key);
3176 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3177 enum dcerpc_AuthLevel auth_level,
3178 const char *service_princ,
3179 const char *username,
3180 const char *password,
3181 struct cli_pipe_auth_data **presult)
3184 struct cli_pipe_auth_data *result;
3186 if ((username != NULL) && (password != NULL)) {
3187 int ret = kerberos_kinit_password(username, password, 0, NULL);
3189 return NT_STATUS_ACCESS_DENIED;
3193 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3194 if (result == NULL) {
3195 return NT_STATUS_NO_MEMORY;
3198 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3199 result->auth_level = auth_level;
3202 * Username / domain need fixing!
3204 result->user_name = talloc_strdup(result, "");
3205 result->domain = talloc_strdup(result, "");
3206 if ((result->user_name == NULL) || (result->domain == NULL)) {
3210 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3211 result, struct kerberos_auth_struct);
3212 if (result->a_u.kerberos_auth == NULL) {
3215 talloc_set_destructor(result->a_u.kerberos_auth,
3216 cli_auth_kerberos_data_destructor);
3218 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3219 result, service_princ);
3220 if (result->a_u.kerberos_auth->service_principal == NULL) {
3225 return NT_STATUS_OK;
3228 TALLOC_FREE(result);
3229 return NT_STATUS_NO_MEMORY;
3231 return NT_STATUS_NOT_SUPPORTED;
3236 * Create an rpc pipe client struct, connecting to a tcp port.
3238 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3240 const struct ndr_syntax_id *abstract_syntax,
3241 struct rpc_pipe_client **presult)
3243 struct rpc_pipe_client *result;
3244 struct sockaddr_storage addr;
3248 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3249 if (result == NULL) {
3250 return NT_STATUS_NO_MEMORY;
3253 result->abstract_syntax = *abstract_syntax;
3254 result->transfer_syntax = ndr_transfer_syntax;
3255 result->dispatch = cli_do_rpc_ndr;
3256 result->dispatch_send = cli_do_rpc_ndr_send;
3257 result->dispatch_recv = cli_do_rpc_ndr_recv;
3259 result->desthost = talloc_strdup(result, host);
3260 result->srv_name_slash = talloc_asprintf_strupper_m(
3261 result, "\\\\%s", result->desthost);
3262 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3263 status = NT_STATUS_NO_MEMORY;
3267 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3268 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3270 if (!resolve_name(host, &addr, 0, false)) {
3271 status = NT_STATUS_NOT_FOUND;
3275 status = open_socket_out(&addr, port, 60, &fd);
3276 if (!NT_STATUS_IS_OK(status)) {
3279 set_socket_options(fd, lp_socket_options());
3281 status = rpc_transport_sock_init(result, fd, &result->transport);
3282 if (!NT_STATUS_IS_OK(status)) {
3287 result->transport->transport = NCACN_IP_TCP;
3290 return NT_STATUS_OK;
3293 TALLOC_FREE(result);
3298 * Determine the tcp port on which a dcerpc interface is listening
3299 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3302 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3303 const struct ndr_syntax_id *abstract_syntax,
3307 struct rpc_pipe_client *epm_pipe = NULL;
3308 struct cli_pipe_auth_data *auth = NULL;
3309 struct dcerpc_binding *map_binding = NULL;
3310 struct dcerpc_binding *res_binding = NULL;
3311 struct epm_twr_t *map_tower = NULL;
3312 struct epm_twr_t *res_towers = NULL;
3313 struct policy_handle *entry_handle = NULL;
3314 uint32_t num_towers = 0;
3315 uint32_t max_towers = 1;
3316 struct epm_twr_p_t towers;
3317 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3319 if (pport == NULL) {
3320 status = NT_STATUS_INVALID_PARAMETER;
3324 /* open the connection to the endpoint mapper */
3325 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3326 &ndr_table_epmapper.syntax_id,
3329 if (!NT_STATUS_IS_OK(status)) {
3333 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3334 if (!NT_STATUS_IS_OK(status)) {
3338 status = rpc_pipe_bind(epm_pipe, auth);
3339 if (!NT_STATUS_IS_OK(status)) {
3343 /* create tower for asking the epmapper */
3345 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3346 if (map_binding == NULL) {
3347 status = NT_STATUS_NO_MEMORY;
3351 map_binding->transport = NCACN_IP_TCP;
3352 map_binding->object = *abstract_syntax;
3353 map_binding->host = host; /* needed? */
3354 map_binding->endpoint = "0"; /* correct? needed? */
3356 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3357 if (map_tower == NULL) {
3358 status = NT_STATUS_NO_MEMORY;
3362 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3363 &(map_tower->tower));
3364 if (!NT_STATUS_IS_OK(status)) {
3368 /* allocate further parameters for the epm_Map call */
3370 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3371 if (res_towers == NULL) {
3372 status = NT_STATUS_NO_MEMORY;
3375 towers.twr = res_towers;
3377 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3378 if (entry_handle == NULL) {
3379 status = NT_STATUS_NO_MEMORY;
3383 /* ask the endpoint mapper for the port */
3385 status = rpccli_epm_Map(epm_pipe,
3387 CONST_DISCARD(struct GUID *,
3388 &(abstract_syntax->uuid)),
3395 if (!NT_STATUS_IS_OK(status)) {
3399 if (num_towers != 1) {
3400 status = NT_STATUS_UNSUCCESSFUL;
3404 /* extract the port from the answer */
3406 status = dcerpc_binding_from_tower(tmp_ctx,
3407 &(towers.twr->tower),
3409 if (!NT_STATUS_IS_OK(status)) {
3413 /* are further checks here necessary? */
3414 if (res_binding->transport != NCACN_IP_TCP) {
3415 status = NT_STATUS_UNSUCCESSFUL;
3419 *pport = (uint16_t)atoi(res_binding->endpoint);
3422 TALLOC_FREE(tmp_ctx);
3427 * Create a rpc pipe client struct, connecting to a host via tcp.
3428 * The port is determined by asking the endpoint mapper on the given
3431 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3432 const struct ndr_syntax_id *abstract_syntax,
3433 struct rpc_pipe_client **presult)
3438 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3439 if (!NT_STATUS_IS_OK(status)) {
3443 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3444 abstract_syntax, presult);
3447 /********************************************************************
3448 Create a rpc pipe client struct, connecting to a unix domain socket
3449 ********************************************************************/
3450 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3451 const struct ndr_syntax_id *abstract_syntax,
3452 struct rpc_pipe_client **presult)
3454 struct rpc_pipe_client *result;
3455 struct sockaddr_un addr;
3459 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3460 if (result == NULL) {
3461 return NT_STATUS_NO_MEMORY;
3464 result->abstract_syntax = *abstract_syntax;
3465 result->transfer_syntax = ndr_transfer_syntax;
3466 result->dispatch = cli_do_rpc_ndr;
3467 result->dispatch_send = cli_do_rpc_ndr_send;
3468 result->dispatch_recv = cli_do_rpc_ndr_recv;
3470 result->desthost = get_myname(result);
3471 result->srv_name_slash = talloc_asprintf_strupper_m(
3472 result, "\\\\%s", result->desthost);
3473 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3474 status = NT_STATUS_NO_MEMORY;
3478 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3479 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3481 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3483 status = map_nt_error_from_unix(errno);
3488 addr.sun_family = AF_UNIX;
3489 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3491 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3492 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3495 return map_nt_error_from_unix(errno);
3498 status = rpc_transport_sock_init(result, fd, &result->transport);
3499 if (!NT_STATUS_IS_OK(status)) {
3504 result->transport->transport = NCALRPC;
3507 return NT_STATUS_OK;
3510 TALLOC_FREE(result);
3514 struct rpc_pipe_client_np_ref {
3515 struct cli_state *cli;
3516 struct rpc_pipe_client *pipe;
3519 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3521 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3525 /****************************************************************************
3526 Open a named pipe over SMB to a remote server.
3528 * CAVEAT CALLER OF THIS FUNCTION:
3529 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3530 * so be sure that this function is called AFTER any structure (vs pointer)
3531 * assignment of the cli. In particular, libsmbclient does structure
3532 * assignments of cli, which invalidates the data in the returned
3533 * rpc_pipe_client if this function is called before the structure assignment
3536 ****************************************************************************/
3538 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3539 const struct ndr_syntax_id *abstract_syntax,
3540 struct rpc_pipe_client **presult)
3542 struct rpc_pipe_client *result;
3544 struct rpc_pipe_client_np_ref *np_ref;
3546 /* sanity check to protect against crashes */
3549 return NT_STATUS_INVALID_HANDLE;
3552 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3553 if (result == NULL) {
3554 return NT_STATUS_NO_MEMORY;
3557 result->abstract_syntax = *abstract_syntax;
3558 result->transfer_syntax = ndr_transfer_syntax;
3559 result->dispatch = cli_do_rpc_ndr;
3560 result->dispatch_send = cli_do_rpc_ndr_send;
3561 result->dispatch_recv = cli_do_rpc_ndr_recv;
3562 result->desthost = talloc_strdup(result, cli->desthost);
3563 result->srv_name_slash = talloc_asprintf_strupper_m(
3564 result, "\\\\%s", result->desthost);
3566 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3567 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3569 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3570 TALLOC_FREE(result);
3571 return NT_STATUS_NO_MEMORY;
3574 status = rpc_transport_np_init(result, cli, abstract_syntax,
3575 &result->transport);
3576 if (!NT_STATUS_IS_OK(status)) {
3577 TALLOC_FREE(result);
3581 result->transport->transport = NCACN_NP;
3583 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3584 if (np_ref == NULL) {
3585 TALLOC_FREE(result);
3586 return NT_STATUS_NO_MEMORY;
3589 np_ref->pipe = result;
3591 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3592 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3595 return NT_STATUS_OK;
3598 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3599 struct rpc_cli_smbd_conn *conn,
3600 const struct ndr_syntax_id *syntax,
3601 struct rpc_pipe_client **presult)
3603 struct rpc_pipe_client *result;
3604 struct cli_pipe_auth_data *auth;
3607 result = talloc(mem_ctx, struct rpc_pipe_client);
3608 if (result == NULL) {
3609 return NT_STATUS_NO_MEMORY;
3611 result->abstract_syntax = *syntax;
3612 result->transfer_syntax = ndr_transfer_syntax;
3613 result->dispatch = cli_do_rpc_ndr;
3614 result->dispatch_send = cli_do_rpc_ndr_send;
3615 result->dispatch_recv = cli_do_rpc_ndr_recv;
3616 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3617 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3619 result->desthost = talloc_strdup(result, global_myname());
3620 result->srv_name_slash = talloc_asprintf_strupper_m(
3621 result, "\\\\%s", global_myname());
3622 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3623 TALLOC_FREE(result);
3624 return NT_STATUS_NO_MEMORY;
3627 status = rpc_transport_smbd_init(result, conn, syntax,
3628 &result->transport);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3631 nt_errstr(status)));
3632 TALLOC_FREE(result);
3636 status = rpccli_anon_bind_data(result, &auth);
3637 if (!NT_STATUS_IS_OK(status)) {
3638 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3639 nt_errstr(status)));
3640 TALLOC_FREE(result);
3644 status = rpc_pipe_bind(result, auth);
3645 if (!NT_STATUS_IS_OK(status)) {
3646 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3647 TALLOC_FREE(result);
3651 result->transport->transport = NCACN_INTERNAL;
3654 return NT_STATUS_OK;
3657 /****************************************************************************
3658 Open a pipe to a remote server.
3659 ****************************************************************************/
3661 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3662 enum dcerpc_transport_t transport,
3663 const struct ndr_syntax_id *interface,
3664 struct rpc_pipe_client **presult)
3666 switch (transport) {
3668 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3671 return rpc_pipe_open_np(cli, interface, presult);
3673 return NT_STATUS_NOT_IMPLEMENTED;
3677 /****************************************************************************
3678 Open a named pipe to an SMB server and bind anonymously.
3679 ****************************************************************************/
3681 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3682 enum dcerpc_transport_t transport,
3683 const struct ndr_syntax_id *interface,
3684 struct rpc_pipe_client **presult)
3686 struct rpc_pipe_client *result;
3687 struct cli_pipe_auth_data *auth;
3690 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3691 if (!NT_STATUS_IS_OK(status)) {
3695 status = rpccli_anon_bind_data(result, &auth);
3696 if (!NT_STATUS_IS_OK(status)) {
3697 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3698 nt_errstr(status)));
3699 TALLOC_FREE(result);
3704 * This is a bit of an abstraction violation due to the fact that an
3705 * anonymous bind on an authenticated SMB inherits the user/domain
3706 * from the enclosing SMB creds
3709 TALLOC_FREE(auth->user_name);
3710 TALLOC_FREE(auth->domain);
3712 auth->user_name = talloc_strdup(auth, cli->user_name);
3713 auth->domain = talloc_strdup(auth, cli->domain);
3714 auth->user_session_key = data_blob_talloc(auth,
3715 cli->user_session_key.data,
3716 cli->user_session_key.length);
3718 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3719 TALLOC_FREE(result);
3720 return NT_STATUS_NO_MEMORY;
3723 status = rpc_pipe_bind(result, auth);
3724 if (!NT_STATUS_IS_OK(status)) {
3726 if (ndr_syntax_id_equal(interface,
3727 &ndr_table_dssetup.syntax_id)) {
3728 /* non AD domains just don't have this pipe, avoid
3729 * level 0 statement in that case - gd */
3732 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3733 "%s failed with error %s\n",
3734 get_pipe_name_from_syntax(talloc_tos(), interface),
3735 nt_errstr(status) ));
3736 TALLOC_FREE(result);
3740 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3741 "%s and bound anonymously.\n",
3742 get_pipe_name_from_syntax(talloc_tos(), interface),
3746 return NT_STATUS_OK;
3749 /****************************************************************************
3750 ****************************************************************************/
3752 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3753 const struct ndr_syntax_id *interface,
3754 struct rpc_pipe_client **presult)
3756 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3757 interface, presult);
3760 /****************************************************************************
3761 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3762 ****************************************************************************/
3764 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3765 const struct ndr_syntax_id *interface,
3766 enum dcerpc_transport_t transport,
3767 enum pipe_auth_type auth_type,
3768 enum dcerpc_AuthLevel auth_level,
3770 const char *username,
3771 const char *password,
3772 struct rpc_pipe_client **presult)
3774 struct rpc_pipe_client *result;
3775 struct cli_pipe_auth_data *auth;
3778 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3779 if (!NT_STATUS_IS_OK(status)) {
3783 status = rpccli_ntlmssp_bind_data(
3784 result, auth_type, auth_level, domain, username,
3786 if (!NT_STATUS_IS_OK(status)) {
3787 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3788 nt_errstr(status)));
3792 status = rpc_pipe_bind(result, auth);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3795 nt_errstr(status) ));
3799 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3800 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3801 get_pipe_name_from_syntax(talloc_tos(), interface),
3802 cli->desthost, domain, username ));
3805 return NT_STATUS_OK;
3809 TALLOC_FREE(result);
3813 /****************************************************************************
3815 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3816 ****************************************************************************/
3818 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3819 const struct ndr_syntax_id *interface,
3820 enum dcerpc_transport_t transport,
3821 enum dcerpc_AuthLevel auth_level,
3823 const char *username,
3824 const char *password,
3825 struct rpc_pipe_client **presult)
3827 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3830 PIPE_AUTH_TYPE_NTLMSSP,
3838 /****************************************************************************
3840 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3841 ****************************************************************************/
3843 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3844 const struct ndr_syntax_id *interface,
3845 enum dcerpc_transport_t transport,
3846 enum dcerpc_AuthLevel auth_level,
3848 const char *username,
3849 const char *password,
3850 struct rpc_pipe_client **presult)
3852 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3855 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3863 /****************************************************************************
3864 Get a the schannel session key out of an already opened netlogon pipe.
3865 ****************************************************************************/
3866 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3867 struct cli_state *cli,
3871 enum netr_SchannelType sec_chan_type = 0;
3872 unsigned char machine_pwd[16];
3873 const char *machine_account;
3876 /* Get the machine account credentials from secrets.tdb. */
3877 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3880 DEBUG(0, ("get_schannel_session_key: could not fetch "
3881 "trust account password for domain '%s'\n",
3883 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3886 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3887 cli->desthost, /* server name */
3888 domain, /* domain */
3889 global_myname(), /* client name */
3890 machine_account, /* machine account name */
3895 if (!NT_STATUS_IS_OK(status)) {
3896 DEBUG(3, ("get_schannel_session_key_common: "
3897 "rpccli_netlogon_setup_creds failed with result %s "
3898 "to server %s, domain %s, machine account %s.\n",
3899 nt_errstr(status), cli->desthost, domain,
3904 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3905 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3907 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3910 return NT_STATUS_OK;;
3913 /****************************************************************************
3914 Open a netlogon pipe and get the schannel session key.
3915 Now exposed to external callers.
3916 ****************************************************************************/
3919 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3922 struct rpc_pipe_client **presult)
3924 struct rpc_pipe_client *netlogon_pipe = NULL;
3927 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3929 if (!NT_STATUS_IS_OK(status)) {
3933 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3935 if (!NT_STATUS_IS_OK(status)) {
3936 TALLOC_FREE(netlogon_pipe);
3940 *presult = netlogon_pipe;
3941 return NT_STATUS_OK;
3944 /****************************************************************************
3946 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3947 using session_key. sign and seal.
3949 The *pdc will be stolen onto this new pipe
3950 ****************************************************************************/
3952 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3953 const struct ndr_syntax_id *interface,
3954 enum dcerpc_transport_t transport,
3955 enum dcerpc_AuthLevel auth_level,
3957 struct netlogon_creds_CredentialState **pdc,
3958 struct rpc_pipe_client **presult)
3960 struct rpc_pipe_client *result;
3961 struct cli_pipe_auth_data *auth;
3964 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3965 if (!NT_STATUS_IS_OK(status)) {
3969 status = rpccli_schannel_bind_data(result, domain, auth_level,
3971 if (!NT_STATUS_IS_OK(status)) {
3972 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3973 nt_errstr(status)));
3974 TALLOC_FREE(result);
3978 status = rpc_pipe_bind(result, auth);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3981 "cli_rpc_pipe_bind failed with error %s\n",
3982 nt_errstr(status) ));
3983 TALLOC_FREE(result);
3988 * The credentials on a new netlogon pipe are the ones we are passed
3989 * in - reference them in
3991 result->dc = talloc_move(result, pdc);
3993 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3994 "for domain %s and bound using schannel.\n",
3995 get_pipe_name_from_syntax(talloc_tos(), interface),
3996 cli->desthost, domain ));
3999 return NT_STATUS_OK;
4002 /****************************************************************************
4003 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4004 Fetch the session key ourselves using a temporary netlogon pipe. This
4005 version uses an ntlmssp auth bound netlogon pipe to get the key.
4006 ****************************************************************************/
4008 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4010 const char *username,
4011 const char *password,
4013 struct rpc_pipe_client **presult)
4015 struct rpc_pipe_client *netlogon_pipe = NULL;
4018 status = cli_rpc_pipe_open_spnego_ntlmssp(
4019 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4020 DCERPC_AUTH_LEVEL_PRIVACY,
4021 domain, username, password, &netlogon_pipe);
4022 if (!NT_STATUS_IS_OK(status)) {
4026 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4028 if (!NT_STATUS_IS_OK(status)) {
4029 TALLOC_FREE(netlogon_pipe);
4033 *presult = netlogon_pipe;
4034 return NT_STATUS_OK;
4037 /****************************************************************************
4038 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4039 Fetch the session key ourselves using a temporary netlogon pipe. This version
4040 uses an ntlmssp bind to get the session key.
4041 ****************************************************************************/
4043 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4044 const struct ndr_syntax_id *interface,
4045 enum dcerpc_transport_t transport,
4046 enum dcerpc_AuthLevel auth_level,
4048 const char *username,
4049 const char *password,
4050 struct rpc_pipe_client **presult)
4052 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4053 struct rpc_pipe_client *netlogon_pipe = NULL;
4054 struct rpc_pipe_client *result = NULL;
4057 status = get_schannel_session_key_auth_ntlmssp(
4058 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4061 "key from server %s for domain %s.\n",
4062 cli->desthost, domain ));
4066 status = cli_rpc_pipe_open_schannel_with_key(
4067 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4070 /* Now we've bound using the session key we can close the netlog pipe. */
4071 TALLOC_FREE(netlogon_pipe);
4073 if (NT_STATUS_IS_OK(status)) {
4079 /****************************************************************************
4080 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4081 Fetch the session key ourselves using a temporary netlogon pipe.
4082 ****************************************************************************/
4084 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4085 const struct ndr_syntax_id *interface,
4086 enum dcerpc_transport_t transport,
4087 enum dcerpc_AuthLevel auth_level,
4089 struct rpc_pipe_client **presult)
4091 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4092 struct rpc_pipe_client *netlogon_pipe = NULL;
4093 struct rpc_pipe_client *result = NULL;
4096 status = get_schannel_session_key(cli, domain, &neg_flags,
4098 if (!NT_STATUS_IS_OK(status)) {
4099 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4100 "key from server %s for domain %s.\n",
4101 cli->desthost, domain ));
4105 status = cli_rpc_pipe_open_schannel_with_key(
4106 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4109 /* Now we've bound using the session key we can close the netlog pipe. */
4110 TALLOC_FREE(netlogon_pipe);
4112 if (NT_STATUS_IS_OK(status)) {
4119 /****************************************************************************
4120 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4121 The idea is this can be called with service_princ, username and password all
4122 NULL so long as the caller has a TGT.
4123 ****************************************************************************/
4125 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4126 const struct ndr_syntax_id *interface,
4127 enum dcerpc_AuthLevel auth_level,
4128 const char *service_princ,
4129 const char *username,
4130 const char *password,
4131 struct rpc_pipe_client **presult)
4134 struct rpc_pipe_client *result;
4135 struct cli_pipe_auth_data *auth;
4138 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4139 if (!NT_STATUS_IS_OK(status)) {
4143 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4144 username, password, &auth);
4145 if (!NT_STATUS_IS_OK(status)) {
4146 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4147 nt_errstr(status)));
4148 TALLOC_FREE(result);
4152 status = rpc_pipe_bind(result, auth);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4155 "with error %s\n", nt_errstr(status)));
4156 TALLOC_FREE(result);
4161 return NT_STATUS_OK;
4163 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4164 return NT_STATUS_NOT_IMPLEMENTED;
4168 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4169 struct rpc_pipe_client *cli,
4170 DATA_BLOB *session_key)
4172 if (!session_key || !cli) {
4173 return NT_STATUS_INVALID_PARAMETER;
4177 return NT_STATUS_INVALID_PARAMETER;
4180 switch (cli->auth->auth_type) {
4181 case PIPE_AUTH_TYPE_SCHANNEL:
4182 *session_key = data_blob_talloc(mem_ctx,
4183 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4185 case PIPE_AUTH_TYPE_NTLMSSP:
4186 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4187 *session_key = data_blob_talloc(mem_ctx,
4188 cli->auth->a_u.ntlmssp_state->session_key.data,
4189 cli->auth->a_u.ntlmssp_state->session_key.length);
4191 case PIPE_AUTH_TYPE_KRB5:
4192 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4193 *session_key = data_blob_talloc(mem_ctx,
4194 cli->auth->a_u.kerberos_auth->session_key.data,
4195 cli->auth->a_u.kerberos_auth->session_key.length);
4197 case PIPE_AUTH_TYPE_NONE:
4198 *session_key = data_blob_talloc(mem_ctx,
4199 cli->auth->user_session_key.data,
4200 cli->auth->user_session_key.length);
4203 return NT_STATUS_NO_USER_SESSION_KEY;
4206 return NT_STATUS_OK;