// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/proxy_resolution/proxy_bypass_rules.h"

#include "base/strings/pattern.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/parse_number.h"
#include "net/base/url_util.h"

namespace net {

namespace {

// The <-loopback> rule corresponds with "remove the implicitly added bypass
// rules".
//
// The name <-loopback> is not a very precise name (as the implicit rules cover
// more than strictly loopback addresses), however this is the name that is
// used on Windows so re-used here.
//
// For platform-differences between implicit rules see
// ProxyResolverRules::MatchesImplicitRules().
const char kSubtractImplicitBypasses[] = "<-loopback>";

// The <local> rule bypasses any hostname that has no dots (and is not
// an IP literal). The name is misleading as it has nothing to do with
// localhost/loopback addresses, and would have better been called
// something like "simple hostnames". However this is the name used on
// Windows so is matched here.
const char kBypassSimpleHostnames[] = "<local>";

bool IsLinkLocalIP(const GURL& url) {
  // Quick fail if definitely not link-local, to avoid doing unnecessary work in
  // common case. The |url| should be canonicalized, which for IPv6 literals
  // means lowercase.
  if (!(url.host_piece().starts_with("169.254.") ||
        url.host_piece().starts_with("[fe"))) {
    return false;
  }

  IPAddress ip_address;
  if (!ip_address.AssignFromIPLiteral(url.HostNoBracketsPiece()))
    return false;

  return ip_address.IsLinkLocal();
}

class HostnamePatternRule : public ProxyBypassRules::Rule {
 public:
  HostnamePatternRule(const std::string& optional_scheme,
                      const std::string& hostname_pattern,
                      int optional_port)
      : optional_scheme_(base::ToLowerASCII(optional_scheme)),
        hostname_pattern_(base::ToLowerASCII(hostname_pattern)),
        optional_port_(optional_port) {}

  Result Evaluate(const GURL& url) const override {
    if (optional_port_ != -1 && url.EffectiveIntPort() != optional_port_)
      return Result::kNoMatch;  // Didn't match port expectation.

    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
      return Result::kNoMatch;  // Didn't match scheme expectation.

    // Note it is necessary to lower-case the host, since GURL uses capital
    // letters for percent-escaped characters.
    return base::MatchPattern(url.host(), hostname_pattern_) ? Result::kBypass
                                                             : Result::kNoMatch;
  }

  std::string ToString() const override {
    std::string str;
    if (!optional_scheme_.empty())
      base::StringAppendF(&str, "%s://", optional_scheme_.c_str());
    str += hostname_pattern_;
    if (optional_port_ != -1)
      base::StringAppendF(&str, ":%d", optional_port_);
    return str;
  }

 private:
  const std::string optional_scheme_;
  const std::string hostname_pattern_;
  const int optional_port_;

  DISALLOW_COPY_AND_ASSIGN(HostnamePatternRule);
};

class BypassSimpleHostnamesRule : public ProxyBypassRules::Rule {
 public:
  BypassSimpleHostnamesRule() = default;

  Result Evaluate(const GURL& url) const override {
    return ((url.host_piece().find('.') == std::string::npos) &&
            !url.HostIsIPAddress())
               ? Result::kBypass
               : Result::kNoMatch;
  }

  std::string ToString() const override { return kBypassSimpleHostnames; }

 private:
  DISALLOW_COPY_AND_ASSIGN(BypassSimpleHostnamesRule);
};

class SubtractImplicitBypassesRule : public ProxyBypassRules::Rule {
 public:
  SubtractImplicitBypassesRule() = default;

  Result Evaluate(const GURL& url) const override {
    return ProxyBypassRules::MatchesImplicitRules(url) ? Result::kDontBypass
                                                       : Result::kNoMatch;
  }

  std::string ToString() const override { return kSubtractImplicitBypasses; }

 private:
  DISALLOW_COPY_AND_ASSIGN(SubtractImplicitBypassesRule);
};

// Rule for matching a URL that is an IP address, if that IP address falls
// within a certain numeric range. For example, you could use this rule to
// match all the IPs in the CIDR block 10.10.3.4/24.
class IPBlockRule : public ProxyBypassRules::Rule {
 public:
  // |ip_prefix| + |prefix_length| define the IP block to match.
  IPBlockRule(const std::string& description,
              const std::string& optional_scheme,
              const IPAddress& ip_prefix,
              size_t prefix_length_in_bits)
      : description_(description),
        optional_scheme_(optional_scheme),
        ip_prefix_(ip_prefix),
        prefix_length_in_bits_(prefix_length_in_bits) {}

  Result Evaluate(const GURL& url) const override {
    if (!url.HostIsIPAddress())
      return Result::kNoMatch;

    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
      return Result::kNoMatch;  // Didn't match scheme expectation.

    // Parse the input IP literal to a number.
    IPAddress ip_address;
    if (!ip_address.AssignFromIPLiteral(url.HostNoBracketsPiece()))
      return Result::kNoMatch;

    // Test if it has the expected prefix.
    return IPAddressMatchesPrefix(ip_address, ip_prefix_,
                                  prefix_length_in_bits_)
               ? Result::kBypass
               : Result::kNoMatch;
  }

