@Override
 public boolean verify(String hostname, SSLSession session) {
   if (defaultVerifier != null) {
     return defaultVerifier.verify(hostname, session);
   }
   return false;
 }
 protected boolean verify(String hostname, SSLSession session, boolean interactive) {
   LOGGER.log(
       Level.FINE, "hostname verifier for " + hostname + ", trying default verifier first");
   // if the default verifier accepts the hostname, we are done
   if (defaultVerifier.verify(hostname, session)) {
     LOGGER.log(Level.FINE, "default verifier accepted " + hostname);
     return true;
   }
   // otherwise, we check if the hostname is an alias for this cert in our keystore
   try {
     X509Certificate cert = (X509Certificate) session.getPeerCertificates()[0];
     // Log.d(TAG, "cert: " + cert);
     if (cert.equals(appKeyStore.getCertificate(hostname.toLowerCase(Locale.US)))) {
       LOGGER.log(Level.FINE, "certificate for " + hostname + " is in our keystore. accepting.");
       return true;
     } else {
       LOGGER.log(
           Level.FINE, "server " + hostname + " provided wrong certificate, asking user.");
       if (interactive) {
         return interactHostname(cert, hostname);
       } else {
         return false;
       }
     }
   } catch (Exception e) {
     e.printStackTrace();
     return false;
   }
 }
 /**
  * Return an {@code SSLSocket} that is not only connected but has also passed hostname
  * verification.
  *
  * @param hostnameVerifier Used to verify the hostname we connected to is an acceptable match for
  *     the peer certificate chain of the SSLSession.
  */
 public SSLSocket verifySecureSocketHostname(HostnameVerifier hostnameVerifier)
     throws IOException {
   if (!hostnameVerifier.verify(address.uriHost, unverifiedSocket.getSession())) {
     throw new IOException("Hostname '" + address.uriHost + "' was not verified");
   }
   sslSocket = unverifiedSocket;
   return sslSocket;
 }
  // Server identity checking is done according to RFC 2818: HTTP over TLS
  // Section 3.1 Server Identity
  private void checkURLSpoofing(HostnameVerifier hostnameVerifier) throws IOException {
    //
    // Get authenticated server name, if any
    //
    boolean done = false;
    String host = url.getHost();

    // if IPv6 strip off the "[]"
    if (host != null && host.startsWith("[") && host.endsWith("]")) {
      host = host.substring(1, host.length() - 1);
    }

    Certificate[] peerCerts = null;
    try {
      // get the subject's certificate
      peerCerts = session.getPeerCertificates();

      X509Certificate peerCert;
      if (peerCerts[0] instanceof java.security.cert.X509Certificate) {
        peerCert = (java.security.cert.X509Certificate) peerCerts[0];
      } else {
        throw new SSLPeerUnverifiedException("");
      }

      HostnameChecker checker = HostnameChecker.getInstance(HostnameChecker.TYPE_TLS);

      checker.match(host, peerCert);

      // if it doesn't throw an exception, we passed. Return.
      return;

    } catch (SSLPeerUnverifiedException e) {

      //
      // client explicitly changed default policy and enabled
      // anonymous ciphers; we can't check the standard policy
      //
      // ignore
    } catch (java.security.cert.CertificateException cpe) {
      // ignore
    }

    // Assume the peerCerts are already cloned.
    String cipher = session.getCipherSuite();
    if ((cipher != null) && (cipher.indexOf("_anon_") != -1)) {
      return;
    } else if ((hostnameVerifier != null) && (hostnameVerifier.verify(host, session))) {
      return;
    }

    serverSocket.close();
    session.invalidate();

    throw new IOException("HTTPS hostname wrong:  should be <" + url.getHost() + ">");
  }
  @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;
  }
  /**
   * Lightweight version of SSLCertificateSocketFactory.verifyHostname, which provides this service
   * but is not in the public API.
   *
   * <p>Verify the hostname of the certificate used by the other end of a connected socket. You MUST
   * call this if you did not supply a hostname to SSLCertificateSocketFactory.createSocket(). It is
   * harmless to call this method redundantly if the hostname has already been verified.
   *
   * <p>Wildcard certificates are allowed to verify any matching hostname, so "foo.bar.example.com"
   * is verified if the peer has a certificate for "*.example.com".
   *
   * @param socket An SSL socket which has been connected to a server
   * @param hostname The expected hostname of the remote server
   * @throws IOException if something goes wrong handshaking with the server
   * @throws SSLPeerUnverifiedException if the server cannot prove its identity
   */
  private static void verifyHostname(Socket socket, String hostname) throws IOException {
    // The code at the start of OpenSSLSocketImpl.startHandshake()
    // ensures that the call is idempotent, so we can safely call it.
    SSLSocket ssl = (SSLSocket) socket;
    ssl.startHandshake();

    SSLSession session = ssl.getSession();
    if (session == null) {
      throw new SSLException("Cannot verify SSL socket without session");
    }
    // TODO: Instead of reporting the name of the server we think we're connecting to,
    // we should be reporting the bad name in the certificate.  Unfortunately this is buried
    // in the verifier code and is not available in the verifier API, and extracting the
    // CN & alts is beyond the scope of this patch.
    if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
      throw new SSLPeerUnverifiedException(
          "Certificate hostname not useable for server: " + hostname);
    }
  }
  /**
   * Verify the hostname of the certificate used by the other end of a connected socket. You MUST
   * call this if you did not supply a hostname to {@link #createSocket()}. It is harmless to call
   * this method redundantly if the hostname has already been verified.
   *
   * <p>Wildcard certificates are allowed to verify any matching hostname, so "foo.bar.example.com"
   * is verified if the peer has a certificate for "*.example.com".
   *
   * @param socket An SSL socket which has been connected to a server
   * @param hostname The expected hostname of the remote server
   * @throws IOException if something goes wrong handshaking with the server
   * @throws SSLPeerUnverifiedException if the server cannot prove its identity
   * @hide
   */
  public static void verifyHostname(Socket socket, String hostname) throws IOException {
    if (!(socket instanceof SSLSocket)) {
      throw new IllegalArgumentException("Attempt to verify non-SSL socket");
    }

    if (!isSslCheckRelaxed()) {
      // The code at the start of OpenSSLSocketImpl.startHandshake()
      // ensures that the call is idempotent, so we can safely call it.
      SSLSocket ssl = (SSLSocket) socket;
      ssl.startHandshake();

      SSLSession session = ssl.getSession();
      if (session == null) {
        throw new SSLException("Cannot verify SSL socket without session");
      }
      if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
        throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
      }
    }
  }
  /**
   * Establishes and verifies a TLS connection to a (TCP-)connected SSLSocket: - set TLS parameters
   * like allowed protocols and ciphers - set SNI host name - verify host name - verify certificate
   *
   * @param socket unconnected SSLSocket
   * @param host host name for SNI
   * @throws java.io.IOException if the connection could not be established.
   */
  private void establishAndVerify(SSLSocket socket, String host) throws IOException {
    setTlsParameters(socket);
    setSniHostname(socket, host);

    // TLS handshake, throws an exception for untrusted certificates
    socket.startHandshake();

    // verify hostname and certificate
    SSLSession session = socket.getSession();
    if (!hostnameVerifier.verify(host, session)) {
      // throw exception for invalid host names
      throw new SSLPeerUnverifiedException(host);
    }

    Log.i(
        TAG,
        "Established "
            + session.getProtocol()
            + " connection with "
            + session.getPeerHost()
            + " using "
            + session.getCipherSuite());
  }
 @Override
 public boolean verify(String s, SSLSession sslSession) {
   return verifier.verify(s, sslSession);
 }
 @Override
 public void verify(String host, SSLSocket ssl) throws IOException {
   if (!verifier.verify(host, ssl.getSession()))
     throw new SSLException("Hostname verification failure");
 }
Beispiel #11
0
 @Override
 public boolean verify(String hostname, SSLSession session) {
   return hostnameVerifier.verify(hostname, session);
 }