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/crypto/gse.h"
30 #include "librpc/crypto/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
96 * @param bigendian Whether the packet is bignedian encoded
98 * @return a NTSTATUS error code
100 NTSTATUS
dcerpc_pull_ncacn_packet(TALLOC_CTX
*mem_ctx
,
101 const DATA_BLOB
*blob
,
102 struct ncacn_packet
*r
,
105 enum ndr_err_code ndr_err
;
106 struct ndr_pull
*ndr
;
108 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
110 return NT_STATUS_NO_MEMORY
;
113 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
116 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, r
);
118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
120 return ndr_map_error2ntstatus(ndr_err
);
124 if (DEBUGLEVEL
>= 10) {
125 NDR_PRINT_DEBUG(ncacn_packet
, r
);
132 * @brief NDR Encodes a NL_AUTH_MESSAGE
134 * @param mem_ctx The memory context the blob will be allocated on
135 * @param r The NL_AUTH_MESSAGE to encode
136 * @param blob [out] The encoded blob if successful
138 * @return a NTSTATUS error code
140 NTSTATUS
dcerpc_push_schannel_bind(TALLOC_CTX
*mem_ctx
,
141 struct NL_AUTH_MESSAGE
*r
,
144 enum ndr_err_code ndr_err
;
146 ndr_err
= ndr_push_struct_blob(blob
, mem_ctx
, r
,
147 (ndr_push_flags_fn_t
)ndr_push_NL_AUTH_MESSAGE
);
148 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
149 return ndr_map_error2ntstatus(ndr_err
);
152 if (DEBUGLEVEL
>= 10) {
153 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE
, r
);
160 * @brief NDR Encodes a dcerpc_auth structure
162 * @param mem_ctx The memory context the blob will be allocated on
163 * @param auth_type The DCERPC Authentication Type
164 * @param auth_level The DCERPC Authentication Level
165 * @param auth_pad_length The padding added to the packet this blob will be
167 * @param auth_context_id The context id
168 * @param credentials The authentication credentials blob (signature)
169 * @param blob [out] The encoded blob if successful
171 * @return a NTSTATUS error code
173 NTSTATUS
dcerpc_push_dcerpc_auth(TALLOC_CTX
*mem_ctx
,
174 enum dcerpc_AuthType auth_type
,
175 enum dcerpc_AuthLevel auth_level
,
176 uint8_t auth_pad_length
,
177 uint32_t auth_context_id
,
178 const DATA_BLOB
*credentials
,
181 struct dcerpc_auth r
;
182 enum ndr_err_code ndr_err
;
184 r
.auth_type
= auth_type
;
185 r
.auth_level
= auth_level
;
186 r
.auth_pad_length
= auth_pad_length
;
188 r
.auth_context_id
= auth_context_id
;
189 r
.credentials
= *credentials
;
191 ndr_err
= ndr_push_struct_blob(blob
, mem_ctx
, &r
,
192 (ndr_push_flags_fn_t
)ndr_push_dcerpc_auth
);
193 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
194 return ndr_map_error2ntstatus(ndr_err
);
197 if (DEBUGLEVEL
>= 10) {
198 NDR_PRINT_DEBUG(dcerpc_auth
, &r
);
205 * @brief Decodes a dcerpc_auth blob
207 * @param mem_ctx The memory context on which to allocate the packet
209 * @param blob The blob of data to decode
210 * @param r An empty dcerpc_auth structure, must not be NULL
212 * @return a NTSTATUS error code
214 NTSTATUS
dcerpc_pull_dcerpc_auth(TALLOC_CTX
*mem_ctx
,
215 const DATA_BLOB
*blob
,
216 struct dcerpc_auth
*r
,
219 enum ndr_err_code ndr_err
;
220 struct ndr_pull
*ndr
;
222 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
224 return NT_STATUS_NO_MEMORY
;
227 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
230 ndr_err
= ndr_pull_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, r
);
232 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
234 return ndr_map_error2ntstatus(ndr_err
);
238 if (DEBUGLEVEL
>= 10) {
239 NDR_PRINT_DEBUG(dcerpc_auth
, r
);
246 * @brief Calculate how much data we can in a packet, including calculating
247 * auth token and pad lengths.
249 * @param auth The pipe_auth_data structure for this pipe.
250 * @param header_len The length of the packet header
251 * @param data_left The data left in the send buffer
252 * @param max_xmit_frag The max fragment size.
253 * @param pad_alignment The NDR padding size.
254 * @param data_to_send [out] The max data we will send in the pdu
255 * @param frag_len [out] The total length of the fragment
256 * @param auth_len [out] The length of the auth trailer
257 * @param pad_len [out] The padding to be applied
259 * @return A NT Error status code.
261 NTSTATUS
dcerpc_guess_sizes(struct pipe_auth_data
*auth
,
262 size_t header_len
, size_t data_left
,
263 size_t max_xmit_frag
, size_t pad_alignment
,
264 size_t *data_to_send
, size_t *frag_len
,
265 size_t *auth_len
, size_t *pad_len
)
269 struct gse_context
*gse_ctx
;
270 enum spnego_mech auth_type
;
275 /* no auth token cases first */
276 switch (auth
->auth_level
) {
277 case DCERPC_AUTH_LEVEL_NONE
:
278 case DCERPC_AUTH_LEVEL_CONNECT
:
279 case DCERPC_AUTH_LEVEL_PACKET
:
280 max_len
= max_xmit_frag
- header_len
;
281 *data_to_send
= MIN(max_len
, data_left
);
284 *frag_len
= header_len
+ *data_to_send
;
287 case DCERPC_AUTH_LEVEL_PRIVACY
:
291 case DCERPC_AUTH_LEVEL_INTEGRITY
:
295 return NT_STATUS_INVALID_PARAMETER
;
299 /* Sign/seal case, calculate auth and pad lengths */
301 max_len
= max_xmit_frag
- header_len
- DCERPC_AUTH_TRAILER_LENGTH
;
303 /* Treat the same for all authenticated rpc requests. */
304 switch (auth
->auth_type
) {
305 case DCERPC_AUTH_TYPE_SPNEGO
:
307 status
= spnego_get_negotiated_mech(auth
->a_u
.spnego_state
,
308 &auth_type
, &auth_ctx
);
309 if (!NT_STATUS_IS_OK(status
)) {
314 *auth_len
= NTLMSSP_SIG_SIZE
;
318 gse_ctx
= talloc_get_type(auth_ctx
,
321 return NT_STATUS_INVALID_PARAMETER
;
323 *auth_len
= gse_get_signature_length(gse_ctx
,
328 return NT_STATUS_INVALID_PARAMETER
;
332 case DCERPC_AUTH_TYPE_NTLMSSP
:
333 *auth_len
= NTLMSSP_SIG_SIZE
;
336 case DCERPC_AUTH_TYPE_SCHANNEL
:
337 *auth_len
= NL_AUTH_SIGNATURE_SIZE
;
340 case DCERPC_AUTH_TYPE_KRB5
:
341 *auth_len
= gse_get_signature_length(auth
->a_u
.gssapi_state
,
346 return NT_STATUS_INVALID_PARAMETER
;
349 max_len
-= *auth_len
;
351 *data_to_send
= MIN(max_len
, data_left
);
353 mod_len
= (header_len
+ *data_to_send
) % pad_alignment
;
355 *pad_len
= pad_alignment
- mod_len
;
360 if (*data_to_send
+ *pad_len
> max_len
) {
361 *data_to_send
-= pad_alignment
;
364 *frag_len
= header_len
+ *data_to_send
+ *pad_len
365 + DCERPC_AUTH_TRAILER_LENGTH
+ *auth_len
;
370 /*******************************************************************
371 Create and add the NTLMSSP sign/seal auth data.
372 ********************************************************************/
374 static NTSTATUS
add_ntlmssp_auth_footer(struct auth_ntlmssp_state
*auth_state
,
375 enum dcerpc_AuthLevel auth_level
,
378 uint16_t data_and_pad_len
= rpc_out
->length
379 - DCERPC_RESPONSE_LENGTH
380 - DCERPC_AUTH_TRAILER_LENGTH
;
385 return NT_STATUS_INVALID_PARAMETER
;
388 switch (auth_level
) {
389 case DCERPC_AUTH_LEVEL_PRIVACY
:
390 /* Data portion is encrypted. */
391 status
= auth_ntlmssp_seal_packet(auth_state
,
394 + DCERPC_RESPONSE_LENGTH
,
399 if (!NT_STATUS_IS_OK(status
)) {
404 case DCERPC_AUTH_LEVEL_INTEGRITY
:
405 /* Data is signed. */
406 status
= auth_ntlmssp_sign_packet(auth_state
,
409 + DCERPC_RESPONSE_LENGTH
,
414 if (!NT_STATUS_IS_OK(status
)) {
421 smb_panic("bad auth level");
423 return NT_STATUS_INVALID_PARAMETER
;
426 /* Finally attach the blob. */
427 if (!data_blob_append(NULL
, rpc_out
,
428 auth_blob
.data
, auth_blob
.length
)) {
429 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
430 (unsigned int)auth_blob
.length
));
431 return NT_STATUS_NO_MEMORY
;
433 data_blob_free(&auth_blob
);
438 /*******************************************************************
439 Check/unseal the NTLMSSP auth data. (Unseal in place).
440 ********************************************************************/
442 static NTSTATUS
get_ntlmssp_auth_footer(struct auth_ntlmssp_state
*auth_state
,
443 enum dcerpc_AuthLevel auth_level
,
444 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
445 DATA_BLOB
*auth_token
)
447 switch (auth_level
) {
448 case DCERPC_AUTH_LEVEL_PRIVACY
:
449 /* Data portion is encrypted. */
450 return auth_ntlmssp_unseal_packet(auth_state
,
457 case DCERPC_AUTH_LEVEL_INTEGRITY
:
458 /* Data is signed. */
459 return auth_ntlmssp_check_packet(auth_state
,
467 return NT_STATUS_INVALID_PARAMETER
;
471 /*******************************************************************
472 Create and add the schannel sign/seal auth data.
473 ********************************************************************/
475 static NTSTATUS
add_schannel_auth_footer(struct schannel_state
*sas
,
476 enum dcerpc_AuthLevel auth_level
,
479 uint8_t *data_p
= rpc_out
->data
+ DCERPC_RESPONSE_LENGTH
;
480 size_t data_and_pad_len
= rpc_out
->length
481 - DCERPC_RESPONSE_LENGTH
482 - DCERPC_AUTH_TRAILER_LENGTH
;
487 return NT_STATUS_INVALID_PARAMETER
;
490 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
493 switch (auth_level
) {
494 case DCERPC_AUTH_LEVEL_PRIVACY
:
495 status
= netsec_outgoing_packet(sas
,
502 case DCERPC_AUTH_LEVEL_INTEGRITY
:
503 status
= netsec_outgoing_packet(sas
,
511 status
= NT_STATUS_INTERNAL_ERROR
;
515 if (!NT_STATUS_IS_OK(status
)) {
516 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
521 if (DEBUGLEVEL
>= 10) {
522 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob
);
525 /* Finally attach the blob. */
526 if (!data_blob_append(NULL
, rpc_out
,
527 auth_blob
.data
, auth_blob
.length
)) {
528 return NT_STATUS_NO_MEMORY
;
530 data_blob_free(&auth_blob
);
535 /*******************************************************************
536 Check/unseal the Schannel auth data. (Unseal in place).
537 ********************************************************************/
539 static NTSTATUS
get_schannel_auth_footer(TALLOC_CTX
*mem_ctx
,
540 struct schannel_state
*auth_state
,
541 enum dcerpc_AuthLevel auth_level
,
542 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
543 DATA_BLOB
*auth_token
)
545 switch (auth_level
) {
546 case DCERPC_AUTH_LEVEL_PRIVACY
:
547 /* Data portion is encrypted. */
548 return netsec_incoming_packet(auth_state
,
554 case DCERPC_AUTH_LEVEL_INTEGRITY
:
555 /* Data is signed. */
556 return netsec_incoming_packet(auth_state
,
563 return NT_STATUS_INVALID_PARAMETER
;
567 /*******************************************************************
568 Create and add the gssapi sign/seal auth data.
569 ********************************************************************/
571 static NTSTATUS
add_gssapi_auth_footer(struct gse_context
*gse_ctx
,
572 enum dcerpc_AuthLevel auth_level
,
580 return NT_STATUS_INVALID_PARAMETER
;
583 data
.data
= rpc_out
->data
+ DCERPC_RESPONSE_LENGTH
;
584 data
.length
= rpc_out
->length
- DCERPC_RESPONSE_LENGTH
585 - DCERPC_AUTH_TRAILER_LENGTH
;
587 switch (auth_level
) {
588 case DCERPC_AUTH_LEVEL_PRIVACY
:
589 status
= gse_seal(talloc_tos(), gse_ctx
, &data
, &auth_blob
);
591 case DCERPC_AUTH_LEVEL_INTEGRITY
:
592 status
= gse_sign(talloc_tos(), gse_ctx
, &data
, &auth_blob
);
595 status
= NT_STATUS_INTERNAL_ERROR
;
599 if (!NT_STATUS_IS_OK(status
)) {
600 DEBUG(1, ("Failed to process packet: %s\n",
605 /* Finally attach the blob. */
606 if (!data_blob_append(NULL
, rpc_out
,
607 auth_blob
.data
, auth_blob
.length
)) {
608 return NT_STATUS_NO_MEMORY
;
611 data_blob_free(&auth_blob
);
616 /*******************************************************************
617 Check/unseal the gssapi auth data. (Unseal in place).
618 ********************************************************************/
620 static NTSTATUS
get_gssapi_auth_footer(TALLOC_CTX
*mem_ctx
,
621 struct gse_context
*gse_ctx
,
622 enum dcerpc_AuthLevel auth_level
,
623 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
624 DATA_BLOB
*auth_token
)
626 /* TODO: pass in full_pkt when
627 * DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN is set */
628 switch (auth_level
) {
629 case DCERPC_AUTH_LEVEL_PRIVACY
:
630 /* Data portion is encrypted. */
631 return gse_unseal(mem_ctx
, gse_ctx
,
634 case DCERPC_AUTH_LEVEL_INTEGRITY
:
635 /* Data is signed. */
636 return gse_sigcheck(mem_ctx
, gse_ctx
,
639 return NT_STATUS_INVALID_PARAMETER
;
643 /*******************************************************************
644 Create and add the spnego-negotiated sign/seal auth data.
645 ********************************************************************/
647 static NTSTATUS
add_spnego_auth_footer(struct spnego_context
*spnego_ctx
,
648 enum dcerpc_AuthLevel auth_level
,
651 enum spnego_mech auth_type
;
652 struct gse_context
*gse_ctx
;
653 struct auth_ntlmssp_state
*ntlmssp_ctx
;
658 return NT_STATUS_INVALID_PARAMETER
;
661 status
= spnego_get_negotiated_mech(spnego_ctx
,
662 &auth_type
, &auth_ctx
);
663 if (!NT_STATUS_IS_OK(status
)) {
669 gse_ctx
= talloc_get_type(auth_ctx
, struct gse_context
);
671 status
= NT_STATUS_INTERNAL_ERROR
;
674 status
= add_gssapi_auth_footer(gse_ctx
,
675 auth_level
, rpc_out
);
679 ntlmssp_ctx
= talloc_get_type(auth_ctx
,
680 struct auth_ntlmssp_state
);
682 status
= NT_STATUS_INTERNAL_ERROR
;
685 status
= add_ntlmssp_auth_footer(ntlmssp_ctx
,
686 auth_level
, rpc_out
);
690 status
= NT_STATUS_INTERNAL_ERROR
;
697 static NTSTATUS
get_spnego_auth_footer(TALLOC_CTX
*mem_ctx
,
698 struct spnego_context
*sp_ctx
,
699 enum dcerpc_AuthLevel auth_level
,
700 DATA_BLOB
*data
, DATA_BLOB
*full_pkt
,
701 DATA_BLOB
*auth_token
)
703 enum spnego_mech auth_type
;
704 struct auth_ntlmssp_state
*ntlmssp_ctx
;
705 struct gse_context
*gse_ctx
;
709 status
= spnego_get_negotiated_mech(sp_ctx
, &auth_type
, &auth_ctx
);
710 if (!NT_STATUS_IS_OK(status
)) {
716 gse_ctx
= talloc_get_type(auth_ctx
,
719 return NT_STATUS_INVALID_PARAMETER
;
722 DEBUG(10, ("KRB5 auth\n"));
724 return get_gssapi_auth_footer(mem_ctx
, gse_ctx
,
729 ntlmssp_ctx
= talloc_get_type(auth_ctx
,
730 struct auth_ntlmssp_state
);
732 return NT_STATUS_INVALID_PARAMETER
;
735 DEBUG(10, ("NTLMSSP auth\n"));
737 return get_ntlmssp_auth_footer(ntlmssp_ctx
,
742 return NT_STATUS_INVALID_PARAMETER
;
747 * @brief Append an auth footer according to what is the current mechanism
749 * @param auth The pipe_auth_data associated with the connection
750 * @param pad_len The padding used in the packet
751 * @param rpc_out Packet blob up to and including the auth header
753 * @return A NTSTATUS error code.
755 NTSTATUS
dcerpc_add_auth_footer(struct pipe_auth_data
*auth
,
756 size_t pad_len
, DATA_BLOB
*rpc_out
)
758 char pad
[CLIENT_NDR_PADDING_SIZE
] = { 0, };
763 if (auth
->auth_type
== DCERPC_AUTH_TYPE_NONE
) {
768 /* Copy the sign/seal padding data. */
769 if (!data_blob_append(NULL
, rpc_out
, pad
, pad_len
)) {
770 return NT_STATUS_NO_MEMORY
;
774 /* marshall the dcerpc_auth with an actually empty auth_blob.
775 * This is needed because the ntmlssp signature includes the
776 * auth header. We will append the actual blob later. */
777 auth_blob
= data_blob_null
;
778 status
= dcerpc_push_dcerpc_auth(rpc_out
->data
,
785 if (!NT_STATUS_IS_OK(status
)) {
789 /* append the header */
790 if (!data_blob_append(NULL
, rpc_out
,
791 auth_info
.data
, auth_info
.length
)) {
792 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
793 (unsigned int)auth_info
.length
));
794 return NT_STATUS_NO_MEMORY
;
796 data_blob_free(&auth_info
);
798 /* Generate any auth sign/seal and add the auth footer. */
799 switch (auth
->auth_type
) {
800 case DCERPC_AUTH_TYPE_NONE
:
801 status
= NT_STATUS_OK
;
803 case DCERPC_AUTH_TYPE_SPNEGO
:
804 status
= add_spnego_auth_footer(auth
->a_u
.spnego_state
,
805 auth
->auth_level
, rpc_out
);
807 case DCERPC_AUTH_TYPE_NTLMSSP
:
808 status
= add_ntlmssp_auth_footer(auth
->a_u
.auth_ntlmssp_state
,
812 case DCERPC_AUTH_TYPE_SCHANNEL
:
813 status
= add_schannel_auth_footer(auth
->a_u
.schannel_auth
,
817 case DCERPC_AUTH_TYPE_KRB5
:
818 status
= add_gssapi_auth_footer(auth
->a_u
.gssapi_state
,
823 status
= NT_STATUS_INVALID_PARAMETER
;
831 * @brief Check authentication for request/response packets
833 * @param auth The auth data for the connection
834 * @param pkt The actual ncacn_packet
835 * @param pkt_trailer The stub_and_verifier part of the packet
836 * @param header_size The header size
837 * @param raw_pkt The whole raw packet data blob
838 * @param pad_len [out] The padding length used in the packet
840 * @return A NTSTATUS error code
842 NTSTATUS
dcerpc_check_auth(struct pipe_auth_data
*auth
,
843 struct ncacn_packet
*pkt
,
844 DATA_BLOB
*pkt_trailer
,
850 struct dcerpc_auth auth_info
;
851 uint32_t auth_length
;
855 switch (auth
->auth_level
) {
856 case DCERPC_AUTH_LEVEL_PRIVACY
:
857 DEBUG(10, ("Requested Privacy.\n"));
860 case DCERPC_AUTH_LEVEL_INTEGRITY
:
861 DEBUG(10, ("Requested Integrity.\n"));
864 case DCERPC_AUTH_LEVEL_CONNECT
:
865 if (pkt
->auth_length
!= 0) {
871 case DCERPC_AUTH_LEVEL_NONE
:
872 if (pkt
->auth_length
!= 0) {
873 DEBUG(3, ("Got non-zero auth len on non "
874 "authenticated connection!\n"));
875 return NT_STATUS_INVALID_PARAMETER
;
881 DEBUG(3, ("Unimplemented Auth Level %d",
883 return NT_STATUS_INVALID_PARAMETER
;
886 /* Paranioa checks for auth_length. */
887 if (pkt
->auth_length
> pkt
->frag_length
) {
888 return NT_STATUS_INFO_LENGTH_MISMATCH
;
890 if (((unsigned int)pkt
->auth_length
891 + DCERPC_AUTH_TRAILER_LENGTH
< (unsigned int)pkt
->auth_length
) ||
892 ((unsigned int)pkt
->auth_length
893 + DCERPC_AUTH_TRAILER_LENGTH
< DCERPC_AUTH_TRAILER_LENGTH
)) {
894 /* Integer wrap attempt. */
895 return NT_STATUS_INFO_LENGTH_MISMATCH
;
898 status
= dcerpc_pull_auth_trailer(pkt
, pkt
, pkt_trailer
,
899 &auth_info
, &auth_length
, false);
900 if (!NT_STATUS_IS_OK(status
)) {
904 data
= data_blob_const(raw_pkt
->data
+ header_size
,
905 pkt_trailer
->length
- auth_length
);
906 full_pkt
= data_blob_const(raw_pkt
->data
,
907 raw_pkt
->length
- auth_info
.credentials
.length
);
909 switch (auth
->auth_type
) {
910 case DCERPC_AUTH_TYPE_NONE
:
913 case DCERPC_AUTH_TYPE_SPNEGO
:
915 status
= get_spnego_auth_footer(pkt
, auth
->a_u
.spnego_state
,
918 &auth_info
.credentials
);
919 if (!NT_STATUS_IS_OK(status
)) {
924 case DCERPC_AUTH_TYPE_NTLMSSP
:
926 DEBUG(10, ("NTLMSSP auth\n"));
928 status
= get_ntlmssp_auth_footer(auth
->a_u
.auth_ntlmssp_state
,
931 &auth_info
.credentials
);
932 if (!NT_STATUS_IS_OK(status
)) {
937 case DCERPC_AUTH_TYPE_SCHANNEL
:
939 DEBUG(10, ("SCHANNEL auth\n"));
941 status
= get_schannel_auth_footer(pkt
,
942 auth
->a_u
.schannel_auth
,
945 &auth_info
.credentials
);
946 if (!NT_STATUS_IS_OK(status
)) {
951 case DCERPC_AUTH_TYPE_KRB5
:
953 DEBUG(10, ("KRB5 auth\n"));
955 status
= get_gssapi_auth_footer(pkt
,
956 auth
->a_u
.gssapi_state
,
959 &auth_info
.credentials
);
960 if (!NT_STATUS_IS_OK(status
)) {
966 DEBUG(0, ("process_request_pdu: "
967 "unknown auth type %u set.\n",
968 (unsigned int)auth
->auth_type
));
969 return NT_STATUS_INVALID_PARAMETER
;
972 /* TODO: remove later
973 * this is still needed because in the server code the
974 * pkt_trailer actually has a copy of the raw data, and they
975 * are still both used in later calls */
976 if (auth
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
977 memcpy(pkt_trailer
->data
, data
.data
, data
.length
);
980 *pad_len
= auth_info
.auth_pad_length
;
981 data_blob_free(&auth_info
.credentials
);