[gnutls-help] gnutls_certificate_set_x509_trust_file and Cygwin

Alexander Ausserstorfer bavariasound at chiemgau-net.de
Sat Apr 20 08:03:51 CEST 2013


Zitat von Alexander Ausserstorfer <bavariasound at chiemgau-net.de>:

> Under Cygwin I set gnutls_certificate_set_x509_trust_file to
>
> #define CAFILE "/usr/ssl/certs/ca-bundle.trust.crt"
>
> gnutls_certificate_set_x509_trust_file (cert_cret, CAFILE,  
> GNUTLS_X509_FMT_PEM);
>
> ca-bundle.trust.crt was part of Cygwin. Now, the function  
> gnutls_certificate_set_x509_trust_file returns 0 and all later  
> verification of certificates fails. I suppose that the function  
> should return another number as 0. Is that mind right?

Yesterday the staff kicked me out the computer room, and today the  
wireless network access here doesn't work, so sorry for the  
circumstances.

The first question is if I use the right certificates. The file  
ca-bundle.trust.crt at cygwin/usr/ssl/certs/ sais:

############################################################################

This is a bundle of X.509 certificates of public Certificate  
Authorities. It was generated from the Mozilla root CA list. These  
certificates are in the OpenSSL "TRUSTED CERTIFICATE" format and have  
trust bits accordingly.

Source: mozilla/security/nss/lib/ckfw/builtins/certdata.txt

[...]

############################################################################

Then I use the function

gnutls_certificate_set_x509_trust_file (cert_cred, CAFILE,  
GNUTLS_X509_FMT_PEM)

to add the list but the function returns zero. It is the first time I  
try GnuTLS. It seems to me that the function does nothing. I work with  
Cygwin. May be Cygwin is the problem?

Here is all the code I wrote (I hope copy & paste work here correctly):

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

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> // AF_INET, SOCK_STREAM, connect()
#include <netdb.h>      // struct hostent
#include <netinet/in.h> // struct sockadd_in
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>

#define MAX_BUF 1024
#define MAXMSG 512
#define CAFILE "/usr/ssl/certs/ca-bundle.trust.crt"

struct hostent *hostinfo;
struct sockaddr_in name;

static int _verify_certificate_callback (gnutls_session_t session);

void IP_number(struct sockaddr_in *name, char *servername, uint16_t port)
{
  char serverIP[16];
  if(hostinfo=gethostbyname(servername))
  {
   // converting name in IP number
   inet_ntop(PF_INET,hostinfo->h_addr_list[0],serverIP,16);
   printf("IP: %s\n",serverIP);
   name->sin_family = PF_INET;
   name->sin_port = htons(port);
   name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
  }
   else
    {
      fprintf(stderr, "Unknown host %s.\n",servername);
      exit (EXIT_FAILURE);
    }
}

main()
{
  int ret, sd, ii;

  gnutls_session_t session;
  gnutls_srp_client_credentials_t srp_cred;
  gnutls_certificate_credentials_t cert_cred;

  char buffer2[MAX_BUF + 1];
  const char *err;

  // Required data
  char server[30];
  printf("Server: ");
  scanf("%s",server);

  char USER[30]="";
  printf("User: ");
  scanf("%s",USER);

  char *password;
  password=(char *)getpass("Password: ");

  char buffer[MAXMSG];
  uint16_t port=110;
  int sock=-1;
  size_t size;

  // converting server name in IP number
  IP_number(&name, server, port);

  // Creating socket for connection to this server
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == -1)
  {
   perror("socket");
   exit (EXIT_FAILURE);
  }

  // Making the connection
  if (connect(sock, (struct sockaddr *) &name, sizeof (struct  
sockaddr_in)) < 0)
  {
   perror ("connect");
   exit (EXIT_FAILURE);
  }

  // Reading
  int amount = read(sock, buffer, MAXMSG);
  printf("%.*s", amount, buffer);
  write(sock,"CAPA\r\n",6);
  amount = read(sock, buffer, MAXMSG);
  printf("%.*s", amount, buffer);
  write(sock,"STLS\r\n",6);
  amount = read(sock, buffer, MAXMSG);
  printf("%.*s", amount, buffer);

// Security connection

gnutls_global_init();

gnutls_srp_allocate_client_credentials (&srp_cred);
gnutls_certificate_allocate_credentials (&cert_cred);
printf("\nAnzahl der verarbeiteten Zertifikate:  
%d\n",gnutls_certificate_set_x509_trust_file (cert_cred, CAFILE,  
GNUTLS_X509_FMT_PEM));
gnutls_certificate_set_verify_function (cert_cred,  
_verify_certificate_callback);
gnutls_srp_set_client_credentials (srp_cred, USER, password);

