Files
Mozilla/mozilla/caps/src/nsPrincipalManager.cpp
arielb%netscape.com f96a17b9c8 adding functionality to security
git-svn-id: svn://10.0.0.236/trunk@42712 18797224-902f-48f8-a5cc-f745e15eee43
1999-08-08 22:29:02 +00:00

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;
}