Implemented the reading of capabilities data from prefs. Reads codebase and certificate principal data and populates ScriptSecurityManager's principals table. bug= 18122 r=norris, rginda

This commit is contained in:
mstoltz%netscape.com 2000-01-18 21:54:01 +00:00
parent fe32b459e5
commit 5014545a00
11 changed files with 316 additions and 88 deletions

View File

@ -29,10 +29,9 @@
[uuid(ebfefcd0-25e1-11d2-8160-006008119d7a)]
interface nsICertificatePrincipal : nsISupports {
void GetPublicKey(out string publicKey);
void GetCompanyName(out string ppCompanyName);
void GetCertificateAuthority(out string ppCertAuthority);
void GetSerialNumber(out string ppSerialNumber);
void GetExpirationDate(out string ppExpDate);
void GetFingerPrint(out string ppFingerPrint);
//-- The Get functions for these attributes DO NOT COPY.
readonly attribute string issuerName;
readonly attribute string serialNumber;
};

View File

@ -57,6 +57,8 @@ interface nsIPrincipal : nsISupports {
void RevertCapability(in string capability, inout voidStar annotation);
void DisableCapability(in string capability, inout voidStar annotation);
void CapabilitiesToString(out string result);
};

View File

@ -84,6 +84,8 @@ interface nsIScriptSecurityManager : nsISupports
void RevertCapability(in string capability);
void DisableCapability(in string capability);
nsIPrincipal GetCertificatePrincipal(in string aIssuer, in string aSerialNumber);
};
%{C++

View File

@ -33,15 +33,18 @@ public:
virtual ~nsBasePrincipal(void);
NS_IMETHOD
CapabilitiesToString(char** aCapString);
NS_IMETHOD
GetJSPrincipals(JSPrincipals **jsprin);
NS_IMETHOD
CanEnableCapability(const char *capability, PRInt16 *result);
NS_IMETHOD
SetCanEnableCapability(const char *capability, PRInt16 canEnable);
NS_IMETHOD
IsCapabilityEnabled(const char *capability, void *annotation,
PRBool *result);
@ -54,6 +57,9 @@ public:
NS_IMETHOD
DisableCapability(const char *capability, void **annotation);
nsresult
Init(const char* data);
protected:
enum AnnotationValue { AnnotationEnabled=1, AnnotationDisabled };

View File

@ -47,23 +47,17 @@ public:
NS_IMETHOD CanEnableCapability(const char *capability, PRInt16 *result);
NS_IMETHOD SetCanEnableCapability(const char *capability,
PRInt16 canEnable);
nsresult Init(const char* data);
nsresult Init(const char* aIssuerName, const char* aSerialNumber);
nsCertificatePrincipal();
nsCertificatePrincipal(PRInt16 type, const char * key);
nsCertificatePrincipal(PRInt16 type, const unsigned char ** certChain, PRUint32 * certChainLengths, PRUint32 noOfCerts);
virtual ~nsCertificatePrincipal(void);
protected:
PRInt16 itsType;
const char * itsKey;
char * itsCompanyName;
char * itsCertificateAuthority;
char * itsSerialNumber;
char * itsExpirationDate;
char * itsFingerPrint;
char * itsNickname;
char * itsString;
const char* mIssuerName;
const char* mSerialNumber;
};
#endif // _NS_CERTIFICATE_PRINCIPAL_H_

View File

@ -52,9 +52,12 @@ public:
nsCodebasePrincipal();
NS_IMETHOD
nsresult
Init(nsIURI *uri);
nsresult
Init(const char* data);
virtual ~nsCodebasePrincipal(void);
protected:

View File

