]> Pileus Git - ~andy/fetchmail/blobdiff - pop3.c
Update website for 6.3.24.
[~andy/fetchmail] / pop3.c
diff --git a/pop3.c b/pop3.c
index 5148c25d50b8fd9625f738a1d4e12ae91d2a8945..5549dc9ac5a56ff41e3efbbb7bbb6a61e581cd99 100644 (file)
--- a/pop3.c
+++ b/pop3.c
@@ -52,6 +52,9 @@ static flag has_cram = FALSE;
 #ifdef OPIE_ENABLE
 flag has_otp = FALSE;
 #endif /* OPIE_ENABLE */
+#ifdef NTLM_ENABLE
+flag has_ntlm = FALSE;
+#endif /* NTLM_ENABLE */
 #ifdef SSL_ENABLE
 static flag has_stls = FALSE;
 #endif /* SSL_ENABLE */
@@ -209,6 +212,9 @@ static int capa_probe(int sock)
 #ifdef OPIE_ENABLE
     has_otp = FALSE;
 #endif /* OPIE_ENABLE */
+#ifdef NTLM_ENABLE
+    has_ntlm = FALSE;
+#endif /* NTLM_ENABLE */
 
     ok = gen_transact(sock, "CAPA");
     if (ok == PS_SUCCESS)
@@ -220,22 +226,32 @@ static int capa_probe(int sock)
        {
            if (DOTLINE(buffer))
                break;
+
 #ifdef SSL_ENABLE
            if (strstr(buffer, "STLS"))
                has_stls = 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 */
+
+#ifdef NTLM_ENABLE
+           if (strstr(buffer, "NTLM"))
+               has_ntlm = TRUE;
+#endif /* NTLM_ENABLE */
+
            if (strstr(buffer, "CRAM-MD5"))
                has_cram = TRUE;
        }
@@ -265,7 +281,6 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
 #endif /* OPIE_ENABLE */
 #ifdef SSL_ENABLE
     flag connection_may_have_tls_errors = FALSE;
-    flag got_tls = FALSE;
 #endif /* SSL_ENABLE */
 
     done_capa = FALSE;
@@ -307,9 +322,9 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
      *
      * Matthias Andree
      */
