Example #1
0
TEST(KnownPortsTest, IsDefaultPortForProtocol)
{
    struct TestCase {
        const unsigned short port;
        const char* protocol;
        const bool isKnown;
    } inputs[] = {
        // Known ones.
        { 80, "http", true },
        { 443, "https", true },
        { 80, "ws", true },
        { 443, "wss", true },
        { 21, "ftp", true },
        { 990, "ftps", true },

        // Unknown ones.
        { 5, "foo", false },
        { 80, "http:", false },
        { 443, "http", false },
        { 21, "ftps", false },
        { 990, "ftp", false },

        // With upper cases.
        { 80, "HTTP", false },
        { 443, "Https", false },
    };

    for (const TestCase& test : inputs) {
        bool result = isDefaultPortForProtocol(test.port, test.protocol);
        EXPECT_EQ(test.isKnown, result);
    }
}
Example #2
0
String DOMURLUtilsReadOnly::host(const KURL& kurl) {
  if (kurl.hostEnd() == kurl.pathStart())
    return kurl.host();
  if (isDefaultPortForProtocol(kurl.port(), kurl.protocol()))
    return kurl.host();
  return kurl.host() + ":" + String::number(kurl.port());
}
Example #3
0
void HTMLAnchorElement::setHost(const String& value)
{
    if (value.isEmpty())
        return;
    KURL url = href();
    if (!url.canSetHostOrPort())
        return;

    size_t separator = value.find(':');
    if (!separator)
        return;

    if (separator == notFound)
        url.setHostAndPort(value);
    else {
        unsigned portEnd;
        unsigned port = parsePortFromStringPosition(value, separator + 1, portEnd);
        if (!port) {
            // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
            // specifically goes against RFC 3986 (p3.2) and
            // requires setting the port to "0" if it is set to empty string.
            url.setHostAndPort(value.substring(0, separator + 1) + "0");
        } else {
            if (isDefaultPortForProtocol(port, url.protocol()))
                url.setHostAndPort(value.substring(0, separator));
            else
                url.setHostAndPort(value.substring(0, portEnd));
        }
    }
    setHref(url.string());
}
Example #4
0
 bool portMatches(const KURL& url) const
 {
     if (m_portHasWildcard)
         return true;
     int port = url.port();
     return port ? port == m_port : isDefaultPortForProtocol(m_port, url.protocol());
 }
