dom/ipc/AppProcessChecker.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=8 et :
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 6 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "AppProcessChecker.h"
michael@0 9 #include "nsIPermissionManager.h"
michael@0 10 #ifdef MOZ_CHILD_PERMISSIONS
michael@0 11 #include "ContentParent.h"
michael@0 12 #include "mozIApplication.h"
michael@0 13 #include "mozilla/hal_sandbox/PHalParent.h"
michael@0 14 #include "nsIAppsService.h"
michael@0 15 #include "nsIPrincipal.h"
michael@0 16 #include "nsIScriptSecurityManager.h"
michael@0 17 #include "nsPrintfCString.h"
michael@0 18 #include "nsIURI.h"
michael@0 19 #include "nsNetUtil.h"
michael@0 20 #include "nsServiceManagerUtils.h"
michael@0 21 #include "TabParent.h"
michael@0 22
michael@0 23 #include <algorithm>
michael@0 24
michael@0 25 using namespace mozilla::dom;
michael@0 26 using namespace mozilla::hal_sandbox;
michael@0 27 using namespace mozilla::services;
michael@0 28 #else
michael@0 29 namespace mozilla {
michael@0 30 namespace dom {
michael@0 31 class PContentParent;
michael@0 32 }
michael@0 33 }
michael@0 34
michael@0 35 class nsIPrincipal;
michael@0 36 #endif
michael@0 37
michael@0 38 namespace mozilla {
michael@0 39
michael@0 40 #ifdef MOZ_CHILD_PERMISSIONS
michael@0 41
michael@0 42 bool
michael@0 43 AssertAppProcess(PBrowserParent* aActor,
michael@0 44 AssertAppProcessType aType,
michael@0 45 const char* aCapability)
michael@0 46 {
michael@0 47 if (!aActor) {
michael@0 48 NS_WARNING("Testing process capability for null actor");
michael@0 49 return false;
michael@0 50 }
michael@0 51
michael@0 52 TabParent* tab = static_cast<TabParent*>(aActor);
michael@0 53 nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
michael@0 54 bool aValid = false;
michael@0 55
michael@0 56 // isBrowser frames inherit their app descriptor to identify their
michael@0 57 // data storage, but they don't inherit the capability associated
michael@0 58 // with that descriptor.
michael@0 59 if (app && (aType == ASSERT_APP_HAS_PERMISSION || !tab->IsBrowserElement())) {
michael@0 60 switch (aType) {
michael@0 61 case ASSERT_APP_HAS_PERMISSION:
michael@0 62 case ASSERT_APP_PROCESS_PERMISSION:
michael@0 63 if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) {
michael@0 64 aValid = false;
michael@0 65 }
michael@0 66 break;
michael@0 67 case ASSERT_APP_PROCESS_MANIFEST_URL: {
michael@0 68 nsAutoString manifestURL;
michael@0 69 if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) &&
michael@0 70 manifestURL.EqualsASCII(aCapability)) {
michael@0 71 aValid = true;
michael@0 72 }
michael@0 73 break;
michael@0 74 }
michael@0 75 default:
michael@0 76 break;
michael@0 77 }
michael@0 78 }
michael@0 79 return aValid;
michael@0 80 }
michael@0 81
michael@0 82 bool
michael@0 83 AssertAppStatus(PBrowserParent* aActor,
michael@0 84 unsigned short aStatus)
michael@0 85 {
michael@0 86 if (!aActor) {
michael@0 87 NS_WARNING("Testing process capability for null actor");
michael@0 88 return false;
michael@0 89 }
michael@0 90
michael@0 91 TabParent* tab = static_cast<TabParent*>(aActor);
michael@0 92 nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
michael@0 93
michael@0 94 bool valid = false;
michael@0 95
michael@0 96 if (app) {
michael@0 97 unsigned short appStatus = 0;
michael@0 98 if (NS_SUCCEEDED(app->GetAppStatus(&appStatus))) {
michael@0 99 valid = appStatus == aStatus;
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 return valid;
michael@0 104 }
michael@0 105
michael@0 106 bool
michael@0 107 AssertAppProcess(PContentParent* aActor,
michael@0 108 AssertAppProcessType aType,
michael@0 109 const char* aCapability)
michael@0 110 {
michael@0 111 const InfallibleTArray<PBrowserParent*>& browsers =
michael@0 112 aActor->ManagedPBrowserParent();
michael@0 113 for (uint32_t i = 0; i < browsers.Length(); ++i) {
michael@0 114 if (AssertAppProcess(browsers[i], aType, aCapability)) {
michael@0 115 return true;
michael@0 116 }
michael@0 117 }
michael@0 118
michael@0 119 NS_ERROR(
michael@0 120 nsPrintfCString(
michael@0 121 "Security problem: Content process does not have `%s'. It will be killed.\n",
michael@0 122 aCapability).get());
michael@0 123
michael@0 124 static_cast<ContentParent*>(aActor)->KillHard();
michael@0 125
michael@0 126 return false;
michael@0 127 }
michael@0 128
michael@0 129 bool
michael@0 130 AssertAppStatus(PContentParent* aActor,
michael@0 131 unsigned short aStatus)
michael@0 132 {
michael@0 133 const InfallibleTArray<PBrowserParent*>& browsers =
michael@0 134 aActor->ManagedPBrowserParent();
michael@0 135 for (uint32_t i = 0; i < browsers.Length(); ++i) {
michael@0 136 if (AssertAppStatus(browsers[i], aStatus)) {
michael@0 137 return true;
michael@0 138 }
michael@0 139 }
michael@0 140
michael@0 141 NS_ERROR(
michael@0 142 nsPrintfCString(
michael@0 143 "Security problem: Content process does not have `%d' status. It will be killed.",
michael@0 144 aStatus).get());
michael@0 145
michael@0 146 static_cast<ContentParent*>(aActor)->KillHard();
michael@0 147
michael@0 148 return false;
michael@0 149 }
michael@0 150
michael@0 151 bool
michael@0 152 AssertAppProcess(PHalParent* aActor,
michael@0 153 AssertAppProcessType aType,
michael@0 154 const char* aCapability)
michael@0 155 {
michael@0 156 return AssertAppProcess(aActor->Manager(), aType, aCapability);
michael@0 157 }
michael@0 158
michael@0 159 bool
michael@0 160 AssertAppPrincipal(PContentParent* aActor,
michael@0 161 nsIPrincipal* aPrincipal)
michael@0 162 {
michael@0 163 if (!aPrincipal) {
michael@0 164 NS_WARNING("Principal is invalid, killing app process");
michael@0 165 static_cast<ContentParent*>(aActor)->KillHard();
michael@0 166 return false;
michael@0 167 }
michael@0 168
michael@0 169 uint32_t principalAppId = aPrincipal->GetAppId();
michael@0 170 bool inBrowserElement = aPrincipal->GetIsInBrowserElement();
michael@0 171
michael@0 172 // Check if the permission's appId matches a child we manage.
michael@0 173 const InfallibleTArray<PBrowserParent*>& browsers =
michael@0 174 aActor->ManagedPBrowserParent();
michael@0 175 for (uint32_t i = 0; i < browsers.Length(); ++i) {
michael@0 176 TabParent* tab = static_cast<TabParent*>(browsers[i]);
michael@0 177 if (tab->OwnOrContainingAppId() == principalAppId) {
michael@0 178 // If the child only runs inBrowserElement content and the principal claims
michael@0 179 // it's not in a browser element, it's lying.
michael@0 180 if (!tab->IsBrowserElement() || inBrowserElement) {
michael@0 181 return true;
michael@0 182 }
michael@0 183 break;
michael@0 184 }
michael@0 185 }
michael@0 186
michael@0 187 NS_WARNING("Principal is invalid, killing app process");
michael@0 188 static_cast<ContentParent*>(aActor)->KillHard();
michael@0 189 return false;
michael@0 190 }
michael@0 191
michael@0 192 already_AddRefed<nsIPrincipal>
michael@0 193 GetAppPrincipal(uint32_t aAppId)
michael@0 194 {
michael@0 195 nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
michael@0 196
michael@0 197 nsCOMPtr<mozIApplication> app;
michael@0 198 nsresult rv = appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
michael@0 199 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 200
michael@0 201 nsString origin;
michael@0 202 rv = app->GetOrigin(origin);
michael@0 203 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 204
michael@0 205 nsCOMPtr<nsIURI> uri;
michael@0 206 NS_NewURI(getter_AddRefs(uri), origin);
michael@0 207
michael@0 208 nsCOMPtr<nsIScriptSecurityManager> secMan =
michael@0 209 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
michael@0 210
michael@0 211 nsCOMPtr<nsIPrincipal> appPrincipal;
michael@0 212 rv = secMan->GetAppCodebasePrincipal(uri, aAppId, false,
michael@0 213 getter_AddRefs(appPrincipal));
michael@0 214 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 215 return appPrincipal.forget();
michael@0 216 }
michael@0 217
michael@0 218 uint32_t
michael@0 219 CheckPermission(PContentParent* aActor,
michael@0 220 nsIPrincipal* aPrincipal,
michael@0 221 const char* aPermission)
michael@0 222 {
michael@0 223 if (!AssertAppPrincipal(aActor, aPrincipal)) {
michael@0 224 return nsIPermissionManager::DENY_ACTION;
michael@0 225 }
michael@0 226
michael@0 227 nsCOMPtr<nsIPermissionManager> pm =
michael@0 228 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
michael@0 229 NS_ENSURE_TRUE(pm, nsIPermissionManager::DENY_ACTION);
michael@0 230
michael@0 231 // Make sure that `aPermission' is an app permission before checking the origin.
michael@0 232 nsCOMPtr<nsIPrincipal> appPrincipal = GetAppPrincipal(aPrincipal->GetAppId());
michael@0 233 uint32_t appPerm = nsIPermissionManager::UNKNOWN_ACTION;
michael@0 234 nsresult rv = pm->TestExactPermissionFromPrincipal(appPrincipal, aPermission, &appPerm);
michael@0 235 NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
michael@0 236 // Setting to "deny" in the settings UI should deny everywhere.
michael@0 237 if (appPerm == nsIPermissionManager::UNKNOWN_ACTION ||
michael@0 238 appPerm == nsIPermissionManager::DENY_ACTION) {
michael@0 239 return appPerm;
michael@0 240 }
michael@0 241
michael@0 242 uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
michael@0 243 rv = pm->TestExactPermissionFromPrincipal(aPrincipal, aPermission, &permission);
michael@0 244 NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
michael@0 245 if (permission == nsIPermissionManager::UNKNOWN_ACTION ||
michael@0 246 permission == nsIPermissionManager::DENY_ACTION) {
michael@0 247 return permission;
michael@0 248 }
michael@0 249
michael@0 250 // For browser content (and if the app hasn't explicitly denied this),
michael@0 251 // consider the requesting origin, not the app.
michael@0 252 if (appPerm == nsIPermissionManager::PROMPT_ACTION &&
michael@0 253 aPrincipal->GetIsInBrowserElement()) {
michael@0 254 return permission;
michael@0 255 }
michael@0 256
michael@0 257 // Setting to "prompt" in the settings UI should prompt everywhere in
michael@0 258 // non-browser content.
michael@0 259 if (appPerm == nsIPermissionManager::PROMPT_ACTION ||
michael@0 260 permission == nsIPermissionManager::PROMPT_ACTION) {
michael@0 261 return nsIPermissionManager::PROMPT_ACTION;
michael@0 262 }
michael@0 263
michael@0 264 if (appPerm == nsIPermissionManager::ALLOW_ACTION ||
michael@0 265 permission == nsIPermissionManager::ALLOW_ACTION) {
michael@0 266 return nsIPermissionManager::ALLOW_ACTION;
michael@0 267 }
michael@0 268
michael@0 269 NS_RUNTIMEABORT("Invalid permission value");
michael@0 270 return nsIPermissionManager::DENY_ACTION;
michael@0 271 }
michael@0 272
michael@0 273 #else
michael@0 274
michael@0 275 bool
michael@0 276 AssertAppProcess(mozilla::dom::PBrowserParent* aActor,
michael@0 277 AssertAppProcessType aType,
michael@0 278 const char* aCapability)
michael@0 279 {
michael@0 280 return true;
michael@0 281 }
michael@0 282
michael@0 283 bool
michael@0 284 AssertAppStatus(mozilla::dom::PBrowserParent* aActor,
michael@0 285 unsigned short aStatus)
michael@0 286 {
michael@0 287 return true;
michael@0 288 }
michael@0 289
michael@0 290
michael@0 291 bool
michael@0 292 AssertAppProcess(mozilla::dom::PContentParent* aActor,
michael@0 293 AssertAppProcessType aType,
michael@0 294 const char* aCapability)
michael@0 295 {
michael@0 296 return true;
michael@0 297 }
michael@0 298
michael@0 299 bool
michael@0 300 AssertAppStatus(mozilla::dom::PContentParent* aActor,
michael@0 301 unsigned short aStatus)
michael@0 302 {
michael@0 303 return true;
michael@0 304 }
michael@0 305
michael@0 306 bool
michael@0 307 AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
michael@0 308 AssertAppProcessType aType,
michael@0 309 const char* aCapability)
michael@0 310 {
michael@0 311 return true;
michael@0 312 }
michael@0 313
michael@0 314 bool
michael@0 315 AssertAppPrincipal(mozilla::dom::PContentParent* aActor,
michael@0 316 nsIPrincipal* aPrincipal)
michael@0 317 {
michael@0 318 return true;
michael@0 319 }
michael@0 320
michael@0 321 uint32_t
michael@0 322 CheckPermission(mozilla::dom::PContentParent* aActor,
michael@0 323 nsIPrincipal* aPrincipal,
michael@0 324 const char* aPermission)
michael@0 325 {
michael@0 326 return nsIPermissionManager::ALLOW_ACTION;
michael@0 327 }
michael@0 328
michael@0 329 #endif
michael@0 330
michael@0 331 } // namespace mozilla

mercurial