818 lines
19 KiB
C++
Executable File
818 lines
19 KiB
C++
Executable File
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
/* TODO:
|
|
*
|
|
* + Remove all XXX's.
|
|
*
|
|
*/
|
|
|
|
#include "prtime.h"
|
|
#include "nsPrincipal.h"
|
|
#include "nsPrivilegeManager.h"
|
|
|
|
#include "structs.h"
|
|
#include "xp_mem.h"
|
|
#include "prmem.h"
|
|
#include "zig.h"
|
|
#include "secnav.h"
|
|
|
|
#ifdef MOZ_SECURITY
|
|
#include "navhook.h"
|
|
#include "jarutil.h"
|
|
#endif /* MOZ_SECURITY */
|
|
|
|
/* XXX: Hack to determine the system principal */
|
|
|
|
PR_BEGIN_EXTERN_C
|
|
|
|
#include "proto.h"
|
|
#include "jpermission.h"
|
|
#include "nsZip.h"
|
|
#include "fe_proto.h"
|
|
#include "nsLoadZig.h"
|
|
|
|
static void destroyCertificates(nsVector* certArray);
|
|
static nsVector* getTempCertificates(const unsigned char **certChain,
|
|
PRUint32 *certChainLengths,
|
|
PRUint32 noOfCerts);
|
|
|
|
/* XXX: Create an error object with all arguments except errorText, instead pass error enum,
|
|
This will be a method on caps consumer interface. */
|
|
PR_PUBLIC_API(int)
|
|
nsPrintZigError(int status, ZIG *zig, const char *metafile, char *pathname,
|
|
char *errortext)
|
|
{
|
|
#ifdef MOZ_SECURITY
|
|
char* data;
|
|
char* error_fmt = "# Error: %s (%d)\n#\tjar file: %s\n#\tpath: %s\n";
|
|
char* zig_name = NULL;
|
|
int len;
|
|
|
|
PR_ASSERT(errortext);
|
|
|
|
if (zig) {
|
|
zig_name = SOB_get_url(zig);
|
|
}
|
|
|
|
if (!zig_name) {
|
|
zig_name = "unknown";
|
|
}
|
|
|
|
if (!pathname) {
|
|
pathname = "";
|
|
}
|
|
|
|
/* Add 16 slop bytes */
|
|
len = strlen(error_fmt) + strlen(zig_name) + strlen(pathname) +
|
|
strlen(errortext) + 32;
|
|
|
|
if ((data = (char *)PR_MALLOC(len)) == 0) {
|
|
return 0;
|
|
}
|
|
sprintf(data, error_fmt, errortext, status, zig_name, pathname);
|
|
|
|
MWContext* someRandomContext = XP_FindSomeContext();
|
|
FE_Alert(someRandomContext, data);
|
|
PR_DELETE(data);
|
|
#endif /* MOZ_SECURITY */
|
|
|
|
return 0;
|
|
}
|
|
|
|
nsPrincipal *
|
|
CreateSystemPrincipal(char* zip_file_name, char *pathname)
|
|
{
|
|
nsPrincipal *sysPrin = NULL;
|
|
|
|
#ifdef MOZ_SECURITY
|
|
ZIG* zig;
|
|
ZIG_Context * context;
|
|
SOBITEM *item;
|
|
FINGERZIG *fingPrint;
|
|
int size=0;
|
|
int slot=0;
|
|
ns_zip_t *zip;
|
|
|
|
if (!pathname)
|
|
return NULL;
|
|
|
|
zip = ns_zip_open(zip_file_name);
|
|
if (zip == NULL) {
|
|
return NULL;
|
|
}
|
|
zig = (ZIG*)nsInitializeZig(zip, nsPrintZigError);
|
|
if (zig == NULL) {
|
|
goto done;
|
|
}
|
|
|
|
/* count the number of signers */
|
|
if ((context = SOB_find(zig, pathname, ZIG_SIGN)) == NULL) {
|
|
goto done;
|
|
}
|
|
while (SOB_find_next (context, &item) >= 0) {
|
|
size++;
|
|
}
|
|
SOB_find_end(context);
|
|
|
|
if ((context = SOB_find(zig, pathname, ZIG_SIGN)) == NULL) {
|
|
goto done;
|
|
}
|
|
while (SOB_find_next(context, &item) >= 0) {
|
|
PR_ASSERT(slot < size);
|
|
|
|
/* Allocate the Cert's FP and put them in an array */
|
|
fingPrint = (FINGERZIG *) item->data;
|
|
sysPrin = new nsPrincipal(nsPrincipalType_CertKey,
|
|
fingPrint->key,
|
|
fingPrint->length);
|
|
if (sysPrin != NULL)
|
|
break;
|
|
}
|
|
SOB_find_end(context);
|
|
|
|
done:
|
|
ns_zip_close(zip);
|
|
#endif /* MOZ_SECURITY */
|
|
return sysPrin;
|
|
}
|
|
|
|
/* XXX: Move all PR_END_EXTERN_C to end of each file */
|
|
PR_END_EXTERN_C
|
|
|
|
/* XXX: end of hack to determine the system principal */
|
|
|
|
|
|
static void destroyCertificates(nsVector* certArray)
|
|
{
|
|
#ifdef MOZ_SECURITY
|
|
if (certArray == NULL)
|
|
return;
|
|
|
|
for (PRUint32 i = certArray->GetSize(); i-- > 0; ) {
|
|
CERTCertificate *cert = (CERTCertificate *)certArray->Get(i);
|
|
if (cert != NULL) {
|
|
CERT_DestroyCertificate(cert);
|
|
certArray->Set(i, NULL);
|
|
}
|
|
}
|
|
delete certArray;
|
|
#endif /* MOZ_SECURITY */
|
|
}
|
|
|
|
|
|
static nsVector* getTempCertificates(const unsigned char **certChain,
|
|
PRUint32 *certChainLengths,
|
|
PRUint32 noOfCerts)
|
|
{
|
|
#ifndef MOZ_SECURITY
|
|
return NULL;
|
|
#else
|
|
CERTCertificate *cert;
|
|
CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
|
|
SECStatus rv;
|
|
|
|
nsVector* certArray = new nsVector();
|
|
certArray->SetSize(noOfCerts, 1);
|
|
if (certArray == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (PRUint32 i = noOfCerts; i-- > 0; ) {
|
|
SECItem derCert;
|
|
|
|
derCert.data = (unsigned char *)certChain[i];
|
|
derCert.len = certChainLengths[i];
|
|
|
|
cert = CERT_NewTempCertificate(handle, &derCert, NULL,
|
|
PR_FALSE, PR_TRUE);
|
|
|
|
if (cert != NULL) {
|
|
certArray->Set(i, (void*)cert);
|
|
} else {
|
|
// unable to add cert to the temp database
|
|
certArray->Set(i, NULL);
|
|
}
|
|
}
|
|
|
|
cert = (CERTCertificate *)certArray->Get(0);
|
|
rv = CERT_VerifyCert(handle, cert, PR_TRUE,
|
|
certUsageObjectSigner,
|
|
PR_Now(), NULL, NULL);
|
|
if (rv != SECSuccess) {
|
|
// Free the certificates and mark this principal as not trusted.
|
|
destroyCertificates(certArray);
|
|
return NULL;
|
|
}
|
|
return certArray;
|
|
#endif /* MOZ_SECURITY */
|
|
}
|
|
|
|
|
|
//
|
|
// PUBLIC METHODS
|
|
//
|
|
|
|
nsPrincipal::nsPrincipal(nsPrincipalType type, const void * key, PRUint32 key_len)
|
|
{
|
|
init(type, key, key_len);
|
|
}
|
|
|
|
nsPrincipal::nsPrincipal(nsPrincipalType type, const void * key, PRUint32 key_len, void *zigObject)
|
|
{
|
|
init(type, key, key_len);
|
|
itsZig = zigObject;
|
|
}
|
|
|
|
nsPrincipal::nsPrincipal(nsPrincipalType type, const void * key, PRUint32 key_len, char *stringRep)
|
|
{
|
|
init(type, key, key_len);
|
|
itsString = stringRep;
|
|
}
|
|
|
|
nsPrincipal::nsPrincipal(nsPrincipalType type,
|
|
const unsigned char **certChain,
|
|
PRUint32 *certChainLengths,
|
|
PRUint32 noOfCerts)
|
|
{
|
|
/* We will store the signers certificate as the key */
|
|
init(type, (void*)certChain[0], certChainLengths[0]);
|
|
itsCertArray = getTempCertificates(certChain,
|
|
certChainLengths,
|
|
noOfCerts);
|
|
}
|
|
|
|
nsPrincipal::~nsPrincipal(void)
|
|
{
|
|
if (itsKey) {
|
|
#ifdef DEBUG_raman
|
|
fprintf(stderr, "Deleting principal %s\n", itsKey);
|
|
#endif /* DEBUG_raman */
|
|
delete []itsKey;
|
|
}
|
|
if (itsCompanyName) {
|
|
delete []itsCompanyName;
|
|
}
|
|
if (itsCertAuth) {
|
|
delete []itsCertAuth;
|
|
}
|
|
if (itsSerialNo) {
|
|
delete []itsSerialNo;
|
|
}
|
|
if (itsExpDate) {
|
|
delete []itsExpDate;
|
|
}
|
|
if (itsAsciiFingerPrint) {
|
|
delete []itsAsciiFingerPrint;
|
|
}
|
|
if (itsNickname) {
|
|
delete []itsNickname;
|
|
}
|
|
if (itsCertArray) {
|
|
destroyCertificates(itsCertArray);
|
|
}
|
|
}
|
|
|
|
|
|
PRBool nsPrincipal::equals(nsPrincipal *prin)
|
|
{
|
|
if (prin == this)
|
|
return PR_TRUE;
|
|
|
|
/* Deal with CertChain principal specially */
|
|
if ((itsType == nsPrincipalType_CertChain) ||
|
|
(prin->itsType == nsPrincipalType_CertChain)) {
|
|
/* Because we have full certificate for the CertChain
|
|
* we will compare different attributes of the principal
|
|
* and if all the attributes match, then we return TRUE
|
|
*/
|
|
if ((XP_STRCMP(getSerialNo(), prin->getSerialNo()) == 0) &&
|
|
(XP_STRCMP(getSecAuth(), prin->getSecAuth()) == 0) &&
|
|
(XP_STRCMP(getExpDate(), prin->getExpDate()) == 0) &&
|
|
(XP_STRCMP(getFingerPrint(), prin->getFingerPrint()) == 0))
|
|
return PR_TRUE;
|
|
}
|
|
|
|
if ((itsType != prin->itsType) ||
|
|
(itsKeyLen != prin->itsKeyLen))
|
|
return PR_FALSE;
|
|
|
|
if (0 == memcmp(itsKey, prin->itsKey, itsKeyLen))
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
char * nsPrincipal::getVendor(void)
|
|
{
|
|
switch(itsType) {
|
|
case nsPrincipalType_Cert:
|
|
case nsPrincipalType_CertKey:
|
|
case nsPrincipalType_CertFingerPrint:
|
|
case nsPrincipalType_CertChain:
|
|
return getNickname();
|
|
|
|
default:
|
|
PR_ASSERT(PR_FALSE);
|
|
return NULL;
|
|
|
|
case nsPrincipalType_CodebaseExact:
|
|
return itsKey;
|
|
}
|
|
}
|
|
|
|
// XXX copyied from ns/lib/libjar/zig.h
|
|
// RAMAN: Why??
|
|
#ifndef ZIG_C_COMPANY
|
|
#define ZIG_C_COMPANY 1
|
|
#endif
|
|
#ifndef ZIG_C_CA
|
|
#define ZIG_C_CA 2
|
|
#endif
|
|
#ifndef ZIG_C_SERIAL
|
|
#define ZIG_C_SERIAL 3
|
|
#endif
|
|
#ifndef ZIG_C_EXPIRES
|
|
#define ZIG_C_EXPIRES 4
|
|
#endif
|
|
#ifndef ZIG_C_NICKNAME
|
|
#define ZIG_C_NICKNAME 5
|
|
#endif
|
|
#ifndef ZIG_C_FP
|
|
#define ZIG_C_FP 6
|
|
#endif
|
|
#ifndef ZIG_C_JAVA
|
|
#define ZIG_C_JAVA 100
|
|
#endif
|
|
|
|
char * nsPrincipal::getCompanyName(void)
|
|
{
|
|
if (itsCompanyName == NULL)
|
|
itsCompanyName = getCertAttribute(ZIG_C_COMPANY);
|
|
return itsCompanyName;
|
|
}
|
|
|
|
char * nsPrincipal::getSecAuth(void)
|
|
{
|
|
if (itsCertAuth == NULL)
|
|
itsCertAuth = getCertAttribute(ZIG_C_CA);
|
|
return itsCertAuth;
|
|
}
|
|
|
|
char * nsPrincipal::getSerialNo(void)
|
|
{
|
|
if (itsSerialNo == NULL)
|
|
itsSerialNo = getCertAttribute(ZIG_C_SERIAL);
|
|
return itsSerialNo;
|
|
}
|
|
|
|
char * nsPrincipal::getExpDate(void)
|
|
{
|
|
if (itsExpDate == NULL)
|
|
itsExpDate = getCertAttribute(ZIG_C_EXPIRES);
|
|
return itsExpDate;
|
|
}
|
|
|
|
char * nsPrincipal::getFingerPrint(void)
|
|
{
|
|
switch(itsType) {
|
|
case nsPrincipalType_Cert:
|
|
case nsPrincipalType_CertFingerPrint:
|
|
case nsPrincipalType_CodebaseExact:
|
|
case nsPrincipalType_CodebaseRegexp:
|
|
return toString();
|
|
|
|
case nsPrincipalType_CertKey:
|
|
case nsPrincipalType_CertChain:
|
|
if (itsAsciiFingerPrint == NULL)
|
|
itsAsciiFingerPrint = getCertAttribute(ZIG_C_FP);
|
|
return itsAsciiFingerPrint;
|
|
default:
|
|
return NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char * nsPrincipal::getNickname(void)
|
|
{
|
|
if ((nsPrincipalType_Cert == itsType) &&
|
|
(this == nsPrivilegeManager::getUnsignedPrincipal())) {
|
|
/* XXX: The following needs to i18n */
|
|
return "Unsigned classes from local hard disk";
|
|
}
|
|
|
|
if ((nsPrincipalType_Cert == itsType) &&
|
|
(this == nsPrivilegeManager::getUnknownPrincipal())) {
|
|
/* XXX: The following needs to i18n */
|
|
return "Classes for whom we don't the principal";
|
|
}
|
|
|
|
if ((nsPrincipalType_CertKey != itsType) &&
|
|
(nsPrincipalType_CertChain != itsType))
|
|
return itsKey;
|
|
|
|
if (itsNickname == NULL)
|
|
itsNickname = getCertAttribute(ZIG_C_NICKNAME);
|
|
return itsNickname;
|
|
}
|
|
|
|
nsPrincipalType
|
|
nsPrincipal::getType()
|
|
{
|
|
return itsType;
|
|
}
|
|
|
|
void*
|
|
nsPrincipal::getCertificate()
|
|
{
|
|
void* cert=NULL;
|
|
if ((itsType == nsPrincipalType_CertChain) &&
|
|
(itsCertArray != NULL)) {
|
|
cert = itsCertArray->Get(0);
|
|
}
|
|
return cert;
|
|
}
|
|
|
|
char *
|
|
nsPrincipal::getKey()
|
|
{
|
|
return itsKey;
|
|
}
|
|
|
|
PRUint32
|
|
nsPrincipal::getKeyLength()
|
|
{
|
|
return itsKeyLen;
|
|
}
|
|
|
|
PRInt32 nsPrincipal::hashCode(void)
|
|
{
|
|
return itsHashCode;
|
|
}
|
|
|
|
PRBool nsPrincipal::isCodebase(void)
|
|
{
|
|
if (itsType == nsPrincipalType_CodebaseExact)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool nsPrincipal::isCodebaseRegexp(void)
|
|
{
|
|
/* We don't support regular expressions yet */
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool nsPrincipal::isCodebaseExact(void)
|
|
{
|
|
if (itsType == nsPrincipalType_CodebaseExact)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
|
|
PRBool nsPrincipal::isSecurePrincipal(void)
|
|
{
|
|
if (this == nsPrivilegeManager::getUnknownPrincipal()) {
|
|
return PR_FALSE;
|
|
}
|
|
|
|
if (!isCodebase())
|
|
return PR_TRUE;
|
|
|
|
PR_ASSERT(itsKey != NULL);
|
|
|
|
if ((0 == memcmp("https:", itsKey, strlen("https:"))) ||
|
|
(0 == memcmp("file:", itsKey, strlen("file:"))))
|
|
return PR_TRUE;
|
|
|
|
/* signed.applets.codebase_principal_support */
|
|
if ((0 == memcmp("http:", itsKey, strlen("http:"))) &&
|
|
(CMGetBoolPref("signed.applets.codebase_principal_support")))
|
|
return PR_TRUE;
|
|
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool nsPrincipal::isTrustedCertChainPrincipal(void)
|
|
{
|
|
/* We destroy the cert array if cert chain didn't verify */
|
|
if ((itsType != nsPrincipalType_CertChain) ||
|
|
(itsCertArray == NULL))
|
|
return PR_FALSE;
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* This method is introduced to check the whether a given url base
|
|
* is a file based or any other type. Returns TRUE if the key is a
|
|
* file based url. Returns FALSE otherwise.
|
|
*/
|
|
PRBool nsPrincipal::isFileCodeBase(void)
|
|
{
|
|
|
|
if (itsKey == NULL)
|
|
return PR_FALSE;
|
|
|
|
if ((memcmp("file:", itsKey, strlen("file:"))) == 0)
|
|
return PR_TRUE;
|
|
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool nsPrincipal::isCert(void)
|
|
{
|
|
if (itsType == nsPrincipalType_Cert)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
|
|
PRBool nsPrincipal::isCertFingerprint(void)
|
|
{
|
|
if ((itsType == nsPrincipalType_CertFingerPrint) ||
|
|
(itsType == nsPrincipalType_CertKey) ||
|
|
(itsType == nsPrincipalType_CertChain))
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
|
|
char * nsPrincipal::toString(void)
|
|
{
|
|
char * str;
|
|
|
|
switch(itsType) {
|
|
case nsPrincipalType_CertKey:
|
|
case nsPrincipalType_CertChain:
|
|
str = getNickname();
|
|
break;
|
|
|
|
case nsPrincipalType_Cert:
|
|
case nsPrincipalType_CertFingerPrint:
|
|
case nsPrincipalType_CodebaseExact:
|
|
if (itsString != NULL) {
|
|
str = itsString;
|
|
} else {
|
|
PR_ASSERT(itsKey != NULL);
|
|
str = itsKey;
|
|
}
|
|
break;
|
|
default:
|
|
str = "Unknown Principal";
|
|
break;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
|
|
char * nsPrincipal::toVerboseString(void)
|
|
{
|
|
return toString();
|
|
}
|
|
|
|
char * nsPrincipal::savePrincipalPermanently(void)
|
|
{
|
|
if ((isCodebase()) || (itsZig == NULL))
|
|
return NULL;
|
|
|
|
char * ret_value = saveCert();
|
|
|
|
// Don't hold the reference to itsZig, once we have saved the
|
|
// principal's certificate permanently. Deleting this reference would
|
|
// allow us to garbage collect ZIG object and thus free up memory.
|
|
itsZig = NULL;
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
/* The following used to be LJ_GetCertificates */
|
|
nsPrincipalArray* nsPrincipal::getSigners(void* zigPtr, char* pathname)
|
|
{
|
|
nsPrincipalArray *result = NULL;
|
|
|
|
#ifdef MOZ_SECURITY
|
|
SOBITEM *item;
|
|
ZIG *zig = (ZIG *)zigPtr;
|
|
struct nsPrincipal *principal;
|
|
ZIG_Context * context;
|
|
FINGERZIG *fingPrint;
|
|
int size=0;
|
|
int slot=0;
|
|
|
|
if (!pathname)
|
|
return NULL;
|
|
|
|
if (!zig) {
|
|
return NULL;
|
|
}
|
|
|
|
/* count the number of signers */
|
|
if ((context = SOB_find(zig, pathname, ZIG_SIGN)) == NULL)
|
|
return NULL;
|
|
while (SOB_find_next (context, &item) >= 0) {
|
|
size++;
|
|
}
|
|
SOB_find_end(context);
|
|
|
|
/* Now allocate the array */
|
|
result = new nsPrincipalArray();
|
|
result->SetSize(size, 1);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((context = SOB_find(zig, pathname, ZIG_SIGN)) == NULL) {
|
|
return NULL;
|
|
}
|
|
while (SOB_find_next(context, &item) >= 0) {
|
|
PR_ASSERT(slot < size);
|
|
|
|
/* Allocate the Cert's FP and put them in an array */
|
|
fingPrint = (FINGERZIG *) item->data;
|
|
principal = nsCapsNewPrincipal(nsPrincipalType_CertKey,
|
|
fingPrint->key,
|
|
fingPrint->length,
|
|
zig);
|
|
nsCapsSetPrincipalArrayElement(result, slot++, principal);
|
|
|
|
}
|
|
SOB_find_end(context);
|
|
#endif /* MOZ_SECURITY */
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//
|
|
// PRIVATE METHODS
|
|
//
|
|
|
|
void nsPrincipal::init(nsPrincipalType type, const void * key, PRUint32 key_len)
|
|
{
|
|
switch(type) {
|
|
case nsPrincipalType_Cert:
|
|
case nsPrincipalType_CertKey:
|
|
case nsPrincipalType_CertChain:
|
|
case nsPrincipalType_CertFingerPrint:
|
|
case nsPrincipalType_CodebaseExact:
|
|
break;
|
|
|
|
default:
|
|
type = nsPrincipalType_Unknown;
|
|
}
|
|
|
|
itsType=type;
|
|
itsKey = new char[key_len+1];
|
|
memcpy(itsKey, key, key_len);
|
|
itsKey[key_len] = '\0';
|
|
#ifdef DEBUG_raman
|
|
fprintf(stderr, "Creating principal %d, %s\n", type, itsKey);
|
|
#endif /* DEBUG_raman */
|
|
itsKeyLen = key_len;
|
|
itsHashCode = computeHashCode();
|
|
itsZig = NULL;
|
|
itsCertArray = NULL;
|
|
itsString = NULL;
|
|
itsCompanyName = NULL;
|
|
itsCertAuth = NULL;
|
|
itsSerialNo = NULL;
|
|
itsExpDate = NULL;
|
|
itsAsciiFingerPrint = NULL;
|
|
itsNickname = NULL;
|
|
}
|
|
|
|
PRInt32 nsPrincipal::computeHashCode(const void * key, PRUint32 keyLen)
|
|
{
|
|
const char *cptr = (char *)key;
|
|
//
|
|
// Same basic hash algorithm as used in java.lang.String --
|
|
// no security relevance, only a performance optimization.
|
|
// The security comes from the equals() method.
|
|
//
|
|
int hashCode=0;
|
|
for (PRUint32 i = 0; i < keyLen; i++)
|
|
hashCode = hashCode * 37 + cptr[i];
|
|
return hashCode;
|
|
}
|
|
|
|
PRInt32 nsPrincipal::computeHashCode(void)
|
|
{
|
|
switch(itsType) {
|
|
case nsPrincipalType_Cert:
|
|
case nsPrincipalType_CertFingerPrint:
|
|
case nsPrincipalType_CertKey:
|
|
case nsPrincipalType_CertChain:
|
|
case nsPrincipalType_CodebaseExact:
|
|
return computeHashCode(itsKey, itsKeyLen);
|
|
default:
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
char * nsPrincipal::saveCert(void)
|
|
{
|
|
if (itsType == nsPrincipalType_CertChain) {
|
|
return NULL;
|
|
}
|
|
if ((!itsZig) || (!itsKey)) {
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef MOZ_SECURITY
|
|
int result;
|
|
result = SOB_stash_cert((ZIG *)itsZig, itsKeyLen, itsKey);
|
|
if (result < 0) {
|
|
return SOB_get_error(result);
|
|
}
|
|
#endif /* MOZ_SECURITY */
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* The caller is responsible for free'ing the memory */
|
|
char *
|
|
nsPrincipal::getCertAttribute(int attrib)
|
|
{
|
|
char *attrStr = "Untrusted certificate (unknown attributes)";
|
|
ZIG *zig = NULL;
|
|
|
|
if (itsZig != NULL) {
|
|
zig = (ZIG *)itsZig;
|
|
}
|
|
|
|
if (itsType == nsPrincipalType_CertChain) {
|
|
char *attributeStr;
|
|
if (itsCertArray == NULL) {
|
|
return "Untrusted certificate (unknown attributes)";
|
|
}
|
|
CERTCertificate *cert = (CERTCertificate *)itsCertArray->Get(0);
|
|
switch (attrib) {
|
|
#ifdef MOZ_SECURITY
|
|
case ZIG_C_COMPANY:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjSubjectName);
|
|
break;
|
|
case ZIG_C_CA:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjIssuerName);
|
|
break;
|
|
case ZIG_C_SERIAL:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjSerialNumber);
|
|
break;
|
|
case ZIG_C_EXPIRES:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjExpirationDate);
|
|
break;
|
|
case ZIG_C_NICKNAME:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjCommonName);
|
|
break;
|
|
case ZIG_C_FP:
|
|
attributeStr = SECNAV_GetJarCertInfo(cert, snjFingerprint);
|
|
break;
|
|
#endif /* MOZ_SECURITY */
|
|
default:
|
|
return NULL;
|
|
}
|
|
if (attributeStr) {
|
|
attrStr = new char[strlen(attributeStr)+1];
|
|
XP_STRCPY(attrStr, attributeStr);
|
|
PR_FREEIF(attributeStr);
|
|
}
|
|
return attrStr;
|
|
}
|
|
|
|
#ifdef MOZ_SECURITY
|
|
void *result;
|
|
unsigned long length;
|
|
if (SOB_cert_attribute(attrib, zig,
|
|
itsKeyLen, itsKey,
|
|
&result, &length) < 0) {
|
|
/* We need to print the message "invalid certificate fingerprint" */
|
|
return NULL;
|
|
}
|
|
attrStr = new char[length+1];
|
|
memcpy(attrStr, result, length);
|
|
attrStr[length] = '\0';
|
|
/* Should be SOB_FREE(result); */
|
|
XP_FREE(result);
|
|
#endif /* MOZ_SECURITY */
|
|
return attrStr;
|
|
}
|
|
|
|
|