Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
sastoken.c@26:b38c66e3e45e, 2017-05-08 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Mon May 08 10:51:21 2017 -0700
- Revision:
- 26:b38c66e3e45e
- Parent:
- 25:8507bf644fdf
1.1.14
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Azure.IoT Build | 0:fa2de1b79154 | 1 | // Copyright (c) Microsoft. All rights reserved. |
| Azure.IoT Build | 0:fa2de1b79154 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| Azure.IoT Build | 0:fa2de1b79154 | 3 | |
| AzureIoTClient | 19:2e0811512ceb | 4 | #include <stdlib.h> |
| AzureIoTClient | 26:b38c66e3e45e | 5 | #include <stdio.h> |
| AzureIoTClient | 26:b38c66e3e45e | 6 | #include <string.h> |
| Azure.IoT Build | 0:fa2de1b79154 | 7 | #include "azure_c_shared_utility/gballoc.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 8 | #include "azure_c_shared_utility/sastoken.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 9 | #include "azure_c_shared_utility/urlencode.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 10 | #include "azure_c_shared_utility/hmacsha256.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 11 | #include "azure_c_shared_utility/base64.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 12 | #include "azure_c_shared_utility/agenttime.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 13 | #include "azure_c_shared_utility/strings.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 14 | #include "azure_c_shared_utility/buffer_.h" |
| Azure.IoT Build | 6:c55b013dfc2a | 15 | #include "azure_c_shared_utility/xlogging.h" |
| AzureIoTClient | 15:956c6d205aa7 | 16 | #include "azure_c_shared_utility/crt_abstractions.h" |
| AzureIoTClient | 15:956c6d205aa7 | 17 | |
| AzureIoTClient | 15:956c6d205aa7 | 18 | static double getExpiryValue(const char* expiryASCII) |
| AzureIoTClient | 15:956c6d205aa7 | 19 | { |
| AzureIoTClient | 15:956c6d205aa7 | 20 | double value = 0; |
| AzureIoTClient | 15:956c6d205aa7 | 21 | size_t i = 0; |
| AzureIoTClient | 15:956c6d205aa7 | 22 | for (i = 0; expiryASCII[i] != '\0'; i++) |
| AzureIoTClient | 15:956c6d205aa7 | 23 | { |
| AzureIoTClient | 15:956c6d205aa7 | 24 | if (expiryASCII[i] >= '0' && expiryASCII[i] <= '9') |
| AzureIoTClient | 15:956c6d205aa7 | 25 | { |
| AzureIoTClient | 15:956c6d205aa7 | 26 | value = value * 10 + (expiryASCII[i] - '0'); |
| AzureIoTClient | 15:956c6d205aa7 | 27 | } |
| AzureIoTClient | 15:956c6d205aa7 | 28 | else |
| AzureIoTClient | 15:956c6d205aa7 | 29 | { |
| AzureIoTClient | 15:956c6d205aa7 | 30 | value = 0; |
| AzureIoTClient | 15:956c6d205aa7 | 31 | break; |
| AzureIoTClient | 15:956c6d205aa7 | 32 | } |
| AzureIoTClient | 15:956c6d205aa7 | 33 | } |
| AzureIoTClient | 15:956c6d205aa7 | 34 | return value; |
| AzureIoTClient | 15:956c6d205aa7 | 35 | } |
| AzureIoTClient | 15:956c6d205aa7 | 36 | |
| AzureIoTClient | 15:956c6d205aa7 | 37 | bool SASToken_Validate(STRING_HANDLE sasToken) |
| AzureIoTClient | 15:956c6d205aa7 | 38 | { |
| AzureIoTClient | 15:956c6d205aa7 | 39 | bool result; |
| AzureIoTClient | 15:956c6d205aa7 | 40 | /*Codes_SRS_SASTOKEN_25_025: [**SASToken_Validate shall get the SASToken value by invoking STRING_c_str on the handle.**]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 41 | const char* sasTokenArray = STRING_c_str(sasToken); |
| AzureIoTClient | 15:956c6d205aa7 | 42 | |
| AzureIoTClient | 26:b38c66e3e45e | 43 | /* Codes_SRS_SASTOKEN_25_024: [**If handle is NULL then SASToken_Validate shall return false.**] */ |
| AzureIoTClient | 26:b38c66e3e45e | 44 | /* Codes_SRS_SASTOKEN_25_026: [**If STRING_c_str on handle return NULL then SASToken_Validate shall return false.**] */ |
| AzureIoTClient | 15:956c6d205aa7 | 45 | if (sasToken == NULL || sasTokenArray == NULL) |
| AzureIoTClient | 15:956c6d205aa7 | 46 | { |
| AzureIoTClient | 15:956c6d205aa7 | 47 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 48 | } |
| AzureIoTClient | 15:956c6d205aa7 | 49 | else |
| AzureIoTClient | 15:956c6d205aa7 | 50 | { |
| AzureIoTClient | 15:956c6d205aa7 | 51 | int seStart = -1, seStop = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 52 | int srStart = -1, srStop = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 53 | int sigStart = -1, sigStop = -1; |
| AzureIoTClient | 26:b38c66e3e45e | 54 | int tokenLength = (int)STRING_length(sasToken); |
| AzureIoTClient | 26:b38c66e3e45e | 55 | int i; |
| AzureIoTClient | 15:956c6d205aa7 | 56 | for (i = 0; i < tokenLength; i++) |
| AzureIoTClient | 15:956c6d205aa7 | 57 | { |
| AzureIoTClient | 15:956c6d205aa7 | 58 | if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'e' && sasTokenArray[i + 2] == '=') // Look for se= |
| AzureIoTClient | 15:956c6d205aa7 | 59 | { |
| AzureIoTClient | 15:956c6d205aa7 | 60 | seStart = i + 3; |
| AzureIoTClient | 15:956c6d205aa7 | 61 | if (srStart > 0 && srStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 62 | { |
| AzureIoTClient | 15:956c6d205aa7 | 63 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') // look for either & or space |
| AzureIoTClient | 15:956c6d205aa7 | 64 | srStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 65 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 66 | srStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 67 | else |
| AzureIoTClient | 15:956c6d205aa7 | 68 | seStart = -1; // as the format is not either "&se=" or " se=" |
| AzureIoTClient | 15:956c6d205aa7 | 69 | } |
| AzureIoTClient | 15:956c6d205aa7 | 70 | else if (sigStart > 0 && sigStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 71 | { |
| AzureIoTClient | 15:956c6d205aa7 | 72 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') |
| AzureIoTClient | 15:956c6d205aa7 | 73 | sigStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 74 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 75 | sigStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 76 | else |
| AzureIoTClient | 15:956c6d205aa7 | 77 | seStart = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 78 | } |
| AzureIoTClient | 15:956c6d205aa7 | 79 | } |
| AzureIoTClient | 26:b38c66e3e45e | 80 | else if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'r' && sasTokenArray[i + 2] == '=') // Look for sr= |
| AzureIoTClient | 15:956c6d205aa7 | 81 | { |
| AzureIoTClient | 15:956c6d205aa7 | 82 | srStart = i + 3; |
| AzureIoTClient | 15:956c6d205aa7 | 83 | if (seStart > 0 && seStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 84 | { |
| AzureIoTClient | 15:956c6d205aa7 | 85 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') |
| AzureIoTClient | 15:956c6d205aa7 | 86 | seStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 87 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 88 | seStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 89 | else |
| AzureIoTClient | 15:956c6d205aa7 | 90 | srStart = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 91 | } |
| AzureIoTClient | 15:956c6d205aa7 | 92 | else if (sigStart > 0 && sigStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 93 | { |
| AzureIoTClient | 15:956c6d205aa7 | 94 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') |
| AzureIoTClient | 15:956c6d205aa7 | 95 | sigStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 96 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 97 | sigStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 98 | else |
| AzureIoTClient | 15:956c6d205aa7 | 99 | srStart = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 100 | } |
| AzureIoTClient | 15:956c6d205aa7 | 101 | } |
| AzureIoTClient | 26:b38c66e3e45e | 102 | else if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'i' && sasTokenArray[i + 2] == 'g' && sasTokenArray[i + 3] == '=') // Look for sig= |
| AzureIoTClient | 15:956c6d205aa7 | 103 | { |
| AzureIoTClient | 15:956c6d205aa7 | 104 | sigStart = i + 4; |
| AzureIoTClient | 15:956c6d205aa7 | 105 | if (srStart > 0 && srStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 106 | { |
| AzureIoTClient | 15:956c6d205aa7 | 107 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') |
| AzureIoTClient | 15:956c6d205aa7 | 108 | srStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 109 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 110 | srStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 111 | else |
| AzureIoTClient | 15:956c6d205aa7 | 112 | sigStart = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 113 | } |
| AzureIoTClient | 15:956c6d205aa7 | 114 | else if (seStart > 0 && seStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 115 | { |
| AzureIoTClient | 15:956c6d205aa7 | 116 | if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') |
| AzureIoTClient | 15:956c6d205aa7 | 117 | seStop = i - 1; |
| AzureIoTClient | 15:956c6d205aa7 | 118 | else if (sasTokenArray[i - 1] == '&') |
| AzureIoTClient | 15:956c6d205aa7 | 119 | seStop = i - 2; |
| AzureIoTClient | 15:956c6d205aa7 | 120 | else |
| AzureIoTClient | 15:956c6d205aa7 | 121 | sigStart = -1; |
| AzureIoTClient | 15:956c6d205aa7 | 122 | } |
| AzureIoTClient | 15:956c6d205aa7 | 123 | } |
| AzureIoTClient | 15:956c6d205aa7 | 124 | } |
| AzureIoTClient | 26:b38c66e3e45e | 125 | |
| AzureIoTClient | 15:956c6d205aa7 | 126 | /*Codes_SRS_SASTOKEN_25_027: [**If SASTOKEN does not obey the SASToken format then SASToken_Validate shall return false.**]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 127 | /*Codes_SRS_SASTOKEN_25_028: [**SASToken_validate shall check for the presence of sr, se and sig from the token and return false if not found**]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 128 | if (seStart < 0 || srStart < 0 || sigStart < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 129 | { |
| AzureIoTClient | 15:956c6d205aa7 | 130 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 131 | } |
| AzureIoTClient | 15:956c6d205aa7 | 132 | else |
| AzureIoTClient | 15:956c6d205aa7 | 133 | { |
| AzureIoTClient | 15:956c6d205aa7 | 134 | if (seStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 135 | { |
| AzureIoTClient | 15:956c6d205aa7 | 136 | seStop = tokenLength; |
| AzureIoTClient | 15:956c6d205aa7 | 137 | } |
| AzureIoTClient | 15:956c6d205aa7 | 138 | else if (srStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 139 | { |
| AzureIoTClient | 15:956c6d205aa7 | 140 | srStop = tokenLength; |
| AzureIoTClient | 15:956c6d205aa7 | 141 | } |
| AzureIoTClient | 15:956c6d205aa7 | 142 | else if (sigStop < 0) |
| AzureIoTClient | 15:956c6d205aa7 | 143 | { |
| AzureIoTClient | 15:956c6d205aa7 | 144 | sigStop = tokenLength; |
| AzureIoTClient | 15:956c6d205aa7 | 145 | } |
| AzureIoTClient | 15:956c6d205aa7 | 146 | |
| AzureIoTClient | 15:956c6d205aa7 | 147 | if ((seStop <= seStart) || |
| AzureIoTClient | 15:956c6d205aa7 | 148 | (srStop <= srStart) || |
| AzureIoTClient | 15:956c6d205aa7 | 149 | (sigStop <= sigStart)) |
| AzureIoTClient | 15:956c6d205aa7 | 150 | { |
| AzureIoTClient | 15:956c6d205aa7 | 151 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 152 | } |
| AzureIoTClient | 15:956c6d205aa7 | 153 | else |
| AzureIoTClient | 15:956c6d205aa7 | 154 | { |
| AzureIoTClient | 25:8507bf644fdf | 155 | char* expiryASCII = (char*)malloc(seStop - seStart + 1); |
| AzureIoTClient | 15:956c6d205aa7 | 156 | /*Codes_SRS_SASTOKEN_25_031: [**If malloc fails during validation then SASToken_Validate shall return false.**]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 157 | if (expiryASCII == NULL) |
| AzureIoTClient | 15:956c6d205aa7 | 158 | { |
| AzureIoTClient | 15:956c6d205aa7 | 159 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 160 | } |
| AzureIoTClient | 15:956c6d205aa7 | 161 | else |
| AzureIoTClient | 15:956c6d205aa7 | 162 | { |
| AzureIoTClient | 15:956c6d205aa7 | 163 | double expiry; |
| AzureIoTClient | 26:b38c66e3e45e | 164 | // Add the Null terminator here |
| AzureIoTClient | 26:b38c66e3e45e | 165 | memset(expiryASCII, 0, seStop - seStart + 1); |
| AzureIoTClient | 15:956c6d205aa7 | 166 | for (i = seStart; i < seStop; i++) |
| AzureIoTClient | 15:956c6d205aa7 | 167 | { |
| AzureIoTClient | 26:b38c66e3e45e | 168 | // The se contains the expiration values, if a & token is encountered then |
| AzureIoTClient | 26:b38c66e3e45e | 169 | // the se field is complete. |
| AzureIoTClient | 26:b38c66e3e45e | 170 | if (sasTokenArray[i] == '&') |
| AzureIoTClient | 26:b38c66e3e45e | 171 | { |
| AzureIoTClient | 26:b38c66e3e45e | 172 | break; |
| AzureIoTClient | 26:b38c66e3e45e | 173 | } |
| AzureIoTClient | 15:956c6d205aa7 | 174 | expiryASCII[i - seStart] = sasTokenArray[i]; |
| AzureIoTClient | 15:956c6d205aa7 | 175 | } |
| AzureIoTClient | 15:956c6d205aa7 | 176 | expiry = getExpiryValue(expiryASCII); |
| AzureIoTClient | 15:956c6d205aa7 | 177 | /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 178 | if (expiry <= 0) |
| AzureIoTClient | 15:956c6d205aa7 | 179 | { |
| AzureIoTClient | 15:956c6d205aa7 | 180 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 181 | } |
| AzureIoTClient | 15:956c6d205aa7 | 182 | else |
| AzureIoTClient | 15:956c6d205aa7 | 183 | { |
| AzureIoTClient | 15:956c6d205aa7 | 184 | double secSinceEpoch = get_difftime(get_time(NULL), (time_t)0); |
| AzureIoTClient | 15:956c6d205aa7 | 185 | if (expiry < secSinceEpoch) |
| AzureIoTClient | 15:956c6d205aa7 | 186 | { |
| AzureIoTClient | 15:956c6d205aa7 | 187 | /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 188 | result = false; |
| AzureIoTClient | 15:956c6d205aa7 | 189 | } |
| AzureIoTClient | 15:956c6d205aa7 | 190 | else |
| AzureIoTClient | 15:956c6d205aa7 | 191 | { |
| AzureIoTClient | 15:956c6d205aa7 | 192 | /*Codes_SRS_SASTOKEN_25_030: [**SASToken_validate shall return true only if the format is obeyed and the token has not yet expired **]***/ |
| AzureIoTClient | 15:956c6d205aa7 | 193 | result = true; |
| AzureIoTClient | 15:956c6d205aa7 | 194 | } |
| AzureIoTClient | 15:956c6d205aa7 | 195 | } |
| AzureIoTClient | 15:956c6d205aa7 | 196 | free(expiryASCII); |
| AzureIoTClient | 15:956c6d205aa7 | 197 | } |
| AzureIoTClient | 15:956c6d205aa7 | 198 | } |
| AzureIoTClient | 15:956c6d205aa7 | 199 | } |
| AzureIoTClient | 15:956c6d205aa7 | 200 | } |
| AzureIoTClient | 15:956c6d205aa7 | 201 | |
| AzureIoTClient | 15:956c6d205aa7 | 202 | return result; |
| AzureIoTClient | 15:956c6d205aa7 | 203 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 204 | |
| AzureIoTClient | 23:ba126c6eb699 | 205 | static STRING_HANDLE construct_sas_token(const char* key, const char* scope, const char* keyname, size_t expiry) |
| AzureIoTClient | 23:ba126c6eb699 | 206 | { |
| AzureIoTClient | 23:ba126c6eb699 | 207 | STRING_HANDLE result; |
| AzureIoTClient | 23:ba126c6eb699 | 208 | |
| AzureIoTClient | 23:ba126c6eb699 | 209 | char tokenExpirationTime[32] = { 0 }; |
| AzureIoTClient | 23:ba126c6eb699 | 210 | |
| AzureIoTClient | 23:ba126c6eb699 | 211 | BUFFER_HANDLE decodedKey; |
| AzureIoTClient | 23:ba126c6eb699 | 212 | |
| AzureIoTClient | 23:ba126c6eb699 | 213 | /*Codes_SRS_SASTOKEN_06_029: [The key parameter is decoded from base64.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 214 | if ((decodedKey = Base64_Decoder(key)) == NULL) |
| AzureIoTClient | 23:ba126c6eb699 | 215 | { |
| AzureIoTClient | 23:ba126c6eb699 | 216 | /*Codes_SRS_SASTOKEN_06_030: [If there is an error in the decoding then SASToken_Create shall return NULL.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 217 | LogError("Unable to decode the key for generating the SAS."); |
| AzureIoTClient | 23:ba126c6eb699 | 218 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 219 | } |
| AzureIoTClient | 23:ba126c6eb699 | 220 | else |
| AzureIoTClient | 23:ba126c6eb699 | 221 | { |
| AzureIoTClient | 23:ba126c6eb699 | 222 | /*Codes_SRS_SASTOKEN_06_026: [If the conversion to string form fails for any reason then SASToken_Create shall return NULL.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 223 | if (size_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0) |
| AzureIoTClient | 23:ba126c6eb699 | 224 | { |
| AzureIoTClient | 23:ba126c6eb699 | 225 | LogError("For some reason converting seconds to a string failed. No SAS can be generated."); |
| AzureIoTClient | 23:ba126c6eb699 | 226 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 227 | } |
| AzureIoTClient | 23:ba126c6eb699 | 228 | else |
| AzureIoTClient | 23:ba126c6eb699 | 229 | { |
| AzureIoTClient | 23:ba126c6eb699 | 230 | STRING_HANDLE toBeHashed = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 231 | BUFFER_HANDLE hash = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 232 | if (((hash = BUFFER_new()) == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 233 | ((toBeHashed = STRING_new()) == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 234 | ((result = STRING_new()) == NULL)) |
| AzureIoTClient | 23:ba126c6eb699 | 235 | { |
| AzureIoTClient | 23:ba126c6eb699 | 236 | LogError("Unable to allocate memory to prepare SAS token."); |
| AzureIoTClient | 23:ba126c6eb699 | 237 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 238 | } |
| AzureIoTClient | 23:ba126c6eb699 | 239 | else |
| AzureIoTClient | 23:ba126c6eb699 | 240 | { |
| AzureIoTClient | 23:ba126c6eb699 | 241 | /*Codes_SRS_SASTOKEN_06_009: [The scope is the basis for creating a STRING_HANDLE.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 242 | /*Codes_SRS_SASTOKEN_06_010: [A "\n" is appended to that string.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 243 | /*Codes_SRS_SASTOKEN_06_011: [tokenExpirationTime is appended to that string.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 244 | if ((STRING_concat(toBeHashed, scope) != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 245 | (STRING_concat(toBeHashed, "\n") != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 246 | (STRING_concat(toBeHashed, tokenExpirationTime) != 0)) |
| AzureIoTClient | 23:ba126c6eb699 | 247 | { |
| AzureIoTClient | 23:ba126c6eb699 | 248 | LogError("Unable to build the input to the HMAC to prepare SAS token."); |
| AzureIoTClient | 23:ba126c6eb699 | 249 | STRING_delete(result); |
| AzureIoTClient | 23:ba126c6eb699 | 250 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 251 | } |
| AzureIoTClient | 23:ba126c6eb699 | 252 | else |
| AzureIoTClient | 23:ba126c6eb699 | 253 | { |
| AzureIoTClient | 23:ba126c6eb699 | 254 | STRING_HANDLE base64Signature = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 255 | STRING_HANDLE urlEncodedSignature = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 256 | size_t inLen = STRING_length(toBeHashed); |
| AzureIoTClient | 23:ba126c6eb699 | 257 | const unsigned char* inBuf = (const unsigned char*)STRING_c_str(toBeHashed); |
| AzureIoTClient | 23:ba126c6eb699 | 258 | size_t outLen = BUFFER_length(decodedKey); |
| AzureIoTClient | 23:ba126c6eb699 | 259 | unsigned char* outBuf = BUFFER_u_char(decodedKey); |
| AzureIoTClient | 23:ba126c6eb699 | 260 | /*Codes_SRS_SASTOKEN_06_013: [If an error is returned from the HMAC256 function then NULL is returned from SASToken_Create.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 261 | /*Codes_SRS_SASTOKEN_06_012: [An HMAC256 hash is calculated using the decodedKey, over toBeHashed.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 262 | /*Codes_SRS_SASTOKEN_06_014: [If there are any errors from the following operations then NULL shall be returned.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 263 | /*Codes_SRS_SASTOKEN_06_015: [The hash is base 64 encoded.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 264 | /*Codes_SRS_SASTOKEN_06_028: [base64Signature shall be url encoded.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 265 | /*Codes_SRS_SASTOKEN_06_016: [The string "SharedAccessSignature sr=" is the first part of the result of SASToken_Create.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 266 | /*Codes_SRS_SASTOKEN_06_017: [The scope parameter is appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 267 | /*Codes_SRS_SASTOKEN_06_018: [The string "&sig=" is appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 268 | /*Codes_SRS_SASTOKEN_06_019: [The string urlEncodedSignature shall be appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 269 | /*Codes_SRS_SASTOKEN_06_020: [The string "&se=" shall be appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 270 | /*Codes_SRS_SASTOKEN_06_021: [tokenExpirationTime is appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 271 | /*Codes_SRS_SASTOKEN_06_022: [The string "&skn=" is appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 272 | /*Codes_SRS_SASTOKEN_06_023: [The argument keyName is appended to result.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 273 | if ((HMACSHA256_ComputeHash(outBuf, outLen, inBuf, inLen, hash) != HMACSHA256_OK) || |
| AzureIoTClient | 25:8507bf644fdf | 274 | ((base64Signature = Base64_Encoder(hash)) == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 275 | ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 276 | (STRING_copy(result, "SharedAccessSignature sr=") != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 277 | (STRING_concat(result, scope) != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 278 | (STRING_concat(result, "&sig=") != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 279 | (STRING_concat_with_STRING(result, urlEncodedSignature) != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 280 | (STRING_concat(result, "&se=") != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 281 | (STRING_concat(result, tokenExpirationTime) != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 282 | (STRING_concat(result, "&skn=") != 0) || |
| AzureIoTClient | 23:ba126c6eb699 | 283 | (STRING_concat(result, keyname) != 0)) |
| AzureIoTClient | 23:ba126c6eb699 | 284 | { |
| AzureIoTClient | 23:ba126c6eb699 | 285 | LogError("Unable to build the SAS token."); |
| AzureIoTClient | 23:ba126c6eb699 | 286 | STRING_delete(result); |
| AzureIoTClient | 23:ba126c6eb699 | 287 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 288 | } |
| AzureIoTClient | 23:ba126c6eb699 | 289 | else |
| AzureIoTClient | 23:ba126c6eb699 | 290 | { |
| AzureIoTClient | 23:ba126c6eb699 | 291 | /* everything OK */ |
| AzureIoTClient | 23:ba126c6eb699 | 292 | } |
| AzureIoTClient | 23:ba126c6eb699 | 293 | STRING_delete(base64Signature); |
| AzureIoTClient | 23:ba126c6eb699 | 294 | STRING_delete(urlEncodedSignature); |
| AzureIoTClient | 23:ba126c6eb699 | 295 | } |
| AzureIoTClient | 23:ba126c6eb699 | 296 | } |
| AzureIoTClient | 23:ba126c6eb699 | 297 | STRING_delete(toBeHashed); |
| AzureIoTClient | 23:ba126c6eb699 | 298 | BUFFER_delete(hash); |
| AzureIoTClient | 23:ba126c6eb699 | 299 | } |
| AzureIoTClient | 23:ba126c6eb699 | 300 | BUFFER_delete(decodedKey); |
| AzureIoTClient | 23:ba126c6eb699 | 301 | } |
| AzureIoTClient | 23:ba126c6eb699 | 302 | return result; |
| AzureIoTClient | 23:ba126c6eb699 | 303 | } |
| AzureIoTClient | 23:ba126c6eb699 | 304 | |
| Azure.IoT Build | 0:fa2de1b79154 | 305 | STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry) |
| Azure.IoT Build | 0:fa2de1b79154 | 306 | { |
| AzureIoTClient | 23:ba126c6eb699 | 307 | STRING_HANDLE result; |
| Azure.IoT Build | 0:fa2de1b79154 | 308 | |
| Azure.IoT Build | 0:fa2de1b79154 | 309 | /*Codes_SRS_SASTOKEN_06_001: [If key is NULL then SASToken_Create shall return NULL.]*/ |
| Azure.IoT Build | 0:fa2de1b79154 | 310 | /*Codes_SRS_SASTOKEN_06_003: [If scope is NULL then SASToken_Create shall return NULL.]*/ |
| Azure.IoT Build | 0:fa2de1b79154 | 311 | /*Codes_SRS_SASTOKEN_06_007: [If keyName is NULL then SASToken_Create shall return NULL.]*/ |
| Azure.IoT Build | 0:fa2de1b79154 | 312 | if ((key == NULL) || |
| Azure.IoT Build | 0:fa2de1b79154 | 313 | (scope == NULL) || |
| Azure.IoT Build | 0:fa2de1b79154 | 314 | (keyName == NULL)) |
| Azure.IoT Build | 0:fa2de1b79154 | 315 | { |
| AzureIoTClient | 1:9190c0f4d23a | 316 | LogError("Invalid Parameter to SASToken_Create. handle key: %p, handle scope: %p, handle keyName: %p", key, scope, keyName); |
| AzureIoTClient | 23:ba126c6eb699 | 317 | result = NULL; |
| Azure.IoT Build | 0:fa2de1b79154 | 318 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 319 | else |
| Azure.IoT Build | 0:fa2de1b79154 | 320 | { |
| AzureIoTClient | 23:ba126c6eb699 | 321 | const char* string_key = STRING_c_str(key); |
| AzureIoTClient | 23:ba126c6eb699 | 322 | const char* string_scope = STRING_c_str(scope); |
| AzureIoTClient | 23:ba126c6eb699 | 323 | const char* string_name = STRING_c_str(keyName); |
| AzureIoTClient | 23:ba126c6eb699 | 324 | result = construct_sas_token(string_key, string_scope, string_name, expiry); |
| Azure.IoT Build | 0:fa2de1b79154 | 325 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 326 | return result; |
| Azure.IoT Build | 0:fa2de1b79154 | 327 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 328 | |
| AzureIoTClient | 23:ba126c6eb699 | 329 | STRING_HANDLE SASToken_CreateString(const char* key, const char* scope, const char* keyName, size_t expiry) |
| AzureIoTClient | 23:ba126c6eb699 | 330 | { |
| AzureIoTClient | 23:ba126c6eb699 | 331 | STRING_HANDLE result; |
| AzureIoTClient | 23:ba126c6eb699 | 332 | |
| AzureIoTClient | 23:ba126c6eb699 | 333 | /*Codes_SRS_SASTOKEN_06_001: [If key is NULL then SASToken_Create shall return NULL.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 334 | /*Codes_SRS_SASTOKEN_06_003: [If scope is NULL then SASToken_Create shall return NULL.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 335 | /*Codes_SRS_SASTOKEN_06_007: [If keyName is NULL then SASToken_Create shall return NULL.]*/ |
| AzureIoTClient | 23:ba126c6eb699 | 336 | if ((key == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 337 | (scope == NULL) || |
| AzureIoTClient | 23:ba126c6eb699 | 338 | (keyName == NULL)) |
| AzureIoTClient | 23:ba126c6eb699 | 339 | { |
| AzureIoTClient | 23:ba126c6eb699 | 340 | LogError("Invalid Parameter to SASToken_Create. handle key: %p, handle scope: %p, handle keyName: %p", key, scope, keyName); |
| AzureIoTClient | 23:ba126c6eb699 | 341 | result = NULL; |
| AzureIoTClient | 23:ba126c6eb699 | 342 | } |
| AzureIoTClient | 23:ba126c6eb699 | 343 | else |
| AzureIoTClient | 23:ba126c6eb699 | 344 | { |
| AzureIoTClient | 23:ba126c6eb699 | 345 | result = construct_sas_token(key, scope, keyName, expiry); |
| AzureIoTClient | 23:ba126c6eb699 | 346 | } |
| AzureIoTClient | 23:ba126c6eb699 | 347 | return result; |
| AzureIoTClient | 23:ba126c6eb699 | 348 | } |
