Commit 254e3940 authored by Georg Koppen's avatar Georg Koppen Committed by Matthew Finkel
Browse files

Bug 21537: Mark .onion cookies as secure

parent 37e5cf19
Loading
Loading
Loading
Loading
+30 −47
Original line number Diff line number Diff line
@@ -3005,6 +3005,25 @@ bool nsCookieService::PathMatches(nsCookie* aCookie, const nsACString& aPath) {
  return true;
}

static bool IsSecureHost(nsIURI* aHostURI) {
  bool isSecure = true;
  // If SchemeIs fails, assume an insecure connection, to be on the safe side.
  if (aHostURI && NS_FAILED(aHostURI->SchemeIs("https", &isSecure))) {
    isSecure = false;
  }
  // In case HTTPS is not used check whether we have a .onion host in which
  // case the cookie is secure, too.
  if (aHostURI && !isSecure) {
    nsresult rv;
    nsAutoCString hostFromURI;
    rv = aHostURI->GetAsciiHost(hostFromURI);
    if (NS_SUCCEEDED(rv)) {
      isSecure = StringEndsWith(hostFromURI, NS_LITERAL_CSTRING(".onion"));
    }
  }
  return isSecure;
}

void nsCookieService::GetCookiesForURI(
    nsIURI* aHostURI, nsIChannel* aChannel, bool aIsForeign,
    bool aIsTrackingResource, bool aFirstPartyStorageAccessGranted,
@@ -3068,13 +3087,10 @@ void nsCookieService::GetCookiesForURI(
  // If it changes, please update that function, or file a bug for someone
  // else to do so.

  // check if aHostURI is using an https secure protocol.
  // if it isn't, then we can't send a secure cookie over the connection.
  // if SchemeIs fails, assume an insecure connection, to be on the safe side
  bool isSecure;
  if (NS_FAILED(aHostURI->SchemeIs("https", &isSecure))) {
    isSecure = false;
  }
  // Check if aHostURI is using the HTTPS protocol or if the domain is a
  // .onion. If it isn't, then we can't send a secure cookie over the
  // connection.
  bool isSecure = IsSecureHost(aHostURI);

  nsCookie* cookie;
  int64_t currentTimeInUsec = PR_Now();
@@ -3241,40 +3257,10 @@ bool nsCookieService::CanSetCookie(nsIURI* aHostURI, const nsCookieKey& aKey,
  // so we can handle them separately.
  bool newCookie = ParseAttributes(aCookieHeader, aCookieAttributes);

  // Collect telemetry on how often secure cookies are set from non-secure
  // origins, and vice-versa.
  //
  // 0 = nonsecure and "http:"
  // 1 = nonsecure and "https:"
  // 2 = secure and "http:"
  // 3 = secure and "https:"
  bool isHTTPS = true;
  nsresult rv = aHostURI->SchemeIs("https", &isHTTPS);
  if (NS_SUCCEEDED(rv)) {
    Telemetry::Accumulate(Telemetry::COOKIE_SCHEME_SECURITY,
                          ((aCookieAttributes.isSecure) ? 0x02 : 0x00) |
                              ((isHTTPS) ? 0x01 : 0x00));

    // Collect telemetry on how often are first- and third-party cookies set
    // from HTTPS origins:
    //
    // 0 (000) = first-party and "http:"
    // 1 (001) = first-party and "http:" with bogus Secure cookie flag?!
    // 2 (010) = first-party and "https:"
    // 3 (011) = first-party and "https:" with Secure cookie flag
    // 4 (100) = third-party and "http:"
    // 5 (101) = third-party and "http:" with bogus Secure cookie flag?!
    // 6 (110) = third-party and "https:"
    // 7 (111) = third-party and "https:" with Secure cookie flag
    if (aThirdPartyUtil) {
      bool isThirdParty = true;
      aThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isThirdParty);
      Telemetry::Accumulate(Telemetry::COOKIE_SCHEME_HTTPS,
                            (isThirdParty ? 0x04 : 0x00) |
                                (isHTTPS ? 0x02 : 0x00) |
                                (aCookieAttributes.isSecure ? 0x01 : 0x00));
    }
  }
  // Check if aHostURI is using the HTTPS protocol or if the domain is a
  // .onion. If it isn't, then we can't send a secure cookie over the
  // connection.
  bool isSecure = IsSecureHost(aHostURI);

  int64_t currentTimeInUsec = PR_Now();

@@ -3319,7 +3305,7 @@ bool nsCookieService::CanSetCookie(nsIURI* aHostURI, const nsCookieKey& aKey,
    return newCookie;
  }
  // magic prefix checks. MUST be run after CheckDomain() and CheckPath()
  if (!CheckPrefixes(aCookieAttributes, isHTTPS)) {
  if (!CheckPrefixes(aCookieAttributes, isSecure)) {
    COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader,
                      "failed the prefix tests");
    return newCookie;
@@ -3353,7 +3339,7 @@ bool nsCookieService::CanSetCookie(nsIURI* aHostURI, const nsCookieKey& aKey,
  // If the new cookie is non-https and wants to set secure flag,
  // browser have to ignore this new cookie.
  // (draft-ietf-httpbis-cookie-alone section 3.1)
  if (aCookieAttributes.isSecure && !isHTTPS) {
  if (aCookieAttributes.isSecure && !isSecure) {
    COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
                      "non-https cookie can't set secure flag");
    return newCookie;
@@ -3471,10 +3457,7 @@ void nsCookieService::AddInternal(const nsCookieKey& aKey, nsCookie* aCookie,
  foundCookie = FindCookie(aKey, aCookie->Host(), aCookie->Name(),
                           aCookie->Path(), exactIter);
  bool foundSecureExact = foundCookie && exactIter.Cookie()->IsSecure();
  bool isSecure = true;
  if (aHostURI && NS_FAILED(aHostURI->SchemeIs("https", &isSecure))) {
    isSecure = false;
  }
  bool isSecure = IsSecureHost(aHostURI);
  bool oldCookieIsSession = false;
  // Step1, call FindSecureCookie(). FindSecureCookie() would
  // find the existing cookie with the security flag and has