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]