VirtualBox

Ignore:
Timestamp:
Sep 4, 2015 2:19:44 AM (9 years ago)
Author:
vboxsync
Message:

IPRT,UINetworkReply.cpp: Added RTPathGlob, a set of RTCrStoreCertAddWantedDir/File/Store, a RTCrStoreCertAddWantedFromFishingExpedition, RTCrStoreCertCheckWanted, RTCrStoreCertCount, RTFsIsCaseSensitive and RTFileOpenTemp. Reworked some RTHttp bits and UINetworkReply stuff - this needs testing.

File:
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/crypto/store-cert-add-basic.cpp

    r57607 r57613  
    3333
    3434#include <iprt/assert.h>
     35#include <iprt/crypto/pem.h>
    3536#include <iprt/dir.h>
    3637#include <iprt/err.h>
     38#include <iprt/file.h>
     39#include <iprt/mem.h>
    3740#include <iprt/path.h>
     41#include <iprt/sha.h>
    3842#include <iprt/string.h>
     43
     44#include "x509-internal.h"
     45
     46
     47/*********************************************************************************************************************************
     48*   Global Variables                                                                                                             *
     49*********************************************************************************************************************************/
     50/** BEGIN CERTIFICATE / END CERTIFICATE. */
     51static RTCRPEMMARKERWORD const g_aWords_Certificate[] =
     52{
     53    { RT_STR_TUPLE("CERTIFICATE") }
     54};
     55
     56/** BEGIN TRUSTED CERTIFICATE / END TRUSTED CERTIFICATE. */
     57static 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) */
     64static 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 */
     75RTCRPEMMARKER 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 */
     91DECLINLINE(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 */
     111DECLINLINE(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 */
     151DECLINLINE(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 */
     181static 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
     198RTDECL(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}
     230RT_EXPORT_SYMBOL(RTCrStoreCertAddFromStore);
     231
     232
     233RTDECL(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}
     329RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore);
     330
     331
     332RTDECL(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}
     391RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore);
     392
     393
     394RTDECL(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}
     448RT_EXPORT_SYMBOL(RTCrStoreCertAddFromFile);
     449
     450
     451RTDECL(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}
     602RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromFile);
    39603
    40604
     
    88652        if (cchPath > 0)
    89653        {
    90             size_t const cbFilename = sizeof(szPath) - cchPath;
     654            size_t const cbMaxFilename = sizeof(szPath) - cchPath;
    91655
    92656            /*
     
    109673                    if (RT_SUCCESS(rc2))
    110674                    {
    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)) )
    112679                            && rtCrStoreIsSuffixMatch(&u.DirEntry, paSuffixes, cSuffixes) )
    113680                        {
    114                             if (u.DirEntry.cbName < cbFilename)
     681                            if (u.DirEntry.cbName < cbMaxFilename)
    115682                            {
    116683                                memcpy(&szPath[cchPath], u.DirEntry.szName, u.DirEntry.cbName + 1);
     
    131698                                }
    132699                            }
    133                             else if (   u.DirEntry.enmType == RTDIRENTRYTYPE_FILE
    134                                      || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK
    135                                      || u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN)
     700                            else
    136701                            {
    137702                                rc = RTErrInfoAddF(pErrInfo, VERR_FILENAME_TOO_LONG,
     
    160725    return rc;
    161726}
    162 
    163 
     727RT_EXPORT_SYMBOL(RTCrStoreCertAddFromDir);
     728
     729
     730RTDECL(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}
     848RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromDir);
     849
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette