src/sock_gnutls.c
changeset 2 a834f0559939
child 3 cc94ae754e2a
--- /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 <stdlib.h>
+#include <err.h>
+
+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);
+}
+