Пример #1
0
  private CipherTest(PeerFactory peerFactory) throws IOException {
    THREADS = Integer.parseInt(System.getProperty("numThreads", "4"));
    factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    SSLSocket socket = (SSLSocket) factory.createSocket();
    String[] cipherSuites = socket.getSupportedCipherSuites();
    String[] protocols = socket.getSupportedProtocols();
    //      String[] clientAuths = {null, "RSA", "DSA"};
    String[] clientAuths = {null};
    tests =
        new ArrayList<TestParameters>(cipherSuites.length * protocols.length * clientAuths.length);
    for (int i = 0; i < cipherSuites.length; i++) {
      String cipherSuite = cipherSuites[i];

      for (int j = 0; j < protocols.length; j++) {
        String protocol = protocols[j];

        if (!peerFactory.isSupported(cipherSuite, protocol)) {
          continue;
        }

        for (int k = 0; k < clientAuths.length; k++) {
          String clientAuth = clientAuths[k];
          if ((clientAuth != null) && (cipherSuite.indexOf("DH_anon") != -1)) {
            // no client with anonymous ciphersuites
            continue;
          }
          tests.add(new TestParameters(cipherSuite, protocol, clientAuth));
        }
      }
    }
    testIterator = tests.iterator();
  }
  @Override
  public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
      throws IOException, UnknownHostException {

    SSLCertificateSocketFactory sslSocketFactory =
        (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
    SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(InetAddress.getByName(host), port);

    // enable TLSv1.1/1.2 if available
    // (see https://github.com/rfc2822/davdroid/issues/229)
    ssl.setEnabledProtocols(ssl.getSupportedProtocols());

    // set up SNI before the handshake
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      Log.i("SNISocketFactory", "Setting SNI hostname");
      sslSocketFactory.setHostname(ssl, host);
    } else {
      Log.d(
          "SNISocketFactory", "No documented SNI support on Android <4.2, trying with reflection");
      try {
        java.lang.reflect.Method setHostnameMethod =
            ssl.getClass().getMethod("setHostname", String.class);
        setHostnameMethod.invoke(ssl, host);
      } catch (Exception e) {
        Log.w("SNISocketFactory", "SNI not useable", e);
      }
    }
    return ssl;
  }
Пример #3
0
  /**
   * Updates the provided socket to apply the appropriate set of enabled SSL protocols. This will
   * only have any effect for sockets that are instances of {@code javax.net.ssl.SSLSocket}, but it
   * is safe to call for any kind of {@code java.net.Socket}. This should be called before
   * attempting any communication over the socket, as
   *
   * @param socket The socket on which to apply the configured set of enabled SSL protocols.
   * @param protocols The set of protocols that should be enabled for the socket, if available.
   * @throws IOException If {@link #getEnabledSSLProtocols} returns a non-empty set but none of the
   *     values in that set are supported by the socket.
   */
  static void applyEnabledSSLProtocols(final Socket socket, final Set<String> protocols)
      throws IOException {
    if ((socket == null) || (!(socket instanceof SSLSocket)) || protocols.isEmpty()) {
      return;
    }

    final Set<String> lowerProtocols = new HashSet<String>(protocols.size());
    for (final String s : protocols) {
      lowerProtocols.add(StaticUtils.toLowerCase(s));
    }

    final SSLSocket sslSocket = (SSLSocket) socket;
    final String[] supportedProtocols = sslSocket.getSupportedProtocols();

    final ArrayList<String> enabledList = new ArrayList<String>(supportedProtocols.length);
    for (final String supportedProtocol : supportedProtocols) {
      if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol))) {
        enabledList.add(supportedProtocol);
      }
    }

    if (enabledList.isEmpty()) {
      final StringBuilder enabledBuffer = new StringBuilder();
      final Iterator<String> enabledIterator = protocols.iterator();
      while (enabledIterator.hasNext()) {
        enabledBuffer.append('\'');
        enabledBuffer.append(enabledIterator.next());
        enabledBuffer.append('\'');

        if (enabledIterator.hasNext()) {
          enabledBuffer.append(", ");
        }
      }

      final StringBuilder supportedBuffer = new StringBuilder();
      for (int i = 0; i < supportedProtocols.length; i++) {
        if (i > 0) {
          supportedBuffer.append(", ");
        }

        supportedBuffer.append('\'');
        supportedBuffer.append(supportedProtocols[i]);
        supportedBuffer.append('\'');
      }

      throw new IOException(
          ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get(
              enabledBuffer.toString(),
              supportedBuffer.toString(),
              PROPERTY_ENABLED_SSL_PROTOCOLS,
              SSLUtil.class.getName() + ".setEnabledSSLProtocols"));
    } else {
      final String[] enabledArray = new String[enabledList.size()];
      sslSocket.setEnabledProtocols(enabledList.toArray(enabledArray));
    }
  }
