2014-08-03 08:46:42 +02:00
|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2015-02-08 16:28:04 +01:00
|
|
|
#include <stdlib.h>
|
2014-08-03 08:46:42 +02:00
|
|
|
|
|
|
|
#include <gnutls/gnutls.h>
|
|
|
|
|
2015-02-08 16:28:04 +01:00
|
|
|
#include "dtls_gnutls.h"
|
|
|
|
|
|
|
|
#include "conn.h"
|
2015-02-06 21:38:42 +01:00
|
|
|
#include "cw_log.h"
|
2015-02-08 16:28:04 +01:00
|
|
|
#include "cw_util.h"
|
2014-08-03 08:46:42 +02:00
|
|
|
|
|
|
|
int dtls_gnutls_init()
|
|
|
|
{
|
2015-02-08 11:42:01 +01:00
|
|
|
cw_dbg(DBG_CW_INFO,"Init SSL library - using GnuTLS %s",gnutls_check_version(NULL));
|
2014-08-03 08:46:42 +02:00
|
|
|
gnutls_global_init();
|
|
|
|
return 1;
|
|
|
|
}
|
2015-02-08 16:28:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* Set credentials */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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));
|
|
|
|
dtls_gnutls_data_destroy(d);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
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_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_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|