bool nsCSPKeywordSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPKeywordSrc::allows, aKeyWord: %s, a HashOrNonce: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); return mKeyword == aKeyword; }
bool nsCSPHashSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPHashSrc::allows, aKeyWord: %s, a HashOrNonce: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); if (aKeyword != CSP_HASH) { return false; } // Convert aHashOrNonce to UTF-8 NS_ConvertUTF16toUTF8 utf8_hash(aHashOrNonce); nsresult rv; nsCOMPtr<nsICryptoHash> hasher; hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv); NS_ENSURE_SUCCESS(rv, false); rv = hasher->InitWithString(NS_ConvertUTF16toUTF8(mAlgorithm)); NS_ENSURE_SUCCESS(rv, false); rv = hasher->Update((uint8_t *)utf8_hash.get(), utf8_hash.Length()); NS_ENSURE_SUCCESS(rv, false); nsAutoCString hash; rv = hasher->Finish(true, hash); NS_ENSURE_SUCCESS(rv, false); // The NSS Base64 encoder automatically adds linebreaks "\r\n" every 64 // characters. We need to remove these so we can properly validate longer // (SHA-512) base64-encoded hashes hash.StripChars("\r\n"); return NS_ConvertUTF16toUTF8(mHash).Equals(hash); }
// ::allows is only called for inlined loads, therefore: // nsCSPSchemeSrc, nsCSPHostSrc fall back // to this base class implementation which will never allow the load. bool nsCSPBaseSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPBaseSrc::allows, aKeyWord: %s, a HashOrNonce: %s", aKeyword == CSP_HASH ? "hash" : CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); return false; }
nsCSPPolicy::~nsCSPPolicy() { CSPUTILSLOG(("nsCSPPolicy::~nsCSPPolicy")); for (uint32_t i = 0; i < mDirectives.Length(); i++) { delete mDirectives[i]; } }
bool nsCSPPolicy::permits(nsContentPolicyType aContentType, nsIURI* aUri, const nsAString& aNonce, nsAString& outViolatedDirective) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPPolicy::permits, aContentType: %d, aUri: %s, aNonce: %s", aContentType, spec.get(), NS_ConvertUTF16toUTF8(aNonce).get())); } #endif NS_ASSERTION(aUri, "permits needs an uri to perform the check!"); nsCSPDirective* defaultDir = nullptr; // These directive arrays are short (1-5 elements), not worth using a hashtable. for (uint32_t i = 0; i < mDirectives.Length(); i++) { // Check if the directive name matches if (mDirectives[i]->restrictsContentType(aContentType)) { if (!mDirectives[i]->permits(aUri, aNonce)) { mDirectives[i]->toString(outViolatedDirective); return false; } return true; } if (mDirectives[i]->isDefaultDirective()) { defaultDir = mDirectives[i]; } } // If [frame-ancestors] is not listed explicitly then default to true // without consulting [default-src] // TODO: currently [frame-ancestors] is mapped to TYPE_DOCUMENT (needs to be fixed) if (aContentType == nsIContentPolicy::TYPE_DOCUMENT) { return true; } // If the above loop runs through, we haven't found a matching directive. // Avoid relooping, just store the result of default-src while looping. if (defaultDir) { if (!defaultDir->permits(aUri, aNonce)) { defaultDir->toString(outViolatedDirective); return false; } return true; } // unspecified default-src should default to no restrictions // see bug 764937 return true; }
// ::permits is only called for external load requests, therefore: // nsCSPKeywordSrc and nsCSPHashSource fall back to this base class // implementation which will never allow the load. bool nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPBaseSrc::permits, aUri: %s", spec.get())); } return false; }
bool nsCSPNonceSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPNonceSrc::allows, aKeyWord: %s, a HashOrNonce: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); if (aKeyword != CSP_NONCE) { return false; } return mNonce.Equals(aHashOrNonce); }
bool nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPNonceSrc::permits, aUri: %s, aNonce: %s", spec.get(), NS_ConvertUTF16toUTF8(aNonce).get())); } return mNonce.Equals(aNonce); }
bool nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, bool aUpgradeInsecure) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPSchemeSrc::permits, aUri: %s", spec.get())); } MOZ_ASSERT((!mScheme.EqualsASCII("")), "scheme can not be the empty string"); return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure); }
// ::permits is only called for external load requests, therefore: // nsCSPKeywordSrc and nsCSPHashSource fall back to this base class // implementation which will never allow the load. bool nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPBaseSrc::permits, aUri: %s", spec.get())); } #endif return false; }
bool nsCSPDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPDirective::allows, aKeyWord: %s, a HashOrNonce: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); for (uint32_t i = 0; i < mSrcs.Length(); i++) { if (mSrcs[i]->allows(aKeyword, aHashOrNonce)) { return true; } } return false; }
bool nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPNonceSrc::permits, aUri: %s, aNonce: %s", spec.get(), NS_ConvertUTF16toUTF8(aNonce).get())); } #endif return mNonce.Equals(aNonce); }
bool nsCSPPolicy::permits(CSPDirective aDir, nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, bool aSpecific, nsAString& outViolatedDirective) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPPolicy::permits, aUri: %s, aDir: %d, aSpecific: %s", spec.get(), aDir, aSpecific ? "true" : "false")); } #endif NS_ASSERTION(aUri, "permits needs an uri to perform the check!"); nsCSPDirective* defaultDir = nullptr; // Try to find a relevant directive // These directive arrays are short (1-5 elements), not worth using a hashtable. for (uint32_t i = 0; i < mDirectives.Length(); i++) { if (mDirectives[i]->equals(aDir)) { if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected)) { mDirectives[i]->toString(outViolatedDirective); return false; } return true; } if (mDirectives[i]->isDefaultDirective()) { defaultDir = mDirectives[i]; } } // If the above loop runs through, we haven't found a matching directive. // Avoid relooping, just store the result of default-src while looping. if (!aSpecific && defaultDir) { if (!defaultDir->permits(aUri, aNonce, aWasRedirected)) { defaultDir->toString(outViolatedDirective); return false; } return true; } // Nothing restricts this, so we're allowing the load // See bug 764937 return true; }
bool nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPSchemeSrc::permits, aUri: %s", spec.get())); } NS_ASSERTION((!mScheme.EqualsASCII("")), "scheme can not be the empty string"); nsAutoCString scheme; nsresult rv = aUri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, false); return mScheme.EqualsASCII(scheme.get()); }
bool nsCSPKeywordSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPKeywordSrc::allows, aKeyWord: %s, aHashOrNonce: %s, mInvalidated: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get(), mInvalidated ? "yes" : "false")); // if unsafe-inline should be ignored, then bail early if (mInvalidated) { NS_ASSERTION(mKeyword == CSP_UNSAFE_INLINE, "should only invalidate unsafe-inline within script-src"); return false; } return mKeyword == aKeyword; }
bool nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPDirective::permits, aUri: %s", spec.get())); } for (uint32_t i = 0; i < mSrcs.Length(); i++) { if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected)) { return true; } } return false; }
bool nsCSPPolicy::allows(nsContentPolicyType aContentType, enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const { CSPUTILSLOG(("nsCSPPolicy::allows, aKeyWord: %s, a HashOrNonce: %s", CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get())); nsCSPDirective* defaultDir = nullptr; // Try to find a matching directive for (uint32_t i = 0; i < mDirectives.Length(); i++) { if (mDirectives[i]->restrictsContentType(aContentType)) { if (mDirectives[i]->allows(aKeyword, aHashOrNonce)) { return true; } return false; } if (mDirectives[i]->isDefaultDirective()) { defaultDir = mDirectives[i]; } } // {nonce,hash}-source should not consult default-src: // * return false if default-src is specified // * but allow the load if default-src is *not* specified (Bug 1198422) if (aKeyword == CSP_NONCE || aKeyword == CSP_HASH) { if (!defaultDir) { return true; } return false; } // If the above loop runs through, we haven't found a matching directive. // Avoid relooping, just store the result of default-src while looping. if (defaultDir) { return defaultDir->allows(aKeyword, aHashOrNonce); } // Allowing the load; see Bug 885433 // a) inline scripts (also unsafe eval) should only be blocked // if there is a [script-src] or [default-src] // b) inline styles should only be blocked // if there is a [style-src] or [default-src] return true; }
bool nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPSchemeSrc::permits, aUri: %s", spec.get())); } #endif NS_ASSERTION((!mScheme.EqualsASCII("")), "scheme can not be the empty string"); nsAutoCString scheme; nsresult rv = aUri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, false); return mScheme.EqualsASCII(scheme.get()); }
bool nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPDirective::permits, aUri: %s", spec.get())); } #endif for (uint32_t i = 0; i < mSrcs.Length(); i++) { if (mSrcs[i]->permits(aUri, aNonce)) { return true; } } return false; }
nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp, const nsAString& aHeaderValue, bool aReportOnly) { NS_ENSURE_ARG(aCsp); // Need to tokenize the header value since multiple headers could be // concatenated into one comma-separated list of policies. // See RFC2616 section 4.2 (last paragraph) nsresult rv = NS_OK; nsCharSeparatedTokenizer tokenizer(aHeaderValue, ','); while (tokenizer.hasMoreTokens()) { const nsSubstring& policy = tokenizer.nextToken(); rv = aCsp->AppendPolicy(policy, aReportOnly, false); NS_ENSURE_SUCCESS(rv, rv); { CSPUTILSLOG(("CSP refined with policy: \"%s\"", NS_ConvertUTF16toUTF8(policy).get())); } } return NS_OK; }
bool nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPHostSrc::permits, aUri: %s", spec.get())); } #endif // we are following the enforcement rules from the spec, see: // http://www.w3.org/TR/CSP11/#match-source-expression // 4.3) scheme matching: Check if the scheme matches. nsAutoCString scheme; nsresult rv = aUri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, false); if (!mScheme.IsEmpty() && !mScheme.EqualsASCII(scheme.get())) { // We should not return false for scheme-less sources where the protected resource // is http and the load is https, see: // http://www.w3.org/TR/CSP2/#match-source-expression bool isHttpsScheme = (NS_SUCCEEDED(aUri->SchemeIs("https", &isHttpsScheme)) && isHttpsScheme); if (!(isHttpsScheme && mAllowHttps)) { return false; } } // The host in nsCSpHostSrc should never be empty. In case we are enforcing // just a specific scheme, the parser should generate a nsCSPSchemeSource. NS_ASSERTION((!mHost.IsEmpty()), "host can not be the empty string"); // 2) host matching: Enforce a single * if (mHost.EqualsASCII("*")) { return true; } // Before we can check if the host matches, we have to // extract the host part from aUri. nsAutoCString uriHost; rv = aUri->GetHost(uriHost); NS_ENSURE_SUCCESS(rv, false); // 4.5) host matching: Check if the allowed host starts with a wilcard. if (mHost.First() == '*') { NS_ASSERTION(mHost[1] == '.', "Second character needs to be '.' whenever host starts with '*'"); // Eliminate leading "*", but keeping the FULL STOP (.) thereafter before checking // if the remaining characters match nsString wildCardHost = mHost; wildCardHost = Substring(wildCardHost, 1, wildCardHost.Length() - 1); if (!StringEndsWith(NS_ConvertUTF8toUTF16(uriHost), wildCardHost)) { return false; } } // 4.6) host matching: Check if hosts match. else if (!mHost.Equals(NS_ConvertUTF8toUTF16(uriHost))) { return false; } // 4.9) Path matching: If there is a path, we have to enforce // path-level matching, unless the channel got redirected, see: // http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects if (!aWasRedirected && !mPath.IsEmpty()) { // cloning uri so we can ignore the ref nsCOMPtr<nsIURI> uri; aUri->CloneIgnoringRef(getter_AddRefs(uri)); nsAutoCString uriPath; rv = uri->GetPath(uriPath); NS_ENSURE_SUCCESS(rv, false); // check if the last character of mPath is '/'; if so // we just have to check loading resource is within // the allowed path. if (mPath.Last() == '/') { if (!StringBeginsWith(NS_ConvertUTF8toUTF16(uriPath), mPath)) { return false; } } // otherwise mPath whitelists a specific file, and we have to // check if the loading resource matches that whitelisted file. else { if (!mPath.Equals(NS_ConvertUTF8toUTF16(uriPath))) { return false; } } } // 4.8) Port matching: If port uses wildcard, allow the load. if (mPort.EqualsASCII("*")) { return true; } // Before we can check if the port matches, we have to // query the port from aUri. int32_t uriPort; rv = aUri->GetPort(&uriPort); NS_ENSURE_SUCCESS(rv, false); uriPort = (uriPort > 0) ? uriPort : NS_GetDefaultPort(scheme.get()); // 4.7) Default port matching: If mPort is empty, we have to compare default ports. if (mPort.IsEmpty()) { int32_t port = NS_GetDefaultPort(NS_ConvertUTF16toUTF8(mScheme).get()); if (port != uriPort) { // We should not return false for scheme-less sources where the protected resource // is http and the load is https, see: http://www.w3.org/TR/CSP2/#match-source-expression // BUT, we only allow scheme-less sources to be upgraded from http to https if CSP // does not explicitly define a port. if (!(uriPort == NS_GetDefaultPort("https") && mAllowHttps)) { return false; } } } // 4.7) Port matching: Compare the ports. else { nsString portStr; portStr.AppendInt(uriPort); if (!mPort.Equals(portStr)) { return false; } } // At the end: scheme, host, path, and port match -> allow the load. return true; }
nsCSPPolicy::nsCSPPolicy() : mReportOnly(false) { CSPUTILSLOG(("nsCSPPolicy::nsCSPPolicy")); }
nsCSPPolicy::nsCSPPolicy() : mUpgradeInsecDir(nullptr) , mReportOnly(false) { CSPUTILSLOG(("nsCSPPolicy::nsCSPPolicy")); }
bool nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const { #ifdef PR_LOGGING { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPHostSrc::permits, aUri: %s", spec.get())); } #endif // If the host is defined as a "*", and: // a) no scheme, and // b) no port is defined, allow the load. // http://www.w3.org/TR/CSP11/#matching if (mHost.EqualsASCII("*") && mScheme.IsEmpty() && mPort.IsEmpty()) { return true; } // Check if the scheme matches. nsAutoCString scheme; nsresult rv = aUri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, false); if (!mScheme.EqualsASCII(scheme.get())) { return false; } // The host in nsCSpHostSrc should never be empty. In case we are enforcing // just a specific scheme, the parser should generate a nsCSPSchemeSource. NS_ASSERTION((!mHost.IsEmpty()), "host can not be the empty string"); // Extract the host part from aUri. nsAutoCString uriHost; rv = aUri->GetHost(uriHost); NS_ENSURE_SUCCESS(rv, false); // Check it the allowed host starts with a wilcard. if (mHost.First() == '*') { NS_ASSERTION(mHost[1] == '.', "Second character needs to be '.' whenever host starts with '*'"); // Eliminate leading "*", but keeping the FULL STOP (.) thereafter before checking // if the remaining characters match: see http://www.w3.org/TR/CSP11/#matching nsString wildCardHost = mHost; wildCardHost = Substring(wildCardHost, 1, wildCardHost.Length() - 1); if (!StringEndsWith(NS_ConvertUTF8toUTF16(uriHost), wildCardHost)) { return false; } } // Check if hosts match. else if (!mHost.Equals(NS_ConvertUTF8toUTF16(uriHost))) { return false; } // If port uses wildcard, allow the load. if (mPort.EqualsASCII("*")) { return true; } // Check if ports match int32_t uriPort; rv = aUri->GetPort(&uriPort); NS_ENSURE_SUCCESS(rv, false); uriPort = (uriPort > 0) ? uriPort : NS_GetDefaultPort(scheme.get()); // If mPort is empty, we have to compare default ports. if (mPort.IsEmpty()) { int32_t port = NS_GetDefaultPort(NS_ConvertUTF16toUTF8(mScheme).get()); if (port != uriPort) { return false; } } // Otherwise compare the ports else { nsString portStr; portStr.AppendInt(uriPort); if (!mPort.Equals(portStr)) { return false; } } // At the end: scheme, host, port, match; allow the load. return true; }
bool nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, bool aUpgradeInsecure) const { if (CSPUTILSLOGENABLED()) { nsAutoCString spec; aUri->GetSpec(spec); CSPUTILSLOG(("nsCSPHostSrc::permits, aUri: %s", spec.get())); } // we are following the enforcement rules from the spec, see: // http://www.w3.org/TR/CSP11/#match-source-expression // 4.3) scheme matching: Check if the scheme matches. if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure)) { return false; } // The host in nsCSpHostSrc should never be empty. In case we are enforcing // just a specific scheme, the parser should generate a nsCSPSchemeSource. NS_ASSERTION((!mHost.IsEmpty()), "host can not be the empty string"); // 2) host matching: Enforce a single * if (mHost.EqualsASCII("*")) { // The single ASTERISK character (*) does not match a URI's scheme of a type // designating a globally unique identifier (such as blob:, data:, or filesystem:) // At the moment firefox does not support filesystem; but for future compatibility // we support it in CSP according to the spec, see: 4.2.2 Matching Source Expressions // Note, that whitelisting any of these schemes would call nsCSPSchemeSrc::permits(). bool isBlobScheme = (NS_SUCCEEDED(aUri->SchemeIs("blob", &isBlobScheme)) && isBlobScheme); bool isDataScheme = (NS_SUCCEEDED(aUri->SchemeIs("data", &isDataScheme)) && isDataScheme); bool isFileScheme = (NS_SUCCEEDED(aUri->SchemeIs("filesystem", &isFileScheme)) && isFileScheme); if (isBlobScheme || isDataScheme || isFileScheme) { return false; } return true; } // Before we can check if the host matches, we have to // extract the host part from aUri. nsAutoCString uriHost; nsresult rv = aUri->GetHost(uriHost); NS_ENSURE_SUCCESS(rv, false); // 4.5) host matching: Check if the allowed host starts with a wilcard. if (mHost.First() == '*') { NS_ASSERTION(mHost[1] == '.', "Second character needs to be '.' whenever host starts with '*'"); // Eliminate leading "*", but keeping the FULL STOP (.) thereafter before checking // if the remaining characters match nsString wildCardHost = mHost; wildCardHost = Substring(wildCardHost, 1, wildCardHost.Length() - 1); if (!StringEndsWith(NS_ConvertUTF8toUTF16(uriHost), wildCardHost)) { return false; } } // 4.6) host matching: Check if hosts match. else if (!mHost.Equals(NS_ConvertUTF8toUTF16(uriHost))) { return false; } // 4.9) Path matching: If there is a path, we have to enforce // path-level matching, unless the channel got redirected, see: // http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects if (!aWasRedirected && !mPath.IsEmpty()) { // converting aUri into nsIURL so we can strip query and ref // example.com/test#foo -> example.com/test // example.com/test?val=foo -> example.com/test nsCOMPtr<nsIURL> url = do_QueryInterface(aUri); if (!url) { NS_ASSERTION(false, "can't QI into nsIURI"); return false; } nsAutoCString uriPath; rv = url->GetFilePath(uriPath); NS_ENSURE_SUCCESS(rv, false); // check if the last character of mPath is '/'; if so // we just have to check loading resource is within // the allowed path. if (mPath.Last() == '/') { if (!StringBeginsWith(NS_ConvertUTF8toUTF16(uriPath), mPath)) { return false; } } // otherwise mPath whitelists a specific file, and we have to // check if the loading resource matches that whitelisted file. else { if (!mPath.Equals(NS_ConvertUTF8toUTF16(uriPath))) { return false; } } } // 4.8) Port matching: If port uses wildcard, allow the load. if (mPort.EqualsASCII("*")) { return true; } // Before we can check if the port matches, we have to // query the port from aUri. int32_t uriPort; rv = aUri->GetPort(&uriPort); NS_ENSURE_SUCCESS(rv, false); nsAutoCString scheme; rv = aUri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, false); uriPort = (uriPort > 0) ? uriPort : NS_GetDefaultPort(scheme.get()); // 4.7) Default port matching: If mPort is empty, we have to compare default ports. if (mPort.IsEmpty()) { int32_t port = NS_GetDefaultPort(NS_ConvertUTF16toUTF8(mScheme).get()); if (port != uriPort) { // We should not return false for scheme-less sources where the protected resource // is http and the load is https, see: http://www.w3.org/TR/CSP2/#match-source-expression // BUT, we only allow scheme-less sources to be upgraded from http to https if CSP // does not explicitly define a port. if (!(uriPort == NS_GetDefaultPort("https"))) { return false; } } } // 4.7) Port matching: Compare the ports. else { nsString portStr; portStr.AppendInt(uriPort); if (!mPort.Equals(portStr)) { return false; } } // At the end: scheme, host, path, and port match -> allow the load. return true; }