tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

OnionAliasService.cpp (2927B)


      1 #include "torproject/OnionAliasService.h"
      2 
      3 #include "mozilla/ClearOnShutdown.h"
      4 #include "mozilla/StaticPrefs_browser.h"
      5 #include "nsUnicharUtils.h"
      6 
      7 /**
      8 * Check if a hostname is a valid Onion v3 hostname.
      9 *
     10 * @param aHostname
     11 *        The hostname to verify. It is not a const reference because any
     12 *        uppercase character will be transformed to lowercase during the
     13 *        verification.
     14 * @return Tells whether the input string is an Onion v3 address
     15 */
     16 static bool ValidateOnionV3(nsACString& aHostname) {
     17  constexpr nsACString::size_type v3Length = 56 + 6;
     18  if (aHostname.Length() != v3Length) {
     19    return false;
     20  }
     21  ToLowerCase(aHostname);
     22  if (!StringEndsWith(aHostname, ".onion"_ns)) {
     23    return false;
     24  }
     25 
     26  const char* cur = aHostname.BeginWriting();
     27  // We have already checked that it ends by ".onion"
     28  const char* end = aHostname.EndWriting() - 6;
     29  for (; cur < end; ++cur) {
     30    if (!(islower(*cur) || ('2' <= *cur && *cur <= '7'))) {
     31      return false;
     32    }
     33  }
     34 
     35  return true;
     36 }
     37 
     38 namespace torproject {
     39 
     40 NS_IMPL_ISUPPORTS(OnionAliasService, IOnionAliasService)
     41 
     42 static mozilla::StaticRefPtr<OnionAliasService> gOAService;
     43 
     44 // static
     45 already_AddRefed<IOnionAliasService> OnionAliasService::GetSingleton() {
     46  if (gOAService) {
     47    return do_AddRef(gOAService);
     48  }
     49 
     50  gOAService = new OnionAliasService();
     51  ClearOnShutdown(&gOAService);
     52  return do_AddRef(gOAService);
     53 }
     54 
     55 NS_IMETHODIMP
     56 OnionAliasService::AddOnionAlias(const nsACString& aShortHostname,
     57                                 const nsACString& aLongHostname) {
     58  nsAutoCString shortHostname;
     59  ToLowerCase(aShortHostname, shortHostname);
     60  mozilla::UniquePtr<nsAutoCString> longHostname =
     61      mozilla::MakeUnique<nsAutoCString>(aLongHostname);
     62  if (!longHostname) {
     63    return NS_ERROR_OUT_OF_MEMORY;
     64  }
     65  if (!StringEndsWith(shortHostname, ".tor.onion"_ns) ||
     66      !ValidateOnionV3(*longHostname)) {
     67    return NS_ERROR_INVALID_ARG;
     68  }
     69  mozilla::AutoWriteLock lock(mLock);
     70  mOnionAliases.InsertOrUpdate(shortHostname, std::move(longHostname));
     71  return NS_OK;
     72 }
     73 
     74 NS_IMETHODIMP
     75 OnionAliasService::GetOnionAlias(const nsACString& aShortHostname,
     76                                 nsACString& aLongHostname) {
     77  aLongHostname = aShortHostname;
     78  if (mozilla::StaticPrefs::browser_urlbar_onionRewrites_enabled() &&
     79      StringEndsWith(aShortHostname, ".tor.onion"_ns)) {
     80    nsAutoCString* alias = nullptr;
     81    // We want to keep the string stored in the map alive at least until we
     82    // finish to copy it to the output parameter.
     83    mozilla::AutoReadLock lock(mLock);
     84    if (mOnionAliases.Get(aShortHostname, &alias)) {
     85      // We take for granted aliases have already been validated
     86      aLongHostname.Assign(*alias);
     87    }
     88  }
     89  return NS_OK;
     90 }
     91 
     92 NS_IMETHODIMP
     93 OnionAliasService::ClearOnionAliases() {
     94  mozilla::AutoWriteLock lock(mLock);
     95  mOnionAliases.Clear();
     96  return NS_OK;
     97 }
     98 
     99 }  // namespace torproject