security/nss/lib/softoken/legacydb/lgfind.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include "secitem.h"
     5 #include "pkcs11.h"
     6 #include "lgdb.h"
     7 #include "lowkeyi.h"
     8 #include "pcert.h"
     9 #include "blapi.h"
    11 #include "keydbi.h" 
    13 /*
    14  * This code maps PKCS #11 Finds to legacy database searches. This code
    15  * was orginally in pkcs11.c in previous versions of NSS.
    16  */
    18 struct SDBFindStr {
    19     CK_OBJECT_HANDLE    *handles;
    20     int                 size;
    21     int                 index;
    22     int                 array_size;
    23 };
    26 /*
    27  * free a search structure
    28  */
    29 void
    30 lg_FreeSearch(SDBFind *search)
    31 {
    32     if (search->handles) {
    33 	PORT_Free(search->handles);
    34     }
    35     PORT_Free(search);
    36 }
    38 void
    39 lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
    40 {
    41     if (search->handles == NULL) {
    42 	return;
    43     }
    44     if (search->size >= search->array_size) {
    45 	search->array_size += LG_SEARCH_BLOCK_SIZE;
    46 	search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
    47 				 sizeof(CK_OBJECT_HANDLE)* search->array_size);
    48 	if (search->handles == NULL) {
    49 	   return;
    50 	}
    51     }
    52     search->handles[search->size] = handle;
    53     search->size++;
    54 }
    56 /*
    57  * find any certs that may match the template and load them.
    58  */
    59 #define LG_CERT 	0x00000001
    60 #define LG_TRUST	0x00000002
    61 #define LG_CRL		0x00000004
    62 #define LG_SMIME	0x00000008
    63 #define LG_PRIVATE	0x00000010
    64 #define LG_PUBLIC	0x00000020
    65 #define LG_KEY		0x00000040
    67 /*
    68  * structure to collect key handles.
    69  */
    70 typedef struct lgEntryDataStr {
    71     SDB *sdb;
    72     SDBFind *searchHandles;
    73     const CK_ATTRIBUTE *template;
    74     CK_ULONG templ_count;
    75 } lgEntryData;
    78 static SECStatus
    79 lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
    80 {
    81     lgEntryData *crlData;
    82     CK_OBJECT_HANDLE class_handle;
    83     SDB *sdb;
    85     crlData = (lgEntryData *)arg;
    86     sdb = crlData->sdb;
    88     class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
    89 							LG_TOKEN_KRL_HANDLE;
    90     if (lg_tokenMatch(sdb, key, class_handle,
    91 			crlData->template, crlData->templ_count)) {
    92 	lg_addHandle(crlData->searchHandles,
    93 				 lg_mkHandle(sdb,key,class_handle));
    94     }
    95     return(SECSuccess);
    96 }
    98 static void
    99 lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl, 
   100 		unsigned long classFlags, SDBFind *search,
   101 		const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
   102 {
   103     NSSLOWCERTCertDBHandle *certHandle = NULL;
   105     certHandle = lg_getCertDB(sdb);
   106     if (certHandle == NULL) {
   107 	return;
   108     }
   109     if (derSubject->data != NULL)  {
   110 	certDBEntryRevocation *crl = 
   111 	    nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
   113 	if (crl != NULL) {
   114 	    lg_addHandle(search, lg_mkHandle(sdb, derSubject,
   115 		isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
   116 	    nsslowcert_DestroyDBEntry((certDBEntry *)crl);
   117 	}
   118     } else {
   119 	lgEntryData crlData;
   121 	/* traverse */
   122 	crlData.sdb = sdb;
   123 	crlData.searchHandles = search;
   124 	crlData.template = pTemplate;
   125 	crlData.templ_count = ulCount;
   126 	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
   127 		lg_crl_collect, (void *)&crlData);
   128 	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
   129 		lg_crl_collect, (void *)&crlData);
   130     } 
   131 }
   133 /*
   134  * structure to collect key handles.
   135  */
   136 typedef struct lgKeyDataStr {
   137     SDB *sdb;
   138     NSSLOWKEYDBHandle *keyHandle;
   139     SDBFind *searchHandles;
   140     SECItem *id;
   141     const CK_ATTRIBUTE *template;
   142     CK_ULONG templ_count;
   143     unsigned long classFlags;
   144     PRBool strict;
   145 } lgKeyData;
   147 static PRBool
   148 isSecretKey(NSSLOWKEYPrivateKey *privKey)
   149 {
   150   if (privKey->keyType == NSSLOWKEYRSAKey &&
   151                 privKey->u.rsa.publicExponent.len == 1 &&
   152                                 privKey->u.rsa.publicExponent.data[0] == 0)
   153     return PR_TRUE;
   155   return PR_FALSE;
   156 }
   160 static SECStatus
   161 lg_key_collect(DBT *key, DBT *data, void *arg)
   162 {
   163     lgKeyData *keyData;
   164     NSSLOWKEYPrivateKey *privKey = NULL;
   165     SECItem tmpDBKey;
   166     SDB *sdb;
   167     unsigned long classFlags;
   169     keyData = (lgKeyData *)arg;
   170     sdb = keyData->sdb;
   171     classFlags = keyData->classFlags;
   173     tmpDBKey.data = key->data;
   174     tmpDBKey.len = key->size;
   175     tmpDBKey.type = siBuffer;
   177     PORT_Assert(keyData->keyHandle);
   178     if (!keyData->strict && keyData->id && keyData->id->data) {
   179 	SECItem result;
   180 	PRBool haveMatch= PR_FALSE;
   181 	unsigned char hashKey[SHA1_LENGTH];
   182 	result.data = hashKey;
   183 	result.len = sizeof(hashKey);
   185 	if (keyData->id->len == 0) {
   186 	    /* Make sure this isn't a LG_KEY */
   187 	    privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, 
   188 					&tmpDBKey, keyData->sdb/*->password*/);
   189 	    if (privKey) {
   190 		/* turn off the unneeded class flags */
   191 		classFlags &= isSecretKey(privKey) ?  ~(LG_PRIVATE|LG_PUBLIC) :
   192 							~LG_KEY;
   193 		haveMatch = (PRBool)
   194 			((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
   195 		lg_nsslowkey_DestroyPrivateKey(privKey);
   196 	    }
   197 	} else {
   198 	    SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
   199 	    haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
   200 	    if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
   201 		/* This is a fix for backwards compatibility.  The key
   202 		 * database indexes private keys by the public key, and
   203 		 * versions of NSS prior to 3.4 stored the public key as
   204 		 * a signed integer.  The public key is now treated as an
   205 		 * unsigned integer, with no leading zero.  In order to
   206 		 * correctly compute the hash of an old key, it is necessary
   207 		 * to fallback and detect the leading zero.
   208 		 */
   209 		SHA1_HashBuf(hashKey, 
   210 		             (unsigned char *)key->data + 1, key->size - 1);
   211 		haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
   212 	    }
   213 	}
   214 	if (haveMatch) {
   215 	    if (classFlags & LG_PRIVATE)  {
   216 		lg_addHandle(keyData->searchHandles,
   217 			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
   218 	    }
   219 	    if (classFlags & LG_PUBLIC) {
   220 		lg_addHandle(keyData->searchHandles,
   221 			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
   222 	    }
   223 	    if (classFlags & LG_KEY) {
   224 		lg_addHandle(keyData->searchHandles,
   225 			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
   226 	    }
   227 	}
   228 	return SECSuccess;
   229     }
   231     privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey, 
   232 						 keyData->sdb/*->password*/);
   233     if ( privKey == NULL ) {
   234 	goto loser;
   235     }
   237     if (isSecretKey(privKey)) {
   238 	if ((classFlags & LG_KEY) && 
   239 		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
   240 			keyData->template, keyData->templ_count)) {
   241 	    lg_addHandle(keyData->searchHandles,
   242 		lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
   243 	}
   244     } else {
   245 	if ((classFlags & LG_PRIVATE) && 
   246 		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
   247 			keyData->template, keyData->templ_count)) {
   248 	    lg_addHandle(keyData->searchHandles,
   249 		lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
   250 	}
   251 	if ((classFlags & LG_PUBLIC) && 
   252 		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
   253 			keyData->template, keyData->templ_count)) {
   254 	    lg_addHandle(keyData->searchHandles,
   255 		lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
   256 	}
   257     }
   259 loser:
   260     if ( privKey ) {
   261 	lg_nsslowkey_DestroyPrivateKey(privKey);
   262     }
   263     return(SECSuccess);
   264 }
   266 static void
   267 lg_searchKeys(SDB *sdb, SECItem *key_id,
   268 	unsigned long classFlags, SDBFind *search, PRBool mustStrict,
   269 	const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
   270 {
   271     NSSLOWKEYDBHandle *keyHandle = NULL;
   272     NSSLOWKEYPrivateKey *privKey;
   273     lgKeyData keyData;
   274     PRBool found = PR_FALSE;
   276     keyHandle = lg_getKeyDB(sdb);
   277     if (keyHandle == NULL) {
   278 	return;
   279     }
   281     if (key_id->data) {
   282 	privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
   283 	if (privKey) {
   284 	    if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
   285     	        lg_addHandle(search,
   286 			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
   287 		found = PR_TRUE;
   288 	    }
   289 	    if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
   290     	        lg_addHandle(search,
   291 			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
   292 		found = PR_TRUE;
   293 	    }
   294 	    if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
   295     	        lg_addHandle(search,
   296 			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
   297 		found = PR_TRUE;
   298 	    }
   299     	    lg_nsslowkey_DestroyPrivateKey(privKey);
   300 	}
   301 	/* don't do the traversal if we have an up to date db */
   302 	if (keyHandle->version != 3) {
   303 	    goto loser;
   304 	}
   305 	/* don't do the traversal if it can't possibly be the correct id */
   306 	/* all soft token id's are SHA1_HASH_LEN's */
   307 	if (key_id->len != SHA1_LENGTH) {
   308 	    goto loser;
   309 	}
   310 	if (found) {
   311 	   /* if we already found some keys, don't do the traversal */
   312 	   goto loser;
   313 	}
   314     }
   315     keyData.sdb = sdb;
   316     keyData.keyHandle = keyHandle;
   317     keyData.searchHandles = search;
   318     keyData.id = key_id;
   319     keyData.template = pTemplate;
   320     keyData.templ_count = ulCount;
   321     keyData.classFlags = classFlags;
   322     keyData.strict = mustStrict ? mustStrict : LG_STRICT;
   324     nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
   326 loser:
   327     return;
   328 }
   330 /*
   331  * structure to collect certs into
   332  */
   333 typedef struct lgCertDataStr {
   334     SDB *sdb;
   335     int cert_count;
   336     int max_cert_count;
   337     NSSLOWCERTCertificate **certs;
   338     const CK_ATTRIBUTE *template;
   339     CK_ULONG	templ_count;
   340     unsigned long classFlags;
   341     PRBool	strict;
   342 } lgCertData;
   344 /*
   345  * collect all the certs from the traverse call.
   346  */	
   347 static SECStatus
   348 lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
   349 {
   350     lgCertData *cd = (lgCertData *)arg;
   352     if (cert == NULL) {
   353 	return SECSuccess;
   354     }
   356     if (cd->certs == NULL) {
   357 	return SECFailure;
   358     }
   360     if (cd->strict) {
   361 	if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
   362 	  &cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
   363 	    return SECSuccess;
   364 	}
   365 	if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
   366 	  &cert->certKey, LG_TOKEN_TYPE_TRUST, 
   367 					     cd->template, cd->templ_count)) {
   368 	    return SECSuccess;
   369 	}
   370     }
   372     /* allocate more space if we need it. This should only happen in
   373      * the general traversal case */
   374     if (cd->cert_count >= cd->max_cert_count) {
   375 	int size;
   376 	cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
   377 	size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
   378 	cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
   379 	if (cd->certs == NULL) {
   380 	    return SECFailure;
   381 	}
   382     }
   384     cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
   385     return SECSuccess;
   386 }
   388 /* provide impedence matching ... */
   389 static SECStatus
   390 lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
   391 {
   392     return lg_cert_collect(cert, arg);
   393 }
   395 static void
   396 lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
   397 {
   398     if (cert == NULL) {
   399 	    return;
   400     }
   401     if (certData->strict && 
   402 	!lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT, 
   403 				certData->template,certData->templ_count)) {
   404 	nsslowcert_DestroyCertificate(cert);
   405 	return;
   406     }
   407     certData->certs = (NSSLOWCERTCertificate **) 
   408 				PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
   409     if (certData->certs == NULL) {
   410 	nsslowcert_DestroyCertificate(cert);
   411 	return;
   412     }
   413     certData->certs[0] = cert;
   414     certData->cert_count = 1;
   415 }
   417 static void
   418 lg_CertSetupData(lgCertData *certData,int count)
   419 {
   420     certData->max_cert_count = count;
   422     if (certData->max_cert_count <= 0) {
   423 	return;
   424     }
   425     certData->certs = (NSSLOWCERTCertificate **)
   426 			 PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
   427     return;
   428 }
   430 static void
   431 lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name, 
   432 			SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN, 
   433 			SECItem *email,
   434 			unsigned long classFlags, SDBFind *handles, 
   435 			const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   436 {
   437     NSSLOWCERTCertDBHandle *certHandle = NULL;
   438     lgCertData certData;
   439     int i;
   441     certHandle = lg_getCertDB(sdb);
   442     if (certHandle == NULL) return;
   444     certData.sdb = sdb;
   445     certData.max_cert_count = 0;
   446     certData.certs = NULL;
   447     certData.cert_count = 0;
   448     certData.template = pTemplate;
   449     certData.templ_count = ulCount;
   450     certData.classFlags = classFlags; 
   451     certData.strict = LG_STRICT; 
   454     /*
   455      * Find the Cert.
   456      */
   457     if (derCert->data != NULL) {
   458 	NSSLOWCERTCertificate *cert = 
   459 			nsslowcert_FindCertByDERCert(certHandle,derCert);
   460 	lg_searchSingleCert(&certData,cert);
   461     } else if (name->data != NULL) {
   462 	char *tmp_name = (char*)PORT_Alloc(name->len+1);
   463 	int count;
   465 	if (tmp_name == NULL) {
   466 	    return;
   467 	}
   468 	PORT_Memcpy(tmp_name,name->data,name->len);
   469 	tmp_name[name->len] = 0;
   471 	count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
   472 	lg_CertSetupData(&certData,count);
   473 	nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
   474 				lg_cert_collect, &certData);
   475 	PORT_Free(tmp_name);
   476     } else if (derSubject->data != NULL) {
   477 	int count;
   479 	count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
   480 	lg_CertSetupData(&certData,count);
   481 	nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
   482 				lg_cert_collect, &certData);
   483     } else if ((issuerSN->derIssuer.data != NULL) && 
   484 			(issuerSN->serialNumber.data != NULL)) {
   485         if (classFlags & LG_CERT) {
   486 	    NSSLOWCERTCertificate *cert = 
   487 		nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
   489 	    lg_searchSingleCert(&certData,cert);
   490 	}
   491 	if (classFlags & LG_TRUST) {
   492 	    NSSLOWCERTTrust *trust = 
   493 		nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
   495 	    if (trust) {
   496 		lg_addHandle(handles,
   497 		    lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
   498 		nsslowcert_DestroyTrust(trust);
   499 	    }
   500 	}
   501     } else if (email->data != NULL) {
   502 	char *tmp_name = (char*)PORT_Alloc(email->len+1);
   503 	certDBEntrySMime *entry = NULL;
   505 	if (tmp_name == NULL) {
   506 	    return;
   507 	}
   508 	PORT_Memcpy(tmp_name,email->data,email->len);
   509 	tmp_name[email->len] = 0;
   511 	entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
   512 	if (entry) {
   513 	    int count;
   514 	    SECItem *subjectName = &entry->subjectName;
   516 	    count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
   517 	    lg_CertSetupData(&certData,count);
   518 	    nsslowcert_TraversePermCertsForSubject(certHandle, subjectName, 
   519 						lg_cert_collect, &certData);
   521 	    nsslowcert_DestroyDBEntry((certDBEntry *)entry);
   522 	}
   523 	PORT_Free(tmp_name);
   524     } else {
   525 	/* we aren't filtering the certs, we are working on all, so turn
   526 	 * on the strict filters. */
   527 	certData.strict = PR_TRUE;
   528 	lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
   529 	nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
   530     }
   532     /*
   533      * build the handles
   534      */	
   535     for (i=0 ; i < certData.cert_count ; i++) {
   536 	NSSLOWCERTCertificate *cert = certData.certs[i];
   538 	/* if we filtered it would have been on the stuff above */
   539 	if (classFlags & LG_CERT) {
   540 	    lg_addHandle(handles,
   541 		lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
   542 	}
   543 	if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
   544 	    lg_addHandle(handles,
   545 		lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
   546 	}
   547 	nsslowcert_DestroyCertificate(cert);
   548     }
   550     if (certData.certs) PORT_Free(certData.certs);
   551     return;
   552 }
   554 static SECStatus
   555 lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
   556 {
   557     lgEntryData *smimeData;
   558     SDB *sdb;
   560     smimeData = (lgEntryData *)arg;
   561     sdb = smimeData->sdb;
   563     if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
   564 			smimeData->template, smimeData->templ_count)) {
   565 	lg_addHandle(smimeData->searchHandles,
   566 				 lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
   567     }
   568     return(SECSuccess);
   569 }
   571 static void
   572 lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles, 
   573 			const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   574 {
   575     NSSLOWCERTCertDBHandle *certHandle = NULL;
   576     certDBEntrySMime *entry;
   578     certHandle = lg_getCertDB(sdb);
   579     if (certHandle == NULL) return;
   581     if (email->data != NULL) {
   582 	char *tmp_name = (char*)PORT_Alloc(email->len+1);
   584 	if (tmp_name == NULL) {
   585 	    return;
   586 	}
   587 	PORT_Memcpy(tmp_name,email->data,email->len);
   588 	tmp_name[email->len] = 0;
   590 	entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
   591 	if (entry) {
   592 	    SECItem emailKey;
   594 	    emailKey.data = (unsigned char *)tmp_name;
   595 	    emailKey.len = PORT_Strlen(tmp_name)+1;
   596 	    emailKey.type = 0;
   597 	    lg_addHandle(handles,
   598 		lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
   599 	    nsslowcert_DestroyDBEntry((certDBEntry *)entry);
   600 	}
   601 	PORT_Free(tmp_name);
   602     } else {
   603 	/* traverse */
   604 	lgEntryData smimeData;
   606 	/* traverse */
   607 	smimeData.sdb = sdb;
   608 	smimeData.searchHandles = handles;
   609 	smimeData.template = pTemplate;
   610 	smimeData.templ_count = ulCount;
   611 	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
   612 		lg_smime_collect, (void *)&smimeData);
   613     }
   614     return;
   615 }
   617 static CK_RV
   618 lg_searchTokenList(SDB *sdb, SDBFind *search,
   619 	 		const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   620 {
   621     int i;
   622     PRBool isKrl = PR_FALSE;
   623     SECItem derCert = { siBuffer, NULL, 0 };
   624     SECItem derSubject = { siBuffer, NULL, 0 };
   625     SECItem name = { siBuffer, NULL, 0 };
   626     SECItem email = { siBuffer, NULL, 0 };
   627     SECItem key_id = { siBuffer, NULL, 0 };
   628     SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
   629     SECItem cert_md5_hash  = { siBuffer, NULL, 0 };
   630     NSSLOWCERTIssuerAndSN issuerSN = {
   631 	{ siBuffer, NULL, 0 },
   632 	{ siBuffer, NULL, 0 }
   633     };
   634     SECItem *copy = NULL;
   635     CK_CERTIFICATE_TYPE certType;
   636     CK_OBJECT_CLASS objectClass;
   637     CK_RV crv;
   638     unsigned long classFlags;
   640     if (lg_getCertDB(sdb) == NULL) {
   641 	classFlags = LG_PRIVATE|LG_KEY;
   642     } else {
   643 	classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
   644     }
   646     /*
   647      * look for things to search on token objects for. If the right options
   648      * are specified, we can use them as direct indeces into the database
   649      * (rather than using linear searches. We can also use the attributes to
   650      * limit the kinds of objects we are searching for. Later we can use this
   651      * array to filter the remaining objects more finely.
   652      */
   653     for (i=0 ;classFlags && i < (int)ulCount; i++) {
   655 	switch (pTemplate[i].type) {
   656 	case CKA_SUBJECT:
   657 	    copy = &derSubject;
   658 	    classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
   659 	    break;
   660 	case CKA_ISSUER: 
   661 	    copy = &issuerSN.derIssuer;
   662 	    classFlags &= (LG_CERT|LG_TRUST);
   663 	    break;
   664 	case CKA_SERIAL_NUMBER: 
   665 	    copy = &issuerSN.serialNumber;
   666 	    classFlags &= (LG_CERT|LG_TRUST);
   667 	    break;
   668 	case CKA_VALUE:
   669 	    copy = &derCert;
   670 	    classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
   671 	    break;
   672 	case CKA_LABEL:
   673 	    copy = &name;
   674 	    break;
   675 	case CKA_NETSCAPE_EMAIL:
   676 	    copy = &email;
   677 	    classFlags &= LG_SMIME|LG_CERT;
   678 	    break;
   679 	case CKA_NETSCAPE_SMIME_TIMESTAMP:
   680 	    classFlags &= LG_SMIME;
   681 	    break;
   682 	case CKA_CLASS:
   683 	    crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
   684 	    if (crv != CKR_OK) {
   685 		classFlags = 0;
   686 		break;
   687 	    }
   688 	    switch (objectClass) {
   689 	    case CKO_CERTIFICATE:
   690 		classFlags &= LG_CERT;
   691 		break;
   692 	    case CKO_NETSCAPE_TRUST:
   693 		classFlags &= LG_TRUST;
   694 		break;
   695 	    case CKO_NETSCAPE_CRL:
   696 		classFlags &= LG_CRL;
   697 		break;
   698 	    case CKO_NETSCAPE_SMIME:
   699 		classFlags &= LG_SMIME;
   700 		break;
   701 	    case CKO_PRIVATE_KEY:
   702 		classFlags &= LG_PRIVATE;
   703 		break;
   704 	    case CKO_PUBLIC_KEY:
   705 		classFlags &= LG_PUBLIC;
   706 		break;
   707 	    case CKO_SECRET_KEY:
   708 		classFlags &= LG_KEY;
   709 		break;
   710 	    default:
   711 		classFlags = 0;
   712 		break;
   713 	    }
   714 	    break;
   715 	case CKA_PRIVATE:
   716 	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   717 		classFlags = 0;
   718 		break;
   719 	    }
   720 	    if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
   721 		classFlags &= (LG_PRIVATE|LG_KEY);
   722 	    } else {
   723 		classFlags &= ~(LG_PRIVATE|LG_KEY);
   724 	    }
   725 	    break;
   726 	case CKA_SENSITIVE:
   727 	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   728 		classFlags = 0;
   729 		break;
   730 	    }
   731 	    if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
   732 		classFlags &= (LG_PRIVATE|LG_KEY);
   733 	    } else {
   734 		classFlags = 0;
   735 	    }
   736 	    break;
   737 	case CKA_TOKEN:
   738 	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   739 		classFlags = 0;
   740 		break;
   741 	    }
   742 	    if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
   743 		classFlags = 0;
   744 	    }
   745 	    break;
   746 	case CKA_CERT_SHA1_HASH:
   747 	    classFlags &= LG_TRUST;
   748 	    copy = &cert_sha1_hash; break;
   749 	case CKA_CERT_MD5_HASH:
   750 	    classFlags &= LG_TRUST;
   751 	    copy = &cert_md5_hash; break;
   752 	case CKA_CERTIFICATE_TYPE:
   753 	    crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE,&pTemplate[i],
   754 								1,&certType);
   755 	    if (crv != CKR_OK) {
   756 		classFlags = 0;
   757 		break;
   758 	    }
   759 	    classFlags &= LG_CERT;
   760 	    if (certType != CKC_X_509) {
   761 		classFlags = 0;
   762 	    }
   763 	    break;
   764 	case CKA_ID:
   765 	    copy = &key_id;
   766 	    classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
   767 	    break;
   768 	case CKA_NETSCAPE_KRL:
   769 	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   770 		classFlags = 0;
   771 		break;
   772 	    }
   773 	    classFlags &= LG_CRL;
   774 	    isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
   775 	    break;
   776 	case CKA_MODIFIABLE:
   777 	     break;
   778 	case CKA_KEY_TYPE:
   779 	case CKA_DERIVE:
   780 	    classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
   781 	    break;
   782 	case CKA_VERIFY_RECOVER:
   783 	    classFlags &= LG_PUBLIC;
   784 	    break;
   785 	case CKA_SIGN_RECOVER:
   786 	    classFlags &= LG_PRIVATE;
   787 	    break;
   788 	case CKA_ENCRYPT:
   789 	case CKA_VERIFY:
   790 	case CKA_WRAP:
   791 	    classFlags &= LG_PUBLIC|LG_KEY;
   792 	    break;
   793 	case CKA_DECRYPT:
   794 	case CKA_SIGN:
   795 	case CKA_UNWRAP:
   796 	case CKA_ALWAYS_SENSITIVE:
   797 	case CKA_EXTRACTABLE:
   798 	case CKA_NEVER_EXTRACTABLE:
   799 	    classFlags &= LG_PRIVATE|LG_KEY;
   800 	    break;
   801 	/* can't be a certificate if it doesn't match one of the above 
   802 	 * attributes */
   803 	default: 
   804 	     classFlags  = 0;
   805 	     break;
   806 	}
   807  	if (copy) {
   808 	    copy->data = (unsigned char*)pTemplate[i].pValue;
   809 	    copy->len = pTemplate[i].ulValueLen;
   810 	}
   811 	copy = NULL;
   812     }
   814     /* certs */
   815     if (classFlags & (LG_CERT|LG_TRUST)) {
   816 	lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
   817 				 &issuerSN, &email,classFlags,search, 
   818 				pTemplate, ulCount);
   819     }
   821     /* keys */
   822     if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
   823 	PRBool mustStrict = (name.len != 0);
   824 	lg_searchKeys(sdb, &key_id, classFlags, search,
   825 			 mustStrict, pTemplate, ulCount);
   826     }
   828     /* crl's */
   829     if (classFlags & LG_CRL) {
   830 	lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
   831 			pTemplate, ulCount);
   832     }
   833     /* Add S/MIME entry stuff */
   834     if (classFlags & LG_SMIME) {
   835 	lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
   836     }
   837     return CKR_OK;
   838 }
   841 /* lg_FindObjectsInit initializes a search for token and session objects 
   842  * that match a template. */
   843 CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
   844 			 CK_ULONG ulCount, SDBFind **retSearch)
   845 {
   846     SDBFind *search;
   847     CK_RV crv = CKR_OK;
   849     *retSearch = NULL; 
   851     search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
   852     if (search == NULL) {
   853 	crv = CKR_HOST_MEMORY;
   854 	goto loser;
   855     }
   856     search->handles = (CK_OBJECT_HANDLE *)
   857 		PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
   858     if (search->handles == NULL) {
   859 	crv = CKR_HOST_MEMORY;
   860 	goto loser;
   861     }
   862     search->index = 0;
   863     search->size = 0;
   864     search->array_size = LG_SEARCH_BLOCK_SIZE;
   865     /* FIXME - do we still need to get Login state? */
   867     crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
   868     if (crv != CKR_OK) {
   869 	goto loser;
   870     }
   872     *retSearch = search;
   873     return CKR_OK;
   875 loser:
   876     if (search) {
   877 	lg_FreeSearch(search);
   878     }
   879     return crv;
   880 }
   883 /* lg_FindObjects continues a search for token and session objects 
   884  * that match a template, obtaining additional object handles. */
   885 CK_RV lg_FindObjects(SDB *sdb, SDBFind *search, 
   886     CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
   887     					CK_ULONG *pulObjectCount)
   888 {
   889     int	transfer;
   890     int left;
   892     *pulObjectCount = 0;
   893     left = search->size - search->index;
   894     transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
   895     if (transfer > 0) {
   896 	PORT_Memcpy(phObject,&search->handles[search->index],
   897                                         transfer*sizeof(CK_OBJECT_HANDLE));
   898     } else {
   899        *phObject = CK_INVALID_HANDLE;
   900     }
   902     search->index += transfer;
   903     *pulObjectCount = transfer;
   904     return CKR_OK;
   905 }
   907 /* lg_FindObjectsFinal finishes a search for token and session objects. */
   908 CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
   909 {
   911     if (search != NULL) {
   912 	lg_FreeSearch(search);
   913     }
   914     return CKR_OK;
   915 }

mercurial