On Wed, 05. Jul 2006, 21:31:05 +0200, Julien Louis wrote:
> > Would it instead be possible to point the admins of the mail server in
> > question to the problem and kindly ask them to consider an upgrade?
> 
> Sure, but i think he is not the only guy who have this bug.

And it should not be said that some things only work with OpenSSL and
not GnuTLS.

I finally found the time to write a patch that adds a tls_sslv3only
command (and --tls-sslv3only option).

Do you agree with the patch? Any suggestions for improvements?

Marko, could you please test if using this command fixes the problems? I
do not have access to an appropriate server myself.

Martin



Index: src/conf.c
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/conf.c,v
retrieving revision 1.6
diff -u -r1.6 conf.c
--- src/conf.c  4 Jul 2006 06:55:12 -0000       1.6
+++ src/conf.c  16 Jul 2006 19:15:30 -0000
@@ -75,11 +75,12 @@
     a->password = NULL;
     a->ntlmdomain = NULL;
     a->tls = 0;
+    a->tls_nostarttls = 0;
     a->tls_key_file = NULL;
     a->tls_cert_file = NULL;
     a->tls_trust_file = NULL;
-    a->tls_nostarttls = 0;
     a->tls_nocertcheck = 0;
+    a->tls_sslv3only = 0;
     a->logfile = NULL;
     a->syslog = NULL;
     return a;
@@ -118,13 +119,14 @@
        a->password = acc->password ? xstrdup(acc->password) : NULL;
        a->ntlmdomain = acc->ntlmdomain ? xstrdup(acc->ntlmdomain) : NULL;
        a->tls = acc->tls;
+       a->tls_nostarttls = acc->tls_nostarttls;
        a->tls_key_file = acc->tls_key_file ? xstrdup(acc->tls_key_file) : NULL;
        a->tls_cert_file = 
            acc->tls_cert_file ? xstrdup(acc->tls_cert_file) : NULL;
        a->tls_trust_file = 
            acc->tls_trust_file ? xstrdup(acc->tls_trust_file) : NULL;
-       a->tls_nostarttls = acc->tls_nostarttls;
        a->tls_nocertcheck = acc->tls_nocertcheck;
+       a->tls_sslv3only = acc->tls_sslv3only;
        a->logfile = acc->logfile ? xstrdup(acc->logfile) : NULL;
        a->syslog = acc->syslog ? xstrdup(acc->syslog) : NULL;
     }
@@ -462,6 +464,10 @@
     {
        acc1->tls = acc2->tls;
     }
+    if (acc2->mask & ACC_TLS_NOSTARTTLS)
+    {
+       acc1->tls_nostarttls = acc2->tls_nostarttls;
+    }
     if (acc2->mask & ACC_TLS_KEY_FILE)
     {
        free(acc1->tls_key_file);
@@ -480,9 +486,9 @@
        acc1->tls_trust_file = 
            acc2->tls_trust_file ? xstrdup(acc2->tls_trust_file) : NULL;
     }
-    if (acc2->mask & ACC_TLS_NOSTARTTLS)
+    if (acc2->mask & ACC_TLS_SSLV3ONLY)
     {
-       acc1->tls_nostarttls = acc2->tls_nostarttls;
+       acc1->tls_sslv3only = acc2->tls_sslv3only;
     }
     if (acc2->mask & ACC_TLS_NOCERTCHECK)
     {
@@ -1094,6 +1100,26 @@
                break;
            }
        }
+       else if (strcmp(cmd, "tls_starttls") == 0)
+       {
+           acc->mask |= ACC_TLS_NOSTARTTLS;
+           if (*arg == '\0' || is_on(arg))
+           {
+               acc->tls_nostarttls = 0;
+           }
+           else if (is_off(arg))
+           {
+               acc->tls_nostarttls = 1;
+           }
+           else
+           {
+               *errstr = xasprintf(
+                       _("line %d: invalid argument %s for command %s"),
+                       line, arg, cmd);
+               e = CONF_ESYNTAX;
+               break;
+           }
+       }
        else if (strcmp(cmd, "tls_key_file") == 0)
        {
            acc->mask |= ACC_TLS_KEY_FILE;
@@ -1153,16 +1179,16 @@
                break;
            }
        }
