summaryrefslogtreecommitdiff
blob: 77fe9320228df41797901f0f26262246ad232e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
From d7516e56dc854308349419b81904e9a61751cde4 Mon Sep 17 00:00:00 2001
From: Alexander V Vershilov <alexander.vershilov@gmail.com>
Date: Thu, 1 Nov 2012 11:44:10 +0400
Subject: [PATCH 1/2] neon gnutls-3 fixes

---
 macros/neon.m4  |  9 ++++++++-
 src/ne_gnutls.c | 13 +++++++++++--
 src/ne_socket.c | 10 +++++++---
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/macros/neon.m4 b/macros/neon.m4
index 32111c7..40f1d71 100644
--- a/macros/neon.m4
+++ b/macros/neon.m4
@@ -982,13 +982,20 @@ gnutls)
    # 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_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])
    fi
+
+   # 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:
    if test ${ac_cv_func_gnutls_x509_dn_get_rdn_ava}X${ac_cv_header_iconv_h} = yesXyes; then
diff --git a/src/ne_gnutls.c b/src/ne_gnutls.c
index eec5655..d50c6ce 100644
--- a/src/ne_gnutls.c
+++ b/src/ne_gnutls.c
@@ -692,7 +692,7 @@ void ne_ssl_context_destroy(ne_ssl_context *ctx)
     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,
@@ -747,20 +747,29 @@ static ne_ssl_certificate *make_peers_chain(gnutls_session sock,
         }
     }
 
-#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);
diff --git a/src/ne_socket.c b/src/ne_socket.c
index 12cf020..faee20c 100644
--- a/src/ne_socket.c
+++ b/src/ne_socket.c
@@ -721,9 +721,11 @@ static ssize_t error_gnutls(ne_socket *sock, ssize_t sret)
                     _("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;
@@ -1678,6 +1680,8 @@ int ne_sock_accept_ssl(ne_socket *sock, ne_ssl_context *ctx)
         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);
@@ -1697,7 +1701,7 @@ int ne_sock_accept_ssl(ne_socket *sock, ne_ssl_context *ctx)
     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;
     }
-- 
1.7.12.3