libmicrohttpd

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

commit 909af47012fe33f9e5c566f2ab303fa82163d57e
parent 337922f27f5f7368e0f3cb674acacbb23736d2be
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 24 Aug 2008 18:44:21 +0000

docu

Diffstat:
Msrc/daemon/daemon.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/daemon/https/gnutls.h | 2--
Msrc/daemon/https/tls/Makefile.am | 3+--
Dsrc/daemon/https/tls/ext_inner_application.c | 152-------------------------------------------------------------------------------
Dsrc/daemon/https/tls/ext_inner_application.h | 28----------------------------
Msrc/daemon/https/tls/gnutls_alert.c | 5-----
Msrc/daemon/https/tls/gnutls_extensions.c | 5-----
Msrc/include/microhttpd.h | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
8 files changed, 175 insertions(+), 246 deletions(-)

diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -69,19 +69,32 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) /* certificate & key loaded from file */ if (daemon->https_cert_path && daemon->https_key_path) { - /* test for private key & certificate file exsitance */ + if (daemon->https_mem_cert || daemon->https_mem_key) + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, "You specified certificates both in memory and on disk!", + daemon->https_cert_path, + strerror(errno)); +#endif + return -1; + } + /* test for private key & certificate file exsitance */ if (access (daemon->https_cert_path, R_OK)) { #if HAVE_MESSAGES - MHD_DLOG (daemon, "Missing X.509 certificate file\n"); + MHD_DLOG (daemon, "Missing X.509 certificate file `%s': %s\n", + daemon->https_cert_path, + strerror(errno)); #endif return -1; - } - + } + if (access (daemon->https_key_path, R_OK)) { #if HAVE_MESSAGES - MHD_DLOG (daemon, "Missing X.509 key file\n"); + MHD_DLOG (daemon, "Missing X.509 key file `%s': %s\n", + daemon->https_key_path, + strerror(errno)); #endif return -1; } @@ -91,8 +104,17 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) GNUTLS_X509_FMT_PEM); } /* certificate & key loaded from memory */ - else if (daemon->https_mem_cert && daemon->https_mem_key) + if (daemon->https_mem_cert && daemon->https_mem_key) { + if (daemon->https_cert_path || daemon->https_key_path) + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, "You specified certificates both in memory and on disk!", + daemon->https_cert_path, + strerror(errno)); +#endif + return -1; + } key.data = (unsigned char *) daemon->https_mem_key; key.size = strlen (daemon->https_mem_key); cert.data = (unsigned char *) daemon->https_mem_cert; @@ -102,13 +124,10 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) &cert, &key, GNUTLS_X509_FMT_PEM); } - else - { #if HAVE_MESSAGES - MHD_DLOG (daemon, "Failed to load certificate\n"); + MHD_DLOG (daemon, "You need to specify a certificate and key location\n"); #endif - return -1; - } + return -1; } /* initialize security aspects of the HTTPS daemon */ @@ -121,11 +140,9 @@ MHD_TLS_init (struct MHD_Daemon *daemon) { case MHD_GNUTLS_CRD_ANON: ret = MHD_gnutls_anon_allocate_server_credentials (&daemon->anon_cred); - ret += MHD_gnutls_dh_params_init (&daemon->dh_params); + ret |= MHD_gnutls_dh_params_init (&daemon->dh_params); if (ret != 0) - { - return GNUTLS_E_MEMORY_ERROR; - } + return GNUTLS_E_MEMORY_ERROR; MHD_gnutls_dh_params_generate2 (daemon->dh_params, 1024); MHD_gnutls_anon_set_server_dh_params (daemon->anon_cred, daemon->dh_params); @@ -138,29 +155,23 @@ MHD_TLS_init (struct MHD_Daemon *daemon) default: #if HAVE_MESSAGES MHD_DLOG (daemon, - "Error: no daemon credentials type found. f: %s, l: %d\n", - __FUNCTION__, __LINE__); + "Error: invalid credentials type %d specified.\n", + daemon->cred_type); #endif return -1; } } -inline static int +static int _set_priority (mhd_gtls_priority_st * st, const int *list) { - int num = 0, i; + int num = 0; - while (list[num] != 0) + while ( (list[num] != 0) && + (num < MAX_ALGOS) ) num++; - if (num > MAX_ALGOS) - num = MAX_ALGOS; st->num_algorithms = num; - - for (i = 0; i < num; i++) - { - st->priority[i] = list[i]; - } - + memcpy(st->priority, list, num * sizeof(int)); return 0; } #endif @@ -1116,6 +1127,23 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) free (daemon); } +/** + * Obtain information about the given daemon + * (not fully implemented!). + * + * @param daemon what daemon to get information about + * @param infoType what information is desired? + * @param ... depends on infoType + * @return NULL if this information is not available + * (or if the infoType is unknown) + */ +const union MHD_DaemonInfo *MHD_get_daemon_info (struct MHD_Daemon *daemon, + enum MHD_DaemonInfoType + infoType, ...) +{ + return NULL; +} + #ifndef WINDOWS static struct sigaction sig; diff --git a/src/daemon/https/gnutls.h b/src/daemon/https/gnutls.h @@ -110,8 +110,6 @@ extern "C" GNUTLS_A_CERTIFICATE_UNOBTAINABLE = 111, GNUTLS_A_UNRECOGNIZED_NAME = 112, GNUTLS_A_UNKNOWN_PSK_IDENTITY = 115, - GNUTLS_A_INNER_APPLICATION_FAILURE = 208, - GNUTLS_A_INNER_APPLICATION_VERIFICATION = 209 } gnutls_alert_description_t; typedef enum diff --git a/src/daemon/https/tls/Makefile.am b/src/daemon/https/tls/Makefile.am @@ -16,7 +16,7 @@ noinst_LTLIBRARIES = libtls.la libtls_la_LDFLAGS = \ -L$(GCRYPT_LIB_PATH) - + libtls_la_SOURCES = \ auth_anon.c \ auth_cert.c \ @@ -29,7 +29,6 @@ ext_cert_type.c \ ext_max_record.c \ ext_oprfi.c \ ext_server_name.c \ -ext_inner_application.c \ gnutls_alert.c \ gnutls_algorithms.c \ gnutls_anon_cred.c \ diff --git a/src/daemon/https/tls/ext_inner_application.c b/src/daemon/https/tls/ext_inner_application.c @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Free Software Foundation - * - * Author: Simon Josefsson - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include "gnutls_int.h" -#include "gnutls_auth_int.h" -#include "gnutls_errors.h" -#include "gnutls_num.h" -#include "ext_inner_application.h" - -#define NO 0 -#define YES 1 - -int -mhd_gtls_inner_app_rcv_params (mhd_gtls_session_t session, - const opaque * data, size_t data_size) -{ - mhd_gtls_ext_st *ext = &session->security_parameters.extensions; - - if (data_size != 1) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - ext->gnutls_ia_peer_enable = 1; - ext->gnutls_ia_peer_allowskip = 0; - - switch ((unsigned char) *data) - { - case NO: /* Peer's ia_on_resume == no */ - ext->gnutls_ia_peer_allowskip = 1; - break; - - case YES: - break; - - default: - gnutls_assert (); - } - - return 0; -} - - -/** - * returns data_size or a negative number on failure - */ -int -mhd_gtls_inner_app_send_params (mhd_gtls_session_t session, - opaque * data, size_t data_size) -{ - mhd_gtls_ext_st *ext = &session->security_parameters.extensions; - - /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA - credential in the session. */ -#if MHD_DEBUG_TLS - if (session->security_parameters.entity == GNUTLS_CLIENT) - { - gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t) - mhd_gtls_get_cred (session->key, MHD_GNUTLS_CRD_IA, NULL); - - if (cred) - ext->gnutls_ia_enable = 1; - } - else -#endif - { - struct gnutls_ia_server_credentials_st *cred = - (struct gnutls_ia_server_credentials_st *) - mhd_gtls_get_cred (session->key, MHD_GNUTLS_CRD_IA, NULL); - - if (cred) - ext->gnutls_ia_enable = 1; - } - - /* If we don't want gnutls_ia locally, or we are a server and the - * client doesn't want it, don't advertise TLS/IA support at all, as - * required. */ - - if (!ext->gnutls_ia_enable) - return 0; - - if (session->security_parameters.entity == GNUTLS_SERVER && - !ext->gnutls_ia_peer_enable) - return 0; - - /* We'll advertise. Check if there's room in the hello buffer. */ - - if (data_size < 1) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - /* default: require new application phase */ - - *data = YES; - -#if MHD_DEBUG_TLS - if (session->security_parameters.entity == GNUTLS_CLIENT) - { - - /* Client: value follows local setting */ - - if (ext->gnutls_ia_allowskip) - *data = NO; - } - else -#endif - { - - /* Server: value follows local setting and client's setting, but only - * if we are resuming. - * - * XXX Can server test for resumption at this stage? - * - * Ai! It seems that read_client_hello only calls parse_extensions if - * we're NOT resuming! That would make us automatically violate the IA - * draft; if we're resuming, we must first learn what the client wants - * -- IA or no IA -- and then prepare our response. Right now we'll - * always skip IA on resumption, because recv_ext isn't even called - * to record the peer's support for IA at all. Simon? */ - - if (ext->gnutls_ia_allowskip && - ext->gnutls_ia_peer_allowskip && - session->internals.resumed == RESUME_TRUE) - *data = NO; - } - - return 1; -} diff --git a/src/daemon/https/tls/ext_inner_application.h b/src/daemon/https/tls/ext_inner_application.h @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2005 Free Software Foundation - * - * Author: Simon Josefsson - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - -int mhd_gtls_inner_app_rcv_params (mhd_gtls_session_t session, - const opaque * data, size_t data_size); -int mhd_gtls_inner_app_send_params (mhd_gtls_session_t session, - opaque * data, size_t); diff --git a/src/daemon/https/tls/gnutls_alert.c b/src/daemon/https/tls/gnutls_alert.c @@ -64,11 +64,6 @@ static const gnutls_alert_entry mhd_gtls_sup_alerts[] = { "The server name sent was not recognized"}, {GNUTLS_A_UNKNOWN_PSK_IDENTITY, "The SRP/PSK username is missing or not known"}, - {GNUTLS_A_INNER_APPLICATION_FAILURE, - "Inner application negotiation failed"}, - {GNUTLS_A_INNER_APPLICATION_VERIFICATION, - "Inner application verification failed"}, - {0, NULL} }; #define GNUTLS_ALERT_LOOP(b) \ diff --git a/src/daemon/https/tls/gnutls_extensions.c b/src/daemon/https/tls/gnutls_extensions.c @@ -34,7 +34,6 @@ #include <ext_cert_type.h> #include <ext_server_name.h> #include <ext_oprfi.h> -#include <ext_inner_application.h> #include <gnutls_num.h> /* Key Exchange Section */ @@ -70,10 +69,6 @@ mhd_gtls_extension_entry mhd_gtls_extensions[MAX_EXT_SIZE] = { _gnutls_srp_recv_params, _gnutls_srp_send_params), #endif - GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_INNER_APPLICATION, - EXTENSION_TLS, - mhd_gtls_inner_app_rcv_params, - mhd_gtls_inner_app_send_params), {0, 0, 0, 0} }; diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -56,7 +56,8 @@ * standard and use those with MHD.<p> * * All functions are guaranteed to be completely reentrant and - * thread-safe.<p> + * thread-safe (with the exception of 'MHD_set_connection_value', + * which must only be used in a particular context).<p> * * NEW: Before including "microhttpd.h" you should add the * necessary includes to define the "size_t", "fd_set", "socklen_t" and @@ -526,7 +527,7 @@ enum MHD_RequestTerminationCode }; /** - * Which symmetric cipher should be used by HTTPS? + * List of symmetric ciphers. * Note that not all listed algorithms are necessarily * supported by all builds of MHD. */ @@ -543,11 +544,10 @@ enum MHD_GNUTLS_CipherAlgorithm MHD_GNUTLS_CIPHER_CAMELLIA_256_CBC, MHD_GNUTLS_CIPHER_RC2_40_CBC = 90, MHD_GNUTLS_CIPHER_DES_CBC -}; // enum MHD_GNUTLS_CipherAlgorithm; +}; /** - * Which public key algorithm should be used - * for the key exchange? + * List of key exchange algorithms. * Note that not all listed algorithms are necessarily * supported by all builds of MHD. */ @@ -565,20 +565,38 @@ enum MHD_GNUTLS_KeyExchangeAlgorithm }; /** - * Server credentials type + * Server credentials type (note that not all types + * maybe supported by all MHD builds). */ enum MHD_GNUTLS_CredentialsType { + /** + * We have a x.509 certificate. + */ MHD_GNUTLS_CRD_CERTIFICATE = 1, + + /** + * We have no certificate ("anonymous"). + */ MHD_GNUTLS_CRD_ANON, + + /** + * Use SRP (password-based authentication). + */ MHD_GNUTLS_CRD_SRP, + + /** + * Use PSK (pre-shared keys). + */ MHD_GNUTLS_CRD_PSK, - MHD_GNUTLS_CRD_IA + }; /** * Enumeration of possible cryptographic * hash functions (for MAC and Digest operations). + * Note that not all listed algorithms are necessarily + * supported by all builds of MHD. */ enum MHD_GNUTLS_HashAlgorithm { @@ -587,22 +605,37 @@ enum MHD_GNUTLS_HashAlgorithm MHD_GNUTLS_MAC_MD5, MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_MAC_SHA256 - //GNUTLS_MAC_SHA384, - //GNUTLS_MAC_SHA512 +#if 0 + /* unsupported */ + MHD_GNUTLS_MAC_SHA384, + MHD_GNUTLS_MAC_SHA512 +#endif }; /** - * Compression methods. + * List of compression methods. + * Note that not all listed algorithms are necessarily + * supported by all builds of MHD. */ enum MHD_GNUTLS_CompressionMethod { - MHD_GNUTLS_COMP_UNKNOWN = 0, + MHD_GNUTLS_COMP_UNKNOWN = 0, + + /** + * No compression. + */ MHD_GNUTLS_COMP_NULL = 1, + + /** + * gzip compression. + */ MHD_GNUTLS_COMP_DEFLATE }; /** * SSL/TLS Protocol types. + * Note that not all listed algorithms are necessarily + * supported by all builds of MHD. */ enum MHD_GNUTLS_Protocol { @@ -615,7 +648,7 @@ enum MHD_GNUTLS_Protocol }; /** - * Specify what type of certificate should be used. + * Types of certificates. */ enum MHD_GNUTLS_CertificateType { @@ -623,11 +656,19 @@ enum MHD_GNUTLS_CertificateType MHD_GNUTLS_CRT_X509 = 1 }; +/** + * List of public key algorithms. + * Note that not all listed algorithms are necessarily + * supported by all builds of MHD. + */ enum MHD_GNUTLS_PublicKeyAlgorithm { MHD_GNUTLS_PK_UNKNOWN = 0, MHD_GNUTLS_PK_RSA = 1 - //GNUTLS_PK_DSA +#if 0 + /* unsupported */ + MHD_GNUTLS_PK_DSA +#endif }; /** @@ -730,7 +771,6 @@ struct MHD_PostProcessor; /** * Allow or deny a client to connect. * - * * @param addr address information from the client * @param addrlen length of the address information * @return MHD_YES if connection is allowed, MHD_NO if not @@ -888,8 +928,11 @@ typedef int const char *transfer_encoding, const char *data, size_t off, size_t size); +/* **************** Daemon handling functions ***************** */ + /** * Start a webserver on the given port. + * * @param flags combination of MHD_FLAG values * @param port port to bind to * @param apc callback to call to check which clients @@ -910,9 +953,20 @@ struct MHD_Daemon *MHD_start_daemon_va (unsigned int options, MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap); -/* - * Variadic version of MHD_start_daemon_va. This function will delegate calls - * to MHD_start_daemon_va() once argument list is analyzed. +/** + * Start a webserver on the given port. Variadic version of + * MHD_start_daemon_va. + * + * @param flags combination of MHD_FLAG values + * @param port port to bind to + * @param apc callback to call to check which clients + * will be allowed to connect; you can pass NULL + * in which case connections from any IP will be + * accepted + * @param apc_cls extra argument to apc + * @param dh handler called for all requests (repeatedly) + * @param dh_cls extra argument to dh + * @return NULL on error, handle to daemon on success */ struct MHD_Daemon *MHD_start_daemon (unsigned int flags, unsigned short port, @@ -921,10 +975,10 @@ struct MHD_Daemon *MHD_start_daemon (unsigned int flags, MHD_AccessHandlerCallback dh, void *dh_cls, ...); - - /** * Shutdown an http daemon. + * + * @param daemon daemon to stop */ void MHD_stop_daemon (struct MHD_Daemon *daemon); @@ -932,6 +986,12 @@ void MHD_stop_daemon (struct MHD_Daemon *daemon); /** * Obtain the select sets for this daemon. * + * @param daemon daemon to get sets from + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @param max_fd increased to largest FD added (if larger + * than existing value) * @return MHD_YES on success, MHD_NO if this * daemon was not started with the right * options for this call. @@ -946,7 +1006,8 @@ MHD_get_fdset (struct MHD_Daemon *daemon, * (only needed if connection timeout is used). The * returned value is how long select should at most * block, not the timeout value set for connections. - * + * + * @param daemon daemon to query for timeout * @param timeout set to the timeout (in milliseconds) * @return MHD_YES on success, MHD_NO if timeouts are * not used (or no connections exist that would @@ -961,15 +1022,21 @@ int MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout); * by clients in combination with MHD_get_fdset * if the client-controlled select method is used. * + * @param daemon daemon to run * @return MHD_YES on success, MHD_NO if this * daemon was not started with the right * options for this call. */ int MHD_run (struct MHD_Daemon *daemon); + +/* **************** Connection handling functions ***************** */ + /** * Get all of the headers from the request. * + * @param connection connection to get values from + * @param kind types of values to iterate over * @param iterator callback to call on each header; * maybe NULL (then just count headers) * @param iterator_cls extra argument to iterator @@ -1018,6 +1085,8 @@ MHD_set_connection_value (struct MHD_Connection *connection, * Get a particular header value. If multiple * values match the kind, return any one of them. * + * @param connection connection to get values from + * @param kind what kind of value are we looking for * @param key the header to look for * @return NULL if no such item was found */ @@ -1040,6 +1109,8 @@ MHD_queue_response (struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response); +/* **************** Response manipulation functions ***************** */ + /** * Create a response object. The response object can be extended with * header information and then be used any number of times. @@ -1085,13 +1156,19 @@ struct MHD_Response *MHD_create_response_from_data (size_t size, * libmicrohttpd may keep some of the resources around if the response * is still in the queue for some clients, so the memory may not * necessarily be freed immediatley. + * + * @param response response to destroy */ void MHD_destroy_response (struct MHD_Response *response); /** * Add a header line to the response. * - * @return MHD_NO on error (i.e. invalid header or content format). + * @param response response to add a header to + * @param header the header to add + * @param content value to add + * @return MHD_NO on error (i.e. invalid header or content format), + * or out of memory */ int MHD_add_response_header (struct MHD_Response *response, @@ -1100,6 +1177,9 @@ MHD_add_response_header (struct MHD_Response *response, /** * Delete a header line from the response. * + * @param response response to remove a header from + * @param header the header to delete + * @param content value to delete * @return MHD_NO on error (no such header known) */ int @@ -1109,6 +1189,7 @@ MHD_del_response_header (struct MHD_Response *response, /** * Get all of the headers added to a response. * + * @param response response to query * @param iterator callback to call on each header; * maybe NULL (then just count headers) * @param iterator_cls extra argument to iterator @@ -1122,6 +1203,7 @@ MHD_get_response_headers (struct MHD_Response *response, /** * Get a particular header from the response. * + * @param response response to query * @param key which header to get * @return NULL if header does not exist */ @@ -1129,11 +1211,17 @@ const char *MHD_get_response_header (struct MHD_Response *response, const char *key); +/* ********************** PostProcessor functions ********************** */ + /** * Create a PostProcessor. * - * A PostProcessor can be used to (incrementally) - * parse the data portion of a POST request. + * A PostProcessor can be used to (incrementally) parse the data + * portion of a POST request. Note that some buggy browsers fail to + * set the encoding type. If you want to support those, you may have + * to call 'MHD_set_connection_value' with the proper encoding type + * before creating a post processor (if no supported encoding type is + * set, this function will fail). * * @param connection the connection on which the POST is * happening (used to determine the POST format) @@ -1175,6 +1263,7 @@ MHD_post_process (struct MHD_PostProcessor *pp, /** * Release PostProcessor resources. * + * @param pp the PostProcessor to destroy * @return MHD_YES if processing completed nicely, * MHD_NO if there were spurious characters / formatting * problems; it is common to ignore the return @@ -1183,6 +1272,10 @@ MHD_post_process (struct MHD_PostProcessor *pp, int MHD_destroy_post_processor (struct MHD_PostProcessor *pp); + +/* ********************** generic query functions ********************** */ + + /** * Information about a connection. */ @@ -1231,7 +1324,8 @@ union MHD_DaemonInfo }; /** - * Obtain information about the given daemon. + * Obtain information about the given daemon + * (not fully implemented!). * * @param daemon what daemon to get information about * @param infoType what information is desired?