static STRING_HANDLE construct_sas_token()

in src/sastoken.c [210:308]


static STRING_HANDLE construct_sas_token(const char* key, const char* scope, const char* keyname, uint64_t expiry)
{
    STRING_HANDLE result;

    char tokenExpirationTime[32] = { 0 };

    BUFFER_HANDLE decodedKey;

    /*Codes_SRS_SASTOKEN_06_029: [The key parameter is decoded from base64.]*/
    if ((decodedKey = Azure_Base64_Decode(key)) == NULL)
    {
        /*Codes_SRS_SASTOKEN_06_030: [If there is an error in the decoding then SASToken_Create shall return NULL.]*/
        LogError("Unable to decode the key for generating the SAS.");
        result = NULL;
    }
    else
    {
        /*Codes_SRS_SASTOKEN_06_026: [If the conversion to string form fails for any reason then SASToken_Create shall return NULL.]*/
        if (uint64_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0)
        {
            LogError("For some reason converting seconds to a string failed.  No SAS can be generated.");
            result = NULL;
        }
        else
        {
            STRING_HANDLE toBeHashed = NULL;
            BUFFER_HANDLE hash = NULL;
            if (((hash = BUFFER_new()) == NULL) ||
                ((toBeHashed = STRING_new()) == NULL) ||
                ((result = STRING_new()) == NULL))
            {
                LogError("Unable to allocate memory to prepare SAS token.");
                result = NULL;
            }
            else
            {
                /*Codes_SRS_SASTOKEN_06_009: [The scope is the basis for creating a STRING_HANDLE.]*/
                /*Codes_SRS_SASTOKEN_06_010: [A "\n" is appended to that string.]*/
                /*Codes_SRS_SASTOKEN_06_011: [tokenExpirationTime is appended to that string.]*/
                if ((STRING_concat(toBeHashed, scope) != 0) ||
                    (STRING_concat(toBeHashed, "\n") != 0) ||
                    (STRING_concat(toBeHashed, tokenExpirationTime) != 0))
                {
                    LogError("Unable to build the input to the HMAC to prepare SAS token.");
                    STRING_delete(result);
                    result = NULL;
                }
                else
                {
                    STRING_HANDLE base64Signature = NULL;
                    STRING_HANDLE urlEncodedSignature = NULL;
                    size_t inLen = STRING_length(toBeHashed);
                    const unsigned char* inBuf = (const unsigned char*)STRING_c_str(toBeHashed);
                    size_t outLen = BUFFER_length(decodedKey);
                    unsigned char* outBuf = BUFFER_u_char(decodedKey);
                    /*Codes_SRS_SASTOKEN_06_013: [If an error is returned from the HMAC256 function then NULL is returned from SASToken_Create.]*/
                    /*Codes_SRS_SASTOKEN_06_012: [An HMAC256 hash is calculated using the decodedKey, over toBeHashed.]*/
                    /*Codes_SRS_SASTOKEN_06_014: [If there are any errors from the following operations then NULL shall be returned.]*/
                    /*Codes_SRS_SASTOKEN_06_015: [The hash is base 64 encoded.]*/
                    /*Codes_SRS_SASTOKEN_06_028: [base64Signature shall be url encoded.]*/
                    /*Codes_SRS_SASTOKEN_06_016: [The string "SharedAccessSignature sr=" is the first part of the result of SASToken_Create.]*/
                    /*Codes_SRS_SASTOKEN_06_017: [The scope parameter is appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_018: [The string "&sig=" is appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_019: [The string urlEncodedSignature shall be appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_020: [The string "&se=" shall be appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_021: [tokenExpirationTime is appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_022: [If keyName is non-NULL, the string "&skn=" is appended to result.]*/
                    /*Codes_SRS_SASTOKEN_06_023: [If keyName is non-NULL, the argument keyName is appended to result.]*/
                    if ((HMACSHA256_ComputeHash(outBuf, outLen, inBuf, inLen, hash) != HMACSHA256_OK) ||
                        ((base64Signature = Azure_Base64_Encode(hash)) == NULL) ||
                        ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL) ||
                        (STRING_copy(result, "SharedAccessSignature sr=") != 0) ||
                        (STRING_concat(result, scope) != 0) ||
                        (STRING_concat(result, "&sig=") != 0) ||
                        (STRING_concat_with_STRING(result, urlEncodedSignature) != 0) ||
                        (STRING_concat(result, "&se=") != 0) ||
                        (STRING_concat(result, tokenExpirationTime) != 0) ||
                        ((keyname != NULL) && (STRING_concat(result, "&skn=") != 0)) ||
                        ((keyname != NULL) && (STRING_concat(result, keyname) != 0)))
                    {
                        LogError("Unable to build the SAS token.");
                        STRING_delete(result);
                        result = NULL;
                    }
                    else
                    {
                        /* everything OK */
                    }
                    STRING_delete(base64Signature);
                    STRING_delete(urlEncodedSignature);
                }
            }
            STRING_delete(toBeHashed);
            BUFFER_delete(hash);
        }
        BUFFER_delete(decodedKey);
    }
    return result;
}