help-gnutls
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-gnutls] gnutls_record_send() problem


From: Laurent Birtz
Subject: [Help-gnutls] gnutls_record_send() problem
Date: Mon, 21 Jan 2008 16:02:12 -0500
User-agent: Mozilla-Thunderbird 2.0.0.4 (X11/20070622)

I've encountered a weird problem with the stock code examples (anonymous
server and client). By itself the example works fine, but if I replace
the string sent ("GET / HTTP/1.0\r\n\r\n") by a zeroed buffer, then the
client hangs. This does not occur if I send a buffer containing bytes
with the value 1.

The sample code is shown below. I am using GnuTLS 2.2.1-1, kernel
2.6.22-3-686, Debian unstable, Debian package libgnutls26. Can someone
tell me what is going on?


***** Makefile *****
all:
   gcc -Wall -g ex-serv-anon.c -o serv /usr/lib/libgnutls-openssl.so.26.1.2
gcc -Wall -g ex-client1.c tcp.c -o client /usr/lib/libgnutls-openssl.so.26.1.2



***** tcp.c *****:

#if HAVE_CONFIG_H
# include <config.h>
#endif

#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>

#define SA struct sockaddr

/* Connects to the peer and returns a socket
* descriptor.
*/
extern int
tcp_connect (void)
{
 const char *PORT = "5556";
 const char *SERVER = "127.0.0.1";
 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);
}

***** ex-client1.c *****:

#if HAVE_CONFIG_H
# include <config.h>
#endif

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

/* A very basic TLS client, with anonymous authentication.
*/

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

extern int tcp_connect (void);
extern void tcp_close (int sd);

int
main (void)
{
 int ret, sd, ii;
 gnutls_session_t session;
 char buffer[MAX_BUF + 1];
 gnutls_anon_client_credentials_t anoncred;
 /* Need to enable anonymous KX specifically. */
 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };

 gnutls_global_init ();

 gnutls_anon_allocate_client_credentials (&anoncred);

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

 /* Use default priorities */
 gnutls_set_default_priority (session);
 gnutls_kx_set_priority (session, kx_prio);

 /* put the anonymous credentials to the current session
  */
 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);

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

/* CHANGE HERE */
 #if 1
 char s[100]; memset(s, 0, 100);
 gnutls_record_send (session, s, 100);
 #else
 gnutls_record_send (session, MSG, strlen (MSG));
 #endif
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_anon_free_client_credentials (anoncred);

 gnutls_global_deinit ();

 return 0;
}


***** ex-serv-anon.c: *****

#if HAVE_CONFIG_H
# include <config.h>
#endif

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

/* This is a sample TLS 1.0 echo server, for anonymous authentication only.
*/


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

/* These are global */
gnutls_anon_server_credentials_t anoncred;

gnutls_session_t
initialize_tls_session (void)
{
 gnutls_session_t session;
 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };

 gnutls_init (&session, GNUTLS_SERVER);

 /* avoid calling all the priority functions, since the defaults
  * are adequate.
  */
 gnutls_set_default_priority (session);
 gnutls_kx_set_priority (session, kx_prio);

 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);

 gnutls_dh_set_prime_bits (session, DH_BITS);

 return session;
}

static gnutls_dh_params_t dh_params;

static int
generate_dh_params (void)
{

 /* Generate Diffie Hellman parameters - for use with DHE
  * kx algorithms. These should be discarded and regenerated
  * once a day, once a week or once a month. Depending on the
  * security requirements.
  */
 gnutls_dh_params_init (&dh_params);
 gnutls_dh_params_generate2 (dh_params, DH_BITS);

 return 0;
}

int
main (void)
{
 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_session_t session;
 char buffer[MAX_BUF + 1];
 int optval = 1;

 /* this must be called once in the program
  */
 gnutls_global_init ();

 gnutls_anon_allocate_server_credentials (&anoncred);

 generate_dh_params ();

 gnutls_anon_set_server_dh_params (anoncred, dh_params);

 /* Socket operations
  */
 listen_sd = socket (AF_INET, SOCK_STREAM, 0);
 SOCKET_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));
 SOCKET_ERR (err, "bind");
 err = listen (listen_sd, 1024);
 SOCKET_ERR (err, "listen");

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

 client_len = sizeof (sa_cli);
 for (;;)
   {
     session = initialize_tls_session ();

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

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

     /* see the Getting peer's information example */
     /* print_info(session); */

     i = 0;
     for (;;)
   {
     memset (buffer, 0, MAX_BUF + 1);
     ret = gnutls_record_recv (session, buffer, MAX_BUF);

     if (ret == 0)
       {
         printf ("\n- Peer has closed the GNUTLS connection\n");
         break;
       }
     else if (ret < 0)
       {
         fprintf (stderr, "\n*** Received corrupted "
              "data(%d). Closing the connection.\n\n", ret);
         break;
       }
     else if (ret > 0)
       {
         /* echo data back to the client
          */
         gnutls_record_send (session, buffer, strlen (buffer));
       }
   }
     printf ("\n");
     /* do not wait for the peer to close the connection.
      */
     gnutls_bye (session, GNUTLS_SHUT_WR);

     close (sd);
     gnutls_deinit (session);

   }
 close (listen_sd);

 gnutls_anon_free_server_credentials (anoncred);

 gnutls_global_deinit ();

 return 0;

}


The 'ldd' dump of the server binary is:
> ldd serv
linux-gate.so.1 =>  (0xffffe000)
libgnutls-openssl.so.26 => /usr/lib/libgnutls-openssl.so.26 (0xb7f22000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7dd5000)
libgnutls.so.26 => /usr/lib/libgnutls.so.26 (0xb7d5b000)
libtasn1.so.3 => /usr/lib/libtasn1.so.3 (0xb7d4b000)
libgcrypt.so.11 => /usr/lib/libgcrypt.so.11 (0xb7ce3000)
libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0xb7cdf000)
/lib/ld-linux.so.2 (0xb7f45000)


Thanks,
Laurent Birtz





reply via email to

[Prev in Thread] Current Thread [Next in Thread]