Add database upgrade support.

git-svn-id: svn://10.0.0.236/branches/NSS_BOB_SHARED@226480 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rrelyea%redhat.com
2007-05-15 21:59:52 +00:00
parent 7fb0950700
commit 261c99b079
13 changed files with 1449 additions and 160 deletions

View File

@@ -351,10 +351,9 @@ lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
}
static NSSLOWCERTTrust *
lg_getTrust(LGObjectCache *obj)
lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
{
NSSLOWCERTTrust *trust;
NSSLOWCERTCertDBHandle *certHandle;
if (obj->objclass != CKO_NETSCAPE_TRUST) {
return NULL;
@@ -362,10 +361,6 @@ lg_getTrust(LGObjectCache *obj)
if (obj->objectInfo) {
return (NSSLOWCERTTrust *)obj->objectInfo;
}
certHandle = lg_getCertDB(obj->sdb);
if (!certHandle) {
return NULL;
}
trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey);
obj->objectInfo = (void *)trust;
obj->infoFree = (LGFreeFunc) nsslowcert_DestroyTrust ;
@@ -1086,8 +1081,11 @@ lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
CK_ATTRIBUTE *attribute)
{
NSSLOWCERTTrust *trust;
NSSLOWCERTCertDBHandle *certHandle;
NSSLOWCERTCertificate *cert;
unsigned char hash[SHA1_LENGTH];
unsigned int trustFlags;
CK_RV crv;
switch (type) {
case CKA_PRIVATE:
@@ -1101,11 +1099,17 @@ lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
case CKA_TRUST_EMAIL_PROTECTION:
case CKA_TRUST_CODE_SIGNING:
case CKA_TRUST_STEP_UP_APPROVED:
case CKA_ISSUER:
case CKA_SERIAL_NUMBER:
break;
default:
return lg_invalidAttribute(attribute);
}
trust = lg_getTrust(obj);
certHandle = lg_getCertDB(obj->sdb);
if (!certHandle) {
return CKR_OBJECT_HANDLE_INVALID;
}
trust = lg_getTrust(obj, certHandle);
if (trust == NULL) {
return CKR_OBJECT_HANDLE_INVALID;
}
@@ -1161,27 +1165,28 @@ trust:
break;
}
#ifdef notdef
switch (type) {
case CKA_ISSUER:
cert = lg_getCertObject(object);
cert = lg_getCert(obj, certHandle);
if (cert == NULL) break;
attr = lg_CopyAttribute(attribute,type,cert->derIssuer.data,
crv = lg_CopyAttribute(attribute,type,cert->derIssuer.data,
cert->derIssuer.len);
break;
case CKA_SERIAL_NUMBER:
cert = lg_getCertObject(object);
cert = lg_getCert(obj, certHandle);
if (cert == NULL) break;
item = SEC_ASN1EncodeItem(NULL,NULL,cert,lg_SerialTemplate);
if (item == NULL) break;
attr = lg_CopyAttribute(attribute, type, item->data, item->len);
SECITEM_FreeItem(item,PR_TRUE);
crv = lg_CopyAttribute(attribute,type,cert->derSN.data,
cert->derSN.len);
break;
default:
cert = NULL;
break;
}
if (cert) {
NSSLOWCERTDestroyCertificate(cert);
return attr;
nsslowcert_DestroyCertificate(cert);
return crv;
}
#endif
return lg_invalidAttribute(attribute);
}

View File

