GNU libmicrohttpd  0.9.72
digestauth.c File Reference

Implements HTTP digest authentication. More...

#include "platform.h"
#include "mhd_limits.h"
#include "internal.h"
#include "md5.h"
#include "sha256.h"
#include "mhd_mono_clock.h"
#include "mhd_str.h"
#include "mhd_compat.h"
#include "mhd_assert.h"
Include dependency graph for digestauth.c:

Go to the source code of this file.

Macros

#define TIMESTAMP_BIN_SIZE   4
 
#define NONCE_STD_LEN(digest_size)    ((digest_size) * 2 + TIMESTAMP_BIN_SIZE * 2)
 
#define MAX_DIGEST   SHA256_DIGEST_SIZE
 
#define VLA_ARRAY_LEN_DIGEST(n)   (n)
 
#define VLA_CHECK_LEN_DIGEST(n)
 
#define _BASE   "Digest "
 
#define MAX_USERNAME_LENGTH   128
 
#define MAX_REALM_LENGTH   256
 
#define MAX_AUTH_RESPONSE_LENGTH   256
 
#define SETUP_DA(algo, da)
 

Functions

static void cvthex (const unsigned char *bin, size_t len, char *hex)
 
static void digest_calc_ha1_from_digest (const char *alg, struct DigestAlgorithm *da, const uint8_t *digest, const char *nonce, const char *cnonce)
 
static void digest_calc_ha1_from_user (const char *alg, const char *username, const char *realm, const char *password, const char *nonce, const char *cnonce, struct DigestAlgorithm *da)
 
static void digest_calc_response (const char *ha1, const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, const char *hentity, struct DigestAlgorithm *da)
 
static size_t lookup_sub_value (char *dest, size_t size, const char *data, const char *key)
 
static enum MHD_Result check_nonce_nc (struct MHD_Connection *connection, const char *nonce, uint64_t nc)
 
_MHD_EXTERN char * MHD_digest_auth_get_username (struct MHD_Connection *connection)
 
static void calculate_nonce (uint32_t nonce_time, const char *method, const char *rnd, size_t rnd_size, const char *uri, const char *realm, struct DigestAlgorithm *da, char *nonce)
 
static enum MHD_Result test_header (struct MHD_Connection *connection, const char *key, size_t key_size, const char *value, size_t value_size, enum MHD_ValueKind kind)
 
static enum MHD_Result check_argument_match (struct MHD_Connection *connection, const char *args)
 
static int digest_auth_check_all (struct MHD_Connection *connection, struct DigestAlgorithm *da, const char *realm, const char *username, const char *password, const uint8_t *digest, unsigned int nonce_timeout)
 
