/* * Encode the report as JSON. */ internal void Print(JSON js) { js.OpenInit(false); js.AddPair("connectionName", connName); js.AddPair("connectionPort", connPort); js.AddPair("SNI", sni); if (ssl2Suites != null && ssl2Suites.Length > 0) { js.OpenPairObject("SSLv2"); js.OpenPairArray("suites"); foreach (int s in ssl2Suites) { js.OpenElementObject(); js.AddPair("id", s); js.AddPair("name", CipherSuite.ToNameV2(s)); js.Close(); } js.Close(); js.Close(); } foreach (int v in suites.Keys) { js.OpenPairObject(M.VersionString(v)); SupportedCipherSuites scs = suites[v]; string sel; if (scs.PrefClient) { sel = "client"; } else if (scs.PrefServer) { sel = "server"; } else { sel = "complex"; } js.AddPair("suiteSelection", sel); js.OpenPairArray("suites"); foreach (int s in scs.Suites) { js.OpenElementObject(); js.AddPair("id", s); js.AddPair("name", CipherSuite.ToName(s)); CipherSuite cs; if (CipherSuite.ALL.TryGetValue(s, out cs)) { js.AddPair("strength", cs.Strength); js.AddPair("forwardSecrecy", cs.HasForwardSecrecy); js.AddPair("anonymous", cs.IsAnonymous); js.AddPair("serverKeyType", cs.ServerKeyType); } js.Close(); } js.Close(); js.Close(); } if (ssl2Chain != null) { js.OpenPairObject("ssl2Cert"); PrintCert(js, ssl2Chain, 0); js.Close(); } js.OpenPairArray("ssl3Chains"); foreach (X509Chain xchain in chains.Values) { js.OpenElementObject(); int n = xchain.Elements.Length; js.AddPair("length", n); js.AddPair("decoded", xchain.Decodable); if (xchain.Decodable) { js.AddPair("namesMatch", xchain.NamesMatch); js.AddPair("includesRoot", xchain.IncludesRoot); js.OpenPairArray("signHashes"); foreach (string name in xchain.SignHashes) { js.AddElement(name); } js.Close(); } js.OpenPairArray("certificates"); for (int i = 0; i < n; i++) { js.OpenElementObject(); PrintCert(js, xchain, i); js.Close(); } js.Close(); js.Close(); } js.Close(); js.AddPair("deflateCompress", DeflateCompress); if (serverTimeOffset == Int64.MinValue) { js.AddPair("serverTime", "none"); } else if (serverTimeOffset == Int64.MaxValue) { js.AddPair("serverTime", "random"); } else { DateTime dt = DateTime.UtcNow; dt = dt.AddMilliseconds((double)serverTimeOffset); js.AddPair("serverTime", string.Format( "{0:yyyy-MM-dd HH:mm:ss} UTC", dt)); js.AddPair("serverTimeOffsetMillis", serverTimeOffset); } js.AddPair("secureRenegotiation", doesRenego); js.AddPair("rfc7366EtM", doesEtM); js.AddPair("ssl2HelloFormat", helloV2); if (minDHSize > 0) { js.AddPair("minDHSize", minDHSize); js.AddPair("kxReuseDH", kxReuseDH); } if (minECSize > 0) { js.AddPair("minECSize", minECSize); } if (minECSizeExt > 0) { js.AddPair("minECSizeExt", minECSizeExt); } if (minECSize > 0 || minECSizeExt > 0) { js.AddPair("kxReuseECDH", kxReuseECDH); } if ((namedCurves != null && namedCurves.Length > 0) || curveExplicitPrime > 0 || curveExplicitChar2 > 0) { js.OpenPairArray("namedCurves"); foreach (SSLCurve nc in namedCurves) { js.OpenElementObject(); js.AddPair("name", nc.Name); js.AddPair("size", nc.Size); js.AddPair("spontaneous", IsSpontaneous(nc)); js.Close(); } if (curveExplicitPrime > 0) { js.OpenElementObject(); js.AddPair("name", "explicitPrime"); js.AddPair("size", curveExplicitPrime); js.Close(); } if (curveExplicitChar2 > 0) { js.OpenElementObject(); js.AddPair("name", "explicitChar2"); js.AddPair("size", curveExplicitChar2); js.Close(); } js.Close(); } if (warnings == null) { Analyse(); } js.OpenPairArray("warnings"); foreach (string k in warnings.Keys) { js.OpenElementObject(); js.AddPair("id", k); js.AddPair("text", warnings[k]); js.Close(); } js.Close(); js.Close(); }
public static void UpdateReportAggregator(ReportAggregator aggregator, Report report) { String serverUnderTest = $"{report.ConnName}:{report.ConnPort}"; if (report.SSLv2Chain != null) { aggregator.AddSsl2Cert(serverUnderTest, report.SSLv2Chain); X509Cert xc = report.SSLv2Chain.ElementsRev[0]; if (xc != null && xc.ValidTo.CompareTo(DateTime.Now) < 0) { aggregator.AddOverduedCertificate(serverUnderTest, xc.ValidTo); } } if (report.ssl2Suites != null && report.ssl2Suites.Length > 0) { aggregator.AddSuportedSslVersion(M.VersionString(M.SSLv20)); foreach (int s in report.ssl2Suites) { aggregator.AddSupportedCipherSuite(CipherSuite.ToNameV2(s)); } } aggregator.AddSsl3Certs(serverUnderTest, report.chains.Values); InspectCerts(aggregator, report, serverUnderTest); foreach (int v in report.suites.Keys) { aggregator.AddSuportedSslVersion(M.VersionString(v)); SupportedCipherSuites scs = report.suites[v]; if (scs.PrefClient) { aggregator.AddCipherSuiteSelectionMode("uses client preferences"); } else if (scs.PrefServer) { aggregator.AddCipherSuiteSelectionMode("enforce server preferences"); } else { aggregator.AddCipherSuiteSelectionMode("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; } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } aggregator.AddSupportedCipherSuite($"{strength}{fsf}{anon} (key: {kt,4}) {CipherSuite.ToName(s)}"); } } foreach (var warning in report.Warnings) { aggregator.AddWarning(warning.Value); } }
/* * Print the report on the provided writer (text version for * humans). */ internal void Print(TextWriter w) { w.WriteLine("Connection: {0}:{1}", connName, connPort); 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]; if (scs.Equals(last)) { w.WriteLine(" idem"); continue; } 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; } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } w.WriteLine(" {0}{1}{2} (key: {3,4}) {4}", strength, fsf, anon, kt, CipherSuite.ToName(s)); } } w.WriteLine("========================================="); if (ssl2Chain != null) { w.WriteLine("+++++ SSLv2 certificate"); PrintCert(w, ssl2Chain, 0); } 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"); } for (int i = 0; i < n; i++) { w.WriteLine("+ certificate order: {0}", i); PrintCert(w, xchain, i); } } w.WriteLine("========================================="); 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("========================================="); if (warnings == null) { Analyse(); } if (warnings.Count == 0) { w.WriteLine("No warning."); } else { foreach (string k in warnings.Keys) { w.WriteLine("WARN[{0}]: {1}", k, warnings[k]); } } }
/* * Print the report on the provided writer (text version for * humans). */ internal void Print(TextWriter w) { w.WriteLine("Connection: {0}:{1}", connName, connPort); 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]; if (scs.Equals(last)) { w.WriteLine(" idem"); continue; } 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; } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } w.WriteLine(" {0}{1}{2} (key: {3,4}) {4}", strength, fsf, anon, kt, CipherSuite.ToName(s)); } } w.WriteLine("========================================="); if (ssl2Chain != null) { w.WriteLine("+++++ SSLv2 certificate"); PrintCert(w, ssl2Chain, 0, withPEM); } w.WriteLine("+++++ SSLv3/TLS: {0} certificate chain(s)", chains.Count); foreach (X509Chain xchain in chains.Values) { PrintChain(w, xchain, withPEM); } w.WriteLine("========================================="); 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"); if (minDHSize > 0) { w.WriteLine("Minimum DH size: {0}", minDHSize); } 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 (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("========================================="); if (warnings == null) { Analyse(); } if (warnings.Count == 0) { w.WriteLine("No warning."); } else { foreach (string k in warnings.Keys) { w.WriteLine("WARN[{0}]: {1}", k, warnings[k]); } } }