@@ -98,22 +98,22 @@ lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
/*
* structure to collect key handles.
*/
typedef struct lgCrlDataStr {
typedef struct lgEntryDataStr {
SDB *sdb;
SDBFind *searchHandles;
const CK_ATTRIBUTE *template;
CK_ULONG templ_count;
} lgCrlData;
} lgEntryData;
static SECStatus
lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
{
lgCrlData *crlData;
lgEntryData *crlData;
CK_OBJECT_HANDLE class_handle;
SDB *sdb;
crlData = (lgCrlData *)arg;
crlData = (lgEntryData *)arg;
sdb = crlData->sdb;
class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
@@ -147,7 +147,7 @@ lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl,
nsslowcert_DestroyDBEntry((certDBEntry *)crl);
}
} else {
lgCrlData crlData;
lgEntryData crlData;
/* traverse */
crlData.sdb = sdb;
@@ -195,9 +195,11 @@ lg_key_collect(DBT *key, DBT *data, void *arg)
NSSLOWKEYPrivateKey *privKey = NULL;
SECItem tmpDBKey;
SDB *sdb;
unsigned long classFlags;
keyData = (lgKeyData *)arg;
sdb = keyData->sdb;
classFlags = keyData->classFlags;
tmpDBKey.data = key->data;
tmpDBKey.len = key->size;
@@ -216,10 +218,11 @@ lg_key_collect(DBT *key, DBT *data, void *arg)
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
&tmpDBKey, keyData->sdb/*->password*/);
if (privKey) {
haveMatch = isSecretKey(privKey) ?
(PRBool)(keyData->classFlags & LG_KEY) != 0:
(PRBool)(keyData->classFlags &
(LG_PRIVATE|LG_PUBLIC)) != 0;
/* turn off the unneeded class flags */
classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE|LG_PUBLIC) :
~LG_KEY;
haveMatch = (PRBool)
((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
nsslowkey_DestroyPrivateKey(privKey);
}
} else {
@@ -240,15 +243,15 @@ lg_key_collect(DBT *key, DBT *data, void *arg)
}
}
if (haveMatch) {
if (keyData->classFlags & LG_PRIVATE) {
if (classFlags & LG_PRIVATE) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
}
if (keyData->classFlags & LG_PUBLIC) {
if (classFlags & LG_PUBLIC) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
}
if (keyData->classFlags & LG_KEY) {
if (classFlags & LG_KEY) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
}
@@ -263,20 +266,20 @@ lg_key_collect(DBT *key, DBT *data, void *arg)
}
if (isSecretKey(privKey)) {
if ((keyData->classFlags & LG_KEY) &&
if ((classFlags & LG_KEY) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
}
} else {
if ((keyData->classFlags & LG_PRIVATE) &&
if ((classFlags & LG_PRIVATE) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
}
if ((keyData->classFlags & LG_PUBLIC) &&
if ((classFlags & LG_PUBLIC) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
@@ -579,6 +582,23 @@ lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name,
return;
}
static SECStatus
lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
{
lgEntryData *smimeData;
SDB *sdb;
smimeData = (lgEntryData *)arg;
sdb = smimeData->sdb;
if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
smimeData->template, smimeData->templ_count)) {
lg_addHandle(smimeData->searchHandles,
lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
}
return(SECSuccess);
}
static void
lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
@@ -610,6 +630,17 @@ lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(tmp_name);
} else {
/* traverse */
lgEntryData smimeData;
/* traverse */
smimeData.sdb = sdb;
smimeData.searchHandles = handles;
smimeData.template = pTemplate;
smimeData.templ_count = ulCount;
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
lg_smime_collect, (void *)&smimeData);
}
return;
}

View File

