From 184058eaaf22abed55c5c918194a1220901e3593 Mon Sep 17 00:00:00 2001 From: "mstoltz%netscape.com" Date: Tue, 18 Jan 2000 21:54:01 +0000 Subject: [PATCH] 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 --- caps/idl/nsICertificatePrincipal.idl | 11 +- caps/idl/nsIPrincipal.idl | 2 + caps/idl/nsIScriptSecurityManager.idl | 2 + caps/include/nsBasePrincipal.h | 10 +- caps/include/nsCertificatePrincipal.h | 20 ++-- caps/include/nsCodebasePrincipal.h | 5 +- caps/include/nsScriptSecurityManager.h | 7 ++ caps/src/nsBasePrincipal.cpp | 61 ++++++++++ caps/src/nsCertificatePrincipal.cpp | 147 +++++++++++++++---------- caps/src/nsCodebasePrincipal.cpp | 45 +++++++- caps/src/nsScriptSecurityManager.cpp | 94 +++++++++++++++- 11 files changed, 316 insertions(+), 88 deletions(-) diff --git a/caps/idl/nsICertificatePrincipal.idl b/caps/idl/nsICertificatePrincipal.idl index 1accfb651ee..cbfc3641c4a 100644 --- a/caps/idl/nsICertificatePrincipal.idl +++ b/caps/idl/nsICertificatePrincipal.idl @@ -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; + }; diff --git a/caps/idl/nsIPrincipal.idl b/caps/idl/nsIPrincipal.idl index 18d3d781c8e..e44b862b8f3 100644 --- a/caps/idl/nsIPrincipal.idl +++ b/caps/idl/nsIPrincipal.idl @@ -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); }; diff --git a/caps/idl/nsIScriptSecurityManager.idl b/caps/idl/nsIScriptSecurityManager.idl index 38db0ec003f..cbab9c101db 100644 --- a/caps/idl/nsIScriptSecurityManager.idl +++ b/caps/idl/nsIScriptSecurityManager.idl @@ -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++ diff --git a/caps/include/nsBasePrincipal.h b/caps/include/nsBasePrincipal.h index a1d689801ff..85e7d50e8dd 100644 --- a/caps/include/nsBasePrincipal.h +++ b/caps/include/nsBasePrincipal.h @@ -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 }; diff --git a/caps/include/nsCertificatePrincipal.h b/caps/include/nsCertificatePrincipal.h index f42deab2b42..b534176f31a 100644 --- a/caps/include/nsCertificatePrincipal.h +++ b/caps/include/nsCertificatePrincipal.h @@ -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_ diff --git a/caps/include/nsCodebasePrincipal.h b/caps/include/nsCodebasePrincipal.h index dd314024eab..9b23ebd4b78 100644 --- a/caps/include/nsCodebasePrincipal.h +++ b/caps/include/nsCodebasePrincipal.h @@ -52,9 +52,12 @@ public: nsCodebasePrincipal(); - NS_IMETHOD + nsresult Init(nsIURI *uri); + nsresult + Init(const char* data); + virtual ~nsCodebasePrincipal(void); protected: diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index 59f821eaa7a..12c5b84f04f 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -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* 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); diff --git a/caps/src/nsBasePrincipal.cpp b/caps/src/nsBasePrincipal.cpp index d72821507b5..95c242a531f 100644 --- a/caps/src/nsBasePrincipal.cpp +++ b/caps/src/nsBasePrincipal.cpp @@ -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; +} diff --git a/caps/src/nsCertificatePrincipal.cpp b/caps/src/nsCertificatePrincipal.cpp index 3bef04911a1..41129508d02 100644 --- a/caps/src/nsCertificatePrincipal.cpp +++ b/caps/src/nsCertificatePrincipal.cpp @@ -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 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); } diff --git a/caps/src/nsCodebasePrincipal.cpp b/caps/src/nsCodebasePrincipal.cpp index 51e6c9d6229..42cdb0377c8 100644 --- a/caps/src/nsCodebasePrincipal.cpp +++ b/caps/src/nsCodebasePrincipal.cpp @@ -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) diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 8654320f9db..45bd567e5ea 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -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 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 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 principal; - rv = codebase->QueryInterface(NS_GET_IID(nsIPrincipal), - (void **) getter_AddRefs(principal)); + nsCOMPtr 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 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; }