@ -28,6 +28,7 @@
#include "nsIXPCSecurityManager.h"
#include "nsHashtable.h"
#include "nsDOMPropEnums.h"
#include "nsCOMPtr.h"
#define NS_SCRIPTSECURITYMANAGER_CID \
{ 0x7ee2a4c0, 0x4b93, 0x17d3, \
@ -52,6 +53,9 @@ public:
nsObjectHashtable *mOriginToPolicyMap;
private:
void
LookupPrincipal(nsCOMPtr<nsIPrincipal>* aPrincipal);
NS_IMETHOD
GetSubjectPrincipal(JSContext *aCx, nsIPrincipal **result);
@ -77,6 +81,9 @@ private:
static void
enumeratePolicyCallback(const char *prefName, void *data);
static void
enumeratePrincipalsCallback(const char *prefName, void *data);
static int
JSEnabledPrefChanged(const char *pref, void *data);

View File

@ -18,6 +18,7 @@
#include "nsBasePrincipal.h"
#include "nsString.h"
#include "plstr.h"
//////////////////////////
@ -134,3 +135,63 @@ nsBasePrincipal::SetCapability(const char *capability, void **annotation,
ht->Put(&key, (void *) value);
return NS_OK;
}
nsresult
nsBasePrincipal::Init(const char* data)
{
// Parses capabilities strings of the form
// "Capability=value ..."
// ie. "UniversalBrowserRead=0 UniversalBrowserWrite=1"
// where value is from 0 to 3 as defined in nsIPrincipal.idl
if (mCapabilities)
mCapabilities->Reset();
for (;;)
{
char* wordEnd = PL_strchr(data, '=');
if (wordEnd == nsnull)
break;
*wordEnd = '\0';
const char* cap = data;
data = wordEnd+1; // data is now pointing at the numeric value
PRInt16 value = (PRInt16)(*data) - (PRInt16)'0';
nsresult rv = SetCanEnableCapability(cap, value);
if (NS_FAILED(rv)) return rv;
if (data[1] == '\0') // End of the data
break;
else
data += 2; // data is now at the beginning of the next capability string
}
return NS_OK;
}
PR_STATIC_CALLBACK(PRBool)
AppendCapability(nsHashKey *aKey, void* aData, void* aStr)
{
nsAutoString name( ((nsStringKey*)aKey)->GetString() );
char value = (char)aData + '0';
nsString* capStr = (nsString*)aStr;
capStr->Append(' ');
capStr->Append(name);
capStr->Append('=');
capStr->Append(value);
return (capStr != nsnull);
}
NS_IMETHODIMP
nsBasePrincipal::CapabilitiesToString(char** aStr)
{
if (!mCapabilities || !aStr)
return NS_OK;
nsAutoString capStr;
// The following line is a guess at how long the capabilities string
// will be (~15 chars per capability). This will minimize copying.
capStr.SetCapacity(mCapabilities->Count() * 15);
mCapabilities->Enumerate(AppendCapability, (void*)&capStr);
*aStr = capStr.ToNewCString();
if (!(*aStr)) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}

View File

@ -21,6 +21,7 @@
*/
/*describes principals for use in signed scripts*/
#include "nsCertificatePrincipal.h"
#include "nsCOMPtr.h"
static NS_DEFINE_IID(kICertificatePrincipalIID, NS_ICERTIFICATEPRINCIPAL_IID);
@ -33,94 +34,128 @@ NS_IMETHODIMP
nsCertificatePrincipal::CanEnableCapability(const char *capability,
PRInt16 *result)
{
// XXX: query database as to whether this principal has this capability enabled
*result = nsIPrincipal::ENABLE_DENIED;
if(NS_FAILED(nsBasePrincipal::CanEnableCapability(capability, result)))
return NS_ERROR_FAILURE;
if (*result == nsIPrincipal::ENABLE_UNKNOWN)
*result = ENABLE_WITH_USER_PERMISSION;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::SetCanEnableCapability(const char *capability,
PRInt16 canEnable)
{
// XXX: modify database as to whether this principal has this capability enabled
return NS_ERROR_FAILURE;
}
// Unclear if we need any of these methods, and if so, where they should live.
NS_IMETHODIMP
nsCertificatePrincipal::GetPublicKey(char ** publicKey)
nsCertificatePrincipal::GetIssuerName(char ** issuerName)
{
* publicKey = (char *)this->itsKey;
return (itsKey == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
*issuerName = (char*)mIssuerName;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetCompanyName(char * * companyName)
nsCertificatePrincipal::GetSerialNumber(char ** serialNumber)
{
companyName = & this->itsCompanyName;
return (itsCompanyName == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
*serialNumber = (char*)mSerialNumber;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetCertificateAuthority(char * * certificateAuthority)
{
certificateAuthority = & this->itsCertificateAuthority;
return (itsCertificateAuthority == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetSerialNumber(char * * serialNumber)
{
serialNumber = & this->itsSerialNumber;
return (itsSerialNumber == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetExpirationDate(char * * expirationDate)
{
expirationDate = & this->itsExpirationDate;
return (itsExpirationDate == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetFingerPrint(char * * fingerPrint)
{
fingerPrint = & this->itsFingerPrint;
return (itsFingerPrint == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::ToString(char **result)
{
return NS_ERROR_NOT_IMPLEMENTED;
nsAutoString str;
str += "[Certificate ";
str += mIssuerName;
str += ' ';
str += mSerialNumber;
str += ']';
*result = str.ToNewCString();
return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsCertificatePrincipal::Equals(nsIPrincipal * other, PRBool * result)
{
return NS_ERROR_NOT_IMPLEMENTED;
if (this == other) {
*result = PR_TRUE;
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsICertificatePrincipal> otherCertificate =
do_QueryInterface(other, &rv);
if (NS_FAILED(rv))
{
*result = PR_FALSE;
return NS_OK;
}
char* otherIssuer;
otherCertificate->GetIssuerName(&otherIssuer);
char* otherSerial;
otherCertificate->GetSerialNumber(&otherSerial);
*result = ( (PL_strcmp(mIssuerName, otherIssuer) == 0) &&
(PL_strcmp(mSerialNumber, otherSerial) == 0) );
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::HashValue(PRUint32 *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
char* str;
if (NS_FAILED(ToString(&str)) || !str) return NS_ERROR_FAILURE;
*result = nsCRT::HashValue(str);
nsCRT::free(str);
return NS_OK;
}
nsCertificatePrincipal::nsCertificatePrincipal(PRInt16 type, const char * key)
nsresult
nsCertificatePrincipal::Init(const char* data)
{
this->itsType = type;
this->itsKey = key;
// Parses preference strings of the form
// "[Certificate Issuer Serial#] capabilities string"
// ie. "[Certificate CertCo 12:34:AB:CD] UniversalBrowserRead=1"
if (!data)
return NS_ERROR_ILLEGAL_VALUE;
data = PL_strchr(data, ' '); // Jump to issuer
NS_ASSERTION(data, "Malformed security.principal preference");
data += 1;
char* wordEnd = PL_strchr(data, ' '); // Find end of issuer
NS_ASSERTION(wordEnd, "Malformed security.principal preference");
*wordEnd = '\0';
const char* issuer = data;
data = wordEnd+1; // Jump to serial#
wordEnd = PL_strchr(data, ']'); // Find end of serial#
NS_ASSERTION(wordEnd, "Malformed security.principal preference");
*wordEnd = '\0';
const char* serial = data;
if(NS_FAILED(Init(issuer, serial))) return NS_ERROR_FAILURE;
if (wordEnd[1] != '\0')
{
data = wordEnd+2; // Jump to beginning of caps data
return nsBasePrincipal::Init(data);
}
else
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::Init(const char* aIssuerName, const char* aSerialNumber)
{
mIssuerName = nsCRT::strdup(aIssuerName);
mSerialNumber = nsCRT::strdup(aSerialNumber);
if (!mIssuerName || !mSerialNumber) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsCertificatePrincipal::nsCertificatePrincipal(PRInt16 type, const unsigned char **certChain,
PRUint32 *certChainLengths, PRUint32 noOfCerts)
nsCertificatePrincipal::nsCertificatePrincipal()
{
this->itsType = type;
NS_INIT_ISUPPORTS();
}
nsCertificatePrincipal::~nsCertificatePrincipal(void)
{
if (mIssuerName)
nsCRT::free((char*)mIssuerName);
if (mSerialNumber)
nsCRT::free((char*)mSerialNumber);
}

View File

@ -25,6 +25,7 @@
#include "nsCodebasePrincipal.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "nsIURL.h"
#include "nsCOMPtr.h"
#include "nsIPref.h"
@ -43,12 +44,12 @@ NS_IMETHODIMP
nsCodebasePrincipal::ToString(char **result)
{
nsAutoString buf;
buf += "[";
buf += "[Codebase ";
nsXPIDLCString spec;
if (NS_FAILED(mURI->GetSpec(getter_Copies(spec))))
return NS_ERROR_FAILURE;
buf += spec;
buf += "]";
buf += ']';
*result = buf.ToNewCString();
return *result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
@ -180,9 +181,7 @@ nsCodebasePrincipal::SameOrigin(nsIPrincipal *other, PRBool *result)
rv = mURI->GetScheme(&scheme2);
if (NS_SUCCEEDED(rv) && PL_strcmp(scheme1, scheme2) == 0) {
if (PL_strcmp(scheme1, "file") == 0 ||
PL_strcmp(scheme1, "resource") == 0)
{
if (PL_strcmp(scheme1, "file") == 0) {
// All file: urls are considered to have the same origin.
*result = PR_TRUE;
} else if (PL_strcmp(scheme1, "imap") == 0 ||
@ -232,7 +231,7 @@ nsCodebasePrincipal::nsCodebasePrincipal()
mURI = nsnull;
}
NS_IMETHODIMP
nsresult
nsCodebasePrincipal::Init(nsIURI *uri)
{
char *codebase;
@ -248,6 +247,40 @@ nsCodebasePrincipal::Init(nsIURI *uri)
return NS_OK;
}
// This one overrides nsBasePrincipal::Init
nsresult
nsCodebasePrincipal::Init(const char* data)
{
// Parses preference strings of the form
// "[Codebase URL] capabilities string"
// ie. "[Codebase http://www.mozilla.org] UniversalBrowserRead=1"
if (!data)
return NS_ERROR_ILLEGAL_VALUE;
data = PL_strchr(data, ' '); // Jump to URL
if (!data)
return NS_ERROR_FAILURE;
data += 1;
char* urlEnd = PL_strchr(data, ']'); // Find end of URL
NS_ASSERTION(urlEnd, "Malformed security.principal preference.");
*urlEnd = '\0';
if (NS_FAILED(NS_NewURI(&mURI, data, nsnull)))
{
NS_ASSERTION(PR_FALSE, "Malformed URI in security.principal preference.");
return NS_ERROR_FAILURE;
}
if (urlEnd[1] != 0)
{
data = urlEnd+2; // Jump to beginning of caps data
return nsBasePrincipal::Init(data);
}
else
return NS_OK;
}
nsCodebasePrincipal::~nsCodebasePrincipal(void)
{
if (mURI)

View File

@ -30,6 +30,7 @@
#include "nsJSPrincipals.h"
#include "nsSystemPrincipal.h"
#include "nsCodebasePrincipal.h"
#include "nsCertificatePrincipal.h"
#include "nsCRT.h"
#include "nsXPIDLString.h"
#include "nsIJSContextStack.h"
@ -520,22 +521,54 @@ nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetCertificatePrincipal(const char* aIssuerName,
const char* aSerialNumber,
nsIPrincipal **result)
{
nsresult rv;
nsCertificatePrincipal *certificate = new nsCertificatePrincipal();
if (!certificate)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(certificate);
if (NS_FAILED(certificate->Init(aIssuerName, aSerialNumber)))
{
NS_RELEASE(certificate);
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal =
do_QueryInterface((nsBasePrincipal*)certificate, &rv);
NS_RELEASE(certificate);
if (NS_FAILED(rv))
return rv;
if (mPrincipals) {
// Check to see if we already have this principal.
nsIPrincipalKey key(principal);
nsCOMPtr<nsIPrincipal> p2 = (nsIPrincipal *) mPrincipals->Get(&key);
if (p2)
principal = p2;
}
*result = principal;
NS_ADDREF(*result);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetCodebasePrincipal(nsIURI *aURI,
nsIPrincipal **result)
{
nsresult rv;
nsCodebasePrincipal *codebase = new nsCodebasePrincipal();
NS_ADDREF(codebase);
if (!codebase)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(codebase);
if (NS_FAILED(codebase->Init(aURI))) {
NS_RELEASE(codebase);
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal;
rv = codebase->QueryInterface(NS_GET_IID(nsIPrincipal),
(void **) getter_AddRefs(principal));
nsCOMPtr<nsIPrincipal> principal =
do_QueryInterface((nsBasePrincipal*)codebase, &rv);
NS_RELEASE(codebase);
if (NS_FAILED(rv))
return rv;
@ -1220,6 +1253,48 @@ nsScriptSecurityManager::enumeratePolicyCallback(const char *prefName,
NS_ASSERTION(PR_FALSE, "DOM property name invalid or not found");
}
void
nsScriptSecurityManager::enumeratePrincipalsCallback(const char *prefName,
void *aPrincipals)
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_FAILED(rv)) return;
char* data;
if (NS_FAILED(prefs->CopyCharPref(prefName, &data))) return;
static char codebaseName[] = "[Codebase ";
static char certificateName[] = "[Certificate ";
nsCOMPtr<nsIPrincipal> principal;
if (PL_strncasecmp(data, codebaseName, sizeof(codebaseName)-1) == 0)
{
nsCodebasePrincipal *codebase = new nsCodebasePrincipal();
NS_ADDREF(codebase);
if (!codebase) return;
rv = codebase->Init(data);
if (NS_FAILED(rv)) return;
principal = do_QueryInterface((nsBasePrincipal*)codebase);
NS_RELEASE(codebase);
}
else if (PL_strncasecmp(data, certificateName, sizeof(certificateName)-1) == 0)
{
nsCertificatePrincipal *certificate = new nsCertificatePrincipal();
NS_ADDREF(certificate);
if (!certificate) return;
rv = certificate->Init(data);
if (NS_FAILED(rv)) return;
principal = do_QueryInterface((nsBasePrincipal*)certificate);
NS_RELEASE(certificate);
}
else
return;
nsCRT::free(data);
nsSupportsHashtable* principals = (nsSupportsHashtable*)aPrincipals;
nsIPrincipalKey key(principal);
principals->Put(&key, principal);
}
static const char jsEnabledPrefName[] = "javascript.enabled";
static const char jsMailEnabledPrefName[] = "javascript.allow.mailnews";
@ -1276,5 +1351,16 @@ nsScriptSecurityManager::InitFromPrefs()
prefs->EnumerateChildren("security.policy",
nsScriptSecurityManager::enumeratePolicyCallback,
(void *) &info);
if (!mPrincipals)
{
mPrincipals = new nsSupportsHashtable(31);
if (!mPrincipals)
return NS_ERROR_OUT_OF_MEMORY;
}
prefs->EnumerateChildren("security.principal",
nsScriptSecurityManager::enumeratePrincipalsCallback,
(void *)mPrincipals);
return NS_OK;
}