PolicyContainer.cpp (6617B)
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 "PolicyContainer.h" 8 9 #include "mozilla/dom/IntegrityPolicy.h" 10 #include "mozilla/dom/nsCSPContext.h" 11 #include "mozilla/ipc/PBackgroundSharedTypes.h" 12 #include "nsIClassInfoImpl.h" 13 #include "nsIObjectInputStream.h" 14 #include "nsIObjectOutputStream.h" 15 16 using namespace mozilla; 17 using namespace mozilla::dom; 18 19 PolicyContainer::~PolicyContainer() = default; 20 21 constexpr static uint32_t kPolicyContainerSerializationVersion = 1; 22 23 NS_IMETHODIMP 24 PolicyContainer::Read(nsIObjectInputStream* aStream) { 25 // Currently, we don't care about the version, but we might in the future. 26 uint32_t version = 0; 27 nsresult rv = aStream->Read32(&version); 28 NS_ENSURE_SUCCESS(rv, rv); 29 30 if (version != kPolicyContainerSerializationVersion) { 31 return NS_ERROR_FAILURE; 32 } 33 34 auto ReadOptionalCSPObject = [aStream](nsISupports** aOutCSP) { 35 bool nonnull = false; 36 nsresult rv = aStream->ReadBoolean(&nonnull); 37 NS_ENSURE_SUCCESS(rv, rv); 38 39 if (nonnull) { 40 nsCID cid; 41 rv = aStream->ReadID(&cid); 42 NS_ENSURE_SUCCESS(rv, rv); 43 MOZ_ASSERT(cid.Equals(nsCSPContext::GetCID()), 44 "Expected nsCSPContext CID"); 45 46 nsIID iid; 47 rv = aStream->ReadID(&iid); 48 NS_ENSURE_SUCCESS(rv, rv); 49 MOZ_ASSERT(iid.Equals(NS_GET_IID(nsIContentSecurityPolicy)), 50 "Expected nsIContentSecurityPolicy IID"); 51 52 RefPtr<nsCSPContext> csp = new nsCSPContext(); 53 rv = csp->PolicyContainerRead(aStream); 54 NS_ENSURE_SUCCESS(rv, rv); 55 csp.forget(aOutCSP); 56 } 57 58 return NS_OK; 59 }; 60 61 nsCOMPtr<nsISupports> csp; 62 rv = ReadOptionalCSPObject(getter_AddRefs(csp)); 63 NS_ENSURE_SUCCESS(rv, rv); 64 mCSP = do_QueryInterface(csp); 65 66 nsCOMPtr<nsISupports> integrityPolicy; 67 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(integrityPolicy)); 68 NS_ENSURE_SUCCESS(rv, rv); 69 mIntegrityPolicy = do_QueryInterface(integrityPolicy); 70 return NS_OK; 71 } 72 73 NS_IMETHODIMP 74 PolicyContainer::Write(nsIObjectOutputStream* aStream) { 75 aStream->Write32(kPolicyContainerSerializationVersion); 76 77 nsresult rv = NS_WriteOptionalCompoundObject( 78 aStream, mCSP, NS_GET_IID(nsIContentSecurityPolicy), true); 79 NS_ENSURE_SUCCESS(rv, rv); 80 81 rv = NS_WriteOptionalCompoundObject(aStream, mIntegrityPolicy, 82 NS_GET_IID(nsIIntegrityPolicy), true); 83 NS_ENSURE_SUCCESS(rv, rv); 84 85 return NS_OK; 86 } 87 88 void PolicyContainer::ToArgs(const PolicyContainer* aPolicy, 89 mozilla::ipc::PolicyContainerArgs& aArgs) { 90 if (!aPolicy) { 91 return; 92 } 93 94 if (aPolicy->mCSP) { 95 mozilla::ipc::CSPInfo cspInfo; 96 mozilla::ipc::CSPToCSPInfo(aPolicy->mCSP, &cspInfo); 97 aArgs.csp() = Some(cspInfo); 98 } 99 100 if (aPolicy->mIntegrityPolicy) { 101 mozilla::ipc::IntegrityPolicyArgs integrityPolicyArgs; 102 IntegrityPolicy::ToArgs(IntegrityPolicy::Cast(aPolicy->mIntegrityPolicy), 103 integrityPolicyArgs); 104 aArgs.integrityPolicy() = Some(integrityPolicyArgs); 105 } 106 } 107 108 void PolicyContainer::FromArgs(const mozilla::ipc::PolicyContainerArgs& aArgs, 109 mozilla::dom::Document* aRequestingDocument, 110 PolicyContainer** aPolicy) { 111 RefPtr<PolicyContainer> policy = new PolicyContainer(); 112 113 if (aArgs.csp().isSome()) { 114 nsCOMPtr<nsIContentSecurityPolicy> csp = 115 mozilla::ipc::CSPInfoToCSP(*aArgs.csp(), aRequestingDocument); 116 policy->SetCSP(nsCSPContext::Cast(csp)); 117 } 118 119 if (aArgs.integrityPolicy().isSome()) { 120 RefPtr<dom::IntegrityPolicy> integrityPolicy = new dom::IntegrityPolicy(); 121 IntegrityPolicy::FromArgs(*aArgs.integrityPolicy(), 122 getter_AddRefs(integrityPolicy)); 123 policy->SetIntegrityPolicy(integrityPolicy); 124 } 125 126 policy.forget(aPolicy); 127 } 128 129 void PolicyContainer::InitFromOther(PolicyContainer* aOther) { 130 if (!aOther) { 131 return; 132 } 133 134 if (aOther->mCSP) { 135 RefPtr<nsCSPContext> csp = new nsCSPContext(); 136 csp = new nsCSPContext(); 137 csp->InitFromOther(nsCSPContext::Cast(aOther->mCSP)); 138 mCSP = csp; 139 } 140 141 if (aOther->mIntegrityPolicy) { 142 RefPtr<dom::IntegrityPolicy> integrityPolicy = new dom::IntegrityPolicy(); 143 integrityPolicy->InitFromOther( 144 IntegrityPolicy::Cast(aOther->mIntegrityPolicy)); 145 mIntegrityPolicy = integrityPolicy; 146 } 147 } 148 149 NS_IMETHODIMP PolicyContainer::InitFromCSP(nsIContentSecurityPolicy* aCSP) { 150 SetCSP(aCSP); 151 152 return NS_OK; 153 } 154 155 bool PolicyContainer::Equals(const PolicyContainer* aContainer, 156 const PolicyContainer* aOtherContainer) { 157 // Do a quick pointer check first, also checks if both are null. 158 if (aContainer == aOtherContainer) { 159 return true; 160 } 161 162 // We checked if they were null above, so make sure one of them is not null. 163 if (!aContainer || !aOtherContainer) { 164 return false; 165 } 166 167 if (!nsCSPContext::Equals(aContainer->mCSP, aOtherContainer->mCSP)) { 168 return false; 169 } 170 171 if (!IntegrityPolicy::Equals( 172 IntegrityPolicy::Cast(aContainer->mIntegrityPolicy), 173 IntegrityPolicy::Cast(aOtherContainer->mIntegrityPolicy))) { 174 return false; 175 } 176 177 return true; 178 } 179 180 // == CSP == 181 void PolicyContainer::SetCSP(nsIContentSecurityPolicy* aPolicy) { 182 mCSP = aPolicy; 183 } 184 185 nsIContentSecurityPolicy* PolicyContainer::GetCSP() const { return mCSP; } 186 187 nsIContentSecurityPolicy* PolicyContainer::GetCSP( 188 const nsIPolicyContainer* aPolicyContainer) { 189 if (!aPolicyContainer) { 190 return nullptr; 191 } 192 return PolicyContainer::Cast(aPolicyContainer)->GetCSP(); 193 } 194 195 // == Integrity Policy == 196 void PolicyContainer::SetIntegrityPolicy(nsIIntegrityPolicy* aPolicy) { 197 mIntegrityPolicy = aPolicy; 198 } 199 200 nsIIntegrityPolicy* PolicyContainer::GetIntegrityPolicy() const { 201 return mIntegrityPolicy; 202 } 203 204 nsIIntegrityPolicy* PolicyContainer::GetIntegrityPolicy( 205 const nsIPolicyContainer* aPolicyContainer) { 206 if (!aPolicyContainer) { 207 return nullptr; 208 } 209 return PolicyContainer::Cast(aPolicyContainer)->GetIntegrityPolicy(); 210 } 211 212 NS_IMETHODIMP PolicyContainer::GetCsp(nsIContentSecurityPolicy** aCsp) { 213 nsCOMPtr<nsIContentSecurityPolicy> csp = mCSP; 214 csp.forget(aCsp); 215 return NS_OK; 216 } 217 218 NS_IMPL_CLASSINFO(PolicyContainer, nullptr, 0, NS_IPOLICYCONTAINER_IID) 219 NS_IMPL_ISUPPORTS_CI(PolicyContainer, nsIPolicyContainer, nsISerializable)