1
0
mirror of https://github.com/lammertb/libhttp.git synced 2026-01-27 08:02:47 +03:00

Moved set_ssl_option to own file

This commit is contained in:
Lammert Bies
2016-12-09 01:30:47 +01:00
parent 21a0219fe6
commit f8718947b3
5 changed files with 217 additions and 155 deletions

View File

@@ -63,6 +63,7 @@ LIB_SOURCES = src/libhttp.c \
src/httplib_reset_per_request_attributes.c \
src/httplib_set_acl_option.c \
src/httplib_set_gpass_option.c \
src/httplib_set_ssl_option.c \
src/httplib_set_sock_timeout.c \
src/httplib_set_tcp_nodelay.c \
src/httplib_start.c \
@@ -70,7 +71,8 @@ LIB_SOURCES = src/libhttp.c \
src/httplib_uninitialize_ssl.c \
src/httplib_version.c \
src/httplib_websocket_client_thread.c \
src/httplib_worker_thread.c
src/httplib_worker_thread.c \
src/md5.c
LIB_INLINE = src/mod_lua.inl src/md5.inl
APP_SOURCES = src/main.c
WINDOWS_RESOURCES = resources/res.rc

View File

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2016 Lammert Bies
* Copyright (c) 2013-2016 the Civetweb developers
* Copyright (c) 2004-2013 Sergey Lyubka
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "libhttp-private.h"
static void *ssllib_dll_handle; /* Store the ssl library handle. */
/*
* int XX_httplib_set_ssl_option( struct mg_context *ctx );
*
* The function XX_httplib_set_ssl_option() loads the SSL library in a dynamic
* way.
*/
#if !defined(NO_SSL)
int XX_httplib_set_ssl_option( struct mg_context *ctx ) {
const char *pem;
int callback_ret;
int should_verify_peer;
const char *ca_path;
const char *ca_file;
int use_default_verify_paths;
int verify_depth;
time_t now_rt = time(NULL);
struct timespec now_mt;
md5_byte_t ssl_context_id[16];
md5_state_t md5state;
int protocol_ver;
/* If PEM file is not specified and the init_ssl callback
* is not specified, skip SSL initialization. */
if ( ctx == NULL ) return 0;
if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL && ctx->callbacks.init_ssl == NULL) return 1;
if (!XX_httplib_initialize_ssl(ctx)) return 0;
#if !defined(NO_SSL_DL)
if (!ssllib_dll_handle) {
ssllib_dll_handle = XX_httplib_load_dll(ctx, SSL_LIB, XX_httplib_ssl_sw);
if (!ssllib_dll_handle) return 0;
}
#endif /* NO_SSL_DL */
/* Initialize SSL library */
SSL_library_init();
SSL_load_error_strings();
if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_new (server) error: %s", XX_httplib_ssl_error());
return 0;
}
SSL_CTX_clear_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
SSL_CTX_set_options(ctx->ssl_ctx, XX_httplib_ssl_get_protocol(protocol_ver));
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
/* If a callback has been specified, call it. */
callback_ret = (ctx->callbacks.init_ssl == NULL) ? 0 : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
/* If callback returns 0, LibHTTP sets up the SSL certificate.
* If it returns 1, LibHTTP assumes the calback already did this.
* If it returns -1, initializing ssl fails. */
if (callback_ret < 0) {
mg_cry( XX_httplib_fc(ctx), "SSL callback returned error: %i", callback_ret);
return 0;
}
if (callback_ret > 0) {
if (pem != NULL) {
SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
}
return 1;
}
/* Use some UID as session context ID. */
md5_init(&md5state);
md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
clock_gettime(CLOCK_MONOTONIC, &now_mt);
md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
md5_append(&md5state,
(const md5_byte_t *)ctx->config[LISTENING_PORTS],
strlen(ctx->config[LISTENING_PORTS]));
md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
md5_finish(&md5state, ssl_context_id);
SSL_CTX_set_session_id_context(ctx->ssl_ctx, (const unsigned char *)&ssl_context_id, sizeof(ssl_context_id));
if (pem != NULL) {
if (!XX_httplib_ssl_use_pem_file(ctx, pem)) return 0;
}
should_verify_peer =
(ctx->config[SSL_DO_VERIFY_PEER] != NULL)
&& (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
use_default_verify_paths =
(ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
&& (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
if (should_verify_peer) {
ca_path = ctx->config[SSL_CA_PATH];
ca_file = ctx->config[SSL_CA_FILE];
if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
!= 1) {
mg_cry( XX_httplib_fc(ctx),
"SSL_CTX_load_verify_locations error: %s "
"ssl_verify_peer requires setting "
"either ssl_ca_path or ssl_ca_file. Is any of them "
"present in "
"the .conf file?",
XX_httplib_ssl_error());
return 0;
}
SSL_CTX_set_verify(ctx->ssl_ctx,
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
NULL);
if (use_default_verify_paths
&& SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_set_default_verify_paths error: %s", XX_httplib_ssl_error());
return 0;
}
if (ctx->config[SSL_VERIFY_DEPTH]) {
verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
}
}
if (ctx->config[SSL_CIPHER_LIST] != NULL) {
if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST]) != 1) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_set_cipher_list error: %s", XX_httplib_ssl_error());
}
}
return 1;
} /* XX_httplib_set_ssl_option */
#endif /* !NO_SSL */