Example #5
0
String HTMLAnchorElement::host() const
{
    const KURL& url = href();
    if (url.hostEnd() == url.pathStart())
        return url.host();
    if (isDefaultPortForProtocol(url.port(), url.protocol()))
        return url.host();
    return url.host() + ":" + String::number(url.port());
}
Example #6
0
bool CSPSource::portMatches(int port, const String& protocol) const {
  if (m_portWildcard == HasWildcard)
    return true;

  if (port == m_port)
    return true;

  if (m_port == 80 &&
      (port == 443 || (port == 0 && defaultPortForProtocol(protocol) == 443)))
    return true;

  if (!port)
    return isDefaultPortForProtocol(m_port, protocol);

  if (!m_port)
    return isDefaultPortForProtocol(port, protocol);

  return false;
}
Example #7
0
bool CSPSource::portMatches(const KURL& url) const
{
    if (m_portWildcard == HasWildcard)
        return true;

    int port = url.port();

    if (port == m_port)
        return true;

    if (m_port == 80 && (port == 443 || (port == 0 && (url.protocol() == "https" || url.protocol() == "wss"))))
        return true;

    if (!port)
        return isDefaultPortForProtocol(m_port, url.protocol());

    if (!m_port)
        return isDefaultPortForProtocol(port, url.protocol());

    return false;
}
Example #8
0
void KURL::setPort(unsigned short port)
{
    if (isDefaultPortForProtocol(port, protocol())) {
        removePort();
        return;
    }

    String portString = String::number(port);
    ASSERT(portString.is8Bit());

    url::Replacements<char> replacements;
    replacements.SetPort(reinterpret_cast<const char*>(portString.characters8()), url::Component(0, portString.length()));
    replaceComponents(replacements);
}
Example #9
0
void HTMLAnchorElement::setPort(const String& value)
{
    KURL url = href();
    if (!url.canSetHostOrPort())
        return;

    // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
    // specifically goes against RFC 3986 (p3.2) and
    // requires setting the port to "0" if it is set to empty string.
    unsigned port = value.toUInt();
    if (isDefaultPortForProtocol(port, url.protocol()))
        url.removePort();
    else
        url.setPort(port);

    setHref(url.string());
}
void applyBlockedStatusToRequest(const BlockedStatus& status, ResourceRequest& request)
{
    if (status.blockedCookies)
        request.setAllowCookies(false);

    if (status.madeHTTPS) {
        const URL& originalURL = request.url();
        ASSERT(originalURL.protocolIs("http"));
        ASSERT(!originalURL.port() || isDefaultPortForProtocol(originalURL.port().value(), originalURL.protocol()));

        URL newURL = originalURL;
        newURL.setProtocol("https");
        if (originalURL.port())
            newURL.setPort(defaultPortForProtocol("https").value());
        request.setURL(newURL);
    }
}
Example #11
0
SecurityOrigin::SecurityOrigin(const URL& url)
    : m_protocol(url.protocol().isNull() ? emptyString() : url.protocol().toString().convertToASCIILowercase())
    , m_host(url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase())
    , m_port(url.port())
{
    // document.domain starts as m_host, but can be set by the DOM.
    m_domain = m_host;

    if (m_port && isDefaultPortForProtocol(m_port.value(), m_protocol))
        m_port = Nullopt;

    // By default, only local SecurityOrigins can load local resources.
    m_canLoadLocalResources = isLocal();

    if (m_canLoadLocalResources)
        m_filePath = url.path(); // In case enforceFilePathSeparation() is called.
}
Example #12
0
void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
{
    ASSERT(!m_reachedTerminalState);

    // Protect this in this delegate method since the additional processing can do
    // anything including possibly derefing this; one example of this is Radar 3266216.
    Ref<ResourceLoader> protectedThis(*this);

    logResourceResponseSource(m_frame.get(), r.source());

    m_response = r;

    if (m_response.isHttpVersion0_9()) {
        auto url = m_response.url();
        // Non-HTTP responses are interpreted as HTTP/0.9 which may allow exfiltration of data
        // from non-HTTP services. Therefore cancel if the document was loaded with different
        // HTTP version or if the resource request was to a non-default port.
        if (!m_documentLoader->response().isHttpVersion0_9()) {
            String message = "Cancelled resource load from '" + url.string() + "' because it is using HTTP/0.9 and the document was loaded with a different HTTP version.";
            m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, identifier());
            ResourceError error(emptyString(), 0, url, message);
            didFail(error);
            return;
        }
        if (!isDefaultPortForProtocol(url.port(), url.protocol())) {
            String message = "Cancelled resource load from '" + url.string() + "' because it is using HTTP/0.9 on a non-default port.";
            m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, identifier());
            ResourceError error(emptyString(), 0, url, message);
            didFail(error);
            return;
        }
            
        String message = "Sandboxing '" + m_response.url().string() + "' because it is using HTTP/0.9.";
        m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, m_identifier);
        frameLoader()->forceSandboxFlags(SandboxScripts | SandboxPlugins);
    }

    if (FormData* data = m_request.httpBody())
        data->removeGeneratedFilesIfNeeded();
        
    if (m_options.sendLoadCallbacks() == SendCallbacks)
        frameLoader()->notifier().didReceiveResponse(this, m_response);
}
Example #13
0
SecurityOrigin::SecurityOrigin(const KUrl& url) :
      m_protocol(url.protocol().toLower())
    , m_host(url.host().toLower())
    , m_port(url.port())
    , m_domainWasSetInDOM(false)
    , m_isUnique(false)
{
    // These protocols do not create security origins; the owner frame provides the origin
    if (m_protocol == "about" || m_protocol == "javascript")
        m_protocol = "";

    // For edge case URLs that were probably misparsed, make sure that the origin is unique.
    if (m_host.isEmpty() && KProtocolInfo::protocolClass(m_protocol) == QLatin1String(":internet"))
        m_isUnique = true;

    // document.domain starts as m_host, but can be set by the DOM.
    m_domain = m_host;

    if (url.port() == -1 || isDefaultPortForProtocol(m_port, m_protocol))
        m_port = 0;
}
Example #14
0
SecurityOrigin::SecurityOrigin(const KURL& url)
    : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower())
    , m_host(url.host().isNull() ? "" : url.host().lower())
    , m_port(url.port())
    , m_isUnique(false)
    , m_universalAccess(false)
    , m_domainWasSetInDOM(false)
    , m_enforceFilePathSeparation(false)
    , m_needsDatabaseIdentifierQuirkForFiles(false)
{
    // document.domain starts as m_host, but can be set by the DOM.
    m_domain = m_host;

    if (isDefaultPortForProtocol(m_port, m_protocol))
        m_port = InvalidPort;

    // By default, only local SecurityOrigins can load local resources.
    m_canLoadLocalResources = isLocal();

    if (m_canLoadLocalResources)
        m_filePath = url.path(); // In case enforceFilePathSeparation() is called.
}
Example #15
0
SecurityOrigin::SecurityOrigin(const KURL& url)
    : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower())
    , m_host(url.host().isNull() ? "" : url.host().lower())
    , m_port(url.port())
    , m_noAccess(false)
    , m_domainWasSetInDOM(false)
{
    // These protocols do not create security origins; the owner frame provides the origin
    if (m_protocol == "about" || m_protocol == "javascript")
        m_protocol = "";

    // data: URLs are not allowed access to anything other than themselves.
    if (m_protocol == "data")
        m_noAccess = true;

    // document.domain starts as m_host, but can be set by the DOM.
    m_domain = m_host;

    // By default, only local SecurityOrigins can load local resources.
    m_canLoadLocalResources = isLocal();

    if (isDefaultPortForProtocol(m_port, m_protocol))
        m_port = 0;
}
BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
{
    if (m_contentExtensions.isEmpty())
        return { };

    Document* currentDocument = nullptr;
    URL mainDocumentURL;

    if (Frame* frame = initiatingDocumentLoader.frame()) {
        currentDocument = frame->document();

        if (initiatingDocumentLoader.isLoadingMainResource()
            && frame->isMainFrame()
            && resourceType == ResourceType::Document)
            mainDocumentURL = url;
        else if (Document* mainDocument = frame->mainFrame().document())
            mainDocumentURL = mainDocument->url();
    }

    ResourceLoadInfo resourceLoadInfo = { url, mainDocumentURL, resourceType };
    Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo);

    bool willBlockLoad = false;
    bool willBlockCookies = false;
    bool willMakeHTTPS = false;
    for (const auto& action : actions) {
        switch (action.type()) {
        case ContentExtensions::ActionType::BlockLoad:
            willBlockLoad = true;
            break;
        case ContentExtensions::ActionType::BlockCookies:
            willBlockCookies = true;
            break;
        case ContentExtensions::ActionType::CSSDisplayNoneSelector:
            if (resourceType == ResourceType::Document)
                initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
            else if (currentDocument)
                currentDocument->extensionStyleSheets().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
            break;
        case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet: {
            StyleSheetContents* styleSheetContents = globalDisplayNoneStyleSheet(action.stringArgument());
            if (styleSheetContents) {
                if (resourceType == ResourceType::Document)
                    initiatingDocumentLoader.addPendingContentExtensionSheet(action.stringArgument(), *styleSheetContents);
                else if (currentDocument)
                    currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(action.stringArgument(), *styleSheetContents);
            }
            break;
        }
        case ContentExtensions::ActionType::MakeHTTPS: {
            if ((url.protocolIs("http") || url.protocolIs("ws"))
                && (!url.port() || isDefaultPortForProtocol(url.port().value(), url.protocol())))
                willMakeHTTPS = true;
            break;
        }
        case ContentExtensions::ActionType::IgnorePreviousRules:
        case ContentExtensions::ActionType::InvalidAction:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }

    if (currentDocument) {
        if (willMakeHTTPS) {
            ASSERT(url.protocolIs("http") || url.protocolIs("ws"));
            String newProtocol = url.protocolIs("http") ? ASCIILiteral("https") : ASCIILiteral("wss");
            currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", url.string(), " to ", newProtocol));
        }
        if (willBlockLoad)
            currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", url.string()));
    }
    return { willBlockLoad, willBlockCookies, willMakeHTTPS };
}
BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(ResourceRequest& request, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
{
    Document* currentDocument = nullptr;
    URL mainDocumentURL;

    if (Frame* frame = initiatingDocumentLoader.frame()) {
        currentDocument = frame->document();

        if (initiatingDocumentLoader.isLoadingMainResource()
            && frame->isMainFrame()
            && resourceType == ResourceType::Document)
            mainDocumentURL = request.url();
        else if (Document* mainDocument = frame->mainFrame().document())
            mainDocumentURL = mainDocument->url();
    }

    ResourceLoadInfo resourceLoadInfo = { request.url(), mainDocumentURL, resourceType };
    Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo);

    bool willBlockLoad = false;
    for (const auto& action : actions) {
        switch (action.type()) {
        case ContentExtensions::ActionType::BlockLoad:
            willBlockLoad = true;
            break;
        case ContentExtensions::ActionType::BlockCookies:
            request.setAllowCookies(false);
            break;
        case ContentExtensions::ActionType::CSSDisplayNoneSelector:
            if (resourceType == ResourceType::Document)
                initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
            else if (currentDocument)
                currentDocument->extensionStyleSheets().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
            break;
        case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet: {
            StyleSheetContents* styleSheetContents = globalDisplayNoneStyleSheet(action.stringArgument());
            if (styleSheetContents) {
                if (resourceType == ResourceType::Document)
                    initiatingDocumentLoader.addPendingContentExtensionSheet(action.stringArgument(), *styleSheetContents);
                else if (currentDocument)
                    currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(action.stringArgument(), *styleSheetContents);
            }
            break;
        }
        case ContentExtensions::ActionType::MakeHTTPS: {
            const URL originalURL = request.url();
            if (originalURL.protocolIs("http") && (!originalURL.hasPort() || isDefaultPortForProtocol(originalURL.port(), originalURL.protocol()))) {
                URL newURL = originalURL;
                newURL.setProtocol("https");
                if (originalURL.hasPort())
                    newURL.setPort(defaultPortForProtocol("https"));
                request.setURL(newURL);

                if (resourceType == ResourceType::Document && initiatingDocumentLoader.isLoadingMainResource()) {
                    // This is to make sure the correct 'new' URL shows in the location bar.
                    initiatingDocumentLoader.request().setURL(newURL);
                    initiatingDocumentLoader.frameLoader()->client().dispatchDidChangeProvisionalURL();
                }
                if (currentDocument)
                    currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", originalURL.string(), " to ", newURL.string()));
            }
            break;
        }
        case ContentExtensions::ActionType::IgnorePreviousRules:
        case ContentExtensions::ActionType::InvalidAction:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }

    if (willBlockLoad) {
        if (currentDocument)
            currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", request.url().string()));
        return BlockedStatus::Blocked;
    }
    return BlockedStatus::NotBlocked;
}