-       else if (strcmp(cmd, "tls_starttls") == 0)
+       else if (strcmp(cmd, "tls_sslv3only") == 0)
        {
-           acc->mask |= ACC_TLS_NOSTARTTLS;
+           acc->mask |= ACC_TLS_SSLV3ONLY;
            if (*arg == '\0' || is_on(arg))
            {
-               acc->tls_nostarttls = 0;
+               acc->tls_sslv3only = 1;
            }
            else if (is_off(arg))
            {
-               acc->tls_nostarttls = 1;
+               acc->tls_sslv3only = 0;
            }
            else
            {
Index: src/conf.h
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/conf.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 conf.h
--- src/conf.h  27 Dec 2005 21:32:45 -0000      1.1.1.1
+++ src/conf.h  16 Jul 2006 19:15:30 -0000
@@ -3,7 +3,7 @@
  *
  * This file is part of msmtp, an SMTP client.
  *
- * Copyright (C) 2000, 2003, 2004, 2005
+ * Copyright (C) 2000, 2003, 2004, 2005, 2006
  * Martin Lambers <[EMAIL PROTECTED]>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -59,13 +59,14 @@
 #define ACC_PASSWORD           (1 << 13)
 #define ACC_NTLMDOMAIN         (1 << 14)
 #define ACC_TLS                        (1 << 15)
-#define ACC_TLS_KEY_FILE       (1 << 16)
-#define ACC_TLS_CERT_FILE      (1 << 17)
-#define ACC_TLS_TRUST_FILE     (1 << 18)
-#define ACC_TLS_NOCERTCHECK    (1 << 19)
-#define ACC_TLS_NOSTARTTLS     (1 << 20)
-#define ACC_LOGFILE            (1 << 21)
-#define ACC_SYSLOG             (1 << 22)
+#define ACC_TLS_NOSTARTTLS     (1 << 16)
+#define ACC_TLS_KEY_FILE       (1 << 17)
+#define ACC_TLS_CERT_FILE      (1 << 18)
+#define ACC_TLS_TRUST_FILE     (1 << 19)
+#define ACC_TLS_NOCERTCHECK    (1 << 20)
+#define ACC_TLS_SSLV3ONLY      (1 << 21)
+#define ACC_LOGFILE            (1 << 22)
+#define ACC_SYSLOG             (1 << 23)
 
 typedef struct
 {
@@ -99,9 +100,10 @@
     char *tls_key_file;                /* file in PEM format */
     char *tls_cert_file;       /* file in PEM format */
     char *tls_trust_file;      /* file in PEM format */
-    int tls_nocertcheck;       /* flag: do not check certificate? */
     int tls_nostarttls;                /* flag: start TLS immediatly 
                                   (without STARTTLS command)? */
+    int tls_nocertcheck;       /* flag: do not check certificate? */
+    int tls_sslv3only;         /* flag: use only SSLv3? */
     /* logging */
     char *logfile;             /* NULL or logfile */
     char *syslog;              /* NULL or syslog facility */
Index: src/msmtp.c
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/msmtp.c,v
retrieving revision 1.18
diff -u -r1.18 msmtp.c
--- src/msmtp.c 16 Jul 2006 11:38:49 -0000      1.18
+++ src/msmtp.c 16 Jul 2006 19:15:31 -0000
@@ -461,7 +461,8 @@
     if (acc->tls)
     {
        if ((e = smtp_tls_init(&srv, acc->tls_key_file, acc->tls_cert_file, 
-                       acc->tls_trust_file, errstr)) != TLS_EOK)
+                       acc->tls_trust_file, acc->tls_sslv3only, errstr)) 
+               != TLS_EOK)
        {
            return exitcode_tls(e);
        }
@@ -634,7 +635,8 @@
     {
        tci = tls_cert_info_new();
        if ((e = smtp_tls_init(&srv, acc->tls_key_file, acc->tls_cert_file, 
-                       acc->tls_trust_file, errstr)) != TLS_EOK)
+                       acc->tls_trust_file, acc->tls_sslv3only, errstr)) 
+               != TLS_EOK)
        {
            e = exitcode_tls(e);
            goto error_exit;
@@ -1370,7 +1372,8 @@
     if (acc->tls)
     {
        if ((e = smtp_tls_init(&srv, acc->tls_key_file, acc->tls_cert_file, 
-                       acc->tls_trust_file, errstr)) != TLS_EOK)
+                       acc->tls_trust_file, acc->tls_sslv3only, errstr)) 
+               != TLS_EOK)
        {
            e = exitcode_tls(e);
            goto error_exit;
@@ -2120,6 +2123,7 @@
            "  --user=[username]            Set/unset user name for "
                "authentication.\n"
            "  --tls[=(on|off)]             Enable/disable TLS encryption.\n"
+           "  --tls-starttls[=(on|off)]    Enable/disable STARTTLS for TLS.\n"
            "  --tls-trust-file=[file]      Set/unset trust file for TLS.\n"
             "  --tls-key-file=[file]        Set/unset private key file for "
                "TLS.\n"
@@ -2127,7 +2131,8 @@
                "TLS.\n"
            "  --tls-certcheck[=(on|off)]   Enable/disable server certificate "
                "checks for TLS.\n"
-           "  --tls-starttls[=(on|off)]    Enable/disable STARTTLS for TLS.\n"
+           "  --tls-sslv3only[=(on|off)]   Allow only SSLv3, or allow all "
+               "versions.\n"
             "Options specific to sendmail mode:\n"
            "  --auto-from[=(on|off)]       Enable/disable automatic "
                "envelope-from addresses.\n"
@@ -2189,18 +2194,19 @@
 #define LONGONLYOPT_AUTH               5
 #define LONGONLYOPT_USER               6
 #define LONGONLYOPT_TLS                        7
-#define LONGONLYOPT_TLS_TRUST_FILE     8
-#define LONGONLYOPT_TLS_KEY_FILE       9
-#define LONGONLYOPT_TLS_CERT_FILE      10
-#define LONGONLYOPT_TLS_CERTCHECK      11
-#define LONGONLYOPT_TLS_STARTTLS       12
-#define LONGONLYOPT_PROTOCOL           13
-#define LONGONLYOPT_DOMAIN             14
-#define LONGONLYOPT_KEEPBCC            15
-#define LONGONLYOPT_RMQS               16
-#define LONGONLYOPT_SYSLOG             17
-#define LONGONLYOPT_MAILDOMAIN         18
-#define LONGONLYOPT_AUTO_FROM          19
+#define LONGONLYOPT_TLS_STARTTLS       8
+#define LONGONLYOPT_TLS_TRUST_FILE     9
+#define LONGONLYOPT_TLS_KEY_FILE       10
+#define LONGONLYOPT_TLS_CERT_FILE      11
+#define LONGONLYOPT_TLS_CERTCHECK      12
+#define LONGONLYOPT_TLS_SSLV3ONLY      13
+#define LONGONLYOPT_PROTOCOL           14
+#define LONGONLYOPT_DOMAIN             15
+#define LONGONLYOPT_KEEPBCC            16
+#define LONGONLYOPT_RMQS               17
+#define LONGONLYOPT_SYSLOG             18
+#define LONGONLYOPT_MAILDOMAIN         19
+#define LONGONLYOPT_AUTO_FROM          20
 
 int msmtp_cmdline(msmtp_cmdline_conf_t *conf, int argc, char *argv[])
 {
@@ -2226,11 +2232,12 @@
        { "auth",            optional_argument, 0, LONGONLYOPT_AUTH },
        { "user",            required_argument, 0, LONGONLYOPT_USER },
        { "tls",             optional_argument, 0, LONGONLYOPT_TLS },
+       { "tls-starttls",    optional_argument, 0, LONGONLYOPT_TLS_STARTTLS },
        { "tls-trust-file",  required_argument, 0, LONGONLYOPT_TLS_TRUST_FILE },
        { "tls-key-file",    required_argument, 0, LONGONLYOPT_TLS_KEY_FILE },
        { "tls-cert-file",   required_argument, 0, LONGONLYOPT_TLS_CERT_FILE },
        { "tls-certcheck",   optional_argument, 0, LONGONLYOPT_TLS_CERTCHECK },
-       { "tls-starttls",    optional_argument, 0, LONGONLYOPT_TLS_STARTTLS },
+       { "tls-sslv3only",   optional_argument, 0, LONGONLYOPT_TLS_SSLV3ONLY },
        { "dsn-notify",      required_argument, 0, 'N' },
        { "dsn-return",      required_argument, 0, 'R' },
        { "protocol",        required_argument, 0, LONGONLYOPT_PROTOCOL },
@@ -2480,6 +2487,24 @@
                }
                conf->cmdline_account->mask |= ACC_TLS;
                break;
+               
+           case LONGONLYOPT_TLS_STARTTLS:
+               if (!optarg || is_on(optarg))
+               {
+                   conf->cmdline_account->tls_nostarttls = 0;
+               }
+               else if (is_off(optarg))
+               {
+                   conf->cmdline_account->tls_nostarttls = 1;
+               }
+               else
+               {
+                   print_error(_("invalid argument %s for %s"), 
+                           optarg, "--tls-starttls");
+                   error_code = 1;
+               }
+               conf->cmdline_account->mask |= ACC_TLS_NOSTARTTLS;
+               break;
 
            case LONGONLYOPT_TLS_TRUST_FILE:
                free(conf->cmdline_account->tls_trust_file);
@@ -2539,22 +2564,22 @@
                conf->cmdline_account->mask |= ACC_TLS_NOCERTCHECK;
                break;
 
-           case LONGONLYOPT_TLS_STARTTLS:
-               if (!optarg || is_on(optarg))
+           case LONGONLYOPT_TLS_SSLV3ONLY:
+               if (!optarg || is_on(optarg))
                {
-                   conf->cmdline_account->tls_nostarttls = 0;
+                   conf->cmdline_account->tls_sslv3only = 1;
                }
                else if (is_off(optarg))
                {
-                   conf->cmdline_account->tls_nostarttls = 1;
+                   conf->cmdline_account->tls_sslv3only = 0;
                }
                else
                {
                    print_error(_("invalid argument %s for %s"), 
-                           optarg, "--tls-starttls");
+                           optarg, "--tls-sslv3only");
                    error_code = 1;
                }
