aws-samples / amazon-kinesis-video-streams-producer-embedded-c

Light-wight Amazon Kinesis Video Streams Producer SDK For FreeRTOS/Embedded Linux
Apache License 2.0
30 stars 18 forks source link

Header generation for DescribeStream request produces bad request #52

Closed gtapizquent closed 2 years ago

gtapizquent commented 2 years ago

Describe the bug When calling Kvs_describeStream the request fails with a 403 error code

To Reproduce Steps to reproduce the behavior:

  1. Latest commit from master as of today
  2. Running on ameba pro device
  3. Run example app using IOT cert authentication
  4. Need to add printing of the http response even when the status code is not 200 (currently it is only copied over when the status code is 200 in Http_recvHttpRsp)

Expected behavior The server returns: {"message":"Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP: '20220128T191012Z' != '20220128', from '20220128T191012Z'."} with a 403 http code.

Environments (please complete the following information):

Additional context It is interesting that the issue only happens for this platform since I have the same code running on a different platform (Linux bases), and that one authenticates correctly.


Using these platform functions:

#define PAST_OLD_TIME_IN_EPOCH 1600000000

int platformInit(void)
{
    int xRes = KVS_ERRNO_NONE;

    srand(time(NULL));

    return xRes;
}

int getTimeInIso8601(char *pBuf, size_t uBufSize)
{
    int xRes = KVS_ERRNO_NONE;
    time_t xTimeUtcNow = {0};

    if (pBuf == NULL || uBufSize < DATE_TIME_ISO_8601_FORMAT_STRING_SIZE)
    {
        xRes = KVS_ERRNO_FAIL;
    }
    else
    {
        xTimeUtcNow = time(NULL);
        /* Current time should not less than a specific old time. If it does, then it means system time is incorrect. */
        if ((long)xTimeUtcNow < (long)PAST_OLD_TIME_IN_EPOCH)
        {
            xRes = KVS_ERRNO_FAIL;
        }
        else
        {
            strftime(pBuf, DATE_TIME_ISO_8601_FORMAT_STRING_SIZE, "%Y%m%dT%H%M%SZ", gmtime(&xTimeUtcNow));
        }
    }

    return xRes;
}

uint64_t getEpochTimestampInMs(void)
{
    uint64_t timestamp = 0;

    struct timeval tv;
    gettimeofday(&tv, NULL);
    timestamp = (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000;

    return timestamp;
}

uint8_t getRandomNumber(void)
{
    return (uint8_t)rand();
}

void sleepInMs(uint32_t ms)
{
    vTaskDelay( ms / portTICK_PERIOD_MS );
}
gtapizquent commented 2 years ago

BTW, I debugged/got around the issue with these changes.

diff --git a/src/source/net/http_helper.c b/src/source/net/http_helper.c
index 5d51ffb..a719156 100644
--- a/src/source/net/http_helper.c
+++ b/src/source/net/http_helper.c
@@ -235,6 +235,8 @@ int Http_recvHttpRsp(NetIoHandle xNetIoHandle, unsigned int *puHttpStatus, char
                         *ppRspBody = pRspBody;
                         *puRspBodyLen = uBodyLen;
                     }
+
+                    printf("%s\r\n", pBodyLoc);
                 }
             }
         } while (xRes != KVS_ERRNO_NONE);
