@@ -1594,8 +1594,9 @@ static int mg_init_library_called = 0;
15941594static int mg_openssl_initialized = 0;
15951595#endif
15961596#if !defined(OPENSSL_API_1_0) && !defined(OPENSSL_API_1_1) \
1597- && !defined(OPENSSL_API_3_0) && !defined(USE_MBEDTLS)
1598- #error "Please define OPENSSL_API_#_# or USE_MBEDTLS"
1597+ && !defined(OPENSSL_API_3_0) && !defined(USE_MBEDTLS) \
1598+ && !defined(USE_GNUTLS)
1599+ #error "Please define OPENSSL_API_#_# or USE_MBEDTLS or USE_GNUTLS"
15991600#endif
16001601#if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_1_1)
16011602#error "Multiple OPENSSL_API versions defined"
@@ -1608,7 +1609,10 @@ static int mg_openssl_initialized = 0;
16081609#endif
16091610#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \
16101611 || defined(OPENSSL_API_3_0)) \
1611- && defined(USE_MBEDTLS)
1612+ && (defined(USE_MBEDTLS) || defined(USE_GNUTLS))
1613+ #error "Multiple SSL libraries defined"
1614+ #endif
1615+ #if defined(USE_MBEDTLS) && defined(USE_GNUTLS)
16121616#error "Multiple SSL libraries defined"
16131617#endif
16141618#endif
@@ -1773,11 +1777,15 @@ typedef int socklen_t;
17731777#endif
17741778
17751779
1776- /* SSL: mbedTLS vs. no-ssl vs. OpenSSL */
1780+ /* SSL: mbedTLS vs. GnuTLS vs. no-ssl vs. OpenSSL */
17771781#if defined(USE_MBEDTLS)
17781782/* mbedTLS */
17791783#include "mod_mbedtls.inl"
17801784
1785+ #elif defined(USE_GNUTLS)
1786+ /* GnuTLS */
1787+ #include "mod_gnutls.inl"
1788+
17811789#elif defined(NO_SSL)
17821790/* no SSL */
17831791typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
@@ -2564,7 +2572,6 @@ struct mg_connection {
25642572 * versions. For the current definition, see
25652573 * mg_get_connection_info_impl */
25662574#endif
2567-
25682575 SSL *ssl; /* SSL descriptor */
25692576 struct socket client; /* Connected client */
25702577 time_t conn_birth_time; /* Time (wall clock) when connection was
@@ -3330,6 +3337,7 @@ mg_get_server_ports(const struct mg_context *ctx,
33303337 ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa)));
33313338 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
33323339 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3340+ ports[cnt].is_optional = ctx->listening_sockets[i].is_optional;
33333341
33343342 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
33353343 /* IPv4 */
@@ -6131,7 +6139,7 @@ push_inner(struct mg_context *ctx,
61316139 return -2;
61326140 }
61336141
6134- #if defined(NO_SSL) && !defined(USE_MBEDTLS)
6142+ #if defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS)
61356143 if (ssl) {
61366144 return -2;
61376145 }
@@ -6157,6 +6165,16 @@ push_inner(struct mg_context *ctx,
61576165 err = 0;
61586166 }
61596167 } else
6168+ #elif defined(USE_GNUTLS)
6169+ if (ssl != NULL) {
6170+ n = gtls_ssl_write(ssl, (const unsigned char *)buf, (size_t) len);
6171+ if (n < 0) {
6172+ fprintf(stderr, "SSL write failed (%d): %s", n, gnutls_strerror(n));
6173+ return -2;
6174+ } else {
6175+ err = 0;
6176+ }
6177+ } else
61606178#elif !defined(NO_SSL)
61616179 if (ssl != NULL) {
61626180 ERR_clear_error();
@@ -6413,6 +6431,62 @@ pull_inner(FILE *fp,
64136431 nread = 0;
64146432 }
64156433
6434+ #elif defined(USE_GNUTLS)
6435+ } else if (conn->ssl != NULL) {
6436+ struct mg_pollfd pfd[2];
6437+ size_t to_read;
6438+ int pollres;
6439+ unsigned int num_sock = 1;
6440+
6441+ to_read = gnutls_record_check_pending(conn->ssl->sess);
6442+
6443+ if (to_read > 0) {
6444+ /* We already know there is no more data buffered in conn->buf
6445+ * but there is more available in the SSL layer. So don't poll
6446+ * conn->client.sock yet. */
6447+
6448+ pollres = 1;
6449+ if (to_read > (size_t)len)
6450+ to_read = (size_t)len;
6451+ } else {
6452+ pfd[0].fd = conn->client.sock;
6453+ pfd[0].events = POLLIN;
6454+
6455+ if (conn->phys_ctx->context_type == CONTEXT_SERVER) {
6456+ pfd[num_sock].fd =
6457+ conn->phys_ctx->thread_shutdown_notification_socket;
6458+ pfd[num_sock].events = POLLIN;
6459+ num_sock++;
6460+ }
6461+
6462+ to_read = (size_t)len;
6463+
6464+ pollres = mg_poll(pfd,
6465+ num_sock,
6466+ (int)(timeout * 1000.0),
6467+ &(conn->phys_ctx->stop_flag));
6468+
6469+ if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) {
6470+ return -2;
6471+ }
6472+ }
6473+
6474+ if (pollres > 0) {
6475+ nread = gtls_ssl_read(conn->ssl, (unsigned char *)buf, to_read);
6476+ if (nread < 0) {
6477+ fprintf(stderr, "SSL read failed (%d): %s", nread, gnutls_strerror(nread));
6478+ return -2;
6479+ } else {
6480+ err = 0;
6481+ }
6482+ } else if (pollres < 0) {
6483+ /* Error */
6484+ return -2;
6485+ } else {
6486+ /* pollres = 0 means timeout */
6487+ nread = 0;
6488+ }
6489+
64166490#elif !defined(NO_SSL)
64176491 } else if (conn->ssl != NULL) {
64186492 int ssl_pending;
@@ -9555,7 +9629,7 @@ connect_socket(
95559629 return 0;
95569630 }
95579631
9558- #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(NO_SSL_DL)
9632+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) && !defined( NO_SSL_DL)
95599633#if defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)
95609634 if (use_ssl && (TLS_client_method == NULL)) {
95619635 if (error != NULL) {
@@ -16660,6 +16734,37 @@ mg_sslctx_init(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
1666016734 : 0;
1666116735}
1666216736
16737+ #elif defined(USE_GNUTLS)
16738+ /* Check if SSL is required.
16739+ * If so, set up ctx->ssl_ctx pointer. */
16740+ static int
16741+ mg_sslctx_init(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
16742+ {
16743+ if (!phys_ctx) {
16744+ return 0;
16745+ }
16746+
16747+ if (!dom_ctx) {
16748+ dom_ctx = &(phys_ctx->dd);
16749+ }
16750+
16751+ if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) {
16752+ /* No SSL port is set. No need to setup SSL. */
16753+ return 1;
16754+ }
16755+
16756+ dom_ctx->ssl_ctx = (SSL_CTX *)mg_calloc(1, sizeof(*dom_ctx->ssl_ctx));
16757+ if (dom_ctx->ssl_ctx == NULL) {
16758+ fprintf(stderr, "ssl_ctx malloc failed\n");
16759+ return 0;
16760+ }
16761+
16762+ return gtls_sslctx_init(dom_ctx->ssl_ctx, dom_ctx->config[SSL_CERTIFICATE])
16763+ == 0
16764+ ? 1
16765+ : 0;
16766+ }
16767+
1666316768#elif !defined(NO_SSL)
1666416769
1666516770static int ssl_use_pem_file(struct mg_context *phys_ctx,
@@ -17935,7 +18040,7 @@ uninitialize_openssl(void)
1793518040#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */
1793618041 }
1793718042}
17938- #endif /* !defined(NO_SSL) && !defined(USE_MBEDTLS) */
18043+ #endif /* !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) */
1793918044
1794018045
1794118046#if !defined(NO_FILESYSTEMS)
@@ -18207,6 +18312,11 @@ close_connection(struct mg_connection *conn)
1820718312 mbed_ssl_close(conn->ssl);
1820818313 conn->ssl = NULL;
1820918314 }
18315+ #elif defined(USE_GNUTLS)
18316+ if (conn->ssl != NULL) {
18317+ gtls_ssl_close(conn->ssl);
18318+ conn->ssl = NULL;
18319+ }
1821018320#elif !defined(NO_SSL)
1821118321 if (conn->ssl != NULL) {
1821218322 /* Run SSL_shutdown twice to ensure completely close SSL connection
@@ -18278,7 +18388,7 @@ mg_close_connection(struct mg_connection *conn)
1827818388
1827918389 close_connection(conn);
1828018390
18281- #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
18391+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) // TODO: mbedTLS client
1828218392 if (((conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT)
1828318393 || (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT))
1828418394 && (conn->phys_ctx->dd.ssl_ctx != NULL)) {
@@ -18380,7 +18490,7 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
1838018490 return NULL;
1838118491 }
1838218492
18383- #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
18493+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) // TODO: mbedTLS client
1838418494#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \
1838518495 && !defined(NO_SSL_DL)
1838618496
@@ -18457,15 +18567,15 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
1845718567 error->text_buffer_size,
1845818568 "Can not create mutex");
1845918569 }
18460- #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
18570+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) // TODO: mbedTLS client
1846118571 SSL_CTX_free(conn->dom_ctx->ssl_ctx);
1846218572#endif
1846318573 closesocket(sock);
1846418574 mg_free(conn);
1846518575 return NULL;
1846618576 }
1846718577
18468- #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
18578+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS) // TODO: mbedTLS client
1846918579 if (use_ssl) {
1847018580 /* TODO: Check ssl_verify_peer and ssl_ca_path here.
1847118581 * SSL_CTX_set_verify call is needed to switch off server
@@ -20186,6 +20296,24 @@ worker_thread_run(struct mg_connection *conn)
2018620296 close_connection(conn);
2018720297 }
2018820298
20299+ #elif defined(USE_GNUTLS)
20300+ /* HTTPS connection */
20301+ if (gtls_ssl_accept(&(conn->ssl),
20302+ conn->dom_ctx->ssl_ctx,
20303+ conn->client.sock,
20304+ conn->phys_ctx)
20305+ == 0) {
20306+ /* conn->dom_ctx is set in get_request */
20307+ /* process HTTPS connection */
20308+ init_connection(conn);
20309+ conn->connection_type = CONNECTION_TYPE_REQUEST;
20310+ conn->protocol_type = PROTOCOL_TYPE_HTTP1;
20311+ process_new_connection(conn);
20312+ } else {
20313+ /* make sure the connection is cleaned up on SSL failure */
20314+ close_connection(conn);
20315+ }
20316+
2018920317#elif !defined(NO_SSL)
2019020318 /* HTTPS connection */
2019120319 if (sslize(conn, SSL_accept, NULL)) {
@@ -20693,6 +20821,13 @@ free_context(struct mg_context *ctx)
2069320821 ctx->dd.ssl_ctx = NULL;
2069420822 }
2069520823
20824+ #elif defined(USE_GNUTLS)
20825+ if (ctx->dd.ssl_ctx != NULL) {
20826+ gtls_sslctx_uninit(ctx->dd.ssl_ctx);
20827+ mg_free(ctx->dd.ssl_ctx);
20828+ ctx->dd.ssl_ctx = NULL;
20829+ }
20830+
2069620831#elif !defined(NO_SSL)
2069720832 /* Deallocate SSL context */
2069820833 if (ctx->dd.ssl_ctx != NULL) {
@@ -21383,7 +21518,7 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
2138321518 }
2138421519#endif
2138521520
21386- #if defined(USE_MBEDTLS)
21521+ #if defined(USE_MBEDTLS) || defined(USE_GNUTLS)
2138721522 if (!mg_sslctx_init(ctx, NULL)) {
2138821523 const char *err_msg = "Error initializing SSL context";
2138921524 /* Fatal error - abort start. */
@@ -21868,7 +22003,7 @@ mg_start_domain2(struct mg_context *ctx,
2186822003 new_dom->shared_lua_websockets = NULL;
2186922004#endif
2187022005
21871- #if !defined(NO_SSL) && !defined(USE_MBEDTLS)
22006+ #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(USE_GNUTLS)
2187222007 if (!init_ssl_ctx(ctx, new_dom)) {
2187322008 /* Init SSL failed */
2187422009 if (error != NULL) {
@@ -21947,7 +22082,7 @@ mg_check_feature(unsigned feature)
2194722082#if !defined(NO_FILES)
2194822083 | MG_FEATURES_FILES
2194922084#endif
21950- #if !defined(NO_SSL) || defined(USE_MBEDTLS)
22085+ #if !defined(NO_SSL) || defined(USE_MBEDTLS) || defined(USE_GNUTLS)
2195122086 | MG_FEATURES_SSL
2195222087#endif
2195322088#if !defined(NO_CGI)
0 commit comments