-               conf->cmdline_account->mask |= ACC_TLS_NOSTARTTLS;
+               conf->cmdline_account->mask |= ACC_TLS_NOCERTCHECK;
                break;
 
            case 'N':
@@ -2942,20 +2967,22 @@
            "password        = %s\n"
            "ntlmdomain      = %s\n"
            "tls             = %s\n"
+           "tls_starttls    = %s\n"
            "tls_trust_file  = %s\n"
            "tls_key_file    = %s\n"
            "tls_cert_file   = %s\n"
-           "tls_starttls    = %s\n"
-           "tls_certcheck   = %s\n",
+           "tls_certcheck   = %s\n"
+           "tls_sslv3only   = %s\n",
            account->username ? account->username : _("(not set)"),
            account->password ? "*" : _("(not set)"),
            account->ntlmdomain ? account->ntlmdomain : _("(not set)"),
            account->tls ? _("on") : _("off"), 
+           account->tls_nostarttls ? _("off") : _("on"),
            account->tls_trust_file ? account->tls_trust_file : _("(not set)"),
            account->tls_key_file ? account->tls_key_file : _("(not set)"),
            account->tls_cert_file ? account->tls_cert_file : _("(not set)"),
-           account->tls_nostarttls ? _("off") : _("on"),
-           account->tls_nocertcheck ? _("off") : _("on"));
+           account->tls_nocertcheck ? _("off") : _("on"),
+           account->tls_sslv3only ? _("on") : _("off"));
     if (conf.sendmail)
     {
        printf("auto_from       = %s\n"
Index: src/smtp.c
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/smtp.c,v
retrieving revision 1.5
diff -u -r1.5 smtp.c
--- src/smtp.c  4 Jul 2006 06:55:12 -0000       1.5
+++ src/smtp.c  16 Jul 2006 19:15:31 -0000
@@ -531,10 +531,11 @@
 
 #ifdef HAVE_SSL
 int smtp_tls_init(smtp_server_t *srv, const char *tls_key_file, 
-       const char *tls_ca_file, const char *tls_trust_file, char **errstr)
+       const char *tls_ca_file, const char *tls_trust_file, 
+       int sslv3only, char **errstr)
 {
     return tls_init(&srv->tls, tls_key_file, tls_ca_file, tls_trust_file, 
-           errstr);
+           sslv3only, errstr);
 }
 #endif /* HAVE_SSL */
 
