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