Home | History | Annotate | Download | only in dom
      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 COMPUTER, 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 "core/dom/SecurityContext.h"
     29 
     30 #include "core/html/parser/HTMLParserIdioms.h"
     31 #include "core/page/ContentSecurityPolicy.h"
     32 #include "weborigin/SecurityOrigin.h"
     33 #include "wtf/text/StringBuilder.h"
     34 
     35 namespace WebCore {
     36 
     37 SecurityContext::SecurityContext()
     38     : m_mayDisplaySeamlesslyWithParent(false)
     39     , m_haveInitializedSecurityOrigin(false)
     40     , m_sandboxFlags(SandboxNone)
     41 {
     42 }
     43 
     44 SecurityContext::~SecurityContext()
     45 {
     46 }
     47 
     48 void SecurityContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
     49 {
     50     m_securityOrigin = securityOrigin;
     51     m_haveInitializedSecurityOrigin = true;
     52 }
     53 
     54 void SecurityContext::setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy> contentSecurityPolicy)
     55 {
     56     m_contentSecurityPolicy = contentSecurityPolicy;
     57 }
     58 
     59 bool SecurityContext::isSecureTransitionTo(const KURL& url) const
     60 {
     61     // If we haven't initialized our security origin by now, this is probably
     62     // a new window created via the API (i.e., that lacks an origin and lacks
     63     // a place to inherit the origin from).
     64     if (!haveInitializedSecurityOrigin())
     65         return true;
     66 
     67     RefPtr<SecurityOrigin> other = SecurityOrigin::create(url);
     68     return securityOrigin()->canAccess(other.get());
     69 }
     70 
     71 void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
     72 {
     73     m_sandboxFlags |= mask;
     74 
     75     // The SandboxOrigin is stored redundantly in the security origin.
     76     if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) {
     77         setSecurityOrigin(SecurityOrigin::createUnique());
     78         didUpdateSecurityOrigin();
     79     }
     80 }
     81 
     82 void SecurityContext::didUpdateSecurityOrigin()
     83 {
     84     // Subclasses can override this function if the need to do extra work when the security origin changes.
     85 }
     86 
     87 SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
     88 {
     89     // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
     90     // Parse the unordered set of unique space-separated tokens.
     91     SandboxFlags flags = SandboxAll;
     92     unsigned length = policy.length();
     93     unsigned start = 0;
     94     unsigned numberOfTokenErrors = 0;
     95     StringBuilder tokenErrors;
     96     while (true) {
     97         while (start < length && isHTMLSpace(policy[start]))
     98             ++start;
     99         if (start >= length)
    100             break;
    101         unsigned end = start + 1;
    102         while (end < length && !isHTMLSpace(policy[end]))
    103             ++end;
    104 
    105         // Turn off the corresponding sandbox flag if it's set as "allowed".
    106         String sandboxToken = policy.substring(start, end - start);
    107         if (equalIgnoringCase(sandboxToken, "allow-same-origin"))
    108             flags &= ~SandboxOrigin;
    109         else if (equalIgnoringCase(sandboxToken, "allow-forms"))
    110             flags &= ~SandboxForms;
    111         else if (equalIgnoringCase(sandboxToken, "allow-scripts")) {
    112             flags &= ~SandboxScripts;
    113             flags &= ~SandboxAutomaticFeatures;
    114         } else if (equalIgnoringCase(sandboxToken, "allow-top-navigation"))
    115             flags &= ~SandboxTopNavigation;
    116         else if (equalIgnoringCase(sandboxToken, "allow-popups"))
    117             flags &= ~SandboxPopups;
    118         else if (equalIgnoringCase(sandboxToken, "allow-pointer-lock"))
    119             flags &= ~SandboxPointerLock;
    120         else {
    121             if (numberOfTokenErrors)
    122                 tokenErrors.appendLiteral(", '");
    123             else
    124                 tokenErrors.append('\'');
    125             tokenErrors.append(sandboxToken);
    126             tokenErrors.append('\'');
    127             numberOfTokenErrors++;
    128         }
    129 
    130         start = end + 1;
    131     }
    132 
    133     if (numberOfTokenErrors) {
    134         if (numberOfTokenErrors > 1)
    135             tokenErrors.appendLiteral(" are invalid sandbox flags.");
    136         else
    137             tokenErrors.appendLiteral(" is an invalid sandbox flag.");
    138         invalidTokensErrorMessage = tokenErrors.toString();
    139     }
    140 
    141     return flags;
    142 }
    143 
    144 }
    145