next_inactive up previous


GNU Transport Layer Security Library

Nikos Mavroyanopoulos


Contents

Introduction

gnuTLS is a library which implements the TLS 1.0 and SSL 3.0 protocols. TLS stands for 'Transport Layer Security' and is the sucessor of SSL (Secure Sockets Layer). TLS 1.0 is described is RFC 2246 and is an Internet protocol (thus it's mostly used over TCP/IP), that provides confidentiality, and authentication layers. Currently gnuTLS implements:

Confidentiality

Confidentiality is provided by using symmetric encryption algorithms like 3DES, AES, or stream algorithms like ARCFOUR. A symmetric encryption algorithm uses a single (secret) key to encrypt and decrypt data.

Authentication

The following authentication schemas are supported in gnuTLS:

  1. X509 Public Key Infrastructure
  2. Anonymous authentication
  3. SRP authentication

Client Examples

This section contains examples of TLS and SSL clients, using gnuTLS.

Simple Client example with X509 Authentication

Let's assume now that we want to create a client which communicates with servers using the X509 authentication schema. The following client is a very simple TLS client, it does not support session resuming nor any other fancy features.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gnutls.h>

#define MAX_BUF 1024
#define CRLFILE "crl.pem"
#define CAFILE "ca.pem"
#define SA struct sockaddr
#define MSG "GET / HTTP/1.0\r\n\r\n"

int main()
{
       const char *PORT = "443";
       const char *SERVER = "127.0.0.1";
       int err, ret;
       int sd, ii;
       struct sockaddr_in sa;
       GNUTLS_STATE state;
       char buffer[MAX_BUF + 1];
       X509PKI_CLIENT_CREDENTIALS xcred;

       if (gnutls_global_init() < 0) {
	      fprintf(stderr, "global state initialization error\n");
	      exit(1);
       }
       /* X509 stuff */
       if (gnutls_allocate_x509_client_sc(&xcred, 0) < 0) {	/* no client private key */
	      fprintf(stderr, "memory error\n");
	      exit(1);
       }
       /* set's the trusted cas file
        */
       gnutls_set_x509_client_trust(xcred, CAFILE, CRLFILE);

       /* connects to server 
        */
       sd = socket(AF_INET, SOCK_STREAM, 0);

       memset(&sa, '\0', sizeof(sa));
       sa.sin_family = AF_INET;
       sa.sin_port = htons(atoi(PORT));
       inet_pton(AF_INET, SERVER, &sa.sin_addr);

       err = connect(sd, (SA *) & sa, sizeof(sa));
       if (err < 0) {
	      fprintf(stderr, "Connect error\n");
	      exit(1);
       }
       /* Initialize TLS state 
        */
       gnutls_init(&state, GNUTLS_CLIENT);

       /* allow both SSL3 and TLS1
        */
       gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);

       /* allow only ARCFOUR and 3DES ciphers
        * (3DES has the highest priority)
        */
       gnutls_set_cipher_priority(state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);

       /* only allow null compression
        */
       gnutls_set_compression_priority(state, GNUTLS_NULL_COMPRESSION, 0);

       /* use GNUTLS_KX_RSA
        */
       gnutls_set_kx_priority(state, GNUTLS_KX_RSA, 0);

       /* allow the usage of both SHA and MD5
        */
       gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);


       /* put the x509 credentials to the current state
        */
       gnutls_set_cred(state, GNUTLS_X509PKI, xcred);

       /* This should be the CN in the server's 
        * certificate.
        */
       gnutls_x509_set_cn(state, "www.host.com");


       /* Perform the TLS handshake
        */
       ret = gnutls_handshake(sd, state);

       if (ret < 0) {
	      fprintf(stderr, "*** Handshake failed\n");
	      gnutls_perror(ret);
	      goto end;
       } else {
	      printf("- Handshake was completed\n");
       }

       gnutls_write(sd, state, MSG, strlen(MSG));

       ret = gnutls_read(sd, state, buffer, MAX_BUF);
       if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
	      if (ret == 0) {
		     printf("- Peer has closed the GNUTLS connection\n");
		     goto end;
	      } else {
		     fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
			     ret);
		     goto end;
	      }
       } else {
	      if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
		     printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
	      if (ret == GNUTLS_E_GOT_HELLO_REQUEST)
		     printf("* Received HelloRequest message (server asked to rehandshake)\n");
       }

       if (ret > 0) {
	      printf("- Received %d bytes: ", ret);
	      for (ii = 0; ii < ret; ii++) {
		     fputc(buffer[ii], stdout);
	      }
	      fputs("\n", stdout);
       }
       gnutls_bye(sd, state, 0);

     end:

       shutdown(sd, SHUT_RDWR);	/* no more receptions */
       close(sd);

       gnutls_deinit(state);

       gnutls_free_x509_client_sc(xcred);

       gnutls_global_deinit();

       return 0;
}

Getting peer's information

The above example was the simplest form of a client, it didn't even check the result of the peer's certificate verification function (ie. if we have an authenticated connection). The following function does check the peer's X509 Certificate, and prints some information about the current state.

