java.lang.Object
net.i2p.util.I2PSSLSocketFactory

public class I2PSSLSocketFactoryextends Object
Loads trusted ASCII certs from ~/.i2p/certificates/ and $I2P/certificates/.
  • Field Details

    • PROP_DISABLE

      private static final String PROP_DISABLE
      Config key for disabling hostname verification.
      See Also:
    • PROP_GEOIP_DIR

      private static final String PROP_GEOIP_DIR
      Config key of the GeoIP directory.
      See Also:
    • GEOIP_DIR_DEFAULT

      private static final String GEOIP_DIR_DEFAULT
      Default GeoIP directory name.
      See Also:
    • COUNTRY_FILE_DEFAULT

      private static final String COUNTRY_FILE_DEFAULT
      Default country list file name.
      See Also:
    • PUBLIC_SUFFIX_LIST

      private static final String PUBLIC_SUFFIX_LIST
      File holding the public suffix list.
      See Also:
    • DEFAULT_MATCHER

      private static volatile PublicSuffixMatcher DEFAULT_MATCHER
      The cached public suffix matcher.
    • _matcherLoaded

      private static volatile boolean _matcherLoaded
      True once the matcher was loaded.
    • DEFAULT_TLDS

      private static final String[] DEFAULT_TLDS
      The public top level domains allowed by default, not the private ones, from the country list.
    • ADDITIONAL_TLDS

      private static final String[] ADDITIONAL_TLDS
      Extra top level domains that are allowed, missing from the country list and the public suffix list.
    • EXCLUDE_PROTOCOLS

      public static final List<String> EXCLUDE_PROTOCOLS
      Unmodifiable. Public for RouterConsoleRunner.
    • INCLUDE_PROTOCOLS

      public static final List<String> INCLUDE_PROTOCOLS
      Java 7 does not enable 1.1 or 1.2 by default on the client side. Java 8 does enable 1.1 and 1.2 by default on the client side. 1.3 in Java 11, but it requires: ChaCha20/Poly1305 in Java 12 (we could add a provider) X25519 in Java 13 but may be pulled in to 12 (can't use our unsigned provider) Ed25519 in Java 13 (but we can use our provider) ref: https://openjdk.java.net/jeps/332

      ref: http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html Unmodifiable. Public for RouterConsoleRunner.

    • EXCLUDE_CIPHERS

      public static final List<String> EXCLUDE_CIPHERS
      We exclude everything that Java 8 disables by default, plus some others. ref: http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html See also: https://developer.android.com/reference/javax/net/ssl/SSLSocket.html Unmodifiable. Public for RouterConsoleRunner.
    • INCLUDE_CIPHERS

      public static final List<String> INCLUDE_CIPHERS
      Nothing for now. There's nothing disabled by default we would want to enable. Unmodifiable. Public for RouterConsoleRunner.
    • _factory

      private final SSLSocketFactory _factory
      The "real" factory.
    • _context

      private final I2PAppContext _context
      The app context.
  • Constructor Details

    • I2PSSLSocketFactory

      public I2PSSLSocketFactory(I2PAppContext context, boolean loadSystemCerts, String relativeCertPath) throws GeneralSecurityException
      Create a socket factory with the given context and certificate path.
      Parameters:
      context - the app context whose config and base dirs hold the certificates
      loadSystemCerts - true to trust the JVM key store in addition to the loaded certs
      relativeCertPath - e.g. "certificates/i2cp"; as of 0.9.41, may be absolute
      Throws:
      GeneralSecurityException - if the key store cannot be loaded or the context cannot be initialized
  • Method Details

    • createSocket

      public Socket createSocket(String host, int port) throws IOException
      Returns a socket to the host.

      A host argument that's an IP address (instead of a host name) is not recommended, as this will probably fail SSL certificate validation.

      Hostname validation is skipped for localhost addresses, but you still must trust the certificate.

      Parameters:
      host - the hostname to validate the certificate against, not an IP literal
      port - the TCP port to connect to
      Returns:
      an SSL socket with the protocol, ciphers and hostname already checked
      Throws:
      IOException - if the connection cannot be established
    • createSocket

      public Socket createSocket(InetAddress host, int port) throws IOException
      Returns a socket to the host.

      An InetAddress argument created with an IP address (instead of a host name) is not recommended, as this will perform a reverse DNS lookup to get the host name for certificate validation, which will probably then fail.

      Hostname validation is skipped for localhost addresses, but you still must trust the certificate.

      Parameters:
      host - the address to connect to, reverse resolved for certificate validation
      port - the TCP port to connect to
      Returns:
      an SSL socket with the protocol, ciphers and hostname already checked
      Throws:
      IOException - if the connection cannot be established
    • verifyHostname

      public static void verifyHostname(I2PAppContext ctx, SSLSocket socket, String host) throws SSLException
      Validate the hostname. Warning - be sure to remove [] from IPv6 addresses in host parameter if you got it from URI.getHost().

      ref: https://developer.android.com/training/articles/security-ssl.html ref: http://op-co.de/blog/posts/java_sslsocket_mitm/ ref: http://kevinlocke.name/bits/2012/10/03/ssl-certificate-verification-in-dispatch-and-asynchttpclient/

      Parameters:
      ctx - the app context supplying the config that can disable verification
      socket - the connected socket whose certificate is checked
      host - the hostname to validate against, without [] around an IPv6 literal
      Throws:
      SSLException - on hostname verification failure
    • getDefaultMatcher

      private static PublicSuffixMatcher getDefaultMatcher(I2PAppContext ctx)
      From Apache PublicSuffixMatcherLoader.getDefault()

      https://publicsuffix.org/list/effective_tld_names.dat What does this get us? Deciding whether to issue or accept an SSL wildcard certificate for *.public.suffix.

      Parameters:
      ctx - the app context supplying the geoip directory property
      Returns:
      null on failure
    • merge

      private static PublicSuffixList merge(PublicSuffixList a, PublicSuffixList b)
      Merge two PublicSuffixLists Have to do this because they are unmodifiable.
      Parameters:
      a - the first list, its rules and exceptions come first
      b - the second list, appended after the first
      Returns:
      a new list holding the rules and exceptions of both
    • addCountries

      private static void addCountries(I2PAppContext ctx, List<String> tlds)
      Read in the country file and add all TLDs to the list. It would almost be easier just to add all possible 26*26 two-letter codes. Adapted from the GeoIP country-file loader.
      Parameters:
      ctx - the app context supplying the geoip directory property
      tlds - list that collects each lowercased TLD read from the country file
    • initSSLContext

      private static SSLSocketFactory initSSLContext(I2PAppContext context, boolean loadSystemCerts, String relativeCertPath) throws GeneralSecurityException
      Loads certs from the ~/.i2p/certificates/ and $I2P/certificates/ directories, or from the absolute path given.
      Parameters:
      context - the app context, source of the log, the config and base directories, and the randomness for the SSL context
      loadSystemCerts - true to start from the JVM's default trust store, which also lets the result stand when no I2P certificates are found
      relativeCertPath - e.g. "certificates/i2cp"; as of 0.9.41, may be absolute
      Returns:
      a socket factory trusting the certificates that were loaded
      Throws:
      GeneralSecurityException - if the key store cannot be created, or no trusted certificates were found at all
    • setProtocolsAndCiphers

      public static void setProtocolsAndCiphers(SSLSocket socket)
      Select protocols and cipher suites to be used based on configured inclusion and exclusion lists as well as enabled and supported protocols and cipher suites.

      Adapted from Jetty SslContextFactory.java.

      Parameters:
      socket - the socket whose enabled protocols and cipher suites are narrowed
    • setProtocolsAndCiphers

      public static void setProtocolsAndCiphers(SSLServerSocket socket)
      Select protocols and cipher suites to be used based on configured inclusion and exclusion lists as well as enabled and supported protocols and cipher suites.

      Adapted from Jetty SslContextFactory.java.

      Parameters:
      socket - the server socket whose enabled protocols and cipher suites are narrowed
    • selectProtocols

      private static String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
      Select protocols to be used based on configured inclusion and exclusion lists as well as enabled and supported protocols.

      Adapted from Jetty SslContextFactory.java.

      Parameters:
      enabledProtocols - Array of enabled protocols
      supportedProtocols - Array of supported protocols
      Returns:
      Array of protocols to enable
    • selectCipherSuites

      private static String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
      Select cipher suites to be used based on configured inclusion and exclusion lists as well as enabled and supported cipher suite lists.

      Adapted from Jetty SslContextFactory.java.

      Parameters:
      enabledCipherSuites - Array of enabled cipher suites
      supportedCipherSuites - Array of supported cipher suites
      Returns:
      Array of cipher suites to enable
    • select

      private static String[] select(String[] enabledArr, String[] supportedArr, List<String> toEnable, List<String> toExclude)
      Adapted from Jetty SslContextFactory.java.
      Parameters:
      enabledArr - the cipher suites the socket has enabled to start from
      supportedArr - the cipher suites the socket supports, the only ones that can be added
      toEnable - Add all these to what is enabled, if supported
      toExclude - Remove all these from what is enabled
      Returns:
      the cipher suites to enable, in no particular order, or enabledArr unchanged when the selection comes out empty