@@ -277,6 +277,19 @@ impl Sspi for Kerberos {
277
277
let key_usage = self . encryption_params . sspi_encrypt_key_usage ;
278
278
279
279
let mut wrap_token = WrapToken :: with_seq_number ( seq_number as u64 ) ;
280
+ if self . server . is_some ( ) {
281
+ // [Flags Field](https://datatracker.ietf.org/doc/html/rfc4121#section-4.2.2):
282
+ //
283
+ // The meanings of bits in this field (the least significant bit is bit 0) are as follows:
284
+ // Bit Name Description
285
+ // --------------------------------------------------------------
286
+ // 0 SentByAcceptor When set, this flag indicates the sender
287
+ // is the context acceptor. When not set,
288
+ // it indicates the sender is the context
289
+ // initiator.
290
+ // When the Kerberos is used as the Kerberos server we have to set the `SentByAcceptor` flag.
291
+ wrap_token. flags |= 0x01 ;
292
+ }
280
293
wrap_token. ec = self . encryption_params . ec ;
281
294
282
295
let mut payload = data_to_encrypt. fold ( Vec :: new ( ) , |mut acc, buffer| {
@@ -379,6 +392,33 @@ impl Sspi for Kerberos {
379
392
let key_usage = self . encryption_params . sspi_decrypt_key_usage ;
380
393
381
394
let wrap_token = WrapToken :: decode ( encrypted. as_slice ( ) ) ?;
395
+ // [Flags Field](https://datatracker.ietf.org/doc/html/rfc4121#section-4.2.2):
396
+ //
397
+ // The meanings of bits in this field (the least significant bit is bit 0) are as follows:
398
+ // Bit Name Description
399
+ // --------------------------------------------------------------
400
+ // 0 SentByAcceptor When set, this flag indicates the sender
401
+ // is the context acceptor. When not set,
402
+ // it indicates the sender is the context
403
+ // initiator.
404
+ let is_server = u8:: from ( self . server . is_some ( ) ) ;
405
+ // If the Kerberos acts as the Kerberos application server, then the `SentByAcceptor` flag
406
+ // of the incoming WRAP token must be disabled (because it is sent by initiator).
407
+ if wrap_token. flags & 0x01 == is_server {
408
+ return Err ( Error :: new (
409
+ ErrorKind :: InvalidToken ,
410
+ "invalid WRAP token SentByAcceptor flag" ,
411
+ ) ) ;
412
+ }
413
+ // 1 Sealed When set in Wrap tokens, this flag
414
+ // indicates confidentiality is provided
415
+ // for. It SHALL NOT be set in MIC tokens.
416
+ if wrap_token. flags & 0b10 != 0b10 {
417
+ return Err ( Error :: new (
418
+ ErrorKind :: InvalidToken ,
419
+ "the Sealed flag has to be set in WRAP token" ,
420
+ ) ) ;
421
+ }
382
422
383
423
let mut checksum = wrap_token. checksum ;
384
424
// [3.4.5.4.1 Kerberos Binding of GSS_WrapEx()](learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/e94b3acd-8415-4d0d-9786-749d0c39d550):
@@ -623,10 +663,18 @@ impl SspiEx for Kerberos {
623
663
624
664
#[ cfg( any( feature = "__test-data" , test) ) ]
625
665
pub mod test_data {
666
+ use std:: time:: Duration ;
667
+
668
+ use picky_asn1:: restricted_string:: IA5String ;
669
+ use picky_asn1:: wrapper:: { Asn1SequenceOf , ExplicitContextTag0 , ExplicitContextTag1 , IntegerAsn1 } ;
626
670
use picky_krb:: constants:: key_usages:: { ACCEPTOR_SEAL , INITIATOR_SEAL } ;
671
+ use picky_krb:: constants:: types:: NT_SRV_INST ;
627
672
use picky_krb:: crypto:: CipherSuite ;
673
+ use picky_krb:: data_types:: { KerberosStringAsn1 , PrincipalName } ;
674
+ use picky_krb:: gss_api:: MechTypeList ;
628
675
629
676
use super :: { EncryptionParams , KerberosConfig , KerberosState } ;
677
+ use crate :: kerberos:: ServerProperties ;
630
678
use crate :: Kerberos ;
631
679
632
680
const SESSION_KEY : & [ u8 ] = & [
@@ -664,6 +712,24 @@ pub mod test_data {
664
712
}
665
713
}
666
714
715
+ pub fn fake_server_properties ( ) -> ServerProperties {
716
+ ServerProperties {
717
+ mech_types : MechTypeList :: from ( Vec :: new ( ) ) ,
718
+ max_time_skew : Duration :: from_secs ( 3 * 60 ) ,
719
+ ticket_decryption_key : None ,
720
+ service_name : PrincipalName {
721
+ name_type : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ NT_SRV_INST ] ) ) ,
722
+ name_string : ExplicitContextTag1 :: from ( Asn1SequenceOf :: from ( vec ! [
723
+ KerberosStringAsn1 :: from( IA5String :: from_string( "TERMSRV" . to_owned( ) ) . unwrap( ) ) ,
724
+ KerberosStringAsn1 :: from( IA5String :: from_string( "VM1.example.com" . to_owned( ) ) . unwrap( ) ) ,
725
+ ] ) ) ,
726
+ } ,
727
+ user : None ,
728
+ client : None ,
729
+ authenticators_cache : Default :: default ( ) ,
730
+ }
731
+ }
732
+
667
733
pub fn fake_server ( ) -> Kerberos {
668
734
Kerberos {
669
735
state : KerberosState :: Final ,
@@ -686,7 +752,7 @@ pub mod test_data {
686
752
channel_bindings : None ,
687
753
dh_parameters : None ,
688
754
krb5_user_to_user : false ,
689
- server : None ,
755
+ server : Some ( Box :: new ( fake_server_properties ( ) ) ) ,
690
756
}
691
757
}
692
758
}
0 commit comments