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:
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,