Files
libstrophe-gh-mirror/src/tls_gnutls.c
Dmitry Podgorny db8a511f68 style: remove extra const keyword from interfaces
Const variables in prototypes don't add much value, but make the code
larger and redundant. Remove these const keywords.
Note, this doesn't apply to pointers to const memory.
2021-03-19 22:12:15 +02:00

148 lines
3.1 KiB
C

/* tls.c
** strophe XMPP client library -- TLS abstraction header
**
** Copyright (C) 2005-2009 Collecta, Inc.
**
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
* TLS implementation with GNUTLS
*/
#include <gnutls/gnutls.h>
#include "common.h"
#include "tls.h"
#include "sock.h"
/* FIXME this shouldn't be a constant string */
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
struct _tls {
xmpp_ctx_t *ctx; /* do we need this? */
sock_t sock;
gnutls_session_t session;
gnutls_certificate_credentials_t cred;
int lasterror;
};
void tls_initialize(void)
{
/* initialize the GNU TLS global state */
gnutls_global_init();
/* TODO: wire in xmpp_ctx_t allocator somehow?
unfortunately in gnutls it's global, so we can
only do so much. */
}
void tls_shutdown(void)
{
/* tear down the GNU TLS global state */
gnutls_global_deinit();
}
tls_t *tls_new(xmpp_conn_t *conn)
{
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(tls_t));
if (tls) {
tls->ctx = conn->ctx;
tls->sock = conn->sock;
gnutls_init(&tls->session, GNUTLS_CLIENT);
gnutls_certificate_allocate_credentials(&tls->cred);
tls_set_credentials(tls, CAFILE);
gnutls_set_default_priority(tls->session);
/* fixme: this may require setting a callback on win32? */
gnutls_transport_set_int(tls->session, conn->sock);
}
return tls;
}
void tls_free(tls_t *tls)
{
gnutls_deinit(tls->session);
gnutls_certificate_free_credentials(tls->cred);
xmpp_free(tls->ctx, tls);
}
int tls_set_credentials(tls_t *tls, const char *cafilename)
{
int err;
/* set trusted credentials -- takes a .pem filename */
err = gnutls_certificate_set_x509_trust_file(tls->cred, cafilename,
GNUTLS_X509_FMT_PEM);
if (err >= 0) {
err = gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE,
tls->cred);
}
tls->lasterror = err;
return err == GNUTLS_E_SUCCESS;
}
int tls_start(tls_t *tls)
{
sock_set_blocking(tls->sock);
tls->lasterror = gnutls_handshake(tls->session);
sock_set_nonblocking(tls->sock);
return tls->lasterror == GNUTLS_E_SUCCESS;
}
int tls_stop(tls_t *tls)
{
tls->lasterror = gnutls_bye(tls->session, GNUTLS_SHUT_RDWR);
return tls->lasterror == GNUTLS_E_SUCCESS;
}
int tls_error(tls_t *tls)
{
return tls->lasterror;
}
int tls_is_recoverable(int error)
{
return !gnutls_error_is_fatal(error);
}
int tls_pending(tls_t *tls)
{
return gnutls_record_check_pending(tls->session);
}
int tls_read(tls_t *tls, void *buff, size_t len)
{
int ret;
ret = gnutls_record_recv(tls->session, buff, len);
tls->lasterror = ret < 0 ? ret : 0;
return ret;
}
int tls_write(tls_t *tls, const void *buff, size_t len)
{
int ret;
ret = gnutls_record_send(tls->session, buff, len);
tls->lasterror = ret < 0 ? ret : 0;
return ret;
}
int tls_clear_pending_write(tls_t *tls)
{
UNUSED(tls);
return 0;
}