@@ -803,7 +803,7 @@ pub fn generate_tgs_ap_req(
803803 } ) )
804804}
805805
806- #[ instrument( level = "trace" , ret) ]
806+ #[ instrument( level = "trace" , ret, skip_all ) ]
807807pub fn generate_ap_req (
808808 ticket : Ticket ,
809809 session_key : & Secret < Vec < u8 > > ,
@@ -817,11 +817,7 @@ pub fn generate_ap_req(
817817 let encoded_authenticator = picky_asn1_der:: to_vec ( & authenticator) ?;
818818 let encrypted_authenticator = cipher. encrypt ( session_key. as_ref ( ) , AP_REQ_AUTHENTICATOR , & encoded_authenticator) ?;
819819
820- trace ! (
821- plain = ?encoded_authenticator,
822- encrypted = ?encrypted_authenticator,
823- "AP_REQ authenticator" ,
824- ) ;
820+ trace ! ( encrypted = ?encrypted_authenticator, "AP_REQ authenticator" ) ;
825821
826822 Ok ( ApReq :: from ( ApReqInner {
827823 pvno : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ KERBEROS_VERSION ] ) ) ,
@@ -843,7 +839,7 @@ pub fn get_mech_list() -> MechTypeList {
843839 MechTypeList :: from ( vec ! [ MechType :: from( oids:: ms_krb5( ) ) , MechType :: from( oids:: krb5( ) ) ] )
844840}
845841
846- #[ instrument( level = "trace" , ret) ]
842+ #[ instrument( level = "trace" , ret, skip_all ) ]
847843pub fn generate_krb_priv_request (
848844 ticket : Ticket ,
849845 session_key : & Secret < Vec < u8 > > ,
@@ -877,12 +873,8 @@ pub fn generate_krb_priv_request(
877873
878874 let enc_part = cipher. encrypt ( encryption_key, KRB_PRIV_ENC_PART , & encoded_krb_priv) ?;
879875
880- trace ! ( ?encryption_key, ?encryption_type, "KRB_PRIV encryption params" , ) ;
881- trace ! (
882- plain = ?encoded_krb_priv,
883- encrypted = ?enc_part,
884- "KRB_PRIV encrypted part" ,
885- ) ;
876+ trace ! ( ?encryption_type, "KRB_PRIV encryption params" , ) ;
877+ trace ! ( encrypted = ?enc_part, "KRB_PRIV encrypted part" ) ;
886878
887879 let krb_priv = KrbPriv :: from ( KrbPrivInner {
888880 pvno : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ KERBEROS_VERSION ] ) ) ,
@@ -903,6 +895,7 @@ pub fn generate_krb_priv_request(
903895#[ cfg( test) ]
904896mod tests {
905897 use picky_krb:: constants:: types:: NT_PRINCIPAL ;
898+ use picky_krb:: data_types:: TicketInner ;
906899
907900 use super :: * ;
908901
@@ -1106,4 +1099,100 @@ mod tests {
11061099 ) ;
11071100 assert_eq ! ( decoded. pausec. 0 . unwrap( ) . 0.0 , 123_000_u32 . to_be_bytes( ) ) ;
11081101 }
1102+
1103+ #[ derive( Clone , Default ) ]
1104+ struct CapturedLogs ( std:: sync:: Arc < std:: sync:: Mutex < Vec < u8 > > > ) ;
1105+
1106+ impl std:: io:: Write for CapturedLogs {
1107+ fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
1108+ self . 0 . lock ( ) . unwrap ( ) . extend_from_slice ( buf) ;
1109+ Ok ( buf. len ( ) )
1110+ }
1111+
1112+ fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
1113+ Ok ( ( ) )
1114+ }
1115+ }
1116+
1117+ fn krb_string ( value : & str ) -> KerberosStringAsn1 {
1118+ KerberosStringAsn1 :: from ( IA5String :: from_string ( value. to_owned ( ) ) . unwrap ( ) )
1119+ }
1120+
1121+ fn principal ( ) -> PrincipalName {
1122+ PrincipalName {
1123+ name_type : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ NT_PRINCIPAL ] ) ) ,
1124+ name_string : ExplicitContextTag1 :: from ( Asn1SequenceOf :: from ( vec ! [ krb_string( "alice" ) ] ) ) ,
1125+ }
1126+ }
1127+
1128+ #[ test]
1129+ fn krb_priv_request_does_not_trace_new_password_or_subkey ( ) {
1130+ let new_password = b"hunter2-new-password" ;
1131+ let sub_key = vec ! [ 0xA5_u8 ; 32 ] ;
1132+ let session_key = Secret :: from ( vec ! [ 0x5A_u8 ; 32 ] ) ;
1133+
1134+ let ticket = Ticket :: from ( TicketInner {
1135+ tkt_vno : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ KERBEROS_VERSION ] ) ) ,
1136+ realm : ExplicitContextTag1 :: from ( krb_string ( "EXAMPLE.COM" ) ) ,
1137+ sname : ExplicitContextTag2 :: from ( principal ( ) ) ,
1138+ enc_part : ExplicitContextTag3 :: from ( EncryptedData {
1139+ etype : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ 18 ] ) ) ,
1140+ kvno : Optional :: from ( None ) ,
1141+ cipher : ExplicitContextTag2 :: from ( OctetStringAsn1 :: from ( vec ! [ 0x11 ; 16 ] ) ) ,
1142+ } ) ,
1143+ } ) ;
1144+ let authenticator = Authenticator :: from ( AuthenticatorInner {
1145+ authenticator_vno : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ KERBEROS_VERSION ] ) ) ,
1146+ crealm : ExplicitContextTag1 :: from ( krb_string ( "EXAMPLE.COM" ) ) ,
1147+ cname : ExplicitContextTag2 :: from ( principal ( ) ) ,
1148+ cksum : Optional :: from ( None ) ,
1149+ cusec : ExplicitContextTag4 :: from ( IntegerAsn1 :: from ( vec ! [ 0 ] ) ) ,
1150+ ctime : ExplicitContextTag5 :: from ( KerberosTime :: from ( GeneralizedTime :: from (
1151+ OffsetDateTime :: from_unix_timestamp ( 1_700_000_000 ) . unwrap ( ) ,
1152+ ) ) ) ,
1153+ subkey : Optional :: from ( Some ( ExplicitContextTag6 :: from ( EncryptionKey {
1154+ key_type : ExplicitContextTag0 :: from ( IntegerAsn1 :: from ( vec ! [ 18 ] ) ) ,
1155+ key_value : ExplicitContextTag1 :: from ( OctetStringAsn1 :: from ( sub_key. clone ( ) ) ) ,
1156+ } ) ) ) ,
1157+ seq_number : Optional :: from ( None ) ,
1158+ authorization_data : Optional :: from ( None ) ,
1159+ } ) ;
1160+ let enc_params = EncryptionParams {
1161+ encryption_type : Some ( CipherSuite :: Aes256CtsHmacSha196 ) ,
1162+ ..EncryptionParams :: default_for_client ( )
1163+ } ;
1164+
1165+ let logs = CapturedLogs :: default ( ) ;
1166+ let subscriber = tracing_subscriber:: fmt ( )
1167+ . with_max_level ( tracing:: Level :: TRACE )
1168+ . with_ansi ( false )
1169+ . with_writer ( {
1170+ let logs = logs. clone ( ) ;
1171+ move || logs. clone ( )
1172+ } )
1173+ . finish ( ) ;
1174+ tracing:: subscriber:: with_default ( subscriber, || {
1175+ generate_krb_priv_request (
1176+ ticket,
1177+ & session_key,
1178+ new_password,
1179+ & authenticator,
1180+ & enc_params,
1181+ 1 ,
1182+ "HOST" ,
1183+ )
1184+ . expect ( "generate KRB_PRIV request" ) ;
1185+ } ) ;
1186+
1187+ let output = String :: from_utf8 ( logs. 0 . lock ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
1188+ assert ! ( !output. is_empty( ) , "the trace subscriber captured nothing" ) ;
1189+ // Byte slices are rendered by `Debug` as `[a, b, ...]` and ASN.1 octet strings as `0xabcd...`.
1190+ for ( name, secret) in [ ( "new password" , & new_password[ ..] ) , ( "sub-session key" , & sub_key[ ..] ) ] {
1191+ let list = format ! ( "{secret:?}" ) ;
1192+ let hex: String = secret. iter ( ) . map ( |byte| format ! ( "{byte:02x}" ) ) . collect ( ) ;
1193+ for rendered in [ list, hex] {
1194+ assert ! ( !output. contains( & rendered) , "trace output leaks the {name}: {output}" ) ;
1195+ }
1196+ }
1197+ }
11091198}
0 commit comments