diff --git a/libcw.project b/libcw.project index e928bb53..7595c1e3 100644 --- a/libcw.project +++ b/libcw.project @@ -276,6 +276,8 @@ + + diff --git a/src/ac/conf.c b/src/ac/conf.c index fb4827ea..291e37b2 100644 --- a/src/ac/conf.c +++ b/src/ac/conf.c @@ -27,6 +27,7 @@ #include "cw/log.h" #include "cw/dbg.h" #include "cw/cw_util.h" +#include "cw/dtls.h" #include "conf.h" diff --git a/src/ac/config.ktv b/src/ac/config.ktv index 85bb0021..0eccc6d0 100644 --- a/src/ac/config.ktv +++ b/src/ac/config.ktv @@ -1,9 +1,7 @@ -capwap/ac-descriptor/hardware/version:Bstr16: "ACTube 1.0" -capwap/ac-descriptor/hardware/vendor:Bastr16: 12346 -capwap/ssl-cert:Str: "/usr/local/etc/ssl/tube.ssl" -capwap/ssl-key:Str: "/usr/local/etc/key" -capwap/ssl-dhbits:Word: 2048 +# +capwap/ac-descriptor/hardware/version:Bstr16: "ACTube 1.0" +capwap/ac-descriptor/hardware/vendor:Bstr16: 12346 ac-descriptor/stations:Word:05 ac-descriptor/station-limit:Word:6 ac-descriptor/active-wtps:Word:7 @@ -23,11 +21,21 @@ capwap-control-ip-address/wtps.0:Word:0 #capwap-control-ip-address/wtps.1:Word:11 -capwap/ssl-keyfile:Str:"../../ssl/certs/ac-cisco.key" -capwap/ssl-certfile:Str:"../../ssl/certs/ac-cisco.pem" -capwap/ssl-cipher:Str:+RSA:+AES-256-CBC:+AES-128-CBC:+SHA1 -#capwap/ssl-psk:Str:"HalloWelt" +#capwap/ssl-keyfile:Str:"../../ssl/certs/ac-cisco.key" +#capwap/ssl-certfile:Str:"../../ssl/certs/ac-cisco.pem" + +capwap/ssl-cipher:Str:+DHE-RSA:+RSA:+AES-256-CBC:+AES-128-CBC:+SHA1:+PSK +capwap/ssl-psk-enable:Bool:true +capwap/ssl-psk:Bstr16:"HalloWelt" +capwap/ssl-dhbits:Word: 64 -actube/listen::192.168.0.1 +psk:Bstr16:1234 +psk/ap1:Bstr16:hallo + +#capwap/ssl-psk:Str:HalloWelt1 + + + +actube/listen:Bstr16:192.168.0.1 diff --git a/src/cw/bstr.h b/src/cw/bstr.h index 2feff0ca..70f61142 100644 --- a/src/cw/bstr.h +++ b/src/cw/bstr.h @@ -139,7 +139,7 @@ static inline int bstr16_ncpy(uint8_t *dst,uint8_t*src,uint16_t len) */ -extern uint8_t * bstr16_create(const uint8_t *data, uint16_t len); +bstr16_t bstr16_create(const uint8_t *data, uint16_t len); uint8_t * bstr16_create_from_str(const char *s); extern uint8_t * bstr16_create_from_cfgstr(const char * s); diff --git a/src/cw/bstr16_create.c b/src/cw/bstr16_create.c index 4738e1b1..2631570d 100644 --- a/src/cw/bstr16_create.c +++ b/src/cw/bstr16_create.c @@ -1,6 +1,6 @@ #include "bstr.h" -uint8_t * bstr16_create(const uint8_t *data, uint16_t len) +bstr16_t bstr16_create(const uint8_t *data, uint16_t len) { uint8_t * str = malloc(2+len*sizeof(uint8_t)); if (!str) @@ -10,4 +10,3 @@ uint8_t * bstr16_create(const uint8_t *data, uint16_t len) return str; } - diff --git a/src/cw/conn.h b/src/cw/conn.h index d5f42fa5..d55291eb 100644 --- a/src/cw/conn.h +++ b/src/cw/conn.h @@ -175,9 +175,11 @@ struct conn { int (*dtls_start) (struct conn *); int (*dtls_accept) (struct conn *); - char *dtls_psk; - int dtls_psk_len; + bstr16_t dtls_psk; + int dtls_psk_enable; + int dtls_dhbits; + int (*dtls_get_psk)(struct conn *,const char *user,uint8_t**psk, int *len); struct cw_Mod *cmod, *bmod; diff --git a/src/cw/cw.h b/src/cw/cw.h index 2bee16c9..f5b0078e 100644 --- a/src/cw/cw.h +++ b/src/cw/cw.h @@ -502,7 +502,7 @@ int cw_put_msg(struct conn *conn, uint8_t * rawout); char *cw_strdup(const char *s); -int cw_strcicmp(char const *a, char const *b); +int cw_stricmp(char const *a, char const *b); /** diff --git a/src/cw/cw_setup_dtls.c b/src/cw/cw_setup_dtls.c index 8968da64..7a34725c 100644 --- a/src/cw/cw_setup_dtls.c +++ b/src/cw/cw_setup_dtls.c @@ -1,4 +1,30 @@ #include "cw.h" + + + +static int get_psk(struct conn * conn,const char * username, uint8_t **psk, unsigned int *len) +{ + char key[CW_KTV_MAX_KEY_LEN]; + cw_KTV_t * result; + sprintf(key,"%s/%s","psk",username); + result = cw_ktv_get(conn->local_cfg,key,CW_TYPE_BSTR16); + if (result == NULL){ + if (conn->dtls_psk != NULL){ + *psk = bstr16_data(conn->dtls_psk); + *len = bstr16_len(conn->dtls_psk); + return 1; + } + return 0; + } + + if (result == NULL) + return 0; + *psk = result->type->data(result); + *len = result->type->len(result); + return 1; +} + + /** * @brief Setup DTLS parameters from config * @param conn @@ -10,7 +36,7 @@ int cw_setup_dtls(struct conn * conn, mavl_t cfg, const char *prefix, char * default_cipher) { char key[CW_KTV_MAX_KEY_LEN]; - char *ssl_psk,*ssl_cert,*ssl_key; + char *ssl_cert,*ssl_key; uint8_t security; security = 0; @@ -18,13 +44,18 @@ int cw_setup_dtls(struct conn * conn, mavl_t cfg, const char *prefix, char * de sprintf(key,"%s/%s",prefix,"ssl-cipher"); conn->dtls_cipher = cw_ktv_get_str(cfg,key, default_cipher); + sprintf(key,"%s/%s",prefix,"ssl-psk"); - ssl_psk = cw_ktv_get_str(cfg,key,NULL); - if (ssl_psk != NULL){ - conn->dtls_psk=ssl_psk; - conn->dtls_psk_len=strlen(ssl_psk); + conn->dtls_psk = cw_ktv_get_bstr16(cfg,key,NULL); + + sprintf(key,"%s/%s",prefix,"ssl-psk-enable"); + conn->dtls_psk_enable = cw_ktv_get_bool(cfg,key,0); + + if (conn->dtls_psk_enable ){ security |= CAPWAP_FLAG_AC_SECURITY_S; } + + sprintf(key,"%s/%s",prefix,"ssl-certfile"); ssl_cert = cw_ktv_get_str(conn->local_cfg,key,NULL); @@ -41,6 +72,8 @@ int cw_setup_dtls(struct conn * conn, mavl_t cfg, const char *prefix, char * de sprintf(key,"%s/%s",prefix,"ssl-dhbits"); conn->dtls_dhbits = cw_ktv_get_word(cfg,key,1024); + + conn->dtls_get_psk = get_psk; return security; } \ No newline at end of file diff --git a/src/cw/cw_stricmp.c b/src/cw/cw_stricmp.c index 58549aba..a49e33a9 100644 --- a/src/cw/cw_stricmp.c +++ b/src/cw/cw_stricmp.c @@ -2,7 +2,7 @@ #include "cw.h" -int cw_strcicmp(char const *a, char const *b) +int cw_stricmp(char const *a, char const *b) { for (;; a++, b++) { int d = tolower(*a) - tolower(*b); diff --git a/src/cw/cw_type_bstr16.c b/src/cw/cw_type_bstr16.c index e7bcad37..ae37a621 100644 --- a/src/cw/cw_type_bstr16.c +++ b/src/cw/cw_type_bstr16.c @@ -77,13 +77,13 @@ static struct cw_KTV *from_str ( struct cw_KTV * data, const char *src ) } -static int len ( struct cw_KTV * data ){ +static int len (cw_KTV_t * data ){ return bstr16_len(data->val.ptr); } -static void * data(struct cw_KTV_t * data) +static void * data(cw_KTV_t * data) { - return bstr16_data(data); + return bstr16_data(data->val.ptr); } const struct cw_Type cw_type_bstr16 = { diff --git a/src/cw/dtls_gnutls.c b/src/cw/dtls_gnutls.c index 964dc569..b331c7a2 100644 --- a/src/cw/dtls_gnutls.c +++ b/src/cw/dtls_gnutls.c @@ -128,6 +128,7 @@ struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config) { const char *errpos; int rc; + gnutls_datum_t key; int bits; struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data)); if (!d) @@ -204,16 +205,18 @@ struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config) 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)); + cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_certificate_set_verify_function(d->x509_cred,verify_cert); - + gnutls_session_set_ptr(d->session, conn); gnutls_transport_set_ptr(d->session, conn); gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read); gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write); diff --git a/src/cw/dtls_gnutls.h b/src/cw/dtls_gnutls.h index 44a16d74..ec17565c 100644 --- a/src/cw/dtls_gnutls.h +++ b/src/cw/dtls_gnutls.h @@ -35,7 +35,7 @@ const char * dtls_gnutls_get_cipher(struct conn * conn, char * dst); struct dtls_ssl_cert dtls_gnutls_get_peers_cert(struct conn * conn,unsigned int n); extern int dtls_gnutls_shutdown(struct conn *conn); -#define CAPWAP_CIPHER "+DHE-RSA:+RSA:+AES-256-CBC:+AES-128-CBC:+SHA1" +#define CAPWAP_CIPHER "+RSA:+AES-128-CBC:+SHA1" /* functions used only by capwap libray */ diff --git a/src/cw/dtls_gnutls_accept.c b/src/cw/dtls_gnutls_accept.c index cfca75d0..4bff8228 100644 --- a/src/cw/dtls_gnutls_accept.c +++ b/src/cw/dtls_gnutls_accept.c @@ -35,6 +35,29 @@ #include "timer.h" +int psk_creds(gnutls_session_t session, const char *user, gnutls_datum_t *key) +{ + struct conn *conn; + + int rc; + uint8_t * psk; + int psk_len; + + conn = gnutls_session_get_ptr(session); + + rc = conn->dtls_get_psk(conn,user, &psk,&psk_len); + if (!rc) + return -1; + key->size=psk_len; + key->data = gnutls_malloc(key->size); + if (key->data == NULL) { + return -1; + } + memcpy(key->data, psk, psk_len); + return 0; +} + + int dtls_gnutls_accept(struct conn *conn) { char sock_buf[SOCK_ADDR_BUFSIZE]; @@ -47,15 +70,15 @@ int dtls_gnutls_accept(struct conn *conn) gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; - - - + + + gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); cw_dbg(DBG_DTLS, "Session cookie for %s generated: %s", - sock_addr2str(&conn->addr,sock_buf), + sock_addr2str(&conn->addr, sock_buf), sock_hwaddrtostr((uint8_t *) (&cookie_key), - sizeof(cookie_key),cookie_buf,"")); + sizeof(cookie_key), cookie_buf, "")); memset(&prestate, 0, sizeof(prestate)); @@ -63,31 +86,34 @@ int dtls_gnutls_accept(struct conn *conn) 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); + &prestate, (gnutls_transport_ptr_t) conn, + dtls_gnutls_bio_write); - rc=-1; + rc = -1; c_timer = cw_timer_start(10); - while(!cw_timer_timeout(c_timer)){ + while (!cw_timer_timeout(c_timer)) { - tlen = conn_q_recv_packet_peek(conn,buffer,sizeof(buffer)); + tlen = conn_q_recv_packet_peek(conn, buffer, sizeof(buffer)); - if (tlen <0 && errno == EAGAIN) + if (tlen < 0 && errno == EAGAIN) continue; - if (tlen < 0 ){ + if (tlen < 0) { /* something went wrong, iwe should log a message */ continue; } - + rc = gnutls_dtls_cookie_verify(&cookie_key, &conn->addr, - sizeof(conn->addr), buffer+4, tlen-4, &prestate); + sizeof(conn->addr), buffer + 4, tlen - 4, + &prestate); - if (rc<0){ - cw_dbg(DBG_DTLS, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); + if (rc < 0) { + cw_dbg(DBG_DTLS, "Cookie couldn't be verified: %s", + gnutls_strerror(rc)); dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); continue; } @@ -96,61 +122,81 @@ int dtls_gnutls_accept(struct conn *conn) } - if (rc <0 ){ + if (rc < 0) { cw_log(LOG_ERR, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); return 0; } - cw_dbg(DBG_DTLS, "Cookie verified! Starting handshake with %s ...",sock_addr2str(&conn->addr,sock_buf)); + cw_dbg(DBG_DTLS, "Cookie verified! Starting handshake with %s ...", + sock_addr2str(&conn->addr, sock_buf)); - d = dtls_gnutls_data_create(conn,GNUTLS_SERVER | GNUTLS_DATAGRAM); + d = dtls_gnutls_data_create(conn, GNUTLS_SERVER | GNUTLS_DATAGRAM); if (!d) return 0; + if (conn->dtls_psk_enable) { + gnutls_psk_server_credentials_t cred; + rc = gnutls_psk_allocate_server_credentials(&cred); + if (rc != 0) { + cw_log(LOG_ERR,"gnutls_psk_allocate_server_credentials() failed."); + } + /* GnuTLS will call psk_creds to ask for the key associated with the + client's username.*/ + gnutls_psk_set_server_credentials_function(cred, psk_creds); + /* // Pass the "credentials" to the GnuTLS session. GnuTLS does NOT make an + // internal copy of the information, so we have to keep the 'cred' structure + // in memory (and not modify it) until we're done with this session.*/ + rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, cred); + if (rc != 0) { + cw_log(LOG_ERR,"gnutls_credentials_set() failed.\n"); + } + + } + + + + /* Generate Diffie-Hellman parameters - for use with DHE - * kx algorithms. When short bit length is used, it might - * be wise to regenerate parameters often. - */ - /*bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);*/ + * kx algorithms. When short bit length is used, it might + * be wise to regenerate parameters often. + */ + /*bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY); */ bits = conn->dtls_dhbits; - + gnutls_dh_params_init(&d->dh_params); - cw_dbg(DBG_DTLS,"Generating DH params, %d",bits); - gnutls_dh_params_generate2(d->dh_params, bits); - cw_dbg(DBG_DTLS,"DH params generated, %d",bits); + cw_dbg(DBG_DTLS, "Generating DH params, %d", bits); + gnutls_dh_params_generate2(d->dh_params, bits); + cw_dbg(DBG_DTLS, "DH params generated, %d", bits); + gnutls_certificate_set_dh_params(d->x509_cred, d->dh_params); - gnutls_certificate_set_dh_params(d->x509_cred, d->dh_params); - - - - gnutls_certificate_server_set_request(d->session,GNUTLS_CERT_REQUEST); + gnutls_certificate_server_set_request(d->session, GNUTLS_CERT_REQUEST); gnutls_dtls_prestate_set(d->session, &prestate); c_timer = cw_timer_start(10); - do{ + do { rc = gnutls_handshake(d->session); - }while(!cw_timer_timeout(c_timer) && rc==GNUTLS_E_AGAIN); - + } while (!cw_timer_timeout(c_timer) && rc == GNUTLS_E_AGAIN); - if ( rc < 0 ) { - cw_log(LOG_ERR, "Error in handshake with %s: %s",sock_addr2str(&conn->addr,sock_buf), gnutls_strerror(rc)); + + if (rc < 0) { + cw_log(LOG_ERR, "Error in handshake with %s: %s", + sock_addr2str(&conn->addr, sock_buf), gnutls_strerror(rc)); return 0; } - cw_dbg(DBG_DTLS,"Handshake with %s successful.",sock_addr2str(&conn->addr,sock_buf)); + cw_dbg(DBG_DTLS, "Handshake with %s successful.", + sock_addr2str(&conn->addr, sock_buf)); - conn->dtls_data=d; + conn->dtls_data = d; conn->read = dtls_gnutls_read; conn->write = dtls_gnutls_write; return 1; } - - diff --git a/src/cw/dtls_gnutls_connect.c b/src/cw/dtls_gnutls_connect.c index 9b046f3c..d7d82c4e 100644 --- a/src/cw/dtls_gnutls_connect.c +++ b/src/cw/dtls_gnutls_connect.c @@ -34,13 +34,14 @@ #include "sock.h" /** * Establish a DTLS connection using gnutls library - * @see #dtls_connect + * @see #dtls_connec */ int dtls_gnutls_connect(struct conn *conn) { int rc; char sock_buf[SOCK_ADDR_BUFSIZE]; struct dtls_gnutls_data *d; + gnutls_datum_t key; d = dtls_gnutls_data_create(conn, GNUTLS_CLIENT | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK); @@ -56,6 +57,50 @@ int dtls_gnutls_connect(struct conn *conn) gnutls_dtls_set_mtu(d->session, 1500); */ +/* + if (conn->dtls_psk != NULL){ + key.data=(unsigned char*)conn->dtls_psk; + key.size=strlen(conn->dtls_psk); + + rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, &key); + if (rc<0) { + cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc)); + dtls_gnutls_data_destroy(d); + return 0; + + } + } + +*/ + + + if (conn->dtls_psk_enable){ + gnutls_psk_client_credentials_t cred; + rc = gnutls_psk_allocate_client_credentials(&cred); + if (rc != 0) { + cw_dbg(DBG_DTLS,"gnutls_psk_allocate_client_credentials() failed.\n"); + return 0; + } + + + key.size = bstr16_len(conn->dtls_psk); + key.data = bstr16_data(conn->dtls_psk); + + + /* Put the username and key into the structure we use to tell GnuTLs what + // the credentials are. The example server doesn't care about usernames, so + // we use "Alice" here.*/ + rc = gnutls_psk_set_client_credentials(cred, "Alice", &key, GNUTLS_PSK_KEY_RAW); + rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, cred); + if (rc != 0) { + cw_log(LOG_ERR,"gnutls_credentials_set() failed."); + } + + + + } + + cw_dbg(DBG_DTLS,"Starting handshake"); do { diff --git a/src/cw/dtls_openssl.c b/src/cw/dtls_openssl.c index 6fb3af87..c1f5839a 100644 --- a/src/cw/dtls_openssl.c +++ b/src/cw/dtls_openssl.c @@ -294,7 +294,8 @@ static unsigned int psk_server_cb(SSL *ssl,const char *identity, unsigned char * { BIO * b = SSL_get_rbio(ssl); struct conn * conn = b->ptr; - int l = conn->dtls_psk_len < max_psk_len ? conn->dtls_psk_len : max_psk_len; + + int l = bstr16_len(conn->dtls_psk) < max_psk_len ? bstr16_len(conn->dtls_psk) : max_psk_len; memcpy(psk,conn->dtls_psk,l); return l; } diff --git a/src/cw/dtls_openssl_connect.c b/src/cw/dtls_openssl_connect.c index 4ad10827..e7bb2183 100644 --- a/src/cw/dtls_openssl_connect.c +++ b/src/cw/dtls_openssl_connect.c @@ -34,8 +34,8 @@ static BIO_METHOD bio_methods = { snprintf(identity, max_identity_len, "CLient_identity"); - l = conn->dtls_psk_len < max_psk_len ? conn->dtls_psk_len : max_psk_len; - memcpy(psk, conn->dtls_psk, l); + l = bstr16_len(conn->dtls_psk) < max_psk_len ? bstr16_len(conn->dtls_psk) : max_psk_len; + memcpy(psk, bstr16_data(conn->dtls_psk), l); return l; } diff --git a/src/wtp/config.ktv b/src/wtp/config.ktv index 6666528a..2ad03929 100644 --- a/src/wtp/config.ktv +++ b/src/wtp/config.ktv @@ -2,14 +2,15 @@ -capwap/ssl-certfile:Str:"../../ssl/certs/wtp.crt" -capwap/ssl-keyfile:Str:"../../ssl/certs/wtp.key" +#capwap/ssl-certfile:Str:"../../ssl/certs/wtp.crt" +#capwap/ssl-keyfile:Str:"../../ssl/certs/wtp.key" #capwap/ssl-cipher:Str: +RSA:+AES-128-CBC:+SHA1 -#capwap/ssl-cipher:Str: +DHE-RSA:+RSA:+AES-256-CBC:+AES-128-CBC:+SHA1 -#capwap/ssl-psk:Str:"HalloWelt" +capwap/ssl-cipher:Str: +DHE-RSA:+RSA:+AES-256-CBC:+AES-128-CBC:+SHA1:+PSK +capwap/ssl-psk:Bstr16:"HalloWelt" +capwap/ssl-psk-enable:Bool:true -cisco/ssl-certfile:Str:"../../ssl/certs/wtp.crt" -cisco/ssl-keyfile:Str:"../../ssl/certs/wtp.key" +#cisco/ssl-certfile:Str:"../../ssl/certs/wtp.crt" +#cisco/ssl-keyfile:Str:"../../ssl/certs/wtp.key" discovery-type:Byte:0 wtp-frame-tunnel-mode:Byte:1 @@ -48,7 +49,6 @@ capwap-timers/echo-interval:Byte:3 "discovery-interval":Byte:1 - location-data:Bstr16:Entangeled