@@ -38,7 +38,7 @@
/*
* Certificate handling code
*
* $Id: lowcert.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
* $Id: lowcert.c,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
*/
#include "seccomon.h"
@@ -187,7 +187,7 @@ nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
static int
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
SECItem *valid, SECItem *subjkey)
SECItem *valid, SECItem *subjkey, SECItem *extensions)
{
unsigned char *buf;
unsigned int buf_length;
@@ -245,6 +245,21 @@ nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
if (subjkey->data == NULL) return SECFailure;
buf_length -= (subjkey->data-buf) + subjkey->len;
buf = subjkey->data + subjkey->len;
extensions->data = NULL;
extensions->len = 0;
while (buf_length > 0) {
/* EXTENSIONS */
if (buf[0] == 0xa3) {
extensions->data = nsslowcert_dataStart(buf,buf_length,
&extensions->len, PR_FALSE, NULL);
break;
}
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy - buf) + dummylen;
buf = dummy + dummylen;
}
return SECSuccess;
}
@@ -388,6 +403,196 @@ loser:
}
static char *
nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
{
unsigned char *buf;
unsigned int buf_length;
/* unwrap outer sequence */
buf=nsslowcert_dataStart(derDN->data,derDN->len,&buf_length,PR_FALSE,NULL);
if (buf == NULL) return NULL;
/* Walk each RDN */
while (buf_length > 0) {
unsigned char *rdn;
unsigned int rdn_length;
/* grab next rdn */
rdn=nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
if (rdn == NULL) { return NULL; }
buf_length -= (rdn - buf) + rdn_length;
buf = rdn+rdn_length;
while (rdn_length > 0) {
unsigned char *ava;
unsigned int ava_length;
unsigned char *oid;
unsigned int oid_length;
unsigned char *name;
unsigned int name_length;
SECItem oidItem;
SECOidTag type;
/* unwrap the ava */
ava=nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
NULL);
if (ava == NULL) return NULL;
rdn_length -= (ava-rdn)+ava_length;
rdn = ava + ava_length;
oid=nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
NULL);
if (oid == NULL) { return NULL; }
ava_length -= (oid-ava)+oid_length;
ava = oid+oid_length;
name=nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
NULL);
if (oid == NULL) { return NULL; }
ava_length -= (name-ava)+name_length;
ava = name+name_length;
oidItem.data = oid;
oidItem.len = oid_length;
type = SECOID_FindOIDTag(&oidItem);
if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
(type == SEC_OID_RFC1274_MAIL)) {
/* Email is supposed to be IA5String, so no
* translation necessary */
char *emailAddr;
emailAddr = (char *)pkcs11_copyStaticData(name,name_length+1,
(unsigned char *)space,len);
if (emailAddr) {
emailAddr[name_length] = 0;
}
return emailAddr;
}
}
}
return NULL;
}
static char *
nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
unsigned int len)
{
unsigned char *exts;
unsigned int exts_length;
/* unwrap the sequence */
exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
&exts_length, PR_FALSE, NULL);
/* loop through extension */
while (exts && exts_length > 0) {
unsigned char * ext;
unsigned int ext_length;
unsigned char *oid;
unsigned int oid_length;
unsigned char *nameList;
unsigned int nameList_length;
SECItem oidItem;
SECOidTag type;
ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
PR_FALSE, NULL);
if (ext == NULL) { break; }
exts_length -= (ext - exts) + ext_length;
exts = ext+ext_length;
oid=nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
if (oid == NULL) { break; }
ext_length -= (oid - ext) + oid_length;
ext = oid+oid_length;
oidItem.data = oid;
oidItem.len = oid_length;
type = SECOID_FindOIDTag(&oidItem);
/* get Alt Extension */
if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
continue;
}
/* skip passed the critical flag */
if (ext[0] == 0x01) { /* BOOLEAN */
unsigned char *dummy;
unsigned int dummy_length;
dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
PR_FALSE, NULL);
if (dummy == NULL) { break; }
ext_length -= (dummy - ext) + dummy_length;
ext = dummy+dummy_length;
}
/* unwrap the name list */
nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
PR_FALSE, NULL);
if (nameList == NULL) { break; }
ext_length -= (nameList - ext) + nameList_length;
ext = nameList+nameList_length;
nameList = nsslowcert_dataStart(nameList, nameList_length,
&nameList_length, PR_FALSE, NULL);
/* loop through the name list */
while (nameList && nameList_length > 0) {
unsigned char *thisName;
unsigned int thisName_length;
thisName = nsslowcert_dataStart(nameList, nameList_length,
&thisName_length, PR_FALSE, NULL);
if (thisName == NULL) { break; }
if (nameList[0] == 0xa2) { /* DNS Name */
SECItem dn;
char *emailAddr;
dn.data = thisName;
dn.len = thisName_length;
emailAddr = nsslowcert_EmailName(&dn, space, len);
if (emailAddr) {
return emailAddr;
}
}
if (nameList[0] == 0x81) { /* RFC 822name */
char *emailAddr;
emailAddr = (char *)pkcs11_copyStaticData(thisName,
thisName_length+1, (unsigned char *)space,len);
if (emailAddr) {
emailAddr[thisName_length] = 0;
}
return emailAddr;
}
nameList_length -= (thisName-nameList) + thisName_length;
nameList = thisName + thisName_length;
}
break;
}
return NULL;
}
static char *
nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
{
char *emailAddr = NULL;
char *str;
emailAddr = nsslowcert_EmailName(&cert->derSubject,cert->emailAddrSpace,
sizeof(cert->emailAddrSpace));
/* couldn't find the email address in the DN, check the subject Alt name */
if (!emailAddr && cert->extensions.data) {
emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
sizeof(cert->emailAddrSpace));
}
/* make it lower case */
str = emailAddr;
while ( str && *str ) {
*str = tolower( *str );
str++;
}
return emailAddr;
}
/*
* take a DER certificate and decode it into a certificate structure
@@ -414,7 +619,7 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
/* decode the certificate info */
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
&cert->validity, &cert->derSubjKeyInfo);
&cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
/* cert->subjectKeyID; x509v3 subject key identifier */
cert->subjectKeyID.data = NULL;
@@ -446,11 +651,11 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
if ( rv != SECSuccess ) {
goto loser;
}
#endif
/* set the email address */
cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
#endif
cert->referenceCount = 1;
@@ -503,7 +708,8 @@ nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
NULL, NULL, NULL);
if ( rv ) {
goto loser;

View File

@@ -37,7 +37,7 @@
/*
* Permanent Certificate database handling code
*
* $Id: pcertdb.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
* $Id: pcertdb.c,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
*/
#include "lowkeyti.h"
#include "pcert.h"
@@ -4972,6 +4972,7 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
}
pkcs11_freeNickname(cert->nickname,cert->nicknameSpace);
pkcs11_freeNickname(cert->emailAddr,cert->emailAddrSpace);
pkcs11_freeStaticData(cert->certKey.data,cert->certKeySpace);
cert->certKey.data = NULL;
cert->nickname = NULL;

