aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--imap.c62
-rwxr-xr-xindexgen.sh2
-rw-r--r--pop3.c138
-rw-r--r--rcfile_y.y6
-rw-r--r--transact.c22
6 files changed, 142 insertions, 94 deletions
diff --git a/NEWS b/NEWS
index 3f76e34c..f52f1035 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@
(The `lines' figures total .c, .h, .l, and .y files under version control.)
+* Sunil Shetye's patch to imprive behavior in empty messages.
+* Conform to RFC2595; reissue capability probes after successful
+ STARTTLS negotiation.
+* Sunil's patch to make handling of failed STARTTLS more graceful.
+* Sunil's JF2 fix patch for .fetchmailrc security fix.
+
fetchmail-6.2.1 (Tue Jan 14 08:17:19 EST 2003), 22219 lines:
* Updated German, Turkish, Spanish, and Danish translation files.
diff --git a/imap.c b/imap.c
index 3ea5c27d..9d4a506d 100644
--- a/imap.c
+++ b/imap.c
@@ -248,13 +248,10 @@ static int imap_canonicalize(char *result, char *raw, int maxlen)
return(i);
}
-static int imap_getauth(int sock, struct query *ctl, char *greeting)
-/* apply for connection authorization */
+static void capa_probe(int sock, struct query *ctl)
+/* set capability variables from a CAPA probe */
{
- int ok = 0;
-#ifdef SSL_ENABLE
- flag did_stls = FALSE;
-#endif /* SSL_ENABLE */
+ int ok;
/* probe to see if we're running IMAP4 and can use RFC822.PEEK */
capabilities[0] = '\0';
@@ -287,19 +284,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
if (outlevel >= O_DEBUG)
report(stdout, GT_("Protocol identified as IMAP2 or IMAP2BIS\n"));
}
- else
- return(ok);
-
- peek_capable = (imap_version >= IMAP4);
-
- /*
- * Assumption: expunges are cheap, so we want to do them
- * after every message unless user said otherwise.
- */
- if (NUM_SPECIFIED(ctl->expunge))
- expunge_period = NUM_VALUE_OUT(ctl->expunge);
- else
- expunge_period = 1;
/*
* Handle idling. We depend on coming through here on startup
@@ -311,6 +295,17 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
if (outlevel >= O_VERBOSE)
report(stdout, GT_("will idle after poll\n"));
}
+}
+
+static int imap_getauth(int sock, struct query *ctl, char *greeting)
+/* apply for connection authorization */
+{
+ int ok = 0;
+#ifdef SSL_ENABLE
+ flag did_stls = FALSE;
+#endif /* SSL_ENABLE */
+
+ capa_probe(sock, ctl);
/*
* If either (a) we saw a PREAUTH token in the greeting, or
@@ -321,7 +316,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
preauth = FALSE; /* reset for the next session */
return(PS_SUCCESS);
}
-
/*
* Time to authenticate the user.
* Try the protocol variants that don't require passwords first.
@@ -369,12 +363,13 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
char *realhost;
realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
- gen_transact(sock, "STARTTLS");
+ ok = gen_transact(sock, "STARTTLS");
/* We use "tls1" instead of ctl->sslproto, as we want STARTTLS,
* not other SSL protocols
*/
- if (SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck, ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1)
+ if (ok == PS_SUCCESS &&
+ SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck, ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1)
{
if (!ctl->sslproto && !ctl->wehaveauthed)
{
@@ -387,9 +382,32 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
return(PS_AUTHFAIL);
}
did_stls = TRUE;
+
+ /*
+ * RFC 2595 says this:
+ *
+ * "Once TLS has been started, the client MUST discard cached
+ * information about server capabilities and SHOULD re-issue the
+ * CAPABILITY command. This is necessary to protect against
+ * man-in-the-middle attacks which alter the capabilities list prior
+ * to STARTTLS. The server MAY advertise different capabilities
+ * after STARTTLS."
+ */
+ capa_probe(sock, ctl);
}
#endif /* SSL_ENABLE */
+ peek_capable = (imap_version >= IMAP4);
+
+ /*
+ * Assumption: expunges are cheap, so we want to do them
+ * after every message unless user said otherwise.
+ */
+ if (NUM_SPECIFIED(ctl->expunge))
+ expunge_period = NUM_VALUE_OUT(ctl->expunge);
+ else
+ expunge_period = 1;
+
/*
* No such luck. OK, now try the variants that mask your password
* in a challenge-response.
diff --git a/indexgen.sh b/indexgen.sh
index 7917b501..0843952c 100755
--- a/indexgen.sh
+++ b/indexgen.sh
@@ -278,7 +278,7 @@ as a technical effort. I ran it as a test of some theories about why the
Linux development model works.</p>
<p>I wrote a paper, <a
-href="http://www.tuxedo.org/~esr/writings/cathedral-bazaar/">The
+href="http://www.catb.org/~esr/writings/cathedral-bazaar/">The
Cathedral And The Bazaar</a>, about these theories and the project.
I developed the line of analysis it suggested in two later essays.
These papers became quite popular and (to my continuing astonishment) may
diff --git a/pop3.c b/pop3.c
index a2f7d5f0..123e1b81 100644
--- a/pop3.c
+++ b/pop3.c
@@ -39,6 +39,21 @@ char *sdps_envto;
static char lastok[POPBUFSIZE+1];
#endif /* OPIE_ENABLE */
+/* these variables are shared between the CAPA probe and the authenticator */
+#if defined(GSSAPI)
+ flag has_gssapi = FALSE;
+#endif /* defined(GSSAPI) */
+#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
+ flag has_kerberos = FALSE;
+#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
+ flag has_cram = FALSE;
+#ifdef OPIE_ENABLE
+ flag has_otp = FALSE;
+#endif /* OPIE_ENABLE */
+#ifdef SSL_ENABLE
+ flag has_ssl = FALSE;
+#endif /* SSL_ENABLE */
+
#define DOTLINE(s) (s[0] == '.' && (s[1]=='\r'||s[1]=='\n'||s[1]=='\0'))
static int pop3_ok (int sock, char *argbuf)
@@ -124,6 +139,46 @@ static int pop3_ok (int sock, char *argbuf)
return(ok);
}
+
+
+static int capa_probe(sock)
+/* probe the capabilities of the remote server */
+{
+ int ok;
+
+ ok = gen_transact(sock, "CAPA");
+ if (ok == PS_SUCCESS)
+ {
+ char buffer[64];
+
+ /* determine what authentication methods we have available */
+ while ((ok = gen_recv(sock, buffer, sizeof(buffer))) == 0)
+ {
+ if (DOTLINE(buffer))
+ break;
+#ifdef SSL_ENABLE
+ if (strstr(buffer, "STLS"))
+ has_ssl = TRUE;
+#endif /* SSL_ENABLE */
+#if defined(GSSAPI)
+ if (strstr(buffer, "GSSAPI"))
+ has_gssapi = TRUE;
+#endif /* defined(GSSAPI) */
+#if defined(KERBEROS_V4)
+ if (strstr(buffer, "KERBEROS_V4"))
+ has_kerberos = TRUE;
+#endif /* defined(KERBEROS_V4) */
+#ifdef OPIE_ENABLE
+ if (strstr(buffer, "X-OTP"))
+ has_otp = TRUE;
+#endif /* OPIE_ENABLE */
+ if (strstr(buffer, "CRAM-MD5"))
+ has_cram = TRUE;
+ }
+ }
+ return(ok);
+}
+
static int pop3_getauth(int sock, struct query *ctl, char *greeting)
/* apply for connection authorization */
{
@@ -133,18 +188,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
#if OPIE_ENABLE
char *challenge;
#endif /* OPIE_ENABLE */
-#if defined(GSSAPI)
- flag has_gssapi = FALSE;
-#endif /* defined(GSSAPI) */
-#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
- flag has_kerberos = FALSE;
-#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
- flag has_cram = FALSE;
-#ifdef OPIE_ENABLE
- flag has_otp = FALSE;
-#endif /* OPIE_ENABLE */
#ifdef SSL_ENABLE
- flag has_ssl = FALSE;
flag did_stls = FALSE;
#endif /* SSL_ENABLE */
@@ -201,50 +245,21 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
*/
if (ctl->server.authenticate == A_ANY)
{
- ok = gen_transact(sock, "CAPA");
- if (ok == PS_SUCCESS)
- {
- char buffer[64];
-
- /* determine what authentication methods we have available */
- while ((ok = gen_recv(sock, buffer, sizeof(buffer))) == 0)
+ if (capa_probe(sock) != PS_SUCCESS)
+ /* we are in STAGE_GETAUTH! */
+ if (ok == PS_AUTHFAIL ||
+ /* Some servers directly close the socket. However, if we
+ * have already authenticated before, then a previous CAPA
+ * must have succeeded. In that case, treat this as a
+ * genuine socket error and do not change the auth method.
+ */
+ (ok == PS_SOCKET && !ctl->wehaveauthed))
{
- if (DOTLINE(buffer))
- break;
-#ifdef SSL_ENABLE
- if (strstr(buffer, "STLS"))
- has_ssl = TRUE;
-#endif /* SSL_ENABLE */
-#if defined(GSSAPI)
- if (strstr(buffer, "GSSAPI"))
- has_gssapi = TRUE;
-#endif /* defined(GSSAPI) */
-#if defined(KERBEROS_V4)
- if (strstr(buffer, "KERBEROS_V4"))
- has_kerberos = TRUE;
-#endif /* defined(KERBEROS_V4) */
-#ifdef OPIE_ENABLE
- if (strstr(buffer, "X-OTP"))
- has_otp = TRUE;
-#endif /* OPIE_ENABLE */
- if (strstr(buffer, "CRAM-MD5"))
- has_cram = TRUE;
+ ctl->server.authenticate = A_PASSWORD;
+ /* repoll immediately */
+ ok = PS_REPOLL;
+ break;
}
- }
- /* we are in STAGE_GETAUTH! */
- else if (ok == PS_AUTHFAIL ||
- /* Some servers directly close the socket. However, if we
- * have already authenticated before, then a previous CAPA
- * must have succeeded. In that case, treat this as a
- * genuine socket error and do not change the auth method.
- */
- (ok == PS_SOCKET && !ctl->wehaveauthed))
- {
- ctl->server.authenticate = A_PASSWORD;
- /* repoll immediately */
- ok = PS_REPOLL;
- break;
- }
}
#ifdef SSL_ENABLE
@@ -255,12 +270,13 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
char *realhost;
realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
- gen_transact(sock, "STLS");
+ ok = gen_transact(sock, "STLS");
/* We use "tls1" instead of ctl->sslproto, as we want STLS,
* not other SSL protocols
*/
- if (SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck, ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1)
+ if (ok == PS_SUCCESS &&
+ SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck, ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1)
{
if (!ctl->sslproto && !ctl->wehaveauthed)
{
@@ -273,6 +289,18 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
return(PS_AUTHFAIL);
}
did_stls = TRUE;
+
+ /*
+ * RFC 2595 says this:
+ *
+ * "Once TLS has been started, the client MUST discard cached
+ * information about server capabilities and SHOULD re-issue the
+ * CAPABILITY command. This is necessary to protect against
+ * man-in-the-middle attacks which alter the capabilities list prior
+ * to STARTTLS. The server MAY advertise different capabilities
+ * after STARTTLS."
+ */
+ capa_probe(sock);
}
#endif /* SSL_ENABLE */
diff --git a/rcfile_y.y b/rcfile_y.y
index 3dac325b..bd5faa6d 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -428,14 +428,14 @@ int prc_filecheck(const char *pathname, const flag securecheck)
if (!securecheck) return PS_SUCCESS;
- if ((statbuf.st_mode & S_IFLNK) == S_IFLNK)
+ if (!S_ISREG(statbuf.st_mode))
{
- fprintf(stderr, GT_("File %s must not be a symbolic link.\n"), pathname);
+ fprintf(stderr, GT_("File %s must be a regular file.\n"), pathname);
return(PS_IOERR);
}
#ifndef __BEOS__
- if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE | S_IEXEC | S_IXGRP))
+ if (statbuf.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH))
{
fprintf(stderr, GT_("File %s must have no more than -rwx--x--- (0710) permissions.\n"),
pathname);
diff --git a/transact.c b/transact.c
index f419828e..6fbe1879 100644
--- a/transact.c
+++ b/transact.c
@@ -865,18 +865,6 @@ int readheaders(int sock,
}
/*
- * We want to detect this early in case there are so few headers that the
- * dispatch logic barfs.
- */
- if (!headers_ok)
- {
- if (outlevel > O_SILENT)
- report(stdout,
- GT_("message delimiter found while scanning headers\n"));
- return(PS_TRUNCATED);
- }
-
- /*
* Hack time. If the first line of the message was blank, with no headers
* (this happens occasionally due to bad gatewaying software) cons up
* a set of fake headers.
@@ -1255,7 +1243,15 @@ int readheaders(int sock,
*cp++ = '\0';
stuffline(ctl, buf);
- return(headers_ok ? PS_SUCCESS : PS_TRUNCATED);
+ if (!headers_ok)
+ {
+ if (outlevel > O_SILENT)
+ report(stdout,
+ GT_("message delimiter found while scanning headers\n"));
+ return(PS_TRUNCATED);
+ }
+
+ return(PS_SUCCESS);
}
int readbody(int sock, struct query *ctl, flag forward, int len)