  std::string ToString() const override { return description_; }

 private:
  const std::string description_;
  const std::string optional_scheme_;
  const IPAddress ip_prefix_;
  const size_t prefix_length_in_bits_;

  DISALLOW_COPY_AND_ASSIGN(IPBlockRule);
};

// Returns true if the given string represents an IP address.
// IPv6 addresses are expected to be bracketed.
bool IsIPAddress(const std::string& domain) {
  // From GURL::HostIsIPAddress()
  url::RawCanonOutputT<char, 128> ignored_output;
  url::CanonHostInfo host_info;
  url::Component domain_comp(0, domain.size());
  url::CanonicalizeIPAddress(domain.c_str(), domain_comp, &ignored_output,
                             &host_info);
  return host_info.IsIPAddress();
}

std::unique_ptr<ProxyBypassRules::Rule> ParseRule(
    const std::string& raw_untrimmed,
    ProxyBypassRules::ParseFormat format) {
  std::string raw;
  base::TrimWhitespaceASCII(raw_untrimmed, base::TRIM_ALL, &raw);

  // <local> and <-loopback> are special syntax used by WinInet's bypass list
  // -- we allow it on all platforms and interpret it the same way.
  if (base::LowerCaseEqualsASCII(raw, kBypassSimpleHostnames))
    return std::make_unique<BypassSimpleHostnamesRule>();
  if (base::LowerCaseEqualsASCII(raw, kSubtractImplicitBypasses))
    return std::make_unique<SubtractImplicitBypassesRule>();

  // Extract any scheme-restriction.
  std::string::size_type scheme_pos = raw.find("://");
  std::string scheme;
  if (scheme_pos != std::string::npos) {
    scheme = raw.substr(0, scheme_pos);
    raw = raw.substr(scheme_pos + 3);
    if (scheme.empty())
      return nullptr;
  }

  if (raw.empty())
    return nullptr;

  // If there is a forward slash in the input, it is probably a CIDR style
  // mask.
  if (raw.find('/') != std::string::npos) {
    IPAddress ip_prefix;
    size_t prefix_length_in_bits;

    if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
      return nullptr;

    return std::make_unique<IPBlockRule>(raw, scheme, ip_prefix,
                                         prefix_length_in_bits);
  }

  // Check if we have an <ip-address>[:port] input. We need to treat this
  // separately since the IP literal may not be in a canonical form.
  std::string host;
  int port;
  if (ParseHostAndPort(raw, &host, &port)) {
    // TODO(eroman): HostForURL() below DCHECKs() when |host| contains an
    // embedded NULL.
    if (host.find('\0') != std::string::npos)
      return nullptr;

    // Note that HostPortPair is used to merely to convert any IPv6 literals to
    // a URL-safe format that can be used by canonicalization below.
    std::string bracketed_host = HostPortPair(host, 80).HostForURL();
    if (IsIPAddress(bracketed_host)) {
      // Canonicalize the IP literal before adding it as a string pattern.
      GURL tmp_url("http://" + bracketed_host);
      return std::make_unique<HostnamePatternRule>(scheme, tmp_url.host(),
                                                   port);
    }
  }

  // Otherwise assume we have <hostname-pattern>[:port].
  std::string::size_type pos_colon = raw.rfind(':');
  port = -1;
  if (pos_colon != std::string::npos) {
    if (!ParseInt32(base::StringPiece(raw.begin() + pos_colon + 1, raw.end()),
                    ParseIntFormat::NON_NEGATIVE, &port) ||
        port > 0xFFFF) {
      return nullptr;  // Port was invalid.
    }
    raw = raw.substr(0, pos_colon);
  }

  // Special-case hostnames that begin with a period.
  // For example, we remap ".google.com" --> "*.google.com".
  if (base::StartsWith(raw, ".", base::CompareCase::SENSITIVE))
    raw = "*" + raw;

  // If suffix matching was asked for, make sure the pattern starts with a
  // wildcard.
  if (format == ProxyBypassRules::ParseFormat::kHostnameSuffixMatching &&
      !base::StartsWith(raw, "*", base::CompareCase::SENSITIVE))
    raw = "*" + raw;

  return std::make_unique<HostnamePatternRule>(scheme, raw, port);
}

}  // namespace

ProxyBypassRules::Rule::Rule() = default;

ProxyBypassRules::Rule::~Rule() = default;

bool ProxyBypassRules::Rule::Equals(const Rule& rule) const {
  return ToString() == rule.ToString();
}

ProxyBypassRules::ProxyBypassRules() = default;

ProxyBypassRules::ProxyBypassRules(const ProxyBypassRules& rhs) {
  *this = rhs;
}

ProxyBypassRules::ProxyBypassRules(ProxyBypassRules&& rhs) {
  *this = std::move(rhs);
}

ProxyBypassRules::~ProxyBypassRules() = default;

ProxyBypassRules& ProxyBypassRules::operator=(const ProxyBypassRules& rhs) {
  ParseFromString(rhs.ToString());
  return *this;
}

ProxyBypassRules& ProxyBypassRules::operator=(ProxyBypassRules&& rhs) {
  rules_ = std::move(rhs.rules_);
  return *this;
}

bool ProxyBypassRules::Matches(const GURL& url, bool reverse) const {
  // Later rules override earlier rules, so evaluating the rule list can be
  // done by iterating over it in reverse and short-circuiting when a match is
  // found. If no matches are found then the implicit rules are consulted.
  //
  // The order of evaluation generally doesn't matter, since the common
  // case is to have a set of (positive) bypass rules.
  //
  // However when mixing positive and negative bypass rules evaluation
  // order makes a difference. The chosen evaluation order here matches
  // WinInet (which supports <-loopback> as a negative rule).
  //
  // Consider these two rule lists:
  //  (a) "localhost; <-loopback>"
  //  (b) "<-loopback>; localhost"
  //
  // The expectation is that Matches("http://localhost/") returns false
  // for (a) since the final rule <-loopback> unbypasses it. Whereas it is
  // expected to return true for (b), since the final rule "localhost"
  // bypasses it again.
  for (auto it = rules_.rbegin(); it != rules_.rend(); ++it) {
    const std::unique_ptr<Rule>& rule = *it;

    switch (rule->Evaluate(url)) {
      case Rule::Result::kBypass:
        return !reverse;
      case Rule::Result::kDontBypass:
        return reverse;
      case Rule::Result::kNoMatch:
        continue;
    }
  }

  // If none of the explicit rules matched, fall back to the implicit rules.
  bool matches_implicit = MatchesImplicitRules(url);
  if (matches_implicit)
    return matches_implicit;

  return reverse;
}

bool ProxyBypassRules::operator==(const ProxyBypassRules& other) const {
  if (rules_.size() != other.rules_.size())
    return false;

  for (size_t i = 0; i < rules_.size(); ++i) {
    if (!rules_[i]->Equals(*other.rules_[i]))
      return false;
  }
  return true;
}

void ProxyBypassRules::ParseFromString(const std::string& raw,
                                       ParseFormat format) {
  Clear();

  base::StringTokenizer entries(raw, ",;");
  while (entries.GetNext()) {
    AddRuleFromString(entries.token(), format);
  }
}

bool ProxyBypassRules::AddRuleForHostname(const std::string& optional_scheme,
                                          const std::string& hostname_pattern,
                                          int optional_port) {
  if (hostname_pattern.empty())
    return false;

  rules_.push_back(std::make_unique<HostnamePatternRule>(
      optional_scheme, hostname_pattern, optional_port));
  return true;
}

void ProxyBypassRules::PrependRuleToBypassSimpleHostnames() {
  rules_.insert(rules_.begin(), std::make_unique<BypassSimpleHostnamesRule>());
}

bool ProxyBypassRules::AddRuleFromString(const std::string& raw_untrimmed,
                                         ParseFormat format) {
  auto rule = ParseRule(raw_untrimmed, format);

  if (rule) {
    rules_.push_back(std::move(rule));
    return true;
  }

  return false;
}

void ProxyBypassRules::AddRulesToSubtractImplicit() {
  rules_.push_back(std::make_unique<SubtractImplicitBypassesRule>());
}

std::string ProxyBypassRules::GetRulesToSubtractImplicit() {
  ProxyBypassRules rules;
  rules.AddRulesToSubtractImplicit();
  return rules.ToString();
}

std::string ProxyBypassRules::ToString() const {
  std::string result;
  for (auto rule(rules_.begin()); rule != rules_.end(); ++rule) {
    result += (*rule)->ToString();
    result += ";";
  }
  return result;
}

void ProxyBypassRules::Clear() {
  rules_.clear();
}

bool ProxyBypassRules::MatchesImplicitRules(const GURL& url) {
  // On Windows the implict rules are:
  //
  //     localhost
  //     loopback
  //     127.0.0.1
  //     [::1]
  //     169.254/16
  //     [FE80::]/10
  //
  // And on macOS they are:
  //
  //     localhost
  //     127.0.0.1/8
  //     [::1]
  //     169.254/16
  //
  // Our implicit rules are approximately:
  //
  //     localhost
  //     localhost.
  //     *.localhost
  //     localhost6
  //     localhost6.localdomain6
  //     loopback  [Windows only]
  //     loopback. [Windows only]
  //     [::1]
  //     127.0.0.1/8
  //     169.254/16
  //     [FE80::]/10
  return net::IsLocalhost(url) ||
         IsLinkLocalIP(url)
#if defined(OS_WIN)
         // See http://crbug.com/904889
         || (url.host_piece() == "loopback") ||
         (url.host_piece() == "loopback.")
#endif
      ;
}

}  // namespace net