Index: src/smtp.h
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/smtp.h,v
retrieving revision 1.2
diff -u -r1.2 smtp.h
--- src/smtp.h  4 Jul 2006 06:55:12 -0000       1.2
+++ src/smtp.h  16 Jul 2006 19:15:32 -0000
@@ -3,7 +3,7 @@
  * 
  * This file is part of msmtp, an SMTP client.
  *
- * Copyright (C) 2000, 2003, 2004, 2005
+ * Copyright (C) 2000, 2003, 2004, 2005, 2006
  * Martin Lambers <[EMAIL PROTECTED]>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -173,7 +173,8 @@
  */
 #ifdef HAVE_SSL
 int smtp_tls_init(smtp_server_t *srv, const char *tls_key_file, 
-       const char *tls_ca_file, const char *tls_trust_file, char **errstr);
+       const char *tls_ca_file, const char *tls_trust_file, 
+       int sslv3only, char **errstr);
 #endif /* HAVE_SSL */
 
 /*
Index: src/tls.c
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/tls.c,v
retrieving revision 1.6
diff -u -r1.6 tls.c
--- src/tls.c   4 Jul 2006 06:55:12 -0000       1.6
+++ src/tls.c   16 Jul 2006 19:15:32 -0000
@@ -926,7 +926,7 @@
  */
 
 int tls_init(tls_t *tls, const char *key_file, const char *cert_file, 
-       const char *trust_file, char **errstr)
+       const char *trust_file, int sslv3only, char **errstr)
 {
 #ifdef HAVE_GNUTLS
     int error_code;
@@ -944,6 +944,18 @@
        gnutls_deinit(tls->session);
        return TLS_ELIBFAILED;
     }
