зеркало из https://github.com/mozilla/pjs.git
Bug 734891 - part 2: Adding ExpandedPrincipal support
This commit is contained in:
Родитель
f6671a8565
Коммит
277f347d94
|
@ -10,6 +10,8 @@
|
|||
%{C++
|
||||
struct JSContext;
|
||||
struct JSPrincipals;
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
%}
|
||||
|
||||
interface nsIURI;
|
||||
|
@ -17,6 +19,7 @@ interface nsIContentSecurityPolicy;
|
|||
|
||||
[ptr] native JSContext(JSContext);
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||
|
||||
[scriptable, uuid(42ba6a38-d619-49ab-8248-3d247e959d5e)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
|
@ -210,3 +213,25 @@ interface nsIPrincipal : nsISerializable
|
|||
*/
|
||||
[noscript] attribute nsIContentSecurityPolicy csp;
|
||||
};
|
||||
|
||||
/**
|
||||
* If nsSystemPrincipal is too risky to use, but we want a principal to access
|
||||
* more than one origin, nsExpandedPrincipals letting us define an array of
|
||||
* principals it subsumes. So script with an nsExpandedPrincipals will gain
|
||||
* same origin access when at least one of its principals it contains gained
|
||||
* sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system
|
||||
* principal, and by another nsExpandedPrincipal that has all its principals.
|
||||
* It is added for jetpack content-scripts to let them interact with the
|
||||
* content and a well defined set of other domains, without the risk of
|
||||
* leaking out a system principal to the content. See: Bug 734891
|
||||
*/
|
||||
[uuid(f3e177Df-6a5e-489f-80a7-2dd1481471d8)]
|
||||
interface nsIExpandedPrincipal : nsISupports
|
||||
{
|
||||
/**
|
||||
* An array of principals that the expanded principal subsumes.
|
||||
* Note: this list is not reference counted, it is shared, so
|
||||
* should not be changed and should only be used ephemerally.
|
||||
*/
|
||||
[notxpcom] readonly attribute PrincipalArray whiteList;
|
||||
};
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class nsIObjectInputStream;
|
||||
class nsIObjectOutputStream;
|
||||
class DomainPolicy;
|
||||
|
||||
class nsBasePrincipal : public nsJSPrincipals
|
||||
{
|
||||
|
@ -160,6 +161,37 @@ public:
|
|||
bool mInitialized;
|
||||
};
|
||||
|
||||
class nsExpandedPrincipal : public nsIExpandedPrincipal, public nsBasePrincipal
|
||||
{
|
||||
public:
|
||||
nsExpandedPrincipal(nsTArray< nsCOMPtr<nsIPrincipal> > &aWhiteList);
|
||||
|
||||
protected:
|
||||
virtual ~nsExpandedPrincipal();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIEXPANDEDPRINCIPAL
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
|
||||
NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
|
||||
NS_IMETHOD GetHashValue(PRUint32* aHashValue);
|
||||
NS_IMETHOD GetURI(nsIURI** aURI);
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain);
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain);
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
|
||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
#endif
|
||||
|
||||
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsTArray< nsCOMPtr<nsIPrincipal> > mPrincipals;
|
||||
};
|
||||
|
||||
#define NS_PRINCIPAL_CLASSNAME "principal"
|
||||
#define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1"
|
||||
|
@ -167,5 +199,10 @@ public:
|
|||
{ 0x36102b6b, 0x7b62, 0x451a, \
|
||||
{ 0xa1, 0xc8, 0xa0, 0xd4, 0x56, 0xc9, 0x2d, 0xc5 }}
|
||||
|
||||
#define NS_EXPANDEDPRINCIPAL_CLASSNAME "expandedprincipal"
|
||||
#define NS_EXPANDEDPRINCIPAL_CONTRACTID "@mozilla.org/expandedprincipal;1"
|
||||
#define NS_EXPANDEDPRINCIPAL_CID \
|
||||
{ 0xb33a3807, 0xb76c, 0x44e5, \
|
||||
{ 0xb9, 0x9d, 0x95, 0x7e, 0xe9, 0xba, 0x6e, 0x39 }}
|
||||
|
||||
#endif // nsPrincipal_h__
|
||||
|
|
|
@ -1202,3 +1202,206 @@ nsPrincipal::Write(nsIObjectOutputStream* aStream)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
|
||||
|
||||
NS_IMPL_CLASSINFO(nsExpandedPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
|
||||
NS_EXPANDEDPRINCIPAL_CID)
|
||||
NS_IMPL_QUERY_INTERFACE2_CI(nsExpandedPrincipal,
|
||||
nsIPrincipal,
|
||||
nsIExpandedPrincipal)
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsExpandedPrincipal,
|
||||
nsIPrincipal,
|
||||
nsIExpandedPrincipal)
|
||||
NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal);
|
||||
NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal);
|
||||
|
||||
nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWhiteList)
|
||||
{
|
||||
mPrincipals.AppendElements(aWhiteList);
|
||||
}
|
||||
|
||||
nsExpandedPrincipal::~nsExpandedPrincipal()
|
||||
{ }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetDomain(nsIURI** aDomain)
|
||||
{
|
||||
*aDomain = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetOrigin(char** aOrigin)
|
||||
{
|
||||
*aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC));
|
||||
return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOther,
|
||||
bool* aResult);
|
||||
#define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN))
|
||||
|
||||
// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsIgnoringDomain
|
||||
// shares the same logic. The difference only that Equals requires 'this'
|
||||
// and 'aOther' to Subsume each other while EqualsIgnoringDomain requires
|
||||
// bidirectional SubsumesIgnoringDomain.
|
||||
static nsresult
|
||||
Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
|
||||
bool* aResult)
|
||||
{
|
||||
// If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesIgnoringDomain
|
||||
// each other, then they are Equal.
|
||||
*aResult = false;
|
||||
// Calling the corresponding subsume function on this (aFn).
|
||||
nsresult rv = CALL_MEMBER_FUNCTION(aThis, aFn)(aOther, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!*aResult)
|
||||
return NS_OK;
|
||||
|
||||
// Calling the corresponding subsume function on aOther (aFn).
|
||||
rv = CALL_MEMBER_FUNCTION(aOther, aFn)(aThis, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult)
|
||||
{
|
||||
return ::Equals(this, &nsIPrincipal::Subsumes, aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::EqualsIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
|
||||
{
|
||||
return ::Equals(this, &nsIPrincipal::SubsumesIgnoringDomain, aOther, aResult);
|
||||
}
|
||||
|
||||
// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesIgnoringDomain
|
||||
// shares the same logic. The difference only that Subsumes calls are replaced
|
||||
//with SubsumesIgnoringDomain calls in the second case.
|
||||
static nsresult
|
||||
Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
|
||||
bool* aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
|
||||
if (expanded) {
|
||||
// If aOther is an ExpandedPrincipal too, check if all of its
|
||||
// principals are subsumed.
|
||||
nsTArray< nsCOMPtr<nsIPrincipal> >* otherList;
|
||||
expanded->GetWhiteList(&otherList);
|
||||
for (uint32_t i = 0; i < otherList->Length(); ++i){
|
||||
rv = CALL_MEMBER_FUNCTION(aThis, aFn)((*otherList)[i], aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!*aResult) {
|
||||
// If we don't subsume at least one principal of aOther, return false.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For a regular aOther, one of our principals must subsume it.
|
||||
nsTArray< nsCOMPtr<nsIPrincipal> >* list;
|
||||
aThis->GetWhiteList(&list);
|
||||
for (uint32_t i = 0; i < list->Length(); ++i){
|
||||
rv = CALL_MEMBER_FUNCTION((*list)[i], aFn)(aOther, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (*aResult) {
|
||||
// If one of our principal subsumes it, return true.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#undef CALL_MEMBER_FUNCTION
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult)
|
||||
{
|
||||
return ::Subsumes(this, &nsIPrincipal::Subsumes, aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::SubsumesIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
|
||||
{
|
||||
return ::Subsumes(this, &nsIPrincipal::SubsumesIgnoringDomain, aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
{
|
||||
nsresult rv;
|
||||
for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
|
||||
rv = mPrincipals[i]->CheckMayLoad(uri, aReport);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetHashValue(PRUint32* result)
|
||||
{
|
||||
MOZ_NOT_REACHED("extended principal should never be used as key in a hash map");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetURI(nsIURI** aURI)
|
||||
{
|
||||
*aURI = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
|
||||
{
|
||||
*aWhiteList = &mPrincipals;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
|
||||
{
|
||||
if (mCert) {
|
||||
aStr.Assign(mCert->fingerprint);
|
||||
} else {
|
||||
// Is that a good idea to list it's principals?
|
||||
aStr.Assign(EXPANDED_PRINCIPAL_SPEC);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void nsExpandedPrincipal::dumpImpl()
|
||||
{
|
||||
fprintf(stderr, "nsExpandedPrincipal (%p)\n", this);
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Methods implementing nsISerializable //
|
||||
//////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -1344,7 +1344,22 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
nsCOMPtr<nsIURI> sourceURI;
|
||||
aPrincipal->GetURI(getter_AddRefs(sourceURI));
|
||||
if (!sourceURI) {
|
||||
NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
|
||||
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal);
|
||||
if (expanded) {
|
||||
nsTArray< nsCOMPtr<nsIPrincipal> > *whiteList;
|
||||
expanded->GetWhiteList(&whiteList);
|
||||
for (uint32_t i = 0; i < whiteList->Length(); ++i) {
|
||||
nsresult rv = CheckLoadURIWithPrincipal((*whiteList)[i],
|
||||
aTargetURI,
|
||||
aFlags);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Allow access if it succeeded with one of the white listed principals
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ERROR("Non-system principals or expanded principal passed to CheckLoadURIWithPrincipal "
|
||||
"must have a URI!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче