libmicrohttpd

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

commit fc861fda8e9e93f1bb6a379b0553884f016b8eaf
parent 7012df14efccc46a3724203545b2250c47b65f99
Author: lv-426 <oxcafebaby@yahoo.com>
Date:   Wed,  2 Jul 2008 00:51:22 +0000

- switched to hard coded certificates


Diffstat:
Mconfigure.ac | 1+
Msrc/daemon/Makefile.am | 3++-
Msrc/daemon/daemon.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/daemon/https/includes/gnutls.h | 26+++++++++++++-------------
Msrc/daemon/internal.h | 10+++++++---
Msrc/examples/https_server_example.c | 45++++++++++++++++++++++++++++++++++++---------
Msrc/include/microhttpd.h | 29++++++++++++++++++++++++-----
Msrc/testcurl/Makefile.am | 7++++---
Dsrc/testcurl/daemon_HTTPS_test_get.c | 276-------------------------------------------------------------------------------
9 files changed, 149 insertions(+), 344 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -257,6 +257,7 @@ src/daemon/https/minitasn1/Makefile src/daemon/https/includes/Makefile src/examples/Makefile src/testcurl/Makefile +src/testcurl/https/Makefile src/testzzuf/Makefile]) AC_OUTPUT diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am @@ -1,4 +1,5 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/include \ +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/include \ -I$(top_srcdir)/src/daemon \ -I$(top_srcdir)/src/daemon/https/lgl \ -I$(top_srcdir)/src/daemon/https/x509 \ diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -220,7 +220,7 @@ MHDS_handle_connection (void *data) con->daemon->x509_cret); /* avoid gnutls blocking recv / write calls */ - // gnutls_transport_set_pull_function(tls_session, &recv); + gnutls_transport_set_pull_function(tls_session, &recv); // gnutls_transport_set_push_function(tls_session, &send); gnutls_transport_set_ptr (tls_session, con->socket_fd); @@ -786,14 +786,10 @@ MHD_start_daemon (unsigned int options, retVal->pool_size = MHD_POOL_SIZE_DEFAULT; retVal->connection_timeout = 0; /* no timeout */ - /* initialize ssl path parameters to the local path */ - retVal->https_cert_path = "cert.pem"; - retVal->https_key_path = "key.pem"; - /* initializes the argument pointer variable */ va_start (ap, dh_cls); /* - * loop through daemon options + * loop through daemon options */ while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) { @@ -817,10 +813,16 @@ MHD_start_daemon (unsigned int options, retVal->per_ip_connection_limit = va_arg (ap, unsigned int); break; case MHD_OPTION_HTTPS_KEY_PATH: - retVal->https_key_path = va_arg (ap, const char *); + retVal->https_key_path = va_arg (ap, const char *); break; case MHD_OPTION_HTTPS_CERT_PATH: - retVal->https_cert_path = va_arg (ap, const char* ); + retVal->https_cert_path = va_arg (ap, const char *); + break; + case MHD_OPTION_HTTPS_MEM_KEY: + retVal->https_mem_key = va_arg (ap, const char *); + break; + case MHD_OPTION_HTTPS_MEM_CERT: + retVal->https_mem_cert = va_arg (ap, const char *); break; default: #if HAVE_MESSAGES @@ -832,25 +834,13 @@ MHD_start_daemon (unsigned int options, } #if HTTPS_SUPPORT /* initialize HTTPS daemon certificate aspects & send / recv functions */ - if (options & MHD_USE_SSL) + if (options & MHD_USE_SSL && MHD_NO == MHDS_init (retVal)) { - /* test for private key & certificate file exsitance */ - FILE *cert_file = fopen (retVal->https_cert_path, "r"); - FILE *key_file = fopen (retVal->https_key_path, "r"); - if (key_file == NULL || cert_file == NULL) - { - printf ("missing cert files"); #if HAVE_MESSAGES - MHD_DLOG (retVal, "Missing X.509 key or certificate file\n"); + MHD_DLOG (retVal, "Failed to initialize MHDS\n", STRERROR (errno)); #endif - free (retVal); - CLOSE (socket_fd); - return NULL; - } - - fclose (cert_file); - fclose (key_file); - MHDS_init (retVal); + free (retVal); + return NULL; } #endif va_end (ap); @@ -923,13 +913,13 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) } /* TLS clean up */ -#if HTTPS_SUPPORT +#if HTTPS_SUPPORT if (daemon->options & MHD_USE_SSL) { gnutls_priority_deinit (daemon->priority_cache); gnutls_global_deinit (); } -#endif +#endif free (daemon); } @@ -952,13 +942,13 @@ MHDS_init (struct MHD_Daemon *daemon) gnutls_global_init (); /* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */ - // TODO should we be initializing RSA params or DH params ? + // TODO should we be initializing RSA params or DH params ? gnutls_dh_params_init (&daemon->dh_params); gnutls_dh_params_generate2 (daemon->dh_params, DH_BITS); + // TODO rm NONE:+AES-256-CBC:+RSA:+SHA1:+COMP-NULL", NULL); gnutls_priority_init (&daemon->priority_cache, - "NONE:+AES-256-CBC:+RSA:+SHA1:+COMP-NULL", - NULL); + "NONE:+AES-256-CBC:+RSA:+SHA1:+COMP-NULL", NULL); /* setup server certificate */ gnutls_certificate_allocate_credentials (&daemon->x509_cret); @@ -971,15 +961,53 @@ MHDS_init (struct MHD_Daemon *daemon) //gnutls_certificate_set_x509_crl_file(x509_cret, CRLFILE, GNUTLS_X509_FMT_PEM); /* sets a certificate private key pair */ - gnutls_certificate_set_x509_key_file (daemon->x509_cret, - daemon->https_cert_path, - daemon->https_key_path, - GNUTLS_X509_FMT_PEM); + if (daemon->https_cert_path && daemon->https_key_path ) + { + /* test for private key & certificate file exsitance */ + FILE *cert_file = fopen (daemon->https_cert_path, "r"); + FILE *key_file = fopen (daemon->https_key_path, "r"); + if (key_file == NULL || cert_file == NULL) + { + printf ("missing cert files"); +#if HAVE_MESSAGES + MHD_DLOG (daemon, "Missing X.509 key or certificate file\n"); +#endif + free (daemon); + CLOSE (daemon->socket_fd); + return NULL; + } + fclose (cert_file); + fclose (key_file); + gnutls_certificate_set_x509_key_file (daemon->x509_cret, + daemon->https_cert_path, + daemon->https_key_path, + GNUTLS_X509_FMT_PEM); + } + else if (daemon->https_mem_cert && daemon->https_mem_key ) + { + // TODO free + gnutls_datum_t * key = ( gnutls_datum_t * ) malloc (sizeof(gnutls_datum_t)); + gnutls_datum_t * cert = ( gnutls_datum_t * ) malloc (sizeof(gnutls_datum_t)); + + _gnutls_set_datum_m(key,daemon->https_mem_key,strlen (daemon->https_mem_key), &malloc); + _gnutls_set_datum_m(cert,daemon->https_mem_cert,strlen (daemon->https_mem_cert), &malloc); + + gnutls_certificate_set_x509_key_mem (daemon->x509_cret, cert, key, + GNUTLS_X509_FMT_PEM); + printf(""); + } + else + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, "Failed to load certificate\n"); +#endif + return MHD_NO; + } gnutls_certificate_set_dh_params (daemon->x509_cret, daemon->dh_params); // TODO address error case return value - return 0; + return MHD_YES; } #endif diff --git a/src/daemon/https/includes/gnutls.h b/src/daemon/https/includes/gnutls.h @@ -227,7 +227,7 @@ extern "C" */ /* Those are extra information about the verification - * process. Will be set only if the certificate was + * process. Will be set only if the certificate was * not verified. */ GNUTLS_CERT_SIGNER_NOT_FOUND = 64, @@ -494,7 +494,7 @@ extern "C" const char *gnutls_supplemental_get_name (gnutls_supplemental_data_format_type_t type); -/* functions to set priority of cipher suites +/* functions to set priority of cipher suites */ int gnutls_cipher_set_priority (gnutls_session_t session, const int *list); int gnutls_mac_set_priority (gnutls_session_t session, const int *list); @@ -510,7 +510,7 @@ extern "C" */ int gnutls_priority_init( gnutls_priority_t*, const char *priority, const char** err_pos); void gnutls_priority_deinit( gnutls_priority_t); - + int gnutls_priority_set(gnutls_session_t session, gnutls_priority_t); int gnutls_priority_set_direct(gnutls_session_t session, const char *priority, const char** err_pos); @@ -533,7 +533,7 @@ extern "C" const char *gnutls_protocol_get_name (gnutls_protocol_t version); -/* get/set session +/* get/set session */ int gnutls_session_set_data (gnutls_session_t session, const void *session_data, @@ -548,7 +548,7 @@ extern "C" int gnutls_session_get_id (gnutls_session_t session, void *session_id, size_t * session_id_size); -/* returns security values. +/* returns security values. * Do not use them unless you know what you're doing. */ #define TLS_MASTER_SIZE 48 @@ -557,7 +557,7 @@ extern "C" const void *gnutls_session_get_client_random (gnutls_session_t session); const void *gnutls_session_get_master_secret (gnutls_session_t session); -/* checks if this session is a resumed one +/* checks if this session is a resumed one */ int gnutls_session_is_resumed (gnutls_session_t session); @@ -583,7 +583,7 @@ extern "C" typedef int (*gnutls_handshake_post_client_hello_func)(gnutls_session_t); void gnutls_handshake_set_post_client_hello_function(gnutls_session_t, gnutls_handshake_post_client_hello_func); - + void gnutls_handshake_set_max_packet_length (gnutls_session_t session, size_t max); @@ -684,7 +684,7 @@ extern "C" void gnutls_certificate_send_x509_rdn_sequence (gnutls_session_t session, int status); - + extern int gnutls_certificate_set_x509_simple_pkcs12_file @@ -769,7 +769,7 @@ extern "C" int gnutls_dh_params_cpy (gnutls_dh_params_t dst, gnutls_dh_params_t src); -/* RSA params +/* RSA params */ int gnutls_rsa_params_init (gnutls_rsa_params_t * rsa_params); void gnutls_rsa_params_deinit (gnutls_rsa_params_t rsa_params); @@ -825,7 +825,7 @@ extern "C" void gnutls_transport_set_errno (gnutls_session_t session, int err); void gnutls_transport_set_global_errno (int err); -/* session specific +/* session specific */ void gnutls_session_set_ptr (gnutls_session_t session, void *ptr); void *gnutls_session_get_ptr (gnutls_session_t session); @@ -833,7 +833,7 @@ extern "C" void gnutls_openpgp_send_cert (gnutls_session_t session, gnutls_openpgp_crt_status_t status); -/* fingerprint +/* fingerprint * Actually this function returns the hash of the given data. */ int gnutls_fingerprint (gnutls_digest_algorithm_t algo, @@ -841,7 +841,7 @@ extern "C" size_t * result_size); -/* SRP +/* SRP */ typedef struct gnutls_srp_server_credentials_st @@ -1117,7 +1117,7 @@ extern "C" gnutls_datum_t * result); int gnutls_global_init (void); - + /* key_usage will be an OR of the following values: */ diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -308,7 +308,7 @@ enum MHDS_CONNECTION_STATE /* while receiving an HTTP request through the encrypted channel */ MHDS_REPLY_SENDING, - + MHDS_REPLY_SENT, MHDS_CONNECTION_CLOSED @@ -549,7 +549,7 @@ struct MHD_Connection int (*idle_handler) (struct MHD_Connection * connection); - /* + /* * function pointers to the appropriate send & receive funtions * according to whether this is a HTTPS / HTTP daemon */ @@ -586,7 +586,7 @@ struct MHD_Daemon /** * Linked list of our current connections. */ - // TODO switch to a dedicated tls connection struct + // TODO switch to a dedicated tls connection struct struct MHD_Connection *tls_connections; MHD_AcceptPolicyCallback apc; @@ -657,6 +657,10 @@ struct MHD_Daemon const char * https_key_path; const char * https_cert_path; + + const char * https_mem_key; + + const char * https_mem_cert; #endif }; diff --git a/src/examples/https_server_example.c b/src/examples/https_server_example.c @@ -50,16 +50,45 @@ #define BUF_SIZE 1024 #define MAX_URL_LEN 255 -#define KEYFILE "key.pem" -#define CERTFILE "cert.pem" - - // TODO remove if unused #define CAFILE "ca.pem" #define CRLFILE "crl.pem" #define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>" +/* Test Certificate */ +const char cert_pem[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICHjCCAYmgAwIBAgIERiYdNzALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n" + "VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTI3WhcNMDgwNDE3MTMyOTI3WjAdMRsw\n" + "GQYDVQQDExJHbnVUTFMgdGVzdCBjbGllbnQwgZwwCwYJKoZIhvcNAQEBA4GMADCB\n" + "iAKBgLtmQ/Xyxde2jMzF3/WIO7HJS2oOoa0gUEAIgKFPXKPQ+GzP5jz37AR2ExeL\n" + "ZIkiW8DdU3w77XwEu4C5KL6Om8aOoKUSy/VXHqLnu7czSZ/ju0quak1o/8kR4jKN\n" + "zj2AC41179gAgY8oBAOgIo1hBAf6tjd9IQdJ0glhaZiQo1ipAgMBAAGjdjB0MAwG\n" + "A1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDwYDVR0PAQH/BAUDAweg\n" + "ADAdBgNVHQ4EFgQUTLkKm/odNON+3svSBxX+odrLaJEwHwYDVR0jBBgwFoAU6Twc\n" + "+62SbuYGpFYsouHAUyfI8pUwCwYJKoZIhvcNAQEFA4GBALujmBJVZnvaTXr9cFRJ\n" + "jpfc/3X7sLUsMvumcDE01ls/cG5mIatmiyEU9qI3jbgUf82z23ON/acwJf875D3/\n" + "U7jyOsBJ44SEQITbin2yUeJMIm1tievvdNXBDfW95AM507ShzP12sfiJkJfjjdhy\n" + "dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n"; + +const char key_pem[] = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICXAIBAAKBgQC7ZkP18sXXtozMxd/1iDuxyUtqDqGtIFBACIChT1yj0Phsz+Y8\n" + "9+wEdhMXi2SJIlvA3VN8O+18BLuAuSi+jpvGjqClEsv1Vx6i57u3M0mf47tKrmpN\n" + "aP/JEeIyjc49gAuNde/YAIGPKAQDoCKNYQQH+rY3fSEHSdIJYWmYkKNYqQIDAQAB\n" + "AoGADpmARG5CQxS+AesNkGmpauepiCz1JBF/JwnyiX6vEzUh0Ypd39SZztwrDxvF\n" + "PJjQaKVljml1zkJpIDVsqvHdyVdse8M+Qn6hw4x2p5rogdvhhIL1mdWo7jWeVJTF\n" + "RKB7zLdMPs3ySdtcIQaF9nUAQ2KJEvldkO3m/bRJFEp54k0CQQDYy+RlTmwRD6hy\n" + "7UtMjR0H3CSZJeQ8svMCxHLmOluG9H1UKk55ZBYfRTsXniqUkJBZ5wuV1L+pR9EK\n" + "ca89a+1VAkEA3UmBelwEv2u9cAU1QjKjmwju1JgXbrjEohK+3B5y0ESEXPAwNQT9\n" + "TrDM1m9AyxYTWLxX93dI5QwNFJtmbtjeBQJARSCWXhsoaDRG8QZrCSjBxfzTCqZD\n" + "ZXtl807ymCipgJm60LiAt0JLr4LiucAsMZz6+j+quQbSakbFCACB8SLV1QJBAKZQ\n" + "YKf+EPNtnmta/rRKKvySsi3GQZZN+Dt3q0r094XgeTsAqrqujVNfPhTMeP4qEVBX\n" + "/iVX2cmMTSh3w3z8MaECQEp0XJWDVKOwcTW6Ajp9SowtmiZ3YDYo1LF9igb4iaLv\n" + "sWZGfbnU3ryjvkb6YuFjgtzbZDZHWQCo8/cOtOBmPdk=\n" + "-----END RSA PRIVATE KEY-----\n"; + static int file_reader (void *cls, size_t pos, char *buf, int max) { @@ -93,7 +122,7 @@ http_ahc (void *cls, return MHD_YES; } *ptr = NULL; /* reset when done */ - + file = fopen (url, "r"); if (file == NULL) { @@ -105,7 +134,7 @@ http_ahc (void *cls, } else { - stat (&url[1], &buf); + stat (url, &buf); response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */ &file_reader, file, (MHD_ContentReaderFreeCallback) @@ -115,12 +144,10 @@ http_ahc (void *cls, } return ret; } - + int main (int argc, char *const *argv) { - char keyfile[255] = KEYFILE; - char certfile[255] = CERTFILE; struct MHD_Daemon *TLS_daemon; /* look for HTTPS arguments */ diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -307,7 +307,7 @@ enum MHD_OPTION MHD_OPTION_CONNECTION_MEMORY_LIMIT = 1, /** - * Maximum number of concurrenct connections to + * Maximum number of concurrent connections to * accept (followed by an unsigned int). */ MHD_OPTION_CONNECTION_LIMIT = 2, @@ -345,21 +345,40 @@ enum MHD_OPTION */ MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5, + // TODO rename /** - * Filename for the private key (key.pem) to be used by the + * Filename for the private key (key.pem) to be used by the * HTTPS daemon. This option should be followed by an * "const char*" argument. The memory of the filename must * not be released until the application terminates. + * This should be used in conjunction with 'MHD_OPTION_HTTPS_CERT_PATH'. */ MHD_OPTION_HTTPS_KEY_PATH = 6, /** - * Filename for the certificate (cert.pem) to be used by the + * Filename for the certificate (cert.pem) to be used by the * HTTPS daemon. This option should be followed by an * "const char*" argument. The memory of the filename must * not be released until the application terminates. + * This should be used in conjunction with 'MHD_OPTION_HTTPS_KEY_PATH'. */ MHD_OPTION_HTTPS_CERT_PATH = 7, + + /** + * Memory pointer for the private key (key.pem) to be used by the + * HTTPS daemon. This option should be followed by an + * "const char*" argument. + * This should be used in conjunction with 'MHD_OPTION_HTTPS_MEM_CERT'. + */ + MHD_OPTION_HTTPS_MEM_KEY = 8, + + /** + * Memory pointer for the certificate (cert.pem) to be used by the + * HTTPS daemon. This option should be followed by an + * "const char*" argument. + * This should be used in conjunction with 'MHD_OPTION_HTTPS_MEM_KEY'. + */ + MHD_OPTION_HTTPS_MEM_CERT = 9, }; /** @@ -866,10 +885,10 @@ MHD_post_process (struct MHD_PostProcessor *pp, /** * Release PostProcessor resources. - * + * * @return MHD_YES if processing completed nicely, * MHD_NO if there were spurious characters / formatting - * problems; it is common to ignore the return + * problems; it is common to ignore the return * value of this function */ int MHD_destroy_post_processor (struct MHD_PostProcessor *pp); diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am @@ -1,6 +1,8 @@ -SUBDIRS = . +SUBDIRS = https . -INCLUDES = -I$(top_srcdir)/src/include +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/daemon \ +-I$(top_srcdir)/src/include check_PROGRAMS = \ daemontest_get \ @@ -93,7 +95,6 @@ daemontest_put11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ - daemontest_large_put_SOURCES = \ daemontest_large_put.c daemontest_large_put_LDADD = \ diff --git a/src/testcurl/daemon_HTTPS_test_get.c b/src/testcurl/daemon_HTTPS_test_get.c @@ -1,276 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007 Christian Grothoff - - libmicrohttpd is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemon_HTTPS_test_get.c - * @brief Testcase for libmicrohttpd GET operations - * @author lv-426 - */ - -#include "config.h" -#include "plibc.h" -#include "microhttpd.h" -#include <errno.h> - -#include <curl/curl.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#define BUF_SIZE 1024 -#define MAX_URL_LEN 255 - -/* Test Certificate */ -const char cert_pem[] = - "-----BEGIN CERTIFICATE-----\n" - "MIIB5zCCAVKgAwIBAgIERiYdJzALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n" - "VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTExWhcNMDgwNDE3MTMyOTExWjAZMRcw\n" - "FQYDVQQDEw5HbnVUTFMgdGVzdCBDQTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA\n" - "vuyYeh1vfmslnuggeEKgZAVmQ5ltSdUY7H25WGSygKMUYZ0KT74v8C780qtcNt9T\n" - "7EPH/N6RvB4BprdssgcQLsthR3XKA84jbjjxNCcaGs33lvOz8A1nf8p3hD+cKfRi\n" - "kfYSW2JazLrtCC4yRCas/SPOUxu78of+3HiTfFm/oXUCAwEAAaNDMEEwDwYDVR0T\n" - "AQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBTpPBz7rZJu5gak\n" - "Viyi4cBTJ8jylTALBgkqhkiG9w0BAQUDgYEAiaIRqGfp1jPpNeVhABK60SU0KIAy\n" - "njuu7kHq5peUgYn8Jd9zNzExBOEp1VOipGsf6G66oQAhDFp2o8zkz7ZH71zR4HEW\n" - "KoX6n5Emn6DvcEH/9pAhnGxNHJAoS7czTKv/JDZJhkqHxyrE1fuLsg5Qv25DTw7+\n" - "PfqUpIhz5Bbm7J4=\n" "-----END CERTIFICATE-----\n"; - -const char key_pem[] = - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXAIBAAKBgQC7ZkP18sXXtozMxd/1iDuxyUtqDqGtIFBACIChT1yj0Phsz+Y8\n" - "9+wEdhMXi2SJIlvA3VN8O+18BLuAuSi+jpvGjqClEsv1Vx6i57u3M0mf47tKrmpN\n" - "aP/JEeIyjc49gAuNde/YAIGPKAQDoCKNYQQH+rY3fSEHSdIJYWmYkKNYqQIDAQAB\n" - "AoGADpmARG5CQxS+AesNkGmpauepiCz1JBF/JwnyiX6vEzUh0Ypd39SZztwrDxvF\n" - "PJjQaKVljml1zkJpIDVsqvHdyVdse8M+Qn6hw4x2p5rogdvhhIL1mdWo7jWeVJTF\n" - "RKB7zLdMPs3ySdtcIQaF9nUAQ2KJEvldkO3m/bRJFEp54k0CQQDYy+RlTmwRD6hy\n" - "7UtMjR0H3CSZJeQ8svMCxHLmOluG9H1UKk55ZBYfRTsXniqUkJBZ5wuV1L+pR9EK\n" - "ca89a+1VAkEA3UmBelwEv2u9cAU1QjKjmwju1JgXbrjEohK+3B5y0ESEXPAwNQT9\n" - "TrDM1m9AyxYTWLxX93dI5QwNFJtmbtjeBQJARSCWXhsoaDRG8QZrCSjBxfzTCqZD\n" - "ZXtl807ymCipgJm60LiAt0JLr4LiucAsMZz6+j+quQbSakbFCACB8SLV1QJBAKZQ\n" - "YKf+EPNtnmta/rRKKvySsi3GQZZN+Dt3q0r094XgeTsAqrqujVNfPhTMeP4qEVBX\n" - "/iVX2cmMTSh3w3z8MaECQEp0XJWDVKOwcTW6Ajp9SowtmiZ3YDYo1LF9igb4iaLv\n" - "sWZGfbnU3ryjvkb6YuFjgtzbZDZHWQCo8/cOtOBmPdk=\n" - "-----END RSA PRIVATE KEY-----\n"; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -static int -file_reader (void *cls, size_t pos, char *buf, int max) -{ - FILE *file = cls; - fseek (file, pos, SEEK_SET); - return fread (buf, 1, max, file); -} - -/* HTTP access handler call back */ -static int -http_ahc (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *upload_data, - const char *version, unsigned int *upload_data_size, void **ptr) -{ - static int aptr; - static char full_url[MAX_URL_LEN]; - struct MHD_Response *response; - int ret; - FILE *file; - struct stat buf; - - // TODO never respond on first call - if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) - return MHD_NO; /* unexpected method */ - if (&aptr != *ptr) - { - /* do never respond on first call */ - *ptr = &aptr; - return MHD_YES; - } - *ptr = NULL; /* reset when done */ - - file = fopen (url, "r"); - if (file == NULL) - { - return 1; - } - else - { - stat (&url[1], &buf); - response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */ - &file_reader, file, - (MHD_ContentReaderFreeCallback) - & fclose); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - } - return ret; -} - -static int -test_HTTPS_Get () -{ - struct MHD_Daemon *d; - CURL *c; - struct CBC cbc; - CURLcode errornum; - char *doc_path; - char *url; - /* currently use self as test file - consider better alternatives */ - char *test_file_name = "daemon_HTTPS_test_get"; - struct stat test_file_stat; - FILE *key_file, *cert_file, *test_file; - - /* used to memcmp local copy & deamon supplied copy */ - unsigned char *mem_test_file_local; - unsigned char *mem_test_file_recv; - - /* setup test file path, url */ - doc_path = get_current_dir_name (); - - /* construct url - this might use doc_path */ - url = - (char *) malloc (sizeof (char) * - (strlen (test_file_name) + - strlen ("https://127.0.0.1:42433/"))); - strncat (url, "https://127.0.0.1:42433/", strlen ("https://127.0.0.1:42433/")); - strncat (url, test_file_name, strlen (test_file_name)); - - /* look for test file used for testing */ - key_file = fopen ("key_file", "w"); - cert_file = fopen ("cert_file", "w"); - test_file = fopen (test_file_name, "r"); - if ( key_file == NULL) - { - fprintf (stderr, "Error : failed to open key_file. errno:%d\n", errno); - return 1; - } - if (!cert_file) - { - fprintf (stderr, "Error : failed to open cert_file. errno:%d\n", errno); - return 1; - } - if (!test_file) - { - fprintf (stderr, "Error : failed to open test_file. errno:%d\n", errno); - return 1; - } - if (stat (test_file_name, &test_file_stat) == -1) - return 1; - - /* create test cert & key */ - fwrite (key_pem, 1, sizeof (key_pem), key_file); - fwrite (cert_pem, 1, sizeof (cert_pem), cert_file); - mem_test_file_local = malloc (test_file_stat.st_size); - mem_test_file_recv = malloc (test_file_stat.st_size); - fread (mem_test_file_local, 1, test_file_stat.st_size, test_file); - - fclose (key_file); - fclose (cert_file); - fclose (test_file); - - cbc.buf = mem_test_file_recv; - cbc.size = test_file_stat.st_size; - cbc.pos = 0; - - /* setup test */ - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, - 42433, NULL, NULL, &http_ahc, NULL, - MHD_OPTION_DOC_ROOT, doc_path, MHD_OPTION_END); - if (d == NULL) - return 1; - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, url); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - /* TLS options */ - curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); - curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, "AES256-SHA"); - /* currently skip peer authentication */ - curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); - // curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - if (CURLE_OK != (errornum = curl_easy_perform (c))) - { - fprintf (stderr, - "curl_easy_perform failed: `%s'\n", - curl_easy_strerror (errornum)); - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 2; - } - curl_easy_cleanup (c); - MHD_stop_daemon (d); - if (remove ("key_file") != 0) - fprintf (stderr, "Error : failed to remove key_file.\n"); - if (remove ("cert_file") != 0) - fprintf (stderr, "Error : failed to remove cert_file.\n"); - - fprintf (stderr, "file = %s.\n" , mem_test_file_recv ); - if (memcmp (cbc.buf, mem_test_file_local, test_file_stat.st_size) == 0) - { - // TODO find proper error code - return 1; - } - return 0; -} - -int -main (int argc, char *const *argv) -{ - - unsigned int errorCount = 0; - - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += test_HTTPS_Get (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount == 0; /* 0 == pass */ -}