This function should be called after a successful gnutls_handshake()

int print_info(GNUTLS_STATE state)
{
       const char *tmp;
       const X509PKI_CLIENT_AUTH_INFO *x509_info;

       /* print the key exchange's algorithm name
        */
       tmp = gnutls_kx_get_name(gnutls_get_current_kx(state));
       printf("- Key Exchange: %s\n", tmp);

       /* in case of X509 PKI
        */
       if (gnutls_get_auth_info_type(state) == GNUTLS_X509PKI) {
	      x509_info = gnutls_get_auth_info(state);
	      if (x509_info != NULL) {
		     switch (x509_info->peer_certificate_status) {
		     case GNUTLS_CERT_NOT_TRUSTED:
			    printf("- Peer's X509 Certificate was NOT verified\n");
			    break;
		     case GNUTLS_CERT_EXPIRED:
			    printf("- Peer's X509 Certificate was verified but is expired\n");
			    break;
		     case GNUTLS_CERT_TRUSTED:
			    printf("- Peer's X509 Certificate was verified\n");
			    break;
		     case GNUTLS_CERT_WRONG_CN:
			    /* the server's name
			     * is set by using the gnutls_set_x509_cn() function.
			     */
			    printf("- Peer's X509 Certificate was verified but it does not match the server's name\n");
			    break;
		     case GNUTLS_CERT_INVALID:
		     default:
			    printf("- Peer's X509 Certificate was invalid\n");
			    break;

		     }
	      }
       }
       printf(" - Certificate info:\n");
       printf(" - Certificate version: #%d\n", x509_info->peer_certificate_version);

       PRINT_DN(peer_dn);

       printf(" - Certificate Issuer's info:\n");
       PRINT_DN(issuer_dn);


       tmp = gnutls_version_get_name(gnutls_get_current_version(state));
       printf("- Version: %s\n", tmp);

       tmp = gnutls_compression_get_name(gnutls_get_current_compression_method(state));
       printf("- Compression: %s\n", tmp);

       tmp = gnutls_cipher_get_name(gnutls_get_current_cipher(state));
       printf("- Cipher: %s\n", tmp);

       tmp = gnutls_mac_get_name(gnutls_get_current_mac_algorithm(state));
       printf("- MAC: %s\n", tmp);

       return 0;
}

Resuming Sessions

The gnutls_handshake() function, is expensive since a lot of calculations are performed. In order to support many fast connections to the same server a client may use session resuming. Session resuming is a feature of the TLS protocol which allows a client to connect to a server, after a successful handshake, without the expensive calculations (ie. use the previously established keys). gnuTLS supports this feature, and this example illustrates a typical use of it (This is a modification of the simple client example).

Keep in mind that sessions are expired after some time (for security reasons), thus it may be normal for a server not to resume a session even if you requested that.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gnutls.h>

#define MAX_BUF 1024
#define CRLFILE "crl.pem"
#define CAFILE "ca.pem"
#define SA struct sockaddr
#define MSG "GET / HTTP/1.0\r\n\r\n"

