help-gnutls
[Top][All Lists]
Advanced

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

[Help-gnutls] Equivalent to fdopen?


From: Brian Lavender
Subject: [Help-gnutls] Equivalent to fdopen?
Date: Sun, 3 Aug 2008 14:11:52 -0700
User-agent: Mutt/1.5.13 (2006-08-11)

I am trying to take a simple socket program and convert it to use
gnutls. Is there an equivalent to fdopen so I can stream my secured
socket as an fstream?

int sock_fd;
FILE *sock_fpi;

sock_fd = accept( sock_id, (struct sockaddr *) &sa_cli, &client_len );

sock_fpi = fdopen( sock_fd, "r" ))

But when I attempt to convert it to use gnutls, I run into the
following.

sock_fd = accept( sock_id, (struct sockaddr *) &sa_cli, &client_len );

session = initialize_tls_session ();

gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sock_fd );

ret = gnutls_handshake (session);

And, it appears that I can only read using the following command.

ret = gnutls_record_recv (session, buffer, MAX_BUF);

Any sugguestions? Is there an fdopen equivalent, so I can still use the
fgets and friends? Or, do I have to write my own buffering routine?

brian


#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <string.h>
#include <gnutls/gnutls.h>
#include <gcrypt.h> /* for gcry_control */

#define PORTNUM 15000
#define HOSTLEN 256
#define DH_BITS 2048
#define oops(msg) { perror(msg); exit(1); }

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

/* These are global */
gnutls_certificate_credentials_t x509_cred;
gnutls_priority_t priority_cache;

gnutls_session_t
initialize_tls_session (void)
{
  gnutls_session_t session;

  gnutls_init (&session, GNUTLS_SERVER);

  gnutls_priority_set (session, priority_cache);

  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);

  /* request client certificate if any.
   */
  gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
  
  /* Set maximum compatibility mode. This is only suggested on public webservers
   * that need to trade security for compatibility
   */
  gnutls_session_enable_compatibility_mode( session);

  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. When short bit length is used, it might
   * be wise to regenerate parameters.
   *
   * Check the ex-serv-export.c example for using static
   * parameters.
   */
  gnutls_dh_params_init (&dh_params);
  gnutls_dh_params_generate2 (dh_params, DH_BITS);

  return 0;
}


int main(int ac, char *av[] )
{
  int ret; // return value
        struct sockaddr_in saddr;
        struct sockaddr_in sa_cli;
        int client_len;
        struct hostent *hp;
        char hostname[HOSTLEN];
        int sock_id, sock_fd;
        FILE *sock_fpi, *sock_fpo;
        FILE *pipe_fp;
        char topbuf[512];
        char dirname[BUFSIZ];
        char command[BUFSIZ];
        int dirlen, c;
        gnutls_session_t session;


        /* to disallow usage of the blocking /dev/random 
         */
        /*      gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);*/
        
        /* this must be called once in the program
         */
        gnutls_global_init ();

        gnutls_certificate_allocate_credentials (&x509_cred);
        gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE,
                                                GNUTLS_X509_FMT_PEM);

        gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE,
                                              GNUTLS_X509_FMT_PEM);

        gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE,
                                              GNUTLS_X509_FMT_PEM);

        generate_dh_params ();

        gnutls_priority_init( &priority_cache, "NORMAL", NULL);


        gnutls_certificate_set_dh_params (x509_cred, dh_params);



        
        /* step 1 */
        
        sock_id = socket( PF_INET, SOCK_STREAM, 0 );
        if ( sock_id == -1 )
                oops("socket");

        /* step 2 */

        bzero( (void *)&saddr, sizeof(saddr) );
        gethostname( hostname, HOSTLEN );
        hp = gethostbyname( hostname );

//      bcopy( (void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);

        saddr.sin_addr.s_addr = INADDR_ANY;
        
        saddr.sin_port = htons(PORTNUM);
        saddr.sin_family = AF_INET;
        
        if( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 )
                oops( "bind" );



        /* step 3 */

        if ( listen(sock_id, 1) != 0 )
                oops("listen");

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

        /* main loop: accept, write, close */

        client_len = sizeof (sa_cli);

        while(1) 
        {
                session = initialize_tls_session ();

                sock_fd = accept( sock_id, (struct sockaddr *) &sa_cli, 
&client_len );
                if ( sock_fd == -1 )
                        oops("accept");

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

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

                /* STOP here. PARE aca. :) Now we have a tls_session that 
                   we read from. It's not
                   a file descriptor anymore. Can't use fdopen on session :( */
                

                /* open reading direction as buffered stream */
                if ( ( sock_fpi = fdopen( sock_fd, "r" )) == NULL )
                        oops("fdopen reading ");

                if ( fgets( dirname, BUFSIZ - 5, sock_fpi) == NULL )
                        oops("reading dirname");
                sanitize(dirname);

                /* open writing direction as buffered stream */
                if ( (sock_fpo = fdopen(sock_fd,"w")) == NULL )
                        oops("fdopen writing");

                sprintf( command, "ls %s", dirname);

                if ( (pipe_fp = popen(command, "r")) == NULL)
                        oops("popen");

                /* transfer data from ls to socket */

                while ( ( c = getc(pipe_fp)) != EOF )
                        putc( c , sock_fpo );

                pclose(pipe_fp);
                fclose(sock_fpo);
                fclose(sock_fpi);

        }

        return 0;
}

sanitize( char *str )
{
        char *src, *dest;
        
        for( src = dest = str; *src; src++ )
                if ( *src == '/' || isalnum(*src) )
                        *dest++ = *src;

        *dest = '\0';
}
                
-- 
Brian Lavender
http://www.brie.com/brian/




reply via email to

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