[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
8.1.2 Simple client example with X.509 certificate support
Let’s assume now that we want to create a TCP client which communicates with servers that use X.509 or OpenPGP certificate authentication. The following client is a very simple TLS client, which uses the high level verification functions for certificates, but does not support session resumption.
/* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <gnutls/gnutls.h> #include <gnutls/x509.h> #include "examples.h" /* A very basic TLS client, with X.509 authentication and server certificate * verification. */ #define MAX_BUF 1024 #define CAFILE "ca.pem" #define MSG "GET / HTTP/1.0\r\n\r\n" extern int tcp_connect (void); extern void tcp_close (int sd); static int _verify_certificate_callback (gnutls_session_t session); int main (void) { int ret, sd, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; const char *err; gnutls_certificate_credentials_t xcred; gnutls_global_init (); /* X509 stuff */ gnutls_certificate_allocate_credentials (&xcred); /* sets the trusted cas file */ gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_verify_function (xcred, _verify_certificate_callback); /* Initialize TLS session */ gnutls_init (&session, GNUTLS_CLIENT); gnutls_session_set_ptr (session, (void *) "my_host_name"); /* Use default priorities */ ret = gnutls_priority_set_direct (session, "NORMAL", &err); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) { fprintf (stderr, "Syntax error at: %s\n", err); } exit (1); } /* put the x509 credentials to the current session */ gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); /* connect to the peer */ sd = tcp_connect (); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); /* Perform the TLS handshake */ ret = gnutls_handshake (session); if (ret < 0) { fprintf (stderr, "*** Handshake failed\n"); gnutls_perror (ret); goto end; } else { printf ("- Handshake was completed\n"); } gnutls_record_send (session, MSG, strlen (MSG)); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { printf ("- Peer has closed the TLS connection\n"); goto end; } else if (ret < 0) { fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret)); goto end; } printf ("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc (buffer[ii], stdout); } fputs ("\n", stdout); gnutls_bye (session, GNUTLS_SHUT_RDWR); end: tcp_close (sd); gnutls_deinit (session); gnutls_certificate_free_credentials (xcred); gnutls_global_deinit (); return 0; } /* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (status & GNUTLS_CERT_INVALID) printf ("The certificate is not trusted.\n"); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) printf ("The certificate hasn't got a known issuer.\n"); if (status & GNUTLS_CERT_REVOKED) printf ("The certificate has been revoked.\n"); if (status & GNUTLS_CERT_EXPIRED) printf ("The certificate has expired\n"); if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return GNUTLS_E_CERTIFICATE_ERROR; if (gnutls_x509_crt_init (&cert) < 0) { printf ("error in initialization\n"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { printf ("No certificate was found!\n"); return GNUTLS_E_CERTIFICATE_ERROR; } /* This is not a real world example, since we only check the first * certificate in the given chain. */ if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { printf ("error parsing certificate\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { printf ("The certificate's owner does not match hostname '%s'\n", hostname); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_deinit (cert); /* notify gnutls to continue handshake normally */ return 0; }
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on January 4, 2012 using texi2html 5.0.