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