1/* 2 * Copyright (C) 2011 Google Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27#include "config.h" 28#include "SecurityContext.h" 29 30#include "ContentSecurityPolicy.h" 31#include "HTMLParserIdioms.h" 32#include "SecurityOrigin.h" 33#include <wtf/text/StringBuilder.h> 34 35namespace WebCore { 36 37SecurityContext::SecurityContext() 38 : m_haveInitializedSecurityOrigin(false) 39 , m_sandboxFlags(SandboxNone) 40{ 41} 42 43SecurityContext::~SecurityContext() 44{ 45} 46 47void SecurityContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin) 48{ 49 m_securityOrigin = securityOrigin; 50 m_haveInitializedSecurityOrigin = true; 51} 52 53void SecurityContext::setContentSecurityPolicy(std::unique_ptr<ContentSecurityPolicy> contentSecurityPolicy) 54{ 55 m_contentSecurityPolicy = WTF::move(contentSecurityPolicy); 56} 57 58bool SecurityContext::isSecureTransitionTo(const URL& url) const 59{ 60 // If we haven't initialized our security origin by now, this is probably 61 // a new window created via the API (i.e., that lacks an origin and lacks 62 // a place to inherit the origin from). 63 if (!haveInitializedSecurityOrigin()) 64 return true; 65 66 RefPtr<SecurityOrigin> other = SecurityOrigin::create(url); 67 return securityOrigin()->canAccess(other.get()); 68} 69 70void SecurityContext::enforceSandboxFlags(SandboxFlags mask) 71{ 72 m_sandboxFlags |= mask; 73 74 // The SandboxOrigin is stored redundantly in the security origin. 75 if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) 76 setSecurityOrigin(SecurityOrigin::createUnique()); 77} 78 79SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage) 80{ 81 // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox 82 // Parse the unordered set of unique space-separated tokens. 83 SandboxFlags flags = SandboxAll; 84 unsigned length = policy.length(); 85 unsigned start = 0; 86 unsigned numberOfTokenErrors = 0; 87 StringBuilder tokenErrors; 88 while (true) { 89 while (start < length && isHTMLSpace(policy[start])) 90 ++start; 91 if (start >= length) 92 break; 93 unsigned end = start + 1; 94 while (end < length && !isHTMLSpace(policy[end])) 95 ++end; 96 97 // Turn off the corresponding sandbox flag if it's set as "allowed". 98 String sandboxToken = policy.substring(start, end - start); 99 if (equalIgnoringCase(sandboxToken, "allow-same-origin")) 100 flags &= ~SandboxOrigin; 101 else if (equalIgnoringCase(sandboxToken, "allow-forms")) 102 flags &= ~SandboxForms; 103 else if (equalIgnoringCase(sandboxToken, "allow-scripts")) { 104 flags &= ~SandboxScripts; 105 flags &= ~SandboxAutomaticFeatures; 106 } else if (equalIgnoringCase(sandboxToken, "allow-top-navigation")) 107 flags &= ~SandboxTopNavigation; 108 else if (equalIgnoringCase(sandboxToken, "allow-popups")) 109 flags &= ~SandboxPopups; 110 else if (equalIgnoringCase(sandboxToken, "allow-pointer-lock")) 111 flags &= ~SandboxPointerLock; 112 else { 113 if (numberOfTokenErrors) 114 tokenErrors.appendLiteral(", '"); 115 else 116 tokenErrors.append('\''); 117 tokenErrors.append(sandboxToken); 118 tokenErrors.append('\''); 119 numberOfTokenErrors++; 120 } 121 122 start = end + 1; 123 } 124 125 if (numberOfTokenErrors) { 126 if (numberOfTokenErrors > 1) 127 tokenErrors.appendLiteral(" are invalid sandbox flags."); 128 else 129 tokenErrors.appendLiteral(" is an invalid sandbox flag."); 130 invalidTokensErrorMessage = tokenErrors.toString(); 131 } 132 133 return flags; 134} 135 136} 137