int main()
{
       const char *PORT = "443";
       const char *SERVER = "127.0.0.1";
       int err, ret;
       int sd, ii;
       struct sockaddr_in sa;
       GNUTLS_STATE state;
       char buffer[MAX_BUF + 1];
       X509PKI_CLIENT_CREDENTIALS xcred;
       /* variables used in session resuming */
       int t;
       char *session;
       char *session_id;
       int session_size;
       int session_id_size;
       char *tmp_session_id;
       int tmp_session_id_size;

       if (gnutls_global_init() < 0) {
	      fprintf(stderr, "global state initialization error\n");
	      exit(1);
       }
       /* X509 stuff */
       if (gnutls_allocate_x509_client_sc(&xcred, 0) < 0) {	/* no client private key */
	      fprintf(stderr, "memory error\n");
	      exit(1);
       }
       gnutls_set_x509_client_trust(xcred, CAFILE, CRLFILE);

       for (t = 0; t < 2; t++) {	/* connect 2 times to the server */

	      sd = socket(AF_INET, SOCK_STREAM, 0);
	      memset(&sa, '\0', sizeof(sa));
	      sa.sin_family = AF_INET;
	      sa.sin_port = htons(atoi(PORT));
	      inet_pton(AF_INET, SERVER, &sa.sin_addr);

	      err = connect(sd, (SA *) & sa, sizeof(sa));
	      if (err < 0) {
		     fprintf(stderr, "Connect error");
		     exit(1);
	      }
	      gnutls_init(&state, GNUTLS_CLIENT);
	      gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
	      gnutls_set_cipher_priority(state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);
	      gnutls_set_compression_priority(state, GNUTLS_NULL_COMPRESSION, 0);
	      gnutls_set_kx_priority(state, GNUTLS_KX_RSA, 0);
	      gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);


	      gnutls_set_cred(state, GNUTLS_X509PKI, xcred);
	      gnutls_x509_set_cn(state, "www.host.com");


	      if (t > 0) {	/* if this is not the first time we connect */
		     gnutls_set_current_session(state, session, session_size);
		     free(session);
	      }
	      /* Perform the TLS handshake
	       */
	      ret = gnutls_handshake(sd, state);

	      if (ret < 0) {
		     fprintf(stderr, "*** Handshake failed\n");
		     gnutls_perror(ret);
		     goto end;
	      } else {
		     printf("- Handshake was completed\n");
	      }

	      if (t == 0) {	/* the first time we connect */
		     /* get the session data size */
		     gnutls_get_current_session(state, NULL, &session_size);
		     session = malloc(session_size);

		     /* put session data to the session variable */
		     gnutls_get_current_session(state, session, &session_size);

		     /* keep the current session ID. This is only needed
		      * in order to check if the server actually resumed this
		      * connection.
		      */
		     gnutls_get_current_session_id(state, NULL, &session_id_size);
		     session_id = malloc(session_id_size);
		     gnutls_get_current_session_id(state, session_id, &session_id_size);

	      } else {		/* the second time we connect */

		     /* check if we actually resumed the previous session */
		     gnutls_get_current_session_id(state, NULL, &tmp_session_id_size);
		     tmp_session_id = malloc(tmp_session_id_size);
		     gnutls_get_current_session_id(state, tmp_session_id, &tmp_session_id_size);

		     if (memcmp(tmp_session_id, session_id, session_id_size) == 0) {
			    printf("- Previous session was resumed\n");
		     } else {
			    fprintf(stderr, "*** Previous session was NOT resumed\n");
		     }
		     free(tmp_session_id);
		     free(session_id);
	      }

	      /* This function is defined in a previous example
	       */
	      print_info(state);

	      gnutls_write(sd, state, MSG, strlen(MSG));

	      ret = gnutls_read(sd, state, buffer, MAX_BUF);
	      if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
		     if (ret == 0) {
			    printf("- Peer has closed the GNUTLS connection\n");
			    goto end;
		     } else {
			    fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
				    ret);
			    goto end;
		     }
	      } else {
		     if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
			    printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
		     if (ret == GNUTLS_E_GOT_HELLO_REQUEST)
			    printf("* Received HelloRequest message (server asked to rehandshake)\n");
	      }

	      if (ret > 0) {
		     printf("- Received %d bytes: ", ret);
		     for (ii = 0; ii < ret; ii++) {
			    fputc(buffer[ii], stdout);
		     }
		     fputs("\n", stdout);
	      }
	      gnutls_bye(sd, state, 0);

	    end:

	      shutdown(sd, SHUT_RDWR);	/* no more receptions */
	      close(sd);

	      gnutls_deinit(state);

       }			/* for() */

       gnutls_free_x509_client_sc(xcred);

       gnutls_global_deinit();

       return 0;
}

Simple Client example with SRP Authentication

Although SRP is not part of the TLS standard, gnuTLS implements draft-ietf-tls-srp-01 which defines a way to use the SRP algorithm within the TLS handshake. The following client is a very simple SRP-TLS client which connects to a server by using username and password.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gnutls.h>

#define MAX_BUF 1024
#define USERNAME "user"
#define PASSWORD "password"
#define SA struct sockaddr
#define MSG "GET / HTTP/1.0\r\n\r\n"

int main()
{
       const char *PORT = "443";
       const char *SERVER = "127.0.0.1";
       int err, ret;
       int sd, ii;
       struct sockaddr_in sa;
       GNUTLS_STATE state;
       char buffer[MAX_BUF + 1];
       SRP_CLIENT_CREDENTIALS xcred;

       if (gnutls_global_init() < 0) {
	      fprintf(stderr, "global state initialization error\n");
	      exit(1);
       }

       if (gnutls_allocate_srp_client_sc( &xcred)<0) {
               fprintf(stderr, "memory error\n");
               exit(1);
       }
       gnutls_set_srp_client_cred( xcred, USERNAME, PASSWORD);

       /* connects to server 
        */
       sd = socket(AF_INET, SOCK_STREAM, 0);

       memset(&sa, '\0', sizeof(sa));
       sa.sin_family = AF_INET;
       sa.sin_port = htons(atoi(PORT));
       inet_pton(AF_INET, SERVER, &sa.sin_addr);

       err = connect(sd, (SA *) & sa, sizeof(sa));
       if (err < 0) {
	      fprintf(stderr, "Connect error\n");
	      exit(1);
       }
       /* Initialize TLS state 
        */
       gnutls_init(&state, GNUTLS_CLIENT);

       /* allow both SSL3 and TLS1
        */
       gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);

       /* allow only ARCFOUR and 3DES ciphers
        * (3DES has the highest priority)
        */
       gnutls_set_cipher_priority(state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);

       /* only allow null compression
        */
       gnutls_set_compression_priority(state, GNUTLS_NULL_COMPRESSION, 0);

       /* use GNUTLS_KX_RSA
        */
       gnutls_set_kx_priority(state, GNUTLS_KX_SRP, 0);

       /* allow the usage of both SHA and MD5
        */
       gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);


       /* put the SRP credentials to the current state
        */
       gnutls_set_cred(state, GNUTLS_SRP, xcred);


       /* Perform the TLS handshake
        */
       ret = gnutls_handshake(sd, state);

       if (ret < 0) {
	      fprintf(stderr, "*** Handshake failed\n");
	      gnutls_perror(ret);
	      goto end;
       } else {
	      printf("- Handshake was completed\n");
       }

       gnutls_write(sd, state, MSG, strlen(MSG));

       ret = gnutls_read(sd, state, buffer, MAX_BUF);
       if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
	      if (ret == 0) {
		     printf("- Peer has closed the GNUTLS connection\n");
		     goto end;
	      } else {
		     fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
			     ret);
		     goto end;
	      }
       } else {
	      if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
		     printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
	      if (ret == GNUTLS_E_GOT_HELLO_REQUEST)
		     printf("* Received HelloRequest message (server asked to rehandshake)\n");
       }

       if (ret > 0) {
	      printf("- Received %d bytes: ", ret);
	      for (ii = 0; ii < ret; ii++) {
		     fputc(buffer[ii], stdout);
	      }
	      fputs("\n", stdout);
       }
       gnutls_bye(sd, state, 0);

     end:

       shutdown(sd, SHUT_RDWR);	/* no more receptions */
       close(sd);

       gnutls_deinit(state);

       gnutls_free_srp_client_sc(xcred);

       gnutls_global_deinit();

       return 0;
}

