diff -r cf0e1bb6bcab -r a834f0559939 src/sock_gnutls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sock_gnutls.c Sun Feb 22 05:27:29 2009 +0200 @@ -0,0 +1,105 @@ + +#include "sock_gnutls.h" + +#include +#include + +static void _sock_gnutls_error (struct sock_gnutls *sock, const char *func, int _err) { + if (_err == GNUTLS_E_FATAL_ALERT_RECEIVED) + errx(1, "%s: %s: %s", func, gnutls_strerror(_err), gnutls_alert_get_name(gnutls_alert_get(sock->session))); + + else + errx(1, "%s: %s", func, gnutls_strerror(_err)); +} + +static int sock_gnutls_read (struct sock_stream *base_sock, void *buf, size_t len) +{ + struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls); + + // just map to gnutls_record_recv + return gnutls_record_recv(sock->session, buf, len); +} + +static int sock_gnutls_write (struct sock_stream *base_sock, const void *buf, size_t len) +{ + struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls); + + // just map to gnutls_record_send + return gnutls_record_send(sock->session, buf, len); +} + +/* + * Our sock_stream_Type + */ +struct sock_stream_type sock_gnutls_type = { + .methods.read = &sock_gnutls_read, + .methods.write = &sock_gnutls_write, +}; + +/* + * XXX: global shared sock_gnutls_ctx + */ +struct sock_gnutls_client_ctx _sock_gnutls_client_ctx; + +/* + * Configure the given gnutls socket context to use simple anonymous client credentials + * + * XXX: errors + */ +void sock_gnutls_client_ctx_anon (struct sock_gnutls_client_ctx *ctx) +{ + gnutls_certificate_allocate_credentials(&ctx->xcred); +} + +// XXX: errors +void sock_gnutls_init (void) +{ + int _err; + + // global init + if ((_err = gnutls_global_init()) < 0) + errx(1, "gnutls_global_init: %s", gnutls_strerror(_err)); + + // init _sock_gnutls_ctx + sock_gnutls_client_ctx_anon(&_sock_gnutls_client_ctx); +} + + +// XXX: errors +struct sock_stream *sock_ssl_connect (const char *host, const char *service) +{ + int _err; + struct sock_gnutls *sock; + struct sock_gnutls_client_ctx *ctx = &_sock_gnutls_client_ctx; + + // alloc + if ((sock = calloc(1, sizeof(*sock))) == NULL) + errx(1, "calloc"); + + // initialize + sock->base_tcp.base.type = &sock_gnutls_type; + + // initialize client session + if ((_err = gnutls_init(&sock->session, GNUTLS_CLIENT)) < 0) + errx(1, "gnutls_init: %s", gnutls_strerror(_err)); + + // ...default priority stuff + gnutls_set_default_priority(sock->session); + + // bind anon credentials + gnutls_credentials_set(sock->session, GNUTLS_CRD_CERTIFICATE, ctx->xcred); + + // TCP connect + sock_tcp_init_connect(SOCK_GNUTLS_TCP(sock), host, service); + + // bind default transport functions (recv/send) to use the TCP fd + gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr_t) sock->base_tcp.fd); + + // perform the handshake + if ((_err = gnutls_handshake(sock->session)) < 0) + _sock_gnutls_error(sock, "gnutls_handshake", _err); + + // done + return SOCK_GNUTLS_BASE(sock); +} +