diff --git a/src/Config.mak b/src/Config.mak index d26b622e..5ce18cdc 100644 --- a/src/Config.mak +++ b/src/Config.mak @@ -1,18 +1,24 @@ #Define SSL Library: OPENSSL or GNUTLS (GNUTLS not supported for now) -SSL_LIBRARY=GNUTLS #SSL_LIBRARY=OPENSSL +SSL_LIBRARY=GNUTLS # use openssl library in ../contrib/ +OPENSSL_VERSION=openssl-1.0.1i USE_CONTRIB_OPENSSL=1 +#OPENSSL_VERSION=openssl-1.0.1l # doesn't work +#OPENSSL_VERSION=openssl-1.0.2 # doesn't work +# use gnutls lib in ../contrib/ +GNUTLS_VERSION=3.3.9 +USE_CONTRIB_GNUTLS=1 + CONF_LIBRARY=UCI USE_CONTRIB_UCI=0 CC=clang - #CC=mips-openwrt-linux-uclibc-gcc #LD=mips-openwrt-linux-uclibc-ld #AR=mips-openwrt-linux-uclibc-ar diff --git a/src/Macros.mak b/src/Macros.mak index f00116f8..3c771f69 100644 --- a/src/Macros.mak +++ b/src/Macros.mak @@ -1,14 +1,21 @@ -OPENSSL_VERSION=openssl-1.0.1i -#OPENSSL_VERSION=openssl-1.0.1l -#OPENSSL_VERSION=openssl-1.0.2 - ifeq ($(USE_CONTRIB_OPENSSL),1) -OPENSSLLIB=../contrib/$(OPENSSL_VERSION)/libssl.a ../contrib/$(OPENSSL_VERSION)/libcrypto.a -ldl -OPENSSLINC=../contrib/$(OPENSSL_VERSION)/include/openssl +OPENSSL_LIBS=../contrib/$(OPENSSL_VERSION)/libssl.a ../contrib/$(OPENSSL_VERSION)/libcrypto.a -ldl +OPENSSL_CFLAGS=../contrib/$(OPENSSL_VERSION)/include/ else -OPENSSLLIB=-lssl -OPENSSLINC=openssl +OPENSSL_LDFLAGS=-lssl -lcrypto -ldl +OPENSSL_CFLAGS= endif +ifeq ($(USE_CONTRIB_GNUTLS),1) +GNUTLS_CFLAGS=-I../contrib/gnutls-${GNUTLS_VERSION}/lib/includes +#GNUTLS_LIBS=-lnettle -lgmp ../contrib/gnutls-${GNUTLS_VERSION}/lib/.libs/libgnutls.a +GNUTLS_LIBS=-lgmp -lgnutls -lnettle +GNUTLS_LDFLAGS=-L../contrib/gnutls-${GNUTLS_VERSION}/lib/.libs/ +else +GNUTLS_CFLAGS= +GNUTLS_LIBS= +GNUTLS_LDFLAGS=-lgnutls -nettle -lgmp + +endif diff --git a/src/ac/Makefile b/src/ac/Makefile index c100fd46..b7777fb1 100644 --- a/src/ac/Makefile +++ b/src/ac/Makefile @@ -5,43 +5,39 @@ include ../Macros.mak ifndef CC CC=gcc endif -SYSARCH := $(shell uname -m) +#SYSARCH := $(shell uname -m) ifndef ARCH -# ARCH=$(SYSARCH) ARCH = $(shell $(CC) -dumpmachine) endif -LDFLAGS+=-g -D_REENTRANT -L/usr/local/lib -L../capwap/$(ARCH) - -CFLAGS += -I$(OPENSSLINC) -Wall -g -O0 -D_REENTRANT -DIPV6 -I/usr/local/include -I../capwap - +LDFLAGS+=-g -D_REENTRANT -L/usr/local/lib -L../capwap/$(ARCH) +CFLAGS += -Wall -g -O0 -D_REENTRANT -DIPV6 -I/usr/local/include -I../capwap LIBS+=-lcapwap LIBS+=-lrt -ifdef WITH_GNUTLS - -else -endif - - -#LIBS+=-lcrypto LIBS+=-lpthread LIBS+=-lconfuse LIBS+=-lsqlite3 -LIBS+=-ldl ifeq ($(SSL_LIBRARY),GNUTLS) CFLAGS+=-DWITH_GNUTLS -LIBS+=-lgnutls -else +CFLAGS+=$(GNUTLS_CFLAGS) +LIBS+=$(GNUTLS_LIBS) +LDFLAGS+=$(GNUTLS_LDFLAGS) +endif + +ifeq ($(SSL_LIBRARY),OPENSSL) CFLAGS+=-DWITH_OPENSSL -LIBS+=$(OPENSSLLIB) +CFLAGS+=$(OPESSL_CFLAGS) +LDFLAGS+=$(OPENSSL_LDFLAGS) +LIBS+=$(OPENSSL_LIBS) endif CFLAGS += -DWITH_CW_LOG CFLAGS += -DWITH_CW_LOG_DEBUG + CFLAGS += -DWITH_RMAC_SUPPORT CFLAGS += -DWITH_DTLS CFLAGS += -DWITH_IPV6 @@ -66,7 +62,7 @@ AC_NAME = actube all: $(AC_NAME) $(AC_NAME): $(AC_OBJS) - $(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) -o $(AC_NAME) $(LDFLAGS) $(LIBS) + $(CC) $(AC_OBJS) -o $(AC_NAME) $(LDFLAGS) $(LIBS) clean: diff --git a/src/ac/ac_main.c b/src/ac/ac_main.c index 2a8ffab8..8768ad10 100644 --- a/src/ac/ac_main.c +++ b/src/ac/ac_main.c @@ -55,8 +55,7 @@ int main (int argc, const char * argv[]) cw_log_name="AC-Tube"; read_config("ac.conf"); - cw_log_debug_level=conf_debug_level; - +// cw_log_debug_level=conf_debug_level; cw_log(LOG_INFO,"Starting AC-Tube, Name=%s, ID=%s",conf_acname,conf_acid); diff --git a/src/ac/conf.c b/src/ac/conf.c index 1dac0315..0b12ef7c 100644 --- a/src/ac/conf.c +++ b/src/ac/conf.c @@ -531,7 +531,7 @@ static int conf_read_dbg_level(cfg_t *cfg) for (i=0; isoftware_vendor_id,wtpinfo->software_version,-1); diff --git a/src/capwap/dtls_bio.c b/src/capwap/dtls_bio.c index 251d5854..b0d42d2f 100644 --- a/src/capwap/dtls_bio.c +++ b/src/capwap/dtls_bio.c @@ -37,33 +37,37 @@ int dtls_bio_read(struct conn *conn, char *out, int maxlen) memcpy(out, conn->dtls_buffer + conn->dtls_buffer_pos, maxlen); conn->dtls_buffer_len -= maxlen; conn->dtls_buffer_pos += maxlen; - cw_dbg(DBG_DTLS_BIO, "SSL BIO read: (maxlen = %d), remain %d", maxlen,conn->dtls_buffer_len); - cw_dbg_dmp(DBG_DTLS_BIO_DMP,(uint8_t*)out,maxlen,"Dump..."); + cw_dbg(DBG_DTLS_BIO, "SSL BIO read: (maxlen = %d), read %d, remain %d", maxlen, + maxlen, conn->dtls_buffer_len); + cw_dbg_dmp(DBG_DTLS_BIO_DMP, (uint8_t *) out, maxlen, "Dump..."); return maxlen; - } + memcpy(out, conn->dtls_buffer + conn->dtls_buffer_pos, conn->dtls_buffer_len); int ret = conn->dtls_buffer_len; conn->dtls_buffer_len = 0; - cw_dbg(DBG_DTLS_BIO, "SSL BIO read: (maxlen = %d), remain %d", ret,conn->dtls_buffer_len); - cw_dbg_dmp(DBG_DTLS_BIO_DMP,(uint8_t*)out,ret,"Dump..."); + cw_dbg(DBG_DTLS_BIO, "SSL BIO read: (maxlen = %d), read %d, remain %d", maxlen, ret, + conn->dtls_buffer_len); + cw_dbg_dmp(DBG_DTLS_BIO_DMP, (uint8_t *) out, ret, "Dump..."); return ret; } -int dtls_bio_write(struct conn * conn, const char *data, int len) +int dtls_bio_write(struct conn *conn, const char *data, int len) { uint8_t buffer[2048]; *((uint32_t *) buffer) = htonl(1 << 24); memcpy(buffer + 4, data, len); int rc = conn->send_packet(conn, buffer, len + 4); + if (rc>=0) + rc-=4; + - cw_dbg(DBG_DTLS_BIO, "SSL BIO write: %d bytes, rc=%d, ptr: %p", len, rc, data); - cw_dbg_dmp(DBG_DTLS_BIO_DMP,(uint8_t*)data,len,"Dump ..."); + cw_dbg(DBG_DTLS_BIO, "SSL BIO write: %d bytes, wrote=%d, ptr: %p", len, rc, data); + cw_dbg_dmp(DBG_DTLS_BIO_DMP, (uint8_t *) data, len, "Dump ..."); if (rc < 0) return rc; - return rc - 4; + return rc ; } - diff --git a/src/capwap/dtls_gnutls.c b/src/capwap/dtls_gnutls.c index c1379a87..4fa80974 100644 --- a/src/capwap/dtls_gnutls.c +++ b/src/capwap/dtls_gnutls.c @@ -23,7 +23,8 @@ int dtls_gnutls_init() { - cw_dbg(DBG_CW_INFO,"Init SSL library - using GnuTLS"); + cw_dbg(DBG_CW_INFO,"Init SSL library - using GnuTLS %s",gnutls_check_version(NULL)); gnutls_global_init(); + return 1; } diff --git a/src/capwap/dtls_gnutls_accept.c b/src/capwap/dtls_gnutls_accept.c index be94c119..636991a9 100644 --- a/src/capwap/dtls_gnutls_accept.c +++ b/src/capwap/dtls_gnutls_accept.c @@ -17,17 +17,22 @@ */ #include +#include +#include #include +#include #include "dtls_gnutls.h" #include "conn.h" #include "cw_log.h" +#include "sock.h" +#include "cw_util.h" -struct dtls_gnutls_data{ +struct dtls_gnutls_data { gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; gnutls_priority_t priority_cache; @@ -38,106 +43,224 @@ void dtls_gnutls_data_destroy(struct dtls_gnutls_data *d) free(d); } -struct dtls_gnutls_data * dtls_gnutls_data_create(struct conn * conn) + + +int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len) { - struct dtls_gnutls_data * d = malloc(sizeof(struct dtls_gnutls_data)); + struct dtls_gnutls_data * d = conn->dtls_data; + int rc = gnutls_record_recv(d->session,buffer,len); + + if ( rc == GNUTLS_E_AGAIN ) + return 0; + + if ( rc < 0 ){ + cw_log(LOG_ERR, "DTLS - read error: %s", gnutls_strerror(rc)); + conn->dtls_error=1; + return -1; + } + + return rc; + +} + +int dtls_gnutls_write(struct conn * conn, const uint8_t *buffer, int len) +{ + struct dtls_gnutls_data * d = conn->dtls_data; + + int rc = gnutls_record_send(d->session,buffer,len); + + if ( rc < 0 ){ + cw_log(LOG_ERR, "DTLS - write error: %s", gnutls_strerror(rc)); + conn->dtls_error=1; + return -1; + } + + return rc; +} + + +static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms) +{ + struct conn * conn = (struct conn*)ptr; + time_t timer = cw_timer_start(ms/1000); + int rc; + + uint8_t buffer[5]; + + do { + rc = conn_q_recv_packet_peek(conn,buffer,sizeof(buffer)); + + }while(!cw_timer_timeout(timer) && rc==GNUTLS_E_AGAIN); + + return rc; + +} + +struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn) +{ + struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data)); if (!d) return 0; - - - gnutls_certificate_allocate_credentials(&d->x509_cred); - int rc; + int rc; /* Set credentials */ - rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file, - conn->dtls_key_file, - GNUTLS_X509_FMT_PEM); + rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file, + conn->dtls_key_file, GNUTLS_X509_FMT_PEM); - if (rc<0){ - cw_log(LOG_ERR,"DTLS - Can't set cert/key: %s",gnutls_strerror(rc)); + if (rc < 0) { + cw_log(LOG_ERR, "DTLS - Can't set cert/key: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } - + /* Set ciphers */ - const char * errpos; - rc = gnutls_priority_init(&d->priority_cache, - conn->dtls_cipher, - &errpos); - if (rc<0){ - cw_log(LOG_ERR,"DTLS - Can't init ciphers '%s' at '%s' : %s",conn->dtls_cipher,errpos,gnutls_strerror(rc)); + const char *errpos; + rc = gnutls_priority_init(&d->priority_cache, conn->dtls_cipher, &errpos); + if (rc < 0) { + cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher, + errpos, gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } - rc = gnutls_init(&d->session, GNUTLS_SERVER ); - if (rc<0){ - cw_log(LOG_ERR,"DTLS - Can't init session: %s",gnutls_strerror(rc)); + rc = gnutls_init(&d->session, GNUTLS_SERVER | GNUTLS_DATAGRAM); + if (rc < 0) { + cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } - gnutls_transport_set_ptr(d->session,conn); + gnutls_transport_set_ptr(d->session, conn); rc = gnutls_priority_set(d->session, d->priority_cache); - if (rc<0){ - cw_log(LOG_ERR,"DTLS - Can't set priority: %s",gnutls_strerror(rc)); + if (rc < 0) { + cw_log(LOG_ERR, "DTLS - Can't set priority: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } - rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, - d->x509_cred); - - if (rc<0){ - cw_log(LOG_ERR,"DTLS - Can't set credentials: %s",gnutls_strerror(rc)); + rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred); + + if (rc < 0) { + cw_log(LOG_ERR, "DTLS - Can't set credentials: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } - gnutls_transport_set_pull_function(d->session,dtls_gnutls_bio_read); - gnutls_transport_set_push_function(d->session,dtls_gnutls_bio_write); + gnutls_certificate_server_set_request(d->session,GNUTLS_CERT_REQUEST); + + gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read); + gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write); - return d; + return d; } -int dtls_gnutls_accept(struct conn * conn) +int dtls_gnutls_accept(struct conn *conn) { struct dtls_gnutls_data *d; + + gnutls_datum_t cookie_key; + + gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); + cw_dbg(DBG_DTLS, "DTLS session cookie for %s generated: %s", + sock_addr2str(&conn->addr), sock_hwaddr2idstr((uint8_t *) (&cookie_key), + sizeof(cookie_key))); + + gnutls_dtls_prestate_st prestate; + memset(&prestate, 0, sizeof(prestate)); + + + + uint8_t buffer[2048]; + int tlen; + tlen = dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); + + gnutls_dtls_cookie_send(&cookie_key, &conn->addr, sizeof(conn->addr), + &prestate, (gnutls_transport_ptr_t) conn, dtls_gnutls_bio_write); + + int rc=-1; + + time_t c_timer = cw_timer_start(10); + + while(!cw_timer_timeout(c_timer)){ + + tlen = conn_q_recv_packet_peek(conn,buffer,sizeof(buffer)); + + if (tlen <0 && errno == EAGAIN) + continue; + if (tlen < 0 ){ + /* something went wrong, log a message */ + continue; + } + + rc = gnutls_dtls_cookie_verify(&cookie_key, + &conn->addr, + sizeof(conn->addr), buffer+4, tlen-4, &prestate); + if (rc<0){ + cw_dbg(DBG_DTLS, "DTLS - Cookie couldn't be verified: %s", gnutls_strerror(rc)); + dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); + continue; + } + + dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); + break; + + } + + if (rc <0 ){ + cw_log(LOG_ERR, "DTLS - Cookie couldn't be verified: %s", gnutls_strerror(rc)); + return 0; + } + + + cw_dbg(DBG_DTLS, "DTLS - Cookie verified! Starting handshake ..."); + + d = dtls_gnutls_data_create(conn); if (!d) return 0; + gnutls_transport_set_pull_timeout_function(d->session, pull_timeout_func); + gnutls_dtls_prestate_set(d->session, &prestate); - int rc; - - do { + c_timer = cw_timer_start(10); + do{ rc = gnutls_handshake(d->session); - }while(rc == GNUTLS_E_AGAIN); - - cw_log(LOG_ERR,"DTLS - Can't set credentials: %s",gnutls_strerror(rc)); - - // gnutls_certificate_allocate_credentials(&x509_cred); + }while(!cw_timer_timeout(c_timer) && rc==GNUTLS_E_AGAIN); + -return 0; + if ( rc < 0 ) { + cw_log(LOG_ERR, "DTLS - Error in handshake: %s", gnutls_strerror(rc)); + return 0; + } - return 1; + // gnutls_certificate_allocate_credentials(&x509_cred); + + + cw_dbg(DBG_DTLS,"DTLS - Handshake successful"); + + conn->dtls_data=d; + conn->read = dtls_gnutls_read; + conn->write = dtls_gnutls_write; + + + return 1; } -const char * dtls_gnutls_get_cipher(struct conn * conn) +const char *dtls_gnutls_get_cipher(struct conn *conn) { return "Unknown"; } diff --git a/src/capwap/dtls_gnutls_bio.c b/src/capwap/dtls_gnutls_bio.c index c8b09457..9397c029 100644 --- a/src/capwap/dtls_gnutls_bio.c +++ b/src/capwap/dtls_gnutls_bio.c @@ -22,11 +22,20 @@ #include "dtls.h" #include "dtls_gnutls.h" + +#include +#include + ssize_t dtls_gnutls_bio_read(gnutls_transport_ptr_t b, void *out, size_t maxlen) { - struct conn *conn = (struct conn *)b; - return dtls_bio_read(conn,out,maxlen); + int rc = dtls_bio_read(conn,out,maxlen); + if (rc<=0){ + errno = EAGAIN; + return -1; + } + errno=0; + return rc; } ssize_t dtls_gnutls_bio_write(gnutls_transport_ptr_t b, const void *data, size_t len) diff --git a/src/capwap/dtls_openssl.c b/src/capwap/dtls_openssl.c index 47870796..bc086fef 100644 --- a/src/capwap/dtls_openssl.c +++ b/src/capwap/dtls_openssl.c @@ -246,8 +246,8 @@ static int dtls_verify_peer_callback (int ok, X509_STORE_CTX *ctx) { printf ("Verify callback called with ok = %d\n",ok); - SSL *ssl; - ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); +// SSL *ssl; +// ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); char buf[1024]; X509 *err_cert; @@ -292,7 +292,7 @@ struct dtls_openssl_data * dtls_openssl_data_create(struct conn * conn, const SS int rc = SSL_CTX_set_cipher_list(d->ctx, conn->dtls_cipher); if (!rc){ - dtls_openssl_log_error(0,rc,"DTLS setup error:"); + dtls_openssl_log_error(0,rc,"DTLS setup cipher error:"); dtls_openssl_data_destroy(d); return 0; } diff --git a/src/capwap/dtls_openssl.h b/src/capwap/dtls_openssl.h index a950a11b..9445d687 100644 --- a/src/capwap/dtls_openssl.h +++ b/src/capwap/dtls_openssl.h @@ -3,7 +3,7 @@ #include -#include +#include #include "conn.h" diff --git a/src/contrib/install_openssl.sh b/src/contrib/install_openssl.sh index e27a95ea..e311dbfe 100755 --- a/src/contrib/install_openssl.sh +++ b/src/contrib/install_openssl.sh @@ -5,7 +5,7 @@ VERSION="1.0.1i" #VERSION="1.0.1l" #VERSION="1.0.2" -if [ ! -e openssl-${VERSION} ] +if [ ! -e openssl-${VERSION}.tar.gz ] then wget https://www.openssl.org/source/openssl-${VERSION}.tar.gz fi