|
|
|
|
@@ -33,10 +33,10 @@
|
|
|
|
|
#include "nsIURL.h"
|
|
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIXPCSecurityManagerIID, NS_IXPCSECURITYMANAGER_IID);
|
|
|
|
|
static NS_DEFINE_IID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
|
|
|
|
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
|
|
|
|
static NS_DEFINE_IID(kIScriptSecurityManagerIID, NS_ISCRIPTSECURITYMANAGER_IID);
|
|
|
|
|
static NS_DEFINE_IID(kICapsSecurityCallbacksIID, NS_ICAPSSECURITYCALLBACKS_IID);
|
|
|
|
|
static NS_DEFINE_IID(kURLCID, NS_STANDARDURL_CID);
|
|
|
|
|
static NS_DEFINE_CID(kURLCID, NS_STANDARDURL_CID);
|
|
|
|
|
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
|
|
|
|
|
static NS_DEFINE_IID(kIScriptGlobalObjectDataIID, NS_ISCRIPTGLOBALOBJECTDATA_IID);
|
|
|
|
|
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
|
|
|
|
@@ -57,7 +57,7 @@ static char * targetStrings[] = {
|
|
|
|
|
"AccountSetup",
|
|
|
|
|
/* See Target.java for more targets */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
extern "C" NS_DOM nsresult
|
|
|
|
|
NS_NewScriptSecurityManager(nsIScriptSecurityManager ** aInstancePtrResult)
|
|
|
|
|
{
|
|
|
|
|
@@ -68,7 +68,7 @@ NS_NewScriptSecurityManager(nsIScriptSecurityManager ** aInstancePtrResult)
|
|
|
|
|
if (NS_FAILED(ret)) NS_RELEASE(*aInstancePtrResult);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
nsJSSecurityManager::nsJSSecurityManager()
|
|
|
|
|
{
|
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
|
@@ -85,11 +85,6 @@ NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
|
|
|
{
|
|
|
|
|
if (nsnull == aInstancePtr) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
if (aIID.Equals(kIScriptSecurityManagerIID)) {
|
|
|
|
|
*aInstancePtr = (void*)(nsIScriptSecurityManager*)this;
|
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
if (aIID.Equals(kICapsSecurityCallbacksIID)) {
|
|
|
|
|
*aInstancePtr = (void*)(nsICapsSecurityCallbacks*)this;
|
|
|
|
|
@@ -132,10 +127,8 @@ static nsJSPrincipalsData unknownPrincipals = {
|
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
|
|
|
DestroyJSPrincipals(JSContext *aCx, JSPrincipals *aPrincipals)
|
|
|
|
|
{
|
|
|
|
|
if (aPrincipals != nsnull &&
|
|
|
|
|
aPrincipals != (JSPrincipals*)&unknownPrincipals) {
|
|
|
|
|
if (aPrincipals != nsnull && aPrincipals != (JSPrincipals*)&unknownPrincipals) {
|
|
|
|
|
nsJSPrincipalsData* data = (nsJSPrincipalsData*)aPrincipals;
|
|
|
|
|
|
|
|
|
|
if (aPrincipals->codebase) delete aPrincipals->codebase;
|
|
|
|
|
if (data->principalsArrayRef != nsnull) {
|
|
|
|
|
/* XXX: raman: Should we free up the principals that are in that array also? */
|
|
|
|
|
@@ -145,9 +138,7 @@ DestroyJSPrincipals(JSContext *aCx, JSPrincipals *aPrincipals)
|
|
|
|
|
if (data->name) delete data->name;
|
|
|
|
|
//data->untransformed
|
|
|
|
|
//data->transformed
|
|
|
|
|
if (data->codebaseBeforeSettingDomain) {
|
|
|
|
|
delete data->codebaseBeforeSettingDomain;
|
|
|
|
|
}
|
|
|
|
|
if (data->codebaseBeforeSettingDomain) delete data->codebaseBeforeSettingDomain;
|
|
|
|
|
if (data->zip)
|
|
|
|
|
//ns_zip_close(data->zip);
|
|
|
|
|
if (data->url) NS_RELEASE(data->url);
|
|
|
|
|
@@ -186,502 +177,6 @@ GlobalPrivilegesEnabled(JSContext *aCx, JSPrincipals *aPrincipals)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::NewJSPrincipals(nsIURI *aURL, nsString* aName, nsIPrincipal * * result)
|
|
|
|
|
{
|
|
|
|
|
nsJSPrincipalsData * pdata;
|
|
|
|
|
PRBool needUnlock = PR_FALSE;
|
|
|
|
|
#ifdef CERT_PRINS
|
|
|
|
|
void *zip = nsnull; //ns_zip_t
|
|
|
|
|
if (aURL) {
|
|
|
|
|
char *fn = nsnull;
|
|
|
|
|
if (NET_IsLocalFileURL(archive->address)) {
|
|
|
|
|
char* pathPart = ParseURL(archive->address, GET_PATH_PART);
|
|
|
|
|
fn = WH_FileName(pathPart, xpURL);
|
|
|
|
|
PR_Free(pathPart);
|
|
|
|
|
}
|
|
|
|
|
else if (archive->cache_file && NET_ChangeCacheFileLock(archive, TRUE)) {
|
|
|
|
|
fn = WH_FileName(archive->cache_file, xpCache);
|
|
|
|
|
needUnlock = PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
if (fn) {
|
|
|
|
|
#ifdef XP_MAC
|
|
|
|
|
/*
|
|
|
|
|
* Unfortunately, ns_zip_open wants a Unix-style name. Convert
|
|
|
|
|
* Mac path to a Unix-style path. This code is copied from
|
|
|
|
|
* appletStubs.c.
|
|
|
|
|
*/
|
|
|
|
|
OSErr ConvertMacPathToUnixPath(const char *macPath, char **unixPath);
|
|
|
|
|
char *unixPath = nsnull;
|
|
|
|
|
|
|
|
|
|
if (ConvertMacPathToUnixPath(fn, &unixPath) == 0) {
|
|
|
|
|
zip = ns_zip_open(unixPath);
|
|
|
|
|
}
|
|
|
|
|
PR_FREEIF(unixPath);
|
|
|
|
|
#else
|
|
|
|
|
zip = ns_zip_open(fn);
|
|
|
|
|
#endif
|
|
|
|
|
pdata->zip = zip;
|
|
|
|
|
PR_Free(fn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
//Allocate and fill the nsJSPrincipalsData struct
|
|
|
|
|
pdata = PR_NEWZAP(nsJSPrincipalsData);
|
|
|
|
|
if (pdata == nsnull) return NS_ERROR_FAILURE;
|
|
|
|
|
nsresult rv;
|
|
|
|
|
char * codebaseStr = NULL;
|
|
|
|
|
rv = this->GetOriginFromSourceURL(aURL,& codebaseStr);
|
|
|
|
|
if (rv != NS_OK) return rv;
|
|
|
|
|
if (!codebaseStr) {
|
|
|
|
|
PR_Free(pdata);
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
pdata->principals.codebase = PL_strdup(codebaseStr);
|
|
|
|
|
if (pdata->principals.codebase == nsnull) {
|
|
|
|
|
PR_Free(pdata);
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (aName) pdata->name = aName ? aName->ToNewCString() : nsnull;
|
|
|
|
|
pdata->principals.destroy = DestroyJSPrincipals;
|
|
|
|
|
pdata->principals.getPrincipalArray = GetPrincipalArray;
|
|
|
|
|
pdata->principals.globalPrivilegesEnabled = GlobalPrivilegesEnabled;
|
|
|
|
|
pdata->url = aURL;
|
|
|
|
|
NS_IF_ADDREF(aURL);
|
|
|
|
|
pdata->needUnlock = needUnlock;
|
|
|
|
|
NS_WITH_SERVICE(nsIPrincipalManager, prinMan,NS_PRINCIPALMANAGER_PROGID,&rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = prinMan->CreateCodebasePrincipal(codebaseStr, aURL, result);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::CheckScriptAccess(nsIScriptContext* aContext, void* aObj, const char* aProp, PRBool* aResult)
|
|
|
|
|
{
|
|
|
|
|
*aResult = PR_FALSE;
|
|
|
|
|
JSContext* cx = (JSContext*)aContext->GetNativeContext();
|
|
|
|
|
PRInt32 secLevel = CheckForPrivilege(cx, (char*)aProp, nsnull);
|
|
|
|
|
switch (secLevel) {
|
|
|
|
|
case SCRIPT_SECURITY_ALL_ACCESS:
|
|
|
|
|
*aResult = PR_TRUE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
case SCRIPT_SECURITY_SAME_DOMAIN_ACCESS:
|
|
|
|
|
return this->CheckPermissions(cx, (JSObject*)aObj, eJSTarget_Max, aResult);
|
|
|
|
|
default:
|
|
|
|
|
// Default is no access
|
|
|
|
|
*aResult = PR_FALSE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::GetSubjectOriginURL(JSContext *aCx, char * * aOrigin)
|
|
|
|
|
{
|
|
|
|
|
// Get origin from script of innermost interpreted frame.
|
|
|
|
|
JSPrincipals *principals;
|
|
|
|
|
JSStackFrame *fp;
|
|
|
|
|
JSScript *script;
|
|
|
|
|
#ifdef OJI
|
|
|
|
|
JSStackFrame *pFrameToStartLooking = *JVM_GetStartJSFrameFromParallelStack();
|
|
|
|
|
JSStackFrame *pFrameToEndLooking = JVM_GetEndJSFrameFromParallelStack(pFrameToStartLooking);
|
|
|
|
|
if (pFrameToStartLooking == nsnull) {
|
|
|
|
|
pFrameToStartLooking = JS_FrameIterator(aCx, &pFrameToStartLooking);
|
|
|
|
|
if (pFrameToStartLooking == nsnull) {
|
|
|
|
|
// There are no frames or scripts at this point.
|
|
|
|
|
pFrameToEndLooking = nsnull;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
JSStackFrame *pFrameToStartLooking = JS_FrameIterator(aCx, &fp);
|
|
|
|
|
JSStackFrame *pFrameToEndLooking = nsnull;
|
|
|
|
|
#endif
|
|
|
|
|
fp = pFrameToStartLooking;
|
|
|
|
|
while (fp != pFrameToEndLooking) {
|
|
|
|
|
script = JS_GetFrameScript(aCx, fp);
|
|
|
|
|
if (script) {
|
|
|
|
|
principals = JS_GetScriptPrincipals(aCx, script);
|
|
|
|
|
*aOrigin = principals ? (char *)principals->codebase : (char *)JS_GetScriptFilename(aCx, script);
|
|
|
|
|
return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
fp = JS_FrameIterator(aCx, &fp);
|
|
|
|
|
}
|
|
|
|
|
#ifdef OJI
|
|
|
|
|
principals = JVM_GetJavaPrincipalsFromStack(pFrameToStartLooking);
|
|
|
|
|
if (principals) {
|
|
|
|
|
*aOrigin = principals->codebase;
|
|
|
|
|
return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Not called from either JS or Java. We must be called
|
|
|
|
|
* from the interpreter. Get the origin from the decoder.
|
|
|
|
|
*/
|
|
|
|
|
return GetObjectOriginURL(aCx, JS_GetGlobalObject(aCx), aOrigin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::GetObjectOriginURL(JSContext *aCx, JSObject *aObj, char * * aOrigin)
|
|
|
|
|
{
|
|
|
|
|
nsresult rv;
|
|
|
|
|
JSObject *parent;
|
|
|
|
|
while (parent = JS_GetParent(aCx, aObj)) aObj = parent;
|
|
|
|
|
nsIPrincipal * prin;
|
|
|
|
|
if((rv = GetContainerPrincipals(aCx, aObj, & prin)) != NS_OK) return rv;
|
|
|
|
|
nsICodebasePrincipal * cbprin;
|
|
|
|
|
if((rv = prin->QueryInterface(nsICodebasePrincipal::GetIID(),(void * *)& cbprin)) != NS_OK) return rv;
|
|
|
|
|
cbprin->GetURLString(aOrigin);
|
|
|
|
|
return (* aOrigin) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::GetContainerPrincipals(JSContext *aCx, JSObject *container, nsIPrincipal * * result)
|
|
|
|
|
{
|
|
|
|
|
nsresult rv;
|
|
|
|
|
* result = nsnull;
|
|
|
|
|
// Need to check that the origin hasn't changed underneath us
|
|
|
|
|
char * originUrl = this->FindOriginURL(aCx, container);
|
|
|
|
|
if (!originUrl) return NS_ERROR_FAILURE;
|
|
|
|
|
nsISupports * tmp;
|
|
|
|
|
nsIScriptGlobalObjectData * globalData;
|
|
|
|
|
tmp = (nsISupports *)JS_GetPrivate(aCx, container);
|
|
|
|
|
if (tmp == nsnull || (rv = tmp->QueryInterface(kIScriptGlobalObjectDataIID, (void * *)& globalData)) != NS_OK)
|
|
|
|
|
{
|
|
|
|
|
delete originUrl;
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
globalData->GetPrincipal(result);
|
|
|
|
|
if (* result) {
|
|
|
|
|
nsICodebasePrincipal * cbprin;
|
|
|
|
|
char * cbStr;
|
|
|
|
|
(* result)->QueryInterface(nsICodebasePrincipal::GetIID(),(void * *)& cbprin);
|
|
|
|
|
cbprin->GetURLString(& cbStr);
|
|
|
|
|
if (this->SameOrigins(aCx, originUrl,cbStr)) {
|
|
|
|
|
delete originUrl;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef THREADING_ISSUES
|
|
|
|
|
// nsJSPrincipalsData * data;
|
|
|
|
|
// data = (nsJSPrincipalsData*)*aPrincipals;
|
|
|
|
|
// if (data->codebaseBeforeSettingDomain &&
|
|
|
|
|
// this->SameOrigins(aCx, originUrl, data->codebaseBeforeSettingDomain)) {
|
|
|
|
|
/* document.domain was set, so principals are okay */
|
|
|
|
|
// delete originUrl;
|
|
|
|
|
// return NS_OK;
|
|
|
|
|
// }
|
|
|
|
|
/* Principals have changed underneath us. Remove them. */
|
|
|
|
|
// globalData->SetPrincipals(nsnull);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/* Create new principals and return them. */
|
|
|
|
|
//why should we create a new principal, removing this
|
|
|
|
|
// nsAutoString originUrlStr(originUrl);
|
|
|
|
|
// if (!NS_SUCCEEDED(this->NewJSPrincipals(nsnull, nsnull, &originUrlStr, aPrincipals))) {
|
|
|
|
|
// delete originUrl;
|
|
|
|
|
// return NS_ERROR_FAILURE;
|
|
|
|
|
// }
|
|
|
|
|
// globalData->SetPrincipals((void*)*aPrincipals);
|
|
|
|
|
delete originUrl;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char*
|
|
|
|
|
nsJSSecurityManager::FindOriginURL(JSContext *aCx, JSObject *aGlobal)
|
|
|
|
|
{
|
|
|
|
|
nsISupports * tmp1, * tmp2;
|
|
|
|
|
nsIScriptGlobalObjectData* globalData = nsnull;
|
|
|
|
|
nsIURI *origin = nsnull;
|
|
|
|
|
tmp1 = (nsISupports *)JS_GetPrivate(aCx, aGlobal);
|
|
|
|
|
if (nsnull != tmp1 &&
|
|
|
|
|
NS_OK == tmp1->QueryInterface(kIScriptGlobalObjectDataIID, (void**)&globalData)) {
|
|
|
|
|
globalData->GetOrigin(&origin);
|
|
|
|
|
}
|
|
|
|
|
if (origin == nsnull) {
|
|
|
|
|
// does this ever happen?
|
|
|
|
|
/* Must be a new, empty window? Use running origin. */
|
|
|
|
|
tmp2 = (nsISupports*)JS_GetPrivate(aCx, JS_GetGlobalObject(aCx));
|
|
|
|
|
/* Compare running and current to avoid infinite recursion. */
|
|
|
|
|
if (tmp1 == tmp2) {
|
|
|
|
|
nsAutoString urlString = "[unknown origin]";
|
|
|
|
|
NS_IF_RELEASE(globalData);
|
|
|
|
|
return urlString.ToNewCString();
|
|
|
|
|
} else if (nsnull != tmp2 && NS_OK == tmp2->QueryInterface(kIScriptGlobalObjectDataIID, (void**)&globalData)) {
|
|
|
|
|
globalData->GetOrigin(&origin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (origin != nsnull) {
|
|
|
|
|
char *spec;
|
|
|
|
|
origin->GetSpec(&spec);
|
|
|
|
|
nsAutoString urlString(spec);
|
|
|
|
|
NS_IF_RELEASE(globalData);
|
|
|
|
|
return urlString.ToNewCString();
|
|
|
|
|
}
|
|
|
|
|
NS_IF_RELEASE(globalData);
|
|
|
|
|
nsAutoString urlString;
|
|
|
|
|
return urlString.ToNewCString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
|
nsJSSecurityManager::CheckForPrivilege(JSContext *cx, char *prop_name, int priv_code)
|
|
|
|
|
{
|
|
|
|
|
char *tmp_prop_name;
|
|
|
|
|
if(prop_name == NULL) return SCRIPT_SECURITY_NO_ACCESS;
|
|
|
|
|
tmp_prop_name = AddSecPolicyPrefix(cx, prop_name);
|
|
|
|
|
if(tmp_prop_name == NULL) return SCRIPT_SECURITY_NO_ACCESS;
|
|
|
|
|
PRInt32 secLevel = SCRIPT_SECURITY_NO_ACCESS;
|
|
|
|
|
if (NS_OK == mPrefs->GetIntPref(tmp_prop_name, &secLevel)) {
|
|
|
|
|
PR_FREEIF(tmp_prop_name);
|
|
|
|
|
return secLevel;
|
|
|
|
|
}
|
|
|
|
|
PR_FREEIF(tmp_prop_name);
|
|
|
|
|
return SCRIPT_SECURITY_ALL_ACCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
nsJSSecurityManager::AddSecPolicyPrefix(JSContext *cx, char *pref_str)
|
|
|
|
|
{
|
|
|
|
|
const char *subjectOrigin = "";//GetSubjectOriginURL(cx);
|
|
|
|
|
char *policy_str, *retval = 0;
|
|
|
|
|
if ((policy_str = this->GetSitePolicy(subjectOrigin)) == 0) {
|
|
|
|
|
/* No site-specific policy. Get global policy name. */
|
|
|
|
|
|
|
|
|
|
if (NS_OK != mPrefs->CopyCharPref("javascript.security_policy", &policy_str))
|
|
|
|
|
policy_str = PL_strdup("default");
|
|
|
|
|
}
|
|
|
|
|
if (policy_str) { //why can't this be default? && PL_strcasecmp(policy_str, "default") != 0) {
|
|
|
|
|
retval = PR_sprintf_append(NULL, "js_security.%s.%s", policy_str, pref_str);
|
|
|
|
|
PR_Free(policy_str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the site-specific policy associated with object origin org. */
|
|
|
|
|
char *
|
|
|
|
|
nsJSSecurityManager::GetSitePolicy(const char *org)
|
|
|
|
|
{
|
|
|
|
|
char *sitepol, *sp, *nextsp, *orghost = 0, *retval = 0, *prot, *bar, *end, *match = 0;
|
|
|
|
|
int splen, matlen;
|
|
|
|
|
nsIURL * url;
|
|
|
|
|
nsresult rv;
|
|
|
|
|
NS_WITH_SERVICE(nsIComponentManager, compMan,kComponentManagerCID,&rv);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
rv = compMan->CreateInstance(kURLCID,NULL,nsIURL::GetIID(),(void**)&url);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
if (NS_OK != mPrefs->CopyCharPref("js_security.site_policy", &sitepol)) return 0;
|
|
|
|
|
/* Site policy comprises text of the form site1-policy,site2-policy,siteNpolicy
|
|
|
|
|
* where each site-policy is site|policy and policy is presumed to be one of strict/moderate/default
|
|
|
|
|
* site may be either a URL or a hostname. In the former case we do a prefix match with the origin URL; in the latter case
|
|
|
|
|
* we just compare hosts. Process entry by entry. Take longest match, to account for
|
|
|
|
|
* cases like: * http://host/|moderate,http://host/dir/|strict
|
|
|
|
|
*/
|
|
|
|
|
for (sp = sitepol; sp != 0; sp = nextsp) {
|
|
|
|
|
if ((nextsp = strchr(sp, ',')) != 0) *nextsp++ = '\0';
|
|
|
|
|
if ((bar = strchr(sp, '|')) == 0) continue; /* no | for this entry */
|
|
|
|
|
*bar = '\0';
|
|
|
|
|
/* Isolate host, then policy. */
|
|
|
|
|
sp += strspn(sp, " "); /* skip leading spaces */
|
|
|
|
|
end = sp + strcspn(sp, " |"); /* skip up to space or | */
|
|
|
|
|
*end = '\0';
|
|
|
|
|
if ((splen = end-sp) == 0) continue; /* no URL or hostname */
|
|
|
|
|
/* Check whether this is long enough. */
|
|
|
|
|
if (match != 0 && matlen >= splen) continue; /* Nope. New shorter than old. */
|
|
|
|
|
/* Check which case, URL or hostname, we're dealing with. */
|
|
|
|
|
rv = url->SetSpec(sp);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
url->GetScheme(& prot);
|
|
|
|
|
if (prot != 0 && *prot != '\0') {
|
|
|
|
|
/* URL case. Do prefix match, make sure we're at proper boundaries. */
|
|
|
|
|
if (PL_strncmp(org, sp, splen) != 0 || (org[splen] != '\0' /* exact match */
|
|
|
|
|
&& sp[splen-1] != '/' /* site policy ends with / */
|
|
|
|
|
&& org[splen] != '/' /* site policy doesn't, but org does */
|
|
|
|
|
)) {
|
|
|
|
|
PR_Free(prot);
|
|
|
|
|
continue; /* no match */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Host-only case. */
|
|
|
|
|
PR_FREEIF(prot);
|
|
|
|
|
rv = url->SetSpec((char *)org);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
url->GetHost(& orghost);
|
|
|
|
|
if (orghost == 0) return 0; /* out of mem */
|
|
|
|
|
if (PL_strcasecmp(orghost, sp) != 0) continue; /* no match */
|
|
|
|
|
}
|
|
|
|
|
/* Had a match. Remember policy and length of host/URL match. */
|
|
|
|
|
match = bar;
|
|
|
|
|
matlen = splen;
|
|
|
|
|
}
|
|
|
|
|
if (match != 0) {
|
|
|
|
|
/* Longest hostname or URL match. Get policy.
|
|
|
|
|
** match points to |.
|
|
|
|
|
** Skip spaces after | and after policy name.
|
|
|
|
|
*/
|
|
|
|
|
++match;
|
|
|
|
|
sp = match + strspn(match, " ");
|
|
|
|
|
end = sp + strcspn(sp, " ");
|
|
|
|
|
*end = '\0';
|
|
|
|
|
if (sp != end) retval = PL_strdup(sp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PR_FREEIF(orghost);
|
|
|
|
|
PR_FREEIF(sitepol);
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::CheckPermissions(JSContext *aCx, JSObject *aObj, PRInt16 aTarget, PRBool* aReturn)
|
|
|
|
|
{
|
|
|
|
|
char * subjectOrigin = nsnull, * objectOrigin = nsnull;
|
|
|
|
|
nsresult rv = GetSubjectOriginURL(aCx,& subjectOrigin);
|
|
|
|
|
if (rv != NS_OK) return rv;
|
|
|
|
|
/*
|
|
|
|
|
* Hold onto reference to the running decoder's principals
|
|
|
|
|
* in case a call to GetObjectOriginURL ends up
|
|
|
|
|
* dropping a reference due to an origin changing
|
|
|
|
|
* underneath us.
|
|
|
|
|
*/
|
|
|
|
|
rv = GetObjectOriginURL(aCx, aObj, &objectOrigin);
|
|
|
|
|
if (rv != NS_OK || !subjectOrigin || !objectOrigin) {
|
|
|
|
|
*aReturn = PR_FALSE;
|
|
|
|
|
return NS_OK;;
|
|
|
|
|
}
|
|
|
|
|
/* Now see whether the origin methods and servers match. */
|
|
|
|
|
if (this->SameOrigins(aCx, subjectOrigin, objectOrigin)) {
|
|
|
|
|
*aReturn = PR_TRUE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* If we failed the origin tests it still might be the case that we
|
|
|
|
|
* are a signed script and have permissions to do this operation.
|
|
|
|
|
* Check for that here
|
|
|
|
|
*/
|
|
|
|
|
if (aTarget != eJSTarget_Max) {
|
|
|
|
|
PRBool canAccess;
|
|
|
|
|
CanAccessTarget(aCx, aTarget, &canAccess);
|
|
|
|
|
if (canAccess) {
|
|
|
|
|
*aReturn = PR_TRUE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_ReportError(aCx, "Access error message", subjectOrigin);
|
|
|
|
|
* aReturn = PR_FALSE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
|
nsJSSecurityManager::SameOrigins(JSContext * aCx, const char * aOrigin1, const char * aOrigin2)
|
|
|
|
|
{
|
|
|
|
|
if ((aOrigin1 == nsnull) || (aOrigin2 == nsnull) || (PL_strlen(aOrigin1) == 0) || (PL_strlen(aOrigin2) == 0))
|
|
|
|
|
return PR_FALSE;
|
|
|
|
|
// Shouldn't return true if both origin1 and origin2 are unknownOriginStr.
|
|
|
|
|
nsString * tmp = new nsString(aOrigin1);
|
|
|
|
|
if (gUnknownOriginStr.EqualsIgnoreCase(*tmp))
|
|
|
|
|
{
|
|
|
|
|
delete tmp;
|
|
|
|
|
return PR_FALSE;
|
|
|
|
|
}
|
|
|
|
|
delete tmp;
|
|
|
|
|
if (PL_strcmp(aOrigin1, aOrigin2) == 0) return PR_TRUE;
|
|
|
|
|
nsString * cmp1 = new nsString(this->GetCanonicalizedOrigin(aCx, aOrigin1));
|
|
|
|
|
nsString * cmp2 = new nsString(this->GetCanonicalizedOrigin(aCx, aOrigin2));
|
|
|
|
|
|
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
|
// Either the strings are equal or they are both file: uris.
|
|
|
|
|
if (cmp1 && cmp2 &&
|
|
|
|
|
(*cmp1 == *cmp2 ||
|
|
|
|
|
(cmp1->Find(gFileUrlPrefix) == 0 &&
|
|
|
|
|
cmp2->Find(gFileUrlPrefix) == 0)))
|
|
|
|
|
{
|
|
|
|
|
result = PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
delete cmp1;
|
|
|
|
|
delete cmp2;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
nsJSSecurityManager::GetCanonicalizedOrigin(JSContext* aCx, const char * aUrlString)
|
|
|
|
|
{
|
|
|
|
|
nsString * buffer;
|
|
|
|
|
nsIURL * url;
|
|
|
|
|
nsresult rv;
|
|
|
|
|
char * origin = (char *)aUrlString;
|
|
|
|
|
NS_WITH_SERVICE(nsIComponentManager, compMan,kComponentManagerCID,&rv);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
rv = compMan->CreateInstance(kURLCID,NULL,nsIURL::GetIID(),(void**)&url);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
rv = url->SetSpec(origin);
|
|
|
|
|
if (!NS_SUCCEEDED(rv)) return nsnull;
|
|
|
|
|
url->GetScheme(& origin);
|
|
|
|
|
buffer = new nsString(origin);
|
|
|
|
|
url->GetHost(& origin);
|
|
|
|
|
buffer->Append(origin);
|
|
|
|
|
if (!buffer) {
|
|
|
|
|
JS_ReportOutOfMemory(aCx);
|
|
|
|
|
return nsnull;
|
|
|
|
|
}
|
|
|
|
|
origin = buffer->ToNewCString();
|
|
|
|
|
delete buffer;
|
|
|
|
|
return origin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::GetPrincipalsFromStackFrame(JSContext *aCx, JSPrincipals** aPrincipals)
|
|
|
|
|
{
|
|
|
|
|
//* Get principals from script of innermost interpreted frame.
|
|
|
|
|
JSStackFrame *fp;
|
|
|
|
|
JSScript *script;
|
|
|
|
|
#ifdef OJI
|
|
|
|
|
JSStackFrame *pFrameToStartLooking = *JVM_GetStartJSFrameFromParallelStack();
|
|
|
|
|
JSStackFrame *pFrameToEndLooking = JVM_GetEndJSFrameFromParallelStack(pFrameToStartLooking);
|
|
|
|
|
if (pFrameToStartLooking == nsnull) {
|
|
|
|
|
pFrameToStartLooking = JS_FrameIterator(aCx, &pFrameToStartLooking);
|
|
|
|
|
if (pFrameToStartLooking == nsnull) {
|
|
|
|
|
/*
|
|
|
|
|
** There are no frames or scripts at this point.
|
|
|
|
|
*/
|
|
|
|
|
pFrameToEndLooking = nsnull;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
JSStackFrame *pFrameToStartLooking = JS_FrameIterator(aCx, &fp);
|
|
|
|
|
JSStackFrame *pFrameToEndLooking = nsnull;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
fp = pFrameToStartLooking;
|
|
|
|
|
while ((fp = JS_FrameIterator(aCx, &fp)) != pFrameToEndLooking) {
|
|
|
|
|
script = JS_GetFrameScript(aCx, fp);
|
|
|
|
|
if (script) {
|
|
|
|
|
*aPrincipals = JS_GetScriptPrincipals(aCx, script);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#ifdef OJI
|
|
|
|
|
*aPrincipals = JVM_GetJavaPrincipalsFromStack(pFrameToStartLooking);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
#endif
|
|
|
|
|
*aPrincipals = nsnull;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::GetOriginFromSourceURL(nsIURI * url, char * * result)
|
|
|
|
|
{
|
|
|
|
|
char * tempChars;// = ParseURL(aSourceURL, GET_PROTOCOL_PART|GET_HOST_PART|GET_PATH_PART);
|
|
|
|
|
url->GetScheme(& tempChars);
|
|
|
|
|
nsString * buffer = new nsString(tempChars);
|
|
|
|
|
buffer->Append("://");
|
|
|
|
|
url->GetHost(& tempChars);
|
|
|
|
|
buffer->Append(tempChars);
|
|
|
|
|
url->GetPath(& tempChars);
|
|
|
|
|
buffer->Append(tempChars);
|
|
|
|
|
* result = (buffer->Length() == 0 || buffer->EqualsIgnoreCase(gUnknownOriginStr))
|
|
|
|
|
? nsnull : buffer->ToNewCString();
|
|
|
|
|
delete buffer;
|
|
|
|
|
return * result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::CanCreateWrapper(JSContext * aJSContext, const nsIID & aIID, nsISupports * aObj)
|
|
|
|
|
@@ -734,35 +229,6 @@ nsJSSecurityManager::CanSetProperty(JSContext * aJSContext,
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsJSSecurityManager::CanAccessTarget(JSContext *aCx, PRInt16 aTarget, PRBool* aReturn)
|
|
|
|
|
{
|
|
|
|
|
JSPrincipals *principals;
|
|
|
|
|
*aReturn = PR_TRUE;
|
|
|
|
|
|
|
|
|
|
GetPrincipalsFromStackFrame(aCx, &principals);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if ((nsCapsGetRegistrationModeFlag()) && principals &&
|
|
|
|
|
(NET_URL_Type(principals->codebase) == FILE_TYPE_URL)) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if (principals && !principals->globalPrivilegesEnabled(aCx, principals)) {
|
|
|
|
|
*aReturn = PR_FALSE;
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
// only if signed scripts
|
|
|
|
|
else if (!PrincipalsCanAccessTarget(aCx, aTarget)) {
|
|
|
|
|
*aReturn = PR_FALSE;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
*aReturn = PR_FALSE;
|
|
|
|
|
#endif
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|