VirtualBox

Ignore:
Timestamp:
Sep 4, 2018 12:04:01 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/http: Adding RTHttpSignHeaders, re-implemented header handling. bugref:9167

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/http-curl.cpp

    r74060 r74062  
    4242#include <iprt/asm.h>
    4343#include <iprt/assert.h>
     44#include <iprt/base64.h>
    4445#include <iprt/cidr.h>
    4546#include <iprt/crypto/store.h>
     
    5859#include <iprt/uni.h>
    5960#include <iprt/uri.h>
     61#include <iprt/crypto/digest.h>
     62#include <iprt/crypto/pkix.h>
     63#include <iprt/crypto/key.h>
     64
    6065
    6166#include "internal/magics.h"
     
    111116
    112117/**
     118 * HTTP header.
     119 */
     120typedef struct RTHTTPHEADER
     121{
     122    /** The core list structure. */
     123    struct curl_slist   Core;
     124    /** The field name length. */
     125    uint32_t            cchName;
     126    /** The value offset. */
     127    uint32_t            offValue;
     128    /** The full header field. */
     129    char                szData[RT_FLEXIBLE_ARRAY];
     130} RTHTTPHEADER;
     131/** Pointer to a HTTP header. */
     132typedef RTHTTPHEADER *PRTHTTPHEADER;
     133
     134/**
    113135 * Internal HTTP client instance.
    114136 */
     
    121143    /** The last response code. */
    122144    long                lLastResp;
    123     /** Custom headers/ */
     145    /** Custom headers (PRTHTTPHEADER).
     146     * The list head is registered with curl, though we do all the allocating. */
    124147    struct curl_slist  *pHeaders;
     148    /** Where to append the next header. */
     149    struct curl_slist **ppHeadersTail;
     150
    125151    /** CA certificate file for HTTPS authentication. */
    126152    char               *pszCaFile;
     
    291317static int rtHttpDarwinTryConfigProxies(PRTHTTPINTERNAL pThis, CFArrayRef hArrayProxies, CFURLRef hUrlTarget, bool fIgnorePacType);
    292318#endif
     319static void rtHttpFreeHeaders(PRTHTTPINTERNAL pThis);
    293320
    294321
     
    311338                pThis->u32Magic                 = RTHTTP_MAGIC;
    312339                pThis->pCurl                    = pCurl;
     340                pThis->ppHeadersTail            = &pThis->pHeaders;
     341                pThis->fHaveSetUserAgent        = false;
     342                pThis->fHaveUserAgentHeader     = false;
    313343                pThis->fUseSystemProxySettings  = true;
    314344                pThis->cMaxRedirects            = 0; /* no automatic redir following */
     
    316346                pThis->HeadersOutput.pHttp      = pThis;
    317347
     348
    318349                *phHttp = (RTHTTP)pThis;
    319350
     
    361392    pThis->pCurl = NULL;
    362393
    363     if (pThis->pHeaders)
    364     {
    365         curl_slist_free_all(pThis->pHeaders);
    366         pThis->pHeaders = NULL;
    367     }
     394    rtHttpFreeHeaders(pThis);
    368395
    369396    rtHttpUnsetCaFile(pThis);
     
    19321959 * if it is now in one of the headers.
    19331960 */
    1934 static void rtHttpUpdateUserAgentHeader(PRTHTTPINTERNAL pThis)
    1935 {
    1936     if (   pThis->fHaveUserAgentHeader
    1937         && pThis->fHaveSetUserAgent)
    1938     {
    1939         int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_USERAGENT, (char *)NULL);
    1940         Assert(CURL_SUCCESS(rcCurl)); NOREF(rcCurl);
    1941         pThis->fHaveSetUserAgent = false;
    1942     }
     1961static int rtHttpUpdateUserAgentHeader(PRTHTTPINTERNAL pThis, PRTHTTPHEADER pNewHdr)
     1962{
     1963    static const char s_szUserAgent[] = "User-Agent";
     1964    if (   pNewHdr->cchName == sizeof(s_szUserAgent) - 1
     1965        && RTStrNICmpAscii(pNewHdr->szData, RT_STR_TUPLE(s_szUserAgent)) == 0)
     1966    {
     1967        pThis->fHaveUserAgentHeader = true;
     1968        if (pThis->fHaveSetUserAgent)
     1969        {
     1970            int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_USERAGENT, (char *)NULL);
     1971            Assert(CURL_SUCCESS(rcCurl)); NOREF(rcCurl);
     1972            pThis->fHaveSetUserAgent = false;
     1973        }
     1974    }
     1975    return VINF_SUCCESS;
     1976}
     1977
     1978
     1979/**
     1980 * Free the headers associated with the insance (w/o telling cURL about it).
     1981 *
     1982 * @param   pThis       The HTTP client instance.
     1983 */
     1984static void rtHttpFreeHeaders(PRTHTTPINTERNAL pThis)
     1985{
     1986    struct curl_slist *pHead = pThis->pHeaders;
     1987    pThis->pHeaders = NULL;
     1988    pThis->ppHeadersTail = &pThis->pHeaders;
     1989    pThis->fHaveUserAgentHeader = false;
     1990
     1991    while (pHead)
     1992    {
     1993        struct curl_slist *pFree = pHead;
     1994        pHead = pHead->next;
     1995        ASMCompilerBarrier(); /* paranoia */
     1996
     1997        pFree->next = NULL;
     1998        pFree->data = NULL;
     1999        RTMemFree(pFree);
     2000    }
     2001}
     2002
     2003
     2004/**
     2005 * Worker for RTHttpSetHeaders and RTHttpAddHeader.
     2006 *
     2007 * @returns IPRT status code.
     2008 * @param   pThis       The HTTP client instance.
     2009 * @param   pchName     The field name.  Does not need to be terminated.
     2010 * @param   cchName     The field name length.
     2011 * @param   pchValue    The field value.  Does not need to be terminated.
     2012 * @param   cchValue    The field value length.
     2013 * @param   fFlags      RTHTTPADDHDR_F_XXX.
     2014 */
     2015static int rtHttpAddHeaderWorker(PRTHTTPINTERNAL pThis, const char *pchName, size_t cchName,
     2016                                 const char *pchValue, size_t cchValue, uint32_t fFlags)
     2017{
     2018    /*
     2019     * Create the list entry.
     2020     */
     2021    size_t        cbData = cchName + 2 + cchValue + 1;
     2022    PRTHTTPHEADER pHdr   = (PRTHTTPHEADER)RTMemAlloc(RT_UOFFSETOF_DYN(RTHTTPHEADER, szData[cbData]));
     2023    if (pHdr)
     2024    {
     2025        pHdr->Core.next = NULL;
     2026        pHdr->Core.data = pHdr->szData;
     2027        pHdr->cchName   = (uint32_t)cchName;
     2028        pHdr->offValue  = (uint32_t)(cchName + 2);
     2029        char *psz = pHdr->szData;
     2030        memcpy(psz, pchName, cchName);
     2031        psz += cchName;
     2032        *psz++ = ':';
     2033        *psz++ = ' ';
     2034        memcpy(psz, pchValue, cchValue);
     2035        psz[cchValue] = '\0';
     2036
     2037        /*
     2038         * Append or prepend the header.
     2039         */
     2040        AssertCompile(RTHTTPADDHDR_F_FRONT != 0);
     2041        if (!(fFlags & RTHTTPADDHDR_F_FRONT))
     2042        {
     2043            *pThis->ppHeadersTail = &pHdr->Core;
     2044            pThis->ppHeadersTail  = &pHdr->Core.next;
     2045            if (pThis->pHeaders != NULL)
     2046                return rtHttpUpdateUserAgentHeader(pThis, pHdr);
     2047
     2048            /* Need to update curl about the new list head. */
     2049        }
     2050        else
     2051        {
     2052            pHdr->Core.next = pThis->pHeaders;
     2053            if (!pThis->pHeaders)
     2054                pThis->ppHeadersTail  = &pHdr->Core.next;
     2055        }
     2056        pThis->pHeaders = &pHdr->Core;
     2057
     2058        int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, pThis->pHeaders);
     2059        if (CURL_SUCCESS(rcCurl))
     2060            return rtHttpUpdateUserAgentHeader(pThis, pHdr);
     2061        return VERR_HTTP_CURL_ERROR;
     2062    }
     2063    return VERR_NO_MEMORY;
    19432064}
    19442065
     
    19542075    if (pThis->pHeaders)
    19552076    {
    1956         curl_slist_free_all(pThis->pHeaders);
    1957         pThis->pHeaders = NULL;
    1958         curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, pThis->pHeaders);
    1959     }
     2077        rtHttpFreeHeaders(pThis);
     2078        curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, (struct curl_slist *)NULL);
     2079    }
     2080    pThis->ppHeadersTail = &pThis->pHeaders;
    19602081    pThis->fHaveUserAgentHeader = false;
    19612082
     
    19672088
    19682089    /*
    1969      * Convert the headers into a curl string list, checking each string for User-Agent.
    1970      */
    1971     struct curl_slist *pHeaders = NULL;
     2090     * Add the headers, one by one.
     2091     */
     2092    int rc = VINF_SUCCESS;
    19722093    for (size_t i = 0; i < cHeaders; i++)
    19732094    {
    1974         struct curl_slist *pNewHeaders = curl_slist_append(pHeaders, papszHeaders[i]);
    1975         if (pNewHeaders)
    1976             pHeaders = pNewHeaders;
    1977         else
    1978         {
    1979             if (pHeaders)
    1980                 curl_slist_free_all(pHeaders);
    1981             return VERR_NO_MEMORY;
    1982         }
    1983 
    1984         if (strncmp(papszHeaders[i], RT_STR_TUPLE("User-Agent:")) == 0)
    1985             pThis->fHaveUserAgentHeader = true;
    1986     }
    1987 
    1988     int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, pHeaders);
    1989     if (CURL_FAILURE(rcCurl))
    1990     {
    1991         curl_slist_free_all(pHeaders);
    1992         return VERR_INVALID_PARAMETER;
    1993     }
    1994     pThis->pHeaders = pHeaders;
    1995 
    1996     rtHttpUpdateUserAgentHeader(pThis);
    1997 
    1998     return VINF_SUCCESS;
    1999 }
    2000 
    2001 
     2095        const char *pszHeader = papszHeaders[i];
     2096        size_t      cchHeader = strlen(pszHeader);
     2097        size_t      cchName   = (const char *)memchr(pszHeader, ':', cchHeader) - pszHeader;
     2098        AssertBreakStmt(cchName < cchHeader, rc = VERR_INVALID_PARAMETER);
     2099        size_t      offValue  = RT_C_IS_BLANK(pszHeader[cchName + 1]) ? cchName + 2 : cchName + 1;
     2100        rc = rtHttpAddHeaderWorker(pThis, pszHeader, cchName, &pszHeader[offValue], cchHeader - offValue, RTHTTPADDHDR_F_BACK);
     2101        AssertRCBreak(rc);
     2102    }
     2103    if (RT_SUCCESS(rc))
     2104        return rc;
     2105    rtHttpFreeHeaders(pThis);
     2106    curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, (struct curl_slist *)NULL);
     2107    return rc;
     2108}
     2109
     2110
     2111#if 0 /** @todo reimplement RTHttpAddRawHeader if ever actually needed. */
    20022112RTR3DECL(int) RTHttpAddRawHeader(RTHTTP hHttp, const char *pszHeader, uint32_t fFlags)
    20032113{
     
    20402150    return VINF_SUCCESS;
    20412151}
     2152#endif
    20422153
    20432154
    20442155RTR3DECL(int) RTHttpAddHeader(RTHTTP hHttp, const char *pszField, const char *pszValue, uint32_t fFlags)
    20452156{
    2046 
    2047     /*
    2048      * Currently we don't any encoding here, so we just glue the two strings together.
    2049      */
     2157    /*
     2158     * Validate input and calc string lengths.
     2159     */
     2160    PRTHTTPINTERNAL pThis = hHttp;
     2161    RTHTTP_VALID_RETURN(pThis);
     2162    AssertReturn(!(fFlags & ~RTHTTPADDHDR_F_BACK), VERR_INVALID_FLAGS);
    20502163    AssertPtr(pszField);
    20512164    size_t const cchField = strlen(pszField);
     
    20642177    size_t const cchValue = strlen(pszValue);
    20652178
    2066     AssertReturn(!(fFlags & ~RTHTTPADDHDR_F_BACK), VERR_INVALID_FLAGS);
    2067 
    2068     /*
    2069      * Allocate a temporary buffer, construct the raw header string in it,
    2070      * then use RTHttpAppendRawHeader to do the grunt work.
    2071      */
    2072     size_t const cbNeeded = cchField + 2 + cchValue + 1;
    2073     char *pszHeaderFree = NULL;
    2074     char *pszHeader;
    2075     if (cbNeeded < _2K)
    2076         pszHeader = (char *)alloca(cbNeeded);
    2077     else
    2078         pszHeaderFree = pszHeader = (char *)RTMemTmpAlloc(cbNeeded);
    2079     if (!pszHeader)
    2080         return VERR_NO_TMP_MEMORY;
    2081 
    2082     memcpy(pszHeader, pszField, cchField);
    2083     pszHeader[cchField]     = ':';
    2084     pszHeader[cchField + 1] = ' ';
    2085     memcpy(&pszHeader[cchField + 2], pszValue, cchValue);
    2086     pszHeader[cbNeeded - 1] = '\0';
    2087 
    2088     int rc = RTHttpAddRawHeader(hHttp, pszHeader, fFlags & RTHTTPADDHDR_F_FRONT);
    2089 
    2090     if (pszHeaderFree)
    2091         RTMemTmpFree(pszHeaderFree);
    2092     return rc;
     2179    /*
     2180     * Just pass it along to the worker.
     2181     */
     2182    return rtHttpAddHeaderWorker(pThis, pszField, cchField, pszValue, cchValue, fFlags);
    20932183}
    20942184
     
    20992189    RTHTTP_VALID_RETURN_RC(pThis, NULL);
    21002190
    2101     struct curl_slist *pCur = pThis->pHeaders;
     2191    PRTHTTPHEADER pCur = (PRTHTTPHEADER)pThis->pHeaders;
    21022192    if (pCur)
    21032193    {
     
    21062196        do
    21072197        {
    2108             /* strchr() is probably way faster than RTStrNICmpAscii(), so
    2109                match the field name length first. */
    2110             const char *pszColon = strchr(pCur->data, ':');
    2111             if (   (size_t)(pszColon - pCur->data) == cchField
    2112                 && pszColon != NULL
    2113                 && RTStrNICmpAscii(pCur->data, pszField, cchField) == 0)
     2198            if (   pCur->cchName == cchField
     2199                && RTStrNICmpAscii(pCur->szData, pszField, cchField) == 0)
     2200                return &pCur->szData[pCur->offValue];
     2201
     2202            /* next field. */
     2203            pCur = (PRTHTTPHEADER)pCur->Core.next;
     2204        } while (pCur);
     2205    }
     2206    return NULL;
     2207}
     2208
     2209
     2210RTR3DECL(int) RTHttpSignHeaders(RTHTTP hHttp, RTHTTPMETHOD enmMethod, const char *pszUrl, uint32_t fFlags,
     2211                                RTCRKEY hKey, const char *pszKeyId)
     2212{
     2213    PRTHTTPINTERNAL pThis = hHttp;
     2214    RTHTTP_VALID_RETURN_RC(pThis, NULL);
     2215    AssertReturn(enmMethod > RTHTTPMETHOD_INVALID && enmMethod < RTHTTPMETHOD_END, VERR_INVALID_PARAMETER);
     2216    AssertPtrReturn(pszUrl, VERR_INVALID_POINTER);
     2217    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     2218    AssertPtrReturn(pszKeyId, VERR_INVALID_POINTER);
     2219
     2220    /*
     2221     * Do a little bit of preprocessing while we can easily return without
     2222     * needing clean anything up..
     2223     */
     2224    RTURIPARSED ParsedUrl;
     2225    int rc = RTUriParse(pszUrl, &ParsedUrl);
     2226    AssertRCReturn(rc, rc);
     2227    const char * const pszPath = pszUrl + ParsedUrl.offPath;
     2228
     2229    const char *pszMethodSp = NULL;
     2230    switch (enmMethod)
     2231    {
     2232        case RTHTTPMETHOD_GET:      pszMethodSp = "get "; break;
     2233        case RTHTTPMETHOD_PUT:      pszMethodSp = "put "; break;
     2234        case RTHTTPMETHOD_POST:     pszMethodSp = "post "; break;
     2235        case RTHTTPMETHOD_PATCH:    pszMethodSp = "patch "; break;
     2236        case RTHTTPMETHOD_DELETE:   pszMethodSp = "delete "; break;
     2237        case RTHTTPMETHOD_HEAD:     pszMethodSp = "head "; break;
     2238        case RTHTTPMETHOD_OPTIONS:  pszMethodSp = "options "; break;
     2239        case RTHTTPMETHOD_TRACE:    pszMethodSp = "trace "; break;
     2240        /* no default! */
     2241        case RTHTTPMETHOD_INVALID:
     2242        case RTHTTPMETHOD_END:
     2243        case RTHTTPMETHOD_32BIT_HACK:
     2244            break;
     2245    }
     2246    AssertReturn(pszMethodSp, VERR_INTERNAL_ERROR_4);
     2247
     2248    /*
     2249     * We work the authorization header entry directly here to avoid extra copying and stuff.
     2250     */
     2251
     2252    /* Estimate required string length first. */
     2253    static const char s_szSuffixFmt[]    = "Authorization: Signature version=\"1\",keyId=\"%s\",algorithm=\"rsa-sha256\",headers=\"";
     2254    static const char s_szInfix[]        = "\",signature=\"Base64(RSA-SHA256(";
     2255    static const char s_szPostfix[]      = "))\"";
     2256    static const char s_szRequestField[] = "(request-target)";
     2257    size_t const      cchKeyId           = strlen(pszKeyId);
     2258    size_t const      cbSigRaw           = (RTCrKeyGetBitCount(hKey) + 8) / 8; /** @todo ?? */
     2259    size_t const      cbSigRawAligned    = RT_ALIGN_Z(cbSigRaw, 8);
     2260    size_t const      cchSigStr          = RTBase64EncodedLengthEx(cbSigRaw, RTBASE64_FLAGS_NO_LINE_BREAKS);
     2261    size_t cbEstimated = sizeof(s_szSuffixFmt) + sizeof(s_szInfix) + sizeof(s_szPostfix)
     2262                       + cchKeyId + sizeof(s_szRequestField) + cchSigStr;
     2263    for (PRTHTTPHEADER pCur = (PRTHTTPHEADER)pThis->pHeaders; pCur; pCur = (PRTHTTPHEADER)pCur->Core.next)
     2264        cbEstimated += pCur->cchName + 1;
     2265    cbEstimated += 32; /* safetype fudge */
     2266    /* Lazy bird: Put the raw signature at the end. */
     2267    cbEstimated = RT_ALIGN_Z(cbEstimated, 8) + cbSigRawAligned;
     2268
     2269    /* Allocate and initialize header entry. */
     2270    PRTHTTPHEADER const pHdr = (PRTHTTPHEADER)RTMemAllocZ(cbEstimated);
     2271    AssertPtrReturn(pHdr, VERR_NO_MEMORY);
     2272    uint8_t * const pbSigRaw = (uint8_t *)pHdr + cbEstimated - cbSigRawAligned;
     2273
     2274    pHdr->cchName  = sizeof("Authorization") - 1;
     2275    pHdr->offValue = sizeof("Authorization") + 1;
     2276    char  *pszLeft = pHdr->szData;
     2277    size_t cbLeft  = cbEstimated - RT_UOFFSETOF(RTHTTPHEADER, szData) - cbSigRawAligned;
     2278
     2279    size_t cch = RTStrPrintf(pszLeft, cbLeft, s_szSuffixFmt, pszKeyId);
     2280    cbLeft -= cch;
     2281    pszLeft += cch;
     2282
     2283    /*
     2284     * Instantiate the digest.
     2285     */
     2286    RTCRDIGEST hDigest = NIL_RTCRDIGEST;
     2287    rc = RTCrDigestCreateByType(&hDigest, RTDIGESTTYPE_SHA256);
     2288    if (RT_SUCCESS(rc))
     2289    {
     2290        /*
     2291         * Add the request-target pseudo header first.
     2292         */
     2293        Assert(cbLeft > sizeof(s_szRequestField));
     2294        memcpy(pszLeft, RT_STR_TUPLE(s_szRequestField));
     2295        pszLeft += sizeof(s_szRequestField);
     2296
     2297        rc = RTCrDigestUpdate(hDigest, RT_STR_TUPLE(s_szRequestField));
     2298        if (RT_SUCCESS(rc))
     2299            rc = RTCrDigestUpdate(hDigest, RT_STR_TUPLE(": "));
     2300        if (RT_SUCCESS(rc))
     2301            rc = RTCrDigestUpdate(hDigest, pszMethodSp, strlen(pszMethodSp));
     2302        if (RT_SUCCESS(rc))
     2303            rc = RTCrDigestUpdate(hDigest, pszPath, strlen(pszPath));
     2304
     2305        /*
     2306         * Add the header fields.
     2307         */
     2308        for (PRTHTTPHEADER pCur = (PRTHTTPHEADER)pThis->pHeaders; pCur && RT_SUCCESS(rc); pCur = (PRTHTTPHEADER)pCur->Core.next)
     2309        {
     2310            AssertBreakStmt(cbLeft > pCur->cchName, rc = VERR_INTERNAL_ERROR_3);
     2311            memcpy(pszLeft, pCur->szData, pCur->cchName);
     2312            pszLeft[pCur->cchName] = '\0';
     2313            RTStrToLower(pszLeft);
     2314
     2315            rc = RTCrDigestUpdate(hDigest, RT_STR_TUPLE("\n"));
     2316            AssertRCBreak(rc);
     2317            rc = RTCrDigestUpdate(hDigest, pszLeft, pCur->cchName);
     2318            AssertRCBreak(rc);
     2319            rc = RTCrDigestUpdate(hDigest, RT_STR_TUPLE(": "));
     2320            AssertRCBreak(rc);
     2321            const char *pszValue = &pCur->szData[pCur->offValue];
     2322            rc = RTCrDigestUpdate(hDigest, pszValue, strlen(pszValue));
     2323            AssertRCBreak(rc);
     2324
     2325            pszLeft += pCur->cchName;
     2326            cbLeft -= pCur->cchName;
     2327        }
     2328        if (RT_SUCCESS(rc))
     2329            AssertStmt(cbLeft > sizeof(s_szInfix) + cchSigStr + sizeof(s_szPostfix), rc = VERR_INTERNAL_ERROR_3);
     2330        if (RT_SUCCESS(rc))
     2331        {
     2332            /* Complete the header field part. */
     2333            memcpy(pszLeft, RT_STR_TUPLE(s_szInfix));
     2334            pszLeft += sizeof(s_szInfix) - 1;
     2335            cbLeft  -= sizeof(s_szInfix) - 1;
     2336
     2337            /*
     2338             * Sign the digest.
     2339             */
     2340            RTCRPKIXSIGNATURE hSigner;
     2341            rc = RTCrPkixSignatureCreateByObjIdString(&hSigner, RTCR_PKCS1_SHA256_WITH_RSA_OID, hKey, NULL, true /*fSigning*/);
     2342            AssertRC(rc);
     2343            if (RT_SUCCESS(rc))
    21142344            {
    2115                 pszColon++;
    2116                 if (RT_C_IS_BLANK(*pszColon))
    2117                     pszColon++;
    2118                 return pszColon;
     2345                size_t cbActual = cbSigRawAligned;
     2346                rc = RTCrPkixSignatureSign(hSigner, hDigest, pbSigRaw, &cbActual);
     2347                AssertRC(rc);
     2348                if (RT_SUCCESS(rc))
     2349                {
     2350                    RTCrPkixSignatureRelease(hSigner);
     2351                    hSigner = NIL_RTCRPKIXSIGNATURE;
     2352                    RTCrDigestRelease(hDigest);
     2353                    hDigest = NIL_RTCRDIGEST;
     2354
     2355                    /*
     2356                     * Convert the signature to Base64 and append it to the string.
     2357                     */
     2358                    size_t cchActual;
     2359                    rc = RTBase64EncodeEx(pbSigRaw, cbActual, RTBASE64_FLAGS_NO_LINE_BREAKS, pszLeft, cbLeft, &cchActual);
     2360                    AssertRC(rc);
     2361                    if (RT_SUCCESS(rc))
     2362                    {
     2363                        Assert(cchActual == cchSigStr);
     2364                        pszLeft += cchActual;
     2365                        cbLeft  -= cchActual;
     2366
     2367                        /*
     2368                         * Append the postfix and add the header to the front of the list.
     2369                         */
     2370                        AssertStmt(cbLeft >= sizeof(s_szPostfix), rc = VERR_INTERNAL_ERROR_3);
     2371                        if (RT_SUCCESS(rc))
     2372                        {
     2373                            memcpy(pszLeft, s_szPostfix, sizeof(s_szPostfix));
     2374
     2375                            pHdr->Core.next = pThis->pHeaders;
     2376                            if (!pThis->pHeaders)
     2377                                pThis->ppHeadersTail  = &pHdr->Core.next;
     2378                            pThis->pHeaders = &pHdr->Core;
     2379
     2380                            int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, pThis->pHeaders);
     2381                            if (CURL_SUCCESS(rcCurl))
     2382                                return VINF_SUCCESS;
     2383                            rc = VERR_HTTP_CURL_ERROR;
     2384                        }
     2385                    }
     2386                }
     2387                RTCrPkixSignatureRelease(hSigner);
    21192388            }
    2120 
    2121             /* next field. */
    2122             pCur = pCur->next;
    2123         } while (pCur);
    2124     }
    2125     return NULL;
    2126 }
    2127 
     2389        }
     2390        RTCrDigestRelease(hDigest);
     2391    }
     2392    RTMemFree(pHdr);
     2393    return rc;
     2394}
    21282395
    21292396
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