private void WritePreAuthRequirement(KerberosPasswordCredential credential, KrbError error, KrbAsReq asreq) { if (this.Verbose) { this.WriteLine(); } this.WriteLine(1, "{ErrorCode}: {ErrorText}", error.ErrorCode, error.ETextWithoutCode() ?? "(no message)"); this.WriteLine(); if (!string.IsNullOrWhiteSpace(error.Realm)) { this.WriteLine(1, " Realm: {Realm}", error.Realm); } if (error.CName != null) { this.WriteLine(1, " Client: {CName}", error.CName.FullyQualifiedName); } if (error.SName != null) { this.WriteLine(1, "Server: {SName}", error.SName.FullyQualifiedName); } this.WriteLine(); if (error.ErrorCode == KerberosErrorCode.KDC_ERR_ETYPE_NOSUPP) { this.IO.WriteAsColor(" Error: ", ConsoleColor.Red); this.WriteLine("Client requested the following ETypes but the KDC cannot support any of them."); this.WriteLine(); bool first = true; foreach (var etype in asreq.Body.EType) { var label = first ? "ETypes: " : " "; this.WriteLine(1, label + "{ETypes}", etype); first = false; } if (!asreq.Body.EType.Contains(EncryptionType.RC4_HMAC_NT)) { this.WriteLine(); this.IO.WriteAsColor(" Note: ", ConsoleColor.Green); this.WriteLine("RC4 is not enabled on the client. The KDC likely only supports RC4 for this user."); } return; } if (error.ErrorCode == KerberosErrorCode.KDC_ERR_POLICY && error.EData.HasValue && KrbErrorData.CanDecode(error.EData.Value)) { var decoded = KrbErrorData.Decode(error.EData.Value); var ext = decoded.DecodeExtendedError(); this.WriteLine(1, error.EText); this.WriteLine(); this.WriteLine(1, "Status: {Status}", ext.Status); this.WriteLine(1, " Flags: {Flags}", ext.Flags); return; } if (error.ErrorCode != KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED) { if (error.EData.HasValue) { this.WriteLine(1, "{EData}", error.EData); } return; } var paData = error?.DecodePreAuthentication(); if (paData != null) { int index = 0; foreach (var pa in paData.OrderBy(p => p.Type != PaDataType.PA_ETYPE_INFO2).ThenBy(p => p.Type)) { index++; this.WriteLine(2, "- PA-Data Type: {PAType} ({PATypeValue})", pa.Type, (int)pa.Type); var isEtype = pa.Type == PaDataType.PA_ETYPE_INFO2; if (isEtype) { var etypeData = pa.DecodeETypeInfo2(); this.WriteLine(3, "KDC Supported ETypes for principal {PrincipalName}", credential.UserName); this.WriteLine(); foreach (var etype in etypeData) { this.WriteLine(4, "Etype: {EType}", etype.EType); this.WriteLine(4, " Salt: {Salt}", etype.Salt); this.WriteLine(4, " S2K: {S2kParams}", etype.S2kParams ?? Array.Empty <byte>()); this.WriteLine(); } } if (!isEtype || this.Verbose) { if (pa.Value.Length > 0) { if (!isEtype) { this.WriteLine(); } this.WriteLine(3, pa.Value); } else { this.WriteLine(3, (object)null); if (index < paData.Count()) { this.WriteLine(); } } } } } }