http_server_auth.c
Go to the documentation of this file.
1 /**
2  * @file http_server_auth.c
3  * @brief HTTP authentication
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL HTTP_TRACE_LEVEL
33 
34 //Dependencies
35 #include <stdlib.h>
36 #include "core/net.h"
37 #include "http/http_server.h"
38 #include "http/http_server_auth.h"
39 #include "http/http_server_misc.h"
40 #include "str.h"
41 #include "debug.h"
42 
43 //Check TCP/IP stack configuration
44 #if (HTTP_SERVER_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Password verification
49  * @param[in] connection Structure representing an HTTP connection
50  * @param[in] password NULL-terminated string containing the password to be checked
51  * @param[in] mode HTTP authentication scheme to be used. Acceptable
52  * values are HTTP_AUTH_MODE_BASIC or HTTP_AUTH_MODE_DIGEST
53  * @return TRUE if the password is valid, else FALSE
54  **/
55 
57  const char_t *password, HttpAuthMode mode)
58 {
59  //This flag tells whether the password is valid
60  bool_t status = FALSE;
61 
62  //Debug message
63  TRACE_DEBUG("HTTP password verification...\r\n");
64 
65 #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED)
66  //Basic authentication scheme?
67  if(mode == HTTP_AUTH_MODE_BASIC)
68  {
69  //Point to the authentication credentials
70  HttpAuthorizationHeader *auth = &connection->request.auth;
71 
72  //Make sure authentication credentials have been found
73  if(auth->found && auth->mode == HTTP_AUTH_MODE_BASIC)
74  {
75  //Sanity check
76  if(auth->password != NULL)
77  {
78  //Check whether the password is valid
79  if(!osStrcmp(password, auth->password))
80  status = TRUE;
81  }
82  }
83  }
84 #endif
85 #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
86  //Digest authentication scheme?
87  if(mode == HTTP_AUTH_MODE_DIGEST)
88  {
89  //Point to the authentication credentials
90  HttpAuthorizationHeader *auth = &connection->request.auth;
91 
92  //Make sure authentication credentials have been found
93  if(auth->found && auth->mode == HTTP_AUTH_MODE_DIGEST)
94  {
95  //Sanity check
96  if(auth->realm != NULL && auth->nonce != NULL &&
97  auth->uri != NULL && auth->qop != NULL &&
98  auth->nc != NULL && auth->cnonce != NULL &&
99  auth->response != NULL)
100  {
101  error_t error;
102  Md5Context *md5Context;
103  char_t ha1[2 * MD5_DIGEST_SIZE + 1];
104  char_t ha2[2 * MD5_DIGEST_SIZE + 1];
105 
106  //Allocate a memory buffer to hold the MD5 context
107  md5Context = osAllocMem(sizeof(Md5Context));
108 
109  //MD5 context successfully allocated?
110  if(md5Context != NULL)
111  {
112  //Compute HA1 = MD5(username : realm : password)
113  md5Init(md5Context);
114  md5Update(md5Context, auth->user, osStrlen(auth->user));
115  md5Update(md5Context, ":", 1);
116  md5Update(md5Context, auth->realm, osStrlen(auth->realm));
117  md5Update(md5Context, ":", 1);
118  md5Update(md5Context, password, osStrlen(password));
119  md5Final(md5Context, NULL);
120 
121  //Convert MD5 hash to hex string
123  //Debug message
124  TRACE_DEBUG(" HA1: %s\r\n", ha1);
125 
126  //Compute HA2 = MD5(method : uri)
127  md5Init(md5Context);
128  md5Update(md5Context, connection->request.method, osStrlen(connection->request.method));
129  md5Update(md5Context, ":", 1);
130  md5Update(md5Context, auth->uri, osStrlen(auth->uri));
131  md5Final(md5Context, NULL);
132 
133  //Convert MD5 hash to hex string
135  //Debug message
136  TRACE_DEBUG(" HA2: %s\r\n", ha2);
137 
138  //Compute MD5(HA1 : nonce : nc : cnonce : qop : HA2)
139  md5Init(md5Context);
140  md5Update(md5Context, ha1, osStrlen(ha1));
141  md5Update(md5Context, ":", 1);
142  md5Update(md5Context, auth->nonce, osStrlen(auth->nonce));
143  md5Update(md5Context, ":", 1);
144  md5Update(md5Context, auth->nc, osStrlen(auth->nc));
145  md5Update(md5Context, ":", 1);
146  md5Update(md5Context, auth->cnonce, osStrlen(auth->cnonce));
147  md5Update(md5Context, ":", 1);
148  md5Update(md5Context, auth->qop, osStrlen(auth->qop));
149  md5Update(md5Context, ":", 1);
150  md5Update(md5Context, ha2, osStrlen(ha2));
151  md5Final(md5Context, NULL);
152 
153  //Convert MD5 hash to hex string
155  //Debug message
156  TRACE_DEBUG(" response: %s\r\n", ha1);
157 
158  //Release MD5 context
159  osFreeMem(md5Context);
160 
161  //Check response
162  if(!osStrcasecmp(auth->response, ha1))
163  {
164  //Perform nonce verification
165  error = httpVerifyNonce(connection->serverContext, auth->nonce, auth->nc);
166 
167  //Valid nonce?
168  if(!error)
169  {
170  //Access to the resource is granted
171  status = TRUE;
172  }
173  else
174  {
175  //The client may wish to simply retry the request with a
176  //new encrypted response, without re-prompting the user
177  //for a new username and password
178  connection->response.auth.stale = TRUE;
179  }
180  }
181  }
182  }
183  }
184  }
185 #endif
186 
187  //Return TRUE is the password is valid, else FALSE
188  return status;
189 }
190 
191 
192 /**
193  * @brief Parse Authorization header field
194  * @param[in] connection Structure representing an HTTP connection
195  * @param[in] value Authorization field value
196  **/
197 
199 {
200  char_t *p;
201  char_t *token;
202 
203  //Retrieve the authentication scheme
204  token = osStrtok_r(value, " \t", &p);
205 
206  //Any parsing error?
207  if(token == NULL)
208  {
209  //Exit immediately
210  return;
211  }
212 #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED)
213  //Basic access authentication?
214  else if(!osStrcasecmp(token, "Basic"))
215  {
216  error_t error;
217  size_t n;
218  char_t *separator;
219 
220  //Use the relevant authentication scheme
221  connection->request.auth.mode = HTTP_AUTH_MODE_BASIC;
222  //Retrieve the credentials
223  token = osStrtok_r(NULL, " \t", &p);
224 
225  //Any parsing error?
226  if(token != NULL)
227  {
228  //Decrypt the Base64-encoded string
229  error = base64Decode(token, osStrlen(token), token, &n);
230 
231  //Successful decoding?
232  if(!error)
233  {
234  //Properly terminate the string
235  token[n] = '\0';
236  //Check whether a separator is present
237  separator = osStrchr(token, ':');
238 
239  //Separator found?
240  if(separator != NULL)
241  {
242  //Split the line
243  *separator = '\0';
244 
245  //Save user name
246  strSafeCopy(connection->request.auth.user,
248 
249  //Point to the password
250  token = separator + 1;
251  //Save password
252  connection->request.auth.password = token;
253  }
254  }
255  }
256 
257  //Debug message
258  TRACE_DEBUG("Authorization header:\r\n");
259  TRACE_DEBUG(" username: %s\r\n", connection->request.auth.user);
260  TRACE_DEBUG(" password: %s\r\n", connection->request.auth.password);
261  }
262 #endif
263 #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
264  //Digest access authentication?
265  else if(!osStrcasecmp(token, "Digest"))
266  {
267  size_t n;
268  char_t *separator;
269  char_t *name;
270 
271  //Use the relevant authentication scheme
272  connection->request.auth.mode = HTTP_AUTH_MODE_DIGEST;
273  //Get the first parameter
274  token = osStrtok_r(NULL, ",", &p);
275 
276  //Parse the Authorization header field
277  while(token != NULL)
278  {
279  //Check whether a separator is present
280  separator = osStrchr(token, '=');
281 
282  //Separator found?
283  if(separator != NULL)
284  {
285  //Split the string
286  *separator = '\0';
287 
288  //Get field name and value
290  value = strTrimWhitespace(separator + 1);
291 
292  //Retrieve the length of the value field
293  n = osStrlen(value);
294 
295  //Discard the surrounding quotes
296  if(n > 0 && value[n - 1] == '\"')
297  value[n - 1] = '\0';
298  if(value[0] == '\"')
299  value++;
300 
301  //Check parameter name
302  if(!osStrcasecmp(name, "username"))
303  {
304  //Save user name
305  strSafeCopy(connection->request.auth.user,
307  }
308  else if(!osStrcasecmp(name, "realm"))
309  {
310  //Save realm
311  connection->request.auth.realm = value;
312  }
313  else if(!osStrcasecmp(name, "nonce"))
314  {
315  //Save nonce parameter
316  connection->request.auth.nonce = value;
317  }
318  else if(!osStrcasecmp(name, "uri"))
319  {
320  //Save uri parameter
321  connection->request.auth.uri = value;
322  }
323  else if(!osStrcasecmp(name, "qop"))
324  {
325  //Save qop parameter
326  connection->request.auth.qop = value;
327  }
328  else if(!osStrcasecmp(name, "nc"))
329  {
330  //Save nc parameter
331  connection->request.auth.nc = value;
332  }
333  else if(!osStrcasecmp(name, "cnonce"))
334  {
335  //Save cnonce parameter
336  connection->request.auth.cnonce = value;
337  }
338  else if(!osStrcasecmp(name, "response"))
339  {
340  //Save response parameter
341  connection->request.auth.response = value;
342  }
343  else if(!osStrcasecmp(name, "opaque"))
344  {
345  //Save opaque parameter
346  connection->request.auth.opaque = value;
347  }
348 
349  //Get next parameter
350  token = osStrtok_r(NULL, ",", &p);
351  }
352  }
353 
354  //Debug message
355  TRACE_DEBUG("Authorization header:\r\n");
356  TRACE_DEBUG(" username: %s\r\n", connection->request.auth.user);
357  TRACE_DEBUG(" realm: %s\r\n", connection->request.auth.realm);
358  TRACE_DEBUG(" nonce: %s\r\n", connection->request.auth.nonce);
359  TRACE_DEBUG(" uri: %s\r\n", connection->request.auth.uri);
360  TRACE_DEBUG(" qop: %s\r\n", connection->request.auth.qop);
361  TRACE_DEBUG(" nc: %s\r\n", connection->request.auth.nc);
362  TRACE_DEBUG(" cnonce: %s\r\n", connection->request.auth.cnonce);
363  TRACE_DEBUG(" response: %s\r\n", connection->request.auth.response);
364  TRACE_DEBUG(" opaque: %s\r\n", connection->request.auth.opaque);
365  }
366 #endif
367  else
368  {
369  //The specified authentication scheme is not supported
370  return;
371  }
372 
373 #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
374  //The Authorization header has been found
375  connection->request.auth.found = TRUE;
376 
377  //Invoke user-defined callback, if any
378  if(connection->settings->authCallback != NULL)
379  {
380  //Check whether the access to the specified URI is authorized
381  connection->status = connection->settings->authCallback(connection,
382  connection->request.auth.user, connection->request.uri);
383  }
384  else
385  {
386  //Access to the specified URI is allowed
387  connection->status = HTTP_ACCESS_ALLOWED;
388  }
389 #endif
390 }
391 
392 
393 /**
394  * @brief Format WWW-Authenticate header field
395  * @param[in] connection Structure representing an HTTP connection
396  * @param[out] output Buffer where to format the header field
397  * @return Total length of the header field
398  **/
399 
400 size_t httpAddAuthenticateField(HttpConnection *connection, char_t *output)
401 {
402  size_t n;
403 
404 #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED)
405  //Basic authentication scheme?
406  if(connection->response.auth.mode == HTTP_AUTH_MODE_BASIC)
407  {
408  //Set WWW-Authenticate field
409  n = osSprintf(output, "WWW-Authenticate: Basic realm=\"Protected Area\"\r\n");
410  }
411  else
412 #endif
413 #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
414  //Digest authentication scheme?
415  if(connection->response.auth.mode == HTTP_AUTH_MODE_DIGEST)
416  {
417  error_t error;
418  size_t k;
419  uint8_t opaque[16];
420 
421  //Set WWW-Authenticate field
422  n = osSprintf(output, "WWW-Authenticate: Digest ");
423  n += osSprintf(output + n, "realm=\"Protected Area\", ");
424  n += osSprintf(output + n, "qop=\"auth\", ");
425  n += osSprintf(output + n, "nonce=\"");
426 
427  //The nonce is a server-specified data string which should be uniquely
428  //generated each time a 401 response is made
429  error = httpGenerateNonce(connection->serverContext, output + n, &k);
430  //Any error to report?
431  if(error)
432  return error;
433 
434  //Advance pointer
435  n += k;
436  //Properly terminate the nonce string
437  n += osSprintf(output + n, "\", ");
438 
439  //Format opaque parameter
440  n += osSprintf(output + n, "opaque=\"");
441 
442  //Generate a random value
443  if(connection->settings->randCallback != NULL)
444  {
445  error = connection->settings->randCallback(opaque, 16);
446  }
447  else
448  {
449  error = ERROR_FAILURE;
450  }
451 
452  //Random number generation failed?
453  if(error)
454  return error;
455 
456  //Convert the byte array to hex string
457  httpConvertArrayToHexString(opaque, 16, output + n);
458 
459  //Advance pointer
460  n += 32;
461  //Properly terminate the opaque string
462  n += osSprintf(output + n, "\"");
463 
464  //The STALE flag indicates that the previous request from the client
465  //was rejected because the nonce value was stale
466  if(connection->response.auth.stale)
467  {
468  n += osSprintf(output + n, ", stale=TRUE");
469  }
470 
471  //Properly terminate the WWW-Authenticate field
472  n += osSprintf(output + n, "\r\n");
473  }
474  else
475 #endif
476  //Unknown authentication scheme?
477  {
478  //No need to add the WWW-Authenticate header field
479  n = 0;
480  }
481 
482  //Return the total length of the WWW-Authenticate header field
483  return n;
484 }
485 
486 
487 /**
488  * @brief Nonce generation
489  * @param[in] context Pointer to the HTTP server context
490  * @param[in] output NULL-terminated string containing the nonce
491  * @param[in] length NULL-terminated string containing the nonce count
492  * @return Error code
493  **/
494 
496  char_t *output, size_t *length)
497 {
498 #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
499  error_t error;
500  uint_t i;
501  systime_t time;
502  HttpNonceCacheEntry *entry;
503  HttpNonceCacheEntry *oldestEntry;
504  uint8_t nonce[HTTP_SERVER_NONCE_SIZE];
505 
506  //Acquire exclusive access to the nonce cache
507  osAcquireMutex(&context->nonceCacheMutex);
508 
509  //Get current time
510  time = osGetSystemTime();
511 
512  //Keep track of the oldest entry
513  oldestEntry = &context->nonceCache[0];
514 
515  //Loop through nonce cache entries
516  for(i = 0; i < HTTP_SERVER_NONCE_CACHE_SIZE; i++)
517  {
518  //Point to the current entry
519  entry = &context->nonceCache[i];
520 
521  //Check whether the entry is currently in use or not
522  if(!entry->count)
523  break;
524 
525  //Keep track of the oldest entry in the table
526  if((time - entry->timestamp) > (time - oldestEntry->timestamp))
527  {
528  oldestEntry = entry;
529  }
530  }
531 
532  //The oldest entry is removed whenever the table runs out of space
534  entry = oldestEntry;
535 
536  //Generate a new nonce
537  if(context->settings.randCallback != NULL)
538  {
539  error = context->settings.randCallback(nonce, HTTP_SERVER_NONCE_SIZE);
540  }
541  else
542  {
543  error = ERROR_FAILURE;
544  }
545 
546  //Check status code
547  if(!error)
548  {
549  //Convert the byte array to hex string
551  //Clear nonce count
552  entry->count = 1;
553  //Save the time at which the nonce was generated
554  entry->timestamp = osGetSystemTime();
555 
556  //Copy the nonce to the output buffer
557  osStrcpy(output, entry->nonce);
558  //Return the length of the nonce excluding the NULL character
560  }
561  else
562  {
563  //Random number generation failed
564  osMemset(entry, 0, sizeof(HttpNonceCacheEntry));
565  }
566 
567  //Release exclusive access to the nonce cache
568  osReleaseMutex(&context->nonceCacheMutex);
569  //Return status code
570  return error;
571 
572 #else
573  //Not implemented
574  return ERROR_NOT_IMPLEMENTED;
575 #endif
576 }
577 
578 
579 /**
580  * @brief Nonce verification
581  * @param[in] context Pointer to the HTTP server context
582  * @param[in] nonce NULL-terminated string containing the nonce
583  * @param[in] nc NULL-terminated string containing the nonce count
584  * @return Error code
585  **/
586 
588  const char_t *nonce, const char_t *nc)
589 {
590 #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
591  error_t error;
592  uint_t i;
593  uint32_t count;
594  systime_t time;
595  HttpNonceCacheEntry *entry;
596 
597  //Check parameters
598  if(nonce == NULL || nc == NULL)
600 
601  //Convert the nonce count to integer
602  count = osStrtoul(nc, NULL, 16);
603  //Get current time
604  time = osGetSystemTime();
605 
606  //Acquire exclusive access to the nonce cache
607  osAcquireMutex(&context->nonceCacheMutex);
608 
609  //Loop through nonce cache entries
610  for(i = 0; i < HTTP_SERVER_NONCE_CACHE_SIZE; i++)
611  {
612  //Point to the current entry
613  entry = &context->nonceCache[i];
614 
615  //Check nonce value
616  if(!osStrcasecmp(entry->nonce, nonce))
617  {
618  //Make sure the nonce timestamp has not expired
619  if((time - entry->timestamp) < HTTP_SERVER_NONCE_LIFETIME)
620  {
621  //Check nonce count to prevent replay attacks
622  if(count >= entry->count)
623  {
624  //Update nonce count to the next expected value
625  entry->count = count + 1;
626  //We are done
627  break;
628  }
629  }
630  }
631  }
632 
633  //Check whether the nonce is valid
635  {
636  error = NO_ERROR;
637  }
638  else
639  {
640  error = ERROR_NOT_FOUND;
641  }
642 
643  //Release exclusive access to the nonce cache
644  osReleaseMutex(&context->nonceCacheMutex);
645  //Return status code
646  return error;
647 
648 #else
649  //Not implemented
650  return ERROR_NOT_IMPLEMENTED;
651 #endif
652 }
653 
654 #endif
void md5Update(Md5Context *context, const void *data, size_t length)
Update the MD5 context with a portion of the message being hashed.
error_t base64Decode(const char_t *input, size_t inputLen, void *output, size_t *outputLen)
Base64 decoding algorithm.
Definition: base64.c:258
uint8_t token[]
Definition: coap_common.h:181
unsigned int uint_t
Definition: compiler_port.h:50
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint8_t n
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
HttpAuthMode
HTTP authentication schemes.
Definition: http_common.h:72
@ HTTP_AUTH_MODE_DIGEST
Definition: http_common.h:75
@ HTTP_AUTH_MODE_BASIC
Definition: http_common.h:74
HTTP server (HyperText Transfer Protocol)
@ HTTP_ACCESS_ALLOWED
Definition: http_server.h:347
#define HttpConnection
Definition: http_server.h:332
#define HTTP_SERVER_NONCE_LIFETIME
Definition: http_server.h:258
#define HTTP_SERVER_USERNAME_MAX_LEN
Definition: http_server.h:223
#define HttpServerContext
Definition: http_server.h:328
#define HTTP_SERVER_NONCE_SIZE
Definition: http_server.h:265
#define HTTP_SERVER_NONCE_CACHE_SIZE
Definition: http_server.h:251
error_t httpGenerateNonce(HttpServerContext *context, char_t *output, size_t *length)
Nonce generation.
void httpParseAuthorizationField(HttpConnection *connection, char_t *value)
Parse Authorization header field.
size_t httpAddAuthenticateField(HttpConnection *connection, char_t *output)
Format WWW-Authenticate header field.
bool_t httpCheckPassword(HttpConnection *connection, const char_t *password, HttpAuthMode mode)
Password verification.
error_t httpVerifyNonce(HttpServerContext *context, const char_t *nonce, const char_t *nc)
Nonce verification.
HTTP authentication.
void httpConvertArrayToHexString(const uint8_t *input, size_t inputLen, char_t *output)
Convert byte array to hex string.
HTTP server (miscellaneous functions)
#define MD5_DIGEST_SIZE
Definition: md5.h:45
void md5Init(Md5Context *context)
Initialize MD5 message digest context.
void md5Final(Md5Context *context, uint8_t *digest)
Finish the MD5 message digest.
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osStrcmp(s1, s2)
Definition: os_port.h:171
#define osStrcasecmp(s1, s2)
Definition: os_port.h:183
#define osStrchr(s, c)
Definition: os_port.h:195
#define osStrlen(s)
Definition: os_port.h:165
#define osSprintf(dest,...)
Definition: os_port.h:231
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define osStrcpy(s1, s2)
Definition: os_port.h:207
#define osStrtoul(s, endptr, base)
Definition: os_port.h:249
#define osStrtok_r(s, delim, last)
Definition: os_port.h:225
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
char_t name[]
error_t strSafeCopy(char_t *dest, const char_t *src, size_t destSize)
Copy string.
Definition: str.c:164
char_t * strTrimWhitespace(char_t *s)
Removes all leading and trailing whitespace from a string.
Definition: str.c:78
String manipulation helper functions.
Authorization header.
Definition: http_server.h:443
HttpAuthMode mode
Authentication scheme.
Definition: http_server.h:445
const char_t * nonce
Server nonce.
Definition: http_server.h:452
const char_t * uri
Digest URI.
Definition: http_server.h:453
const char_t * password
Password.
Definition: http_server.h:448
const char_t * cnonce
Client nonce.
Definition: http_server.h:456
const char_t * response
Definition: http_server.h:457
const char_t * nc
Nonce count.
Definition: http_server.h:455
bool_t found
The Authorization header has been found.
Definition: http_server.h:444
char_t user[HTTP_SERVER_USERNAME_MAX_LEN+1]
User name.
Definition: http_server.h:446
const char_t * realm
Definition: http_server.h:451
const char_t * qop
Definition: http_server.h:454
Nonce cache entry.
Definition: http_server.h:577
systime_t timestamp
Time stamp to manage entry lifetime.
Definition: http_server.h:580
char_t nonce[HTTP_SERVER_NONCE_SIZE *2+1]
Nonce.
Definition: http_server.h:578
uint32_t count
Nonce count.
Definition: http_server.h:579
MD5 algorithm context.
Definition: md5.h:62
uint8_t digest[16]
Definition: md5.h:66
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369