2 * DCERPC Helper routines
3 * Günther Deschner <gd@samba.org> 2010.
4 * Simo Sorce <idra@samba.org> 2010.
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/>.
22 #include "librpc/rpc/dcerpc.h"
23 #include "librpc/gen_ndr/ndr_dcerpc.h"
24 #include "librpc/gen_ndr/ndr_schannel.h"
25 #include "../libcli/auth/schannel.h"
26 #include "../libcli/auth/spnego.h"
27 #include "../libcli/auth/ntlmssp.h"
28 #include "ntlmssp_wrap.h"
29 #include "librpc/rpc/dcerpc_gssapi.h"
30 #include "librpc/rpc/dcerpc_spnego.h"
33 #define DBGC_CLASS DBGC_RPC_PARSE
36 * @brief NDR Encodes a ncacn_packet
38 * @param mem_ctx The memory context the blob will be allocated on
39 * @param ptype The DCERPC packet type
40 * @param pfc_flags The DCERPC PFC Falgs
41 * @param auth_length The length of the trailing auth blob
42 * @param call_id The call ID
43 * @param u The payload of the packet
44 * @param blob [out] The encoded blob if successful
46 * @return an NTSTATUS error code
48 NTSTATUS
dcerpc_push_ncacn_packet(TALLOC_CTX
*mem_ctx
,
49 enum dcerpc_pkt_type ptype
,
53 union dcerpc_payload
*u
,
56 struct ncacn_packet r
;
57 enum ndr_err_code ndr_err
;
62 r
.pfc_flags
= pfc_flags
;
63 r
.drep
[0] = DCERPC_DREP_LE
;
67 r
.auth_length
= auth_length
;
71 ndr_err
= ndr_push_struct_blob(blob
, mem_ctx
, &r
,
72 (ndr_push_flags_fn_t
)ndr_push_ncacn_packet
);
73 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
74 return ndr_map_error2ntstatus(ndr_err
);
77 dcerpc_set_frag_length(blob
, blob
->length
);
80 if (DEBUGLEVEL
>= 10) {
81 /* set frag len for print function */
82 r
.frag_length
= blob
->length
;
83 NDR_PRINT_DEBUG(ncacn_packet
, &r
);
90 * @brief Decodes a ncacn_packet
92 * @param mem_ctx The memory context on which to allocate the packet
94 * @param blob The blob of data to decode
95 * @param r An empty ncacn_packet, must not be NULL
97 * @return a NTSTATUS error code
99 NTSTATUS
dcerpc_pull_ncacn_packet(TALLOC_CTX
*mem_ctx
,
100 const DATA_BLOB
*blob
,
101 struct ncacn_packet
*r
,
104 enum ndr_err_code ndr_err
;
105 struct ndr_pull
*ndr
;
107 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
109 return NT_STATUS_NO_MEMORY
;
112 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
115 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, r
);
117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
119 return ndr_map_error2ntstatus(ndr_err
);
123 if (DEBUGLEVEL
>= 10) {
124 NDR_PRINT_DEBUG(ncacn_packet
, r
);
131 * @brief NDR Encodes a NL_AUTH_MESSAGE
133 * @param mem_ctx The memory context the blob will be allocated on
134 * @param r The NL_AUTH_MESSAGE to encode
135 * @param blob [out] The encoded blob if successful
137 * @return a NTSTATUS error code
139 NTSTATUS
dcerpc_push_schannel_bind(TALLOC_CTX
*mem_ctx
,
140 struct NL_AUTH_MESSAGE
*r
,
143 enum ndr_err_code ndr_err
;
145 ndr_err
= ndr_push_struct_blob(blob
, mem_ctx
, r
,
146 (ndr_push_flags_fn_t
)ndr_push_NL_AUTH_MESSAGE
);
147 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
148 return ndr_map_error2ntstatus(ndr_err
);
151 if (DEBUGLEVEL
>= 10) {
152 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE
, r
);
159 * @brief NDR Encodes a dcerpc_auth structure
161 * @param mem_ctx The memory context the blob will be allocated on
162 * @param auth_type The DCERPC Authentication Type
163 * @param auth_level The DCERPC Authentication Level
164 * @param auth_pad_length The padding added to the packet this blob will be
166 * @param auth_context_id The context id
167 * @param credentials The authentication credentials blob (signature)
168 * @param blob [out] The encoded blob if successful
170 * @return a NTSTATUS error code
172 NTSTATUS
dcerpc_push_dcerpc_auth(TALLOC_CTX
*mem_ctx
,
173 enum dcerpc_AuthType auth_type
,
174 enum dcerpc_AuthLevel auth_level
,
175 uint8_t auth_pad_length
,
176 uint32_t auth_context_id
,
177 const DATA_BLOB
*credentials
,
180 struct dcerpc_auth r
;
181 enum ndr_err_code ndr_err
;
183 r
.auth_type
= auth_type
;
184 r
.auth_level
= auth_level
;
185 r
.auth_pad_length
= auth_pad_length
;
187 r
.auth_context_id
= auth_context_id
;
188 r
.credentials
= *credentials
;
190 ndr_err
= ndr_push_struct_blob(blob
, mem_ctx
, &r
,
191 (ndr_push_flags_fn_t
)ndr_push_dcerpc_auth
);
192 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
193 return ndr_map_error2ntstatus(ndr_err
);
196 if (DEBUGLEVEL
>= 10) {
197 NDR_PRINT_DEBUG(dcerpc_auth
, &r
);
204 * @brief Decodes a dcerpc_auth blob
206 * @param mem_ctx The memory context on which to allocate the packet
208 * @param blob The blob of data to decode
209 * @param r An empty dcerpc_auth structure, must not be NULL
211 * @return a NTSTATUS error code
213 NTSTATUS
dcerpc_pull_dcerpc_auth(TALLOC_CTX
*mem_ctx
,
214 const DATA_BLOB
*blob
,
215 struct dcerpc_auth
*r
,
218 enum ndr_err_code ndr_err
;
219 struct ndr_pull
*ndr
;
221 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
223 return NT_STATUS_NO_MEMORY
;
226 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
229 ndr_err
= ndr_pull_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, r
);
231 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
233 return ndr_map_error2ntstatus(ndr_err
);
237 if (DEBUGLEVEL
>= 10) {
238 NDR_PRINT_DEBUG(dcerpc_auth
, r
);
245 * @brief Calculate how much data we can in a packet, including calculating
246 * auth token and pad lengths.
248 * @param auth The pipe_auth_data structure for this pipe.
249 * @param data_left The data left in the send buffer
250 * @param data_to_send The max data we will send in the pdu
251 * @param frag_len The total length of the fragment
252 * @param auth_len The length of the auth trailer
253 * @param pad_len The padding to be applied
255 * @return A NT Error status code.
257 NTSTATUS
dcerpc_guess_sizes(struct pipe_auth_data
*auth
,
258 size_t data_left
, size_t max_xmit_frag
,
259 size_t *data_to_send
, size_t *frag_len
,
260 size_t *auth_len
, size_t *pad_len
)
265 struct gse_context
*gse_ctx
;
266 enum dcerpc_AuthType auth_type
;
271 /* no auth token cases first */
272 switch (auth
->auth_level
) {
273 case DCERPC_AUTH_LEVEL_NONE
:
274 case DCERPC_AUTH_LEVEL_CONNECT
:
275 case DCERPC_AUTH_LEVEL_PACKET
:
276 data_space
= max_xmit_frag
- DCERPC_REQUEST_LENGTH
;
277 *data_to_send
= MIN(data_space
, data_left
);
280 *frag_len
= DCERPC_REQUEST_LENGTH
+ *data_to_send
;
283 case DCERPC_AUTH_LEVEL_PRIVACY
:
287 case DCERPC_AUTH_LEVEL_INTEGRITY
:
291 return NT_STATUS_INVALID_PARAMETER
;
295 /* Sign/seal case, calculate auth and pad lengths */
297 max_len
= max_xmit_frag
298 - DCERPC_REQUEST_LENGTH
299 - DCERPC_AUTH_TRAILER_LENGTH
;
301 /* Treat the same for all authenticated rpc requests. */
302 switch (auth
->auth_type
) {
303 case DCERPC_AUTH_TYPE_SPNEGO
:
304 /* compat for server code */
305 if (auth
->spnego_type
== PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
) {
306 *auth_len
= NTLMSSP_SIG_SIZE
;
310 status
= spnego_get_negotiated_mech(auth
->a_u
.spnego_state
,
311 &auth_type
, &auth_ctx
);
312 if (!NT_STATUS_IS_OK(status
)) {
316 case DCERPC_AUTH_TYPE_NTLMSSP
:
317 *auth_len
= NTLMSSP_SIG_SIZE
;
320 case DCERPC_AUTH_TYPE_KRB5
:
321 gse_ctx
= talloc_get_type(auth_ctx
,
324 return NT_STATUS_INVALID_PARAMETER
;
326 *auth_len
= gse_get_signature_length(gse_ctx
,
331 return NT_STATUS_INVALID_PARAMETER
;
335 case DCERPC_AUTH_TYPE_NTLMSSP
:
336 *auth_len
= NTLMSSP_SIG_SIZE
;
339 case DCERPC_AUTH_TYPE_SCHANNEL
:
340 *auth_len
= NL_AUTH_SIGNATURE_SIZE
;
343 case DCERPC_AUTH_TYPE_KRB5
:
344 *auth_len
= gse_get_signature_length(auth
->a_u
.gssapi_state
,
349 return NT_STATUS_INVALID_PARAMETER
;
352 data_space
= max_len
- *auth_len
;
354 *data_to_send
= MIN(data_space
, data_left
);
355 mod_len
= *data_to_send
% CLIENT_NDR_PADDING_SIZE
;
357 *pad_len
= CLIENT_NDR_PADDING_SIZE
- mod_len
;
361 *frag_len
= DCERPC_REQUEST_LENGTH
+ *data_to_send
+ *pad_len
362 + DCERPC_AUTH_TRAILER_LENGTH
+ *auth_len
;
367 /*******************************************************************
368 Create and add the NTLMSSP sign/seal auth data.
369 ********************************************************************/
371 static NTSTATUS
add_ntlmssp_auth_footer(struct auth_ntlmssp_state
*auth_state
,
372 enum dcerpc_AuthLevel auth_level
,
375 uint16_t data_and_pad_len
= rpc_out
->length
376 - DCERPC_RESPONSE_LENGTH
377 - DCERPC_AUTH_TRAILER_LENGTH
;
382 return NT_STATUS_INVALID_PARAMETER
;
385 switch (auth_level
) {
386 case DCERPC_AUTH_LEVEL_PRIVACY
:
387 /* Data portion is encrypted. */
388 status
= auth_ntlmssp_seal_packet(auth_state
,
391 + DCERPC_RESPONSE_LENGTH
,
396 if (!NT_STATUS_IS_OK(status
)) {
401 case DCERPC_AUTH_LEVEL_INTEGRITY
:
402 /* Data is signed. */
403 status
= auth_ntlmssp_sign_packet(auth_state
,
406 + DCERPC_RESPONSE_LENGTH
,
411 if (!NT_STATUS_IS_OK(status
)) {
418 smb_panic("bad auth level");
420 return NT_STATUS_INVALID_PARAMETER
;
423 /* Finally attach the blob. */
424 if (!data_blob_append(NULL
, rpc_out
,
425 auth_blob
.data
, auth_blob
.length
)) {
426 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
427 (unsigned int)auth_blob
.length
));
428 return NT_STATUS_NO_MEMORY
;
430 data_blob_free(&auth_blob
);
435 /*******************************************************************
436 Check/unseal the NTLMSSP auth data. (Unseal in place).
437 ********************************************************************/
439 static NTSTATUS
get_ntlmssp_auth_footer(struct auth_ntlmssp_state
*auth_state
,
440 enum dcerpc_AuthLevel auth_level
,
441 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
442 DATA_BLOB
*auth_token
)
444 switch (auth_level
) {
445 case DCERPC_AUTH_LEVEL_PRIVACY
:
446 /* Data portion is encrypted. */
447 return auth_ntlmssp_unseal_packet(auth_state
,
454 case DCERPC_AUTH_LEVEL_INTEGRITY
:
455 /* Data is signed. */
456 return auth_ntlmssp_check_packet(auth_state
,
464 return NT_STATUS_INVALID_PARAMETER
;
468 /*******************************************************************
469 Create and add the schannel sign/seal auth data.
470 ********************************************************************/
472 static NTSTATUS
add_schannel_auth_footer(struct schannel_state
*sas
,
473 enum dcerpc_AuthLevel auth_level
,
476 uint8_t *data_p
= rpc_out
->data
+ DCERPC_RESPONSE_LENGTH
;
477 size_t data_and_pad_len
= rpc_out
->length
478 - DCERPC_RESPONSE_LENGTH
479 - DCERPC_AUTH_TRAILER_LENGTH
;
484 return NT_STATUS_INVALID_PARAMETER
;
487 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
490 switch (auth_level
) {
491 case DCERPC_AUTH_LEVEL_PRIVACY
:
492 status
= netsec_outgoing_packet(sas
,
499 case DCERPC_AUTH_LEVEL_INTEGRITY
:
500 status
= netsec_outgoing_packet(sas
,
508 status
= NT_STATUS_INTERNAL_ERROR
;
512 if (!NT_STATUS_IS_OK(status
)) {
513 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
518 if (DEBUGLEVEL
>= 10) {
519 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob
);
522 /* Finally attach the blob. */
523 if (!data_blob_append(NULL
, rpc_out
,
524 auth_blob
.data
, auth_blob
.length
)) {
525 return NT_STATUS_NO_MEMORY
;
527 data_blob_free(&auth_blob
);
532 /*******************************************************************
533 Check/unseal the Schannel auth data. (Unseal in place).
534 ********************************************************************/
536 static NTSTATUS
get_schannel_auth_footer(TALLOC_CTX
*mem_ctx
,
537 struct schannel_state
*auth_state
,
538 enum dcerpc_AuthLevel auth_level
,
539 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
540 DATA_BLOB
*auth_token
)
542 switch (auth_level
) {
543 case DCERPC_AUTH_LEVEL_PRIVACY
:
544 /* Data portion is encrypted. */
545 return netsec_incoming_packet(auth_state
,
551 case DCERPC_AUTH_LEVEL_INTEGRITY
:
552 /* Data is signed. */
553 return netsec_incoming_packet(auth_state
,
560 return NT_STATUS_INVALID_PARAMETER
;
564 /*******************************************************************
565 Create and add the gssapi sign/seal auth data.
566 ********************************************************************/
568 static NTSTATUS
add_gssapi_auth_footer(struct gse_context
*gse_ctx
,
569 enum dcerpc_AuthLevel auth_level
,
577 return NT_STATUS_INVALID_PARAMETER
;
580 data
.data
= rpc_out
->data
+ DCERPC_RESPONSE_LENGTH
;
581 data
.length
= rpc_out
->length
- DCERPC_RESPONSE_LENGTH
582 - DCERPC_AUTH_TRAILER_LENGTH
;
584 switch (auth_level
) {
585 case DCERPC_AUTH_LEVEL_PRIVACY
:
586 status
= gse_seal(talloc_tos(), gse_ctx
, &data
, &auth_blob
);
588 case DCERPC_AUTH_LEVEL_INTEGRITY
:
589 status
= gse_sign(talloc_tos(), gse_ctx
, &data
, &auth_blob
);
592 status
= NT_STATUS_INTERNAL_ERROR
;
596 if (!NT_STATUS_IS_OK(status
)) {
597 DEBUG(1, ("Failed to process packet: %s\n",
602 /* Finally attach the blob. */
603 if (!data_blob_append(NULL
, rpc_out
,
604 auth_blob
.data
, auth_blob
.length
)) {
605 return NT_STATUS_NO_MEMORY
;
608 data_blob_free(&auth_blob
);
613 /*******************************************************************
614 Check/unseal the gssapi auth data. (Unseal in place).
615 ********************************************************************/
617 static NTSTATUS
get_gssapi_auth_footer(TALLOC_CTX
*mem_ctx
,
618 struct gse_context
*gse_ctx
,
619 enum dcerpc_AuthLevel auth_level
,
620 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
621 DATA_BLOB
*auth_token
)
623 /* TODO: pass in full_pkt when
624 * DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN is set */
625 switch (auth_level
) {
626 case DCERPC_AUTH_LEVEL_PRIVACY
:
627 /* Data portion is encrypted. */
628 return gse_unseal(mem_ctx
, gse_ctx
,
631 case DCERPC_AUTH_LEVEL_INTEGRITY
:
632 /* Data is signed. */
633 return gse_sigcheck(mem_ctx
, gse_ctx
,
636 return NT_STATUS_INVALID_PARAMETER
;
640 /*******************************************************************
641 Create and add the spnego-negotiated sign/seal auth data.
642 ********************************************************************/
644 static NTSTATUS
add_spnego_auth_footer(struct spnego_context
*spnego_ctx
,
645 enum dcerpc_AuthLevel auth_level
,
648 enum dcerpc_AuthType auth_type
;
649 struct gse_context
*gse_ctx
;
650 struct auth_ntlmssp_state
*ntlmssp_ctx
;
655 return NT_STATUS_INVALID_PARAMETER
;
658 status
= spnego_get_negotiated_mech(spnego_ctx
,
659 &auth_type
, &auth_ctx
);
660 if (!NT_STATUS_IS_OK(status
)) {
665 case DCERPC_AUTH_TYPE_KRB5
:
666 gse_ctx
= talloc_get_type(auth_ctx
, struct gse_context
);
668 status
= NT_STATUS_INTERNAL_ERROR
;
671 status
= add_gssapi_auth_footer(gse_ctx
,
672 auth_level
, rpc_out
);
675 case DCERPC_AUTH_TYPE_NTLMSSP
:
676 ntlmssp_ctx
= talloc_get_type(auth_ctx
,
677 struct auth_ntlmssp_state
);
679 status
= NT_STATUS_INTERNAL_ERROR
;
682 status
= add_ntlmssp_auth_footer(ntlmssp_ctx
,
683 auth_level
, rpc_out
);
687 status
= NT_STATUS_INTERNAL_ERROR
;
694 static NTSTATUS
get_spnego_auth_footer(TALLOC_CTX
*mem_ctx
,
695 struct spnego_context
*sp_ctx
,
696 enum dcerpc_AuthLevel auth_level
,
697 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
698 DATA_BLOB
*auth_token
)
700 enum dcerpc_AuthType auth_type
;
701 struct auth_ntlmssp_state
*ntlmssp_ctx
;
702 struct gse_context
*gse_ctx
;
706 status
= spnego_get_negotiated_mech(sp_ctx
, &auth_type
, &auth_ctx
);
707 if (!NT_STATUS_IS_OK(status
)) {
712 case DCERPC_AUTH_TYPE_KRB5
:
713 gse_ctx
= talloc_get_type(auth_ctx
,
716 return NT_STATUS_INVALID_PARAMETER
;
719 DEBUG(10, ("KRB5 auth\n"));
721 return get_gssapi_auth_footer(mem_ctx
, gse_ctx
,
725 case DCERPC_AUTH_TYPE_NTLMSSP
:
726 ntlmssp_ctx
= talloc_get_type(auth_ctx
,
727 struct auth_ntlmssp_state
);
729 return NT_STATUS_INVALID_PARAMETER
;
732 DEBUG(10, ("NTLMSSP auth\n"));
734 return get_ntlmssp_auth_footer(ntlmssp_ctx
,
739 return NT_STATUS_INVALID_PARAMETER
;
744 * @brief Append an auth footer according to what is the current mechanism
746 * @param auth The pipe_auth_data associated with the connection
747 * @param pad_len The padding used in the packet
748 * @param rpc_out Packet blob up to and including the auth header
750 * @return A NTSTATUS error code.
752 NTSTATUS
dcerpc_add_auth_footer(struct pipe_auth_data
*auth
,
753 size_t pad_len
, DATA_BLOB
*rpc_out
)
755 char pad
[CLIENT_NDR_PADDING_SIZE
] = { 0, };
760 if (auth
->auth_type
== DCERPC_AUTH_TYPE_NONE
) {
765 /* Copy the sign/seal padding data. */
766 if (!data_blob_append(NULL
, rpc_out
, pad
, pad_len
)) {
767 return NT_STATUS_NO_MEMORY
;
771 /* marshall the dcerpc_auth with an actually empty auth_blob.
772 * This is needed because the ntmlssp signature includes the
773 * auth header. We will append the actual blob later. */
774 auth_blob
= data_blob_null
;
775 status
= dcerpc_push_dcerpc_auth(rpc_out
->data
,
782 if (!NT_STATUS_IS_OK(status
)) {
786 /* append the header */
787 if (!data_blob_append(NULL
, rpc_out
,
788 auth_info
.data
, auth_info
.length
)) {
789 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
790 (unsigned int)auth_info
.length
));
791 return NT_STATUS_NO_MEMORY
;
793 data_blob_free(&auth_info
);
795 /* Generate any auth sign/seal and add the auth footer. */
796 switch (auth
->auth_type
) {
797 case DCERPC_AUTH_TYPE_NONE
:
798 status
= NT_STATUS_OK
;
800 case DCERPC_AUTH_TYPE_SPNEGO
:
801 if (auth
->spnego_type
== PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
) {
802 /* compat for server code */
803 return add_ntlmssp_auth_footer(
804 auth
->a_u
.auth_ntlmssp_state
,
808 status
= add_spnego_auth_footer(auth
->a_u
.spnego_state
,
809 auth
->auth_level
, rpc_out
);
811 case DCERPC_AUTH_TYPE_NTLMSSP
:
812 status
= add_ntlmssp_auth_footer(auth
->a_u
.auth_ntlmssp_state
,
816 case DCERPC_AUTH_TYPE_SCHANNEL
:
817 status
= add_schannel_auth_footer(auth
->a_u
.schannel_auth
,
821 case DCERPC_AUTH_TYPE_KRB5
:
822 status
= add_gssapi_auth_footer(auth
->a_u
.gssapi_state
,
827 status
= NT_STATUS_INVALID_PARAMETER
;
835 * @brief Check authentication for request/response packets
837 * @param auth The auth data for the connection
838 * @param pkt The actual ncacn_packet
839 * @param pkt_trailer The stub_and_verifier part of the packet
840 * @param header_size The header size
841 * @param raw_pkt The whole raw packet data blob
842 * @param pad_len [out] The padding length used in the packet
844 * @return A NTSTATUS error code
846 NTSTATUS
dcerpc_check_auth(struct pipe_auth_data
*auth
,
847 struct ncacn_packet
*pkt
,
848 DATA_BLOB
*pkt_trailer
,
854 struct dcerpc_auth auth_info
;
855 uint32_t auth_length
;
859 switch (auth
->auth_level
) {
860 case DCERPC_AUTH_LEVEL_PRIVACY
:
861 DEBUG(10, ("Requested Privacy.\n"));
864 case DCERPC_AUTH_LEVEL_INTEGRITY
:
865 DEBUG(10, ("Requested Integrity.\n"));
868 case DCERPC_AUTH_LEVEL_CONNECT
:
869 if (pkt
->auth_length
!= 0) {
875 case DCERPC_AUTH_LEVEL_NONE
:
876 if (pkt
->auth_length
!= 0) {
877 DEBUG(3, ("Got non-zero auth len on non "
878 "authenticated connection!\n"));
879 return NT_STATUS_INVALID_PARAMETER
;
885 DEBUG(3, ("Unimplemented Auth Level %d",
887 return NT_STATUS_INVALID_PARAMETER
;
890 /* Paranioa checks for auth_length. */
891 if (pkt
->auth_length
> pkt
->frag_length
) {
892 return NT_STATUS_INFO_LENGTH_MISMATCH
;
894 if ((pkt
->auth_length
895 + DCERPC_AUTH_TRAILER_LENGTH
< pkt
->auth_length
) ||
897 + DCERPC_AUTH_TRAILER_LENGTH
< DCERPC_AUTH_TRAILER_LENGTH
)) {
898 /* Integer wrap attempt. */
899 return NT_STATUS_INFO_LENGTH_MISMATCH
;
902 status
= dcerpc_pull_auth_trailer(pkt
, pkt
, pkt_trailer
,
903 &auth_info
, &auth_length
, false);
904 if (!NT_STATUS_IS_OK(status
)) {
908 data
= data_blob_const(raw_pkt
->data
+ header_size
,
909 pkt_trailer
->length
- auth_length
);
910 full_pkt
= data_blob_const(raw_pkt
->data
,
911 raw_pkt
->length
- auth_info
.credentials
.length
);
913 switch (auth
->auth_type
) {
914 case DCERPC_AUTH_TYPE_NONE
:
917 case DCERPC_AUTH_TYPE_SPNEGO
:
918 if (auth
->spnego_type
== PIPE_AUTH_TYPE_SPNEGO_NTLMSSP
) {
919 /* compat for server code */
920 DEBUG(10, ("NTLMSSP auth\n"));
922 status
= get_ntlmssp_auth_footer(
923 auth
->a_u
.auth_ntlmssp_state
,
926 &auth_info
.credentials
);
927 if (!NT_STATUS_IS_OK(status
)) {
933 status
= get_spnego_auth_footer(pkt
, auth
->a_u
.spnego_state
,
936 &auth_info
.credentials
);
937 if (!NT_STATUS_IS_OK(status
)) {
942 case DCERPC_AUTH_TYPE_NTLMSSP
:
944 DEBUG(10, ("NTLMSSP auth\n"));
946 status
= get_ntlmssp_auth_footer(auth
->a_u
.auth_ntlmssp_state
,
949 &auth_info
.credentials
);
950 if (!NT_STATUS_IS_OK(status
)) {
955 case DCERPC_AUTH_TYPE_SCHANNEL
:
957 DEBUG(10, ("SCHANNEL auth\n"));
959 status
= get_schannel_auth_footer(pkt
,
960 auth
->a_u
.schannel_auth
,
963 &auth_info
.credentials
);
964 if (!NT_STATUS_IS_OK(status
)) {
969 case DCERPC_AUTH_TYPE_KRB5
:
971 DEBUG(10, ("KRB5 auth\n"));
973 status
= get_gssapi_auth_footer(pkt
,
974 auth
->a_u
.gssapi_state
,
977 &auth_info
.credentials
);
978 if (!NT_STATUS_IS_OK(status
)) {
984 DEBUG(0, ("process_request_pdu: "
985 "unknown auth type %u set.\n",
986 (unsigned int)auth
->auth_type
));
987 return NT_STATUS_INVALID_PARAMETER
;
990 /* TODO: remove later
991 * this is still needed because in the server code the
992 * pkt_trailer actually has a copy of the raw data, and they
993 * are still both used in later calls */
994 if (auth
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
995 memcpy(pkt_trailer
->data
, data
.data
, data
.length
);
998 *pad_len
= auth_info
.auth_pad_length
;
999 data_blob_free(&auth_info
.credentials
);
1000 return NT_STATUS_OK
;