View File

@@ -36,7 +36,7 @@
/*
* certt.h - public data structures for the certificate library
*
* $Id: pcertt.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
* $Id: pcertt.h,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
*/
#ifndef _PCERTT_H_
#define _PCERTT_H_
@@ -146,6 +146,7 @@ struct NSSLOWCERTCertificateStr {
SECItem validity;
certDBEntryCert *dbEntry; /* database entry struct */
SECItem subjectKeyID; /* x509v3 subject key identifier */
SECItem extensions;
char *nickname;
char *emailAddr;
NSSLOWCERTCertTrust *trust;
@@ -156,6 +157,7 @@ struct NSSLOWCERTCertificateStr {
int referenceCount;
char nicknameSpace[200];
char emailAddrSpace[200];
unsigned char certKeySpace[512];
};

View File

@@ -0,0 +1,341 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* The following code handles the storage of PKCS 11 modules used by the
* NSS. This file is written to abstract away how the modules are
* stored so we can deside that later.
*/
#include "sftkdb.h"
#include "sdb.h"
#include "prsystem.h"
#include "prprf.h"
#include "lgglue.h"
#include "secerr.h"
static LGOpenFunc legacy_glue_open = NULL;
static LGReadSecmodFunc legacy_glue_readSecmod = NULL;
static LGReleaseSecmodFunc legacy_glue_releaseSecmod = NULL;
static LGDeleteSecmodFunc legacy_glue_deleteSecmod = NULL;
static LGAddSecmodFunc legacy_glue_addSecmod = NULL;
static LGShutdownFunc legacy_glue_shutdown = NULL;
/*
* The following 3 functions duplicate the work done by bl_LoadLibrary.
* We should make bl_LoadLibrary a global and replace the call to
* sftkdb_LoadLibrary(const char *libname) with it.
*/
#ifdef XP_UNIX
#include <unistd.h>
#define LG_MAX_LINKS 20
static char *
sftkdb_resolvePath(const char *orig)
{
int count = 0;
int len =0;
int ret = -1;
char *resolved = NULL;
char *source = NULL;
len = 1025; /* MAX PATH +1*/
if (strlen(orig)+1 > len) {
/* PATH TOO LONG */
return NULL;
}
resolved = PORT_Alloc(len);
if (!resolved) {
return NULL;
}
source = PORT_Alloc(len);
if (!source) {
goto loser;
}
PORT_Strcpy(source, orig);
/* Walk down all the links */
while ( count++ < LG_MAX_LINKS) {
char *tmp;
/* swap our previous sorce out with resolved */
/* read it */
ret = readlink(source, resolved, len-1);
if (ret < 0) {
break;
}
resolved[ret] = 0;
tmp = source; source = resolved; resolved = tmp;
}
if (count > 1) {
ret = 0;
}
loser:
if (resolved) {
PORT_Free(resolved);
}
if (ret < 0) {
if (source) {
PORT_Free(source);
source = NULL;
}
}
return source;
}
#endif
static PRLibrary *
sftkdb_LoadFromPath(const char *path, const char *libname)
{
char *c;
int pathLen, nameLen, fullPathLen;
char *fullPathName = NULL;
PRLibSpec libSpec;
PRLibrary *lib = NULL;
/* strip of our parent's library name */
c = strrchr(path, PR_GetDirectorySeparator());
if (!c) {
return NULL; /* invalid path */
}
pathLen = (c-path)+1;
nameLen = strlen(libname);
fullPathLen = pathLen + nameLen +1;
fullPathName = (char *)PORT_Alloc(fullPathLen);
if (fullPathName == NULL) {
return NULL; /* memory allocation error */
}
PORT_Memcpy(fullPathName, path, pathLen);
PORT_Memcpy(fullPathName+pathLen, libname, nameLen);
fullPathName[fullPathLen-1] = 0;
libSpec.type = PR_LibSpec_Pathname;
libSpec.value.pathname = fullPathName;
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
PORT_Free(fullPathName);
return lib;
}
static PRLibrary *
sftkdb_LoadLibrary(const char *libname)
{
PRLibrary *lib = NULL;
PRFuncPtr fn_addr;
char *parentLibPath = NULL;
fn_addr = (PRFuncPtr) &sftkdb_LoadLibrary;
parentLibPath = PR_GetLibraryFilePathname(SOFTOKEN_LIB_NAME, fn_addr);
if (!parentLibPath) {
goto done;
}
lib = sftkdb_LoadFromPath(parentLibPath, libname);
#ifdef XP_UNIX
/* handle symbolic link case */
if (!lib) {
char *trueParentLibPath = sftkdb_resolvePath(parentLibPath);
if (!trueParentLibPath) {
goto done;
}
lib = sftkdb_LoadFromPath(trueParentLibPath, libname);
PORT_Free(trueParentLibPath);
}
#endif
PORT_Free(parentLibPath);
done:
/* still couldn't load it, try the generic path */
if (!lib) {
PRLibSpec libSpec;
libSpec.type = PR_LibSpec_Pathname;
libSpec.value.pathname = libname;
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
}
return lib;
}
static PRLibrary *legacy_glue_lib = NULL;
static SECStatus
sftkdbLoad_Legacy()
{
PRLibrary *lib = NULL;
LGSetCryptFunc setCryptFunction = NULL;
if (legacy_glue_lib) {
return SECSuccess;
}
lib = sftkdb_LoadLibrary(SHLIB_PREFIX"lgdbm"SHLIB_VERSION"."SHLIB_SUFFIX);
if (lib == NULL) {
return SECFailure;
}
legacy_glue_open = (LGOpenFunc)PR_FindFunctionSymbol(lib, "legacy_Open");
legacy_glue_readSecmod = (LGReadSecmodFunc) PR_FindFunctionSymbol(lib,
"legacy_ReadSecmodDB");
legacy_glue_releaseSecmod = (LGReleaseSecmodFunc) PR_FindFunctionSymbol(lib,
"legacy_ReleaseSecmodDBData");
legacy_glue_deleteSecmod = (LGDeleteSecmodFunc) PR_FindFunctionSymbol(lib,
"legacy_DeleteSecmodDB");
legacy_glue_addSecmod = (LGAddSecmodFunc)PR_FindFunctionSymbol(lib,
"legacy_AddSecmodDB");
legacy_glue_shutdown = (LGShutdownFunc) PR_FindFunctionSymbol(lib,
"legacy_Shutdown");
setCryptFunction = (LGSetCryptFunc) PR_FindFunctionSymbol(lib,
"legacy_SetCryptFunctions");
if (!legacy_glue_open || !legacy_glue_readSecmod ||
!legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod ||
!legacy_glue_addSecmod || !setCryptFunction) {
PR_UnloadLibrary(lib);
return SECFailure;
}
setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub);
legacy_glue_lib = lib;
return SECSuccess;
}
CK_RV
sftkdbCall_open(const char *dir, const char *certPrefix, const char *keyPrefix,
int certVersion, int keyVersion, int flags,
SDB **certDB, SDB **keyDB)
{
SECStatus rv;
rv = sftkdbLoad_Legacy();
if (rv != SECSuccess) {
return CKR_GENERAL_ERROR;
}
if (!legacy_glue_open) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*legacy_glue_open)(dir, certPrefix, keyPrefix,
certVersion, keyVersion,
flags, certDB, keyDB);
}
char **
sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
const char *dbname, char *params, PRBool rw)
{
SECStatus rv;
rv = sftkdbLoad_Legacy();
if (rv != SECSuccess) {
return NULL;
}
if (!legacy_glue_readSecmod) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return NULL;
}
return (*legacy_glue_readSecmod)(appName, filename, dbname, params, rw);
}
SECStatus
sftkdbCall_ReleaseSecmodDBData(const char *appName,
const char *filename, const char *dbname,
char **moduleSpecList, PRBool rw)
{
SECStatus rv;
rv = sftkdbLoad_Legacy();
if (rv != SECSuccess) {
return rv;
}
if (!legacy_glue_releaseSecmod) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*legacy_glue_releaseSecmod)(appName, filename, dbname,
moduleSpecList, rw);
}
SECStatus
sftkdbCall_DeleteSecmodDB(const char *appName,
const char *filename, const char *dbname,
char *args, PRBool rw)
{
SECStatus rv;
rv = sftkdbLoad_Legacy();
if (rv != SECSuccess) {
return rv;
}
if (!legacy_glue_deleteSecmod) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*legacy_glue_deleteSecmod)(appName, filename, dbname, args, rw);
}
SECStatus
sftkdbCall_AddSecmodDB(const char *appName,
const char *filename, const char *dbname,
char *module, PRBool rw)
{
SECStatus rv;
rv = sftkdbLoad_Legacy();
if (rv != SECSuccess) {
return rv;
}
if (!legacy_glue_addSecmod) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*legacy_glue_addSecmod)(appName, filename, dbname, module, rw);
}
CK_RV
sftkdbCall_Shutdown(void)
{
CK_RV crv = CKR_OK;
if (legacy_glue_lib) {
return CKR_OK;
}
if (legacy_glue_shutdown) {
crv = (*legacy_glue_shutdown)();
}
PR_UnloadLibrary(legacy_glue_lib);
legacy_glue_lib = NULL;
legacy_glue_open = NULL;
legacy_glue_readSecmod = NULL;
legacy_glue_releaseSecmod = NULL;
legacy_glue_deleteSecmod = NULL;
legacy_glue_addSecmod = NULL;
return crv;
}

