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