aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--conf.c1
-rw-r--r--driver.c10
-rw-r--r--fetchmail.c3
-rw-r--r--fetchmail.h1
-rw-r--r--fetchmail.man12
-rwxr-xr-xfetchmailconf.py16
-rw-r--r--imap.c19
-rw-r--r--options.c7
-rw-r--r--pop3.c17
-rw-r--r--rcfile_l.l1
-rw-r--r--rcfile_y.y3
12 files changed, 72 insertions, 21 deletions
diff --git a/NEWS b/NEWS
index af27ede1..0e240676 100644
--- a/NEWS
+++ b/NEWS
@@ -102,6 +102,9 @@ fetchmail 6.3.9 (not yet released):
* In KAME/getnameinfo.c it's best to use the correct argument to inet_ntoa.
(Peter O'Gorman)
* In verbose mode, log if --check mode is enabled.
+* Add sslcommonname option (rcfile and commandline) as a way to work around
+ misconfigured upstream SSL servers that use the wrong certificate name. It
+ specifies which CommonName fetchmail expects and logs.
# DOCUMENTATION:
* Add fetchmail-SA-2007-02.txt
diff --git a/conf.c b/conf.c
index 14562575..75fbd34a 100644
--- a/conf.c
+++ b/conf.c
@@ -376,6 +376,7 @@ void dump_config(struct runctl *runp, struct query *querylist)
stringdump("sslproto", ctl->sslproto);
booldump("sslcertck", ctl->sslcertck);
stringdump("sslcertpath", ctl->sslcertpath);
+ stringdump("sslcommonname", ctl->sslcommonname);
stringdump("sslfingerprint", ctl->sslfingerprint);
#endif /* SSL_ENABLE */
numdump("expunge", ctl->expunge);
diff --git a/driver.c b/driver.c
index d93c01c2..de078871 100644
--- a/driver.c
+++ b/driver.c
@@ -1088,10 +1088,12 @@ static int do_session(
set_timeout(mytimeout);
/* perform initial SSL handshake on open connection */
- /* Note: We pass the realhost name over for certificate
- verification. We may want to make this configurable */
- if (ctl->use_ssl && SSLOpen(mailserver_socket,ctl->sslcert,ctl->sslkey,ctl->sslproto,ctl->sslcertck,
- ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname,&ctl->remotename) == -1)
+ if (ctl->use_ssl &&
+ SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
+ ctl->sslproto, ctl->sslcertck, ctl->sslcertpath,
+ ctl->sslfingerprint, ctl->sslcommonname ?
+ ctl->sslcommonname : realhost, ctl->server.pollname,
+ &ctl->remotename) == -1)
{
report(stderr, GT_("SSL connection failed.\n"));
err = PS_SOCKET;
diff --git a/fetchmail.c b/fetchmail.c
index ab335380..bf88b4dd 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -966,6 +966,7 @@ static void optmerge(struct query *h2, struct query *h1, int force)
FLAG_MERGE(sslproto);
FLAG_MERGE(sslcertck);
FLAG_MERGE(sslcertpath);
+ FLAG_MERGE(sslcommonname);
FLAG_MERGE(sslfingerprint);
#endif
FLAG_MERGE(expunge);
@@ -1637,6 +1638,8 @@ static void dump_params (struct runctl *runp,
if (ctl->sslcertpath != NULL)
printf(GT_(" SSL trusted certificate directory: %s\n"), ctl->sslcertpath);
}
+ if (ctl->sslcommonname != NULL)
+ printf(GT_(" SSL server CommonName: %s\n"), ctl->sslcommonname);
if (ctl->sslfingerprint != NULL)
printf(GT_(" SSL key fingerprint (checked against the server key): %s\n"), ctl->sslfingerprint);
#endif
diff --git a/fetchmail.h b/fetchmail.h
index 107dffc1..35dfa223 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -355,6 +355,7 @@ struct query
use ssl23 for SSL and opportunistic tls1 for non-SSL connections. */
char *sslcertpath; /* Trusted certificate directory for checking the server cert */
flag sslcertck; /* Strictly check the server cert. */
+ char *sslcommonname; /* CommonName to expect from server */
char *sslfingerprint; /* Fingerprint to check against */
char *properties; /* passthrough properties for extensions */
diff --git a/fetchmail.man b/fetchmail.man
index 2db1689c..6e4a254c 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -439,6 +439,18 @@ it - every time you add or modify a certificate in the directory, you need
to use the \fBc_rehash\fR tool (which comes with OpenSSL in the tools/
subdirectory).
.TP
+.B \-\-sslcommonname <common name>
+(Keyword: sslcommonname)
+Use of this option is discouraged. Before using it, contact your
+upstream and ask for a proper SSL certificate to be used. If the
+upstream is clueless, this option can be used to specify the name
+(CommonName) that fetchmail expects on the server certificate. A
+correctly configured server will have this set to the hostname by which
+it is reached, and by default fetchmail will expect as much. Use this
+option when the CommonName is set to some other value, to avoid the
+"Server CommonName mismatch" warning, and only if the upstream can't be
+made to use proper certificates.
+.TP
.B \-\-sslfingerprint <fingerprint>
(Keyword: sslfingerprint)
Specify the fingerprint of the server key (an MD5 hash of the key) in
diff --git a/fetchmailconf.py b/fetchmailconf.py
index 3c7f5c38..8c6decab 100755
--- a/fetchmailconf.py
+++ b/fetchmailconf.py
@@ -5,7 +5,7 @@
# Matthias Andree <matthias.andree@gmx.de>
# Requires Python with Tkinter, and the following OS-dependent services:
# posix, posixpath, socket
-version = "1.53 $Revision$"
+version = "1.54 $Revision$"
from Tkinter import *
from Dialog import *
@@ -258,6 +258,7 @@ class User:
self.sslproto = None # Force SSL?
self.sslcertck = 0 # Enable strict SSL cert checking
self.sslcertpath = None # Path to trusted certificates
+ self.sslcommonname = None # SSL CommonName to expect
self.sslfingerprint = None # SSL key fingerprint to check
self.properties = None # Extension properties
User.typemap = (
@@ -297,6 +298,7 @@ class User:
('sslcert', 'String'),
('sslcertck', 'Boolean'),
('sslcertpath', 'String'),
+ ('sslcommonname', 'String'),
('sslfingerprint', 'String'),
('properties', 'String'))
@@ -371,6 +373,8 @@ class User:
res = res + flag2str(self.sslcertck, 'sslcertck')
if self.sslcertpath and self.sslcertpath != UserDefaults.sslcertpath:
res = res + " sslcertpath " + `self.sslcertpath`
+ if self.sslcommonname and self.sslcommonname != UserDefaults.sslcommonname:
+ res = res + " sslcommonname " + `self.sslcommonname`
if self.sslfingerprint and self.sslfingerprint != UserDefaults.sslfingerprint:
res = res + " sslfingerprint " + `self.sslfingerprint`
if self.expunge != UserDefaults.expunge:
@@ -1000,8 +1004,10 @@ The ssl option enables SSL communication with a mailserver
supporting Secure Sockets Layer. The sslkey and sslcert options
declare key and certificate files for use with SSL.
The sslcertck option enables strict checking of SSL server
-certificates (and sslcertpath gives trusted certificate
-directory). With sslfingerprint, you can specify a finger-
+certificates (and sslcertpath gives the trusted certificate
+directory). The sslcommonname option helps if the server is
+misconfigured and returning "Server CommonName mismatch"
+warnings. With sslfingerprint, you can specify a finger-
print the server's key is checked against.
"""}
@@ -1641,6 +1647,8 @@ class UserEdit(Frame, MyWidget):
variable=self.sslcertck).pack(side=TOP, fill=X)
LabeledEntry(sslwin, 'SSL trusted certificate directory:',
self.sslcertpath, '14').pack(side=TOP, fill=X)
+ LabeledEntry(sslwin, 'SSL CommonName:',
+ self.sslcommonname, '14').pack(side=TOP, fill=X)
LabeledEntry(sslwin, 'SSL key fingerprint:',
self.sslfingerprint, '14').pack(side=TOP, fill=X)
sslwin.pack(fill=X, anchor=N)
@@ -1942,7 +1950,7 @@ def copy_instance(toclass, fromdict):
optional = ('interface', 'monitor',
'esmtpname', 'esmtppassword',
'ssl', 'sslkey', 'sslcert', 'sslproto', 'sslcertck',
- 'sslcertpath', 'sslfingerprint', 'showdots')
+ 'sslcertpath', 'sslcommonname', 'sslfingerprint', 'showdots')
class_sig = setdiff(toclass.__dict__.keys(), optional)
class_sig.sort()
dict_keys = setdiff(fromdict.keys(), optional)
diff --git a/imap.c b/imap.c
index ec097eb5..ab446777 100644
--- a/imap.c
+++ b/imap.c
@@ -381,7 +381,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
int ok = 0;
#ifdef SSL_ENABLE
int got_tls = 0;
- char *realhost;
#endif
(void)greeting;
@@ -407,9 +406,15 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
}
#ifdef SSL_ENABLE
- realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
-
if (maybe_tls(ctl)) {
+ char *commonname;
+
+ commonname = ctl->server.pollname;
+ if (ctl->server.via)
+ commonname = ctl->server.via;
+ if (ctl->sslcommonname)
+ commonname = ctl->sslcommonname;
+
if (strstr(capabilities, "STARTTLS"))
{
/* Use "tls1" rather than ctl->sslproto because tls1 is the only
@@ -418,7 +423,7 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
* (see below). */
if (gen_transact(sock, "STARTTLS") == PS_SUCCESS
&& SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
- ctl->sslcertpath, ctl->sslfingerprint, realhost,
+ ctl->sslcertpath, ctl->sslfingerprint, commonname,
ctl->server.pollname, &ctl->remotename) != -1)
{
/*
@@ -438,7 +443,7 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
capa_probe(sock, ctl);
if (outlevel >= O_VERBOSE)
{
- report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), realhost);
+ report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), commonname);
}
}
}
@@ -447,11 +452,11 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
if (must_tls(ctl)) {
/* Config required TLS but we couldn't guarantee it, so we must
* stop. */
- report(stderr, GT_("%s: upgrade to TLS failed.\n"), realhost);
+ report(stderr, GT_("%s: upgrade to TLS failed.\n"), commonname);
return PS_SOCKET;
} else {
if (outlevel >= O_VERBOSE) {
- report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue\n"), realhost);
+ report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue\n"), commonname);
}
/* We don't know whether the connection is in a working state, so
* test by issuing a NOOP. */
diff --git a/options.c b/options.c
index 87a308c7..56569bcb 100644
--- a/options.c
+++ b/options.c
@@ -46,6 +46,7 @@ enum {
LA_SSLPROTO,
LA_SSLCERTCK,
LA_SSLCERTPATH,
+ LA_SSLCOMMONNAME,
LA_SSLFINGERPRINT,
LA_FETCHSIZELIMIT,
LA_FASTUIDL,
@@ -125,6 +126,7 @@ static const struct option longoptions[] = {
{"sslproto", required_argument, (int *) 0, LA_SSLPROTO },
{"sslcertck", no_argument, (int *) 0, LA_SSLCERTCK },
{"sslcertpath", required_argument, (int *) 0, LA_SSLCERTPATH },
+ {"sslcommonname", required_argument, (int *) 0, LA_SSLCOMMONNAME },
{"sslfingerprint", required_argument, (int *) 0, LA_SSLFINGERPRINT },
#endif
@@ -539,6 +541,10 @@ int parsecmdline (int argc /** argument count */,
ctl->sslcertpath = prependdir(optarg, currentwd);
break;
+ case LA_SSLCOMMONNAME:
+ ctl->sslcommonname = xstrdup(optarg);
+ break;
+
case LA_SSLFINGERPRINT:
ctl->sslfingerprint = xstrdup(optarg);
break;
@@ -611,6 +617,7 @@ int parsecmdline (int argc /** argument count */,
P(GT_(" --sslcert ssl client certificate\n"));
P(GT_(" --sslcertck do strict server certificate check (recommended)\n"));
P(GT_(" --sslcertpath path to ssl certificates\n"));
+ P(GT_(" --sslcommonname expect this CommonName from server (discouraged)\n"));
P(GT_(" --sslfingerprint fingerprint that must match that of the server's cert.\n"));
P(GT_(" --sslproto force ssl protocol (SSL2/SSL3/TLS1)\n"));
#endif
diff --git a/pop3.c b/pop3.c
index 84dbc69c..561a4b59 100644
--- a/pop3.c
+++ b/pop3.c
@@ -307,7 +307,6 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
char *challenge;
#endif /* OPIE_ENABLE */
#ifdef SSL_ENABLE
- char *realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
flag connection_may_have_tls_errors = FALSE;
flag got_tls = FALSE;
#endif /* SSL_ENABLE */
@@ -476,6 +475,14 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
#ifdef SSL_ENABLE
if (maybe_tls(ctl)) {
+ char *commonname;
+
+ commonname = ctl->server.pollname;
+ if (ctl->server.via)
+ commonname = ctl->server.via;
+ if (ctl->sslcommonname)
+ commonname = ctl->sslcommonname;
+
if (has_stls)
{
/* Use "tls1" rather than ctl->sslproto because tls1 is the only
@@ -484,7 +491,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
* (see below). */
if (gen_transact(sock, "STLS") == PS_SUCCESS
&& SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
- ctl->sslcertpath, ctl->sslfingerprint, realhost,
+ ctl->sslcertpath, ctl->sslfingerprint, commonname,
ctl->server.pollname, &ctl->remotename) != -1)
{
/*
@@ -508,7 +515,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
}
if (outlevel >= O_VERBOSE)
{
- report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), realhost);
+ report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), commonname);
}
}
}
@@ -517,7 +524,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
if (must_tls(ctl)) {
/* Config required TLS but we couldn't guarantee it, so we must
* stop. */
- report(stderr, GT_("%s: upgrade to TLS failed.\n"), realhost);
+ report(stderr, GT_("%s: upgrade to TLS failed.\n"), commonname);
return PS_SOCKET;
} else {
/* We don't know whether the connection is usable, and there's
@@ -528,7 +535,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
connection_may_have_tls_errors = TRUE;
if (outlevel >= O_VERBOSE)
{
- report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue.\n"), realhost);
+ report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue.\n"), commonname);
}
}
}
diff --git a/rcfile_l.l b/rcfile_l.l
index 4b0b0fed..03a1e55c 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -187,6 +187,7 @@ sslcert { return SSLCERT; }
sslproto { return SSLPROTO; }
sslcertck { return SSLCERTCK; }
sslcertpath { return SSLCERTPATH; }
+sslcommonname { return SSLCOMMONNAME; }
sslfingerprint { return SSLFINGERPRINT; }
checkalias { return CHECKALIAS; }
diff --git a/rcfile_y.y b/rcfile_y.y
index 300fcc7f..0e622002 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -76,7 +76,7 @@ extern char * yytext;
%token NO KEEP FLUSH LIMITFLUSH FETCHALL REWRITE FORCECR STRIPCR PASS8BITS
%token DROPSTATUS DROPDELIVERED
%token DNS SERVICE PORT UIDL INTERVAL MIMEDECODE IDLE CHECKALIAS
-%token SSL SSLKEY SSLCERT SSLPROTO SSLCERTCK SSLCERTPATH SSLFINGERPRINT
+%token SSL SSLKEY SSLCERT SSLPROTO SSLCERTCK SSLCERTPATH SSLCOMMONNAME SSLFINGERPRINT
%token PRINCIPAL ESMTPNAME ESMTPPASSWORD
%token TRACEPOLLS
@@ -338,6 +338,7 @@ user_option : TO localnames HERE
| SSLPROTO STRING {current.sslproto = xstrdup($2);}
| SSLCERTCK {current.sslcertck = FLAG_TRUE;}
| SSLCERTPATH STRING {current.sslcertpath = prependdir($2, rcfiledir);}
+ | SSLCOMMONNAME STRING {current.sslcommonname = xstrdup($2);}
| SSLFINGERPRINT STRING {current.sslfingerprint = xstrdup($2);}
| NO KEEP {current.keep = FLAG_FALSE;}