Bug 904298 - Implement mozilla::{AssertAppPrincipal,CheckPermission}. r=sicking

This commit is contained in:
Reuben Morais 2013-11-05 08:14:46 -02:00
parent bd20efcb13
commit 4d3f928a88
2 changed files with 146 additions and 0 deletions

View File

@ -6,15 +6,27 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AppProcessChecker.h"
#include "nsIPermissionManager.h"
#ifdef MOZ_CHILD_PERMISSIONS
#include "ContentParent.h"
#include "mozIApplication.h"
#include "mozilla/hal_sandbox/PHalParent.h"
#include "nsIAppsService.h"
#include "nsIPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "TabParent.h"
#include <algorithm>
using namespace mozilla::dom;
using namespace mozilla::hal_sandbox;
using namespace mozilla::services;
#else
class PContentParent;
class nsIPrincipal;
#endif
namespace mozilla {
@ -126,6 +138,106 @@ AssertAppProcess(PHalParent* aActor,
return AssertAppProcess(aActor->Manager(), aType, aCapability);
}
bool
AssertAppPrincipal(PContentParent* aActor,
nsIPrincipal* aPrincipal)
{
if (!aPrincipal) {
NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard();
return false;
}
uint32_t principalAppId = aPrincipal->GetAppId();
bool inBrowserElement = aPrincipal->GetIsInBrowserElement();
// Check if the permission's appId matches a child we manage.
const InfallibleTArray<PBrowserParent*>& browsers =
aActor->ManagedPBrowserParent();
for (uint32_t i = 0; i < browsers.Length(); ++i) {
TabParent* tab = static_cast<TabParent*>(browsers[i]);
if (tab->OwnOrContainingAppId() == principalAppId) {
// If the child only runs inBrowserElement content and the principal claims
// it's not in a browser element, it's lying.
if (!tab->IsBrowserElement() || inBrowserElement) {
return true;
}
break;
}
}
NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard();
return false;
}
already_AddRefed<nsIPrincipal>
GetAppPrincipal(uint32_t aAppId)
{
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
nsString manifestURL;
nsresult rv = appsService->GetManifestURLByLocalId(aAppId, manifestURL);
NS_ENSURE_SUCCESS(rv, nullptr);
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), manifestURL);
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
nsCOMPtr<nsIPrincipal> appPrincipal;
rv = secMan->GetAppCodebasePrincipal(uri, aAppId, false,
getter_AddRefs(appPrincipal));
NS_ENSURE_SUCCESS(rv, nullptr);
return appPrincipal.forget();
}
uint32_t
CheckPermission(PContentParent* aActor,
nsIPrincipal* aPrincipal,
const char* aPermission)
{
if (!AssertAppPrincipal(aActor, aPrincipal)) {
return nsIPermissionManager::DENY_ACTION;
}
nsCOMPtr<nsIPermissionManager> pm =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
NS_ENSURE_TRUE(pm, nsIPermissionManager::DENY_ACTION);
// Make sure that `aPermission' is an app permission before checking the origin.
nsCOMPtr<nsIPrincipal> appPrincipal = GetAppPrincipal(aPrincipal->GetAppId());
uint32_t appPerm = nsIPermissionManager::UNKNOWN_ACTION;
nsresult rv = pm->TestExactPermissionFromPrincipal(appPrincipal, aPermission, &appPerm);
NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
if (appPerm == nsIPermissionManager::UNKNOWN_ACTION ||
appPerm == nsIPermissionManager::DENY_ACTION) {
return appPerm;
}
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
rv = pm->TestExactPermissionFromPrincipal(aPrincipal, aPermission, &permission);
NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
if (permission == nsIPermissionManager::UNKNOWN_ACTION ||
permission == nsIPermissionManager::DENY_ACTION) {
return permission;
}
if (appPerm == nsIPermissionManager::PROMPT_ACTION ||
permission == nsIPermissionManager::PROMPT_ACTION) {
return nsIPermissionManager::PROMPT_ACTION;
}
if (appPerm == nsIPermissionManager::ALLOW_ACTION ||
permission == nsIPermissionManager::ALLOW_ACTION) {
return nsIPermissionManager::ALLOW_ACTION;
}
NS_RUNTIMEABORT("Invalid permission value");
return nsIPermissionManager::DENY_ACTION;
}
#else
bool
@ -167,6 +279,21 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
return true;
}
bool
AssertAppPrincipal(PContentParent* aActor,
nsIPrincipal* aPrincipal)
{
return true;
}
uint32_t
CheckPermission(PContentParent*,
nsIPrincipal*,
const char*)
{
return nsIPermissionManager::ALLOW_ACTION;
}
#endif
} // namespace mozilla

View File

@ -8,6 +8,10 @@
#ifndef mozilla_AppProcessChecker_h
#define mozilla_AppProcessChecker_h
#include <stdint.h>
class nsIPrincipal;
namespace mozilla {
namespace dom {
@ -66,6 +70,21 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
// return AssertAppProcess(aActor->Manager(), aType);
// }
bool
AssertAppPrincipal(mozilla::dom::PContentParent* aParent,
nsIPrincipal* aPrincipal);
/**
* Check if the specified principal is valid, and return the saved permission
* value for permission `aPermission' on that principal.
* See nsIPermissionManager.idl for possible return values.
*
* nsIPermissionManager::UNKNOWN_ACTION is retuned if the principal is invalid.
*/
uint32_t
CheckPermission(mozilla::dom::PContentParent* aParent,
nsIPrincipal* aPrincipal, const char* aPermission);
/**
* Inline function for asserting the process's permission.
*/