View File

@@ -842,8 +842,10 @@ void XX_httplib_get_system_name( char **sysName );
int XX_httplib_get_uri_type( const char *uri );
int XX_httplib_getreq( struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err );
void XX_httplib_handle_request( struct mg_connection *conn );
int XX_httplib_initialize_ssl( struct mg_context *ctx );
int XX_httplib_is_valid_port( unsigned long port );
int XX_httplib_join_thread( pthread_t threadid );
void * XX_httplib_load_dll( struct mg_context *ctx, const char *dll_name, struct ssl_func *sw );
void XX_httplib_log_access( const struct mg_connection *conn );
int XX_httplib_parse_http_message( char *buf, int len, struct mg_request_info *ri );
void XX_httplib_process_new_connection( struct mg_connection *conn );
@@ -863,8 +865,10 @@ void XX_httplib_set_thread_name( const char *name );
int XX_httplib_set_uid_option( struct mg_context *ctx );
int XX_httplib_should_keep_alive( const struct mg_connection *conn );
void XX_httplib_snprintf( const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(5, 6);
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa);
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa );
const char * XX_httplib_ssl_error( void );
void XX_httplib_ssl_get_client_cert_info( struct mg_connection *conn );
long XX_httplib_ssl_get_protocol( int version_id );
int XX_httplib_ssl_use_pem_file( struct mg_context *ctx, const char *pem );
int XX_httplib_sslize( struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *) );
int XX_httplib_stat( struct mg_connection *conn, const char *path, struct file *filep );
@@ -875,6 +879,21 @@ int XX_httplib_vprintf( struct mg_connection *conn, const char *fmt, va_list a
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
void md5_init( md5_state_t *pms );
void md5_append( md5_state_t *pms, const md5_byte_t *data, size_t nbytes );
void md5_finish( md5_state_t *pms, md5_byte_t digest[16] );
#ifdef _WIN32
unsigned __stdcall XX_httplib_master_thread( void *thread_func_param );
int XX_httplib_start_thread_with_id( unsigned(__stdcall *f)(void *), void *p, pthread_t *threadidptr );

View File

@@ -464,9 +464,6 @@ static void mg_vsnprintf(const struct mg_connection *conn, int *truncated, char
#define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
#endif
#define MD5_STATIC static
#include "md5.inl"
/* Darwin prior to 7.0 and Win32 do not have socklen_t */
#ifdef NO_SOCKLEN_T
typedef int socklen_t;
@@ -8415,7 +8412,6 @@ ssl_id_callback(void)
}
static const char *ssl_error(void);
static int refresh_trust( struct mg_connection *conn ) {
@@ -8457,7 +8453,7 @@ static int refresh_trust( struct mg_connection *conn ) {
"either ssl_ca_path or ssl_ca_file. Is any of them "
"present in "
"the .conf file?",
ssl_error());
XX_httplib_ssl_error());
return 0;
}
}
@@ -8546,12 +8542,13 @@ int XX_httplib_sslize( struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *
/* Return OpenSSL error message (from CRYPTO lib) */
static const char * ssl_error(void) {
const char * XX_httplib_ssl_error(void) {
unsigned long err;
err = ERR_get_error();
return ((err == 0) ? "" : ERR_error_string(err, NULL));
}
} /* XX_httplib_ssl_error */
static int hexdump2string(void *mem, int memlen, char *buf, int buflen) {
@@ -8647,7 +8644,7 @@ static void ssl_locking_callback(int mode, int mutex_num, const char *file, int
#if !defined(NO_SSL_DL)
static void * load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw) {
void *XX_httplib_load_dll( struct mg_context *ctx, const char *dll_name, struct ssl_func *sw ) {
union {
void *p;
@@ -8679,10 +8676,10 @@ static void * load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_
}
return dll_handle;
}
} /* XX_httplib_load_dll */
static void *ssllib_dll_handle; /* Store the ssl library handle. */
static void *cryptolib_dll_handle; /* Store the crypto library handle. */
#endif /* NO_SSL_DL */
@@ -8695,14 +8692,14 @@ int XX_httplib_cryptolib_users = 0; /* Reference counter for crypto library. */
#endif
static int initialize_ssl(struct mg_context *ctx) {
int XX_httplib_initialize_ssl( struct mg_context *ctx ) {
int i;
size_t size;
#if !defined(NO_SSL_DL)
if (!cryptolib_dll_handle) {
cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, XX_httplib_crypto_sw);
cryptolib_dll_handle = XX_httplib_load_dll(ctx, CRYPTO_LIB, XX_httplib_crypto_sw);
if (!cryptolib_dll_handle) return 0;
}
#endif /* NO_SSL_DL */
@@ -8716,7 +8713,7 @@ static int initialize_ssl(struct mg_context *ctx) {
if (i < 0) i = 0;
size = sizeof(pthread_mutex_t) * ((size_t)(i));
if ((XX_httplib_ssl_mutexes = (pthread_mutex_t *)XX_httplib_malloc(size)) == NULL) {
mg_cry( XX_httplib_fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error());
mg_cry( XX_httplib_fc(ctx), "%s: cannot allocate mutexes: %s", __func__, XX_httplib_ssl_error());
return 0;
}
@@ -8728,19 +8725,20 @@ static int initialize_ssl(struct mg_context *ctx) {
CRYPTO_set_id_callback(&ssl_id_callback);
return 1;
}
} /* XX_httplib_initialize_ssl */
int XX_httplib_ssl_use_pem_file( struct mg_context *ctx, const char *pem ) {
if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
mg_cry( XX_httplib_fc(ctx), "%s: cannot open certificate file %s: %s", __func__, pem, ssl_error());
mg_cry( XX_httplib_fc(ctx), "%s: cannot open certificate file %s: %s", __func__, pem, XX_httplib_ssl_error());
return 0;
}
/* could use SSL_CTX_set_default_passwd_cb_userdata */
if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
mg_cry( XX_httplib_fc(ctx), "%s: cannot open private key file %s: %s", __func__, pem, ssl_error());
mg_cry( XX_httplib_fc(ctx), "%s: cannot open private key file %s: %s", __func__, pem, XX_httplib_ssl_error());
return 0;
}
@@ -8750,7 +8748,7 @@ int XX_httplib_ssl_use_pem_file( struct mg_context *ctx, const char *pem ) {
}
if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
mg_cry( XX_httplib_fc(ctx), "%s: cannot use certificate chain file %s: %s", __func__, pem, ssl_error());
mg_cry( XX_httplib_fc(ctx), "%s: cannot use certificate chain file %s: %s", __func__, pem, XX_httplib_ssl_error());
return 0;
}
return 1;
@@ -8758,7 +8756,7 @@ int XX_httplib_ssl_use_pem_file( struct mg_context *ctx, const char *pem ) {
} /* XX_httplib_ssl_use_pem_file */
static long ssl_get_protocol( int version_id ) {
long XX_httplib_ssl_get_protocol( int version_id ) {
long ret = SSL_OP_ALL;
@@ -8768,141 +8766,7 @@ static long ssl_get_protocol( int version_id ) {
if (version_id > 3) ret |= SSL_OP_NO_TLSv1_1;
return ret;
}
/* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
int XX_httplib_set_ssl_option( struct mg_context *ctx ) {
const char *pem;
int callback_ret;
int should_verify_peer;
const char *ca_path;
const char *ca_file;
int use_default_verify_paths;
int verify_depth;
time_t now_rt = time(NULL);
struct timespec now_mt;
md5_byte_t ssl_context_id[16];
md5_state_t md5state;
int protocol_ver;
/* If PEM file is not specified and the init_ssl callback
* is not specified, skip SSL initialization. */
if (!ctx) {
return 0;
}
if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
&& ctx->callbacks.init_ssl == NULL) {
return 1;
}
if (!initialize_ssl(ctx)) return 0;
#if !defined(NO_SSL_DL)
if (!ssllib_dll_handle) {
ssllib_dll_handle = load_dll(ctx, SSL_LIB, XX_httplib_ssl_sw);
if (!ssllib_dll_handle) return 0;
}
#endif /* NO_SSL_DL */
/* Initialize SSL library */
SSL_library_init();
SSL_load_error_strings();
if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
return 0;
}
SSL_CTX_clear_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
/* If a callback has been specified, call it. */
callback_ret = (ctx->callbacks.init_ssl == NULL) ? 0 : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
/* If callback returns 0, LibHTTP sets up the SSL certificate.
* If it returns 1, LibHTTP assumes the calback already did this.
* If it returns -1, initializing ssl fails. */
if (callback_ret < 0) {
mg_cry( XX_httplib_fc(ctx), "SSL callback returned error: %i", callback_ret);
return 0;
}
if (callback_ret > 0) {
if (pem != NULL) {
SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
}
return 1;
}
/* Use some UID as session context ID. */
md5_init(&md5state);
md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
clock_gettime(CLOCK_MONOTONIC, &now_mt);
md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
md5_append(&md5state,
(const md5_byte_t *)ctx->config[LISTENING_PORTS],
strlen(ctx->config[LISTENING_PORTS]));
md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
md5_finish(&md5state, ssl_context_id);
SSL_CTX_set_session_id_context(ctx->ssl_ctx, (const unsigned char *)&ssl_context_id, sizeof(ssl_context_id));
if (pem != NULL) {
if (!XX_httplib_ssl_use_pem_file(ctx, pem)) return 0;
}
should_verify_peer =
(ctx->config[SSL_DO_VERIFY_PEER] != NULL)
&& (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
use_default_verify_paths =
(ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
&& (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
if (should_verify_peer) {
ca_path = ctx->config[SSL_CA_PATH];
ca_file = ctx->config[SSL_CA_FILE];
if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
!= 1) {
mg_cry( XX_httplib_fc(ctx),
"SSL_CTX_load_verify_locations error: %s "
"ssl_verify_peer requires setting "
"either ssl_ca_path or ssl_ca_file. Is any of them "
"present in "
"the .conf file?",
ssl_error());
return 0;
}
SSL_CTX_set_verify(ctx->ssl_ctx,
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
NULL);
if (use_default_verify_paths
&& SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_set_default_verify_paths error: %s", ssl_error());
return 0;
}
if (ctx->config[SSL_VERIFY_DEPTH]) {
verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
}
}
if (ctx->config[SSL_CIPHER_LIST] != NULL) {
if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST]) != 1) {
mg_cry( XX_httplib_fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
}
}
return 1;
} /* XX_httplib_set_ssl_option */
} /* XX_httplib_ssl_get_protocol */
#endif /* !NO_SSL */

View File

@@ -47,6 +47,11 @@
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
#include <stdlib.h>
#include <string.h>
#define MD5_STATIC
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */