Basically complete SSL support: Optional OpenSSL and CyaSSl(wolfssl)
Signed-off-by: Jianhui Zhao <jianhuizhao329@gmail.com>main
parent
a0618b0c07
commit
fbbea9df30
|
@ -5,7 +5,7 @@ project(libuhttp C)
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
#add_definitions(--DUH_DEBUG)
|
||||
#add_definitions(-DUH_DEBUG)
|
||||
|
||||
add_definitions(-O -Wall -Werror --std=gnu99 -D_GNU_SOURCE)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
struct ev_loop *loop = EV_DEFAULT;
|
||||
ev_signal *sig_watcher = NULL;
|
||||
struct uh_server *srv;
|
||||
struct uh_server *srv = NULL;
|
||||
|
||||
uh_log_info("libuhttp version: %s\n", uh_version());
|
||||
|
||||
|
@ -46,15 +46,19 @@ int main(int argc, char **argv)
|
|||
srv = uh_server_new(loop, "0.0.0.0", 8000);
|
||||
if (!srv) {
|
||||
uh_log_err("uh_server_new failed\n");
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (uh_ssl_init(srv, "server.pem", "server.key") < 0)
|
||||
goto err;
|
||||
|
||||
uh_register_route(srv, "/test", route_test);
|
||||
|
||||
uh_log_info("Listen on 8000...\n");
|
||||
|
||||
ev_run(loop, 0);
|
||||
|
||||
err:
|
||||
free(sig_watcher);
|
||||
uh_server_free(srv);
|
||||
|
||||
|
|
|
@ -12,26 +12,59 @@ find_package(CyaSSL)
|
|||
|
||||
include_directories(${LIBEV_INCLUDE_DIRS} ${HTTPPARSER_INCLUDE_DIRS})
|
||||
set(EXTRA_LIBS ${LIBEV_LIBRARIES} ${HTTPPARSER_LIBRARIES})
|
||||
set(SOURCE_FILES uhttp.c uhttp_log.c uhttp_buf.c)
|
||||
|
||||
set(UHTTP_FOUND_SSL OFF)
|
||||
set(SOURCE_FILES uhttp.c uhttp_log.c uhttp_buf.c uhttp_ssl.c)
|
||||
|
||||
option(UHTTP_DISABLE_SSL "Disable ssl support" OFF)
|
||||
option(UHTTP_USE_OPENSSL "Force use OpenSSL as SSL backend" OFF)
|
||||
option(UHTTP_USE_CYASSL "Force use CyaSSL as SSL backend" OFF)
|
||||
|
||||
set(UHTTP_SSL_ENABLED OFF)
|
||||
set(UHTTP_SSL_ENABLED_CONFIG 0)
|
||||
set(UHTTP_USE_OPENSSL_CONFIG 0)
|
||||
set(UHTTP_USE_CYASSL_CONFIG 0)
|
||||
|
||||
if(NOT UHTTP_DISABLE_SSL)
|
||||
if(OPENSSL_FOUND)
|
||||
set(UHTTP_FOUND_SSL ON)
|
||||
if(UHTTP_USE_OPENSSL)
|
||||
if(NOT OPENSSL_FOUND)
|
||||
message(FATAL_ERROR "Could NOT find OpenSSL")
|
||||
endif()
|
||||
|
||||
set(UHTTP_SSL_ENABLED ON)
|
||||
set(UHTTP_SSL_ENABLED_CONFIG 1)
|
||||
set(UHTTP_USE_OPENSSL_CONFIG 1)
|
||||
|
||||
list(APPEND EXTRA_LIBS ${OPENSSL_LIBRARIES})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
elseif(CYASSL_FOUND)
|
||||
set(UHTTP_FOUND_SSL ON)
|
||||
elseif(UHTTP_USE_CYASSL)
|
||||
if (NOT CYASSL_FOUND)
|
||||
message(FATAL_ERROR "Could NOT find CyaSSL")
|
||||
endif()
|
||||
|
||||
set(UHTTP_SSL_ENABLED ON)
|
||||
set(UHTTP_SSL_ENABLED_CONFIG 1)
|
||||
set(UHTTP_USE_CYASSL_CONFIG 1)
|
||||
|
||||
list(APPEND EXTRA_LIBS ${CYASSL_LIBRARIES})
|
||||
include_directories(${CYASSL_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UHTTP_FOUND_SSL)
|
||||
list(APPEND SOURCE_FILES uhttp_ssl.c)
|
||||
if(NOT UHTTP_SSL_ENABLED)
|
||||
if(OPENSSL_FOUND)
|
||||
set(UHTTP_SSL_ENABLED ON)
|
||||
set(UHTTP_SSL_ENABLED_CONFIG 1)
|
||||
set(UHTTP_USE_OPENSSL_CONFIG 1)
|
||||
|
||||
list(APPEND EXTRA_LIBS ${OPENSSL_LIBRARIES})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
elseif(CYASSL_FOUND)
|
||||
set(UHTTP_SSL_ENABLED ON)
|
||||
set(UHTTP_SSL_ENABLED_CONFIG 1)
|
||||
set(UHTTP_USE_CYASSL_CONFIG 1)
|
||||
|
||||
list(APPEND EXTRA_LIBS ${CYASSL_LIBRARIES})
|
||||
include_directories(${CYASSL_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(uhttp SHARED ${SOURCE_FILES})
|
||||
|
@ -52,7 +85,10 @@ install(
|
|||
)
|
||||
|
||||
message("")
|
||||
message(STATUS "UHTTP_VERSION = ${UHTTP_VERSION_MAJOR}.${UHTTP_VERSION_MINOR}")
|
||||
message(STATUS "UHTTP_DISABLE_SSL = ${UHTTP_DISABLE_SSL}")
|
||||
message(STATUS "UHTTP_FOUND_SSL = ${UHTTP_FOUND_SSL}")
|
||||
message(STATUS "UHTTP_VERSION: ${UHTTP_VERSION_MAJOR}.${UHTTP_VERSION_MINOR}")
|
||||
if(UHTTP_USE_OPENSSL_CONFIG)
|
||||
message(STATUS "UHTTP_SSL_ENABLED: OpenSSL")
|
||||
elseif(UHTTP_USE_CYASSL_CONFIG)
|
||||
message(STATUS "UHTTP_SSL_ENABLED: CyaSSL")
|
||||
endif()
|
||||
message("")
|
23
src/uhttp.c
23
src/uhttp.c
|
@ -1,14 +1,13 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <http_parser.h>
|
||||
|
||||
#include "uhttp.h"
|
||||
#include "uhttp_internal.h"
|
||||
#include "uhttp_ssl.h"
|
||||
|
||||
static struct {
|
||||
int code;
|
||||
|
@ -61,6 +60,8 @@ static void uh_connection_destroy(struct uh_connection *con)
|
|||
ev_timer_stop(loop, &con->timer_watcher);
|
||||
|
||||
list_del(&con->list);
|
||||
|
||||
uh_ssl_free(con);
|
||||
free(con);
|
||||
}
|
||||
}
|
||||
|
@ -201,9 +202,9 @@ static void connection_read_cb(struct ev_loop *loop, ev_io *w, int revents)
|
|||
|
||||
base = buf->base + buf->len;
|
||||
|
||||
len = read(w->fd, base, UH_BUFFER_SIZE);
|
||||
len = uh_ssl_read(con, base, UH_BUFFER_SIZE);
|
||||
if (unlikely(len < 0)) {
|
||||
if (errno == EINTR)
|
||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return;
|
||||
uh_log_err("read");
|
||||
uh_send_error(con, 500, NULL);
|
||||
|
@ -234,7 +235,7 @@ static void connection_write_cb(struct ev_loop *loop, ev_io *w, int revents)
|
|||
struct uh_buf *buf = &con->write_buf;
|
||||
|
||||
if (buf->len > 0) {
|
||||
int len = write(w->fd, buf->base, buf->len);
|
||||
int len = uh_ssl_write(con, buf->base, buf->len);
|
||||
uh_buf_remove(buf, len);
|
||||
}
|
||||
|
||||
|
@ -252,8 +253,6 @@ static void connection_write_cb(struct ev_loop *loop, ev_io *w, int revents)
|
|||
static void uh_accept_cb(struct ev_loop *loop, ev_io *w, int revents)
|
||||
{
|
||||
int sock = -1;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
struct uh_server *srv = container_of(w, struct uh_server, read_watcher);
|
||||
struct uh_connection *con = NULL;
|
||||
ev_io *read_watcher, *write_watcher;
|
||||
|
@ -268,15 +267,13 @@ static void uh_accept_cb(struct ev_loop *loop, ev_io *w, int revents)
|
|||
con->srv = srv;
|
||||
list_add(&con->list, &srv->connections);
|
||||
|
||||
sock = accept4(w->fd, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
sock = uh_ssl_accept(srv, con);
|
||||
if (unlikely(sock < 0)) {
|
||||
if (errno != EINTR)
|
||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
uh_log_err("accept");
|
||||
goto err;
|
||||
}
|
||||
|
||||
con->sock = sock;
|
||||
|
||||
read_watcher = &con->read_watcher;
|
||||
ev_io_init(read_watcher, connection_read_cb, sock, EV_READ);
|
||||
ev_io_start(loop,read_watcher);
|
||||
|
@ -373,6 +370,8 @@ void uh_server_free(struct uh_server *srv)
|
|||
free(r);
|
||||
}
|
||||
|
||||
uh_ssl_ctx_free(srv);
|
||||
|
||||
free(srv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,4 +86,6 @@ int uh_register_route(struct uh_server *srv, const char *path, uh_route_handler_
|
|||
struct uh_value *uh_get_url(struct uh_connection *con);
|
||||
struct uh_value *uh_get_header(struct uh_connection *con, const char *name);
|
||||
|
||||
int uh_ssl_init(struct uh_server *srv, const char *cert, const char *key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define UHTTP_VERSION_MINOR @UHTTP_VERSION_MINOR@
|
||||
#define UHTTP_VERSION_STRING "@UHTTP_VERSION_MAJOR@.@UHTTP_VERSION_MINOR@"
|
||||
|
||||
#define UHTTP_SSL_ENABLED @SSL_ENABLED@
|
||||
#define UHTTP_USE_OPENSSL @USE_OPENSSL@
|
||||
#define UHTTP_USE_CYASSL @USE_CYASSL@
|
||||
#define UHTTP_SSL_ENABLED @UHTTP_SSL_ENABLED_CONFIG@
|
||||
#define UHTTP_USE_OPENSSL @UHTTP_USE_OPENSSL_CONFIG@
|
||||
#define UHTTP_USE_CYASSL @UHTTP_USE_CYASSL_CONFIG@
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _UHTTP_INTERNAL_H
|
||||
#define _UHTTP_INTERNAL_H
|
||||
|
||||
#include <http_parser.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "uhttp.h"
|
||||
|
||||
|
@ -21,6 +23,9 @@ struct uh_route {
|
|||
|
||||
struct uh_server {
|
||||
int sock;
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
void *ssl_ctx;
|
||||
#endif
|
||||
ev_io read_watcher;
|
||||
struct ev_loop *loop;
|
||||
struct list_head routes;
|
||||
|
@ -41,6 +46,9 @@ struct uh_request {
|
|||
|
||||
struct uh_connection {
|
||||
int sock;
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
void *ssl;
|
||||
#endif
|
||||
unsigned char flags;
|
||||
struct uh_buf read_buf;
|
||||
struct uh_buf write_buf;
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
#include "uhttp_ssl.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
#include <wolfssl/ssl.h>
|
||||
#endif
|
||||
|
||||
int uh_ssl_init(struct uh_server *srv, const char *cert, const char *key)
|
||||
{
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
SSL_CTX *ctx = NULL;
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
WOLFSSL_CTX *ctx = NULL;
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
SSL_library_init();
|
||||
|
||||
/* creates a new SSL_CTX object */
|
||||
ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (!ctx) {
|
||||
uh_log_err("Failed to create SSL context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* loads the first certificate stored in file into ctx */
|
||||
if (!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) {
|
||||
uh_log_err("OpenSSL Error: loading certificate file failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* adds the first private RSA key found in file to ctx.
|
||||
*
|
||||
* checks the consistency of a private key with the corresponding
|
||||
* certificate loaded into ctx. If more than one key/certificate
|
||||
* pair (RSA/DSA) is installed, the last item installed will be checked.
|
||||
*/
|
||||
if (!SSL_CTX_use_RSAPrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
|
||||
uh_log_err("OpenSSL Error: loading key failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
/* Initialize wolfSSL */
|
||||
wolfSSL_Init();
|
||||
|
||||
/* Create the WOLFSSL_CTX */
|
||||
ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
|
||||
if (!ctx) {
|
||||
uh_log_err("Failed to create wolfSSL context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load server certificates into WOLFSSL_CTX */
|
||||
if (wolfSSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) != SSL_SUCCESS) {
|
||||
uh_log_err("wolfSSL Error: loading certificate file failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Load keys */
|
||||
if (wolfSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) != SSL_SUCCESS){
|
||||
uh_log_err("wolfSSL Error: loading key failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
srv->ssl_ctx = ctx;
|
||||
#endif
|
||||
return 0;
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
err:
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
SSL_CTX_free(ctx);
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
wolfSSL_CTX_free(ctx);
|
||||
wolfSSL_Cleanup();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uh_ssl_ctx_free(struct uh_server *srv)
|
||||
{
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
if (!srv->ssl_ctx)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
SSL_CTX_free(srv->ssl_ctx);
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
wolfSSL_CTX_free(srv->ssl_ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void uh_ssl_free(struct uh_connection *con)
|
||||
{
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
if (!con->ssl)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
SSL_free(con->ssl);
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
wolfSSL_free(con->ssl);
|
||||
#endif
|
||||
}
|
||||
|
||||
int uh_ssl_read(struct uh_connection *con, void *buf, int count)
|
||||
{
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
if (!con->ssl)
|
||||
return read(con->sock, buf, count);
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
return SSL_read(con->ssl, buf, count);
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
return wolfSSL_read(con->ssl, buf, count);
|
||||
#endif
|
||||
|
||||
return read(con->sock, buf, count);
|
||||
}
|
||||
|
||||
int uh_ssl_write(struct uh_connection *con, void *buf, int count)
|
||||
{
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
if (!con->ssl)
|
||||
return write(con->sock, buf, count);
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
return SSL_write(con->ssl, buf, count);
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
return wolfSSL_write(con->ssl, buf, count);
|
||||
#endif
|
||||
|
||||
return write(con->sock, buf, count);
|
||||
}
|
||||
|
||||
int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con)
|
||||
{
|
||||
int sock = -1;
|
||||
|
||||
sock = accept4(srv->sock, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if (sock < 0)
|
||||
return sock;
|
||||
|
||||
con->sock = sock;
|
||||
|
||||
#if (UHTTP_SSL_ENABLED)
|
||||
if (!srv->ssl_ctx)
|
||||
return sock;
|
||||
#endif
|
||||
|
||||
#if (UHTTP_USE_OPENSSL)
|
||||
con->ssl = SSL_new(srv->ssl_ctx);
|
||||
if (!con->ssl)
|
||||
return -1;
|
||||
|
||||
SSL_set_fd(con->ssl, sock);
|
||||
|
||||
if (!SSL_accept(con->ssl)) {
|
||||
uh_log_err("SSL_accept Error: %s", ERR_reason_error_string(ERR_get_error()));
|
||||
return -1;
|
||||
}
|
||||
#elif (UHTTP_USE_CYASSL)
|
||||
con->ssl = wolfSSL_new(srv->ssl_ctx);
|
||||
if (!con->ssl)
|
||||
return -1;
|
||||
|
||||
wolfSSL_set_fd(con->ssl, sock);
|
||||
#endif
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _UHTTP_SSL_H
|
||||
#define _UHTTP_SSL_H
|
||||
|
||||
#include "uhttp_internal.h"
|
||||
|
||||
void uh_ssl_ctx_free(struct uh_server *srv);
|
||||
void uh_ssl_free(struct uh_connection *con);
|
||||
int uh_ssl_read(struct uh_connection *con, void *buf, int count);
|
||||
int uh_ssl_write(struct uh_connection *con, void *buf, int count);
|
||||
int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue