seg fault in crypto.h code

Simon Josefsson simon at josefsson.org
Thu Apr 24 14:30:21 CEST 2008


Hi Nikos,

I tried to replace the internal rng using the new interfaces, but
couldn't get it to work.  This self-contained example trigger a
segmentation fault.  Could you look into this?

I noticed that the code uses global variables for the hooks:

static cipher_list glob_cl = { GNUTLS_CIPHER_NULL, 0, NULL, NULL };
static mac_list glob_ml = { GNUTLS_MAC_NULL, 0, NULL, NULL };
static digest_list glob_dl = { GNUTLS_MAC_NULL, 0, NULL, NULL };
static rnd_list glob_rnd = { 0, 0, NULL, NULL };

Is all code related to this thread safe?  I would think that if you use
global variables, you must call thread mutex hooks to avoid problems.

/Simon

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

/* A very basic TLS client, with X.509 authentication.
 */

#define MAX_BUF 1024
#define CAFILE \
  "/etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority.pem"

#define MSG1 "GET / HTTP/1.1 \r\n Accept:*/* \r\n Host: mail.google.com \r\n Connection: Keep-Alive\r\n\r\n"

#define SA struct sockaddr

/* Connects to the peer and returns a socket
 * descriptor.
 */
extern int
tcp_connect (void)
{
  const char *PORT = "443";
  const char *SERVER = "66.249.91.19";
  int err, sd;
  struct sockaddr_in sa;

  /* 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);
    }

  return sd;
}

/* closes the given socket descriptor.
 */
extern void
tcp_close (int sd)
{
  shutdown (sd, SHUT_RDWR);	/* no more receptions */
  close (sd);
}

void mylogfn( int level, const char*ptr)
{
	printf ("Got Logs: ");
	if (ptr)
		printf ("%s", ptr);
}

int rng_init( void** ctx)
{
  return 0;
}

int rng_rnd ( void* ctx, int level, void* data, int datasize)
{
  return 0;
}

void rng_deinit( void* ctx)
{
}

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_crypto_rnd_st rng = { rng_init, rng_rnd, rng_deinit };

  gnutls_global_init ();

  ret = gnutls_crypto_rnd_register (0, &rng);
  printf ("ret %d\n", ret);

  /* X509 stuff */
  gnutls_certificate_allocate_credentials (&xcred);

  /* Initialize TLS session 
   */
  gnutls_init (&session, GNUTLS_CLIENT);

  /* 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;
    }

  gnutls_record_send (session, MSG1, strlen (MSG1));

  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;
    }

  /*  for (ii = 0; ii < ret; ii++)
    {
       fputc (buffer[ii], stdout); 
       } */
  fputs ("Finished\n", stdout);

  gnutls_bye (session, GNUTLS_SHUT_RDWR);

end:

  tcp_close (sd);

  gnutls_deinit (session);
  gnutls_global_deinit ();
  return 0;
}





More information about the Gnutls-devel mailing list