Server Examples

This section contains examples of TLS and SSL servers, using gnuTLS.

Echo Server with X509 and SRP authentication

The following example is a server which supports both SRP and X509 authentication. This server also supports session resuming.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <gnutls.h>

#define KEYFILE "key.pem"
#define CERTFILE "cert.pem"
#define CAFILE "ca.pem"
#define CRLFILE NULL

#define SRP_PASSWD "tpasswd"
#define SRP_PASSWD_CONF "tpasswd.conf"


/* This is a sample TCP echo server.
 */


#define SA struct sockaddr
#define ERR(err,s) if(err==-1) {perror(s);return(1);}
#define MAX_BUF 1024
#define PORT 5556 /* listen to 5556 port */

/* These are global */
SRP_SERVER_CREDENTIALS srp_cred;
X509PKI_SERVER_CREDENTIALS x509_cred;

GNUTLS_STATE initialize_state()
{
       GNUTLS_STATE state;
       int ret;

       gnutls_init(&state, GNUTLS_SERVER);
	
       /* in order to support session resuming:
        */
       if ((ret = gnutls_set_db_name(state, "gnutls-rsm.db")) < 0)
	      fprintf(stderr, "*** DB error (%d)\n\n", ret);

       gnutls_set_cipher_priority(state, GNUTLS_RIJNDAEL_CBC, GNUTLS_3DES_CBC, 0);
       gnutls_set_compression_priority(state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0);
       gnutls_set_kx_priority(state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, 0);
       gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
       gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);

       gnutls_set_cred(state, GNUTLS_SRP, srp_cred);
       gnutls_set_cred(state, GNUTLS_X509PKI, x509_cred);


       return state;
}

void print_info(GNUTLS_STATE state)
{
       const SRP_SERVER_AUTH_INFO *srp_info;
       const char *tmp;
       unsigned char sesid[32];
       int sesid_size, i;

       /* print session_id specific data */
       gnutls_get_current_session_id(state, sesid, &sesid_size);
       printf("\n- Session ID: ");
       for (i = 0; i < sesid_size; i++)
	      printf("%.2X", sesid[i]);
       printf("\n");

       /* print srp specific data */
       if (gnutls_get_auth_info_type(state) == GNUTLS_SRP) {
	      srp_info = gnutls_get_auth_info(state);
	      if (srp_info != NULL)
		     printf("\n- User '%s' connected\n",
			    srp_info->username);
       }
       /* print state information */
       tmp = gnutls_version_get_name(gnutls_get_current_version(state));
       printf("- Version: %s\n", tmp);

       tmp = gnutls_kx_get_name(gnutls_get_current_kx(state));
       printf("- Key Exchange: %s\n", tmp);

       tmp =
	   gnutls_compression_get_name
	   (gnutls_get_current_compression_method(state));
       printf("- Compression: %s\n", tmp);

       tmp = gnutls_cipher_get_name(gnutls_get_current_cipher(state));
       printf("- Cipher: %s\n", tmp);

       tmp = gnutls_mac_get_name(gnutls_get_current_mac_algorithm(state));
       printf("- MAC: %s\n", tmp);

}



