/*
 *  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
 *
 *     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;

/**
 * A HostnameVerifier consistent with <a
 * href="http://www.ietf.org/rfc/rfc2818.txt">RFC 2818</a>.
 */
public final class OkHostnameVerifier implements HostnameVerifier {
  // Android-changed: Add a mode which disallows top-level domain wildcards. b/144694112
  // public static final OkHostnameVerifier INSTANCE = new OkHostnameVerifier();
  public static final OkHostnameVerifier INSTANCE = new OkHostnameVerifier(false);

  /**
   * 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;

  // BEGIN Android-changed: Add a mode which disallows top-level domain wildcards. b/144694112
  // private OkHostnameVerifier() {
  // }
  private final boolean strictWildcardMode;

  private OkHostnameVerifier(boolean strictWildcardMode) {
    this.strictWildcardMode = strictWildcardMode;
  }

  public static OkHostnameVerifier strictInstance() {
    return new OkHostnameVerifier(true);
  }
  // END Android-changed: Add a mode which disallows top-level domain wildcards. b/144694112

  @Override
  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) {
    List<String> altNames = getSubjectAltNames(certificate, ALT_IPA_NAME);
    for (int i = 0, size = altNames.size(); i < size; i++) {
      if (ipAddress.equalsIgnoreCase(altNames.get(i))) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if {@code certificate} matches {@code hostName}.
   */
  private boolean verifyHostName(String hostName, X509Certificate certificate) {
    // BEGIN Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
    if (!isPrintableAscii(hostName)) {
      return false;
    }
    // END Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
    hostName = hostName.toLowerCase(Locale.US);
    boolean hasDns = false;
    List<String> altNames = getSubjectAltNames(certificate, ALT_DNS_NAME);
    for (int i = 0, size = altNames.size(); i < size; i++) {
      hasDns = true;
      if (verifyHostName(hostName, altNames.get(i))) {
        return true;
      }
    }

    // BEGIN Android-removed: Ignore common name in hostname verification. http://b/70278814
    /*
    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);
      }
    }
    */
    // END Android-removed: Ignore common name in hostname verification. http://b/70278814

    return false;
  }

  public static List<String> allSubjectAltNames(X509Certificate certificate) {
    List<String> altIpaNames = getSubjectAltNames(certificate, ALT_IPA_NAME);
    List<String> altDnsNames = getSubjectAltNames(certificate, ALT_DNS_NAME);
    List<String> result = new ArrayList<>(altIpaNames.size() + altDnsNames.size());
    result.addAll(altIpaNames);
    result.addAll(altDnsNames);
    return result;
  }

  private static List<String> getSubjectAltNames(X509Certificate certificate, int type) {
    List<String> result = new ArrayList<>();
    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 {@code true} iff {@code hostName} matches the domain name {@code pattern}.
   *
   * @param hostName lower-case host name.
   * @param pattern domain name pattern from certificate. May be a wildcard pattern such as
   *        {@code *.android.com}.
   */
  private boolean verifyHostName(String hostName, String pattern) {
    // Basic sanity checks
    // Check length == 0 instead of .isEmpty() to support Java 5.
    if ((hostName == null) || (hostName.length() == 0) || (hostName.startsWith("."))
        || (hostName.endsWith(".."))) {
      // Invalid domain name
      return false;
    }
    if ((pattern == null) || (pattern.length() == 0) || (pattern.startsWith("."))
        || (pattern.endsWith(".."))) {
      // Invalid pattern/domain name
      return false;
    }

    // Normalize hostName and pattern by turning them into absolute domain names if they are not
    // yet absolute. This is needed because server certificates do not normally contain absolute
    // names or patterns, but they should be treated as absolute. At the same time, any hostName
    // presented to this method should also be treated as absolute for the purposes of matching
    // to the server certificate.
    //   www.android.com  matches www.android.com
    //   www.android.com  matches www.android.com.
    //   www.android.com. matches www.android.com.
    //   www.android.com. matches www.android.com
    if (!hostName.endsWith(".")) {
      hostName += '.';
    }
    if (!pattern.endsWith(".")) {
      pattern += '.';
    }
    // hostName and pattern are now absolute domain names.

    // BEGIN Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
    if (!isPrintableAscii(pattern)) {
      return false;
    }
    // END Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
    pattern = pattern.toLowerCase(Locale.US);
    // hostName and pattern are now in lower case -- domain names are case-insensitive.

    if (!pattern.contains("*")) {
      // Not a wildcard pattern -- hostName and pattern must match exactly.
      return hostName.equals(pattern);
    }
    // Wildcard pattern

    // WILDCARD PATTERN RULES:
    // 1. Asterisk (*) is only permitted in the left-most domain name label and must be the
    //    only character in that label (i.e., must match the whole left-most label).
    //    For example, *.example.com is permitted, while *a.example.com, a*.example.com,
    //    a*b.example.com, a.*.example.com are not permitted.
    // 2. Asterisk (*) cannot match across domain name labels.
    //    For example, *.example.com matches test.example.com but does not match
    //    sub.test.example.com.
    // 3. Wildcard patterns for single-label domain names are not permitted.
    // 4. Android-added: if strictWildcardMode is true then wildcards matching top-level domains,
    //    e.g. *.com, are not permitted.

    if ((!pattern.startsWith("*.")) || (pattern.indexOf('*', 1) != -1)) {
      // Asterisk (*) is only permitted in the left-most domain name label and must be the only
      // character in that label
      return false;
    }

    // Optimization: check whether hostName is too short to match the pattern. hostName must be at
    // least as long as the pattern because asterisk must match the whole left-most label and
    // hostName starts with a non-empty label. Thus, asterisk has to match one or more characters.
    if (hostName.length() < pattern.length()) {
      // hostName too short to match the pattern.
      return false;
    }

    if ("*.".equals(pattern)) {
      // Wildcard pattern for single-label domain name -- not permitted.
      return false;
    }

    // BEGIN Android-added: Disallow top-level wildcards in strict mode. http://b/144694112
    if (strictWildcardMode) {
      // By this point we know the pattern has been normalised and starts with a wildcard,
      // i.e. "*.domainpart."
      String domainPart = pattern.substring(2, pattern.length() - 1);
      // If the domain part contains no dots then this pattern will match top level domains.
      if (domainPart.indexOf('.') < 0) {
        return false;
      }
    }
    // END Android-added: Disallow top-level wildcards in strict mode. http://b/144694112

    // hostName must end with the region of pattern following the asterisk.
    String suffix = pattern.substring(1);
    if (!hostName.endsWith(suffix)) {
      // hostName does not end with the suffix
      return false;
    }

    // Check that asterisk did not match across domain name labels.
    int suffixStartIndexInHostName = hostName.length() - suffix.length();
    if ((suffixStartIndexInHostName > 0)
        && (hostName.lastIndexOf('.', suffixStartIndexInHostName - 1) != -1)) {
      // Asterisk is matching across domain name labels -- not permitted.
      return false;
    }

    // hostName matches pattern
    return true;
  }

  // BEGIN Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
  /**
   * Returns true if the  input string contains only printable 7-bit ASCII
   * characters, otherwise false.
   */
  private static final char DEL = 127;
  static boolean isPrintableAscii(String input) {
    if (input == null) {
      return false;
    }
    for (char c : input.toCharArray()) {
      // Space is illegal in a DNS name. DEL and anything less than space is non-printing so
      // also illegal. Anything greater than DEL is not 7-bit.
      if (c <= ' ' || c >= DEL) {
        return false;
      }
    }
    return true;
  }
  // END Android-added: Reject non-ASCII hostnames and SANs. http://b/171980069
}
