mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-27 12:26:24 +00:00
Moved HTTP client, ssl and some util code into separate files
This commit is contained in:
1 parent
47606a71ee
commit
cafaecfc56
8 files changed
+702
-693
No files matched your search
+179
@@ -0,0 +1,179 @@
|
||||
#include "internal.h"
|
||||
|
||||
#if !defined(NO_SSL)
|
||||
// set_ssl_option() function updates this array.
|
||||
// It loads SSL library dynamically and changes NULLs to the actual addresses
|
||||
// of respective functions. The macros above (like SSL_connect()) are really
|
||||
// just calling these functions indirectly via the pointer.
|
||||
static struct ssl_func ssl_sw[] = {
|
||||
{"SSL_free", NULL},
|
||||
{"SSL_accept", NULL},
|
||||
{"SSL_connect", NULL},
|
||||
{"SSL_read", NULL},
|
||||
{"SSL_write", NULL},
|
||||
{"SSL_get_error", NULL},
|
||||
{"SSL_set_fd", NULL},
|
||||
{"SSL_new", NULL},
|
||||
{"SSL_CTX_new", NULL},
|
||||
{"SSLv23_server_method", NULL},
|
||||
{"SSL_library_init", NULL},
|
||||
{"SSL_CTX_use_PrivateKey_file", NULL},
|
||||
{"SSL_CTX_use_certificate_file",NULL},
|
||||
{"SSL_CTX_set_default_passwd_cb",NULL},
|
||||
{"SSL_CTX_free", NULL},
|
||||
{"SSL_load_error_strings", NULL},
|
||||
{"SSL_CTX_use_certificate_chain_file", NULL},
|
||||
{"SSLv23_client_method", NULL},
|
||||
{"SSL_pending", NULL},
|
||||
{"SSL_CTX_set_verify", NULL},
|
||||
{"SSL_shutdown", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
// Similar array as ssl_sw. These functions could be located in different lib.
|
||||
static struct ssl_func crypto_sw[] = {
|
||||
{"CRYPTO_num_locks", NULL},
|
||||
{"CRYPTO_set_locking_callback", NULL},
|
||||
{"CRYPTO_set_id_callback", NULL},
|
||||
{"ERR_get_error", NULL},
|
||||
{"ERR_error_string", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static pthread_mutex_t *ssl_mutexes;
|
||||
|
||||
static int sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *)) {
|
||||
return (conn->ssl = SSL_new(s)) != NULL &&
|
||||
SSL_set_fd(conn->ssl, conn->client.sock) == 1 &&
|
||||
func(conn->ssl) == 1;
|
||||
}
|
||||
|
||||
// Return OpenSSL error message
|
||||
static const char *ssl_error(void) {
|
||||
unsigned long err;
|
||||
err = ERR_get_error();
|
||||
return err == 0 ? "" : ERR_error_string(err, NULL);
|
||||
}
|
||||
|
||||
static void ssl_locking_callback(int mode, int mutex_num, const char *file,
|
||||
int line) {
|
||||
(void) line;
|
||||
(void) file;
|
||||
|
||||
if (mode & 1) { // 1 is CRYPTO_LOCK
|
||||
(void) pthread_mutex_lock(&ssl_mutexes[mutex_num]);
|
||||
} else {
|
||||
(void) pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long ssl_id_callback(void) {
|
||||
return (unsigned long) pthread_self();
|
||||
}
|
||||
|
||||
#if !defined(NO_SSL_DL)
|
||||
static int load_dll(struct mg_context *ctx, const char *dll_name,
|
||||
struct ssl_func *sw) {
|
||||
union {void *p; void (*fp)(void);} u;
|
||||
void *dll_handle;
|
||||
struct ssl_func *fp;
|
||||
|
||||
if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
|
||||
cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (fp = sw; fp->name != NULL; fp++) {
|
||||
#ifdef _WIN32
|
||||
// GetProcAddress() returns pointer to function
|
||||
u.fp = (void (*)(void)) dlsym(dll_handle, fp->name);
|
||||
#else
|
||||
// dlsym() on UNIX returns void *. ISO C forbids casts of data pointers to
|
||||
// function pointers. We need to use a union to make a cast.
|
||||
u.p = dlsym(dll_handle, fp->name);
|
||||
#endif // _WIN32
|
||||
if (u.fp == NULL) {
|
||||
cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name);
|
||||
return 0;
|
||||
} else {
|
||||
fp->ptr = u.fp;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif // NO_SSL_DL
|
||||
|
||||
// Dynamically load SSL library. Set up ctx->ssl_ctx pointer.
|
||||
static int set_ssl_option(struct mg_context *ctx) {
|
||||
int i, size;
|
||||
const char *pem;
|
||||
|
||||
// If PEM file is not specified and the init_ssl callback
|
||||
// is not specified, skip SSL initialization.
|
||||
if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL) {
|
||||
// MG_INIT_SSL
|
||||
// ctx->callbacks.init_ssl == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(NO_SSL_DL)
|
||||
if (!load_dll(ctx, SSL_LIB, ssl_sw) ||
|
||||
!load_dll(ctx, CRYPTO_LIB, crypto_sw)) {
|
||||
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) {
|
||||
cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If user callback returned non-NULL, that means that user callback has
|
||||
// set up certificate itself. In this case, skip sertificate setting.
|
||||
// MG_INIT_SSL
|
||||
if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 ||
|
||||
SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
|
||||
cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pem != NULL) {
|
||||
(void) SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
|
||||
}
|
||||
|
||||
// Initialize locking callbacks, needed for thread safety.
|
||||
// http://www.openssl.org/support/faq.html#PROG1
|
||||
size = sizeof(pthread_mutex_t) * CRYPTO_num_locks();
|
||||
if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) {
|
||||
cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error());
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < CRYPTO_num_locks(); i++) {
|
||||
pthread_mutex_init(&ssl_mutexes[i], NULL);
|
||||
}
|
||||
|
||||
CRYPTO_set_locking_callback(&ssl_locking_callback);
|
||||
CRYPTO_set_id_callback(&ssl_id_callback);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void uninitialize_ssl(struct mg_context *ctx) {
|
||||
int i;
|
||||
if (ctx->ssl_ctx != NULL) {
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
for (i = 0; i < CRYPTO_num_locks(); i++) {
|
||||
pthread_mutex_destroy(&ssl_mutexes[i]);
|
||||
}
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
}
|
||||
}
|
||||
#endif // !NO_SSL
|
||||
|
||||
Reference in new issue
Block a user