Пример #4
0
 /** Inits supported and enabled protocol versions. */
 private void initSupportedProtocols() {
   try {
     SSLSocket ssl_socket = (SSLSocket) ssl_factory.createSocket();
     if (supported_protocols == null) supported_protocols = ssl_socket.getSupportedProtocols();
     if (enabled_protocols == null) enabled_protocols = ssl_socket.getEnabledProtocols();
     ssl_socket.close();
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
  protected CamelContext createPropertiesPlaceholderAwareContext() throws Exception {
    Properties supplementalProperties = new Properties();

    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    SecureRandom sr = null;
    try {
      sr = SecureRandom.getInstance("SHA1PRNG");
    } catch (NoSuchAlgorithmException e) {
      // Ignore
    }

    SSLContext sslc = SSLContext.getInstance("TLS");
    sslc.init(null, null, null);
    SSLSocket socket = (SSLSocket) sslc.getSocketFactory().createSocket();

    supplementalProperties.setProperty("keyStoreParameters.type", KeyStore.getDefaultType());
    supplementalProperties.setProperty("keyStoreParameters.provider", ks.getProvider().getName());

    supplementalProperties.setProperty(
        "keyManagersParameters.algorithm", KeyManagerFactory.getDefaultAlgorithm());
    supplementalProperties.setProperty(
        "keyManagersParameters.provider", kmf.getProvider().getName());

    supplementalProperties.setProperty(
        "trustManagersParameters.algorithm", TrustManagerFactory.getDefaultAlgorithm());
    supplementalProperties.setProperty(
        "trustManagersParameters.provider", tmf.getProvider().getName());

    if (sr != null) {
      supplementalProperties.setProperty("secureRandomParameters.algorithm", "SHA1PRNG");
      supplementalProperties.setProperty(
          "secureRandomParameters.provider", sr.getProvider().getName());
    }

    supplementalProperties.setProperty(
        "sslContextParameters.provider", sslc.getProvider().getName());
    supplementalProperties.setProperty("cipherSuite.0", socket.getSupportedCipherSuites()[0]);

    // Have to skip this guy because he doesn't work with TLS as the SSLContext protocol
    String ssp = "";
    for (String protocol : socket.getSupportedProtocols()) {
      if (!"SSLv2Hello".equals(protocol)) {
        ssp = protocol;
        break;
      }
    }
    supplementalProperties.setProperty("secureSocketProtocol.0", ssp);

    return this.createPropertiesPlaceholderAwareContext(supplementalProperties);
  }
Пример #6
0
  @Override
  public Socket createSocket(Socket plainSocket, String host, int port, boolean autoClose)
      throws IOException {
    String peerHost = this.conn.getRequestProperty("Host");
    if (peerHost == null) peerHost = host;
    Log.i(TAG, "customized createSocket. host: " + peerHost);
    InetAddress address = plainSocket.getInetAddress();
    if (autoClose) {
      // we don't need the plainSocket
      plainSocket.close();
    }
    // create and connect SSL socket, but don't do hostname/certificate verification yet
    SSLCertificateSocketFactory sslSocketFactory =
        (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
    SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(address, port);

    // enable TLSv1.1/1.2 if available
    ssl.setEnabledProtocols(ssl.getSupportedProtocols());

    // set up SNI before the handshake
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      Log.i(TAG, "Setting SNI hostname");
      sslSocketFactory.setHostname(ssl, peerHost);
    } else {
      Log.d(TAG, "No documented SNI support on Android <4.2, trying with reflection");
      try {
        java.lang.reflect.Method setHostnameMethod =
            ssl.getClass().getMethod("setHostname", String.class);
        setHostnameMethod.invoke(ssl, peerHost);
      } catch (Exception e) {
        Log.w(TAG, "SNI not useable", e);
      }
    }

    // verify hostname and certificate
    SSLSession session = ssl.getSession();

    if (!hostnameVerifier.verify(peerHost, session))
      throw new SSLPeerUnverifiedException("Cannot verify hostname: " + peerHost);

    Log.i(
        TAG,
        "Established "
            + session.getProtocol()
            + " connection with "
            + session.getPeerHost()
            + " using "
            + session.getCipherSuite());

    return ssl;
  }
 /** {@inheritDoc} Used to enforce the preferred TLS protocol during SSL handshake. */
 @Override
 protected final void prepareSocket(final SSLSocket socket) {
   String[] supported = socket.getSupportedProtocols();
   String[] enabled = socket.getEnabledProtocols();
   if (LOG.isDebugEnabled()) {
     LOG.debug(
         "socket.getSupportedProtocols(): "
             + Arrays.toString(supported)
             + ", socket.getEnabledProtocols(): "
             + Arrays.toString(enabled));
   }
   List<String> target = new ArrayList<String>();
   if (supported != null) {
     // Append the preferred protocols in descending order of preference
     // but only do so if the protocols are supported
     TLSProtocol[] values = TLSProtocol.values();
     for (int i = 0; i < values.length; i++) {
       final String pname = values[i].getProtocolName();
       if (existsIn(pname, supported)) {
         target.add(pname);
       }
     }
   }
   if (enabled != null) {
     // Append the rest of the already enabled protocols to the end
     // if not already included in the list
     for (String pname : enabled) {
       if (!target.contains(pname)) {
         target.add(pname);
       }
     }
   }
   if (target.size() > 0) {
     String[] enabling = target.toArray(new String[target.size()]);
     socket.setEnabledProtocols(enabling);
     if (LOG.isDebugEnabled()) {
       LOG.debug("TLS protocol enabled for SSL handshake: " + Arrays.toString(enabling));
     }
   }
 }
  @SuppressLint("NewApi")
  private Socket enableSNI(SSLSocket ssl, String host) throws SSLPeerUnverifiedException {
    // enable TLSv1.1/1.2 if available
    // (see https://github.com/rfc2822/davdroid/issues/229)
    ssl.setEnabledProtocols(ssl.getSupportedProtocols());

    // set up SNI before the handshake
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      AppLog.i(T.API, "Setting SNI hostname");
      mFactory.setHostname(ssl, host);
    } else {
      AppLog.i(T.API, "No documented SNI support on Android <4.2, trying with reflection");
      try {
        java.lang.reflect.Method setHostnameMethod =
            ssl.getClass().getMethod("setHostname", String.class);
        setHostnameMethod.invoke(ssl, host);
      } catch (Exception e) {
        AppLog.e(T.API, "SNI not useable", e);
      }
    }

    // verify hostname and certificate
    SSLSession session = ssl.getSession();
    if (!mHostnameVerifier.verify(host, session)) {
      throw new SSLPeerUnverifiedException("Cannot verify hostname: " + host);
    }

    AppLog.i(
        T.API,
        "Established "
            + session.getProtocol()
            + " connection with "
            + session.getPeerHost()
            + " using "
            + session.getCipherSuite());

    return ssl;
  }
Пример #9
0
  /**
   * Prepares a TLS/SSL connection socket by: - setting reasonable TLS protocol versions - setting
   * reasonable cipher suites (if required)
   *
   * @param socket unconnected SSLSocket to prepare
   */
  private void setTlsParameters(SSLSocket socket) {
    // Android 5.0+ (API level21) provides reasonable default settings
    // but it still allows SSLv3
    // https://developer.android.com/about/versions/android-5.0-changes.html#ssl

    /* set reasonable protocol versions */
    // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
    // - remove all SSL versions (especially SSLv3) because they're insecure now
    final List<String> protocols = new LinkedList<String>();
    for (String protocol : socket.getSupportedProtocols()) {
      if (!protocol.toUpperCase().contains("SSL")) {
        protocols.add(protocol);
      }
    }
    Log.v(TAG, "Setting allowed TLS protocols: " + TextUtils.join(", ", protocols));
    socket.setEnabledProtocols(protocols.toArray(new String[protocols.size()]));

    /* set reasonable cipher suites */
    if (Build.VERSION.SDK_INT < VERSION_CODES_LOLLIPOP) {
      // choose secure cipher suites

      final List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());

      // preferred ciphers = allowed Ciphers \ availableCiphers
      final Set<String> preferredCiphers = new HashSet<String>(ALLOWED_CIPHERS);
      preferredCiphers.retainAll(availableCiphers);

      // add enabled ciphers to preferred ciphers
      // for maximum security, preferred ciphers should *replace* enabled ciphers,
      // but for the security level of ACRA, disabling of insecure
      // ciphers should be a server-side task
      preferredCiphers.addAll(Arrays.asList(socket.getEnabledCipherSuites()));

      Log.v(TAG, "Setting allowed TLS ciphers: " + TextUtils.join(", ", preferredCiphers));
      socket.setEnabledCipherSuites(preferredCiphers.toArray(new String[preferredCiphers.size()]));
    }
  }
 public String[] getSupportedProtocols() {
   return delegate.getSupportedProtocols();
 }