Changeset 57613 in vbox for trunk/src/VBox/Runtime/common/crypto/store-cert-add-basic.cpp
- Timestamp:
- Sep 4, 2015 2:19:44 AM (9 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/crypto/store-cert-add-basic.cpp
r57607 r57613 33 33 34 34 #include <iprt/assert.h> 35 #include <iprt/crypto/pem.h> 35 36 #include <iprt/dir.h> 36 37 #include <iprt/err.h> 38 #include <iprt/file.h> 39 #include <iprt/mem.h> 37 40 #include <iprt/path.h> 41 #include <iprt/sha.h> 38 42 #include <iprt/string.h> 43 44 #include "x509-internal.h" 45 46 47 /********************************************************************************************************************************* 48 * Global Variables * 49 *********************************************************************************************************************************/ 50 /** BEGIN CERTIFICATE / END CERTIFICATE. */ 51 static RTCRPEMMARKERWORD const g_aWords_Certificate[] = 52 { 53 { RT_STR_TUPLE("CERTIFICATE") } 54 }; 55 56 /** BEGIN TRUSTED CERTIFICATE / END TRUSTED CERTIFICATE. */ 57 static RTCRPEMMARKERWORD const g_aWords_TrustedCertificate[] = 58 { 59 { RT_STR_TUPLE("TRUSTED") }, 60 { RT_STR_TUPLE("CERTIFICATE") } 61 }; 62 63 /** BEGIN X509 CERTIFICATE / END X509 CERTIFICATE. (old) */ 64 static RTCRPEMMARKERWORD const g_aWords_X509Certificate[] = 65 { 66 { RT_STR_TUPLE("X509") }, 67 { RT_STR_TUPLE("CERTIFICATE") } 68 }; 69 70 /** 71 * X509 Certificate markers. 72 * 73 * @remark See crypto/pem/pem.h in OpenSSL for a matching list. 74 */ 75 RTCRPEMMARKER const g_aX509CertificateMarkers[3] = 76 { 77 { g_aWords_Certificate, RT_ELEMENTS(g_aWords_Certificate) }, 78 { g_aWords_TrustedCertificate, RT_ELEMENTS(g_aWords_TrustedCertificate) }, 79 { g_aWords_X509Certificate, RT_ELEMENTS(g_aWords_X509Certificate) } 80 }; 81 82 83 84 /** 85 * Checks if we've found all the certificates already. 86 * 87 * @returns true if all found, false if not. 88 * @param afFound Indicator array. 89 * @param cWanted Number of wanted certificates. 90 */ 91 DECLINLINE(bool) rtCrStoreAllDone(bool const *afFound, size_t cWanted) 92 { 93 while (cWanted-- > 0) 94 if (!afFound[cWanted]) 95 return false; 96 return true; 97 } 98 99 100 /** 101 * Checks if the given certificate specs matches the given wanted poster. 102 * 103 * @returns true if match, false if not. 104 * @param pWanted The certificate wanted poster. 105 * @param cbEncoded The candidate certificate encoded size. 106 * @param paSha1 The candidate certificate SHA-1 fingerprint. 107 * @param paSha512 The candidate certificate SHA-512 fingerprint. 108 * @param pCert The decoded candidate certificate, optional. If not 109 * given the result will be uncertain. 110 */ 111 DECLINLINE(bool) rtCrStoreIsCertEqualToWanted(PCRTCRCERTWANTED pWanted, 112 size_t cbEncoded, 113 uint8_t const pabSha1[RTSHA1_HASH_SIZE], 114 uint8_t const pabSha512[RTSHA512_HASH_SIZE], 115 PCRTCRX509CERTIFICATE pCert) 116 { 117 if ( pWanted->cbEncoded != cbEncoded 118 && pWanted->cbEncoded != 0) 119 return false; 120 121 if ( pWanted->fSha1Fingerprint 122 && memcmp(pWanted->abSha1, pabSha1, RTSHA1_HASH_SIZE) != 0) 123 return false; 124 125 if ( pWanted->fSha512Fingerprint 126 && memcmp(pWanted->abSha512, pabSha512, RTSHA512_HASH_SIZE) != 0) 127 return false; 128 129 if ( pWanted->pszSubject 130 && pCert 131 && !RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, pWanted->pszSubject)) 132 return false; 133 134 return true; 135 } 136 137 138 /** 139 * Checks if a certificate is wanted. 140 * 141 * @returns true if match, false if not. 142 * @param paWanted The certificate wanted posters. 143 * @param cWanted The number of wanted posters. 144 * @param apfFound Found initicators running paralell to @a paWanted. 145 * @param cbEncoded The candidate certificate encoded size. 146 * @param paSha1 The candidate certificate SHA-1 fingerprint. 147 * @param paSha512 The candidate certificate SHA-512 fingerprint. 148 * @param pCert The decoded candidate certificate, optional. If not 149 * given the result will be uncertain. 150 */ 151 DECLINLINE(bool) rtCrStoreIsCertWanted(PCRTCRCERTWANTED paWanted, size_t cWanted, bool const *pafFound, size_t cbEncoded, 152 uint8_t const pabSha1[RTSHA1_HASH_SIZE], uint8_t const pabSha512[RTSHA512_HASH_SIZE], 153 PCRTCRX509CERTIFICATE pCert) 154 { 155 for (size_t iCert = 0; iCert < cWanted; iCert++) 156 if (!pafFound[iCert]) 157 if (rtCrStoreIsCertEqualToWanted(&paWanted[iCert], cbEncoded, pabSha1, pabSha512, pCert)) 158 return true; 159 return false; 160 } 161 162 163 /** 164 * Marks a certificate as found after it has been added to the store. 165 * 166 * May actually mark several certificates as found if there are duplicates or 167 * ambiguities in the wanted list. 168 * 169 * @returns true if all have been found, false if more to search for. 170 * 171 * @param apfFound Found initicators running paralell to @a paWanted. 172 * This is what this function updates. 173 * @param paWanted The certificate wanted posters. 174 * @param cWanted The number of wanted posters. 175 * @param cbEncoded The candidate certificate encoded size. 176 * @param paSha1 The candidate certificate SHA-1 fingerprint. 177 * @param paSha512 The candidate certificate SHA-512 fingerprint. 178 * @param pCert The decoded candidate certificate, optional. If not 179 * given the result will be uncertain. 180 */ 181 static bool rtCrStoreMarkCertFound(bool *pafFound, PCRTCRCERTWANTED paWanted, size_t cWanted, size_t cbEncoded, 182 uint8_t const pabSha1[RTSHA1_HASH_SIZE], uint8_t const pabSha512[RTSHA512_HASH_SIZE], 183 PCRTCRX509CERTIFICATE pCert) 184 { 185 size_t cFound = 0; 186 for (size_t iCert = 0; iCert < cWanted; iCert++) 187 if (pafFound[iCert]) 188 cFound++; 189 else if (rtCrStoreIsCertEqualToWanted(&paWanted[iCert], cbEncoded, pabSha1, pabSha512, pCert)) 190 { 191 pafFound[iCert] = true; 192 cFound++; 193 } 194 return cFound == cWanted; 195 } 196 197 198 RTDECL(int) RTCrStoreCertAddFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hStoreSrc) 199 { 200 /* 201 * Validate input. 202 */ 203 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 204 205 /* 206 * Enumerate all the certificates in the source store, adding them to the destination. 207 */ 208 RTCRSTORECERTSEARCH Search; 209 int rc = RTCrStoreCertFindAll(hStoreSrc, &Search); 210 if (RT_SUCCESS(rc)) 211 { 212 PCRTCRCERTCTX pCertCtx; 213 while ((pCertCtx = RTCrStoreCertSearchNext(hStoreSrc, &Search)) != NULL) 214 { 215 int rc2 = RTCrStoreCertAddEncoded(hStore, pCertCtx->fFlags | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 216 pCertCtx->pabEncoded, pCertCtx->cbEncoded, NULL); 217 if (RT_FAILURE(rc2)) 218 { 219 rc = rc2; 220 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 221 break; 222 } 223 RTCrCertCtxRelease(pCertCtx); 224 } 225 226 int rc2 = RTCrStoreCertSearchDestroy(hStoreSrc, &Search); AssertRC(rc2); 227 } 228 return rc; 229 } 230 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromStore); 231 232 233 RTDECL(int) RTCrStoreCertAddWantedFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hSrcStore, 234 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound) 235 { 236 /* 237 * Validate input a little. 238 */ 239 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 240 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 241 242 AssertReturn(cWanted, VERR_NOT_FOUND); 243 for (uint32_t i = 0; i < cWanted; i++) 244 { 245 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 246 AssertReturn( paWanted[i].pszSubject 247 || paWanted[i].fSha1Fingerprint 248 || paWanted[i].fSha512Fingerprint, 249 VERR_INVALID_PARAMETER); 250 } 251 252 /* 253 * Make sure we've got a result array. 254 */ 255 bool *pafFoundFree = NULL; 256 if (!pafFound) 257 { 258 pafFound = pafFoundFree = (bool *)RTMemTmpAllocZ(sizeof(bool) * cWanted); 259 AssertReturn(pafFound, VERR_NO_TMP_MEMORY); 260 } 261 262 /* 263 * Enumerate the store entries. 264 */ 265 RTCRSTORECERTSEARCH Search; 266 int rc = RTCrStoreCertFindAll(hSrcStore, &Search); 267 if (RT_SUCCESS(rc)) 268 { 269 rc = VWRN_NOT_FOUND; 270 PCRTCRCERTCTX pCertCtx; 271 while ((pCertCtx = RTCrStoreCertSearchNext(hSrcStore, &Search)) != NULL) 272 { 273 if ( (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) == RTCRCERTCTX_F_ENC_X509_DER 274 && pCertCtx->cbEncoded > 0 275 && pCertCtx->pCert) 276 { 277 /* 278 * If the certificate is wanted, try add it to the store. 279 */ 280 uint8_t abSha1[RTSHA1_HASH_SIZE]; 281 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha1); 282 uint8_t abSha512[RTSHA512_HASH_SIZE]; 283 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha512); 284 if (rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 285 { 286 int rc2 = RTCrStoreCertAddEncoded(hStore, 287 RTCRCERTCTX_F_ENC_X509_DER | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 288 pCertCtx->pabEncoded, pCertCtx->cbEncoded, NULL /*pErrInfo*/); 289 if (RT_SUCCESS(rc2)) 290 { 291 /* 292 * Mark it as found, stop if we've found all. 293 */ 294 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, 295 pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 296 { 297 if (RT_SUCCESS(rc)) 298 rc = VINF_SUCCESS; 299 RTCrCertCtxRelease(pCertCtx); 300 break; 301 } 302 } 303 else 304 { 305 /* 306 * Some error adding the certificate. Since it cannot be anything with 307 * the encoding, it must be something with the store or resources, so 308 * always return the error status. 309 */ 310 rc = rc2; 311 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 312 { 313 RTCrCertCtxRelease(pCertCtx); 314 break; 315 } 316 } 317 } 318 } 319 RTCrCertCtxRelease(pCertCtx); 320 } 321 int rc2 = RTCrStoreCertSearchDestroy(hSrcStore, &Search); 322 AssertRC(rc2); 323 } 324 325 if (pafFoundFree) 326 RTMemTmpFree(pafFoundFree); 327 return rc; 328 } 329 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore); 330 331 332 RTDECL(int) RTCrStoreCertCheckWanted(RTCRSTORE hStore, PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound) 333 { 334 /* 335 * Validate input a little. 336 */ 337 AssertReturn(cWanted, VERR_NOT_FOUND); 338 for (uint32_t i = 0; i < cWanted; i++) 339 { 340 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 341 AssertReturn( paWanted[i].pszSubject 342 || paWanted[i].fSha1Fingerprint 343 || paWanted[i].fSha512Fingerprint, 344 VERR_INVALID_PARAMETER); 345 } 346 AssertPtrReturn(pafFound, VERR_INVALID_POINTER); 347 348 /* 349 * Clear the found array. 350 */ 351 for (uint32_t iCert = 0; iCert < cWanted; iCert++) 352 pafFound[iCert] = false; 353 354 /* 355 * Enumerate the store entries. 356 */ 357 RTCRSTORECERTSEARCH Search; 358 int rc = RTCrStoreCertFindAll(hStore, &Search); 359 if (RT_SUCCESS(rc)) 360 { 361 rc = VWRN_NOT_FOUND; 362 PCRTCRCERTCTX pCertCtx; 363 while ((pCertCtx = RTCrStoreCertSearchNext(hStore, &Search)) != NULL) 364 { 365 if ( (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) == RTCRCERTCTX_F_ENC_X509_DER 366 && pCertCtx->cbEncoded > 0 367 && pCertCtx->pCert) 368 { 369 /* 370 * Hash it and check if it's wanted. Stop when we've found all. 371 */ 372 uint8_t abSha1[RTSHA1_HASH_SIZE]; 373 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha1); 374 uint8_t abSha512[RTSHA512_HASH_SIZE]; 375 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha512); 376 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 377 { 378 rc = VINF_SUCCESS; 379 RTCrCertCtxRelease(pCertCtx); 380 break; 381 } 382 } 383 RTCrCertCtxRelease(pCertCtx); 384 } 385 int rc2 = RTCrStoreCertSearchDestroy(hStore, &Search); 386 AssertRC(rc2); 387 } 388 389 return rc; 390 } 391 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore); 392 393 394 RTDECL(int) RTCrStoreCertAddFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo) 395 { 396 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 397 398 size_t cbContent; 399 void *pvContent; 400 int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, &pvContent, &cbContent); 401 if (RT_SUCCESS(rc)) 402 { 403 /* 404 * Is it a java key store file? 405 */ 406 if ( cbContent > 32 407 && ((uint32_t const *)pvContent)[0] == RT_H2BE_U32_C(UINT32_C(0xfeedfeed)) /* magic */ 408 && ((uint32_t const *)pvContent)[1] == RT_H2BE_U32_C(UINT32_C(0x00000002)) /* version */ ) 409 rc = RTCrStoreCertAddFromJavaKeyStoreInMem(hStore, fFlags, pvContent, cbContent, pszFilename, pErrInfo); 410 /* 411 * No assume PEM or DER encoded binary certificate. 412 */ 413 else 414 { 415 PCRTCRPEMSECTION pSectionHead; 416 rc = RTCrPemParseContent(pvContent, cbContent, 417 (fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR) 418 ? RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR : 0, 419 g_aX509CertificateMarkers, RT_ELEMENTS(g_aX509CertificateMarkers), 420 &pSectionHead, pErrInfo); 421 if (RT_SUCCESS(rc)) 422 { 423 PCRTCRPEMSECTION pCurSec = pSectionHead; 424 while (pCurSec) 425 { 426 int rc2 = RTCrStoreCertAddEncoded(hStore, 427 RTCRCERTCTX_F_ENC_X509_DER | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 428 pCurSec->pbData, pCurSec->cbData, 429 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL); 430 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 431 { 432 rc = rc2; 433 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 434 break; 435 } 436 pCurSec = pCurSec->pNext; 437 } 438 439 RTCrPemFreeSections(pSectionHead); 440 } 441 } 442 RTFileReadAllFree(pvContent, cbContent); 443 } 444 else 445 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileReadAllEx failed with %Rrc on '%s'", rc, pszFilename); 446 return rc; 447 } 448 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromFile); 449 450 451 RTDECL(int) RTCrStoreCertAddWantedFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, 452 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo) 453 { 454 /* 455 * Validate input a little. 456 */ 457 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 458 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 459 460 AssertReturn(cWanted, VERR_NOT_FOUND); 461 for (uint32_t i = 0; i < cWanted; i++) 462 { 463 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 464 AssertReturn( paWanted[i].pszSubject 465 || paWanted[i].fSha1Fingerprint 466 || paWanted[i].fSha512Fingerprint, 467 VERR_INVALID_PARAMETER); 468 } 469 470 /* 471 * Make sure we've got a result array. 472 */ 473 bool *pafFoundFree = NULL; 474 if (!pafFound) 475 { 476 pafFound = pafFoundFree = (bool *)RTMemTmpAllocZ(sizeof(bool) * cWanted); 477 AssertReturn(pafFound, VERR_NO_TMP_MEMORY); 478 } 479 480 size_t cbContent; 481 void *pvContent; 482 int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, &pvContent, &cbContent); 483 if (RT_SUCCESS(rc)) 484 { 485 /* 486 * Is it a java key store file? If so, load it into a tmp store 487 * which we can search. Don't want to duplicate the JKS reader code. 488 */ 489 if ( cbContent > 32 490 && ((uint32_t const *)pvContent)[0] == RT_H2BE_U32_C(UINT32_C(0xfeedfeed)) /* magic */ 491 && ((uint32_t const *)pvContent)[1] == RT_H2BE_U32_C(UINT32_C(0x00000002)) /* version */ ) 492 { 493 RTCRSTORE hTmpStore; 494 rc = RTCrStoreCreateInMem(&hTmpStore, 64); 495 if (RT_SUCCESS(rc)) 496 { 497 rc = RTCrStoreCertAddFromJavaKeyStoreInMem(hStore, fFlags, pvContent, cbContent, pszFilename, pErrInfo); 498 if (RT_SUCCESS(rc)) 499 rc = RTCrStoreCertAddWantedFromStore(hStore, fFlags, hTmpStore, paWanted, cWanted, pafFound); 500 RTCrStoreRelease(hTmpStore); 501 } 502 else 503 rc = RTErrInfoSet(pErrInfo, rc, "Error creating temporary crypto store"); 504 } 505 /* 506 * No assume PEM or DER encoded binary certificate. Inspect them one by one. 507 */ 508 else 509 { 510 PCRTCRPEMSECTION pSectionHead; 511 rc = RTCrPemParseContent(pvContent, cbContent, 512 (fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR) 513 ? RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR : 0, 514 g_aX509CertificateMarkers, RT_ELEMENTS(g_aX509CertificateMarkers), 515 &pSectionHead, pErrInfo); 516 if (RT_SUCCESS(rc)) 517 { 518 rc = VWRN_NOT_FOUND; 519 for (PCRTCRPEMSECTION pCurSec = pSectionHead; pCurSec; pCurSec = pCurSec->pNext) 520 { 521 if (!pCurSec->cbData) 522 continue; 523 524 /* 525 * See if this is a binary blob we might be interested in. 526 */ 527 uint8_t abSha1[RTSHA1_HASH_SIZE]; 528 RTSha1(pCurSec->pbData, pCurSec->cbData, abSha1); 529 uint8_t abSha512[RTSHA512_HASH_SIZE]; 530 RTSha1(pCurSec->pbData, pCurSec->cbData, abSha512); 531 if (!rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCurSec->cbData, abSha1, abSha512, NULL)) 532 continue; 533 534 /* 535 * Decode the certificate so we can match the subject string. 536 */ 537 RTASN1CURSORPRIMARY Cursor; 538 RTAsn1CursorInitPrimary(&Cursor, pCurSec->pbData, (uint32_t)pCurSec->cbData, 539 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL, 540 &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "InMem"); 541 RTCRX509CERTIFICATE X509Cert; 542 int rc2 = RTCrX509Certificate_DecodeAsn1(&Cursor.Cursor, 0, &X509Cert, "Cert"); 543 if (RT_SUCCESS(rc2)) 544 { 545 rc2 = RTCrX509Certificate_CheckSanity(&X509Cert, 0, !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL, "Cert"); 546 if (RT_SUCCESS(rc2)) 547 { 548 if (rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCurSec->cbData, abSha1, abSha512, &X509Cert)) 549 { 550 /* 551 * The certificate is wanted, now add it to the store. 552 */ 553 rc2 = RTCrStoreCertAddEncoded(hStore, 554 RTCRCERTCTX_F_ENC_X509_DER 555 | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 556 pCurSec->pbData, pCurSec->cbData, 557 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL); 558 if (RT_SUCCESS(rc2)) 559 { 560 /* 561 * Mark it as found, stop if we've found all. 562 */ 563 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, 564 pCurSec->cbData, abSha1, abSha512, &X509Cert)) 565 { 566 RTAsn1VtDelete(&X509Cert.SeqCore.Asn1Core); 567 rc = VINF_SUCCESS; 568 break; 569 } 570 } 571 } 572 } 573 else 574 Assert(!pErrInfo || RTErrInfoIsSet(pErrInfo)); 575 RTAsn1VtDelete(&X509Cert.SeqCore.Asn1Core); 576 } 577 else if (!RTErrInfoIsSet(pErrInfo)) 578 RTErrInfoSetF(pErrInfo, rc2, "RTCrX509Certificate_DecodeAsn1 failed"); 579 580 /* 581 * Stop on error, if requested. Otherwise, let pErrInfo keep it. 582 */ 583 if (RT_FAILURE(rc2) && !(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 584 { 585 rc = rc2; 586 break; 587 } 588 } /* For each PEM section. */ 589 590 RTCrPemFreeSections(pSectionHead); 591 } 592 } 593 RTFileReadAllFree(pvContent, cbContent); 594 } 595 else 596 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileReadAllEx failed with %Rrc on '%s'", rc, pszFilename); 597 598 if (pafFoundFree) 599 RTMemTmpFree(pafFoundFree); 600 return rc; 601 } 602 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromFile); 39 603 40 604 … … 88 652 if (cchPath > 0) 89 653 { 90 size_t const cb Filename = sizeof(szPath) - cchPath;654 size_t const cbMaxFilename = sizeof(szPath) - cchPath; 91 655 92 656 /* … … 109 673 if (RT_SUCCESS(rc2)) 110 674 { 111 if ( !RTDirEntryIsStdDotLink(&u.DirEntry) 675 if ( ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 676 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 677 || ( u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN 678 && !RTDirEntryIsStdDotLink(&u.DirEntry)) ) 112 679 && rtCrStoreIsSuffixMatch(&u.DirEntry, paSuffixes, cSuffixes) ) 113 680 { 114 if (u.DirEntry.cbName < cb Filename)681 if (u.DirEntry.cbName < cbMaxFilename) 115 682 { 116 683 memcpy(&szPath[cchPath], u.DirEntry.szName, u.DirEntry.cbName + 1); … … 131 698 } 132 699 } 133 else if ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 134 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 135 || u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN) 700 else 136 701 { 137 702 rc = RTErrInfoAddF(pErrInfo, VERR_FILENAME_TOO_LONG, … … 160 725 return rc; 161 726 } 162 163 727 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromDir); 728 729 730 RTDECL(int) RTCrStoreCertAddWantedFromDir(RTCRSTORE hStore, uint32_t fFlags, 731 const char *pszDir, PCRTSTRTUPLE paSuffixes, size_t cSuffixes, 732 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo) 733 { 734 /* 735 * Validate input a little. 736 */ 737 AssertReturn(*pszDir, VERR_PATH_ZERO_LENGTH); 738 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 739 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 740 741 AssertReturn(cWanted, VERR_NOT_FOUND); 742 for (uint32_t i = 0; i < cWanted; i++) 743 { 744 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 745 AssertReturn( paWanted[i].pszSubject 746 || paWanted[i].fSha1Fingerprint 747 || paWanted[i].fSha512Fingerprint, 748 VERR_INVALID_PARAMETER); 749 } 750 751 /* 752 * Prepare for constructing path to the files in the directory, so that we 753 * can open them. 754 */ 755 char szPath[RTPATH_MAX]; 756 int rc = RTStrCopy(szPath, sizeof(szPath), pszDir); 757 if (RT_SUCCESS(rc)) 758 { 759 size_t cchPath = RTPathEnsureTrailingSeparator(szPath, sizeof(szPath)); 760 if (cchPath > 0) 761 { 762 size_t const cbMaxFilename = sizeof(szPath) - cchPath; 763 764 /* 765 * Enumerate the directory. 766 */ 767 PRTDIR hDir; 768 rc = RTDirOpen(&hDir, pszDir); 769 if (RT_SUCCESS(rc)) 770 { 771 rc = VWRN_NOT_FOUND; 772 for (;;) 773 { 774 /* Read the next entry. */ 775 union 776 { 777 RTDIRENTRY DirEntry; 778 uint8_t abPadding[RT_OFFSETOF(RTDIRENTRY, szName) + RTPATH_MAX]; 779 } u; 780 size_t cbEntry = sizeof(u); 781 int rc2 = RTDirRead(hDir, &u.DirEntry, &cbEntry); 782 if (RT_SUCCESS(rc2)) 783 { 784 if ( ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 785 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 786 || ( u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN 787 && !RTDirEntryIsStdDotLink(&u.DirEntry)) ) 788 && rtCrStoreIsSuffixMatch(&u.DirEntry, paSuffixes, cSuffixes) ) 789 { 790 if (u.DirEntry.cbName < cbMaxFilename) 791 { 792 memcpy(&szPath[cchPath], u.DirEntry.szName, u.DirEntry.cbName); 793 szPath[cchPath + u.DirEntry.cbName] = '\0'; 794 if (u.DirEntry.enmType != RTDIRENTRYTYPE_FILE) 795 RTDirQueryUnknownType(szPath, true /*fFollowSymlinks*/, &u.DirEntry.enmType); 796 if (u.DirEntry.enmType == RTDIRENTRYTYPE_FILE) 797 { 798 rc2 = RTCrStoreCertAddWantedFromFile(hStore, fFlags, szPath, 799 paWanted, cWanted, pafFound, pErrInfo); 800 if (rc2 == VINF_SUCCESS) 801 { 802 Assert(rtCrStoreAllDone(pafFound, cWanted)); 803 if (RT_SUCCESS(rc)) 804 rc = VINF_SUCCESS; 805 break; 806 } 807 if (RT_FAILURE(rc2) && !(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 808 { 809 rc = rc2; 810 break; 811 } 812 } 813 } 814 else 815 { 816 /* 817 * pErrInfo keeps the status code unless it's fatal. 818 */ 819 RTErrInfoAddF(pErrInfo, VERR_FILENAME_TOO_LONG, 820 " Too long filename (%u bytes)", u.DirEntry.cbName); 821 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 822 { 823 rc = VERR_FILENAME_TOO_LONG; 824 break; 825 } 826 } 827 } 828 } 829 else 830 { 831 if (rc2 != VERR_NO_MORE_FILES) 832 { 833 RTErrInfoAddF(pErrInfo, rc2, "RTDirRead failed: %Rrc", rc2); 834 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 835 rc = rc2; 836 } 837 break; 838 } 839 } 840 RTDirClose(hDir); 841 } 842 } 843 else 844 rc = VERR_FILENAME_TOO_LONG; 845 } 846 return rc; 847 } 848 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromDir); 849
Note:
See TracChangeset
for help on using the changeset viewer.