+    if (sslv3only)
+    {
+       const int sslv3only_proto_prio[2] = { GNUTLS_SSL3, 0 };
+       if ((error_code = gnutls_protocol_set_priority(tls->session, 
+                       sslv3only_proto_prio)) != 0)
+       {
+           *errstr = xasprintf(_("cannot set SSLv3-only option: %s"),
+                   gnutls_strerror(error_code));
+           gnutls_deinit(tls->session);
+           return TLS_ELIBFAILED;
+       }
+    }
     if ((error_code = gnutls_certificate_allocate_credentials(&tls->cred)) < 0)
     {
        *errstr = xasprintf(
@@ -996,18 +1008,20 @@
     
     SSL_METHOD *ssl_method = NULL;
     
-    if (!(ssl_method = SSLv23_client_method()))
+    ssl_method = sslv3only ? SSLv3_client_method() : SSLv23_client_method();
+    if (!ssl_method)
     {
        *errstr = xasprintf(_("cannot set TLS method"));
        return TLS_ELIBFAILED;
     }
-    tls->ssl_ctx = SSL_CTX_new(ssl_method);
-    if (!tls->ssl_ctx)
+    if (!(tls->ssl_ctx = SSL_CTX_new(ssl_method)))
     {
        *errstr = xasprintf(_("cannot create TLS context: %s"),
                ERR_error_string(ERR_get_error(), NULL));
        return TLS_ELIBFAILED;
     }
+    /* SSLv2 has known flaws. Disable it. */
+    (void)SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv2);
     if (key_file && cert_file)
     {
        if (SSL_CTX_use_PrivateKey_file(
Index: src/tls.h
===================================================================
RCS file: /cvsroot/msmtp/msmtp/src/tls.h,v
retrieving revision 1.2
diff -u -r1.2 tls.h
--- src/tls.h   4 Jul 2006 06:55:12 -0000       1.2
+++ src/tls.h   16 Jul 2006 19:15:32 -0000
@@ -3,7 +3,7 @@
  * 
  * This file is part of msmtp, an SMTP client.
  *
- * Copyright (C) 2000, 2003, 2004, 2005
+ * Copyright (C) 2000, 2003, 2004, 2005, 2006
  * Martin Lambers <[EMAIL PROTECTED]>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -110,11 +110,14 @@
  * set to be used when the peer request a certificate. If 'trust_file' is not
  * NULL, it will be used to verify the peer certificate.
  * All files must be in PEM format.
+ * If sslv3only is set, then only the SSLv3 protocol will be accepted. This
+ * option might be needed to talk to some obsolete broken servers, but is not
+ * recommended!
  * Used error codes: TLS_ELIBFAILED, TLS_EFILE
  */
 int tls_init(tls_t *tls, 
        const char *key_file, const char *ca_file, const char *trust_file, 
-       char **errstr);
+       int sslv3only, char **errstr);
 
 /*
  * tls_start()


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to