in src/source/Common/AwsV4Signer.c [414:522]
STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestStr, PUINT32 pRequestLen)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
PCHAR pCurPtr, pVerbString, pUriStart, pUriEnd, pQueryStart, pQueryEnd;
UINT32 requestLen = 0, curLen, urlLen, len, itemCount;
BOOL defaultPath;
CHK(pRequestInfo != NULL && pRequestLen != NULL, STATUS_NULL_ARG);
CHK_STATUS(singleListGetNodeCount(pRequestInfo->pRequestHeaders, &itemCount));
// Calculate the rough max size first including the new lines and hex of the 256 bit hash (2 * 32)
// CanonicalRequest =
// HTTPRequestMethod + '\n' +
// CanonicalURI + '\n' +
// CanonicalQueryString + '\n' +
// CanonicalHeaders + '\n' +
// SignedHeaders + '\n' +
// HexEncode(Hash(RequestPayload))
requestLen = MAX_REQUEST_VERB_STRING_LEN + 1 + MAX_URI_CHAR_LEN + 1 + MAX_URI_CHAR_LEN + 1 +
itemCount * (MAX_REQUEST_HEADER_NAME_LEN + 1 + MAX_REQUEST_HEADER_VALUE_LEN + 1) + itemCount * (MAX_REQUEST_HEADER_NAME_LEN + 1) +
SHA256_DIGEST_LENGTH * 2 + 1;
// See if we only are interested in the size
CHK(pRequestStr != NULL, retStatus);
pCurPtr = pRequestStr;
requestLen = *pRequestLen;
curLen = 0;
// Get the request verb string
pVerbString = getRequestVerbString(pRequestInfo->verb);
CHK(pVerbString != NULL, STATUS_INVALID_ARG);
len = (UINT32) STRLEN(pVerbString);
CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL);
MEMCPY(pCurPtr, pVerbString, SIZEOF(CHAR) * len);
pCurPtr += len;
*pCurPtr++ = '\n';
curLen += len + 1;
// Store the length of the URL
urlLen = (UINT32) STRLEN(pRequestInfo->url);
// Get the canonical URI
CHK_STATUS(getCanonicalUri(pRequestInfo->url, urlLen, &pUriStart, &pUriEnd, &defaultPath));
len = defaultPath ? 1 : (UINT32)(pUriEnd - pUriStart);
CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL);
MEMCPY(pCurPtr, pUriStart, len * SIZEOF(CHAR));
pCurPtr += len;
*pCurPtr++ = '\n';
curLen += len + 1;
// Get the canonical query.
// We assume the params have been URI encoded and the in an ascending order
pQueryEnd = pRequestInfo->url + urlLen;
// The start of the query params is either end of the URI or ? so we skip one in that case
pQueryStart = (pUriEnd == pQueryEnd) ? pUriEnd : pUriEnd + 1;
len = (UINT32)(pQueryEnd - pQueryStart);
CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL);
MEMCPY(pCurPtr, pQueryStart, len * SIZEOF(CHAR));
pCurPtr += len;
*pCurPtr++ = '\n';
curLen += len + 1;
len = requestLen - curLen;
CHK_STATUS(generateCanonicalHeaders(pRequestInfo, pCurPtr, &len));
CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL);
pCurPtr += len;
*pCurPtr++ = '\n';
curLen += len + 1;
len = requestLen - curLen;
CHK_STATUS(generateSignedHeaders(pRequestInfo, pCurPtr, &len));
CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL);
pCurPtr += len;
*pCurPtr++ = '\n';
curLen += len + 1;
// Generate the hex encoded hash
len = SHA256_DIGEST_LENGTH * 2;
CHK(curLen + len <= requestLen, STATUS_BUFFER_TOO_SMALL);
if (pRequestInfo->body == NULL) {
// Streaming treats this portion as if the body were empty
CHK_STATUS(hexEncodedSha256((PBYTE) EMPTY_STRING, 0, pCurPtr));
} else {
// standard signing
CHK_STATUS(hexEncodedSha256((PBYTE) pRequestInfo->body, pRequestInfo->bodySize, pCurPtr));
}
pCurPtr += len;
curLen += len;
CHK(curLen <= requestLen, STATUS_BUFFER_TOO_SMALL);
requestLen = curLen;
CleanUp:
if (pRequestLen != NULL) {
*pRequestLen = requestLen;
}
LEAVES();
return retStatus;
}