@@ -243,4 +245,4 @@ int Http_recvHttpRsp(NetIoHandle xNetIoHandle, unsigned int *puHttpStatus, char
     BUFFER_delete(xBufRecv);

     return xRes;
-}
\ No newline at end of file
+}
diff --git a/src/source/restful/aws_signer_v4.c b/src/source/restful/aws_signer_v4.c
index d38a9c3..830e995 100644
--- a/src/source/restful/aws_signer_v4.c
+++ b/src/source/restful/aws_signer_v4.c
@@ -267,6 +267,14 @@ int AwsSigV4_Sign(AwsSigV4Handle xSigV4Handle, char *pcAccessKey, char *pcSecret
     char pHmac[AWS_SIG_V4_MAX_HMAC_SIZE] = {0};
     int i = 0;

+    char pcXAmzDateNoTime[9];
+
+    if (pcXAmzDate != NULL)
+    {
+        memset(pcXAmzDateNoTime, 0, sizeof(pcXAmzDateNoTime));
+        memcpy(pcXAmzDateNoTime, pcXAmzDate, sizeof(pcXAmzDateNoTime) - 1);
+    }
+
     if (pxAwsSigV4 == NULL || pcSecretKey == NULL || pcRegion == NULL || pcService == NULL || pcXAmzDate == NULL)
     {
         xRes = KVS_ERRNO_FAIL;
@@ -288,7 +296,7 @@ int AwsSigV4_Sign(AwsSigV4Handle xSigV4Handle, char *pcAccessKey, char *pcSecret
         xRes = KVS_ERRNO_FAIL;
     }
     /* Generate the scope string. */
-    else if (STRING_sprintf(pxAwsSigV4->xStScope, TEMPLATE_CANONICAL_SCOPE, SIGNATURE_DATE_STRING_LEN, pcXAmzDate, pcRegion, pcService, AWS_SIG_V4_SIGNATURE_END) != 0)
+    else if (STRING_sprintf(pxAwsSigV4->xStScope, TEMPLATE_CANONICAL_SCOPE, SIGNATURE_DATE_STRING_LEN, pcXAmzDateNoTime, pcRegion, pcService, AWS_SIG_V4_SIGNATURE_END) != 0)
     {
         xRes = KVS_ERRNO_FAIL;
     }
@@ -340,6 +348,8 @@ int AwsSigV4_Sign(AwsSigV4Handle xSigV4Handle, char *pcAccessKey, char *pcSecret
             {
                 xRes = KVS_ERRNO_FAIL;
             }
+
+            printf("\n\n\n\r%s\n\n\n\r", STRING_c_str(pxAwsSigV4->xStAuthorization));
         }
     }

@@ -360,4 +370,4 @@ const char *AwsSigV4_GetAuthorization(AwsSigV4Handle xSigV4Handle)
     {
         return NULL;
     }
-}
\ No newline at end of file
+}
weichihl commented 2 years ago

Thanks, I'll look into this and provide a fix.

weichihl commented 2 years ago

@gtapizquent As I know, Realtek already have a workable embedded producer and merged into their media framework. Did this happened at their port?

gtapizquent commented 2 years ago

@weichihl Not sure. I was just testing their example. They do compile the source for this repo directly without changes, so it could be an environment issue that causes STRING_sprintf to not work correctly in this case.

weichihl commented 2 years ago

@gtapizquent I think it's more possible that strftime or gmtime(&xTimeUtcNow) goes wrong. I don't have an AmebaPro EVB in hand, and Realtek folks are in the Chinese New Year holidays. Could you add logs around function getTimeInIso8601 if it's not too trouble? Thanks.

gtapizquent commented 2 years ago

@weichihl any particular log you want to see? This log came from the device: {"message":"Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP: '20220128T191012Z' != '20220128', from '20220128T191012Z'."}

Which is the printing of the server response (with the date that the device sent). That date seems correct to me.

gtapizquent commented 2 years ago

Also, per my diff, the date that makes it to function AwsSigV4_Sign is right, as the only change I made was to copy the first 8 chars into a different buffer.

weichihl commented 2 years ago

@gtapizquent Per talk with Realtek folks, could you check if the snprintf wrapper has been removed? remove_snprintf_wrapper

gtapizquent commented 2 years ago

@weichihl it has not been removed. Is their recommendation that it should be removed?

gtapizquent commented 2 years ago

@weichihl removing the snprintf and vsnprintf wrappers as shown here fixed the issue. Thanks!

weichihl commented 2 years ago

@gtapizquent There are wrappers that use the implementations of Ameba Pro instead of the standard library. It saves memories by using their wrappers. However, its behavior may differ from the standard library. I think that's why removing the wrapper fixed this issue.