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