summaryrefslogtreecommitdiff
path: root/src/rexmpp_tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rexmpp_tls.c')
-rw-r--r--src/rexmpp_tls.c173
1 files changed, 88 insertions, 85 deletions
diff --git a/src/rexmpp_tls.c b/src/rexmpp_tls.c
index 7919556..96c042a 100644
--- a/src/rexmpp_tls.c
+++ b/src/rexmpp_tls.c
@@ -25,15 +25,15 @@
#if defined(USE_OPENSSL)
rexmpp_tls_err_t rexmpp_process_openssl_ret (rexmpp_t *s, int ret) {
- int err = SSL_get_error(s->tls.openssl_conn, ret);
- s->tls.openssl_direction = REXMPP_OPENSSL_NONE;
+ int err = SSL_get_error(s->tls->openssl_conn, ret);
+ s->tls->openssl_direction = REXMPP_OPENSSL_NONE;
if (ret == 1) {
return REXMPP_TLS_SUCCESS;
} else if (err == SSL_ERROR_WANT_READ) {
- s->tls.openssl_direction = REXMPP_OPENSSL_READ;
+ s->tls->openssl_direction = REXMPP_OPENSSL_READ;
return REXMPP_TLS_E_AGAIN;
} else if (err == SSL_ERROR_WANT_WRITE) {
- s->tls.openssl_direction = REXMPP_OPENSSL_WRITE;
+ s->tls->openssl_direction = REXMPP_OPENSSL_WRITE;
return REXMPP_TLS_E_AGAIN;
} else {
rexmpp_log(s, LOG_ERR, "OpenSSL error %d", err);
@@ -43,27 +43,28 @@ rexmpp_tls_err_t rexmpp_process_openssl_ret (rexmpp_t *s, int ret) {
#endif
int rexmpp_tls_init (rexmpp_t *s) {
+ s->tls = malloc(sizeof(struct rexmpp_tls));
#if defined(USE_GNUTLS)
int err;
- s->tls.tls_session_data = NULL;
- s->tls.tls_session_data_size = 0;
+ s->tls->tls_session_data = NULL;
+ s->tls->tls_session_data_size = 0;
- err = gnutls_certificate_allocate_credentials(&(s->tls.gnutls_cred));
+ err = gnutls_certificate_allocate_credentials(&(s->tls->gnutls_cred));
if (err) {
rexmpp_log(s, LOG_CRIT, "gnutls credentials allocation error: %s",
gnutls_strerror(err));
return 1;
}
- err = gnutls_certificate_set_x509_system_trust(s->tls.gnutls_cred);
+ err = gnutls_certificate_set_x509_system_trust(s->tls->gnutls_cred);
if (err < 0) {
rexmpp_log(s, LOG_CRIT, "Certificates loading error: %s",
gnutls_strerror(err));
return 1;
}
#ifdef ENABLE_CALLS
- err = gnutls_certificate_allocate_credentials(&(s->jingle.dtls_cred));
+ err = gnutls_certificate_allocate_credentials(&(s->tls->dtls_cred));
if (err) {
- gnutls_certificate_free_credentials(s->tls.gnutls_cred);
+ gnutls_certificate_free_credentials(s->tls->gnutls_cred);
rexmpp_log(s, LOG_CRIT, "gnutls credentials allocation error: %s",
gnutls_strerror(err));
return 1;
@@ -73,23 +74,23 @@ int rexmpp_tls_init (rexmpp_t *s) {
#elif defined(USE_OPENSSL)
SSL_library_init();
SSL_load_error_strings();
- s->tls.openssl_direction = REXMPP_OPENSSL_NONE;
- s->tls.openssl_conn = NULL;
- s->tls.openssl_ctx = SSL_CTX_new(TLS_client_method());
- if (s->tls.openssl_ctx == NULL) {
+ s->tls->openssl_direction = REXMPP_OPENSSL_NONE;
+ s->tls->openssl_conn = NULL;
+ s->tls->openssl_ctx = SSL_CTX_new(TLS_client_method());
+ if (s->tls->openssl_ctx == NULL) {
rexmpp_log(s, LOG_CRIT, "OpenSSL context creation error");
return 1;
}
- SSL_CTX_set_verify(s->tls.openssl_ctx, SSL_VERIFY_PEER, NULL);
- if (SSL_CTX_set_default_verify_paths(s->tls.openssl_ctx) == 0) {
+ SSL_CTX_set_verify(s->tls->openssl_ctx, SSL_VERIFY_PEER, NULL);
+ if (SSL_CTX_set_default_verify_paths(s->tls->openssl_ctx) == 0) {
rexmpp_log(s, LOG_CRIT, "Failed to set default verify paths for OpenSSL context");
- SSL_CTX_free(s->tls.openssl_ctx);
- s->tls.openssl_ctx = NULL;
+ SSL_CTX_free(s->tls->openssl_ctx);
+ s->tls->openssl_ctx = NULL;
return 1;
}
return 0;
#else
- (void)s;
+ s->tls = NULL;
return 0;
#endif
}
@@ -99,13 +100,13 @@ void rexmpp_tls_cleanup (rexmpp_t *s) {
if (s->tls_state != REXMPP_TLS_INACTIVE &&
s->tls_state != REXMPP_TLS_AWAITING_DIRECT) {
#if defined(USE_GNUTLS)
- gnutls_deinit(s->tls.gnutls_session);
+ gnutls_deinit(s->tls->gnutls_session);
#elif defined(USE_OPENSSL)
- if (s->tls.openssl_conn != NULL) {
- SSL_free(s->tls.openssl_conn);
- s->tls.openssl_conn = NULL;
+ if (s->tls->openssl_conn != NULL) {
+ SSL_free(s->tls->openssl_conn);
+ s->tls->openssl_conn = NULL;
}
- s->tls.openssl_direction = REXMPP_OPENSSL_NONE;
+ s->tls->openssl_direction = REXMPP_OPENSSL_NONE;
#else
(void)s;
#endif
@@ -114,22 +115,24 @@ void rexmpp_tls_cleanup (rexmpp_t *s) {
void rexmpp_tls_deinit (rexmpp_t *s) {
#if defined(USE_GNUTLS)
- gnutls_certificate_free_credentials(s->tls.gnutls_cred);
- if (s->tls.tls_session_data != NULL) {
- free(s->tls.tls_session_data);
- s->tls.tls_session_data = NULL;
+ gnutls_certificate_free_credentials(s->tls->gnutls_cred);
+ if (s->tls->tls_session_data != NULL) {
+ free(s->tls->tls_session_data);
+ s->tls->tls_session_data = NULL;
}
#ifdef ENABLE_CALLS
- gnutls_certificate_free_credentials(s->jingle.dtls_cred);
+ gnutls_certificate_free_credentials(s->tls->dtls_cred);
#endif
#elif defined(USE_OPENSSL)
- if (s->tls.openssl_ctx != NULL) {
- SSL_CTX_free(s->tls.openssl_ctx);
+ if (s->tls->openssl_ctx != NULL) {
+ SSL_CTX_free(s->tls->openssl_ctx);
}
- s->tls.openssl_ctx = NULL;
-#else
- (void)s;
+ s->tls->openssl_ctx = NULL;
#endif
+ if (s->tls != NULL) {
+ free(s->tls);
+ s->tls = NULL;
+ }
}
rexmpp_tls_err_t
@@ -138,33 +141,33 @@ rexmpp_tls_connect (rexmpp_t *s) {
if (s->tls_state != REXMPP_TLS_HANDSHAKE) {
gnutls_datum_t xmpp_client_protocol = {"xmpp-client", strlen("xmpp-client")};
rexmpp_log(s, LOG_DEBUG, "starting TLS");
- gnutls_init(&s->tls.gnutls_session, GNUTLS_CLIENT);
- gnutls_session_set_ptr(s->tls.gnutls_session, s);
- gnutls_alpn_set_protocols(s->tls.gnutls_session, &xmpp_client_protocol, 1, 0);
- gnutls_server_name_set(s->tls.gnutls_session, GNUTLS_NAME_DNS,
+ gnutls_init(&s->tls->gnutls_session, GNUTLS_CLIENT);
+ gnutls_session_set_ptr(s->tls->gnutls_session, s);
+ gnutls_alpn_set_protocols(s->tls->gnutls_session, &xmpp_client_protocol, 1, 0);
+ gnutls_server_name_set(s->tls->gnutls_session, GNUTLS_NAME_DNS,
s->initial_jid.domain,
strlen(s->initial_jid.domain));
- gnutls_set_default_priority(s->tls.gnutls_session);
- gnutls_credentials_set(s->tls.gnutls_session, GNUTLS_CRD_CERTIFICATE,
- s->tls.gnutls_cred);
- gnutls_transport_set_int(s->tls.gnutls_session, s->server_socket);
- gnutls_handshake_set_timeout(s->tls.gnutls_session,
+ gnutls_set_default_priority(s->tls->gnutls_session);
+ gnutls_credentials_set(s->tls->gnutls_session, GNUTLS_CRD_CERTIFICATE,
+ s->tls->gnutls_cred);
+ gnutls_transport_set_int(s->tls->gnutls_session, s->server_socket);
+ gnutls_handshake_set_timeout(s->tls->gnutls_session,
GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
- if (s->tls.tls_session_data != NULL) {
- int ret = gnutls_session_set_data(s->tls.gnutls_session,
- s->tls.tls_session_data,
- s->tls.tls_session_data_size);
+ if (s->tls->tls_session_data != NULL) {
+ int ret = gnutls_session_set_data(s->tls->gnutls_session,
+ s->tls->tls_session_data,
+ s->tls->tls_session_data_size);
if (ret != GNUTLS_E_SUCCESS) {
rexmpp_log(s, LOG_WARNING, "Failed to set TLS session data: %s",
gnutls_strerror(ret));
- free(s->tls.tls_session_data);
- s->tls.tls_session_data = NULL;
- s->tls.tls_session_data_size = 0;
+ free(s->tls->tls_session_data);
+ s->tls->tls_session_data = NULL;
+ s->tls->tls_session_data_size = 0;
}
}
}
- int ret = gnutls_handshake(s->tls.gnutls_session);
+ int ret = gnutls_handshake(s->tls->gnutls_session);
if (ret == GNUTLS_E_AGAIN) {
rexmpp_log(s, LOG_DEBUG, "Waiting for TLS handshake to complete");
return REXMPP_TLS_E_AGAIN;
@@ -190,7 +193,7 @@ rexmpp_tls_connect (rexmpp_t *s) {
service/source host
(<https://tools.ietf.org/html/rfc7712#section-5.1>,
<https://tools.ietf.org/html/rfc7673#section-6>). */
- ret = dane_verify_session_crt(NULL, s->tls.gnutls_session, s->server_host,
+ ret = dane_verify_session_crt(NULL, s->tls->gnutls_session, s->server_host,
"tcp", s->server_port, 0, 0, &status);
if (ret) {
rexmpp_log(s, LOG_WARNING, "DANE verification error: %s",
@@ -212,7 +215,7 @@ rexmpp_tls_connect (rexmpp_t *s) {
}
}
- ret = gnutls_certificate_verify_peers3(s->tls.gnutls_session,
+ ret = gnutls_certificate_verify_peers3(s->tls->gnutls_session,
s->initial_jid.domain,
&status);
if (ret || status) {
@@ -224,23 +227,23 @@ rexmpp_tls_connect (rexmpp_t *s) {
} else {
rexmpp_log(s, LOG_ERR, "Untrusted certificate");
}
- gnutls_bye(s->tls.gnutls_session, GNUTLS_SHUT_RDWR);
+ gnutls_bye(s->tls->gnutls_session, GNUTLS_SHUT_RDWR);
return REXMPP_TLS_E_OTHER;
}
- if (gnutls_session_is_resumed(s->tls.gnutls_session)) {
+ if (gnutls_session_is_resumed(s->tls->gnutls_session)) {
rexmpp_log(s, LOG_INFO, "TLS session is resumed");
} else {
- if (s->tls.tls_session_data != NULL) {
+ if (s->tls->tls_session_data != NULL) {
rexmpp_log(s, LOG_DEBUG, "TLS session is not resumed");
- free(s->tls.tls_session_data);
- s->tls.tls_session_data = NULL;
+ free(s->tls->tls_session_data);
+ s->tls->tls_session_data = NULL;
}
- gnutls_session_get_data(s->tls.gnutls_session, NULL,
- &s->tls.tls_session_data_size);
- s->tls.tls_session_data = malloc(s->tls.tls_session_data_size);
- ret = gnutls_session_get_data(s->tls.gnutls_session, s->tls.tls_session_data,
- &s->tls.tls_session_data_size);
+ gnutls_session_get_data(s->tls->gnutls_session, NULL,
+ &s->tls->tls_session_data_size);
+ s->tls->tls_session_data = malloc(s->tls->tls_session_data_size);
+ ret = gnutls_session_get_data(s->tls->gnutls_session, s->tls->tls_session_data,
+ &s->tls->tls_session_data_size);
if (ret != GNUTLS_E_SUCCESS) {
rexmpp_log(s, LOG_ERR, "Failed to get TLS session data: %s",
gnutls_strerror(ret));
@@ -256,26 +259,26 @@ rexmpp_tls_connect (rexmpp_t *s) {
}
#elif defined(USE_OPENSSL)
if (s->tls_state != REXMPP_TLS_HANDSHAKE) {
- s->tls.openssl_conn = SSL_new(s->tls.openssl_ctx);
- if (s->tls.openssl_conn == NULL) {
+ s->tls->openssl_conn = SSL_new(s->tls->openssl_ctx);
+ if (s->tls->openssl_conn == NULL) {
rexmpp_log(s, LOG_ERR, "Failed to create an OpenSSL connection object");
return REXMPP_TLS_E_OTHER;
}
- if (SSL_set_fd(s->tls.openssl_conn, s->server_socket) == 0) {
+ if (SSL_set_fd(s->tls->openssl_conn, s->server_socket) == 0) {
rexmpp_log(s, LOG_ERR, "Failed to set a file descriptor for OpenSSL connection");
return REXMPP_TLS_E_OTHER;
}
- if (SSL_set1_host(s->tls.openssl_conn, s->initial_jid.domain) == 0) {
+ if (SSL_set1_host(s->tls->openssl_conn, s->initial_jid.domain) == 0) {
rexmpp_log(s, LOG_ERR, "Failed to set a hostname for OpenSSL connection");
return REXMPP_TLS_E_OTHER;
}
/* For SNI */
- if (SSL_set_tlsext_host_name(s->tls.openssl_conn, s->initial_jid.domain) == 0) {
+ if (SSL_set_tlsext_host_name(s->tls->openssl_conn, s->initial_jid.domain) == 0) {
rexmpp_log(s, LOG_ERR, "Failed to set a tlsext hostname for OpenSSL connection");
return REXMPP_TLS_E_OTHER;
}
}
- return rexmpp_process_openssl_ret(s, SSL_connect(s->tls.openssl_conn));
+ return rexmpp_process_openssl_ret(s, SSL_connect(s->tls->openssl_conn));
#else
rexmpp_log(s, LOG_ERR, "rexmpp is compiled without TLS support");
return REXMPP_TLS_E_OTHER;
@@ -285,7 +288,7 @@ rexmpp_tls_connect (rexmpp_t *s) {
rexmpp_tls_err_t
rexmpp_tls_disconnect (rexmpp_t *s) {
#if defined(USE_GNUTLS)
- int ret = gnutls_bye(s->tls.gnutls_session, GNUTLS_SHUT_RDWR);
+ int ret = gnutls_bye(s->tls->gnutls_session, GNUTLS_SHUT_RDWR);
if (ret == GNUTLS_E_SUCCESS) {
return REXMPP_TLS_SUCCESS;
} else {
@@ -294,9 +297,9 @@ rexmpp_tls_disconnect (rexmpp_t *s) {
return REXMPP_TLS_E_OTHER;
}
#elif defined(USE_OPENSSL)
- int ret = SSL_shutdown(s->tls.openssl_conn);
+ int ret = SSL_shutdown(s->tls->openssl_conn);
if (ret == 0) {
- s->tls.openssl_direction = REXMPP_OPENSSL_READ;
+ s->tls->openssl_direction = REXMPP_OPENSSL_READ;
return REXMPP_TLS_E_AGAIN;
} else {
return rexmpp_process_openssl_ret(s, ret);
@@ -312,7 +315,7 @@ rexmpp_tls_send (rexmpp_t *s, void *data, size_t data_size, ssize_t *written)
{
#if defined(USE_GNUTLS)
*written = -1;
- ssize_t ret = gnutls_record_send(s->tls.gnutls_session,
+ ssize_t ret = gnutls_record_send(s->tls->gnutls_session,
data,
data_size);
if (ret >= 0) {
@@ -326,7 +329,7 @@ rexmpp_tls_send (rexmpp_t *s, void *data, size_t data_size, ssize_t *written)
}
#elif defined(USE_OPENSSL)
*written = -1;
- int ret = SSL_write_ex(s->tls.openssl_conn, data, data_size, written);
+ int ret = SSL_write_ex(s->tls->openssl_conn, data, data_size, written);
if (ret > 0) {
return REXMPP_TLS_SUCCESS;
} else {
@@ -345,7 +348,7 @@ rexmpp_tls_err_t
rexmpp_tls_recv (rexmpp_t *s, void *data, size_t data_size, ssize_t *received) {
#if defined(USE_GNUTLS)
*received = -1;
- ssize_t ret = gnutls_record_recv(s->tls.gnutls_session, data, data_size);
+ ssize_t ret = gnutls_record_recv(s->tls->gnutls_session, data, data_size);
if (ret >= 0) {
*received = ret;
return REXMPP_TLS_SUCCESS;
@@ -357,7 +360,7 @@ rexmpp_tls_recv (rexmpp_t *s, void *data, size_t data_size, ssize_t *received) {
}
#elif defined(USE_OPENSSL)
*received = -1;
- int ret = SSL_read_ex(s->tls.openssl_conn, data, data_size, received);
+ int ret = SSL_read_ex(s->tls->openssl_conn, data, data_size, received);
if (ret > 0) {
return REXMPP_TLS_SUCCESS;
} else {
@@ -374,18 +377,18 @@ rexmpp_tls_recv (rexmpp_t *s, void *data, size_t data_size, ssize_t *received) {
int rexmpp_tls_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) {
#if defined(USE_GNUTLS)
- if (gnutls_record_get_direction(s->tls.gnutls_session) == 0) {
+ if (gnutls_record_get_direction(s->tls->gnutls_session) == 0) {
FD_SET(s->server_socket, read_fds);
} else {
FD_SET(s->server_socket, write_fds);
}
return s->server_socket + 1;
#elif defined(USE_OPENSSL)
- if (s->tls.openssl_direction == REXMPP_OPENSSL_READ) {
+ if (s->tls->openssl_direction == REXMPP_OPENSSL_READ) {
FD_SET(s->server_socket, read_fds);
return s->server_socket + 1;
}
- if (s->tls.openssl_direction == REXMPP_OPENSSL_WRITE) {
+ if (s->tls->openssl_direction == REXMPP_OPENSSL_WRITE) {
FD_SET(s->server_socket, write_fds);
return s->server_socket + 1;
}
@@ -404,12 +407,12 @@ rexmpp_tls_set_x509_key_file (rexmpp_t *s,
const char *key_file)
{
#if defined(USE_GNUTLS)
- int ret = gnutls_certificate_set_x509_key_file(s->tls.gnutls_cred,
+ int ret = gnutls_certificate_set_x509_key_file(s->tls->gnutls_cred,
cert_file,
key_file,
GNUTLS_X509_FMT_PEM);
#ifdef ENABLE_CALLS
- gnutls_certificate_set_x509_key_file(s->jingle.dtls_cred,
+ gnutls_certificate_set_x509_key_file(s->tls->dtls_cred,
cert_file,
key_file,
GNUTLS_X509_FMT_PEM);
@@ -422,13 +425,13 @@ rexmpp_tls_set_x509_key_file (rexmpp_t *s,
return REXMPP_TLS_E_OTHER;
}
#elif defined(USE_OPENSSL)
- if (SSL_CTX_use_certificate_file(s->tls.openssl_ctx,
+ if (SSL_CTX_use_certificate_file(s->tls->openssl_ctx,
cert_file,
SSL_FILETYPE_PEM) != 1) {
rexmpp_log(s, LOG_ERR, "Failed to set a certificate file");
return REXMPP_TLS_E_OTHER;
}
- if (SSL_CTX_use_PrivateKey_file(s->tls.openssl_ctx,
+ if (SSL_CTX_use_PrivateKey_file(s->tls->openssl_ctx,
key_file,
SSL_FILETYPE_PEM) != 1) {
rexmpp_log(s, LOG_ERR, "Failed to set a key file");
@@ -448,12 +451,12 @@ rexmpp_tls_set_x509_trust_file (rexmpp_t *s,
const char *cert_file)
{
#if defined(USE_GNUTLS)
- gnutls_certificate_set_x509_trust_file(s->tls.gnutls_cred,
+ gnutls_certificate_set_x509_trust_file(s->tls->gnutls_cred,
cert_file,
GNUTLS_X509_FMT_PEM);
return REXMPP_TLS_SUCCESS;
#elif defined(USE_OPENSSL)
- if (SSL_CTX_load_verify_locations(s->tls.openssl_ctx, cert_file, NULL) != 1) {
+ if (SSL_CTX_load_verify_locations(s->tls->openssl_ctx, cert_file, NULL) != 1) {
rexmpp_log(s, LOG_ERR, "Failed to set a trusted certificate file");
return REXMPP_TLS_E_OTHER;
}