/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Google, Inc. ("Google") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GOOGLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "SecurityPolicy.h"

#include "OriginAccessEntry.h"
#include "SecurityOrigin.h"
#include "UserContentURLPattern.h"
#include <memory>
#include <wtf/HashMap.h>
#include <wtf/Lock.h>
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/URL.h>
#include <wtf/text/StringHash.h>

namespace WebCore {

static SecurityPolicy::LocalLoadPolicy localLoadPolicy = SecurityPolicy::AllowLocalLoadsForLocalOnly;

using OriginAccessAllowlist = Vector<OriginAccessEntry>;
using OriginAccessMap = HashMap<SecurityOriginData, std::unique_ptr<OriginAccessAllowlist>>;

static Lock originAccessMapLock;
static OriginAccessMap& originAccessMap() WTF_REQUIRES_LOCK(originAccessMapLock)
{
    ASSERT(originAccessMapLock.isHeld());
    static NeverDestroyed<OriginAccessMap> originAccessMap;
    return originAccessMap;
}

static Lock originAccessPatternLock;
static Vector<UserContentURLPattern>& originAccessPatterns() WTF_REQUIRES_LOCK(originAccessPatternLock)
{
    ASSERT(originAccessPatternLock.isHeld());
    static NeverDestroyed<Vector<UserContentURLPattern>> originAccessPatterns;
    return originAccessPatterns;
}

bool SecurityPolicy::shouldHideReferrer(const URL& url, const String& referrer)
{
    bool referrerIsSecureURL = protocolIs(referrer, "https"_s);
    bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http"_s);

    if (!referrerIsWebURL)
        return true;

    if (!referrerIsSecureURL)
        return false;

    bool URLIsSecureURL = url.protocolIs("https"_s);

    return !URLIsSecureURL;
}

String SecurityPolicy::referrerToOriginString(const String& referrer)
{
    String originString = SecurityOrigin::createFromString(referrer)->toString();
    if (originString == "null"_s)
        return String();
    // A security origin is not a canonical URL as it lacks a path. Add /
    // to turn it into a canonical URL we can use as referrer.
    return originString + "/";
}

String SecurityPolicy::generateReferrerHeader(ReferrerPolicy referrerPolicy, const URL& url, const String& referrer)
{
    ASSERT(referrer == URL { referrer }.strippedForUseAsReferrer()
        || referrer == SecurityOrigin::create(URL { referrer })->toString());

    if (referrer.isEmpty())
        return String();

    if (!protocolIsInHTTPFamily(referrer))
        return String();

    switch (referrerPolicy) {
    case ReferrerPolicy::EmptyString:
        ASSERT_NOT_REACHED();
        break;
    case ReferrerPolicy::NoReferrer:
        return String();
    case ReferrerPolicy::NoReferrerWhenDowngrade:
        break;
    case ReferrerPolicy::SameOrigin: {
        auto origin = SecurityOrigin::createFromString(referrer);
        if (!origin->canRequest(url))
            return String();
        break;
    }
    case ReferrerPolicy::Origin:
        return referrerToOriginString(referrer);
    case ReferrerPolicy::StrictOrigin:
        if (shouldHideReferrer(url, referrer))
            return String();
        return referrerToOriginString(referrer);
    case ReferrerPolicy::OriginWhenCrossOrigin: {
        auto origin = SecurityOrigin::createFromString(referrer);
        if (!origin->canRequest(url))
            return referrerToOriginString(referrer);
        break;
    }
    case ReferrerPolicy::StrictOriginWhenCrossOrigin: {
        auto origin = SecurityOrigin::createFromString(referrer);
        if (!origin->canRequest(url)) {
            if (shouldHideReferrer(url, referrer))
                return String();
            return referrerToOriginString(referrer);
        }
        break;
    }
    case ReferrerPolicy::UnsafeUrl:
        return referrer;
    }

    return shouldHideReferrer(url, referrer) ? String() : referrer;
}

String SecurityPolicy::generateOriginHeader(ReferrerPolicy referrerPolicy, const URL& url, const SecurityOrigin& securityOrigin)
{
    switch (referrerPolicy) {
    case ReferrerPolicy::NoReferrer:
        return "null"_s;
    case ReferrerPolicy::NoReferrerWhenDowngrade:
    case ReferrerPolicy::StrictOrigin:
    case ReferrerPolicy::StrictOriginWhenCrossOrigin:
        if (protocolIs(securityOrigin.protocol(), "https"_s) && !url.protocolIs("https"_s))
            return "null"_s;
        break;
    case ReferrerPolicy::SameOrigin:
        if (!securityOrigin.canRequest(url))
            return "null"_s;
        break;
    case ReferrerPolicy::EmptyString:
    case ReferrerPolicy::Origin:
    case ReferrerPolicy::OriginWhenCrossOrigin:
    case ReferrerPolicy::UnsafeUrl:
        break;
    }

    return securityOrigin.toString();
}

bool SecurityPolicy::shouldInheritSecurityOriginFromOwner(const URL& url)
{
    // Paraphrased from <https://html.spec.whatwg.org/multipage/browsers.html#origin> (8 July 2016)
    //
    // If a Document has the address "about:blank"
    //      The origin of the document is the origin it was assigned when its browsing context was created.
    // If a Document has the address "about:srcdoc"
    //      The origin of the document is the origin of its parent document.
    //
    // Note: We generalize this to invalid URLs because we treat such URLs as about:blank.
    // FIXME: We also allow some URLs like "about:BLANK". We should probably block navigation to these URLs, see rdar://problem/57966056.
    return url.isEmpty() || url.isAboutBlank() || url.isAboutSrcDoc() || equalIgnoringASCIICase(url.string(), aboutBlankURL().string());
}

bool SecurityPolicy::isBaseURLSchemeAllowed(const URL& url)
{
    // See <https://github.com/whatwg/html/issues/2249>.
    return !url.protocolIsData() && !url.protocolIsJavaScript();
}

void SecurityPolicy::setLocalLoadPolicy(LocalLoadPolicy policy)
{
    localLoadPolicy = policy;
}

bool SecurityPolicy::restrictAccessToLocal()
{
    return localLoadPolicy != SecurityPolicy::AllowLocalLoadsForAll;
}

bool SecurityPolicy::allowSubstituteDataAccessToLocal()
{
    return localLoadPolicy != SecurityPolicy::AllowLocalLoadsForLocalOnly;
}

bool SecurityPolicy::isAccessAllowed(const SecurityOrigin& activeOrigin, const SecurityOrigin& targetOrigin, const URL& targetURL)
{
    ASSERT(targetOrigin.equal(SecurityOrigin::create(targetURL).ptr()));
    {
        Locker locker { originAccessMapLock };
        if (auto* list = originAccessMap().get(activeOrigin.data())) {
            for (auto& entry : *list) {
                if (entry.matchesOrigin(targetOrigin))
                    return true;
            }
        }
    }
    Locker locker { originAccessPatternLock };
    for (const auto& pattern : originAccessPatterns()) {
        if (pattern.matches(targetURL))
            return true;
    }
    return false;
}

bool SecurityPolicy::isAccessAllowed(const SecurityOrigin& activeOrigin, const URL& url)
{
    return isAccessAllowed(activeOrigin, SecurityOrigin::create(url).get(), url);
}

void SecurityPolicy::addOriginAccessAllowlistEntry(const SecurityOrigin& sourceOrigin, const String& destinationProtocol, const String& destinationDomain, bool allowDestinationSubdomains)
{
    ASSERT(!sourceOrigin.isUnique());
    if (sourceOrigin.isUnique())
        return;

    Locker locker { originAccessMapLock };
    auto* allowList = originAccessMap().ensure(sourceOrigin.data(), [] { return makeUnique<OriginAccessAllowlist>(); }).iterator->value.get();
    allowList->append(OriginAccessEntry(destinationProtocol, destinationDomain, allowDestinationSubdomains ? OriginAccessEntry::AllowSubdomains : OriginAccessEntry::DisallowSubdomains, OriginAccessEntry::TreatIPAddressAsIPAddress));
}

void SecurityPolicy::removeOriginAccessAllowlistEntry(const SecurityOrigin& sourceOrigin, const String& destinationProtocol, const String& destinationDomain, bool allowDestinationSubdomains)
{
    ASSERT(!sourceOrigin.isUnique());
    if (sourceOrigin.isUnique())
        return;

    Locker locker { originAccessMapLock };
    auto& map = originAccessMap();
    auto it = map.find(sourceOrigin.data());
    if (it == map.end())
        return;

    auto& list = *it->value;
    OriginAccessEntry originAccessEntry(destinationProtocol, destinationDomain, allowDestinationSubdomains ? OriginAccessEntry::AllowSubdomains : OriginAccessEntry::DisallowSubdomains, OriginAccessEntry::TreatIPAddressAsIPAddress);
    if (!list.removeFirst(originAccessEntry))
        return;

    if (list.isEmpty())
        map.remove(it);
}

void SecurityPolicy::resetOriginAccessAllowlists()
{
    Locker locker { originAccessMapLock };
    originAccessMap().clear();
}

void SecurityPolicy::allowAccessTo(const UserContentURLPattern& pattern)
{
    Locker locker { originAccessPatternLock };
    originAccessPatterns().append(pattern);
}

} // namespace WebCore
