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 "../libcli/auth/libcli_auth.h"
22 #include "librpc/gen_ndr/cli_epmapper.h"
23 #include "../librpc/gen_ndr/ndr_schannel.h"
24 #include "../libcli/auth/schannel.h"
25 #include "../libcli/auth/schannel_proto.h"
28 #define DBGC_CLASS DBGC_RPC_CLI
30 /*******************************************************************
31 interface/version dce/rpc pipe identification
32 ********************************************************************/
34 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
35 #define PIPE_SAMR "\\PIPE\\samr"
36 #define PIPE_WINREG "\\PIPE\\winreg"
37 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
38 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
39 #define PIPE_NTLSA "\\PIPE\\ntlsa"
40 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
41 #define PIPE_LSASS "\\PIPE\\lsass"
42 #define PIPE_LSARPC "\\PIPE\\lsarpc"
43 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
44 #define PIPE_NETDFS "\\PIPE\\netdfs"
45 #define PIPE_ECHO "\\PIPE\\rpcecho"
46 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
47 #define PIPE_EPM "\\PIPE\\epmapper"
48 #define PIPE_SVCCTL "\\PIPE\\svcctl"
49 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
50 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
51 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
54 * IMPORTANT!! If you update this structure, make sure to
55 * update the index #defines in smb.h.
58 static const struct pipe_id_info
{
59 /* the names appear not to matter: the syntaxes _do_ matter */
61 const char *client_pipe
;
62 const struct ndr_syntax_id
*abstr_syntax
; /* this one is the abstract syntax id */
65 { PIPE_LSARPC
, &ndr_table_lsarpc
.syntax_id
},
66 { PIPE_LSARPC
, &ndr_table_dssetup
.syntax_id
},
67 { PIPE_SAMR
, &ndr_table_samr
.syntax_id
},
68 { PIPE_NETLOGON
, &ndr_table_netlogon
.syntax_id
},
69 { PIPE_SRVSVC
, &ndr_table_srvsvc
.syntax_id
},
70 { PIPE_WKSSVC
, &ndr_table_wkssvc
.syntax_id
},
71 { PIPE_WINREG
, &ndr_table_winreg
.syntax_id
},
72 { PIPE_SPOOLSS
, &ndr_table_spoolss
.syntax_id
},
73 { PIPE_NETDFS
, &ndr_table_netdfs
.syntax_id
},
74 { PIPE_ECHO
, &ndr_table_rpcecho
.syntax_id
},
75 { PIPE_SHUTDOWN
, &ndr_table_initshutdown
.syntax_id
},
76 { PIPE_SVCCTL
, &ndr_table_svcctl
.syntax_id
},
77 { PIPE_EVENTLOG
, &ndr_table_eventlog
.syntax_id
},
78 { PIPE_NTSVCS
, &ndr_table_ntsvcs
.syntax_id
},
79 { PIPE_EPMAPPER
, &ndr_table_epmapper
.syntax_id
},
80 { PIPE_DRSUAPI
, &ndr_table_drsuapi
.syntax_id
},
84 /****************************************************************************
85 Return the pipe name from the interface.
86 ****************************************************************************/
88 const char *get_pipe_name_from_iface(const struct ndr_syntax_id
*interface
)
93 for (i
= 0; pipe_names
[i
].client_pipe
; i
++) {
94 if (ndr_syntax_id_equal(pipe_names
[i
].abstr_syntax
,
96 return &pipe_names
[i
].client_pipe
[5];
101 * Here we should ask \\epmapper, but for now our code is only
102 * interested in the known pipes mentioned in pipe_names[]
105 guid_str
= GUID_string(talloc_tos(), &interface
->uuid
);
106 if (guid_str
== NULL
) {
109 result
= talloc_asprintf(talloc_tos(), "Interface %s.%d", guid_str
,
110 (int)interface
->if_version
);
111 TALLOC_FREE(guid_str
);
113 if (result
== NULL
) {
119 /********************************************************************
120 Map internal value to wire value.
121 ********************************************************************/
123 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type
)
127 case PIPE_AUTH_TYPE_NONE
:
128 return DCERPC_AUTH_TYPE_NONE
;
130 case PIPE_AUTH_TYPE_NTLMSSP
:
131 return DCERPC_AUTH_TYPE_NTLMSSP
;
133 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
134 case PIPE_AUTH_TYPE_SPNEGO_KRB5
:
135 return DCERPC_AUTH_TYPE_SPNEGO
;
137 case PIPE_AUTH_TYPE_SCHANNEL
:
138 return DCERPC_AUTH_TYPE_SCHANNEL
;
140 case PIPE_AUTH_TYPE_KRB5
:
141 return DCERPC_AUTH_TYPE_KRB5
;
144 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
146 (unsigned int)auth_type
));
152 /********************************************************************
153 Pipe description for a DEBUG
154 ********************************************************************/
155 static const char *rpccli_pipe_txt(TALLOC_CTX
*mem_ctx
,
156 struct rpc_pipe_client
*cli
)
158 char *result
= talloc_asprintf(mem_ctx
, "host %s", cli
->desthost
);
159 if (result
== NULL
) {
165 /********************************************************************
167 ********************************************************************/
169 static uint32
get_rpc_call_id(void)
171 static uint32 call_id
= 0;
176 * Realloc pdu to have a least "size" bytes
179 static bool rpc_grow_buffer(prs_struct
*pdu
, size_t size
)
183 if (prs_data_size(pdu
) >= size
) {
187 extra_size
= size
- prs_data_size(pdu
);
189 if (!prs_force_grow(pdu
, extra_size
)) {
190 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
191 "%d bytes.\n", (int)extra_size
));
195 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
196 (int)extra_size
, prs_data_size(pdu
)));
201 /*******************************************************************
202 Use SMBreadX to get rest of one fragment's worth of rpc data.
203 Reads the whole size or give an error message
204 ********************************************************************/
206 struct rpc_read_state
{
207 struct event_context
*ev
;
208 struct rpc_cli_transport
*transport
;
214 static void rpc_read_done(struct tevent_req
*subreq
);
216 static struct tevent_req
*rpc_read_send(TALLOC_CTX
*mem_ctx
,
217 struct event_context
*ev
,
218 struct rpc_cli_transport
*transport
,
219 uint8_t *data
, size_t size
)
221 struct tevent_req
*req
, *subreq
;
222 struct rpc_read_state
*state
;
224 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_read_state
);
229 state
->transport
= transport
;
234 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size
));
236 subreq
= transport
->read_send(state
, ev
, (uint8_t *)data
, size
,
238 if (subreq
== NULL
) {
241 tevent_req_set_callback(subreq
, rpc_read_done
, req
);
249 static void rpc_read_done(struct tevent_req
*subreq
)
251 struct tevent_req
*req
= tevent_req_callback_data(
252 subreq
, struct tevent_req
);
253 struct rpc_read_state
*state
= tevent_req_data(
254 req
, struct rpc_read_state
);
258 status
= state
->transport
->read_recv(subreq
, &received
);
260 if (!NT_STATUS_IS_OK(status
)) {
261 tevent_req_nterror(req
, status
);
265 state
->num_read
+= received
;
266 if (state
->num_read
== state
->size
) {
267 tevent_req_done(req
);
271 subreq
= state
->transport
->read_send(state
, state
->ev
,
272 state
->data
+ state
->num_read
,
273 state
->size
- state
->num_read
,
274 state
->transport
->priv
);
275 if (tevent_req_nomem(subreq
, req
)) {
278 tevent_req_set_callback(subreq
, rpc_read_done
, req
);
281 static NTSTATUS
rpc_read_recv(struct tevent_req
*req
)
283 return tevent_req_simple_recv_ntstatus(req
);
286 struct rpc_write_state
{
287 struct event_context
*ev
;
288 struct rpc_cli_transport
*transport
;
294 static void rpc_write_done(struct tevent_req
*subreq
);
296 static struct tevent_req
*rpc_write_send(TALLOC_CTX
*mem_ctx
,
297 struct event_context
*ev
,
298 struct rpc_cli_transport
*transport
,
299 const uint8_t *data
, size_t size
)
301 struct tevent_req
*req
, *subreq
;
302 struct rpc_write_state
*state
;
304 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_write_state
);
309 state
->transport
= transport
;
312 state
->num_written
= 0;
314 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size
));
316 subreq
= transport
->write_send(state
, ev
, data
, size
, transport
->priv
);
317 if (subreq
== NULL
) {
320 tevent_req_set_callback(subreq
, rpc_write_done
, req
);
327 static void rpc_write_done(struct tevent_req
*subreq
)
329 struct tevent_req
*req
= tevent_req_callback_data(
330 subreq
, struct tevent_req
);
331 struct rpc_write_state
*state
= tevent_req_data(
332 req
, struct rpc_write_state
);
336 status
= state
->transport
->write_recv(subreq
, &written
);
338 if (!NT_STATUS_IS_OK(status
)) {
339 tevent_req_nterror(req
, status
);
343 state
->num_written
+= written
;
345 if (state
->num_written
== state
->size
) {
346 tevent_req_done(req
);
350 subreq
= state
->transport
->write_send(state
, state
->ev
,
351 state
->data
+ state
->num_written
,
352 state
->size
- state
->num_written
,
353 state
->transport
->priv
);
354 if (tevent_req_nomem(subreq
, req
)) {
357 tevent_req_set_callback(subreq
, rpc_write_done
, req
);
360 static NTSTATUS
rpc_write_recv(struct tevent_req
*req
)
362 return tevent_req_simple_recv_ntstatus(req
);
366 static NTSTATUS
parse_rpc_header(struct rpc_pipe_client
*cli
,
367 struct rpc_hdr_info
*prhdr
,
371 * This next call sets the endian bit correctly in current_pdu. We
372 * will propagate this to rbuf later.
375 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr
, pdu
, 0)) {
376 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
377 return NT_STATUS_BUFFER_TOO_SMALL
;
380 if (prhdr
->frag_len
> cli
->max_recv_frag
) {
381 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
382 " we only allow %d\n", (int)prhdr
->frag_len
,
383 (int)cli
->max_recv_frag
));
384 return NT_STATUS_BUFFER_TOO_SMALL
;
390 /****************************************************************************
391 Try and get a PDU's worth of data from current_pdu. If not, then read more
393 ****************************************************************************/
395 struct get_complete_frag_state
{
396 struct event_context
*ev
;
397 struct rpc_pipe_client
*cli
;
398 struct rpc_hdr_info
*prhdr
;
402 static void get_complete_frag_got_header(struct tevent_req
*subreq
);
403 static void get_complete_frag_got_rest(struct tevent_req
*subreq
);
405 static struct tevent_req
*get_complete_frag_send(TALLOC_CTX
*mem_ctx
,
406 struct event_context
*ev
,
407 struct rpc_pipe_client
*cli
,
408 struct rpc_hdr_info
*prhdr
,
411 struct tevent_req
*req
, *subreq
;
412 struct get_complete_frag_state
*state
;
416 req
= tevent_req_create(mem_ctx
, &state
,
417 struct get_complete_frag_state
);
423 state
->prhdr
= prhdr
;
426 pdu_len
= prs_data_size(pdu
);
427 if (pdu_len
< RPC_HEADER_LEN
) {
428 if (!rpc_grow_buffer(pdu
, RPC_HEADER_LEN
)) {
429 status
= NT_STATUS_NO_MEMORY
;
432 subreq
= rpc_read_send(
434 state
->cli
->transport
,
435 (uint8_t *)(prs_data_p(state
->pdu
) + pdu_len
),
436 RPC_HEADER_LEN
- pdu_len
);
437 if (subreq
== NULL
) {
438 status
= NT_STATUS_NO_MEMORY
;
441 tevent_req_set_callback(subreq
, get_complete_frag_got_header
,
446 status
= parse_rpc_header(cli
, prhdr
, pdu
);
447 if (!NT_STATUS_IS_OK(status
)) {
452 * Ensure we have frag_len bytes of data.
454 if (pdu_len
< prhdr
->frag_len
) {
455 if (!rpc_grow_buffer(pdu
, prhdr
->frag_len
)) {
456 status
= NT_STATUS_NO_MEMORY
;
459 subreq
= rpc_read_send(state
, state
->ev
,
460 state
->cli
->transport
,
461 (uint8_t *)(prs_data_p(pdu
) + pdu_len
),
462 prhdr
->frag_len
- pdu_len
);
463 if (subreq
== NULL
) {
464 status
= NT_STATUS_NO_MEMORY
;
467 tevent_req_set_callback(subreq
, get_complete_frag_got_rest
,
472 status
= NT_STATUS_OK
;
474 if (NT_STATUS_IS_OK(status
)) {
475 tevent_req_done(req
);
477 tevent_req_nterror(req
, status
);
479 return tevent_req_post(req
, ev
);
482 static void get_complete_frag_got_header(struct tevent_req
*subreq
)
484 struct tevent_req
*req
= tevent_req_callback_data(
485 subreq
, struct tevent_req
);
486 struct get_complete_frag_state
*state
= tevent_req_data(
487 req
, struct get_complete_frag_state
);
490 status
= rpc_read_recv(subreq
);
492 if (!NT_STATUS_IS_OK(status
)) {
493 tevent_req_nterror(req
, status
);
497 status
= parse_rpc_header(state
->cli
, state
->prhdr
, state
->pdu
);
498 if (!NT_STATUS_IS_OK(status
)) {
499 tevent_req_nterror(req
, status
);
503 if (!rpc_grow_buffer(state
->pdu
, state
->prhdr
->frag_len
)) {
504 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
509 * We're here in this piece of code because we've read exactly
510 * RPC_HEADER_LEN bytes into state->pdu.
513 subreq
= rpc_read_send(
514 state
, state
->ev
, state
->cli
->transport
,
515 (uint8_t *)(prs_data_p(state
->pdu
) + RPC_HEADER_LEN
),
516 state
->prhdr
->frag_len
- RPC_HEADER_LEN
);
517 if (tevent_req_nomem(subreq
, req
)) {
520 tevent_req_set_callback(subreq
, get_complete_frag_got_rest
, req
);
523 static void get_complete_frag_got_rest(struct tevent_req
*subreq
)
525 struct tevent_req
*req
= tevent_req_callback_data(
526 subreq
, struct tevent_req
);
529 status
= rpc_read_recv(subreq
);
531 if (!NT_STATUS_IS_OK(status
)) {
532 tevent_req_nterror(req
, status
);
535 tevent_req_done(req
);
538 static NTSTATUS
get_complete_frag_recv(struct tevent_req
*req
)
540 return tevent_req_simple_recv_ntstatus(req
);
543 /****************************************************************************
544 NTLMSSP specific sign/seal.
545 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
546 In fact I should probably abstract these into identical pieces of code... JRA.
547 ****************************************************************************/
549 static NTSTATUS
cli_pipe_verify_ntlmssp(struct rpc_pipe_client
*cli
, RPC_HDR
*prhdr
,
550 prs_struct
*current_pdu
,
551 uint8
*p_ss_padding_len
)
553 RPC_HDR_AUTH auth_info
;
554 uint32 save_offset
= prs_offset(current_pdu
);
555 uint32 auth_len
= prhdr
->auth_len
;
556 NTLMSSP_STATE
*ntlmssp_state
= cli
->auth
->a_u
.ntlmssp_state
;
557 unsigned char *data
= NULL
;
559 unsigned char *full_packet_data
= NULL
;
560 size_t full_packet_data_len
;
564 if (cli
->auth
->auth_level
== DCERPC_AUTH_LEVEL_NONE
565 || cli
->auth
->auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
569 if (!ntlmssp_state
) {
570 return NT_STATUS_INVALID_PARAMETER
;
573 /* Ensure there's enough data for an authenticated response. */
574 if ((auth_len
> RPC_MAX_SIGN_SIZE
) ||
575 (RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ RPC_HDR_AUTH_LEN
+ auth_len
> prhdr
->frag_len
)) {
576 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
577 (unsigned int)auth_len
));
578 return NT_STATUS_BUFFER_TOO_SMALL
;
582 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
583 * after the RPC header.
584 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
585 * functions as NTLMv2 checks the rpc headers also.
588 data
= (unsigned char *)(prs_data_p(current_pdu
) + RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
);
589 data_len
= (size_t)(prhdr
->frag_len
- RPC_HEADER_LEN
- RPC_HDR_RESP_LEN
- RPC_HDR_AUTH_LEN
- auth_len
);
591 full_packet_data
= (unsigned char *)prs_data_p(current_pdu
);
592 full_packet_data_len
= prhdr
->frag_len
- auth_len
;
594 /* Pull the auth header and the following data into a blob. */
595 if(!prs_set_offset(current_pdu
, RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ data_len
)) {
596 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
597 (unsigned int)RPC_HEADER_LEN
+ (unsigned int)RPC_HDR_RESP_LEN
+ (unsigned int)data_len
));
598 return NT_STATUS_BUFFER_TOO_SMALL
;
601 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info
, current_pdu
, 0)) {
602 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
603 return NT_STATUS_BUFFER_TOO_SMALL
;
606 auth_blob
.data
= (unsigned char *)prs_data_p(current_pdu
) + prs_offset(current_pdu
);
607 auth_blob
.length
= auth_len
;
609 switch (cli
->auth
->auth_level
) {
610 case DCERPC_AUTH_LEVEL_PRIVACY
:
611 /* Data is encrypted. */
612 status
= ntlmssp_unseal_packet(ntlmssp_state
,
615 full_packet_data_len
,
617 if (!NT_STATUS_IS_OK(status
)) {
618 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
619 "packet from %s. Error was %s.\n",
620 rpccli_pipe_txt(debug_ctx(), cli
),
621 nt_errstr(status
) ));
625 case DCERPC_AUTH_LEVEL_INTEGRITY
:
626 /* Data is signed. */
627 status
= ntlmssp_check_packet(ntlmssp_state
,
630 full_packet_data_len
,
632 if (!NT_STATUS_IS_OK(status
)) {
633 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
634 "packet from %s. Error was %s.\n",
635 rpccli_pipe_txt(debug_ctx(), cli
),
636 nt_errstr(status
) ));
641 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
642 "auth level %d\n", cli
->auth
->auth_level
));
643 return NT_STATUS_INVALID_INFO_CLASS
;
647 * Return the current pointer to the data offset.
650 if(!prs_set_offset(current_pdu
, save_offset
)) {
651 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
652 (unsigned int)save_offset
));
653 return NT_STATUS_BUFFER_TOO_SMALL
;
657 * Remember the padding length. We must remove it from the real data
658 * stream once the sign/seal is done.
661 *p_ss_padding_len
= auth_info
.auth_pad_len
;
666 /****************************************************************************
667 schannel specific sign/seal.
668 ****************************************************************************/
670 static NTSTATUS
cli_pipe_verify_schannel(struct rpc_pipe_client
*cli
, RPC_HDR
*prhdr
,
671 prs_struct
*current_pdu
,
672 uint8
*p_ss_padding_len
)
674 RPC_HDR_AUTH auth_info
;
675 struct NL_AUTH_SIGNATURE schannel_chk
;
676 uint32 auth_len
= prhdr
->auth_len
;
677 uint32 save_offset
= prs_offset(current_pdu
);
678 struct schannel_state
*schannel_auth
=
679 cli
->auth
->a_u
.schannel_auth
;
681 enum ndr_err_code ndr_err
;
685 if (cli
->auth
->auth_level
== DCERPC_AUTH_LEVEL_NONE
686 || cli
->auth
->auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
690 if (auth_len
< RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN
) {
691 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len
));
692 return NT_STATUS_INVALID_PARAMETER
;
695 if (!schannel_auth
) {
696 return NT_STATUS_INVALID_PARAMETER
;
699 /* Ensure there's enough data for an authenticated response. */
700 if ((auth_len
> RPC_MAX_SIGN_SIZE
) ||
701 (RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ RPC_HDR_AUTH_LEN
+ auth_len
> prhdr
->frag_len
)) {
702 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
703 (unsigned int)auth_len
));
704 return NT_STATUS_INVALID_PARAMETER
;
707 data_len
= prhdr
->frag_len
- RPC_HEADER_LEN
- RPC_HDR_RESP_LEN
- RPC_HDR_AUTH_LEN
- auth_len
;
709 if(!prs_set_offset(current_pdu
, RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ data_len
)) {
710 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
711 (unsigned int)RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ data_len
));
712 return NT_STATUS_BUFFER_TOO_SMALL
;
715 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info
, current_pdu
, 0)) {
716 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
717 return NT_STATUS_BUFFER_TOO_SMALL
;
720 if (auth_info
.auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
721 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
722 auth_info
.auth_type
));
723 return NT_STATUS_BUFFER_TOO_SMALL
;
726 blob
= data_blob_const(prs_data_p(current_pdu
) + prs_offset(current_pdu
), auth_len
);
728 ndr_err
= ndr_pull_struct_blob(&blob
, talloc_tos(), NULL
, &schannel_chk
,
729 (ndr_pull_flags_fn_t
)ndr_pull_NL_AUTH_SIGNATURE
);
730 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
731 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
732 return ndr_map_error2ntstatus(ndr_err
);
735 if (DEBUGLEVEL
>= 10) {
736 NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE
, &schannel_chk
);
739 switch (cli
->auth
->auth_level
) {
740 case DCERPC_AUTH_LEVEL_PRIVACY
:
741 status
= schannel_unseal_packet(schannel_auth
,
743 (uint8_t *)prs_data_p(current_pdu
)+RPC_HEADER_LEN
+RPC_HDR_RESP_LEN
,
747 case DCERPC_AUTH_LEVEL_INTEGRITY
:
748 status
= schannel_check_packet(schannel_auth
,
750 (uint8_t *)prs_data_p(current_pdu
)+RPC_HEADER_LEN
+RPC_HDR_RESP_LEN
,
755 status
= NT_STATUS_INTERNAL_ERROR
;
759 if (!NT_STATUS_IS_OK(status
)) {
760 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
761 "Connection to %s (%s).\n",
762 rpccli_pipe_txt(debug_ctx(), cli
),
764 return NT_STATUS_INVALID_PARAMETER
;
768 * Return the current pointer to the data offset.
771 if(!prs_set_offset(current_pdu
, save_offset
)) {
772 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
773 (unsigned int)save_offset
));
774 return NT_STATUS_BUFFER_TOO_SMALL
;
778 * Remember the padding length. We must remove it from the real data
779 * stream once the sign/seal is done.
782 *p_ss_padding_len
= auth_info
.auth_pad_len
;
787 /****************************************************************************
788 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
789 ****************************************************************************/
791 static NTSTATUS
cli_pipe_validate_rpc_response(struct rpc_pipe_client
*cli
, RPC_HDR
*prhdr
,
792 prs_struct
*current_pdu
,
793 uint8
*p_ss_padding_len
)
795 NTSTATUS ret
= NT_STATUS_OK
;
797 /* Paranioa checks for auth_len. */
798 if (prhdr
->auth_len
) {
799 if (prhdr
->auth_len
> prhdr
->frag_len
) {
800 return NT_STATUS_INVALID_PARAMETER
;
803 if (prhdr
->auth_len
+ (unsigned int)RPC_HDR_AUTH_LEN
< prhdr
->auth_len
||
804 prhdr
->auth_len
+ (unsigned int)RPC_HDR_AUTH_LEN
< (unsigned int)RPC_HDR_AUTH_LEN
) {
805 /* Integer wrap attempt. */
806 return NT_STATUS_INVALID_PARAMETER
;
811 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
814 switch(cli
->auth
->auth_type
) {
815 case PIPE_AUTH_TYPE_NONE
:
816 if (prhdr
->auth_len
) {
817 DEBUG(3, ("cli_pipe_validate_rpc_response: "
818 "Connection to %s - got non-zero "
820 rpccli_pipe_txt(debug_ctx(), cli
),
821 (unsigned int)prhdr
->auth_len
));
822 return NT_STATUS_INVALID_PARAMETER
;
826 case PIPE_AUTH_TYPE_NTLMSSP
:
827 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
828 ret
= cli_pipe_verify_ntlmssp(cli
, prhdr
, current_pdu
, p_ss_padding_len
);
829 if (!NT_STATUS_IS_OK(ret
)) {
834 case PIPE_AUTH_TYPE_SCHANNEL
:
835 ret
= cli_pipe_verify_schannel(cli
, prhdr
, current_pdu
, p_ss_padding_len
);
836 if (!NT_STATUS_IS_OK(ret
)) {
841 case PIPE_AUTH_TYPE_KRB5
:
842 case PIPE_AUTH_TYPE_SPNEGO_KRB5
:
844 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
845 "to %s - unknown internal auth type %u.\n",
846 rpccli_pipe_txt(debug_ctx(), cli
),
847 cli
->auth
->auth_type
));
848 return NT_STATUS_INVALID_INFO_CLASS
;
854 /****************************************************************************
855 Do basic authentication checks on an incoming pdu.
856 ****************************************************************************/
858 static NTSTATUS
cli_pipe_validate_current_pdu(struct rpc_pipe_client
*cli
, RPC_HDR
*prhdr
,
859 prs_struct
*current_pdu
,
860 uint8 expected_pkt_type
,
863 prs_struct
*return_data
)
866 NTSTATUS ret
= NT_STATUS_OK
;
867 uint32 current_pdu_len
= prs_data_size(current_pdu
);
869 if (current_pdu_len
!= prhdr
->frag_len
) {
870 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
871 (unsigned int)current_pdu_len
, (unsigned int)prhdr
->frag_len
));
872 return NT_STATUS_INVALID_PARAMETER
;
876 * Point the return values at the real data including the RPC
877 * header. Just in case the caller wants it.
879 *ppdata
= prs_data_p(current_pdu
);
880 *pdata_len
= current_pdu_len
;
882 /* Ensure we have the correct type. */
883 switch (prhdr
->pkt_type
) {
884 case RPC_ALTCONTRESP
:
887 /* Alter context and bind ack share the same packet definitions. */
893 RPC_HDR_RESP rhdr_resp
;
894 uint8 ss_padding_len
= 0;
896 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp
, current_pdu
, 0)) {
897 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
898 return NT_STATUS_BUFFER_TOO_SMALL
;
901 /* Here's where we deal with incoming sign/seal. */
902 ret
= cli_pipe_validate_rpc_response(cli
, prhdr
,
903 current_pdu
, &ss_padding_len
);
904 if (!NT_STATUS_IS_OK(ret
)) {
908 /* Point the return values at the NDR data. Remember to remove any ss padding. */
909 *ppdata
= prs_data_p(current_pdu
) + RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
;
911 if (current_pdu_len
< RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
+ ss_padding_len
) {
912 return NT_STATUS_BUFFER_TOO_SMALL
;
915 *pdata_len
= current_pdu_len
- RPC_HEADER_LEN
- RPC_HDR_RESP_LEN
- ss_padding_len
;
917 /* Remember to remove the auth footer. */
918 if (prhdr
->auth_len
) {
919 /* We've already done integer wrap tests on auth_len in
920 cli_pipe_validate_rpc_response(). */
921 if (*pdata_len
< RPC_HDR_AUTH_LEN
+ prhdr
->auth_len
) {
922 return NT_STATUS_BUFFER_TOO_SMALL
;
924 *pdata_len
-= (RPC_HDR_AUTH_LEN
+ prhdr
->auth_len
);
927 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
928 current_pdu_len
, *pdata_len
, ss_padding_len
));
931 * If this is the first reply, and the allocation hint is reasonably, try and
932 * set up the return_data parse_struct to the correct size.
935 if ((prs_data_size(return_data
) == 0) && rhdr_resp
.alloc_hint
&& (rhdr_resp
.alloc_hint
< 15*1024*1024)) {
936 if (!prs_set_buffer_size(return_data
, rhdr_resp
.alloc_hint
)) {
937 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
938 "too large to allocate\n",
939 (unsigned int)rhdr_resp
.alloc_hint
));
940 return NT_STATUS_NO_MEMORY
;
948 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
949 "received from %s!\n",
950 rpccli_pipe_txt(debug_ctx(), cli
)));
951 /* Use this for now... */
952 return NT_STATUS_NETWORK_ACCESS_DENIED
;
956 RPC_HDR_RESP rhdr_resp
;
957 RPC_HDR_FAULT fault_resp
;
959 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp
, current_pdu
, 0)) {
960 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
961 return NT_STATUS_BUFFER_TOO_SMALL
;
964 if(!smb_io_rpc_hdr_fault("fault", &fault_resp
, current_pdu
, 0)) {
965 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
966 return NT_STATUS_BUFFER_TOO_SMALL
;
969 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
970 "code %s received from %s!\n",
971 dcerpc_errstr(debug_ctx(), NT_STATUS_V(fault_resp
.status
)),
972 rpccli_pipe_txt(debug_ctx(), cli
)));
973 if (NT_STATUS_IS_OK(fault_resp
.status
)) {
974 return NT_STATUS_UNSUCCESSFUL
;
976 return fault_resp
.status
;
981 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
983 (unsigned int)prhdr
->pkt_type
,
984 rpccli_pipe_txt(debug_ctx(), cli
)));
985 return NT_STATUS_INVALID_INFO_CLASS
;
988 if (prhdr
->pkt_type
!= expected_pkt_type
) {
989 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
990 "got an unexpected RPC packet type - %u, not %u\n",
991 rpccli_pipe_txt(debug_ctx(), cli
),
994 return NT_STATUS_INVALID_INFO_CLASS
;
997 /* Do this just before return - we don't want to modify any rpc header
998 data before now as we may have needed to do cryptographic actions on
1001 if ((prhdr
->pkt_type
== RPC_BINDACK
) && !(prhdr
->flags
& RPC_FLG_LAST
)) {
1002 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1003 "setting fragment first/last ON.\n"));
1004 prhdr
->flags
|= RPC_FLG_FIRST
|RPC_FLG_LAST
;
1007 return NT_STATUS_OK
;
1010 /****************************************************************************
1011 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1012 Normally the frag_len and buffer size will match, but on the first trans
1013 reply there is a theoretical chance that buffer size > frag_len, so we must
1015 ****************************************************************************/
1017 static NTSTATUS
cli_pipe_reset_current_pdu(struct rpc_pipe_client
*cli
, RPC_HDR
*prhdr
, prs_struct
*current_pdu
)
1019 uint32 current_pdu_len
= prs_data_size(current_pdu
);
1021 if (current_pdu_len
< prhdr
->frag_len
) {
1022 return NT_STATUS_BUFFER_TOO_SMALL
;
1026 if (current_pdu_len
== (uint32
)prhdr
->frag_len
) {
1027 prs_mem_free(current_pdu
);
1028 prs_init_empty(current_pdu
, prs_get_mem_context(current_pdu
), UNMARSHALL
);
1029 /* Make current_pdu dynamic with no memory. */
1030 prs_give_memory(current_pdu
, 0, 0, True
);
1031 return NT_STATUS_OK
;
1035 * Oh no ! More data in buffer than we processed in current pdu.
1036 * Cheat. Move the data down and shrink the buffer.
1039 memcpy(prs_data_p(current_pdu
), prs_data_p(current_pdu
) + prhdr
->frag_len
,
1040 current_pdu_len
- prhdr
->frag_len
);
1042 /* Remember to set the read offset back to zero. */
1043 prs_set_offset(current_pdu
, 0);
1045 /* Shrink the buffer. */
1046 if (!prs_set_buffer_size(current_pdu
, current_pdu_len
- prhdr
->frag_len
)) {
1047 return NT_STATUS_BUFFER_TOO_SMALL
;
1050 return NT_STATUS_OK
;
1053 /****************************************************************************
1054 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1055 ****************************************************************************/
1057 struct cli_api_pipe_state
{
1058 struct event_context
*ev
;
1059 struct rpc_cli_transport
*transport
;
1064 static void cli_api_pipe_trans_done(struct tevent_req
*subreq
);
1065 static void cli_api_pipe_write_done(struct tevent_req
*subreq
);
1066 static void cli_api_pipe_read_done(struct tevent_req
*subreq
);
1068 static struct tevent_req
*cli_api_pipe_send(TALLOC_CTX
*mem_ctx
,
1069 struct event_context
*ev
,
1070 struct rpc_cli_transport
*transport
,
1071 uint8_t *data
, size_t data_len
,
1072 uint32_t max_rdata_len
)
1074 struct tevent_req
*req
, *subreq
;
1075 struct cli_api_pipe_state
*state
;
1078 req
= tevent_req_create(mem_ctx
, &state
, struct cli_api_pipe_state
);
1083 state
->transport
= transport
;
1085 if (max_rdata_len
< RPC_HEADER_LEN
) {
1087 * For a RPC reply we always need at least RPC_HEADER_LEN
1088 * bytes. We check this here because we will receive
1089 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1091 status
= NT_STATUS_INVALID_PARAMETER
;
1095 if (transport
->trans_send
!= NULL
) {
1096 subreq
= transport
->trans_send(state
, ev
, data
, data_len
,
1097 max_rdata_len
, transport
->priv
);
1098 if (subreq
== NULL
) {
1101 tevent_req_set_callback(subreq
, cli_api_pipe_trans_done
, req
);
1106 * If the transport does not provide a "trans" routine, i.e. for
1107 * example the ncacn_ip_tcp transport, do the write/read step here.
1110 subreq
= rpc_write_send(state
, ev
, transport
, data
, data_len
);
1111 if (subreq
== NULL
) {
1114 tevent_req_set_callback(subreq
, cli_api_pipe_write_done
, req
);
1117 status
= NT_STATUS_INVALID_PARAMETER
;
1120 tevent_req_nterror(req
, status
);
1121 return tevent_req_post(req
, ev
);
1127 static void cli_api_pipe_trans_done(struct tevent_req
*subreq
)
1129 struct tevent_req
*req
= tevent_req_callback_data(
1130 subreq
, struct tevent_req
);
1131 struct cli_api_pipe_state
*state
= tevent_req_data(
1132 req
, struct cli_api_pipe_state
);
1135 status
= state
->transport
->trans_recv(subreq
, state
, &state
->rdata
,
1137 TALLOC_FREE(subreq
);
1138 if (!NT_STATUS_IS_OK(status
)) {
1139 tevent_req_nterror(req
, status
);
1142 tevent_req_done(req
);
1145 static void cli_api_pipe_write_done(struct tevent_req
*subreq
)
1147 struct tevent_req
*req
= tevent_req_callback_data(
1148 subreq
, struct tevent_req
);
1149 struct cli_api_pipe_state
*state
= tevent_req_data(
1150 req
, struct cli_api_pipe_state
);
1153 status
= rpc_write_recv(subreq
);
1154 TALLOC_FREE(subreq
);
1155 if (!NT_STATUS_IS_OK(status
)) {
1156 tevent_req_nterror(req
, status
);
1160 state
->rdata
= TALLOC_ARRAY(state
, uint8_t, RPC_HEADER_LEN
);
1161 if (tevent_req_nomem(state
->rdata
, req
)) {
1166 * We don't need to use rpc_read_send here, the upper layer will cope
1167 * with a short read, transport->trans_send could also return less
1168 * than state->max_rdata_len.
1170 subreq
= state
->transport
->read_send(state
, state
->ev
, state
->rdata
,
1172 state
->transport
->priv
);
1173 if (tevent_req_nomem(subreq
, req
)) {
1176 tevent_req_set_callback(subreq
, cli_api_pipe_read_done
, req
);
1179 static void cli_api_pipe_read_done(struct tevent_req
*subreq
)
1181 struct tevent_req
*req
= tevent_req_callback_data(
1182 subreq
, struct tevent_req
);
1183 struct cli_api_pipe_state
*state
= tevent_req_data(
1184 req
, struct cli_api_pipe_state
);
1188 status
= state
->transport
->read_recv(subreq
, &received
);
1189 TALLOC_FREE(subreq
);
1190 if (!NT_STATUS_IS_OK(status
)) {
1191 tevent_req_nterror(req
, status
);
1194 state
->rdata_len
= received
;
1195 tevent_req_done(req
);
1198 static NTSTATUS
cli_api_pipe_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
1199 uint8_t **prdata
, uint32_t *prdata_len
)
1201 struct cli_api_pipe_state
*state
= tevent_req_data(
1202 req
, struct cli_api_pipe_state
);
1205 if (tevent_req_is_nterror(req
, &status
)) {
1209 *prdata
= talloc_move(mem_ctx
, &state
->rdata
);
1210 *prdata_len
= state
->rdata_len
;
1211 return NT_STATUS_OK
;
1214 /****************************************************************************
1215 Send data on an rpc pipe via trans. The prs_struct data must be the last
1216 pdu fragment of an NDR data stream.
1218 Receive response data from an rpc pipe, which may be large...
1220 Read the first fragment: unfortunately have to use SMBtrans for the first
1221 bit, then SMBreadX for subsequent bits.
1223 If first fragment received also wasn't the last fragment, continue
1224 getting fragments until we _do_ receive the last fragment.
1226 Request/Response PDU's look like the following...
1228 |<------------------PDU len----------------------------------------------->|
1229 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1231 +------------+-----------------+-------------+---------------+-------------+
1232 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1233 +------------+-----------------+-------------+---------------+-------------+
1235 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1236 signing & sealing being negotiated.
1238 ****************************************************************************/
1240 struct rpc_api_pipe_state
{
1241 struct event_context
*ev
;
1242 struct rpc_pipe_client
*cli
;
1243 uint8_t expected_pkt_type
;
1245 prs_struct incoming_frag
;
1246 struct rpc_hdr_info rhdr
;
1248 prs_struct incoming_pdu
; /* Incoming reply */
1249 uint32_t incoming_pdu_offset
;
1252 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state
*state
)
1254 prs_mem_free(&state
->incoming_frag
);
1255 prs_mem_free(&state
->incoming_pdu
);
1259 static void rpc_api_pipe_trans_done(struct tevent_req
*subreq
);
1260 static void rpc_api_pipe_got_pdu(struct tevent_req
*subreq
);
1262 static struct tevent_req
*rpc_api_pipe_send(TALLOC_CTX
*mem_ctx
,
1263 struct event_context
*ev
,
1264 struct rpc_pipe_client
*cli
,
1265 prs_struct
*data
, /* Outgoing PDU */
1266 uint8_t expected_pkt_type
)
1268 struct tevent_req
*req
, *subreq
;
1269 struct rpc_api_pipe_state
*state
;
1270 uint16_t max_recv_frag
;
1273 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_api_pipe_state
);
1279 state
->expected_pkt_type
= expected_pkt_type
;
1280 state
->incoming_pdu_offset
= 0;
1282 prs_init_empty(&state
->incoming_frag
, state
, UNMARSHALL
);
1284 prs_init_empty(&state
->incoming_pdu
, state
, UNMARSHALL
);
1285 /* Make incoming_pdu dynamic with no memory. */
1286 prs_give_memory(&state
->incoming_pdu
, NULL
, 0, true);
1288 talloc_set_destructor(state
, rpc_api_pipe_state_destructor
);
1291 * Ensure we're not sending too much.
1293 if (prs_offset(data
) > cli
->max_xmit_frag
) {
1294 status
= NT_STATUS_INVALID_PARAMETER
;
1298 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli
)));
1300 max_recv_frag
= cli
->max_recv_frag
;
1303 max_recv_frag
= RPC_HEADER_LEN
+ 10 + (sys_random() % 32);
1306 subreq
= cli_api_pipe_send(state
, ev
, cli
->transport
,
1307 (uint8_t *)prs_data_p(data
),
1308 prs_offset(data
), max_recv_frag
);
1309 if (subreq
== NULL
) {
1312 tevent_req_set_callback(subreq
, rpc_api_pipe_trans_done
, req
);
1316 tevent_req_nterror(req
, status
);
1317 return tevent_req_post(req
, ev
);
1323 static void rpc_api_pipe_trans_done(struct tevent_req
*subreq
)
1325 struct tevent_req
*req
= tevent_req_callback_data(
1326 subreq
, struct tevent_req
);
1327 struct rpc_api_pipe_state
*state
= tevent_req_data(
1328 req
, struct rpc_api_pipe_state
);
1330 uint8_t *rdata
= NULL
;
1331 uint32_t rdata_len
= 0;
1334 status
= cli_api_pipe_recv(subreq
, state
, &rdata
, &rdata_len
);
1335 TALLOC_FREE(subreq
);
1336 if (!NT_STATUS_IS_OK(status
)) {
1337 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status
)));
1338 tevent_req_nterror(req
, status
);
1342 if (rdata
== NULL
) {
1343 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1344 rpccli_pipe_txt(debug_ctx(), state
->cli
)));
1345 tevent_req_done(req
);
1350 * Give the memory received from cli_trans as dynamic to the current
1351 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1354 rdata_copy
= (char *)memdup(rdata
, rdata_len
);
1356 if (tevent_req_nomem(rdata_copy
, req
)) {
1359 prs_give_memory(&state
->incoming_frag
, rdata_copy
, rdata_len
, true);
1361 /* Ensure we have enough data for a pdu. */
1362 subreq
= get_complete_frag_send(state
, state
->ev
, state
->cli
,
1363 &state
->rhdr
, &state
->incoming_frag
);
1364 if (tevent_req_nomem(subreq
, req
)) {
1367 tevent_req_set_callback(subreq
, rpc_api_pipe_got_pdu
, req
);
1370 static void rpc_api_pipe_got_pdu(struct tevent_req
*subreq
)
1372 struct tevent_req
*req
= tevent_req_callback_data(
1373 subreq
, struct tevent_req
);
1374 struct rpc_api_pipe_state
*state
= tevent_req_data(
1375 req
, struct rpc_api_pipe_state
);
1378 uint32_t rdata_len
= 0;
1380 status
= get_complete_frag_recv(subreq
);
1381 TALLOC_FREE(subreq
);
1382 if (!NT_STATUS_IS_OK(status
)) {
1383 DEBUG(5, ("get_complete_frag failed: %s\n",
1384 nt_errstr(status
)));
1385 tevent_req_nterror(req
, status
);
1389 status
= cli_pipe_validate_current_pdu(
1390 state
->cli
, &state
->rhdr
, &state
->incoming_frag
,
1391 state
->expected_pkt_type
, &rdata
, &rdata_len
,
1392 &state
->incoming_pdu
);
1394 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1395 (unsigned)prs_data_size(&state
->incoming_frag
),
1396 (unsigned)state
->incoming_pdu_offset
,
1397 nt_errstr(status
)));
1399 if (!NT_STATUS_IS_OK(status
)) {
1400 tevent_req_nterror(req
, status
);
1404 if ((state
->rhdr
.flags
& RPC_FLG_FIRST
)
1405 && (state
->rhdr
.pack_type
[0] == 0)) {
1407 * Set the data type correctly for big-endian data on the
1410 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1412 rpccli_pipe_txt(debug_ctx(), state
->cli
)));
1413 prs_set_endian_data(&state
->incoming_pdu
, RPC_BIG_ENDIAN
);
1416 * Check endianness on subsequent packets.
1418 if (state
->incoming_frag
.bigendian_data
1419 != state
->incoming_pdu
.bigendian_data
) {
1420 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1422 state
->incoming_pdu
.bigendian_data
?"big":"little",
1423 state
->incoming_frag
.bigendian_data
?"big":"little"));
1424 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1428 /* Now copy the data portion out of the pdu into rbuf. */
1429 if (!prs_force_grow(&state
->incoming_pdu
, rdata_len
)) {
1430 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1434 memcpy(prs_data_p(&state
->incoming_pdu
) + state
->incoming_pdu_offset
,
1435 rdata
, (size_t)rdata_len
);
1436 state
->incoming_pdu_offset
+= rdata_len
;
1438 status
= cli_pipe_reset_current_pdu(state
->cli
, &state
->rhdr
,
1439 &state
->incoming_frag
);
1440 if (!NT_STATUS_IS_OK(status
)) {
1441 tevent_req_nterror(req
, status
);
1445 if (state
->rhdr
.flags
& RPC_FLG_LAST
) {
1446 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1447 rpccli_pipe_txt(debug_ctx(), state
->cli
),
1448 (unsigned)prs_data_size(&state
->incoming_pdu
)));
1449 tevent_req_done(req
);
1453 subreq
= get_complete_frag_send(state
, state
->ev
, state
->cli
,
1454 &state
->rhdr
, &state
->incoming_frag
);
1455 if (tevent_req_nomem(subreq
, req
)) {
1458 tevent_req_set_callback(subreq
, rpc_api_pipe_got_pdu
, req
);
1461 static NTSTATUS
rpc_api_pipe_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
1462 prs_struct
*reply_pdu
)
1464 struct rpc_api_pipe_state
*state
= tevent_req_data(
1465 req
, struct rpc_api_pipe_state
);
1468 if (tevent_req_is_nterror(req
, &status
)) {
1472 *reply_pdu
= state
->incoming_pdu
;
1473 reply_pdu
->mem_ctx
= mem_ctx
;
1476 * Prevent state->incoming_pdu from being freed in
1477 * rpc_api_pipe_state_destructor()
1479 prs_init_empty(&state
->incoming_pdu
, state
, UNMARSHALL
);
1481 return NT_STATUS_OK
;
1484 /*******************************************************************
1485 Creates krb5 auth bind.
1486 ********************************************************************/
1488 static NTSTATUS
create_krb5_auth_bind_req( struct rpc_pipe_client
*cli
,
1489 enum dcerpc_AuthLevel auth_level
,
1490 RPC_HDR_AUTH
*pauth_out
,
1491 prs_struct
*auth_data
)
1495 struct kerberos_auth_struct
*a
= cli
->auth
->a_u
.kerberos_auth
;
1496 DATA_BLOB tkt
= data_blob_null
;
1497 DATA_BLOB tkt_wrapped
= data_blob_null
;
1499 /* We may change the pad length before marshalling. */
1500 init_rpc_hdr_auth(pauth_out
, DCERPC_AUTH_TYPE_KRB5
, (int)auth_level
, 0, 1);
1502 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1503 a
->service_principal
));
1505 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1507 ret
= cli_krb5_get_ticket(a
->service_principal
, 0, &tkt
,
1508 &a
->session_key
, (uint32
)AP_OPTS_MUTUAL_REQUIRED
, NULL
, NULL
);
1511 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1513 a
->service_principal
,
1514 error_message(ret
) ));
1516 data_blob_free(&tkt
);
1517 prs_mem_free(auth_data
);
1518 return NT_STATUS_INVALID_PARAMETER
;
1521 /* wrap that up in a nice GSS-API wrapping */
1522 tkt_wrapped
= spnego_gen_krb5_wrap(tkt
, TOK_ID_KRB_AP_REQ
);
1524 data_blob_free(&tkt
);
1526 /* Auth len in the rpc header doesn't include auth_header. */
1527 if (!prs_copy_data_in(auth_data
, (char *)tkt_wrapped
.data
, tkt_wrapped
.length
)) {
1528 data_blob_free(&tkt_wrapped
);
1529 prs_mem_free(auth_data
);
1530 return NT_STATUS_NO_MEMORY
;
1533 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1534 dump_data(5, tkt_wrapped
.data
, tkt_wrapped
.length
);
1536 data_blob_free(&tkt_wrapped
);
1537 return NT_STATUS_OK
;
1539 return NT_STATUS_INVALID_PARAMETER
;
1543 /*******************************************************************
1544 Creates SPNEGO NTLMSSP auth bind.
1545 ********************************************************************/
1547 static NTSTATUS
create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client
*cli
,
1548 enum dcerpc_AuthLevel auth_level
,
1549 RPC_HDR_AUTH
*pauth_out
,
1550 prs_struct
*auth_data
)
1553 DATA_BLOB null_blob
= data_blob_null
;
1554 DATA_BLOB request
= data_blob_null
;
1555 DATA_BLOB spnego_msg
= data_blob_null
;
1557 /* We may change the pad length before marshalling. */
1558 init_rpc_hdr_auth(pauth_out
, DCERPC_AUTH_TYPE_SPNEGO
, (int)auth_level
, 0, 1);
1560 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1561 nt_status
= ntlmssp_update(cli
->auth
->a_u
.ntlmssp_state
,
1565 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1566 data_blob_free(&request
);
1567 prs_mem_free(auth_data
);
1571 /* Wrap this in SPNEGO. */
1572 spnego_msg
= gen_negTokenInit(OID_NTLMSSP
, request
);
1574 data_blob_free(&request
);
1576 /* Auth len in the rpc header doesn't include auth_header. */
1577 if (!prs_copy_data_in(auth_data
, (char *)spnego_msg
.data
, spnego_msg
.length
)) {
1578 data_blob_free(&spnego_msg
);
1579 prs_mem_free(auth_data
);
1580 return NT_STATUS_NO_MEMORY
;
1583 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1584 dump_data(5, spnego_msg
.data
, spnego_msg
.length
);
1586 data_blob_free(&spnego_msg
);
1587 return NT_STATUS_OK
;
1590 /*******************************************************************
1591 Creates NTLMSSP auth bind.
1592 ********************************************************************/
1594 static NTSTATUS
create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client
*cli
,
1595 enum dcerpc_AuthLevel auth_level
,
1596 RPC_HDR_AUTH
*pauth_out
,
1597 prs_struct
*auth_data
)
1600 DATA_BLOB null_blob
= data_blob_null
;
1601 DATA_BLOB request
= data_blob_null
;
1603 /* We may change the pad length before marshalling. */
1604 init_rpc_hdr_auth(pauth_out
, DCERPC_AUTH_TYPE_NTLMSSP
, (int)auth_level
, 0, 1);
1606 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1607 nt_status
= ntlmssp_update(cli
->auth
->a_u
.ntlmssp_state
,
1611 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1612 data_blob_free(&request
);
1613 prs_mem_free(auth_data
);
1617 /* Auth len in the rpc header doesn't include auth_header. */
1618 if (!prs_copy_data_in(auth_data
, (char *)request
.data
, request
.length
)) {
1619 data_blob_free(&request
);
1620 prs_mem_free(auth_data
);
1621 return NT_STATUS_NO_MEMORY
;
1624 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1625 dump_data(5, request
.data
, request
.length
);
1627 data_blob_free(&request
);
1628 return NT_STATUS_OK
;
1631 /*******************************************************************
1632 Creates schannel auth bind.
1633 ********************************************************************/
1635 static NTSTATUS
create_schannel_auth_rpc_bind_req( struct rpc_pipe_client
*cli
,
1636 enum dcerpc_AuthLevel auth_level
,
1637 RPC_HDR_AUTH
*pauth_out
,
1638 prs_struct
*auth_data
)
1640 struct NL_AUTH_MESSAGE r
;
1641 enum ndr_err_code ndr_err
;
1644 /* We may change the pad length before marshalling. */
1645 init_rpc_hdr_auth(pauth_out
, DCERPC_AUTH_TYPE_SCHANNEL
, (int)auth_level
, 0, 1);
1647 /* Use lp_workgroup() if domain not specified */
1649 if (!cli
->auth
->domain
|| !cli
->auth
->domain
[0]) {
1650 cli
->auth
->domain
= talloc_strdup(cli
, lp_workgroup());
1651 if (cli
->auth
->domain
== NULL
) {
1652 return NT_STATUS_NO_MEMORY
;
1657 * Now marshall the data into the auth parse_struct.
1660 r
.MessageType
= NL_NEGOTIATE_REQUEST
;
1661 r
.Flags
= NL_FLAG_OEM_NETBIOS_DOMAIN_NAME
|
1662 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME
;
1663 r
.oem_netbios_domain
.a
= cli
->auth
->domain
;
1664 r
.oem_netbios_computer
.a
= global_myname();
1666 ndr_err
= ndr_push_struct_blob(&blob
, talloc_tos(), NULL
, &r
,
1667 (ndr_push_flags_fn_t
)ndr_push_NL_AUTH_MESSAGE
);
1668 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1669 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1670 prs_mem_free(auth_data
);
1671 return ndr_map_error2ntstatus(ndr_err
);
1674 if (DEBUGLEVEL
>= 10) {
1675 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE
, &r
);
1678 if (!prs_copy_data_in(auth_data
, (const char *)blob
.data
, blob
.length
))
1680 prs_mem_free(auth_data
);
1681 return NT_STATUS_NO_MEMORY
;
1684 return NT_STATUS_OK
;
1687 /*******************************************************************
1688 Creates the internals of a DCE/RPC bind request or alter context PDU.
1689 ********************************************************************/
1691 static NTSTATUS
create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type
,
1692 prs_struct
*rpc_out
,
1694 const struct ndr_syntax_id
*abstract
,
1695 const struct ndr_syntax_id
*transfer
,
1696 RPC_HDR_AUTH
*phdr_auth
,
1697 prs_struct
*pauth_info
)
1701 RPC_CONTEXT rpc_ctx
;
1702 uint16 auth_len
= prs_offset(pauth_info
);
1703 uint8 ss_padding_len
= 0;
1704 uint16 frag_len
= 0;
1706 /* create the RPC context. */
1707 init_rpc_context(&rpc_ctx
, 0 /* context id */, abstract
, transfer
);
1709 /* create the bind request RPC_HDR_RB */
1710 init_rpc_hdr_rb(&hdr_rb
, RPC_MAX_PDU_FRAG_LEN
, RPC_MAX_PDU_FRAG_LEN
, 0x0, &rpc_ctx
);
1712 /* Start building the frag length. */
1713 frag_len
= RPC_HEADER_LEN
+ RPC_HDR_RB_LEN(&hdr_rb
);
1715 /* Do we need to pad ? */
1717 uint16 data_len
= RPC_HEADER_LEN
+ RPC_HDR_RB_LEN(&hdr_rb
);
1719 ss_padding_len
= 8 - (data_len
% 8);
1720 phdr_auth
->auth_pad_len
= ss_padding_len
;
1722 frag_len
+= RPC_HDR_AUTH_LEN
+ auth_len
+ ss_padding_len
;
1725 /* Create the request RPC_HDR */
1726 init_rpc_hdr(&hdr
, pkt_type
, RPC_FLG_FIRST
|RPC_FLG_LAST
, rpc_call_id
, frag_len
, auth_len
);
1728 /* Marshall the RPC header */
1729 if(!smb_io_rpc_hdr("hdr" , &hdr
, rpc_out
, 0)) {
1730 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1731 return NT_STATUS_NO_MEMORY
;
1734 /* Marshall the bind request data */
1735 if(!smb_io_rpc_hdr_rb("", &hdr_rb
, rpc_out
, 0)) {
1736 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1737 return NT_STATUS_NO_MEMORY
;
1741 * Grow the outgoing buffer to store any auth info.
1745 if (ss_padding_len
) {
1747 memset(pad
, '\0', 8);
1748 if (!prs_copy_data_in(rpc_out
, pad
, ss_padding_len
)) {
1749 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1750 return NT_STATUS_NO_MEMORY
;
1754 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth
, rpc_out
, 0)) {
1755 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1756 return NT_STATUS_NO_MEMORY
;
1760 if(!prs_append_prs_data( rpc_out
, pauth_info
)) {
1761 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1762 return NT_STATUS_NO_MEMORY
;
1766 return NT_STATUS_OK
;
1769 /*******************************************************************
1770 Creates a DCE/RPC bind request.
1771 ********************************************************************/
1773 static NTSTATUS
create_rpc_bind_req(struct rpc_pipe_client
*cli
,
1774 prs_struct
*rpc_out
,
1776 const struct ndr_syntax_id
*abstract
,
1777 const struct ndr_syntax_id
*transfer
,
1778 enum pipe_auth_type auth_type
,
1779 enum dcerpc_AuthLevel auth_level
)
1781 RPC_HDR_AUTH hdr_auth
;
1782 prs_struct auth_info
;
1783 NTSTATUS ret
= NT_STATUS_OK
;
1785 ZERO_STRUCT(hdr_auth
);
1786 if (!prs_init(&auth_info
, RPC_HDR_AUTH_LEN
, prs_get_mem_context(rpc_out
), MARSHALL
))
1787 return NT_STATUS_NO_MEMORY
;
1789 switch (auth_type
) {
1790 case PIPE_AUTH_TYPE_SCHANNEL
:
1791 ret
= create_schannel_auth_rpc_bind_req(cli
, auth_level
, &hdr_auth
, &auth_info
);
1792 if (!NT_STATUS_IS_OK(ret
)) {
1793 prs_mem_free(&auth_info
);
1798 case PIPE_AUTH_TYPE_NTLMSSP
:
1799 ret
= create_ntlmssp_auth_rpc_bind_req(cli
, auth_level
, &hdr_auth
, &auth_info
);
1800 if (!NT_STATUS_IS_OK(ret
)) {
1801 prs_mem_free(&auth_info
);
1806 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
1807 ret
= create_spnego_ntlmssp_auth_rpc_bind_req(cli
, auth_level
, &hdr_auth
, &auth_info
);
1808 if (!NT_STATUS_IS_OK(ret
)) {
1809 prs_mem_free(&auth_info
);
1814 case PIPE_AUTH_TYPE_KRB5
:
1815 ret
= create_krb5_auth_bind_req(cli
, auth_level
, &hdr_auth
, &auth_info
);
1816 if (!NT_STATUS_IS_OK(ret
)) {
1817 prs_mem_free(&auth_info
);
1822 case PIPE_AUTH_TYPE_NONE
:
1826 /* "Can't" happen. */
1827 return NT_STATUS_INVALID_INFO_CLASS
;
1830 ret
= create_bind_or_alt_ctx_internal(RPC_BIND
,
1838 prs_mem_free(&auth_info
);
1842 /*******************************************************************
1843 Create and add the NTLMSSP sign/seal auth header and data.
1844 ********************************************************************/
1846 static NTSTATUS
add_ntlmssp_auth_footer(struct rpc_pipe_client
*cli
,
1848 uint32 ss_padding_len
,
1849 prs_struct
*outgoing_pdu
)
1851 RPC_HDR_AUTH auth_info
;
1853 DATA_BLOB auth_blob
= data_blob_null
;
1854 uint16 data_and_pad_len
= prs_offset(outgoing_pdu
) - RPC_HEADER_LEN
- RPC_HDR_RESP_LEN
;
1856 if (!cli
->auth
->a_u
.ntlmssp_state
) {
1857 return NT_STATUS_INVALID_PARAMETER
;
1860 /* Init and marshall the auth header. */
1861 init_rpc_hdr_auth(&auth_info
,
1862 map_pipe_auth_type_to_rpc_auth_type(
1863 cli
->auth
->auth_type
),
1864 cli
->auth
->auth_level
,
1866 1 /* context id. */);
1868 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info
, outgoing_pdu
, 0)) {
1869 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1870 data_blob_free(&auth_blob
);
1871 return NT_STATUS_NO_MEMORY
;
1874 switch (cli
->auth
->auth_level
) {
1875 case DCERPC_AUTH_LEVEL_PRIVACY
:
1876 /* Data portion is encrypted. */
1877 status
= ntlmssp_seal_packet(cli
->auth
->a_u
.ntlmssp_state
,
1878 (unsigned char *)prs_data_p(outgoing_pdu
) + RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
,
1880 (unsigned char *)prs_data_p(outgoing_pdu
),
1881 (size_t)prs_offset(outgoing_pdu
),
1883 if (!NT_STATUS_IS_OK(status
)) {
1884 data_blob_free(&auth_blob
);
1889 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1890 /* Data is signed. */
1891 status
= ntlmssp_sign_packet(cli
->auth
->a_u
.ntlmssp_state
,
1892 (unsigned char *)prs_data_p(outgoing_pdu
) + RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
,
1894 (unsigned char *)prs_data_p(outgoing_pdu
),
1895 (size_t)prs_offset(outgoing_pdu
),
1897 if (!NT_STATUS_IS_OK(status
)) {
1898 data_blob_free(&auth_blob
);
1905 smb_panic("bad auth level");
1907 return NT_STATUS_INVALID_PARAMETER
;
1910 /* Finally marshall the blob. */
1912 if (!prs_copy_data_in(outgoing_pdu
, (const char *)auth_blob
.data
, NTLMSSP_SIG_SIZE
)) {
1913 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1914 (unsigned int)NTLMSSP_SIG_SIZE
));
1915 data_blob_free(&auth_blob
);
1916 return NT_STATUS_NO_MEMORY
;
1919 data_blob_free(&auth_blob
);
1920 return NT_STATUS_OK
;
1923 /*******************************************************************
1924 Create and add the schannel sign/seal auth header and data.
1925 ********************************************************************/
1927 static NTSTATUS
add_schannel_auth_footer(struct rpc_pipe_client
*cli
,
1929 uint32 ss_padding_len
,
1930 prs_struct
*outgoing_pdu
)
1932 RPC_HDR_AUTH auth_info
;
1933 struct NL_AUTH_SIGNATURE verf
;
1934 struct schannel_state
*sas
= cli
->auth
->a_u
.schannel_auth
;
1935 char *data_p
= prs_data_p(outgoing_pdu
) + RPC_HEADER_LEN
+ RPC_HDR_RESP_LEN
;
1936 size_t data_and_pad_len
= prs_offset(outgoing_pdu
) - RPC_HEADER_LEN
- RPC_HDR_RESP_LEN
;
1937 enum ndr_err_code ndr_err
;
1942 return NT_STATUS_INVALID_PARAMETER
;
1945 /* Init and marshall the auth header. */
1946 init_rpc_hdr_auth(&auth_info
,
1947 map_pipe_auth_type_to_rpc_auth_type(cli
->auth
->auth_type
),
1948 cli
->auth
->auth_level
,
1950 1 /* context id. */);
1952 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info
, outgoing_pdu
, 0)) {
1953 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1954 return NT_STATUS_NO_MEMORY
;
1957 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1960 switch (cli
->auth
->auth_level
) {
1961 case DCERPC_AUTH_LEVEL_PRIVACY
:
1962 status
= schannel_seal_packet(sas
,
1968 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1969 status
= schannel_sign_packet(sas
,
1976 status
= NT_STATUS_INTERNAL_ERROR
;
1980 if (!NT_STATUS_IS_OK(status
)) {
1981 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1982 nt_errstr(status
)));
1986 ndr_err
= ndr_push_struct_blob(&blob
, talloc_tos(), NULL
, &verf
,
1987 (ndr_push_flags_fn_t
)ndr_push_NL_AUTH_SIGNATURE
);
1988 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1989 return ndr_map_error2ntstatus(ndr_err
);
1992 if (DEBUGLEVEL
>= 10) {
1993 NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE
, &verf
);
1996 /* Finally marshall the blob. */
1997 if (!prs_copy_data_in(outgoing_pdu
, (const char *)blob
.data
, blob
.length
)) {
1998 return NT_STATUS_NO_MEMORY
;
2001 return NT_STATUS_OK
;
2004 /*******************************************************************
2005 Calculate how much data we're going to send in this packet, also
2006 work out any sign/seal padding length.
2007 ********************************************************************/
2009 static uint32
calculate_data_len_tosend(struct rpc_pipe_client
*cli
,
2013 uint32
*p_ss_padding
)
2015 uint32 data_space
, data_len
;
2018 if ((data_left
> 0) && (sys_random() % 2)) {
2019 data_left
= MAX(data_left
/2, 1);
2023 switch (cli
->auth
->auth_level
) {
2024 case DCERPC_AUTH_LEVEL_NONE
:
2025 case DCERPC_AUTH_LEVEL_CONNECT
:
2026 data_space
= cli
->max_xmit_frag
- RPC_HEADER_LEN
- RPC_HDR_REQ_LEN
;
2027 data_len
= MIN(data_space
, data_left
);
2030 *p_frag_len
= RPC_HEADER_LEN
+ RPC_HDR_REQ_LEN
+ data_len
;
2033 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2034 case DCERPC_AUTH_LEVEL_PRIVACY
:
2035 /* Treat the same for all authenticated rpc requests. */
2036 switch(cli
->auth
->auth_type
) {
2037 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
2038 case PIPE_AUTH_TYPE_NTLMSSP
:
2039 *p_auth_len
= NTLMSSP_SIG_SIZE
;
2041 case PIPE_AUTH_TYPE_SCHANNEL
:
2042 *p_auth_len
= RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN
;
2045 smb_panic("bad auth type");
2049 data_space
= cli
->max_xmit_frag
- RPC_HEADER_LEN
- RPC_HDR_REQ_LEN
-
2050 RPC_HDR_AUTH_LEN
- *p_auth_len
;
2052 data_len
= MIN(data_space
, data_left
);
2055 *p_ss_padding
= 8 - (data_len
% 8);
2057 *p_frag_len
= RPC_HEADER_LEN
+ RPC_HDR_REQ_LEN
+ /* Normal headers. */
2058 data_len
+ *p_ss_padding
+ /* data plus padding. */
2059 RPC_HDR_AUTH_LEN
+ *p_auth_len
; /* Auth header and auth data. */
2063 smb_panic("bad auth level");
2069 /*******************************************************************
2071 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2072 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2073 and deals with signing/sealing details.
2074 ********************************************************************/
2076 struct rpc_api_pipe_req_state
{
2077 struct event_context
*ev
;
2078 struct rpc_pipe_client
*cli
;
2081 prs_struct
*req_data
;
2082 uint32_t req_data_sent
;
2083 prs_struct outgoing_frag
;
2084 prs_struct reply_pdu
;
2087 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state
*s
)
2089 prs_mem_free(&s
->outgoing_frag
);
2090 prs_mem_free(&s
->reply_pdu
);
2094 static void rpc_api_pipe_req_write_done(struct tevent_req
*subreq
);
2095 static void rpc_api_pipe_req_done(struct tevent_req
*subreq
);
2096 static NTSTATUS
prepare_next_frag(struct rpc_api_pipe_req_state
*state
,
2097 bool *is_last_frag
);
2099 struct tevent_req
*rpc_api_pipe_req_send(TALLOC_CTX
*mem_ctx
,
2100 struct event_context
*ev
,
2101 struct rpc_pipe_client
*cli
,
2103 prs_struct
*req_data
)
2105 struct tevent_req
*req
, *subreq
;
2106 struct rpc_api_pipe_req_state
*state
;
2110 req
= tevent_req_create(mem_ctx
, &state
,
2111 struct rpc_api_pipe_req_state
);
2117 state
->op_num
= op_num
;
2118 state
->req_data
= req_data
;
2119 state
->req_data_sent
= 0;
2120 state
->call_id
= get_rpc_call_id();
2122 if (cli
->max_xmit_frag
2123 < RPC_HEADER_LEN
+ RPC_HDR_REQ_LEN
+ RPC_MAX_SIGN_SIZE
) {
2124 /* Server is screwed up ! */
2125 status
= NT_STATUS_INVALID_PARAMETER
;
2129 prs_init_empty(&state
->reply_pdu
, state
, UNMARSHALL
);
2131 if (!prs_init(&state
->outgoing_frag
, cli
->max_xmit_frag
,
2136 talloc_set_destructor(state
, rpc_api_pipe_req_state_destructor
);
2138 status
= prepare_next_frag(state
, &is_last_frag
);
2139 if (!NT_STATUS_IS_OK(status
)) {
2144 subreq
= rpc_api_pipe_send(state
, ev
, state
->cli
,
2145 &state
->outgoing_frag
,
2147 if (subreq
== NULL
) {
2150 tevent_req_set_callback(subreq
, rpc_api_pipe_req_done
, req
);
2152 subreq
= rpc_write_send(
2153 state
, ev
, cli
->transport
,
2154 (uint8_t *)prs_data_p(&state
->outgoing_frag
),
2155 prs_offset(&state
->outgoing_frag
));
2156 if (subreq
== NULL
) {
2159 tevent_req_set_callback(subreq
, rpc_api_pipe_req_write_done
,
2165 tevent_req_nterror(req
, status
);
2166 return tevent_req_post(req
, ev
);
2172 static NTSTATUS
prepare_next_frag(struct rpc_api_pipe_req_state
*state
,
2176 RPC_HDR_REQ hdr_req
;
2177 uint32_t data_sent_thistime
;
2181 uint32_t ss_padding
;
2183 char pad
[8] = { 0, };
2186 data_left
= prs_offset(state
->req_data
) - state
->req_data_sent
;
2188 data_sent_thistime
= calculate_data_len_tosend(
2189 state
->cli
, data_left
, &frag_len
, &auth_len
, &ss_padding
);
2191 if (state
->req_data_sent
== 0) {
2192 flags
= RPC_FLG_FIRST
;
2195 if (data_sent_thistime
== data_left
) {
2196 flags
|= RPC_FLG_LAST
;
2199 if (!prs_set_offset(&state
->outgoing_frag
, 0)) {
2200 return NT_STATUS_NO_MEMORY
;
2203 /* Create and marshall the header and request header. */
2204 init_rpc_hdr(&hdr
, RPC_REQUEST
, flags
, state
->call_id
, frag_len
,
2207 if (!smb_io_rpc_hdr("hdr ", &hdr
, &state
->outgoing_frag
, 0)) {
2208 return NT_STATUS_NO_MEMORY
;
2211 /* Create the rpc request RPC_HDR_REQ */
2212 init_rpc_hdr_req(&hdr_req
, prs_offset(state
->req_data
),
2215 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req
,
2216 &state
->outgoing_frag
, 0)) {
2217 return NT_STATUS_NO_MEMORY
;
2220 /* Copy in the data, plus any ss padding. */
2221 if (!prs_append_some_prs_data(&state
->outgoing_frag
,
2222 state
->req_data
, state
->req_data_sent
,
2223 data_sent_thistime
)) {
2224 return NT_STATUS_NO_MEMORY
;
2227 /* Copy the sign/seal padding data. */
2228 if (!prs_copy_data_in(&state
->outgoing_frag
, pad
, ss_padding
)) {
2229 return NT_STATUS_NO_MEMORY
;
2232 /* Generate any auth sign/seal and add the auth footer. */
2233 switch (state
->cli
->auth
->auth_type
) {
2234 case PIPE_AUTH_TYPE_NONE
:
2235 status
= NT_STATUS_OK
;
2237 case PIPE_AUTH_TYPE_NTLMSSP
:
2238 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
2239 status
= add_ntlmssp_auth_footer(state
->cli
, &hdr
, ss_padding
,
2240 &state
->outgoing_frag
);
2242 case PIPE_AUTH_TYPE_SCHANNEL
:
2243 status
= add_schannel_auth_footer(state
->cli
, &hdr
, ss_padding
,
2244 &state
->outgoing_frag
);
2247 status
= NT_STATUS_INVALID_PARAMETER
;
2251 state
->req_data_sent
+= data_sent_thistime
;
2252 *is_last_frag
= ((flags
& RPC_FLG_LAST
) != 0);
2257 static void rpc_api_pipe_req_write_done(struct tevent_req
*subreq
)
2259 struct tevent_req
*req
= tevent_req_callback_data(
2260 subreq
, struct tevent_req
);
2261 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
2262 req
, struct rpc_api_pipe_req_state
);
2266 status
= rpc_write_recv(subreq
);
2267 TALLOC_FREE(subreq
);
2268 if (!NT_STATUS_IS_OK(status
)) {
2269 tevent_req_nterror(req
, status
);
2273 status
= prepare_next_frag(state
, &is_last_frag
);
2274 if (!NT_STATUS_IS_OK(status
)) {
2275 tevent_req_nterror(req
, status
);
2280 subreq
= rpc_api_pipe_send(state
, state
->ev
, state
->cli
,
2281 &state
->outgoing_frag
,
2283 if (tevent_req_nomem(subreq
, req
)) {
2286 tevent_req_set_callback(subreq
, rpc_api_pipe_req_done
, req
);
2288 subreq
= rpc_write_send(
2290 state
->cli
->transport
,
2291 (uint8_t *)prs_data_p(&state
->outgoing_frag
),
2292 prs_offset(&state
->outgoing_frag
));
2293 if (tevent_req_nomem(subreq
, req
)) {
2296 tevent_req_set_callback(subreq
, rpc_api_pipe_req_write_done
,
2301 static void rpc_api_pipe_req_done(struct tevent_req
*subreq
)
2303 struct tevent_req
*req
= tevent_req_callback_data(
2304 subreq
, struct tevent_req
);
2305 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
2306 req
, struct rpc_api_pipe_req_state
);
2309 status
= rpc_api_pipe_recv(subreq
, state
, &state
->reply_pdu
);
2310 TALLOC_FREE(subreq
);
2311 if (!NT_STATUS_IS_OK(status
)) {
2312 tevent_req_nterror(req
, status
);
2315 tevent_req_done(req
);
2318 NTSTATUS
rpc_api_pipe_req_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
2319 prs_struct
*reply_pdu
)
2321 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
2322 req
, struct rpc_api_pipe_req_state
);
2325 if (tevent_req_is_nterror(req
, &status
)) {
2327 * We always have to initialize to reply pdu, even if there is
2328 * none. The rpccli_* caller routines expect this.
2330 prs_init_empty(reply_pdu
, mem_ctx
, UNMARSHALL
);
2334 *reply_pdu
= state
->reply_pdu
;
2335 reply_pdu
->mem_ctx
= mem_ctx
;
2338 * Prevent state->req_pdu from being freed in
2339 * rpc_api_pipe_req_state_destructor()
2341 prs_init_empty(&state
->reply_pdu
, state
, UNMARSHALL
);
2343 return NT_STATUS_OK
;
2347 /****************************************************************************
2348 Set the handle state.
2349 ****************************************************************************/
2351 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client
*cli
,
2352 const char *pipe_name
, uint16 device_state
)
2354 bool state_set
= False
;
2356 uint16 setup
[2]; /* only need 2 uint16 setup parameters */
2357 char *rparam
= NULL
;
2359 uint32 rparam_len
, rdata_len
;
2361 if (pipe_name
== NULL
)
2364 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2365 cli
->fnum
, pipe_name
, device_state
));
2367 /* create parameters: device state */
2368 SSVAL(param
, 0, device_state
);
2370 /* create setup parameters. */
2372 setup
[1] = cli
->fnum
; /* pipe file handle. got this from an SMBOpenX. */
2374 /* send the data on \PIPE\ */
2375 if (cli_api_pipe(cli
->cli
, "\\PIPE\\",
2376 setup
, 2, 0, /* setup, length, max */
2377 param
, 2, 0, /* param, length, max */
2378 NULL
, 0, 1024, /* data, length, max */
2379 &rparam
, &rparam_len
, /* return param, length */
2380 &rdata
, &rdata_len
)) /* return data, length */
2382 DEBUG(5, ("Set Handle state: return OK\n"));
2393 /****************************************************************************
2394 Check the rpc bind acknowledge response.
2395 ****************************************************************************/
2397 static bool check_bind_response(RPC_HDR_BA
*hdr_ba
,
2398 const struct ndr_syntax_id
*transfer
)
2400 if ( hdr_ba
->addr
.len
== 0) {
2401 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2404 /* check the transfer syntax */
2405 if ((hdr_ba
->transfer
.if_version
!= transfer
->if_version
) ||
2406 (memcmp(&hdr_ba
->transfer
.uuid
, &transfer
->uuid
, sizeof(transfer
->uuid
)) !=0)) {
2407 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2411 if (hdr_ba
->res
.num_results
!= 0x1 || hdr_ba
->res
.result
!= 0) {
2412 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2413 hdr_ba
->res
.num_results
, hdr_ba
->res
.reason
));
2416 DEBUG(5,("check_bind_response: accepted!\n"));
2420 /*******************************************************************
2421 Creates a DCE/RPC bind authentication response.
2422 This is the packet that is sent back to the server once we
2423 have received a BIND-ACK, to finish the third leg of
2424 the authentication handshake.
2425 ********************************************************************/
2427 static NTSTATUS
create_rpc_bind_auth3(struct rpc_pipe_client
*cli
,
2429 enum pipe_auth_type auth_type
,
2430 enum dcerpc_AuthLevel auth_level
,
2431 DATA_BLOB
*pauth_blob
,
2432 prs_struct
*rpc_out
)
2435 RPC_HDR_AUTH hdr_auth
;
2438 /* Create the request RPC_HDR */
2439 init_rpc_hdr(&hdr
, RPC_AUTH3
, RPC_FLG_FIRST
|RPC_FLG_LAST
, rpc_call_id
,
2440 RPC_HEADER_LEN
+ 4 /* pad */ + RPC_HDR_AUTH_LEN
+ pauth_blob
->length
,
2441 pauth_blob
->length
);
2444 if(!smb_io_rpc_hdr("hdr", &hdr
, rpc_out
, 0)) {
2445 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2446 return NT_STATUS_NO_MEMORY
;
2450 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2451 about padding - shouldn't this pad to length 8 ? JRA.
2454 /* 4 bytes padding. */
2455 if (!prs_uint32("pad", rpc_out
, 0, &pad
)) {
2456 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2457 return NT_STATUS_NO_MEMORY
;
2460 /* Create the request RPC_HDR_AUTHA */
2461 init_rpc_hdr_auth(&hdr_auth
,
2462 map_pipe_auth_type_to_rpc_auth_type(auth_type
),
2465 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth
, rpc_out
, 0)) {
2466 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2467 return NT_STATUS_NO_MEMORY
;
2471 * Append the auth data to the outgoing buffer.
2474 if(!prs_copy_data_in(rpc_out
, (char *)pauth_blob
->data
, pauth_blob
->length
)) {
2475 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2476 return NT_STATUS_NO_MEMORY
;
2479 return NT_STATUS_OK
;
2482 /*******************************************************************
2483 Creates a DCE/RPC bind alter context authentication request which
2484 may contain a spnego auth blobl
2485 ********************************************************************/
2487 static NTSTATUS
create_rpc_alter_context(uint32 rpc_call_id
,
2488 const struct ndr_syntax_id
*abstract
,
2489 const struct ndr_syntax_id
*transfer
,
2490 enum dcerpc_AuthLevel auth_level
,
2491 const DATA_BLOB
*pauth_blob
, /* spnego auth blob already created. */
2492 prs_struct
*rpc_out
)
2494 RPC_HDR_AUTH hdr_auth
;
2495 prs_struct auth_info
;
2496 NTSTATUS ret
= NT_STATUS_OK
;
2498 ZERO_STRUCT(hdr_auth
);
2499 if (!prs_init(&auth_info
, RPC_HDR_AUTH_LEN
, prs_get_mem_context(rpc_out
), MARSHALL
))
2500 return NT_STATUS_NO_MEMORY
;
2502 /* We may change the pad length before marshalling. */
2503 init_rpc_hdr_auth(&hdr_auth
, DCERPC_AUTH_TYPE_SPNEGO
, (int)auth_level
, 0, 1);
2505 if (pauth_blob
->length
) {
2506 if (!prs_copy_data_in(&auth_info
, (const char *)pauth_blob
->data
, pauth_blob
->length
)) {
2507 prs_mem_free(&auth_info
);
2508 return NT_STATUS_NO_MEMORY
;
2512 ret
= create_bind_or_alt_ctx_internal(RPC_ALTCONT
,
2519 prs_mem_free(&auth_info
);
2523 /****************************************************************************
2525 ****************************************************************************/
2527 struct rpc_pipe_bind_state
{
2528 struct event_context
*ev
;
2529 struct rpc_pipe_client
*cli
;
2531 uint32_t rpc_call_id
;
2534 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state
*state
)
2536 prs_mem_free(&state
->rpc_out
);
2540 static void rpc_pipe_bind_step_one_done(struct tevent_req
*subreq
);
2541 static NTSTATUS
rpc_finish_auth3_bind_send(struct tevent_req
*req
,
2542 struct rpc_pipe_bind_state
*state
,
2543 struct rpc_hdr_info
*phdr
,
2544 prs_struct
*reply_pdu
);
2545 static void rpc_bind_auth3_write_done(struct tevent_req
*subreq
);
2546 static NTSTATUS
rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req
*req
,
2547 struct rpc_pipe_bind_state
*state
,
2548 struct rpc_hdr_info
*phdr
,
2549 prs_struct
*reply_pdu
);
2550 static void rpc_bind_ntlmssp_api_done(struct tevent_req
*subreq
);
2552 struct tevent_req
*rpc_pipe_bind_send(TALLOC_CTX
*mem_ctx
,
2553 struct event_context
*ev
,
2554 struct rpc_pipe_client
*cli
,
2555 struct cli_pipe_auth_data
*auth
)
2557 struct tevent_req
*req
, *subreq
;
2558 struct rpc_pipe_bind_state
*state
;
2561 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_pipe_bind_state
);
2566 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2567 rpccli_pipe_txt(debug_ctx(), cli
),
2568 (unsigned int)auth
->auth_type
,
2569 (unsigned int)auth
->auth_level
));
2573 state
->rpc_call_id
= get_rpc_call_id();
2575 prs_init_empty(&state
->rpc_out
, state
, MARSHALL
);
2576 talloc_set_destructor(state
, rpc_pipe_bind_state_destructor
);
2578 cli
->auth
= talloc_move(cli
, &auth
);
2580 /* Marshall the outgoing data. */
2581 status
= create_rpc_bind_req(cli
, &state
->rpc_out
,
2583 &cli
->abstract_syntax
,
2584 &cli
->transfer_syntax
,
2585 cli
->auth
->auth_type
,
2586 cli
->auth
->auth_level
);
2588 if (!NT_STATUS_IS_OK(status
)) {
2592 subreq
= rpc_api_pipe_send(state
, ev
, cli
, &state
->rpc_out
,
2594 if (subreq
== NULL
) {
2597 tevent_req_set_callback(subreq
, rpc_pipe_bind_step_one_done
, req
);
2601 tevent_req_nterror(req
, status
);
2602 return tevent_req_post(req
, ev
);
2608 static void rpc_pipe_bind_step_one_done(struct tevent_req
*subreq
)
2610 struct tevent_req
*req
= tevent_req_callback_data(
2611 subreq
, struct tevent_req
);
2612 struct rpc_pipe_bind_state
*state
= tevent_req_data(
2613 req
, struct rpc_pipe_bind_state
);
2614 prs_struct reply_pdu
;
2615 struct rpc_hdr_info hdr
;
2616 struct rpc_hdr_ba_info hdr_ba
;
2619 status
= rpc_api_pipe_recv(subreq
, talloc_tos(), &reply_pdu
);
2620 TALLOC_FREE(subreq
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2623 rpccli_pipe_txt(debug_ctx(), state
->cli
),
2624 nt_errstr(status
)));
2625 tevent_req_nterror(req
, status
);
2629 /* Unmarshall the RPC header */
2630 if (!smb_io_rpc_hdr("hdr", &hdr
, &reply_pdu
, 0)) {
2631 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2632 prs_mem_free(&reply_pdu
);
2633 tevent_req_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2637 if (!smb_io_rpc_hdr_ba("", &hdr_ba
, &reply_pdu
, 0)) {
2638 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2640 prs_mem_free(&reply_pdu
);
2641 tevent_req_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2645 if (!check_bind_response(&hdr_ba
, &state
->cli
->transfer_syntax
)) {
2646 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2647 prs_mem_free(&reply_pdu
);
2648 tevent_req_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2652 state
->cli
->max_xmit_frag
= hdr_ba
.bba
.max_tsize
;
2653 state
->cli
->max_recv_frag
= hdr_ba
.bba
.max_rsize
;
2656 * For authenticated binds we may need to do 3 or 4 leg binds.
2659 switch(state
->cli
->auth
->auth_type
) {
2661 case PIPE_AUTH_TYPE_NONE
:
2662 case PIPE_AUTH_TYPE_SCHANNEL
:
2663 /* Bind complete. */
2664 prs_mem_free(&reply_pdu
);
2665 tevent_req_done(req
);
2668 case PIPE_AUTH_TYPE_NTLMSSP
:
2669 /* Need to send AUTH3 packet - no reply. */
2670 status
= rpc_finish_auth3_bind_send(req
, state
, &hdr
,
2672 prs_mem_free(&reply_pdu
);
2673 if (!NT_STATUS_IS_OK(status
)) {
2674 tevent_req_nterror(req
, status
);
2678 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
2679 /* Need to send alter context request and reply. */
2680 status
= rpc_finish_spnego_ntlmssp_bind_send(req
, state
, &hdr
,
2682 prs_mem_free(&reply_pdu
);
2683 if (!NT_STATUS_IS_OK(status
)) {
2684 tevent_req_nterror(req
, status
);
2688 case PIPE_AUTH_TYPE_KRB5
:
2692 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2693 (unsigned int)state
->cli
->auth
->auth_type
));
2694 prs_mem_free(&reply_pdu
);
2695 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2699 static NTSTATUS
rpc_finish_auth3_bind_send(struct tevent_req
*req
,
2700 struct rpc_pipe_bind_state
*state
,
2701 struct rpc_hdr_info
*phdr
,
2702 prs_struct
*reply_pdu
)
2704 DATA_BLOB server_response
= data_blob_null
;
2705 DATA_BLOB client_reply
= data_blob_null
;
2706 struct rpc_hdr_auth_info hdr_auth
;
2707 struct tevent_req
*subreq
;
2710 if ((phdr
->auth_len
== 0)
2711 || (phdr
->frag_len
< phdr
->auth_len
+ RPC_HDR_AUTH_LEN
)) {
2712 return NT_STATUS_INVALID_PARAMETER
;
2715 if (!prs_set_offset(
2717 phdr
->frag_len
- phdr
->auth_len
- RPC_HDR_AUTH_LEN
)) {
2718 return NT_STATUS_INVALID_PARAMETER
;
2721 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth
, reply_pdu
, 0)) {
2722 return NT_STATUS_INVALID_PARAMETER
;
2725 /* TODO - check auth_type/auth_level match. */
2727 server_response
= data_blob_talloc(talloc_tos(), NULL
, phdr
->auth_len
);
2728 prs_copy_data_out((char *)server_response
.data
, reply_pdu
,
2731 status
= ntlmssp_update(state
->cli
->auth
->a_u
.ntlmssp_state
,
2732 server_response
, &client_reply
);
2734 if (!NT_STATUS_IS_OK(status
)) {
2735 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2736 "blob failed: %s.\n", nt_errstr(status
)));
2740 prs_init_empty(&state
->rpc_out
, talloc_tos(), MARSHALL
);
2742 status
= create_rpc_bind_auth3(state
->cli
, state
->rpc_call_id
,
2743 state
->cli
->auth
->auth_type
,
2744 state
->cli
->auth
->auth_level
,
2745 &client_reply
, &state
->rpc_out
);
2746 data_blob_free(&client_reply
);
2748 if (!NT_STATUS_IS_OK(status
)) {
2752 subreq
= rpc_write_send(state
, state
->ev
, state
->cli
->transport
,
2753 (uint8_t *)prs_data_p(&state
->rpc_out
),
2754 prs_offset(&state
->rpc_out
));
2755 if (subreq
== NULL
) {
2756 return NT_STATUS_NO_MEMORY
;
2758 tevent_req_set_callback(subreq
, rpc_bind_auth3_write_done
, req
);
2759 return NT_STATUS_OK
;
2762 static void rpc_bind_auth3_write_done(struct tevent_req
*subreq
)
2764 struct tevent_req
*req
= tevent_req_callback_data(
2765 subreq
, struct tevent_req
);
2768 status
= rpc_write_recv(subreq
);
2769 TALLOC_FREE(subreq
);
2770 if (!NT_STATUS_IS_OK(status
)) {
2771 tevent_req_nterror(req
, status
);
2774 tevent_req_done(req
);
2777 static NTSTATUS
rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req
*req
,
2778 struct rpc_pipe_bind_state
*state
,
2779 struct rpc_hdr_info
*phdr
,
2780 prs_struct
*reply_pdu
)
2782 DATA_BLOB server_spnego_response
= data_blob_null
;
2783 DATA_BLOB server_ntlm_response
= data_blob_null
;
2784 DATA_BLOB client_reply
= data_blob_null
;
2785 DATA_BLOB tmp_blob
= data_blob_null
;
2786 RPC_HDR_AUTH hdr_auth
;
2787 struct tevent_req
*subreq
;
2790 if ((phdr
->auth_len
== 0)
2791 || (phdr
->frag_len
< phdr
->auth_len
+ RPC_HDR_AUTH_LEN
)) {
2792 return NT_STATUS_INVALID_PARAMETER
;
2795 /* Process the returned NTLMSSP blob first. */
2796 if (!prs_set_offset(
2798 phdr
->frag_len
- phdr
->auth_len
- RPC_HDR_AUTH_LEN
)) {
2799 return NT_STATUS_INVALID_PARAMETER
;
2802 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth
, reply_pdu
, 0)) {
2803 return NT_STATUS_INVALID_PARAMETER
;
2806 server_spnego_response
= data_blob(NULL
, phdr
->auth_len
);
2807 prs_copy_data_out((char *)server_spnego_response
.data
,
2808 reply_pdu
, phdr
->auth_len
);
2811 * The server might give us back two challenges - tmp_blob is for the
2814 if (!spnego_parse_challenge(server_spnego_response
,
2815 &server_ntlm_response
, &tmp_blob
)) {
2816 data_blob_free(&server_spnego_response
);
2817 data_blob_free(&server_ntlm_response
);
2818 data_blob_free(&tmp_blob
);
2819 return NT_STATUS_INVALID_PARAMETER
;
2822 /* We're finished with the server spnego response and the tmp_blob. */
2823 data_blob_free(&server_spnego_response
);
2824 data_blob_free(&tmp_blob
);
2826 status
= ntlmssp_update(state
->cli
->auth
->a_u
.ntlmssp_state
,
2827 server_ntlm_response
, &client_reply
);
2829 /* Finished with the server_ntlm response */
2830 data_blob_free(&server_ntlm_response
);
2832 if (!NT_STATUS_IS_OK(status
)) {
2833 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2834 "using server blob failed.\n"));
2835 data_blob_free(&client_reply
);
2839 /* SPNEGO wrap the client reply. */
2840 tmp_blob
= spnego_gen_auth(client_reply
);
2841 data_blob_free(&client_reply
);
2842 client_reply
= tmp_blob
;
2843 tmp_blob
= data_blob_null
;
2845 /* Now prepare the alter context pdu. */
2846 prs_init_empty(&state
->rpc_out
, state
, MARSHALL
);
2848 status
= create_rpc_alter_context(state
->rpc_call_id
,
2849 &state
->cli
->abstract_syntax
,
2850 &state
->cli
->transfer_syntax
,
2851 state
->cli
->auth
->auth_level
,
2854 data_blob_free(&client_reply
);
2856 if (!NT_STATUS_IS_OK(status
)) {
2860 subreq
= rpc_api_pipe_send(state
, state
->ev
, state
->cli
,
2861 &state
->rpc_out
, RPC_ALTCONTRESP
);
2862 if (subreq
== NULL
) {
2863 return NT_STATUS_NO_MEMORY
;
2865 tevent_req_set_callback(subreq
, rpc_bind_ntlmssp_api_done
, req
);
2866 return NT_STATUS_OK
;
2869 static void rpc_bind_ntlmssp_api_done(struct tevent_req
*subreq
)
2871 struct tevent_req
*req
= tevent_req_callback_data(
2872 subreq
, struct tevent_req
);
2873 struct rpc_pipe_bind_state
*state
= tevent_req_data(
2874 req
, struct rpc_pipe_bind_state
);
2875 DATA_BLOB server_spnego_response
= data_blob_null
;
2876 DATA_BLOB tmp_blob
= data_blob_null
;
2877 prs_struct reply_pdu
;
2878 struct rpc_hdr_info hdr
;
2879 struct rpc_hdr_auth_info hdr_auth
;
2882 status
= rpc_api_pipe_recv(subreq
, talloc_tos(), &reply_pdu
);
2883 TALLOC_FREE(subreq
);
2884 if (!NT_STATUS_IS_OK(status
)) {
2885 tevent_req_nterror(req
, status
);
2889 /* Get the auth blob from the reply. */
2890 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr
, &reply_pdu
, 0)) {
2891 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
2892 "unmarshall RPC_HDR.\n"));
2893 tevent_req_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2897 if (!prs_set_offset(
2899 hdr
.frag_len
- hdr
.auth_len
- RPC_HDR_AUTH_LEN
)) {
2900 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2904 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth
, &reply_pdu
, 0)) {
2905 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2909 server_spnego_response
= data_blob(NULL
, hdr
.auth_len
);
2910 prs_copy_data_out((char *)server_spnego_response
.data
, &reply_pdu
,
2913 /* Check we got a valid auth response. */
2914 if (!spnego_parse_auth_response(server_spnego_response
, NT_STATUS_OK
,
2915 OID_NTLMSSP
, &tmp_blob
)) {
2916 data_blob_free(&server_spnego_response
);
2917 data_blob_free(&tmp_blob
);
2918 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2922 data_blob_free(&server_spnego_response
);
2923 data_blob_free(&tmp_blob
);
2925 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2926 "%s.\n", rpccli_pipe_txt(debug_ctx(), state
->cli
)));
2927 tevent_req_done(req
);
2930 NTSTATUS
rpc_pipe_bind_recv(struct tevent_req
*req
)
2932 return tevent_req_simple_recv_ntstatus(req
);
2935 NTSTATUS
rpc_pipe_bind(struct rpc_pipe_client
*cli
,
2936 struct cli_pipe_auth_data
*auth
)
2938 TALLOC_CTX
*frame
= talloc_stackframe();
2939 struct event_context
*ev
;
2940 struct tevent_req
*req
;
2941 NTSTATUS status
= NT_STATUS_OK
;
2943 ev
= event_context_init(frame
);
2945 status
= NT_STATUS_NO_MEMORY
;
2949 req
= rpc_pipe_bind_send(frame
, ev
, cli
, auth
);
2951 status
= NT_STATUS_NO_MEMORY
;
2955 if (!tevent_req_poll(req
, ev
)) {
2956 status
= map_nt_error_from_unix(errno
);
2960 status
= rpc_pipe_bind_recv(req
);
2966 unsigned int rpccli_set_timeout(struct rpc_pipe_client
*rpc_cli
,
2967 unsigned int timeout
)
2969 struct cli_state
*cli
= rpc_pipe_np_smb_conn(rpc_cli
);
2974 return cli_set_timeout(cli
, timeout
);
2977 bool rpccli_get_pwd_hash(struct rpc_pipe_client
*rpc_cli
, uint8_t nt_hash
[16])
2979 struct cli_state
*cli
;
2981 if ((rpc_cli
->auth
->auth_type
== PIPE_AUTH_TYPE_NTLMSSP
)
2982 || (rpc_cli
->auth
->auth_type
== PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
)) {
2983 memcpy(nt_hash
, rpc_cli
->auth
->a_u
.ntlmssp_state
->nt_hash
, 16);
2987 cli
= rpc_pipe_np_smb_conn(rpc_cli
);
2991 E_md4hash(cli
->password
? cli
->password
: "", nt_hash
);
2995 NTSTATUS
rpccli_anon_bind_data(TALLOC_CTX
*mem_ctx
,
2996 struct cli_pipe_auth_data
**presult
)
2998 struct cli_pipe_auth_data
*result
;
3000 result
= talloc(mem_ctx
, struct cli_pipe_auth_data
);
3001 if (result
== NULL
) {
3002 return NT_STATUS_NO_MEMORY
;
3005 result
->auth_type
= PIPE_AUTH_TYPE_NONE
;
3006 result
->auth_level
= DCERPC_AUTH_LEVEL_NONE
;
3008 result
->user_name
= talloc_strdup(result
, "");
3009 result
->domain
= talloc_strdup(result
, "");
3010 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
3011 TALLOC_FREE(result
);
3012 return NT_STATUS_NO_MEMORY
;
3016 return NT_STATUS_OK
;
3019 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data
*auth
)
3021 ntlmssp_end(&auth
->a_u
.ntlmssp_state
);
3025 NTSTATUS
rpccli_ntlmssp_bind_data(TALLOC_CTX
*mem_ctx
,
3026 enum pipe_auth_type auth_type
,
3027 enum dcerpc_AuthLevel auth_level
,
3029 const char *username
,
3030 const char *password
,
3031 struct cli_pipe_auth_data
**presult
)
3033 struct cli_pipe_auth_data
*result
;
3036 result
= talloc(mem_ctx
, struct cli_pipe_auth_data
);
3037 if (result
== NULL
) {
3038 return NT_STATUS_NO_MEMORY
;
3041 result
->auth_type
= auth_type
;
3042 result
->auth_level
= auth_level
;
3044 result
->user_name
= talloc_strdup(result
, username
);
3045 result
->domain
= talloc_strdup(result
, domain
);
3046 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
3047 status
= NT_STATUS_NO_MEMORY
;
3051 status
= ntlmssp_client_start(&result
->a_u
.ntlmssp_state
);
3052 if (!NT_STATUS_IS_OK(status
)) {
3056 talloc_set_destructor(result
, cli_auth_ntlmssp_data_destructor
);
3058 status
= ntlmssp_set_username(result
->a_u
.ntlmssp_state
, username
);
3059 if (!NT_STATUS_IS_OK(status
)) {
3063 status
= ntlmssp_set_domain(result
->a_u
.ntlmssp_state
, domain
);
3064 if (!NT_STATUS_IS_OK(status
)) {
3068 status
= ntlmssp_set_password(result
->a_u
.ntlmssp_state
, password
);
3069 if (!NT_STATUS_IS_OK(status
)) {
3074 * Turn off sign+seal to allow selected auth level to turn it back on.
3076 result
->a_u
.ntlmssp_state
->neg_flags
&=
3077 ~(NTLMSSP_NEGOTIATE_SIGN
| NTLMSSP_NEGOTIATE_SEAL
);
3079 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
3080 result
->a_u
.ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_SIGN
;
3081 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
3082 result
->a_u
.ntlmssp_state
->neg_flags
3083 |= NTLMSSP_NEGOTIATE_SEAL
| NTLMSSP_NEGOTIATE_SIGN
;
3087 return NT_STATUS_OK
;
3090 TALLOC_FREE(result
);
3094 NTSTATUS
rpccli_schannel_bind_data(TALLOC_CTX
*mem_ctx
, const char *domain
,
3095 enum dcerpc_AuthLevel auth_level
,
3096 struct netlogon_creds_CredentialState
*creds
,
3097 struct cli_pipe_auth_data
**presult
)
3099 struct cli_pipe_auth_data
*result
;
3101 result
= talloc(mem_ctx
, struct cli_pipe_auth_data
);
3102 if (result
== NULL
) {
3103 return NT_STATUS_NO_MEMORY
;
3106 result
->auth_type
= PIPE_AUTH_TYPE_SCHANNEL
;
3107 result
->auth_level
= auth_level
;
3109 result
->user_name
= talloc_strdup(result
, "");
3110 result
->domain
= talloc_strdup(result
, domain
);
3111 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
3115 result
->a_u
.schannel_auth
= talloc(result
, struct schannel_state
);
3116 if (result
->a_u
.schannel_auth
== NULL
) {
3120 result
->a_u
.schannel_auth
->state
= SCHANNEL_STATE_START
;
3121 result
->a_u
.schannel_auth
->seq_num
= 0;
3122 result
->a_u
.schannel_auth
->initiator
= true;
3123 result
->a_u
.schannel_auth
->creds
= creds
;
3126 return NT_STATUS_OK
;
3129 TALLOC_FREE(result
);
3130 return NT_STATUS_NO_MEMORY
;
3134 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct
*auth
)
3136 data_blob_free(&auth
->session_key
);
3141 NTSTATUS
rpccli_kerberos_bind_data(TALLOC_CTX
*mem_ctx
,
3142 enum dcerpc_AuthLevel auth_level
,
3143 const char *service_princ
,
3144 const char *username
,
3145 const char *password
,
3146 struct cli_pipe_auth_data
**presult
)
3149 struct cli_pipe_auth_data
*result
;
3151 if ((username
!= NULL
) && (password
!= NULL
)) {
3152 int ret
= kerberos_kinit_password(username
, password
, 0, NULL
);
3154 return NT_STATUS_ACCESS_DENIED
;
3158 result
= talloc(mem_ctx
, struct cli_pipe_auth_data
);
3159 if (result
== NULL
) {
3160 return NT_STATUS_NO_MEMORY
;
3163 result
->auth_type
= PIPE_AUTH_TYPE_KRB5
;
3164 result
->auth_level
= auth_level
;
3167 * Username / domain need fixing!
3169 result
->user_name
= talloc_strdup(result
, "");
3170 result
->domain
= talloc_strdup(result
, "");
3171 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
3175 result
->a_u
.kerberos_auth
= TALLOC_ZERO_P(
3176 result
, struct kerberos_auth_struct
);
3177 if (result
->a_u
.kerberos_auth
== NULL
) {
3180 talloc_set_destructor(result
->a_u
.kerberos_auth
,
3181 cli_auth_kerberos_data_destructor
);
3183 result
->a_u
.kerberos_auth
->service_principal
= talloc_strdup(
3184 result
, service_princ
);
3185 if (result
->a_u
.kerberos_auth
->service_principal
== NULL
) {
3190 return NT_STATUS_OK
;
3193 TALLOC_FREE(result
);
3194 return NT_STATUS_NO_MEMORY
;
3196 return NT_STATUS_NOT_SUPPORTED
;
3201 * Create an rpc pipe client struct, connecting to a tcp port.
3203 static NTSTATUS
rpc_pipe_open_tcp_port(TALLOC_CTX
*mem_ctx
, const char *host
,
3205 const struct ndr_syntax_id
*abstract_syntax
,
3206 struct rpc_pipe_client
**presult
)
3208 struct rpc_pipe_client
*result
;
3209 struct sockaddr_storage addr
;
3213 result
= TALLOC_ZERO_P(mem_ctx
, struct rpc_pipe_client
);
3214 if (result
== NULL
) {
3215 return NT_STATUS_NO_MEMORY
;
3218 result
->abstract_syntax
= *abstract_syntax
;
3219 result
->transfer_syntax
= ndr_transfer_syntax
;
3220 result
->dispatch
= cli_do_rpc_ndr
;
3221 result
->dispatch_send
= cli_do_rpc_ndr_send
;
3222 result
->dispatch_recv
= cli_do_rpc_ndr_recv
;
3224 result
->desthost
= talloc_strdup(result
, host
);
3225 result
->srv_name_slash
= talloc_asprintf_strupper_m(
3226 result
, "\\\\%s", result
->desthost
);
3227 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
3228 status
= NT_STATUS_NO_MEMORY
;
3232 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
3233 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
3235 if (!resolve_name(host
, &addr
, 0, false)) {
3236 status
= NT_STATUS_NOT_FOUND
;
3240 status
= open_socket_out(&addr
, port
, 60, &fd
);
3241 if (!NT_STATUS_IS_OK(status
)) {
3244 set_socket_options(fd
, lp_socket_options());
3246 status
= rpc_transport_sock_init(result
, fd
, &result
->transport
);
3247 if (!NT_STATUS_IS_OK(status
)) {
3252 result
->transport
->transport
= NCACN_IP_TCP
;
3255 return NT_STATUS_OK
;
3258 TALLOC_FREE(result
);
3263 * Determine the tcp port on which a dcerpc interface is listening
3264 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3267 static NTSTATUS
rpc_pipe_get_tcp_port(const char *host
,
3268 const struct ndr_syntax_id
*abstract_syntax
,
3272 struct rpc_pipe_client
*epm_pipe
= NULL
;
3273 struct cli_pipe_auth_data
*auth
= NULL
;
3274 struct dcerpc_binding
*map_binding
= NULL
;
3275 struct dcerpc_binding
*res_binding
= NULL
;
3276 struct epm_twr_t
*map_tower
= NULL
;
3277 struct epm_twr_t
*res_towers
= NULL
;
3278 struct policy_handle
*entry_handle
= NULL
;
3279 uint32_t num_towers
= 0;
3280 uint32_t max_towers
= 1;
3281 struct epm_twr_p_t towers
;
3282 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3284 if (pport
== NULL
) {
3285 status
= NT_STATUS_INVALID_PARAMETER
;
3289 /* open the connection to the endpoint mapper */
3290 status
= rpc_pipe_open_tcp_port(tmp_ctx
, host
, 135,
3291 &ndr_table_epmapper
.syntax_id
,
3294 if (!NT_STATUS_IS_OK(status
)) {
3298 status
= rpccli_anon_bind_data(tmp_ctx
, &auth
);
3299 if (!NT_STATUS_IS_OK(status
)) {
3303 status
= rpc_pipe_bind(epm_pipe
, auth
);
3304 if (!NT_STATUS_IS_OK(status
)) {
3308 /* create tower for asking the epmapper */
3310 map_binding
= TALLOC_ZERO_P(tmp_ctx
, struct dcerpc_binding
);
3311 if (map_binding
== NULL
) {
3312 status
= NT_STATUS_NO_MEMORY
;
3316 map_binding
->transport
= NCACN_IP_TCP
;
3317 map_binding
->object
= *abstract_syntax
;
3318 map_binding
->host
= host
; /* needed? */
3319 map_binding
->endpoint
= "0"; /* correct? needed? */
3321 map_tower
= TALLOC_ZERO_P(tmp_ctx
, struct epm_twr_t
);
3322 if (map_tower
== NULL
) {
3323 status
= NT_STATUS_NO_MEMORY
;
3327 status
= dcerpc_binding_build_tower(tmp_ctx
, map_binding
,
3328 &(map_tower
->tower
));
3329 if (!NT_STATUS_IS_OK(status
)) {
3333 /* allocate further parameters for the epm_Map call */
3335 res_towers
= TALLOC_ARRAY(tmp_ctx
, struct epm_twr_t
, max_towers
);
3336 if (res_towers
== NULL
) {
3337 status
= NT_STATUS_NO_MEMORY
;
3340 towers
.twr
= res_towers
;
3342 entry_handle
= TALLOC_ZERO_P(tmp_ctx
, struct policy_handle
);
3343 if (entry_handle
== NULL
) {
3344 status
= NT_STATUS_NO_MEMORY
;
3348 /* ask the endpoint mapper for the port */
3350 status
= rpccli_epm_Map(epm_pipe
,
3352 CONST_DISCARD(struct GUID
*,
3353 &(abstract_syntax
->uuid
)),
3360 if (!NT_STATUS_IS_OK(status
)) {
3364 if (num_towers
!= 1) {
3365 status
= NT_STATUS_UNSUCCESSFUL
;
3369 /* extract the port from the answer */
3371 status
= dcerpc_binding_from_tower(tmp_ctx
,
3372 &(towers
.twr
->tower
),
3374 if (!NT_STATUS_IS_OK(status
)) {
3378 /* are further checks here necessary? */
3379 if (res_binding
->transport
!= NCACN_IP_TCP
) {
3380 status
= NT_STATUS_UNSUCCESSFUL
;
3384 *pport
= (uint16_t)atoi(res_binding
->endpoint
);
3387 TALLOC_FREE(tmp_ctx
);
3392 * Create a rpc pipe client struct, connecting to a host via tcp.
3393 * The port is determined by asking the endpoint mapper on the given
3396 NTSTATUS
rpc_pipe_open_tcp(TALLOC_CTX
*mem_ctx
, const char *host
,
3397 const struct ndr_syntax_id
*abstract_syntax
,
3398 struct rpc_pipe_client
**presult
)
3405 status
= rpc_pipe_get_tcp_port(host
, abstract_syntax
, &port
);
3406 if (!NT_STATUS_IS_OK(status
)) {
3410 status
= rpc_pipe_open_tcp_port(mem_ctx
, host
, port
,
3411 abstract_syntax
, presult
);
3417 /********************************************************************
3418 Create a rpc pipe client struct, connecting to a unix domain socket
3419 ********************************************************************/
3420 NTSTATUS
rpc_pipe_open_ncalrpc(TALLOC_CTX
*mem_ctx
, const char *socket_path
,
3421 const struct ndr_syntax_id
*abstract_syntax
,
3422 struct rpc_pipe_client
**presult
)
3424 struct rpc_pipe_client
*result
;
3425 struct sockaddr_un addr
;
3429 result
= talloc_zero(mem_ctx
, struct rpc_pipe_client
);
3430 if (result
== NULL
) {
3431 return NT_STATUS_NO_MEMORY
;
3434 result
->abstract_syntax
= *abstract_syntax
;
3435 result
->transfer_syntax
= ndr_transfer_syntax
;
3436 result
->dispatch
= cli_do_rpc_ndr
;
3437 result
->dispatch_send
= cli_do_rpc_ndr_send
;
3438 result
->dispatch_recv
= cli_do_rpc_ndr_recv
;
3440 result
->desthost
= get_myname(result
);
3441 result
->srv_name_slash
= talloc_asprintf_strupper_m(
3442 result
, "\\\\%s", result
->desthost
);
3443 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
3444 status
= NT_STATUS_NO_MEMORY
;
3448 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
3449 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
3451 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
3453 status
= map_nt_error_from_unix(errno
);
3458 addr
.sun_family
= AF_UNIX
;
3459 strncpy(addr
.sun_path
, socket_path
, sizeof(addr
.sun_path
));
3461 if (sys_connect(fd
, (struct sockaddr
*)(void *)&addr
) == -1) {
3462 DEBUG(0, ("connect(%s) failed: %s\n", socket_path
,
3465 return map_nt_error_from_unix(errno
);
3468 status
= rpc_transport_sock_init(result
, fd
, &result
->transport
);
3469 if (!NT_STATUS_IS_OK(status
)) {
3474 result
->transport
->transport
= NCALRPC
;
3477 return NT_STATUS_OK
;
3480 TALLOC_FREE(result
);
3484 static int rpc_pipe_client_np_destructor(struct rpc_pipe_client
*p
)
3486 struct cli_state
*cli
;
3488 cli
= rpc_pipe_np_smb_conn(p
);
3490 DLIST_REMOVE(cli
->pipe_list
, p
);
3495 /****************************************************************************
3496 Open a named pipe over SMB to a remote server.
3498 * CAVEAT CALLER OF THIS FUNCTION:
3499 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3500 * so be sure that this function is called AFTER any structure (vs pointer)
3501 * assignment of the cli. In particular, libsmbclient does structure
3502 * assignments of cli, which invalidates the data in the returned
3503 * rpc_pipe_client if this function is called before the structure assignment
3506 ****************************************************************************/
3508 static NTSTATUS
rpc_pipe_open_np(struct cli_state
*cli
,
3509 const struct ndr_syntax_id
*abstract_syntax
,
3510 struct rpc_pipe_client
**presult
)
3512 struct rpc_pipe_client
*result
;
3515 /* sanity check to protect against crashes */
3518 return NT_STATUS_INVALID_HANDLE
;
3521 result
= TALLOC_ZERO_P(NULL
, struct rpc_pipe_client
);
3522 if (result
== NULL
) {
3523 return NT_STATUS_NO_MEMORY
;
3526 result
->abstract_syntax
= *abstract_syntax
;
3527 result
->transfer_syntax
= ndr_transfer_syntax
;
3528 result
->dispatch
= cli_do_rpc_ndr
;
3529 result
->dispatch_send
= cli_do_rpc_ndr_send
;
3530 result
->dispatch_recv
= cli_do_rpc_ndr_recv
;
3531 result
->desthost
= talloc_strdup(result
, cli
->desthost
);
3532 result
->srv_name_slash
= talloc_asprintf_strupper_m(
3533 result
, "\\\\%s", result
->desthost
);
3535 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
3536 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
3538 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
3539 TALLOC_FREE(result
);
3540 return NT_STATUS_NO_MEMORY
;
3543 status
= rpc_transport_np_init(result
, cli
, abstract_syntax
,
3544 &result
->transport
);
3545 if (!NT_STATUS_IS_OK(status
)) {
3546 TALLOC_FREE(result
);
3550 result
->transport
->transport
= NCACN_NP
;
3552 DLIST_ADD(cli
->pipe_list
, result
);
3553 talloc_set_destructor(result
, rpc_pipe_client_np_destructor
);
3556 return NT_STATUS_OK
;
3559 NTSTATUS
rpc_pipe_open_local(TALLOC_CTX
*mem_ctx
,
3560 struct rpc_cli_smbd_conn
*conn
,
3561 const struct ndr_syntax_id
*syntax
,
3562 struct rpc_pipe_client
**presult
)
3564 struct rpc_pipe_client
*result
;
3565 struct cli_pipe_auth_data
*auth
;
3568 result
= talloc(mem_ctx
, struct rpc_pipe_client
);
3569 if (result
== NULL
) {
3570 return NT_STATUS_NO_MEMORY
;
3572 result
->abstract_syntax
= *syntax
;
3573 result
->transfer_syntax
= ndr_transfer_syntax
;
3574 result
->dispatch
= cli_do_rpc_ndr
;
3575 result
->dispatch_send
= cli_do_rpc_ndr_send
;
3576 result
->dispatch_recv
= cli_do_rpc_ndr_recv
;
3577 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
3578 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
3580 result
->desthost
= talloc_strdup(result
, global_myname());
3581 result
->srv_name_slash
= talloc_asprintf_strupper_m(
3582 result
, "\\\\%s", global_myname());
3583 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
3584 TALLOC_FREE(result
);
3585 return NT_STATUS_NO_MEMORY
;
3588 status
= rpc_transport_smbd_init(result
, conn
, syntax
,
3589 &result
->transport
);
3590 if (!NT_STATUS_IS_OK(status
)) {
3591 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3592 nt_errstr(status
)));
3593 TALLOC_FREE(result
);
3597 status
= rpccli_anon_bind_data(result
, &auth
);
3598 if (!NT_STATUS_IS_OK(status
)) {
3599 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3600 nt_errstr(status
)));
3601 TALLOC_FREE(result
);
3605 status
= rpc_pipe_bind(result
, auth
);
3606 if (!NT_STATUS_IS_OK(status
)) {
3607 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status
)));
3608 TALLOC_FREE(result
);
3612 result
->transport
->transport
= NCACN_INTERNAL
;
3615 return NT_STATUS_OK
;
3618 /****************************************************************************
3619 Open a pipe to a remote server.
3620 ****************************************************************************/
3622 static NTSTATUS
cli_rpc_pipe_open(struct cli_state
*cli
,
3623 enum dcerpc_transport_t transport
,
3624 const struct ndr_syntax_id
*interface
,
3625 struct rpc_pipe_client
**presult
)
3627 switch (transport
) {
3629 return rpc_pipe_open_tcp(NULL
, cli
->desthost
, interface
,
3632 return rpc_pipe_open_np(cli
, interface
, presult
);
3634 return NT_STATUS_NOT_IMPLEMENTED
;
3638 /****************************************************************************
3639 Open a named pipe to an SMB server and bind anonymously.
3640 ****************************************************************************/
3642 NTSTATUS
cli_rpc_pipe_open_noauth_transport(struct cli_state
*cli
,
3643 enum dcerpc_transport_t transport
,
3644 const struct ndr_syntax_id
*interface
,
3645 struct rpc_pipe_client
**presult
)
3647 struct rpc_pipe_client
*result
;
3648 struct cli_pipe_auth_data
*auth
;
3651 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
3652 if (!NT_STATUS_IS_OK(status
)) {
3656 status
= rpccli_anon_bind_data(result
, &auth
);
3657 if (!NT_STATUS_IS_OK(status
)) {
3658 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3659 nt_errstr(status
)));
3660 TALLOC_FREE(result
);
3665 * This is a bit of an abstraction violation due to the fact that an
3666 * anonymous bind on an authenticated SMB inherits the user/domain
3667 * from the enclosing SMB creds
3670 TALLOC_FREE(auth
->user_name
);
3671 TALLOC_FREE(auth
->domain
);
3673 auth
->user_name
= talloc_strdup(auth
, cli
->user_name
);
3674 auth
->domain
= talloc_strdup(auth
, cli
->domain
);
3675 auth
->user_session_key
= data_blob_talloc(auth
,
3676 cli
->user_session_key
.data
,
3677 cli
->user_session_key
.length
);
3679 if ((auth
->user_name
== NULL
) || (auth
->domain
== NULL
)) {
3680 TALLOC_FREE(result
);
3681 return NT_STATUS_NO_MEMORY
;
3684 status
= rpc_pipe_bind(result
, auth
);
3685 if (!NT_STATUS_IS_OK(status
)) {
3687 if (ndr_syntax_id_equal(interface
,
3688 &ndr_table_dssetup
.syntax_id
)) {
3689 /* non AD domains just don't have this pipe, avoid
3690 * level 0 statement in that case - gd */
3693 DEBUG(lvl
, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3694 "%s failed with error %s\n",
3695 get_pipe_name_from_iface(interface
),
3696 nt_errstr(status
) ));
3697 TALLOC_FREE(result
);
3701 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3702 "%s and bound anonymously.\n",
3703 get_pipe_name_from_iface(interface
), cli
->desthost
));
3706 return NT_STATUS_OK
;
3709 /****************************************************************************
3710 ****************************************************************************/
3712 NTSTATUS
cli_rpc_pipe_open_noauth(struct cli_state
*cli
,
3713 const struct ndr_syntax_id
*interface
,
3714 struct rpc_pipe_client
**presult
)
3716 return cli_rpc_pipe_open_noauth_transport(cli
, NCACN_NP
,
3717 interface
, presult
);
3720 /****************************************************************************
3721 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3722 ****************************************************************************/
3724 static NTSTATUS
cli_rpc_pipe_open_ntlmssp_internal(struct cli_state
*cli
,
3725 const struct ndr_syntax_id
*interface
,
3726 enum dcerpc_transport_t transport
,
3727 enum pipe_auth_type auth_type
,
3728 enum dcerpc_AuthLevel auth_level
,
3730 const char *username
,
3731 const char *password
,
3732 struct rpc_pipe_client
**presult
)
3734 struct rpc_pipe_client
*result
;
3735 struct cli_pipe_auth_data
*auth
;
3738 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
3739 if (!NT_STATUS_IS_OK(status
)) {
3743 status
= rpccli_ntlmssp_bind_data(
3744 result
, auth_type
, auth_level
, domain
, username
,
3746 if (!NT_STATUS_IS_OK(status
)) {
3747 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3748 nt_errstr(status
)));
3752 status
= rpc_pipe_bind(result
, auth
);
3753 if (!NT_STATUS_IS_OK(status
)) {
3754 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3755 nt_errstr(status
) ));
3759 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3760 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3761 get_pipe_name_from_iface(interface
), cli
->desthost
, domain
,
3765 return NT_STATUS_OK
;
3769 TALLOC_FREE(result
);
3773 /****************************************************************************
3775 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3776 ****************************************************************************/
3778 NTSTATUS
cli_rpc_pipe_open_ntlmssp(struct cli_state
*cli
,
3779 const struct ndr_syntax_id
*interface
,
3780 enum dcerpc_transport_t transport
,
3781 enum dcerpc_AuthLevel auth_level
,
3783 const char *username
,
3784 const char *password
,
3785 struct rpc_pipe_client
**presult
)
3787 return cli_rpc_pipe_open_ntlmssp_internal(cli
,
3790 PIPE_AUTH_TYPE_NTLMSSP
,
3798 /****************************************************************************
3800 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3801 ****************************************************************************/
3803 NTSTATUS
cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state
*cli
,
3804 const struct ndr_syntax_id
*interface
,
3805 enum dcerpc_transport_t transport
,
3806 enum dcerpc_AuthLevel auth_level
,
3808 const char *username
,
3809 const char *password
,
3810 struct rpc_pipe_client
**presult
)
3812 return cli_rpc_pipe_open_ntlmssp_internal(cli
,
3815 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
,
3823 /****************************************************************************
3824 Get a the schannel session key out of an already opened netlogon pipe.
3825 ****************************************************************************/
3826 static NTSTATUS
get_schannel_session_key_common(struct rpc_pipe_client
*netlogon_pipe
,
3827 struct cli_state
*cli
,
3831 uint32 sec_chan_type
= 0;
3832 unsigned char machine_pwd
[16];
3833 const char *machine_account
;
3836 /* Get the machine account credentials from secrets.tdb. */
3837 if (!get_trust_pw_hash(domain
, machine_pwd
, &machine_account
,
3840 DEBUG(0, ("get_schannel_session_key: could not fetch "
3841 "trust account password for domain '%s'\n",
3843 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3846 status
= rpccli_netlogon_setup_creds(netlogon_pipe
,
3847 cli
->desthost
, /* server name */
3848 domain
, /* domain */
3849 global_myname(), /* client name */
3850 machine_account
, /* machine account name */
3855 if (!NT_STATUS_IS_OK(status
)) {
3856 DEBUG(3, ("get_schannel_session_key_common: "
3857 "rpccli_netlogon_setup_creds failed with result %s "
3858 "to server %s, domain %s, machine account %s.\n",
3859 nt_errstr(status
), cli
->desthost
, domain
,
3864 if (((*pneg_flags
) & NETLOGON_NEG_SCHANNEL
) == 0) {
3865 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3867 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
3870 return NT_STATUS_OK
;;
3873 /****************************************************************************
3874 Open a netlogon pipe and get the schannel session key.
3875 Now exposed to external callers.
3876 ****************************************************************************/
3879 NTSTATUS
get_schannel_session_key(struct cli_state
*cli
,
3882 struct rpc_pipe_client
**presult
)
3884 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
3887 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_netlogon
.syntax_id
,
3889 if (!NT_STATUS_IS_OK(status
)) {
3893 status
= get_schannel_session_key_common(netlogon_pipe
, cli
, domain
,
3895 if (!NT_STATUS_IS_OK(status
)) {
3896 TALLOC_FREE(netlogon_pipe
);
3900 *presult
= netlogon_pipe
;
3901 return NT_STATUS_OK
;
3904 /****************************************************************************
3906 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3907 using session_key. sign and seal.
3909 The *pdc will be stolen onto this new pipe
3910 ****************************************************************************/
3912 NTSTATUS
cli_rpc_pipe_open_schannel_with_key(struct cli_state
*cli
,
3913 const struct ndr_syntax_id
*interface
,
3914 enum dcerpc_transport_t transport
,
3915 enum dcerpc_AuthLevel auth_level
,
3917 struct netlogon_creds_CredentialState
**pdc
,
3918 struct rpc_pipe_client
**presult
)
3920 struct rpc_pipe_client
*result
;
3921 struct cli_pipe_auth_data
*auth
;
3924 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
3925 if (!NT_STATUS_IS_OK(status
)) {
3929 status
= rpccli_schannel_bind_data(result
, domain
, auth_level
,
3931 if (!NT_STATUS_IS_OK(status
)) {
3932 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3933 nt_errstr(status
)));
3934 TALLOC_FREE(result
);
3938 status
= rpc_pipe_bind(result
, auth
);
3939 if (!NT_STATUS_IS_OK(status
)) {
3940 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3941 "cli_rpc_pipe_bind failed with error %s\n",
3942 nt_errstr(status
) ));
3943 TALLOC_FREE(result
);
3948 * The credentials on a new netlogon pipe are the ones we are passed
3949 * in - reference them in
3951 result
->dc
= talloc_move(result
, pdc
);
3952 if (result
->dc
== NULL
) {
3953 DEBUG(0, ("talloc reference failed\n"));
3954 TALLOC_FREE(result
);
3955 return NT_STATUS_NO_MEMORY
;
3958 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3959 "for domain %s and bound using schannel.\n",
3960 get_pipe_name_from_iface(interface
),
3961 cli
->desthost
, domain
));
3964 return NT_STATUS_OK
;
3967 /****************************************************************************
3968 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3969 Fetch the session key ourselves using a temporary netlogon pipe. This
3970 version uses an ntlmssp auth bound netlogon pipe to get the key.
3971 ****************************************************************************/
3973 static NTSTATUS
get_schannel_session_key_auth_ntlmssp(struct cli_state
*cli
,
3975 const char *username
,
3976 const char *password
,
3978 struct rpc_pipe_client
**presult
)
3980 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
3983 status
= cli_rpc_pipe_open_spnego_ntlmssp(
3984 cli
, &ndr_table_netlogon
.syntax_id
, NCACN_NP
,
3985 DCERPC_AUTH_LEVEL_PRIVACY
,
3986 domain
, username
, password
, &netlogon_pipe
);
3987 if (!NT_STATUS_IS_OK(status
)) {
3991 status
= get_schannel_session_key_common(netlogon_pipe
, cli
, domain
,
3993 if (!NT_STATUS_IS_OK(status
)) {
3994 TALLOC_FREE(netlogon_pipe
);
3998 *presult
= netlogon_pipe
;
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 version
4005 uses an ntlmssp bind to get the session key.
4006 ****************************************************************************/
4008 NTSTATUS
cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state
*cli
,
4009 const struct ndr_syntax_id
*interface
,
4010 enum dcerpc_transport_t transport
,
4011 enum dcerpc_AuthLevel auth_level
,
4013 const char *username
,
4014 const char *password
,
4015 struct rpc_pipe_client
**presult
)
4017 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
4018 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
4019 struct rpc_pipe_client
*result
= NULL
;
4022 status
= get_schannel_session_key_auth_ntlmssp(
4023 cli
, domain
, username
, password
, &neg_flags
, &netlogon_pipe
);
4024 if (!NT_STATUS_IS_OK(status
)) {
4025 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4026 "key from server %s for domain %s.\n",
4027 cli
->desthost
, domain
));
4031 status
= cli_rpc_pipe_open_schannel_with_key(
4032 cli
, interface
, transport
, auth_level
, domain
, &netlogon_pipe
->dc
,
4035 /* Now we've bound using the session key we can close the netlog pipe. */
4036 TALLOC_FREE(netlogon_pipe
);
4038 if (NT_STATUS_IS_OK(status
)) {
4044 /****************************************************************************
4045 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4046 Fetch the session key ourselves using a temporary netlogon pipe.
4047 ****************************************************************************/
4049 NTSTATUS
cli_rpc_pipe_open_schannel(struct cli_state
*cli
,
4050 const struct ndr_syntax_id
*interface
,
4051 enum dcerpc_transport_t transport
,
4052 enum dcerpc_AuthLevel auth_level
,
4054 struct rpc_pipe_client
**presult
)
4056 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
4057 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
4058 struct rpc_pipe_client
*result
= NULL
;
4061 status
= get_schannel_session_key(cli
, domain
, &neg_flags
,
4063 if (!NT_STATUS_IS_OK(status
)) {
4064 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4065 "key from server %s for domain %s.\n",
4066 cli
->desthost
, domain
));
4070 status
= cli_rpc_pipe_open_schannel_with_key(
4071 cli
, interface
, transport
, auth_level
, domain
, &netlogon_pipe
->dc
,
4074 /* Now we've bound using the session key we can close the netlog pipe. */
4075 TALLOC_FREE(netlogon_pipe
);
4077 if (NT_STATUS_IS_OK(status
)) {
4081 return NT_STATUS_OK
;
4084 /****************************************************************************
4085 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4086 The idea is this can be called with service_princ, username and password all
4087 NULL so long as the caller has a TGT.
4088 ****************************************************************************/
4090 NTSTATUS
cli_rpc_pipe_open_krb5(struct cli_state
*cli
,
4091 const struct ndr_syntax_id
*interface
,
4092 enum dcerpc_AuthLevel auth_level
,
4093 const char *service_princ
,
4094 const char *username
,
4095 const char *password
,
4096 struct rpc_pipe_client
**presult
)
4099 struct rpc_pipe_client
*result
;
4100 struct cli_pipe_auth_data
*auth
;
4103 status
= cli_rpc_pipe_open(cli
, NCACN_NP
, interface
, &result
);
4104 if (!NT_STATUS_IS_OK(status
)) {
4108 status
= rpccli_kerberos_bind_data(result
, auth_level
, service_princ
,
4109 username
, password
, &auth
);
4110 if (!NT_STATUS_IS_OK(status
)) {
4111 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4112 nt_errstr(status
)));
4113 TALLOC_FREE(result
);
4117 status
= rpc_pipe_bind(result
, auth
);
4118 if (!NT_STATUS_IS_OK(status
)) {
4119 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4120 "with error %s\n", nt_errstr(status
)));
4121 TALLOC_FREE(result
);
4126 return NT_STATUS_OK
;
4128 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4129 return NT_STATUS_NOT_IMPLEMENTED
;
4133 NTSTATUS
cli_get_session_key(TALLOC_CTX
*mem_ctx
,
4134 struct rpc_pipe_client
*cli
,
4135 DATA_BLOB
*session_key
)
4137 if (!session_key
|| !cli
) {
4138 return NT_STATUS_INVALID_PARAMETER
;
4142 return NT_STATUS_INVALID_PARAMETER
;
4145 switch (cli
->auth
->auth_type
) {
4146 case PIPE_AUTH_TYPE_SCHANNEL
:
4147 *session_key
= data_blob_talloc(mem_ctx
,
4148 cli
->auth
->a_u
.schannel_auth
->creds
->session_key
, 16);
4150 case PIPE_AUTH_TYPE_NTLMSSP
:
4151 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
:
4152 *session_key
= data_blob_talloc(mem_ctx
,
4153 cli
->auth
->a_u
.ntlmssp_state
->session_key
.data
,
4154 cli
->auth
->a_u
.ntlmssp_state
->session_key
.length
);
4156 case PIPE_AUTH_TYPE_KRB5
:
4157 case PIPE_AUTH_TYPE_SPNEGO_KRB5
:
4158 *session_key
= data_blob_talloc(mem_ctx
,
4159 cli
->auth
->a_u
.kerberos_auth
->session_key
.data
,
4160 cli
->auth
->a_u
.kerberos_auth
->session_key
.length
);
4162 case PIPE_AUTH_TYPE_NONE
:
4163 *session_key
= data_blob_talloc(mem_ctx
,
4164 cli
->auth
->user_session_key
.data
,
4165 cli
->auth
->user_session_key
.length
);
4168 return NT_STATUS_NO_USER_SESSION_KEY
;
4171 return NT_STATUS_OK
;