int main()
{
       int err, listen_sd, i;
       int sd, ret;
       struct sockaddr_in sa_serv;
       struct sockaddr_in sa_cli;
       int client_len;
       char topbuf[512];
       GNUTLS_STATE state;
       char buffer[MAX_BUF + 1];
       int optval = 1;
       int http = 0;
       char name[256];

       strcpy(name, "Echo Server");

       /* this must be called once in the program
        */
       if (gnutls_global_init() < 0) {
	      fprintf(stderr, "global state initialization error\n");
	      exit(1);
       }
       if (gnutls_allocate_x509_server_sc(&x509_cred, 1) < 0) {
	      fprintf(stderr, "memory error\n");
	      exit(1);
       }
       if (gnutls_set_x509_server_trust(x509_cred, CAFILE, CRLFILE) < 0) {
	      fprintf(stderr, "X509 PARSE ERROR\nDid you have ca.pem?\n");
	      exit(1);
       }
       if (gnutls_set_x509_server_key(x509_cred, CERTFILE, KEYFILE) < 0) {
	      fprintf(stderr, "X509 PARSE ERROR\nDid you have key.pem and cert.pem?\n");
	      exit(1);
       }
       /* SRP_PASSWD a password file (created with the included crypt utility) 
        * Read README.crypt prior to using SRP.
        */
       gnutls_allocate_srp_server_sc(&srp_cred);
       gnutls_set_srp_server_cred(srp_cred, SRP_PASSWD, SRP_PASSWD_CONF);


       /* Socket operations
        */
       listen_sd = socket(AF_INET, SOCK_STREAM, 0);
       ERR(listen_sd, "socket");

       memset(&sa_serv, '\0', sizeof(sa_serv));
       sa_serv.sin_family = AF_INET;
       sa_serv.sin_addr.s_addr = INADDR_ANY;
       sa_serv.sin_port = htons(PORT);	/* Server Port number */

       setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
       
       err = bind(listen_sd, (SA *) & sa_serv, sizeof(sa_serv));
       ERR(err, "bind");
       err = listen(listen_sd, 1024);
       ERR(err, "listen");

       printf("%s ready. Listening to port '%d'.\n\n", name, PORT);

       client_len = sizeof(sa_cli);
       for (;;) {
	      state = initialize_state();

	      sd = accept(listen_sd, (SA *) & sa_cli, &client_len);

	      printf("- connection from %s, port %d\n",
		     inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf,
			       sizeof(topbuf)), ntohs(sa_cli.sin_port));


	      ret = gnutls_handshake(sd, state);
	      if (ret < 0) {
		     close(sd);
		     gnutls_deinit(state);
		     fprintf(stderr, "*** Handshake has failed (%s)\n\n",
			     gnutls_strerror(ret));
		     continue;
	      }
	      printf("- Handshake was completed\n");

	      print_info(state);

	      i = 0;
	      for (;;) {
		     bzero(buffer, MAX_BUF + 1);
		     ret = gnutls_read(sd, state, buffer, MAX_BUF);

		     if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
			    if (ret == 0) {
				   printf
				       ("\n- Peer has closed the GNUTLS connection\n");
				   break;
			    } else {
				   fprintf(stderr,
					   "\n*** Received corrupted data(%d). Closing the connection.\n\n",
					   ret);
				   break;
			    }

		     }
		     if (ret > 0) {
			    /* echo data back to the client
			     */
			    gnutls_write(sd, state, buffer,
					 strlen(buffer));
		     }
		     if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
			    ret = gnutls_get_last_alert(state);
			    printf("* Received alert '%d'.\n", ret);
		     }
	      }
	      printf("\n");
	      gnutls_bye(sd, state, 1); /* do not wait for
	                                 * the peer to close the connection.
                                         */
                                         
	      close(sd);
	      gnutls_deinit(state);

       }
       close(listen_sd);

       gnutls_free_x509_server_sc(x509_cred);
       gnutls_free_srp_server_sc(srp_cred);

       gnutls_global_deinit();

       return 0;

}

Function Reference


gnutls_mac_get_name

const char * gnutls_mac_get_name ( MACAlgorithm algorithm )

Arguments

Description Returns an allocated (with malloc) string that contains the name of the specified MAC algorithm.


gnutls_compression_get_name

const char * gnutls_compression_get_name ( CompressionMethod algorithm )

Arguments

Description Returns a localy allocated (with malloc) pointer to a string that contains the name of the specified compression algorithm.


gnutls_cipher_get_name

const char * gnutls_cipher_get_name ( BulkCipherAlgorithm algorithm )

Arguments

Description Returns a localy allocated (with malloc) pointer to a string that contains the name of the specified cipher.


gnutls_kx_get_name

const char * gnutls_kx_get_name ( KXAlgorithm algorithm )

Arguments

Description Returns a localy allocated (with malloc) pointer to a string that contains the name of the specified key exchange algorithm.


gnutls_version_get_name

const char * gnutls_version_get_name ( GNUTLS_Version version )

Arguments

Description Returns an allocated (with malloc) string that contains the name of the specified TLS version.


gnutls_free_anon_server_sc

