blob: 7425a5eb34f1cd91b3c431e01a95eafe946d4ffc [file] [log] [blame]
/*
* Copyright (C) 2013 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.
*
* THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``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 COMPUTER, INC. OR
* 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 "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
const SandboxFlagFeaturePolicyPairs& SandboxFlagsWithFeaturePolicies() {
DEFINE_STATIC_LOCAL(
SandboxFlagFeaturePolicyPairs, array,
({{WebSandboxFlags::kTopNavigation,
mojom::FeaturePolicyFeature::kTopNavigation},
{WebSandboxFlags::kForms, mojom::FeaturePolicyFeature::kFormSubmission},
{WebSandboxFlags::kScripts, mojom::FeaturePolicyFeature::kScript},
{WebSandboxFlags::kPopups, mojom::FeaturePolicyFeature::kPopups},
{WebSandboxFlags::kPointerLock,
mojom::FeaturePolicyFeature::kPointerLock},
{WebSandboxFlags::kModals, mojom::FeaturePolicyFeature::kModals},
{WebSandboxFlags::kOrientationLock,
mojom::FeaturePolicyFeature::kOrientationLock},
{WebSandboxFlags::kPresentationController,
mojom::FeaturePolicyFeature::kPresentation},
{WebSandboxFlags::kDownloads,
mojom::FeaturePolicyFeature::kDownloadsWithoutUserActivation}}));
return array;
}
// This returns a super mask which indicates the set of all flags that have
// corresponding feature policies. With FeaturePolicyForSandbox, these flags
// are always removed from the set of sandbox flags set for a sandboxed
// <iframe> (those sandbox flags are now contained in the |ContainerPolicy|).
WebSandboxFlags SandboxFlagsImplementedByFeaturePolicy() {
DEFINE_STATIC_LOCAL(WebSandboxFlags, mask, (WebSandboxFlags::kNone));
if (mask == WebSandboxFlags::kNone) {
for (const auto& pair : SandboxFlagsWithFeaturePolicies())
mask |= pair.first;
}
return mask;
}
WebSandboxFlags ParseSandboxPolicy(const SpaceSplitString& policy,
String& invalid_tokens_error_message) {
// http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
// Parse the unordered set of unique space-separated tokens.
WebSandboxFlags flags = WebSandboxFlags::kAll;
unsigned length = policy.size();
unsigned number_of_token_errors = 0;
StringBuilder token_errors;
for (unsigned index = 0; index < length; index++) {
// Turn off the corresponding sandbox flag if it's set as "allowed".
String sandbox_token(policy[index]);
if (EqualIgnoringASCIICase(sandbox_token, "allow-same-origin")) {
flags = flags & ~WebSandboxFlags::kOrigin;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-forms")) {
flags = flags & ~WebSandboxFlags::kForms;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-scripts")) {
flags = flags & ~WebSandboxFlags::kScripts;
flags = flags & ~WebSandboxFlags::kAutomaticFeatures;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-top-navigation")) {
flags = flags & ~WebSandboxFlags::kTopNavigation;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-popups")) {
flags = flags & ~WebSandboxFlags::kPopups;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-pointer-lock")) {
flags = flags & ~WebSandboxFlags::kPointerLock;
} else if (EqualIgnoringASCIICase(sandbox_token,
"allow-orientation-lock")) {
flags = flags & ~WebSandboxFlags::kOrientationLock;
} else if (EqualIgnoringASCIICase(sandbox_token,
"allow-popups-to-escape-sandbox")) {
flags = flags & ~WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-modals")) {
flags = flags & ~WebSandboxFlags::kModals;
} else if (EqualIgnoringASCIICase(sandbox_token, "allow-presentation")) {
flags = flags & ~WebSandboxFlags::kPresentationController;
} else if (EqualIgnoringASCIICase(
sandbox_token, "allow-top-navigation-by-user-activation")) {
flags = flags & ~WebSandboxFlags::kTopNavigationByUserActivation;
} else if (EqualIgnoringASCIICase(
sandbox_token, "allow-downloads-without-user-activation")) {
flags = flags & ~WebSandboxFlags::kDownloads;
} else {
token_errors.Append(token_errors.IsEmpty() ? "'" : ", '");
token_errors.Append(sandbox_token);
token_errors.Append("'");
number_of_token_errors++;
}
}
if (number_of_token_errors) {
token_errors.Append(number_of_token_errors > 1
? " are invalid sandbox flags."
: " is an invalid sandbox flag.");
invalid_tokens_error_message = token_errors.ToString();
}
return flags;
}
// Removes a certain set of flags from |sandbox_flags| for which we have feature
// policies implemented.
WebSandboxFlags GetSandboxFlagsNotImplementedAsFeaturePolicy(
WebSandboxFlags sandbox_flags) {
// Punch all the sandbox flags which are converted to feature policy.
return sandbox_flags & ~SandboxFlagsImplementedByFeaturePolicy();
}
void ApplySandboxFlagsToParsedFeaturePolicy(
WebSandboxFlags sandbox_flags,
ParsedFeaturePolicy& parsed_feature_policy) {
for (const auto& pair : SandboxFlagsWithFeaturePolicies()) {
if ((sandbox_flags & pair.first) != WebSandboxFlags::kNone)
DisallowFeatureIfNotPresent(pair.second, parsed_feature_policy);
}
}
} // namespace blink