Mozilla/mozilla/caps/src/nsPrincipal.cpp
warren%netscape.com 3c42f93bf9 Landing changes in the OJI_19980727_BRANCH since the OJI_19980727_TIP_MERGE tag.
git-svn-id: svn://10.0.0.236/trunk@6967 18797224-902f-48f8-a5cc-f745e15eee43
1998-07-31 20:19:50 +00:00

545 lines
11 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.
*/
#include "nsPrincipal.h"
#include "nsPrivilegeManager.h"
#include "structs.h"
#include "xp_mem.h"
#include "prmem.h"
#include "zig.h"
/* 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"
/* 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)
{
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);
return 0;
}
nsPrincipal *
CreateSystemPrincipal(char* zip_file_name, char *pathname)
{
ZIG* zig;
ZIG_Context * context;
SOBITEM *item;
FINGERZIG *fingPrint;
int size=0;
int slot=0;
ns_zip_t *zip;
nsPrincipal *sysPrin = NULL;
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);
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 */
//
// PUBLIC METHODS
//
nsPrincipal::nsPrincipal(nsPrincipalType type, void * key, PRUint32 key_len)
{
init(type, key, key_len);
}
nsPrincipal::nsPrincipal(nsPrincipalType type, void * key, PRUint32 key_len, void *zigObject)
{
init(type, key, key_len);
itsZig = zigObject;
}
nsPrincipal::nsPrincipal(nsPrincipalType type, void * key, PRUint32 key_len, char *stringRep)
{
init(type, key, key_len);
itsString = stringRep;
}
nsPrincipal::~nsPrincipal(void)
{
#ifdef DEBUG_raman
fprintf(stderr, "Deleting principal %s\n", itsKey);
#endif /* DEBUG_raman */
if (itsKey) {
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;
}
}
PRBool nsPrincipal::equals(nsPrincipal *prin)
{
if (prin == this)
return PR_TRUE;
if ((itsKeyLen != prin->itsKeyLen) ||
(itsType != prin->itsType))
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:
return getNickname();
default:
PR_ASSERT(PR_FALSE);
return NULL;
case nsPrincipalType_CodebaseExact:
return itsKey;
}
}
// XXX copyied from ns/lib/libjar/zig.h
#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:
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)
return itsKey;
if (itsNickname == NULL)
itsNickname = getCertAttribute(ZIG_C_NICKNAME);
return itsNickname;
}
nsPrincipalType
nsPrincipal::getType()
{
return itsType;
}
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;
if ((memcmp("https:", itsKey, strlen("https:"))) ||
(memcmp("file:", itsKey, strlen("file:"))))
return PR_TRUE;
/* signed.applets.codebase_principal_support */
if ((memcmp("http:", itsKey, strlen("http:"))) &&
(!CMGetBoolPref("signed.applets.codebase_principal_support")))
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))
return PR_TRUE;
return PR_FALSE;
}
char * nsPrincipal::toString(void)
{
char * str;
switch(itsType) {
case nsPrincipalType_CertKey:
str = getNickname();
break;
case nsPrincipalType_Cert:
case nsPrincipalType_CertFingerPrint:
case nsPrincipalType_CodebaseExact:
if (itsString != NULL)
str = itsString;
else
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;
}
//
// PRIVATE METHODS
//
void nsPrincipal::init(nsPrincipalType type, void * key, PRUint32 key_len)
{
switch(type) {
case nsPrincipalType_Cert:
case nsPrincipalType_CertKey:
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;
itsString = NULL;
itsCompanyName = NULL;
itsCertAuth = NULL;
itsSerialNo = NULL;
itsExpDate = NULL;
itsAsciiFingerPrint = NULL;
itsNickname = NULL;
}
PRInt32 nsPrincipal::computeHashCode(void * key, PRUint32 keyLen)
{
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_CodebaseExact:
return computeHashCode(itsKey, itsKeyLen);
default:
return -1;
}
return -1;
}
char * nsPrincipal::saveCert(void)
{
int result;
if ((!itsZig)) {
return NULL;
}
result = SOB_stash_cert((ZIG *)itsZig, itsKeyLen, itsKey);
if (result < 0) {
return SOB_get_error(result);
}
return NULL;
}
/* The caller is responsible for free'ing the memory */
char *
nsPrincipal::getCertAttribute(int attrib)
{
void *result;
unsigned long length;
char *attrStr;
ZIG *zig = NULL;
if (itsZig != NULL) {
zig = (ZIG *)itsZig;
}
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);
return attrStr;
}