View File

@@ -0,0 +1,92 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* This code defines the glue layer between softoken and the legacy DB library
*/
#include "sdb.h"
/*
* function prototypes for the callbacks into softoken from the legacyDB
*/
typedef SECStatus (*LGEncryptFunc)(PRArenaPool *arena, SDB *sdb,
SECItem *plainText, SECItem **cipherText);
typedef SECStatus (*LGDecryptFunc)(SDB *sdb, SECItem *cipherText,
SECItem **plainText);
/*
* function prototypes for the exported functions.
*/
typedef CK_RV (*LGOpenFunc) (const char *dir, const char *certPrefix,
const char *keyPrefix,
int certVersion, int keyVersion, int flags,
SDB **certDB, SDB **keyDB);
typedef char ** (*LGReadSecmodFunc)(const char *appName,
const char *filename,
const char *dbname, char *params, PRBool rw);
typedef SECStatus (*LGReleaseSecmodFunc)(const char *appName,
const char *filename,
const char *dbname, char **params, PRBool rw);
typedef SECStatus (*LGDeleteSecmodFunc)(const char *appName,
const char *filename,
const char *dbname, char *params, PRBool rw);
typedef SECStatus (*LGAddSecmodFunc)(const char *appName,
const char *filename,
const char *dbname, char *params, PRBool rw);
typedef SECStatus (*LGShutdownFunc)(void);
typedef void (*LGSetCryptFunc)(LGEncryptFunc, LGDecryptFunc);
/*
* Softoken Glue Functions
*/
CK_RV sftkdbCall_open(const char *dir, const char *certPrefix,
const char *keyPrefix,
int certVersion, int keyVersion, int flags,
SDB **certDB, SDB **keyDB);
char ** sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
const char *dbname, char *params, PRBool rw);
SECStatus sftkdbCall_ReleaseSecmodDBData(const char *appName,
const char *filename, const char *dbname,
char **moduleSpecList, PRBool rw);
SECStatus sftkdbCall_DeleteSecmodDB(const char *appName,
const char *filename, const char *dbname,
char *args, PRBool rw);
SECStatus sftkdbCall_AddSecmodDB(const char *appName,
const char *filename, const char *dbname,
char *module, PRBool rw);
CK_RV sftkdbCall_Shutdown(void);

