authentication.inc (34626B)
1 @cindex authentication 2 @noindent 3 MHD supports three types of client authentication: 4 5 @itemize 6 7 @item Basic authentication uses a simple authentication method that 8 transmits username and password in simple base64 encoding. Username 9 and password are exchanged in cleartext between the client and the 10 server, so this method must only be used for non-sensitive content or 11 when the session is protected with TLS. When using basic 12 authentication MHD will have access to the clear password, possibly 13 allowing the application to create a chained authentication toward an 14 external authentication server. 15 16 @item Digest authentication uses a one-way authentication method based on 17 cryptographic hash algorithms. Only the hash is transmitted over the 18 network, hence protecting the user's password. A nonce is used to 19 prevent replay attacks. This method is appropriate for general use, 20 especially when TLS is not used to encrypt the transmission. 21 22 @item Client certificate authentication uses a X.509 certificate from the 23 client. This is the strongest authentication mechanism and also 24 requires the use of TLS. Client certificate authentication can be used 25 simultaneously with Basic or Digest Authentication in order to provide 26 a two levels authentication (like, for instance, separate machine and 27 user authentication). 28 29 @end itemize 30 31 @menu 32 * libmicrohttpd-bauth basic:: Using Basic Authentication. 33 * libmicrohttpd-bauth example:: Example for Basic Authentication. 34 * libmicrohttpd-dauth digest:: Using Digest Authentication. 35 @c * libmicrohttpd-dauth example:: Example for Digest Authentication. 36 @c * libmicrohttpd-dauth token:: Using Token Authentication. 37 @c FIXME * libmicrohttpd-dauth tls:: Using TLS Client Authentication. 38 @end menu 39 40 41 @node libmicrohttpd-bauth basic 42 @section Using Basic Authentication 43 @cindex basic authentication 44 45 @ref{MHD_LIB_INFO_FIXED_HAS_AUTH_BASIC,,@code{MHD_LIB_INFO_FIXED_HAS_AUTH_BASIC}} 46 can be used to detect if the MHD build includes support for HTTP basic 47 authorization. 48 49 To use HTTP basic authentication, the HTTP server must first return a 50 response with status @code{MHD_HTTP_STATUS_UNAUTHORIZED} asking the 51 client to authenticate. This is usually done @emph{after} checking 52 whether the client did already authenticate, which we will look at 53 later in this section. To challenge a client to authenticate using 54 HTTP basic authentication, MHD offers the 55 @code{MHD_response_add_auth_basic_challenge()} function which 56 @emph{modifies} an existing response, adding HTTP headers asking the 57 client to authenticate. 58 59 @deftypefun {enum MHD_StatusCode} MHD_response_add_auth_basic_challenge (struct MHD_Response *response, const char *realm, enum MHD_Bool prefer_utf8) 60 61 Adds a basic authentication "challenge" to the response. The 62 @var{response} must use @code{MHD_HTTP_STATUS_UNAUTHORIZED} for its 63 HTTP status code. 64 65 If access to any resource should be limited to specific users, 66 authenticated by basic authentication mechanism, and the request for 67 this resource does not have basic authentication information 68 (see @ref{MHD_AuthBasicCreds,,@code{MHD_AuthBasicCreds}}), then a 69 response with a basic authentication "challenge" should be sent by 70 extending an error response using this function. This works as an 71 indication that basic authentication should be used for the access. 72 73 See RFC 7617, section 2 for details. 74 75 @table @var 76 @item response 77 the response to update; should contain the "access denied" body; note: this 78 function sets the "WWW Authenticate" header and thus the caller 79 should not set this header; the response must have 80 @code{MHD_HTTP_STATUS_UNAUTHORIZED} HTTP status code; passing 81 @code{NULL} is tolerated, in which case the result will be 82 @code{MHD_SC_RESP_POINTER_NULL} 83 84 @item realm 85 the realm presented to the client 86 87 @item prefer_utf8 88 if not set to @code{MHD_NO} the parameter 'charset="UTF-8"' 89 will be added, indicating for client that UTF-8 encoding is preferred 90 91 @end table 92 93 The function returns 94 @itemize 95 @item @code{MHD_SC_OK} if it succeeded 96 @item @code{MHD_SC_TOO_LATE} if the response has been already "frozen" (used to create an action), 97 @item @code{MHD_SC_RESP_HEADERS_CONFLICT} if a Basic Authentication "challenge" was already added, 98 @item @code{MHD_SC_RESP_POINTER_NULL} if @var{response} was set to @code{NULL}, 99 @item @code{MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE} is response status code is wrong, 100 @item @code{MHD_SC_RESP_HEADER_VALUE_INVALID} if realm is zero-length or has CR or LF characters, 101 @item @code{MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED} if memory allocation failed, 102 @item or possibly other error codes (that could be defined in the future) on failure. 103 @end itemize 104 105 @end deftypefun 106 107 @c FIXME: current header ONLY exports this API (and the _p/_a variants) if static inline is supported; that's not nice, API changes based on compiler. 108 @c FIXME: also not convinced this API is even all that useful. Maybe remove? 109 MHD provides a convenience API that adds the basic authentication challenge 110 to response and turns it into the action to be returned 111 from the @ref{MHD_RequestCallback,,@code{MHD_RequestCallback}}. 112 113 @deftypefun {const struct MHD_Action *} MHD_action_basic_auth_challenge (struct MHD_Request *request, const char *realm, enum MHD_Bool prefer_utf8, struct MHD_Response *response, enum MHD_Bool abort_if_failed) 114 115 Creates an action to reply with a basic authentication "challenge". 116 The response must use @code{MHD_HTTP_STATUS_UNAUTHORIZED} for its HTTP 117 status code. 118 119 If access to any resource should be limited to specific users, 120 authenticated by basic authentication mechanism, and the request for 121 this resource does not have basic authentication information 122 (see @ref{MHD_AuthBasicCreds,,@code{MHD_AuthBasicCreds}}), then a response with a basic 123 authentication "challenge" should be sent by extending an error 124 response using this function. This works as an indication that basic 125 authentication should be used for the access. 126 127 See RFC 7617, section-2 for details. 128 129 @table @var 130 @item request 131 the client request to generate the action for 132 133 @item realm 134 the realm presented to the client 135 136 @item response 137 the reply to send; should contain the "access denied" body; note: this 138 function sets the "WWW Authenticate" header and thus the caller 139 should not set this header; the response must have 140 @code{MHD_HTTP_STATUS_UNAUTHORIZED} HTTP status code; passing 141 @code{NULL} is tolerated, in which case the result will be 142 @code{MHD_SC_RESP_POINTER_NULL} 143 144 @item prefer_utf8 145 if not set to @code{MHD_NO} the parameter 'charset="UTF-8"' 146 will be added, indicating for client that UTF-8 encoding is preferred 147 148 @item abort_if_failed 149 if set to @code{MHD_NO} the response will be returned even if 150 MHD failed to add Basic Authentication "challenge", 151 if set to @code{MHD_YES} the HTTP request will be aborted 152 if the "challenge" could not be added. 153 @end table 154 @end deftypefun 155 156 If the client has supplied an HTTP basic authorization header, the 157 application can obtain the credentials using request introspection. 158 @ref{MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS,,@code{MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS}} 159 can be used to obtain the credentials as a @code{struct 160 MHD_AuthBasicCreds}. 161 162 @anchor{MHD_AuthBasicCreds} 163 @deftp {C Struct} MHD_AuthBasicCreds username password 164 165 Information decoded from a client's header with basic authentication data. 166 @table @var 167 @item @code{struct MHD_String} username 168 The username; 169 170 @item @code{struct MHD_StringNullable} password 171 The password, string pointer may be @code{NULL} if 172 the password is not properly encoded in the 173 transmission from the client. 174 @end table 175 @end deftp 176 177 @node libmicrohttpd-bauth example 178 @section Example for Basic Authentication 179 @cindex basic authentication 180 181 182 @example 183 @verbatiminclude examples/basic-authentication.c 184 @end example 185 186 187 188 @node libmicrohttpd-dauth digest 189 @section Using Digest Authentication 190 @cindex digest authentication 191 192 @ref{MHD_LIB_INFO_FIXED_HAS_AUTH_DIGEST,,@code{MHD_LIB_INFO_FIXED_HAS_AUTH_DIGEST}} 193 can be used to detect if the MHD build includes support for HTTP digest 194 authorization. 195 196 197 To use HTTP digest authentication, the HTTP server must first return a 198 response with status @code{MHD_HTTP_STATUS_UNAUTHORIZED} asking the 199 client to authenticate. This is usually done @emph{after} checking 200 whether the client did already authenticate, which we will look at 201 later in this section. To challenge a client to authenticate using 202 HTTP digest authentication, MHD offers the 203 @code{MHD_response_add_auth_digest_challenge()} function which 204 @emph{modifies} an existing response, adding HTTP headers asking the 205 client to authenticate. 206 MHD supports various features of HTTP digest authentication, including 207 various hash algorithms and levels of quality of protection (qop) which 208 must be specified by the application when creating the challenge. 209 210 @anchor{MHD_response_add_auth_digest_challenge} 211 @deftypefun {enum MHD_StatusCode} MHD_response_add_auth_digest_challenge (struct MHD_Response *response, const char *realm, const char *opaque, const char *domain, enum MHD_Bool indicate_stale, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo malgo, enum MHD_Bool userhash_support, enum MHD_Bool prefer_utf8) 212 213 Adds a digest authentication "challenge" to the response. 214 The @var{response} must use @code{MHD_HTTP_STATUS_UNAUTHORIZED} for its HTTP status code. 215 216 @cindex qop 217 If @var{mqop} allows both RFC 2069 (@code{MHD_DIGEST_AUTH_QOP_NONE}) 218 and other QOP values, then the "challenge" is formed like if 219 @code{MHD_DIGEST_AUTH_QOP_NONE} bit was not set, because such 220 a "challenge" should be backwards-compatible with RFC 2069. 221 222 If @var{mqop} allows only @code{MHD_DIGEST_AUTH_MULT_QOP_NONE}, 223 then the response is formed in strict accordance with RFC 2069 224 (no 'qop', no 'userhash', no 'charset'). 225 For better compatibility with clients, it is recommended (but 226 not required) to set @var{domain} to @code{NULL} in this mode. 227 228 New nonces are generated each time when the resulting response is 229 used. 230 231 See RFC 7616, section 3.3 for details. 232 233 @table @var 234 235 @item response 236 the response to update; should contain the "access denied" 237 body; note: this function sets the "WWW Authenticate" header and 238 the caller should not set this header; 239 the response must have a @code{MHD_HTTP_STATUS_UNAUTHORIZED} HTTP status 240 code; a value of @code{NULL} is tolerated (the result will then be 241 @code{MHD_SC_RESP_POINTER_NULL}); 242 243 @item realm 244 the realm presented to the client; 245 246 @item opaque 247 the string for the opaque value, can be @code{NULL}, but @code{NULL} is 248 not recommended for better compatibility with clients; 249 the recommended format are string using hex or Base64 encoding; 250 251 @item domain 252 an optional space-separated list of URIs for which the 253 same authorisation could be used, URIs can be in form 254 "path-absolute" (the path for the same host with initial slash) 255 or in form "absolute-URI" (the full path with protocol), in 256 any case client may assume that URI is in the same "protection 257 space" if it starts with any of values specified here; 258 could be @code{NULL} (clients typically assume that the same 259 credentials could be used for any URI on the same host); 260 this list provides information for the client only and does 261 not actually restrict anything on the server side; 262 263 @item indicate_stale 264 if set to @code{MHD_YES} then an indication of a stale nonce 265 having been used in the client's request is indicated by adding 266 ``stale=true'' to the authentication header; this 267 instructs the client to retry immediately with the new 268 nonce and the same credentials, without asking the user 269 for the new password; 270 271 @item mqop 272 the quality of protection to use (see @ref{MHD_DigestAuthMultiQOP,,@code{MHD_DigestAuthMultiQOP}}); 273 274 @item algo 275 digest algorithm to use; if several algorithms are allowed 276 then one challenge for each allowed algorithm is added to the 277 response (@xref{MHD_DigestAuthMultiAlgo}); 278 279 @item userhash_support 280 if set to @code{MHD_YES} then support of the ``userhash'' variant is 281 indicated, allowing the client to provide @code{hash("username:realm")} 282 instead of the username in clear text; 283 note that clients are @emph{allowed} to provide the username 284 in cleartext even if this parameter set to @code{MHD_YES}; 285 when userhash is used, the application must be ready to 286 identify users by provided userhash value instead of 287 the plaintext username; see @ref{MHD_digest_auth_calc_userhash} 288 @c and @ref{MHD_digest_auth_calc_userhash_hex} 289 290 @item prefer_utf8 291 if set to @code{MHD_YES}, the parameter ``charset=UTF-8'' is 292 added, indicating to the client that UTF-8 encoding for 293 the username is preferred 294 @end table 295 296 The function returns 297 @itemize 298 @item @code{MHD_SC_OK} if it succeeded 299 @item @code{MHD_SC_TOO_LATE} if the response has been already "frozen" (used to create an action), 300 @item @code{MHD_SC_RESP_HEADERS_CONFLICT} if a Basic Authentication "challenge" was already added, 301 @item @code{MHD_SC_RESP_POINTER_NULL} if @var{response} was set to @code{NULL}, 302 @item @code{MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE} is response status code is wrong, 303 @item @code{MHD_SC_RESP_HEADER_VALUE_INVALID} if realm is zero-length or has CR or LF characters, 304 @item @code{MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED} if memory allocation failed, 305 @item or possibly other error codes (that could be defined in the future) on failure. 306 @end itemize 307 @end deftypefun 308 309 310 @cindex qop 311 @anchor{MHD_DigestAuthMultiQOP} 312 @deftp {Enumeration} MHD_DigestAuthMultiQOP 313 314 Quality of protection (QOP) levels supported by the server. Values of 315 this enumeration can be combined with OR to create a bitmask, allowing 316 the server to offer multiple protection levels to the client. 317 318 @table @code 319 320 @item MHD_DIGEST_AUTH_MULT_QOP_INVALID 321 Invalid/unknown QOP. 322 323 @item MHD_DIGEST_AUTH_MULT_QOP_NONE 324 No QOP parameter. 325 The digest authentication is to proceed as described in 326 the old RFC 2069 original specification. 327 This mode is not allowed by latest RFCs and should be used only to 328 communicate with clients that do not support more modern modes (with QOP 329 parameter). 330 This mode is less secure than other modes and inefficient. 331 332 @item MHD_DIGEST_AUTH_MULT_QOP_AUTH 333 The 'auth' QOP type. 334 335 @item MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT 336 The 'auth-int' QOP type. This value is @emph{not} actually supported by MHD. 337 Reserved value. 338 339 @item MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT 340 The 'auth' QOP type OR the old RFC2069 (no QOP) type. 341 In other words: any types except 'auth-int'. 342 RFC2069-compatible mode is allowed, thus this value should be used only 343 when it is really necessary. 344 345 @item MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY 346 Any 'auth' QOP type ('auth' or 'auth-int'). 347 Currently supported by MHD as 'auth' QOP type only. 348 349 @end table 350 @end deftp 351 352 353 @cindex hash 354 @cindex digest 355 @anchor{MHD_DigestAuthMultiAlgo} 356 @deftp {Enumeration} MHD_DigestAuthMultiAlgo 357 Which digest algorithm should be used. Values of 358 this enumeration can be combined with OR to create a bitmask, allowing 359 the server to offer multiple hash functions to the client. 360 361 @table @code 362 363 @item MHD_DIGEST_AUTH_MULT_ALGO_INVALID 364 Unknown or invalid algorithm type. 365 366 @item MHD_DIGEST_AUTH_MULT_ALGO_MD5 367 The 'MD5' algorithm, non-session version. Deprecated, only use if you 368 have legacy clients that require it. 369 370 @item MHD_DIGEST_AUTH_MULT_ALGO_MD5_SESSION 371 The 'MD5-sess' algorithm. 372 Not actually supported by MHD for authentication. 373 Reserved value. 374 375 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA256 376 The 'SHA-256' algorithm, non-session version. 377 378 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA256_SESSION 379 The 'SHA-256-sess' algorithm. 380 Not supported by MHD for authentication. 381 Reserved value. 382 383 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256 384 The 'SHA-512-256' (SHA-512/256) algorithm, non-session version. 385 386 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256_SESSION 387 The 'SHA-512-256-sess' (SHA-512/256 session) algorithm. 388 Not supported by MHD for authentication. 389 Reserved value. 390 391 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_NON_SESSION 392 SHA-256 or SHA-512/256 non-session algorithm, MHD will choose 393 the preferred or the matching one. 394 395 @item MHD_DIGEST_AUTH_MULT_ALGO_ANY_NON_SESSION 396 Any non-session algorithm, MHD will choose the preferred or 397 the matching one. 398 399 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_SESSION 400 The SHA-256 or SHA-512/256 session algorithm. 401 Not supported by MHD. 402 Reserved value. 403 404 @item MHD_DIGEST_AUTH_MULT_ALGO_ANY_SESSION 405 Any session algorithm. 406 Not supported by MHD. 407 Reserved value. 408 409 @item MHD_DIGEST_AUTH_MULT_ALGO_MD5_ANY 410 The MD5 algorithm, session or non-session. 411 Currently supported as non-session only. 412 413 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA256_ANY 414 The SHA-256 algorithm, session or non-session. 415 Currently supported as non-session only. 416 417 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256_ANY, 418 The SHA-512/256 algorithm, session or non-session. 419 Currently supported as non-session only. 420 421 @item MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_ANY 422 The SHA-256 or SHA-512/256 algorithm, session or non-session. 423 Currently supported as non-session only. 424 425 @item MHD_DIGEST_AUTH_MULT_ALGO_ANY 426 Any algorithm. When sending a challenge to the client, 427 MHD will send challenges for each supported algorithms. When checking 428 client requests with responses to challenges, MHD will allow 429 the client to answer with any algorithm it supports. 430 @end table 431 @end deftp 432 433 434 @c FIXME: did not document MHD_action_digest_auth_challenge (and _p/_a variants), again not always available (depends on static inline!) 435 @c FIXME: not convinced we want to keep that, just looks like bloat, 436 437 When using digest authentication with @var{userhash_support}, applications 438 have to compute the @var{userhash} from the @var{username} and the 439 @var{realm}. This can be done using @code{MHD_digest_auth_calc_userhash()}. 440 441 442 443 @cindex userhash 444 445 @anchor{MHD_digest_auth_calc_userhash} 446 @deftypefun {enum MHD_StatusCode} MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo algo, const char *username, const char *realm, size_t bin_buf_size, void *userhash_bin) 447 448 Calculates the @var{userhash_bin} and returns it as binary data. 449 450 The "userhash" is the hash of the string "username:realm". 451 452 The "userhash" can be used to avoid sending username in cleartext in 453 a header when a client is using digest authorization. 454 455 The userhash is not designed to hide the username in a local database or files, as the username in cleartext is still required for 456 the @code{MHD_digest_auth_check_digest()} function to check the response, 457 it can only can be used to hide the plaintext username in HTTP headers. 458 459 This function could be used when the new username is added to a username 460 database to save the "userhash" alongside with the username (preferably) or 461 when loading list of the usernames to generate the userhash for every loaded 462 username (this will cause delays at the start with longer lists). 463 464 Once "userhash" is generated it could be used to identify users by clients 465 with "userhash" support. 466 467 The result of the computation may be cached and reused across requests. 468 @table @var 469 470 @item algo 471 the hash algorithm to use for userhash calculations, see @ref{MHD_DigestAuthAlgorithm}; 472 473 @item username 474 the username; 475 476 @item realm 477 the realm; 478 479 @item bin_buf_size 480 the size of the @var{userhash_bin} buffer, must be at least 481 @code{#MHD_digest_get_hash_size()} bytes long; 482 483 @item userhash_bin 484 the output buffer for userhash as binary data; 485 if this function succeeds, then this buffer will be set to 486 @code{MHD_digest_get_hash_size()} bytes of userhash upon return; 487 488 @end table 489 490 Possible return values include: 491 @itemize 492 @item @code{MHD_SC_OK} on success, 493 @item @code{MHD_SC_OUT_BUFF_TOO_SMALL} if @var{bin_buf_size} is too small, 494 @item @code{MHD_SC_HASH_FAILED} if hashing failed, or 495 @item @code{MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED} if 496 the requested @var{algo} is unknown or unsupported. 497 @end itemize 498 499 @end deftypefun 500 501 Different hash algorithms can be specified for the 502 @var{algo} when computing the userhash. 503 504 @cindex hash 505 @cindex digest 506 @anchor{MHD_DigestAuthAlgorithm} 507 @deftp {Enumeration} MHD_DigestAuthAlgorithm 508 Which digest algorithm should be used. 509 510 @table @code 511 @item MHD_DIGEST_AUTH_ALGO_INVALID 512 Unknown or invalid algorithm type. Using this value will cause MHD to fail. 513 514 @item MHD_DIGEST_AUTH_ALGO_MD5 515 Use (deprecated, ancient, insecure) MD5. 516 517 @item MHD_DIGEST_AUTH_ALGO_MD5_SESSION 518 Use (deprecated, ancient, insecure) MD5-sess. Not supported by MHD. 519 520 @item MHD_DIGEST_ALG_SHA256 521 Use SHA-256. 522 523 @item MHD_DIGEST_ALG_SHA256_SESSION 524 Use SHA-256-sess. Not supported by MHD. 525 526 @item MHD_DIGEST_ALG_SHA512_256 527 Use SHA-512_256. 528 529 @item MHD_DIGEST_ALG_SHA512_256_SESSION 530 Use SHA-512_256-sess. Not supported by MHD. 531 532 @end table 533 @end deftp 534 535 Given a @ref{MHD_DigestAuthAlgorithm,,@code{MHD_DigestAuthAlgorithm}}, 536 @code{MHD_digest_get_hash_size()} can be used to determine the length 537 of the corresponding binary hash value. 538 539 540 @deftypefun {size_t} MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo algo) 541 542 Return the digest size in bytes for the specified hash algorithm @var{algo}. 543 544 @table @var 545 546 @item algo 547 the hash algorithm to use for userhash calculations, see @ref{MHD_DigestAuthAlgorithm}; 548 @end table 549 The function returns the number of bytes of a hash value of the 550 given @var{algo}. It returns zero if @var{algo} is invalid or 551 unknown. 552 553 @end deftypefun 554 555 556 @c FIXME: MHD_digest_auth_calc_userhash_hex not yet documented, why is this one useful in a MICRO-API that is supposed to be minimal? Do we want to keep it!? 557 558 One key advantage of using digest authentication is not only that 559 the password does not have to be transmitted in the clear, but 560 also that the application does not need to store the user's password 561 in cleartext. Instead, applications @emph{should} use 562 @code{MHD_digest_auth_calc_userdigest()} to compute a hash of 563 the user's credentials and only store the resulting digest. 564 565 @cindex userdigest 566 567 @anchor{MHD_digest_auth_calc_userdigest} 568 @deftypefun {enum MHD_StatusCode} MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo algo, const char *username, const char *realm, const char *password, size_t bin_buf_size, void *userhash_bin) 569 570 Calculates a userdigest and returns it as a binary data. 571 The "userdigest" is the hash of the "username:realm:password" string. 572 The "userdigest" can be used to avoid storing the password in clear text 573 in database/files of the application. 574 575 This function is designed to improve security of stored credentials, 576 using "userdigest" does not improve security of the authentication process. 577 578 The result can be used to store @var{username} and @var{userdigest_bin} pairs instead of 579 @var{username} and @var{password} pairs. 580 To further improve privacy, application may 581 store @var{username}, @var{userhash} and @var{userdigest} triplets 582 and enable @var{userhash_support}. 583 584 585 @table @var 586 587 @item algo 588 the hash algorithm to use for userhash calculations, see @ref{MHD_DigestAuthAlgorithm}; 589 590 @item username 591 the username 592 593 @item realm 594 the realm 595 596 @item password 597 the password belonging to @var{username} 598 599 @item bin_buf_size 600 the size of the @var{userdigest_bin} buffer, must be at least 601 @code{#MHD_digest_get_hash_size()} bytes long 602 603 @item userdigest_bin 604 the output buffer for userdigest as binary data; 605 if this function succeeds, then this buffer will be set to 606 @code{MHD_digest_get_hash_size()} bytes of userhash upon return 607 608 @end table 609 610 Possible return values include: 611 @itemize 612 @item @code{MHD_SC_OK} on success, 613 @item @code{MHD_SC_OUT_BUFF_TOO_SMALL} if @var{bin_buf_size} is too small, 614 @item @code{MHD_SC_HASH_FAILED} if hashing failed, 615 @item @code{MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED} if 616 the requested @var{algo} is unknown or unsupported. 617 @end itemize 618 619 @end deftypefun 620 621 When a client provides a digest authentication header, the application 622 @emph{must} first use introspection using 623 @ref{MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO,,@code{MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO}} 624 to determine the client's identity and algorithmic choices. 625 Introspection will return a @code{struct MHD_AuthDigestInfo}, or 626 @code{NULL} if the client did not provide a digest 627 authorization header. 628 629 @c FIXME: MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_USERNAME is not discussed. When exactly is this necessary!? => will be removed. 630 631 @anchor{MHD_AuthDigestInfo} 632 @deftp {C Struct} MHD_AuthDigestInfo 633 634 Information decoded from a client's header with digest authentication data. 635 @table @var 636 637 @item @code{enum MHD_DigestAuthAlgo} algo 638 The algorithm as selected by the client. 639 Set automatically to MD5 if not explicitly specified by client. 640 641 @item @code{enum MHD_DigestAuthUsernameType} uname_type 642 The type of username used by client. 643 @xref{MHD_DigestAuthUsernameType}. 644 645 @item @code{struct MHD_StringNullable} username 646 The username as a string. 647 Used only if @var{uname_type} is standard or extended, always 648 @code{NULL} otherwise. 649 If extended notation is used, this string is a pct-decoded string 650 with charset and language tag removed (i.e. it is original username 651 extracted from the extended notation). 652 When userhash is used by the client, the string pointer is @code{NULL} and 653 @var{userhash_hex} and @var{userhash_bin} will be set instead. 654 655 @item @code{struct MHD_StringNullable} userhash_hex 656 The userhash string. 657 Valid only if @var{uname_type} is userhash. 658 This is unqoted string without decoding of the hexadecimal 659 digits (as provided by the client). 660 @c FIXME: why do we return both the _hex and the _bin variants? Seems redundant! 661 662 @item @code{const uint8_t *} userhash_bin 663 The userhash decoded to binary form. 664 Used only if @var{uname_type} is userhash, always @code{NULL} otherwise. 665 When not @code{NULL}, this points to binary sequence of @var{userhash_bin_size} bytes. 666 The valid size should be @code{MHD_digest_get_hash_size()} bytes. 667 @emph{Warning:} This buffer points to binary data, there is no zero termination! 668 @emph{Warning:} To avoid buffer overruns, always check the size of the data before 669 use, because @var{userhash_bin} can point even to zero bytes of data. 670 671 @item @code{size_t} userhash_bin_size 672 The size of the data pointed by @var{userhash_bin}. 673 Always zero when @var{userhash_bin} is @code{NULL}. 674 675 @item @code{struct MHD_StringNullable} opaque 676 The 'opaque' parameter value, as specified by client. 677 If not specified by client then string pointer is @code{NULL}. 678 679 @item @code{struct MHD_StringNullable} realm 680 The 'realm' parameter value, as specified by client. 681 If not specified by client then string pointer is @code{NULL}. 682 683 @item @code{enum MHD_DigestAuthQOP} qop 684 The quality of protection (qop) parameter value. 685 686 @item @code{size_t} cnonce_len 687 Length of the @var{cnonce} parameter, including possible 688 backslash-escape characters. @var{cnonce} is used in hash 689 calculation. 690 An application may want to reject too large @var{cnonce} 691 values to limit CPU load. 692 A few kilobytes is a reasonable limit, typical values for 693 @var{cnonce} should just use 32-160 characters. 694 695 @item @code{enum MHD_DigestAuthNC} nc_type 696 The type of the nonce count (nc) value provided in the request. 697 @xref{MHD_DigestAuthNC}. 698 699 @item @code{uint_fast32_t} nc 700 The nonce count (nc) parameter value. 701 Can be used by application to limit the number of nonce re-uses. If @var{nc} 702 is higher than application wants to allow, then "auth required" response 703 with ``stale=true'' could be used to force client to retry with the fresh 704 @var{nonce}. 705 Set to zero when @var{nc_type} is not set to 706 @code{MHD_DIGEST_AUTH_NC_NUMBER}. 707 708 @end table 709 @end deftp 710 711 The type of client nonce provided by the client is represented 712 by an @code{enum MHD_DigestAuthNC}. 713 714 @anchor{MHD_DigestAuthNC} 715 @deftp {Enumeration} MHD_DigestAuthNC 716 717 The type of nonce count (nc) value provided in the request. 718 719 @table @code 720 721 @item MHD_DIGEST_AUTH_NC_NUMBER 722 Readable hexdecimal non-zero number. 723 The decoded value is placed in the @var{nc} member of 724 @ref{MHD_AuthDigestInfo,,@code{MHD_AuthDigestInfo}}. 725 726 @item MHD_DIGEST_AUTH_NC_ZERO 727 Readable zero number. 728 Compliant clients should not use such values. 729 Should probably be treated as an invalid request. 730 731 @item MHD_DIGEST_AUTH_NC_NONE 732 No @var{nc} value was provided by the client. 733 Unless old RFC 2069 mode is allowed, this should be treated as an invalid 734 request. 735 736 @item MHD_DIGEST_AUTH_NC_TOO_LONG 737 The provided ``nc'' value was too long to be decoded. 738 Compliant clients should not use such values. 739 Should be treated as an invalid request. 740 741 @item MHD_DIGEST_AUTH_NC_TOO_LARGE 742 The provided ``nc'' value was too large to fit into a @code{uint32_t}. 743 Compliant clients should not use such values. 744 Can be treated as request with a stale nonce or as an invalid request. 745 746 @end table 747 @end deftp 748 749 @c FIXME: MHD_DigestAuthUsernameType not defined 750 751 @anchor{MHD_DigestAuthUsernameType} 752 @deftp {enum} MHD_DigestAuthUsernameType 753 754 Type of username encoded by the client in a digest authorization 755 header. 756 757 @table @var 758 @item @code{MHD_DIGEST_AUTH_UNAME_TYPE_MISSING} 759 No username parameter is in Digest Authorization header. 760 Not used currently. Value @code{MHD_SC_REQ_AUTH_DATA_BROKEN} is returned 761 by @ref{MHD_request_get_info_dynamic_sz,,@code{MHD_request_get_info_dynamic_sz()}} 762 if the request has no username. 763 764 @item @code{MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD} 765 The 'username' parameter is used to specify the username. 766 767 @item @code{MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED} 768 The username is specified by 'username*' parameter with 769 the extended notation (see RFC 5987, section-3.2.1). 770 The only difference between standard and extended types is 771 the way how username value is encoded in the header. 772 773 @item @code{MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH} 774 The username provided in form of 'userhash' as 775 specified by RFC 7616, section-3.4.4. 776 @xref{MHD_digest_auth_calc_userhash,,@code{MHD_digest_auth_calc_userhash()}}. 777 778 @item @code{MHD_DIGEST_AUTH_UNAME_TYPE_INVALID} 779 The invalid combination of username parameters are used by client. 780 Either: 781 @itemize @bullet 782 @item both 'username' and 'username*' are used 783 @item 'username*' is used with 'userhash=true' 784 @item 'username*' used with invalid extended notation 785 @item 'username' is not hexadecimal string, while 'userhash' set to 'true' 786 @end itemize 787 Not used currently. Value @code{MHD_SC_REQ_AUTH_DATA_BROKEN} is returned by 788 @ref{MHD_request_get_info_dynamic_sz,,@code{MHD_request_get_info_dynamic_sz()}} 789 if the request has broken username. 790 @end table 791 @end deftp 792 793 794 795 Finally, given the client's identity (username or userhash) the 796 application must possibly determine the username from the userhash, 797 and always determine the userdigest. Given the @var{username} and 798 @var{userdigest} and the set of algorithms allowed by the application, 799 it can can use @code{MHD_digest_auth_check_digest()} to actually check 800 the digest authentication provided by the client's request. 801 802 @anchor{MHD_digest_auth_check_digest} 803 @deftypefun {enum MHD_DigestAuthResult} MHD_digest_auth_check_digest (struct MHD_Request *request, const char *realm, const char *username, size_t userdigest_size, const void *userdigest, uint_fast32_t max_nc, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo malgo) 804 805 @cindex userdigest 806 Authenticates the authorization header sent by the client by using 807 hash of "username:realm:password". 808 809 If RFC2069 mode is allowed by setting bit @code{MHD_DIGEST_AUTH_QOP_NONE} in 810 @var{mqop} and the client uses this mode, then server generated nonces are 811 used as one-time nonces because nonce-count is not supported in this old RFC. 812 Communication in this mode is very inefficient, especially if the client 813 requests several resources one-by-one as for every request a new nonce must 814 be generated and client repeats all requests twice (first time to get a new 815 nonce and second time to perform an authorised request). 816 817 @table @var 818 @item request 819 the request; 820 821 @item realm 822 the realm for authorization of the client; 823 824 @item username 825 the username to be authenticated, must be in clear text 826 even if userhash is used by the client; 827 828 @item userdigest_size 829 the size of the @var{userdigest} in bytes, must match the 830 hashing algorithm; 831 832 @item userdigest 833 the precalculated binary hash of the string 834 "username:realm:password"; 835 see @ref{MHD_digest_auth_calc_userdigest,,@code{MHD_digest_auth_calc_userdigest}}; 836 837 @item max_nc 838 the maximum allowed nonce counter (nc) value, if a client's nc 839 exceeds the specified value then @code{MHD_DAUTH_NONCE_STALE} is 840 returned; if zero is specified the daemon's default value is used; 841 842 @item mqop 843 the quality of protection (QOP) level to use; 844 845 @item malgo 846 digest algorithms allowed to use, authentication will fail if 847 the algorithm used by the client is not allowed by this parameter; 848 only the base algorithms (MD5, SHA-256, SHA-512/256) 849 cannot be used at the same time for this function 850 as the @var{userdigest} must match specified algorithm; 851 852 @end table 853 854 The function returns the result of the authentication check. 855 @xref{MHD_DigestAuthResult}. 856 857 @end deftypefun 858 859 @anchor{MHD_DigestAuthResult} 860 @deftp {Enumeration} MHD_DigestAuthResult 861 862 The result of digest authentication of the client. 863 864 @table @code 865 @item MHD_DAUTH_OK 866 Authentication is OK; 867 868 @item MHD_DAUTH_ERROR 869 General error, like ``out of memory''; 870 Authentication may be valid, but cannot be checked; 871 872 @item MHD_DAUTH_HEADER_MISSING 873 No "Authorization" header for digest authentication 874 is present in the client's request. 875 876 @item MHD_DAUTH_HEADER_BROKEN 877 Header is in a wrong format. 878 Also returned if required parameters in Authorization header are missing 879 or broken. 880 881 @item MHD_DAUTH_UNSUPPORTED_ALGO 882 Unsupported algorithm used by the client. 883 884 @item MHD_DAUTH_UNSUPPORTED_QOP 885 Unsupported quality of protection (qop) level used by the client. 886 887 @item MHD_DAUTH_INVALID_USERDIGEST_SIZE 888 Incorrect userdigest size used by the client. 889 890 @item MHD_DAUTH_WRONG_USERNAME 891 Wrong 'username'. 892 893 @item MHD_DAUTH_WRONG_REALM 894 Wrong 'realm'. 895 896 @item MHD_DAUTH_WRONG_URI 897 Wrong 'URI' (or URI parameters). 898 899 @item MHD_DAUTH_WRONG_QOP 900 'qop' value specified by the client is not in the set of values 901 allowed by the specification or the server disallowed the use of 902 the given 'qop' mode. 903 904 @item MHD_DAUTH_WRONG_ALGO 905 The (hash) algorithm value specified by the client is not in the set of values 906 allowed by the specification or the server disallowed the use of 907 the given hash function mode. 908 909 @item MHD_DAUTH_TOO_LARGE 910 Too large (larger than 64 KiB) ``Authorization'' parameter value. 911 912 @item MHD_DAUTH_NONCE_STALE 913 The 'nonce' is too old. Suggest the client to retry with the same 914 username and password to get the fresh 'nonce'. 915 The validity of the 'nonce' may be not checked. 916 917 @item MHD_DAUTH_NONCE_WRONG 918 The 'nonce' is wrong. May indicate an attempted attack. 919 920 @item MHD_DAUTH_RESPONSE_WRONG 921 The 'response' is wrong. May indicate using the wrong password. 922 923 @end table 924 @end deftp 925 926 927 @c @node libmicrohttpd-dauth example 928 @c @section Example for Digest Authentication 929 @c @cindex digest authentication 930 931 @c FIXME: we should probably add an example here... 932 933 @c @example 934 @c @verbatiminclude examples/digest-authentication.c 935 @c @end example