gnutls_init (&session, GNUTLS_CLIENT);

gnutls_session_set_ptr (session, (void *) server);
gnutls_server_name_set (session, GNUTLS_NAME_DNS, server, strlen(server));

/* Use default priorities */
ret = gnutls_priority_set_direct (session,  
"NORMAL:+SRP:+SRP-RSA:+SRP-DSS", &err);
if (ret < 0)
   {
      if (ret == GNUTLS_E_INVALID_REQUEST)
	    {
		   fprintf (stderr, "Syntax error at: %s\n", err);
		}
	 exit(1);
   }

gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cert_cred);
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sock);

do
    {
      ret = gnutls_handshake (session);
    } while (ret < 00 && gnutls_error_is_fatal (ret) == 0);

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

gnutls_record_send(session, "USER ########\r\n",15);
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
  if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
  {
    if (ret == 0)
      {
	   printf ("- Peer has closed the GnuTLS connection\n");
	   goto end;
	 }
	else
	 {
	   fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
	   goto end;
	 }
  }

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

gnutls_record_send(session, "PASS ########\r\n",15);
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
  if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
  {
    if (ret == 0)
      {
	   printf ("- Peer has closed the GnuTLS connection\n");
	   goto end;
	 }
	else
	 {
	   fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
	   goto end;
	 }
  }

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

gnutls_record_send(session, "RETR 1\r\n",8);
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
  if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
  {
    if (ret == 0)
      {
	   printf ("- Peer has closed the GnuTLS connection\n");
	   goto end;
	 }
	else
	 {
	   fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
	   goto end;
	 }
  }

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


   gnutls_bye (session, GNUTLS_SHUT_RDWR);

end:

  // Closing socket
  close(sock);

  gnutls_deinit(session);

  gnutls_srp_free_client_credentials (srp_cred);
  gnutls_certificate_free_credentials (cert_cred);

  gnutls_global_deinit();

  printf("Ready\n");

}

static int _verify_certificate_callback (gnutls_session_t session)
{
     unsigned int status;
	const gnutls_datum_t *cert_list;
	unsigned int cert_list_size;
	int ret;
	gnutls_x509_crt_t cert;
	const char *hostname;

	/* read hostname */
	hostname = gnutls_session_get_ptr (session);

	/* This varification function uses the trusted CAs in the credentials
	 * structure. So you must have installed one or more CA certificates.
	*/

	ret = gnutls_certificate_verify_peers2 (session, &status);
	if (ret < 0)
	  {
	    printf ("Error\n");
		return GNUTLS_E_CERTIFICATE_ERROR;
       }

	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
	  printf ("The certificate hasn't got a known issuer\n");

	if (status & GNUTLS_CERT_REVOKED)
	  printf ("The certificate has been revoked\n");

	if (status & GNUTLS_CERT_EXPIRED)
       printf ("The certificate has expired\n");

     if (status & GNUTLS_CERT_NOT_ACTIVATED)
       printf ("The certificate is not yet activated\n");

     if (status & GNUTLS_CERT_INVALID)
       {
         printf ("The certificate is not trusted\n");
         return GNUTLS_E_CERTIFICATE_ERROR;
       }

     /* Up to here the process is the same for X.509 certificates and
      * OpenPGP keys. From now on X.509 certificates are assumed. This can
      * be easily extended to work with openpgp keys as well.
     */

     if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
       return GNUTLS_E_CERTIFICATE_ERROR;

     if (gnutls_x509_crt_init (&cert) < 0 )
       {
        printf ("error in initialization\n");
        return GNUTLS_E_CERTIFICATE_ERROR;
       }

     cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
     if (cert_list == NULL)
       {
         printf ("No certificate was found!\n");
         return GNUTLS_E_CERTIFICATE_ERROR;
       }

     if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
        {
          printf ("error parsing certificate\n");
          return GNUTLS_E_CERTIFICATE_ERROR;
        }

      if (!gnutls_x509_crt_check_hostname (cert, hostname))
        {
          printf ("The certificate's owner does not match hostname  
'%s'\n", hostname);
		 return GNUTLS_E_CERTIFICATE_ERROR;
	   }

	gnutls_x509_crt_deinit (cert);

	/* notify gnutls to continue handshake normally */
     return 0;
}

Some sensible data were replaced by ########. Thanks for any help / hints.

Alex'


-- 
http://home.chiemgau-net.de/ausserstorfer/


----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.




More information about the Gnutls-help mailing list