View File

@@ -815,7 +815,8 @@ sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
*/
PRBool optimizeSpace = isSessionObject &&
((SFTKSessionObject *)object)->optimizeSpace;
if (!optimizeSpace && (list->count < MAX_OBJECT_LIST_SIZE)) {
if (object->refLock && !optimizeSpace
&& (list->count < MAX_OBJECT_LIST_SIZE)) {
PZ_Lock(list->lock);
object->next = list->head;
list->head = object;
@@ -1805,18 +1806,18 @@ sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
search->size++;
}
static CK_OBJECT_CLASS
handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
static CK_RV
handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle,
CK_OBJECT_CLASS *objClass)
{
SFTKDBHandle *dbHandle = sftk_getDBForObject(slot, handle);
CK_ATTRIBUTE objClassTemplate;
CK_OBJECT_CLASS objClass = CKO_DATA;
*objClass = CKO_DATA;
objClassTemplate.type = CKA_CLASS;
objClassTemplate.pValue = &objClass;
objClassTemplate.ulValueLen = sizeof(objClass);
sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
return objClass;
objClassTemplate.pValue = objClass;
objClassTemplate.ulValueLen = sizeof(*objClass);
return sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
}
SFTKObject *
@@ -1825,6 +1826,7 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
SFTKObject *object = NULL;
SFTKTokenObject *tokObject = NULL;
PRBool hasLocks = PR_FALSE;
CK_RV crv;
object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0,
PR_FALSE);
@@ -1833,8 +1835,13 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
}
tokObject = (SFTKTokenObject *) object;
object->objclass = handleToClass(slot, handle);
object->handle = handle;
/* every object must have a class, if we can't get it, the object
* doesn't exist */
crv = handleToClass(slot, handle, &object->objclass);
if (crv != CKR_OK) {
goto loser;
}
object->slot = slot;
object->objectInfo = NULL;
object->infoFree = NULL;

