A Port of TI's Webserver for the CC3000

Dependencies:   mbed

Committer:
dflet
Date:
Mon Sep 16 18:37:14 2013 +0000
Revision:
2:e6a185df9e4c
Parent:
0:6ad60d78b315
ADC and Leds now work on board and config.html page.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dflet 0:6ad60d78b315 1 /*****************************************************************************
dflet 0:6ad60d78b315 2 *
dflet 0:6ad60d78b315 3 * HttpAuth.c
dflet 0:6ad60d78b315 4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
dflet 0:6ad60d78b315 5 *
dflet 0:6ad60d78b315 6 * Redistribution and use in source and binary forms, with or without
dflet 0:6ad60d78b315 7 * modification, are permitted provided that the following conditions
dflet 0:6ad60d78b315 8 * are met:
dflet 0:6ad60d78b315 9 *
dflet 0:6ad60d78b315 10 * Redistributions of source code must retain the above copyright
dflet 0:6ad60d78b315 11 * notice, this list of conditions and the following disclaimer.
dflet 0:6ad60d78b315 12 *
dflet 0:6ad60d78b315 13 * Redistributions in binary form must reproduce the above copyright
dflet 0:6ad60d78b315 14 * notice, this list of conditions and the following disclaimer in the
dflet 0:6ad60d78b315 15 * documentation and/or other materials provided with the
dflet 0:6ad60d78b315 16 * distribution.
dflet 0:6ad60d78b315 17 *
dflet 0:6ad60d78b315 18 * Neither the name of Texas Instruments Incorporated nor the names of
dflet 0:6ad60d78b315 19 * its contributors may be used to endorse or promote products derived
dflet 0:6ad60d78b315 20 * from this software without specific prior written permission.
dflet 0:6ad60d78b315 21 *
dflet 0:6ad60d78b315 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dflet 0:6ad60d78b315 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dflet 0:6ad60d78b315 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dflet 0:6ad60d78b315 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dflet 0:6ad60d78b315 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dflet 0:6ad60d78b315 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dflet 0:6ad60d78b315 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dflet 0:6ad60d78b315 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dflet 0:6ad60d78b315 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dflet 0:6ad60d78b315 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dflet 0:6ad60d78b315 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dflet 0:6ad60d78b315 33 *
dflet 0:6ad60d78b315 34 *****************************************************************************/
dflet 0:6ad60d78b315 35 #include "HttpAuth.h"
dflet 0:6ad60d78b315 36
dflet 0:6ad60d78b315 37 #ifdef HTTP_CORE_ENABLE_AUTH
dflet 0:6ad60d78b315 38
dflet 0:6ad60d78b315 39 #include "md5.h"
dflet 0:6ad60d78b315 40 #include <string.h>
dflet 0:6ad60d78b315 41 #include "HttpString.h"
dflet 0:6ad60d78b315 42 /**
dflet 0:6ad60d78b315 43 * @addtogroup HttpAuth
dflet 0:6ad60d78b315 44 * @{
dflet 0:6ad60d78b315 45 */
dflet 0:6ad60d78b315 46
dflet 0:6ad60d78b315 47 #define DIGEST_AUTHENTICATION_BUFFER_SIZE (32)
dflet 0:6ad60d78b315 48
dflet 0:6ad60d78b315 49 /**
dflet 0:6ad60d78b315 50 * This structure holds the HTTP digest-access authentication state
dflet 0:6ad60d78b315 51 */
dflet 0:6ad60d78b315 52 struct HttpAuthState
dflet 0:6ad60d78b315 53 {
dflet 0:6ad60d78b315 54 /// Last-generated nonce
dflet 0:6ad60d78b315 55 uint8 nonce[DIGEST_AUTHENTICATION_BUFFER_SIZE];
dflet 0:6ad60d78b315 56 /// Last-generated opaque
dflet 0:6ad60d78b315 57 uint8 opaque[DIGEST_AUTHENTICATION_BUFFER_SIZE];
dflet 0:6ad60d78b315 58 /// The hash of the username, realm, and password
dflet 0:6ad60d78b315 59 uint8 ha1[DIGEST_AUTHENTICATION_BUFFER_SIZE];
dflet 0:6ad60d78b315 60 };
dflet 0:6ad60d78b315 61
dflet 0:6ad60d78b315 62
dflet 0:6ad60d78b315 63
dflet 0:6ad60d78b315 64 /// The global state for digest-access authentication
dflet 0:6ad60d78b315 65
dflet 0:6ad60d78b315 66 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:6ad60d78b315 67 // {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:6ad60d78b315 68 // {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:6ad60d78b315 69
dflet 0:6ad60d78b315 70 ///
dflet 0:6ad60d78b315 71 MD5_CTX MD5state;
dflet 0:6ad60d78b315 72
dflet 0:6ad60d78b315 73 char HTTP_AUTH_REALM[] = "mbed web server";
dflet 0:6ad60d78b315 74
dflet 0:6ad60d78b315 75 /// Header strings to be used for response headers
dflet 0:6ad60d78b315 76 char HTTP_AUTHENTICATE_RESPONSE_REALM[] = "WWW-Authenticate: Digest realm=\"";
dflet 0:6ad60d78b315 77 char HTTP_AUTHENTICATE_RESPONSE_NONCE[] = "\",qop=\"auth\",nonce=\"";
dflet 0:6ad60d78b315 78 char HTTP_AUTHENTICATE_RESPONSE_OPAQUE[] = "\",opaque=\"";
dflet 0:6ad60d78b315 79 char HTTP_AUTHENTICATE_RESPONSE_EOH[] = "\"\r\n";
dflet 0:6ad60d78b315 80
dflet 0:6ad60d78b315 81 /// Authenticate header tokens
dflet 0:6ad60d78b315 82 char HTTP_AUTHENTICATE_REALM[] = "realm";
dflet 0:6ad60d78b315 83 char HTTP_AUTHENTICATE_QOP[] = "qop";
dflet 0:6ad60d78b315 84 char HTTP_AUTHENTICATE_AUTH[] = "auth";
dflet 0:6ad60d78b315 85 char HTTP_AUTHENTICATE_NONCE[] = "nonce";
dflet 0:6ad60d78b315 86 char HTTP_AUTHENTICATE_OPAQUE[] = "opaque";
dflet 0:6ad60d78b315 87 char HTTP_AUTHENTICATE_DIGEST[] = "digest";
dflet 0:6ad60d78b315 88 char HTTP_AUTHENTICATE_URI[] = "uri";
dflet 0:6ad60d78b315 89 char HTTP_AUTHENTICATE_NC[] = "nc=";
dflet 0:6ad60d78b315 90 char HTTP_AUTHENTICATE_CNONCE[] = "cnonce";
dflet 0:6ad60d78b315 91 char HTTP_AUTHENTICATE_RESPONSE[] = "response";
dflet 0:6ad60d78b315 92 char HTTP_AUTHENTICATE_USERNAME[] = "username";
dflet 0:6ad60d78b315 93 char HTTP_DELIMITER_QUOTE[] = "\"";
dflet 0:6ad60d78b315 94 char HTTP_DELIMITER_COMMA[] = ",";
dflet 0:6ad60d78b315 95
dflet 0:6ad60d78b315 96
dflet 0:6ad60d78b315 97 /// The length of the response authentication header
dflet 0:6ad60d78b315 98 /// The two 32 numbers represent nonce and opaque strings and the -5 is to compensate for the sizeof() calls
dflet 0:6ad60d78b315 99 uint16 HTTP_AUTHENTICATE_RESPONSE_HEADER_LENGTH =
dflet 0:6ad60d78b315 100 sizeof(HTTP_AUTHENTICATE_RESPONSE_REALM) +
dflet 0:6ad60d78b315 101 sizeof(HTTP_AUTHENTICATE_RESPONSE_NONCE) +
dflet 0:6ad60d78b315 102 sizeof(HTTP_AUTHENTICATE_RESPONSE_OPAQUE) +
dflet 0:6ad60d78b315 103 sizeof(HTTP_AUTHENTICATE_RESPONSE_EOH) +
dflet 0:6ad60d78b315 104 sizeof(HTTP_AUTH_REALM) +
dflet 0:6ad60d78b315 105 DIGEST_AUTHENTICATION_BUFFER_SIZE + DIGEST_AUTHENTICATION_BUFFER_SIZE - 5;
dflet 0:6ad60d78b315 106
dflet 0:6ad60d78b315 107
dflet 0:6ad60d78b315 108 /**
dflet 0:6ad60d78b315 109 * Simple random generator
dflet 0:6ad60d78b315 110 * To improve randomness the initial seed has to be dynamic
dflet 0:6ad60d78b315 111 */
dflet 0:6ad60d78b315 112 static uint32 GetRandomUint()
dflet 0:6ad60d78b315 113 {
dflet 0:6ad60d78b315 114 // set static seed
dflet 0:6ad60d78b315 115 static uint32 m_z = 1234;
dflet 0:6ad60d78b315 116 static uint32 m_w = 98877;
dflet 0:6ad60d78b315 117
dflet 0:6ad60d78b315 118 m_z = 36969 * (m_z & 65535) + (m_z >> 16);
dflet 0:6ad60d78b315 119 m_w = 18000 * (m_w & 65535) + (m_w >> 16);
dflet 0:6ad60d78b315 120 return (m_z << 16) + m_w;
dflet 0:6ad60d78b315 121 }
dflet 0:6ad60d78b315 122
dflet 0:6ad60d78b315 123 static void MD5_FinalToString(uint8* str, MD5_CTX *md5stat)
dflet 0:6ad60d78b315 124 {
dflet 0:6ad60d78b315 125 uint8 tmp[16];
dflet 0:6ad60d78b315 126 uint8 i;
dflet 0:6ad60d78b315 127 struct HttpBlob location;
dflet 0:6ad60d78b315 128 location.uLength = 2;
dflet 0:6ad60d78b315 129 location.pData = str;
dflet 0:6ad60d78b315 130 MD5_Final(tmp, md5stat);
dflet 0:6ad60d78b315 131 for (i=0; i<16; i++, location.pData += 2)
dflet 0:6ad60d78b315 132 HttpString_htoa(tmp[i], &location, 1);
dflet 0:6ad60d78b315 133 }
dflet 0:6ad60d78b315 134
dflet 0:6ad60d78b315 135
dflet 0:6ad60d78b315 136 /**
dflet 0:6ad60d78b315 137 * This function will generate random 16 bytes to be used for Nonce and opaque strings
dflet 0:6ad60d78b315 138 */
dflet 0:6ad60d78b315 139 static void Generate32BytesRandomString(uint8 *str)
dflet 0:6ad60d78b315 140 {
dflet 0:6ad60d78b315 141 struct HttpBlob str1;
dflet 0:6ad60d78b315 142 str1.uLength = 8;
dflet 0:6ad60d78b315 143 str1.pData = str;
dflet 0:6ad60d78b315 144 HttpString_htoa(GetRandomUint(), &str1, 1);
dflet 0:6ad60d78b315 145 str1.pData = str + 8;
dflet 0:6ad60d78b315 146 HttpString_htoa(GetRandomUint(), &str1, 1);
dflet 0:6ad60d78b315 147 str1.pData = str + 16;
dflet 0:6ad60d78b315 148 HttpString_htoa(GetRandomUint(), &str1, 1);
dflet 0:6ad60d78b315 149 str1.pData = str + 24;
dflet 0:6ad60d78b315 150 HttpString_htoa(GetRandomUint(), &str1, 1);
dflet 0:6ad60d78b315 151 }
dflet 0:6ad60d78b315 152
dflet 0:6ad60d78b315 153 void HttpAuth_Init(struct HttpBlob username, struct HttpBlob password)
dflet 0:6ad60d78b315 154 {
dflet 0:6ad60d78b315 155 MD5_Init(&MD5state);
dflet 0:6ad60d78b315 156 MD5_Update(&MD5state, username.pData, username.uLength);
dflet 0:6ad60d78b315 157 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 158 MD5_Update(&MD5state, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM)-1);
dflet 0:6ad60d78b315 159 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 160 MD5_Update(&MD5state, password.pData, password.uLength);
dflet 0:6ad60d78b315 161 MD5_FinalToString(g_authState.ha1, &MD5state);
dflet 0:6ad60d78b315 162 }
dflet 0:6ad60d78b315 163
dflet 0:6ad60d78b315 164 static void AddStringToBlob(struct HttpBlob * trgt, char *str, uint16 length)
dflet 0:6ad60d78b315 165 {
dflet 0:6ad60d78b315 166 memcpy(trgt->pData + trgt->uLength, str, length);
dflet 0:6ad60d78b315 167 trgt->uLength += length;
dflet 0:6ad60d78b315 168 }
dflet 0:6ad60d78b315 169
dflet 0:6ad60d78b315 170 void HttpAuth_ResponseAuthenticate(struct HttpRequest* pRequest, struct HttpBlob* pWWWAuthenticate)
dflet 0:6ad60d78b315 171 {
dflet 0:6ad60d78b315 172 struct HttpBlob headerBlob;
dflet 0:6ad60d78b315 173
dflet 0:6ad60d78b315 174 if (pWWWAuthenticate->uLength < HTTP_AUTHENTICATE_RESPONSE_HEADER_LENGTH)
dflet 0:6ad60d78b315 175 {
dflet 0:6ad60d78b315 176 pWWWAuthenticate->uLength = 0;
dflet 0:6ad60d78b315 177 return;
dflet 0:6ad60d78b315 178 }
dflet 0:6ad60d78b315 179 // There is enough space to add the authenticate header
dflet 0:6ad60d78b315 180
dflet 0:6ad60d78b315 181 headerBlob.pData = pWWWAuthenticate->pData;
dflet 0:6ad60d78b315 182 headerBlob.uLength = 0;
dflet 0:6ad60d78b315 183
dflet 0:6ad60d78b315 184 // Generate new Nonce and opaque
dflet 0:6ad60d78b315 185 Generate32BytesRandomString(g_authState.nonce);
dflet 0:6ad60d78b315 186 Generate32BytesRandomString(g_authState.opaque);
dflet 0:6ad60d78b315 187
dflet 0:6ad60d78b315 188 // Build response header
dflet 0:6ad60d78b315 189 AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_REALM, sizeof(HTTP_AUTHENTICATE_RESPONSE_REALM)-1);
dflet 0:6ad60d78b315 190 AddStringToBlob(&headerBlob, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM) -1);
dflet 0:6ad60d78b315 191 AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_NONCE, sizeof(HTTP_AUTHENTICATE_RESPONSE_NONCE) -1);
dflet 0:6ad60d78b315 192 AddStringToBlob(&headerBlob, (char*)g_authState.nonce, sizeof(g_authState.nonce));
dflet 0:6ad60d78b315 193 AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_OPAQUE, sizeof(HTTP_AUTHENTICATE_RESPONSE_OPAQUE) -1);
dflet 0:6ad60d78b315 194 AddStringToBlob(&headerBlob, (char*)g_authState.opaque, sizeof(g_authState.opaque));
dflet 0:6ad60d78b315 195 AddStringToBlob(&headerBlob, HTTP_AUTHENTICATE_RESPONSE_EOH, sizeof(HTTP_AUTHENTICATE_RESPONSE_EOH) - 1);
dflet 0:6ad60d78b315 196
dflet 0:6ad60d78b315 197 pWWWAuthenticate->uLength = headerBlob.uLength;
dflet 0:6ad60d78b315 198 }
dflet 0:6ad60d78b315 199
dflet 0:6ad60d78b315 200 /**
dflet 0:6ad60d78b315 201 * Find/verify name value pair in the input blob
dflet 0:6ad60d78b315 202 *
dflet 0:6ad60d78b315 203 * After return the location is stays in the same place since the order of the name value pairs in not constant
dflet 0:6ad60d78b315 204 * Returns: if header not found return 0
dflet 0:6ad60d78b315 205 * if value token is NULL - return pointer to start of value length of value till the \" delimiter
dflet 0:6ad60d78b315 206 * if value token is not NULL - return 1 if values match
dflet 0:6ad60d78b315 207 */
dflet 0:6ad60d78b315 208 static uint16 HttpAuth_VerifyHeaderNameValue(struct HttpBlob *location, char* nameToken, uint8 tokenlenLen, char *value, uint8 valuelen, char** outValue)
dflet 0:6ad60d78b315 209 {
dflet 0:6ad60d78b315 210 uint8 * found;
dflet 0:6ad60d78b315 211 struct HttpBlob originalLocation;
dflet 0:6ad60d78b315 212 originalLocation.uLength = location->uLength;
dflet 0:6ad60d78b315 213 originalLocation.pData = location->pData;
dflet 0:6ad60d78b315 214
dflet 0:6ad60d78b315 215 found = HttpString_nextToken(nameToken, tokenlenLen, *location);
dflet 0:6ad60d78b315 216
dflet 0:6ad60d78b315 217 // Missing header name
dflet 0:6ad60d78b315 218 if (found == 0)
dflet 0:6ad60d78b315 219 return 0;
dflet 0:6ad60d78b315 220 else
dflet 0:6ad60d78b315 221 {
dflet 0:6ad60d78b315 222 location->uLength = originalLocation.uLength - (uint16)(found - originalLocation.pData) - (tokenlenLen + 2);
dflet 0:6ad60d78b315 223 location->pData = found + tokenlenLen + 2;
dflet 0:6ad60d78b315 224 // Return the value pointer and size
dflet 0:6ad60d78b315 225 if (value == NULL)
dflet 0:6ad60d78b315 226 {
dflet 0:6ad60d78b315 227 *outValue= (char*)location->pData;
dflet 0:6ad60d78b315 228 nameToken = (char *)location->pData;
dflet 0:6ad60d78b315 229 found = HttpString_nextToken(HTTP_DELIMITER_QUOTE, sizeof(HTTP_DELIMITER_QUOTE) - 1, *location);
dflet 0:6ad60d78b315 230 if (found==0)
dflet 0:6ad60d78b315 231 found = HttpString_nextToken(HTTP_DELIMITER_COMMA, sizeof(HTTP_DELIMITER_COMMA) - 1, *location);
dflet 0:6ad60d78b315 232
dflet 0:6ad60d78b315 233 // Restore current location
dflet 0:6ad60d78b315 234 location->uLength = originalLocation.uLength;
dflet 0:6ad60d78b315 235 location->pData = originalLocation.pData;
dflet 0:6ad60d78b315 236 return (uint16)((char *)found - nameToken);
dflet 0:6ad60d78b315 237 }
dflet 0:6ad60d78b315 238
dflet 0:6ad60d78b315 239 found = HttpString_nextToken(value, valuelen, *location);
dflet 0:6ad60d78b315 240 // Value does not match - restore location
dflet 0:6ad60d78b315 241 if (found == 0)
dflet 0:6ad60d78b315 242 {
dflet 0:6ad60d78b315 243 location->uLength = originalLocation.uLength;
dflet 0:6ad60d78b315 244 location->pData = originalLocation.pData;
dflet 0:6ad60d78b315 245 return 0;
dflet 0:6ad60d78b315 246 }
dflet 0:6ad60d78b315 247
dflet 0:6ad60d78b315 248 // Restore location
dflet 0:6ad60d78b315 249 location->uLength = originalLocation.uLength;
dflet 0:6ad60d78b315 250 location->pData = originalLocation.pData;
dflet 0:6ad60d78b315 251 return 1;
dflet 0:6ad60d78b315 252 }
dflet 0:6ad60d78b315 253 }
dflet 0:6ad60d78b315 254
dflet 0:6ad60d78b315 255
dflet 0:6ad60d78b315 256 void HttpAuth_RequestAuthenticate(struct HttpRequest* pRequest, struct HttpBlob authorization)
dflet 0:6ad60d78b315 257 {
dflet 0:6ad60d78b315 258 uint8 ha2[DIGEST_AUTHENTICATION_BUFFER_SIZE], correctResponse[DIGEST_AUTHENTICATION_BUFFER_SIZE];
dflet 0:6ad60d78b315 259 struct HttpBlob currentLocation, blob;
dflet 0:6ad60d78b315 260 // HA1 was not copmuted
dflet 0:6ad60d78b315 261 if ((uint32)*g_authState.ha1 == 0)
dflet 0:6ad60d78b315 262 {
dflet 0:6ad60d78b315 263 return;
dflet 0:6ad60d78b315 264 }
dflet 0:6ad60d78b315 265
dflet 0:6ad60d78b315 266 // Parse the header - find relevant tokens and handle
dflet 0:6ad60d78b315 267 currentLocation.pData = authorization.pData;
dflet 0:6ad60d78b315 268 currentLocation.uLength = authorization.uLength;
dflet 0:6ad60d78b315 269
dflet 0:6ad60d78b315 270 // Verify the mandatory tokens, whose content we ignore are present
dflet 0:6ad60d78b315 271
dflet 0:6ad60d78b315 272 // verify we are in degest authentication method, any other is not supported
dflet 0:6ad60d78b315 273 if (HttpString_nextToken(HTTP_AUTHENTICATE_DIGEST, sizeof(HTTP_AUTHENTICATE_DIGEST)-1, currentLocation) == 0)
dflet 0:6ad60d78b315 274 return;
dflet 0:6ad60d78b315 275
dflet 0:6ad60d78b315 276 // verify username exists
dflet 0:6ad60d78b315 277 if (HttpString_nextToken(HTTP_AUTHENTICATE_USERNAME, sizeof(HTTP_AUTHENTICATE_USERNAME)-1, currentLocation) == 0)
dflet 0:6ad60d78b315 278 return;
dflet 0:6ad60d78b315 279
dflet 0:6ad60d78b315 280 // Verify realm
dflet 0:6ad60d78b315 281 if (HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_REALM, sizeof(HTTP_AUTHENTICATE_REALM)-1, HTTP_AUTH_REALM, sizeof(HTTP_AUTH_REALM)-1, 0) != 1)
dflet 0:6ad60d78b315 282 return;
dflet 0:6ad60d78b315 283
dflet 0:6ad60d78b315 284 // Verify correct nonce
dflet 0:6ad60d78b315 285 if (HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_NONCE, sizeof(HTTP_AUTHENTICATE_NONCE)-1, (char *)g_authState.nonce, DIGEST_AUTHENTICATION_BUFFER_SIZE, 0) != 1)
dflet 0:6ad60d78b315 286 return;
dflet 0:6ad60d78b315 287
dflet 0:6ad60d78b315 288 // Verify correct opaque
dflet 0:6ad60d78b315 289 if (HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_OPAQUE, sizeof(HTTP_AUTHENTICATE_OPAQUE)-1, (char *)g_authState.opaque, DIGEST_AUTHENTICATION_BUFFER_SIZE, 0) != 1)
dflet 0:6ad60d78b315 290 return;
dflet 0:6ad60d78b315 291
dflet 0:6ad60d78b315 292 // Find neccessary tokents and compute HA2 if some tokens are not found - return
dflet 0:6ad60d78b315 293 blob.pData = NULL;
dflet 0:6ad60d78b315 294 blob.uLength = HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_URI, sizeof(HTTP_AUTHENTICATE_URI)-1, 0, 0, (char**)&blob.pData);
dflet 0:6ad60d78b315 295 // Uri is missing
dflet 0:6ad60d78b315 296 if (blob.uLength == 0)
dflet 0:6ad60d78b315 297 return;
dflet 0:6ad60d78b315 298
dflet 0:6ad60d78b315 299 MD5_Init(&MD5state);
dflet 0:6ad60d78b315 300 if ((pRequest->uFlags & HTTP_REQUEST_FLAG_METHOD_POST) != 0)
dflet 0:6ad60d78b315 301 MD5_Update(&MD5state, (unsigned char*)"POST", 4);
dflet 0:6ad60d78b315 302 else
dflet 0:6ad60d78b315 303 MD5_Update(&MD5state, (unsigned char*)"GET", 3);
dflet 0:6ad60d78b315 304 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 305 MD5_Update(&MD5state, blob.pData, blob.uLength);
dflet 0:6ad60d78b315 306 MD5_FinalToString(ha2, &MD5state);
dflet 0:6ad60d78b315 307
dflet 0:6ad60d78b315 308 // Find tokens to compute correct response
dflet 0:6ad60d78b315 309 blob.pData = HttpString_nextToken(HTTP_AUTHENTICATE_NC, sizeof(HTTP_AUTHENTICATE_NC)-1, currentLocation);
dflet 0:6ad60d78b315 310 // Ncount is missing
dflet 0:6ad60d78b315 311 if (blob.pData == 0)
dflet 0:6ad60d78b315 312 return;
dflet 0:6ad60d78b315 313 blob.pData += sizeof(HTTP_AUTHENTICATE_NC) - 1;
dflet 0:6ad60d78b315 314 blob.uLength = 8;
dflet 0:6ad60d78b315 315
dflet 0:6ad60d78b315 316 MD5_Init(&MD5state);
dflet 0:6ad60d78b315 317 MD5_Update(&MD5state, g_authState.ha1, DIGEST_AUTHENTICATION_BUFFER_SIZE);
dflet 0:6ad60d78b315 318 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 319 MD5_Update(&MD5state, g_authState.nonce, DIGEST_AUTHENTICATION_BUFFER_SIZE);
dflet 0:6ad60d78b315 320 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 321 MD5_Update(&MD5state, blob.pData, blob.uLength);
dflet 0:6ad60d78b315 322
dflet 0:6ad60d78b315 323 blob.pData = NULL;
dflet 0:6ad60d78b315 324 blob.uLength = HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_CNONCE, sizeof(HTTP_AUTHENTICATE_CNONCE)-1, 0, 0, (char **)&blob.pData);
dflet 0:6ad60d78b315 325 // Cnonce is missing
dflet 0:6ad60d78b315 326 if (blob.uLength == 0)
dflet 0:6ad60d78b315 327 return;
dflet 0:6ad60d78b315 328 MD5_Update(&MD5state, (unsigned char*)":", 1);
dflet 0:6ad60d78b315 329 MD5_Update(&MD5state, blob.pData, blob.uLength);
dflet 0:6ad60d78b315 330 MD5_Update(&MD5state, (unsigned char*)":auth:", 6);
dflet 0:6ad60d78b315 331 MD5_Update(&MD5state, ha2, DIGEST_AUTHENTICATION_BUFFER_SIZE);
dflet 0:6ad60d78b315 332 MD5_FinalToString(correctResponse, &MD5state);
dflet 0:6ad60d78b315 333
dflet 0:6ad60d78b315 334 // Compare received response to the one computed locally - if equal then authorize
dflet 0:6ad60d78b315 335 blob.pData = NULL;
dflet 0:6ad60d78b315 336 blob.uLength = HttpAuth_VerifyHeaderNameValue(&currentLocation, HTTP_AUTHENTICATE_RESPONSE, sizeof(HTTP_AUTHENTICATE_RESPONSE)-1, 0, 0, (char **)&blob.pData);
dflet 0:6ad60d78b315 337 // Response is missing
dflet 0:6ad60d78b315 338 if (blob.uLength != DIGEST_AUTHENTICATION_BUFFER_SIZE)
dflet 0:6ad60d78b315 339 return;
dflet 0:6ad60d78b315 340
dflet 0:6ad60d78b315 341 currentLocation.pData = correctResponse;
dflet 0:6ad60d78b315 342 currentLocation.uLength = DIGEST_AUTHENTICATION_BUFFER_SIZE;
dflet 0:6ad60d78b315 343 // if the responses are equal
dflet 0:6ad60d78b315 344 if (HttpString_strcmp(blob, currentLocation) == 0)
dflet 0:6ad60d78b315 345 pRequest->uFlags |= HTTP_REQUEST_FLAG_AUTHENTICATED;
dflet 0:6ad60d78b315 346
dflet 0:6ad60d78b315 347 }
dflet 0:6ad60d78b315 348 #endif
dflet 0:6ad60d78b315 349