[package] uhttpd: rework CyaSSL and OpenSSL integration; move protected recv() and...
[openwrt.git] / package / uhttpd / src / uhttpd-tls.c
index 6beae25..4a9e907 100644 (file)
 #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;
                }