Update gnutls code (require at least 2.2.0).
authorGabriel VLASIU <gabriel@vlasiu.net>
Mon, 8 Apr 2013 12:55:25 +0000 (8 15:55 +0300)
committerCarlos R. Mafra <crmafra@gmail.com>
Mon, 8 Apr 2013 17:03:34 +0000 (8 18:03 +0100)
wmbiff/configure.ac
wmbiff/wmbiff/Imap4Client.c
wmbiff/wmbiff/Pop3Client.c
wmbiff/wmbiff/gnutls-common.c
wmbiff/wmbiff/test_tlscomm.c
wmbiff/wmbiff/test_wmbiff.c
wmbiff/wmbiff/tlsComm.c
wmbiff/wmbiff/wmbiff.c
wmbiff/wmbiff/wmbiffrc.5.in

index b8960ce..941e704 100644 (file)
@@ -77,7 +77,7 @@ AC_ARG_ENABLE(crypto, AC_HELP_STRING([ --disable-crypto ], [ disable gnutls/gcry
 
 GNUTLS_MAN_STATUS="This copy of WMBiff was not compiled with GNUTLS."
 if test "$gnutls" = "ok"; then
- PKG_CHECK_MODULES([LIBGNUTLS], [gnutls > 1.0.4], [LIBS="$LIBS $LIBGNUTLS_LIBS"
+ PKG_CHECK_MODULES([LIBGNUTLS], [gnutls > 2.2.0], [LIBS="$LIBS $LIBGNUTLS_LIBS"
                           CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
                          CPPFLAGS="$CPPFLAGS $LIBGNUTLS_CFLAGS"
                          GNUTLS_COMMON_O="gnutls-common.o"
index be5d972..c4115e7 100644 (file)
@@ -507,16 +507,7 @@ int imap4Create( /*@notnull@ */ Pop3 pc, const char *const str)
        /* If 'str' line is badly formatted, wmbiff won't display the mailbox. */
        if (strncmp("sslimap:", str, 8) == 0 || strncmp("imaps:", str, 6) == 0) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
-               static int haveBeenWarned;
                PCU.dossl = 1;
-               if (!haveBeenWarned) {
-                       printf("wmbiff uses gnutls for TLS/SSL encryption support:\n"
-                                  "  If you distribute software that uses gnutls, don't forget\n"
-                                  "  to warn the users of your software that gnutls is at a\n"
-                                  "  testing phase and may be totally insecure.\n"
-                                  "\nConsider yourself warned.\n");
-                       haveBeenWarned = 1;
-               }
 #else
                printf("This copy of wmbiff was not compiled with gnutls;\n"
                           "imaps is unavailable.  Exiting to protect your\n"
index 0f642cb..6792c42 100644 (file)
@@ -233,16 +233,7 @@ int pop3Create(Pop3 pc, const char *str)
 
        if (strncmp("pop3s:", str, 6) == 0) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
-               static int haveBeenWarned;
                PCU.dossl = 1;
-               if (!haveBeenWarned) {
-                       printf("wmbiff uses gnutls for TLS/SSL encryption support:\n"
-                                  "  If you distribute software that uses gnutls, don't forget\n"
-                                  "  to warn the users of your software that gnutls is at a\n"
-                                  "  testing phase and may be totally insecure.\n"
-                                  "\nConsider yourself warned.\n");
-                       haveBeenWarned = 1;
-               }
 #else
                printf("This copy of wmbiff was not compiled with gnutls;\n"
                           "imaps is unavailable.  Exiting to protect your\n"
index db6bd17..5f2bf76 100644 (file)
@@ -336,17 +336,20 @@ void print_openpgp_info(gnutls_session session, const char* hostname)
 void print_cert_vrfy(gnutls_session session)
 {
 
-       int status;
-       status = gnutls_certificate_verify_peers(session);
+       unsigned int status;
+       int ret;
+
+       ret = gnutls_certificate_verify_peers2(session, &status);
+
        printf("\n");
 
-       if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) {
-               printf("- Peer did not send any certificate.\n");
-               return;
-       }
-       if (status < 0) {
-               printf("- Could not verify certificate (err: %s)\n",
-                      gnutls_strerror(status));
+       if(ret < 0)
+       {
+               if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
+                       printf("- Peer did not send any certificate.\n");
+               else
+                       printf("- Could not verify certificate (err: %s (%d))\n",
+                               gnutls_strerror(ret), ret);
                return;
        }
 
index 2c15652..5b89530 100644 (file)
@@ -9,6 +9,8 @@
 int debug_default = 2;
 int SkipCertificateCheck = 0;
 const char *certificate_filename = NULL;
+const char *tls = "NORMAL";
+
 int exists(const char *filename __attribute__ ((unused)))
 {
        return (0);
index 950cbb6..5add324 100644 (file)
@@ -398,6 +398,7 @@ int print_info(UNUSED(void *state))
        return (0);
 }
 const char *certificate_filename = NULL;
+const char *tls = "NORMAL";
 int SkipCertificateCheck = 0;
 int exists(UNUSED(const char *filename))
 {
index 05e6dd8..90fbc68 100644 (file)
@@ -38,6 +38,9 @@ extern const char *certificate_filename;
 /* if set, don't fail when dealing with a bad certificate.
    (continue to whine, though, as bad certs should be fixed) */
 extern int SkipCertificateCheck;
+/* gnutls: specify the priorities to use on the ciphers, key exchange methods,
+   macs and compression methods. */
+extern const char *tls;
 
 /* WARNING: implcitly uses scs to gain access to the mailbox
    that holds the per-mailbox debug flag. */
@@ -342,6 +345,16 @@ bad_certificate(const struct connection_state *scs, const char *msg)
        }
 }
 
+static void
+warn_certificate(const struct connection_state *scs, const char *msg)
+{
+       if (!SkipCertificateCheck) {
+               TDM(DEBUG_ERROR, "%s", msg);
+               TDM(DEBUG_ERROR, "to ignore this warning, run wmbiff "
+                       "with the -skip-certificate-check option\n");
+       }
+}
+
 /* a start of a hack at verifying certificates.  does not
    provide any security at all.  I'm waiting for either
    gnutls to make this as easy as it should be, or someone
@@ -412,7 +425,8 @@ static void
 tls_check_certificate(struct connection_state *scs,
                                          const char *remote_hostname) 
 {
-       int certstat;
+       int ret;
+       unsigned int certstat;
        const gnutls_datum *cert_list;
        unsigned int cert_list_size = 0;
        gnutls_x509_crt cert;
@@ -421,23 +435,35 @@ tls_check_certificate(struct connection_state *scs,
                bad_certificate(scs, "Unable to get certificate from peer.\n");
                return; /* bad_cert will exit if -skip-certificate-check was not given */
        }
-       certstat = gnutls_certificate_verify_peers(scs->tls_state);
-       if (certstat == GNUTLS_E_NO_CERTIFICATE_FOUND) {
-               bad_certificate(scs, "server presented no certificate.\n");
+       ret = gnutls_certificate_verify_peers2(scs->tls_state, &certstat);
+
+       if (ret < 0) {
+               char errbuf[1024];
+
+               snprintf(errbuf, 1024, "could not verify certificate: %s (%d).\n",
+                       gnutls_strerror(ret), ret);
+               bad_certificate(scs, (ret == GNUTLS_E_NO_CERTIFICATE_FOUND ?
+                       "server presented no certificate.\n" :
+                       errbuf));
+               return;
 #ifdef GNUTLS_CERT_CORRUPTED
        } else if (certstat & GNUTLS_CERT_CORRUPTED) {
                bad_certificate(scs, "server's certificate is corrupt.\n");
 #endif
        } else if (certstat & GNUTLS_CERT_REVOKED) {
                bad_certificate(scs, "server's certificate has been revoked.\n");
+       } else if (certstat & GNUTLS_CERT_EXPIRED) {
+               bad_certificate(scs, "server's certificate is expired.\n");
+       } else if (certstat & GNUTLS_CERT_INSECURE_ALGORITHM) {
+               warn_certificate(scs, "server's certificate use an insecure algorithm.\n");
        } else if (certstat & GNUTLS_CERT_INVALID) {
                if (gnutls_certificate_type_get(scs->tls_state) == GNUTLS_CRT_X509) {
                        /* bad_certificate(scs, "server's certificate is not trusted.\n"
                           "there may be a problem with the certificate stored in your certfile\n"); */
                } else {
                        bad_certificate(scs,
-                                                       "server's certificate is invalid or not X.509.\n"
-                                                       "there may be a problem with the certificate stored in your certfile\n");
+                               "server's certificate is invalid or not X.509.\n"
+                               "there may be a problem with the certificate stored in your certfile\n");
                }
 #if defined(GNUTLS_CERT_SIGNER_NOT_FOUND)
        } else if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND) {
@@ -456,7 +482,7 @@ tls_check_certificate(struct connection_state *scs,
 
        if (gnutls_x509_crt_init(&cert) < 0) {
                bad_certificate(scs,
-                                               "Unable to initialize certificate data structure");
+                       "Unable to initialize certificate data structure");
        }
 
 
@@ -504,7 +530,7 @@ tls_check_certificate(struct connection_state *scs,
        if (certificate_filename != NULL &&
                tls_compare_certificates(&cert_list[0]) == 0) {
                bad_certificate(scs,
-                                               "server's certificate was not found in the certificate file.\n");
+                       "server's certificate was not found in the certificate file.\n");
        }
 
        gnutls_x509_crt_deinit(cert);
@@ -532,25 +558,16 @@ struct connection_state *initialize_gnutls(int sd, char *name, Pop3 pc,
 
        assert(gnutls_init(&scs->tls_state, GNUTLS_CLIENT) == 0);
        {
-               const int protocols[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
-               const int ciphers[] =
-                       { GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC,
-                       GNUTLS_CIPHER_RIJNDAEL_256_CBC,
-                       GNUTLS_CIPHER_ARCFOUR, 0
-               };
-               const int compress[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
-               const int key_exch[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS,
-                       GNUTLS_KX_DHE_RSA, 0
-               };
-               /* mutt with gnutls doesn't use kx_srp or kx_anon_dh */
-               const int mac[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
-               assert(gnutls_protocol_set_priority(scs->tls_state, protocols) ==
-                          0);
-               assert(gnutls_cipher_set_priority(scs->tls_state, ciphers) == 0);
-               assert(gnutls_compression_set_priority(scs->tls_state, compress) ==
-                          0);
-               assert(gnutls_kx_set_priority(scs->tls_state, key_exch) == 0);
-               assert(gnutls_mac_set_priority(scs->tls_state, mac) == 0);
+               const char *err_pos;
+               if (GNUTLS_E_SUCCESS != gnutls_priority_set_direct(scs->tls_state, tls, &err_pos)) {
+                       DMA(DEBUG_ERROR,
+                               "Unable to set the priorities to use on the ciphers, "
+                               "key exchange methods, macs and/or compression methods.\n"
+                               "See 'tls' parameter in config file: '%s'.\n",
+                               err_pos);
+                       exit(1);
+               }
+
                /* no client private key */
                if (gnutls_certificate_allocate_credentials(&scs->xcred) < 0) {
                        DMA(DEBUG_ERROR, "gnutls memory error\n");
@@ -566,9 +583,9 @@ struct connection_state *initialize_gnutls(int sd, char *name, Pop3 pc,
                                exit(1);
                        }
                        zok = gnutls_certificate_set_x509_trust_file(scs->xcred,
-                                                                                                                (char *)
-                                                                                                                certificate_filename,
-                                                                                                                GNUTLS_X509_FMT_PEM);
+                                       (char *)
+                                       certificate_filename,
+                                       GNUTLS_X509_FMT_PEM);
                        if (zok < 0) {
                                DMA(DEBUG_ERROR,
                                        "GNUTLS did not like your certificate file %s (%d).\n",
index 8a4fa07..f0b8136 100644 (file)
@@ -69,6 +69,10 @@ static const char *globalnotify = NULL;
 static const char *skin_search_path = DEFAULT_SKIN_PATH;
 /* for gnutls */
 const char *certificate_filename = NULL;
+/* gnutls: specify the priorities to use on the ciphers, key exchange methods,
+   macs and compression methods. */
+const char *tls = NULL;
+
 
 /* it could be argued that a better default exists. */
 #define DEFAULT_FONT  "-*-fixed-*-r-*-*-10-*-*-*-*-*-*-*"
@@ -260,6 +264,9 @@ static int Read_Config_File(char *filename, int *loopinterval)
                } else if (!strcmp(setting, "globalnotify")) {
                        globalnotify = strdup_ordie(value);
                        continue;
+               } else if (!strcmp(setting, "tls")) {
+                       tls = strdup_ordie(value);
+                       continue;
                } else if (mbox_index == -1) {
                        DMA(DEBUG_INFO, "Unknown global setting '%s'\n", setting);
                        continue;                       /* Didn't read any setting.[0-5] value */
@@ -375,6 +382,11 @@ static int Read_Config_File(char *filename, int *loopinterval)
                }
        }
        (void) fclose(fp);
+
+       if (!tls)
+               // use GnuTLS's default ciphers.
+               tls = "NORMAL";
+
        for (i = 0; i < num_mailboxes; i++)
                if (mbox[i].label[0] != '\0')
                        parse_mbox_path(i);
index 0443bc5..66924e3 100644 (file)
@@ -43,6 +43,45 @@ example, if mutt is your mailreader, you may add:
 certfile=/home/<me>/.muttsslcerts
 .RE
 .TP
+\fBtls\fP
+Specify cipher suite preferences on a TLS session. Can be a
+predefined value from gnults or a custom value. Default value
+is: \fINORMAL\fP.
+
+gnutls predefined values:
+.SP
+.RS 8
+\fIPERFORMANCE\fP (gnutls >= 2.2.0)
+.RE
+.RS 8
+\fINORMAL\fP (gnutls >= 2.2.0)
+.RE
+.RS 8
+\fISECURE128\fP (gnutls >= 2.2.0)
+.RE
+.RS 8
+\fISECURE192\fP (gnutls >= 3.0.0)
+.RE
+.RS 8
+\fISECURE256\fP (gnutls >= 2.2.0)
+.RE
+.RS 8
+\fISUITEB128\fP (gnutls >= 3.0.0)
+.RE
+.RS 8
+\fISUITEB192\fP (gnutls >= 3.0.0)
+.RE
+.RS 8
+\fIEXPORT\fP (gnutls >= 2.2.0)
+.RE
+.RS 8
+\fINONE\fP (gnutls >= 2.2.0)
+.RE
+.RS
+.TP
+See \fBhttp://gnutls.org/manual/gnutls.html#Priority-Strings\fR for more details.
+.RE
+.TP
 \fBinterval\fP
 Global interval between mailbox checking. Value is the number of seconds, 5
 is the default.