Changeset 28761


Ignore:
Timestamp:
2011-11-05T04:19:07+01:00 (6 years ago)
Author:
jow
Message:

[package] uhttpd: rework CyaSSL and OpenSSL integration; move protected recv() and send() operations below the ssl layer - fixes hangs when accessing via https

Location:
trunk/package/uhttpd
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/uhttpd/Makefile

    r28254 r28761  
    6666UHTTPD_TLS:= 
    6767TLS_CFLAGS:= 
     68TLS_LDFLAGS:= 
    6869 
    6970ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_cyassl),) 
    7071  UHTTPD_TLS:=cyassl 
    71   TLS_CFLAGS:=-I$(STAGING_DIR)/usr/include/cyassl 
     72  TLS_CFLAGS:=-I$(STAGING_DIR)/usr/include/cyassl -DTLS_IS_CYASSL 
    7273endif 
    7374 
    7475ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_openssl),) 
    7576  UHTTPD_TLS:=openssl 
     77  TLS_CFLAGS:=-DTLS_IS_OPENSSL 
    7678endif 
    7779 
  • trunk/package/uhttpd/src/Makefile

    r27686 r28761  
    44UHTTPD_TLS ?= cyassl 
    55 
    6 CFLAGS ?= -I./lua-5.1.4/src -I$(TLS_INCLUDE_DIR) -O0 -ggdb3 
    7 LDFLAGS ?= -L./lua-5.1.4/src -L$(TLS_LIB_DIR) 
     6CFLAGS ?= -I./lua-5.1.4/src $(TLS_CFLAGS) -O0 -ggdb3 
     7LDFLAGS ?= -L./lua-5.1.4/src $(TLS_LDFLAGS) 
    88 
    99CFLAGS += -Wall --std=gnu99 
    1010 
    1111ifeq ($(UHTTPD_TLS),openssl) 
    12   TLS_LDFLAGS := -lssl 
    13   TLS_INCLUDE_DIR := ./openssl-0.9.8m/include 
    14   TLS_LIB_DIR := ./openssl-0.9.8m 
     12  TLS_LDFLAGS := -L./openssl-0.9.8m -lssl 
     13  TLS_CFLAGS := -I./openssl-0.9.8m/include -DTLS_IS_OPENSSL 
    1514else 
    16   TLS_LDFLAGS := -lcyassl 
    17   TLS_INCLUDE_DIR := ./cyassl-1.4.0/include 
    18   TLS_LIB_DIR := ./cyassl-1.4.0/src/.libs 
     15  TLS_LDFLAGS := -L./cyassl-1.4.0/src/.libs -lcyassl 
     16  TLS_CFLAGS := -I./cyassl-1.4.0/include -DTLS_IS_CYASSL 
    1917endif 
    2018 
     
    3230endif 
    3331 
    34 world: compile 
     32ifeq ($(TLS_SUPPORT),1) 
     33  CFLAGS += -DHAVE_TLS 
     34endif 
    3535 
    3636ifeq ($(CGI_SUPPORT),1) 
    37   OBJ += uhttpd-cgi.o 
    3837  CFLAGS += -DHAVE_CGI 
    3938endif 
     
    4140ifeq ($(LUA_SUPPORT),1) 
    4241  CFLAGS += -DHAVE_LUA 
     42endif 
     43 
     44 
     45world: compile 
     46 
     47ifeq ($(CGI_SUPPORT),1) 
     48  OBJ += uhttpd-cgi.o 
     49endif 
     50 
     51ifeq ($(LUA_SUPPORT),1) 
    4352  LUALIB := uhttpd_lua.so 
    4453 
     
    5059 
    5160ifeq ($(TLS_SUPPORT),1) 
    52   CFLAGS += -DHAVE_TLS 
    5361  TLSLIB := uhttpd_tls.so 
    5462 
    5563  $(TLSLIB): uhttpd-tls.c 
    5664                $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \ 
    57                         -shared $(TLS_LDFLAGS) \ 
     65                        -shared \ 
    5866                        -o $(TLSLIB) uhttpd-tls.c 
    5967endif 
  • trunk/package/uhttpd/src/uhttpd-tls.c

    r27686 r28761  
    2121#include "uhttpd-utils.h" 
    2222 
     23#include <syslog.h> 
     24#define dbg(...) syslog(LOG_INFO, __VA_ARGS__) 
     25 
     26#ifdef TLS_IS_CYASSL 
     27static int uh_cyassl_recv_cb(char *buf, int sz, void *ctx) 
     28{ 
     29        int rv; 
     30        int socket = *(int *)ctx; 
     31        struct client *cl; 
     32 
     33        if (!(cl = uh_client_lookup(socket))) 
     34                return -1; /* unexpected error */ 
     35 
     36        rv = uh_tcp_recv_lowlevel(cl, buf, sz); 
     37 
     38        if (rv < 0) 
     39                return -4; /* interrupted */ 
     40 
     41        if (rv == 0) 
     42                return -5; /* connection closed */ 
     43 
     44        return rv; 
     45} 
     46 
     47static int uh_cyassl_send_cb(char *buf, int sz, void *ctx) 
     48{ 
     49        int rv; 
     50        int socket = *(int *)ctx; 
     51        struct client *cl; 
     52 
     53        if (!(cl = uh_client_lookup(socket))) 
     54                return -1; /* unexpected error */ 
     55 
     56        rv = uh_tcp_send_lowlevel(cl, buf, sz); 
     57 
     58        if (rv <= 0) 
     59                return -5; /* connection dead */ 
     60 
     61        return rv; 
     62} 
     63 
     64void SetCallbackIORecv_Ctx(SSL_CTX*, int (*)(char *, int, void *)); 
     65void SetCallbackIOSend_Ctx(SSL_CTX*, int (*)(char *, int, void *)); 
     66 
     67static void uh_tls_ctx_setup(SSL_CTX *ctx) 
     68{ 
     69        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 
     70        SetCallbackIORecv_Ctx(ctx, uh_cyassl_recv_cb); 
     71        SetCallbackIOSend_Ctx(ctx, uh_cyassl_send_cb); 
     72        return; 
     73} 
     74 
     75static int uh_tls_client_ctx_setup(SSL *ssl, int socket) 
     76{ 
     77        return SSL_set_fd(ssl, socket); 
     78} 
     79#endif /* TLS_IS_CYASSL */ 
     80 
     81#ifdef TLS_IS_OPENSSL 
     82static long uh_openssl_bio_ctrl_cb(BIO *b, int cmd, long num, void *ptr) 
     83{ 
     84        long rv = 1; 
     85 
     86        switch (cmd) 
     87        { 
     88                case BIO_C_SET_FD: 
     89                        b->num      = *((int *)ptr); 
     90                        b->shutdown = (int)num; 
     91                        b->init     = 1; 
     92                        break; 
     93 
     94                case BIO_C_GET_FD: 
     95                        if (!b->init) 
     96                                return -1; 
     97 
     98                        if (ptr) 
     99                                *((int *)ptr) = b->num; 
     100 
     101                        rv = b->num; 
     102                        break; 
     103        } 
     104 
     105        return rv; 
     106} 
     107 
     108static int uh_openssl_bio_read_cb(BIO *b, char *out, int outl) 
     109{ 
     110        int rv = 0; 
     111        struct client *cl; 
     112 
     113        if (!(cl = uh_client_lookup(b->num))) 
     114                return -1; 
     115 
     116        if (out != NULL) 
     117                rv = uh_tcp_recv_lowlevel(cl, out, outl); 
     118 
     119        return rv; 
     120} 
     121 
     122static int uh_openssl_bio_write_cb(BIO *b, const char *in, int inl) 
     123{ 
     124        struct client *cl; 
     125 
     126        if (!(cl = uh_client_lookup(b->num))) 
     127                return -1; 
     128 
     129        return uh_tcp_send_lowlevel(cl, in, inl); 
     130} 
     131 
     132static BIO_METHOD uh_openssl_bio_methods = { 
     133        .type   = BIO_TYPE_SOCKET, 
     134        .name   = "uhsocket", 
     135        .ctrl   = uh_openssl_bio_ctrl_cb, 
     136        .bwrite = uh_openssl_bio_write_cb, 
     137        .bread  = uh_openssl_bio_read_cb 
     138}; 
     139 
     140static void uh_tls_ctx_setup(SSL_CTX *ctx) 
     141{ 
     142        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 
     143        return; 
     144} 
     145 
     146static int uh_tls_client_ctx_setup(SSL *ssl, int socket) 
     147{ 
     148        BIO *b; 
     149 
     150        if (!(b = BIO_new(&uh_openssl_bio_methods))) 
     151                return 0; 
     152 
     153        BIO_set_fd(b, socket, BIO_NOCLOSE); 
     154        SSL_set_bio(ssl, b, b); 
     155 
     156        return 1; 
     157} 
     158#endif /* TLS_IS_OPENSSL */ 
     159 
    23160 
    24161SSL_CTX * uh_tls_ctx_init() 
     
    29166        SSL_library_init(); 
    30167 
    31         if( (c = SSL_CTX_new(TLSv1_server_method())) != NULL ) 
    32                 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); 
     168        if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL) 
     169                uh_tls_ctx_setup(c); 
    33170 
    34171        return c; 
     
    70207                if( c->tls ) 
    71208                { 
    72                         if( (rv = SSL_set_fd(c->tls, c->socket)) < 1 ) 
     209                        if( (rv = uh_tls_client_ctx_setup(c->tls, c->socket)) < 1 ) 
    73210                                goto cleanup; 
     211 
    74212                        if( (rv = SSL_accept(c->tls)) < 1 ) 
    75213                                goto cleanup; 
  • trunk/package/uhttpd/src/uhttpd-utils.c

    r24952 r28761  
    125125 
    126126 
    127 int uh_tcp_send(struct client *cl, const char *buf, int len) 
     127int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len) 
    128128{ 
    129129        fd_set writer; 
     
    136136        timeout.tv_usec = 0; 
    137137 
    138         if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 ) 
    139         { 
     138        if (select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0) 
     139                return send(cl->socket, buf, len, 0); 
     140 
     141        return -1; 
     142} 
     143 
     144int uh_tcp_send(struct client *cl, const char *buf, int len) 
     145{ 
    140146#ifdef HAVE_TLS 
    141                 if( cl->tls ) 
    142                         return cl->server->conf->tls_send(cl, (void *)buf, len); 
     147        if (cl->tls) 
     148                return cl->server->conf->tls_send(cl, (void *)buf, len); 
     149        else 
     150#endif 
     151                return uh_tcp_send_lowlevel(cl, buf, len); 
     152} 
     153 
     154int uh_tcp_peek(struct client *cl, char *buf, int len) 
     155{ 
     156        /* sanity check, prevent overflowing peek buffer */ 
     157        if (len > sizeof(cl->peekbuf)) 
     158                return -1; 
     159 
     160        int sz = uh_tcp_recv(cl, buf, len); 
     161 
     162        /* store received data in peek buffer */ 
     163        if( sz > 0 ) 
     164        { 
     165                cl->peeklen = sz; 
     166                memcpy(cl->peekbuf, buf, sz); 
     167        } 
     168 
     169        return sz; 
     170} 
     171 
     172int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len) 
     173{ 
     174        fd_set reader; 
     175        struct timeval timeout; 
     176 
     177        FD_ZERO(&reader); 
     178        FD_SET(cl->socket, &reader); 
     179 
     180        timeout.tv_sec  = cl->server->conf->network_timeout; 
     181        timeout.tv_usec = 0; 
     182 
     183        if (select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0) 
     184                return recv(cl->socket, buf, len, 0); 
     185 
     186        return -1; 
     187} 
     188 
     189int uh_tcp_recv(struct client *cl, char *buf, int len) 
     190{ 
     191        int sz = 0; 
     192        int rsz = 0; 
     193 
     194        /* first serve data from peek buffer */ 
     195        if (cl->peeklen > 0) 
     196        { 
     197                sz = min(cl->peeklen, len); 
     198                len -= sz; cl->peeklen -= sz; 
     199                memcpy(buf, cl->peekbuf, sz); 
     200                memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen); 
     201        } 
     202 
     203        /* caller wants more */ 
     204        if (len > 0) 
     205        { 
     206#ifdef HAVE_TLS 
     207                if (cl->tls) 
     208                        rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len); 
    143209                else 
    144210#endif 
    145                         return send(cl->socket, buf, len, 0); 
    146         } 
    147  
    148         return -1; 
    149 } 
    150  
    151 int uh_tcp_peek(struct client *cl, char *buf, int len) 
    152 { 
    153         int sz = uh_tcp_recv(cl, buf, len); 
    154  
    155         /* store received data in peek buffer */ 
    156         if( sz > 0 ) 
    157         { 
    158                 cl->peeklen = sz; 
    159                 memcpy(cl->peekbuf, buf, sz); 
    160         } 
    161  
    162         return sz; 
    163 } 
    164  
    165 int uh_tcp_recv(struct client *cl, char *buf, int len) 
    166 { 
    167         int sz = 0; 
    168         int rsz = 0; 
    169  
    170         fd_set reader; 
    171         struct timeval timeout; 
    172  
    173         /* first serve data from peek buffer */ 
    174         if( cl->peeklen > 0 ) 
    175         { 
    176                 sz = min(cl->peeklen, len); 
    177                 len -= sz; cl->peeklen -= sz; 
    178  
    179                 memcpy(buf, cl->peekbuf, sz); 
    180                 memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen); 
    181         } 
    182  
    183         /* caller wants more */ 
    184         if( len > 0 ) 
    185         { 
    186                 FD_ZERO(&reader); 
    187                 FD_SET(cl->socket, &reader); 
    188  
    189                 timeout.tv_sec  = cl->server->conf->network_timeout; 
    190                 timeout.tv_usec = 0; 
    191  
    192                 if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 ) 
    193                 { 
    194 #ifdef HAVE_TLS 
    195                         if( cl->tls ) 
    196                                 rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len); 
    197                         else 
    198 #endif 
    199                                 rsz = recv(cl->socket, (void *)&buf[sz], len, 0); 
    200  
    201                         if( (sz == 0) || (rsz > 0) ) 
    202                                 sz += rsz; 
    203                 } 
    204                 else if( sz == 0 ) 
    205                 { 
    206                         sz = -1; 
    207                 } 
     211                        rsz = uh_tcp_recv_lowlevel(cl, (void *)&buf[sz], len); 
     212 
     213                if (rsz < 0) 
     214                        return rsz; 
     215 
     216                sz += rsz; 
    208217        } 
    209218 
  • trunk/package/uhttpd/src/uhttpd-utils.h

    r23952 r28761  
    6868 
    6969int uh_tcp_send(struct client *cl, const char *buf, int len); 
     70int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len); 
    7071int uh_tcp_peek(struct client *cl, char *buf, int len); 
    7172int uh_tcp_recv(struct client *cl, char *buf, int len); 
     73int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len); 
    7274 
    7375int uh_http_sendhf( 
Note: See TracChangeset for help on using the changeset viewer.