TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.

Dependencies:   mbed

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?

UserRevisionLine numberNew 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(&currentLocation, 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(&currentLocation, 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(&currentLocation, 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(&currentLocation, 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(&currentLocation, 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(&currentLocation, 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