diff options
author | jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2011-11-05 03:19:07 +0000 |
---|---|---|
committer | jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2011-11-05 03:19:07 +0000 |
commit | 52f10ff67fb41ea3738a4b0ab48b561c22200009 (patch) | |
tree | 34be5f9820379f7b7a9edaad8fcba5e461b10663 /package/uhttpd/src/uhttpd-tls.c | |
parent | 47cebba347fe9e484656576a0df3459921d517d5 (diff) |
[package] uhttpd: rework CyaSSL and OpenSSL integration; move protected recv() and send() operations below the ssl layer - fixes hangs when accessing via https
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@28761 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/uhttpd/src/uhttpd-tls.c')
-rw-r--r-- | package/uhttpd/src/uhttpd-tls.c | 144 |
1 files changed, 141 insertions, 3 deletions
diff --git a/package/uhttpd/src/uhttpd-tls.c b/package/uhttpd/src/uhttpd-tls.c index 6beae25aa1..4a9e907922 100644 --- a/package/uhttpd/src/uhttpd-tls.c +++ b/package/uhttpd/src/uhttpd-tls.c @@ -20,6 +20,143 @@ #include "uhttpd-tls.h" #include "uhttpd-utils.h" +#include <syslog.h> +#define dbg(...) syslog(LOG_INFO, __VA_ARGS__) + +#ifdef TLS_IS_CYASSL +static int uh_cyassl_recv_cb(char *buf, int sz, void *ctx) +{ + int rv; + int socket = *(int *)ctx; + struct client *cl; + + if (!(cl = uh_client_lookup(socket))) + return -1; /* unexpected error */ + + rv = uh_tcp_recv_lowlevel(cl, buf, sz); + + if (rv < 0) + return -4; /* interrupted */ + + if (rv == 0) + return -5; /* connection closed */ + + return rv; +} + +static int uh_cyassl_send_cb(char *buf, int sz, void *ctx) +{ + int rv; + int socket = *(int *)ctx; + struct client *cl; + + if (!(cl = uh_client_lookup(socket))) + return -1; /* unexpected error */ + + rv = uh_tcp_send_lowlevel(cl, buf, sz); + + if (rv <= 0) + return -5; /* connection dead */ + + return rv; +} + +void SetCallbackIORecv_Ctx(SSL_CTX*, int (*)(char *, int, void *)); +void SetCallbackIOSend_Ctx(SSL_CTX*, int (*)(char *, int, void *)); + +static void uh_tls_ctx_setup(SSL_CTX *ctx) +{ + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + SetCallbackIORecv_Ctx(ctx, uh_cyassl_recv_cb); + SetCallbackIOSend_Ctx(ctx, uh_cyassl_send_cb); + return; +} + +static int uh_tls_client_ctx_setup(SSL *ssl, int socket) +{ + return SSL_set_fd(ssl, socket); +} +#endif /* TLS_IS_CYASSL */ + +#ifdef TLS_IS_OPENSSL +static long uh_openssl_bio_ctrl_cb(BIO *b, int cmd, long num, void *ptr) +{ + long rv = 1; + + switch (cmd) + { + case BIO_C_SET_FD: + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + + case BIO_C_GET_FD: + if (!b->init) + return -1; + + if (ptr) + *((int *)ptr) = b->num; + + rv = b->num; + break; + } + + return rv; +} + +static int uh_openssl_bio_read_cb(BIO *b, char *out, int outl) +{ + int rv = 0; + struct client *cl; + + if (!(cl = uh_client_lookup(b->num))) + return -1; + + if (out != NULL) + rv = uh_tcp_recv_lowlevel(cl, out, outl); + + return rv; +} + +static int uh_openssl_bio_write_cb(BIO *b, const char *in, int inl) +{ + struct client *cl; + + if (!(cl = uh_client_lookup(b->num))) + return -1; + + return uh_tcp_send_lowlevel(cl, in, inl); +} + +static BIO_METHOD uh_openssl_bio_methods = { + .type = BIO_TYPE_SOCKET, + .name = "uhsocket", + .ctrl = uh_openssl_bio_ctrl_cb, + .bwrite = uh_openssl_bio_write_cb, + .bread = uh_openssl_bio_read_cb +}; + +static void uh_tls_ctx_setup(SSL_CTX *ctx) +{ + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + return; +} + +static int uh_tls_client_ctx_setup(SSL *ssl, int socket) +{ + BIO *b; + + if (!(b = BIO_new(&uh_openssl_bio_methods))) + return 0; + + BIO_set_fd(b, socket, BIO_NOCLOSE); + SSL_set_bio(ssl, b, b); + + return 1; +} +#endif /* TLS_IS_OPENSSL */ + SSL_CTX * uh_tls_ctx_init() { @@ -28,8 +165,8 @@ SSL_CTX * uh_tls_ctx_init() SSL_load_error_strings(); SSL_library_init(); - if( (c = SSL_CTX_new(TLSv1_server_method())) != NULL ) - SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); + if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL) + uh_tls_ctx_setup(c); return c; } @@ -69,8 +206,9 @@ int uh_tls_client_accept(struct client *c) c->tls = SSL_new(c->server->tls); if( c->tls ) { - if( (rv = SSL_set_fd(c->tls, c->socket)) < 1 ) + if( (rv = uh_tls_client_ctx_setup(c->tls, c->socket)) < 1 ) goto cleanup; + if( (rv = SSL_accept(c->tls)) < 1 ) goto cleanup; } |