コード例 #1
0
  /**
   * Verifies the identity of the server.
   *
   * <p>The server certificate is verified first.
   *
   * <p>Then, the host name is compared with the content of the server certificate using the current
   * host name verifier, if any.
   *
   * @param socket
   */
  private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
    try {
      CertificateCombinedException failInHandshake = null;
      /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an
      // instance of AdvancedX509TrustManager)
      try {
        SSLSocket sock =
            (SSLSocket) socket; // a new SSLSession instance is created as a "side effect"
        sock.startHandshake();

      } catch (RuntimeException e) {

        if (e instanceof CertificateCombinedException) {
          failInHandshake = (CertificateCombinedException) e;
        } else {
          Throwable cause = e.getCause();
          Throwable previousCause = null;
          while (cause != null
              && cause != previousCause
              && !(cause instanceof CertificateCombinedException)) {
            previousCause = cause;
            cause = cause.getCause();
          }
          if (cause != null && cause instanceof CertificateCombinedException) {
            failInHandshake = (CertificateCombinedException) cause;
          }
        }
        if (failInHandshake == null) {
          throw e;
        }
        failInHandshake.setHostInUrl(host);
      }

      /// 2. VERIFY HOSTNAME
      SSLSession newSession = null;
      boolean verifiedHostname = true;
      if (mHostnameVerifier != null) {
        if (failInHandshake != null) {
          /// 2.1 : a new SSLSession instance was NOT created in the handshake
          X509Certificate serverCert = failInHandshake.getServerCertificate();
          try {
            mHostnameVerifier.verify(host, serverCert);
          } catch (SSLException e) {
            verifiedHostname = false;
          }

        } else {
          /// 2.2 : a new SSLSession instance was created in the handshake
          newSession = ((SSLSocket) socket).getSession();
          if (!mTrustManager.isKnownServer(
              (X509Certificate) (newSession.getPeerCertificates()[0]))) {
            verifiedHostname = mHostnameVerifier.verify(host, newSession);
          }
        }
      }

      /// 3. Combine the exceptions to throw, if any
      if (!verifiedHostname) {
        SSLPeerUnverifiedException pue =
            new SSLPeerUnverifiedException(
                "Names in the server certificate do not match to " + host + " in the URL");
        if (failInHandshake == null) {
          failInHandshake =
              new CertificateCombinedException(
                  (X509Certificate) newSession.getPeerCertificates()[0]);
          failInHandshake.setHostInUrl(host);
        }
        failInHandshake.setSslPeerUnverifiedException(pue);
        pue.initCause(failInHandshake);
        throw pue;

      } else if (failInHandshake != null) {
        SSLHandshakeException hse =
            new SSLHandshakeException("Server certificate could not be verified");
        hse.initCause(failInHandshake);
        throw hse;
      }

    } catch (IOException io) {
      try {
        socket.close();
      } catch (Exception x) {
        // NOTHING - irrelevant exception for the caller
      }
      throw io;
    }
  }