View File

@@ -136,7 +136,7 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST
};
int known_attributes_size= sizeof(known_attributes)/
static int known_attributes_size= sizeof(known_attributes)/
sizeof(known_attributes[0]);
/* Magic for an explicit NULL. NOTE: ideally this should be
@@ -627,7 +627,60 @@ loser:
return error;
}
static CK_OBJECT_HANDLE next_obj = 0;
/*
* check to see if a candidate object handle already exists.
*/
static PRBool
sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
{
CK_RV crv;
CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 };
crv = sdb_GetAttributeValue(sdb,candidate,&template, 1);
if (crv == CKR_OBJECT_HANDLE_INVALID) {
return PR_FALSE;
}
return PR_TRUE;
}
/*
* if we're here, we are in a transaction, so it's safe
* to examine the current state of the database
*/
static CK_OBJECT_HANDLE
sdb_getObjectId(SDB *sdb)
{
CK_OBJECT_HANDLE candidate;
static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE;
int count;
/*
* get an initial object handle to use
*/
if (next_obj == CK_INVALID_HANDLE) {
PRTime time;
time = PR_Now();
next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL);
}
candidate = next_obj++;
/* detect that we've looped through all the handles... */
for (count = 0; count < 0x40000000; count++, candidate = next_obj++) {
/* mask off excess bits */
candidate &= 0x3fffffff;
/* if we hit zero, go to the next entry */
if (candidate == CK_INVALID_HANDLE) {
continue;
}
/* make sure we aren't already using */
if (!sdb_objectExists(sdb, candidate)) {
/* this one is free */
return candidate;
}
}
/* no handle is free, fail */
return CK_INVALID_HANDLE;
}
#define CREATE_CMD "INSERT INTO %s (id%s) VALUES($ID%s);"
CK_RV
@@ -642,6 +695,7 @@ sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
char *newStr = NULL;
int sqlerr = SQLITE_OK;
CK_RV error = CKR_OK;
CK_OBJECT_HANDLE this_object;
int retry = 0;
int i;
@@ -650,17 +704,19 @@ sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
}
LOCK_SQLITE()
/* This needs to get the next object ID from the database */
/* SDB_FIX_ME reviewers don't let this code through as is */
if (next_obj == 0) {
PRTime time;
time = PR_Now();
next_obj = (CK_ULONG)(time & 0x3ffffffL);
if ((*object_id != CK_INVALID_HANDLE) &&
!sdb_objectExists(sdb, *object_id)) {
this_object = *object_id;
} else {
this_object = sdb_getObjectId(sdb);
}
if (this_object == CK_INVALID_HANDLE) {
UNLOCK_SQLITE();
return CKR_HOST_MEMORY;
}
columnStr = sqlite3_mprintf("");
valueStr = sqlite3_mprintf("");
*object_id = next_obj++;
*object_id = this_object;
for (i=0; columnStr && valueStr && i < count; i++) {
newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type);
sqlite3_free(columnStr);
@@ -1186,7 +1242,7 @@ static int tableExists(sqlite3 *sqlDB, const char *tableName)
CK_RV
sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
int *needUpdate, int flags, SDB **pSdb)
int *newInit, int flags, SDB **pSdb)
{
int i;
char *initStr = NULL;
@@ -1231,6 +1287,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
inTransaction = 1;
}
if (!tableExists(sqlDB,table)) {
*newInit = 1;
if (flags != SDB_CREATE) {
error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
goto loser;
@@ -1272,7 +1329,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
sdb_p->sqlXactDB = NULL;
sdb_p->sqlXactThread = NULL;
sdb->private = sdb_p;
sdb->sdb_type = SDB_SHARED;
sdb->sdb_type = SDB_SQL;
sdb->sdb_flags = flags;
sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
sdb->sdb_FindObjects = sdb_FindObjects;
@@ -1342,17 +1399,18 @@ static char *sdb_BuildFileName(const char * directory,
CK_RV
s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
int cert_version, int key_version, int flags,
SDB **certdb, SDB **keydb)
SDB **certdb, SDB **keydb, int *newInit)
{
char *cert = sdb_BuildFileName(directory, certPrefix,
"cert", cert_version, flags);
char *key = sdb_BuildFileName(directory, keyPrefix,
"key", key_version, flags);
CK_RV error = CKR_OK;
int inUpdate, needUpdate;
int inUpdate;
*certdb = NULL;
*keydb = NULL;
*newInit = 0;
#ifdef SQLITE_UNSAFE_THREADS
if (sqlite_lock == NULL) {
@@ -1370,7 +1428,7 @@ s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
if (certdb) {
/* initialize Certificate database */
error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate,
&needUpdate, flags, certdb);
newInit, flags, certdb);
if (error != CKR_OK) {
goto loser;
}
@@ -1387,7 +1445,7 @@ s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
if (keydb) {
/* initialize the Key database */
error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate,
&needUpdate, flags, keydb);
newInit, flags, keydb);
if (error != CKR_OK) {
goto loser;
}

View File

@@ -104,7 +104,7 @@ struct SDBPasswordEntryStr {
CK_RV s_open(const char *directory, const char *certPrefix,
const char *keyPrefix,
int cert_version, int key_version,
int flags, SDB **certdb, SDB **keydb);
int flags, SDB **certdb, SDB **keydb, int *newInit);
CK_RV s_shutdown();
/* flags */

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,8 @@
typedef struct SFTKDBHandleStr SFTKDBHandle;
typedef enum {
SDB_SHARED,
SDB_LOADABLE,
SDB_SQL,
SDB_EXTERN,
SDB_LEGACY,
SDB_MULTIACCESS
} SDBType;

View File

@@ -518,8 +518,8 @@ sftk_freeParams(sftk_parameters *params)
FREE_CLEAR(params->tokens);
}
#define SHAREDB "shared:"
#define LOADABLE "load:"
#define SQLDB "sql:"
#define EXTERNDB "extern:"
#define LEGACY "dbm:"
const char *
sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
@@ -543,12 +543,12 @@ sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
cdir++;
}
configdir = cdir;
} else if (PORT_Strncmp(configdir, SHAREDB, sizeof(SHAREDB)-1) == 0) {
*dbType = SDB_SHARED;
configdir = configdir + sizeof(SHAREDB) -1;
} else if (PORT_Strncmp(configdir, LOADABLE, sizeof(LOADABLE)-1) == 0) {
*dbType = SDB_LOADABLE;
configdir = configdir + sizeof(LOADABLE) -1;
} else if (PORT_Strncmp(configdir, SQLDB, sizeof(SQLDB)-1) == 0) {
*dbType = SDB_SQL;
configdir = configdir + sizeof(SQLDB) -1;
} else if (PORT_Strncmp(configdir, EXTERNDB, sizeof(EXTERNDB)-1) == 0) {
*dbType = SDB_EXTERN;
configdir = configdir + sizeof(EXTERNDB) -1;
} else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY)-1) == 0) {
*dbType = SDB_LEGACY;
configdir = configdir + sizeof(LEGACY) -1;
@@ -559,10 +559,10 @@ sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
/* none specified, go with the legacy */
return configdir;
}
if (PORT_Strncmp(defaultType, SHAREDB, sizeof(SHAREDB)-2) == 0) {
*dbType = SDB_SHARED;
} else if (PORT_Strncmp(defaultType,LOADABLE,sizeof(LOADABLE)-2)==0) {
*dbType = SDB_LOADABLE;
if (PORT_Strncmp(defaultType, SQLDB, sizeof(SQLDB)-2) == 0) {
*dbType = SDB_SQL;
} else if (PORT_Strncmp(defaultType,EXTERNDB,sizeof(EXTERNDB)-2)==0) {
*dbType = SDB_EXTERN;
} else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY)-2) == 0) {
*dbType = SDB_LEGACY;
}
@@ -572,7 +572,7 @@ sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
char *
sftk_getSecmodName(char *param, SDBType *dbType, char **appName,
char **filename,PRBool *rw)
char **filename, PRBool *rw)
{
int next;
char *configdir = NULL;
@@ -597,10 +597,15 @@ sftk_getSecmodName(char *param, SDBType *dbType, char **appName,
if (secmodName) PORT_Free(secmodName);
secmodName = PORT_Strdup(SECMOD_DB);
}
*filename = secmodName;
*filename = secmodName;
lconfigdir = sftk_EvaluateConfigDir(configdir, dbType, appName);
/* only use the renamed secmod for legacy databases */
if ((*dbType != SDB_LEGACY) && (*dbType != SDB_MULTIACCESS)) {
secmodName="pkcs11.txt";
}
if (lconfigdir) {
value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName);
} else {