]> Pileus Git - ~andy/fetchmail/blob - pop3.c
Rediff patch.
[~andy/fetchmail] / pop3.c
1 /*
2  * pop3.c -- POP3 protocol methods
3  *
4  * Copyright 1998 by Eric S. Raymond.
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include  "config.h"
9 #ifdef POP3_ENABLE
10 #include  <stdio.h>
11 #include  <string.h>
12 #include  <ctype.h>
13 #include <unistd.h>
14 #include  <stdlib.h>
15 #include  <errno.h>
16
17 #include  "fetchmail.h"
18 #include  "socket.h"
19 #include  "gettext.h"
20 #include  "uid_db.h"
21
22 #ifdef OPIE_ENABLE
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 #include <opie.h>
27 #ifdef __cplusplus
28 }
29 #endif
30 #endif /* OPIE_ENABLE */
31
32 /* global variables: please reinitialize them explicitly for proper
33  * working in daemon mode */
34
35 /* TODO: session variables to be initialized before server greeting */
36 #ifdef OPIE_ENABLE
37 static char lastok[POPBUFSIZE+1];
38 #endif /* OPIE_ENABLE */
39
40 /* session variables initialized in capa_probe() or pop3_getauth() */
41 flag done_capa = FALSE;
42 #if defined(GSSAPI)
43 flag has_gssapi = FALSE;
44 #endif /* defined(GSSAPI) */
45 #if defined(KERBEROS_V5)
46 flag has_kerberos = FALSE;
47 #endif /* defined(KERBEROS_V5) */
48 static flag has_cram = FALSE;
49 #ifdef OPIE_ENABLE
50 flag has_otp = FALSE;
51 #endif /* OPIE_ENABLE */
52 #ifdef NTLM_ENABLE
53 flag has_ntlm = FALSE;
54 #endif /* NTLM_ENABLE */
55 #ifdef SSL_ENABLE
56 static flag has_stls = FALSE;
57 #endif /* SSL_ENABLE */
58
59 /* mailbox variables initialized in pop3_getrange() */
60 static int last;
61
62 /* mail variables initialized in pop3_fetch() */
63 #ifdef SDPS_ENABLE
64 char *sdps_envfrom;
65 char *sdps_envto;
66 #endif /* SDPS_ENABLE */
67
68 #ifdef NTLM_ENABLE
69 #include "ntlm.h"
70
71 /*
72  * NTLM support by Grant Edwards.
73  *
74  * Handle MS-Exchange NTLM authentication method.  This is the same
75  * as the NTLM auth used by Samba for SMB related services. We just
76  * encode the packets in base64 instead of sending them out via a
77  * network interface.
78  * 
79  * Much source (ntlm.h, smb*.c smb*.h) was borrowed from Samba.
80  */
81
82 static int do_pop3_ntlm(int sock, struct query *ctl,
83         int msn_instead /** if true, send AUTH MSN, else send AUTH NTLM */)
84 {
85     char msgbuf[POPBUFSIZE+1];
86     int result;
87
88     gen_send(sock, msn_instead ? "AUTH MSN" : "AUTH NTLM");
89
90     if ((result = ntlm_helper(sock, ctl, "POP3")))
91         return result;
92
93     if ((result = gen_recv (sock, msgbuf, sizeof msgbuf)))
94         return result;
95
96     if (strstr (msgbuf, "OK"))
97         return PS_SUCCESS;
98     else
99         return PS_AUTHFAIL;
100 }
101 #endif /* NTLM */
102
103
104 #define DOTLINE(s)      (s[0] == '.' && (s[1]=='\r'||s[1]=='\n'||s[1]=='\0'))
105
106 static int pop3_ok (int sock, char *argbuf)
107 /* parse command response */
108 {
109     int ok;
110     char buf [POPBUFSIZE+1];
111     char *bufp;
112
113     if ((ok = gen_recv(sock, buf, sizeof(buf))) == 0)
114     {   bufp = buf;
115         if (*bufp == '+' || *bufp == '-')
116             bufp++;
117         else
118             return(PS_PROTOCOL);
119
120         while (isalpha((unsigned char)*bufp))
121             bufp++;
122
123         if (*bufp)
124           *(bufp++) = '\0';
125
126         if (strcmp(buf,"+OK") == 0)
127         {
128 #ifdef OPIE_ENABLE
129             strcpy(lastok, bufp);
130 #endif /* OPIE_ENABLE */
131             ok = 0;
132         }
133         else if (strncmp(buf,"-ERR", 4) == 0)
134         {
135             if (stage == STAGE_FETCH)
136                 ok = PS_TRANSIENT;
137             else if (stage > STAGE_GETAUTH)
138                 ok = PS_PROTOCOL;
139             /*
140              * We're checking for "lock busy", "unable to lock", 
141              * "already locked", "wait a few minutes" etc. here. 
142              * This indicates that we have to wait for the server to
143              * unwedge itself before we can poll again.
144              *
145              * PS_LOCKBUSY check empirically verified with two recent
146              * versions of the Berkeley popper; QPOP (version 2.2)  and
147              * QUALCOMM Pop server derived from UCB (version 2.1.4-R3)
148              * These are caught by the case-indifferent "lock" check.
149              * The "wait" catches "mail storage services unavailable,
150              * wait a few minutes and try again" on the InterMail server.
151              *
152              * If these aren't picked up on correctly, fetchmail will 
153              * think there is an authentication failure and wedge the
154              * connection in order to prevent futile polls.
155              *
156              * Gad, what a kluge.
157              */
158             else if (strstr(bufp,"lock")
159                      || strstr(bufp,"Lock")
160                      || strstr(bufp,"LOCK")
161                      || strstr(bufp,"wait")
162                      /* these are blessed by RFC 2449 */
163                      || strstr(bufp,"[IN-USE]")||strstr(bufp,"[LOGIN-DELAY]"))
164                 ok = PS_LOCKBUSY;
165             else if ((strstr(bufp,"Service")
166                      || strstr(bufp,"service"))
167                          && (strstr(bufp,"unavailable")))
168                 ok = PS_SERVBUSY;
169             else
170                 ok = PS_AUTHFAIL;
171             /*
172              * We always want to pass the user lock-busy messages, because
173              * they're red flags.  Other stuff (like AUTH failures on non-
174              * RFC1734 servers) only if we're debugging.
175              */
176             if (*bufp && (ok == PS_LOCKBUSY || outlevel >= O_MONITOR))
177               report(stderr, "%s\n", bufp);
178         }
179         else
180             ok = PS_PROTOCOL;
181
182 #if POPBUFSIZE > MSGBUFSIZE
183 #error "POPBUFSIZE must not be larger than MSGBUFSIZE"
184 #endif
185         if (argbuf != NULL)
186             strcpy(argbuf,bufp);
187     }
188
189     return(ok);
190 }
191
192
193
194 static int capa_probe(int sock)
195 /* probe the capabilities of the remote server */
196 {
197     int ok;
198
199     if (done_capa) {
200         return PS_SUCCESS;
201     }
202 #if defined(GSSAPI)
203     has_gssapi = FALSE;
204 #endif /* defined(GSSAPI) */
205 #if defined(KERBEROS_V5)
206     has_kerberos = FALSE;
207 #endif /* defined(KERBEROS_V5) */
208     has_cram = FALSE;
209 #ifdef OPIE_ENABLE
210     has_otp = FALSE;
211 #endif /* OPIE_ENABLE */
212 #ifdef NTLM_ENABLE
213     has_ntlm = FALSE;
214 #endif /* NTLM_ENABLE */
215
216     ok = gen_transact(sock, "CAPA");
217     if (ok == PS_SUCCESS)
218     {
219         char buffer[64];
220
221         /* determine what authentication methods we have available */
222         while ((ok = gen_recv(sock, buffer, sizeof(buffer))) == 0)
223         {
224             if (DOTLINE(buffer))
225                 break;
226
227 #ifdef SSL_ENABLE
228             if (strstr(buffer, "STLS"))
229                 has_stls = TRUE;
230 #endif /* SSL_ENABLE */
231
232 #if defined(GSSAPI)
233             if (strstr(buffer, "GSSAPI"))
234                 has_gssapi = TRUE;
235 #endif /* defined(GSSAPI) */
236
237 #ifdef OPIE_ENABLE
238             if (strstr(buffer, "X-OTP"))
239                 has_otp = TRUE;
240 #endif /* OPIE_ENABLE */
241
242 #ifdef NTLM_ENABLE
243             if (strstr(buffer, "NTLM"))
244                 has_ntlm = TRUE;
245 #endif /* NTLM_ENABLE */
246
247             if (strstr(buffer, "CRAM-MD5"))
248                 has_cram = TRUE;
249         }
250     }
251     done_capa = TRUE;
252     return(ok);
253 }
254
255 static void set_peek_capable(struct query *ctl)
256 {
257     /* we're peek-capable means that the use of TOP is enabled,
258      * see pop3_fetch for details - short story, we can use TOP if
259      * we have a means of reliably tracking which mail we need to
260      * refetch should the connection abort in the middle.
261      * fetchall forces RETR, as does keep without UIDL */
262     peek_capable = !ctl->fetchall;
263 }
264
265 static int do_apop(int sock, struct query *ctl, char *greeting)
266 {
267     char *start, *end;
268
269     /* build MD5 digest from greeting timestamp + password */
270     /* find start of timestamp */
271     start = strchr(greeting, '<');
272     if (!start) {
273         report(stderr,
274                 GT_("Required APOP timestamp not found in greeting\n"));
275         return PS_AUTHFAIL;
276     }
277
278     /* find end of timestamp */
279     end = strchr(start + 1, '>');
280
281     if (!end || end == start + 1) {
282         report(stderr,
283                 GT_("Timestamp syntax error in greeting\n"));
284         return(PS_AUTHFAIL);
285     } else {
286         *++end = '\0';
287     }
288
289     /* SECURITY: 2007-03-17
290      * Strictly validating the presented challenge for RFC-822
291      * conformity (it must be a msg-id in terms of that standard) is
292      * supposed to make attacks against the MD5 implementation
293      * harder[1]
294      *
295      * [1] "Security vulnerability in APOP authentication",
296      *     Gaëtan Leurent, fetchmail-devel, 2007-03-17 */
297     if (!rfc822_valid_msgid((unsigned char *)start)) {
298         report(stderr,
299                 GT_("Invalid APOP timestamp.\n"));
300         return PS_AUTHFAIL;
301     }
302
303     /* copy timestamp and password into digestion buffer */
304     char *msg = (char *)xmalloc((end-start+1) + strlen(ctl->password) + 1);
305     strcpy(msg,start);
306     strcat(msg,ctl->password);
307     strcpy((char *)ctl->digest, MD5Digest((unsigned char *)msg));
308     free(msg);
309
310     return gen_transact(sock, "APOP %s %s", ctl->remotename, (char *)ctl->digest);
311 }
312
313 static int pop3_getauth(int sock, struct query *ctl, char *greeting)
314 /* apply for connection authorization */
315 {
316     int ok;
317 #ifdef OPIE_ENABLE
318     char *challenge;
319 #endif /* OPIE_ENABLE */
320 #ifdef SSL_ENABLE
321     flag connection_may_have_tls_errors = FALSE;
322 #endif /* SSL_ENABLE */
323
324     done_capa = FALSE;
325 #if defined(GSSAPI)
326     has_gssapi = FALSE;
327 #endif /* defined(GSSAPI) */
328 #if defined(KERBEROS_V5)
329     has_kerberos = FALSE;
330 #endif /* defined(KERBEROS_V5) */
331     has_cram = FALSE;
332 #ifdef OPIE_ENABLE
333     has_otp = FALSE;
334 #endif /* OPIE_ENABLE */
335 #ifdef SSL_ENABLE
336     has_stls = FALSE;
337 #endif /* SSL_ENABLE */
338
339     /* Set this up before authentication quits early. */
340     set_peek_capable(ctl);
341
342     /* Hack: allow user to force RETR. */
343     if (peek_capable && getenv("FETCHMAIL_POP3_FORCE_RETR")) {
344         peek_capable = 0;
345     }
346
347     /*
348      * The "Maillennium POP3/PROXY server" deliberately truncates
349      * TOP replies after c. 64 or 80 kByte (we have varying reports), so
350      * disable TOP. Comcast once spewed marketing babble to the extent
351      * of protecting Outlook -- pretty overzealous to break a protocol
352      * for that that Microsoft could have read, too. Comcast aren't
353      * alone in using this software though.
354      * <http://lists.ccil.org/pipermail/fetchmail-friends/2004-April/008523.html>
355      * (Thanks to Ed Wilts for reminding me of that.)
356      *
357      * The warning is printed once per server, until fetchmail exits.
358      * It will be suppressed when --fetchall or other circumstances make
359      * us use RETR anyhow.
360      *
361      * Matthias Andree
362      */
363     if (peek_capable && strstr(greeting, "Maillennium POP3/PROXY server")) {
364         if ((ctl->server.workarounds & WKA_TOP) == 0) {
365             report(stdout, GT_("Warning: \"Maillennium POP3/PROXY server\" found, using RETR command instead of TOP.\n"));
366             ctl->server.workarounds |= WKA_TOP;
367         }
368         peek_capable = 0;
369     }
370     if (ctl->server.authenticate == A_SSH) {
371         return PS_SUCCESS;
372     }
373
374 #ifdef SDPS_ENABLE
375     /*
376      * This needs to catch both demon.co.uk and demon.net.
377      * If we see either, and we're in multidrop mode, try to use
378      * the SDPS *ENV extension.
379      */
380     if (!(ctl->server.sdps) && MULTIDROP(ctl) && strstr(greeting, "demon."))
381         ctl->server.sdps = TRUE;
382 #endif /* SDPS_ENABLE */
383
384     /* this is a leftover from the times 6.3.X and older when APOP was a
385      * "protocol" (P_APOP) rather than an authenticator (A_APOP),
386      * however, the switch is still useful because we can break; after
387      * an authenticator failed. */
388    switch (ctl->server.protocol) {
389    case P_POP3:
390 #ifdef RPA_ENABLE
391         /* XXX FIXME: AUTH probing (RFC1734) should become global */
392         /* CompuServe POP3 Servers as of 990730 want AUTH first for RPA */
393         if (strstr(ctl->remotename, "@compuserve.com"))
394         {
395             /* AUTH command should return a list of available mechanisms */
396             if (gen_transact(sock, "AUTH") == 0)
397             {
398                 char buffer[10];
399                 flag has_rpa = FALSE;
400
401                 while ((ok = gen_recv(sock, buffer, sizeof(buffer))) == 0)
402                 {
403                     if (DOTLINE(buffer))
404                         break;
405                     if (strncasecmp(buffer, "rpa", 3) == 0)
406                         has_rpa = TRUE;
407                 }
408                 if (has_rpa && !POP3_auth_rpa(ctl->remotename, 
409                                               ctl->password, sock))
410                     return(PS_SUCCESS);
411             }
412
413             return(PS_AUTHFAIL);
414         }
415 #endif /* RPA_ENABLE */
416
417         /*
418          * CAPA command may return a list including available
419          * authentication mechanisms and STLS capability.
420          *
421          * If it doesn't, no harm done, we just fall back to a plain
422          * login -- if the user allows it.
423          *
424          * Note that this code latches the server's authentication type,
425          * so that in daemon mode the CAPA check only needs to be done
426          * once at start of run.
427          *
428          * If CAPA fails, then force the authentication method to
429          * PASSWORD, switch off opportunistic and repoll immediately.
430          * If TLS is mandatory, fail up front.
431          */
432         if ((ctl->server.authenticate == A_ANY) ||
433                 (ctl->server.authenticate == A_GSSAPI) ||
434                 (ctl->server.authenticate == A_KERBEROS_V5) ||
435                 (ctl->server.authenticate == A_OTP) ||
436                 (ctl->server.authenticate == A_CRAM_MD5) ||
437                 maybe_tls(ctl))
438         {
439             if ((ok = capa_probe(sock)) != PS_SUCCESS)
440                 /* we are in STAGE_GETAUTH => failure is PS_AUTHFAIL! */
441                 if (ok == PS_AUTHFAIL ||
442                     /* Some servers directly close the socket. However, if we
443                      * have already authenticated before, then a previous CAPA
444                      * must have succeeded. In that case, treat this as a
445                      * genuine socket error and do not change the auth method.
446                      */
447                     (ok == PS_SOCKET && !ctl->wehaveauthed))
448                 {
449 #ifdef SSL_ENABLE
450                     if (must_tls(ctl)) {
451                         /* fail with mandatory STLS without repoll */
452                         report(stderr, GT_("TLS is mandatory for this session, but server refused CAPA command.\n"));
453                         report(stderr, GT_("The CAPA command is however necessary for TLS.\n"));
454                         return ok;
455                     } else if (maybe_tls(ctl)) {
456                         /* defeat opportunistic STLS */
457                         xfree(ctl->sslproto);
458                         ctl->sslproto = xstrdup("");
459                     }
460 #endif
461                     /* If strong authentication was opportunistic, retry without, else fail. */
462                     switch (ctl->server.authenticate) {
463                         case A_ANY:
464                             ctl->server.authenticate = A_PASSWORD;
465                             /* FALLTHROUGH */
466                         case A_PASSWORD: /* this should only happen with TLS enabled */
467                             return PS_REPOLL;
468                         default:
469                             return PS_AUTHFAIL;
470                     }
471                 }
472         }
473
474 #ifdef SSL_ENABLE
475         if (maybe_tls(ctl)) {
476             char *commonname;
477
478             commonname = ctl->server.pollname;
479             if (ctl->server.via)
480                 commonname = ctl->server.via;
481             if (ctl->sslcommonname)
482                 commonname = ctl->sslcommonname;
483
484            if (has_stls
485                    || must_tls(ctl)) /* if TLS is mandatory, ignore capabilities */
486            {
487                /* Use "tls1" rather than ctl->sslproto because tls1 is the only
488                 * protocol that will work with STARTTLS.  Don't need to worry
489                 * whether TLS is mandatory or opportunistic unless SSLOpen() fails
490                 * (see below). */
491                if (gen_transact(sock, "STLS") == PS_SUCCESS
492                        && (set_timeout(mytimeout), SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
493                            ctl->sslcertfile, ctl->sslcertpath, ctl->sslfingerprint, commonname,
494                            ctl->server.pollname, &ctl->remotename)) != -1)
495                {
496                    /*
497                     * RFC 2595 says this:
498                     *
499                     * "Once TLS has been started, the client MUST discard cached
500                     * information about server capabilities and SHOULD re-issue the
501                     * CAPABILITY command.  This is necessary to protect against
502                     * man-in-the-middle attacks which alter the capabilities list prior
503                     * to STARTTLS.  The server MAY advertise different capabilities
504                     * after STARTTLS."
505                     *
506                     * Now that we're confident in our TLS connection we can
507                     * guarantee a secure capability re-probe.
508                     */
509                    set_timeout(0);
510                    done_capa = FALSE;
511                    ok = capa_probe(sock);
512                    if (ok != PS_SUCCESS) {
513                        return ok;
514                    }
515                    if (outlevel >= O_VERBOSE)
516                    {
517                        report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), commonname);
518                    }
519                } else if (must_tls(ctl)) {
520                    /* Config required TLS but we couldn't guarantee it, so we must
521                     * stop. */
522                    set_timeout(0);
523                    report(stderr, GT_("%s: upgrade to TLS failed.\n"), commonname);
524                    return PS_SOCKET;
525                } else {
526                    /* We don't know whether the connection is usable, and there's
527                     * no command we can reasonably issue to test it (NOOP isn't
528                     * allowed til post-authentication), so leave it in an unknown
529                     * state, mark it as such, and check more carefully if things
530                     * go wrong when we try to authenticate. */
531                    set_timeout(0);
532                    connection_may_have_tls_errors = TRUE;
533                    if (outlevel >= O_VERBOSE)
534                    {
535                        report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue.\n"), commonname);
536                    }
537                }
538            }
539         } /* maybe_tls() */
540 #endif /* SSL_ENABLE */
541
542         /*
543          * OK, we have an authentication type now.
544          */
545
546 #if defined(GSSAPI)
547         if (has_gssapi &&
548             (ctl->server.authenticate == A_GSSAPI ||
549             (ctl->server.authenticate == A_ANY
550              && check_gss_creds("pop", ctl->server.truename) == PS_SUCCESS)))
551         {
552             ok = do_gssauth(sock,"AUTH","pop",ctl->server.truename,ctl->remotename);
553             if (ok == PS_SUCCESS || ctl->server.authenticate != A_ANY)
554                 break;
555         }
556 #endif /* defined(GSSAPI) */
557
558 #ifdef OPIE_ENABLE
559         if (has_otp &&
560             (ctl->server.authenticate == A_OTP ||
561              ctl->server.authenticate == A_ANY))
562         {
563             ok = do_otp(sock, "AUTH", ctl);
564             if (ok == PS_SUCCESS || ctl->server.authenticate != A_ANY)
565                 break;
566         }
567 #endif /* OPIE_ENABLE */
568
569 #ifdef NTLM_ENABLE
570         /* MSN servers require the use of NTLM (MSN) authentication */
571         if (!strcasecmp(ctl->server.pollname, "pop3.email.msn.com") ||
572                 ctl->server.authenticate == A_MSN)
573             return (do_pop3_ntlm(sock, ctl, 1) == 0) ? PS_SUCCESS : PS_AUTHFAIL;
574         if (ctl->server.authenticate == A_NTLM || (has_ntlm && ctl->server.authenticate == A_ANY)) {
575             ok = do_pop3_ntlm(sock, ctl, 0);
576             if (ok == 0 || ctl->server.authenticate != A_ANY)
577                 break;
578         }
579 #else
580         if (ctl->server.authenticate == A_NTLM || ctl->server.authenticate == A_MSN)
581         {
582             report(stderr,
583                     GT_("Required NTLM capability not compiled into fetchmail\n"));
584         }
585 #endif
586
587         if (ctl->server.authenticate == A_CRAM_MD5 ||
588                 (has_cram && ctl->server.authenticate == A_ANY))
589         {
590             ok = do_cram_md5(sock, "AUTH", ctl, NULL);
591             if (ok == PS_SUCCESS || ctl->server.authenticate != A_ANY)
592                 break;
593         }
594
595         if (ctl->server.authenticate == A_APOP
596                     || ctl->server.authenticate == A_ANY)
597         {
598             ok = do_apop(sock, ctl, greeting);
599             if (ok == PS_SUCCESS || ctl->server.authenticate != A_ANY)
600                 break;
601         }
602
603         /* ordinary validation, no one-time password or RPA */ 
604         if ((ok = gen_transact(sock, "USER %s", ctl->remotename)))
605             break;
606
607 #ifdef OPIE_ENABLE
608         /* see RFC1938: A One-Time Password System */
609         if ((challenge = strstr(lastok, "otp-"))) {
610           char response[OPIE_RESPONSE_MAX+1];
611           int i;
612           char *n = xstrdup("");
613
614           i = opiegenerator(challenge, !strcmp(ctl->password, "opie") ? n : ctl->password, response);
615           free(n);
616           if ((i == -2) && !run.poll_interval) {
617             char secret[OPIE_SECRET_MAX+1];
618             fprintf(stderr, GT_("Secret pass phrase: "));
619             if (opiereadpass(secret, sizeof(secret), 0))
620               i = opiegenerator(challenge,  secret, response);
621             memset(secret, 0, sizeof(secret));
622           };
623
624           if (i) {
625             ok = PS_ERROR;
626             break;
627           };
628
629           ok = gen_transact(sock, "PASS %s", response);
630           break;
631         }
632 #endif /* OPIE_ENABLE */
633
634         /* KPOP uses out-of-band authentication and does not check what
635          * we send here, so send some random fixed string, to avoid
636          * users switching *to* KPOP accidentally revealing their
637          * password */
638         if ((ctl->server.authenticate == A_ANY
639                     || ctl->server.authenticate == A_KERBEROS_V5)
640                 && (ctl->server.service != NULL
641                     && strcmp(ctl->server.service, KPOP_PORT) == 0))
642         {
643             ok = gen_transact(sock, "PASS krb_ticket");
644             break;
645         }
646
647         /* check if we are actually allowed to send the password */
648         if (ctl->server.authenticate == A_ANY
649                 || ctl->server.authenticate == A_PASSWORD) {
650             strlcpy(shroud, ctl->password, sizeof(shroud));
651             ok = gen_transact(sock, "PASS %s", ctl->password);
652         } else {
653             report(stderr, GT_("We've run out of allowed authenticators and cannot continue.\n"));
654             ok = PS_AUTHFAIL;
655         }
656         memset(shroud, 0x55, sizeof(shroud));
657         shroud[0] = '\0';
658         break;
659
660     default:
661         report(stderr, GT_("Undefined protocol request in POP3_auth\n"));
662         ok = PS_ERROR;
663     }
664
665 #ifdef SSL_ENABLE
666     /* this is for servers which claim to support TLS, but actually
667      * don't! */
668     if (connection_may_have_tls_errors
669                     && (ok == PS_SOCKET || ok == PS_PROTOCOL))
670     {
671         xfree(ctl->sslproto);
672         ctl->sslproto = xstrdup("");
673         /* repoll immediately without TLS */
674         ok = PS_REPOLL;
675     }
676 #endif
677
678     if (ok != 0)
679     {
680         /* maybe we detected a lock-busy condition? */
681         if (ok == PS_LOCKBUSY)
682             report(stderr, GT_("lock busy!  Is another session active?\n")); 
683
684         return(ok);
685     }
686
687     /* we're approved */
688     return(PS_SUCCESS);
689 }
690
691 /* cut off C string at first POSIX space */
692 static void trim(char *s) {
693     s += strcspn(s, POSIX_space);
694     s[0] = '\0';
695 }
696
697 /** Parse the UID response (leading +OK must have been
698  * stripped off) in buf, store the number in gotnum, and store the ID
699  * into the caller-provided buffer "id" of size "idsize".
700  * Returns PS_SUCCESS or PS_PROTOCOL for failure. */
701 static int parseuid(const char *buf, unsigned long *gotnum, char *id, size_t idsize)
702 {
703     const char *i;
704     char *j;
705
706     /* skip leading blanks ourselves */
707     i = buf;
708     i += strspn(i, POSIX_space);
709     errno = 0;
710     *gotnum = strtoul(i, &j, 10);
711     if (j == i || !*j || errno || NULL == strchr(POSIX_space, *j)) {
712         report(stderr, GT_("Cannot handle UIDL response from upstream server.\n"));
713         return PS_PROTOCOL;
714     }
715     j += strspn(j, POSIX_space);
716     strlcpy(id, j, idsize);
717     trim(id);
718     return PS_SUCCESS;
719 }
720
721 /** request UIDL for single message \a num and stuff the result into the
722  * buffer \a id which can hold \a idsize bytes */
723 static int pop3_getuidl(int sock, int num, char *id /** output */, size_t idsize)
724 {
725     int ok;
726     char buf [POPBUFSIZE+1];
727     unsigned long gotnum;
728
729     gen_send(sock, "UIDL %d", num);
730     if ((ok = pop3_ok(sock, buf)) != 0)
731         return(ok);
732     if ((ok = parseuid(buf, &gotnum, id, idsize)))
733         return ok;
734     if (gotnum != (unsigned long)num) {
735         report(stderr, GT_("Server responded with UID for wrong message.\n"));
736         return PS_PROTOCOL;
737     }
738     return(PS_SUCCESS);
739 }
740
741 static int pop3_fastuidl( int sock,  struct query *ctl, unsigned int count, int *newp)
742 {
743     int ok;
744     unsigned int first_nr, last_nr, try_nr;
745     char id [IDLEN+1];
746
747     first_nr = 0;
748     last_nr = count + 1;
749     while (first_nr < last_nr - 1)
750     {
751         struct uid_db_record *rec;
752
753         try_nr = (first_nr + last_nr) / 2;
754         if ((ok = pop3_getuidl(sock, try_nr, id, sizeof(id))) != 0)
755             return ok;
756         if ((rec = find_uid_by_id(&ctl->oldsaved, id)))
757         {
758             flag mark = rec->status;
759             if (mark == UID_DELETED || mark == UID_EXPUNGED)
760             {
761                 if (outlevel >= O_VERBOSE)
762                     report(stderr, GT_("id=%s (num=%u) was deleted, but is still present!\n"), id, try_nr);
763                 /* just mark it as seen now! */
764                 rec->status = mark = UID_SEEN;
765             }
766
767             /* narrow the search region! */
768             if (mark == UID_UNSEEN)
769             {
770                 if (outlevel >= O_DEBUG)
771                     report(stdout, GT_("%u is unseen\n"), try_nr);
772                 last_nr = try_nr;
773             }
774             else
775                 first_nr = try_nr;
776
777             /* save the number */
778             set_uid_db_num(&ctl->oldsaved, rec, try_nr);
779         }
780         else
781         {
782             if (outlevel >= O_DEBUG)
783                 report(stdout, GT_("%u is unseen\n"), try_nr);
784             last_nr = try_nr;
785
786             /* save it */
787             rec = uid_db_insert(&ctl->oldsaved, id, UID_UNSEEN);
788             set_uid_db_num(&ctl->oldsaved, rec, try_nr);
789         }
790     }
791     if (outlevel >= O_DEBUG && last_nr <= count)
792         report(stdout, GT_("%u is first unseen\n"), last_nr);
793
794     /* update last! */
795     *newp = count - first_nr;
796     last = first_nr;
797     return 0;
798 }
799
800 static int pop3_getrange(int sock, 
801                          struct query *ctl,
802                          const char *folder,
803                          int *countp, int *newp, int *bytes)
804 /* get range of messages to be fetched */
805 {
806     int ok;
807     char buf [POPBUFSIZE+1];
808
809     (void)folder;
810     /* Ensure that the new list is properly empty */
811     clear_uid_db(&ctl->newsaved);
812
813 #ifdef MBOX
814     /* Alain Knaff suggests this, but it's not RFC standard */
815     if (folder)
816         if ((ok = gen_transact(sock, "MBOX %s", folder)))
817             return ok;
818 #endif /* MBOX */
819
820     /* get the total message count */
821     gen_send(sock, "STAT");
822     ok = pop3_ok(sock, buf);
823     if (ok == 0) {
824         int asgn;
825
826         asgn = sscanf(buf,"%d %d", countp, bytes);
827         if (asgn != 2)
828                 return PS_PROTOCOL;
829     } else
830         return(ok);
831
832     /* unless fetching all mail, get UID list (UIDL) */
833     last = 0;
834     *newp = -1;
835     if (*countp > 0)
836     {
837         int fastuidl;
838         char id [IDLEN+1];
839
840         set_uid_db_num_pos_0(&ctl->oldsaved, *countp);
841         set_uid_db_num_pos_0(&ctl->newsaved, *countp);
842
843         /* should we do fast uidl this time? */
844         fastuidl = ctl->fastuidl;
845         if (*countp > 7 &&              /* linear search is better if there are few mails! */
846             !ctl->fetchall &&           /* with fetchall, all uids are required */
847             !ctl->flush &&              /* with flush, it is safer to disable fastuidl */
848             NUM_NONZERO (fastuidl))
849         {
850             if (fastuidl == 1)
851                 dofastuidl = 1;
852             else
853                 dofastuidl = ctl->fastuidlcount != 0;
854         }
855         else
856             dofastuidl = 0;
857
858         {
859             /* do UIDL */
860             if (dofastuidl)
861                 return(pop3_fastuidl( sock, ctl, *countp, newp));
862             /* grab the mailbox's UID list */
863             if (gen_transact(sock, "UIDL") != 0)
864             {
865                 if (!ctl->fetchall) {
866                     report(stderr, GT_("protocol error while fetching UIDLs\n"));
867                     return(PS_ERROR);
868                 }
869             }
870             else
871             {
872                 /* UIDL worked - parse reply */
873                 unsigned long unum;
874
875                 *newp = 0;
876                 while (gen_recv(sock, buf, sizeof(buf)) == PS_SUCCESS)
877                 {
878                     if (DOTLINE(buf))
879                         break;
880
881                     if (parseuid(buf, &unum, id, sizeof(id)) == PS_SUCCESS)
882                     {
883                         struct uid_db_record    *old_rec, *new_rec;
884
885                         new_rec = uid_db_insert(&ctl->newsaved, id, UID_UNSEEN);
886
887                         if ((old_rec = find_uid_by_id(&ctl->oldsaved, id)))
888                         {
889                             flag mark = old_rec->status;
890                             if (mark == UID_DELETED || mark == UID_EXPUNGED)
891                             {
892                                 /* XXX FIXME: switch 3 occurrences from
893                                  * (int)unum or (unsigned int)unum to
894                                  * remove the cast and use %lu - not now
895                                  * though, time for new release */
896                                 if (outlevel >= O_VERBOSE)
897                                     report(stderr, GT_("id=%s (num=%d) was deleted, but is still present!\n"), id, (int)unum);
898                                 /* just mark it as seen now! */
899                                 old_rec->status = mark = UID_SEEN;
900                             }
901                             new_rec->status = mark;
902                             if (mark == UID_UNSEEN)
903                             {
904                                 (*newp)++;
905                                 if (outlevel >= O_DEBUG)
906                                     report(stdout, GT_("%u is unseen\n"), (unsigned int)unum);
907                             }
908                         }
909                         else
910                         {
911                             (*newp)++;
912                             if (outlevel >= O_DEBUG)
913                                 report(stdout, GT_("%u is unseen\n"), (unsigned int)unum);
914                             /* add it to oldsaved also! In case, we do not
915                              * swap the lists (say, due to socket error),
916                              * the same mail will not be downloaded again.
917                              */
918                             old_rec = uid_db_insert(&ctl->oldsaved, id, UID_UNSEEN);
919
920                         }
921                         /*
922                          * save the number if it will be needed later on
923                          * (messsage will either be fetched or deleted)
924                          */
925                         if (new_rec->status == UID_UNSEEN || ctl->flush) {
926                             set_uid_db_num(&ctl->oldsaved, old_rec, unum);
927                             set_uid_db_num(&ctl->newsaved, new_rec, unum);
928                         }
929                     } else
930                         return PS_ERROR;
931                 } /* multi-line loop for UIDL reply */
932             } /* UIDL parser */
933         } /* do UIDL */
934     }
935
936     return(PS_SUCCESS);
937 }
938
939 static int pop3_getpartialsizes(int sock, int first, int last, int *sizes)
940 /* capture the size of message #first */
941 {
942     int ok = 0, i, num;
943     char buf [POPBUFSIZE+1];
944     unsigned int size;
945
946     for (i = first; i <= last; i++) {
947         gen_send(sock, "LIST %d", i);
948         if ((ok = pop3_ok(sock, buf)) != 0)
949             return(ok);
950         if (sscanf(buf, "%d %u", &num, &size) == 2) {
951             if (num == i)
952                 sizes[i - first] = size;
953             else
954                 /* warn about possible attempt to induce buffer overrun
955                  *
956                  * we expect server reply message number and requested
957                  * message number to match */
958                 report(stderr, "Warning: ignoring bogus data for message sizes returned by server.\n");
959         }
960     }
961     return(ok);
962 }
963
964 static int pop3_getsizes(int sock, int count, int *sizes)
965 /* capture the sizes of all messages */
966 {
967     int ok;
968
969     if ((ok = gen_transact(sock, "LIST")) != 0)
970         return(ok);
971     else
972     {
973         char buf [POPBUFSIZE+1];
974
975         while ((ok = gen_recv(sock, buf, sizeof(buf))) == 0)
976         {
977             unsigned int num, size;
978
979             if (DOTLINE(buf))
980                 break;
981             else if (sscanf(buf, "%u %u", &num, &size) == 2) {
982                 if (num > 0 && num <= (unsigned)count)
983                     sizes[num - 1] = size;
984                 else
985                     /* warn about possible attempt to induce buffer overrun */
986                     report(stderr, "Warning: ignoring bogus data for message sizes returned by server.\n");
987             }
988         }
989
990         return(ok);
991     }
992 }
993
994 static int pop3_is_old(int sock, struct query *ctl, int num)
995 /* is the given message old? */
996 {
997     struct uid_db_record *rec;
998
999     if (!uid_db_n_records(&ctl->oldsaved))
1000         return (num <= last);
1001     else if (dofastuidl)
1002     {
1003         char id [IDLEN+1];
1004
1005         if (num <= last)
1006             return(TRUE);
1007
1008         /* in fast uidl, we manipulate the old list only! */
1009         if ((rec = find_uid_by_num(&ctl->oldsaved, num)))
1010         {
1011             /* we already have the id! */
1012             return(rec->status != UID_UNSEEN);
1013         }
1014
1015         /* get the uidl first! */
1016         if (pop3_getuidl(sock, num, id, sizeof(id)) != PS_SUCCESS)
1017             return(TRUE);
1018
1019         if ((rec = find_uid_by_id(&ctl->oldsaved, id))) {
1020             /* we already have the id! */
1021             set_uid_db_num(&ctl->oldsaved, rec, num);
1022             return(rec->status != UID_UNSEEN);
1023         }
1024
1025         /* save it */
1026         rec = uid_db_insert(&ctl->oldsaved, id, UID_UNSEEN);
1027         set_uid_db_num(&ctl->oldsaved, rec, num);
1028
1029         return(FALSE);
1030     } else {
1031         rec = find_uid_by_num(&ctl->newsaved, num);
1032         return !rec || rec->status != UID_UNSEEN;
1033     }
1034 }
1035
1036 static int pop3_fetch(int sock, struct query *ctl, int number, int *lenp)
1037 /* request nth message */
1038 {
1039     int ok;
1040     char buf[POPBUFSIZE+1];
1041
1042 #ifdef SDPS_ENABLE
1043     /*
1044      * See http://www.demon.net/helpdesk/producthelp/mail/sdps-tech.html/
1045      * for a description of what we're parsing here.
1046      * -- updated 2006-02-22
1047      */
1048     if (ctl->server.sdps)
1049     {
1050         int     linecount = 0;
1051
1052         sdps_envfrom = (char *)NULL;
1053         sdps_envto = (char *)NULL;
1054         gen_send(sock, "*ENV %d", number);
1055         do {
1056             if (gen_recv(sock, buf, sizeof(buf)))
1057             {
1058                 break;
1059             }
1060             linecount++;
1061             switch (linecount) {
1062             case 4:
1063                 /* No need to wrap envelope from address */
1064                 /* FIXME: some parts of fetchmail don't handle null
1065                  * envelope senders, so use <> to mark null sender
1066                  * as a workaround. */
1067                 if (strspn(buf, " \t") == strlen(buf))
1068                     strcpy(buf, "<>");
1069                 sdps_envfrom = (char *)xmalloc(strlen(buf)+1);
1070                 strcpy(sdps_envfrom,buf);
1071                 break;
1072             case 5:
1073                 /* Wrap address with To: <> so nxtaddr() likes it */
1074                 sdps_envto = (char *)xmalloc(strlen(buf)+7);
1075                 sprintf(sdps_envto,"To: <%s>",buf);
1076                 break;
1077             }
1078         } while
1079             (!(buf[0] == '.' && (buf[1] == '\r' || buf[1] == '\n' || buf[1] == '\0')));
1080     }
1081 #else
1082     (void)ctl;
1083 #endif /* SDPS_ENABLE */
1084
1085     /*
1086      * Though the POP RFCs don't document this fact, on almost every
1087      * POP3 server I know of messages are marked "seen" only at the
1088      * time the OK response to a RETR is issued.
1089      *
1090      * This means we can use TOP to fetch the message without setting its
1091      * seen flag.  This is good!  It means that if the protocol exchange
1092      * craps out during the message, it will still be marked `unseen' on
1093      * the server.  (Exception: in early 1999 SpryNet's POP3 servers were
1094      * reported to mark messages seen on a TOP fetch.)
1095      *
1096      * However...*don't* do this if we're using keep to suppress deletion!
1097      * In that case, marking the seen flag is the only way to prevent the
1098      * message from being re-fetched on subsequent runs.
1099      *
1100      * Also use RETR (that means no TOP, no peek) if fetchall is on.
1101      * This gives us a workaround for servers like usa.net's that bungle
1102      * TOP.  It's pretty harmless because fetchall guarantees that any
1103      * message dropped by an interrupted RETR will be picked up on the
1104      * next poll of the site.
1105      *
1106      * We take advantage here of the fact that, according to all the
1107      * POP RFCs, "if the number of lines requested by the POP3 client
1108      * is greater than than the number of lines in the body, then the
1109      * POP3 server sends the entire message.").
1110      *
1111      * The line count passed (99999999) is the maximum value CompuServe will
1112      * accept; it's much lower than the natural value 2147483646 (the maximum
1113      * twos-complement signed 32-bit integer minus 1) */
1114     if (!peek_capable)
1115         gen_send(sock, "RETR %d", number);
1116     else
1117         gen_send(sock, "TOP %d 99999999", number);
1118     if ((ok = pop3_ok(sock, buf)) != 0)
1119         return(ok);
1120
1121     *lenp = -1;         /* we got sizes from the LIST response */
1122
1123     return(PS_SUCCESS);
1124 }
1125
1126 static void mark_uid_seen(struct query *ctl, int number)
1127 /* Tell the UID code we've seen this. */
1128 {
1129     struct uid_db_record *rec;
1130
1131     if ((rec = find_uid_by_num(&ctl->newsaved, number)))
1132         rec->status = UID_SEEN;
1133     /* mark it as seen in oldsaved also! In case, we do not swap the lists
1134      * (say, due to socket error), the same mail will not be downloaded
1135      * again.
1136      */
1137     if ((rec = find_uid_by_num(&ctl->oldsaved, number)))
1138         rec->status = UID_SEEN;
1139 }
1140
1141 static int pop3_delete(int sock, struct query *ctl, int number)
1142 /* delete a given message */
1143 {
1144     struct uid_db_record *rec;
1145     int ok;
1146     mark_uid_seen(ctl, number);
1147     /* actually, mark for deletion -- doesn't happen until QUIT time */
1148     ok = gen_transact(sock, "DELE %d", number);
1149     if (ok != PS_SUCCESS)
1150         return(ok);
1151
1152     rec = find_uid_by_num(dofastuidl ? &ctl->oldsaved : &ctl->newsaved, number);
1153     rec->status = UID_DELETED;
1154     return(PS_SUCCESS);
1155 }
1156
1157 static int pop3_mark_seen(int sock, struct query *ctl, int number)
1158 /* mark a given message as seen */
1159 {
1160     (void)sock;
1161     mark_uid_seen(ctl, number);
1162     return(PS_SUCCESS);
1163 }
1164
1165 static int pop3_logout(int sock, struct query *ctl)
1166 /* send logout command */
1167 {
1168     int ok;
1169
1170     ok = gen_transact(sock, "QUIT");
1171     if (!ok)
1172         expunge_uids(ctl);
1173
1174     return(ok);
1175 }
1176
1177 static const struct method pop3 =
1178 {
1179     "POP3",             /* Post Office Protocol v3 */
1180     "pop3",             /* port for plain and TLS POP3 */
1181     "pop3s",            /* port for SSL POP3 */
1182     FALSE,              /* this is not a tagged protocol */
1183     TRUE,               /* this uses a message delimiter */
1184     pop3_ok,            /* parse command response */
1185     pop3_getauth,       /* get authorization */
1186     pop3_getrange,      /* query range of messages */
1187     pop3_getsizes,      /* we can get a list of sizes */
1188     pop3_getpartialsizes,       /* we can get the size of 1 mail */
1189     pop3_is_old,        /* how do we tell a message is old? */
1190     pop3_fetch,         /* request given message */
1191     NULL,               /* no way to fetch body alone */
1192     NULL,               /* no message trailer */
1193     pop3_delete,        /* how to delete a message */
1194     pop3_mark_seen,     /* how to mark a message as seen */
1195     NULL,               /* no action at end of mailbox */
1196     pop3_logout,        /* log out, we're done */
1197     FALSE,              /* no, we can't re-poll */
1198 };
1199
1200 int doPOP3 (struct query *ctl)
1201 /* retrieve messages using POP3 */
1202 {
1203 #ifndef MBOX
1204     if (ctl->mailboxes->id) {
1205         fprintf(stderr,GT_("Option --folder is not supported with POP3\n"));
1206         return(PS_SYNTAX);
1207     }
1208 #endif /* MBOX */
1209
1210     return(do_protocol(ctl, &pop3));
1211 }
1212 #endif /* POP3_ENABLE */
1213
1214 /* pop3.c ends here */