_MHD_EXTERN int MHD_digest_auth_check (struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
 
_MHD_EXTERN int MHD_digest_auth_check2 (struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
 
_MHD_EXTERN int MHD_digest_auth_check_digest2 (struct MHD_Connection *connection, const char *realm, const char *username, const uint8_t *digest, size_t digest_size, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
 
_MHD_EXTERN int MHD_digest_auth_check_digest (struct MHD_Connection *connection, const char *realm, const char *username, const uint8_t digest[MHD_MD5_DIGEST_SIZE], unsigned int nonce_timeout)
 
_MHD_EXTERN enum MHD_Result MHD_queue_auth_fail_response2 (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale, enum MHD_DigestAuthAlgorithm algo)
 
_MHD_EXTERN enum MHD_Result MHD_queue_auth_fail_response (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
 

Detailed Description

Implements HTTP digest authentication.

Author
Amr Ali
Matthieu Speder
Christian Grothoff (RFC 7616 support)

Definition in file digestauth.c.

Macro Definition Documentation

◆ _BASE

#define _BASE   "Digest "

Beginning string for any valid Digest authentication header.

Definition at line 94 of file digestauth.c.

◆ MAX_AUTH_RESPONSE_LENGTH

#define MAX_AUTH_RESPONSE_LENGTH   256

Maximum length of the response in digest authentication.

Definition at line 109 of file digestauth.c.

◆ MAX_DIGEST

#define MAX_DIGEST   SHA256_DIGEST_SIZE

Maximum size of any digest hash supported by MHD. (SHA-256 > MD5).

Definition at line 61 of file digestauth.c.

◆ MAX_REALM_LENGTH

#define MAX_REALM_LENGTH   256

Maximum length of a realm for digest authentication.

Definition at line 104 of file digestauth.c.

◆ MAX_USERNAME_LENGTH

#define MAX_USERNAME_LENGTH   128

Maximum length of a username for digest authentication.

Definition at line 99 of file digestauth.c.

◆ NONCE_STD_LEN

#define NONCE_STD_LEN (   digest_size)     ((digest_size) * 2 + TIMESTAMP_BIN_SIZE * 2)

Standard server nonce length, not including terminating null,

Parameters
digest_sizedigest size

Definition at line 53 of file digestauth.c.

◆ SETUP_DA

#define SETUP_DA (   algo,
  da 
)

Setup digest authentication data structures (on the stack, hence must be done inline!). Initializes a "struct DigestAlgorithm da" for algorithm algo.

Parameters
algodigest algorithm to provide
dadata structure to setup

Definition at line 1185 of file digestauth.c.

◆ TIMESTAMP_BIN_SIZE

#define TIMESTAMP_BIN_SIZE   4

32 bit value is 4 bytes

Definition at line 46 of file digestauth.c.

◆ VLA_ARRAY_LEN_DIGEST

#define VLA_ARRAY_LEN_DIGEST (   n)    (n)

Macro to avoid using VLAs if the compiler does not support them. Return n.

Parameters
nlength of the digest to be used for a VLA

Definition at line 80 of file digestauth.c.

◆ VLA_CHECK_LEN_DIGEST

#define VLA_CHECK_LEN_DIGEST (   n)
Value:
do { if ((n) > MAX_DIGEST) mhd_panic ( \
mhd_panic_cls, __FILE__, __LINE__, \
"VLA too big.\n"); } while (0)
#define MAX_DIGEST
Definition: digestauth.c:61
MHD_PanicCallback mhd_panic
Definition: panic.c:31
void * mhd_panic_cls
Definition: panic.c:36

Check that n is below #MAX_NONCE

Definition at line 86 of file digestauth.c.

Function Documentation

◆ calculate_nonce()

static void calculate_nonce ( uint32_t  nonce_time,
const char *  method,
const char *  rnd,
size_t  rnd_size,
const char *  uri,
const char *  realm,
struct DigestAlgorithm *  da,
char *  nonce 
)
static

Calculate the server nonce so that it mitigates replay attacks The current format of the nonce is ... H(timestamp ":" method ":" random ":" uri ":" realm) + Hex(timestamp)

Parameters
nonce_timeThe amount of time in seconds for a nonce to be invalid
methodHTTP method
rndA pointer to a character array for the random seed
rnd_sizeThe size of the random seed array rnd
uriHTTP URI (in MHD, without the arguments ("?k=v")
realmA string of characters that describes the realm of auth.
dadigest algorithm to use
[out]nonceA pointer to a character array for the nonce to put in, must provide NONCE_STD_LEN(da->digest_size)+1 bytes

Definition at line 674 of file digestauth.c.

References cvthex(), MHD_NonceNc::nonce, TIMESTAMP_BIN_SIZE, VLA_ARRAY_LEN_DIGEST, and VLA_CHECK_LEN_DIGEST.

Referenced by digest_auth_check_all().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_argument_match()

static enum MHD_Result check_argument_match ( struct MHD_Connection connection,
const char *  args 
)
static

Check that the arguments given by the client as part of the authentication header match the arguments we got as part of the HTTP request URI.

Parameters
connectionconnections with headers to compare against
argsargument URI string (after "?" in URI)
Returns
MHD_YES if the arguments match, MHD_NO if not

Definition at line 674 of file digestauth.c.

Referenced by digest_auth_check_all().

Here is the caller graph for this function:

◆ check_nonce_nc()

static enum MHD_Result check_nonce_nc ( struct MHD_Connection connection,
const char *  nonce,
uint64_t  nc 
)
static

Check nonce-nc map array with either new nonce counter or a whole new nonce.

Parameters
connectionThe MHD connection structure
nonceA pointer that referenced a zero-terminated array of nonce
ncThe nonce counter, zero to add the nonce to the array
Returns
MHD_YES if successful, MHD_NO if invalid (or we have no NC array)

Definition at line 433 of file digestauth.c.

References data, MHD_str_equal_caseless_n_(), and NULL.

Referenced by digest_auth_check_all().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cvthex()

static void cvthex ( const unsigned char *  bin,
size_t  len,
char *  hex 
)
static

convert bin to hex

Parameters
binbinary data
lennumber of bytes in bin
hexpointer to len*2+1 bytes

Definition at line 179 of file digestauth.c.

Referenced by calculate_nonce(), digest_calc_ha1_from_digest(), and digest_calc_response().

Here is the caller graph for this function:

◆ digest_calc_ha1_from_digest()

static void digest_calc_ha1_from_digest ( const char *  alg,
struct DigestAlgorithm *  da,
const uint8_t *  digest,
const char *  nonce,
const char *  cnonce 
)
static

calculate H(A1) from given hash as per RFC2617 spec and store the * result in 'sessionkey'.

Parameters
algThe hash algorithm used, can be "md5" or "md5-sess" or "sha-256" or "sha-256-sess" Note that the rest of the code does not support the the "-sess" variants!
[in,out]dadigest implementation, must match alg; the da->sessionkey will be initialized to the digest in HEX
digestAn ‘unsigned char *’ pointer to the binary MD5 sum for the precalculated hash value "username:realm:password" of MHD_MD5_DIGEST_SIZE or #MHD_SHA256_DIGEST_SIZE bytes
nonceA ‘char *’ pointer to the nonce value
cnonceA ‘char *’ pointer to the cnonce value

Definition at line 213 of file digestauth.c.

References cvthex(), MHD_MD5_DIGEST_SIZE, MHD_str_equal_caseless_(), VLA_ARRAY_LEN_DIGEST, and VLA_CHECK_LEN_DIGEST.

Referenced by digest_auth_check_all(), and digest_calc_ha1_from_user().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ digest_calc_ha1_from_user()

static void digest_calc_ha1_from_user ( const char *  alg,
const char *  username,
const char *  realm,
const char *  password,
const char *  nonce,
const char *  cnonce,
struct DigestAlgorithm *  da 
)
static

calculate H(A1) from username, realm and password as per RFC2617 spec and store the result in 'sessionkey'.

Parameters
algThe hash algorithm used, can be "md5" or "md5-sess" or "sha-256" or "sha-256-sess"
usernameA ‘char *’ pointer to the username value
realmA ‘char *’ pointer to the realm value
passwordA ‘char *’ pointer to the password value
nonceA ‘char *’ pointer to the nonce value
cnonceA ‘char *’ pointer to the cnonce value
[in,out]dadigest algorithm to use, and where to write the sessionkey to

Definition at line 273 of file digestauth.c.

References digest_calc_ha1_from_digest(), VLA_ARRAY_LEN_DIGEST, and VLA_CHECK_LEN_DIGEST.

Referenced by digest_auth_check_all().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ digest_calc_response()

static void digest_calc_response ( const char *  ha1,
const char *  nonce,
const char *  noncecount,
const char *  cnonce,
const char *  qop,
const char *  method,
const char *  uri,
const char *  hentity,
struct DigestAlgorithm *  da 
)
static

Calculate request-digest/response-digest as per RFC2617 / RFC7616 spec.

Parameters
ha1H(A1), twice the da->digest_size + 1 bytes (0-terminated), MUST NOT be aliased with da->sessionkey!
noncenonce from server
noncecount8 hex digits
cnonceclient nonce
qopqop-value: "", "auth" or "auth-int" (NOTE: only 'auth' is supported today.)
methodmethod from request
urirequested URL
hentityH(entity body) if qop="auth-int"
[in,out]dadigest algorithm to use, also we write da->sessionkey (set to response request-digest or response-digest)

Definition at line 327 of file digestauth.c.

References cvthex(), NULL, VLA_ARRAY_LEN_DIGEST, and VLA_CHECK_LEN_DIGEST.

Referenced by digest_auth_check_all().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_sub_value()

static size_t lookup_sub_value ( char *  dest,
size_t  size,
const char *  data,
const char *  key 
)
static

Lookup subvalue off of the HTTP Authorization header.

A description of the input format for 'data' is at http://en.wikipedia.org/wiki/Digest_access_authentication

Parameters
destwhere to store the result (possibly truncated if the buffer is not big enough).
sizesize of dest
datapointer to the Authorization header
keykey to look up in data
Returns
size of the located value, 0 if otherwise

Definition at line 433 of file digestauth.c.

Referenced by digest_auth_check_all(), and MHD_digest_auth_get_username().

Here is the caller graph for this function:

◆ test_header()

static enum MHD_Result test_header ( struct MHD_Connection connection,
const char *  key,
size_t  key_size,
const char *  value,
size_t  value_size,
enum MHD_ValueKind  kind 
)
static

Test if the given key-value pair is in the headers for the given connection.

Parameters
connectionthe connection
keythe key
key_sizenumber of bytes in key
valuethe value, can be NULL
value_sizenumber of bytes in value
kindtype of the header
Returns
MHD_YES if the key-value pair is in the headers, MHD_NO if not

Definition at line 674 of file digestauth.c.