]> Pileus Git - ~andy/fetchmail/blob - driver.c
Consistent error-message formats.
[~andy/fetchmail] / driver.c
1 /*
2  * driver.c -- generic driver for mail fetch method protocols
3  *
4  * Copyright 1997 by Eric S. Raymond
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include  "config.h"
9 #include  <stdio.h>
10 #include  <setjmp.h>
11 #include  <errno.h>
12 #include  <ctype.h>
13 #include  <string.h>
14 #ifdef HAVE_MEMORY_H
15 #include  <memory.h>
16 #endif /* HAVE_MEMORY_H */
17 #if defined(STDC_HEADERS)
18 #include  <stdlib.h>
19 #endif
20 #if defined(HAVE_UNISTD_H)
21 #include <unistd.h>
22 #endif
23 #if defined(HAVE_STDARG_H)
24 #include  <stdarg.h>
25 #else
26 #include  <varargs.h>
27 #endif
28 #if defined(HAVE_SYS_ITIMER_H)
29 #include <sys/itimer.h>
30 #endif
31 #include  <sys/time.h>
32 #include  <signal.h>
33
34 #ifdef HAVE_NET_SOCKET_H
35 #include <net/socket.h>
36 #endif
37
38 #ifdef HAVE_RES_SEARCH
39 #include <netdb.h>
40 #include "mx.h"
41 #endif /* HAVE_RES_SEARCH */
42
43 #ifdef KERBEROS_V4
44 #ifdef KERBEROS_V5
45 #include <kerberosIV/des.h>
46 #include <kerberosIV/krb.h>
47 #else
48 #if defined (__bsdi__)
49 #include <des.h> /* order of includes matters */
50 #include <krb.h>
51 #define krb_get_err_text(e) (krb_err_txt[e])
52 #else
53 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__)
54 #define krb_get_err_text(e) (krb_err_txt[e])
55 #include <krb.h>
56 #include <des.h>
57 #else
58 #include <krb.h>
59 #include <des.h>
60 #endif /* ! defined (__FreeBSD__) */
61 #endif /* ! defined (__bsdi__) */
62 #endif /* KERBEROS_V5 */
63 #include <netinet/in.h>
64 #include <netdb.h>
65 #endif /* KERBEROS_V4 */
66 #ifdef KERBEROS_V5
67 #include <krb5.h>
68 #include <com_err.h>
69 #endif /* KERBEROS_V5 */
70 #include "i18n.h"
71
72 #include "socket.h"
73 #include "fetchmail.h"
74 #include "tunable.h"
75
76 /* throw types for runtime errors */
77 #define THROW_TIMEOUT   1               /* server timed out */
78 #define THROW_SIGPIPE   2               /* SIGPIPE on stream socket */
79
80 #ifndef strstr          /* glibc-2.1 declares this as a macro */
81 extern char *strstr();  /* needed on sysV68 R3V7.1. */
82 #endif /* strstr */
83
84 int batchcount;         /* count of messages sent in current batch */
85 flag peek_capable;      /* can we peek for better error recovery? */
86 int pass;               /* how many times have we re-polled? */
87 int stage;              /* where are we? */
88 int phase;              /* where are we, for error-logging purposes? */
89 int mytimeout;          /* value of nonreponse timeout */
90 int suppress_tags;      /* emit tags? */
91
92 static const struct method *protocol;
93 static jmp_buf  restart;
94
95 char tag[TAGLEN];
96 static int tagnum;
97 #define GENSYM  (sprintf(tag, "A%04d", ++tagnum % TAGMOD), tag)
98
99 static char shroud[PASSWORDLEN];        /* string to shroud in debug output */
100 static int timeoutcount;                /* count consecutive timeouts */
101 static int msglen;                      /* actual message length */
102
103 void set_timeout(int timeleft)
104 /* reset the nonresponse-timeout */
105 {
106 #if !defined(__EMX__) && !defined(__BEOS__) 
107     struct itimerval ntimeout;
108
109     if (timeleft == 0)
110         timeoutcount = 0;
111
112     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
113     ntimeout.it_value.tv_sec  = timeleft;
114     ntimeout.it_value.tv_usec = 0;
115     setitimer(ITIMER_REAL, &ntimeout, (struct itimerval *)NULL);
116 #endif
117 }
118
119 static void timeout_handler (int signal)
120 /* handle SIGALRM signal indicating a server timeout */
121 {
122     timeoutcount++;
123     longjmp(restart, THROW_TIMEOUT);
124 }
125
126 static void sigpipe_handler (int signal)
127 /* handle SIGPIPE signal indicating a broken stream socket */
128 {
129     longjmp(restart, THROW_SIGPIPE);
130 }
131
132 static int accept_count, reject_count;
133
134 static void map_name(const char *name, struct query *ctl, struct idlist **xmit_names)
135 /* add given name to xmit_names if it matches declared localnames */
136 /*   name:       name to map */
137 /*   ctl:        list of permissible aliases */
138 /*   xmit_names: list of recipient names parsed out */
139 {
140     const char  *lname;
141     int off = 0;
142     
143     lname = idpair_find(&ctl->localnames, name+off);
144     if (!lname && ctl->wildcard)
145         lname = name+off;
146
147     if (lname != (char *)NULL)
148     {
149         if (outlevel >= O_DEBUG)
150             report(stdout, _("mapped %s to local %s\n"), name, lname);
151         save_str(xmit_names, lname, XMIT_ACCEPT);
152         accept_count++;
153     }
154 }
155
156 static void find_server_names(const char *hdr,
157                               struct query *ctl,
158                               struct idlist **xmit_names)
159 /* parse names out of a RFC822 header into an ID list */
160 /*   hdr:               RFC822 header in question */
161 /*   ctl:               list of permissible aliases */
162 /*   xmit_names:        list of recipient names parsed out */
163 {
164     if (hdr == (char *)NULL)
165         return;
166     else
167     {
168         char    *cp;
169
170         for (cp = nxtaddr(hdr);
171              cp != NULL;
172              cp = nxtaddr(NULL))
173         {
174             char        *atsign;
175
176             /*
177              * If the name of the user begins with a qmail virtual
178              * domain prefix, ignore the prefix.  Doing this here
179              * means qvirtual will work either with ordinary name
180              * mapping or with a localdomains option.
181              */
182             if (ctl->server.qvirtual)
183             {
184                 int sl = strlen(ctl->server.qvirtual);
185  
186                 if (!strncasecmp(cp, ctl->server.qvirtual, sl))
187                     cp += sl;
188             }
189
190             if ((atsign = strchr(cp, '@'))) {
191                 struct idlist   *idp;
192
193                 /*
194                  * Does a trailing segment of the hostname match something
195                  * on the localdomains list?  If so, save the whole name
196                  * and keep going.
197                  */
198                 for (idp = ctl->server.localdomains; idp; idp = idp->next) {
199                     char        *rhs;
200
201                     rhs = atsign + (strlen(atsign) - strlen(idp->id));
202                     if (rhs > atsign &&
203                         (rhs[-1] == '.' || rhs[-1] == '@') &&
204                         strcasecmp(rhs, idp->id) == 0)
205                     {
206                         if (outlevel >= O_DEBUG)
207                             report(stdout, _("passed through %s matching %s\n"), 
208                                   cp, idp->id);
209                         save_str(xmit_names, cp, XMIT_ACCEPT);
210                         accept_count++;
211                         goto nomap;
212                     }
213                 }
214
215                 /* if we matched a local domain, idp != NULL */
216                 if (!idp)
217                 {
218                     /*
219                      * Check to see if the right-hand part is an alias
220                      * or MX equivalent of the mailserver.  If it's
221                      * not, skip this name.  If it is, we'll keep
222                      * going and try to find a mapping to a client name.
223                      */
224                     if (!is_host_alias(atsign+1, ctl))
225                     {
226                         save_str(xmit_names, cp, XMIT_REJECT);
227                         reject_count++;
228                         continue;
229                     }
230                 }
231                 atsign[0] = '\0';
232                 map_name(cp, ctl, xmit_names);
233             nomap:;
234             }
235         }
236     }
237 }
238
239 /*
240  * Return zero on a syntactically invalid address, nz on a valid one.
241  *
242  * This used to be strchr(a, '.'), but it turns out that lines like this
243  *
244  * Received: from punt-1.mail.demon.net by mailstore for markb@ordern.com
245  *          id 938765929:10:27223:2; Fri, 01 Oct 99 08:18:49 GMT
246  *
247  * are not uncommon.  So now we just check that the following token is
248  * not itself an email address.
249  */
250 #define VALID_ADDRESS(a)        !strchr(a, '@')
251
252 static char *parse_received(struct query *ctl, char *bufp)
253 /* try to extract real address from the Received line */
254 /* If a valid Received: line is found, we return the full address in
255  * a buffer which can be parsed from nxtaddr().  This is to ansure that
256  * the local domain part of the address can be passed along in 
257  * find_server_names() if it contains one.
258  * Note: We should return a dummy header containing the address 
259  * which makes nxtaddr() behave correctly. 
260  */
261 {
262     char *base, *ok = (char *)NULL;
263     static char rbuf[HOSTLEN + USERNAMELEN + 4]; 
264
265     /*
266      * Try to extract the real envelope addressee.  We look here
267      * specifically for the mailserver's Received line.
268      * Note: this will only work for sendmail, or an MTA that
269      * shares sendmail's convention for embedding the envelope
270      * address in the Received line.  Sendmail itself only
271      * does this when the mail has a single recipient.
272      */
273     if (outlevel >= O_DEBUG)
274         report(stdout, _("analyzing Received line:\n%s"), bufp);
275
276     /* search for whitepace-surrounded "by" followed by valid address */
277     for (base = bufp;  ; base = ok + 2)
278     {
279         if (!(ok = strstr(base, "by")))
280             break;
281         else if (!isspace(ok[-1]) || !isspace(ok[2]))
282             continue;
283         else
284         {
285             char        *sp, *tp;
286
287             /* extract space-delimited token after "by" */
288             for (sp = ok + 2; isspace(*sp); sp++)
289                 continue;
290             tp = rbuf;
291             for (; !isspace(*sp); sp++)
292                 *tp++ = *sp;
293             *tp = '\0';
294
295             /* look for valid address */
296             if (VALID_ADDRESS(rbuf))
297                 break;
298             else
299                 ok = sp - 1;    /* arrange to skip this token */
300         }
301     }
302     if (ok)
303     {
304         /*
305          * If it's a DNS name of the mail server, look for the
306          * recipient name after a following "for".  Otherwise
307          * punt.
308          */
309         if (is_host_alias(rbuf, ctl))
310         {
311             if (outlevel >= O_DEBUG)
312                 report(stdout, 
313                       _("line accepted, %s is an alias of the mailserver\n"), rbuf);
314         }
315         else
316         {
317             if (outlevel >= O_DEBUG)
318                 report(stdout, 
319                       _("line rejected, %s is not an alias of the mailserver\n"), 
320                       rbuf);
321             return(NULL);
322         }
323
324         /* search for whitepace-surrounded "for" followed by xxxx@yyyy */
325         for (base = ok + 4 + strlen(rbuf);  ; base = ok + 2)
326         {
327             if (!(ok = strstr(base, "for")))
328                 break;
329             else if (!isspace(ok[-1]) || !isspace(ok[3]))
330                 continue;
331             else
332             {
333                 char    *sp, *tp;
334
335                 /* extract space-delimited token after "for" */
336                 for (sp = ok + 3; isspace(*sp); sp++)
337                     continue;
338                 tp = rbuf;
339                 for (; !isspace(*sp); sp++)
340                     *tp++ = *sp;
341                 *tp = '\0';
342
343                 if (strchr(rbuf, '@'))
344                     break;
345                 else
346                     ok = sp - 1;        /* arrange to skip this token */
347             }
348         }
349         if (ok)
350         {
351             flag        want_gt = FALSE;
352             char        *sp, *tp;
353
354             /* char after "for" could be space or a continuation newline */
355             for (sp = ok + 4; isspace(*sp); sp++)
356                 continue;
357             tp = rbuf;
358             *tp++ = ':';        /* Here is the hack.  This is to be friends */
359             *tp++ = ' ';        /* with nxtaddr()... */
360             if (*sp == '<')
361             {
362                 want_gt = TRUE;
363                 sp++;
364             }
365             while (*sp == '@')          /* skip routes */
366                 while (*sp && *sp++ != ':')
367                     continue;
368             while (*sp
369                    && (want_gt ? (*sp != '>') : !isspace(*sp))
370                    && *sp != ';')
371                 if (!isspace(*sp))
372                     *tp++ = *sp++;
373                 else
374                 {
375                     /* uh oh -- whitespace here can't be right! */
376                     ok = (char *)NULL;
377                     break;
378                 }
379             *tp++ = '\n';
380             *tp = '\0';
381             if (strlen(rbuf) <= 3)      /* apparently nothing has been found */
382                 ok = NULL;
383         } else
384             ok = (char *)NULL;
385     }
386
387     if (!ok)
388     {
389         if (outlevel >= O_DEBUG)
390             report(stdout, _("no Received address found\n"));
391         return(NULL);
392     }
393     else
394     {
395         if (outlevel >= O_DEBUG) {
396             char *lf = rbuf + strlen(rbuf)-1;
397             *lf = '\0';
398             if (outlevel >= O_DEBUG)
399                 report(stdout, _("found Received address `%s'\n"), rbuf+2);
400             *lf = '\n';
401         }
402         return(rbuf);
403     }
404 }
405
406 /* shared by readheaders and readbody */
407 static int sizeticker;
408 static struct msgblk msgblk;
409
410 #define EMPTYLINE(s)    ((s)[0] == '\r' && (s)[1] == '\n' && (s)[2] == '\0')
411
412 static int readheaders(int sock,
413                        long fetchlen,
414                        long reallen,
415                        struct query *ctl,
416                        int num)
417 /* read message headers and ship to SMTP or MDA */
418 /*   sock:              to which the server is connected */
419 /*   fetchlen:          length of message according to fetch response */
420 /*   reallen:           length of message according to getsizes */
421 /*   ctl:               query control record */
422 /*   num:               index of message */
423 {
424     struct addrblk
425     {
426         int             offset;
427         struct addrblk  *next;
428     };
429     struct addrblk      *to_addrchain = NULL;
430     struct addrblk      **to_chainptr = &to_addrchain;
431     struct addrblk      *resent_to_addrchain = NULL;
432     struct addrblk      **resent_to_chainptr = &resent_to_addrchain;
433
434     char                buf[MSGBUFSIZE+1];
435     int                 from_offs, reply_to_offs, resent_from_offs;
436     int                 app_from_offs, sender_offs, resent_sender_offs;
437     int                 env_offs;
438     char                *received_for, *rcv, *cp, *delivered_to;
439     int                 n, linelen, oldlen, ch, remaining, skipcount;
440     struct idlist       *idp;
441     flag                no_local_matches = FALSE;
442     flag                headers_ok, has_nuls;
443     int                 olderrs, good_addresses, bad_addresses;
444
445     sizeticker = 0;
446     has_nuls = headers_ok = FALSE;
447     msgblk.return_path[0] = '\0';
448     olderrs = ctl->errcount;
449
450     /* read message headers */
451     msgblk.reallen = reallen;
452
453     /*
454      * We used to free the header block unconditionally at the end of 
455      * readheaders, but it turns out that if close_sink() hits an error
456      * condition the code for sending bouncemail will actually look
457      * at the freed storage and coredump...
458      */
459     if (msgblk.headers)
460        free(msgblk.headers);
461
462     msgblk.headers = received_for = delivered_to = NULL;
463     from_offs = reply_to_offs = resent_from_offs = app_from_offs = 
464         sender_offs = resent_sender_offs = env_offs = -1;
465     oldlen = 0;
466     msglen = 0;
467     skipcount = 0;
468     ctl->mimemsg = 0;
469
470     for (remaining = fetchlen; remaining > 0 || protocol->delimited; remaining -= linelen)
471     {
472         char *line;
473
474         line = xmalloc(sizeof(buf));
475         linelen = 0;
476         line[0] = '\0';
477         do {
478             set_timeout(mytimeout);
479             if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) {
480                 set_timeout(0);
481                 free(line);
482                 free(msgblk.headers);
483                 msgblk.headers = NULL;
484                 return(PS_SOCKET);
485             }
486             set_timeout(0);
487             linelen += n;
488             msglen += n;
489
490             /* lines may not be properly CRLF terminated; fix this for qmail */
491             if (ctl->forcecr)
492             {
493                 cp = buf + strlen(buf) - 1;
494                 if (*cp == '\n' && (cp == buf || cp[-1] != '\r'))
495                 {
496                     *cp++ = '\r';
497                     *cp++ = '\n';
498                     *cp++ = '\0';
499                 }
500             }
501
502             /*
503              * Decode MIME encoded headers. We MUST do this before
504              * looking at the Content-Type / Content-Transfer-Encoding
505              * headers (RFC 2046).
506              */
507             if (ctl->mimedecode)
508                 UnMimeHeader(buf);
509
510             line = (char *) realloc(line, strlen(line) + strlen(buf) +1);
511
512             strcat(line, buf);
513
514             /* check for end of headers */
515             if (EMPTYLINE(line))
516             {
517                 headers_ok = TRUE;
518                 has_nuls = (linelen != strlen(line));
519                 free(line);
520                 goto process_headers;
521             }
522
523             /*
524              * Check for end of message immediately.  If one of your folders
525              * has been mangled, the delimiter may occur directly after the
526              * header.
527              */
528             if (protocol->delimited && line[0] == '.' && EMPTYLINE(line+1))
529             {
530                 free(line);
531                 has_nuls = (linelen != strlen(line));
532                 goto process_headers;
533             }
534
535             /*
536              * At least one brain-dead website (netmind.com) is known to
537              * send out robotmail that's missing the RFC822 delimiter blank
538              * line before the body! Without this check fetchmail segfaults.
539              * With it, we treat such messages as though they had the missing
540              * blank line.
541              */
542             if (!isspace(line[0]) && !strchr(line, ':'))
543             {
544                 headers_ok = TRUE;
545                 free(line);
546                 has_nuls = (linelen != strlen(line));
547                 goto process_headers;
548             }
549
550             /* check for RFC822 continuations */
551             set_timeout(mytimeout);
552             ch = SockPeek(sock);
553             set_timeout(0);
554         } while
555             (ch == ' ' || ch == '\t');  /* continuation to next line? */
556
557         /* write the message size dots */
558         if ((outlevel > O_SILENT && outlevel < O_VERBOSE) && linelen > 0)
559         {
560             sizeticker += linelen;
561             while (sizeticker >= SIZETICKER)
562             {
563                 if ((!run.use_syslog && !isafile(1)) || run.showdots)
564                 {
565                     fputc('.', stdout);
566                     fflush(stdout);
567                 }
568                 sizeticker -= SIZETICKER;
569             }
570         }
571
572         /* we see an ordinary (non-header, non-message-delimiter line */
573         has_nuls = (linelen != strlen(line));
574
575         /*
576          * When mail delivered to a multidrop mailbox on the server is
577          * addressed to multiple people on the client machine, there
578          * will be one copy left in the box for each recipient.  Thus,
579          * if the mail is addressed to N people, each recipient will
580          * get N copies.  This is bad when N > 1.
581          *
582          * Foil this by suppressing all but one copy of a message with
583          * a given Message-ID.  The accept_count test ensures that
584          * multiple pieces of email with the same Message-ID, each
585          * with a *single* addressee (the N == 1 case), won't be 
586          * suppressed.
587          *
588          * Note: This implementation only catches runs of successive
589          * messages with the same ID, but that should be good
590          * enough. A more general implementation would have to store
591          * ever-growing lists of seen message-IDs; in a long-running
592          * daemon this would turn into a memory leak even if the 
593          * implementation were perfect.
594          * 
595          * Don't mess with this code casually.  It would be way too easy
596          * to break it in a way that blackholed mail.  Better to pass
597          * the occasional duplicate than to do that...
598          */
599         if (MULTIDROP(ctl) && !strncasecmp(line, "Message-ID:", 11))
600         {
601             if (ctl->lastid && !strcasecmp(ctl->lastid, line))
602             {
603                 if (accept_count > 1)
604                     return(PS_REFUSED);
605             }
606             else
607             {
608                 if (ctl->lastid)
609                     free(ctl->lastid);
610                 ctl->lastid = strdup(line);
611             }
612         }
613
614         /*
615          * The University of Washington IMAP server (the reference
616          * implementation of IMAP4 written by Mark Crispin) relies
617          * on being able to keep base-UID information in a special
618          * message at the head of the mailbox.  This message should
619          * neither be deleted nor forwarded.
620          */
621 #ifdef POP2_ENABLE
622         /*
623          * We disable this check under POP2 because there's no way to
624          * prevent deletion of the message.  So at least we ought to 
625          * forward it to the user so he or she will have some clue
626          * that things have gone awry.
627          */
628 #if INET6_ENABLE
629         if (strncmp(protocol->service, "pop2", 4))
630 #else /* INET6_ENABLE */
631         if (protocol->port != 109)
632 #endif /* INET6_ENABLE */
633 #endif /* POP2_ENABLE */
634             if (num == 1 && !strncasecmp(line, "X-IMAP:", 7)) {
635                 free(line);
636                 free(msgblk.headers);
637                 msgblk.headers = NULL;
638                 return(PS_RETAINED);
639             }
640
641         /*
642          * This code prevents fetchmail from becoming an accessory after
643          * the fact to upstream sendmails with the `E' option on.  It also
644          * copes with certain brain-dead POP servers (like NT's) that pass
645          * through Unix from_ lines.
646          *
647          * Either of these bugs can result in a non-RFC822 line at the
648          * beginning of the headers.  If fetchmail just passes it
649          * through, the client listener may think the message has *no*
650          * headers (since the first) line it sees doesn't look
651          * RFC822-conformant) and fake up a set.
652          *
653          * What the user would see in this case is bogus (synthesized)
654          * headers, followed by a blank line, followed by the >From, 
655          * followed by the real headers, followed by a blank line,
656          * followed by text.
657          *
658          * We forestall this lossage by tossing anything that looks
659          * like an escaped or passed-through From_ line in headers.
660          * These aren't RFC822 so our conscience is clear...
661          */
662         if (!strncasecmp(line, ">From ", 6) || !strncasecmp(line, "From ", 5))
663         {
664             free(line);
665             continue;
666         }
667
668         /*
669          * We remove all Delivered-To: headers.
670          * 
671          * This is to avoid false mail loops messages when delivering
672          * local messages to and from a Postfix/qmail mailserver. 
673          */
674         if (ctl->dropdelivered && !strncasecmp(line, "Delivered-To:", 13)) 
675         {
676             if (delivered_to)
677                 free(line);
678             else 
679                 delivered_to = line;
680             continue;
681         }
682
683         /*
684          * If we see a Status line, it may have been inserted by an MUA
685          * on the mail host, or it may have been inserted by the server
686          * program after the headers in the transaction stream.  This
687          * can actually hose some new-mail notifiers such as xbuffy,
688          * which assumes any Status line came from a *local* MDA and
689          * therefore indicates that the message has been seen.
690          *
691          * Some buggy POP servers (including at least the 3.3(20)
692          * version of the one distributed with IMAP) insert empty
693          * Status lines in the transaction stream; we'll chuck those
694          * unconditionally.  Nonempty ones get chucked if the user
695          * turns on the dropstatus flag.
696          */
697         {
698             char        *cp;
699
700             if (!strncasecmp(line, "Status:", 7))
701                 cp = line + 7;
702             else if (!strncasecmp(line, "X-Mozilla-Status:", 17))
703                 cp = line + 17;
704             else
705                 cp = NULL;
706             if (cp) {
707                 while (*cp && isspace(*cp)) cp++;
708                 if (!*cp || ctl->dropstatus)
709                 {
710                     free(line);
711                     continue;
712                 }
713             }
714         }
715
716         if (ctl->rewrite)
717             line = reply_hack(line, ctl->server.truename);
718
719         /*
720          * OK, this is messy.  If we're forwarding by SMTP, it's the
721          * SMTP-receiver's job (according to RFC821, page 22, section
722          * 4.1.1) to generate a Return-Path line on final delivery.
723          * The trouble is, we've already got one because the
724          * mailserver's SMTP thought *it* was responsible for final
725          * delivery.
726          *
727          * Stash away the contents of Return-Path (as modified by reply_hack)
728          * for use in generating MAIL FROM later on, then prevent the header
729          * from being saved with the others.  In effect, we strip it off here.
730          *
731          * If the SMTP server conforms to the standards, and fetchmail gets the
732          * envelope sender from the Return-Path, the new Return-Path should be
733          * exactly the same as the original one.
734          *
735          * We do *not* want to ignore empty Return-Path headers.  These should
736          * be passed through as a way of indicating that a message should
737          * not trigger bounces if delivery fails.  What we *do* need to do is
738          * make sure we never try to rewrite such a blank Return-Path.  We
739          * handle this with a check for <> in the rewrite logic above.
740          */
741         if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
742         {
743             strcpy(msgblk.return_path, cp);
744             if (!ctl->mda) {
745                 free(line);
746                 continue;
747             }
748         }
749
750         if (!msgblk.headers)
751         {
752             oldlen = strlen(line);
753             msgblk.headers = xmalloc(oldlen + 1);
754             (void) strcpy(msgblk.headers, line);
755             free(line);
756             line = msgblk.headers;
757         }
758         else
759         {
760             char *newhdrs;
761             int newlen;
762
763             newlen = oldlen + strlen(line);
764             newhdrs = (char *) realloc(msgblk.headers, newlen + 1);
765             if (newhdrs == NULL) {
766                 free(line);
767                 return(PS_IOERR);
768             }
769             msgblk.headers = newhdrs;
770             strcpy(msgblk.headers + oldlen, line);
771             free(line);
772             line = msgblk.headers + oldlen;
773             oldlen = newlen;
774         }
775
776         if (!strncasecmp("From:", line, 5))
777             from_offs = (line - msgblk.headers);
778         else if (!strncasecmp("Reply-To:", line, 9))
779             reply_to_offs = (line - msgblk.headers);
780         else if (!strncasecmp("Resent-From:", line, 12))
781             resent_from_offs = (line - msgblk.headers);
782         else if (!strncasecmp("Apparently-From:", line, 16))
783             app_from_offs = (line - msgblk.headers);
784         else if (!strncasecmp("Sender:", line, 7))
785             sender_offs = (line - msgblk.headers);
786         else if (!strncasecmp("Resent-Sender:", line, 14))
787             resent_sender_offs = (line - msgblk.headers);
788
789 #ifdef __UNUSED__
790         else if (!strncasecmp("Message-Id:", line, 11))
791         {
792             if (ctl->server.uidl)
793             {
794                 char id[IDLEN+1];
795
796                 line[IDLEN+12] = 0;             /* prevent stack overflow */
797                 sscanf(line+12, "%s", id);
798                 if (!str_find( &ctl->newsaved, num))
799                 {
800                     struct idlist *new = save_str(&ctl->newsaved,id,UID_SEEN);
801                     new->val.status.num = num;
802                 }
803             }
804         }
805 #endif /* __UNUSED__ */
806
807         else if (!MULTIDROP(ctl))
808             continue;
809
810         else if (!strncasecmp("To:", line, 3)
811                         || !strncasecmp("Cc:", line, 3)
812                         || !strncasecmp("Bcc:", line, 4)
813                         || !strncasecmp("Apparently-To:", line, 14))
814         {
815             *to_chainptr = xmalloc(sizeof(struct addrblk));
816             (*to_chainptr)->offset = (line - msgblk.headers);
817             to_chainptr = &(*to_chainptr)->next; 
818             *to_chainptr = NULL;
819         }
820
821         else if (!strncasecmp("Resent-To:", line, 10)
822                         || !strncasecmp("Resent-Cc:", line, 10)
823                         || !strncasecmp("Resent-Bcc:", line, 11))
824         {
825             *resent_to_chainptr = xmalloc(sizeof(struct addrblk));
826             (*resent_to_chainptr)->offset = (line - msgblk.headers);
827             resent_to_chainptr = &(*resent_to_chainptr)->next; 
828             *resent_to_chainptr = NULL;
829         }
830
831         else if (ctl->server.envelope != STRING_DISABLED)
832         {
833             if (ctl->server.envelope 
834                         && strcasecmp(ctl->server.envelope, "Received"))
835             {
836                 if (env_offs == -1 && !strncasecmp(ctl->server.envelope,
837                                                 line,
838                                                 strlen(ctl->server.envelope)))
839                 {                               
840                     if (skipcount++ != ctl->server.envskip)
841                         continue;
842                     env_offs = (line - msgblk.headers);
843                 }    
844             }
845             else if (!received_for && !strncasecmp("Received:", line, 9))
846             {
847                 if (skipcount++ != ctl->server.envskip)
848                     continue;
849                 received_for = parse_received(ctl, line);
850             }
851         }
852     }
853
854  process_headers:
855     /*
856      * We want to detect this early in case there are so few headers that the
857      * dispatch logic barfs.
858      */
859     if (!headers_ok)
860     {
861         if (outlevel > O_SILENT)
862             report(stdout,
863                    _("message delimiter found while scanning headers\n"));
864     }
865
866     /*
867      * Hack time.  If the first line of the message was blank, with no headers
868      * (this happens occasionally due to bad gatewaying software) cons up
869      * a set of fake headers.  
870      *
871      * If you modify the fake header template below, be sure you don't
872      * make either From or To address @-less, otherwise the reply_hack
873      * logic will do bad things.
874      */
875     if (msgblk.headers == (char *)NULL)
876     {
877 #ifdef HAVE_SNPRINTF
878         snprintf(buf, sizeof(buf),
879 #else
880         sprintf(buf, 
881 #endif /* HAVE_SNPRINTF */
882         "From: FETCHMAIL-DAEMON\r\nTo: %s@%s\r\nSubject: Headerless mail from %s's mailbox on %s\r\n",
883                 user, fetchmailhost, ctl->remotename, ctl->server.truename);
884         msgblk.headers = xstrdup(buf);
885     }
886
887     /*
888      * We can now process message headers before reading the text.
889      * In fact we have to, as this will tell us where to forward to.
890      */
891
892     /* Check for MIME headers indicating possible 8-bit data */
893     ctl->mimemsg = MimeBodyType(msgblk.headers, ctl->mimedecode);
894
895 #ifdef SDPS_ENABLE
896     if (ctl->server.sdps && sdps_envfrom)
897     {
898         /* We have the real envelope return-path, stored out of band by
899          * SDPS - that's more accurate than any header is going to be.
900          */
901         strcpy(msgblk.return_path, sdps_envfrom);
902         free(sdps_envfrom);
903     } else
904 #endif /* SDPS_ENABLE */
905     /*
906      * If there is a Return-Path address on the message, this was
907      * almost certainly the MAIL FROM address given the originating
908      * sendmail.  This is the best thing to use for logging the
909      * message origin (it sets up the right behavior for bounces and
910      * mailing lists).  Otherwise, fall down to the next available 
911      * envelope address (which is the most probable real sender).
912      * *** The order is important! ***
913      * This is especially useful when receiving mailing list
914      * messages in multidrop mode.  if a local address doesn't
915      * exist, the bounce message won't be returned blindly to the 
916      * author or to the list itself but rather to the list manager
917      * (ex: specified by "Sender:") which is much less annoying.  This 
918      * is true for most mailing list packages.
919      */
920     if( !msgblk.return_path[0] ){
921         char *ap = NULL;
922         if (resent_sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_sender_offs)));
923         else if (sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + sender_offs)));
924         else if (resent_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_from_offs)));
925         else if (from_offs >= 0 && (ap = nxtaddr(msgblk.headers + from_offs)));
926         else if (reply_to_offs >= 0 && (ap = nxtaddr(msgblk.headers + reply_to_offs)));
927         else if (app_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + app_from_offs)));
928         if (ap) strcpy( msgblk.return_path, ap );
929     }
930
931     /* cons up a list of local recipients */
932     msgblk.recipients = (struct idlist *)NULL;
933     accept_count = reject_count = 0;
934     /* is this a multidrop box? */
935     if (MULTIDROP(ctl))
936     {
937 #ifdef SDPS_ENABLE
938         if (ctl->server.sdps && sdps_envto)
939         {
940             /* We have the real envelope recipient, stored out of band by
941              * SDPS - that's more accurate than any header is going to be.
942              */
943             find_server_names(sdps_envto, ctl, &msgblk.recipients);
944             free(sdps_envto);
945         } else
946 #endif /* SDPS_ENABLE */ 
947         if (env_offs > -1)          /* We have the actual envelope addressee */
948             find_server_names(msgblk.headers + env_offs, ctl, &msgblk.recipients);
949         else if (delivered_to && ctl->server.envelope != STRING_DISABLED &&
950       ctl->server.envelope && !strcasecmp(ctl->server.envelope, "Delivered-To"))
951    {
952             find_server_names(delivered_to, ctl, &msgblk.recipients);
953        free(delivered_to);
954    }
955         else if (received_for)
956             /*
957              * We have the Received for addressee.  
958              * It has to be a mailserver address, or we
959              * wouldn't have got here.
960              * We use find_server_names() to let local 
961              * hostnames go through.
962              */
963             find_server_names(received_for, ctl, &msgblk.recipients);
964         else
965         {
966             /*
967              * We haven't extracted the envelope address.
968              * So check all the "Resent-To" header addresses if 
969              * they exist.  If and only if they don't, consider
970              * the "To" addresses.
971              */
972             register struct addrblk *nextptr;
973             if (resent_to_addrchain) {
974                 /* delete the "To" chain and substitute it 
975                  * with the "Resent-To" list 
976                  */
977                 while (to_addrchain) {
978                     nextptr = to_addrchain->next;
979                     free(to_addrchain);
980                     to_addrchain = nextptr;
981                 }
982                 to_addrchain = resent_to_addrchain;
983                 resent_to_addrchain = NULL;
984             }
985             /* now look for remaining adresses */
986             while (to_addrchain) {
987                 find_server_names(msgblk.headers+to_addrchain->offset, ctl, &msgblk.recipients);
988                 nextptr = to_addrchain->next;
989                 free(to_addrchain);
990                 to_addrchain = nextptr;
991             }
992         }
993         if (!accept_count)
994         {
995             no_local_matches = TRUE;
996             save_str(&msgblk.recipients, run.postmaster, XMIT_ACCEPT);
997             if (outlevel >= O_DEBUG)
998                 report(stdout,
999                       _("no local matches, forwarding to %s\n"),
1000                       run.postmaster);
1001         }
1002     }
1003     else        /* it's a single-drop box, use first localname */
1004         save_str(&msgblk.recipients, ctl->localnames->id, XMIT_ACCEPT);
1005
1006
1007     /*
1008      * Time to either address the message or decide we can't deliver it yet.
1009      */
1010     if (ctl->errcount > olderrs)        /* there were DNS errors above */
1011     {
1012         if (outlevel >= O_DEBUG)
1013             report(stdout,
1014                    _("forwarding and deletion suppressed due to DNS errors\n"));
1015         free(msgblk.headers);
1016         msgblk.headers = NULL;
1017         free_str_list(&msgblk.recipients);
1018         return(PS_TRANSIENT);
1019     }
1020     else
1021     {
1022         /* set up stuffline() so we can deliver the message body through it */ 
1023         if ((n = open_sink(ctl, &msgblk,
1024                            &good_addresses, &bad_addresses)) != PS_SUCCESS)
1025         {
1026             free(msgblk.headers);
1027             msgblk.headers = NULL;
1028             free_str_list(&msgblk.recipients);
1029             return(n);
1030         }
1031     }
1032
1033     n = 0;
1034     /*
1035      * Some server/sendmail combinations cause problems when our
1036      * synthetic Received line is before the From header.  Cope
1037      * with this...
1038      */
1039     if ((rcv = strstr(msgblk.headers, "Received:")) == (char *)NULL)
1040         rcv = msgblk.headers;
1041     /* handle ">Received:" lines too */
1042     while (rcv > msgblk.headers && rcv[-1] != '\n')
1043         rcv--;
1044     if (rcv > msgblk.headers)
1045     {
1046         char    c = *rcv;
1047
1048         *rcv = '\0';
1049         n = stuffline(ctl, msgblk.headers);
1050         *rcv = c;
1051     }
1052     if (!run.invisible && n != -1)
1053     {
1054         /* utter any per-message Received information we need here */
1055         if (ctl->server.trueaddr) {
1056             sprintf(buf, "Received: from %s [%u.%u.%u.%u]\r\n", 
1057                     ctl->server.truename,
1058                     (unsigned char)ctl->server.trueaddr[0],
1059                     (unsigned char)ctl->server.trueaddr[1],
1060                     (unsigned char)ctl->server.trueaddr[2],
1061                     (unsigned char)ctl->server.trueaddr[3]);
1062         } else {
1063           sprintf(buf, "Received: from %s\r\n", ctl->server.truename);
1064         }
1065         n = stuffline(ctl, buf);
1066         if (n != -1)
1067         {
1068             /*
1069              * This header is technically invalid under RFC822.
1070              * POP3, IMAP, etc. are not legal mail-parameter values.
1071              *
1072              * We used to include ctl->remotename in this log line,
1073              * but this can be secure information that would be bad
1074              * to reveal.
1075              */
1076             sprintf(buf, "\tby %s with %s (fetchmail-%s)\r\n",
1077                     fetchmailhost,
1078                     protocol->name,
1079                     VERSION);
1080             n = stuffline(ctl, buf);
1081             if (n != -1)
1082             {
1083                 buf[0] = '\t';
1084                 if (good_addresses == 0)
1085                 {
1086                     sprintf(buf+1, 
1087                             "for %s@%s (by default); ",
1088                             user, ctl->destaddr);
1089                 }
1090                 else if (good_addresses == 1)
1091                 {
1092                     for (idp = msgblk.recipients; idp; idp = idp->next)
1093                         if (idp->val.status.mark == XMIT_ACCEPT)
1094                             break;      /* only report first address */
1095                     if (strchr(idp->id, '@'))
1096                         sprintf(buf+1, "for %s", idp->id);
1097                     else
1098                         /*
1099                          * This could be a bit misleading, as destaddr is
1100                          * the forwarding host rather than the actual 
1101                          * destination.  Most of the time they coincide.
1102                          */
1103                         sprintf(buf+1, "for %s@%s", idp->id, ctl->destaddr);
1104                     sprintf(buf+strlen(buf), " (%s); ",
1105                             MULTIDROP(ctl) ? "multi-drop" : "single-drop");
1106                 }
1107                 else
1108                     buf[1] = '\0';
1109
1110                 strcat(buf, rfc822timestamp());
1111                 strcat(buf, "\r\n");
1112                 n = stuffline(ctl, buf);
1113             }
1114         }
1115     }
1116
1117     if (n != -1)
1118         n = stuffline(ctl, rcv);        /* ship out rest of msgblk.headers */
1119
1120     if (n == -1)
1121     {
1122         report(stdout, _("writing RFC822 msgblk.headers\n"));
1123         release_sink(ctl);
1124         free(msgblk.headers);
1125         msgblk.headers = NULL;
1126         free_str_list(&msgblk.recipients);
1127         return(PS_IOERR);
1128     }
1129     else if ((run.poll_interval == 0 || nodetach) && outlevel >= O_VERBOSE && !isafile(2))
1130         fputs("#", stderr);
1131
1132     /* write error notifications */
1133     if (no_local_matches || has_nuls || bad_addresses)
1134     {
1135         int     errlen = 0;
1136         char    errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
1137
1138         errmsg = errhd;
1139         (void) strcpy(errhd, "X-Fetchmail-Warning: ");
1140         if (no_local_matches)
1141         {
1142             if (reject_count != 1)
1143                 strcat(errhd, _("no recipient addresses matched declared local names"));
1144             else
1145             {
1146                 for (idp = msgblk.recipients; idp; idp = idp->next)
1147                     if (idp->val.status.mark == XMIT_REJECT)
1148                         break;
1149                 sprintf(errhd+strlen(errhd), _("recipient address %s didn't match any local name"), idp->id);
1150             }
1151         }
1152
1153         if (has_nuls)
1154         {
1155             if (errhd[sizeof("X-Fetchmail-Warning: ")])
1156                 strcat(errhd, "; ");
1157             strcat(errhd, _("message has embedded NULs"));
1158         }
1159
1160         if (bad_addresses)
1161         {
1162             if (errhd[sizeof("X-Fetchmail-Warning: ")])
1163                 strcat(errhd, "; ");
1164             strcat(errhd, _("SMTP listener rejected local recipient addresses: "));
1165             errlen = strlen(errhd);
1166             for (idp = msgblk.recipients; idp; idp = idp->next)
1167                 if (idp->val.status.mark == XMIT_RCPTBAD)
1168                     errlen += strlen(idp->id) + 2;
1169
1170             xalloca(errmsg, char *, errlen+3);
1171             (void) strcpy(errmsg, errhd);
1172             for (idp = msgblk.recipients; idp; idp = idp->next)
1173                 if (idp->val.status.mark == XMIT_RCPTBAD)
1174                 {
1175                     strcat(errmsg, idp->id);
1176                     if (idp->next)
1177                         strcat(errmsg, ", ");
1178                 }
1179
1180         }
1181
1182         strcat(errmsg, "\r\n");
1183
1184         /* ship out the error line */
1185         stuffline(ctl, errmsg);
1186     }
1187
1188     /* issue the delimiter line */
1189     cp = buf;
1190     *cp++ = '\r';
1191     *cp++ = '\n';
1192     *cp++ = '\0';
1193     stuffline(ctl, buf);
1194
1195 /*    free(msgblk.headers); */
1196     free_str_list(&msgblk.recipients);
1197     return(headers_ok ? PS_SUCCESS : PS_TRUNCATED);
1198 }
1199
1200 static int readbody(int sock, struct query *ctl, flag forward, int len)
1201 /* read and dispose of a message body presented on sock */
1202 /*   ctl:               query control record */
1203 /*   sock:              to which the server is connected */
1204 /*   len:               length of message */
1205 /*   forward:           TRUE to forward */
1206 {
1207     int linelen;
1208     unsigned char buf[MSGBUFSIZE+4];
1209     unsigned char *inbufp = buf;
1210     flag issoftline = FALSE;
1211
1212     /*
1213      * Pass through the text lines in the body.
1214      *
1215      * Yes, this wants to be ||, not &&.  The problem is that in the most
1216      * important delimited protocol, POP3, the length is not reliable.
1217      * As usual, the problem is Microsoft brain damage; see FAQ item S2.
1218      * So, for delimited protocols we need to ignore the length here and
1219      * instead drop out of the loop with a break statement when we see
1220      * the message delimiter.
1221      */
1222     while (protocol->delimited || len > 0)
1223     {
1224         set_timeout(mytimeout);
1225         if ((linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf)))==-1)
1226         {
1227             set_timeout(0);
1228             release_sink(ctl);
1229             return(PS_SOCKET);
1230         }
1231         set_timeout(0);
1232
1233         /* write the message size dots */
1234         if (linelen > 0)
1235         {
1236             sizeticker += linelen;
1237             while (sizeticker >= SIZETICKER)
1238             {
1239                 if (outlevel > O_SILENT && (((run.poll_interval == 0 || nodetach) && !isafile(1)) || run.showdots))
1240                 {
1241                     fputc('.', stdout);
1242                     fflush(stdout);
1243                 }
1244                 sizeticker -= SIZETICKER;
1245             }
1246         }
1247         len -= linelen;
1248
1249         /* check for end of message */
1250         if (protocol->delimited && *inbufp == '.')
1251         {
1252             if (inbufp[1] == '\r' && inbufp[2] == '\n' && inbufp[3] == '\0')
1253                 break;
1254             else if (inbufp[1] == '\n' && inbufp[2] == '\0')
1255                 break;
1256             else
1257                 msglen--;       /* subtract the size of the dot escape */
1258         }
1259
1260         msglen += linelen;
1261
1262         if (ctl->mimedecode && (ctl->mimemsg & MSG_NEEDS_DECODE)) {
1263             issoftline = UnMimeBodyline(&inbufp, protocol->delimited, issoftline);
1264             if (issoftline && (sizeof(buf)-1-(inbufp-buf) < 200))
1265             {
1266                 /*
1267                  * Soft linebreak, but less than 200 bytes left in
1268                  * input buffer. Rather than doing a buffer overrun,
1269                  * ignore the soft linebreak, NL-terminate data and
1270                  * deliver what we have now.
1271                  * (Who writes lines longer than 2K anyway?)
1272                  */
1273                 *inbufp = '\n'; *(inbufp+1) = '\0';
1274                 issoftline = 0;
1275             }
1276         }
1277
1278         /* ship out the text line */
1279         if (forward && (!issoftline))
1280         {
1281             int n;
1282             inbufp = buf;
1283
1284             /* guard against very long lines */
1285             buf[MSGBUFSIZE+1] = '\r';
1286             buf[MSGBUFSIZE+2] = '\n';
1287             buf[MSGBUFSIZE+3] = '\0';
1288
1289             n = stuffline(ctl, buf);
1290
1291             if (n < 0)
1292             {
1293                 report(stdout, _("writing message text\n"));
1294                 release_sink(ctl);
1295                 return(PS_IOERR);
1296             }
1297             else if (outlevel >= O_VERBOSE && !isafile(1))
1298             {
1299                 fputc('*', stdout);
1300                 fflush(stdout);
1301             }
1302         }
1303     }
1304
1305     return(PS_SUCCESS);
1306 }
1307
1308 #ifdef KERBEROS_V4
1309 int
1310 kerberos_auth (socket, canonical, principal) 
1311 /* authenticate to the server host using Kerberos V4 */
1312 int socket;             /* socket to server host */
1313 char *canonical;        /* server name */
1314 char *principal;
1315 {
1316     char * host_primary;
1317     KTEXT ticket;
1318     MSG_DAT msg_data;
1319     CREDENTIALS cred;
1320     Key_schedule schedule;
1321     int rem;
1322     char * prin_copy = (char *) NULL;
1323     char * prin = (char *) NULL;
1324     char * inst = (char *) NULL;
1325     char * realm = (char *) NULL;
1326
1327     if (principal != (char *)NULL && *principal)
1328     {
1329         char *cp;
1330         prin = prin_copy = xstrdup(principal);
1331         for (cp = prin_copy; *cp && *cp != '.'; ++cp)
1332             ;
1333         if (*cp)
1334         {
1335             *cp++ = '\0';
1336             inst = cp;
1337             while (*cp && *cp != '@')
1338                 ++cp;
1339             if (*cp)
1340             {
1341                 *cp++ = '\0';
1342                 realm = cp;
1343             }
1344         }
1345     }
1346   
1347     xalloca(ticket, KTEXT, sizeof (KTEXT_ST));
1348     rem = (krb_sendauth (0L, socket, ticket,
1349                          prin ? prin : "pop",
1350                          inst ? inst : canonical,
1351                          realm ? realm : ((char *) (krb_realmofhost (canonical))),
1352                          ((unsigned long) 0),
1353                          (&msg_data),
1354                          (&cred),
1355                          (schedule),
1356                          ((struct sockaddr_in *) 0),
1357                          ((struct sockaddr_in *) 0),
1358                          "KPOPV0.1"));
1359     if (prin_copy)
1360     {
1361         free(prin_copy);
1362     }
1363     if (rem != KSUCCESS)
1364     {
1365         report(stderr, _("kerberos error %s\n"), (krb_get_err_text (rem)));
1366         return (PS_AUTHFAIL);
1367     }
1368     return (0);
1369 }
1370 #endif /* KERBEROS_V4 */
1371
1372 #ifdef KERBEROS_V5
1373 static int kerberos5_auth(socket, canonical)
1374 /* authenticate to the server host using Kerberos V5 */
1375 int socket;             /* socket to server host */
1376 const char *canonical;  /* server name */
1377 {
1378     krb5_error_code retval;
1379     krb5_context context;
1380     krb5_ccache ccdef;
1381     krb5_principal client = NULL, server = NULL;
1382     krb5_error *err_ret = NULL;
1383
1384     krb5_auth_context auth_context = NULL;
1385
1386     krb5_init_context(&context);
1387     krb5_init_ets(context);
1388     krb5_auth_con_init(context, &auth_context);
1389
1390     if (retval = krb5_cc_default(context, &ccdef)) {
1391         report(stderr, "krb5_cc_default: %s\n", error_message(retval));
1392         return(PS_ERROR);
1393     }
1394
1395     if (retval = krb5_cc_get_principal(context, ccdef, &client)) {
1396         report(stderr, "krb5_cc_get_principal: %s\n", error_message(retval));
1397         return(PS_ERROR);
1398     }
1399
1400     if (retval = krb5_sname_to_principal(context, canonical, "pop",
1401            KRB5_NT_UNKNOWN,
1402            &server)) {
1403         report(stderr, "krb5_sname_to_principal: %s\n", error_message(retval));
1404         return(PS_ERROR);
1405     }
1406
1407     retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &socket,
1408          "KPOPV1.0", client, server,
1409          AP_OPTS_MUTUAL_REQUIRED,
1410          NULL,  /* no data to checksum */
1411          0,   /* no creds, use ccache instead */
1412          ccdef,
1413          &err_ret, 0,
1414
1415          NULL); /* don't need reply */
1416
1417     krb5_free_principal(context, server);
1418     krb5_free_principal(context, client);
1419     krb5_auth_con_free(context, auth_context);
1420
1421     if (retval) {
1422 #ifdef HEIMDAL
1423       if (err_ret && err_ret->e_text) {
1424           report(stderr, _("krb5_sendauth: %s [server says '%*s'] \n"),
1425                  error_message(retval),
1426                  err_ret->e_text);
1427 #else
1428       if (err_ret && err_ret->text.length) {
1429           report(stderr, _("krb5_sendauth: %s [server says '%*s'] \n"),
1430                  error_message(retval),
1431                  err_ret->text.length,
1432                  err_ret->text.data);
1433 #endif
1434           krb5_free_error(context, err_ret);
1435       } else
1436           report(stderr, "krb5_sendauth: %s\n", error_message(retval));
1437       return(PS_ERROR);
1438     }
1439
1440     return 0;
1441 }
1442 #endif /* KERBEROS_V5 */
1443
1444 static void clean_skipped_list(struct idlist **skipped_list)
1445 /* struct "idlist" contains no "prev" ptr; we must remove unused items first */
1446 {
1447     struct idlist *current=NULL, *prev=NULL, *tmp=NULL, *head=NULL;
1448     prev = current = head = *skipped_list;
1449
1450     if (!head)
1451         return;
1452     do
1453     {
1454         /* if item has no reference, remove it */
1455         if (current && current->val.status.mark == 0)
1456         {
1457             if (current == head) /* remove first item (head) */
1458             {
1459                 head = current->next;
1460                 if (current->id) free(current->id);
1461                 free(current);
1462                 prev = current = head;
1463             }
1464             else /* remove middle/last item */
1465             {
1466                 tmp = current->next;
1467                 prev->next = tmp;
1468                 if (current->id) free(current->id);
1469                 free(current);
1470                 current = tmp;
1471             }
1472         }
1473         else /* skip this item */
1474         {
1475             prev = current;
1476             current = current->next;
1477         }
1478     } while(current);
1479
1480     *skipped_list = head;
1481 }
1482
1483 static void send_size_warnings(struct query *ctl)
1484 /* send warning mail with skipped msg; reset msg count when user notified */
1485 {
1486     int size, nbr;
1487     int msg_to_send = FALSE;
1488     struct idlist *head=NULL, *current=NULL;
1489     int max_warning_poll_count;
1490
1491     head = ctl->skipped;
1492     if (!head)
1493         return;
1494
1495     /* don't start a notification message unless we need to */
1496     for (current = head; current; current = current->next)
1497         if (current->val.status.num == 0 && current->val.status.mark)
1498             msg_to_send = TRUE;
1499     if (!msg_to_send)
1500         return;
1501
1502     /*
1503      * There's no good way to recover if we can't send notification mail, 
1504      * but it's not a disaster, either, since the skipped mail will not
1505      * be deleted.
1506      */
1507     if (open_warning_by_mail(ctl, (struct msgblk *)NULL))
1508         return;
1509     stuff_warning(ctl,
1510            _("Subject: Fetchmail oversized-messages warning.\r\n"
1511              "\r\n"
1512              "The following oversized messages remain on the mail server %s:"),
1513                   ctl->server.pollname);
1514  
1515     if (run.poll_interval == 0)
1516         max_warning_poll_count = 0;
1517     else
1518         max_warning_poll_count = ctl->warnings/run.poll_interval;
1519
1520     /* parse list of skipped msg, adding items to the mail */
1521     for (current = head; current; current = current->next)
1522     {
1523         if (current->val.status.num == 0 && current->val.status.mark)
1524         {
1525             nbr = current->val.status.mark;
1526             size = atoi(current->id);
1527             stuff_warning(ctl, 
1528                     _("\t%d msg %d octets long skipped by fetchmail.\r\n"),
1529                     nbr, size);
1530         }
1531         current->val.status.num++;
1532         current->val.status.mark = 0;
1533
1534         if (current->val.status.num >= max_warning_poll_count)
1535             current->val.status.num = 0;
1536     }
1537
1538     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1539 }
1540
1541 static int do_session(ctl, proto, maxfetch)
1542 /* retrieve messages from server using given protocol method table */
1543 struct query *ctl;              /* parsed options with merged-in defaults */
1544 const struct method *proto;     /* protocol method table */
1545 const int maxfetch;             /* maximum number of messages to fetch */
1546 {
1547     int js;
1548 #ifdef HAVE_VOLATILE
1549     volatile int ok, mailserver_socket = -1;    /* pacifies -Wall */
1550 #else
1551     int ok, mailserver_socket = -1;
1552 #endif /* HAVE_VOLATILE */
1553     const char *msg;
1554     void (*pipesave)(int);
1555     void (*alrmsave)(int);
1556     struct idlist *current=NULL, *tmp=NULL;
1557
1558     protocol = proto;
1559     ctl->server.base_protocol = protocol;
1560
1561     pass = 0;
1562     tagnum = 0;
1563     tag[0] = '\0';      /* nuke any tag hanging out from previous query */
1564     ok = 0;
1565
1566     /* set up the server-nonresponse timeout */
1567     alrmsave = signal(SIGALRM, timeout_handler);
1568     mytimeout = ctl->server.timeout;
1569
1570     /* set up the broken-pipe timeout */
1571     pipesave = signal(SIGPIPE, sigpipe_handler);
1572
1573     if ((js = setjmp(restart)))
1574     {
1575 #ifdef HAVE_SIGPROCMASK
1576         /*
1577          * Don't rely on setjmp() to restore the blocked-signal mask.
1578          * It does this under BSD but is required not to under POSIX.
1579          *
1580          * If your Unix doesn't have sigprocmask, better hope it has
1581          * BSD-like behavior.  Otherwise you may see fetchmail get
1582          * permanently wedged after a second timeout on a bad read,
1583          * because alarm signals were blocked after the first.
1584          */
1585         sigset_t        allsigs;
1586
1587         sigfillset(&allsigs);
1588         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1589 #endif /* HAVE_SIGPROCMASK */
1590
1591         if (js == THROW_SIGPIPE)
1592         {
1593             signal(SIGPIPE, SIG_IGN);
1594             report(stdout,
1595                    _("SIGPIPE thrown from an MDA or a stream socket error\n"));
1596             ok = PS_SOCKET;
1597             goto cleanUp;
1598         }
1599         else if (js == THROW_TIMEOUT)
1600         {
1601             if (phase == OPEN_WAIT)
1602                 report(stdout,
1603                        _("timeout after %d seconds waiting to connect to server %s.\n"),
1604                        ctl->server.timeout, ctl->server.pollname);
1605             else if (phase == SERVER_WAIT)
1606                 report(stdout,
1607                        _("timeout after %d seconds waiting for server %s.\n"),
1608                        ctl->server.timeout, ctl->server.pollname);
1609             else if (phase == FORWARDING_WAIT)
1610                 report(stdout,
1611                        _("timeout after %d seconds waiting for %s.\n"),
1612                        ctl->server.timeout,
1613                        ctl->mda ? "MDA" : "SMTP");
1614             else if (phase == LISTENER_WAIT)
1615                 report(stdout,
1616                        _("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
1617             else
1618                 report(stdout, 
1619                        _("timeout after %d seconds.\n"), ctl->server.timeout);
1620
1621             /*
1622              * If we've exceeded our threshold for consecutive timeouts, 
1623              * try to notify the user, then mark the connection wedged.
1624              * Don't do this if the connection can idle, though; idle
1625              * timeouts just mean the frequency of mail is low.
1626              */
1627             if (timeoutcount > MAX_TIMEOUTS 
1628                 && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
1629             {
1630                 stuff_warning(ctl,
1631                               _("Subject: fetchmail sees repeated timeouts\r\n"));
1632                 stuff_warning(ctl,
1633                               _("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\r\n"), 
1634                               MAX_TIMEOUTS,
1635                               ctl->remotename,
1636                               ctl->server.truename);
1637                 stuff_warning(ctl, 
1638     _("This could mean that your mailserver is stuck, or that your SMTP\r\n" \
1639     "server is wedged, or that your mailbox file on the server has been\r\n" \
1640     "corrupted by a server error.  You can run `fetchmail -v -v' to\r\n" \
1641     "diagnose the problem.\r\n\r\n" \
1642     "Fetchmail won't poll this mailbox again until you restart it.\r\n"));
1643                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
1644                 ctl->wedged = TRUE;
1645             }
1646
1647             ok = PS_ERROR;
1648         }
1649
1650         /* try to clean up all streams */
1651         release_sink(ctl);
1652         if (ctl->smtp_socket != -1)
1653             SockClose(ctl->smtp_socket);
1654         if (mailserver_socket != -1)
1655             SockClose(mailserver_socket);
1656     }
1657     else
1658     {
1659         char buf[MSGBUFSIZE+1], *realhost;
1660         int len, num, count, new, bytes, deletions = 0, *msgsizes = NULL;
1661 #if INET6_ENABLE
1662         int fetches, dispatches, oldphase;
1663 #else /* INET6_ENABLE */
1664         int port, fetches, dispatches, oldphase;
1665 #endif /* INET6_ENABLE */
1666         struct idlist *idp;
1667
1668         /* execute pre-initialization command, if any */
1669         if (ctl->preconnect && (ok = system(ctl->preconnect)))
1670         {
1671             report(stderr, 
1672                    _("pre-connection command failed with status %d\n"), ok);
1673             ok = PS_SYNTAX;
1674             goto closeUp;
1675         }
1676
1677         /* open a socket to the mail server */
1678         oldphase = phase;
1679         phase = OPEN_WAIT;
1680         set_timeout(mytimeout);
1681 #if !INET6_ENABLE
1682 #ifdef SSL_ENABLE
1683         port = ctl->server.port ? ctl->server.port : ( ctl->use_ssl ? protocol->sslport : protocol->port );
1684 #else
1685         port = ctl->server.port ? ctl->server.port : protocol->port;
1686 #endif
1687 #endif /* !INET6_ENABLE */
1688         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
1689
1690         /* allow time for the port to be set up if we have a plugin */
1691         if (ctl->server.plugin)
1692             (void)sleep(1);
1693 #if INET6_ENABLE
1694         if ((mailserver_socket = SockOpen(realhost, 
1695                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? protocol->sslservice : protocol->service ),
1696                              ctl->server.netsec, ctl->server.plugin)) == -1)
1697 #else /* INET6_ENABLE */
1698         if ((mailserver_socket = SockOpen(realhost, port, NULL, ctl->server.plugin)) == -1)
1699 #endif /* INET6_ENABLE */
1700         {
1701             char        errbuf[BUFSIZ];
1702 #if !INET6_ENABLE
1703             int err_no = errno;
1704 #ifdef HAVE_RES_SEARCH
1705             if (err_no != 0 && h_errno != 0)
1706                 report(stderr, _("internal inconsistency\n"));
1707 #endif
1708             /*
1709              * Avoid generating a bogus error every poll cycle when we're
1710              * in daemon mode but the connection to the outside world
1711              * is down.
1712              */
1713             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
1714                   && run.poll_interval))
1715             {
1716                 report_build(stderr, _("%s connection to %s failed"), 
1717                              protocol->name, ctl->server.pollname);
1718 #ifdef HAVE_RES_SEARCH
1719                 if (h_errno != 0)
1720                 {
1721                     if (h_errno == HOST_NOT_FOUND)
1722                         strcpy(errbuf, _("host is unknown."));
1723 #ifndef __BEOS__
1724                     else if (h_errno == NO_ADDRESS)
1725                         strcpy(errbuf, _("name is valid but has no IP address."));
1726 #endif
1727                     else if (h_errno == NO_RECOVERY)
1728                         strcpy(errbuf, _("unrecoverable name server error."));
1729                     else if (h_errno == TRY_AGAIN)
1730                         strcpy(errbuf, _("temporary name server error."));
1731                     else
1732                         sprintf(errbuf, _("unknown DNS error %d."), h_errno);
1733                 }
1734                 else
1735 #endif /* HAVE_RES_SEARCH */
1736                     strcpy(errbuf, strerror(err_no));
1737                 report_complete(stderr, ": %s\n", errbuf);
1738
1739 #ifdef __UNUSED
1740                 /* 
1741                  * Don't use this.  It was an attempt to address Debian bug
1742                  * #47143 (Notify user by mail when pop server nonexistent).
1743                  * Trouble is, that doesn't work; you trip over the case 
1744                  * where your SLIP or PPP link is down...
1745                  */
1746                 /* warn the system administrator */
1747                 if (open_warning_by_mail(ctl, (struct msgblk *)NULL) == 0)
1748                 {
1749                     stuff_warning(ctl,
1750                          _("Subject: Fetchmail unreachable-server warning.\r\n"
1751                            "\r\n"
1752                            "Fetchmail could not reach the mail server %s:")
1753                                   ctl->server.pollname);
1754                     stuff_warning(ctl, errbuf, ctl->server.pollname);
1755                     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1756                 }
1757 #endif
1758             }
1759 #endif /* INET6_ENABLE */
1760             ok = PS_SOCKET;
1761             set_timeout(0);
1762             phase = oldphase;
1763             goto closeUp;
1764         }
1765         set_timeout(0);
1766         phase = oldphase;
1767
1768 #ifdef SSL_ENABLE
1769         /* perform initial SSL handshake on open connection */
1770         /* Note:  We pass the realhost name over for certificate
1771                 verification.  We may want to make this configurable */
1772         if (ctl->use_ssl && SSLOpen(mailserver_socket,ctl->sslkey,ctl->sslcert,ctl->sslproto,realhost) == -1) 
1773         {
1774             report(stderr, _("SSL connection failed.\n"));
1775             goto closeUp;
1776         }
1777 #endif
1778
1779 #ifdef KERBEROS_V4
1780         if (ctl->server.authenticate == A_KERBEROS_V4)
1781         {
1782             set_timeout(mytimeout);
1783             ok = kerberos_auth(mailserver_socket, ctl->server.truename,
1784                                ctl->server.principal);
1785             set_timeout(0);
1786             if (ok != 0)
1787                 goto cleanUp;
1788         }
1789 #endif /* KERBEROS_V4 */
1790
1791 #ifdef KERBEROS_V5
1792         if (ctl->server.authenticate == A_KERBEROS_V5)
1793         {
1794             set_timeout(mytimeout);
1795             ok = kerberos5_auth(mailserver_socket, ctl->server.truename);
1796             set_timeout(0);
1797             if (ok != 0)
1798                 goto cleanUp;
1799         }
1800 #endif /* KERBEROS_V5 */
1801
1802         /* accept greeting message from mail server */
1803         ok = (protocol->parse_response)(mailserver_socket, buf);
1804         if (ok != 0)
1805             goto cleanUp;
1806
1807         /* try to get authorized to fetch mail */
1808         stage = STAGE_GETAUTH;
1809         if (protocol->getauth)
1810         {
1811             if (protocol->password_canonify)
1812                 (protocol->password_canonify)(shroud, ctl->password, PASSWORDLEN);
1813             else
1814                 strcpy(shroud, ctl->password);
1815
1816             ok = (protocol->getauth)(mailserver_socket, ctl, buf);
1817             if (ok != 0)
1818             {
1819                 if (ok == PS_LOCKBUSY)
1820                     report(stderr, _("Lock-busy error on %s@%s\n"),
1821                           ctl->remotename,
1822                           ctl->server.truename);
1823                 else if (ok == PS_SERVBUSY)
1824                     report(stderr, _("Server busy error on %s@%s\n"),
1825                           ctl->remotename,
1826                           ctl->server.truename);
1827                 else if (ok == PS_AUTHFAIL)
1828                 {
1829                     report(stderr, _("Authorization failure on %s@%s%s\n"), 
1830                            ctl->remotename,
1831                            ctl->server.truename,
1832                            (ctl->wehaveauthed ? " (previously authorized)" : " ")
1833                         );
1834
1835                     /*
1836                      * If we're running in background, try to mail the
1837                      * calling user a heads-up about the authentication 
1838                      * failure once it looks like this isn't a fluke 
1839                      * due to the server being temporarily inaccessible.
1840                      * When we get third succesive failure, we notify the user
1841                      * but only if we haven't already managed to get
1842                      * authorization.  After that, once we get authorization
1843                      * we let the user know service is restored.
1844                      */
1845                     if (run.poll_interval
1846                         && ctl->wehavesentauthnote
1847                         && ((ctl->wehaveauthed && ++ctl->authfailcount == 10)
1848                             || ++ctl->authfailcount == 3)
1849                         && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
1850                     {
1851                         ctl->wehavesentauthnote = 1;
1852                         stuff_warning(ctl,
1853                                       _("Subject: fetchmail authentication failed\r\n"));
1854                         stuff_warning(ctl,
1855                                       _("Fetchmail could not get mail from %s@%s.\r\n"), 
1856                                       ctl->remotename,
1857                                       ctl->server.truename);
1858                         if (ctl->wehaveauthed)
1859                             stuff_warning(ctl, _("\
1860 The attempt to get authorization failed.\r\n\
1861 Since we have already succeeded in getting authorization for this\r\n\
1862 connection, this is probably another failure mode (such as busy server)\r\n\
1863 that fetchmail cannot distinguish because the server didn't send a useful\r\n\
1864 error message.\r\n\
1865 \r\n\
1866 However, if you HAVE changed you account details since starting the\r\n\
1867 fetchmail daemon, you need to stop the daemon, change your configuration\r\n\
1868 of fetchmail, and then restart the daemon.\r\n\
1869 \r\n\
1870 The fetchmail daemon will continue running and attempt to connect\r\n\
1871 at each cycle.  No future notifications will be sent until service\r\n\
1872 is restored."));
1873                         else
1874                             stuff_warning(ctl, _("\
1875 The attempt to get authorization failed.\r\n\
1876 This probably means your password is invalid, but some servers have\r\n\
1877 other failure modes that fetchmail cannot distinguish from this\r\n\
1878 because they don't send useful error messages on login failure.\r\n\
1879 \r\n\
1880 The fetchmail daemon will continue running and attempt to connect\r\n\
1881 at each cycle.  No future notifications will be sent until service\r\n\
1882 is restored."));
1883                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1884                     }
1885                 }
1886                 else
1887                     report(stderr, _("Unknown login or authentication error on %s@%s\n"),
1888                            ctl->remotename,
1889                            ctl->server.truename);
1890                     
1891                 goto cleanUp;
1892             }
1893             else
1894             {
1895                         /*
1896                          * This connection has given us authorization
1897                          * at least once.
1898                          *
1899                          * There are dodgy server (clubinternet.fr for
1900                          * example) that give spurious authorization
1901                          * failures on patently good account/password
1902                          * details, then 5 minutes later let you in!
1903                          *
1904                          * This is meant to build in some tolerance of
1905                          * such nasty bits of work
1906                          */
1907                         ctl->wehaveauthed = 1;
1908                         /*if (ctl->authfailcount >= 3)*/
1909                         if (ctl->wehavesentauthnote)
1910                         {
1911                                 ctl->wehavesentauthnote = 0;
1912                                 report(stderr,
1913                                    _("Authorization OK on %s@%s\n"),
1914                                    ctl->remotename,
1915                                    ctl->server.truename);
1916                             if (!open_warning_by_mail(ctl, (struct msgblk *)NULL))
1917                             {
1918                                         stuff_warning(ctl,
1919                                             _("Subject: fetchmail authentication OK\r\n"));
1920                                         stuff_warning(ctl,
1921                                             _("Fetchmail was able to log into %s@%s.\r\n"), 
1922                                             ctl->remotename,
1923                                             ctl->server.truename);
1924                                         stuff_warning(ctl, 
1925                                             _("Service has been restored.\r\n"));
1926                                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1927                     
1928                             }
1929                         }
1930                         /*
1931                          * Reporting only after the first three
1932                          * consecutive failures, or ten consecutive
1933                          * failures after we have managed to get
1934                          * authorization.
1935                          */
1936                         ctl->authfailcount = 0;
1937             }
1938         }
1939
1940         ctl->errcount = fetches = 0;
1941
1942         /* now iterate over each folder selected */
1943         for (idp = ctl->mailboxes; idp; idp = idp->next)
1944         {
1945             pass = 0;
1946             do {
1947                 dispatches = 0;
1948                 ++pass;
1949
1950                 /* reset timeout, in case we did an IDLE */
1951                 mytimeout = ctl->server.timeout;
1952
1953                 if (outlevel >= O_DEBUG)
1954                 {
1955                     if (idp->id)
1956                         report(stdout, _("selecting or re-polling folder %s\n"), idp->id);
1957                     else
1958                         report(stdout, _("selecting or re-polling default folder\n"));
1959                 }
1960
1961                 /* compute # of messages and number of new messages waiting */
1962                 stage = STAGE_GETRANGE;
1963                 ok = (protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &new, &bytes);
1964                 if (ok != 0)
1965                     goto cleanUp;
1966
1967                 /* show user how many messages we downloaded */
1968                 if (idp->id)
1969                     (void) sprintf(buf, _("%s at %s (folder %s)"),
1970                                    ctl->remotename, ctl->server.truename, idp->id);
1971                 else
1972                     (void) sprintf(buf, _("%s at %s"),
1973                                    ctl->remotename, ctl->server.truename);
1974                 if (outlevel > O_SILENT)
1975                 {
1976                     if (count == -1)            /* only used for ETRN */
1977                         report(stdout, _("Polling %s\n"), ctl->server.truename);
1978                     else if (count != 0)
1979                     {
1980                         if (new != -1 && (count - new) > 0)
1981                             report_build(stdout, _("%d %s (%d seen) for %s"),
1982                                   count, count > 1 ? _("messages") :
1983                                                      _("message"),
1984                                   count-new, buf);
1985                         else
1986                             report_build(stdout, _("%d %s for %s"), 
1987                                   count, count > 1 ? _("messages") :
1988                                                      _("message"), buf);
1989                         if (bytes == -1)
1990                             report_complete(stdout, ".\n");
1991                         else
1992                             report_complete(stdout, _(" (%d octets).\n"), bytes);
1993                     }
1994                     else
1995                     {
1996                         /* these are pointless in normal daemon mode */
1997                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1998                             report(stdout, _("No mail for %s\n"), buf); 
1999                     }
2000                 }
2001
2002                 /* very important, this is where we leave the do loop */ 
2003                 if (count == 0)
2004                     break;
2005
2006                 if (check_only)
2007                 {
2008                     if (new == -1 || ctl->fetchall)
2009                         new = count;
2010                     fetches = new;      /* set error status ccorrectly */
2011                     /*
2012                      * There used to be a `got noerror' here, but this
2013                      * prevneted checking of multiple folders.  This
2014                      * comment is a reminder in case I introduced some
2015                      * subtle bug by removing it...
2016                      */
2017                 }
2018                 else if (count > 0)
2019                 {    
2020                     flag        force_retrieval;
2021
2022                     /*
2023                      * What forces this code is that in POP2 and
2024                      * IMAP2bis you can't fetch a message without
2025                      * having it marked `seen'.  In POP3 and IMAP4, on the
2026                      * other hand, you can (peek_capable is set by 
2027                      * each driver module to convey this; it's not a
2028                      * method constant because of the difference between
2029                      * IMAP2bis and IMAP4, and because POP3 doesn't  peek
2030                      * if fetchall is on).
2031                      *
2032                      * The result of being unable to peek is that if there's
2033                      * any kind of transient error (DNS lookup failure, or
2034                      * sendmail refusing delivery due to process-table limits)
2035                      * the message will be marked "seen" on the server without
2036                      * having been delivered.  This is not a big problem if
2037                      * fetchmail is running in foreground, because the user
2038                      * will see a "skipped" message when it next runs and get
2039                      * clued in.
2040                      *
2041                      * But in daemon mode this leads to the message
2042                      * being silently ignored forever.  This is not
2043                      * acceptable.
2044                      *
2045                      * We compensate for this by checking the error
2046                      * count from the previous pass and forcing all
2047                      * messages to be considered new if it's nonzero.
2048                      */
2049                     force_retrieval = !peek_capable && (ctl->errcount > 0);
2050
2051                     /* 
2052                      * We need the size of each message before it's
2053                      * loaded in order to pass it to the ESMTP SIZE
2054                      * option.  If the protocol has a getsizes method,
2055                      * we presume this means it doesn't get reliable
2056                      * sizes from message fetch responses.
2057                      */
2058                     if (proto->getsizes)
2059                     {
2060                         int     i;
2061
2062                         xalloca(msgsizes, int *, sizeof(int) * count);
2063                         for (i = 0; i < count; i++)
2064                             msgsizes[i] = -1;
2065
2066                         stage = STAGE_GETSIZES;
2067                         ok = (proto->getsizes)(mailserver_socket, count, msgsizes);
2068                         if (ok != 0)
2069                             goto cleanUp;
2070
2071                         if (bytes == -1)
2072                         {
2073                             bytes = 0;
2074                             for (i = 0; i < count; i++)
2075                                 bytes += msgsizes[i];
2076                         }
2077                     }
2078
2079                     /* read, forward, and delete messages */
2080                     stage = STAGE_FETCH;
2081                     for (num = 1; num <= count; num++)
2082                     {
2083                         flag toolarge = NUM_NONZERO(ctl->limit)
2084                             && msgsizes && (msgsizes[num-1] > ctl->limit);
2085                         flag oldmsg = (!new) || (protocol->is_old && (protocol->is_old)(mailserver_socket,ctl,num));
2086                         flag fetch_it = !toolarge 
2087                             && (ctl->fetchall || force_retrieval || !oldmsg);
2088                         flag suppress_delete = FALSE;
2089                         flag suppress_forward = FALSE;
2090                         flag suppress_readbody = FALSE;
2091                         flag retained = FALSE;
2092
2093                         /*
2094                          * This check copes with Post Office/NT's
2095                          * annoying habit of randomly prepending bogus
2096                          * LIST items of length -1.  Patrick Audley
2097                          * <paudley@pobox.com> tells us: LIST shows a
2098                          * size of -1, RETR and TOP return "-ERR
2099                          * System error - couldn't open message", and
2100                          * DELE succeeds but doesn't actually delete
2101                          * the message.
2102                          */
2103                         if (msgsizes && msgsizes[num-1] == -1)
2104                         {
2105                             if (outlevel >= O_VERBOSE)
2106                                 report(stdout, 
2107                                       _("Skipping message %d, length -1\n"),
2108                                       num);
2109                             continue;
2110                         }
2111
2112                         /*
2113                          * We may want to reject this message if it's old
2114                          * or oversized, and we're not forcing retrieval.
2115                          */
2116                         if (!fetch_it)
2117                         {
2118                             if (outlevel > O_SILENT)
2119                             {
2120                                 report_build(stdout, 
2121                                      _("skipping message %d (%d octets)"),
2122                                      num, msgsizes[num-1]);
2123                                 if (toolarge && !check_only) 
2124                                 {
2125                                     char size[32];
2126                                     int cnt;
2127
2128                                     /* convert sz to string */
2129                                     sprintf(size, "%d", msgsizes[num-1]);
2130
2131                                     /* build a list of skipped messages
2132                                      * val.id = size of msg (string cnvt)
2133                                      * val.status.num = warning_poll_count
2134                                      * val.status.mask = nbr of msg this size
2135                                      */
2136
2137                                     current = ctl->skipped;
2138
2139                                     /* initialise warning_poll_count to the
2140                                      * current value so that all new msg will
2141                                      * be included in the next mail
2142                                      */
2143                                     cnt = current? current->val.status.num : 0;
2144
2145                                     /* if entry exists, increment the count */
2146                                     if (current && 
2147                                         str_in_list(&current, size, FALSE))
2148                                     {
2149                                         for ( ; current; 
2150                                                 current = current->next)
2151                                         {
2152                                             if (strcmp(current->id, size) == 0)
2153                                             {
2154                                                 current->val.status.mark++;
2155                                                 break;
2156                                             }
2157                                         }
2158                                     }
2159                                     /* otherwise, create a new entry */
2160                                     /* initialise with current poll count */
2161                                     else
2162                                     {
2163                                         tmp = save_str(&ctl->skipped, size, 1);
2164                                         tmp->val.status.num = cnt;
2165                                     }
2166
2167                                     report_build(stdout, _(" (oversized, %d octets)"),
2168                                                 msgsizes[num-1]);
2169                                 }
2170                             }
2171                         }
2172                         else
2173                         {
2174                             flag wholesize = !protocol->fetch_body;
2175
2176                             /* request a message */
2177                             ok = (protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
2178                             if (ok != 0)
2179                                 goto cleanUp;
2180
2181                             /* -1 means we didn't see a size in the response */
2182                             if (len == -1 && msgsizes)
2183                             {
2184                                 len = msgsizes[num - 1];
2185                                 wholesize = TRUE;
2186                             }
2187
2188                             if (outlevel > O_SILENT)
2189                             {
2190                                 report_build(stdout, _("reading message %d of %d"),
2191                                             num,count);
2192
2193                                 if (len > 0)
2194                                     report_build(stdout, _(" (%d %soctets)"),
2195                                         len, wholesize ? "" : _("header "));
2196                                 if (outlevel >= O_VERBOSE)
2197                                     report_complete(stdout, "\n");
2198                                 else
2199                                     report_complete(stdout, " ");
2200                             }
2201
2202                             /* 
2203                              * Read the message headers and ship them to the
2204                              * output sink.  
2205                              */
2206                             ok = readheaders(mailserver_socket, len, msgsizes[num-1],
2207                                              ctl, num);
2208                             if (ok == PS_RETAINED)
2209                                 suppress_forward = retained = TRUE;
2210                             else if (ok == PS_TRANSIENT)
2211                                 suppress_delete = suppress_forward = TRUE;
2212                             else if (ok == PS_REFUSED)
2213                                 suppress_forward = TRUE;
2214                             else if (ok == PS_TRUNCATED)
2215                                 suppress_readbody = TRUE;
2216                             else if (ok)
2217                                 goto cleanUp;
2218
2219                             /* 
2220                              * If we're using IMAP4 or something else that
2221                              * can fetch headers separately from bodies,
2222                              * it's time to request the body now.  This
2223                              * fetch may be skipped if we got an anti-spam
2224                              * or other PS_REFUSED error response during
2225                              * readheaders.
2226                              */
2227                             if (protocol->fetch_body && !suppress_readbody) 
2228                             {
2229                                 if (outlevel >= O_VERBOSE && !isafile(1))
2230                                 {
2231                                     fputc('\n', stdout);
2232                                     fflush(stdout);
2233                                 }
2234
2235                                 if ((ok = (protocol->trail)(mailserver_socket, ctl, num)))
2236                                     goto cleanUp;
2237                                 len = 0;
2238                                 if (!suppress_forward)
2239                                 {
2240                                     if ((ok=(protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
2241                                         goto cleanUp;
2242                                     /*
2243                                      * Work around a bug in Novell's
2244                                      * broken GroupWise IMAP server;
2245                                      * its body FETCH response is missing
2246                                      * the required length for the data
2247                                      * string.  This violates RFC2060.
2248                                      */
2249                                     if (len == -1)
2250                                        len = msgsizes[num-1] - msglen;
2251                                     if (outlevel > O_SILENT && !wholesize)
2252                                         report_complete(stdout,
2253                                                _(" (%d body octets) "), len);
2254                                 }
2255                             }
2256
2257                             /* process the body now */
2258                             if (len > 0)
2259                             {
2260                                 if (suppress_readbody)
2261                                 {
2262                                   /* When readheaders returns PS_TRUNCATED,
2263                                      the body (which has no content
2264                                      has already been read by readheaders,
2265                                      so we say readbody returned PS_SUCCESS */
2266                                   ok = PS_SUCCESS;
2267                                 }
2268                                 else
2269                                 {
2270                                   ok = readbody(mailserver_socket,
2271                                                 ctl,
2272                                                 !suppress_forward,
2273                                                 len);
2274                                 }
2275                                 if (ok == PS_TRANSIENT)
2276                                     suppress_delete = suppress_forward = TRUE;
2277                                 else if (ok)
2278                                     goto cleanUp;
2279
2280                                 /* tell server we got it OK and resynchronize */
2281                                 if (protocol->trail)
2282                                 {
2283                                     if (outlevel >= O_VERBOSE && !isafile(1))
2284                                     {
2285                                         fputc('\n', stdout);
2286                                         fflush(stdout);
2287                                     }
2288
2289                                     ok = (protocol->trail)(mailserver_socket, ctl, num);
2290                                     if (ok != 0)
2291                                         goto cleanUp;
2292                                 }
2293                             }
2294
2295                             /* count # messages forwarded on this pass */
2296                             if (!suppress_forward)
2297                                 dispatches++;
2298
2299                             /*
2300                              * Check to see if the numbers matched?
2301                              *
2302                              * Yes, some servers foo this up horribly.
2303                              * All IMAP servers seem to get it right, and
2304                              * so does Eudora QPOP at least in 2.xx
2305                              * versions.
2306                              *
2307                              * Microsoft Exchange gets it completely
2308                              * wrong, reporting compressed rather than
2309                              * actual sizes (so the actual length of
2310                              * message is longer than the reported size).
2311                              * Another fine example of Microsoft brain death!
2312                              *
2313                              * Some older POP servers, like the old UCB
2314                              * POP server and the pre-QPOP QUALCOMM
2315                              * versions, report a longer size in the LIST
2316                              * response than actually gets shipped up.
2317                              * It's unclear what is going on here, as the
2318                              * QUALCOMM server (at least) seems to be
2319                              * reporting the on-disk size correctly.
2320                              */
2321                             if (msgsizes && msglen != msgsizes[num-1])
2322                             {
2323                                 if (outlevel >= O_DEBUG)
2324                                     report(stdout,
2325                                           _("message %d was not the expected length (%d actual != %d expected)\n"),
2326                                           num, msglen, msgsizes[num-1]);
2327                             }
2328
2329                             /* end-of-message processing starts here */
2330                             if (!close_sink(ctl, &msgblk, !suppress_forward))
2331                             {
2332                                 ctl->errcount++;
2333                                 suppress_delete = TRUE;
2334                             }
2335                             fetches++;
2336                         }
2337
2338                         /*
2339                          * At this point in flow of control, either
2340                          * we've bombed on a protocol error or had
2341                          * delivery refused by the SMTP server
2342                          * (unlikely -- I've never seen it) or we've
2343                          * seen `accepted for delivery' and the
2344                          * message is shipped.  It's safe to mark the
2345                          * message seen and delete it on the server
2346                          * now.
2347                          */
2348
2349                         /* tell the UID code we've seen this */
2350                         if (ctl->newsaved)
2351                         {
2352                             struct idlist       *sdp;
2353
2354                             for (sdp = ctl->newsaved; sdp; sdp = sdp->next)
2355                                 if ((sdp->val.status.num == num)
2356                                                 && (!toolarge || oldmsg))
2357                                     sdp->val.status.mark = UID_SEEN;
2358                         }
2359
2360                         /* maybe we delete this message now? */
2361                         if (retained)
2362                         {
2363                             if (outlevel > O_SILENT) 
2364                                 report(stdout, _(" retained\n"));
2365                         }
2366                         else if (protocol->delete
2367                                  && !suppress_delete
2368                                  && (fetch_it ? !ctl->keep : ctl->flush))
2369                         {
2370                             deletions++;
2371                             if (outlevel > O_SILENT) 
2372                                 report_complete(stdout, _(" flushed\n"));
2373                             ok = (protocol->delete)(mailserver_socket, ctl, num);
2374                             if (ok != 0)
2375                                 goto cleanUp;
2376 #ifdef POP3_ENABLE
2377                             delete_str(&ctl->newsaved, num);
2378 #endif /* POP3_ENABLE */
2379                         }
2380                         else if (outlevel > O_SILENT) 
2381                             report_complete(stdout, _(" not flushed\n"));
2382
2383                         /* perhaps this as many as we're ready to handle */
2384                         if (maxfetch && maxfetch <= fetches && fetches < count)
2385                         {
2386                             report(stdout, _("fetchlimit %d reached; %d messages left on server\n"),
2387                                   maxfetch, count - fetches);
2388                             ok = PS_MAXFETCH;
2389                             goto cleanUp;
2390                         }
2391                     }
2392
2393                     if (!check_only && ctl->skipped
2394                         && run.poll_interval > 0 && !nodetach)
2395                     {
2396                         clean_skipped_list(&ctl->skipped);
2397                         send_size_warnings(ctl);
2398                     }
2399                 }
2400             } while
2401                   /*
2402                    * Only re-poll if we either had some actual forwards and 
2403                    * either allowed deletions and had no errors.
2404                    * Otherwise it is far too easy to get into infinite loops.
2405                    */
2406                   (dispatches && protocol->retry && !ctl->keep && !ctl->errcount);
2407         }
2408
2409     /* no_error: */
2410         /* ordinary termination with no errors -- officially log out */
2411         ok = (protocol->logout_cmd)(mailserver_socket, ctl);
2412         /*
2413          * Hmmmm...arguably this would be incorrect if we had fetches but
2414          * no dispatches (due to oversized messages, etc.)
2415          */
2416         if (ok == 0)
2417             ok = (fetches > 0) ? PS_SUCCESS : PS_NOMAIL;
2418         SockClose(mailserver_socket);
2419         goto closeUp;
2420
2421     cleanUp:
2422         /* we only get here on error */
2423         if (ok != 0 && ok != PS_SOCKET)
2424         {
2425             stage = STAGE_LOGOUT;
2426             (protocol->logout_cmd)(mailserver_socket, ctl);
2427         }
2428         SockClose(mailserver_socket);
2429     }
2430
2431     msg = (const char *)NULL;   /* sacrifice to -Wall */
2432     switch (ok)
2433     {
2434     case PS_SOCKET:
2435         msg = _("socket");
2436         break;
2437     case PS_SYNTAX:
2438         msg = _("missing or bad RFC822 header");
2439         break;
2440     case PS_IOERR:
2441         msg = _("MDA");
2442         break;
2443     case PS_ERROR:
2444         msg = _("client/server synchronization");
2445         break;
2446     case PS_PROTOCOL:
2447         msg = _("client/server protocol");
2448         break;
2449     case PS_LOCKBUSY:
2450         msg = _("lock busy on server");
2451         break;
2452     case PS_SMTP:
2453         msg = _("SMTP transaction");
2454         break;
2455     case PS_DNS:
2456         msg = _("DNS lookup");
2457         break;
2458     case PS_UNDEFINED:
2459         report(stderr, _("undefined error\n"));
2460         break;
2461     }
2462     /* no report on PS_MAXFETCH or PS_UNDEFINED or PS_AUTHFAIL */
2463     if (ok==PS_SOCKET || ok==PS_SYNTAX
2464                 || ok==PS_IOERR || ok==PS_ERROR || ok==PS_PROTOCOL 
2465                 || ok==PS_LOCKBUSY || ok==PS_SMTP || ok==PS_DNS)
2466     {
2467         char    *stem;
2468
2469         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT)
2470             stem = _("%s error while delivering to SMTP host %s\n");
2471         else
2472             stem = _("%s error while fetching from %s\n");
2473         report(stderr, stem, msg, ctl->server.pollname);
2474     }
2475
2476 closeUp:
2477     /* execute post-initialization command, if any */
2478     if (ctl->postconnect && (ok = system(ctl->postconnect)))
2479     {
2480         report(stderr, _("post-connection command failed with status %d\n"), ok);
2481         if (ok == PS_SUCCESS)
2482             ok = PS_SYNTAX;
2483     }
2484
2485     signal(SIGALRM, alrmsave);
2486     signal(SIGPIPE, pipesave);
2487     return(ok);
2488 }
2489
2490 int do_protocol(ctl, proto)
2491 /* retrieve messages from server using given protocol method table */
2492 struct query *ctl;              /* parsed options with merged-in defaults */
2493 const struct method *proto;     /* protocol method table */
2494 {
2495     int ok;
2496
2497 #ifndef KERBEROS_V4
2498     if (ctl->server.authenticate == A_KERBEROS_V4)
2499     {
2500         report(stderr, _("Kerberos V4 support not linked.\n"));
2501         return(PS_ERROR);
2502     }
2503 #endif /* KERBEROS_V4 */
2504
2505 #ifndef KERBEROS_V5
2506     if (ctl->server.authenticate == A_KERBEROS_V5)
2507     {
2508         report(stderr, _("Kerberos V5 support not linked.\n"));
2509         return(PS_ERROR);
2510     }
2511 #endif /* KERBEROS_V5 */
2512
2513     /* lacking methods, there are some options that may fail */
2514     if (!proto->is_old)
2515     {
2516         /* check for unsupported options */
2517         if (ctl->flush) {
2518             report(stderr,
2519                     _("Option --flush is not supported with %s\n"),
2520                     proto->name);
2521             return(PS_SYNTAX);
2522         }
2523         else if (ctl->fetchall) {
2524             report(stderr,
2525                     _("Option --all is not supported with %s\n"),
2526                     proto->name);
2527             return(PS_SYNTAX);
2528         }
2529     }
2530     if (!proto->getsizes && NUM_SPECIFIED(ctl->limit))
2531     {
2532         report(stderr,
2533                 _("Option --limit is not supported with %s\n"),
2534                 proto->name);
2535         return(PS_SYNTAX);
2536     }
2537
2538     /*
2539      * If no expunge limit or we do expunges within the driver,
2540      * then just do one session, passing in any fetchlimit.
2541      */
2542     if (proto->retry || !NUM_SPECIFIED(ctl->expunge))
2543         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
2544     /*
2545      * There's an expunge limit, and it isn't handled in the driver itself.
2546      * OK; do multiple sessions, each fetching a limited # of messages.
2547      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
2548      * (if it was nonzero).
2549      */
2550     else
2551     {
2552         int totalcount = 0; 
2553         int lockouts   = 0;
2554         int expunge    = NUM_VALUE_OUT(ctl->expunge);
2555         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
2556
2557         do {
2558             ok = do_session(ctl, proto, expunge);
2559             totalcount += expunge;
2560             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
2561                 break;
2562             if (ok != PS_LOCKBUSY)
2563                 lockouts = 0;
2564             else if (lockouts >= MAX_LOCKOUTS)
2565                 break;
2566             else /* ok == PS_LOCKBUSY */
2567             {
2568                 /*
2569                  * Allow time for the server lock to release.  if we
2570                  * don't do this, we'll often hit a locked-mailbox
2571                  * condition and fail.
2572                  */
2573                 lockouts++;
2574                 sleep(3);
2575             }
2576         } while
2577             (ok == PS_MAXFETCH || ok == PS_LOCKBUSY);
2578
2579         return(ok);
2580     }
2581 }
2582
2583 #if defined(HAVE_STDARG_H)
2584 void gen_send(int sock, const char *fmt, ... )
2585 #else
2586 void gen_send(sock, fmt, va_alist)
2587 int sock;               /* socket to which server is connected */
2588 const char *fmt;        /* printf-style format */
2589 va_dcl
2590 #endif
2591 /* assemble command in printf(3) style and send to the server */
2592 {
2593     char buf [MSGBUFSIZE+1];
2594     va_list ap;
2595
2596     if (protocol->tagged && !suppress_tags)
2597         (void) sprintf(buf, "%s ", GENSYM);
2598     else
2599         buf[0] = '\0';
2600
2601 #if defined(HAVE_STDARG_H)
2602     va_start(ap, fmt) ;
2603 #else
2604     va_start(ap);
2605 #endif
2606 #ifdef HAVE_VSNPRINTF
2607     vsnprintf(buf + strlen(buf), sizeof(buf), fmt, ap);
2608 #else
2609     vsprintf(buf + strlen(buf), fmt, ap);
2610 #endif
2611     va_end(ap);
2612
2613     strcat(buf, "\r\n");
2614     SockWrite(sock, buf, strlen(buf));
2615
2616     if (outlevel >= O_MONITOR)
2617     {
2618         char *cp;
2619
2620         if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
2621         {
2622             char        *sp;
2623
2624             sp = cp + strlen(shroud);
2625             *cp++ = '*';
2626             while (*sp)
2627                 *cp++ = *sp++;
2628             *cp = '\0';
2629         }
2630         buf[strlen(buf)-2] = '\0';
2631         report(stdout, "%s> %s\n", protocol->name, buf);
2632     }
2633 }
2634
2635 int gen_recv(sock, buf, size)
2636 /* get one line of input from the server */
2637 int sock;       /* socket to which server is connected */
2638 char *buf;      /* buffer to receive input */
2639 int size;       /* length of buffer */
2640 {
2641     int oldphase = phase;       /* we don't have to be re-entrant */
2642
2643     phase = SERVER_WAIT;
2644     set_timeout(mytimeout);
2645     if (SockRead(sock, buf, size) == -1)
2646     {
2647         set_timeout(0);
2648         phase = oldphase;
2649         return(PS_SOCKET);
2650     }
2651     else
2652     {
2653         set_timeout(0);
2654         if (buf[strlen(buf)-1] == '\n')
2655             buf[strlen(buf)-1] = '\0';
2656         if (buf[strlen(buf)-1] == '\r')
2657             buf[strlen(buf)-1] = '\0';
2658         if (outlevel >= O_MONITOR)
2659             report(stdout, "%s< %s\n", protocol->name, buf);
2660         phase = oldphase;
2661         return(PS_SUCCESS);
2662     }
2663 }
2664
2665 #if defined(HAVE_STDARG_H)
2666 int gen_transact(int sock, const char *fmt, ... )
2667 #else
2668 int gen_transact(int sock, fmt, va_alist)
2669 int sock;               /* socket to which server is connected */
2670 const char *fmt;        /* printf-style format */
2671 va_dcl
2672 #endif
2673 /* assemble command in printf(3) style, send to server, accept a response */
2674 {
2675     int ok;
2676     char buf [MSGBUFSIZE+1];
2677     va_list ap;
2678     int oldphase = phase;       /* we don't have to be re-entrant */
2679
2680     phase = SERVER_WAIT;
2681
2682     if (protocol->tagged && !suppress_tags)
2683         (void) sprintf(buf, "%s ", GENSYM);
2684     else
2685         buf[0] = '\0';
2686
2687 #if defined(HAVE_STDARG_H)
2688     va_start(ap, fmt) ;
2689 #else
2690     va_start(ap);
2691 #endif
2692 #ifdef HAVE_VSNPRINTF
2693     vsnprintf(buf + strlen(buf), sizeof(buf), fmt, ap);
2694 #else
2695     vsprintf(buf + strlen(buf), fmt, ap);
2696 #endif
2697     va_end(ap);
2698
2699     strcat(buf, "\r\n");
2700     SockWrite(sock, buf, strlen(buf));
2701
2702     if (outlevel >= O_MONITOR)
2703     {
2704         char *cp;
2705
2706         if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
2707         {
2708             char        *sp;
2709
2710             sp = cp + strlen(shroud);
2711             *cp++ = '*';
2712             while (*sp)
2713                 *cp++ = *sp++;
2714             *cp = '\0';
2715         }
2716         buf[strlen(buf)-1] = '\0';
2717         report(stdout, "%s> %s\n", protocol->name, buf);
2718     }
2719
2720     /* we presume this does its own response echoing */
2721     ok = (protocol->parse_response)(sock, buf);
2722
2723     phase = oldphase;
2724     return(ok);
2725 }
2726
2727 /* driver.c ends here */