static SigV4Status_t parseHeaderKeyValueEntries()

in source/sigv4.c [1610:1703]


    static SigV4Status_t parseHeaderKeyValueEntries( const char * pHeaders,
                                                     size_t headersDataLen,
                                                     uint32_t flags,
                                                     size_t * headerCount,
                                                     CanonicalContext_t * pCanonicalRequest )
    {
        size_t index = 0, noOfHeaders;
        const char * pKeyOrValStartLoc;
        const char * pCurrLoc;
        bool keyFlag = true;
        SigV4Status_t sigV4Status = SigV4Success;
        ptrdiff_t dataLen = 0;

        assert( pHeaders != NULL );
        assert( headersDataLen > 0 );
        assert( pCanonicalRequest != NULL );
        assert( headerCount != NULL );

        noOfHeaders = *headerCount;
        pKeyOrValStartLoc = pHeaders;
        pCurrLoc = pHeaders;

        for( index = 0; index < headersDataLen; index++ )
        {
            if( noOfHeaders == SIGV4_MAX_HTTP_HEADER_COUNT )
            {
                sigV4Status = SigV4MaxHeaderPairCountExceeded;
                break;
            }
            /* Look for key part of an header field entry. */
            else if( ( keyFlag ) && ( pHeaders[ index ] == ':' ) )
            {
                dataLen = pCurrLoc - pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].key.pData = pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].key.dataLen = ( size_t ) dataLen;
                pKeyOrValStartLoc = &( pCurrLoc[ 1 ] );
                keyFlag = false;
            }
            /* Look for header value part of a header field entry for both canonicalized and non-canonicalized forms. */
            /* Non-canonicalized headers will have header values ending with "\r\n". */
            else if( ( !keyFlag ) && !FLAG_IS_SET( flags, SIGV4_HTTP_HEADERS_ARE_CANONICAL_FLAG ) && ( ( index + 1U ) < headersDataLen ) &&
                     ( 0 == strncmp( pCurrLoc, HTTP_REQUEST_LINE_ENDING, HTTP_REQUEST_LINE_ENDING_LEN ) ) )
            {
                dataLen = pCurrLoc - pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].value.pData = pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].value.dataLen = ( size_t ) dataLen;

                /* Storing location of hashed request payload */
                storeHashedPayloadLocation( noOfHeaders, SIGV4_HTTP_X_AMZ_CONTENT_SHA256_HEADER, SIGV4_HTTP_X_AMZ_CONTENT_SHA256_HEADER_LENGTH, pCanonicalRequest );

                /* Set starting location of the next header key string after the "\r\n". */
                pKeyOrValStartLoc = &( pCurrLoc[ 2 ] );
                keyFlag = true;
                noOfHeaders++;
            }
            /* Canonicalized headers will have header values ending just with "\n". */
            else if( ( !keyFlag ) && FLAG_IS_SET( flags, SIGV4_HTTP_HEADERS_ARE_CANONICAL_FLAG ) && ( pHeaders[ index ] == '\n' ) )
            {
                dataLen = pCurrLoc - pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].value.pData = pKeyOrValStartLoc;
                pCanonicalRequest->pHeadersLoc[ noOfHeaders ].value.dataLen = ( size_t ) dataLen;

                /* Storing location of hashed request payload */
                storeHashedPayloadLocation( noOfHeaders, SIGV4_HTTP_X_AMZ_CONTENT_SHA256_HEADER, SIGV4_HTTP_X_AMZ_CONTENT_SHA256_HEADER_LENGTH, pCanonicalRequest );

                /* Set starting location of the next header key string after the "\n". */
                pKeyOrValStartLoc = &( pCurrLoc[ 1 ] );
                keyFlag = true;
                noOfHeaders++;
            }
            else
            {
                /* Empty else. */
            }

            pCurrLoc++;
        }

        /* Ensure each key has its corresponding value. */
        assert( keyFlag == true );

        /* If no header was found OR header value was not found for a header key,
         *  that represents incorrect HTTP headers data passed by the application. */
        if( ( noOfHeaders == 0U ) || ( keyFlag == false ) )
        {
            sigV4Status = SigV4InvalidHttpHeaders;
        }
        else
        {
            *headerCount = noOfHeaders;
        }

        return sigV4Status;
    }