Android Open Source - android Ok Hostname Verifier






From Project

Back to project page android.

License

The source code is released under:

GNU General Public License

If you think the Android project android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *//w  ww .j a v a  2  s. co m
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.squareup.okhttp.internal.tls;

import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.security.auth.x500.X500Principal;

/**
 * A HostnameVerifier consistent with <a
 * href="http://www.ietf.org/rfc/rfc2818.txt">RFC 2818</a>.
 */
public final class OkHostnameVerifier implements HostnameVerifier {
  public static final OkHostnameVerifier INSTANCE = new OkHostnameVerifier();

  /**
   * Quick and dirty pattern to differentiate IP addresses from hostnames. This
   * is an approximation of Android's private InetAddress#isNumeric API.
   *
   * <p>This matches IPv6 addresses as a hex string containing at least one
   * colon, and possibly including dots after the first colon. It matches IPv4
   * addresses as strings containing only decimal digits and dots. This pattern
   * matches strings like "a:.23" and "54" that are neither IP addresses nor
   * hostnames; they will be verified as IP addresses (which is a more strict
   * verification).
   */
  private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile(
      "([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");

  private static final int ALT_DNS_NAME = 2;
  private static final int ALT_IPA_NAME = 7;

  private OkHostnameVerifier() {
  }

  public boolean verify(String host, SSLSession session) {
    try {
      Certificate[] certificates = session.getPeerCertificates();
      return verify(host, (X509Certificate) certificates[0]);
    } catch (SSLException e) {
      return false;
    }
  }

  public boolean verify(String host, X509Certificate certificate) {
    return verifyAsIpAddress(host)
        ? verifyIpAddress(host, certificate)
        : verifyHostName(host, certificate);
  }

  static boolean verifyAsIpAddress(String host) {
    return VERIFY_AS_IP_ADDRESS.matcher(host).matches();
  }

  /**
   * Returns true if {@code certificate} matches {@code ipAddress}.
   */
  private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {
    for (String altName : getSubjectAltNames(certificate, ALT_IPA_NAME)) {
      if (ipAddress.equalsIgnoreCase(altName)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if {@code certificate} matches {@code hostName}.
   */
  private boolean verifyHostName(String hostName, X509Certificate certificate) {
    hostName = hostName.toLowerCase(Locale.US);
    boolean hasDns = false;
    for (String altName : getSubjectAltNames(certificate, ALT_DNS_NAME)) {
      hasDns = true;
      if (verifyHostName(hostName, altName)) {
        return true;
      }
    }

    if (!hasDns) {
      X500Principal principal = certificate.getSubjectX500Principal();
      // RFC 2818 advises using the most specific name for matching.
      String cn = new DistinguishedNameParser(principal).findMostSpecific("cn");
      if (cn != null) {
        return verifyHostName(hostName, cn);
      }
    }

    return false;
  }

  private List<String> getSubjectAltNames(X509Certificate certificate, int type) {
    List<String> result = new ArrayList<String>();
    try {
      Collection<?> subjectAltNames = certificate.getSubjectAlternativeNames();
      if (subjectAltNames == null) {
        return Collections.emptyList();
      }
      for (Object subjectAltName : subjectAltNames) {
        List<?> entry = (List<?>) subjectAltName;
        if (entry == null || entry.size() < 2) {
          continue;
        }
        Integer altNameType = (Integer) entry.get(0);
        if (altNameType == null) {
          continue;
        }
        if (altNameType == type) {
          String altName = (String) entry.get(1);
          if (altName != null) {
            result.add(altName);
          }
        }
      }
      return result;
    } catch (CertificateParsingException e) {
      return Collections.emptyList();
    }
  }

  /**
   * Returns true if {@code hostName} matches the name or pattern {@code cn}.
   *
   * @param hostName lowercase host name.
   * @param cn certificate host name. May include wildcards like
   *     {@code *.android.com}.
   */
  public boolean verifyHostName(String hostName, String cn) {
    // Check length == 0 instead of .isEmpty() to support Java 5.
    if (hostName == null || hostName.length() == 0 || cn == null || cn.length() == 0) {
      return false;
    }

    cn = cn.toLowerCase(Locale.US);

    if (!cn.contains("*")) {
      return hostName.equals(cn);
    }

    if (cn.startsWith("*.") && hostName.regionMatches(0, cn, 2, cn.length() - 2)) {
      return true; // "*.foo.com" matches "foo.com"
    }

    int asterisk = cn.indexOf('*');
    int dot = cn.indexOf('.');
    if (asterisk > dot) {
      return false; // malformed; wildcard must be in the first part of the cn
    }

    if (!hostName.regionMatches(0, cn, 0, asterisk)) {
      return false; // prefix before '*' doesn't match
    }

    int suffixLength = cn.length() - (asterisk + 1);
    int suffixStart = hostName.length() - suffixLength;
    if (hostName.indexOf('.', asterisk) < suffixStart) {
      // TODO: remove workaround for *.clients.google.com http://b/5426333
      if (!hostName.endsWith(".clients.google.com")) {
        return false; // wildcard '*' can't match a '.'
      }
    }

    if (!hostName.regionMatches(suffixStart, cn, asterisk + 1, suffixLength)) {
      return false; // suffix after '*' doesn't match
    }

    return true;
  }
}




Java Source Code List

com.phonegap.helloworld.BuildConfig.java
com.phonegap.helloworld.HelloWorld.java
com.squareup.okhttp.Address.java
com.squareup.okhttp.ConnectionPool.java
com.squareup.okhttp.Connection.java
com.squareup.okhttp.Dispatcher.java
com.squareup.okhttp.Failure.java
com.squareup.okhttp.HttpResponseCache.java
com.squareup.okhttp.Job.java
com.squareup.okhttp.MediaType.java
com.squareup.okhttp.OkAuthenticator.java
com.squareup.okhttp.OkHttpClient.java
com.squareup.okhttp.OkResponseCache.java
com.squareup.okhttp.Request.java
com.squareup.okhttp.ResponseSource.java
com.squareup.okhttp.Response.java
com.squareup.okhttp.RouteDatabase.java
com.squareup.okhttp.Route.java
com.squareup.okhttp.TunnelRequest.java
com.squareup.okhttp.internal.AbstractOutputStream.java
com.squareup.okhttp.internal.Base64.java
com.squareup.okhttp.internal.DiskLruCache.java
com.squareup.okhttp.internal.Dns.java
com.squareup.okhttp.internal.FaultRecoveringOutputStream.java
com.squareup.okhttp.internal.NamedRunnable.java
com.squareup.okhttp.internal.Platform.java
com.squareup.okhttp.internal.StrictLineReader.java
com.squareup.okhttp.internal.Util.java
com.squareup.okhttp.internal.http.AbstractHttpInputStream.java
com.squareup.okhttp.internal.http.HeaderParser.java
com.squareup.okhttp.internal.http.HttpAuthenticator.java
com.squareup.okhttp.internal.http.HttpDate.java
com.squareup.okhttp.internal.http.HttpEngine.java
com.squareup.okhttp.internal.http.HttpTransport.java
com.squareup.okhttp.internal.http.HttpURLConnectionImpl.java
com.squareup.okhttp.internal.http.HttpsEngine.java
com.squareup.okhttp.internal.http.HttpsURLConnectionImpl.java
com.squareup.okhttp.internal.http.OkResponseCacheAdapter.java
com.squareup.okhttp.internal.http.Policy.java
com.squareup.okhttp.internal.http.RawHeaders.java
com.squareup.okhttp.internal.http.RequestHeaders.java
com.squareup.okhttp.internal.http.ResponseHeaders.java
com.squareup.okhttp.internal.http.RetryableOutputStream.java
com.squareup.okhttp.internal.http.RouteSelector.java
com.squareup.okhttp.internal.http.SpdyTransport.java
com.squareup.okhttp.internal.http.Transport.java
com.squareup.okhttp.internal.http.UnknownLengthHttpInputStream.java
com.squareup.okhttp.internal.spdy.ErrorCode.java
com.squareup.okhttp.internal.spdy.FrameReader.java
com.squareup.okhttp.internal.spdy.FrameWriter.java
com.squareup.okhttp.internal.spdy.HeadersMode.java
com.squareup.okhttp.internal.spdy.Hpack.java
com.squareup.okhttp.internal.spdy.Http20Draft06.java
com.squareup.okhttp.internal.spdy.IncomingStreamHandler.java
com.squareup.okhttp.internal.spdy.NameValueBlockReader.java
com.squareup.okhttp.internal.spdy.Ping.java
com.squareup.okhttp.internal.spdy.Settings.java
com.squareup.okhttp.internal.spdy.Spdy3.java
com.squareup.okhttp.internal.spdy.SpdyConnection.java
com.squareup.okhttp.internal.spdy.SpdyStream.java
com.squareup.okhttp.internal.spdy.Variant.java
com.squareup.okhttp.internal.tls.DistinguishedNameParser.java
com.squareup.okhttp.internal.tls.OkHostnameVerifier.java
org.apache.cordova.App.java
org.apache.cordova.AuthenticationToken.java
org.apache.cordova.BuildConfig.java
org.apache.cordova.CallbackContext.java
org.apache.cordova.Config.java
org.apache.cordova.CordovaActivity.java
org.apache.cordova.CordovaArgs.java
org.apache.cordova.CordovaChromeClient.java
org.apache.cordova.CordovaInterface.java
org.apache.cordova.CordovaPlugin.java
org.apache.cordova.CordovaResourceApi.java
org.apache.cordova.CordovaUriHelper.java
org.apache.cordova.CordovaWebViewClient.java
org.apache.cordova.CordovaWebView.java
org.apache.cordova.DirectoryManager.java
org.apache.cordova.DroidGap.java
org.apache.cordova.ExifHelper.java
org.apache.cordova.ExposedJsApi.java
org.apache.cordova.FileHelper.java
org.apache.cordova.IceCreamCordovaWebViewClient.java
org.apache.cordova.JSONUtils.java
org.apache.cordova.LOG.java
org.apache.cordova.LinearLayoutSoftKeyboardDetect.java
org.apache.cordova.NativeToJsMessageQueue.java
org.apache.cordova.PluginEntry.java
org.apache.cordova.PluginManager.java
org.apache.cordova.PluginResult.java
org.apache.cordova.ScrollEvent.java
org.apache.cordova.Whitelist.java