Skip to content
Snippets Groups Projects
Commit 0970e080 authored by Sergey Lyubka's avatar Sergey Lyubka
Browse files

Added OpenSSL support

parent 52fe1461
No related branches found
No related tags found
No related merge requests found
...@@ -109,6 +109,12 @@ typedef struct stat file_stat_t; ...@@ -109,6 +109,12 @@ typedef struct stat file_stat_t;
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
#ifdef USE_SSL
// Following define gets rid of openssl deprecation messages
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
#include <openssl/ssl.h>
#endif
#include "mongoose.h" #include "mongoose.h"
struct linked_list_link { struct linked_list_link *prev, *next; }; struct linked_list_link { struct linked_list_link *prev, *next; };
...@@ -182,8 +188,8 @@ enum { ...@@ -182,8 +188,8 @@ enum {
ACCESS_CONTROL_LIST, ACCESS_LOG_FILE, AUTH_DOMAIN, CGI_INTERPRETER, ACCESS_CONTROL_LIST, ACCESS_LOG_FILE, AUTH_DOMAIN, CGI_INTERPRETER,
CGI_PATTERN, DOCUMENT_ROOT, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE, CGI_PATTERN, DOCUMENT_ROOT, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
EXTRA_MIME_TYPES, GLOBAL_AUTH_FILE, HIDE_FILES_PATTERN, IDLE_TIMEOUT_MS, EXTRA_MIME_TYPES, GLOBAL_AUTH_FILE, HIDE_FILES_PATTERN, IDLE_TIMEOUT_MS,
INDEX_FILES, LISTENING_PORT, DAV_AUTH_FILE, RUN_AS_USER, INDEX_FILES, LISTENING_PORT, DAV_AUTH_FILE,
SSL_CERTIFICATE, URL_REWRITES, NUM_OPTIONS RUN_AS_USER, SSL_CERTIFICATE, URL_REWRITES, NUM_OPTIONS
}; };
struct mg_server { struct mg_server {
...@@ -193,7 +199,8 @@ struct mg_server { ...@@ -193,7 +199,8 @@ struct mg_server {
struct linked_list_link uri_handlers; struct linked_list_link uri_handlers;
char *config_options[NUM_OPTIONS]; char *config_options[NUM_OPTIONS];
void *server_data; void *server_data;
sock_t ctl[2]; // Control socketpair. Used to wake up from select() call void *ssl_ctx; // SSL context
sock_t ctl[2]; // Control socketpair. Used to wake up from select() call
}; };
// Expandable IO buffer // Expandable IO buffer
...@@ -212,7 +219,9 @@ union endpoint { ...@@ -212,7 +219,9 @@ union endpoint {
}; };
enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT }; enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT };
enum connection_flags { CONN_CLOSE = 1, CONN_SPOOL_DONE = 2, CONN_SSL = 4 }; enum connection_flags {
CONN_CLOSE = 1, CONN_SPOOL_DONE = 2, CONN_SSL_HANDS_SHAKEN = 4
};
struct connection { struct connection {
struct mg_connection mg_conn; // XXX: Must be first struct mg_connection mg_conn; // XXX: Must be first
...@@ -232,6 +241,7 @@ struct connection { ...@@ -232,6 +241,7 @@ struct connection {
int request_len; // Request length, including last \r\n after last header int request_len; // Request length, including last \r\n after last header
int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc
mutex_t mutex; // Guards concurrent mg_write() calls mutex_t mutex; // Guards concurrent mg_write() calls
void *ssl; // SSL descriptor
}; };
static void close_local_endpoint(struct connection *conn); static void close_local_endpoint(struct connection *conn);
...@@ -726,7 +736,7 @@ static void prepare_cgi_environment(struct connection *conn, ...@@ -726,7 +736,7 @@ static void prepare_cgi_environment(struct connection *conn,
addenv(blk, "SCRIPT_FILENAME=%s", prog); addenv(blk, "SCRIPT_FILENAME=%s", prog);
addenv(blk, "PATH_TRANSLATED=%s", prog); addenv(blk, "PATH_TRANSLATED=%s", prog);
addenv(blk, "HTTPS=%s", conn->flags & CONN_SSL ? "on" : "off"); addenv(blk, "HTTPS=%s", conn->ssl != NULL ? "on" : "off");
if ((s = mg_get_header(ri, "Content-Type")) != NULL) if ((s = mg_get_header(ri, "Content-Type")) != NULL)
addenv(blk, "CONTENT_TYPE=%s", s); addenv(blk, "CONTENT_TYPE=%s", s);
...@@ -892,6 +902,15 @@ static struct connection *accept_new_connection(struct mg_server *server) { ...@@ -892,6 +902,15 @@ static struct connection *accept_new_connection(struct mg_server *server) {
closesocket(sock); closesocket(sock);
} else if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) { } else if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) {
closesocket(sock); closesocket(sock);
#ifdef USE_SSL
} else if (server->ssl_ctx != NULL &&
((conn->ssl = SSL_new(server->ssl_ctx)) == NULL ||
SSL_set_fd(conn->ssl, sock) != 1)) {
DBG(("SSL error"));
closesocket(sock);
free(conn);
conn = NULL;
#endif
} else { } else {
set_close_on_exec(sock); set_close_on_exec(sock);
set_non_blocking_mode(sock); set_non_blocking_mode(sock);
...@@ -913,6 +932,9 @@ static void close_conn(struct connection *conn) { ...@@ -913,6 +932,9 @@ static void close_conn(struct connection *conn) {
free(conn->path_info); free(conn->path_info);
free(conn->remote_iobuf.buf); free(conn->remote_iobuf.buf);
free(conn->local_iobuf.buf); free(conn->local_iobuf.buf);
#ifdef USE_SSL
if (conn->ssl != NULL) SSL_free(conn->ssl);
#endif
mutex_destroy(&conn->mutex); mutex_destroy(&conn->mutex);
free(conn); free(conn);
} }
...@@ -1494,7 +1516,12 @@ static int is_error(int n) { ...@@ -1494,7 +1516,12 @@ static int is_error(int n) {
static void write_to_client(struct connection *conn) { static void write_to_client(struct connection *conn) {
struct iobuf *io = &conn->remote_iobuf; struct iobuf *io = &conn->remote_iobuf;
int n = send(conn->client_sock, io->buf, io->len, 0); int n = conn->ssl == NULL ? send(conn->client_sock, io->buf, io->len, 0) :
#ifdef USE_SSL
SSL_write(conn->ssl, io->buf, io->len);
#else
0;
#endif
DBG(("Written %d of %d(%d): [%.*s ...]", n, io->len, io->size, 40, io->buf)); DBG(("Written %d of %d(%d): [%.*s ...]", n, io->len, io->size, 40, io->buf));
...@@ -2914,7 +2941,21 @@ static void process_request(struct connection *conn) { ...@@ -2914,7 +2941,21 @@ static void process_request(struct connection *conn) {
static void read_from_client(struct connection *conn) { static void read_from_client(struct connection *conn) {
char buf[IOBUF_SIZE]; char buf[IOBUF_SIZE];
int n = recv(conn->client_sock, buf, sizeof(buf), 0); int n = 0;
if (conn->ssl != NULL) {
#ifdef USE_SSL
if (conn->flags & CONN_SSL_HANDS_SHAKEN) {
n = SSL_read(conn->ssl, buf, sizeof(buf));
} else {
if (SSL_accept(conn->ssl) == 1) {
conn->flags |= CONN_SSL_HANDS_SHAKEN;
}
return;
}
#endif
} else {
n = recv(conn->client_sock, buf, sizeof(buf), 0);
}
if (is_error(n)) { if (is_error(n)) {
conn->flags |= CONN_CLOSE; conn->flags |= CONN_CLOSE;
...@@ -3167,6 +3208,9 @@ void mg_destroy_server(struct mg_server **server) { ...@@ -3167,6 +3208,9 @@ void mg_destroy_server(struct mg_server **server) {
LINKED_LIST_FOREACH(&(*server)->uri_handlers, lp, tmp) { LINKED_LIST_FOREACH(&(*server)->uri_handlers, lp, tmp) {
free(LINKED_LIST_ENTRY(lp, struct uri_handler, link)); free(LINKED_LIST_ENTRY(lp, struct uri_handler, link));
} }
#ifdef USE_SSL
if ((*server)->ssl_ctx != NULL) SSL_CTX_free((*server)->ssl_ctx);
#endif
free(*server); free(*server);
*server = NULL; *server = NULL;
} }
...@@ -3356,6 +3400,19 @@ const char *mg_set_option(struct mg_server *server, const char *name, ...@@ -3356,6 +3400,19 @@ const char *mg_set_option(struct mg_server *server, const char *name,
} else if (setuid(pw->pw_uid) != 0) { } else if (setuid(pw->pw_uid) != 0) {
error_msg = "setuid() failed"; error_msg = "setuid() failed";
} }
#endif
} else if (ind == SSL_CERTIFICATE) {
#ifdef USE_SSL
SSL_library_init();
//SSL_load_error_strings();
if ((server->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
error_msg = "SSL_CTX_new() failed";
} else if (SSL_CTX_use_certificate_file(server->ssl_ctx, value, 1) == 0 ||
SSL_CTX_use_PrivateKey_file(server->ssl_ctx, value, 1) == 0) {
error_msg = "Cannot load PEM file";
} else {
SSL_CTX_use_certificate_chain_file(server->ssl_ctx, value);
}
#endif #endif
} }
} }
...@@ -3383,7 +3440,13 @@ struct mg_server *mg_create_server(void *server_data) { ...@@ -3383,7 +3440,13 @@ struct mg_server *mg_create_server(void *server_data) {
LINKED_LIST_INIT(&server->active_connections); LINKED_LIST_INIT(&server->active_connections);
LINKED_LIST_INIT(&server->uri_handlers); LINKED_LIST_INIT(&server->uri_handlers);
do { mg_socketpair(server->ctl); } while (server->ctl[0] < 0);
// Create control socket pair. Do it in a loop to protect from
// interrupted syscalls in mg_socketpair().
do {
mg_socketpair(server->ctl);
} while (server->ctl[0] < 0);
server->server_data = server_data; server->server_data = server_data;
server->listening_sock = INVALID_SOCKET; server->listening_sock = INVALID_SOCKET;
set_default_option_values(server->config_options); set_default_option_values(server->config_options);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment