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.

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

mercurial