void gnutls_free_anon_server_sc ( ANON_SERVER_CREDENTIALS* sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to free (deallocate) the structure.


gnutls_allocate_anon_server_sc

int gnutls_allocate_anon_server_sc ( ANON_SERVER_CREDENTIALS ** sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to allocate the structure.


gnutls_set_anon_server_cred

int gnutls_set_anon_server_cred ( ANON_SERVER_CREDENTIALS* res , int dh_bits )

Arguments


gnutls_set_cred

int gnutls_set_cred ( GNUTLS_STATE state , CredType type , void* cred )

Arguments

Description Sets the needed credentials for the specified type. Eg username, password - or public and private keys etc. The (void* cred) parameter is a structure that depends on the specified type and on the current state (client or server). [ In order to minimize memory usage, and share credentials between several threads gnutls keeps a pointer to cred, and not the whole cred structure. Thus you will have to keep the structure allocated until you call gnutls_deinit(). ]

For In case of a server it should be &ANON_SERVER_CREDENTIALS.

For in case of a client, and &SRP_SERVER_CREDENTIALS, in case of a server.


gnutls_get_auth_info_type

CredType gnutls_get_auth_info_type ( GNUTLS_STATE state )

Arguments

Description Returns type of credentials for the current authentication schema. The returned information can be used to distinguish the appropriate structures for the gnutls_get_auth_info() function. Eg. if this function returns GNUTLS_X509PKI then the return type of gnutls_get_auth_info() will be X509PKI_(SERVER/CLIENT)_AUTH_INFO (depends on the side - client/server)


gnutls_get_auth_info

const void* gnutls_get_auth_info ( GNUTLS_STATE state )

Arguments

Description This function must be called after a succesful gnutls_handshake(). Returns a pointer to authentication information. That information is data obtained by the handshake protocol, the key exchange algorithm, and the TLS extensions messages.

In case of In case of In case of


gnutls_x509_set_cn

int gnutls_x509_set_cn ( GNUTLS_STATE state , const char* cn )

Arguments

Description This function is to be used by clients that want to verify also the peer's Common Name (ie. the certificate may be verified, but it may have been issued for someone else).


gnutls_check_pending

int gnutls_check_pending ( GNUTLS_STATE state )

Arguments

Description This function checks if there are any data to receive in the gnutls buffers. Returns the size of that data or 0. Notice that you may also use select() to check for data in the TCP connection, instead of this function. (gnutls leaves some data in the tcp buffer in order for select to work).


gnutls_free_x509_sc

void gnutls_free_x509_sc ( X509PKI_CREDENTIALS sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to free (deallocate) the structure.


gnutls_allocate_x509_sc

int gnutls_allocate_x509_sc ( X509PKI_CREDENTIALS* res , int ncerts )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to allocate the structure.


gnutls_set_x509_key

int gnutls_set_x509_key ( X509PKI_CREDENTIALS res , char* CERTFILE , char * KEYFILE )

Arguments

Description This function sets a certificate/private key pair in the X509PKI_CREDENTIALS structure. This function may be called more than once (in case multiple keys/certificates exist for the server)


gnutls_set_x509_trust

int gnutls_set_x509_trust ( X509PKI_CREDENTIALS res , char* CAFILE , char* CRLFILE )

Arguments

Description This function sets the trusted CAs in order to verify client certificates.


gnutls_set_cache_expiration

int gnutls_set_cache_expiration ( GNUTLS_STATE state , int seconds )

Arguments

Description Sets the expiration time for resumed sessions. The default is 3600 (one hour) at the time writing this.


gnutls_set_db_name

int gnutls_set_db_name ( GNUTLS_STATE state , char* filename )

Arguments

Description Sets the name of the (gdbm) database to be used to keep the sessions to be resumed. This function also creates the database - if it does not exist - and opens it for reading.


gnutls_clean_db

int gnutls_clean_db ( GNUTLS_STATE state )

Arguments

Description This function Deletes all expired records in the resumed sessions' database. This database may become huge if this function is not called. (this function is also quite expensive)


gnutls_is_fatal_error

int gnutls_is_fatal_error ( int error )

Arguments

Description If a function returns a negative value you may feed that value to this function to see if it is fatal. Returns 1 for a fatal error 0 otherwise. However you may want to check the error code manualy, since some non-fatal errors to the protocol may be fatal for you (your program).


gnutls_perror

void gnutls_perror ( int error )

Arguments

Description This function is like perror(). However it accepts an error returned by a gnutls function.


gnutls_strerror

const char* gnutls_strerror ( int error )

Arguments

Description This function is like strerror(). However it accepts an error returned by a gnutls function. gnutls_strerror() returns a malloc'ed value thus it should be free'd.


gnutls_ext_get_dnsname

const char* gnutls_ext_get_dnsname ( GNUTLS_STATE state )

Arguments

Description This function is to be used by servers that support virtual hosting. The client may give the server the dnsname they connected to. if no name was given this function returns NULL.


gnutls_ext_set_dnsname

int gnutls_ext_set_dnsname ( GNUTLS_STATE state , const char* dnsname )

Arguments

Description This function is to be used by clients that want to inform ( via a TLS extension mechanism) the server of the name they connected to. This should be used by clients that connect to servers that do virtual hosting.


gnutls_global_set_recv_func

void gnutls_global_set_recv_func ( RECV_FUNC recv_func )

Arguments

Description This is the function were you set the recv() function gnutls is going to use. Normaly you may not use this function since the default (recv(2)) will probably be ok, unless you use some external library (like gnu pthreads), which provide a front end to this function. This function should be called once and after gnutls_global_init().


gnutls_global_set_send_func

void gnutls_global_set_send_func ( SEND_FUNC send_func )

Arguments

Description This is the function were you set the send() function gnutls is going to use. Normaly you may not use this function since the default (send(2)) will probably be ok, unless you use some external library (like gnu pthreads), which provide a front end to this function. This function should be called once and after gnutls_global_init().


gnutls_global_set_log_func

void gnutls_global_set_log_func ( LOG_FUNC log_func )

Arguments

Description This is the function were you set the logging function gnutls is going to use. This function only accepts a character array. Normaly you may not use this function since it is only used for debugging reasons.


gnutls_global_init

int gnutls_global_init ( )

Arguments

Description

This function initializes the global state to defaults. Every gnutls application has a global state which holds common parameters shared by gnutls state structures. You must call gnutls_global_deinit() when gnutls usage is no longer needed Returns zero on success.


gnutls_global_deinit

void gnutls_global_deinit ( )

Arguments

Description

This function deinitializes the global state.


gnutls_rehandshake

int gnutls_rehandshake ( SOCKET cd , GNUTLS_STATE state )

Arguments

Description This function will renegotiate security parameters with the client. This should only be called in case of a server. If the client does not wish to renegotiate parameters he will reply with an alert message, thus the return code will be GNUTLS_E_WARNING_ALERT_RECEIVED and the alert will be GNUTLS_NO_RENEGOTIATION.


gnutls_handshake

int gnutls_handshake ( SOCKET cd , GNUTLS_STATE state )

Arguments

Description This function does the handshake of the TLS/SSL protocol, and initializes the TLS connection. Here the identity of the peer is checked automatically. This function will fail if any problem is encountered, and the connection should be terminated.


gnutls_set_cipher_priority

int gnutls_set_cipher_priority ( GNUTLS_STATE state , LIST )

Arguments

Description Sets the priority on the ciphers supported by gnutls. Priority is higher for ciphers specified before others. After specifying the ciphers you want, you should add 0. Note that the priority is set on the client. The server does not use the algorithm's priority except for disabling algorithms that were not specified.


gnutls_set_kx_priority

int gnutls_set_kx_priority ( GNUTLS_STATE state , LIST )

Arguments

Description Sets the priority on the key exchange algorithms supported by gnutls. Priority is higher for algorithms specified before others. After specifying the algorithms you want, you should add 0. Note that the priority is set on the client. The server does not use the algorithm's priority except for disabling algorithms that were not specified.


gnutls_set_mac_priority

int gnutls_set_mac_priority ( GNUTLS_STATE state , LIST )

Arguments

Description Sets the priority on the mac algorithms supported by gnutls. Priority is higher for algorithms specified before others. After specifying the algorithms you want, you should add 0. Note that the priority is set on the client. The server does not use the algorithm's priority except for disabling algorithms that were not specified.


gnutls_set_compression_priority

int gnutls_set_compression_priority ( GNUTLS_STATE state , LIST )

Arguments

Description Sets the priority on the compression algorithms supported by gnutls. Priority is higher for algorithms specified before others. After specifying the algorithms you want, you should add 0. Note that the priority is set on the client. The server does not use the algorithm's priority except for disabling algorithms that were not specified.


gnutls_set_protocol_priority

int gnutls_set_protocol_priority ( GNUTLS_STATE state , LIST )

Arguments

Description Sets the priority on the protocol versions supported by gnutls. Priority is higher for protocols specified before others. After specifying the protocols you want, you should add 0. Note that the priority is set on the client. The server does not use the protocols's priority except for disabling protocols that were not specified.


gnutls_set_lowat

int gnutls_set_lowat ( GNUTLS_STATE state , int num )

Arguments

Description Used to set the lowat value in order for select to check if there are pending data to socket buffer. Used only if you have changed the default low water value (default is 1). Normally you will not need that function.


gnutls_init

int gnutls_init ( GNUTLS_STATE * state , ConnectionEnd con_end )

Arguments

Description This function initializes the current state to null. Every state must be initialized before use, so internal structures can be allocated. This function allocates structures which can only be free'd by calling gnutls_deinit(). Returns zero on success.


gnutls_deinit

int gnutls_deinit ( GNUTLS_STATE state )

Arguments

Description This function clears all buffers associated with the &state.


gnutls_bye

int gnutls_bye ( SOCKET cd , GNUTLS_STATE state , int wait )

Arguments

Description Terminates the current TLS/SSL connection. If the return value is 0 you may continue using the TCP connection. The connection should have been initiated using gnutls_handshake() or similar function. If 'wait' is non-zero then we will not wait for the other peer to close the TLS connection.


gnutls_get_current_cipher

BulkCipherAlgorithm gnutls_get_current_cipher ( GNUTLS_STATE state )

Arguments

Description Returns the currently used cipher.


gnutls_get_current_kx

KXAlgorithm gnutls_get_current_kx ( GNUTLS_STATE state )

Arguments

Description Returns the key exchange algorithm used in the last handshake.


gnutls_get_current_mac_algorithm

MACAlgorithm gnutls_get_current_mac_algorithm ( GNUTLS_STATE state )

Arguments

Description Returns the currently used mac algorithm.


gnutls_get_current_compression_method

CompressionMethod gnutls_get_current_compression_method ( GNUTLS_STATE state )

Arguments

Description Returns the currently used compression method.


gnutls_get_last_alert

AlertDescription gnutls_get_last_alert ( GNUTLS_STATE state )

Arguments

Description Returns the last alert number received. This function should be called if The peer may send alerts if he thinks some things were not right. Check gnutls.h for the available alert descriptions.


gnutls_send

ssize_t gnutls_send ( SOCKET cd , GNUTLS_STATE state , const void * data , size_t sizeofdata , int flags )

Arguments

Description This function has the same semantics as send() has. The only difference is that is accepts a GNUTLS state. Currently flags cannot be anything except 0.


gnutls_recv

ssize_t gnutls_recv ( SOCKET cd , GNUTLS_STATE state , void * data , size_t sizeofdata , int flags )

Arguments

Description This function has the same semantics as recv() has. The only difference is that is accepts a GNUTLS state. Flags are the flags passed to recv() and should be used with care in gnutls. The only acceptable flag is currently MSG_DONTWAIT. In that case, if the socket is set to non blocking IO it will return GNUTLS_E_AGAIN, if there are no data in the socket. Returns the number of bytes received, zero on EOF, or a negative error code.


gnutls_write

ssize_t gnutls_write ( SOCKET cd , GNUTLS_STATE state , const void * data , size_t sizeofdata )

Arguments

Description This function has the same semantics as write() has. The only difference is that is accepts a GNUTLS state.


gnutls_read

ssize_t gnutls_read ( SOCKET cd , GNUTLS_STATE state , void * data , size_t sizeofdata )

Arguments

Description This function has the same semantics as read() has. The only difference is that is accepts a GNUTLS state. Returns the number of bytes received, zero on EOF, or a negative error code.


gnutls_get_current_session

int gnutls_get_current_session ( GNUTLS_STATE state , opaque* session , int * session_size )

Arguments

Description Returns all session parameters - in order to support resuming. The client should call this - and keep the returned session - if he wants to resume that current version later by calling gnutls_set_current_session() This function must be called after a successful handshake.

Resuming sessions is really useful and speedups connections after a succesful one.


gnutls_get_current_session_id

int gnutls_get_current_session_id ( GNUTLS_STATE state , void* session , int * session_size )

Arguments

Description Returns the current session id. This can be used if you want to check if the next session you tried to resume was actually resumed. (resumed sessions have the same sessionID with the first session)

Session id is some data set by the server, that identify the current session. In TLS 1.0 session id should not be more than 32 bytes.


gnutls_set_current_session

int gnutls_set_current_session ( GNUTLS_STATE state , opaque* session , int session_size )

Arguments

Description Sets all session parameters - in order to support resuming session must be the one returned by gnutls_get_current_session(); This function should be called before gnutls_handshake(). Keep in mind that session resuming is advisory. The server may choose not to resume the session, thus a full handshake will be performed.


gnutls_free_srp_client_sc

void gnutls_free_srp_client_sc ( SRP_CLIENT_CREDENTIALS* sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to free (deallocate) the structure.


gnutls_allocate_srp_client_sc

int gnutls_allocate_srp_client_sc ( SRP_CLIENT_CREDENTIALS ** sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to allocate the structure.


gnutls_set_srp_client_cred

int gnutls_set_srp_client_cred ( SRP_CLIENT_CREDENTIALS* res , char * username , char * password )

Arguments


gnutls_free_srp_server_sc

void gnutls_free_srp_server_sc ( SRP_SERVER_CREDENTIALS* sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to free (deallocate) the structure.


gnutls_allocate_srp_server_sc

int gnutls_allocate_srp_server_sc ( SRP_SERVER_CREDENTIALS ** sc )

Arguments

Description This structure is complex enough to manipulate directly thus this helper function is provided in order to allocate the structure.


gnutls_set_srp_server_cred

int gnutls_set_srp_server_cred ( SRP_SERVER_CREDENTIALS* res , char * password_file , char * password_conf_file )

Arguments

About this document ...

GNU Transport Layer Security Library

This document was generated using the LaTeX2HTML translator Version 2K.1beta (1.48)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html gnutls.tex -no_subdir 1 -split 0 -local_icons -prefix ./

The translation was initiated by Nikos Mavroyanopoulos on 2001-07-30


next_inactive up previous
Nikos Mavroyanopoulos 2001-07-30