// 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/http/http_auth_cache.h"

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"

namespace {

// Helper to find the containing directory of path. In RFC 2617 this is what
// they call the "last symbolic element in the absolute path".
// Examples:
//   "/foo/bar.txt" --> "/foo/"
//   "/foo/" --> "/foo/"
std::string GetParentDirectory(const std::string& path) {
  std::string::size_type last_slash = path.rfind("/");
  if (last_slash == std::string::npos) {
    // No slash (absolute paths always start with slash, so this must be
    // the proxy case which uses empty string).
    DCHECK(path.empty());
    return path;
  }
  return path.substr(0, last_slash + 1);
}

// Debug helper to check that |path| arguments are properly formed.
// (should be absolute path, or empty string).
void CheckPathIsValid(const std::string& path) {
  DCHECK(path.empty() || path[0] == '/');
}

// Return true if |path| is a subpath of |container|. In other words, is
// |container| an ancestor of |path|?
bool IsEnclosingPath(const std::string& container, const std::string& path) {
  DCHECK(container.empty() || *(container.end() - 1) == '/');
  return ((container.empty() && path.empty()) ||
          (!container.empty() &&
           base::StartsWith(path, container, base::CompareCase::SENSITIVE)));
}

// Debug helper to check that |origin| arguments are properly formed.
void CheckOriginIsValid(const GURL& origin) {
  DCHECK(origin.is_valid());
  // Note that the scheme may be FTP when we're using a HTTP proxy.
  DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp") ||
         origin.SchemeIsWSOrWSS());
  DCHECK(origin.GetOrigin() == origin);
}

// Functor used by EraseIf.
struct IsEnclosedBy {
  explicit IsEnclosedBy(const std::string& path) : path(path) { }
  bool operator() (const std::string& x) const {
    return IsEnclosingPath(path, x);
  }
  const std::string& path;
};

void RecordLookupPosition(int position) {
  UMA_HISTOGRAM_COUNTS_100("Net.HttpAuthCacheLookupPosition", position);
}

void RecordLookupByPathPosition(int position) {
  UMA_HISTOGRAM_COUNTS_100("Net.HttpAuthCacheLookupByPathPosition", position);
}

void RecordEntriesExaminedWhenNoMatch(int num_examined_entries) {
  UMA_HISTOGRAM_COUNTS_100("Net.HttpAuthCacheEntriesExaminedWhenNoMatch",
                           num_examined_entries);
}

}  // namespace

namespace net {

HttpAuthCache::HttpAuthCache() = default;

HttpAuthCache::~HttpAuthCache() = default;

// Performance: O(n), where n is the number of realm entries.
HttpAuthCache::Entry* HttpAuthCache::Lookup(const GURL& origin,
                                            const std::string& realm,
                                            HttpAuth::Scheme scheme) {
  CheckOriginIsValid(origin);

  int entries_examined = 0;
  // Linear scan through the realm entries.
  for (auto it = entries_.begin(); it != entries_.end(); ++it) {
    ++entries_examined;
    if (it->origin() == origin && it->realm() == realm &&
        it->scheme() == scheme) {
      it->last_use_time_ticks_ = tick_clock_->NowTicks();
      RecordLookupPosition(entries_examined);
      return &(*it);
    }
  }
  RecordLookupPosition(0);
  RecordEntriesExaminedWhenNoMatch(entries_examined);
  return NULL;  // No realm entry found.
}

// Performance: O(n*m), where n is the number of realm entries, m is the number
// of path entries per realm. Both n amd m are expected to be small; m is
// kept small because AddPath() only keeps the shallowest entry.
HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const GURL& origin,
                                                  const std::string& path) {
  HttpAuthCache::Entry* best_match = NULL;
  size_t best_match_length = 0;
  int best_match_position = 0;
  CheckOriginIsValid(origin);
  CheckPathIsValid(path);

  // RFC 2617 section 2:
  // A client SHOULD assume that all paths at or deeper than the depth of
  // the last symbolic element in the path field of the Request-URI also are
  // within the protection space ...
  std::string parent_dir = GetParentDirectory(path);

  int entries_examined = 0;
  // Linear scan through the realm entries.
  for (auto it = entries_.begin(); it != entries_.end(); ++it) {
    ++entries_examined;
    size_t len = 0;
    if (it->origin() == origin && it->HasEnclosingPath(parent_dir, &len) &&
        (!best_match || len > best_match_length)) {
      best_match = &(*it);
      best_match_length = len;
      best_match_position = entries_examined;
    }
  }
  if (best_match)
    best_match->last_use_time_ticks_ = tick_clock_->NowTicks();
  else
    RecordEntriesExaminedWhenNoMatch(entries_examined);
  RecordLookupByPathPosition(best_match_position);
  return best_match;
}

HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
                                         const std::string& realm,
                                         HttpAuth::Scheme scheme,
                                         const std::string& auth_challenge,
                                         const AuthCredentials& credentials,
                                         const std::string& path) {
  CheckOriginIsValid(origin);
  CheckPathIsValid(path);

  base::TimeTicks now_ticks = tick_clock_->NowTicks();

  // Check for existing entry (we will re-use it if present).
  HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
  if (!entry) {
    bool evicted = false;
    // Failsafe to prevent unbounded memory growth of the cache.
    if (entries_.size() >= kMaxNumRealmEntries) {
      LOG(WARNING) << "Num auth cache entries reached limit -- evicting";
      UMA_HISTOGRAM_LONG_TIMES(
          "Net.HttpAuthCacheAddEvictedCreation",
          now_ticks - entries_.back().creation_time_ticks_);
      UMA_HISTOGRAM_LONG_TIMES(
          "Net.HttpAuthCacheAddEvictedLastUse",
          now_ticks - entries_.back().last_use_time_ticks_);
      entries_.pop_back();
      evicted = true;
    }
    UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddEvicted", evicted);

    entries_.push_front(Entry());
    entry = &entries_.front();
    entry->origin_ = origin;
    entry->realm_ = realm;
    entry->scheme_ = scheme;
    entry->creation_time_ticks_ = now_ticks;
    entry->creation_time_ = clock_->Now();
  }
  DCHECK_EQ(origin, entry->origin_);
  DCHECK_EQ(realm, entry->realm_);
  DCHECK_EQ(scheme, entry->scheme_);

  entry->auth_challenge_ = auth_challenge;
  entry->credentials_ = credentials;
  entry->nonce_count_ = 1;
  entry->AddPath(path);
  entry->last_use_time_ticks_ = now_ticks;

  return entry;
}

HttpAuthCache::Entry::Entry(const Entry& other) = default;

HttpAuthCache::Entry::~Entry() = default;

void HttpAuthCache::Entry::UpdateStaleChallenge(
    const std::string& auth_challenge) {
  auth_challenge_ = auth_challenge;
  nonce_count_ = 1;
}

HttpAuthCache::Entry::Entry()
    : scheme_(HttpAuth::AUTH_SCHEME_MAX),
      nonce_count_(0) {
}

void HttpAuthCache::Entry::AddPath(const std::string& path) {
  std::string parent_dir = GetParentDirectory(path);
  if (!HasEnclosingPath(parent_dir, NULL)) {
    // Remove any entries that have been subsumed by the new entry.
    base::EraseIf(paths_, IsEnclosedBy(parent_dir));

    bool evicted = false;
    // Failsafe to prevent unbounded memory growth of the cache.
    if (paths_.size() >= kMaxNumPathsPerRealmEntry) {
      LOG(WARNING) << "Num path entries for " << origin()
                   << " has grown too large -- evicting";
      paths_.pop_back();
      evicted = true;
    }
    UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddPathEvicted", evicted);

    // Add new path.
    paths_.push_front(parent_dir);
  }
}

bool HttpAuthCache::Entry::HasEnclosingPath(const std::string& dir,
                                            size_t* path_len) {
  DCHECK(GetParentDirectory(dir) == dir);
  for (PathList::const_iterator it = paths_.begin(); it != paths_.end();
       ++it) {
    if (IsEnclosingPath(*it, dir)) {
      // No element of paths_ may enclose any other element.
      // Therefore this path is the tightest bound.  Important because
      // the length returned is used to determine the cache entry that
      // has the closest enclosing path in LookupByPath().
      if (path_len)
        *path_len = it->length();
      return true;
    }
  }
  return false;
}

bool HttpAuthCache::Remove(const GURL& origin,
                           const std::string& realm,
                           HttpAuth::Scheme scheme,
                           const AuthCredentials& credentials) {
  for (auto it = entries_.begin(); it != entries_.end(); ++it) {
    if (it->origin() == origin && it->realm() == realm &&
        it->scheme() == scheme) {
      if (credentials.Equals(it->credentials())) {
        entries_.erase(it);
        return true;
      }
      return false;
    }
  }
  return false;
}

void HttpAuthCache::ClearEntriesAddedSince(base::Time begin_time) {
  if (begin_time.is_null()) {
    ClearAllEntries();
  } else {
    base::EraseIf(entries_, [begin_time](const Entry& entry) {
      return entry.creation_time_ >= begin_time;
    });
  }
}

void HttpAuthCache::ClearAllEntries() {
  entries_.clear();
}

bool HttpAuthCache::UpdateStaleChallenge(const GURL& origin,
                                         const std::string& realm,
                                         HttpAuth::Scheme scheme,
                                         const std::string& auth_challenge) {
  HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
  if (!entry)
    return false;
  entry->UpdateStaleChallenge(auth_challenge);
  entry->last_use_time_ticks_ = tick_clock_->NowTicks();
  return true;
}

void HttpAuthCache::UpdateAllFrom(const HttpAuthCache& other) {
  for (auto it = other.entries_.begin(); it != other.entries_.end(); ++it) {
    // Add an Entry with one of the original entry's paths.
    DCHECK(it->paths_.size() > 0);
    Entry* entry = Add(it->origin(), it->realm(), it->scheme(),
                       it->auth_challenge(), it->credentials(),
                       it->paths_.back());
    // Copy all other paths.
    for (auto it2 = ++it->paths_.rbegin(); it2 != it->paths_.rend(); ++it2)
      entry->AddPath(*it2);
    // Copy nonce count (for digest authentication).
    entry->nonce_count_ = it->nonce_count_;
  }
}

size_t HttpAuthCache::GetEntriesSizeForTesting() {
  return entries_.size();
}

}  // namespace net
