[PATCH] GnuTLS 3 support

b.brachaczek at gmail.com b.brachaczek at gmail.com
Wed Sep 26 17:21:25 EDT 2012


Hello,

I prepared a patch which makes neon from trunk compile and not regress in the 
test suite when compiled with gnutls-3 as the ssl backend. (Actually there are 
3 tests that fail with gnutls-2.12.18 and 2.12.20 while they pass with 
gnutls-3.0.23 and 3.1.1). I'm attaching it.

Bartosz Brachaczek
-------------- next part --------------
Index: macros/neon.m4
===================================================================
--- macros/neon.m4	(revision 1895)
+++ macros/neon.m4	(working copy)
@@ -989,12 +989,13 @@
    # Check for functions in later releases
    NE_CHECK_FUNCS([gnutls_session_get_data2 gnutls_x509_dn_get_rdn_ava \
                   gnutls_sign_callback_set \
+                  gnutls_certificate_get_issuer \
                   gnutls_certificate_get_x509_cas \
-                  gnutls_certificate_verify_peers2])
+                  gnutls_x509_crt_sign2])
 
-   # fail if gnutls_certificate_verify_peers2 is not found
-   if test x${ac_cv_func_gnutls_certificate_verify_peers2} != xyes; then
-       AC_MSG_ERROR([GnuTLS version predates gnutls_certificate_verify_peers2, newer version required])
+   # fail if gnutls_x509_crt_sign2 is not found (it was introduced in 1.2.0, which is required)
+   if test x${ac_cv_func_gnutls_x509_crt_sign2} != xyes; then
+       AC_MSG_ERROR([GnuTLS version predates gnutls_x509_crt_sign2, newer version required (at least 1.2.0)])
    fi
                   
    # Check for iconv support if using the new RDN access functions:
Index: src/ne_gnutls.c
===================================================================
--- src/ne_gnutls.c	(revision 1895)
+++ src/ne_gnutls.c	(working copy)
@@ -83,7 +83,7 @@
 };
 
 struct ne_ssl_client_cert_s {
-    gnutls_pkcs12 p12;
+    gnutls_pkcs12_t p12;
     int decrypted; /* non-zero if successfully decrypted. */
     int keyless;
     ne_ssl_certificate cert;
@@ -697,7 +697,7 @@
     ne_free(ctx);
 }
 
-#ifdef HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS
+#if !defined(HAVE_GNUTLS_CERTIFICATE_GET_ISSUER) && defined(HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS)
 /* Return the issuer of the given certificate, or NULL if none can be
  * found. */
 static gnutls_x509_crt find_issuer(gnutls_x509_crt *ca_list,
@@ -752,20 +752,29 @@
         }
     }
 
-#ifdef HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS
+#if defined(HAVE_GNUTLS_CERTIFICATE_GET_ISSUER) || defined(HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS)
     /* GnuTLS only returns the peers which were *sent* by the server
      * in the Certificate list during the handshake.  Fill in the
      * complete chain manually against the certs we trust: */
     if (current->issuer == NULL) {
         gnutls_x509_crt issuer;
+
+#ifndef HAVE_GNUTLS_CERTIFICATE_GET_ISSUER
         gnutls_x509_crt *ca_list;
         unsigned int num_cas;
         
         gnutls_certificate_get_x509_cas(crd, &ca_list, &num_cas);
+#endif
 
         do { 
             /* Look up the issuer. */
+#ifndef HAVE_GNUTLS_CERTIFICATE_GET_ISSUER
             issuer = find_issuer(ca_list, num_cas, current->subject);
+#else
+            if (gnutls_certificate_get_issuer(crd, current->subject, &issuer, 0))
+                issuer = NULL;
+#endif
+
             if (issuer) {
                 issuer = x509_crt_copy(issuer);
                 cert = populate_cert(ne_calloc(sizeof *cert), issuer);
@@ -1037,11 +1046,11 @@
 /* Parses a PKCS#12 structure and loads the certificate, private key
  * and friendly name if possible.  Returns zero on success, non-zero
  * on error. */
-static int pkcs12_parse(gnutls_pkcs12 p12, gnutls_x509_privkey *pkey,
+static int pkcs12_parse(gnutls_pkcs12_t p12, gnutls_x509_privkey *pkey,
                         gnutls_x509_crt *x5, char **friendly_name,
                         const char *password)
 {
-    gnutls_pkcs12_bag bag = NULL;
+    gnutls_pkcs12_bag_t bag = NULL;
     int i, j, ret = 0;
 
     for (i = 0; ret == 0; ++i) {
@@ -1056,7 +1065,7 @@
         gnutls_pkcs12_bag_decrypt(bag, password);
 
         for (j = 0; ret == 0 && j < gnutls_pkcs12_bag_get_count(bag); ++j) {
-            gnutls_pkcs12_bag_type type;
+            gnutls_pkcs12_bag_type_t type;
             gnutls_datum data;
 
             if (friendly_name && *friendly_name == NULL) {
@@ -1141,7 +1150,7 @@
 {
     int ret;
     gnutls_datum data;
-    gnutls_pkcs12 p12;
+    gnutls_pkcs12_t p12;
     ne_ssl_client_cert *cc;
     char *friendly_name = NULL;
     gnutls_x509_crt cert = NULL;
Index: src/ne_socket.c
===================================================================
--- src/ne_socket.c	(revision 1895)
+++ src/ne_socket.c	(working copy)
@@ -724,9 +724,11 @@
                     _("SSL alert received: %s"),
                     gnutls_alert_get_name(gnutls_alert_get(sock->ssl)));
         break;
+#if GNUTLS_VERSION_MAJOR > 2 || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR >= 99)
+    case GNUTLS_E_PREMATURE_TERMINATION:
+#else
     case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
-        /* It's not exactly an API guarantee but this error will
-         * always mean a premature EOF. */
+#endif
         ret = NE_SOCK_TRUNC;
         set_error(sock, _("Secure connection truncated"));
         break;
@@ -1705,6 +1707,8 @@
         NE_DEBUG(NE_DBG_SSL, "ssl: Server reused session.\n");
     }
 #elif defined(HAVE_GNUTLS)
+    unsigned int verify_status;
+
     gnutls_init(&ssl, GNUTLS_SERVER);
     gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, ctx->cred);
     gnutls_set_default_priority(ssl);
@@ -1724,7 +1728,7 @@
     if (ret < 0) {
         return error_gnutls(sock, ret);
     }
-    if (ctx->verify && gnutls_certificate_verify_peers(ssl)) {
+    if (ctx->verify && (gnutls_certificate_verify_peers2(ssl, &verify_status) || verify_status)) {
         set_error(sock, _("Client certificate verification failed"));
         return NE_SOCK_ERROR;
     }


More information about the neon mailing list