-    if (peek_capable && strstr(greeting, "Maillennium POP3/PROXY server")) {
+    if (peek_capable && strstr(greeting, "Maillennium POP3")) {
        if ((ctl->server.workarounds & WKA_TOP) == 0) {
-           report(stdout, GT_("Warning: \"Maillennium POP3/PROXY server\" found, using RETR command instead of TOP.\n"));
+           report(stdout, GT_("Warning: \"Maillennium POP3\" found, using RETR command instead of TOP.\n"));
            ctl->server.workarounds |= WKA_TOP;
        }
        peek_capable = 0;
@@ -328,22 +343,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
         ctl->server.sdps = TRUE;
 #endif /* SDPS_ENABLE */
 
-#ifdef NTLM_ENABLE
-    /* MSN servers require the use of NTLM (MSN) authentication */
-    if (!strcasecmp(ctl->server.pollname, "pop3.email.msn.com") ||
-           ctl->server.authenticate == A_MSN)
-       return (do_pop3_ntlm(sock, ctl, 1) == 0) ? PS_SUCCESS : PS_AUTHFAIL;
-    if (ctl->server.authenticate == A_NTLM)
-       return (do_pop3_ntlm(sock, ctl, 0) == 0) ? PS_SUCCESS : PS_AUTHFAIL;
-#else
-    if (ctl->server.authenticate == A_NTLM || ctl->server.authenticate == A_MSN)
-    {
-       report(stderr,
-          GT_("Required NTLM capability not compiled into fetchmail\n"));
-    }
-#endif
-
-    switch (ctl->server.protocol) {
+   switch (ctl->server.protocol) {
     case P_POP3:
 #ifdef RPA_ENABLE
        /* XXX FIXME: AUTH probing (RFC1734) should become global */
@@ -440,16 +440,17 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
            if (ctl->sslcommonname)
                commonname = ctl->sslcommonname;
 
-          if (has_stls)
+          if (has_stls
+                  || must_tls(ctl)) /* if TLS is mandatory, ignore capabilities */
           {
               /* Use "tls1" rather than ctl->sslproto because tls1 is the only
                * protocol that will work with STARTTLS.  Don't need to worry
                * whether TLS is mandatory or opportunistic unless SSLOpen() fails
                * (see below). */
               if (gen_transact(sock, "STLS") == PS_SUCCESS
-                      && SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
+                      && (set_timeout(mytimeout), SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
                           ctl->sslcertfile, ctl->sslcertpath, ctl->sslfingerprint, commonname,
-                          ctl->server.pollname, &ctl->remotename) != -1)
+                          ctl->server.pollname, &ctl->remotename)) != -1)
               {
                   /*
                    * RFC 2595 says this:
@@ -464,7 +465,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
                    * Now that we're confident in our TLS connection we can
                    * guarantee a secure capability re-probe.
                    */
-                  got_tls = TRUE;
+                  set_timeout(0);
                   done_capa = FALSE;
                   ok = capa_probe(sock);
                   if (ok != PS_SUCCESS) {
@@ -474,13 +475,10 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
                   {
                       report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), commonname);
                   }
-              }
-          }
-
-          if (!got_tls) {
-              if (must_tls(ctl)) {
+              } else if (must_tls(ctl)) {
                   /* Config required TLS but we couldn't guarantee it, so we must
                    * stop. */
+                  set_timeout(0);
                   report(stderr, GT_("%s: upgrade to TLS failed.\n"), commonname);
                   return PS_SOCKET;
               } else {
@@ -489,6 +487,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
                    * allowed til post-authentication), so leave it in an unknown
                    * state, mark it as such, and check more carefully if things
                    * go wrong when we try to authenticate. */
+                  set_timeout(0);
                   connection_may_have_tls_errors = TRUE;
                   if (outlevel >= O_VERBOSE)
                   {
@@ -542,7 +541,25 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
        }
 #endif /* OPIE_ENABLE */
 
-       if (ctl->server.authenticate == A_CRAM_MD5 || 
+#ifdef NTLM_ENABLE
+    /* MSN servers require the use of NTLM (MSN) authentication */
+    if (!strcasecmp(ctl->server.pollname, "pop3.email.msn.com") ||
+           ctl->server.authenticate == A_MSN)
+       return (do_pop3_ntlm(sock, ctl, 1) == 0) ? PS_SUCCESS : PS_AUTHFAIL;
+    if (ctl->server.authenticate == A_NTLM || (has_ntlm && ctl->server.authenticate == A_ANY)) {
+       ok = do_pop3_ntlm(sock, ctl, 0);
+        if (ok == 0 || ctl->server.authenticate != A_ANY)
+           break;
+    }
+#else
+    if (ctl->server.authenticate == A_NTLM || ctl->server.authenticate == A_MSN)
+    {
+       report(stderr,
+          GT_("Required NTLM capability not compiled into fetchmail\n"));
+    }
+#endif
+
+       if (ctl->server.authenticate == A_CRAM_MD5 || 
            (has_cram && ctl->server.authenticate == A_ANY))
        {
            ok = do_cram_md5(sock, "AUTH", ctl, NULL);
@@ -798,6 +815,7 @@ static int pop3_fastuidl( int sock,  struct query *ctl, unsigned int count, int
     int ok;
     unsigned int first_nr, last_nr, try_nr;
     char id [IDLEN+1];
+    struct idlist *savep = NULL; /** pointer to cache save_str result, speeds up saves */
 
     first_nr = 0;
     last_nr = count + 1;
@@ -839,8 +857,8 @@ static int pop3_fastuidl( int sock,  struct query *ctl, unsigned int count, int
            last_nr = try_nr;
 
            /* save it */
-           newl = save_str(&ctl->oldsaved, id, UID_UNSEEN);
-           newl->val.status.num = try_nr;
+           savep = save_str(savep ? &savep : &ctl->oldsaved, id, UID_UNSEEN);
+           savep->val.status.num = try_nr;
        }
     }
     if (outlevel >= O_DEBUG && last_nr <= count)
@@ -1040,6 +1058,7 @@ static int pop3_getrange(int sock,
            {
                /* UIDL worked - parse reply */
                unsigned long unum;
+               struct idlist *newl = NULL;
 
                *newp = 0;
                while (gen_recv(sock, buf, sizeof(buf)) == PS_SUCCESS)
@@ -1049,9 +1068,9 @@ static int pop3_getrange(int sock,
 
                    if (parseuid(buf, &unum, id, sizeof(id)) == PS_SUCCESS)
                    {
-                       struct idlist   *old, *newl;
+                       struct idlist   *old;
 
-                       newl = save_str(&ctl->newsaved, id, UID_UNSEEN);
+                       newl = save_str(newl ? &newl : &ctl->newsaved, id, UID_UNSEEN);
                        newl->val.status.num = unum;
 
                        if ((old = str_in_list(&ctl->oldsaved, id, FALSE)))