<commit_before>package de.thiemann.ssl.report;

/*
 * Command-line tool to test a SSL/TLS parameter on a server.
 * =====================================================================
 *
 * This application connects to the provided SSL/TLS server (by name and
 * port) and extracts the following information:
 * - supported versions (SSL 2.0, SSL 3.0, TLS 1.0 to 1.2)
 * - support of Deflate compression
 * - list of supported cipher suites (for each protocol version)
 *
 * ----------------------------------------------------------------------
 * Copyright (c) 2012  <NAME> <<EMAIL>>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * ----------------------------------------------------------------------
 */

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class SSLParameterReport {

	private static String NL = System.getProperty("line.separator");

	static void usage() {
		System.err.println("usage: SSLParameterReport servername [ port ]");
		System.exit(1);
	}

	public static void main(String[] args) throws IOException {
		if (args.length == 0 || args.length > 2) {
			usage();
		}
		String name = args[0];
		int port = 443;
		if (args.length == 2) {
			try {
				port = Integer.parseInt(args[1]);
			} catch (NumberFormatException nfe) {
				usage();
			}
			if (port <= 0 || port > 65535) {
				usage();
			}
		}
		InetSocketAddress isa = new InetSocketAddress(name, port);

		// check support for versions SSL3, TLS1.0, TLS1.1, TLS1.2
		Set<Integer> supportedVersions = new TreeSet<Integer>();
		boolean compress = false;
		for (int v = 0x0300; v <= 0x0303; v++) {
			ServerHello serverHello = connect(isa, v,
					CipherSuiteUtil.CIPHER_SUITES.keySet());
			if (serverHello == null) {
				continue;
			}
			supportedVersions.add(serverHello.protoVersion);
			compress = serverHello.compression;
		}

		// check support for version SSL2
		ServerHelloSSLv2 serverHelloV2 = connectV2(isa);

		if (serverHelloV2 != null) {
			supportedVersions.add(0x0200);
		}

		if (supportedVersions.size() == 0) {
			System.out.println("No SSL/TLS server at " + isa);
			System.exit(1);
		}

		StringBuffer sb = new StringBuffer();

		sb.append(NL)
				.append("Report from: ")
				.append(String.format("%1$tF %1$tT", System.currentTimeMillis()));

		sb.append(NL)
				.append("--------------------------------------------------------------------------------");

		sb.append(NL).append("Supported protocol versions:");
		for (int version : supportedVersions) {
			sb.append(" ").append(versionString(version));
		}

		sb.append(NL).append("Deflate compression: ")
				.append((compress ? "YES" : "no"));

		sb.append(NL)
				.append("--------------------------------------------------------------------------------");

		sb.append(NL).append("Supported cipher suites")
				.append(" (ORDER IS NOT SIGNIFICANT):");

		Map<Integer, Set<Integer>> supportedCipherSuite = new TreeMap<Integer, Set<Integer>>();
		Set<String> certID = new TreeSet<String>();

		if (serverHelloV2 != null) {
			sb.append(NL).append("  ").append(versionString(0x0200));
			Set<Integer> vc2 = new TreeSet<Integer>();
			for (int c : serverHelloV2.cipherSuites) {
				vc2.add(c);
			}
			for (int c : vc2) {
				sb.append(NL).append("     ")
						.append(CipherSuiteUtil.cipherSuiteStringV2(c));
			}

			supportedCipherSuite.put(0x0200, vc2);

			if (serverHelloV2.serverCertName != null) {
				certID.add(serverHelloV2.serverCertHash + ": "
						+ serverHelloV2.serverCertName);
			}
		}

		for (int version : supportedVersions) {

			if (version == 0x0200) {
				continue;
			}

			Set<Integer> versionSupportedCiphers = supportedSuites(isa, version);
			supportedCipherSuite.put(version, versionSupportedCiphers);

			addCertificates(certID, isa, version);
			
			sb.append(NL).append("  ").append(versionString(version));
			for (int c : versionSupportedCiphers) {
				sb.append(NL).append("     ")
						.append(CipherSuiteUtil.cipherSuiteString(c));
			}

		}

		sb.append(NL)
				.append("--------------------------------------------------------------------------------");
		if (certID.size() == 0) {
			sb.append(NL).append("No server certificate !");
		} else {
			sb.append(NL).append("Server certificate(s):");
			for (String cc : certID) {
				sb.append(NL).append("  ").append(cc);
			}
		}

		System.out.println(sb.toString());
	}

	static final int CHANGE_CIPHER_SPEC = 20;
	static final int HANDSHAKE = 22;
	static final int APPLICATION = 23;

	/*
	 * Get cipher suites supported by the server. This is done by repeatedly
	 * contacting the server, each time removing from our list of supported
	 * suites the suite which the server just selected. We keep on until the
	 * server can no longer respond to us with a ServerHello.
	 */
	static Set<Integer> supportedSuites(InetSocketAddress isa, int version) {
		Set<Integer> cs = new TreeSet<Integer>(
				CipherSuiteUtil.CIPHER_SUITES.keySet());
		Set<Integer> rs = new TreeSet<Integer>();
		for (;;) {
			ServerHello sh = connect(isa, version, cs);
			if (sh == null) {<commit_msg>update to report output<commit_after>package de.thiemann.ssl.report;

/*
 * Command-line tool to test a SSL/TLS parameter on a server.
 * =====================================================================
 *
 * This application connects to the provided SSL/TLS server (by name and
 * port) and extracts the following information:
 * - supported versions (SSL 2.0, SSL 3.0, TLS 1.0 to 1.2)
 * - support of Deflate compression
 * - list of supported cipher suites (for each protocol version)
 *
 * ----------------------------------------------------------------------
 * Copyright (c) 2012  <NAME> <<EMAIL>>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * ----------------------------------------------------------------------
 */

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class SSLParameterReport {

	private static String NL = System.getProperty("line.separator");

	static void usage() {
		System.err.println("usage: SSLParameterReport servername [ port ]");
		System.exit(1);
	}

	public static void main(String[] args) throws IOException {
		if (args.length == 0 || args.length > 2) {
			usage();
		}

		String webName = args[0];
		int port = 443;

		if (args.length == 2) {
			try {
				port = Integer.parseInt(args[1]);
			} catch (NumberFormatException nfe) {
				usage();
			}
			if (port <= 0 || port > 65535) {
				usage();
			}
		}

		SSLParameterReport reportObject = new SSLParameterReport(webName, port);
		System.out.println(reportObject.generateReport());
	}

	private String webName;
	private int port;

	public SSLParameterReport(String webName, int port) {
		super();
		this.webName = webName;
		this.port = port;
	}

	public String generateReport() {
		StringBuffer sb = new StringBuffer();

		InetSocketAddress isa = new InetSocketAddress(this.webName, this.port);

		// check support for versions SSL3, TLS1.0, TLS1.1, TLS1.2
		int sslVersions[] = { 0x0200, 0x0300, 0x0301, 0x0302, 0x0303 };

		Set<Integer> supportedVersions = new TreeSet<Integer>();
		boolean compress = false;
		for (int version : sslVersions) {

			if (version == 0x0200)
				continue;

			ServerHello serverHello = connect(isa, version,
					CipherSuiteUtil.CIPHER_SUITES.keySet());
			if (serverHello == null) {
				continue;
			}
			supportedVersions.add(serverHello.protoVersion);
			compress = serverHello.compression;
		}

		// check support for version SSL2
		ServerHelloSSLv2 serverHelloV2 = connectV2(isa);

		if (serverHelloV2 != null) {
			supportedVersions.add(0x0200);
		}

		if (supportedVersions.size() == 0) {
			sb.append(NL).append("No SSL/TLS server at " + isa);
			return sb.toString();
		}

		sb.append(NL)
				.append("**************************** SSL Parameter Report *****************************");
		sb.append(NL)
				.append(NL)
				.append("----------------------------- Common Information -------------------------------");

		// output common values
		sb.append(NL)
				.append("Report from: ")
				.append(String.format("%1$tF %1$tT", System.currentTimeMillis()));
		sb.append(NL).append("Web-Name: ").append(webName);
		sb.append(NL).append("IP-Address: ").append(isa);
		sb.append(NL).append("Port: ").append(port);

		sb.append(NL).append(NL)
				.append("--------------------------------- Protocol -------------------------------------");

		sb.append(NL).append("Supported protocol versions:");
		for (int version : supportedVersions) {
			sb.append(" ").append(versionString(version));
		}

		sb.append(NL).append("Deflate compression: ")
				.append((compress ? "YES" : "no"));

		sb.append(NL).append(NL)
				.append("-------------------------- Supported Cipher Suites -----------------------------");

		Map<Integer, Set<Integer>> supportedCipherSuite = new TreeMap<Integer, Set<Integer>>();
		Set<String> certID = new TreeSet<String>();

		if (serverHelloV2 != null) {
			sb.append(NL).append("  ").append(versionString(0x0200));
			Set<Integer> vc2 = new TreeSet<Integer>();
			for (int c : serverHelloV2.cipherSuites) {
				vc2.add(c);
			}
			for (int c : vc2) {
				sb.append(NL).append("     ")
						.append(CipherSuiteUtil.cipherSuiteStringV2(c));
			}

			supportedCipherSuite.put(0x0200, vc2);

			if (serverHelloV2.serverCertName != null) {
				certID.add(serverHelloV2.serverCertHash + ": "
						+ serverHelloV2.serverCertName);
			}
		}

		for (int version : supportedVersions) {

			if (version == 0x0200) {
				continue;
			}

			Set<Integer> versionSupportedCiphers = supportedSuites(isa, version);
			supportedCipherSuite.put(version, versionSupportedCiphers);

			addCertificates(certID, isa, version);

			sb.append(NL).append("  ").append(versionString(version));
			for (int c : versionSupportedCiphers) {
				sb.append(NL).append("      ")
						.append(CipherSuiteUtil.cipherSuiteString(c));
			}

		}

		sb.append(NL).append(NL)
				.append("---------------------------- Server certificates -------------------------------");
		if (certID.size() == 0) {
			sb.append(NL).append("No server certificate!");
		} else {
			for (String cc : certID) {
				sb.append(NL).append("  ").append(cc);
			}
		}

		return sb.toString();
	}

	static final int CHANGE_CIPHER_SPEC = 20;
	static final int HANDSHAKE = 22;
	static final int APPLICATION = 23;

	/*
	 * Get cipher suites supported by the server. This is done by repeatedly
	 * contacting the server, each time removing from our list of supported
	 * suites the suite which the server just selected. We keep on until the
	 * server can no longer respond to us with a ServerHello.
	 */
	static Set<Integer> supportedSuites(InetSocketAddress isa, int version) {
		Set<Integer> cs = new TreeSet<Integer>(
				CipherSuiteUtil.CIPHER_SUITES.keySet());
		Set<Integer> rs = new TreeSet<Integer>();
		for (;;) {
			ServerHello sh = connect(isa, version, cs);
			if (sh == null) {
{'fraction_non_alphanumeric': 0.18642039931204665, 'fraction_numerical': 0.01488072982875944, 'mean_word_length': 2.976806422836753, 'pattern_counts': {'":': 2, '<': 44, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4042403', 'n_tokens_mistral': 4503, 'n_tokens_neox': 3833, 'n_words': 1155}