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