TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.
http/server/HttpAuth.cpp@0:400d8e75a8d0, 2015-09-06 (annotated)
- Committer:
- dflet
- Date:
- Sun Sep 06 15:19:36 2015 +0000
- Revision:
- 0:400d8e75a8d0
TI's websocket Camera demo, also uses Arducam mini 0v5642 camera.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dflet | 0:400d8e75a8d0 | 1 | //***************************************************************************** |
dflet | 0:400d8e75a8d0 | 2 | // Copyright (C) 2014 Texas Instruments Incorporated |
dflet | 0:400d8e75a8d0 | 3 | // |
dflet | 0:400d8e75a8d0 | 4 | // All rights reserved. Property of Texas Instruments Incorporated. |
dflet | 0:400d8e75a8d0 | 5 | // Restricted rights to use, duplicate or disclose this code are |
dflet | 0:400d8e75a8d0 | 6 | // granted through contract. |
dflet | 0:400d8e75a8d0 | 7 | // The program may not be used without the written permission of |
dflet | 0:400d8e75a8d0 | 8 | // Texas Instruments Incorporated or against the terms and conditions |
dflet | 0:400d8e75a8d0 | 9 | // stipulated in the agreement under which this program has been supplied, |
dflet | 0:400d8e75a8d0 | 10 | // and under no circumstances can it be used with non-TI connectivity device. |
dflet | 0:400d8e75a8d0 | 11 | // |
dflet | 0:400d8e75a8d0 | 12 | //***************************************************************************** |
dflet | 0:400d8e75a8d0 | 13 | |
dflet | 0:400d8e75a8d0 | 14 | #include "HttpAuth.h" |
dflet | 0:400d8e75a8d0 | 15 | |
dflet | 0:400d8e75a8d0 | 16 | #ifdef HTTP_CORE_ENABLE_AUTH |
dflet | 0:400d8e75a8d0 | 17 | |
dflet | 0:400d8e75a8d0 | 18 | #include <string.h> |
dflet | 0:400d8e75a8d0 | 19 | #include "HttpString.h" |
dflet | 0:400d8e75a8d0 | 20 | /** |
dflet | 0:400d8e75a8d0 | 21 | * @addtogroup HttpAuth |
dflet | 0:400d8e75a8d0 | 22 | * @{ |
dflet | 0:400d8e75a8d0 | 23 | */ |
dflet | 0:400d8e75a8d0 | 24 | |
dflet | 0:400d8e75a8d0 | 25 | #define DIGEST_AUTHENTICATION_BUFFER_SIZE (32) |
dflet | 0:400d8e75a8d0 | 26 | |
dflet | 0:400d8e75a8d0 | 27 | /** |
dflet | 0:400d8e75a8d0 | 28 | * This structure holds the HTTP digest-access authentication state |
dflet | 0:400d8e75a8d0 | 29 | */ |
dflet | 0:400d8e75a8d0 | 30 | struct HttpAuthState |
dflet | 0:400d8e75a8d0 | 31 | { |
dflet | 0:400d8e75a8d0 | 32 | /// Last-generated nonce |
dflet | 0:400d8e75a8d0 | 33 | UINT8 nonce[DIGEST_AUTHENTICATION_BUFFER_SIZE]; |
dflet | 0:400d8e75a8d0 | 34 | /// Last-generated opaque |
dflet | 0:400d8e75a8d0 | 35 | UINT8 opaque[DIGEST_AUTHENTICATION_BUFFER_SIZE]; |
dflet | 0:400d8e75a8d0 | 36 | /// The hash of the username, realm, and password |
dflet | 0:400d8e75a8d0 | 37 | UINT8 ha1[DIGEST_AUTHENTICATION_BUFFER_SIZE]; |
dflet | 0:400d8e75a8d0 | 38 | }; |
dflet | 0:400d8e75a8d0 | 39 | |
dflet | 0:400d8e75a8d0 | 40 | |
dflet | 0:400d8e75a8d0 | 41 | |
dflet | 0:400d8e75a8d0 | 42 | /// The global state for digest-access authentication |
dflet | 0:400d8e75a8d0 | 43 | |
dflet | 0:400d8e75a8d0 | 44 | static struct HttpAuthState g_authState; // = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, |
dflet | 0:400d8e75a8d0 | 45 | // {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, |
dflet | 0:400d8e75a8d0 | 46 | // {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; |
dflet | 0:400d8e75a8d0 | 47 | |
dflet | 0:400d8e75a8d0 | 48 | /// |
dflet | 0:400d8e75a8d0 | 49 | MD5_CTX MD5state; |
dflet | 0:400d8e75a8d0 | 50 | |
dflet | 0:400d8e75a8d0 | 51 | char HTTP_AUTH_REALM[] = "cc3200 web server"; |
dflet | 0:400d8e75a8d0 | 52 | |
dflet | 0:400d8e75a8d0 | 53 | /// Header strings to be used for response headers |
dflet | 0:400d8e75a8d0 | 54 | char HTTP_AUTHENTICATE_RESPONSE_REALM[] = "WWW-Authenticate: Digest realm=\""; |
dflet | 0:400d8e75a8d0 | 55 | char HTTP_AUTHENTICATE_RESPONSE_NONCE[] = "\",qop=\"auth\",nonce=\""; |
dflet | 0:400d8e75a8d0 | 56 | char HTTP_AUTHENTICATE_RESPONSE_OPAQUE[] = "\",opaque=\""; |
dflet | 0:400d8e75a8d0 | 57 | char HTTP_AUTHENTICATE_RESPONSE_EOH[] = "\"\r\n"; |
dflet | 0:400d8e75a8d0 | 58 | |
dflet | 0:400d8e75a8d0 | 59 | /// Authenticate header tokens |
dflet | 0:400d8e75a8d0 | 60 | char HTTP_AUTHENTICATE_REALM[] = "realm"; |
dflet | 0:400d8e75a8d0 | 61 | char HTTP_AUTHENTICATE_QOP[] = "qop"; |
dflet | 0:400d8e75a8d0 | 62 | char HTTP_AUTHENTICATE_AUTH[] = "auth"; |
dflet | 0:400d8e75a8d0 | 63 | char HTTP_AUTHENTICATE_NONCE[] = "nonce"; |
dflet | 0:400d8e75a8d0 | 64 | char HTTP_AUTHENTICATE_OPAQUE[] = "opaque"; |
dflet | 0:400d8e75a8d0 | 65 | char HTTP_AUTHENTICATE_DIGEST[] = "digest"; |
dflet | 0:400d8e75a8d0 | 66 | char HTTP_AUTHENTICATE_URI[] = "uri"; |
dflet | 0:400d8e75a8d0 | 67 | char HTTP_AUTHENTICATE_NC[] = "nc="; |
dflet | 0:400d8e75a8d0 | 68 | char HTTP_AUTHENTICATE_CNONCE[] = "cnonce"; |
dflet | 0:400d8e75a8d0 | 69 | char HTTP_AUTHENTICATE_RESPONSE[] = "response"; |
dflet | 0:400d8e75a8d0 | 70 | char HTTP_AUTHENTICATE_USERNAME[] = "username"; |
dflet | 0:400d8e75a8d0 | 71 | char HTTP_DELIMITER_QUOTE[] = "\""; |
dflet | 0:400d8e75a8d0 | 72 | char HTTP_DELIMITER_COMMA[] = ","; |
dflet | 0:400d8e75a8d0 | 73 | |
dflet | 0:400d8e75a8d0 | 74 | |
dflet | 0:400d8e75a8d0 | 75 | /// The length of the response authentication header |
dflet | 0:400d8e75a8d0 | 76 | /// The two 32 numbers represent nonce and opaque strings and the -5 is to compensate for the sizeof() calls |
dflet | 0:400d8e75a8d0 | 77 | UINT16 HTTP_AUTHENTICATE_RESPONSE_HEADER_LENGTH = |
dflet | 0:400d8e75a8d0 | 78 | sizeof(HTTP_AUTHENTICATE_RESPONSE_REALM) + |
dflet | 0:400d8e75a8d0 | 79 | sizeof(HTTP_AUTHENTICATE_RESPONSE_NONCE) + |
dflet | 0:400d8e75a8d0 | 80 | sizeof(HTTP_AUTHENTICATE_RESPONSE_OPAQUE) + |
dflet | 0:400d8e75a8d0 | 81 | sizeof(HTTP_AUTHENTICATE_RESPONSE_EOH) + |
dflet | 0:400d8e75a8d0 | 82 | sizeof(HTTP_AUTH_REALM) + |
dflet | 0:400d8e75a8d0 | 83 | DIGEST_AUTHENTICATION_BUFFER_SIZE + DIGEST_AUTHENTICATION_BUFFER_SIZE - 5; |
dflet | 0:400d8e75a8d0 | 84 | |
dflet | 0:400d8e75a8d0 | 85 | |
dflet | 0:400d8e75a8d0 | 86 | /** |
dflet | 0:400d8e75a8d0 | 87 | * Simple random generator |
dflet | 0:400d8e75a8d0 | 88 | * To improve randomness the initial seed has to be dynamic |
dflet | 0:400d8e75a8d0 | 89 | */ |
dflet | 0:400d8e75a8d0 | 90 | static UINT32 GetRandomUint() |
dflet | 0:400d8e75a8d0 | 91 | { |
dflet | 0:400d8e75a8d0 | 92 | // set static seed |
dflet | 0:400d8e75a8d0 | 93 | static UINT32 m_z = 1234; |
dflet | 0:400d8e75a8d0 | 94 | static UINT32 m_w = 98877; |
dflet | 0:400d8e75a8d0 | 95 | |
dflet | 0:400d8e75a8d0 | 96 | m_z = 36969 * (m_z & 65535) + (m_z >> 16); |
dflet | 0:400d8e75a8d0 | 97 | m_w = 18000 * (m_w & 65535) + (m_w >> 16); |
dflet | 0:400d8e75a8d0 | 98 | return (m_z << 16) + m_w; |
dflet | 0:400d8e75a8d0 | 99 | } |
dflet | 0:400d8e75a8d0 | 100 | |
dflet | 0:400d8e75a8d0 | 101 | static void MD5_FinalToString(UINT8* str, MD5_CTX *md5stat) |
dflet | 0:400d8e75a8d0 | 102 | { |
dflet | 0:400d8e75a8d0 | 103 | UINT8 tmp[16]; |
dflet | 0:400d8e75a8d0 | 104 | UINT8 i; |
dflet | 0:400d8e75a8d0 | 105 | struct HttpBlob location; |
dflet | 0:400d8e75a8d0 | 106 | location.uLength = 2; |
dflet | 0:400d8e75a8d0 | 107 | location.pData = str; |
dflet | 0:400d8e75a8d0 | 108 | MD5_Final(tmp, md5stat); |
dflet | 0:400d8e75a8d0 | 109 | for (i=0; i<16; i++, location.pData += 2) |
dflet | 0:400d8e75a8d0 | 110 | HttpString_htoa(tmp[i], &location, 1); |
dflet | 0:400d8e75a8d0 | 111 | } |
dflet | 0:400d8e75a8d0 | 112 | |
dflet | 0:400d8e75a8d0 | 113 | |
dflet | 0:400d8e75a8d0 | 114 | /** |
dflet | 0:400d8e75a8d0 | 115 | * This function will generate random 16 bytes to be used for Nonce and opaque strings |
dflet | 0:400d8e75a8d0 | 116 | */ |
dflet | 0:400d8e75a8d0 | 117 | static void Generate32BytesRandomString(UINT8 *str) |
dflet | 0:400d8e75a8d0 | 118 | { |
dflet | 0:400d8e75a8d0 | 119 | struct HttpBlob str1; |
dflet | 0:400d8e75a8d0 | 120 | str1.uLength = 8; |
dflet | 0:400d8e75a8d0 | 121 | str1.pData = str; |
dflet | 0:400d8e75a8d0 | 122 | HttpString_htoa(GetRandomUint(), &str1, 1); |
dflet | 0:400d8e75a8d0 | 123 | str1.pData = str + 8; |
dflet | 0:400d8e75a8d0 | 124 | HttpString_htoa(GetRandomUint(), &str1, 1); |
dflet | 0:400d8e75a8d0 | 125 | str1.pData = str + 16; |
dflet | 0:400d8e75a8d0 | 126 | HttpString_htoa(GetRandomUint(), &str1, 1); |
dflet | 0:400d8e75a8d0 | 127 | str1.pData = str + 24; |
dflet | 0:400d8e75a8d0 | 128 | HttpString_htoa(GetRandomUint(), &str1, 1); |
dflet | 0:400d8e75a8d0 | 129 | } |
dflet | 0:400d8e75a8d0 | 130 | |
dflet | 0:400d8e75a8d0 | 131 | void HttpAuth_Init(struct HttpBlob username, struct HttpBlob password) |
dflet | 0:400d8e75a8d0 | 132 | { |
dflet | 0:400d8e75a8d0 | 133 | MD5_Init(&MD5state); |
dflet | 0:400d8e75a8d0 | 134 | MD5_Update(&MD5state, username.pData, username.uLength); |
dflet | 0:400d8e75a8d0 | 135 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 136 | MD5_Update(&MD5state, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM)-1); |
dflet | 0:400d8e75a8d0 | 137 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 138 | MD5_Update(&MD5state, password.pData, password.uLength); |
dflet | 0:400d8e75a8d0 | 139 | MD5_FinalToString(g_authState.ha1, &MD5state); |
dflet | 0:400d8e75a8d0 | 140 | } |
dflet | 0:400d8e75a8d0 | 141 | |
dflet | 0:400d8e75a8d0 | 142 | static void AddStringToBlob(struct HttpBlob * trgt, char *str, UINT16 length) |
dflet | 0:400d8e75a8d0 | 143 | { |
dflet | 0:400d8e75a8d0 | 144 | memcpy(trgt->pData + trgt->uLength, str, length); |
dflet | 0:400d8e75a8d0 | 145 | trgt->uLength += length; |
dflet | 0:400d8e75a8d0 | 146 | } |
dflet | 0:400d8e75a8d0 | 147 | |
dflet | 0:400d8e75a8d0 | 148 | void HttpAuth_ResponseAuthenticate(struct HttpRequest* pRequest, struct HttpBlob* pWWWAuthenticate) |
dflet | 0:400d8e75a8d0 | 149 | { |
dflet | 0:400d8e75a8d0 | 150 | struct HttpBlob headerBlob; |
dflet | 0:400d8e75a8d0 | 151 | |
dflet | 0:400d8e75a8d0 | 152 | if (pWWWAuthenticate->uLength < HTTP_AUTHENTICATE_RESPONSE_HEADER_LENGTH) |
dflet | 0:400d8e75a8d0 | 153 | { |
dflet | 0:400d8e75a8d0 | 154 | pWWWAuthenticate->uLength = 0; |
dflet | 0:400d8e75a8d0 | 155 | return; |
dflet | 0:400d8e75a8d0 | 156 | } |
dflet | 0:400d8e75a8d0 | 157 | // There is enough space to add the authenticate header |
dflet | 0:400d8e75a8d0 | 158 | |
dflet | 0:400d8e75a8d0 | 159 | headerBlob.pData = pWWWAuthenticate->pData; |
dflet | 0:400d8e75a8d0 | 160 | headerBlob.uLength = 0; |
dflet | 0:400d8e75a8d0 | 161 | |
dflet | 0:400d8e75a8d0 | 162 | // Generate new Nonce and opaque |
dflet | 0:400d8e75a8d0 | 163 | Generate32BytesRandomString(g_authState.nonce); |
dflet | 0:400d8e75a8d0 | 164 | Generate32BytesRandomString(g_authState.opaque); |
dflet | 0:400d8e75a8d0 | 165 | |
dflet | 0:400d8e75a8d0 | 166 | // Build response header |
dflet | 0:400d8e75a8d0 | 167 | AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_REALM, sizeof(HTTP_AUTHENTICATE_RESPONSE_REALM)-1); |
dflet | 0:400d8e75a8d0 | 168 | AddStringToBlob(&headerBlob, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM) -1); |
dflet | 0:400d8e75a8d0 | 169 | AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_NONCE, sizeof(HTTP_AUTHENTICATE_RESPONSE_NONCE) -1); |
dflet | 0:400d8e75a8d0 | 170 | AddStringToBlob(&headerBlob, (char*)g_authState.nonce, sizeof(g_authState.nonce)); |
dflet | 0:400d8e75a8d0 | 171 | AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_OPAQUE, sizeof(HTTP_AUTHENTICATE_RESPONSE_OPAQUE) -1); |
dflet | 0:400d8e75a8d0 | 172 | AddStringToBlob(&headerBlob, (char*)g_authState.opaque, sizeof(g_authState.opaque)); |
dflet | 0:400d8e75a8d0 | 173 | AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_EOH, sizeof(HTTP_AUTHENTICATE_RESPONSE_EOH) - 1); |
dflet | 0:400d8e75a8d0 | 174 | |
dflet | 0:400d8e75a8d0 | 175 | pWWWAuthenticate->uLength = headerBlob.uLength; |
dflet | 0:400d8e75a8d0 | 176 | } |
dflet | 0:400d8e75a8d0 | 177 | |
dflet | 0:400d8e75a8d0 | 178 | /** |
dflet | 0:400d8e75a8d0 | 179 | * Find/verify name value pair in the input blob |
dflet | 0:400d8e75a8d0 | 180 | * |
dflet | 0:400d8e75a8d0 | 181 | * After return the location is stays in the same place since the order of the name value pairs in not constant |
dflet | 0:400d8e75a8d0 | 182 | * Returns: if header not found return 0 |
dflet | 0:400d8e75a8d0 | 183 | * if value token is NULL - return pointer to start of value length of value till the \" delimiter |
dflet | 0:400d8e75a8d0 | 184 | * if value token is not NULL - return 1 if values match |
dflet | 0:400d8e75a8d0 | 185 | */ |
dflet | 0:400d8e75a8d0 | 186 | static UINT16 HttpAuth_VerifyHeaderNameValue(struct HttpBlob *location, char* nameToken, UINT8 tokenlenLen, char *value, UINT8 valuelen, char** outValue) |
dflet | 0:400d8e75a8d0 | 187 | { |
dflet | 0:400d8e75a8d0 | 188 | UINT8 * found; |
dflet | 0:400d8e75a8d0 | 189 | struct HttpBlob originalLocation; |
dflet | 0:400d8e75a8d0 | 190 | originalLocation.uLength = location->uLength; |
dflet | 0:400d8e75a8d0 | 191 | originalLocation.pData = location->pData; |
dflet | 0:400d8e75a8d0 | 192 | |
dflet | 0:400d8e75a8d0 | 193 | found = HttpString_nextToken(nameToken, tokenlenLen, *location); |
dflet | 0:400d8e75a8d0 | 194 | |
dflet | 0:400d8e75a8d0 | 195 | // Missing header name |
dflet | 0:400d8e75a8d0 | 196 | if (found == 0) |
dflet | 0:400d8e75a8d0 | 197 | return 0; |
dflet | 0:400d8e75a8d0 | 198 | else |
dflet | 0:400d8e75a8d0 | 199 | { |
dflet | 0:400d8e75a8d0 | 200 | location->uLength = originalLocation.uLength - (UINT16)(found - originalLocation.pData) - (tokenlenLen + 2); |
dflet | 0:400d8e75a8d0 | 201 | location->pData = found + tokenlenLen + 2; |
dflet | 0:400d8e75a8d0 | 202 | // Return the value pointer and size |
dflet | 0:400d8e75a8d0 | 203 | if (value == NULL) |
dflet | 0:400d8e75a8d0 | 204 | { |
dflet | 0:400d8e75a8d0 | 205 | *outValue= (char*)location->pData; |
dflet | 0:400d8e75a8d0 | 206 | nameToken = (char *)location->pData; |
dflet | 0:400d8e75a8d0 | 207 | found = HttpString_nextToken(HTTP_DELIMITER_QUOTE, sizeof(HTTP_DELIMITER_QUOTE) - 1, *location); |
dflet | 0:400d8e75a8d0 | 208 | if (found==0) |
dflet | 0:400d8e75a8d0 | 209 | found = HttpString_nextToken(HTTP_DELIMITER_COMMA, sizeof(HTTP_DELIMITER_COMMA) - 1, *location); |
dflet | 0:400d8e75a8d0 | 210 | |
dflet | 0:400d8e75a8d0 | 211 | // Restore current location |
dflet | 0:400d8e75a8d0 | 212 | location->uLength = originalLocation.uLength; |
dflet | 0:400d8e75a8d0 | 213 | location->pData = originalLocation.pData; |
dflet | 0:400d8e75a8d0 | 214 | return (UINT16)((char *)found - nameToken); |
dflet | 0:400d8e75a8d0 | 215 | } |
dflet | 0:400d8e75a8d0 | 216 | |
dflet | 0:400d8e75a8d0 | 217 | found = HttpString_nextToken(value, valuelen, *location); |
dflet | 0:400d8e75a8d0 | 218 | // Value does not match - restore location |
dflet | 0:400d8e75a8d0 | 219 | if (found == 0) |
dflet | 0:400d8e75a8d0 | 220 | { |
dflet | 0:400d8e75a8d0 | 221 | location->uLength = originalLocation.uLength; |
dflet | 0:400d8e75a8d0 | 222 | location->pData = originalLocation.pData; |
dflet | 0:400d8e75a8d0 | 223 | return 0; |
dflet | 0:400d8e75a8d0 | 224 | } |
dflet | 0:400d8e75a8d0 | 225 | |
dflet | 0:400d8e75a8d0 | 226 | // Restore location |
dflet | 0:400d8e75a8d0 | 227 | location->uLength = originalLocation.uLength; |
dflet | 0:400d8e75a8d0 | 228 | location->pData = originalLocation.pData; |
dflet | 0:400d8e75a8d0 | 229 | return 1; |
dflet | 0:400d8e75a8d0 | 230 | } |
dflet | 0:400d8e75a8d0 | 231 | } |
dflet | 0:400d8e75a8d0 | 232 | |
dflet | 0:400d8e75a8d0 | 233 | |
dflet | 0:400d8e75a8d0 | 234 | void HttpAuth_RequestAuthenticate(struct HttpRequest* pRequest, struct HttpBlob authorization) |
dflet | 0:400d8e75a8d0 | 235 | { |
dflet | 0:400d8e75a8d0 | 236 | UINT8 ha2[DIGEST_AUTHENTICATION_BUFFER_SIZE], correctResponse[DIGEST_AUTHENTICATION_BUFFER_SIZE]; |
dflet | 0:400d8e75a8d0 | 237 | struct HttpBlob currentLocation, blob; |
dflet | 0:400d8e75a8d0 | 238 | // HA1 was not copmuted |
dflet | 0:400d8e75a8d0 | 239 | if ((UINT32)*g_authState.ha1 == 0) |
dflet | 0:400d8e75a8d0 | 240 | { |
dflet | 0:400d8e75a8d0 | 241 | return; |
dflet | 0:400d8e75a8d0 | 242 | } |
dflet | 0:400d8e75a8d0 | 243 | |
dflet | 0:400d8e75a8d0 | 244 | // Parse the header - find relevant tokens and handle |
dflet | 0:400d8e75a8d0 | 245 | currentLocation.pData = authorization.pData; |
dflet | 0:400d8e75a8d0 | 246 | currentLocation.uLength = authorization.uLength; |
dflet | 0:400d8e75a8d0 | 247 | |
dflet | 0:400d8e75a8d0 | 248 | // Verify the mandatory tokens, whose content we ignore are present |
dflet | 0:400d8e75a8d0 | 249 | |
dflet | 0:400d8e75a8d0 | 250 | // verify we are in degest authentication method, any other is not supported |
dflet | 0:400d8e75a8d0 | 251 | if (HttpString_nextToken(HTTP_AUTHENTICATE_DIGEST, sizeof(HTTP_AUTHENTICATE_DIGEST)-1, currentLocation) == 0) |
dflet | 0:400d8e75a8d0 | 252 | return; |
dflet | 0:400d8e75a8d0 | 253 | |
dflet | 0:400d8e75a8d0 | 254 | // verify username exists |
dflet | 0:400d8e75a8d0 | 255 | if (HttpString_nextToken(HTTP_AUTHENTICATE_USERNAME, sizeof(HTTP_AUTHENTICATE_USERNAME)-1, currentLocation) == 0) |
dflet | 0:400d8e75a8d0 | 256 | return; |
dflet | 0:400d8e75a8d0 | 257 | |
dflet | 0:400d8e75a8d0 | 258 | // Verify realm |
dflet | 0:400d8e75a8d0 | 259 | if (HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_REALM, sizeof(HTTP_AUTHENTICATE_REALM)-1, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM)-1, 0) != 1) |
dflet | 0:400d8e75a8d0 | 260 | return; |
dflet | 0:400d8e75a8d0 | 261 | |
dflet | 0:400d8e75a8d0 | 262 | // Verify correct nonce |
dflet | 0:400d8e75a8d0 | 263 | if (HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_NONCE, sizeof(HTTP_AUTHENTICATE_NONCE)-1, (char *)g_authState.nonce, DIGEST_AUTHENTICATION_BUFFER_SIZE, 0) != 1) |
dflet | 0:400d8e75a8d0 | 264 | return; |
dflet | 0:400d8e75a8d0 | 265 | |
dflet | 0:400d8e75a8d0 | 266 | // Verify correct opaque |
dflet | 0:400d8e75a8d0 | 267 | if (HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_OPAQUE, sizeof(HTTP_AUTHENTICATE_OPAQUE)-1, (char *)g_authState.opaque, DIGEST_AUTHENTICATION_BUFFER_SIZE, 0) != 1) |
dflet | 0:400d8e75a8d0 | 268 | return; |
dflet | 0:400d8e75a8d0 | 269 | |
dflet | 0:400d8e75a8d0 | 270 | // Find neccessary tokents and compute HA2 if some tokens are not found - return |
dflet | 0:400d8e75a8d0 | 271 | blob.pData = NULL; |
dflet | 0:400d8e75a8d0 | 272 | blob.uLength = HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_URI, sizeof(HTTP_AUTHENTICATE_URI)-1, 0, 0, (char**)&blob.pData); |
dflet | 0:400d8e75a8d0 | 273 | // Uri is missing |
dflet | 0:400d8e75a8d0 | 274 | if (blob.uLength == 0) |
dflet | 0:400d8e75a8d0 | 275 | return; |
dflet | 0:400d8e75a8d0 | 276 | |
dflet | 0:400d8e75a8d0 | 277 | MD5_Init(&MD5state); |
dflet | 0:400d8e75a8d0 | 278 | if ((pRequest->uFlags & HTTP_REQUEST_FLAG_METHOD_POST) != 0) |
dflet | 0:400d8e75a8d0 | 279 | MD5_Update(&MD5state, "POST", 4); |
dflet | 0:400d8e75a8d0 | 280 | else |
dflet | 0:400d8e75a8d0 | 281 | MD5_Update(&MD5state, "GET", 3); |
dflet | 0:400d8e75a8d0 | 282 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 283 | MD5_Update(&MD5state, blob.pData, blob.uLength); |
dflet | 0:400d8e75a8d0 | 284 | MD5_FinalToString(ha2, &MD5state); |
dflet | 0:400d8e75a8d0 | 285 | |
dflet | 0:400d8e75a8d0 | 286 | // Find tokens to compute correct response |
dflet | 0:400d8e75a8d0 | 287 | blob.pData = HttpString_nextToken(HTTP_AUTHENTICATE_NC, sizeof(HTTP_AUTHENTICATE_NC)-1, currentLocation); |
dflet | 0:400d8e75a8d0 | 288 | // Ncount is missing |
dflet | 0:400d8e75a8d0 | 289 | if (blob.pData == 0) |
dflet | 0:400d8e75a8d0 | 290 | return; |
dflet | 0:400d8e75a8d0 | 291 | blob.pData += sizeof(HTTP_AUTHENTICATE_NC) - 1; |
dflet | 0:400d8e75a8d0 | 292 | blob.uLength = 8; |
dflet | 0:400d8e75a8d0 | 293 | |
dflet | 0:400d8e75a8d0 | 294 | MD5_Init(&MD5state); |
dflet | 0:400d8e75a8d0 | 295 | MD5_Update(&MD5state, g_authState.ha1, DIGEST_AUTHENTICATION_BUFFER_SIZE); |
dflet | 0:400d8e75a8d0 | 296 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 297 | MD5_Update(&MD5state, g_authState.nonce, DIGEST_AUTHENTICATION_BUFFER_SIZE); |
dflet | 0:400d8e75a8d0 | 298 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 299 | MD5_Update(&MD5state, blob.pData, blob.uLength); |
dflet | 0:400d8e75a8d0 | 300 | |
dflet | 0:400d8e75a8d0 | 301 | blob.pData = NULL; |
dflet | 0:400d8e75a8d0 | 302 | blob.uLength = HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_CNONCE, sizeof(HTTP_AUTHENTICATE_CNONCE)-1, 0, 0, (char **)&blob.pData); |
dflet | 0:400d8e75a8d0 | 303 | // Cnonce is missing |
dflet | 0:400d8e75a8d0 | 304 | if (blob.uLength == 0) |
dflet | 0:400d8e75a8d0 | 305 | return; |
dflet | 0:400d8e75a8d0 | 306 | MD5_Update(&MD5state, ":", 1); |
dflet | 0:400d8e75a8d0 | 307 | MD5_Update(&MD5state, blob.pData, blob.uLength); |
dflet | 0:400d8e75a8d0 | 308 | MD5_Update(&MD5state, ":auth:", 6); |
dflet | 0:400d8e75a8d0 | 309 | MD5_Update(&MD5state, ha2, DIGEST_AUTHENTICATION_BUFFER_SIZE); |
dflet | 0:400d8e75a8d0 | 310 | MD5_FinalToString(correctResponse, &MD5state); |
dflet | 0:400d8e75a8d0 | 311 | |
dflet | 0:400d8e75a8d0 | 312 | // Compare received response to the one computed locally - if equal then authorize |
dflet | 0:400d8e75a8d0 | 313 | blob.pData = NULL; |
dflet | 0:400d8e75a8d0 | 314 | blob.uLength = HttpAuth_VerifyHeaderNameValue(¤tLocation, HTTP_AUTHENTICATE_RESPONSE, sizeof(HTTP_AUTHENTICATE_RESPONSE)-1, 0, 0, (char **)&blob.pData); |
dflet | 0:400d8e75a8d0 | 315 | // Response is missing |
dflet | 0:400d8e75a8d0 | 316 | if (blob.uLength != DIGEST_AUTHENTICATION_BUFFER_SIZE) |
dflet | 0:400d8e75a8d0 | 317 | return; |
dflet | 0:400d8e75a8d0 | 318 | |
dflet | 0:400d8e75a8d0 | 319 | currentLocation.pData = correctResponse; |
dflet | 0:400d8e75a8d0 | 320 | currentLocation.uLength = DIGEST_AUTHENTICATION_BUFFER_SIZE; |
dflet | 0:400d8e75a8d0 | 321 | // if the responses are equal |
dflet | 0:400d8e75a8d0 | 322 | if (HttpString_strcmp(blob, currentLocation) == 0) |
dflet | 0:400d8e75a8d0 | 323 | pRequest->uFlags |= HTTP_REQUEST_FLAG_AUTHENTICATED; |
dflet | 0:400d8e75a8d0 | 324 | |
dflet | 0:400d8e75a8d0 | 325 | } |
dflet | 0:400d8e75a8d0 | 326 | #endif |
dflet | 0:400d8e75a8d0 | 327 | |
dflet | 0:400d8e75a8d0 | 328 | /// @} |
dflet | 0:400d8e75a8d0 | 329 | |
dflet | 0:400d8e75a8d0 | 330 |