ADD_DEFINITIONS(-Wno-unused-parameter -Wmissing-declarations)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+IF (NOT APPLE)
+ SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined")
+ENDIF()
IF(MBEDTLS)
ADD_DEFINITIONS(-DHAVE_MBEDTLS)
U_SSL_OK = 0,
U_SSL_PENDING = -1,
U_SSL_ERROR = -2,
+ U_SSL_RETRY = -3,
};
-void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *s);
+void ustream_set_io(struct ustream_ssl *us);
struct ustream_ssl_ctx *__ustream_ssl_context_new(bool server);
int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file);
int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file);
int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file);
int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers);
int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require);
+void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level, ustream_ssl_debug_cb cb, void *cb_priv);
void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx);
enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us);
int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len);
int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len);
+void __ustream_ssl_session_free(struct ustream_ssl *us);
#endif
return bio;
}
-__hidden void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *conn)
+static BIO *fd_bio_new(int fd)
{
- BIO *bio = ustream_bio_new(conn);
- SSL_set_bio(ssl, bio, bio);
+ BIO *bio = BIO_new(BIO_s_socket());
+
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+
+ return bio;
+}
+
+__hidden void ustream_set_io(struct ustream_ssl *us)
+{
+ BIO *bio;
+
+ if (us->conn)
+ bio = ustream_bio_new(us->conn);
+ else
+ bio = fd_bio_new(us->fd.fd);
+
+ SSL_set_bio(us->ssl, bio, bio);
}
return s_ustream_write(buf, sz, ctx);
}
-__hidden void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *conn)
+__hidden void ustream_set_io(struct ustream_ssl *us)
{
- wolfSSL_SSLSetIORecv(ssl, io_recv_cb);
- wolfSSL_SSLSetIOSend(ssl, io_send_cb);
- wolfSSL_SetIOReadCtx(ssl, conn);
- wolfSSL_SetIOWriteCtx(ssl, conn);
+ if (!us->conn) {
+ wolfSSL_set_fd(us->ssl, us->fd.fd);
+ return;
+ }
+
+ wolfSSL_SSLSetIORecv(us->ssl, io_recv_cb);
+ wolfSSL_SSLSetIOSend(us->ssl, io_send_cb);
+ wolfSSL_SetIOReadCtx(us->ssl, us->conn);
+ wolfSSL_SetIOWriteCtx(us->ssl, us->conn);
}
#include "ustream-ssl.h"
#include "ustream-internal.h"
+#include <psa/crypto.h>
+#include <mbedtls/debug.h>
+
+static void debug_cb(void *ctx_p, int level,
+ const char *file, int line,
+ const char *str)
+{
+ struct ustream_ssl_ctx *ctx = ctx_p;
+ const char *fstr;
+ char buf[512];
+ int len;
+
+ if (!ctx->debug_cb)
+ return;
+
+ while ((fstr = strstr(file + 1, "library/")) != NULL)
+ file = fstr;
+
+ len = snprintf(buf, sizeof(buf), "%s:%04d: %s", file, line, str);
+ if (len >= (int)sizeof(buf))
+ len = (int)sizeof(buf) - 1;
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = 0;
+ ctx->debug_cb(ctx->debug_cb_priv, level, buf);
+}
static int s_ustream_read(void *ctx, unsigned char *buf, size_t len)
{
return ret;
}
-__hidden void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *conn)
+static int s_fd_read(void *ctx, unsigned char *buf, size_t len)
+{
+ struct uloop_fd *ufd = ctx;
+ mbedtls_net_context net = {
+ .fd = ufd->fd
+ };
+
+ return mbedtls_net_recv(&net, buf, len);
+}
+
+static int s_fd_write(void *ctx, const unsigned char *buf, size_t len)
+{
+ struct uloop_fd *ufd = ctx;
+ mbedtls_net_context net = {
+ .fd = ufd->fd
+ };
+
+ return mbedtls_net_send(&net, buf, len);
+}
+
+__hidden void ustream_set_io(struct ustream_ssl *us)
{
- mbedtls_ssl_set_bio(ssl, conn, s_ustream_write, s_ustream_read, NULL);
+ if (us->conn)
+ mbedtls_ssl_set_bio(us->ssl, us->conn, s_ustream_write, s_ustream_read, NULL);
+ else
+ mbedtls_ssl_set_bio(us->ssl, &us->fd, s_fd_write, s_fd_read, NULL);
}
static int _random(void *ctx, unsigned char *out, size_t len)
{
- ssize_t ret;
+#ifdef linux
+ if (getrandom(out, len, 0) != (ssize_t) len)
+ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+#else
+ static FILE *f;
- ret = getrandom(out, len, 0);
- if (ret < 0 || (size_t)ret != len)
+ if (!f)
+ f = fopen("/dev/urandom", "r");
+ if (fread(out, len, 1, f) != 1)
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+#endif
return 0;
}
static const int default_ciphersuites_server[] =
{
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
+ MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
+ MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
+ MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
+ MBEDTLS_TLS1_3_AES_128_CCM_SHA256,
+ MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,
+#endif
+
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
AES_GCM_CIPHERS(ECDHE_ECDSA),
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
static const int default_ciphersuites_client[] =
{
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
+ MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
+ MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
+ MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
+ MBEDTLS_TLS1_3_AES_128_CCM_SHA256,
+ MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,
+#endif
+
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
AES_GCM_CIPHERS(ECDHE_ECDSA),
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
mbedtls_ssl_config *conf;
int ep;
+#ifdef MBEDTLS_PSA_CRYPTO_C
+ static bool psa_init;
+
+ if (!psa_init && !psa_crypto_init())
+ psa_init = true;
+#endif
+
ctx = calloc(1, sizeof(*ctx));
if (!ctx)
return NULL;
if (!require)
mode = MBEDTLS_SSL_VERIFY_NONE;
+ /* force TLS 1.2 when not requiring validation for now */
+ if (!require && !ctx->server)
+ mbedtls_ssl_conf_max_version(&ctx->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+ MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_authmode(&ctx->conf, mode);
return 0;
__hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
{
+ free(ctx->session_data);
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_free(&ctx->cache);
#endif
uloop_timeout_set(&us->error_timer, 0);
}
-static bool ssl_do_wait(int ret)
+#ifdef MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET
+static void
+__ustream_ssl_save_session(struct ustream_ssl *us)
+{
+ struct ustream_ssl_ctx *ctx = us->ctx;
+ mbedtls_ssl_session sess;
+
+ if (ctx->server)
+ return;
+
+ free(ctx->session_data);
+ ctx->session_data = NULL;
+
+ mbedtls_ssl_session_init(&sess);
+ if (mbedtls_ssl_get_session(us->ssl, &sess) != 0)
+ return;
+
+ mbedtls_ssl_session_save(&sess, NULL, 0, &ctx->session_data_len);
+ ctx->session_data = malloc(ctx->session_data_len);
+ if (mbedtls_ssl_session_save(&sess, ctx->session_data, ctx->session_data_len,
+ &ctx->session_data_len))
+ ctx->session_data_len = 0;
+ mbedtls_ssl_session_free(&sess);
+}
+#endif
+
+static int ssl_check_return(struct ustream_ssl *us, int ret)
{
switch(ret) {
case MBEDTLS_ERR_SSL_WANT_READ:
case MBEDTLS_ERR_SSL_WANT_WRITE:
- return true;
+ return U_SSL_PENDING;
+#ifdef MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET
+ case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
+ __ustream_ssl_save_session(us);
+ return U_SSL_RETRY;
+#endif
+#ifdef MBEDTLS_ECP_RESTARTABLE
+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
+ return U_SSL_RETRY;
+#endif
+ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+ case MBEDTLS_ERR_NET_CONN_RESET:
+ return 0;
default:
- return false;
+ ustream_ssl_error(us, ret);
+ return U_SSL_ERROR;
}
}
void *ssl = us->ssl;
int r;
- r = mbedtls_ssl_handshake(ssl);
- if (r == 0) {
- ustream_ssl_verify_cert(us);
- return U_SSL_OK;
- }
+ do {
+ r = mbedtls_ssl_handshake(ssl);
+ if (r == 0) {
+ ustream_ssl_verify_cert(us);
+ return U_SSL_OK;
+ }
- if (ssl_do_wait(r))
- return U_SSL_PENDING;
+ r = ssl_check_return(us, r);
+ } while (r == U_SSL_RETRY);
- ustream_ssl_error(us, r);
- return U_SSL_ERROR;
+ return r;
}
__hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len)
while (done != len) {
ret = mbedtls_ssl_write(ssl, (const unsigned char *) buf + done, len - done);
-
if (ret < 0) {
- if (ssl_do_wait(ret))
+ ret = ssl_check_return(us, ret);
+ if (ret == U_SSL_RETRY)
+ continue;
+
+ if (ret == U_SSL_PENDING)
return done;
- ustream_ssl_error(us, ret);
return -1;
}
__hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len)
{
- int ret = mbedtls_ssl_read(us->ssl, (unsigned char *) buf, len);
-
- if (ret < 0) {
- if (ssl_do_wait(ret))
- return U_SSL_PENDING;
+ int ret;
- if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
- return 0;
+ do {
+ ret = mbedtls_ssl_read(us->ssl, (unsigned char *) buf, len);
+ if (ret >= 0)
+ return ret;
- ustream_ssl_error(us, ret);
- return U_SSL_ERROR;
- }
+ ret = ssl_check_return(us, ret);
+ } while (ret == U_SSL_RETRY);
return ret;
}
+__hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level,
+ ustream_ssl_debug_cb cb, void *cb_priv)
+{
+ ctx->debug_cb = cb;
+ ctx->debug_cb_priv = cb_priv;
+ mbedtls_ssl_conf_dbg(&ctx->conf, debug_cb, ctx);
+#ifdef MBEDTLS_DEBUG_C
+ mbedtls_debug_set_threshold(level);
+#endif
+}
+
__hidden void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx)
{
mbedtls_ssl_context *ssl;
+ mbedtls_ssl_session sess;
ssl = calloc(1, sizeof(*ssl));
if (!ssl)
return NULL;
}
+ if (!ctx->session_data_len)
+ return ssl;
+
+ mbedtls_ssl_session_init(&sess);
+ if (mbedtls_ssl_session_load(&sess, ctx->session_data, ctx->session_data_len) == 0)
+ mbedtls_ssl_set_session(ssl, &sess);
+
return ssl;
}
-__hidden void __ustream_ssl_session_free(void *ssl)
+__hidden void __ustream_ssl_session_free(struct ustream_ssl *us)
{
- mbedtls_ssl_free(ssl);
- free(ssl);
+ mbedtls_ssl_free(us->ssl);
+ free(us->ssl);
}
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache;
#endif
+ ustream_ssl_debug_cb debug_cb;
+ void *debug_cb_priv;
bool server;
int *ciphersuites;
+
+ void *session_data;
+ size_t session_data_len;
};
static inline char *__ustream_ssl_strerror(int error, char *buffer, int len)
mbedtls_ssl_set_hostname(us->ssl, us->peer_cn);
}
-void __ustream_ssl_session_free(void *ssl);
void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx);
#endif
__hidden struct ustream_ssl_ctx *
__ustream_ssl_context_new(bool server)
{
+ struct ustream_ssl_ctx *ctx;
const void *m;
SSL_CTX *c;
if (!c)
return NULL;
+ ctx = calloc(1, sizeof(*ctx));
+ ctx->ssl = c;
+
#if defined(HAVE_WOLFSSL)
if (server)
SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
}
SSL_CTX_set_quiet_shutdown(c, 1);
- return (void *) c;
+ return ctx;
}
__hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
{
int ret;
- ret = SSL_CTX_load_verify_locations((void *) ctx, file, NULL);
+ ret = SSL_CTX_load_verify_locations(ctx->ssl, file, NULL);
if (ret < 1)
return -1;
{
int ret;
- ret = SSL_CTX_use_certificate_chain_file((void *) ctx, file);
+ ret = SSL_CTX_use_certificate_chain_file(ctx->ssl, file);
if (ret < 1)
- ret = SSL_CTX_use_certificate_file((void *) ctx, file, SSL_FILETYPE_ASN1);
+ ret = SSL_CTX_use_certificate_file(ctx->ssl, file, SSL_FILETYPE_ASN1);
if (ret < 1)
return -1;
{
int ret;
- ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_PEM);
+ ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_PEM);
if (ret < 1)
- ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_ASN1);
+ ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_ASN1);
if (ret < 1)
return -1;
__hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers)
{
- int ret = SSL_CTX_set_cipher_list((void *) ctx, ciphers);
+ int ret = SSL_CTX_set_cipher_list(ctx->ssl, ciphers);
if (ret == 0)
return -1;
if (!require)
mode = SSL_VERIFY_NONE;
- SSL_CTX_set_verify((void *) ctx, mode, NULL);
+ SSL_CTX_set_verify(ctx->ssl, mode, NULL);
return 0;
}
__hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
{
- SSL_CTX_free((void *) ctx);
+ SSL_CTX_free(ctx->ssl);
+ if (ctx->debug_bio)
+ BIO_free(ctx->debug_bio);
+ free(ctx);
}
-void __ustream_ssl_session_free(void *ssl)
+__hidden void __ustream_ssl_session_free(struct ustream_ssl *us)
{
- BIO *bio = SSL_get_wbio(ssl);
- struct bio_ctx *ctx = BIO_get_data(bio);
+ BIO *bio = SSL_get_wbio(us->ssl);
+ struct bio_ctx *ctx;
+
+ SSL_shutdown(us->ssl);
+ SSL_free(us->ssl);
- SSL_shutdown(ssl);
- SSL_free(ssl);
+ if (!us->conn)
+ return;
+
+ ctx = BIO_get_data(bio);
if (ctx) {
BIO_meth_free(ctx->meth);
free(ctx);
return ret;
}
+
+#ifndef WOLFSSL_SSL_H
+static long
+debug_cb(BIO *bio, int cmd, const char *argp, size_t len, int argi, long argl,
+ int ret, size_t *processed)
+{
+ struct ustream_ssl_ctx *ctx = (void *)BIO_get_callback_arg(bio);
+ char buf[256];
+ char *str, *sep;
+ ssize_t cur_len;
+
+ if (cmd != (BIO_CB_WRITE|BIO_CB_RETURN))
+ goto out;
+
+ while (1) {
+ cur_len = BIO_get_mem_data(bio, (void *)&str);
+ if (!cur_len)
+ break;
+
+ sep = memchr(str, '\n', cur_len);
+ if (!sep)
+ break;
+
+ cur_len = sep + 1 - str;
+ if (cur_len >= (ssize_t)sizeof(buf))
+ cur_len = sizeof(buf) - 1;
+
+ cur_len = BIO_read(bio, buf, cur_len);
+ if (cur_len <= 1)
+ break;
+
+ cur_len--;
+ buf[cur_len] = 0;
+ if (ctx->debug_cb)
+ ctx->debug_cb(ctx->debug_cb_priv, 1, buf);
+ }
+
+out:
+ return ret;
+}
+#endif
+
+__hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level,
+ ustream_ssl_debug_cb cb, void *cb_priv)
+{
+#ifndef WOLFSSL_SSL_H
+ if (!ctx->debug_bio)
+ ctx->debug_bio = BIO_new(BIO_s_mem());
+
+ ctx->debug_cb = cb;
+ ctx->debug_cb_priv = cb_priv;
+ SSL_CTX_set_msg_callback(ctx->ssl, SSL_trace);
+ SSL_CTX_set_msg_callback_arg(ctx->ssl, ctx->debug_bio);
+
+ BIO_set_callback_ex(ctx->debug_bio, debug_cb);
+ BIO_set_callback_arg(ctx->debug_bio, (void *)ctx);
+#endif
+}
#include <stdbool.h>
-void __ustream_ssl_session_free(void *ssl);
+struct ustream_ssl_ctx {
+ SSL_CTX *ssl;
+ BIO *debug_bio;
+ ustream_ssl_debug_cb debug_cb;
+ void *debug_cb_priv;
+};
struct bio_ctx {
BIO_METHOD *meth;
struct ustream *stream;
};
-static inline void *__ustream_ssl_session_new(void *ctx)
+static inline void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx)
{
- return SSL_new(ctx);
+ return SSL_new(ctx->ssl);
}
static inline char *__ustream_ssl_strerror(int error, char *buffer, int len)
}
}
-static bool __ustream_ssl_poll(struct ustream *s)
+static bool __ustream_ssl_poll(struct ustream_ssl *us)
{
- struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
char *buf;
int len, ret;
bool more = false;
break;
ret = __ustream_ssl_read(us, buf, len);
+ if (ret == U_SSL_PENDING) {
+ if (us->conn)
+ ustream_poll(us->conn);
+ ret = __ustream_ssl_read(us, buf, len);
+ }
+
switch (ret) {
case U_SSL_PENDING:
return more;
static void ustream_ssl_notify_read(struct ustream *s, int bytes)
{
- __ustream_ssl_poll(s);
+ struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
+
+ __ustream_ssl_poll(us);
}
static void ustream_ssl_notify_write(struct ustream *s, int bytes)
if (!us->connected || us->error)
return 0;
- if (us->conn->w.data_bytes)
+ if (us->conn && us->conn->w.data_bytes)
return 0;
return __ustream_ssl_write(us, buf, len);
static void ustream_ssl_set_read_blocked(struct ustream *s)
{
struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
+ unsigned int ev = ULOOP_WRITE | ULOOP_EDGE_TRIGGER;
+
+ if (us->conn) {
+ ustream_set_read_blocked(us->conn, !!s->read_blocked);
+ return;
+ }
+
+ if (!s->read_blocked)
+ ev |= ULOOP_READ;
- ustream_set_read_blocked(us->conn, !!s->read_blocked);
+ uloop_fd_add(&us->fd, ev);
}
static void ustream_ssl_free(struct ustream *s)
us->conn->notify_read = NULL;
us->conn->notify_write = NULL;
us->conn->notify_state = NULL;
+ } else {
+ uloop_fd_delete(&us->fd);
}
uloop_timeout_cancel(&us->error_timer);
- __ustream_ssl_session_free(us->ssl);
+ __ustream_ssl_session_free(us);
free(us->peer_cn);
us->ctx = NULL;
static bool ustream_ssl_poll(struct ustream *s)
{
struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
- bool fd_poll;
+ bool fd_poll = false;
- fd_poll = ustream_poll(us->conn);
- return __ustream_ssl_poll(us->conn) || fd_poll;
+ if (us->conn)
+ fd_poll = ustream_poll(us->conn);
+
+ return __ustream_ssl_poll(us) || fd_poll;
+}
+
+static void ustream_ssl_fd_cb(struct uloop_fd *fd, unsigned int events)
+{
+ struct ustream_ssl *us = container_of(fd, struct ustream_ssl, fd);
+
+ __ustream_ssl_poll(us);
}
static void ustream_ssl_stream_init(struct ustream_ssl *us)
struct ustream *conn = us->conn;
struct ustream *s = &us->stream;
- conn->notify_read = ustream_ssl_notify_read;
- conn->notify_write = ustream_ssl_notify_write;
- conn->notify_state = ustream_ssl_notify_state;
+ if (conn) {
+ conn->notify_read = ustream_ssl_notify_read;
+ conn->notify_write = ustream_ssl_notify_write;
+ conn->notify_state = ustream_ssl_notify_state;
+ } else {
+ us->fd.cb = ustream_ssl_fd_cb;
+ uloop_fd_add(&us->fd, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
+ }
+ s->set_read_blocked = ustream_ssl_set_read_blocked;
s->free = ustream_ssl_free;
s->write = ustream_ssl_write;
s->poll = ustream_ssl_poll;
- s->set_read_blocked = ustream_ssl_set_read_blocked;
ustream_init_defaults(s);
}
-static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server)
+static int _ustream_ssl_init_common(struct ustream_ssl *us)
{
us->error_timer.cb = ustream_ssl_error_cb;
- us->server = server;
- us->conn = conn;
- us->ctx = ctx;
us->ssl = __ustream_ssl_session_new(us->ctx);
if (!us->ssl)
return -ENOMEM;
- conn->next = &us->stream;
- ustream_set_io(ctx, us->ssl, conn);
+ ustream_set_io(us);
ustream_ssl_stream_init(us);
if (us->server_name)
return 0;
}
+static int _ustream_ssl_init_fd(struct ustream_ssl *us, int fd, struct ustream_ssl_ctx *ctx, bool server)
+{
+ us->server = server;
+ us->ctx = ctx;
+ us->fd.fd = fd;
+
+ return _ustream_ssl_init_common(us);
+}
+
+static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server)
+{
+ us->server = server;
+ us->ctx = ctx;
+
+ us->conn = conn;
+ conn->r.max_buffers = 4;
+ conn->next = &us->stream;
+
+ return _ustream_ssl_init_common(us);
+}
+
static int _ustream_ssl_set_peer_cn(struct ustream_ssl *us, const char *name)
{
us->peer_cn = strdup(name);
.context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file,
.context_set_ciphers = __ustream_ssl_set_ciphers,
.context_set_require_validation = __ustream_ssl_set_require_validation,
+ .context_set_debug = __ustream_ssl_set_debug,
.context_free = __ustream_ssl_context_free,
.init = _ustream_ssl_init,
+ .init_fd = _ustream_ssl_init_fd,
.set_peer_cn = _ustream_ssl_set_peer_cn,
};
struct ustream stream;
struct ustream *conn;
struct uloop_timeout error_timer;
+ struct uloop_fd fd;
void (*notify_connected)(struct ustream_ssl *us);
void (*notify_error)(struct ustream_ssl *us, int error, const char *str);
struct ustream_ssl_ctx;
-struct ustream_ssl_ops {
+typedef void (*ustream_ssl_debug_cb)(void *priv, int level, const char *msg);
+struct ustream_ssl_ops {
struct ustream_ssl_ctx *(*context_new)(bool server);
int (*context_set_crt_file)(struct ustream_ssl_ctx *ctx, const char *file);
int (*context_set_key_file)(struct ustream_ssl_ctx *ctx, const char *file);
int (*context_add_ca_crt_file)(struct ustream_ssl_ctx *ctx, const char *file);
void (*context_free)(struct ustream_ssl_ctx *ctx);
+ int (*init_fd)(struct ustream_ssl *us, int fd, struct ustream_ssl_ctx *ctx, bool server);
int (*init)(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server);
int (*set_peer_cn)(struct ustream_ssl *conn, const char *name);
int (*context_set_ciphers)(struct ustream_ssl_ctx *ctx, const char *ciphers);
+ void (*context_set_debug)(struct ustream_ssl_ctx *ctx, int level, ustream_ssl_debug_cb cb, void *cb_priv);
int (*context_set_require_validation)(struct ustream_ssl_ctx *ctx, bool require);
};
#define ustream_ssl_context_set_key_file ustream_ssl_ops.context_set_key_file
#define ustream_ssl_context_add_ca_crt_file ustream_ssl_ops.context_add_ca_crt_file
#define ustream_ssl_context_set_ciphers ustream_ssl_ops.context_set_ciphers
+#define ustream_ssl_context_set_debug ustream_ssl_ops.context_set_debug
#define ustream_ssl_context_set_require_validation ustream_ssl_ops.context_set_require_validation
#define ustream_ssl_context_free ustream_ssl_ops.context_free
#define ustream_ssl_init ustream_ssl_ops.init