mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
client certs and basic auth support, unmodified patch from MS
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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).
|
||||
|
||||
+5
-5
@@ -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}
|
||||
])
|
||||
|
||||
+123
-8
@@ -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.
|
||||
@@ -1562,6 +1644,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+32
-2
@@ -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)
|
||||
@@ -1472,6 +1491,16 @@ parse_options_va (struct MHD_Daemon *daemon,
|
||||
FPRINTF (stderr,
|
||||
"MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
|
||||
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:
|
||||
@@ -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",
|
||||
|
||||
+221
-1
@@ -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)
|
||||
|
||||
@@ -34,6 +36,11 @@
|
||||
*/
|
||||
#define _BASE "Digest "
|
||||
|
||||
/**
|
||||
* Beginning string for any valid Basic authentication header.
|
||||
*/
|
||||
#define _BASIC_BASE "Basic "
|
||||
|
||||
/**
|
||||
* Maximum length of a username for digest authentication.
|
||||
*/
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ********************** */
|
||||
|
||||
/**
|
||||
@@ -1453,6 +1522,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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user