David Fletcher
/
CC3000WebServer
A Port of TI's Webserver for the CC3000
WebServer/HttpAuth.cpp@0:6ad60d78b315, 2013-09-14 (annotated)
- Committer:
- dflet
- Date:
- Sat Sep 14 17:38:41 2013 +0000
- Revision:
- 0:6ad60d78b315
Mostly working will serve the default pages index.html and config.html, but config.html is not woring at present.
Who changed what in which revision?
User | Revision | Line number | New 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(¤tLocation, 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(¤tLocation, 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(¤tLocation, 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(¤tLocation, 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(¤tLocation, 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(¤tLocation, 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 |