src/sock_gnutls.c
changeset 2 a834f0559939
child 3 cc94ae754e2a
equal deleted inserted replaced
1:cf0e1bb6bcab 2:a834f0559939
       
     1 
       
     2 #include "sock_gnutls.h"
       
     3 
       
     4 #include <stdlib.h>
       
     5 #include <err.h>
       
     6 
       
     7 static void _sock_gnutls_error (struct sock_gnutls *sock, const char *func, int _err) {
       
     8     if (_err == GNUTLS_E_FATAL_ALERT_RECEIVED)
       
     9         errx(1, "%s: %s: %s", func, gnutls_strerror(_err), gnutls_alert_get_name(gnutls_alert_get(sock->session)));
       
    10 
       
    11     else
       
    12         errx(1, "%s: %s", func, gnutls_strerror(_err));
       
    13 }
       
    14 
       
    15 static int sock_gnutls_read (struct sock_stream *base_sock, void *buf, size_t len)
       
    16 {
       
    17     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
       
    18     
       
    19     // just map to gnutls_record_recv
       
    20     return gnutls_record_recv(sock->session, buf, len);
       
    21 }
       
    22 
       
    23 static int sock_gnutls_write (struct sock_stream *base_sock, const void *buf, size_t len)
       
    24 {
       
    25     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
       
    26     
       
    27     // just map to gnutls_record_send
       
    28     return gnutls_record_send(sock->session, buf, len);
       
    29 }
       
    30 
       
    31 /*
       
    32  * Our sock_stream_Type
       
    33  */
       
    34 struct sock_stream_type sock_gnutls_type = {
       
    35     .methods.read   = &sock_gnutls_read,
       
    36     .methods.write  = &sock_gnutls_write,
       
    37 };
       
    38 
       
    39 /*
       
    40  * XXX: global shared sock_gnutls_ctx
       
    41  */
       
    42 struct sock_gnutls_client_ctx _sock_gnutls_client_ctx;
       
    43 
       
    44 /*
       
    45  * Configure the given gnutls socket context to use simple anonymous client credentials
       
    46  *
       
    47  * XXX: errors
       
    48  */
       
    49 void sock_gnutls_client_ctx_anon (struct sock_gnutls_client_ctx *ctx)
       
    50 {
       
    51       gnutls_certificate_allocate_credentials(&ctx->xcred);
       
    52 }
       
    53 
       
    54 // XXX: errors
       
    55 void sock_gnutls_init (void)
       
    56 {
       
    57     int _err;
       
    58 
       
    59     // global init
       
    60     if ((_err = gnutls_global_init()) < 0)
       
    61         errx(1, "gnutls_global_init: %s", gnutls_strerror(_err));
       
    62 
       
    63     // init _sock_gnutls_ctx
       
    64     sock_gnutls_client_ctx_anon(&_sock_gnutls_client_ctx);
       
    65 }
       
    66 
       
    67 
       
    68 // XXX: errors
       
    69 struct sock_stream *sock_ssl_connect (const char *host, const char *service)
       
    70 {
       
    71     int _err;
       
    72     struct sock_gnutls *sock;
       
    73     struct sock_gnutls_client_ctx *ctx = &_sock_gnutls_client_ctx;
       
    74 
       
    75     // alloc
       
    76     if ((sock = calloc(1, sizeof(*sock))) == NULL)
       
    77         errx(1, "calloc");
       
    78 
       
    79     // initialize
       
    80     sock->base_tcp.base.type = &sock_gnutls_type;
       
    81 
       
    82     // initialize client session
       
    83     if ((_err = gnutls_init(&sock->session, GNUTLS_CLIENT)) < 0)
       
    84         errx(1, "gnutls_init: %s", gnutls_strerror(_err));
       
    85 
       
    86     // ...default priority stuff
       
    87     gnutls_set_default_priority(sock->session);
       
    88 
       
    89     // bind anon credentials
       
    90     gnutls_credentials_set(sock->session, GNUTLS_CRD_CERTIFICATE, ctx->xcred);
       
    91 
       
    92     // TCP connect
       
    93     sock_tcp_init_connect(SOCK_GNUTLS_TCP(sock), host, service);
       
    94 
       
    95     // bind default transport functions (recv/send) to use the TCP fd
       
    96     gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr_t) sock->base_tcp.fd);
       
    97 
       
    98     // perform the handshake
       
    99     if ((_err = gnutls_handshake(sock->session)) < 0)
       
   100         _sock_gnutls_error(sock, "gnutls_handshake", _err);
       
   101 
       
   102     // done
       
   103     return SOCK_GNUTLS_BASE(sock);
       
   104 }
       
   105