libmicrohttpd

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

commit fe4e71ecaa788e73582b7ee29d1835a3e3112be3
parent 65c3125ced95cc8f6d151f8c66e0d6a06255f04f
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 25 Dec 2010 20:58:06 +0000

client certs and basic auth support, unmodified patch from MS

Diffstat:
MAUTHORS | 1+
MChangeLog | 3+++
Mconfigure.ac | 10+++++-----
Mdoc/microhttpd.texi | 131++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/daemon/EXPORT.sym | 5+++++
Msrc/daemon/Makefile.am | 3++-
Msrc/daemon/connection.c | 4++++
Msrc/daemon/daemon.c | 34++++++++++++++++++++++++++++++++--
Msrc/daemon/digestauth.c | 222++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/daemon/internal.h | 16++++++++++++++++
Msrc/include/microhttpd.h | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
11 files changed, 489 insertions(+), 20 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -4,6 +4,7 @@ Nils Durner <durner@gnunet.org> (W32 port) Sagie Amir (TLS/SSL support using GNUtls) Richard Alimi <rich@velvetsea.net> (performance) Amr Ali <amr.ali.cc@gmail.com> (digest authentication) +Matthieu Speder <mspeder@users.sourceforge.net> (basic authentication, client certificates) Code contributions also came from: Chris GauthierDickey <chrisg@cs.du.edu> diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,6 @@ +Sat Dec 25 21:57:14 CET 2010 + Adding support for basic authentication and client SSL certificates. -MS + Thu Dec 23 15:40:36 CET 2010 Increasing nonce length to 128 to support digest authentication with Opera (see #1633). diff --git a/configure.ac b/configure.ac @@ -325,18 +325,18 @@ AC_MSG_RESULT($enable_https) AM_CONDITIONAL(ENABLE_HTTPS, test "$enable_https" = "yes") # optional: HTTP Digest Auth support. Enabled by default -AC_MSG_CHECKING(whether to support HTTP Digest authentication) +AC_MSG_CHECKING(whether to support HTTP basic and digest authentication) AC_ARG_ENABLE([dauth], AS_HELP_STRING([--disable-dauth], - [disable HTTP Digest Auth support]), + [disable HTTP basic and digest Auth support]), [enable_dauth=${enableval}], [enable_dauth=no]) if test "$enable_dauth" = "yes" then - AC_DEFINE([DAUTH_SUPPORT],[1],[include Digest Auth support]) + AC_DEFINE([DAUTH_SUPPORT],[1],[include basic and digest Auth support]) else - AC_DEFINE([DAUTH_SUPPORT],[0],[disable Digest Auth support]) + AC_DEFINE([DAUTH_SUPPORT],[0],[disable basic and digest Auth support]) fi AC_MSG_RESULT($enable_dauth) @@ -416,7 +416,7 @@ AC_MSG_NOTICE([Configuration Summary: libcurl (testing): ${MSG_CURL} Target directory: ${prefix} Messages: ${enable_messages} - HTTP Digest Auth: ${enable_dauth} + HTTP Authentic.: ${enable_dauth} Postproc: ${enable_postprocessor} HTTPS support: ${enable_https} ]) diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi @@ -117,7 +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-dauth:: Utilizing Authentication. * microhttpd-post:: Adding a @code{POST} processor. * microhttpd-info:: Obtaining status information. @@ -259,7 +259,6 @@ alternative type and also define @code{MHD_LONG_LONG_PRINTF} to the corresponding format string for printing such a data type (without the percent sign). - @c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @c ------------------------------------------------------------ @@ -449,6 +448,20 @@ HTTPS daemon. This option should be followed by an "const char*" argument. This should be used in conjunction with 'MHD_OPTION_HTTPS_MEM_KEY'. +@item MHD_OPTION_HTTPS_MEM_TRUST +@cindex SSL +@cindex TLS +Memory pointer to the CA certificate to be used by the +HTTPS daemon to authenticate and trust clients certificates. +This option should be followed by an "const char*" argument. +The presence of this option activates the request of certificate +to the client. The request to the client is marked optional, and +it is the responsability of the server to check the presence +of the certificate if needed. +Note that most browsers will only present a client certificate +only if they have one matching the specified CA, not sending +any certificate otherwise. + @item MHD_OPTION_HTTPS_CRED_TYPE @cindex SSL @cindex TLS @@ -680,6 +693,12 @@ Takes no extra arguments. Allows finding out the TLS/SSL protocol used Takes no extra arguments. Allows access to the underlying GNUtls session (HTTPS connections only). +@item MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT +Allows access to the underlying GNUtls client certificate. +Equivalent to calling directly MHD_cert_auth_get_certificate. +Takes no extra arguments. +(HTTPS connections only). + @end table @end deftp @@ -1263,7 +1282,7 @@ the @code{MHD_Response} object is released. @c ------------------------------------------------------------ @node microhttpd-response create -@section Creating response objects +@section Creating a response object @deftypefun {struct MHD_Response *} MHD_create_response_from_callback (uint64_t size, size_t block_size, MHD_ContentReaderCallback crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc) @@ -1457,7 +1476,68 @@ We should not modify the value, unless we know what we are doing. @c ------------------------------------------------------------ @node microhttpd-dauth -@chapter Utilizing Digest Authentication +@chapter Utilizing Authentication + +@noindent +@mhd{} support three types of client authentication. + +Basic authentication uses a simple authentication method based +on BASE64 algorithm. Username and password are exchanged in clear +between the client and the server, so this method must only be used +for non-sensitive content or when the session is protected with https. +When using basic authentication @mhd{} will have access to the clear +password, possibily allowing to create a chained authentication +toward an external authentication server. + +Digest authentication uses a one-way authentication method based +on MD5 hash algorithm. Only the hash will transit over the network, +hence protecting the user password. The nonce will prevent replay +attacks. This method is appropriate for general use, especially +when https is not used to encrypt the session. + +Client certificate authentication uses a X.509 certificate from +the client. This is the strongest authentication mechanism but it +requires the use of https. Client certificate authentication can +be used simultaneously with Basic or Digest Authentication in order +to provide a two levels authentication (like for instance separate +machine and user authentication). + +@menu +* microhttpd-dauth basic:: Using Basic Authentication. +* microhttpd-dauth digest:: Using Digest Authentication. +* microhttpd-dauth cert:: Using Client Certificate Authentication. +@end menu + +@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +@c ------------------------------------------------------------ +@node microhttpd-dauth basic +@section Using Basic Authentication + +@deftypefun {char *} MHD_basic_auth_get_username_password (struct MHD_Connection *connection, char** password) +Get the username and password from the basic authorization header sent by the client. +Return @mynull{} if no username could be found, a pointer to the username if found. +If returned value is not @mynull{}, the value must be free()'ed. + +@var{password} reference a buffer to store the password. It can be @mynull{}. +If returned value is not @mynull{}, the value must be free()'ed. +@end deftypefun + +@deftypefun {int} MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection, const char *realm, struct MHD_Response *response) +Queues a response to request basic authentication from the client. +Return @code{MHD_YES} if successful, otherwise @code{MHD_NO}. + +@var{realm} must reference to a zero-terminated string representing the realm. + +@var{response} a response structure to specify what shall be presented to the +client with a 401 HTTP status. +@end deftypefun + +@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +@c ------------------------------------------------------------ +@node microhttpd-dauth digest +@section Using 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. @@ -1467,7 +1547,7 @@ If returned value is not @mynull{}, the value must be free()'ed. @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. +and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}. @var{realm} must reference to a zero-terminated string representing the realm. @@ -1483,7 +1563,9 @@ Most of the time it is sound to specify 300 seconds as its values. @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. +return @code{MHD_YES} if successful, otherwise @code{MHD_NO}. + +@var{realm} must reference to a zero-terminated string representing the realm. @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 @@ -1494,8 +1576,8 @@ 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. +parameters and only a new nonce gets generated. @code{MHD_YES} to generate a new +nonce, @code{MHD_NO} to ask for authentication parameters. @end deftypefun Example: handling digest authentication requests and responses. @@ -1563,6 +1645,39 @@ ahc_echo (void *cls, @c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @c ------------------------------------------------------------ +@node microhttpd-dauth cert +@section Using Client Certificate Authentication + +@deftypefun {void *} MHD_cert_auth_get_certificate (struct MHD_Connection *connection) +Get the client's X.509 certificate. +Return @mynull{} if no valid client certificate was found, a pointer to the certificate +(which can be casted to gnutls_x509_crt_t) if found. +The certificate is cached between calls for a same https session and must not but +manually modified or free()'ed. +@end deftypefun + +@deftypefun {char *} MHD_cert_auth_get_dn (struct MHD_Connection *connection) +Get the distinguished name from the client's certificate. +Return @mynull{} if the certificate doesn't contain a dn or if no valid certificate was +found, a pointer to the dn if found. If returned value is not @mynull{}, the value must +be free()'ed. +@end deftypefun + +@deftypefun {char *} MHD_cert_auth_get_alt_name (struct MHD_Connection *connection, int nametype, unsigned int index) +Get the alternative name of specified type from the client's certificate. +Return @mynull{} if the certificate doesn't contain a matching alternative name or if no +valid certificate was found, a pointer to the alternative name if found. If returned +value is not @mynull{}, the value must be free()'ed. + +@var{nametype} The requested name type (of type 'enum gnutls_x509_subject_alt_name_t') + +@var{index} The position of the alternative name if multiple names are matching the +requested type, 0 for the first matching name +@end deftypefun + +@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +@c ------------------------------------------------------------ @node microhttpd-post @chapter Adding a @code{POST} processor @cindex POST method diff --git a/src/daemon/EXPORT.sym b/src/daemon/EXPORT.sym @@ -27,3 +27,8 @@ MHD_get_version MHD_digest_auth_get_username MHD_digest_auth_check MHD_queue_auth_fail_response +MHD_basic_auth_get_username_password +MHD_queue_basic_auth_fail_response +MHD_cert_auth_get_certificate +MHD_cert_auth_get_dn +MHD_cert_auth_get_alt_name diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am @@ -37,7 +37,8 @@ endif if ENABLE_DAUTH libmicrohttpd_la_SOURCES += \ digestauth.c \ - md5.c md5.h + md5.c md5.h \ + base64.c base64.h endif if ENABLE_HTTPS diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -2316,6 +2316,10 @@ MHD_get_connection_info (struct MHD_Connection *connection, if (connection->tls_session == NULL) return NULL; return (const union MHD_ConnectionInfo *) &connection->tls_session; +#if DAUTH_SUPPORT + case MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT: + return (const union MHD_ConnectionInfo *) MHD_cert_auth_get_certificate(connection); +#endif #endif case MHD_CONNECTION_INFO_CLIENT_ADDRESS: return (const union MHD_ConnectionInfo *) &connection->addr; diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -439,6 +439,19 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) gnutls_datum_t key; gnutls_datum_t cert; + if (daemon->https_mem_trust) { + cert.data = (unsigned char *) daemon->https_mem_trust; + cert.size = strlen(daemon->https_mem_trust); + if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert, + GNUTLS_X509_FMT_PEM) < 0) { +#if HAVE_MESSAGES + MHD_DLOG(daemon, + "Bad trust certificate format\n"); +#endif + return -1; + } + } + /* certificate & key loaded from memory */ if (daemon->https_mem_cert && daemon->https_mem_key) { @@ -987,6 +1000,10 @@ MHD_accept_connection (struct MHD_Daemon *daemon) gnutls_transport_set_push_function (connection->tls_session, (gnutls_push_func) & send_param_adapter); + + if (daemon->https_mem_trust){ + gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST); + } } #endif @@ -1058,6 +1075,8 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) #if HTTPS_SUPPORT if (pos->tls_session != NULL) gnutls_deinit (pos->tls_session); + if (pos->client_cert != NULL) + gnutls_x509_crt_deinit (pos->client_cert); #endif MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len); if (pos->response != NULL) @@ -1474,6 +1493,16 @@ parse_options_va (struct MHD_Daemon *daemon, opt); #endif break; + case MHD_OPTION_HTTPS_MEM_TRUST: + if (0 != (daemon->options & MHD_USE_SSL)) + daemon->https_mem_trust = va_arg (ap, const char *); +#if HAVE_MESSAGES + else + FPRINTF (stderr, + "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", + opt); +#endif + break; case MHD_OPTION_HTTPS_CRED_TYPE: daemon->cred_type = va_arg (ap, gnutls_credentials_type_t); break; @@ -1561,6 +1590,7 @@ parse_options_va (struct MHD_Daemon *daemon, case MHD_OPTION_SOCK_ADDR: case MHD_OPTION_HTTPS_MEM_KEY: case MHD_OPTION_HTTPS_MEM_CERT: + case MHD_OPTION_HTTPS_MEM_TRUST: case MHD_OPTION_HTTPS_PRIORITIES: case MHD_OPTION_ARRAY: if (MHD_YES != parse_options (daemon, @@ -1606,8 +1636,8 @@ parse_options_va (struct MHD_Daemon *daemon, break; default: #if HAVE_MESSAGES - if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) && - (opt <= MHD_OPTION_HTTPS_PRIORITIES)) + if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) && + (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST)) { FPRINTF (stderr, "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n", diff --git a/src/daemon/digestauth.c b/src/daemon/digestauth.c @@ -19,13 +19,15 @@ /** * @file digestauth.c - * @brief Implements HTTP/1.1 Digest Auth according to RFC2617 + * @brief Implements various HTTP authentication methods * @author Amr Ali + * @author Matthieu Speder */ #include "platform.h" #include "internal.h" #include "md5.h" +#include "base64.h" #define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE) @@ -35,6 +37,11 @@ #define _BASE "Digest " /** + * Beginning string for any valid Basic authentication header. + */ +#define _BASIC_BASE "Basic " + +/** * Maximum length of a username for digest authentication. */ #define MAX_USERNAME_LENGTH 128 @@ -636,5 +643,218 @@ MHD_queue_auth_fail_response(struct MHD_Connection *connection, return ret; } +/** + * Get the username and password from the basic authorization header sent by the client + * + * @param connection The MHD connection structure + * @param password a pointer for the password + * @return NULL if no username could be found, a pointer + * to the username if found + */ +char * +MHD_basic_auth_get_username_password(struct MHD_Connection *connection, + char** password) { + size_t len; + const char *header; + char *decode; + const char *separator; + char *user; + + header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, + MHD_HTTP_HEADER_AUTHORIZATION); + if (header == NULL) + return NULL; + if (strncmp(header, _BASIC_BASE, strlen(_BASIC_BASE)) != 0) + return NULL; + header += strlen(_BASIC_BASE); + decode = BASE64Decode(header); + if (decode == NULL) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, "Error decoding basic authentication\n"); +#endif + return NULL; + } + /* Find user:password pattern */ + separator = strstr(decode, ":"); + if (separator == NULL) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Basic authentication doesn't contain ':' separator\n"); +#endif + free(decode); + return NULL; + } + user = strndup(decode, separator - decode); + if (password != NULL) { + *password = strdup(separator + 1); + } + free(decode); + return user; +} + +/** + * Queues a response to request basic authentication from the client + * + * @param connection The MHD connection structure + * @param realm the realm presented to the client + * @return MHD_YES on success, MHD_NO otherwise + */ +int MHD_queue_basic_auth_fail_response(struct MHD_Connection *connection, + const char *realm, struct MHD_Response *response) { + int ret; + size_t hlen = strlen(realm) + sizeof("Basic realm=\"\""); + char header[hlen]; + snprintf(header, sizeof(header), "Basic realm=\"%s\"", realm); + ret = MHD_add_response_header(response, MHD_HTTP_HEADER_WWW_AUTHENTICATE, + header); + if (MHD_YES == ret) + ret = MHD_queue_response(connection, MHD_HTTP_UNAUTHORIZED, response); + return ret; +} + +#if HTTPS_SUPPORT + +/** + * Get the client's certificate + * + * @param connection The MHD connection structure + * @return NULL if no valid client certificate could be found, a pointer + * to the certificate if found + */ +void* +MHD_cert_auth_get_certificate(struct MHD_Connection *connection) { + + if (connection->client_cert == NULL && connection->client_cert_status == 0) { + if (connection->tls_session == NULL) { + connection->client_cert_status = GNUTLS_CERT_INVALID; + return NULL; + } + + if (gnutls_certificate_verify_peers2(connection->tls_session, + &connection->client_cert_status)) { + connection->client_cert_status = GNUTLS_CERT_INVALID; + return NULL; + } + + unsigned int listsize; + const gnutls_datum_t * pcert = gnutls_certificate_get_peers( + connection->tls_session, &listsize); + if (pcert == NULL || listsize == 0) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Failed to retrieve client certificate chain\n"); +#endif + connection->client_cert_status = GNUTLS_CERT_INVALID; + return NULL; + } + + if (gnutls_x509_crt_init(&connection->client_cert)) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Failed to initialize client certificate\n"); +#endif + connection->client_cert = NULL; + connection->client_cert_status = GNUTLS_CERT_INVALID; + return NULL; + } + if (gnutls_x509_crt_import(connection->client_cert, &pcert[0], + GNUTLS_X509_FMT_DER)) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Failed to import client certificate\n"); +#endif + gnutls_x509_crt_deinit(connection->client_cert); + connection->client_cert = NULL; + connection->client_cert_status = GNUTLS_CERT_INVALID; + return NULL; + } + } + + return connection->client_cert; +} + +/** + * Get the distinguished name from the client's certificate + * + * @param connection The MHD connection structure + * @return NULL if no dn or certificate could be found, a pointer + * to the dn if found + */ +char * +MHD_cert_auth_get_dn(struct MHD_Connection *connection) { + + char* buf; + size_t lbuf = 0; + + gnutls_x509_crt_t cert = MHD_cert_auth_get_certificate(connection); + if (cert == NULL) + return NULL; + + gnutls_x509_crt_get_dn(cert, NULL, &lbuf); + buf = malloc(lbuf); + if (buf == NULL) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Failed to allocate memory for certificate dn\n"); +#endif + return NULL; + } + gnutls_x509_crt_get_dn(cert, buf, &lbuf); + return buf; + +} + +/** + * Get the alternative name of specified type from the client's certificate + * + * @param connection The MHD connection structure + * @param nametype The requested name type + * @param index The position of the alternative name if multiple names are + * matching the requested type, 0 for the first matching name + * @return NULL if no matching alternative name could be found, a pointer + * to the alternative name if found + */ +char * +MHD_cert_auth_get_alt_name(struct MHD_Connection *connection, int nametype, unsigned int index) { + + char* buf; + size_t lbuf; + unsigned int seq = 0; + unsigned int subseq = 0; + int result; + unsigned int type; + + gnutls_x509_crt_t cert = MHD_cert_auth_get_certificate(connection); + if (cert == NULL) + return NULL; + + for (;; seq++) { + lbuf = 0; + result = gnutls_x509_crt_get_subject_alt_name2(cert, seq, NULL, &lbuf, + &type, NULL); + if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + return NULL; + if (type != nametype) + continue; + if (subseq != index) { + subseq++; + continue; + } + buf = malloc(lbuf); + if (buf == NULL) { +#if HAVE_MESSAGES + MHD_DLOG(connection->daemon, + "Failed to allocate memory for certificate alt name\n"); +#endif + return NULL; + } + gnutls_x509_crt_get_subject_alt_name2(cert, seq, buf, &lbuf, NULL, NULL); + return buf; + + } + +} + +#endif /* HTTPS */ /* end of digestauth.c */ diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -705,6 +705,17 @@ struct MHD_Connection * Memory location to return for protocol session info. */ int cipher; + + /** + * Validation status of client's certificate. + */ + gnutls_certificate_status_t client_cert_status; + + /** + * Client's certificate. + */ + gnutls_x509_crt_t client_cert; + #endif }; @@ -920,6 +931,11 @@ struct MHD_Daemon */ const char *https_mem_cert; + /** + * Pointer to our SSL/TLS certificate authority (in ASCII) in memory. + */ + const char *https_mem_trust; + #endif #ifdef DAUTH_SUPPORT diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -580,9 +580,14 @@ enum MHD_OPTION * Desired size of the stack for threads created by MHD. Followed * by an argument of type 'size_t'. Use 0 for system 'default'. */ - MHD_OPTION_THREAD_STACK_SIZE = 19 - + MHD_OPTION_THREAD_STACK_SIZE = 19, + /** + * Memory pointer for the certificate (ca.pem) to be used by the + * HTTPS daemon for client authentification. + * This option should be followed by a "const char*" argument. + */ + MHD_OPTION_HTTPS_MEM_TRUST =20 }; @@ -719,7 +724,12 @@ enum MHD_ConnectionInfoType /** * Get the GNUTLS session handle. */ - MHD_CONNECTION_INFO_GNUTLS_SESSION + MHD_CONNECTION_INFO_GNUTLS_SESSION, + + /** + * Get the GNUTLS client certificate handle. + */ + MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT }; /** @@ -1430,6 +1440,65 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection, int signal_stale); +/** + * Get the username and password from the basic authorization header sent by the client + * + * @param connection The MHD connection structure + * @param password a pointer for the password + * @return NULL if no username could be found, a pointer + * to the username if found + */ +char * +MHD_basic_auth_get_username_password(struct MHD_Connection *connection, + char** password); + +/** + * Queues a response to request basic authentication from the client + * + * @param connection The MHD connection structure + * @param realm the realm presented to the client + * @return MHD_YES on success, MHD_NO otherwise + */ +int +MHD_queue_basic_auth_fail_response(struct MHD_Connection *connection, + const char *realm, + struct MHD_Response *response); + +/** + * Get the client's certificate + * + * @param connection The MHD connection structure + * @return NULL if no valid client certificate could be found, a pointer + * to the certificate if found + */ +void* +MHD_cert_auth_get_certificate(struct MHD_Connection *connection); + +/** + * Get the distinguished name from the client's certificate + * + * @param connection The MHD connection structure + * @return NULL if no dn or certificate could be found, a pointer + * to the dn if found + */ +char * +MHD_cert_auth_get_dn(struct MHD_Connection *connection); + +/** + * Get the alternative name of specified type from the client's certificate + * + * @param connection The MHD connection structure + * @param nametype The requested name type + * @param index The position of the alternative name if multiple names are + * matching the requested type, 0 for the first matching name + * @return NULL if no matching alternative name could be found, a pointer + * to the alternative name if found + */ +char * +MHD_cert_auth_get_alt_name(struct MHD_Connection *connection, + int nametype, + unsigned int index); + /* ********************** generic query functions ********************** */ /** @@ -1454,6 +1523,11 @@ union MHD_ConnectionInfo void * /* gnutls_session_t */ tls_session; /** + * GNUtls client certificate handle, of type "gnutls_x509_crt_t". + */ + void * /* gnutls_x509_crt_t */ client_cert; + + /** * Address information for the client. */ struct sockaddr_in * client_addr;