/* This file is part of libcapwap. libcapwap is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libcapwap is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see . */ #include #include #include #include #include "dtls_common.h" #include "dtls_gnutls.h" #include "conn.h" #include "log.h" #include "dbg.h" #include "cw_util.h" #include "timer.h" int dtls_gnutls_init() { cw_dbg(DBG_INFO,"Init SSL library - using GnuTLS %s",gnutls_check_version(NULL)); gnutls_global_init(); return 1; } int dtls_gnutls_shutdown(struct conn *conn) { /* implement it */ return 1; } void dtls_gnutls_data_destroy(struct dtls_gnutls_data *d) { free(d); } 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; errno=ECONNRESET; return -1; } return rc; } int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len) { uint8_t seq[8]; struct dtls_gnutls_data * d = conn->dtls_data; int rc = gnutls_record_recv_seq(d->session,buffer,len,seq); if (rc==0) { errno = ECONNRESET; return -1; } if ( rc == GNUTLS_E_AGAIN ){ errno = EAGAIN; return -1; } if ( rc < 0 ){ cw_log(LOG_ERR, "DTLS - read error: %s", gnutls_strerror(rc)); conn->dtls_error=1; errno=ECONNRESET; return -1; } return rc; } static int verify_cert(gnutls_session_t sess) { cw_dbg(DBG_DTLS,"Verify cert"); return 0; } static void dtls_log_cb(int level, const char * str) { char buf[2048]; char *c; if (!cw_dbg_is_level(DBG_DTLS_DETAIL)) return; /* switch (level){ case 2: case 6: case 4: return; } */ strcpy(buf,str); c = strchr(buf,'\n'); *c=0; cw_dbg(DBG_DTLS_DETAIL,"%s",buf); } 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) return 0; gnutls_global_set_log_level(10); gnutls_global_set_log_function(dtls_log_cb); rc = gnutls_init(&d->session, config); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_certificate_allocate_credentials(&d->x509_cred); /* Set credentials */ if (conn->dtls_cert_file && conn->dtls_key_file){ 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)); dtls_gnutls_data_destroy(d); return 0; } } /* #if GNUTLS_VERSION_NUMBER >= 0x030100 bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_INSECURE); #else */ bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY); /*#endif*/ /* Set ciphers */ /* 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_priority_set(d->session, d->priority_cache); 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_priority_set_direct(d->session,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_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred); 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; } 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); gnutls_transport_set_pull_timeout_function(d->session, dtls_gnutls_bio_wait); #if GNUTLS_VERSION_NUMBER >= 0x030100 gnutls_handshake_set_timeout(d->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); gnutls_dtls_set_data_mtu(d->session, conn->dtls_mtu); #endif gnutls_dtls_set_mtu(d->session, conn->dtls_mtu); return d; }