394 lines
12 KiB
C++
394 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
/*creates, registers, and performs logical operations on principals*/
|
|
#include "prmem.h"
|
|
#include "prmon.h"
|
|
#include "prlog.h"
|
|
#include "prprf.h"
|
|
#include "plbase64.h"
|
|
#include "plstr.h"
|
|
#include "nsPrincipalManager.h"
|
|
#include "nsPrincipalArray.h"
|
|
#include "nsCaps.h"
|
|
#include "nsCertificatePrincipal.h"
|
|
#include "nsCodebasePrincipal.h"
|
|
#include "nsPrivilegeManager.h"
|
|
|
|
#define UNSIGNED_PRINCIPAL_KEY "4a:52:4f:53:4b:49:4e:44"
|
|
#define UNKNOWN_PRINCIPAL_KEY "52:4f:53:4b:49:4e:44:4a"
|
|
|
|
static nsIPrincipal * theSystemPrincipal = NULL;
|
|
static nsIPrincipal * theUnsignedPrincipal = NULL;
|
|
static nsIPrincipal * theUnknownPrincipal = NULL;
|
|
static nsIPrincipalArray * theUnknownPrincipalArray = NULL;
|
|
static nsIPrincipalArray * theUnsignedPrincipalArray = NULL;
|
|
char * gListOfPrincipals;
|
|
|
|
|
|
static PRBool RDF_RemovePrincipal(nsIPrincipal * prin);
|
|
static PRBool GetPrincipalString(nsHashKey * aKey, void * aData, void * closure);
|
|
|
|
static NS_DEFINE_IID(kIPrincipalManagerIID, NS_IPRINCIPALMANAGER_IID);
|
|
|
|
NS_IMPL_ISUPPORTS(nsPrincipalManager, kIPrincipalManagerIID);
|
|
|
|
nsIPrincipal *
|
|
nsPrincipalManager::GetSystemPrincipal(void)
|
|
{
|
|
return theSystemPrincipal;
|
|
}
|
|
nsIPrincipal *
|
|
nsPrincipalManager::GetUnsignedPrincipal(void)
|
|
{
|
|
return theUnsignedPrincipal;
|
|
}
|
|
|
|
nsIPrincipal *
|
|
nsPrincipalManager::GetUnknownPrincipal(void)
|
|
{
|
|
return theUnknownPrincipal;
|
|
}
|
|
|
|
PRBool
|
|
nsPrincipalManager::HasSystemPrincipal(nsIPrincipalArray * prinArray)
|
|
{
|
|
nsIPrincipal * sysPrin = nsPrincipalManager::GetSystemPrincipal();
|
|
nsIPrincipal * prin;
|
|
if (sysPrin == NULL) return PR_FALSE;
|
|
PRUint32 i;
|
|
prinArray->GetPrincipalArraySize(& i);
|
|
while(i-- > 0) {
|
|
prinArray->GetPrincipalArrayElement(i,& prin);
|
|
PRBool result;
|
|
sysPrin->Equals(prin, & result);
|
|
if (result) return PR_TRUE;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::CreateCodebasePrincipal(const char * codebaseURL, nsIPrincipal * * prin) {
|
|
* prin = new nsCodebasePrincipal(nsIPrincipal::PrincipalType_CodebaseExact, codebaseURL);
|
|
if (prin == NULL) return NS_ERROR_OUT_OF_MEMORY;
|
|
(* prin)->AddRef();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::CreateCertificatePrincipal(const unsigned char * * certChain, PRUint32 * certChainLengths, PRUint32 noOfCerts, nsIPrincipal * * prin)
|
|
{
|
|
* prin = new nsCertificatePrincipal(nsIPrincipal::PrincipalType_Certificate,
|
|
certChain, certChainLengths, noOfCerts);
|
|
if (!prin) return NS_ERROR_OUT_OF_MEMORY;
|
|
(* prin)->AddRef();
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::CanExtendTrust(nsIPrincipalArray * from, nsIPrincipalArray * to, PRBool * result)
|
|
{
|
|
if ((from == NULL) || (to == NULL)) {
|
|
* result = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
nsIPrincipalArray * intersect;
|
|
from->IntersectPrincipalArray(to,& intersect);
|
|
PRUint32 intersectSize = 0, fromSize = 0;
|
|
intersect->GetPrincipalArraySize(& intersectSize);
|
|
from->GetPrincipalArraySize(& fromSize);
|
|
if (intersectSize == fromSize) {
|
|
* result = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
if (intersectSize == 0 || (intersectSize != (fromSize - 1))) return PR_FALSE;
|
|
nsIPrincipal * prin;
|
|
PRUint32 i;
|
|
for (i=0; i < intersectSize; i++) {
|
|
intersect->GetPrincipalArrayElement(i, & prin);
|
|
PRInt16 prinType = nsIPrincipal::PrincipalType_Unknown;
|
|
prin->GetType(& prinType);
|
|
if (prinType == nsIPrincipal::PrincipalType_CodebaseExact ||
|
|
prinType == nsIPrincipal::PrincipalType_CodebaseRegex) {
|
|
* result = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
PRUint32 codebaseCount = 0;
|
|
for (i=0; i < fromSize; i++) {
|
|
from->GetPrincipalArrayElement(i, & prin);
|
|
PRInt16 prinType = nsIPrincipal::PrincipalType_Unknown;
|
|
prin->GetType(& prinType);
|
|
if (prinType == nsIPrincipal::PrincipalType_CodebaseExact ||
|
|
prinType == nsIPrincipal::PrincipalType_CodebaseRegex)
|
|
codebaseCount++;
|
|
}
|
|
* result = (codebaseCount == 1) ? PR_TRUE : PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::CheckMatchPrincipal(nsIScriptContext * context, nsIPrincipal * prin, PRInt32 callerDepth, PRBool * result)
|
|
{
|
|
nsIPrincipalArray * prinArray = new nsPrincipalArray();
|
|
prinArray->AddPrincipalArrayElement(prin);
|
|
nsIPrincipalArray * classPrinArray = this->GetClassPrincipalsFromStack(context, callerDepth);
|
|
PRInt16 compType = 0;
|
|
prinArray->ComparePrincipalArray(classPrinArray,& compType);
|
|
* result = (compType != nsPrincipalArray::SetComparisonType_NoSubset) ? PR_TRUE : PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
nsIPrincipalArray *
|
|
nsPrincipalManager::GetClassPrincipalsFromStack(PRInt32 callerDepth)
|
|
{
|
|
return this->GetClassPrincipalsFromStack(NULL, callerDepth);
|
|
}
|
|
|
|
nsIPrincipalArray *
|
|
nsPrincipalManager::GetClassPrincipalsFromStack(nsIScriptContext * context, PRInt32 callerDepth)
|
|
{
|
|
nsIPrincipalArray * principalArray = theUnknownPrincipalArray;
|
|
int depth = 0;
|
|
struct NSJSJavaFrameWrapper * wrapper = NULL;
|
|
if (nsCapsNewNSJSJavaFrameWrapperCallback == NULL) return NULL;
|
|
wrapper = (* nsCapsNewNSJSJavaFrameWrapperCallback)((void *)context);
|
|
if (wrapper == NULL) return NULL;
|
|
for ((* nsCapsGetStartFrameCallback)(wrapper);(!(* nsCapsIsEndOfFrameCallback)(wrapper));) {
|
|
if ((* nsCapsIsValidFrameCallback)(wrapper)) {
|
|
if (depth >= callerDepth) {
|
|
principalArray = (nsIPrincipalArray *) (* nsCapsGetPrincipalArrayCallback)(wrapper);
|
|
break;
|
|
}
|
|
}
|
|
if (!(* nsCapsGetNextFrameCallback)(wrapper, &depth)) break;
|
|
}
|
|
(* nsCapsFreeNSJSJavaFrameWrapperCallback)(wrapper);
|
|
return principalArray;
|
|
}
|
|
|
|
nsIPrincipalArray *
|
|
nsPrincipalManager::GetMyPrincipals(PRInt32 callerDepth)
|
|
{
|
|
return nsPrincipalManager::GetMyPrincipals(NULL, callerDepth);
|
|
}
|
|
|
|
nsIPrincipalArray *
|
|
nsPrincipalManager::GetMyPrincipals(nsIScriptContext * context, PRInt32 callerDepth)
|
|
{
|
|
return nsPrincipalManager::GetPrincipalManager()->GetClassPrincipalsFromStack(context, callerDepth);
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal *
|
|
nsPrincipalManager::GetPrincipalFromString(char * prinName)
|
|
{
|
|
StringKey prinNameKey(prinName);
|
|
nsCaps_lock();
|
|
nsIPrincipal * prin = (nsIPrincipal *)itsPrinNameToPrincipalTable->Get(& prinNameKey);
|
|
nsCaps_unlock();
|
|
return prin;
|
|
}
|
|
|
|
void
|
|
nsPrincipalManager::AddToPrincipalNameToPrincipalTable(nsIPrincipal * prin)
|
|
{
|
|
char * prinName;
|
|
prin->ToString(& prinName);
|
|
if (prinName == NULL) return;
|
|
StringKey prinNameKey(prinName);
|
|
nsCaps_lock();
|
|
if (!itsPrinNameToPrincipalTable->Get(& prinNameKey))
|
|
itsPrinNameToPrincipalTable->Put(& prinNameKey, prin);
|
|
nsCaps_unlock();
|
|
|
|
}
|
|
|
|
void
|
|
nsPrincipalManager::RemoveFromPrincipalNameToPrincipalTable(nsIPrincipal * prin)
|
|
{
|
|
char * prinName;
|
|
prin->ToString(& prinName);
|
|
StringKey prinNameKey(prinName);
|
|
nsCaps_lock();
|
|
itsPrinNameToPrincipalTable->Remove(& prinNameKey);
|
|
nsCaps_unlock();
|
|
}
|
|
|
|
static PRBool
|
|
GetPrincipalString(nsHashKey * aKey, void * aData, void * closure)
|
|
{
|
|
/* Admin UI */
|
|
/* XXX: Ignore empty strings */
|
|
const char *string = ((StringKey *) aKey)->itsString;
|
|
gListOfPrincipals = (!gListOfPrincipals)
|
|
? PR_sprintf_append(gListOfPrincipals, "\"%s\"", string)
|
|
: PR_sprintf_append(gListOfPrincipals, ",\"%s\"", string);
|
|
return PR_TRUE;
|
|
}
|
|
|
|
const char *
|
|
nsPrincipalManager::GetAllPrincipalsString(void)
|
|
{
|
|
/* Admin UI */
|
|
char *principalStrings=NULL;
|
|
if (itsPrinNameToPrincipalTable == NULL) return NULL;
|
|
nsCaps_lock();
|
|
gListOfPrincipals = NULL;
|
|
itsPrinNameToPrincipalTable->Enumerate(GetPrincipalString);
|
|
if (gListOfPrincipals) {
|
|
principalStrings = PL_strdup(gListOfPrincipals);
|
|
PR_Free(gListOfPrincipals);
|
|
}
|
|
gListOfPrincipals = NULL;
|
|
nsCaps_unlock();
|
|
return principalStrings;
|
|
}
|
|
|
|
void
|
|
nsPrincipalManager::RegisterSystemPrincipal(nsIPrincipal * prin)
|
|
{
|
|
nsPrivilegeManager * itsPrivilegeManager = nsPrivilegeManager::GetPrivilegeManager();
|
|
PrincipalKey prinKey(prin);
|
|
nsCaps_lock();
|
|
if (!itsPrivilegeManager->itsPrinToPrivTable->Get(& prinKey))
|
|
itsPrivilegeManager->itsPrinToPrivTable->Put(& prinKey, new nsSystemPrivilegeTable());
|
|
if (!itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Get(& prinKey))
|
|
itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Put(& prinKey, new nsSystemPrivilegeTable());
|
|
theSystemPrincipal = prin;
|
|
CreateSystemTargets(prin);
|
|
// Load the signed applet's ACL from the persistence store
|
|
itsPrivilegeManager->Load();
|
|
nsCaps_unlock();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::RegisterPrincipal(nsIPrincipal * prin)
|
|
{
|
|
nsPrivilegeManager * itsPrivilegeManager = nsPrivilegeManager::GetPrivilegeManager();
|
|
PrincipalKey prinKey(prin);
|
|
nsCaps_lock();
|
|
if (!itsPrivilegeManager->itsPrinToPrivTable->Get(& prinKey))
|
|
itsPrivilegeManager->itsPrinToPrivTable->Put(&prinKey, new nsPrivilegeTable());
|
|
if (!itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Get(& prinKey)) {
|
|
itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Put(& prinKey, new nsPrivilegeTable());
|
|
}
|
|
this->AddToPrincipalNameToPrincipalTable(prin);
|
|
nsCaps_unlock();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::UnregisterPrincipal(nsIPrincipal * prin, PRBool * result)
|
|
{
|
|
nsPrivilegeManager * itsPrivilegeManager = nsPrivilegeManager::GetPrivilegeManager();
|
|
PRBool eq;
|
|
prin->Equals(this->GetSystemPrincipal(),& eq);
|
|
if (result) {
|
|
* result = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
PrincipalKey prinKey(prin);
|
|
nsCaps_lock();
|
|
/* Get the privilegetables and free them up */
|
|
nsPrivilegeTable * pt =
|
|
(nsPrivilegeTable *)itsPrivilegeManager->itsPrinToPrivTable->Get(& prinKey);
|
|
nsPrivilegeTable * mpt =
|
|
(nsPrivilegeTable *)itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Get(& prinKey);
|
|
if(pt) delete pt;
|
|
if(mpt) delete mpt;
|
|
/* Remove the principal */
|
|
void * old_prin = itsPrivilegeManager->itsPrinToPrivTable->Remove(& prinKey);
|
|
void * old_prin1 = itsPrivilegeManager->itsPrinToMacroTargetPrivTable->Remove(& prinKey);
|
|
/* remove principal from PrinNameToPrincipalTable */
|
|
this->RemoveFromPrincipalNameToPrincipalTable(prin);
|
|
/* remove the principal from RDF also */
|
|
RDF_RemovePrincipal(prin);
|
|
nsCaps_unlock();
|
|
* result = ((old_prin == NULL) && (old_prin1 == NULL)) ? PR_FALSE : PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPrincipalManager::NewPrincipalArray(PRUint32 count, nsIPrincipalArray * * result)
|
|
{
|
|
* result = (nsIPrincipalArray *) new nsPrincipalArray(count);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
|
|
nsPrincipalManager::nsPrincipalManager(void)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
NS_ADDREF(this);
|
|
nsCaps_lock();
|
|
itsPrinNameToPrincipalTable = new nsHashtable();
|
|
theUnsignedPrincipal = new nsCertificatePrincipal(nsIPrincipal::PrincipalType_Certificate, UNSIGNED_PRINCIPAL_KEY);
|
|
theUnsignedPrincipalArray = new nsPrincipalArray();
|
|
theUnsignedPrincipalArray->AddPrincipalArrayElement(theUnsignedPrincipal);
|
|
theUnknownPrincipal = new nsCertificatePrincipal(nsIPrincipal::PrincipalType_Certificate, UNKNOWN_PRINCIPAL_KEY);
|
|
theUnknownPrincipalArray = new nsPrincipalArray();
|
|
theUnknownPrincipalArray->AddPrincipalArrayElement(theUnknownPrincipal);
|
|
nsCaps_unlock();
|
|
}
|
|
|
|
nsPrincipalManager::~nsPrincipalManager(void) {
|
|
nsCaps_lock();
|
|
if (itsPrinNameToPrincipalTable) delete itsPrinNameToPrincipalTable;
|
|
nsCaps_unlock();
|
|
}
|
|
|
|
nsPrincipalManager *
|
|
nsPrincipalManager::GetPrincipalManager()
|
|
{
|
|
static nsPrincipalManager * prinMan = NULL;
|
|
if(!prinMan) prinMan = new nsPrincipalManager();
|
|
return prinMan;
|
|
}
|
|
|
|
static PRBool
|
|
RDF_RemovePrincipal(nsIPrincipal * prin)
|
|
{
|
|
PRBool found = PR_FALSE;
|
|
#ifdef ENABLE_RDF
|
|
nsCaps_lock();
|
|
RDFJSec_InitPrivilegeDB();
|
|
RDF_Cursor prin_cursor = RDFJSec_ListAllPrincipals();
|
|
if (prin_cursor == NULL) {
|
|
nsCaps_unlock();
|
|
return PR_FALSE;
|
|
}
|
|
JSec_Principal jsec_prin;
|
|
nsIPrincipal * cur_prin = NULL;
|
|
while ((jsec_prin = RDFJSec_NextPrincipal(prin_cursor)) != NULL) {
|
|
if ((cur_prin = RDF_getPrincipal(jsec_prin)) == NULL) continue;
|
|
PRBool eq;
|
|
prin->Equals(cur_prin,& eq);
|
|
if (eq) {
|
|
found = PR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
RDFJSec_ReleaseCursor(prin_cursor);
|
|
if (found) RDFJSec_DeletePrincipal(jsec_prin);
|
|
nsCaps_unlock();
|
|
#endif /* ENABLE_RDF */
|
|
return found;
|
|
}
|