ClientValidation.cpp (6530B)
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 "ClientValidation.h" 8 9 #include "mozilla/StaticPrefs_security.h" 10 #include "mozilla/ipc/PBackgroundSharedTypes.h" 11 #include "mozilla/net/MozURL.h" 12 13 namespace mozilla::dom { 14 15 using mozilla::ipc::ContentPrincipalInfo; 16 using mozilla::ipc::PrincipalInfo; 17 using mozilla::net::MozURL; 18 19 bool ClientIsValidPrincipalInfo(const PrincipalInfo& aPrincipalInfo) { 20 // Ideally we would verify that the source process has permission to 21 // create a window or worker with the given principal, but we don't 22 // currently have any such restriction in place. Instead, at least 23 // verify the PrincipalInfo is an expected type and has a parsable 24 // origin/spec. 25 switch (aPrincipalInfo.type()) { 26 // Any system and null principal is acceptable. 27 case PrincipalInfo::TSystemPrincipalInfo: 28 case PrincipalInfo::TNullPrincipalInfo: { 29 return true; 30 } 31 32 // Validate content principals to ensure that the origin and spec are sane. 33 case PrincipalInfo::TContentPrincipalInfo: { 34 const ContentPrincipalInfo& content = 35 aPrincipalInfo.get_ContentPrincipalInfo(); 36 37 // Verify the principal spec parses. 38 RefPtr<MozURL> specURL; 39 nsresult rv = MozURL::Init(getter_AddRefs(specURL), content.spec()); 40 NS_ENSURE_SUCCESS(rv, false); 41 42 // Verify the principal originNoSuffix parses. 43 RefPtr<MozURL> originURL; 44 rv = MozURL::Init(getter_AddRefs(originURL), content.originNoSuffix()); 45 NS_ENSURE_SUCCESS(rv, false); 46 47 nsAutoCString originOrigin; 48 originURL->Origin(originOrigin); 49 50 nsAutoCString specOrigin; 51 specURL->Origin(specOrigin); 52 53 // Linkable about URIs end up with a nested inner scheme of moz-safe-about 54 // which will have been captured in the originNoSuffix but the spec and 55 // its resulting specOrigin will not have this transformed scheme, so 56 // ignore the "moz-safe-" prefix when the originURL has that transformed 57 // scheme. 58 if (originURL->Scheme().Equals("moz-safe-about")) { 59 return specOrigin == originOrigin || 60 specOrigin == Substring(originOrigin, 9 /*moz-safe-*/, 61 specOrigin.Length()); 62 } 63 64 // For now require Clients to have a principal where both its 65 // originNoSuffix and spec have the same origin. This will 66 // exclude a variety of unusual combinations within the browser 67 // but its adequate for the features need to support right now. 68 // If necessary we could expand this function to handle more 69 // cases in the future. 70 71 return specOrigin == originOrigin; 72 } 73 default: { 74 break; 75 } 76 } 77 78 // Windows and workers should not have expanded URLs, etc. 79 return false; 80 } 81 82 bool ClientIsValidCreationURL(const PrincipalInfo& aPrincipalInfo, 83 const nsACString& aURL) { 84 RefPtr<MozURL> url; 85 nsresult rv = MozURL::Init(getter_AddRefs(url), aURL); 86 NS_ENSURE_SUCCESS(rv, false); 87 88 switch (aPrincipalInfo.type()) { 89 case PrincipalInfo::TContentPrincipalInfo: { 90 // Any origin can create an about:blank or about:srcdoc Client. 91 if (aURL.LowerCaseEqualsLiteral("about:blank") || 92 aURL.LowerCaseEqualsLiteral("about:srcdoc")) { 93 return true; 94 } 95 96 const ContentPrincipalInfo& content = 97 aPrincipalInfo.get_ContentPrincipalInfo(); 98 99 // Parse the principal origin URL as well. This ensures any MozURL 100 // parser issues effect both URLs equally. 101 RefPtr<MozURL> principalURL; 102 rv = MozURL::Init(getter_AddRefs(principalURL), content.originNoSuffix()); 103 NS_ENSURE_SUCCESS(rv, false); 104 105 nsAutoCString origin; 106 url->Origin(origin); 107 108 nsAutoCString principalOrigin; 109 principalURL->Origin(principalOrigin); 110 111 // The vast majority of sites should simply result in the same principal 112 // and URL origin. 113 if (principalOrigin == origin) { 114 return true; 115 } 116 117 nsDependentCSubstring scheme = url->Scheme(); 118 119 // Generally any origin can also open javascript: windows and workers. 120 if (scheme.LowerCaseEqualsLiteral("javascript")) { 121 return true; 122 } 123 124 // Linkable about URIs end up with a nested inner scheme of moz-safe-about 125 // but the url and its resulting origin will not have this transformed 126 // scheme, so ignore the "moz-safe-" prefix when the principal has that 127 // transformed scheme. 128 if (principalURL->Scheme().Equals("moz-safe-about")) { 129 return origin == principalOrigin || 130 origin == 131 Substring(principalOrigin, 9 /*moz-safe-*/, origin.Length()); 132 } 133 134 // Otherwise don't support this URL type in the clients sub-system for 135 // now. This will exclude a variety of internal browser clients, but 136 // currently we don't need to support those. This function can be 137 // expanded to handle more cases as necessary. 138 return false; 139 } 140 case PrincipalInfo::TSystemPrincipalInfo: { 141 nsDependentCSubstring scheme = url->Scheme(); 142 143 // While many types of documents can be created with a system principal, 144 // there are only a few that can reasonably become windows. We attempt 145 // to validate the list of known cases here with a simple scheme check. 146 return scheme.LowerCaseEqualsLiteral("about") || 147 scheme.LowerCaseEqualsLiteral("chrome") || 148 scheme.LowerCaseEqualsLiteral("resource") || 149 scheme.LowerCaseEqualsLiteral("blob") || 150 scheme.LowerCaseEqualsLiteral("javascript") || 151 scheme.LowerCaseEqualsLiteral("view-source"); 152 } 153 case PrincipalInfo::TNullPrincipalInfo: { 154 // A wide variety of clients can have a null principal. For example, 155 // sandboxed iframes can have a normal content URL. For now allow 156 // any parsable URL for null principals. This is relatively safe since 157 // null principals have unique origins and won't most ClientManagerService 158 // queries anyway. 159 return true; 160 } 161 default: { 162 break; 163 } 164 } 165 166 // Clients (windows/workers) should never have an expanded principal type. 167 return false; 168 } 169 170 } // namespace mozilla::dom