void PrintCert(TextWriter w, X509Chain xchain, int num, ReportDataDto reportData, String domain) { w.WriteLine("\tThumprint: {0}", xchain.ThumbprintsRev[num]); X509Cert xc = xchain.ElementsRev[num]; if (xc == null) { w.WriteLine("\tUNDECODABLE: {0}", xchain.DecodingIssuesRev[num]); } else { w.WriteLine("\tSerial: {0}", xc.SerialHex); w.WriteLine("\tSubject: {0}", xc.Subject.ToString()); w.WriteLine("\tIssuer: {0}", xc.Issuer.ToString()); w.WriteLine("\tValid from: {0:yyyy-MM-dd HH:mm:ss} UTC", xc.ValidFrom); w.WriteLine("\tValid to: {0:yyyy-MM-dd HH:mm:ss} UTC", xc.ValidTo); w.WriteLine("\tKey type: {0}", xc.KeyType); w.WriteLine("\tKey size: {0}", xc.KeySize); string cname = xc.CurveName; if (cname != null) { w.WriteLine("\tKey curve: {0}", cname); } w.WriteLine("\tSign hash: {0}", xc.HashAlgorithm); if (xc.SelfIssued) { w.WriteLine("\t(Self-Issued)"); } if (num == 0) { w.Write("\tServer names:"); string[] names = xc.ServerNames; if (names.Length == 0) { w.WriteLine(" NONE"); } else { foreach (string name in names) { reportData.NameMismatch = NameMismatch(name, domain); w.Write(name); } } } } if (withPEM) { M.WritePEM(w, "CERTIFICATE", xchain.EncodedRev[num]); } }
/* * Print the report on the provided writer (text version for * humans). */ public ReportDataDto Print(TextWriter w) { var reportData = new ReportDataDto(); if (sni == null) { w.WriteLine("No SNI sent"); } else { w.WriteLine("SNI: {0}", sni); } if (ssl2Suites != null && ssl2Suites.Length > 0) { w.WriteLine(" {0}", M.VersionString(M.SSLv20)); foreach (int s in ssl2Suites) { w.WriteLine(" {0}", CipherSuite.ToNameV2(s)); } } SupportedCipherSuites last = null; foreach (int v in suites.Keys) { w.Write(" {0}:", M.VersionString(v)); SupportedCipherSuites scs = suites[v]; last = scs; w.WriteLine(); w.Write(" server selection: "); if (scs.PrefClient) { w.WriteLine("uses client preferences"); } else if (scs.PrefServer) { w.WriteLine("enforce server preferences"); } else { w.WriteLine("complex"); } foreach (int s in scs.Suites) { CipherSuite cs; string strength; string fsf; string anon; string kt; if (CipherSuite.ALL.TryGetValue(s, out cs)) { strength = cs.Strength.ToString(); fsf = cs.HasForwardSecrecy ? "f" : "-"; anon = cs.IsAnonymous ? "A" : "-"; kt = cs.ServerKeyType; if (cs.Strength < 3) { reportData.WeakCipher = true; } } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } w.WriteLine(" {0}{1}{2} (key: {3,4}) {4}", strength, fsf, anon, kt, CipherSuite.ToName(s)); } } w.WriteLine(Environment.NewLine); if (ssl2Chain != null) { w.WriteLine("SSLv2 certificate"); PrintCert(w, ssl2Chain, 0, reportData, this.ConnName); w.WriteLine(Environment.NewLine); } w.WriteLine("SSLv3/TLS: {0} certificate chain(s)", chains.Count); foreach (X509Chain xchain in chains.Values) { int n = xchain.Elements.Length; w.WriteLine("Chain: length={0}", n); if (xchain.Decodable) { w.WriteLine("Names match: {0}", xchain.NamesMatch ? "yes" : "no"); w.WriteLine("Includes root: {0}", xchain.IncludesRoot ? "yes" : "no"); w.Write("Signature hash(es):"); foreach (string name in xchain.SignHashes) { w.Write(" {0}", name); } w.WriteLine(); } else if (n == 0) { w.WriteLine("CHAIN IS EMPTY"); } else { w.WriteLine("CHAIN PROCESSING ERROR"); } w.WriteLine(); for (int i = 0; i < n; i++) { w.WriteLine("Certificate: {0}", i); PrintCert(w, xchain, i, reportData, this.ConnName); } } w.WriteLine(Environment.NewLine); w.WriteLine("Server compression support: {0}", DeflateCompress ? "yes" : "no"); if (serverTimeOffset == Int64.MinValue) { w.WriteLine("Server does not send its system time."); } else if (serverTimeOffset == Int64.MaxValue) { w.WriteLine("Server sends a random system time."); } else { DateTime dt = DateTime.UtcNow; dt = dt.AddMilliseconds((double)serverTimeOffset); w.WriteLine("Server time: {0:yyyy-MM-dd HH:mm:ss} UTC (offset: {1} ms)", dt, serverTimeOffset); } w.WriteLine("Secure renegotiation support: {0}", doesRenego ? "yes" : "no"); w.WriteLine("Encrypt-then-MAC support (RFC 7366): {0}", doesEtM ? "yes" : "no"); w.WriteLine("SSLv2 ClientHello format (for SSLv3+): {0}", helloV2 ? "yes" : "no"); if (minDHSize > 0) { w.WriteLine("Minimum DH size: {0}", minDHSize); w.WriteLine("DH parameter reuse: {0}", kxReuseDH ? "yes" : " no"); } if (minECSize > 0) { w.WriteLine("Minimum EC size (no extension): {0}", minECSize); } if (minECSizeExt > 0) { w.WriteLine("Minimum EC size (with extension): {0}", minECSizeExt); if (minECSize == 0) { w.WriteLine("Server does not use EC without" + " the client extension"); } } if (minECSize > 0 || minECSizeExt > 0) { w.WriteLine("ECDH parameter reuse: {0}", kxReuseECDH ? "yes" : " no"); } if (namedCurves != null && namedCurves.Length > 0) { w.WriteLine("Supported curves (size and name)" + " ('*' = selected by server):"); foreach (SSLCurve nc in namedCurves) { w.WriteLine(" {0} {1,3} {2}", IsSpontaneous(nc) ? "*" : " ", nc.Size, nc.Name); } if (curveExplicitPrime > 0) { w.WriteLine(" explicit prime, size = {0}", curveExplicitPrime); } if (curveExplicitChar2 > 0) { w.WriteLine(" explicit char2, size = {0}", curveExplicitChar2); } } w.WriteLine(Environment.NewLine); if (warnings == null) { Analyse(); } if (warnings.Count != 0) { foreach (string k in warnings.Keys) { w.WriteLine("WARN[{0}]: {1}", k, warnings[k]); reportData.Issues.Add(warnings[k]); } } return(reportData); }