libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 1516188156d388a9876814daee92b1c4d54efd35
parent c2df52c07c98a5e930cba875b597a6ad5ed2be35
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  5 Sep 2010 11:58:38 +0000

  Hi Christian,
        Please see attached a patch for digest authentication documentation.

Thanks,
Amr Ali


Diffstat:
Mdoc/microhttpd.texi | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/daemon/digestauth.c | 16+++++++++-------
2 files changed, 128 insertions(+), 7 deletions(-)

diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi @@ -117,6 +117,7 @@ GNU libmicrohttpd is a GNU package. * microhttpd-inspect:: Implementing external @code{select}. * microhttpd-requests:: Handling requests. * microhttpd-responses:: Building responses to requests. +* microhttpd-dauth:: Utilizing Digest Authentication. * microhttpd-post:: Adding a @code{POST} processor. * microhttpd-info:: Obtaining status information. @@ -451,6 +452,17 @@ specifying the SSL/TLS protocol versions and ciphers that are acceptable for the application. The string is passed unchanged to gnutls_priority_init. If this option is not specified, ``NORMAL'' is used. + +@item MHD_OPTION_DIGEST_AUTH_RANDOM +@cindex digest auth +@cindex random +Digest Authentication nonce's seed. +This option must be followed by an "const char *" argument +specifying a NULL terminated array of randomly generated values +to be used in generating the server nonce when using digest authentication. +It is a MUST to supply these values before utilizing any of MHD +digest authentication functions, as otherwise, it will read from +an arbitrary address in memory which results in an undefined behavior. @item MHD_OPTION_LISTEN_SOCKET @cindex systemd @@ -1330,6 +1342,113 @@ We should not modify the value, unless we know what we are doing. @c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @c ------------------------------------------------------------ +@node microhttpd-dauth +@chapter Utilizing Digest Authentication + +@deftypefun {char *} MHD_digest_auth_get_username(struct MHD_Connection *connection) +Find and return a pointer to the username value from the request header. +Return @mynull{} if the value is not found or header does not exist. +If returned value is not @mynull{}, the value must be free()'ed. +@end deftypefun + +@deftypefun int MHD_digest_auth_check(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout) +Checks if the provided values in the WWW-Authenticate header are valid +and sound according to RFC2716. If valid return MHD_YES, otherwise return MHD_NO. + +@var{realm} must reference to a zero-terminated string representing the realm. + +@var{username} must reference to a zero-terminated string representing the username, +it is usually the returned value from MHD_digest_auth_get_username. + +@var{password} must reference to a zero-terminated string representing the password, +most probably it will be the result of a lookup of the username against a local database. + +@var{nonce_timeout} is the amount of time in seconds for a nonce to be invalid. +Most of the time it is sound to specify 300 seconds as its values. +@end deftypefun + +@deftypefun int MHD_queue_auth_fail_response(struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale) +Queues a response to request authentication from the client, +return MHD_YES if successful, otherwise MHD_NO. + +@var{opaque} must reference to a zero-terminated string representing a value +that gets passed to the client and expected to be passed again to the server +as-is. This value can be a hexadecimal or base64 string. + +@var{response} a response structure to specify what shall be presented to the +client with a 401 HTTP status. + +@var{signal_stale} a value that signals "stale=true" in the response header to +indicate the invalidity of the nonce and no need to ask for authentication +parameters and only a new nonce gets generated. MHD_YES to generate a new +nonce, MHD_NO to ask for authentication parameters. +@end deftypefun + +Example: handling digest authentication requests and responses. + +@example +#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>" +#define DENIED "<html><head><title>libmicrohttpd demo</title></head><body>Access denied</body></html>" +#define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, void **ptr) +{ + struct MHD_Response *response; + char *username; + const char *password = "testpass"; + const char *realm = "test@example.com"; + int ret; + + username = MHD_digest_auth_get_username(connection); + if (username == NULL) + { + response = MHD_create_response_from_data(strlen (DENIED), + DENIED, + MHD_NO, MHD_NO); + ret = MHD_queue_auth_fail_response(connection, realm, + OPAQUE, + response, + MHD_NO); + MHD_destroy_response(response); + return ret; + } + ret = MHD_digest_auth_check(connection, realm, + username, + password, + 300); + free(username); + if ( (ret == MHD_INVALID_NONCE) || + (ret == MHD_NO) ) + { + response = MHD_create_response_from_data(strlen (DENIED), + DENIED, + MHD_NO, MHD_NO); + if (NULL == response) + return MHD_NO; + ret = MHD_queue_auth_fail_response(connection, realm, + OPAQUE, + response, + (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO); + MHD_destroy_response(response); + return ret; + } + response = MHD_create_response_from_data(strlen(PAGE), PAGE, + MHD_NO, MHD_NO); + ret = MHD_queue_response(connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); + return ret; +} +@end example + +@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +@c ------------------------------------------------------------ @node microhttpd-post @chapter Adding a @code{POST} processor @cindex POST method diff --git a/src/daemon/digestauth.c b/src/daemon/digestauth.c @@ -309,14 +309,16 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection) /** - * FIXME: document + * 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) * - * @param nonce_time FIXME: document - * @param method FIXME: document - * @param rnd FIXME: document - * @param uri FIXME: document - * @param realm FIXME: document - * @param nonce FIXME: document + * @param nonce_time The amount of time in seconds for a nonce to be invalid + * @param method HTTP method + * @param rnd A pointer to a character array for the random seed + * @param uri HTTP URI + * @param realm A string of characters that describes the realm of auth. + * @param nonce A pointer to a character array for the nonce to put in */ static void calculate_nonce (uint32_t nonce_time,