]> Pileus Git - ~andy/fetchmail/blob - driver.c
Note Earl's regression fix for SSL_CTX_clear_options() on older OpenSSL.
[~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  <string.h>
13 #ifdef HAVE_MEMORY_H
14 #include  <memory.h>
15 #endif /* HAVE_MEMORY_H */
16 #if defined(STDC_HEADERS)
17 #include  <stdlib.h>
18 #include  <limits.h>
19 #endif
20 #if defined(HAVE_UNISTD_H)
21 #include <unistd.h>
22 #endif
23 #if defined(HAVE_SYS_ITIMER_H)
24 #include <sys/itimer.h>
25 #endif
26 #include  <signal.h>
27 #ifdef HAVE_SYS_WAIT_H
28 #include <sys/wait.h>
29 #endif
30
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h>
33 #endif
34 #ifdef HAVE_NET_SOCKET_H
35 #include <net/socket.h>
36 #endif
37 #include <netdb.h>
38 #ifdef HAVE_PKG_hesiod
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 #include <hesiod.h>
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 #include <langinfo.h>
49
50 #include "kerberos.h"
51 #ifdef KERBEROS_V4
52 #include <netinet/in.h>
53 #endif /* KERBEROS_V4 */
54
55 #include "i18n.h"
56 #include "socket.h"
57
58 #include "fetchmail.h"
59 #include "getaddrinfo.h"
60 #include "tunable.h"
61
62 #include "sdump.h"
63
64 /* throw types for runtime errors */
65 #define THROW_TIMEOUT   1               /* server timed out */
66
67 /* magic values for the message length array */
68 #define MSGLEN_UNKNOWN  0               /* length unknown (0 is impossible) */
69 #define MSGLEN_INVALID  -1              /* length passed back is invalid */
70 #define MSGLEN_TOOLARGE -2              /* message is too large */
71 #define MSGLEN_OLD      -3              /* message is old */
72
73 int pass;               /* how many times have we re-polled? */
74 int stage;              /* where are we? */
75 int phase;              /* where are we, for error-logging purposes? */
76 int batchcount;         /* count of messages sent in current batch */
77 flag peek_capable;      /* can we peek for better error recovery? */
78 int mailserver_socket_temp = -1;        /* socket to free if connect timeout */ 
79
80 struct addrinfo *ai0, *ai1;     /* clean these up after signal */
81
82 static volatile int timeoutcount = 0;   /* count consecutive timeouts */
83 static volatile int idletimeout = 0;    /* timeout occured in idle stage? */
84
85 static sigjmp_buf       restart;
86
87 int is_idletimeout(void)
88 /* last timeout occured in idle stage? */
89 {
90     return idletimeout;
91 }
92
93 void resetidletimeout(void)
94 {
95     idletimeout = 0;
96 }
97
98 void set_timeout(int timeleft)
99 /* reset the nonresponse-timeout */
100 {
101 #if !defined(__EMX__) && !defined(__BEOS__)
102     struct itimerval ntimeout;
103
104     if (timeleft == 0)
105         timeoutcount = 0;
106
107     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
108     ntimeout.it_value.tv_sec  = timeleft;
109     ntimeout.it_value.tv_usec = 0;
110     setitimer(ITIMER_REAL, &ntimeout, (struct itimerval *)NULL);
111 #endif
112 }
113
114 static RETSIGTYPE timeout_handler (int signal)
115 /* handle SIGALRM signal indicating a server timeout */
116 {
117     (void)signal;
118     if(stage != STAGE_IDLE) {
119         timeoutcount++;
120         /* XXX FIXME: this siglongjmp must die - it's not safe to be
121          * called from a function handler and breaks, for instance,
122          * getaddrinfo() */
123         siglongjmp(restart, THROW_TIMEOUT);
124     } else
125         idletimeout = 1;
126 }
127
128 #define CLEANUP_TIMEOUT 60 /* maximum timeout during cleanup */
129
130 static int cleanupSockClose (int fd)
131 /* close sockets in maximum CLEANUP_TIMEOUT seconds during cleanup */
132 {
133     int scerror;
134     SIGHANDLERTYPE alrmsave;
135     alrmsave = set_signal_handler(SIGALRM, null_signal_handler);
136     set_timeout(CLEANUP_TIMEOUT);
137     scerror = SockClose(fd);
138     set_timeout(0);
139     set_signal_handler(SIGALRM, alrmsave);
140     return (scerror);
141 }
142
143 #ifdef KERBEROS_V4
144 static int kerberos_auth(socket, canonical, principal) 
145 /* authenticate to the server host using Kerberos V4 */
146 int socket;             /* socket to server host */
147 char *canonical;        /* server name */
148 char *principal;
149 {
150     KTEXT ticket;
151     MSG_DAT msg_data;
152     CREDENTIALS cred;
153     Key_schedule schedule;
154     int rem;
155     char * prin_copy = (char *) NULL;
156     char * prin = (char *) NULL;
157     char * inst = (char *) NULL;
158     char * realm = (char *) NULL;
159
160     if (principal != (char *)NULL && *principal)
161     {
162         char *cp;
163         prin = prin_copy = xstrdup(principal);
164         for (cp = prin_copy; *cp && *cp != '.'; ++cp)
165             ;
166         if (*cp)
167         {
168             *cp++ = '\0';
169             inst = cp;
170             while (*cp && *cp != '@')
171                 ++cp;
172             if (*cp)
173             {
174                 *cp++ = '\0';
175                 realm = cp;
176             }
177         }
178     }
179   
180     ticket = xmalloc(sizeof (KTEXT_ST));
181     rem = (krb_sendauth (0L, socket, ticket,
182                          prin ? prin : "pop",
183                          inst ? inst : canonical,
184                          realm ? realm : ((char *) (krb_realmofhost (canonical))),
185                          ((unsigned long) 0),
186                          (&msg_data),
187                          (&cred),
188                          (schedule),
189                          ((struct sockaddr_in *) 0),
190                          ((struct sockaddr_in *) 0),
191                          "KPOPV0.1"));
192     free(ticket);
193     if (prin_copy)
194     {
195         free(prin_copy);
196     }
197     if (rem != KSUCCESS)
198     {
199         report(stderr, GT_("kerberos error %s\n"), (krb_get_err_text (rem)));
200         return (PS_AUTHFAIL);
201     }
202     return (0);
203 }
204 #endif /* KERBEROS_V4 */
205
206 #ifdef KERBEROS_V5
207 static int kerberos5_auth(socket, canonical)
208 /* authenticate to the server host using Kerberos V5 */
209 int socket;             /* socket to server host */
210 const char *canonical;  /* server name */
211 {
212     krb5_error_code retval;
213     krb5_context context;
214     krb5_ccache ccdef;
215     krb5_principal client = NULL, server = NULL;
216     krb5_error *err_ret = NULL;
217
218     krb5_auth_context auth_context = NULL;
219
220     krb5_init_context(&context);
221     krb5_auth_con_init(context, &auth_context);
222
223     if ((retval = krb5_cc_default(context, &ccdef))) {
224         report(stderr, "krb5_cc_default: %s\n", error_message(retval));
225         return(PS_ERROR);
226     }
227
228     if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
229         report(stderr, "krb5_cc_get_principal: %s\n", error_message(retval));
230         return(PS_ERROR);
231     }
232
233     if ((retval = krb5_sname_to_principal(context, canonical, "pop",
234            KRB5_NT_UNKNOWN,
235            &server))) {
236         report(stderr, "krb5_sname_to_principal: %s\n", error_message(retval));
237         return(PS_ERROR);
238     }
239
240     retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &socket,
241          "KPOPV1.0", client, server,
242          AP_OPTS_MUTUAL_REQUIRED,
243          NULL,  /* no data to checksum */
244          0,   /* no creds, use ccache instead */
245          ccdef,
246          &err_ret, 0,
247
248          NULL); /* don't need reply */
249
250     krb5_free_principal(context, server);
251     krb5_free_principal(context, client);
252     krb5_auth_con_free(context, auth_context);
253
254     if (retval) {
255 #ifdef HEIMDAL
256       if (err_ret && err_ret->e_text) {
257           char *t = err_ret->e_text;
258           char *tt = sdump(t, strlen(t));
259           report(stderr, GT_("krb5_sendauth: %s [server says '%s']\n"),
260                  error_message(retval), tt);
261           free(tt);
262 #else
263       if (err_ret && err_ret->text.length) {
264           char *tt = sdump(err_ret->text.data, err_ret->text.length);
265           report(stderr, GT_("krb5_sendauth: %s [server says '%s']\n"),
266                  error_message(retval), tt);
267           free(tt);
268 #endif
269           krb5_free_error(context, err_ret);
270       } else
271           report(stderr, "krb5_sendauth: %s\n", error_message(retval));
272       return(PS_ERROR);
273     }
274
275     return 0;
276 }
277 #endif /* KERBEROS_V5 */
278
279 static void clean_skipped_list(struct idlist **skipped_list)
280 /* struct "idlist" contains no "prev" ptr; we must remove unused items first */
281 {
282     struct idlist *current=NULL, *prev=NULL, *tmp=NULL, *head=NULL;
283     prev = current = head = *skipped_list;
284
285     if (!head)
286         return;
287     do
288     {
289         /* if item has no reference, remove it */
290         if (current && current->val.status.mark == 0)
291         {
292             if (current == head) /* remove first item (head) */
293             {
294                 head = current->next;
295                 if (current->id) free(current->id);
296                 free(current);
297                 prev = current = head;
298             }
299             else /* remove middle/last item */
300             {
301                 tmp = current->next;
302                 prev->next = tmp;
303                 if (current->id) free(current->id);
304                 free(current);
305                 current = tmp;
306             }
307         }
308         else /* skip this item */
309         {
310             prev = current;
311             current = current->next;
312         }
313     } while(current);
314
315     *skipped_list = head;
316 }
317
318 static void send_size_warnings(struct query *ctl)
319 /* send warning mail with skipped msg; reset msg count when user notified */
320 {
321     int size, nbr;
322     int msg_to_send = FALSE;
323     struct idlist *head=NULL, *current=NULL;
324     int max_warning_poll_count;
325
326     head = ctl->skipped;
327     if (!head)
328         return;
329
330     /* don't start a notification message unless we need to */
331     for (current = head; current; current = current->next)
332         if (current->val.status.num == 0 && current->val.status.mark)
333             msg_to_send = TRUE;
334     if (!msg_to_send)
335         return;
336
337     /*
338      * There's no good way to recover if we can't send notification mail, 
339      * but it's not a disaster, either, since the skipped mail will not
340      * be deleted.
341      */
342     if (open_warning_by_mail(ctl))
343         return;
344     stuff_warning(iana_charset, ctl,
345            GT_("Subject: Fetchmail oversized-messages warning"));
346     stuff_warning(NULL, ctl, "%s", "");
347     if (ctl->limitflush)
348         stuff_warning(NULL, ctl,
349                 GT_("The following oversized messages were deleted on server %s account %s:"),
350                 ctl->server.pollname, ctl->remotename);
351     else
352         stuff_warning(NULL, ctl,
353                 GT_("The following oversized messages remain on server %s account %s:"),
354                 ctl->server.pollname, ctl->remotename);
355
356     stuff_warning(NULL, ctl, "%s", "");
357
358     if (run.poll_interval == 0)
359         max_warning_poll_count = 0;
360     else
361         max_warning_poll_count = ctl->warnings/run.poll_interval;
362
363     /* parse list of skipped msg, adding items to the mail */
364     for (current = head; current; current = current->next)
365     {
366         if (current->val.status.num == 0 && current->val.status.mark)
367         {
368             nbr = current->val.status.mark;
369             size = atoi(current->id);
370             if (ctl->limitflush)
371                 stuff_warning(NULL, ctl,
372                         ngettext("  %d message  %d octets long deleted by fetchmail.",
373                                  "  %d messages %d octets long deleted by fetchmail.", nbr),
374                         nbr, size);
375             else
376                 stuff_warning(NULL, ctl,
377                         ngettext("  %d message  %d octets long skipped by fetchmail.",
378                                  "  %d messages %d octets long skipped by fetchmail.", nbr),
379                         nbr, size);
380         }
381         current->val.status.num++;
382         current->val.status.mark = 0;
383
384         if (current->val.status.num >= max_warning_poll_count)
385             current->val.status.num = 0;
386     }
387
388     stuff_warning(NULL, ctl, "%s", "");
389
390     close_warning_by_mail(ctl, (struct msgblk *)NULL);
391 }
392
393 static void mark_oversized(struct query *ctl, int size)
394 /* mark a message oversized */
395 {
396     struct idlist *current=NULL, *tmp=NULL;
397     char sizestr[32];
398     int cnt;
399
400     /* convert size to string */
401     snprintf(sizestr, sizeof(sizestr), "%d", size);
402
403     /* build a list of skipped messages
404      * val.id = size of msg (string cnvt)
405      * val.status.num = warning_poll_count
406      * val.status.mask = nbr of msg this size
407      */
408
409     current = ctl->skipped;
410
411     /* initialise warning_poll_count to the
412      * current value so that all new msg will
413      * be included in the next mail
414      */
415     cnt = current ? current->val.status.num : 0;
416
417     /* if entry exists, increment the count */
418     if (current && (tmp = str_in_list(&current, sizestr, FALSE)))
419     {
420         tmp->val.status.mark++;
421     }
422     /* otherwise, create a new entry */
423     /* initialise with current poll count */
424     else
425     {
426         tmp = save_str(&ctl->skipped, sizestr, 1);
427         tmp->val.status.num = cnt;
428     }
429 }
430
431 static int eat_trailer(int sock, struct query *ctl)
432 {
433     /* we only need this LF if we're printing ticker dots
434      * AND we are dumping protocol traces. */
435     if (outlevel >= O_VERBOSE && want_progress()) fputc('\n', stdout);
436     return (ctl->server.base_protocol->trail)(sock, ctl, tag);
437 }
438
439 static int fetch_messages(int mailserver_socket, struct query *ctl, 
440                           int count, int **msgsizes, int maxfetch,
441                           int *fetches, int *dispatches, int *deletions,
442                           int *transient_errors)
443 /* fetch messages in lockstep mode */
444 {
445     flag force_retrieval;
446     int num, firstnum = 1, lastnum = 0, err, len;
447     int fetchsizelimit = ctl->fetchsizelimit;
448     int msgsize;
449     int initialfetches = *fetches;
450
451     if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit))
452     {
453         /* for POP3, we can get the size of one mail only! Unfortunately, this
454          * protocol specific test cannot be done elsewhere as the protocol
455          * could be "auto". */
456         switch (ctl->server.protocol)
457         {
458             case P_POP3: case P_APOP: case P_RPOP:
459             fetchsizelimit = 1;
460         }
461
462         /* Time to allocate memory to store the sizes */
463         xfree(*msgsizes);
464         *msgsizes = (int *)xmalloc(sizeof(int) * fetchsizelimit);
465     }
466
467     /*
468      * What forces this code is that in POP2 and
469      * IMAP2bis you can't fetch a message without
470      * having it marked `seen'.  In POP3 and IMAP4, on the
471      * other hand, you can (peek_capable is set by 
472      * each driver module to convey this; it's not a
473      * method constant because of the difference between
474      * IMAP2bis and IMAP4, and because POP3 doesn't  peek
475      * if fetchall is on).
476      *
477      * The result of being unable to peek is that if there's
478      * any kind of transient error (DNS lookup failure, or
479      * sendmail refusing delivery due to process-table limits)
480      * the message will be marked "seen" on the server without
481      * having been delivered.  This is not a big problem if
482      * fetchmail is running in foreground, because the user
483      * will see a "skipped" message when it next runs and get
484      * clued in.
485      *
486      * But in daemon mode this leads to the message
487      * being silently ignored forever.  This is not
488      * acceptable.
489      *
490      * We compensate for this by checking the error
491      * count from the previous pass and forcing all
492      * messages to be considered new if it's nonzero.
493      */
494     force_retrieval = !peek_capable && (ctl->errcount > 0);
495
496     for (num = 1; num <= count; num++)
497     {
498         flag suppress_delete = FALSE;
499         flag suppress_forward = FALSE;
500         flag suppress_readbody = FALSE;
501         flag retained = FALSE;
502         int msgcode = MSGLEN_UNKNOWN;
503
504         /* check if the message is old
505          * Note: the size of the message may not be known here */
506         if (ctl->fetchall || force_retrieval) {
507             /* empty */
508         } else { 
509             if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num)) {
510                     msgcode = MSGLEN_OLD;
511             }
512         }
513         if (msgcode == MSGLEN_OLD)
514         {
515             /*
516              * To avoid flooding the logs when using --keep, report
517              * skipping for old messages only when --flush is on.
518              */
519             if (outlevel > O_SILENT && ctl->flush)
520             {
521                 report_build(stdout, 
522                              GT_("skipping message %s@%s:%d"),
523                              ctl->remotename, ctl->server.truename, num);
524             }
525
526             goto flagthemail;
527         }
528
529         if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) &&
530             lastnum < num)
531         {
532             /* Instead of getting the sizes of all mails at the start, we get
533              * the sizes in blocks of fetchsizelimit. This leads to better
534              * performance when there are too many mails (say, 10000) in
535              * the mailbox and either we are not getting all the mails at
536              * one go (--fetchlimit 100) or there is a frequent socket
537              * error while just getting the sizes of all mails! */
538
539             int i;
540             int oldstage = stage;
541             firstnum = num;
542             lastnum = num + fetchsizelimit - 1;
543             if (lastnum > count)
544                 lastnum = count;
545             for (i = 0; i < fetchsizelimit; i++)
546                 (*msgsizes)[i] = 0;
547
548             stage = STAGE_GETSIZES;
549             err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, *msgsizes);
550             if (err != 0) {
551                 return err;
552             }
553             stage = oldstage;
554         }
555
556         msgsize = *msgsizes ? (*msgsizes)[num-firstnum] : 0;
557
558         /* check if the message is oversized */
559         if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit))
560             msgcode = MSGLEN_TOOLARGE;
561 /*      else if (msgsize == 512)
562             msgcode = MSGLEN_OLD;  (hmh) sample code to skip message */
563
564         if (msgcode < 0)
565         {
566             if (msgcode == MSGLEN_TOOLARGE)
567             {
568                 mark_oversized(ctl, msgsize);
569                 if (!ctl->limitflush)
570                     suppress_delete = TRUE;
571             }
572             if (outlevel > O_SILENT)
573             {
574                 /* old messages are already handled above */
575                 report_build(stdout, 
576                              GT_("skipping message %s@%s:%d (%d octets)"),
577                              ctl->remotename, ctl->server.truename, num,
578                              msgsize);
579                 switch (msgcode)
580                 {
581                 case MSGLEN_INVALID:
582                     /*
583                      * Invalid lengths are produced by Post Office/NT's
584                      * annoying habit of randomly prepending bogus
585                      * LIST items of length -1.  Patrick Audley
586                      * <paudley@pobox.com> tells us: LIST shows a
587                      * size of -1, RETR and TOP return "-ERR
588                      * System error - couldn't open message", and
589                      * DELE succeeds but doesn't actually delete
590                      * the message.
591                      */
592                     report_build(stdout, GT_(" (length -1)"));
593                     break;
594                 case MSGLEN_TOOLARGE:
595                     report_build(stdout, GT_(" (oversized)"));
596                     break;
597                 }
598             }
599         }
600         else
601         {
602           /* XXX FIXME: make this one variable, wholesize and
603              separatefetchbody query the same variable just with
604              inverted logic */
605             flag wholesize = !ctl->server.base_protocol->fetch_body;
606             flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
607
608             /* request a message */
609             err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
610             if (err == PS_TRANSIENT)    /* server is probably Exchange */
611             {
612                 report(stdout,
613                              GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
614                              ctl->remotename, ctl->server.truename, num,
615                              msgsize);
616                 (*transient_errors)++;
617                 continue;
618             }
619             else if (err != 0)
620                 return(err);
621
622             /* -1 means we didn't see a size in the response */
623             if (len == -1)
624             {
625                 len = msgsize;
626                 wholesize = TRUE;
627             }
628
629             if (outlevel > O_SILENT)
630             {
631                 report_build(stdout, GT_("reading message %s@%s:%d of %d"),
632                              ctl->remotename, ctl->server.truename,
633                              num, count);
634
635                 if (len > 0)
636                     report_build(stdout, wholesize ? GT_(" (%d octets)")
637                                  : GT_(" (%d header octets)"), len);
638                 if (want_progress()) {
639                     /* flush and add a blank to append ticker dots */
640                     report_flush(stdout);
641                     putchar(' ');
642                 }
643             }
644
645             /* 
646              * Read the message headers and ship them to the
647              * output sink.  
648              */
649             err = readheaders(mailserver_socket, len, msgsize,
650                              ctl, num,
651                              /* pass the suppress_readbody flag only if the underlying
652                               * protocol does not fetch the body separately */
653                              separatefetchbody ? 0 : &suppress_readbody);
654
655             if (err == PS_RETAINED)
656                 suppress_forward = suppress_delete = retained = TRUE;
657             else if (err == PS_TRANSIENT)
658             {
659                 suppress_delete = suppress_forward = TRUE;
660                 (*transient_errors)++;
661             }
662             else if (err == PS_REFUSED)
663                 suppress_forward = TRUE;
664             else if (err)
665                 return(err);
666
667             /* tell server we got it OK and resynchronize */
668             if (separatefetchbody && ctl->server.base_protocol->trail)
669             {
670                 err = eat_trailer(mailserver_socket, ctl);
671                 if (err) return(err);
672             }
673
674             /* do not read the body which is not being forwarded only if
675              * the underlying protocol allows the body to be fetched
676              * separately */
677             if (separatefetchbody && suppress_forward)
678                 suppress_readbody = TRUE;
679
680             /* 
681              * If we're using IMAP4 or something else that
682              * can fetch headers separately from bodies,
683              * it's time to request the body now.  This
684              * fetch may be skipped if we got an anti-spam
685              * or other PS_REFUSED error response during
686              * readheaders.
687              */
688             if (!suppress_readbody)
689             {
690                 if (separatefetchbody)
691                 {
692                     len = -1;
693                     if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
694                         return(err);
695                     /*
696                      * Work around a bug in Novell's
697                      * broken GroupWise IMAP server;
698                      * its body FETCH response is missing
699                      * the required length for the data
700                      * string.  This violates RFC2060.
701                      */
702                     if (len == -1)
703                         len = msgsize - msgblk.msglen;
704                     if (!wholesize) {
705                         if (outlevel > O_SILENT)
706                             report_build(stdout,
707                                     GT_(" (%d body octets)"), len);
708                         if (want_progress()) {
709                             report_flush(stdout);
710                             putchar(' ');
711                         }
712                     }
713                 }
714
715                 /* process the body now */
716                 err = readbody(mailserver_socket,
717                               ctl,
718                               !suppress_forward,
719                               len);
720
721                 if (err == PS_TRANSIENT)
722                 {
723                     suppress_delete = suppress_forward = TRUE;
724                     (*transient_errors)++;
725                 }
726                 else if (err)
727                     return(err);
728
729                 /* tell server we got it OK and resynchronize */
730                 if (ctl->server.base_protocol->trail) {
731                     err = eat_trailer(mailserver_socket, ctl);
732                     if (err) return(err);
733                 }
734             }
735
736             /* count # messages forwarded on this pass */
737             if (!suppress_forward)
738                 (*dispatches)++;
739
740             /*
741              * Check to see if the numbers matched?
742              *
743              * Yes, some servers foo this up horribly.
744              * All IMAP servers seem to get it right, and
745              * so does Eudora QPOP at least in 2.xx
746              * versions.
747              *
748              * Microsoft Exchange gets it completely
749              * wrong, reporting compressed rather than
750              * actual sizes (so the actual length of
751              * message is longer than the reported size).
752              * Another fine example of Microsoft brain death!
753              *
754              * Some older POP servers, like the old UCB
755              * POP server and the pre-QPOP QUALCOMM
756              * versions, report a longer size in the LIST
757              * response than actually gets shipped up.
758              * It's unclear what is going on here, as the
759              * QUALCOMM server (at least) seems to be
760              * reporting the on-disk size correctly.
761              *
762              * qmail-pop3d also goofs up message sizes and does not
763              * count the line end characters properly.
764              */
765             if (msgblk.msglen != msgsize)
766             {
767                 if (outlevel >= O_DEBUG)
768                     report(stdout,
769                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
770                            ctl->remotename, ctl->server.truename, num,
771                            msgblk.msglen, msgsize);
772             }
773
774             /* end-of-message processing starts here */
775             if (!close_sink(ctl, &msgblk, !suppress_forward))
776             {
777                 ctl->errcount++;
778                 suppress_delete = TRUE;
779             }
780             if (!retained)
781                 (*fetches)++;
782         }
783
784 flagthemail:
785         /*
786          * At this point in flow of control,
787          * either we've bombed on a protocol error
788          * or had delivery refused by the SMTP server
789          * or we've seen `accepted for delivery' and the message is shipped.
790          * It's safe to mark the message seen and delete it on the server now.
791          */
792
793         /* in softbounce mode, suppress deletion and marking as seen */
794         if (suppress_forward)
795             suppress_delete = suppress_delete || run.softbounce;
796
797         /* maybe we delete this message now? */
798         if (retained)
799         {
800             if (outlevel > O_SILENT) 
801                 report_complete(stdout, GT_(" retained\n"));
802         }
803         else if (ctl->server.base_protocol->delete_msg
804                  && !suppress_delete
805                  && ((msgcode >= 0 && !ctl->keep)
806                      || (msgcode == MSGLEN_OLD && ctl->flush)
807                      || (msgcode == MSGLEN_TOOLARGE && ctl->limitflush)))
808         {
809             (*deletions)++;
810             if (outlevel > O_SILENT) 
811                 report_complete(stdout, GT_(" flushed\n"));
812             err = (ctl->server.base_protocol->delete_msg)(mailserver_socket, ctl, num);
813             if (err != 0)
814                 return(err);
815         }
816         else
817         {
818             /*
819              * To avoid flooding the logs when using --keep, report
820              * skipping of new messages only.
821              */
822             if (outlevel > O_SILENT && msgcode != MSGLEN_OLD)
823             report_complete(stdout, GT_(" not flushed\n"));
824
825             /* maybe we mark this message as seen now? */
826             if (ctl->server.base_protocol->mark_seen
827                 && !suppress_delete
828                 && (msgcode >= 0 && ctl->keep))
829             {
830                 err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
831                 if (err != 0)
832                     return(err);
833             }
834         }
835
836         /* perhaps this as many as we're ready to handle */
837         if (maxfetch && maxfetch <= *fetches && num < count)
838         {
839             int remcount = count - (*fetches - initialfetches);
840             report(stdout,
841                    ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
842                             "fetchlimit %d reached; %d messages left on server %s account %s\n", remcount),
843                    maxfetch, remcount, ctl->server.truename, ctl->remotename);
844             return(PS_MAXFETCH);
845         }
846     } /* for (num = 1; num <= count; num++) */
847
848     return(PS_SUCCESS);
849 }
850
851 /* retrieve messages from server using given protocol method table */
852 static int do_session(
853         /* parsed options with merged-in defaults */
854         struct query *ctl,
855         /* protocol method table */
856         const struct method *proto,
857         /* maximum number of messages to fetch */
858         const int maxfetch)
859 {
860     static int *msgsizes;
861     volatile int err, mailserver_socket = -1;   /* pacifies -Wall */
862     int tmperr;
863     int deletions = 0, js;
864     const char *msg;
865     SIGHANDLERTYPE alrmsave;
866
867     ctl->server.base_protocol = proto;
868
869     msgsizes = NULL;
870     pass = 0;
871     err = 0;
872     init_transact(proto);
873
874     /* set up the server-nonresponse timeout */
875     alrmsave = set_signal_handler(SIGALRM, timeout_handler);
876     mytimeout = ctl->server.timeout;
877
878     if ((js = sigsetjmp(restart,1)))
879     {
880         /* exception caught */
881         sigset_t        allsigs;
882
883         sigfillset(&allsigs);
884         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
885
886         if (ai0) {
887             fm_freeaddrinfo(ai0); ai0 = NULL;
888         }
889
890         if (ai1) {
891             fm_freeaddrinfo(ai1); ai1 = NULL;
892         }
893         
894         if (js == THROW_TIMEOUT)
895         {
896             if (phase == OPEN_WAIT)
897                 report(stdout,
898                        GT_("timeout after %d seconds waiting to connect to server %s.\n"),
899                        ctl->server.timeout, ctl->server.pollname);
900             else if (phase == SERVER_WAIT)
901                 report(stdout,
902                        GT_("timeout after %d seconds waiting for server %s.\n"),
903                        ctl->server.timeout, ctl->server.pollname);
904             else if (phase == FORWARDING_WAIT)
905                 report(stdout,
906                        GT_("timeout after %d seconds waiting for %s.\n"),
907                        ctl->server.timeout,
908                        ctl->mda ? "MDA" : "SMTP");
909             else if (phase == LISTENER_WAIT)
910                 report(stdout,
911                        GT_("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
912             else
913                 report(stdout, 
914                        GT_("timeout after %d seconds.\n"), ctl->server.timeout);
915
916             /*
917              * If we've exceeded our threshold for consecutive timeouts, 
918              * try to notify the user, then mark the connection wedged.
919              * Don't do this if the connection can idle, though; idle
920              * timeouts just mean the frequency of mail is low.
921              */
922             if (timeoutcount > MAX_TIMEOUTS 
923                 && !open_warning_by_mail(ctl))
924             {
925                 stuff_warning(iana_charset, ctl,
926                               GT_("Subject: fetchmail sees repeated timeouts"));
927                 stuff_warning(NULL, ctl, "%s", "");
928                 stuff_warning(NULL, ctl,
929                               GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"), 
930                               MAX_TIMEOUTS,
931                               ctl->remotename, ctl->server.truename);
932                 stuff_warning(NULL, ctl, 
933     GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
934     "server is wedged, or that your mailbox file on the server has been\n" \
935     "corrupted by a server error.  You can run `fetchmail -v -v' to\n" \
936     "diagnose the problem.\n\n" \
937     "Fetchmail won't poll this mailbox again until you restart it.\n"));
938                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
939                 ctl->wedged = TRUE;
940             }
941         }
942
943         err = PS_SOCKET;
944         goto cleanUp;
945     }
946     else
947     {
948         /* sigsetjmp returned zero -> normal operation */
949         char buf[MSGBUFSIZE+1], *realhost;
950         int count, newm, bytes;
951         int fetches, dispatches, transient_errors, oldphase;
952         struct idlist *idp;
953
954         /* execute pre-initialization command, if any */
955         if (ctl->preconnect && (err = system(ctl->preconnect)))
956         {
957             if (WIFSIGNALED(err))
958                 report(stderr,
959                         GT_("pre-connection command terminated with signal %d\n"), WTERMSIG(err));
960             else
961                 report(stderr,
962                         GT_("pre-connection command failed with status %d\n"), WEXITSTATUS(err));
963             err = PS_SYNTAX;
964             goto closeUp;
965         }
966
967         /* open a socket to the mail server */
968         oldphase = phase;
969         phase = OPEN_WAIT;
970         set_timeout(mytimeout);
971
972 #ifdef HAVE_PKG_hesiod
973         /* If either the pollname or vianame are "hesiod" we want to
974            lookup the user's hesiod pobox host */
975         if (!strcasecmp(ctl->server.queryname, "hesiod")) {
976             struct hes_postoffice *hes_p;
977             hes_p = hes_getmailhost(ctl->remotename);
978             if (hes_p != NULL && strcmp(hes_p->po_type, "POP") == 0) {
979                  free(ctl->server.queryname);
980                  ctl->server.queryname = xstrdup(hes_p->po_host);
981                  if (ctl->server.via)
982                      free(ctl->server.via);
983                  ctl->server.via = xstrdup(hes_p->po_host);
984             } else {
985                  report(stderr,
986                         GT_("couldn't find HESIOD pobox for %s\n"),
987                         ctl->remotename);
988             }
989         }
990 #endif /* HESIOD */
991
992         /*
993          * Canonicalize the server truename for later use.  This also
994          * functions as a probe for whether the mailserver is accessible.
995          * We try it on each poll cycle until we get a result.  This way,
996          * fetchmail won't fail if started up when the network is inaccessible.
997          */
998         if (ctl->server.dns && !ctl->server.trueaddr)
999         {
1000             if (ctl->server.lead_server)
1001             {
1002                 char    *leadname = ctl->server.lead_server->truename;
1003
1004                 /* prevent core dump from ill-formed or duplicate entry */
1005                 if (!leadname)
1006                 {
1007                     report(stderr, GT_("Lead server has no name.\n"));
1008                     err = PS_DNS;
1009                     set_timeout(0);
1010                     phase = oldphase;
1011                     goto closeUp;
1012                 }
1013
1014                 xfree(ctl->server.truename);
1015                 ctl->server.truename = xstrdup(leadname);
1016             }
1017             else
1018             {
1019                 struct addrinfo hints, *res;
1020                 int error;
1021
1022                 memset(&hints, 0, sizeof(hints));
1023                 hints.ai_socktype = SOCK_STREAM;
1024                 hints.ai_family = AF_UNSPEC;
1025                 hints.ai_flags = AI_CANONNAME;
1026 #ifdef AI_ADDRCONFIG
1027                 hints.ai_flags |= AI_ADDRCONFIG;
1028 #endif
1029
1030                 error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
1031                 if (error)
1032                 {
1033                     report(stderr,
1034                            GT_("couldn't find canonical DNS name of %s (%s): %s\n"),
1035                            ctl->server.pollname, ctl->server.queryname,
1036                            gai_strerror(error));
1037                     err = PS_DNS;
1038                     set_timeout(0);
1039                     phase = oldphase;
1040                     goto closeUp;
1041                 }
1042                 else
1043                 {
1044                     xfree(ctl->server.truename);
1045                     /* Older FreeBSD versions return NULL in ai_canonname
1046                      * if they cannot canonicalize, rather than copying
1047                      * the queryname here, as IEEE Std 1003.1-2001
1048                      * requires. Work around NULL. */
1049                     if (res->ai_canonname != NULL) {
1050                         ctl->server.truename = xstrdup(res->ai_canonname);
1051                     } else {
1052                         ctl->server.truename = xstrdup(ctl->server.queryname);
1053                     }
1054                     ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
1055                     ctl->server.trueaddr_len = res->ai_addrlen;
1056                     memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
1057                     fm_freeaddrinfo(res);
1058                 }
1059             }
1060         }
1061
1062         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
1063
1064         /* allow time for the port to be set up if we have a plugin */
1065         if (ctl->server.plugin)
1066             (void)sleep(1);
1067         if ((mailserver_socket = SockOpen(realhost, 
1068                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ),
1069                              ctl->server.plugin, &ai0)) == -1)
1070         {
1071             char        errbuf[BUFSIZ];
1072             int err_no = errno;
1073             /*
1074              * Avoid generating a bogus error every poll cycle when we're
1075              * in daemon mode but the connection to the outside world
1076              * is down.
1077              */
1078             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
1079                   && run.poll_interval))
1080             {
1081                 report_build(stderr, GT_("%s connection to %s failed"), 
1082                              ctl->server.base_protocol->name, ctl->server.pollname);
1083                     strlcpy(errbuf, strerror(err_no), sizeof(errbuf));
1084                 report_complete(stderr, ": %s\n", errbuf);
1085
1086             }
1087             err = PS_SOCKET;
1088             set_timeout(0);
1089             phase = oldphase;
1090             goto closeUp;
1091         }
1092
1093 #ifdef SSL_ENABLE
1094         /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen 
1095          * because the socket can be closed.
1096          */
1097         mailserver_socket_temp = mailserver_socket;
1098         set_timeout(mytimeout);
1099
1100         /* perform initial SSL handshake on open connection */
1101         if (ctl->use_ssl &&
1102                 SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
1103                     ctl->sslproto, ctl->sslcertck,
1104                     ctl->sslcertfile, ctl->sslcertpath,
1105                     ctl->sslfingerprint, ctl->sslcommonname ?
1106                     ctl->sslcommonname : realhost, ctl->server.pollname,
1107                     &ctl->remotename) == -1)
1108         {
1109             set_timeout(0);
1110             report(stderr, GT_("SSL connection failed.\n"));
1111             err = PS_SOCKET;
1112             goto cleanUp;
1113         }
1114         
1115         /* Fetchmail didn't hang on SSLOpen, 
1116          * then no need to set mailserver_socket_temp 
1117          */
1118         mailserver_socket_temp = -1;
1119 #endif
1120         
1121         /* A timeout is still defined before SSLOpen, 
1122          * then Fetchmail hanging on SSLOpen is handled.
1123          */
1124         set_timeout(0);
1125         phase = oldphase;
1126 #ifdef KERBEROS_V4
1127         if (ctl->server.authenticate == A_KERBEROS_V4 && (strcasecmp(proto->name,"IMAP") != 0))
1128         {
1129             set_timeout(mytimeout);
1130             err = kerberos_auth(mailserver_socket, ctl->server.truename,
1131                                ctl->server.principal);
1132             set_timeout(0);
1133             if (err != 0)
1134                 goto cleanUp;
1135         }
1136 #endif /* KERBEROS_V4 */
1137
1138 #ifdef KERBEROS_V5
1139         if (ctl->server.authenticate == A_KERBEROS_V5)
1140         {
1141             set_timeout(mytimeout);
1142             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1143             set_timeout(0);
1144             if (err != 0)
1145                 goto cleanUp;
1146         }
1147 #endif /* KERBEROS_V5 */
1148
1149         /* accept greeting message from mail server */
1150         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1151         if (err != 0)
1152             goto cleanUp;
1153
1154         /* try to get authorized to fetch mail */
1155         stage = STAGE_GETAUTH;
1156         if (ctl->server.base_protocol->getauth)
1157         {
1158             set_timeout(mytimeout);
1159             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1160             set_timeout(0);
1161
1162             if (err != 0)
1163             {
1164                 if (err == PS_LOCKBUSY)
1165                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1166                           ctl->remotename,
1167                           ctl->server.truename);
1168                 else if (err == PS_SERVBUSY)
1169                     report(stderr, GT_("Server busy error on %s@%s\n"),
1170                           ctl->remotename,
1171                           ctl->server.truename);
1172                 else if (err == PS_AUTHFAIL)
1173                 {
1174                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1175                            ctl->remotename,
1176                            ctl->server.truename,
1177                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1178                         );
1179                     if (ctl->server.authenticate == A_ANY && !ctl->wehaveauthed) {
1180                         report(stderr, GT_("For help, see http://www.fetchmail.info/fetchmail-FAQ.html#R15\n"));
1181                     }
1182
1183                     /*
1184                      * If we're running in background, try to mail the
1185                      * calling user a heads-up about the authentication 
1186                      * failure once it looks like this isn't a fluke 
1187                      * due to the server being temporarily inaccessible.
1188                      * When we get third succesive failure, we notify the user
1189                      * but only if we haven't already managed to get
1190                      * authorization.  After that, once we get authorization
1191                      * we let the user know service is restored.
1192                      */
1193                     if (run.poll_interval
1194                         && !ctl->wehavesentauthnote
1195                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1196                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1197                         && !open_warning_by_mail(ctl))
1198                     {
1199                         ctl->wehavesentauthnote = 1;
1200                         stuff_warning(iana_charset, ctl,
1201                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1202                             ctl->remotename, ctl->server.truename);
1203                         stuff_warning(NULL, ctl, "%s", "");
1204                         stuff_warning(NULL, ctl,
1205                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1206                                       ctl->remotename,
1207                                       ctl->server.truename);
1208                         if (ctl->wehaveauthed) {
1209                             stuff_warning(NULL, ctl, GT_("\
1210 The attempt to get authorization failed.\n\
1211 Since we have already succeeded in getting authorization for this\n\
1212 connection, this is probably another failure mode (such as busy server)\n\
1213 that fetchmail cannot distinguish because the server didn't send a useful\n\
1214 error message."));
1215                             stuff_warning(NULL, ctl, GT_("\
1216 \n\
1217 However, if you HAVE changed your account details since starting the\n\
1218 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1219 of fetchmail, and then restart the daemon.\n\
1220 \n\
1221 The fetchmail daemon will continue running and attempt to connect\n\
1222 at each cycle.  No future notifications will be sent until service\n\
1223 is restored."));
1224                         } else {
1225                             stuff_warning(NULL, ctl, GT_("\
1226 The attempt to get authorization failed.\n\
1227 This probably means your password is invalid, but some servers have\n\
1228 other failure modes that fetchmail cannot distinguish from this\n\
1229 because they don't send useful error messages on login failure.\n\
1230 \n\
1231 The fetchmail daemon will continue running and attempt to connect\n\
1232 at each cycle.  No future notifications will be sent until service\n\
1233 is restored."));
1234                         }
1235                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1236                     }
1237                 }
1238                 else if (err == PS_REPOLL)
1239                 {
1240                   if (outlevel >= O_VERBOSE)
1241                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1242                            ctl->remotename,
1243                            ctl->server.truename);
1244                 }
1245                 else
1246                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1247                            ctl->remotename,
1248                            ctl->server.truename);
1249                     
1250                 goto cleanUp;
1251             }
1252             else
1253             {
1254                 /*
1255                  * This connection has given us authorization at least once.
1256                  *
1257                  * There are dodgy server (clubinternet.fr for example) that
1258                  * give spurious authorization failures on patently good
1259                  * account/password details, then 5 minutes later let you in!
1260                  *
1261                  * This is meant to build in some tolerance of such nasty bits
1262                  * of work.
1263                  */
1264                 ctl->wehaveauthed = 1;
1265                 /*if (ctl->authfailcount >= 3)*/
1266                 if (ctl->wehavesentauthnote)
1267                 {
1268                     ctl->wehavesentauthnote = 0;
1269                     report(stderr,
1270                            GT_("Authorization OK on %s@%s\n"),
1271                            ctl->remotename,
1272                            ctl->server.truename);
1273                     if (!open_warning_by_mail(ctl))
1274                     {
1275                         stuff_warning(iana_charset, ctl,
1276                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1277                                       ctl->remotename, ctl->server.truename);
1278                         stuff_warning(NULL, ctl, "%s", "");
1279                         stuff_warning(NULL, ctl,
1280                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1281                                       ctl->remotename,
1282                                       ctl->server.truename);
1283                         stuff_warning(NULL, ctl, 
1284                                       GT_("Service has been restored.\n"));
1285                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1286                     
1287                     }
1288                 }
1289                 /*
1290                  * Reporting only after the first three
1291                  * consecutive failures, or ten consecutive
1292                  * failures after we have managed to get
1293                  * authorization.
1294                  */
1295                 ctl->authfailcount = 0;
1296             }
1297         }
1298
1299         ctl->errcount = fetches = 0;
1300
1301         /* now iterate over each folder selected */
1302         for (idp = ctl->mailboxes; idp; idp = idp->next)
1303         {
1304             ctl->folder = idp->id;
1305             pass = 0;
1306             do {
1307                 dispatches = 0;
1308                 transient_errors = 0;
1309                 ++pass;
1310
1311                 /* reset timeout, in case we did an IDLE */
1312                 mytimeout = ctl->server.timeout;
1313
1314                 if (outlevel >= O_DEBUG)
1315                 {
1316                     if (idp->id)
1317                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1318                     else
1319                         report(stdout, GT_("selecting or re-polling default folder\n"));
1320                 }
1321
1322                 /* compute # of messages and number of new messages waiting */
1323                 stage = STAGE_GETRANGE;
1324                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1325                 if (err != 0)
1326                     goto cleanUp;
1327
1328                 /* show user how many messages we downloaded */
1329                 if (idp->id)
1330                     (void) snprintf(buf, sizeof(buf),
1331                                    GT_("%s at %s (folder %s)"),
1332                                    ctl->remotename, ctl->server.pollname, idp->id);
1333                 else
1334                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1335                                    ctl->remotename, ctl->server.pollname);
1336                 if (outlevel > O_SILENT)
1337                 {
1338                     if (count == -1)            /* only used for ETRN */
1339                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1340                     else if (count != 0)
1341                     {
1342                         if (newm != -1 && (count - newm) > 0)
1343                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1344                                   count,
1345                                   count - newm, 
1346                                   ngettext("seen", "seen", (unsigned long)count-newm),
1347                                   buf);
1348                         else
1349                             report_build(stdout, ngettext("%d message for %s",
1350                                                           "%d messages for %s",
1351                                                           count), 
1352                                   count, buf);
1353                         if (bytes == -1)
1354                             report_complete(stdout, ".\n");
1355                         else
1356                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1357                     }
1358                     else
1359                     {
1360                         /* these are pointless in normal daemon mode */
1361                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1362                             report(stdout, GT_("No mail for %s\n"), buf); 
1363                     }
1364                 }
1365
1366                 /* very important, this is where we leave the do loop */ 
1367                 if (count == 0)
1368                     break;
1369
1370                 if (check_only)
1371                 {
1372                     if (newm == -1 || ctl->fetchall)
1373                         newm = count;
1374                     fetches = newm;     /* set error status correctly */
1375                     /*
1376                      * There used to be a `goto noerror' here, but this
1377                      * prevented checking of multiple folders.  This
1378                      * comment is a reminder in case I introduced some
1379                      * subtle bug by removing it...
1380                      */
1381                 }
1382                 else if (count > 0)
1383                 {    
1384                     int         i;
1385
1386                     /*
1387                      * Don't trust the message count passed by the server.
1388                      * Without this check, it might be possible to do a
1389                      * DNS-spoofing attack that would pass back a ridiculous 
1390                      * count, and allocate a malloc area that would overlap
1391                      * a portion of the stack.
1392                      */
1393                     if ((unsigned)count > INT_MAX/sizeof(int))
1394                     {
1395                         report(stderr, GT_("bogus message count!"));
1396                         err = PS_PROTOCOL;
1397                         goto cleanUp;
1398                     }
1399
1400                     /* 
1401                      * We need the size of each message before it's
1402                      * loaded in order to pass it to the ESMTP SIZE
1403                      * option.  If the protocol has a getsizes method,
1404                      * we presume this means it doesn't get reliable
1405                      * sizes from message fetch responses.
1406                      *
1407                      * If the protocol supports getting sizes of subset of
1408                      * messages, we skip this step now.
1409                      */
1410                     if (proto->getsizes &&
1411                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1412                     {
1413                         xfree(msgsizes);
1414                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1415                         for (i = 0; i < count; i++)
1416                             msgsizes[i] = 0;
1417
1418                         stage = STAGE_GETSIZES;
1419                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1420                         if (err != 0)
1421                             goto cleanUp;
1422
1423                         if (bytes == -1)
1424                         {
1425                             bytes = 0;
1426                             for (i = 0; i < count; i++)
1427                                 bytes += msgsizes[i];
1428                         }
1429                     }
1430
1431                     /* read, forward, and delete messages */
1432                     stage = STAGE_FETCH;
1433
1434                     /* fetch in lockstep mode */
1435                     err = fetch_messages(mailserver_socket, ctl, 
1436                                          count, &msgsizes,
1437                                          maxfetch,
1438                                          &fetches, &dispatches, &deletions,
1439                                          &transient_errors);
1440                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1441                         goto cleanUp;
1442
1443                     if (transient_errors > MAX_TRANSIENT_ERRORS)
1444                     {
1445                         if (outlevel > O_SILENT)
1446                         {
1447                             report(stderr, GT_("Too many mails skipped (%d > %d) due to transient errors for %s\n"),
1448                                     transient_errors, MAX_TRANSIENT_ERRORS, buf);
1449                         }
1450                     }
1451
1452                     if (!check_only && ctl->skipped
1453                         && run.poll_interval > 0 && !nodetach)
1454                     {
1455                         clean_skipped_list(&ctl->skipped);
1456                         send_size_warnings(ctl);
1457                     }
1458                 }
1459
1460                 /* end-of-mailbox processing before we repoll or switch to another one */
1461                 if (ctl->server.base_protocol->end_mailbox_poll)
1462                 {
1463                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1464                     if (tmperr) {
1465                         err = tmperr;
1466                         goto cleanUp;
1467                     }
1468                 }
1469                 /* Return now if we have reached the fetchlimit */
1470                 if (maxfetch && maxfetch <= fetches)
1471                     goto no_error;
1472             } while
1473                   /*
1474                    * Only repoll if we either had some actual forwards
1475                    * or are idling for new mails and had no errors.
1476                    * Otherwise it is far too easy to get into infinite loops.
1477                    */
1478                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1479         }
1480
1481         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1482
1483     no_error:
1484         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1485         stage = STAGE_LOGOUT;
1486         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1487         if (tmperr != PS_SUCCESS)
1488             err = tmperr;
1489         /*
1490          * Hmmmm...arguably this would be incorrect if we had fetches but
1491          * no dispatches (due to oversized messages, etc.)
1492          */
1493         else if (err == PS_SUCCESS && fetches == 0)
1494             err = PS_NOMAIL;
1495         /*
1496          * Close all SMTP delivery sockets.  For optimum performance
1497          * we'd like to hold them open til end of run, but (1) this
1498          * loses if our poll interval is longer than the MTA's
1499          * inactivity timeout, and (2) some MTAs (like smail) don't
1500          * deliver after each message, but rather queue up mail and
1501          * wait to actually deliver it until the input socket is
1502          * closed.
1503          *
1504          * don't send QUIT for ODMR case because we're acting as a
1505          * proxy between the SMTP server and client.
1506          */
1507         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1508         cleanupSockClose(mailserver_socket);
1509         goto closeUp;
1510
1511     cleanUp:
1512         /* we only get here on error */
1513         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1514         {
1515             stage = STAGE_LOGOUT;
1516             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1517         }
1518
1519         /* try to clean up all streams */
1520         release_sink(ctl);
1521         /*
1522          * Sending SMTP QUIT on signal is theoretically nice, but led
1523          * to a subtle bug.  If fetchmail was terminated by signal
1524          * while it was shipping message text, it would hang forever
1525          * waiting for a command acknowledge.  In theory we could
1526          * enable the QUIT only outside of the message send.  In
1527          * practice, we don't care.  All mailservers hang up on a
1528          * dropped TCP/IP connection anyway.
1529          */
1530         smtp_close(ctl, 0);
1531         if (mailserver_socket != -1) {
1532             cleanupSockClose(mailserver_socket);
1533         }
1534         /* If there was a connect timeout, the socket should be closed.
1535          * mailserver_socket_temp contains the socket to close.
1536          */
1537         if (mailserver_socket_temp != -1) {
1538             cleanupSockClose(mailserver_socket_temp);
1539             mailserver_socket_temp = -1;
1540         }
1541     }
1542
1543     /* no report on PS_AUTHFAIL */
1544     msg = NULL;
1545     switch (err)
1546     {
1547     case PS_SOCKET:
1548         msg = GT_("socket");
1549         break;
1550     case PS_SYNTAX:
1551         msg = GT_("missing or bad RFC822 header");
1552         break;
1553     case PS_IOERR:
1554         msg = GT_("MDA");
1555         break;
1556     case PS_ERROR:
1557         msg = GT_("client/server synchronization");
1558         break;
1559     case PS_PROTOCOL:
1560         msg = GT_("client/server protocol");
1561         break;
1562     case PS_LOCKBUSY:
1563         msg = GT_("lock busy on server");
1564         break;
1565     case PS_SMTP:
1566         msg = GT_("SMTP transaction");
1567         break;
1568     case PS_DNS:
1569         msg = GT_("DNS lookup");
1570         break;
1571     case PS_UNDEFINED:
1572         msg = GT_("undefined");
1573         break;
1574     }
1575     if (msg) {
1576         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1577                 || err == PS_SMTP)
1578             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1579                     msg, ctl->remotename, ctl->server.pollname,
1580                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1581         else
1582             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1583                     msg, ctl->remotename, ctl->server.pollname);
1584     }
1585
1586 closeUp:
1587     xfree(msgsizes);
1588     ctl->folder = NULL;
1589
1590     /* execute wrapup command, if any */
1591     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1592     {
1593         if (WIFSIGNALED(tmperr))
1594             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1595         else
1596             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1597         if (err == PS_SUCCESS)
1598             err = PS_SYNTAX;
1599     }
1600
1601     set_timeout(0); /* cancel any pending alarm */
1602     set_signal_handler(SIGALRM, alrmsave);
1603     return(err);
1604 }
1605
1606 /** retrieve messages from server using given protocol method table */
1607 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1608                 const struct method *proto /** protocol method table */)
1609 {
1610     int err;
1611
1612 #ifndef KERBEROS_V4
1613     if (ctl->server.authenticate == A_KERBEROS_V4)
1614     {
1615         report(stderr, GT_("Kerberos V4 support not linked.\n"));
1616         return(PS_ERROR);
1617     }
1618 #endif /* KERBEROS_V4 */
1619
1620 #ifndef KERBEROS_V5
1621     if (ctl->server.authenticate == A_KERBEROS_V5)
1622     {
1623         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1624         return(PS_ERROR);
1625     }
1626 #endif /* KERBEROS_V5 */
1627
1628     /* lacking methods, there are some options that may fail */
1629     if (!proto->is_old)
1630     {
1631         /* check for unsupported options */
1632         if (ctl->flush) {
1633             report(stderr,
1634                     GT_("Option --flush is not supported with %s\n"),
1635                     proto->name);
1636             return(PS_SYNTAX);
1637         }
1638         else if (ctl->fetchall) {
1639             report(stderr,
1640                     GT_("Option --all is not supported with %s\n"),
1641                     proto->name);
1642             return(PS_SYNTAX);
1643         }
1644     }
1645     if (!(proto->getsizes || proto->getpartialsizes)
1646             && NUM_SPECIFIED(ctl->limit))
1647     {
1648         report(stderr,
1649                 GT_("Option --limit is not supported with %s\n"),
1650                 proto->name);
1651         return(PS_SYNTAX);
1652     }
1653
1654     /*
1655      * If no expunge limit or we do expunges within the driver,
1656      * then just do one session, passing in any fetchlimit.
1657      */
1658     if ((ctl->keep && !ctl->flush) ||
1659         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1660         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1661     /*
1662      * There's an expunge limit, and it isn't handled in the driver itself.
1663      * OK; do multiple sessions, each fetching a limited # of messages.
1664      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1665      * (if it was nonzero).
1666      */
1667     else
1668     {
1669         int totalcount = 0; 
1670         int lockouts   = 0;
1671         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1672         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1673
1674         do {
1675             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1676                 expunge = fetchlimit - totalcount;
1677             err = do_session(ctl, proto, expunge);
1678             totalcount += expunge;
1679             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1680                 break;
1681             if (err != PS_LOCKBUSY)
1682                 lockouts = 0;
1683             else if (lockouts >= MAX_LOCKOUTS)
1684                 break;
1685             else /* err == PS_LOCKBUSY */
1686             {
1687                 /*
1688                  * Allow time for the server lock to release.  if we
1689                  * don't do this, we'll often hit a locked-mailbox
1690                  * condition and fail.
1691                  */
1692                 lockouts++;
1693                 sleep(3);
1694             }
1695         } while
1696             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1697
1698         return(err);
1699     }
1700 }
1701
1702
1703 /* driver.c ends here */