| OLD | NEW |
| (Empty) |
| 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 | |
| 5 #include "prtime.h" | |
| 6 | |
| 7 #include "cert.h" | |
| 8 #include "certi.h" | |
| 9 #include "certdb.h" | |
| 10 #include "secitem.h" | |
| 11 #include "secder.h" | |
| 12 | |
| 13 /* Call to PK11_FreeSlot below */ | |
| 14 | |
| 15 #include "secasn1.h" | |
| 16 #include "secerr.h" | |
| 17 #include "nssilock.h" | |
| 18 #include "prmon.h" | |
| 19 #include "base64.h" | |
| 20 #include "sechash.h" | |
| 21 #include "plhash.h" | |
| 22 #include "pk11func.h" /* sigh */ | |
| 23 | |
| 24 #include "nsspki.h" | |
| 25 #include "pki.h" | |
| 26 #include "pkim.h" | |
| 27 #include "pki3hack.h" | |
| 28 #include "ckhelper.h" | |
| 29 #include "base.h" | |
| 30 #include "pkistore.h" | |
| 31 #include "dev3hack.h" | |
| 32 #include "dev.h" | |
| 33 | |
| 34 PRBool | |
| 35 SEC_CertNicknameConflict(const char *nickname, SECItem *derSubject, | |
| 36 CERTCertDBHandle *handle) | |
| 37 { | |
| 38 CERTCertificate *cert; | |
| 39 PRBool conflict = PR_FALSE; | |
| 40 | |
| 41 cert=CERT_FindCertByNickname(handle, nickname); | |
| 42 | |
| 43 if (!cert) { | |
| 44 return conflict; | |
| 45 } | |
| 46 | |
| 47 conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject); | |
| 48 CERT_DestroyCertificate(cert); | |
| 49 return conflict; | |
| 50 } | |
| 51 | |
| 52 SECStatus | |
| 53 SEC_DeletePermCertificate(CERTCertificate *cert) | |
| 54 { | |
| 55 PRStatus nssrv; | |
| 56 NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); | |
| 57 NSSCertificate *c = STAN_GetNSSCertificate(cert); | |
| 58 CERTCertTrust *certTrust; | |
| 59 | |
| 60 if (c == NULL) { | |
| 61 /* error code is set */ | |
| 62 return SECFailure; | |
| 63 } | |
| 64 | |
| 65 certTrust = nssTrust_GetCERTCertTrustForCert(c, cert); | |
| 66 if (certTrust) { | |
| 67 NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); | |
| 68 if (nssTrust) { | |
| 69 nssrv = STAN_DeleteCertTrustMatchingSlot(c); | |
| 70 if (nssrv != PR_SUCCESS) { | |
| 71 CERT_MapStanError(); | |
| 72 } | |
| 73 /* This call always returns PR_SUCCESS! */ | |
| 74 (void) nssTrust_Destroy(nssTrust); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 /* get rid of the token instances */ | |
| 79 nssrv = NSSCertificate_DeleteStoredObject(c, NULL); | |
| 80 | |
| 81 /* get rid of the cache entry */ | |
| 82 nssTrustDomain_LockCertCache(td); | |
| 83 nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); | |
| 84 nssTrustDomain_UnlockCertCache(td); | |
| 85 | |
| 86 return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; | |
| 87 } | |
| 88 | |
| 89 SECStatus | |
| 90 CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust) | |
| 91 { | |
| 92 SECStatus rv; | |
| 93 CERT_LockCertTrust(cert); | |
| 94 if ( cert->trust == NULL ) { | |
| 95 rv = SECFailure; | |
| 96 } else { | |
| 97 *trust = *cert->trust; | |
| 98 rv = SECSuccess; | |
| 99 } | |
| 100 CERT_UnlockCertTrust(cert); | |
| 101 return(rv); | |
| 102 } | |
| 103 | |
| 104 extern const NSSError NSS_ERROR_NO_ERROR; | |
| 105 extern const NSSError NSS_ERROR_INTERNAL_ERROR; | |
| 106 extern const NSSError NSS_ERROR_NO_MEMORY; | |
| 107 extern const NSSError NSS_ERROR_INVALID_POINTER; | |
| 108 extern const NSSError NSS_ERROR_INVALID_ARENA; | |
| 109 extern const NSSError NSS_ERROR_INVALID_ARENA_MARK; | |
| 110 extern const NSSError NSS_ERROR_DUPLICATE_POINTER; | |
| 111 extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED; | |
| 112 extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY; | |
| 113 extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED; | |
| 114 extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD; | |
| 115 extern const NSSError NSS_ERROR_VALUE_TOO_LARGE; | |
| 116 extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE; | |
| 117 extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT; | |
| 118 extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT; | |
| 119 extern const NSSError NSS_ERROR_INVALID_BASE64; | |
| 120 extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT; | |
| 121 extern const NSSError NSS_ERROR_INVALID_ITEM; | |
| 122 extern const NSSError NSS_ERROR_INVALID_STRING; | |
| 123 extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER; | |
| 124 extern const NSSError NSS_ERROR_INVALID_ASN1DECODER; | |
| 125 extern const NSSError NSS_ERROR_INVALID_BER; | |
| 126 extern const NSSError NSS_ERROR_INVALID_ATAV; | |
| 127 extern const NSSError NSS_ERROR_INVALID_ARGUMENT; | |
| 128 extern const NSSError NSS_ERROR_INVALID_UTF8; | |
| 129 extern const NSSError NSS_ERROR_INVALID_NSSOID; | |
| 130 extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE; | |
| 131 extern const NSSError NSS_ERROR_NOT_FOUND; | |
| 132 extern const NSSError NSS_ERROR_INVALID_PASSWORD; | |
| 133 extern const NSSError NSS_ERROR_USER_CANCELED; | |
| 134 extern const NSSError NSS_ERROR_MAXIMUM_FOUND; | |
| 135 extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND; | |
| 136 extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; | |
| 137 extern const NSSError NSS_ERROR_HASH_COLLISION; | |
| 138 extern const NSSError NSS_ERROR_DEVICE_ERROR; | |
| 139 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; | |
| 140 extern const NSSError NSS_ERROR_BUSY; | |
| 141 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; | |
| 142 extern const NSSError NSS_ERROR_PKCS11; | |
| 143 | |
| 144 | |
| 145 /* Look at the stan error stack and map it to NSS 3 errors */ | |
| 146 #define STAN_MAP_ERROR(x,y) \ | |
| 147 else if (error == (x)) { \ | |
| 148 secError = y; \ | |
| 149 } \ | |
| 150 | |
| 151 /* | |
| 152 * map Stan errors into NSS errors | |
| 153 * This function examines the stan error stack and automatically sets | |
| 154 * PORT_SetError(); to the appropriate SEC_ERROR value. | |
| 155 */ | |
| 156 void | |
| 157 CERT_MapStanError() | |
| 158 { | |
| 159 PRInt32 *errorStack; | |
| 160 NSSError error, prevError; | |
| 161 int secError; | |
| 162 int i; | |
| 163 | |
| 164 error = 0; | |
| 165 | |
| 166 errorStack = NSS_GetErrorStack(); | |
| 167 if (errorStack == 0) { | |
| 168 PORT_SetError(0); | |
| 169 return; | |
| 170 } | |
| 171 error = prevError = CKR_GENERAL_ERROR; | |
| 172 /* get the 'top 2' error codes from the stack */ | |
| 173 for (i=0; errorStack[i]; i++) { | |
| 174 prevError = error; | |
| 175 error = errorStack[i]; | |
| 176 } | |
| 177 if (error == NSS_ERROR_PKCS11) { | |
| 178 /* map it */ | |
| 179 secError = PK11_MapError(prevError); | |
| 180 } | |
| 181 STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0) | |
| 182 STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY) | |
| 183 STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA) | |
| 184 STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER) | |
| 185 STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA) | |
| 186 STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD,SEC_ERROR_BAD_PASSWORD) | |
| 187 STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY) | |
| 188 STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO) | |
| 189 STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND, | |
| 190 SEC_ERROR_UNKNOWN_ISSUER) | |
| 191 STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID) | |
| 192 STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA) | |
| 193 STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA) | |
| 194 | |
| 195 /* these are library failure for lack of a better error code */ | |
| 196 STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE) | |
| 197 STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, | |
| 198 SEC_ERROR_LIBRARY_FAILURE) | |
| 199 STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE) | |
| 200 STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE) | |
| 201 STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, | |
| 202 SEC_ERROR_LIBRARY_FAILURE) | |
| 203 STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE) | |
| 204 STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD, | |
| 205 SEC_ERROR_LIBRARY_FAILURE) | |
| 206 STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE) | |
| 207 | |
| 208 STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE) | |
| 209 | |
| 210 /* these are all invalid arguments */ | |
| 211 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS) | |
| 212 STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS) | |
| 213 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS) | |
| 214 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS) | |
| 215 STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS) | |
| 216 STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS) | |
| 217 STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS) | |
| 218 STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS) | |
| 219 STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS) | |
| 220 STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS) | |
| 221 STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS) | |
| 222 STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS) | |
| 223 STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS) | |
| 224 STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS) | |
| 225 STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS) | |
| 226 STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS) | |
| 227 STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS) | |
| 228 else { | |
| 229 secError = SEC_ERROR_LIBRARY_FAILURE; | |
| 230 } | |
| 231 PORT_SetError(secError); | |
| 232 } | |
| 233 | |
| 234 | |
| 235 | |
| 236 SECStatus | |
| 237 CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, | |
| 238 CERTCertTrust *trust) | |
| 239 { | |
| 240 SECStatus rv = SECSuccess; | |
| 241 PRStatus ret; | |
| 242 | |
| 243 ret = STAN_ChangeCertTrust(cert, trust); | |
| 244 if (ret != PR_SUCCESS) { | |
| 245 rv = SECFailure; | |
| 246 CERT_MapStanError(); | |
| 247 } | |
| 248 return rv; | |
| 249 } | |
| 250 | |
| 251 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; | |
| 252 | |
| 253 SECStatus | |
| 254 __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, | |
| 255 CERTCertTrust *trust) | |
| 256 { | |
| 257 NSSUTF8 *stanNick; | |
| 258 PK11SlotInfo *slot; | |
| 259 NSSToken *internal; | |
| 260 NSSCryptoContext *context; | |
| 261 nssCryptokiObject *permInstance; | |
| 262 NSSCertificate *c = STAN_GetNSSCertificate(cert); | |
| 263 nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; | |
| 264 nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; | |
| 265 SECStatus rv; | |
| 266 PRStatus ret; | |
| 267 | |
| 268 if (c == NULL) { | |
| 269 CERT_MapStanError(); | |
| 270 return SECFailure; | |
| 271 } | |
| 272 | |
| 273 context = c->object.cryptoContext; | |
| 274 if (!context) { | |
| 275 PORT_SetError(SEC_ERROR_ADDING_CERT); | |
| 276 return SECFailure; /* wasn't a temp cert */ | |
| 277 } | |
| 278 stanNick = nssCertificate_GetNickname(c, NULL); | |
| 279 if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { | |
| 280 /* different: take the new nickname */ | |
| 281 cert->nickname = NULL; | |
| 282 nss_ZFreeIf(stanNick); | |
| 283 stanNick = NULL; | |
| 284 } | |
| 285 if (!stanNick && nickname) { | |
| 286 /* Either there was no nickname yet, or we have a new nickname */ | |
| 287 stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL); | |
| 288 } /* else: old stanNick is identical to new nickname */ | |
| 289 /* Delete the temp instance */ | |
| 290 nssCertificateStore_Lock(context->certStore, &lockTrace); | |
| 291 nssCertificateStore_RemoveCertLOCKED(context->certStore, c); | |
| 292 nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); | |
| 293 c->object.cryptoContext = NULL; | |
| 294 /* Import the perm instance onto the internal token */ | |
| 295 slot = PK11_GetInternalKeySlot(); | |
| 296 internal = PK11Slot_GetNSSToken(slot); | |
| 297 permInstance = nssToken_ImportCertificate(internal, NULL, | |
| 298 NSSCertificateType_PKIX, | |
| 299 &c->id, | |
| 300 stanNick, | |
| 301 &c->encoding, | |
| 302 &c->issuer, | |
| 303 &c->subject, | |
| 304 &c->serial, | |
| 305 cert->emailAddr, | |
| 306 PR_TRUE); | |
| 307 nss_ZFreeIf(stanNick); | |
| 308 stanNick = NULL; | |
| 309 PK11_FreeSlot(slot); | |
| 310 if (!permInstance) { | |
| 311 if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { | |
| 312 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); | |
| 313 } | |
| 314 return SECFailure; | |
| 315 } | |
| 316 nssPKIObject_AddInstance(&c->object, permInstance); | |
| 317 nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); | |
| 318 /* reset the CERTCertificate fields */ | |
| 319 cert->nssCertificate = NULL; | |
| 320 cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */ | |
| 321 if (!cert) { | |
| 322 CERT_MapStanError(); | |
| 323 return SECFailure; | |
| 324 } | |
| 325 cert->istemp = PR_FALSE; | |
| 326 cert->isperm = PR_TRUE; | |
| 327 if (!trust) { | |
| 328 return SECSuccess; | |
| 329 } | |
| 330 ret = STAN_ChangeCertTrust(cert, trust); | |
| 331 rv = SECSuccess; | |
| 332 if (ret != PR_SUCCESS) { | |
| 333 rv = SECFailure; | |
| 334 CERT_MapStanError(); | |
| 335 } | |
| 336 return rv; | |
| 337 } | |
| 338 | |
| 339 SECStatus | |
| 340 CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, | |
| 341 CERTCertTrust *trust) | |
| 342 { | |
| 343 return __CERT_AddTempCertToPerm(cert, nickname, trust); | |
| 344 } | |
| 345 | |
| 346 CERTCertificate * | |
| 347 CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, | |
| 348 char *nickname, PRBool isperm, PRBool copyDER) | |
| 349 { | |
| 350 NSSCertificate *c; | |
| 351 CERTCertificate *cc; | |
| 352 NSSCertificate *tempCert = NULL; | |
| 353 nssPKIObject *pkio; | |
| 354 NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); | |
| 355 NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); | |
| 356 if (!isperm) { | |
| 357 NSSDER encoding; | |
| 358 NSSITEM_FROM_SECITEM(&encoding, derCert); | |
| 359 /* First, see if it is already a temp cert */ | |
| 360 c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, | |
| 361 &encoding); | |
| 362 if (!c) { | |
| 363 /* Then, see if it is already a perm cert */ | |
| 364 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, | |
| 365 &encoding); | |
| 366 } | |
| 367 if (c) { | |
| 368 /* actually, that search ends up going by issuer/serial, | |
| 369 * so it is still possible to return a cert with the same | |
| 370 * issuer/serial but a different encoding, and we're | |
| 371 * going to reject that | |
| 372 */ | |
| 373 if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { | |
| 374 nssCertificate_Destroy(c); | |
| 375 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); | |
| 376 cc = NULL; | |
| 377 } else { | |
| 378 cc = STAN_GetCERTCertificateOrRelease(c); | |
| 379 if (cc == NULL) { | |
| 380 CERT_MapStanError(); | |
| 381 } | |
| 382 } | |
| 383 return cc; | |
| 384 } | |
| 385 } | |
| 386 pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); | |
| 387 if (!pkio) { | |
| 388 CERT_MapStanError(); | |
| 389 return NULL; | |
| 390 } | |
| 391 c = nss_ZNEW(pkio->arena, NSSCertificate); | |
| 392 if (!c) { | |
| 393 CERT_MapStanError(); | |
| 394 nssPKIObject_Destroy(pkio); | |
| 395 return NULL; | |
| 396 } | |
| 397 c->object = *pkio; | |
| 398 if (copyDER) { | |
| 399 nssItem_Create(c->object.arena, &c->encoding, | |
| 400 derCert->len, derCert->data); | |
| 401 } else { | |
| 402 NSSITEM_FROM_SECITEM(&c->encoding, derCert); | |
| 403 } | |
| 404 /* Forces a decoding of the cert in order to obtain the parts used | |
| 405 * below | |
| 406 */ | |
| 407 /* 'c' is not adopted here, if we fail loser frees what has been | |
| 408 * allocated so far for 'c' */ | |
| 409 cc = STAN_GetCERTCertificate(c); | |
| 410 if (!cc) { | |
| 411 CERT_MapStanError(); | |
| 412 goto loser; | |
| 413 } | |
| 414 nssItem_Create(c->object.arena, | |
| 415 &c->issuer, cc->derIssuer.len, cc->derIssuer.data); | |
| 416 nssItem_Create(c->object.arena, | |
| 417 &c->subject, cc->derSubject.len, cc->derSubject.data); | |
| 418 if (PR_TRUE) { | |
| 419 /* CERTCertificate stores serial numbers decoded. I need the DER | |
| 420 * here. sigh. | |
| 421 */ | |
| 422 SECItem derSerial = { 0 }; | |
| 423 CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); | |
| 424 if (!derSerial.data) goto loser; | |
| 425 nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.dat
a); | |
| 426 PORT_Free(derSerial.data); | |
| 427 } | |
| 428 if (nickname) { | |
| 429 c->object.tempName = nssUTF8_Create(c->object.arena, | |
| 430 nssStringType_UTF8String, | |
| 431 (NSSUTF8 *)nickname, | |
| 432 PORT_Strlen(nickname)); | |
| 433 } | |
| 434 if (cc->emailAddr && cc->emailAddr[0]) { | |
| 435 c->email = nssUTF8_Create(c->object.arena, | |
| 436 nssStringType_PrintableString, | |
| 437 (NSSUTF8 *)cc->emailAddr, | |
| 438 PORT_Strlen(cc->emailAddr)); | |
| 439 } | |
| 440 | |
| 441 tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); | |
| 442 if (!tempCert) { | |
| 443 CERT_MapStanError(); | |
| 444 goto loser; | |
| 445 } | |
| 446 /* destroy our copy */ | |
| 447 NSSCertificate_Destroy(c); | |
| 448 /* and use the stored entry */ | |
| 449 c = tempCert; | |
| 450 cc = STAN_GetCERTCertificateOrRelease(c); | |
| 451 if (!cc) { | |
| 452 /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ | |
| 453 CERT_MapStanError(); | |
| 454 return NULL; | |
| 455 } | |
| 456 | |
| 457 cc->istemp = PR_TRUE; | |
| 458 cc->isperm = PR_FALSE; | |
| 459 return cc; | |
| 460 loser: | |
| 461 /* Perhaps this should be nssCertificate_Destroy(c) */ | |
| 462 nssPKIObject_Destroy(&c->object); | |
| 463 return NULL; | |
| 464 } | |
| 465 | |
| 466 /* This symbol is exported for backward compatibility. */ | |
| 467 CERTCertificate * | |
| 468 __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, | |
| 469 char *nickname, PRBool isperm, PRBool copyDER) | |
| 470 { | |
| 471 return CERT_NewTempCertificate(handle, derCert, nickname, | |
| 472 isperm, copyDER); | |
| 473 } | |
| 474 | |
| 475 /* maybe all the wincx's should be some const for internal token login? */ | |
| 476 CERTCertificate * | |
| 477 CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndS
N) | |
| 478 { | |
| 479 PK11SlotInfo *slot; | |
| 480 CERTCertificate *cert; | |
| 481 | |
| 482 cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL); | |
| 483 if (cert && slot) { | |
| 484 PK11_FreeSlot(slot); | |
| 485 } | |
| 486 | |
| 487 return cert; | |
| 488 } | |
| 489 | |
| 490 static NSSCertificate * | |
| 491 get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp) | |
| 492 { | |
| 493 NSSUsage usage; | |
| 494 NSSCertificate *arr[3]; | |
| 495 if (!ct) { | |
| 496 return nssCertificate_AddRef(cp); | |
| 497 } else if (!cp) { | |
| 498 return nssCertificate_AddRef(ct); | |
| 499 } | |
| 500 arr[0] = ct; | |
| 501 arr[1] = cp; | |
| 502 arr[2] = NULL; | |
| 503 usage.anyUsage = PR_TRUE; | |
| 504 return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL); | |
| 505 } | |
| 506 | |
| 507 CERTCertificate * | |
| 508 CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) | |
| 509 { | |
| 510 NSSCertificate *cp, *ct, *c; | |
| 511 NSSDER subject; | |
| 512 NSSUsage usage; | |
| 513 NSSCryptoContext *cc; | |
| 514 NSSITEM_FROM_SECITEM(&subject, name); | |
| 515 usage.anyUsage = PR_TRUE; | |
| 516 cc = STAN_GetDefaultCryptoContext(); | |
| 517 ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, | |
| 518 NULL, &usage, NULL); | |
| 519 cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, | |
| 520 NULL, &usage, NULL); | |
| 521 c = get_best_temp_or_perm(ct, cp); | |
| 522 if (ct) { | |
| 523 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
| 524 } | |
| 525 if (cp) { | |
| 526 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp)); | |
| 527 } | |
| 528 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
| 529 } | |
| 530 | |
| 531 CERTCertificate * | |
| 532 CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) | |
| 533 { | |
| 534 CERTCertList *list; | |
| 535 CERTCertificate *cert = NULL; | |
| 536 CERTCertListNode *node, *head; | |
| 537 | |
| 538 list = CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); | |
| 539 if (list == NULL) return NULL; | |
| 540 | |
| 541 node = head = CERT_LIST_HEAD(list); | |
| 542 if (head) { | |
| 543 do { | |
| 544 if (node->cert && | |
| 545 SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID) ) { | |
| 546 cert = CERT_DupCertificate(node->cert); | |
| 547 goto done; | |
| 548 } | |
| 549 node = CERT_LIST_NEXT(node); | |
| 550 } while (node && head != node); | |
| 551 } | |
| 552 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); | |
| 553 done: | |
| 554 if (list) { | |
| 555 CERT_DestroyCertList(list); | |
| 556 } | |
| 557 return cert; | |
| 558 } | |
| 559 | |
| 560 CERTCertificate * | |
| 561 CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname) | |
| 562 { | |
| 563 NSSCryptoContext *cc; | |
| 564 NSSCertificate *c, *ct; | |
| 565 CERTCertificate *cert; | |
| 566 NSSUsage usage; | |
| 567 usage.anyUsage = PR_TRUE; | |
| 568 cc = STAN_GetDefaultCryptoContext(); | |
| 569 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, | |
| 570 NULL, &usage, NULL); | |
| 571 cert = PK11_FindCertFromNickname(nickname, NULL); | |
| 572 c = NULL; | |
| 573 if (cert) { | |
| 574 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); | |
| 575 CERT_DestroyCertificate(cert); | |
| 576 if (ct) { | |
| 577 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
| 578 } | |
| 579 } else { | |
| 580 c = ct; | |
| 581 } | |
| 582 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
| 583 } | |
| 584 | |
| 585 CERTCertificate * | |
| 586 CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) | |
| 587 { | |
| 588 NSSCryptoContext *cc; | |
| 589 NSSCertificate *c; | |
| 590 NSSDER encoding; | |
| 591 NSSITEM_FROM_SECITEM(&encoding, derCert); | |
| 592 cc = STAN_GetDefaultCryptoContext(); | |
| 593 c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); | |
| 594 if (!c) { | |
| 595 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, | |
| 596 &encoding); | |
| 597 if (!c) return NULL; | |
| 598 } | |
| 599 return STAN_GetCERTCertificateOrRelease(c); | |
| 600 } | |
| 601 | |
| 602 static CERTCertificate * | |
| 603 common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, | |
| 604 const char *name, | |
| 605 PRBool anyUsage, | |
| 606 SECCertUsage lookingForUsage) | |
| 607 { | |
| 608 NSSCryptoContext *cc; | |
| 609 NSSCertificate *c, *ct; | |
| 610 CERTCertificate *cert = NULL; | |
| 611 NSSUsage usage; | |
| 612 CERTCertList *certlist; | |
| 613 | |
| 614 if (NULL == name) { | |
| 615 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 616 return NULL; | |
| 617 } | |
| 618 | |
| 619 usage.anyUsage = anyUsage; | |
| 620 | |
| 621 if (!anyUsage) { | |
| 622 usage.nss3lookingForCA = PR_FALSE; | |
| 623 usage.nss3usage = lookingForUsage; | |
| 624 } | |
| 625 | |
| 626 cc = STAN_GetDefaultCryptoContext(); | |
| 627 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, | |
| 628 NULL, &usage, NULL); | |
| 629 if (!ct && PORT_Strchr(name, '@') != NULL) { | |
| 630 char* lowercaseName = CERT_FixupEmailAddr(name); | |
| 631 if (lowercaseName) { | |
| 632 ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, | |
| 633 NULL, &usage, NULL); | |
| 634 PORT_Free(lowercaseName); | |
| 635 } | |
| 636 } | |
| 637 | |
| 638 if (anyUsage) { | |
| 639 cert = PK11_FindCertFromNickname(name, NULL); | |
| 640 } | |
| 641 else { | |
| 642 if (ct) { | |
| 643 /* Does ct really have the required usage? */ | |
| 644 nssDecodedCert *dc; | |
| 645 dc = nssCertificate_GetDecoding(ct); | |
| 646 if (!dc->matchUsage(dc, &usage)) { | |
| 647 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
| 648 ct = NULL; | |
| 649 } | |
| 650 } | |
| 651 | |
| 652 certlist = PK11_FindCertsFromNickname(name, NULL); | |
| 653 if (certlist) { | |
| 654 SECStatus rv = CERT_FilterCertListByUsage(certlist, | |
| 655 lookingForUsage, | |
| 656 PR_FALSE); | |
| 657 if (SECSuccess == rv && | |
| 658 !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { | |
| 659 cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert); | |
| 660 } | |
| 661 CERT_DestroyCertList(certlist); | |
| 662 } | |
| 663 } | |
| 664 | |
| 665 if (cert) { | |
| 666 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); | |
| 667 CERT_DestroyCertificate(cert); | |
| 668 if (ct) { | |
| 669 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
| 670 } | |
| 671 } else { | |
| 672 c = ct; | |
| 673 } | |
| 674 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
| 675 } | |
| 676 | |
| 677 CERTCertificate * | |
| 678 CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name) | |
| 679 { | |
| 680 return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, | |
| 681 PR_TRUE, 0); | |
| 682 } | |
| 683 | |
| 684 CERTCertificate * | |
| 685 CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, | |
| 686 const char *name, | |
| 687 SECCertUsage lookingForUsage) | |
| 688 { | |
| 689 return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, | |
| 690 PR_FALSE, | |
| 691 lookingForUsage); | |
| 692 } | |
| 693 | |
| 694 static void | |
| 695 add_to_subject_list(CERTCertList *certList, CERTCertificate *cert, | |
| 696 PRBool validOnly, int64 sorttime) | |
| 697 { | |
| 698 SECStatus secrv; | |
| 699 if (!validOnly || | |
| 700 CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) | |
| 701 == secCertTimeValid) { | |
| 702 secrv = CERT_AddCertToListSorted(certList, cert, | |
| 703 CERT_SortCBValidity, | |
| 704 (void *)&sorttime); | |
| 705 if (secrv != SECSuccess) { | |
| 706 CERT_DestroyCertificate(cert); | |
| 707 } | |
| 708 } else { | |
| 709 CERT_DestroyCertificate(cert); | |
| 710 } | |
| 711 } | |
| 712 | |
| 713 CERTCertList * | |
| 714 CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, | |
| 715 SECItem *name, int64 sorttime, PRBool validOnly) | |
| 716 { | |
| 717 NSSCryptoContext *cc; | |
| 718 NSSCertificate **tSubjectCerts, **pSubjectCerts; | |
| 719 NSSCertificate **ci; | |
| 720 CERTCertificate *cert; | |
| 721 NSSDER subject; | |
| 722 PRBool myList = PR_FALSE; | |
| 723 cc = STAN_GetDefaultCryptoContext(); | |
| 724 NSSITEM_FROM_SECITEM(&subject, name); | |
| 725 /* Collect both temp and perm certs for the subject */ | |
| 726 tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc, | |
| 727 &subject, | |
| 728 NULL, | |
| 729 0, | |
| 730 NULL); | |
| 731 pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, | |
| 732 &subject, | |
| 733 NULL, | |
| 734 0, | |
| 735 NULL); | |
| 736 if (!tSubjectCerts && !pSubjectCerts) { | |
| 737 return NULL; | |
| 738 } | |
| 739 if (certList == NULL) { | |
| 740 certList = CERT_NewCertList(); | |
| 741 myList = PR_TRUE; | |
| 742 if (!certList) goto loser; | |
| 743 } | |
| 744 /* Iterate over the matching temp certs. Add them to the list */ | |
| 745 ci = tSubjectCerts; | |
| 746 while (ci && *ci) { | |
| 747 cert = STAN_GetCERTCertificateOrRelease(*ci); | |
| 748 /* *ci may be invalid at this point, don't reference it again */ | |
| 749 if (cert) { | |
| 750 /* NOTE: add_to_subject_list adopts the incoming cert. */ | |
| 751 add_to_subject_list(certList, cert, validOnly, sorttime); | |
| 752 } | |
| 753 ci++; | |
| 754 } | |
| 755 /* Iterate over the matching perm certs. Add them to the list */ | |
| 756 ci = pSubjectCerts; | |
| 757 while (ci && *ci) { | |
| 758 cert = STAN_GetCERTCertificateOrRelease(*ci); | |
| 759 /* *ci may be invalid at this point, don't reference it again */ | |
| 760 if (cert) { | |
| 761 /* NOTE: add_to_subject_list adopts the incoming cert. */ | |
| 762 add_to_subject_list(certList, cert, validOnly, sorttime); | |
| 763 } | |
| 764 ci++; | |
| 765 } | |
| 766 /* all the references have been adopted or freed at this point, just | |
| 767 * free the arrays now */ | |
| 768 nss_ZFreeIf(tSubjectCerts); | |
| 769 nss_ZFreeIf(pSubjectCerts); | |
| 770 return certList; | |
| 771 loser: | |
| 772 /* need to free the references in tSubjectCerts and pSubjectCerts! */ | |
| 773 nssCertificateArray_Destroy(tSubjectCerts); | |
| 774 nssCertificateArray_Destroy(pSubjectCerts); | |
| 775 if (myList && certList != NULL) { | |
| 776 CERT_DestroyCertList(certList); | |
| 777 } | |
| 778 return NULL; | |
| 779 } | |
| 780 | |
| 781 void | |
| 782 CERT_DestroyCertificate(CERTCertificate *cert) | |
| 783 { | |
| 784 if ( cert ) { | |
| 785 /* don't use STAN_GetNSSCertificate because we don't want to | |
| 786 * go to the trouble of translating the CERTCertificate into | |
| 787 * an NSSCertificate just to destroy it. If it hasn't been done | |
| 788 * yet, don't do it at all. | |
| 789 */ | |
| 790 NSSCertificate *tmp = cert->nssCertificate; | |
| 791 if (tmp) { | |
| 792 /* delete the NSSCertificate */ | |
| 793 NSSCertificate_Destroy(tmp); | |
| 794 } else if (cert->arena) { | |
| 795 PORT_FreeArena(cert->arena, PR_FALSE); | |
| 796 } | |
| 797 } | |
| 798 return; | |
| 799 } | |
| 800 | |
| 801 int | |
| 802 CERT_GetDBContentVersion(CERTCertDBHandle *handle) | |
| 803 { | |
| 804 /* should read the DB content version from the pkcs #11 device */ | |
| 805 return 0; | |
| 806 } | |
| 807 | |
| 808 SECStatus | |
| 809 certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr, | |
| 810 SECItem *emailProfile, SECItem *profileTime) | |
| 811 { | |
| 812 int64 oldtime; | |
| 813 int64 newtime; | |
| 814 SECStatus rv = SECFailure; | |
| 815 PRBool saveit; | |
| 816 SECItem oldprof, oldproftime; | |
| 817 SECItem *oldProfile = NULL; | |
| 818 SECItem *oldProfileTime = NULL; | |
| 819 PK11SlotInfo *slot = NULL; | |
| 820 NSSCertificate *c; | |
| 821 NSSCryptoContext *cc; | |
| 822 nssSMIMEProfile *stanProfile = NULL; | |
| 823 PRBool freeOldProfile = PR_FALSE; | |
| 824 | |
| 825 c = STAN_GetNSSCertificate(cert); | |
| 826 if (!c) return SECFailure; | |
| 827 cc = c->object.cryptoContext; | |
| 828 if (cc != NULL) { | |
| 829 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); | |
| 830 if (stanProfile) { | |
| 831 PORT_Assert(stanProfile->profileData); | |
| 832 SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData); | |
| 833 oldProfile = &oldprof; | |
| 834 SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime); | |
| 835 oldProfileTime = &oldproftime; | |
| 836 } | |
| 837 } else { | |
| 838 oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr, | |
| 839 &cert->derSubject, &oldProfileTime); | |
| 840 freeOldProfile = PR_TRUE; | |
| 841 } | |
| 842 | |
| 843 saveit = PR_FALSE; | |
| 844 | |
| 845 /* both profileTime and emailProfile have to exist or not exist */ | |
| 846 if ( emailProfile == NULL ) { | |
| 847 profileTime = NULL; | |
| 848 } else if ( profileTime == NULL ) { | |
| 849 emailProfile = NULL; | |
| 850 } | |
| 851 | |
| 852 if ( oldProfileTime == NULL ) { | |
| 853 saveit = PR_TRUE; | |
| 854 } else { | |
| 855 /* there was already a profile for this email addr */ | |
| 856 if ( profileTime ) { | |
| 857 /* we have an old and new profile - save whichever is more recent*/ | |
| 858 if ( oldProfileTime->len == 0 ) { | |
| 859 /* always replace if old entry doesn't have a time */ | |
| 860 oldtime = LL_MININT; | |
| 861 } else { | |
| 862 rv = DER_UTCTimeToTime(&oldtime, oldProfileTime); | |
| 863 if ( rv != SECSuccess ) { | |
| 864 goto loser; | |
| 865 } | |
| 866 } | |
| 867 | |
| 868 rv = DER_UTCTimeToTime(&newtime, profileTime); | |
| 869 if ( rv != SECSuccess ) { | |
| 870 goto loser; | |
| 871 } | |
| 872 | |
| 873 if ( LL_CMP(newtime, >, oldtime ) ) { | |
| 874 /* this is a newer profile, save it and cert */ | |
| 875 saveit = PR_TRUE; | |
| 876 } | |
| 877 } else { | |
| 878 saveit = PR_TRUE; | |
| 879 } | |
| 880 } | |
| 881 | |
| 882 | |
| 883 if (saveit) { | |
| 884 if (cc) { | |
| 885 if (stanProfile) { | |
| 886 /* stanProfile is already stored in the crypto context, | |
| 887 * overwrite the data | |
| 888 */ | |
| 889 NSSArena *arena = stanProfile->object.arena; | |
| 890 stanProfile->profileTime = nssItem_Create(arena, | |
| 891 NULL, | |
| 892 profileTime->len, | |
| 893 profileTime->data); | |
| 894 stanProfile->profileData = nssItem_Create(arena, | |
| 895 NULL, | |
| 896 emailProfile->len, | |
| 897 emailProfile->data); | |
| 898 } else if (profileTime && emailProfile) { | |
| 899 PRStatus nssrv; | |
| 900 NSSItem profTime, profData; | |
| 901 NSSITEM_FROM_SECITEM(&profTime, profileTime); | |
| 902 NSSITEM_FROM_SECITEM(&profData, emailProfile); | |
| 903 stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData); | |
| 904 if (!stanProfile) goto loser; | |
| 905 nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile); | |
| 906 rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; | |
| 907 } | |
| 908 } else { | |
| 909 rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr, | |
| 910 &cert->derSubject, emailProfile, profileTime); | |
| 911 } | |
| 912 } else { | |
| 913 rv = SECSuccess; | |
| 914 } | |
| 915 | |
| 916 loser: | |
| 917 if (oldProfile && freeOldProfile) { | |
| 918 SECITEM_FreeItem(oldProfile,PR_TRUE); | |
| 919 } | |
| 920 if (oldProfileTime && freeOldProfile) { | |
| 921 SECITEM_FreeItem(oldProfileTime,PR_TRUE); | |
| 922 } | |
| 923 if (stanProfile) { | |
| 924 nssSMIMEProfile_Destroy(stanProfile); | |
| 925 } | |
| 926 if (slot) { | |
| 927 PK11_FreeSlot(slot); | |
| 928 } | |
| 929 | |
| 930 return(rv); | |
| 931 } | |
| 932 | |
| 933 /* | |
| 934 * | |
| 935 * Manage S/MIME profiles | |
| 936 * | |
| 937 */ | |
| 938 | |
| 939 SECStatus | |
| 940 CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, | |
| 941 SECItem *profileTime) | |
| 942 { | |
| 943 const char *emailAddr; | |
| 944 SECStatus rv; | |
| 945 | |
| 946 if (!cert) { | |
| 947 return SECFailure; | |
| 948 } | |
| 949 | |
| 950 if (cert->slot && !PK11_IsInternal(cert->slot)) { | |
| 951 /* this cert comes from an external source, we need to add it | |
| 952 to the cert db before creating an S/MIME profile */ | |
| 953 PK11SlotInfo* internalslot = PK11_GetInternalKeySlot(); | |
| 954 if (!internalslot) { | |
| 955 return SECFailure; | |
| 956 } | |
| 957 rv = PK11_ImportCert(internalslot, cert, | |
| 958 CK_INVALID_HANDLE, NULL, PR_FALSE); | |
| 959 | |
| 960 PK11_FreeSlot(internalslot); | |
| 961 if (rv != SECSuccess ) { | |
| 962 return SECFailure; | |
| 963 } | |
| 964 } | |
| 965 | |
| 966 if (cert->slot && cert->isperm && CERT_IsUserCert(cert) && | |
| 967 (!emailProfile || !emailProfile->len)) { | |
| 968 /* Don't clobber emailProfile for user certs. */ | |
| 969 return SECSuccess; | |
| 970 } | |
| 971 | |
| 972 for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL; | |
| 973 emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) { | |
| 974 rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime); | |
| 975 if (rv != SECSuccess) { | |
| 976 return SECFailure; | |
| 977 } | |
| 978 } | |
| 979 return SECSuccess; | |
| 980 | |
| 981 } | |
| 982 | |
| 983 | |
| 984 SECItem * | |
| 985 CERT_FindSMimeProfile(CERTCertificate *cert) | |
| 986 { | |
| 987 PK11SlotInfo *slot = NULL; | |
| 988 NSSCertificate *c; | |
| 989 NSSCryptoContext *cc; | |
| 990 SECItem *rvItem = NULL; | |
| 991 | |
| 992 if (!cert || !cert->emailAddr || !cert->emailAddr[0]) { | |
| 993 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 994 return NULL; | |
| 995 } | |
| 996 c = STAN_GetNSSCertificate(cert); | |
| 997 if (!c) return NULL; | |
| 998 cc = c->object.cryptoContext; | |
| 999 if (cc != NULL) { | |
| 1000 nssSMIMEProfile *stanProfile; | |
| 1001 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); | |
| 1002 if (stanProfile) { | |
| 1003 rvItem = SECITEM_AllocItem(NULL, NULL, | |
| 1004 stanProfile->profileData->size); | |
| 1005 if (rvItem) { | |
| 1006 rvItem->data = stanProfile->profileData->data; | |
| 1007 } | |
| 1008 nssSMIMEProfile_Destroy(stanProfile); | |
| 1009 } | |
| 1010 return rvItem; | |
| 1011 } | |
| 1012 rvItem = | |
| 1013 PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL); | |
| 1014 if (slot) { | |
| 1015 PK11_FreeSlot(slot); | |
| 1016 } | |
| 1017 return rvItem; | |
| 1018 } | |
| 1019 | |
| 1020 /* | |
| 1021 * deprecated functions that are now just stubs. | |
| 1022 */ | |
| 1023 /* | |
| 1024 * Close the database | |
| 1025 */ | |
| 1026 void | |
| 1027 __CERT_ClosePermCertDB(CERTCertDBHandle *handle) | |
| 1028 { | |
| 1029 PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL); | |
| 1030 return; | |
| 1031 } | |
| 1032 | |
| 1033 SECStatus | |
| 1034 CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, | |
| 1035 PRBool readOnly) | |
| 1036 { | |
| 1037 PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL); | |
| 1038 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 1039 return SECFailure; | |
| 1040 } | |
| 1041 | |
| 1042 SECItem * | |
| 1043 SECKEY_HashPassword(char *pw, SECItem *salt) | |
| 1044 { | |
| 1045 PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL); | |
| 1046 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 1047 return NULL; | |
| 1048 } | |
| 1049 | |
| 1050 SECStatus | |
| 1051 __CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, | |
| 1052 SECItem *derSubject, | |
| 1053 void *cb, void *cbarg) | |
| 1054 { | |
| 1055 PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL); | |
| 1056 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 1057 return SECFailure; | |
| 1058 } | |
| 1059 | |
| 1060 | |
| 1061 SECStatus | |
| 1062 __CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, | |
| 1063 void *cb, void *cbarg) | |
| 1064 { | |
| 1065 PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL); | |
| 1066 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 1067 return SECFailure; | |
| 1068 } | |
| 1069 | |
| 1070 | |
| 1071 | |
| OLD | NEW |