Added SSL/TLS support on connection level.
This commit is contained in:
@@ -149,7 +149,7 @@ $NXT_BUILD_DIR/utf8_file_name_test: $NXT_LIB_UTF8_FILE_NAME_TEST_SRCS \\
|
||||
-o $NXT_BUILD_DIR/utf8_file_name_test \\
|
||||
$NXT_LIB_UTF8_FILE_NAME_TEST_SRCS \\
|
||||
$NXT_BUILD_DIR/$NXT_LIB_STATIC \\
|
||||
$NXT_LD_OPT $NXT_LIBM $NXT_LIBS
|
||||
$NXT_LD_OPT $NXT_LIBM $NXT_LIBS $NXT_LIB_AUX_LIBS
|
||||
|
||||
$NXT_BUILD_DIR/unit_app_test: $NXT_BUILD_DIR/src/test/nxt_unit_app_test.o \\
|
||||
$NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC
|
||||
|
||||
@@ -19,7 +19,7 @@ NXT_UNIX_DOMAIN=YES
|
||||
NXT_REGEX=NO
|
||||
NXT_PCRE=NO
|
||||
|
||||
NXT_SSLTLS=NO
|
||||
NXT_TLS=NO
|
||||
NXT_OPENSSL=NO
|
||||
NXT_GNUTLS=NO
|
||||
NXT_CYASSL=NO
|
||||
@@ -72,7 +72,6 @@ do
|
||||
|
||||
--pcre) NXT_PCRE=YES ;;
|
||||
|
||||
--ssltls) NXT_SSLTLS=YES ;;
|
||||
--openssl) NXT_OPENSSL=YES ;;
|
||||
--gnutls) NXT_GNUTLS=YES ;;
|
||||
--cyassl) NXT_CYASSL=YES ;;
|
||||
|
||||
10
auto/sources
10
auto/sources
@@ -105,8 +105,8 @@ NXT_LIB_SRC0=" \
|
||||
NXT_LIB_UNIT_SRCS="src/nxt_unit.c"
|
||||
|
||||
|
||||
NXT_LIB_SSLTLS_DEPS="src/nxt_ssltls.h"
|
||||
NXT_LIB_SSLTLS_SRCS="src/nxt_ssltls.c"
|
||||
NXT_LIB_TLS_DEPS="src/nxt_tls.h"
|
||||
NXT_LIB_TLS_SRCS=
|
||||
NXT_LIB_OPENSSL_SRCS="src/nxt_openssl.c"
|
||||
NXT_LIB_GNUTLS_SRCS="src/nxt_gnutls.c"
|
||||
NXT_LIB_CYASSL_SRCS="src/nxt_cyassl.c"
|
||||
@@ -157,9 +157,9 @@ NXT_LIB_UTF8_FILE_NAME_TEST_SRCS=" \
|
||||
"
|
||||
|
||||
|
||||
if [ $NXT_SSLTLS = YES ]; then
|
||||
nxt_have=NXT_SSLTLS . auto/have
|
||||
NXT_LIB_SRCS="$NXT_LIB_SRCS $NXT_LIB_SSLTLS_SRCS"
|
||||
if [ $NXT_TLS = YES ]; then
|
||||
nxt_have=NXT_TLS . auto/have
|
||||
NXT_LIB_SRCS="$NXT_LIB_SRCS $NXT_LIB_TLS_SRCS"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ if [ $NXT_OPENSSL = YES ]; then
|
||||
|
||||
|
||||
if [ $nxt_found = yes ]; then
|
||||
NXT_SSLTLS=YES
|
||||
NXT_TLS=YES
|
||||
NXT_OPENSSL_LIBS="$nxt_feature_libs"
|
||||
|
||||
nxt_feature="OpenSSL version"
|
||||
@@ -78,7 +78,7 @@ if [ $NXT_GNUTLS = YES ]; then
|
||||
|
||||
|
||||
if [ $nxt_found = yes ]; then
|
||||
NXT_SSLTLS=YES
|
||||
NXT_TLS=YES
|
||||
|
||||
$echo " + GnuTLS version: `pkg-config gnutls --modversion`"
|
||||
|
||||
@@ -138,7 +138,7 @@ if [ $NXT_CYASSL = YES ]; then
|
||||
|
||||
|
||||
if [ $nxt_found = yes ]; then
|
||||
NXT_SSLTLS=YES
|
||||
NXT_TLS=YES
|
||||
NXT_CYASSL_CFLAGS="$nxt_feature_incs"
|
||||
NXT_CYASSL_LIBS="$nxt_feature_libs"
|
||||
|
||||
@@ -171,7 +171,7 @@ if [ $NXT_POLARSSL = YES ]; then
|
||||
|
||||
|
||||
if [ $nxt_found = yes ]; then
|
||||
NXT_SSLTLS=YES
|
||||
NXT_TLS=YES
|
||||
NXT_POLARSSL_CFLAGS="$nxt_feature_incs"
|
||||
NXT_POLARSSL_LIBS="$nxt_feature_libs"
|
||||
|
||||
|
||||
@@ -8,36 +8,34 @@
|
||||
|
||||
|
||||
nxt_conn_io_t nxt_unix_conn_io = {
|
||||
nxt_conn_io_connect,
|
||||
nxt_conn_io_accept,
|
||||
.connect = nxt_conn_io_connect,
|
||||
.accept = nxt_conn_io_accept,
|
||||
|
||||
nxt_conn_io_read,
|
||||
nxt_conn_io_recvbuf,
|
||||
nxt_conn_io_recv,
|
||||
.read = nxt_conn_io_read,
|
||||
.recvbuf = nxt_conn_io_recvbuf,
|
||||
.recv = nxt_conn_io_recv,
|
||||
|
||||
nxt_conn_io_write,
|
||||
nxt_event_conn_io_write_chunk,
|
||||
.write = nxt_conn_io_write,
|
||||
.sendbuf = nxt_conn_io_sendbuf,
|
||||
|
||||
#if (NXT_HAVE_LINUX_SENDFILE)
|
||||
nxt_linux_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_linux_event_conn_io_sendfile,
|
||||
#elif (NXT_HAVE_FREEBSD_SENDFILE)
|
||||
nxt_freebsd_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_freebsd_event_conn_io_sendfile,
|
||||
#elif (NXT_HAVE_MACOSX_SENDFILE)
|
||||
nxt_macosx_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_macosx_event_conn_io_sendfile,
|
||||
#elif (NXT_HAVE_SOLARIS_SENDFILEV)
|
||||
nxt_solaris_event_conn_io_sendfilev,
|
||||
.old_sendbuf = nxt_solaris_event_conn_io_sendfilev,
|
||||
#elif (NXT_HAVE_AIX_SEND_FILE)
|
||||
nxt_aix_event_conn_io_send_file,
|
||||
.old_sendbuf = nxt_aix_event_conn_io_send_file,
|
||||
#elif (NXT_HAVE_HPUX_SENDFILE)
|
||||
nxt_hpux_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_hpux_event_conn_io_sendfile,
|
||||
#else
|
||||
nxt_event_conn_io_sendbuf,
|
||||
.old_sendbuf = nxt_event_conn_io_sendbuf,
|
||||
#endif
|
||||
|
||||
nxt_event_conn_io_writev,
|
||||
nxt_event_conn_io_send,
|
||||
|
||||
nxt_conn_io_shutdown,
|
||||
.writev = nxt_event_conn_io_writev,
|
||||
.send = nxt_event_conn_io_send,
|
||||
};
|
||||
|
||||
|
||||
@@ -103,40 +101,6 @@ nxt_conn_free(nxt_task_t *task, nxt_conn_t *c)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
||||
{
|
||||
int ret;
|
||||
nxt_conn_t *c;
|
||||
|
||||
static const struct linger linger_off = {
|
||||
.l_onoff = 1,
|
||||
.l_linger = 0,
|
||||
};
|
||||
|
||||
c = obj;
|
||||
|
||||
nxt_debug(task, "event conn shutdown");
|
||||
|
||||
if (c->socket.timedout) {
|
||||
/*
|
||||
* Resetting of timed out connection on close
|
||||
* releases kernel memory associated with socket.
|
||||
* This also causes sending TCP/IP RST to a peer.
|
||||
*/
|
||||
ret = setsockopt(c->socket.fd, SOL_SOCKET, SO_LINGER, &linger_off,
|
||||
sizeof(struct linger));
|
||||
|
||||
if (nxt_slow_path(ret != 0)) {
|
||||
nxt_alert(task, "setsockopt(%d, SO_LINGER) failed %E",
|
||||
c->socket.fd, nxt_socket_errno);
|
||||
}
|
||||
}
|
||||
|
||||
c->write_state->close_handler(task, c, data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c,
|
||||
const nxt_conn_state_t *state, nxt_timer_t *timer)
|
||||
|
||||
@@ -56,26 +56,20 @@ typedef struct {
|
||||
ssize_t (*recv)(nxt_conn_t *c, void *buf,
|
||||
size_t size, nxt_uint_t flags);
|
||||
|
||||
/*
|
||||
* The write() is an interface to write a buffer chain with a given rate
|
||||
* limit. It calls write_chunk() in a loop and handles write event timer.
|
||||
*/
|
||||
/* The write() is an interface to write a buffer chain. */
|
||||
nxt_work_handler_t write;
|
||||
|
||||
/*
|
||||
* The write_chunk() interface writes a buffer chain with a given limit
|
||||
* and toggles write event. SSL/TLS libraries' write_chunk() interface
|
||||
* buffers data and calls the library specific send() interface to write
|
||||
* the buffered data eventually.
|
||||
*/
|
||||
ssize_t (*write_chunk)(nxt_conn_t *c,
|
||||
nxt_buf_t *b, size_t limit);
|
||||
|
||||
/*
|
||||
* The sendbuf() is an interface for OS-specific sendfile
|
||||
* implementations or simple writev().
|
||||
*/
|
||||
ssize_t (*sendbuf)(nxt_conn_t *c, nxt_buf_t *b,
|
||||
ssize_t (*sendbuf)(nxt_task_t *task,
|
||||
nxt_sendbuf_t *sb);
|
||||
/*
|
||||
* The sendbuf() is an interface for OS-specific sendfile
|
||||
* implementations or simple writev().
|
||||
*/
|
||||
ssize_t (*old_sendbuf)(nxt_conn_t *c, nxt_buf_t *b,
|
||||
size_t limit);
|
||||
/*
|
||||
* The writev() is an interface to write several nxt_iobuf_t buffers.
|
||||
@@ -146,8 +140,8 @@ struct nxt_conn_s {
|
||||
nxt_conn_io_t *io;
|
||||
|
||||
union {
|
||||
#if (NXT_SSLTLS)
|
||||
void *ssltls;
|
||||
#if (NXT_TLS)
|
||||
void *tls;
|
||||
#endif
|
||||
nxt_thread_pool_t *thread_pool;
|
||||
} u;
|
||||
@@ -225,7 +219,6 @@ struct nxt_conn_s {
|
||||
|
||||
NXT_EXPORT nxt_conn_t *nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task);
|
||||
NXT_EXPORT void nxt_conn_free(nxt_task_t *task, nxt_conn_t *c);
|
||||
void nxt_conn_io_shutdown(nxt_task_t *task, void *obj, void *data);
|
||||
NXT_EXPORT void nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c);
|
||||
|
||||
NXT_EXPORT void nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c,
|
||||
@@ -265,8 +258,6 @@ ssize_t nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf,
|
||||
size_t nxt_event_conn_write_limit(nxt_conn_t *c);
|
||||
nxt_bool_t nxt_event_conn_write_delayed(nxt_event_engine_t *engine,
|
||||
nxt_conn_t *c, size_t sent);
|
||||
ssize_t nxt_event_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b,
|
||||
size_t limit);
|
||||
ssize_t nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob,
|
||||
nxt_uint_t niob);
|
||||
ssize_t nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size);
|
||||
|
||||
@@ -39,7 +39,6 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
|
||||
{
|
||||
ssize_t n;
|
||||
nxt_conn_t *c;
|
||||
nxt_work_queue_t *wq;
|
||||
nxt_event_engine_t *engine;
|
||||
nxt_work_handler_t handler;
|
||||
const nxt_conn_state_t *state;
|
||||
@@ -51,7 +50,13 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
|
||||
|
||||
engine = task->thread->engine;
|
||||
|
||||
/*
|
||||
* Here c->io->read() is assigned instead of direct nxt_conn_io_read()
|
||||
* because the function can be called by nxt_kqueue_conn_io_read().
|
||||
*/
|
||||
c->socket.read_handler = c->io->read;
|
||||
state = c->read_state;
|
||||
c->socket.error_handler = state->error_handler;
|
||||
|
||||
if (c->socket.read_ready) {
|
||||
|
||||
@@ -75,35 +80,39 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
|
||||
nxt_timer_disable(engine, &c->read_timer);
|
||||
}
|
||||
|
||||
wq = c->read_work_queue;
|
||||
handler = state->ready_handler;
|
||||
|
||||
nxt_work_queue_add(wq, handler, task, c, data);
|
||||
|
||||
nxt_work_queue_add(c->read_work_queue,
|
||||
state->ready_handler, task, c, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n != NXT_AGAIN) {
|
||||
/* n == 0 or n == NXT_ERROR. */
|
||||
handler = (n == 0) ? state->close_handler : state->error_handler;
|
||||
|
||||
nxt_fd_event_block_read(engine, &c->socket);
|
||||
nxt_timer_disable(engine, &c->read_timer);
|
||||
|
||||
wq = &engine->fast_work_queue;
|
||||
nxt_work_queue_add(&engine->fast_work_queue,
|
||||
handler, task, c, data);
|
||||
return;
|
||||
}
|
||||
|
||||
handler = (n == 0) ? state->close_handler : state->error_handler;
|
||||
/* n == NXT_AGAIN. */
|
||||
|
||||
nxt_work_queue_add(wq, handler, task, c, data);
|
||||
if (c->socket.read_ready) {
|
||||
/*
|
||||
* SSL/TLS library can return NXT_AGAIN if renegotiation
|
||||
* occured during read operation, it toggled write event
|
||||
* internally so only read timer should be set.
|
||||
*/
|
||||
if (c->read_timer.state == NXT_TIMER_DISABLED) {
|
||||
nxt_conn_timer(engine, c, state, &c->read_timer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here c->io->read() is assigned instead of direct nxt_conn_io_read()
|
||||
* because the function can be called by nxt_kqueue_conn_io_read().
|
||||
*/
|
||||
c->socket.read_handler = c->io->read;
|
||||
c->socket.error_handler = state->error_handler;
|
||||
|
||||
if (nxt_fd_event_is_disabled(c->socket.read)) {
|
||||
nxt_fd_event_enable_read(engine, &c->socket);
|
||||
}
|
||||
@@ -195,7 +204,7 @@ nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, nxt_uint_t flags)
|
||||
c->socket.fd, buf, size, flags, n);
|
||||
|
||||
if (n > 0) {
|
||||
if ((size_t) n < size) {
|
||||
if ((size_t) n < size && (flags & MSG_PEEK) == 0) {
|
||||
c->socket.read_ready = 0;
|
||||
}
|
||||
|
||||
@@ -204,7 +213,10 @@ nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, nxt_uint_t flags)
|
||||
|
||||
if (n == 0) {
|
||||
c->socket.closed = 1;
|
||||
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
c->socket.read_ready = 0;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -44,12 +44,15 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
|
||||
sb.sent = 0;
|
||||
sb.size = 0;
|
||||
sb.buf = b;
|
||||
#if (NXT_TLS)
|
||||
sb.tls = c->u.tls;
|
||||
#endif
|
||||
sb.limit = 10 * 1024 * 1024;
|
||||
sb.ready = 1;
|
||||
sb.sync = 0;
|
||||
|
||||
do {
|
||||
ret = nxt_conn_io_sendbuf(task, &sb);
|
||||
ret = c->io->sendbuf(task, &sb);
|
||||
|
||||
c->socket.write_ready = sb.ready;
|
||||
c->socket.error = sb.error;
|
||||
@@ -100,7 +103,7 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
|
||||
/*
|
||||
* SSL libraries can require to toggle either write or read
|
||||
* event if renegotiation occurs during SSL write operation.
|
||||
* This case is handled on the event_io->send() level. Timer
|
||||
* This case is handled on the c->io->send() level. Timer
|
||||
* can be set here because it should be set only for write
|
||||
* direction.
|
||||
*/
|
||||
@@ -301,23 +304,6 @@ nxt_event_conn_write_delayed(nxt_event_engine_t *engine, nxt_conn_t *c,
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
nxt_event_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b, size_t limit)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
ret = c->io->sendbuf(c, b, limit);
|
||||
|
||||
if ((ret == NXT_AGAIN || !c->socket.write_ready)
|
||||
&& nxt_fd_event_is_disabled(c->socket.write))
|
||||
{
|
||||
nxt_fd_event_enable_write(c->socket.task->thread->engine, &c->socket);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b, size_t limit)
|
||||
{
|
||||
|
||||
@@ -97,26 +97,24 @@ static ssize_t nxt_epoll_edge_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b);
|
||||
|
||||
|
||||
static nxt_conn_io_t nxt_epoll_edge_conn_io = {
|
||||
nxt_epoll_edge_conn_io_connect,
|
||||
nxt_conn_io_accept,
|
||||
.connect = nxt_epoll_edge_conn_io_connect,
|
||||
.accept = nxt_conn_io_accept,
|
||||
|
||||
nxt_conn_io_read,
|
||||
nxt_epoll_edge_conn_io_recvbuf,
|
||||
nxt_conn_io_recv,
|
||||
.read = nxt_conn_io_read,
|
||||
.recvbuf = nxt_epoll_edge_conn_io_recvbuf,
|
||||
.recv = nxt_conn_io_recv,
|
||||
|
||||
nxt_conn_io_write,
|
||||
nxt_event_conn_io_write_chunk,
|
||||
.write = nxt_conn_io_write,
|
||||
.sendbuf = nxt_conn_io_sendbuf,
|
||||
|
||||
#if (NXT_HAVE_LINUX_SENDFILE)
|
||||
nxt_linux_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_linux_event_conn_io_sendfile,
|
||||
#else
|
||||
nxt_event_conn_io_sendbuf,
|
||||
.old_sendbuf = nxt_event_conn_io_sendbuf,
|
||||
#endif
|
||||
|
||||
nxt_event_conn_io_writev,
|
||||
nxt_event_conn_io_send,
|
||||
|
||||
nxt_conn_io_shutdown,
|
||||
.writev = nxt_event_conn_io_writev,
|
||||
.send = nxt_event_conn_io_send,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ nxt_event_conn_job_sendfile_handler(nxt_task_t *task, void *obj, void *data)
|
||||
b = jbs->out;
|
||||
|
||||
do {
|
||||
ret = c->io->sendbuf(c, b, jbs->limit);
|
||||
ret = c->io->old_sendbuf(c, b, jbs->limit);
|
||||
|
||||
if (ret == NXT_AGAIN) {
|
||||
break;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -111,28 +111,26 @@ static ssize_t nxt_kqueue_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b);
|
||||
|
||||
|
||||
static nxt_conn_io_t nxt_kqueue_conn_io = {
|
||||
nxt_kqueue_conn_io_connect,
|
||||
nxt_kqueue_conn_io_accept,
|
||||
.connect = nxt_kqueue_conn_io_connect,
|
||||
.accept = nxt_kqueue_conn_io_accept,
|
||||
|
||||
nxt_kqueue_conn_io_read,
|
||||
nxt_kqueue_conn_io_recvbuf,
|
||||
nxt_conn_io_recv,
|
||||
.read = nxt_kqueue_conn_io_read,
|
||||
.recvbuf = nxt_kqueue_conn_io_recvbuf,
|
||||
.recv = nxt_conn_io_recv,
|
||||
|
||||
nxt_conn_io_write,
|
||||
nxt_event_conn_io_write_chunk,
|
||||
.write = nxt_conn_io_write,
|
||||
.sendbuf = nxt_conn_io_sendbuf,
|
||||
|
||||
#if (NXT_HAVE_FREEBSD_SENDFILE)
|
||||
nxt_freebsd_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_freebsd_event_conn_io_sendfile,
|
||||
#elif (NXT_HAVE_MACOSX_SENDFILE)
|
||||
nxt_macosx_event_conn_io_sendfile,
|
||||
.old_sendbuf = nxt_macosx_event_conn_io_sendfile,
|
||||
#else
|
||||
nxt_event_conn_io_sendbuf,
|
||||
.old_sendbuf = nxt_event_conn_io_sendbuf,
|
||||
#endif
|
||||
|
||||
nxt_event_conn_io_writev,
|
||||
nxt_event_conn_io_send,
|
||||
|
||||
nxt_conn_io_shutdown,
|
||||
.writev = nxt_event_conn_io_writev,
|
||||
.send = nxt_event_conn_io_send,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -280,12 +280,12 @@ nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls)
|
||||
break;
|
||||
}
|
||||
|
||||
#if (NXT_SSLTLS)
|
||||
#if (NXT_TLS)
|
||||
|
||||
if (ls->ssltls) {
|
||||
if (ls->tls) {
|
||||
size += 4 * sizeof(void *) /* SSL/TLS connection */
|
||||
+ sizeof(nxt_buf_mem_t)
|
||||
+ sizeof(nxt_mem_pool_cleanup_t);
|
||||
+ sizeof(nxt_work_t); /* nxt_mp_cleanup */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,8 @@ typedef struct {
|
||||
uint8_t flags;
|
||||
uint8_t read_after_accept; /* 1 bit */
|
||||
|
||||
#if (NXT_SSLTLS)
|
||||
uint8_t ssltls; /* 1 bit */
|
||||
#if (NXT_TLS)
|
||||
uint8_t tls; /* 1 bit */
|
||||
#endif
|
||||
#if (NXT_INET6 && defined IPV6_V6ONLY)
|
||||
uint8_t ipv6only; /* 2 bits */
|
||||
|
||||
@@ -113,8 +113,8 @@ typedef struct nxt_conn_s nxt_conn_t;
|
||||
|
||||
#include <nxt_log_moderation.h>
|
||||
|
||||
#if (NXT_SSLTLS)
|
||||
#include <nxt_ssltls.h>
|
||||
#if (NXT_TLS)
|
||||
#include <nxt_tls.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -12,57 +12,68 @@
|
||||
|
||||
typedef struct {
|
||||
SSL *session;
|
||||
nxt_conn_t *conn;
|
||||
|
||||
int ssl_error;
|
||||
uint8_t times; /* 2 bits */
|
||||
uint8_t handshake; /* 1 bit */
|
||||
|
||||
nxt_buf_mem_t buffer;
|
||||
} nxt_openssl_conn_t;
|
||||
|
||||
|
||||
static nxt_int_t nxt_openssl_server_init(nxt_ssltls_conf_t *conf);
|
||||
typedef enum {
|
||||
NXT_OPENSSL_HANDSHAKE = 0,
|
||||
NXT_OPENSSL_READ,
|
||||
NXT_OPENSSL_WRITE,
|
||||
NXT_OPENSSL_SHUTDOWN,
|
||||
} nxt_openssl_io_t;
|
||||
|
||||
static void nxt_openssl_conn_init(nxt_task_t *task, nxt_ssltls_conf_t *conf,
|
||||
|
||||
static nxt_int_t nxt_openssl_library_init(nxt_task_t *task);
|
||||
static void nxt_openssl_library_free(nxt_task_t *task);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100004L
|
||||
static nxt_int_t nxt_openssl_locks_init(void);
|
||||
static void nxt_openssl_lock(int mode, int type, const char *file, int line);
|
||||
static unsigned long nxt_openssl_thread_id(void);
|
||||
static void nxt_openssl_locks_free(void);
|
||||
#endif
|
||||
static nxt_int_t nxt_openssl_server_init(nxt_task_t *task,
|
||||
nxt_tls_conf_t *conf);
|
||||
static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf);
|
||||
static void nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf,
|
||||
nxt_conn_t *c);
|
||||
static void nxt_openssl_session_cleanup(nxt_task_t *task, void *data);
|
||||
static void nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data);
|
||||
static void nxt_openssl_conn_io_read(nxt_task_t *task, void *obj, void *data);
|
||||
static ssize_t nxt_openssl_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b);
|
||||
static ssize_t nxt_openssl_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb);
|
||||
static ssize_t nxt_openssl_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb,
|
||||
void *buf, size_t size);
|
||||
static void nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj,
|
||||
void *data);
|
||||
static ssize_t nxt_openssl_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b,
|
||||
size_t limit);
|
||||
static ssize_t nxt_openssl_conn_io_send(nxt_conn_t *c, void *buf, size_t size);
|
||||
static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task,
|
||||
nxt_conn_t *c, int ret, nxt_err_t sys_err, nxt_work_handler_t handler);
|
||||
static void nxt_cdecl nxt_openssl_conn_error(nxt_conn_t *c, nxt_err_t err,
|
||||
const char *fmt, ...);
|
||||
static nxt_uint_t nxt_openssl_log_error_level(nxt_conn_t *c, nxt_err_t err);
|
||||
static void nxt_cdecl nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log,
|
||||
const char *fmt, ...);
|
||||
static u_char *nxt_openssl_copy_error(u_char *p, u_char *end);
|
||||
static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c,
|
||||
int ret, nxt_err_t sys_err, nxt_openssl_io_t io);
|
||||
static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task,
|
||||
nxt_err_t err, const char *fmt, ...);
|
||||
static nxt_uint_t nxt_openssl_log_error_level(nxt_err_t err);
|
||||
|
||||
|
||||
const nxt_ssltls_lib_t nxt_openssl_lib = {
|
||||
nxt_openssl_server_init,
|
||||
NULL,
|
||||
const nxt_tls_lib_t nxt_openssl_lib = {
|
||||
.library_init = nxt_openssl_library_init,
|
||||
.library_free = nxt_openssl_library_free,
|
||||
|
||||
.server_init = nxt_openssl_server_init,
|
||||
.server_free = nxt_openssl_server_free,
|
||||
};
|
||||
|
||||
|
||||
static nxt_conn_io_t nxt_openssl_conn_io = {
|
||||
NULL,
|
||||
NULL,
|
||||
.read = nxt_conn_io_read,
|
||||
.recvbuf = nxt_openssl_conn_io_recvbuf,
|
||||
|
||||
nxt_openssl_conn_io_read,
|
||||
NULL,
|
||||
NULL,
|
||||
.write = nxt_conn_io_write,
|
||||
.sendbuf = nxt_openssl_conn_io_sendbuf,
|
||||
|
||||
nxt_conn_io_write,
|
||||
nxt_openssl_conn_io_write_chunk,
|
||||
NULL,
|
||||
NULL,
|
||||
nxt_openssl_conn_io_send,
|
||||
|
||||
nxt_openssl_conn_io_shutdown,
|
||||
.shutdown = nxt_openssl_conn_io_shutdown,
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +82,7 @@ static int nxt_openssl_connection_index;
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_openssl_start(nxt_thread_t *thr)
|
||||
nxt_openssl_library_init(nxt_task_t *task)
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -79,6 +90,14 @@ nxt_openssl_start(nxt_thread_t *thr)
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100003L
|
||||
|
||||
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
||||
|
||||
#else
|
||||
{
|
||||
nxt_int_t ret;
|
||||
|
||||
SSL_load_error_strings();
|
||||
|
||||
OPENSSL_config(NULL);
|
||||
@@ -91,9 +110,17 @@ nxt_openssl_start(nxt_thread_t *thr)
|
||||
*/
|
||||
(void) SSL_library_init();
|
||||
|
||||
ret = nxt_openssl_locks_init();
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
nxt_openssl_version = SSLeay();
|
||||
|
||||
nxt_log_error(NXT_LOG_INFO, thr->log, "%s, %xl",
|
||||
nxt_log(task, NXT_LOG_INFO, "%s, %xl",
|
||||
SSLeay_version(SSLEAY_VERSION), nxt_openssl_version);
|
||||
|
||||
#ifndef SSL_OP_NO_COMPRESSION
|
||||
@@ -116,7 +143,7 @@ nxt_openssl_start(nxt_thread_t *thr)
|
||||
index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (index == -1) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_get_ex_new_index() failed");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
@@ -127,29 +154,115 @@ nxt_openssl_start(nxt_thread_t *thr)
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100003L
|
||||
|
||||
static void
|
||||
nxt_openssl_library_free(nxt_task_t *task)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
const char *certificate, *key, *ciphers, *ca_certificate;
|
||||
nxt_thread_t *thr;
|
||||
STACK_OF(X509_NAME) *list;
|
||||
}
|
||||
|
||||
thr = nxt_thread();
|
||||
#else
|
||||
|
||||
if (nxt_openssl_start(thr) != NXT_OK) {
|
||||
static nxt_thread_mutex_t *nxt_openssl_locks;
|
||||
|
||||
static nxt_int_t
|
||||
nxt_openssl_locks_init(void)
|
||||
{
|
||||
int i, n;
|
||||
nxt_int_t ret;
|
||||
|
||||
n = CRYPTO_num_locks();
|
||||
|
||||
nxt_openssl_locks = OPENSSL_malloc(n * sizeof(nxt_thread_mutex_t));
|
||||
if (nxt_slow_path(nxt_openssl_locks == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
ret = nxt_thread_mutex_create(&nxt_openssl_locks[i]);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTO_set_locking_callback(nxt_openssl_lock);
|
||||
|
||||
CRYPTO_set_id_callback(nxt_openssl_thread_id);
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_lock(int mode, int type, const char *file, int line)
|
||||
{
|
||||
nxt_thread_mutex_t *lock;
|
||||
|
||||
lock = &nxt_openssl_locks[type];
|
||||
|
||||
if ((mode & CRYPTO_LOCK) != 0) {
|
||||
(void) nxt_thread_mutex_lock(lock);
|
||||
|
||||
} else {
|
||||
(void) nxt_thread_mutex_unlock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static u_long
|
||||
nxt_openssl_thread_id(void)
|
||||
{
|
||||
return (u_long) nxt_thread_handle();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_library_free(nxt_task_t *task)
|
||||
{
|
||||
nxt_openssl_locks_free();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_locks_free(void)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
n = CRYPTO_num_locks();
|
||||
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
nxt_thread_mutex_destroy(&nxt_openssl_locks[i]);
|
||||
}
|
||||
|
||||
OPENSSL_free(nxt_openssl_locks);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
const char *certificate, *key, *ciphers, *ca_certificate;
|
||||
STACK_OF(X509_NAME) *list;
|
||||
|
||||
ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (ctx == NULL) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log, "SSL_CTX_new() failed");
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CTX_new() failed");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
conf->ctx = ctx;
|
||||
conf->conn_init = nxt_openssl_conn_init;
|
||||
|
||||
#ifdef SSL_OP_NO_RENEGOTIATION
|
||||
/* Renegration is not currently supported. */
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
/*
|
||||
* Disable gzip compression in OpenSSL 1.0.0,
|
||||
@@ -174,7 +287,7 @@ nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
certificate = conf->certificate;
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, certificate) == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_CTX_use_certificate_file(\"%s\") failed",
|
||||
certificate);
|
||||
goto fail;
|
||||
@@ -183,7 +296,7 @@ nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
key = conf->certificate_key;
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_CTX_use_PrivateKey_file(\"%s\") failed",
|
||||
key);
|
||||
goto fail;
|
||||
@@ -192,7 +305,7 @@ nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
ciphers = (conf->ciphers != NULL) ? conf->ciphers : "HIGH:!aNULL:!MD5";
|
||||
|
||||
if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_CTX_set_cipher_list(\"%s\") failed",
|
||||
ciphers);
|
||||
goto fail;
|
||||
@@ -211,7 +324,7 @@ nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
ca_certificate = conf->ca_certificate;
|
||||
|
||||
if (SSL_CTX_load_verify_locations(ctx, ca_certificate, NULL) == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_CTX_load_verify_locations(\"%s\") failed",
|
||||
ca_certificate);
|
||||
goto fail;
|
||||
@@ -220,7 +333,7 @@ nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
|
||||
list = SSL_load_client_CA_file(ca_certificate);
|
||||
|
||||
if (list == NULL) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, thr->log,
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT,
|
||||
"SSL_load_client_CA_file(\"%s\") failed",
|
||||
ca_certificate);
|
||||
goto fail;
|
||||
@@ -246,55 +359,53 @@ fail:
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_conn_init(nxt_task_t *task, nxt_ssltls_conf_t *conf, nxt_conn_t *c)
|
||||
nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf)
|
||||
{
|
||||
SSL_CTX_free(conf->ctx);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c)
|
||||
{
|
||||
int ret;
|
||||
SSL *s;
|
||||
SSL_CTX *ctx;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_mem_pool_cleanup_t *mpcl;
|
||||
nxt_openssl_conn_t *tls;
|
||||
|
||||
nxt_log_debug(c->socket.log, "openssl conn init");
|
||||
|
||||
ssltls = nxt_mp_zget(c->mem_pool, sizeof(nxt_openssl_conn_t));
|
||||
if (ssltls == NULL) {
|
||||
tls = nxt_mp_zget(c->mem_pool, sizeof(nxt_openssl_conn_t));
|
||||
if (tls == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
c->u.ssltls = ssltls;
|
||||
nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size);
|
||||
|
||||
mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0);
|
||||
if (mpcl == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
c->u.tls = tls;
|
||||
nxt_buf_mem_set_size(&tls->buffer, conf->buffer_size);
|
||||
|
||||
ctx = conf->ctx;
|
||||
|
||||
s = SSL_new(ctx);
|
||||
if (s == NULL) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, c->socket.log,
|
||||
"SSL_new() failed");
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_new() failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ssltls->session = s;
|
||||
mpcl->handler = nxt_openssl_session_cleanup;
|
||||
mpcl->data = ssltls;
|
||||
tls->session = s;
|
||||
tls->conn = c;
|
||||
|
||||
ret = SSL_set_fd(s, c->socket.fd);
|
||||
|
||||
if (ret == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, c->socket.log,
|
||||
"SSL_set_fd(%d) failed", c->socket.fd);
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_fd(%d) failed",
|
||||
c->socket.fd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SSL_set_accept_state(s);
|
||||
|
||||
if (SSL_set_ex_data(s, nxt_openssl_connection_index, c) == 0) {
|
||||
nxt_openssl_log_error(NXT_LOG_ALERT, c->socket.log,
|
||||
"SSL_set_ex_data() failed");
|
||||
nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_ex_data() failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -311,18 +422,14 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_openssl_session_cleanup(nxt_task_t *task, void *data)
|
||||
nxt_inline void
|
||||
nxt_openssl_conn_free(nxt_task_t *task, nxt_openssl_conn_t *tls)
|
||||
{
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_debug(task, "openssl conn free");
|
||||
|
||||
ssltls = data;
|
||||
nxt_free(tls->buffer.start);
|
||||
|
||||
nxt_debug(task, "openssl session cleanup");
|
||||
|
||||
nxt_free(ssltls->buffer.start);
|
||||
|
||||
SSL_free(ssltls->session);
|
||||
SSL_free(tls->session);
|
||||
}
|
||||
|
||||
|
||||
@@ -333,16 +440,19 @@ nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data)
|
||||
nxt_int_t n;
|
||||
nxt_err_t err;
|
||||
nxt_conn_t *c;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_work_queue_t *wq;
|
||||
nxt_work_handler_t handler;
|
||||
nxt_openssl_conn_t *tls;
|
||||
const nxt_conn_state_t *state;
|
||||
|
||||
c = obj;
|
||||
ssltls = c->u.ssltls;
|
||||
tls = c->u.tls;
|
||||
|
||||
nxt_debug(task, "openssl conn handshake: %d", ssltls->times);
|
||||
nxt_debug(task, "openssl conn handshake: %d", tls->times);
|
||||
|
||||
/* "ssltls->times == 1" is suitable to run SSL_do_handshake() in job. */
|
||||
/* "tls->times == 1" is suitable to run SSL_do_handshake() in job. */
|
||||
|
||||
ret = SSL_do_handshake(ssltls->session);
|
||||
ret = SSL_do_handshake(tls->session);
|
||||
|
||||
err = (ret <= 0) ? nxt_socket_errno : 0;
|
||||
|
||||
@@ -350,130 +460,161 @@ nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data)
|
||||
|
||||
nxt_debug(task, "SSL_do_handshake(%d): %d err:%d", c->socket.fd, ret, err);
|
||||
|
||||
state = (c->read_state != NULL) ? c->read_state : c->write_state;
|
||||
|
||||
if (ret > 0) {
|
||||
/* ret == 1, the handshake was successfully completed. */
|
||||
nxt_openssl_conn_io_read(task, c, data);
|
||||
tls->handshake = 1;
|
||||
|
||||
if (c->read_state != NULL) {
|
||||
if (state->io_read_handler != NULL || c->read != NULL) {
|
||||
nxt_conn_read(task->thread->engine, c);
|
||||
return;
|
||||
}
|
||||
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err,
|
||||
nxt_openssl_conn_handshake);
|
||||
} else {
|
||||
if (c->write != NULL) {
|
||||
nxt_conn_write(task->thread->engine, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == NXT_ERROR) {
|
||||
nxt_openssl_conn_error(c, err, "SSL_do_handshake(%d) failed",
|
||||
handler = state->ready_handler;
|
||||
|
||||
} else {
|
||||
c->socket.read_handler = nxt_openssl_conn_handshake;
|
||||
c->socket.write_handler = nxt_openssl_conn_handshake;
|
||||
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err,
|
||||
NXT_OPENSSL_HANDSHAKE);
|
||||
switch (n) {
|
||||
|
||||
case NXT_AGAIN:
|
||||
if (tls->ssl_error == SSL_ERROR_WANT_READ && tls->times < 2) {
|
||||
tls->times++;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
case 0:
|
||||
handler = state->close_handler;
|
||||
break;
|
||||
|
||||
default:
|
||||
case NXT_ERROR:
|
||||
c->socket.error = err;
|
||||
nxt_openssl_conn_error(task, err, "SSL_do_handshake(%d) failed",
|
||||
c->socket.fd);
|
||||
|
||||
nxt_work_queue_add(c->read_work_queue, c->read_state->error_handler,
|
||||
task, c, data);
|
||||
|
||||
} else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) {
|
||||
ssltls->times++;
|
||||
handler = state->error_handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wq = (c->read_state != NULL) ? c->read_work_queue : c->write_work_queue;
|
||||
|
||||
static void
|
||||
nxt_openssl_conn_io_read(nxt_task_t *task, void *obj, void *data)
|
||||
nxt_work_queue_add(wq, handler, task, c, data);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
nxt_openssl_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b)
|
||||
{
|
||||
int ret;
|
||||
nxt_buf_t *b;
|
||||
size_t size;
|
||||
nxt_int_t n;
|
||||
nxt_err_t err;
|
||||
nxt_conn_t *c;
|
||||
nxt_work_handler_t handler;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_openssl_conn_t *tls;
|
||||
|
||||
c = obj;
|
||||
tls = c->u.tls;
|
||||
size = b->mem.end - b->mem.free;
|
||||
|
||||
nxt_debug(task, "openssl conn read");
|
||||
|
||||
handler = c->read_state->ready_handler;
|
||||
b = c->read;
|
||||
|
||||
/* b == NULL is used to test descriptor readiness. */
|
||||
|
||||
if (b != NULL) {
|
||||
ssltls = c->u.ssltls;
|
||||
|
||||
ret = SSL_read(ssltls->session, b->mem.free, b->mem.end - b->mem.free);
|
||||
ret = SSL_read(tls->session, b->mem.free, size);
|
||||
|
||||
err = (ret <= 0) ? nxt_socket_errno : 0;
|
||||
|
||||
nxt_debug(task, "SSL_read(%d, %p, %uz): %d err:%d",
|
||||
c->socket.fd, b->mem.free, b->mem.end - b->mem.free,
|
||||
ret, err);
|
||||
nxt_debug(c->socket.task, "SSL_read(%d, %p, %uz): %d err:%d",
|
||||
c->socket.fd, b->mem.free, size, ret, err);
|
||||
|
||||
if (ret > 0) {
|
||||
/* c->socket.read_ready is kept. */
|
||||
b->mem.free += ret;
|
||||
handler = c->read_state->ready_handler;
|
||||
|
||||
} else {
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err,
|
||||
nxt_openssl_conn_io_read);
|
||||
|
||||
if (nxt_fast_path(n != NXT_ERROR)) {
|
||||
return;
|
||||
if ((size_t) ret < size) {
|
||||
c->socket.read_ready = 0;
|
||||
}
|
||||
|
||||
nxt_openssl_conn_error(c, err, "SSL_read(%d, %p, %uz) failed",
|
||||
c->socket.fd, b->mem.free,
|
||||
b->mem.end - b->mem.free);
|
||||
|
||||
handler = c->read_state->error_handler;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxt_work_queue_add(c->read_work_queue, handler, task, c, data);
|
||||
n = nxt_openssl_conn_test_error(c->socket.task, c, ret, err,
|
||||
NXT_OPENSSL_READ);
|
||||
if (n == NXT_ERROR) {
|
||||
c->socket.error = err;
|
||||
nxt_openssl_conn_error(c->socket.task, err,
|
||||
"SSL_read(%d, %p, %uz) failed",
|
||||
c->socket.fd, b->mem.free, size);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
nxt_openssl_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b, size_t limit)
|
||||
nxt_openssl_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb)
|
||||
{
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_uint_t niov;
|
||||
struct iovec iov;
|
||||
|
||||
nxt_debug(c->socket.task, "openssl conn write chunk");
|
||||
niov = nxt_sendbuf_mem_coalesce0(task, sb, &iov, 1);
|
||||
|
||||
ssltls = c->u.ssltls;
|
||||
if (niov == 0 && sb->sync) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit);
|
||||
return nxt_openssl_conn_io_send(task, sb, iov.iov_base, iov.iov_len);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
nxt_openssl_conn_io_send(nxt_conn_t *c, void *buf, size_t size)
|
||||
nxt_openssl_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf,
|
||||
size_t size)
|
||||
{
|
||||
int ret;
|
||||
nxt_err_t err;
|
||||
nxt_int_t n;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_conn_t *c;
|
||||
nxt_openssl_conn_t *tls;
|
||||
|
||||
ssltls = c->u.ssltls;
|
||||
tls = sb->tls;
|
||||
|
||||
ret = SSL_write(ssltls->session, buf, size);
|
||||
ret = SSL_write(tls->session, buf, size);
|
||||
|
||||
if (ret <= 0) {
|
||||
err = nxt_socket_errno;
|
||||
c->socket.error = err;
|
||||
sb->error = err;
|
||||
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
|
||||
nxt_log_debug(c->socket.log, "SSL_write(%d, %p, %uz): %d err:%d",
|
||||
c->socket.fd, buf, size, ret, err);
|
||||
nxt_debug(task, "SSL_write(%d, %p, %uz): %d err:%d",
|
||||
sb->socket, buf, size, ret, err);
|
||||
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
n = nxt_openssl_conn_test_error(c->socket.task, c, ret, err,
|
||||
nxt_conn_io_write);
|
||||
c = tls->conn;
|
||||
c->socket.write_ready = sb->ready;
|
||||
c->socket.error = sb->error;
|
||||
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_WRITE);
|
||||
|
||||
sb->ready = c->socket.write_ready;
|
||||
sb->error = c->socket.error;
|
||||
|
||||
if (n == NXT_ERROR) {
|
||||
nxt_openssl_conn_error(c, err, "SSL_write(%d, %p, %uz) failed",
|
||||
c->socket.fd, buf, size);
|
||||
sb->error = err;
|
||||
nxt_openssl_conn_error(task, err, "SSL_write(%d, %p, %uz) failed",
|
||||
sb->socket, buf, size);
|
||||
}
|
||||
|
||||
return n;
|
||||
@@ -489,18 +630,19 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
||||
nxt_int_t n;
|
||||
nxt_bool_t quiet, once;
|
||||
nxt_conn_t *c;
|
||||
nxt_openssl_conn_t *tls;
|
||||
nxt_work_handler_t handler;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
|
||||
c = obj;
|
||||
|
||||
nxt_debug(task, "openssl conn shutdown");
|
||||
|
||||
ssltls = c->u.ssltls;
|
||||
s = ssltls->session;
|
||||
c->read_state = NULL;
|
||||
tls = c->u.tls;
|
||||
s = tls->session;
|
||||
|
||||
if (s == NULL) {
|
||||
handler = c->write_state->close_handler;
|
||||
if (s == NULL || !tls->handshake) {
|
||||
handler = c->write_state->ready_handler;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -532,22 +674,22 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
||||
|
||||
if (ret > 0) {
|
||||
/* ret == 1, the shutdown was successfully completed. */
|
||||
handler = c->write_state->close_handler;
|
||||
handler = c->write_state->ready_handler;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* If SSL_shutdown() returns 0 then it should be called
|
||||
* again. The second SSL_shutdown() call should returns
|
||||
* again. The second SSL_shutdown() call should return
|
||||
* -1/SSL_ERROR_WANT_READ or -1/SSL_ERROR_WANT_WRITE.
|
||||
* OpenSSL prior to 0.9.8m version however never returns
|
||||
* -1 at all. Fortunately, OpenSSL internals preserve
|
||||
* -1 at all. Fortunately, OpenSSL preserves internally
|
||||
* correct status available via SSL_get_error(-1).
|
||||
*/
|
||||
if (once) {
|
||||
mode = SSL_get_shutdown(s);
|
||||
once = 0;
|
||||
mode = SSL_get_shutdown(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -559,71 +701,82 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err,
|
||||
nxt_openssl_conn_io_shutdown);
|
||||
c->socket.read_handler = nxt_openssl_conn_io_shutdown;
|
||||
c->socket.write_handler = nxt_openssl_conn_io_shutdown;
|
||||
c->socket.error_handler = c->write_state->error_handler;
|
||||
|
||||
if (nxt_fast_path(n == 0)) {
|
||||
return;
|
||||
}
|
||||
n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_SHUTDOWN);
|
||||
|
||||
if (n != NXT_ERROR) { /* n == NXT_AGAIN */
|
||||
c->socket.error_handler = c->read_state->error_handler;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
handler = c->write_state->close_handler;
|
||||
break;
|
||||
|
||||
case NXT_AGAIN:
|
||||
nxt_timer_add(task->thread->engine, &c->read_timer, 5000);
|
||||
return;
|
||||
|
||||
default:
|
||||
case NXT_ERROR:
|
||||
c->socket.error = err;
|
||||
nxt_openssl_conn_error(task, err, "SSL_shutdown(%d) failed",
|
||||
c->socket.fd);
|
||||
handler = c->write_state->error_handler;
|
||||
}
|
||||
|
||||
nxt_openssl_conn_error(c, err, "SSL_shutdown(%d) failed", c->socket.fd);
|
||||
|
||||
handler = c->write_state->error_handler;
|
||||
|
||||
done:
|
||||
|
||||
nxt_openssl_conn_free(task, tls);
|
||||
|
||||
nxt_work_queue_add(c->write_work_queue, handler, task, c, data);
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret,
|
||||
nxt_err_t sys_err, nxt_work_handler_t handler)
|
||||
nxt_err_t sys_err, nxt_openssl_io_t io)
|
||||
{
|
||||
u_long lib_err;
|
||||
nxt_work_queue_t *wq;
|
||||
nxt_openssl_conn_t *ssltls;
|
||||
nxt_openssl_conn_t *tls;
|
||||
|
||||
ssltls = c->u.ssltls;
|
||||
tls = c->u.tls;
|
||||
|
||||
ssltls->ssl_error = SSL_get_error(ssltls->session, ret);
|
||||
tls->ssl_error = SSL_get_error(tls->session, ret);
|
||||
|
||||
nxt_log_debug(c->socket.log, "SSL_get_error(): %d", ssltls->ssl_error);
|
||||
nxt_debug(task, "SSL_get_error(): %d", tls->ssl_error);
|
||||
|
||||
switch (ssltls->ssl_error) {
|
||||
switch (tls->ssl_error) {
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
|
||||
if (io != NXT_OPENSSL_READ) {
|
||||
nxt_fd_event_block_write(task->thread->engine, &c->socket);
|
||||
|
||||
c->socket.read_ready = 0;
|
||||
c->socket.read_handler = handler;
|
||||
|
||||
if (nxt_fd_event_is_disabled(c->socket.read)) {
|
||||
nxt_fd_event_enable_read(task->thread->engine, &c->socket);
|
||||
}
|
||||
}
|
||||
|
||||
return NXT_AGAIN;
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
|
||||
if (io != NXT_OPENSSL_WRITE) {
|
||||
nxt_fd_event_block_read(task->thread->engine, &c->socket);
|
||||
|
||||
c->socket.write_ready = 0;
|
||||
c->socket.write_handler = handler;
|
||||
|
||||
if (nxt_fd_event_is_disabled(c->socket.write)) {
|
||||
nxt_fd_event_enable_write(task->thread->engine, &c->socket);
|
||||
}
|
||||
}
|
||||
|
||||
return NXT_AGAIN;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
|
||||
lib_err = ERR_peek_error();
|
||||
|
||||
nxt_debug(task, "ERR_peek_error(): %l", lib_err);
|
||||
@@ -634,23 +787,10 @@ nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret,
|
||||
|
||||
/* A connection was just closed. */
|
||||
c->socket.closed = 1;
|
||||
|
||||
/* Fall through. */
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
/* A "close notify" alert. */
|
||||
|
||||
if (c->read_state != NULL) {
|
||||
wq = c->read_work_queue;
|
||||
handler = c->read_state->close_handler;
|
||||
|
||||
} else {
|
||||
wq = c->write_work_queue;
|
||||
handler = c->write_state->close_handler;
|
||||
}
|
||||
|
||||
nxt_work_queue_add(wq, handler, task, c, c->socket.data);
|
||||
|
||||
return 0;
|
||||
|
||||
default: /* SSL_ERROR_SSL, etc. */
|
||||
@@ -661,17 +801,16 @@ nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret,
|
||||
|
||||
|
||||
static void nxt_cdecl
|
||||
nxt_openssl_conn_error(nxt_conn_t *c, nxt_err_t err, const char *fmt, ...)
|
||||
nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, const char *fmt, ...)
|
||||
{
|
||||
u_char *p, *end;
|
||||
va_list args;
|
||||
nxt_uint_t level;
|
||||
u_char msg[NXT_MAX_ERROR_STR];
|
||||
|
||||
c->socket.error = err;
|
||||
level = nxt_openssl_log_error_level(c, err);
|
||||
level = nxt_openssl_log_error_level(err);
|
||||
|
||||
if (nxt_log_level_enough(c->socket.log, level)) {
|
||||
if (nxt_log_level_enough(task->log, level)) {
|
||||
|
||||
end = msg + sizeof(msg);
|
||||
|
||||
@@ -685,7 +824,7 @@ nxt_openssl_conn_error(nxt_conn_t *c, nxt_err_t err, const char *fmt, ...)
|
||||
|
||||
p = nxt_openssl_copy_error(p, end);
|
||||
|
||||
nxt_log_error(level, c->socket.log, "%*s", p - msg, msg);
|
||||
nxt_log(task, level, "%*s", p - msg, msg);
|
||||
|
||||
} else {
|
||||
ERR_clear_error();
|
||||
@@ -694,7 +833,7 @@ nxt_openssl_conn_error(nxt_conn_t *c, nxt_err_t err, const char *fmt, ...)
|
||||
|
||||
|
||||
static nxt_uint_t
|
||||
nxt_openssl_log_error_level(nxt_conn_t *c, nxt_err_t err)
|
||||
nxt_openssl_log_error_level(nxt_err_t err)
|
||||
{
|
||||
switch (ERR_GET_REASON(ERR_peek_error())) {
|
||||
|
||||
@@ -707,7 +846,9 @@ nxt_openssl_log_error_level(nxt_conn_t *c, nxt_err_t err)
|
||||
case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST: /* 151 */
|
||||
case SSL_R_EXCESSIVE_MESSAGE_SIZE: /* 152 */
|
||||
case SSL_R_LENGTH_MISMATCH: /* 159 */
|
||||
#ifdef SSL_R_NO_CIPHERS_PASSED
|
||||
case SSL_R_NO_CIPHERS_PASSED: /* 182 */
|
||||
#endif
|
||||
case SSL_R_NO_CIPHERS_SPECIFIED: /* 183 */
|
||||
case SSL_R_NO_COMPRESSION_SPECIFIED: /* 187 */
|
||||
case SSL_R_NO_SHARED_CIPHER: /* 193 */
|
||||
@@ -768,8 +909,8 @@ nxt_openssl_log_error_level(nxt_conn_t *c, nxt_err_t err)
|
||||
}
|
||||
|
||||
|
||||
static void nxt_cdecl
|
||||
nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...)
|
||||
void nxt_cdecl
|
||||
nxt_openssl_log_error(nxt_task_t *task, nxt_uint_t level, const char *fmt, ...)
|
||||
{
|
||||
u_char *p, *end;
|
||||
va_list args;
|
||||
@@ -783,11 +924,11 @@ nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...)
|
||||
|
||||
p = nxt_openssl_copy_error(p, end);
|
||||
|
||||
nxt_log_error(level, log, "%*s", p - msg, msg);
|
||||
nxt_log(task, level, "%*s", p - msg, msg);
|
||||
}
|
||||
|
||||
|
||||
static u_char *
|
||||
u_char *
|
||||
nxt_openssl_copy_error(u_char *p, u_char *end)
|
||||
{
|
||||
int flags;
|
||||
@@ -806,8 +947,8 @@ nxt_openssl_copy_error(u_char *p, u_char *end)
|
||||
p = nxt_sprintf(p, end, " (%d: %s) (OpenSSL: ", ERR_GET_REASON(err), data);
|
||||
|
||||
/*
|
||||
* ... followed by all queued cumbersome OpenSSL
|
||||
* error messages and drain the error queue.
|
||||
* ... followed by all queued cumbersome OpenSSL error messages
|
||||
* and drain the error queue.
|
||||
*/
|
||||
delimiter = "";
|
||||
clear = 0;
|
||||
|
||||
@@ -299,6 +299,18 @@ nxt_router_start(nxt_task_t *task, void *data)
|
||||
|
||||
rt = task->thread->runtime;
|
||||
|
||||
#if (NXT_TLS)
|
||||
rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL");
|
||||
if (nxt_slow_path(rt->tls == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
ret = rt->tls->library_init(task);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = nxt_http_init(task, rt);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return ret;
|
||||
@@ -2773,6 +2785,12 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint)
|
||||
if (rtcf != NULL) {
|
||||
nxt_debug(task, "old router conf is destroyed");
|
||||
|
||||
#if (NXT_TLS)
|
||||
if (skcf->tls != NULL) {
|
||||
task->thread->runtime->tls->server_free(task, skcf->tls);
|
||||
}
|
||||
#endif
|
||||
|
||||
nxt_router_access_log_release(task, lock, rtcf->access_log);
|
||||
|
||||
nxt_mp_thread_adopt(rtcf->mem_pool);
|
||||
|
||||
@@ -153,6 +153,10 @@ typedef struct {
|
||||
nxt_msec_t header_read_timeout;
|
||||
nxt_msec_t body_read_timeout;
|
||||
nxt_msec_t send_timeout;
|
||||
|
||||
#if (NXT_TLS)
|
||||
nxt_tls_conf_t *tls;
|
||||
#endif
|
||||
} nxt_socket_conf_t;
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ struct nxt_runtime_s {
|
||||
|
||||
nxt_file_name_t *pid_file;
|
||||
|
||||
#if (NXT_TLS)
|
||||
const nxt_tls_lib_t *tls;
|
||||
#endif
|
||||
|
||||
nxt_array_t *thread_pools; /* of nxt_thread_pool_t */
|
||||
nxt_runtime_cont_t continuation;
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
typedef struct {
|
||||
nxt_buf_t *buf;
|
||||
void *tls;
|
||||
nxt_socket_t socket;
|
||||
nxt_err_t error;
|
||||
nxt_off_t sent;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_main.h>
|
||||
@@ -4,8 +4,8 @@
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_SSLTLS_H_INCLUDED_
|
||||
#define _NXT_SSLTLS_H_INCLUDED_
|
||||
#ifndef _NXT_TLS_H_INCLUDED_
|
||||
#define _NXT_TLS_H_INCLUDED_
|
||||
|
||||
|
||||
/*
|
||||
@@ -20,24 +20,29 @@
|
||||
* and compatible with tunnels.
|
||||
*/
|
||||
|
||||
#define NXT_SSLTLS_BUFFER_SIZE 4096
|
||||
#define NXT_TLS_BUFFER_SIZE 4096
|
||||
|
||||
|
||||
typedef struct nxt_ssltls_conf_s nxt_ssltls_conf_t;
|
||||
typedef struct nxt_tls_conf_s nxt_tls_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_int_t (*server_init)(nxt_ssltls_conf_t *conf);
|
||||
nxt_int_t (*set_versions)(nxt_ssltls_conf_t *conf);
|
||||
} nxt_ssltls_lib_t;
|
||||
nxt_int_t (*library_init)(nxt_task_t *task);
|
||||
void (*library_free)(nxt_task_t *task);
|
||||
|
||||
nxt_int_t (*server_init)(nxt_task_t *task,
|
||||
nxt_tls_conf_t *conf);
|
||||
void (*server_free)(nxt_task_t *task,
|
||||
nxt_tls_conf_t *conf);
|
||||
} nxt_tls_lib_t;
|
||||
|
||||
|
||||
struct nxt_ssltls_conf_s {
|
||||
struct nxt_tls_conf_s {
|
||||
void *ctx;
|
||||
void (*conn_init)(nxt_task_t *task,
|
||||
nxt_ssltls_conf_t *conf, nxt_conn_t *c);
|
||||
nxt_tls_conf_t *conf, nxt_conn_t *c);
|
||||
|
||||
const nxt_ssltls_lib_t *lib;
|
||||
const nxt_tls_lib_t *lib;
|
||||
|
||||
char *certificate;
|
||||
char *certificate_key;
|
||||
@@ -50,20 +55,24 @@ struct nxt_ssltls_conf_s {
|
||||
|
||||
|
||||
#if (NXT_HAVE_OPENSSL)
|
||||
extern const nxt_ssltls_lib_t nxt_openssl_lib;
|
||||
extern const nxt_tls_lib_t nxt_openssl_lib;
|
||||
|
||||
void nxt_cdecl nxt_openssl_log_error(nxt_task_t *task, nxt_uint_t level,
|
||||
const char *fmt, ...);
|
||||
u_char *nxt_openssl_copy_error(u_char *p, u_char *end);
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_GNUTLS)
|
||||
extern const nxt_ssltls_lib_t nxt_gnutls_lib;
|
||||
extern const nxt_tls_lib_t nxt_gnutls_lib;
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_CYASSL)
|
||||
extern const nxt_ssltls_lib_t nxt_cyassl_lib;
|
||||
extern const nxt_tls_lib_t nxt_cyassl_lib;
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_POLARSSL)
|
||||
extern const nxt_ssltls_lib_t nxt_polar_lib;
|
||||
extern const nxt_tls_lib_t nxt_polar_lib;
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _NXT_SSLTLS_H_INCLUDED_ */
|
||||
#endif /* _NXT_TLS_H_INCLUDED_ */
|
||||
Reference in New Issue
Block a user