FeaturePolicyParser.cpp (4623B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "FeaturePolicyParser.h" 8 9 #include "mozilla/BasePrincipal.h" 10 #include "mozilla/dom/Feature.h" 11 #include "mozilla/dom/FeaturePolicyUtils.h" 12 #include "mozilla/dom/PolicyTokenizer.h" 13 #include "nsIScriptError.h" 14 #include "nsIURI.h" 15 #include "nsNetUtil.h" 16 17 namespace mozilla::dom { 18 19 namespace { 20 21 void ReportToConsoleUnsupportedFeature(Document* aDocument, 22 const nsString& aFeatureName) { 23 if (!aDocument) { 24 return; 25 } 26 27 AutoTArray<nsString, 1> params = {aFeatureName}; 28 29 nsContentUtils::ReportToConsole( 30 nsIScriptError::warningFlag, "Feature Policy"_ns, aDocument, 31 nsContentUtils::eSECURITY_PROPERTIES, 32 "FeaturePolicyUnsupportedFeatureName", params); 33 } 34 35 void ReportToConsoleInvalidEmptyAllowValue(Document* aDocument, 36 const nsString& aFeatureName) { 37 if (!aDocument) { 38 return; 39 } 40 41 AutoTArray<nsString, 1> params = {aFeatureName}; 42 43 nsContentUtils::ReportToConsole( 44 nsIScriptError::warningFlag, "Feature Policy"_ns, aDocument, 45 nsContentUtils::eSECURITY_PROPERTIES, 46 "FeaturePolicyInvalidEmptyAllowValue", params); 47 } 48 49 void ReportToConsoleInvalidAllowValue(Document* aDocument, 50 const nsString& aValue) { 51 if (!aDocument) { 52 return; 53 } 54 55 AutoTArray<nsString, 1> params = {aValue}; 56 57 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 58 "Feature Policy"_ns, aDocument, 59 nsContentUtils::eSECURITY_PROPERTIES, 60 "FeaturePolicyInvalidAllowValue", params); 61 } 62 63 } // namespace 64 65 /* static */ 66 bool FeaturePolicyParser::ParseString(const nsAString& aPolicy, 67 Document* aDocument, 68 nsIPrincipal* aSelfOrigin, 69 nsIPrincipal* aSrcOrigin, 70 nsTArray<Feature>& aParsedFeatures) { 71 MOZ_ASSERT(aSelfOrigin); 72 73 nsTArray<CopyableTArray<nsString>> tokens; 74 PolicyTokenizer::tokenizePolicy(aPolicy, tokens); 75 76 nsTArray<Feature> parsedFeatures; 77 78 for (const nsTArray<nsString>& featureTokens : tokens) { 79 if (featureTokens.IsEmpty()) { 80 continue; 81 } 82 83 if (!FeaturePolicyUtils::IsSupportedFeature(featureTokens[0])) { 84 ReportToConsoleUnsupportedFeature(aDocument, featureTokens[0]); 85 continue; 86 } 87 88 Feature feature(featureTokens[0]); 89 90 if (featureTokens.Length() == 1) { 91 if (aSrcOrigin) { 92 feature.AppendToAllowList(aSrcOrigin); 93 } else { 94 ReportToConsoleInvalidEmptyAllowValue(aDocument, featureTokens[0]); 95 continue; 96 } 97 } else { 98 // we gotta start at 1 here 99 for (uint32_t i = 1; i < featureTokens.Length(); ++i) { 100 const nsString& curVal = featureTokens[i]; 101 if (curVal.LowerCaseEqualsASCII("'none'")) { 102 feature.SetAllowsNone(); 103 break; 104 } 105 106 if (curVal.EqualsLiteral("*")) { 107 feature.SetAllowsAll(); 108 break; 109 } 110 111 if (curVal.LowerCaseEqualsASCII("'self'")) { 112 feature.AppendToAllowList(aSelfOrigin); 113 continue; 114 } 115 116 if (aSrcOrigin && curVal.LowerCaseEqualsASCII("'src'")) { 117 feature.AppendToAllowList(aSrcOrigin); 118 continue; 119 } 120 121 nsCOMPtr<nsIURI> uri; 122 nsresult rv = NS_NewURI(getter_AddRefs(uri), curVal); 123 if (NS_FAILED(rv)) { 124 ReportToConsoleInvalidAllowValue(aDocument, curVal); 125 continue; 126 } 127 128 nsCOMPtr<nsIPrincipal> origin = BasePrincipal::CreateContentPrincipal( 129 uri, BasePrincipal::Cast(aSelfOrigin)->OriginAttributesRef()); 130 if (NS_WARN_IF(!origin)) { 131 ReportToConsoleInvalidAllowValue(aDocument, curVal); 132 continue; 133 } 134 135 feature.AppendToAllowList(origin); 136 } 137 } 138 139 // No duplicate! 140 bool found = false; 141 for (const Feature& parsedFeature : parsedFeatures) { 142 if (parsedFeature.Name() == feature.Name()) { 143 found = true; 144 break; 145 } 146 } 147 148 if (!found) { 149 parsedFeatures.AppendElement(feature); 150 } 151 } 152 153 aParsedFeatures = std::move(parsedFeatures); 154 return true; 155 } 156 157 } // namespace mozilla::dom