mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
removing client authentication API, moving it into tutorial
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
Sat Dec 25 21:57:14 CET 2010
|
||||
Adding support for basic authentication and client SSL certificates. -MS
|
||||
Adding support for basic authentication.
|
||||
Documented how to obtain client SSL certificates in tutorial. -MS
|
||||
|
||||
Thu Dec 23 15:40:36 CET 2010
|
||||
Increasing nonce length to 128 to support digest authentication
|
||||
|
||||
@@ -92,6 +92,7 @@ Untested features:
|
||||
- extend testcase for chunked encoding to validate
|
||||
handling of footers
|
||||
- more testing for SSL support
|
||||
- MHD basic and digest authentication
|
||||
|
||||
|
||||
Functions not covered by "make check":
|
||||
|
||||
@@ -105,6 +105,7 @@ The rest consists of little new besides some additional memory cleanups.
|
||||
|
||||
The rather unexciting file loader can be found in the complete example @code{tlsauthentication.c}.
|
||||
|
||||
|
||||
@heading Remarks
|
||||
@itemize @bullet
|
||||
@item
|
||||
@@ -126,5 +127,174 @@ hardcode certificates in embedded devices.
|
||||
The cryptographic facilities consume memory space and computing time. For this reason, websites usually consists
|
||||
both of uncritically @emph{HTTP} parts and secured @emph{HTTPS}.
|
||||
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@heading Client authentication
|
||||
|
||||
You can also use MHD to authenticate the client via SSL/TLS certificates
|
||||
(as an alternative to using the password-based Basic or Digest authentication).
|
||||
To do this, you will need to link your application against @emph{gnutls}.
|
||||
For this, you first need to obtain the raw GnuTLS session handle from
|
||||
@emph{MHD} using @code{MHD_get_connection_info}.
|
||||
|
||||
@verbatim
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
|
||||
gnutls_session_t tls_session;
|
||||
tls_session = MHD_get_connection_info (connection,
|
||||
MHD_CONNECTION_INFO_GNUTLS_SESSION);
|
||||
@end verbatim
|
||||
|
||||
You can then extract the client certificate:
|
||||
|
||||
@verbatim
|
||||
/**
|
||||
* Get the client's certificate
|
||||
*
|
||||
* @param tls_session the TLS session
|
||||
* @return NULL if no valid client certificate could be found, a pointer
|
||||
* to the certificate if found
|
||||
*/
|
||||
static gnutls_x509_crt_t
|
||||
get_client_certificate (gnutls_session_t tls_session)
|
||||
{
|
||||
unsigned int listsize;
|
||||
const gnutls_datum_t * pcert;
|
||||
gnutls_certificate_status_t client_cert_status;
|
||||
gnutls_x509_crt_t client_cert;
|
||||
|
||||
if (tls_session == NULL)
|
||||
return NULL;
|
||||
if (gnutls_certificate_verify_peers2(tls_session,
|
||||
&client_cert_status))
|
||||
return NULL;
|
||||
pcert = gnutls_certificate_get_peers(tls_session,
|
||||
&listsize);
|
||||
if ( (pcert == NULL) ||
|
||||
(listsize == 0))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to retrieve client certificate chain\n");
|
||||
return NULL;
|
||||
}
|
||||
if (gnutls_x509_crt_init(&client_cert))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to initialize client certificate\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Note that by passing values between 0 and listsize here, you
|
||||
can get access to the CA's certs */
|
||||
if (gnutls_x509_crt_import(client_cert,
|
||||
&pcert[0],
|
||||
GNUTLS_X509_FMT_DER))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to import client certificate\n");
|
||||
gnutls_x509_crt_deinit(client_cert);
|
||||
return NULL;
|
||||
}
|
||||
return client_cert;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
Using the client certificate, you can then get the client's distinguished name
|
||||
and alternative names:
|
||||
|
||||
@verbatim
|
||||
/**
|
||||
* Get the distinguished name from the client's certificate
|
||||
*
|
||||
* @param client_cert the client certificate
|
||||
* @return NULL if no dn or certificate could be found, a pointer
|
||||
* to the dn if found
|
||||
*/
|
||||
char *
|
||||
cert_auth_get_dn(gnutls_x509_crt_c client_cert)
|
||||
{
|
||||
char* buf;
|
||||
size_t lbuf;
|
||||
|
||||
lbuf = 0;
|
||||
gnutls_x509_crt_get_dn(client_cert, NULL, &lbuf);
|
||||
buf = malloc(lbuf);
|
||||
if (buf == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to allocate memory for certificate dn\n");
|
||||
return NULL;
|
||||
}
|
||||
gnutls_x509_crt_get_dn(client_cert, buf, &lbuf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the alternative name of specified type from the client's certificate
|
||||
*
|
||||
* @param client_cert the client certificate
|
||||
* @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(gnutls_x509_crt_t client_cert,
|
||||
int nametype,
|
||||
unsigned int index)
|
||||
{
|
||||
char* buf;
|
||||
size_t lbuf;
|
||||
unsigned int seq;
|
||||
unsigned int subseq;
|
||||
unsigned int type;
|
||||
int result;
|
||||
|
||||
subseq = 0;
|
||||
for (seq=0;;seq++)
|
||||
{
|
||||
lbuf = 0;
|
||||
result = gnutls_x509_crt_get_subject_alt_name2(client_cert, seq, NULL, &lbuf,
|
||||
&type, NULL);
|
||||
if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
||||
return NULL;
|
||||
if (nametype != (int) type)
|
||||
continue;
|
||||
if (subseq == index)
|
||||
break;
|
||||
subseq++;
|
||||
}
|
||||
buf = malloc(lbuf);
|
||||
if (buf == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to allocate memory for certificate alt name\n");
|
||||
return NULL;
|
||||
}
|
||||
result = gnutls_x509_crt_get_subject_alt_name2(client_cert,
|
||||
seq,
|
||||
buf,
|
||||
&lbuf,
|
||||
NULL, NULL);
|
||||
if (result != nametype)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Unexpected return value from gnutls: %d\n",
|
||||
result);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
Finally, you should release the memory associated with the client
|
||||
certificate:
|
||||
|
||||
@verbatim
|
||||
gnutls_x509_crt_deinit (client_cert);
|
||||
@end verbatim
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@finalout
|
||||
@setfilename microhttpd-tutorial.info
|
||||
@set UPDATED 26 Jul 2010
|
||||
@set UPDATED-MONTH Jul 2010
|
||||
@set EDITION 0.9.0
|
||||
@set VERSION 0.9.0
|
||||
@set UPDATED 26 Dec 2010
|
||||
@set UPDATED-MONTH Dec 2010
|
||||
@set EDITION 0.9.3
|
||||
@set VERSION 0.9.3
|
||||
@settitle A tutorial for GNU libmicrohttpd
|
||||
|
||||
@dircategory GNU Libraries
|
||||
|
||||
+9
-47
@@ -690,14 +690,9 @@ Takes no extra arguments. Allows finding out the TLS/SSL protocol used
|
||||
(HTTPS connections only).
|
||||
|
||||
@item MHD_CONNECTION_INFO_GNUTLS_SESSION,
|
||||
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).
|
||||
Takes no extra arguments. Allows access to the underlying GNUtls session,
|
||||
including access to the underlying GNUtls client certificate
|
||||
(HTTPS connections only). Takes no extra arguments.
|
||||
|
||||
@end table
|
||||
@end deftp
|
||||
@@ -1497,15 +1492,15 @@ 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
|
||||
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).
|
||||
machine and user authentication). A code example for using
|
||||
client certificates is presented in the @mhd{} tutorial.
|
||||
|
||||
@menu
|
||||
* microhttpd-dauth basic:: Using Basic Authentication.
|
||||
* microhttpd-dauth digest:: Using Digest Authentication.
|
||||
* microhttpd-dauth cert:: Using Client Certificate Authentication.
|
||||
@end menu
|
||||
|
||||
@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
@@ -1517,10 +1512,10 @@ machine and user 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.
|
||||
If returned value is not @mynull{}, the value must be @code{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.
|
||||
If returned value is not @mynull{}, the value must be @code{free()}'ed.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {int} MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection, const char *realm, struct MHD_Response *response)
|
||||
@@ -1542,7 +1537,7 @@ client with a 401 HTTP status.
|
||||
@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.
|
||||
If returned value is not @mynull{}, the value must be @code{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)
|
||||
@@ -1644,39 +1639,6 @@ 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
|
||||
|
||||
@@ -29,6 +29,4 @@ 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
|
||||
|
||||
|
||||
@@ -2277,6 +2277,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MHD_set_http_callbacks_ (struct MHD_Connection *connection)
|
||||
{
|
||||
@@ -2316,10 +2317,6 @@ 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;
|
||||
|
||||
@@ -1075,8 +1075,6 @@ 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)
|
||||
|
||||
+75
-188
@@ -643,6 +643,7 @@ 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
|
||||
*
|
||||
@@ -653,45 +654,61 @@ MHD_queue_auth_fail_response(struct MHD_Connection *connection,
|
||||
*/
|
||||
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) {
|
||||
char** password)
|
||||
{
|
||||
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");
|
||||
MHD_DLOG(connection->daemon,
|
||||
"Error decoding basic authentication\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
/* Find user:password pattern */
|
||||
separator = strstr(decode, ":");
|
||||
if (separator == NULL) {
|
||||
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");
|
||||
MHD_DLOG(connection->daemon,
|
||||
"Basic authentication doesn't contain ':' separator\n");
|
||||
#endif
|
||||
free(decode);
|
||||
return NULL;
|
||||
free(decode);
|
||||
return NULL;
|
||||
}
|
||||
user = strndup(decode, separator - decode);
|
||||
if (password != NULL)
|
||||
{
|
||||
*password = strdup(separator + 1);
|
||||
if (NULL == *password)
|
||||
{
|
||||
#if HAVE_MESSAGES
|
||||
MHD_DLOG(connection->daemon,
|
||||
"Failed to allocate memory for password\n");
|
||||
#endif
|
||||
free (decode);
|
||||
free (user);
|
||||
return NULL;
|
||||
}
|
||||
user = strndup(decode, separator - decode);
|
||||
if (password != NULL) {
|
||||
*password = strdup(separator + 1);
|
||||
}
|
||||
free(decode);
|
||||
return user;
|
||||
}
|
||||
free(decode);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Queues a response to request basic authentication from the client
|
||||
*
|
||||
@@ -699,162 +716,32 @@ MHD_basic_auth_get_username_password(struct MHD_Connection *connection,
|
||||
* @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;
|
||||
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) + strlen("Basic realm=\"\"") + 1;
|
||||
char header[hlen];
|
||||
|
||||
if (hlen !=
|
||||
snprintf(header,
|
||||
sizeof(header),
|
||||
"Basic realm=\"%s\"",
|
||||
realm))
|
||||
{
|
||||
EXTRA_CHECK (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
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 */
|
||||
|
||||
@@ -706,16 +706,6 @@ struct MHD_Connection
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
@@ -1450,7 +1450,7 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection,
|
||||
*/
|
||||
char *
|
||||
MHD_basic_auth_get_username_password(struct MHD_Connection *connection,
|
||||
char** password);
|
||||
char** password);
|
||||
|
||||
/**
|
||||
* Queues a response to request basic authentication from the client
|
||||
@@ -1461,43 +1461,8 @@ MHD_basic_auth_get_username_password(struct MHD_Connection *connection,
|
||||
*/
|
||||
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);
|
||||
const char *realm,
|
||||
struct MHD_Response *response);
|
||||
|
||||
/* ********************** generic query functions ********************** */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user