diff options
-rw-r--r-- | src/daemon/Makefile.am | 10 | ||||
-rw-r--r-- | src/daemon/daemon.c | 97 | ||||
-rw-r--r-- | src/daemon/internal.h | 20 | ||||
-rw-r--r-- | src/examples/Makefile.am | 13 | ||||
-rw-r--r-- | src/examples/https_server_example.c | 261 | ||||
-rw-r--r-- | src/include/microhttpd.h | 8 |
6 files changed, 339 insertions, 70 deletions
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 718dd023..365c1cf1 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am | |||
@@ -11,8 +11,6 @@ EXTRA_DIST = SYMBOLS | |||
11 | lib_LTLIBRARIES = \ | 11 | lib_LTLIBRARIES = \ |
12 | libmicrohttpd.la | 12 | libmicrohttpd.la |
13 | 13 | ||
14 | libmicrohttpd_la_LDFLAGS = \ | ||
15 | -export-dynamic -version-info 4:3:0 $(retaincommand) | ||
16 | libmicrohttpd_la_SOURCES = \ | 14 | libmicrohttpd_la_SOURCES = \ |
17 | connection.c connection.h \ | 15 | connection.c connection.h \ |
18 | reason_phrase.c reason_phrase.h \ | 16 | reason_phrase.c reason_phrase.h \ |
@@ -21,7 +19,13 @@ libmicrohttpd_la_SOURCES = \ | |||
21 | memorypool.c memorypool.h \ | 19 | memorypool.c memorypool.h \ |
22 | plibc.h \ | 20 | plibc.h \ |
23 | postprocessor.c \ | 21 | postprocessor.c \ |
24 | response.c response.h | 22 | response.c response.h |
23 | libmicrohttpd_la_LDFLAGS = \ | ||
24 | -export-dynamic -version-info 4:3:0 $(retaincommand) \ | ||
25 | -L$(GNUTLS_LIB_PATH) \ | ||
26 | -lgnutls | ||
27 | libmicrohttpd_la_CPPFLAGS = \ | ||
28 | $(GNUTLS_CPPFLAGS) | ||
25 | 29 | ||
26 | check_PROGRAMS = \ | 30 | check_PROGRAMS = \ |
27 | postprocessor_test \ | 31 | postprocessor_test \ |
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 3578823a..cb70e9a9 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "response.h" | 29 | #include "response.h" |
30 | #include "connection.h" | 30 | #include "connection.h" |
31 | #include "memorypool.h" | 31 | #include "memorypool.h" |
32 | #include <gnutls/gnutls.h> | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * Default connection limit. | 35 | * Default connection limit. |
@@ -52,6 +53,12 @@ | |||
52 | */ | 53 | */ |
53 | #define DEBUG_CONNECT MHD_NO | 54 | #define DEBUG_CONNECT MHD_NO |
54 | 55 | ||
56 | // TODO rm | ||
57 | /* HTTPS file path limit, leaving room for file name */ | ||
58 | #define MHD_PATH_LEN 240 | ||
59 | |||
60 | int MHDS_init (struct MHD_Daemon *daemon); | ||
61 | |||
55 | /** | 62 | /** |
56 | * Obtain the select sets for this daemon. | 63 | * Obtain the select sets for this daemon. |
57 | * | 64 | * |
@@ -174,6 +181,8 @@ MHDS_handle_connection (void *data) | |||
174 | if (con == NULL) | 181 | if (con == NULL) |
175 | abort (); | 182 | abort (); |
176 | 183 | ||
184 | // TODO add connection time out code | ||
185 | |||
177 | /* forward call to handler */ | 186 | /* forward call to handler */ |
178 | con->daemon->default_handler (NULL, con, NULL, NULL, NULL, NULL, NULL, | 187 | con->daemon->default_handler (NULL, con, NULL, NULL, NULL, NULL, NULL, |
179 | NULL); | 188 | NULL); |
@@ -690,6 +699,13 @@ MHD_start_daemon (unsigned int options, | |||
690 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; | 699 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; |
691 | retVal->connection_timeout = 0; /* no timeout */ | 700 | retVal->connection_timeout = 0; /* no timeout */ |
692 | 701 | ||
702 | /* set server default document root path */ | ||
703 | getcwd (retVal->doc_root, MHD_PATH_LEN); | ||
704 | |||
705 | /* initialize ssl path parameters to the local path */ | ||
706 | strcpy (retVal->https_cert_path, "cert.pem"); | ||
707 | strcpy (retVal->https_key_path, "key.pem"); | ||
708 | |||
693 | /* initializes the argument pointer variable */ | 709 | /* initializes the argument pointer variable */ |
694 | va_start (ap, dh_cls); | 710 | va_start (ap, dh_cls); |
695 | 711 | ||
@@ -717,6 +733,22 @@ MHD_start_daemon (unsigned int options, | |||
717 | case MHD_OPTION_PER_IP_CONNECTION_LIMIT: | 733 | case MHD_OPTION_PER_IP_CONNECTION_LIMIT: |
718 | retVal->per_ip_connection_limit = va_arg (ap, unsigned int); | 734 | retVal->per_ip_connection_limit = va_arg (ap, unsigned int); |
719 | break; | 735 | break; |
736 | case MHD_OPTION_DOC_ROOT: | ||
737 | strncpy (retVal->doc_root, va_arg (ap, char *), MHD_PATH_LEN); | ||
738 | break; | ||
739 | case MHD_OPTION_HTTPS_KEY_PATH: | ||
740 | strncpy (retVal->https_key_path, va_arg (ap, char *), MHD_PATH_LEN); | ||
741 | strcat (retVal->https_key_path, DIR_SEPARATOR_STR); | ||
742 | strcat (retVal->https_key_path, "key.pem"); | ||
743 | break; | ||
744 | case MHD_OPTION_HTTPS_CERT_PATH: | ||
745 | |||
746 | strncpy (retVal->https_cert_path, | ||
747 | va_arg (ap, char *), MHD_PATH_LEN); | ||
748 | strcat (retVal->https_cert_path, DIR_SEPARATOR_STR); | ||
749 | strcat (retVal->https_cert_path, "cert.pem"); | ||
750 | break; | ||
751 | |||
720 | default: | 752 | default: |
721 | #if HAVE_MESSAGES | 753 | #if HAVE_MESSAGES |
722 | fprintf (stderr, | 754 | fprintf (stderr, |
@@ -725,6 +757,29 @@ MHD_start_daemon (unsigned int options, | |||
725 | abort (); | 757 | abort (); |
726 | } | 758 | } |
727 | } | 759 | } |
760 | |||
761 | /* initialize HTTPS daemon certificate aspects */ | ||
762 | if (options & MHD_USE_SSL) | ||
763 | { | ||
764 | /* test for private key & certificate file exsitance */ | ||
765 | FILE *cert_file = fopen (retVal->https_cert_path, "r"); | ||
766 | FILE *key_file = fopen (retVal->https_key_path, "r"); | ||
767 | if (key_file == NULL || cert_file == NULL) | ||
768 | { | ||
769 | printf ("missing cert files"); | ||
770 | #if HAVE_MESSAGES | ||
771 | MHD_DLOG (retVal, "Missing X.509 key or certificate file\n"); | ||
772 | #endif | ||
773 | free (retVal); | ||
774 | CLOSE (socket_fd); | ||
775 | return NULL; | ||
776 | } | ||
777 | |||
778 | fclose (cert_file); | ||
779 | fclose (key_file); | ||
780 | MHDS_init (retVal); | ||
781 | } | ||
782 | |||
728 | va_end (ap); | 783 | va_end (ap); |
729 | if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (options | 784 | if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (options |
730 | & | 785 | & |
@@ -793,9 +848,51 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
793 | } | 848 | } |
794 | MHD_cleanup_connections (daemon); | 849 | MHD_cleanup_connections (daemon); |
795 | } | 850 | } |
851 | |||
852 | /* TLS clean up */ | ||
853 | if (daemon->options & MHD_USE_SSL) | ||
854 | { | ||
855 | gnutls_priority_deinit (daemon->priority_cache); | ||
856 | gnutls_global_deinit (); | ||
857 | } | ||
858 | |||
796 | free (daemon); | 859 | free (daemon); |
797 | } | 860 | } |
798 | 861 | ||
862 | int | ||
863 | MHDS_init (struct MHD_Daemon *daemon) | ||
864 | { | ||
865 | gnutls_global_init (); | ||
866 | /* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */ | ||
867 | gnutls_dh_params_init (&daemon->dh_params); | ||
868 | gnutls_dh_params_generate2 (daemon->dh_params, DH_BITS); | ||
869 | |||
870 | // TODO make room for cipher settings adjustment | ||
871 | gnutls_priority_init (&daemon->priority_cache, | ||
872 | "NORMAL:+AES-256-CBC:+RSA:+SHA1:+COMP-NULL", NULL); | ||
873 | |||
874 | /* setup server certificate */ | ||
875 | gnutls_certificate_allocate_credentials (&daemon->x509_cret); | ||
876 | |||
877 | // TODO remove if unused | ||
878 | /* add trusted CAs to certificate */ | ||
879 | // gnutls_certificate_set_x509_trust_file(x509_cret, CAFILE,GNUTLS_X509_FMT_PEM); | ||
880 | |||
881 | /* add Certificate revocation list to certificate */ | ||
882 | //gnutls_certificate_set_x509_crl_file(x509_cret, CRLFILE, GNUTLS_X509_FMT_PEM); | ||
883 | |||
884 | /* sets a certificate private key pair */ | ||
885 | gnutls_certificate_set_x509_key_file (daemon->x509_cret, | ||
886 | daemon->https_cert_path, | ||
887 | daemon->https_key_path, | ||
888 | GNUTLS_X509_FMT_PEM); | ||
889 | |||
890 | gnutls_certificate_set_dh_params (daemon->x509_cret, daemon->dh_params); | ||
891 | |||
892 | // TODO address error case return value | ||
893 | return 0; | ||
894 | } | ||
895 | |||
799 | #ifndef WINDOWS | 896 | #ifndef WINDOWS |
800 | 897 | ||
801 | static struct sigaction sig; | 898 | static struct sigaction sig; |
diff --git a/src/daemon/internal.h b/src/daemon/internal.h index 37075bc0..1084de08 100644 --- a/src/daemon/internal.h +++ b/src/daemon/internal.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <errno.h> | 35 | #include <errno.h> |
36 | #include <fcntl.h> | 36 | #include <fcntl.h> |
37 | #include <signal.h> | 37 | #include <signal.h> |
38 | #include <gnutls/gnutls.h> | ||
38 | 39 | ||
39 | #include "config.h" | 40 | #include "config.h" |
40 | #include "plibc.h" | 41 | #include "plibc.h" |
@@ -58,6 +59,9 @@ | |||
58 | */ | 59 | */ |
59 | #define MHD_BUF_INC_SIZE 2048 | 60 | #define MHD_BUF_INC_SIZE 2048 |
60 | 61 | ||
62 | /* TLS Diffie-Hellman parameter */ | ||
63 | #define DH_BITS 1024 | ||
64 | |||
61 | #if HAVE_MESSAGES | 65 | #if HAVE_MESSAGES |
62 | /** | 66 | /** |
63 | * fprintf-like helper function for logging debug | 67 | * fprintf-like helper function for logging debug |
@@ -606,6 +610,22 @@ struct MHD_Daemon | |||
606 | */ | 610 | */ |
607 | unsigned short port; | 611 | unsigned short port; |
608 | 612 | ||
613 | /* server credintials */ | ||
614 | gnutls_certificate_credentials_t x509_cret; | ||
615 | |||
616 | /* cipher priority cache */ | ||
617 | gnutls_priority_t priority_cache; | ||
618 | |||
619 | /* Diffie-Hellman parameters */ | ||
620 | gnutls_dh_params_t dh_params; | ||
621 | |||
622 | // TODO consider switching to variadic length paths | ||
623 | /* server root path used while serving http pages */ | ||
624 | char doc_root[255]; | ||
625 | |||
626 | char https_key_path[255]; | ||
627 | |||
628 | char https_cert_path[255]; | ||
609 | }; | 629 | }; |
610 | 630 | ||
611 | #endif | 631 | #endif |
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index 189284e2..c42672ab 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am | |||
@@ -6,6 +6,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include | |||
6 | 6 | ||
7 | noinst_PROGRAMS = \ | 7 | noinst_PROGRAMS = \ |
8 | https_server_example \ | 8 | https_server_example \ |
9 | https_echo_server_example \ | ||
9 | https_echo_client_example \ | 10 | https_echo_client_example \ |
10 | minimal_example \ | 11 | minimal_example \ |
11 | querystring_example \ | 12 | querystring_example \ |
@@ -43,6 +44,18 @@ https_server_example_LDADD = \ | |||
43 | https_server_example_LDFLAGS = \ | 44 | https_server_example_LDFLAGS = \ |
44 | -L$(GNUTLS_LIB_PATH) \ | 45 | -L$(GNUTLS_LIB_PATH) \ |
45 | -lgnutls | 46 | -lgnutls |
47 | |||
48 | https_echo_server_example_CPPFLAGS = \ | ||
49 | $(GNUTLS_CPPFLAGS) \ | ||
50 | -I$(top_srcdir)/src/daemon \ | ||
51 | -I$(top_srcdir)/src/include | ||
52 | https_echo_server_example_SOURCES = \ | ||
53 | https_echo_server_example.c | ||
54 | https_echo_server_example_LDADD = \ | ||
55 | $(top_builddir)/src/daemon/libmicrohttpd.la | ||
56 | https_echo_server_example_LDFLAGS = \ | ||
57 | -L$(GNUTLS_LIB_PATH) \ | ||
58 | -lgnutls | ||
46 | 59 | ||
47 | https_echo_client_example_CPPFLAGS = \ | 60 | https_echo_client_example_CPPFLAGS = \ |
48 | $(GNUTLS_CPPFLAGS) \ | 61 | $(GNUTLS_CPPFLAGS) \ |
diff --git a/src/examples/https_server_example.c b/src/examples/https_server_example.c index 78f7176b..459b4aa2 100644 --- a/src/examples/https_server_example.c +++ b/src/examples/https_server_example.c | |||
@@ -20,7 +20,17 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file https_server_example.c | 22 | * @file https_server_example.c |
23 | * @brief a simple echo server using TLS. echo input from client until 'exit' message is received. | 23 | * @brief a simple https file server using TLS. |
24 | * | ||
25 | * This example assumes the existence of a private key file named "key.pem" | ||
26 | * and a server certificate file named "cert.pem". File path for these should be | ||
27 | * provided as command-line arguments. 'certtool' may be used to generate these if | ||
28 | * missing. | ||
29 | * | ||
30 | * Access server with your browser of choice or with curl : | ||
31 | * | ||
32 | * curl --insecure --tlsv1 --ciphers AES256-SHA <url> | ||
33 | * | ||
24 | * @author LV-426 | 34 | * @author LV-426 |
25 | */ | 35 | */ |
26 | 36 | ||
@@ -35,64 +45,76 @@ | |||
35 | #include <string.h> | 45 | #include <string.h> |
36 | #include <stdio.h> | 46 | #include <stdio.h> |
37 | #include <gnutls/gnutls.h> | 47 | #include <gnutls/gnutls.h> |
48 | #include <gcrypt.h> | ||
38 | 49 | ||
39 | #define DH_BITS 1024 | 50 | #define BUF_SIZE 1024 |
40 | #define MAX_BUF 1024 | 51 | #define MAX_URL_LEN 255 |
41 | /* server credintials */ | ||
42 | gnutls_anon_server_credentials_t anoncred; | ||
43 | 52 | ||
44 | /* server Diffie-Hellman parameters */ | 53 | #define KEYFILE "key.pem" |
45 | static gnutls_dh_params_t dh_params; | 54 | #define CERTFILE "cert.pem" |
46 | 55 | ||
56 | // TODO remove if unused | ||
57 | #define CAFILE "ca.pem" | ||
58 | #define CRLFILE "crl.pem" | ||
47 | 59 | ||
48 | /* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */ | 60 | #define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>" |
49 | static int | ||
50 | generate_dh_params (void) | ||
51 | { | ||
52 | |||
53 | gnutls_dh_params_init (&dh_params); | ||
54 | gnutls_dh_params_generate2 (dh_params, DH_BITS); | ||
55 | return 0; | ||
56 | } | ||
57 | 61 | ||
58 | gnutls_session_t | 62 | gnutls_session_t |
59 | initialize_tls_session (void) | 63 | initialize_tls_session (struct MHD_Connection *connection) |
60 | { | 64 | { |
61 | gnutls_session_t session; | 65 | gnutls_session_t session; |
62 | 66 | ||
63 | gnutls_init (&session, GNUTLS_SERVER); | 67 | gnutls_init (&session, GNUTLS_SERVER); |
64 | 68 | ||
65 | gnutls_priority_set_direct (session, "NORMAL:+ANON-DH", NULL); | 69 | /* sets cipher priorities */ |
70 | gnutls_priority_set (session, connection->daemon->priority_cache); | ||
66 | 71 | ||
67 | gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); | 72 | /* set needed credentials for certificate authentication. */ |
68 | 73 | gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, | |
69 | gnutls_dh_set_prime_bits (session, DH_BITS); | 74 | connection->daemon->x509_cret); |
70 | 75 | ||
71 | return session; | 76 | return session; |
72 | } | 77 | } |
73 | 78 | ||
74 | /* Accept Policy Callback */ | ||
75 | static int | 79 | static int |
76 | TLS_echo (void *cls, | 80 | file_reader (void *cls, size_t pos, char *buf, int max) |
77 | struct MHD_Connection *connection, | ||
78 | const char *url, | ||
79 | const char *method, | ||
80 | const char *upload_data, | ||
81 | const char *version, unsigned int *upload_data_size, void **ptr) | ||
82 | { | 81 | { |
82 | FILE *file = cls; | ||
83 | |||
84 | fseek (file, pos, SEEK_SET); | ||
85 | return fread (buf, 1, max, file); | ||
86 | } | ||
87 | |||
88 | /* HTTPS access handler call back */ | ||
89 | static int | ||
90 | https_ahc (void *cls, | ||
91 | struct MHD_Connection *connection, | ||
92 | const char *url, | ||
93 | const char *method, | ||
94 | const char *upload_data, | ||
95 | const char *version, unsigned int *upload_data_size, void **ptr) | ||
96 | { | ||
97 | /* loopback HTTP socket */ | ||
98 | int loopback_sd, err; | ||
99 | ssize_t ret; | ||
100 | struct sockaddr_in servaddr4; | ||
101 | const struct sockaddr *servaddr; | ||
102 | struct sockaddr_in loopback_sa; | ||
103 | socklen_t addrlen; | ||
104 | |||
83 | gnutls_session_t session; | 105 | gnutls_session_t session; |
84 | static int aptr; | 106 | static int aptr; |
85 | struct MHD_Response *response; | 107 | struct MHD_Response *response; |
86 | char buffer[MAX_BUF + 1]; | 108 | char buffer[BUF_SIZE]; |
87 | int ret; | ||
88 | 109 | ||
89 | printf ("accepted connection from %d\n", connection->addr->sin_addr); | 110 | printf ("accepted connection from %d\n", connection->addr->sin_addr); |
90 | 111 | ||
91 | session = initialize_tls_session (); | 112 | session = initialize_tls_session (connection); |
92 | 113 | ||
93 | gnutls_transport_set_ptr (session, connection->socket_fd); | 114 | gnutls_transport_set_ptr (session, connection->socket_fd); |
94 | 115 | ||
95 | ret = gnutls_handshake (session); | 116 | ret = gnutls_handshake (session); |
117 | |||
96 | if (ret < 0) | 118 | if (ret < 0) |
97 | { | 119 | { |
98 | /* set connection as closed */ | 120 | /* set connection as closed */ |
@@ -106,77 +128,182 @@ TLS_echo (void *cls, | |||
106 | printf ("TLS Handshake completed\n"); | 128 | printf ("TLS Handshake completed\n"); |
107 | connection->state = MHDS_HANDSHAKE_COMPLETE; | 129 | connection->state = MHDS_HANDSHAKE_COMPLETE; |
108 | 130 | ||
109 | /* simple echo loop. message encryption/decryption is acheived through 'gnutls_record_send' | 131 | /* initialize loopback socket */ |
110 | * & gnutls_record_recv calls. */ | 132 | loopback_sd = socket (AF_INET, SOCK_STREAM, 0); |
133 | memset (&loopback_sa, '\0', sizeof (loopback_sa)); | ||
134 | loopback_sa.sin_family = AF_INET; | ||
135 | |||
136 | // TODO solve magic number issue - the http's daemons port must be shared with the https daemon - rosolve data sharing point | ||
137 | loopback_sa.sin_port = htons (50000); | ||
138 | inet_pton (AF_INET, "127.0.0.1", &loopback_sa.sin_addr); | ||
139 | |||
140 | /* connect loopback socket */ | ||
141 | err = connect (loopback_sd, (struct sockaddr *) &loopback_sa, | ||
142 | sizeof (loopback_sa)); | ||
143 | if (err < 0) | ||
144 | { | ||
145 | // TODO err handle | ||
146 | fprintf (stderr, "Error : failed to create TLS loopback socket\n"); | ||
147 | exit (1); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * This loop pipes data received through the TLS tunnel into the loopback connection. | ||
152 | * message encryption/decryption is acheived via 'gnutls_record_send' & gnutls_record_recv calls. | ||
153 | */ | ||
154 | memset (buffer, 0, BUF_SIZE); | ||
155 | if (gnutls_record_recv (session, buffer, BUF_SIZE) < 0) | ||
156 | { | ||
157 | fprintf (stderr, "\n*** Received corrupted " | ||
158 | "data(%d). Closing the connection.\n\n", ret); | ||
159 | connection->socket_fd = -1; | ||
160 | gnutls_deinit (session); | ||
161 | return MHD_NO; | ||
162 | } | ||
163 | |||
164 | if (write (loopback_sd, buffer, BUF_SIZE) < 0) | ||
165 | { | ||
166 | printf ("failed to write to TLS loopback socket\n"); | ||
167 | connection->socket_fd = -1; | ||
168 | gnutls_deinit (session); | ||
169 | return MHD_NO; | ||
170 | } | ||
171 | |||
111 | for (;;) | 172 | for (;;) |
112 | { | 173 | { |
113 | memset (buffer, 0, MAX_BUF + 1); | 174 | memset (buffer, 0, BUF_SIZE); |
114 | ret = gnutls_record_recv (session, buffer, MAX_BUF); | 175 | |
176 | ret = read (loopback_sd, buffer, BUF_SIZE); | ||
115 | 177 | ||
116 | if (ret < 0) | 178 | if (ret < 0) |
117 | { | 179 | { |
118 | fprintf (stderr, "\n*** Received corrupted " | 180 | printf ("failed to read from TLS loopback socket\n"); |
119 | "data(%d). Closing the connection.\n\n", ret); | ||
120 | break; | 181 | break; |
121 | } | 182 | } |
122 | else if (ret >= 0) | 183 | |
184 | if (ret == 0) | ||
123 | { | 185 | { |
124 | if (strcmp (buffer, "exit") == 0) | 186 | break; |
125 | { | ||
126 | printf ("\n- Peer has closed the GNUTLS connection\n"); | ||
127 | break; | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | /* echo data back to the client */ | ||
132 | gnutls_record_send (session, buffer, strlen (buffer)); | ||
133 | } | ||
134 | } | 187 | } |
135 | } | ||
136 | printf ("\n"); | ||
137 | 188 | ||
189 | /* echo data back to the client */ | ||
190 | ret = gnutls_record_send (session, buffer, ret); | ||
191 | if (ret < 0) | ||
192 | { | ||
193 | printf ("failed to write to TLS socket\n"); | ||
194 | break; | ||
195 | } | ||
196 | } | ||
138 | /* mark connection as closed */ | 197 | /* mark connection as closed */ |
139 | connection->socket_fd = -1; | 198 | connection->socket_fd = -1; |
140 | |||
141 | gnutls_deinit (session); | 199 | gnutls_deinit (session); |
142 | 200 | ||
201 | return MHD_YES; | ||
202 | } | ||
203 | |||
204 | /* HTTP access handler call back */ | ||
205 | static int | ||
206 | http_ahc (void *cls, | ||
207 | struct MHD_Connection *connection, | ||
208 | const char *url, | ||
209 | const char *method, | ||
210 | const char *upload_data, | ||
211 | const char *version, unsigned int *upload_data_size, void **ptr) | ||
212 | { | ||
213 | static int aptr; | ||
214 | static char full_url[MAX_URL_LEN]; | ||
215 | struct MHD_Response *response; | ||
216 | int ret; | ||
217 | FILE *file; | ||
218 | struct stat buf; | ||
219 | |||
220 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) | ||
221 | return MHD_NO; /* unexpected method */ | ||
222 | if (&aptr != *ptr) | ||
223 | { | ||
224 | /* do never respond on first call */ | ||
225 | *ptr = &aptr; | ||
226 | return MHD_YES; | ||
227 | } | ||
228 | *ptr = NULL; /* reset when done */ | ||
229 | |||
230 | /* assemble full url */ | ||
231 | strcpy (full_url, connection->daemon->doc_root); | ||
232 | strncat (full_url, url, | ||
233 | MAX_URL_LEN - strlen (connection->daemon->doc_root) - 1); | ||
234 | |||
235 | file = fopen (full_url, "r"); | ||
236 | if (file == NULL) | ||
237 | { | ||
238 | response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND), | ||
239 | (void *) PAGE_NOT_FOUND, | ||
240 | MHD_NO, MHD_NO); | ||
241 | ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response); | ||
242 | MHD_destroy_response (response); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | stat (&url[1], &buf); | ||
247 | response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */ | ||
248 | &file_reader, file, | ||
249 | (MHD_ContentReaderFreeCallback) | ||
250 | & fclose); | ||
251 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
252 | MHD_destroy_response (response); | ||
253 | } | ||
143 | return ret; | 254 | return ret; |
144 | } | 255 | } |
145 | 256 | ||
146 | int | 257 | int |
147 | main (int argc, char *const *argv) | 258 | main (int argc, char *const *argv) |
148 | { | 259 | { |
149 | struct MHD_Daemon *daemon; | 260 | char keyfile[255] = KEYFILE; |
261 | char certfile[255] = CERTFILE; | ||
262 | struct MHD_Daemon *HTTP_daemon; | ||
150 | struct MHD_Daemon *TLS_daemon; | 263 | struct MHD_Daemon *TLS_daemon; |
151 | 264 | ||
152 | /* look for HTTPS port argument */ | 265 | /* look for HTTPS arguments */ |
153 | if (argc < 4) | 266 | if (argc < 5) |
154 | { | 267 | { |
155 | printf ("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT\n", argv[0]); | 268 | printf |
269 | ("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT X.509_FILE_PATH\n", | ||
270 | argv[0]); | ||
156 | return 1; | 271 | return 1; |
157 | } | 272 | } |
158 | 273 | ||
159 | gnutls_global_init (); | 274 | // TODO check if this is truly necessary - disallow usage of the blocking /dev/random */ |
160 | 275 | // gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); | |
161 | gnutls_anon_allocate_server_credentials (&anoncred); | ||
162 | 276 | ||
163 | generate_dh_params (); | 277 | HTTP_daemon = |
278 | MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, | ||
279 | atoi (argv[1]), NULL, NULL, &http_ahc, MHD_OPTION_END); | ||
164 | 280 | ||
165 | gnutls_anon_set_server_dh_params (anoncred, dh_params); | 281 | if (HTTP_daemon == NULL) |
282 | { | ||
283 | printf ("Error: failed to start HTTP_daemon"); | ||
284 | return 1; | ||
285 | } | ||
166 | 286 | ||
167 | TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | 287 | TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG |
168 | | MHD_USE_DEBUG | MHD_USE_SSL, | 288 | | MHD_USE_SSL, atoi (argv[3]), |
169 | atoi (argv[3]), NULL, NULL, &TLS_echo, NULL, | 289 | NULL, |
290 | NULL, &https_ahc, | ||
291 | NULL, MHD_OPTION_CONNECTION_TIMEOUT, 256, | ||
292 | MHD_OPTION_HTTPS_KEY_PATH, argv[4], | ||
293 | MHD_OPTION_HTTPS_CERT_PATH, argv[4], | ||
170 | MHD_OPTION_END); | 294 | MHD_OPTION_END); |
171 | 295 | ||
172 | if (TLS_daemon == NULL) | 296 | if (TLS_daemon == NULL) |
173 | return 1; | 297 | { |
298 | printf ("Error: failed to start TLS_daemon"); | ||
299 | return 1; | ||
300 | } | ||
301 | |||
174 | sleep (atoi (argv[2])); | 302 | sleep (atoi (argv[2])); |
175 | 303 | ||
176 | MHD_stop_daemon (daemon); | 304 | MHD_stop_daemon (HTTP_daemon); |
177 | 305 | ||
178 | gnutls_anon_free_server_credentials (anoncred); | 306 | MHD_stop_daemon (TLS_daemon); |
179 | 307 | ||
180 | gnutls_global_deinit (); | ||
181 | return 0; | 308 | return 0; |
182 | } | 309 | } |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 0fd8600a..682b7651 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -345,6 +345,14 @@ enum MHD_OPTION | |||
345 | */ | 345 | */ |
346 | MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5, | 346 | MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5, |
347 | 347 | ||
348 | /* server root path used while serving http pages */ | ||
349 | MHD_OPTION_DOC_ROOT = 6, | ||
350 | |||
351 | /* private key path used by the HTTPS daemon */ | ||
352 | MHD_OPTION_HTTPS_KEY_PATH = 7, | ||
353 | |||
354 | /* certificate path used by the HTTPS daemon */ | ||
355 | MHD_OPTION_HTTPS_CERT_PATH = 8, | ||
348 | }; | 356 | }; |
349 | 357 | ||
350 | /** | 358 | /** |