| File: | s/lib/pki/pkibase.c |
| Warning: | line 769, column 9 Value stored to 'status' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | #ifndef DEV_H |
| 6 | #include "dev.h" |
| 7 | #endif /* DEV_H */ |
| 8 | |
| 9 | #ifndef PKIM_H |
| 10 | #include "pkim.h" |
| 11 | #endif /* PKIM_H */ |
| 12 | |
| 13 | #include "pki3hack.h" |
| 14 | |
| 15 | extern const NSSError NSS_ERROR_NOT_FOUND; |
| 16 | |
| 17 | NSS_IMPLEMENT void |
| 18 | nssPKIObject_Lock(nssPKIObject *object) |
| 19 | { |
| 20 | switch (object->lockType) { |
| 21 | case nssPKIMonitor: |
| 22 | PZ_EnterMonitor(object->sync.mlock)PR_EnterMonitor((object->sync.mlock)); |
| 23 | break; |
| 24 | case nssPKILock: |
| 25 | PZ_Lock(object->sync.lock)PR_Lock((object->sync.lock)); |
| 26 | break; |
| 27 | default: |
| 28 | PORT_Assert(0)((0)?((void)0):PR_Assert("0","pkibase.c",28)); |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | NSS_IMPLEMENT void |
| 33 | nssPKIObject_Unlock(nssPKIObject *object) |
| 34 | { |
| 35 | switch (object->lockType) { |
| 36 | case nssPKIMonitor: |
| 37 | PZ_ExitMonitor(object->sync.mlock)PR_ExitMonitor((object->sync.mlock)); |
| 38 | break; |
| 39 | case nssPKILock: |
| 40 | PZ_Unlock(object->sync.lock)PR_Unlock((object->sync.lock)); |
| 41 | break; |
| 42 | default: |
| 43 | PORT_Assert(0)((0)?((void)0):PR_Assert("0","pkibase.c",43)); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | NSS_IMPLEMENT PRStatus |
| 48 | nssPKIObject_NewLock(nssPKIObject *object, nssPKILockType lockType) |
| 49 | { |
| 50 | object->lockType = lockType; |
| 51 | switch (lockType) { |
| 52 | case nssPKIMonitor: |
| 53 | object->sync.mlock = PZ_NewMonitor(nssILockSSL)PR_NewMonitor(); |
| 54 | return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE); |
| 55 | case nssPKILock: |
| 56 | object->sync.lock = PZ_NewLock(nssILockSSL)PR_NewLock(); |
| 57 | return (object->sync.lock ? PR_SUCCESS : PR_FAILURE); |
| 58 | default: |
| 59 | PORT_Assert(0)((0)?((void)0):PR_Assert("0","pkibase.c",59)); |
| 60 | return PR_FAILURE; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | NSS_IMPLEMENT void |
| 65 | nssPKIObject_DestroyLock(nssPKIObject *object) |
| 66 | { |
| 67 | switch (object->lockType) { |
| 68 | case nssPKIMonitor: |
| 69 | PZ_DestroyMonitor(object->sync.mlock)PR_DestroyMonitor((object->sync.mlock)); |
| 70 | object->sync.mlock = NULL((void*)0); |
| 71 | break; |
| 72 | case nssPKILock: |
| 73 | PZ_DestroyLock(object->sync.lock)PR_DestroyLock((object->sync.lock)); |
| 74 | object->sync.lock = NULL((void*)0); |
| 75 | break; |
| 76 | default: |
| 77 | PORT_Assert(0)((0)?((void)0):PR_Assert("0","pkibase.c",77)); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | NSS_IMPLEMENT nssPKIObject * |
| 82 | nssPKIObject_Create( |
| 83 | NSSArena *arenaOpt, |
| 84 | nssCryptokiObject *instanceOpt, |
| 85 | NSSTrustDomain *td, |
| 86 | NSSCryptoContext *cc, |
| 87 | nssPKILockType lockType) |
| 88 | { |
| 89 | NSSArena *arena; |
| 90 | nssArenaMark *mark = NULL((void*)0); |
| 91 | nssPKIObject *object; |
| 92 | if (arenaOpt) { |
| 93 | arena = arenaOpt; |
| 94 | mark = nssArena_Mark(arena); |
| 95 | } else { |
| 96 | arena = nssArena_Create(); |
| 97 | if (!arena) { |
| 98 | return (nssPKIObject *)NULL((void*)0); |
| 99 | } |
| 100 | } |
| 101 | object = nss_ZNEW(arena, nssPKIObject)((nssPKIObject *)nss_ZAlloc((arena), sizeof(nssPKIObject))); |
| 102 | if (!object) { |
| 103 | goto loser; |
| 104 | } |
| 105 | object->arena = arena; |
| 106 | object->trustDomain = td; /* XXX */ |
| 107 | object->cryptoContext = cc; |
| 108 | if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) { |
| 109 | goto loser; |
| 110 | } |
| 111 | if (instanceOpt) { |
| 112 | if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) { |
| 113 | goto loser; |
| 114 | } |
| 115 | } |
| 116 | PR_ATOMIC_INCREMENT(&object->refCount)__sync_add_and_fetch(&object->refCount, 1); |
| 117 | if (mark) { |
| 118 | nssArena_Unmark(arena, mark); |
| 119 | } |
| 120 | return object; |
| 121 | loser: |
| 122 | if (mark) { |
| 123 | nssArena_Release(arena, mark); |
| 124 | } else { |
| 125 | nssArena_Destroy(arena); |
| 126 | } |
| 127 | return (nssPKIObject *)NULL((void*)0); |
| 128 | } |
| 129 | |
| 130 | NSS_IMPLEMENT PRBool |
| 131 | nssPKIObject_Destroy( |
| 132 | nssPKIObject *object) |
| 133 | { |
| 134 | PRUint32 i; |
| 135 | PR_ASSERT(object->refCount > 0)((object->refCount > 0)?((void)0):PR_Assert("object->refCount > 0" ,"pkibase.c",135)); |
| 136 | if (PR_ATOMIC_DECREMENT(&object->refCount)__sync_sub_and_fetch(&object->refCount, 1) == 0) { |
| 137 | for (i = 0; i < object->numInstances; i++) { |
| 138 | nssCryptokiObject_Destroy(object->instances[i]); |
| 139 | } |
| 140 | nssPKIObject_DestroyLock(object); |
| 141 | nssArena_Destroy(object->arena); |
| 142 | return PR_TRUE1; |
| 143 | } |
| 144 | return PR_FALSE0; |
| 145 | } |
| 146 | |
| 147 | NSS_IMPLEMENT nssPKIObject * |
| 148 | nssPKIObject_AddRef( |
| 149 | nssPKIObject *object) |
| 150 | { |
| 151 | PR_ATOMIC_INCREMENT(&object->refCount)__sync_add_and_fetch(&object->refCount, 1); |
| 152 | return object; |
| 153 | } |
| 154 | |
| 155 | NSS_IMPLEMENT PRStatus |
| 156 | nssPKIObject_AddInstance( |
| 157 | nssPKIObject *object, |
| 158 | nssCryptokiObject *instance) |
| 159 | { |
| 160 | nssCryptokiObject **newInstances = NULL((void*)0); |
| 161 | |
| 162 | nssPKIObject_Lock(object); |
| 163 | if (object->numInstances == 0) { |
| 164 | newInstances = nss_ZNEWARRAY(object->arena,((nssCryptokiObject * *)nss_ZAlloc((object->arena), sizeof (nssCryptokiObject *) * (object->numInstances + 1))) |
| 165 | nssCryptokiObject *,((nssCryptokiObject * *)nss_ZAlloc((object->arena), sizeof (nssCryptokiObject *) * (object->numInstances + 1))) |
| 166 | object->numInstances + 1)((nssCryptokiObject * *)nss_ZAlloc((object->arena), sizeof (nssCryptokiObject *) * (object->numInstances + 1))); |
| 167 | } else { |
| 168 | PRBool found = PR_FALSE0; |
| 169 | PRUint32 i; |
| 170 | for (i = 0; i < object->numInstances; i++) { |
| 171 | if (nssCryptokiObject_Equal(object->instances[i], instance)) { |
| 172 | found = PR_TRUE1; |
| 173 | break; |
| 174 | } |
| 175 | } |
| 176 | if (found) { |
| 177 | /* The new instance is identical to one in the array, except |
| 178 | * perhaps that the label may be different. So replace |
| 179 | * the label in the array instance with the label from the |
| 180 | * new instance, and discard the new instance. |
| 181 | */ |
| 182 | nss_ZFreeIf(object->instances[i]->label); |
| 183 | object->instances[i]->label = instance->label; |
| 184 | nssPKIObject_Unlock(object); |
| 185 | instance->label = NULL((void*)0); |
| 186 | nssCryptokiObject_Destroy(instance); |
| 187 | return PR_SUCCESS; |
| 188 | } |
| 189 | newInstances = nss_ZREALLOCARRAY(object->instances,((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances + 1))) |
| 190 | nssCryptokiObject *,((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances + 1))) |
| 191 | object->numInstances + 1)((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances + 1))); |
| 192 | } |
| 193 | if (newInstances) { |
| 194 | object->instances = newInstances; |
| 195 | newInstances[object->numInstances++] = instance; |
| 196 | } |
| 197 | nssPKIObject_Unlock(object); |
| 198 | return (newInstances ? PR_SUCCESS : PR_FAILURE); |
| 199 | } |
| 200 | |
| 201 | NSS_IMPLEMENT PRBool |
| 202 | nssPKIObject_HasInstance( |
| 203 | nssPKIObject *object, |
| 204 | nssCryptokiObject *instance) |
| 205 | { |
| 206 | PRUint32 i; |
| 207 | PRBool hasIt = PR_FALSE0; |
| 208 | ; |
| 209 | nssPKIObject_Lock(object); |
| 210 | for (i = 0; i < object->numInstances; i++) { |
| 211 | if (nssCryptokiObject_Equal(object->instances[i], instance)) { |
| 212 | hasIt = PR_TRUE1; |
| 213 | break; |
| 214 | } |
| 215 | } |
| 216 | nssPKIObject_Unlock(object); |
| 217 | return hasIt; |
| 218 | } |
| 219 | |
| 220 | NSS_IMPLEMENT PRStatus |
| 221 | nssPKIObject_RemoveInstanceForToken( |
| 222 | nssPKIObject *object, |
| 223 | NSSToken *token) |
| 224 | { |
| 225 | PRUint32 i; |
| 226 | nssCryptokiObject *instanceToRemove = NULL((void*)0); |
| 227 | nssPKIObject_Lock(object); |
| 228 | if (object->numInstances == 0) { |
| 229 | nssPKIObject_Unlock(object); |
| 230 | return PR_SUCCESS; |
| 231 | } |
| 232 | for (i = 0; i < object->numInstances; i++) { |
| 233 | if (object->instances[i]->token == token) { |
| 234 | instanceToRemove = object->instances[i]; |
| 235 | object->instances[i] = object->instances[object->numInstances - 1]; |
| 236 | object->instances[object->numInstances - 1] = NULL((void*)0); |
| 237 | break; |
| 238 | } |
| 239 | } |
| 240 | if (--object->numInstances > 0) { |
| 241 | nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances))) |
| 242 | nssCryptokiObject *,((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances))) |
| 243 | object->numInstances)((nssCryptokiObject * *)nss_ZRealloc((object->instances), sizeof (nssCryptokiObject *) * (object->numInstances))); |
| 244 | if (instances) { |
| 245 | object->instances = instances; |
| 246 | } |
| 247 | } else { |
| 248 | nss_ZFreeIf(object->instances); |
| 249 | } |
| 250 | nssCryptokiObject_Destroy(instanceToRemove); |
| 251 | nssPKIObject_Unlock(object); |
| 252 | return PR_SUCCESS; |
| 253 | } |
| 254 | |
| 255 | /* this needs more thought on what will happen when there are multiple |
| 256 | * instances |
| 257 | */ |
| 258 | NSS_IMPLEMENT PRStatus |
| 259 | nssPKIObject_DeleteStoredObject( |
| 260 | nssPKIObject *object, |
| 261 | NSSCallback *uhh, |
| 262 | PRBool isFriendly) |
| 263 | { |
| 264 | PRUint32 i, numNotDestroyed; |
| 265 | PRStatus status = PR_SUCCESS; |
| 266 | numNotDestroyed = 0; |
| 267 | nssPKIObject_Lock(object); |
| 268 | for (i = 0; i < object->numInstances; i++) { |
| 269 | nssCryptokiObject *instance = object->instances[i]; |
| 270 | status = nssToken_DeleteStoredObject(instance); |
| 271 | object->instances[i] = NULL((void*)0); |
| 272 | if (status == PR_SUCCESS) { |
| 273 | nssCryptokiObject_Destroy(instance); |
| 274 | } else { |
| 275 | object->instances[numNotDestroyed++] = instance; |
| 276 | } |
| 277 | } |
| 278 | if (numNotDestroyed == 0) { |
| 279 | nss_ZFreeIf(object->instances); |
| 280 | object->numInstances = 0; |
| 281 | } else { |
| 282 | object->numInstances = numNotDestroyed; |
| 283 | } |
| 284 | nssPKIObject_Unlock(object); |
| 285 | return status; |
| 286 | } |
| 287 | |
| 288 | NSS_IMPLEMENT NSSToken ** |
| 289 | nssPKIObject_GetTokens( |
| 290 | nssPKIObject *object, |
| 291 | PRStatus *statusOpt) |
| 292 | { |
| 293 | NSSToken **tokens = NULL((void*)0); |
| 294 | nssPKIObject_Lock(object); |
| 295 | if (object->numInstances > 0) { |
| 296 | tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1)((NSSToken * *)nss_ZAlloc((((void*)0)), sizeof(NSSToken *) * ( object->numInstances + 1))); |
| 297 | if (tokens) { |
| 298 | PRUint32 i; |
| 299 | for (i = 0; i < object->numInstances; i++) { |
| 300 | tokens[i] = nssToken_AddRef(object->instances[i]->token); |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | nssPKIObject_Unlock(object); |
| 305 | if (statusOpt) |
| 306 | *statusOpt = PR_SUCCESS; /* until more logic here */ |
| 307 | return tokens; |
| 308 | } |
| 309 | |
| 310 | NSS_IMPLEMENT NSSUTF8 * |
| 311 | nssPKIObject_GetNicknameForToken( |
| 312 | nssPKIObject *object, |
| 313 | NSSToken *tokenOpt) |
| 314 | { |
| 315 | PRUint32 i; |
| 316 | NSSUTF8 *nickname = NULL((void*)0); |
| 317 | nssPKIObject_Lock(object); |
| 318 | for (i = 0; i < object->numInstances; i++) { |
| 319 | if ((!tokenOpt && object->instances[i]->label) || |
| 320 | (object->instances[i]->token == tokenOpt)) { |
| 321 | /* Must copy, see bug 745548 */ |
| 322 | nickname = nssUTF8_Duplicate(object->instances[i]->label, NULL((void*)0)); |
| 323 | break; |
| 324 | } |
| 325 | } |
| 326 | nssPKIObject_Unlock(object); |
| 327 | return nickname; |
| 328 | } |
| 329 | |
| 330 | NSS_IMPLEMENT nssCryptokiObject ** |
| 331 | nssPKIObject_GetInstances( |
| 332 | nssPKIObject *object) |
| 333 | { |
| 334 | nssCryptokiObject **instances = NULL((void*)0); |
| 335 | PRUint32 i; |
| 336 | if (object->numInstances == 0) { |
| 337 | return (nssCryptokiObject **)NULL((void*)0); |
| 338 | } |
| 339 | nssPKIObject_Lock(object); |
| 340 | instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,((nssCryptokiObject * *)nss_ZAlloc((((void*)0)), sizeof(nssCryptokiObject *) * (object->numInstances + 1))) |
| 341 | object->numInstances + 1)((nssCryptokiObject * *)nss_ZAlloc((((void*)0)), sizeof(nssCryptokiObject *) * (object->numInstances + 1))); |
| 342 | if (instances) { |
| 343 | for (i = 0; i < object->numInstances; i++) { |
| 344 | instances[i] = nssCryptokiObject_Clone(object->instances[i]); |
| 345 | } |
| 346 | } |
| 347 | nssPKIObject_Unlock(object); |
| 348 | return instances; |
| 349 | } |
| 350 | |
| 351 | NSS_IMPLEMENT void |
| 352 | nssCertificateArray_Destroy( |
| 353 | NSSCertificate **certs) |
| 354 | { |
| 355 | if (certs) { |
| 356 | NSSCertificate **certp; |
| 357 | for (certp = certs; *certp; certp++) { |
| 358 | if ((*certp)->decoding) { |
| 359 | CERTCertificate *cc = STAN_GetCERTCertificate(*certp); |
| 360 | if (cc) { |
| 361 | CERT_DestroyCertificate(cc); |
| 362 | } |
| 363 | continue; |
| 364 | } |
| 365 | nssCertificate_Destroy(*certp); |
| 366 | } |
| 367 | nss_ZFreeIf(certs); |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | NSS_IMPLEMENT void |
| 372 | NSSCertificateArray_Destroy( |
| 373 | NSSCertificate **certs) |
| 374 | { |
| 375 | nssCertificateArray_Destroy(certs); |
| 376 | } |
| 377 | |
| 378 | NSS_IMPLEMENT NSSCertificate ** |
| 379 | nssCertificateArray_Join( |
| 380 | NSSCertificate **certs1, |
| 381 | NSSCertificate **certs2) |
| 382 | { |
| 383 | if (certs1 && certs2) { |
| 384 | NSSCertificate **certs, **cp; |
| 385 | PRUint32 count = 0; |
| 386 | PRUint32 count1 = 0; |
| 387 | cp = certs1; |
| 388 | while (*cp++) |
| 389 | count1++; |
| 390 | count = count1; |
| 391 | cp = certs2; |
| 392 | while (*cp++) |
| 393 | count++; |
| 394 | certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1)((NSSCertificate * *)nss_ZRealloc((certs1), sizeof(NSSCertificate *) * (count + 1))); |
| 395 | if (!certs) { |
| 396 | nss_ZFreeIf(certs1); |
| 397 | nss_ZFreeIf(certs2); |
| 398 | return (NSSCertificate **)NULL((void*)0); |
| 399 | } |
| 400 | for (cp = certs2; *cp; cp++, count1++) { |
| 401 | certs[count1] = *cp; |
| 402 | } |
| 403 | nss_ZFreeIf(certs2); |
| 404 | return certs; |
| 405 | } else if (certs1) { |
| 406 | return certs1; |
| 407 | } else { |
| 408 | return certs2; |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | NSS_IMPLEMENT NSSCertificate * |
| 413 | nssCertificateArray_FindBestCertificate( |
| 414 | NSSCertificate **certs, |
| 415 | NSSTime *timeOpt, |
| 416 | const NSSUsage *usage, |
| 417 | NSSPolicies *policiesOpt) |
| 418 | { |
| 419 | NSSCertificate *bestCert = NULL((void*)0); |
| 420 | nssDecodedCert *bestdc = NULL((void*)0); |
| 421 | NSSTime *time, sTime; |
| 422 | PRBool bestCertMatches = PR_FALSE0; |
| 423 | PRBool thisCertMatches; |
| 424 | PRBool bestCertIsValidAtTime = PR_FALSE0; |
| 425 | PRBool bestCertIsTrusted = PR_FALSE0; |
| 426 | |
| 427 | if (timeOpt) { |
| 428 | time = timeOpt; |
| 429 | } else { |
| 430 | NSSTime_Now(&sTime); |
| 431 | time = &sTime; |
| 432 | } |
| 433 | if (!certs) { |
| 434 | return (NSSCertificate *)NULL((void*)0); |
| 435 | } |
| 436 | for (; *certs; certs++) { |
| 437 | nssDecodedCert *dc; |
| 438 | NSSCertificate *c = *certs; |
| 439 | dc = nssCertificate_GetDecoding(c); |
| 440 | if (!dc) |
| 441 | continue; |
| 442 | thisCertMatches = dc->matchUsage(dc, usage); |
| 443 | if (!bestCert) { |
| 444 | /* always take the first cert, but remember whether or not |
| 445 | * the usage matched |
| 446 | */ |
| 447 | bestCert = nssCertificate_AddRef(c); |
| 448 | bestCertMatches = thisCertMatches; |
| 449 | bestdc = dc; |
| 450 | continue; |
| 451 | } else { |
| 452 | if (bestCertMatches && !thisCertMatches) { |
| 453 | /* if already have a cert for this usage, and if this cert |
| 454 | * doesn't have the correct usage, continue |
| 455 | */ |
| 456 | continue; |
| 457 | } else if (!bestCertMatches && thisCertMatches) { |
| 458 | /* this one does match usage, replace the other */ |
| 459 | nssCertificate_Destroy(bestCert); |
| 460 | bestCert = nssCertificate_AddRef(c); |
| 461 | bestCertMatches = thisCertMatches; |
| 462 | bestdc = dc; |
| 463 | continue; |
| 464 | } |
| 465 | /* this cert match as well as any cert we've found so far, |
| 466 | * defer to time/policies |
| 467 | * */ |
| 468 | } |
| 469 | /* time */ |
| 470 | if (bestCertIsValidAtTime || bestdc->isValidAtTime(bestdc, time)) { |
| 471 | /* The current best cert is valid at time */ |
| 472 | bestCertIsValidAtTime = PR_TRUE1; |
| 473 | if (!dc->isValidAtTime(dc, time)) { |
| 474 | /* If the new cert isn't valid at time, it's not better */ |
| 475 | continue; |
| 476 | } |
| 477 | } else { |
| 478 | /* The current best cert is not valid at time */ |
| 479 | if (dc->isValidAtTime(dc, time)) { |
| 480 | /* If the new cert is valid at time, it's better */ |
| 481 | nssCertificate_Destroy(bestCert); |
| 482 | bestCert = nssCertificate_AddRef(c); |
| 483 | bestdc = dc; |
| 484 | bestCertIsValidAtTime = PR_TRUE1; |
| 485 | continue; |
| 486 | } |
| 487 | } |
| 488 | /* Either they are both valid at time, or neither valid. |
| 489 | * If only one is trusted for this usage, take it. |
| 490 | */ |
| 491 | if (bestCertIsTrusted || bestdc->isTrustedForUsage(bestdc, usage)) { |
| 492 | bestCertIsTrusted = PR_TRUE1; |
| 493 | if (!dc->isTrustedForUsage(dc, usage)) { |
| 494 | continue; |
| 495 | } |
| 496 | } else { |
| 497 | /* The current best cert is not trusted */ |
| 498 | if (dc->isTrustedForUsage(dc, usage)) { |
| 499 | /* If the new cert is trusted, it's better */ |
| 500 | nssCertificate_Destroy(bestCert); |
| 501 | bestCert = nssCertificate_AddRef(c); |
| 502 | bestdc = dc; |
| 503 | bestCertIsTrusted = PR_TRUE1; |
| 504 | continue; |
| 505 | } |
| 506 | } |
| 507 | /* Otherwise, take the newer one. */ |
| 508 | if (!bestdc->isNewerThan(bestdc, dc)) { |
| 509 | nssCertificate_Destroy(bestCert); |
| 510 | bestCert = nssCertificate_AddRef(c); |
| 511 | bestdc = dc; |
| 512 | continue; |
| 513 | } |
| 514 | /* policies */ |
| 515 | /* XXX later -- defer to policies */ |
| 516 | } |
| 517 | return bestCert; |
| 518 | } |
| 519 | |
| 520 | NSS_IMPLEMENT PRStatus |
| 521 | nssCertificateArray_Traverse( |
| 522 | NSSCertificate **certs, |
| 523 | PRStatus (*callback)(NSSCertificate *c, void *arg), |
| 524 | void *arg) |
| 525 | { |
| 526 | PRStatus status = PR_SUCCESS; |
| 527 | if (certs) { |
| 528 | NSSCertificate **certp; |
| 529 | for (certp = certs; *certp; certp++) { |
| 530 | status = (*callback)(*certp, arg); |
| 531 | if (status != PR_SUCCESS) { |
| 532 | break; |
| 533 | } |
| 534 | } |
| 535 | } |
| 536 | return status; |
| 537 | } |
| 538 | |
| 539 | NSS_IMPLEMENT void |
| 540 | nssCRLArray_Destroy( |
| 541 | NSSCRL **crls) |
| 542 | { |
| 543 | if (crls) { |
| 544 | NSSCRL **crlp; |
| 545 | for (crlp = crls; *crlp; crlp++) { |
| 546 | nssCRL_Destroy(*crlp); |
| 547 | } |
| 548 | nss_ZFreeIf(crls); |
| 549 | } |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 | * Object collections |
| 554 | */ |
| 555 | |
| 556 | typedef enum { |
| 557 | pkiObjectType_Certificate = 0, |
| 558 | pkiObjectType_CRL = 1, |
| 559 | pkiObjectType_PrivateKey = 2, |
| 560 | pkiObjectType_PublicKey = 3 |
| 561 | } pkiObjectType; |
| 562 | |
| 563 | /* Each object is defined by a set of items that uniquely identify it. |
| 564 | * Here are the uid sets: |
| 565 | * |
| 566 | * NSSCertificate ==> { issuer, serial } |
| 567 | * NSSPrivateKey |
| 568 | * (RSA) ==> { modulus, public exponent } |
| 569 | * |
| 570 | */ |
| 571 | #define MAX_ITEMS_FOR_UID2 2 |
| 572 | |
| 573 | /* pkiObjectCollectionNode |
| 574 | * |
| 575 | * A node in the collection is the set of unique identifiers for a single |
| 576 | * object, along with either the actual object or a proto-object. |
| 577 | */ |
| 578 | typedef struct |
| 579 | { |
| 580 | PRCList link; |
| 581 | PRBool haveObject; |
| 582 | nssPKIObject *object; |
| 583 | NSSItem uid[MAX_ITEMS_FOR_UID2]; |
| 584 | } pkiObjectCollectionNode; |
| 585 | |
| 586 | /* nssPKIObjectCollection |
| 587 | * |
| 588 | * The collection is the set of all objects, plus the interfaces needed |
| 589 | * to manage the objects. |
| 590 | * |
| 591 | */ |
| 592 | struct nssPKIObjectCollectionStr { |
| 593 | NSSArena *arena; |
| 594 | NSSTrustDomain *td; |
| 595 | NSSCryptoContext *cc; |
| 596 | PRCList head; /* list of pkiObjectCollectionNode's */ |
| 597 | PRUint32 size; |
| 598 | pkiObjectType objectType; |
| 599 | void (*destroyObject)(nssPKIObject *o); |
| 600 | PRStatus (*getUIDFromObject)(nssPKIObject *o, NSSItem *uid); |
| 601 | PRStatus (*getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid, |
| 602 | NSSArena *arena); |
| 603 | nssPKIObject *(*createObject)(nssPKIObject *o); |
| 604 | nssPKILockType lockType; /* type of lock to use for new proto-objects */ |
| 605 | }; |
| 606 | |
| 607 | static nssPKIObjectCollection * |
| 608 | nssPKIObjectCollection_Create( |
| 609 | NSSTrustDomain *td, |
| 610 | NSSCryptoContext *ccOpt, |
| 611 | nssPKILockType lockType) |
| 612 | { |
| 613 | NSSArena *arena; |
| 614 | nssPKIObjectCollection *rvCollection = NULL((void*)0); |
| 615 | arena = nssArena_Create(); |
| 616 | if (!arena) { |
| 617 | return (nssPKIObjectCollection *)NULL((void*)0); |
| 618 | } |
| 619 | rvCollection = nss_ZNEW(arena, nssPKIObjectCollection)((nssPKIObjectCollection *)nss_ZAlloc((arena), sizeof(nssPKIObjectCollection ))); |
| 620 | if (!rvCollection) { |
| 621 | goto loser; |
| 622 | } |
| 623 | PR_INIT_CLIST(&rvCollection->head)do { (&rvCollection->head)->next = (&rvCollection ->head); (&rvCollection->head)->prev = (&rvCollection ->head); } while (0); |
| 624 | rvCollection->arena = arena; |
| 625 | rvCollection->td = td; /* XXX */ |
| 626 | rvCollection->cc = ccOpt; |
| 627 | rvCollection->lockType = lockType; |
| 628 | return rvCollection; |
| 629 | loser: |
| 630 | nssArena_Destroy(arena); |
| 631 | return (nssPKIObjectCollection *)NULL((void*)0); |
| 632 | } |
| 633 | |
| 634 | NSS_IMPLEMENT void |
| 635 | nssPKIObjectCollection_Destroy( |
| 636 | nssPKIObjectCollection *collection) |
| 637 | { |
| 638 | if (collection) { |
| 639 | PRCList *link; |
| 640 | pkiObjectCollectionNode *node; |
| 641 | /* first destroy any objects in the collection */ |
| 642 | link = PR_NEXT_LINK(&collection->head)((&collection->head)->next); |
| 643 | while (link != &collection->head) { |
| 644 | node = (pkiObjectCollectionNode *)link; |
| 645 | if (node->haveObject) { |
| 646 | (*collection->destroyObject)(node->object); |
| 647 | } else { |
| 648 | nssPKIObject_Destroy(node->object); |
| 649 | } |
| 650 | link = PR_NEXT_LINK(link)((link)->next); |
| 651 | } |
| 652 | /* then destroy it */ |
| 653 | nssArena_Destroy(collection->arena); |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | NSS_IMPLEMENT PRUint32 |
| 658 | nssPKIObjectCollection_Count( |
| 659 | nssPKIObjectCollection *collection) |
| 660 | { |
| 661 | return collection->size; |
| 662 | } |
| 663 | |
| 664 | NSS_IMPLEMENT PRStatus |
| 665 | nssPKIObjectCollection_AddObject( |
| 666 | nssPKIObjectCollection *collection, |
| 667 | nssPKIObject *object) |
| 668 | { |
| 669 | pkiObjectCollectionNode *node; |
| 670 | node = nss_ZNEW(collection->arena, pkiObjectCollectionNode)((pkiObjectCollectionNode *)nss_ZAlloc((collection->arena) , sizeof(pkiObjectCollectionNode))); |
| 671 | if (!node) { |
| 672 | return PR_FAILURE; |
| 673 | } |
| 674 | node->haveObject = PR_TRUE1; |
| 675 | node->object = nssPKIObject_AddRef(object); |
| 676 | (*collection->getUIDFromObject)(object, node->uid); |
| 677 | PR_INIT_CLIST(&node->link)do { (&node->link)->next = (&node->link); (& node->link)->prev = (&node->link); } while (0); |
| 678 | PR_INSERT_BEFORE(&node->link, &collection->head)do { (&node->link)->next = (&collection->head ); (&node->link)->prev = (&collection->head) ->prev; (&collection->head)->prev->next = (& node->link); (&collection->head)->prev = (&node ->link); } while (0); |
| 679 | collection->size++; |
| 680 | return PR_SUCCESS; |
| 681 | } |
| 682 | |
| 683 | static pkiObjectCollectionNode * |
| 684 | find_instance_in_collection( |
| 685 | nssPKIObjectCollection *collection, |
| 686 | nssCryptokiObject *instance) |
| 687 | { |
| 688 | PRCList *link; |
| 689 | pkiObjectCollectionNode *node; |
| 690 | link = PR_NEXT_LINK(&collection->head)((&collection->head)->next); |
| 691 | while (link != &collection->head) { |
| 692 | node = (pkiObjectCollectionNode *)link; |
| 693 | if (nssPKIObject_HasInstance(node->object, instance)) { |
| 694 | return node; |
| 695 | } |
| 696 | link = PR_NEXT_LINK(link)((link)->next); |
| 697 | } |
| 698 | return (pkiObjectCollectionNode *)NULL((void*)0); |
| 699 | } |
| 700 | |
| 701 | static pkiObjectCollectionNode * |
| 702 | find_object_in_collection( |
| 703 | nssPKIObjectCollection *collection, |
| 704 | NSSItem *uid) |
| 705 | { |
| 706 | PRUint32 i; |
| 707 | PRStatus status; |
| 708 | PRCList *link; |
| 709 | pkiObjectCollectionNode *node; |
| 710 | link = PR_NEXT_LINK(&collection->head)((&collection->head)->next); |
| 711 | while (link != &collection->head) { |
| 712 | node = (pkiObjectCollectionNode *)link; |
| 713 | for (i = 0; i < MAX_ITEMS_FOR_UID2; i++) { |
| 714 | if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) { |
| 715 | break; |
| 716 | } |
| 717 | } |
| 718 | if (i == MAX_ITEMS_FOR_UID2) { |
| 719 | return node; |
| 720 | } |
| 721 | link = PR_NEXT_LINK(link)((link)->next); |
| 722 | } |
| 723 | return (pkiObjectCollectionNode *)NULL((void*)0); |
| 724 | } |
| 725 | |
| 726 | static pkiObjectCollectionNode * |
| 727 | add_object_instance( |
| 728 | nssPKIObjectCollection *collection, |
| 729 | nssCryptokiObject *instance, |
| 730 | PRBool *foundIt) |
| 731 | { |
| 732 | PRUint32 i; |
| 733 | PRStatus status; |
| 734 | pkiObjectCollectionNode *node; |
| 735 | nssArenaMark *mark = NULL((void*)0); |
| 736 | NSSItem uid[MAX_ITEMS_FOR_UID2]; |
| 737 | nsslibc_memset(uid, 0, sizeof uid); |
| 738 | /* The list is traversed twice, first (here) looking to match the |
| 739 | * { token, handle } tuple, and if that is not found, below a search |
| 740 | * for unique identifier is done. Here, a match means this exact object |
| 741 | * instance is already in the collection, and we have nothing to do. |
| 742 | */ |
| 743 | *foundIt = PR_FALSE0; |
| 744 | node = find_instance_in_collection(collection, instance); |
| 745 | if (node) { |
| 746 | /* The collection is assumed to take over the instance. Since we |
| 747 | * are not using it, it must be destroyed. |
| 748 | */ |
| 749 | nssCryptokiObject_Destroy(instance); |
| 750 | *foundIt = PR_TRUE1; |
| 751 | return node; |
| 752 | } |
| 753 | mark = nssArena_Mark(collection->arena); |
| 754 | if (!mark) { |
| 755 | goto loser; |
| 756 | } |
| 757 | status = (*collection->getUIDFromInstance)(instance, uid, |
| 758 | collection->arena); |
| 759 | if (status != PR_SUCCESS) { |
| 760 | goto loser; |
| 761 | } |
| 762 | /* Search for unique identifier. A match here means the object exists |
| 763 | * in the collection, but does not have this instance, so the instance |
| 764 | * needs to be added. |
| 765 | */ |
| 766 | node = find_object_in_collection(collection, uid); |
| 767 | if (node) { |
| 768 | /* This is an object with multiple instances */ |
| 769 | status = nssPKIObject_AddInstance(node->object, instance); |
Value stored to 'status' is never read | |
| 770 | } else { |
| 771 | /* This is a completely new object. Create a node for it. */ |
| 772 | node = nss_ZNEW(collection->arena, pkiObjectCollectionNode)((pkiObjectCollectionNode *)nss_ZAlloc((collection->arena) , sizeof(pkiObjectCollectionNode))); |
| 773 | if (!node) { |
| 774 | goto loser; |
| 775 | } |
| 776 | node->object = nssPKIObject_Create(NULL((void*)0), instance, |
| 777 | collection->td, collection->cc, |
| 778 | collection->lockType); |
| 779 | if (!node->object) { |
| 780 | goto loser; |
| 781 | } |
| 782 | for (i = 0; i < MAX_ITEMS_FOR_UID2; i++) { |
| 783 | node->uid[i] = uid[i]; |
| 784 | } |
| 785 | node->haveObject = PR_FALSE0; |
| 786 | PR_INIT_CLIST(&node->link)do { (&node->link)->next = (&node->link); (& node->link)->prev = (&node->link); } while (0); |
| 787 | PR_INSERT_BEFORE(&node->link, &collection->head)do { (&node->link)->next = (&collection->head ); (&node->link)->prev = (&collection->head) ->prev; (&collection->head)->prev->next = (& node->link); (&collection->head)->prev = (&node ->link); } while (0); |
| 788 | collection->size++; |
| 789 | status = PR_SUCCESS; |
| 790 | } |
| 791 | nssArena_Unmark(collection->arena, mark); |
| 792 | return node; |
| 793 | loser: |
| 794 | if (mark) { |
| 795 | nssArena_Release(collection->arena, mark); |
| 796 | } |
| 797 | nssCryptokiObject_Destroy(instance); |
| 798 | return (pkiObjectCollectionNode *)NULL((void*)0); |
| 799 | } |
| 800 | |
| 801 | NSS_IMPLEMENT PRStatus |
| 802 | nssPKIObjectCollection_AddInstances( |
| 803 | nssPKIObjectCollection *collection, |
| 804 | nssCryptokiObject **instances, |
| 805 | PRUint32 numInstances) |
| 806 | { |
| 807 | PRStatus status = PR_SUCCESS; |
| 808 | PRUint32 i = 0; |
| 809 | PRBool foundIt; |
| 810 | pkiObjectCollectionNode *node; |
| 811 | if (instances) { |
| 812 | while ((!numInstances || i < numInstances) && *instances) { |
| 813 | if (status == PR_SUCCESS) { |
| 814 | node = add_object_instance(collection, *instances, &foundIt); |
| 815 | if (node == NULL((void*)0)) { |
| 816 | /* add_object_instance freed the current instance */ |
| 817 | /* free the remaining instances */ |
| 818 | status = PR_FAILURE; |
| 819 | } |
| 820 | } else { |
| 821 | nssCryptokiObject_Destroy(*instances); |
| 822 | } |
| 823 | instances++; |
| 824 | i++; |
| 825 | } |
| 826 | } |
| 827 | return status; |
| 828 | } |
| 829 | |
| 830 | static void |
| 831 | nssPKIObjectCollection_RemoveNode( |
| 832 | nssPKIObjectCollection *collection, |
| 833 | pkiObjectCollectionNode *node) |
| 834 | { |
| 835 | PR_REMOVE_LINK(&node->link)do { (&node->link)->prev->next = (&node-> link)->next; (&node->link)->next->prev = (& node->link)->prev; } while (0); |
| 836 | collection->size--; |
| 837 | } |
| 838 | |
| 839 | static PRStatus |
| 840 | nssPKIObjectCollection_GetObjects( |
| 841 | nssPKIObjectCollection *collection, |
| 842 | nssPKIObject **rvObjects, |
| 843 | PRUint32 rvSize) |
| 844 | { |
| 845 | PRUint32 i = 0; |
| 846 | PRCList *link = PR_NEXT_LINK(&collection->head)((&collection->head)->next); |
| 847 | pkiObjectCollectionNode *node; |
| 848 | int error = 0; |
| 849 | while ((i < rvSize) && (link != &collection->head)) { |
| 850 | node = (pkiObjectCollectionNode *)link; |
| 851 | if (!node->haveObject) { |
| 852 | /* Convert the proto-object to an object */ |
| 853 | node->object = (*collection->createObject)(node->object); |
| 854 | if (!node->object) { |
| 855 | link = PR_NEXT_LINK(link)((link)->next); |
| 856 | /*remove bogus object from list*/ |
| 857 | nssPKIObjectCollection_RemoveNode(collection, node); |
| 858 | error++; |
| 859 | continue; |
| 860 | } |
| 861 | node->haveObject = PR_TRUE1; |
| 862 | } |
| 863 | rvObjects[i++] = nssPKIObject_AddRef(node->object); |
| 864 | link = PR_NEXT_LINK(link)((link)->next); |
| 865 | } |
| 866 | if (!error && *rvObjects == NULL((void*)0)) { |
| 867 | nss_SetError(NSS_ERROR_NOT_FOUND); |
| 868 | } |
| 869 | return PR_SUCCESS; |
| 870 | } |
| 871 | |
| 872 | NSS_IMPLEMENT PRStatus |
| 873 | nssPKIObjectCollection_Traverse( |
| 874 | nssPKIObjectCollection *collection, |
| 875 | nssPKIObjectCallback *callback) |
| 876 | { |
| 877 | PRCList *link = PR_NEXT_LINK(&collection->head)((&collection->head)->next); |
| 878 | pkiObjectCollectionNode *node; |
| 879 | while (link != &collection->head) { |
| 880 | node = (pkiObjectCollectionNode *)link; |
| 881 | if (!node->haveObject) { |
| 882 | node->object = (*collection->createObject)(node->object); |
| 883 | if (!node->object) { |
| 884 | link = PR_NEXT_LINK(link)((link)->next); |
| 885 | /*remove bogus object from list*/ |
| 886 | nssPKIObjectCollection_RemoveNode(collection, node); |
| 887 | continue; |
| 888 | } |
| 889 | node->haveObject = PR_TRUE1; |
| 890 | } |
| 891 | switch (collection->objectType) { |
| 892 | case pkiObjectType_Certificate: |
| 893 | (void)(*callback->func.cert)((NSSCertificate *)node->object, |
| 894 | callback->arg); |
| 895 | break; |
| 896 | case pkiObjectType_CRL: |
| 897 | (void)(*callback->func.crl)((NSSCRL *)node->object, |
| 898 | callback->arg); |
| 899 | break; |
| 900 | case pkiObjectType_PrivateKey: |
| 901 | (void)(*callback->func.pvkey)((NSSPrivateKey *)node->object, |
| 902 | callback->arg); |
| 903 | break; |
| 904 | case pkiObjectType_PublicKey: |
| 905 | (void)(*callback->func.pbkey)((NSSPublicKey *)node->object, |
| 906 | callback->arg); |
| 907 | break; |
| 908 | } |
| 909 | link = PR_NEXT_LINK(link)((link)->next); |
| 910 | } |
| 911 | return PR_SUCCESS; |
| 912 | } |
| 913 | |
| 914 | NSS_IMPLEMENT PRStatus |
| 915 | nssPKIObjectCollection_AddInstanceAsObject( |
| 916 | nssPKIObjectCollection *collection, |
| 917 | nssCryptokiObject *instance) |
| 918 | { |
| 919 | pkiObjectCollectionNode *node; |
| 920 | PRBool foundIt; |
| 921 | node = add_object_instance(collection, instance, &foundIt); |
| 922 | if (node == NULL((void*)0)) { |
| 923 | return PR_FAILURE; |
| 924 | } |
| 925 | if (!node->haveObject) { |
| 926 | nssPKIObject *original = node->object; |
| 927 | node->object = (*collection->createObject)(node->object); |
| 928 | if (!node->object) { |
| 929 | /*remove bogus object from list*/ |
| 930 | nssPKIObject_Destroy(original); |
| 931 | nssPKIObjectCollection_RemoveNode(collection, node); |
| 932 | return PR_FAILURE; |
| 933 | } |
| 934 | node->haveObject = PR_TRUE1; |
| 935 | } else if (!foundIt) { |
| 936 | /* The instance was added to a pre-existing node. This |
| 937 | * function is *only* being used for certificates, and having |
| 938 | * multiple instances of certs in 3.X requires updating the |
| 939 | * CERTCertificate. |
| 940 | * But only do it if it was a new instance!!! If the same instance |
| 941 | * is encountered, we set *foundIt to true. Detect that here and |
| 942 | * ignore it. |
| 943 | */ |
| 944 | STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object); |
| 945 | } |
| 946 | return PR_SUCCESS; |
| 947 | } |
| 948 | |
| 949 | /* |
| 950 | * Certificate collections |
| 951 | */ |
| 952 | |
| 953 | static void |
| 954 | cert_destroyObject(nssPKIObject *o) |
| 955 | { |
| 956 | NSSCertificate *c = (NSSCertificate *)o; |
| 957 | if (c->decoding) { |
| 958 | CERTCertificate *cc = STAN_GetCERTCertificate(c); |
| 959 | if (cc) { |
| 960 | CERT_DestroyCertificate(cc); |
| 961 | return; |
| 962 | } /* else destroy it as NSSCertificate below */ |
| 963 | } |
| 964 | nssCertificate_Destroy(c); |
| 965 | } |
| 966 | |
| 967 | static PRStatus |
| 968 | cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid) |
| 969 | { |
| 970 | NSSCertificate *c = (NSSCertificate *)o; |
| 971 | /* The builtins are still returning decoded serial numbers. Until |
| 972 | * this compatibility issue is resolved, use the full DER of the |
| 973 | * cert to uniquely identify it. |
| 974 | */ |
| 975 | NSSDER *derCert; |
| 976 | derCert = nssCertificate_GetEncoding(c); |
| 977 | uid[0].data = NULL((void*)0); |
| 978 | uid[0].size = 0; |
| 979 | uid[1].data = NULL((void*)0); |
| 980 | uid[1].size = 0; |
| 981 | if (derCert != NULL((void*)0)) { |
| 982 | uid[0] = *derCert; |
| 983 | } |
| 984 | return PR_SUCCESS; |
| 985 | } |
| 986 | |
| 987 | static PRStatus |
| 988 | cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, |
| 989 | NSSArena *arena) |
| 990 | { |
| 991 | /* The builtins are still returning decoded serial numbers. Until |
| 992 | * this compatibility issue is resolved, use the full DER of the |
| 993 | * cert to uniquely identify it. |
| 994 | */ |
| 995 | uid[1].data = NULL((void*)0); |
| 996 | uid[1].size = 0; |
| 997 | return nssCryptokiCertificate_GetAttributes(instance, |
| 998 | NULL((void*)0), /* XXX sessionOpt */ |
| 999 | arena, /* arena */ |
| 1000 | NULL((void*)0), /* type */ |
| 1001 | NULL((void*)0), /* id */ |
| 1002 | &uid[0], /* encoding */ |
| 1003 | NULL((void*)0), /* issuer */ |
| 1004 | NULL((void*)0), /* serial */ |
| 1005 | NULL((void*)0)); /* subject */ |
| 1006 | } |
| 1007 | |
| 1008 | static nssPKIObject * |
| 1009 | cert_createObject(nssPKIObject *o) |
| 1010 | { |
| 1011 | NSSCertificate *cert; |
| 1012 | cert = nssCertificate_Create(o); |
| 1013 | /* if (STAN_GetCERTCertificate(cert) == NULL) { |
| 1014 | nssCertificate_Destroy(cert); |
| 1015 | return (nssPKIObject *)NULL; |
| 1016 | } */ |
| 1017 | /* In 3.4, have to maintain uniqueness of cert pointers by caching all |
| 1018 | * certs. Cache the cert here, before returning. If it is already |
| 1019 | * cached, take the cached entry. |
| 1020 | */ |
| 1021 | { |
| 1022 | NSSTrustDomain *td = o->trustDomain; |
| 1023 | nssTrustDomain_AddCertsToCache(td, &cert, 1); |
| 1024 | } |
| 1025 | return (nssPKIObject *)cert; |
| 1026 | } |
| 1027 | |
| 1028 | NSS_IMPLEMENT nssPKIObjectCollection * |
| 1029 | nssCertificateCollection_Create( |
| 1030 | NSSTrustDomain *td, |
| 1031 | NSSCertificate **certsOpt) |
| 1032 | { |
| 1033 | nssPKIObjectCollection *collection; |
| 1034 | collection = nssPKIObjectCollection_Create(td, NULL((void*)0), nssPKIMonitor); |
| 1035 | if (!collection) { |
| 1036 | return NULL((void*)0); |
| 1037 | } |
| 1038 | collection->objectType = pkiObjectType_Certificate; |
| 1039 | collection->destroyObject = cert_destroyObject; |
| 1040 | collection->getUIDFromObject = cert_getUIDFromObject; |
| 1041 | collection->getUIDFromInstance = cert_getUIDFromInstance; |
| 1042 | collection->createObject = cert_createObject; |
| 1043 | if (certsOpt) { |
| 1044 | for (; *certsOpt; certsOpt++) { |
| 1045 | nssPKIObject *object = (nssPKIObject *)(*certsOpt); |
| 1046 | (void)nssPKIObjectCollection_AddObject(collection, object); |
| 1047 | } |
| 1048 | } |
| 1049 | return collection; |
| 1050 | } |
| 1051 | |
| 1052 | NSS_IMPLEMENT NSSCertificate ** |
| 1053 | nssPKIObjectCollection_GetCertificates( |
| 1054 | nssPKIObjectCollection *collection, |
| 1055 | NSSCertificate **rvOpt, |
| 1056 | PRUint32 maximumOpt, |
| 1057 | NSSArena *arenaOpt) |
| 1058 | { |
| 1059 | PRStatus status; |
| 1060 | PRUint32 rvSize; |
| 1061 | PRBool allocated = PR_FALSE0; |
| 1062 | if (collection->size == 0) { |
| 1063 | return (NSSCertificate **)NULL((void*)0); |
| 1064 | } |
| 1065 | if (maximumOpt == 0) { |
| 1066 | rvSize = collection->size; |
| 1067 | } else { |
| 1068 | rvSize = PR_MIN(collection->size, maximumOpt)((collection->size)<(maximumOpt)?(collection->size): (maximumOpt)); |
| 1069 | } |
| 1070 | if (!rvOpt) { |
| 1071 | rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1)((NSSCertificate * *)nss_ZAlloc((arenaOpt), sizeof(NSSCertificate *) * (rvSize + 1))); |
| 1072 | if (!rvOpt) { |
| 1073 | return (NSSCertificate **)NULL((void*)0); |
| 1074 | } |
| 1075 | allocated = PR_TRUE1; |
| 1076 | } |
| 1077 | status = nssPKIObjectCollection_GetObjects(collection, |
| 1078 | (nssPKIObject **)rvOpt, |
| 1079 | rvSize); |
| 1080 | if (status != PR_SUCCESS) { |
| 1081 | if (allocated) { |
| 1082 | nss_ZFreeIf(rvOpt); |
| 1083 | } |
| 1084 | return (NSSCertificate **)NULL((void*)0); |
| 1085 | } |
| 1086 | return rvOpt; |
| 1087 | } |
| 1088 | |
| 1089 | /* |
| 1090 | * CRL/KRL collections |
| 1091 | */ |
| 1092 | |
| 1093 | static void |
| 1094 | crl_destroyObject(nssPKIObject *o) |
| 1095 | { |
| 1096 | NSSCRL *crl = (NSSCRL *)o; |
| 1097 | nssCRL_Destroy(crl); |
| 1098 | } |
| 1099 | |
| 1100 | static PRStatus |
| 1101 | crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid) |
| 1102 | { |
| 1103 | NSSCRL *crl = (NSSCRL *)o; |
| 1104 | NSSDER *encoding; |
| 1105 | encoding = nssCRL_GetEncoding(crl); |
| 1106 | if (!encoding) { |
| 1107 | nss_SetError(NSS_ERROR_INVALID_ARGUMENT); |
| 1108 | return PR_FALSE0; |
| 1109 | } |
| 1110 | uid[0] = *encoding; |
| 1111 | uid[1].data = NULL((void*)0); |
| 1112 | uid[1].size = 0; |
| 1113 | return PR_SUCCESS; |
| 1114 | } |
| 1115 | |
| 1116 | static PRStatus |
| 1117 | crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, |
| 1118 | NSSArena *arena) |
| 1119 | { |
| 1120 | return nssCryptokiCRL_GetAttributes(instance, |
| 1121 | NULL((void*)0), /* XXX sessionOpt */ |
| 1122 | arena, /* arena */ |
| 1123 | &uid[0], /* encoding */ |
| 1124 | NULL((void*)0), /* subject */ |
| 1125 | NULL((void*)0), /* class */ |
| 1126 | NULL((void*)0), /* url */ |
| 1127 | NULL((void*)0)); /* isKRL */ |
| 1128 | } |
| 1129 | |
| 1130 | static nssPKIObject * |
| 1131 | crl_createObject(nssPKIObject *o) |
| 1132 | { |
| 1133 | return (nssPKIObject *)nssCRL_Create(o); |
| 1134 | } |
| 1135 | |
| 1136 | NSS_IMPLEMENT nssPKIObjectCollection * |
| 1137 | nssCRLCollection_Create( |
| 1138 | NSSTrustDomain *td, |
| 1139 | NSSCRL **crlsOpt) |
| 1140 | { |
| 1141 | nssPKIObjectCollection *collection; |
| 1142 | collection = nssPKIObjectCollection_Create(td, NULL((void*)0), nssPKILock); |
| 1143 | if (!collection) { |
| 1144 | return NULL((void*)0); |
| 1145 | } |
| 1146 | collection->objectType = pkiObjectType_CRL; |
| 1147 | collection->destroyObject = crl_destroyObject; |
| 1148 | collection->getUIDFromObject = crl_getUIDFromObject; |
| 1149 | collection->getUIDFromInstance = crl_getUIDFromInstance; |
| 1150 | collection->createObject = crl_createObject; |
| 1151 | if (crlsOpt) { |
| 1152 | for (; *crlsOpt; crlsOpt++) { |
| 1153 | nssPKIObject *object = (nssPKIObject *)(*crlsOpt); |
| 1154 | (void)nssPKIObjectCollection_AddObject(collection, object); |
| 1155 | } |
| 1156 | } |
| 1157 | return collection; |
| 1158 | } |
| 1159 | |
| 1160 | NSS_IMPLEMENT NSSCRL ** |
| 1161 | nssPKIObjectCollection_GetCRLs( |
| 1162 | nssPKIObjectCollection *collection, |
| 1163 | NSSCRL **rvOpt, |
| 1164 | PRUint32 maximumOpt, |
| 1165 | NSSArena *arenaOpt) |
| 1166 | { |
| 1167 | PRStatus status; |
| 1168 | PRUint32 rvSize; |
| 1169 | PRBool allocated = PR_FALSE0; |
| 1170 | if (collection->size == 0) { |
| 1171 | return (NSSCRL **)NULL((void*)0); |
| 1172 | } |
| 1173 | if (maximumOpt == 0) { |
| 1174 | rvSize = collection->size; |
| 1175 | } else { |
| 1176 | rvSize = PR_MIN(collection->size, maximumOpt)((collection->size)<(maximumOpt)?(collection->size): (maximumOpt)); |
| 1177 | } |
| 1178 | if (!rvOpt) { |
| 1179 | rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1)((NSSCRL * *)nss_ZAlloc((arenaOpt), sizeof(NSSCRL *) * (rvSize + 1))); |
| 1180 | if (!rvOpt) { |
| 1181 | return (NSSCRL **)NULL((void*)0); |
| 1182 | } |
| 1183 | allocated = PR_TRUE1; |
| 1184 | } |
| 1185 | status = nssPKIObjectCollection_GetObjects(collection, |
| 1186 | (nssPKIObject **)rvOpt, |
| 1187 | rvSize); |
| 1188 | if (status != PR_SUCCESS) { |
| 1189 | if (allocated) { |
| 1190 | nss_ZFreeIf(rvOpt); |
| 1191 | } |
| 1192 | return (NSSCRL **)NULL((void*)0); |
| 1193 | } |
| 1194 | return rvOpt; |
| 1195 | } |
| 1196 | |
| 1197 | /* how bad would it be to have a static now sitting around, updated whenever |
| 1198 | * this was called? would avoid repeated allocs... |
| 1199 | */ |
| 1200 | NSS_IMPLEMENT NSSTime * |
| 1201 | NSSTime_Now(NSSTime *timeOpt) |
| 1202 | { |
| 1203 | return NSSTime_SetPRTime(timeOpt, PR_Now()); |
| 1204 | } |
| 1205 | |
| 1206 | NSS_IMPLEMENT NSSTime * |
| 1207 | NSSTime_SetPRTime( |
| 1208 | NSSTime *timeOpt, |
| 1209 | PRTime prTime) |
| 1210 | { |
| 1211 | NSSTime *rvTime; |
| 1212 | rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime)((NSSTime *)nss_ZAlloc((((void*)0)), sizeof(NSSTime))); |
| 1213 | if (rvTime) { |
| 1214 | rvTime->prTime = prTime; |
| 1215 | } |
| 1216 | return rvTime; |
| 1217 | } |
| 1218 | |
| 1219 | NSS_IMPLEMENT PRTime |
| 1220 | NSSTime_GetPRTime( |
| 1221 | NSSTime *time) |
| 1222 | { |
| 1223 | return time->prTime; |
| 1224 | } |