]> Pileus Git - ~andy/fetchmail/blob - driver.c
Also run Kerberos errors through sdump().
[~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 #include <hesiod.h>
40 #endif
41
42 #include <langinfo.h>
43
44 #include "kerberos.h"
45 #ifdef KERBEROS_V4
46 #include <netinet/in.h>
47 #endif /* KERBEROS_V4 */
48
49 #include "i18n.h"
50 #include "socket.h"
51
52 #include "fetchmail.h"
53 #include "getaddrinfo.h"
54 #include "tunable.h"
55
56 #include "sdump.h"
57
58 /* throw types for runtime errors */
59 #define THROW_TIMEOUT   1               /* server timed out */
60
61 /* magic values for the message length array */
62 #define MSGLEN_UNKNOWN  0               /* length unknown (0 is impossible) */
63 #define MSGLEN_INVALID  -1              /* length passed back is invalid */
64 #define MSGLEN_TOOLARGE -2              /* message is too large */
65 #define MSGLEN_OLD      -3              /* message is old */
66
67 int pass;               /* how many times have we re-polled? */
68 int stage;              /* where are we? */
69 int phase;              /* where are we, for error-logging purposes? */
70 int batchcount;         /* count of messages sent in current batch */
71 flag peek_capable;      /* can we peek for better error recovery? */
72 int mailserver_socket_temp = -1;        /* socket to free if connect timeout */ 
73
74 struct addrinfo *ai0, *ai1;     /* clean these up after signal */
75
76 static volatile int timeoutcount = 0;   /* count consecutive timeouts */
77 static volatile int idletimeout = 0;    /* timeout occured in idle stage? */
78
79 static sigjmp_buf       restart;
80
81 int is_idletimeout(void)
82 /* last timeout occured in idle stage? */
83 {
84     return idletimeout;
85 }
86
87 void resetidletimeout(void)
88 {
89     idletimeout = 0;
90 }
91
92 void set_timeout(int timeleft)
93 /* reset the nonresponse-timeout */
94 {
95 #if !defined(__EMX__) && !defined(__BEOS__)
96     struct itimerval ntimeout;
97
98     if (timeleft == 0)
99         timeoutcount = 0;
100
101     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
102     ntimeout.it_value.tv_sec  = timeleft;
103     ntimeout.it_value.tv_usec = 0;
104     setitimer(ITIMER_REAL, &ntimeout, (struct itimerval *)NULL);
105 #endif
106 }
107
108 static RETSIGTYPE timeout_handler (int signal)
109 /* handle SIGALRM signal indicating a server timeout */
110 {
111     (void)signal;
112     if(stage != STAGE_IDLE) {
113         timeoutcount++;
114         /* XXX FIXME: this siglongjmp must die - it's not safe to be
115          * called from a function handler and breaks, for instance,
116          * getaddrinfo() */
117         siglongjmp(restart, THROW_TIMEOUT);
118     } else
119         idletimeout = 1;
120 }
121
122 #define CLEANUP_TIMEOUT 60 /* maximum timeout during cleanup */
123
124 static int cleanupSockClose (int fd)
125 /* close sockets in maximum CLEANUP_TIMEOUT seconds during cleanup */
126 {
127     int scerror;
128     SIGHANDLERTYPE alrmsave;
129     alrmsave = set_signal_handler(SIGALRM, null_signal_handler);
130     set_timeout(CLEANUP_TIMEOUT);
131     scerror = SockClose(fd);
132     set_timeout(0);
133     set_signal_handler(SIGALRM, alrmsave);
134     return (scerror);
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                 /* To avoid flooding the syslog when using --keep,
509                  * report "Skipped message" only when:
510                  *  1) --verbose is on, or
511                  *  2) fetchmail does not use syslog
512                  */
513             if (   (outlevel >= O_VERBOSE) ||
514                    (outlevel > O_SILENT && !run.use_syslog)
515                )
516             {
517                 report_build(stdout, 
518                              GT_("skipping message %s@%s:%d"),
519                              ctl->remotename, ctl->server.truename, num);
520             }
521
522             goto flagthemail;
523         }
524
525         if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) &&
526             lastnum < num)
527         {
528             /* Instead of getting the sizes of all mails at the start, we get
529              * the sizes in blocks of fetchsizelimit. This leads to better
530              * performance when there are too many mails (say, 10000) in
531              * the mailbox and either we are not getting all the mails at
532              * one go (--fetchlimit 100) or there is a frequent socket
533              * error while just getting the sizes of all mails! */
534
535             int i;
536             int oldstage = stage;
537             firstnum = num;
538             lastnum = num + fetchsizelimit - 1;
539             if (lastnum > count)
540                 lastnum = count;
541             for (i = 0; i < fetchsizelimit; i++)
542                 (*msgsizes)[i] = 0;
543
544             stage = STAGE_GETSIZES;
545             err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, *msgsizes);
546             if (err != 0) {
547                 return err;
548             }
549             stage = oldstage;
550         }
551
552         msgsize = *msgsizes ? (*msgsizes)[num-firstnum] : 0;
553
554         /* check if the message is oversized */
555         if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit))
556             msgcode = MSGLEN_TOOLARGE;
557 /*      else if (msgsize == 512)
558             msgcode = MSGLEN_OLD;  (hmh) sample code to skip message */
559
560         if (msgcode < 0)
561         {
562             if (msgcode == MSGLEN_TOOLARGE)
563             {
564                 mark_oversized(ctl, msgsize);
565                 if (!ctl->limitflush)
566                     suppress_delete = TRUE;
567             }
568             if (outlevel > O_SILENT)
569             {
570                 /* old messages are already handled above */
571                 report_build(stdout, 
572                              GT_("skipping message %s@%s:%d (%d octets)"),
573                              ctl->remotename, ctl->server.truename, num,
574                              msgsize);
575                 switch (msgcode)
576                 {
577                 case MSGLEN_INVALID:
578                     /*
579                      * Invalid lengths are produced by Post Office/NT's
580                      * annoying habit of randomly prepending bogus
581                      * LIST items of length -1.  Patrick Audley
582                      * <paudley@pobox.com> tells us: LIST shows a
583                      * size of -1, RETR and TOP return "-ERR
584                      * System error - couldn't open message", and
585                      * DELE succeeds but doesn't actually delete
586                      * the message.
587                      */
588                     report_build(stdout, GT_(" (length -1)"));
589                     break;
590                 case MSGLEN_TOOLARGE:
591                     report_build(stdout, GT_(" (oversized)"));
592                     break;
593                 }
594             }
595         }
596         else
597         {
598           /* XXX FIXME: make this one variable, wholesize and
599              separatefetchbody query the same variable just with
600              inverted logic */
601             flag wholesize = !ctl->server.base_protocol->fetch_body;
602             flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
603
604             /* request a message */
605             err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
606             if (err == PS_TRANSIENT)    /* server is probably Exchange */
607             {
608                 report(stdout,
609                              GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
610                              ctl->remotename, ctl->server.truename, num,
611                              msgsize);
612                 continue;
613             }
614             else if (err != 0)
615                 return(err);
616
617             /* -1 means we didn't see a size in the response */
618             if (len == -1)
619             {
620                 len = msgsize;
621                 wholesize = TRUE;
622             }
623
624             if (outlevel > O_SILENT)
625             {
626                 report_build(stdout, GT_("reading message %s@%s:%d of %d"),
627                              ctl->remotename, ctl->server.truename,
628                              num, count);
629
630                 if (len > 0)
631                     report_build(stdout, wholesize ? GT_(" (%d octets)")
632                                  : GT_(" (%d header octets)"), len);
633                 if (want_progress()) {
634                     /* flush and add a blank to append ticker dots */
635                     report_flush(stdout);
636                     putchar(' ');
637                 }
638             }
639
640             /* 
641              * Read the message headers and ship them to the
642              * output sink.  
643              */
644             err = readheaders(mailserver_socket, len, msgsize,
645                              ctl, num,
646                              /* pass the suppress_readbody flag only if the underlying
647                               * protocol does not fetch the body separately */
648                              separatefetchbody ? 0 : &suppress_readbody);
649
650             if (err == PS_RETAINED)
651                 suppress_forward = suppress_delete = retained = TRUE;
652             else if (err == PS_TRANSIENT)
653                 suppress_delete = suppress_forward = TRUE;
654             else if (err == PS_REFUSED)
655                 suppress_forward = TRUE;
656             else if (err)
657                 return(err);
658
659             /* tell server we got it OK and resynchronize */
660             if (separatefetchbody && ctl->server.base_protocol->trail)
661             {
662                 err = eat_trailer(mailserver_socket, ctl);
663                 if (err) return(err);
664             }
665
666             /* do not read the body which is not being forwarded only if
667              * the underlying protocol allows the body to be fetched
668              * separately */
669             if (separatefetchbody && suppress_forward)
670                 suppress_readbody = TRUE;
671
672             /* 
673              * If we're using IMAP4 or something else that
674              * can fetch headers separately from bodies,
675              * it's time to request the body now.  This
676              * fetch may be skipped if we got an anti-spam
677              * or other PS_REFUSED error response during
678              * readheaders.
679              */
680             if (!suppress_readbody)
681             {
682                 if (separatefetchbody)
683                 {
684                     len = -1;
685                     if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
686                         return(err);
687                     /*
688                      * Work around a bug in Novell's
689                      * broken GroupWise IMAP server;
690                      * its body FETCH response is missing
691                      * the required length for the data
692                      * string.  This violates RFC2060.
693                      */
694                     if (len == -1)
695                         len = msgsize - msgblk.msglen;
696                     if (!wholesize) {
697                         if (outlevel > O_SILENT)
698                             report_build(stdout,
699                                     GT_(" (%d body octets)"), len);
700                         if (want_progress()) {
701                             report_flush(stdout);
702                             putchar(' ');
703                         }
704                     }
705                 }
706
707                 /* process the body now */
708                 err = readbody(mailserver_socket,
709                               ctl,
710                               !suppress_forward,
711                               len);
712
713                 if (err == PS_TRANSIENT)
714                     suppress_delete = suppress_forward = TRUE;
715                 else if (err)
716                     return(err);
717
718                 /* tell server we got it OK and resynchronize */
719                 if (ctl->server.base_protocol->trail) {
720                     err = eat_trailer(mailserver_socket, ctl);
721                     if (err) return(err);
722                 }
723             }
724
725             /* count # messages forwarded on this pass */
726             if (!suppress_forward)
727                 (*dispatches)++;
728
729             /*
730              * Check to see if the numbers matched?
731              *
732              * Yes, some servers foo this up horribly.
733              * All IMAP servers seem to get it right, and
734              * so does Eudora QPOP at least in 2.xx
735              * versions.
736              *
737              * Microsoft Exchange gets it completely
738              * wrong, reporting compressed rather than
739              * actual sizes (so the actual length of
740              * message is longer than the reported size).
741              * Another fine example of Microsoft brain death!
742              *
743              * Some older POP servers, like the old UCB
744              * POP server and the pre-QPOP QUALCOMM
745              * versions, report a longer size in the LIST
746              * response than actually gets shipped up.
747              * It's unclear what is going on here, as the
748              * QUALCOMM server (at least) seems to be
749              * reporting the on-disk size correctly.
750              *
751              * qmail-pop3d also goofs up message sizes and does not
752              * count the line end characters properly.
753              */
754             if (msgblk.msglen != msgsize)
755             {
756                 if (outlevel >= O_DEBUG)
757                     report(stdout,
758                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
759                            ctl->remotename, ctl->server.truename, num,
760                            msgblk.msglen, msgsize);
761             }
762
763             /* end-of-message processing starts here */
764             if (!close_sink(ctl, &msgblk, !suppress_forward))
765             {
766                 ctl->errcount++;
767                 suppress_delete = TRUE;
768             }
769             if (!retained)
770                 (*fetches)++;
771         }
772
773 flagthemail:
774         /*
775          * At this point in flow of control,
776          * either we've bombed on a protocol error
777          * or had delivery refused by the SMTP server
778          * or we've seen `accepted for delivery' and the message is shipped.
779          * It's safe to mark the message seen and delete it on the server now.
780          */
781
782         /* in softbounce mode, suppress deletion and marking as seen */
783         if (suppress_forward)
784             suppress_delete = suppress_delete || run.softbounce;
785
786         /* maybe we delete this message now? */
787         if (retained)
788         {
789             if (outlevel > O_SILENT) 
790                 report_complete(stdout, GT_(" retained\n"));
791         }
792         else if (ctl->server.base_protocol->delete_msg
793                  && !suppress_delete
794                  && ((msgcode >= 0 && !ctl->keep)
795                      || (msgcode == MSGLEN_OLD && ctl->flush)
796                      || (msgcode == MSGLEN_TOOLARGE && ctl->limitflush)))
797         {
798             (*deletions)++;
799             if (outlevel > O_SILENT) 
800                 report_complete(stdout, GT_(" flushed\n"));
801             err = (ctl->server.base_protocol->delete_msg)(mailserver_socket, ctl, num);
802             if (err != 0)
803                 return(err);
804         }
805         else
806         {
807             if (   (outlevel >= O_VERBOSE) ||
808                         /* To avoid flooding the syslog when using --keep,
809                          * report "Skipped message" only when:
810                          *  1) --verbose is on, or
811                          *  2) fetchmail does not use syslog, or
812                          *  3) the message was skipped for some other
813                          *     reason than just being old.
814                          */
815                    (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD))
816                )
817             report_complete(stdout, GT_(" not flushed\n"));
818
819             /* maybe we mark this message as seen now? */
820             if (ctl->server.base_protocol->mark_seen
821                 && !suppress_delete
822                 && (msgcode >= 0 && ctl->keep))
823             {
824                 err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
825                 if (err != 0)
826                     return(err);
827             }
828         }
829
830         /* perhaps this as many as we're ready to handle */
831         if (maxfetch && maxfetch <= *fetches && num < count)
832         {
833             int remcount = count - (*fetches - initialfetches);
834             report(stdout,
835                    ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
836                             "fetchlimit %d reached; %d messages left on server %s account %s\n", remcount),
837                    maxfetch, remcount, ctl->server.truename, ctl->remotename);
838             return(PS_MAXFETCH);
839         }
840     } /* for (num = 1; num <= count; num++) */
841
842     return(PS_SUCCESS);
843 }
844
845 /* retrieve messages from server using given protocol method table */
846 static int do_session(
847         /* parsed options with merged-in defaults */
848         struct query *ctl,
849         /* protocol method table */
850         const struct method *proto,
851         /* maximum number of messages to fetch */
852         const int maxfetch)
853 {
854     static int *msgsizes;
855     volatile int err, mailserver_socket = -1;   /* pacifies -Wall */
856     int tmperr;
857     int deletions = 0, js;
858     const char *msg;
859     SIGHANDLERTYPE alrmsave;
860
861     ctl->server.base_protocol = proto;
862
863     msgsizes = NULL;
864     pass = 0;
865     err = 0;
866     init_transact(proto);
867
868     /* set up the server-nonresponse timeout */
869     alrmsave = set_signal_handler(SIGALRM, timeout_handler);
870     mytimeout = ctl->server.timeout;
871
872     if ((js = sigsetjmp(restart,1)))
873     {
874         /* exception caught */
875         sigset_t        allsigs;
876
877         sigfillset(&allsigs);
878         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
879
880         if (ai0) {
881             fm_freeaddrinfo(ai0); ai0 = NULL;
882         }
883
884         if (ai1) {
885             fm_freeaddrinfo(ai1); ai1 = NULL;
886         }
887         
888         if (js == THROW_TIMEOUT)
889         {
890             if (phase == OPEN_WAIT)
891                 report(stdout,
892                        GT_("timeout after %d seconds waiting to connect to server %s.\n"),
893                        ctl->server.timeout, ctl->server.pollname);
894             else if (phase == SERVER_WAIT)
895                 report(stdout,
896                        GT_("timeout after %d seconds waiting for server %s.\n"),
897                        ctl->server.timeout, ctl->server.pollname);
898             else if (phase == FORWARDING_WAIT)
899                 report(stdout,
900                        GT_("timeout after %d seconds waiting for %s.\n"),
901                        ctl->server.timeout,
902                        ctl->mda ? "MDA" : "SMTP");
903             else if (phase == LISTENER_WAIT)
904                 report(stdout,
905                        GT_("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
906             else
907                 report(stdout, 
908                        GT_("timeout after %d seconds.\n"), ctl->server.timeout);
909
910             /*
911              * If we've exceeded our threshold for consecutive timeouts, 
912              * try to notify the user, then mark the connection wedged.
913              * Don't do this if the connection can idle, though; idle
914              * timeouts just mean the frequency of mail is low.
915              */
916             if (timeoutcount > MAX_TIMEOUTS 
917                 && !open_warning_by_mail(ctl))
918             {
919                 stuff_warning(iana_charset, ctl,
920                               GT_("Subject: fetchmail sees repeated timeouts"));
921                 stuff_warning(NULL, ctl, "%s", "");
922                 stuff_warning(NULL, ctl,
923                               GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"), 
924                               MAX_TIMEOUTS,
925                               ctl->remotename, ctl->server.truename);
926                 stuff_warning(NULL, ctl, 
927     GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
928     "server is wedged, or that your mailbox file on the server has been\n" \
929     "corrupted by a server error.  You can run `fetchmail -v -v' to\n" \
930     "diagnose the problem.\n\n" \
931     "Fetchmail won't poll this mailbox again until you restart it.\n"));
932                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
933                 ctl->wedged = TRUE;
934             }
935         }
936
937         err = PS_SOCKET;
938         goto cleanUp;
939     }
940     else
941     {
942         /* sigsetjmp returned zero -> normal operation */
943         char buf[MSGBUFSIZE+1], *realhost;
944         int count, newm, bytes;
945         int fetches, dispatches, oldphase;
946         struct idlist *idp;
947
948         /* execute pre-initialization command, if any */
949         if (ctl->preconnect && (err = system(ctl->preconnect)))
950         {
951             if (WIFSIGNALED(err))
952                 report(stderr,
953                         GT_("pre-connection command terminated with signal %d\n"), WTERMSIG(err));
954             else
955                 report(stderr,
956                         GT_("pre-connection command failed with status %d\n"), WEXITSTATUS(err));
957             err = PS_SYNTAX;
958             goto closeUp;
959         }
960
961         /* open a socket to the mail server */
962         oldphase = phase;
963         phase = OPEN_WAIT;
964         set_timeout(mytimeout);
965
966 #ifdef HAVE_PKG_hesiod
967         /* If either the pollname or vianame are "hesiod" we want to
968            lookup the user's hesiod pobox host */
969         if (!strcasecmp(ctl->server.queryname, "hesiod")) {
970             struct hes_postoffice *hes_p;
971             hes_p = hes_getmailhost(ctl->remotename);
972             if (hes_p != NULL && strcmp(hes_p->po_type, "POP") == 0) {
973                  free(ctl->server.queryname);
974                  ctl->server.queryname = xstrdup(hes_p->po_host);
975                  if (ctl->server.via)
976                      free(ctl->server.via);
977                  ctl->server.via = xstrdup(hes_p->po_host);
978             } else {
979                  report(stderr,
980                         GT_("couldn't find HESIOD pobox for %s\n"),
981                         ctl->remotename);
982             }
983         }
984 #endif /* HESIOD */
985
986         /*
987          * Canonicalize the server truename for later use.  This also
988          * functions as a probe for whether the mailserver is accessible.
989          * We try it on each poll cycle until we get a result.  This way,
990          * fetchmail won't fail if started up when the network is inaccessible.
991          */
992         if (ctl->server.dns && !ctl->server.trueaddr)
993         {
994             if (ctl->server.lead_server)
995             {
996                 char    *leadname = ctl->server.lead_server->truename;
997
998                 /* prevent core dump from ill-formed or duplicate entry */
999                 if (!leadname)
1000                 {
1001                     report(stderr, GT_("Lead server has no name.\n"));
1002                     err = PS_DNS;
1003                     set_timeout(0);
1004                     phase = oldphase;
1005                     goto closeUp;
1006                 }
1007
1008                 xfree(ctl->server.truename);
1009                 ctl->server.truename = xstrdup(leadname);
1010             }
1011             else
1012             {
1013                 struct addrinfo hints, *res;
1014                 int error;
1015
1016                 memset(&hints, 0, sizeof(hints));
1017                 hints.ai_socktype = SOCK_STREAM;
1018                 hints.ai_family = AF_UNSPEC;
1019                 hints.ai_flags = AI_CANONNAME;
1020 #ifdef AI_ADDRCONFIG
1021                 hints.ai_flags |= AI_ADDRCONFIG;
1022 #endif
1023
1024                 error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
1025                 if (error)
1026                 {
1027                     report(stderr,
1028                            GT_("couldn't find canonical DNS name of %s (%s): %s\n"),
1029                            ctl->server.pollname, ctl->server.queryname,
1030                            gai_strerror(error));
1031                     err = PS_DNS;
1032                     set_timeout(0);
1033                     phase = oldphase;
1034                     goto closeUp;
1035                 }
1036                 else
1037                 {
1038                     xfree(ctl->server.truename);
1039                     /* Older FreeBSD versions return NULL in ai_canonname
1040                      * if they cannot canonicalize, rather than copying
1041                      * the queryname here, as IEEE Std 1003.1-2001
1042                      * requires. Work around NULL. */
1043                     if (res->ai_canonname != NULL) {
1044                         ctl->server.truename = xstrdup(res->ai_canonname);
1045                     } else {
1046                         ctl->server.truename = xstrdup(ctl->server.queryname);
1047                     }
1048                     ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
1049                     ctl->server.trueaddr_len = res->ai_addrlen;
1050                     memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
1051                     fm_freeaddrinfo(res);
1052                 }
1053             }
1054         }
1055
1056         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
1057
1058         /* allow time for the port to be set up if we have a plugin */
1059         if (ctl->server.plugin)
1060             (void)sleep(1);
1061         if ((mailserver_socket = SockOpen(realhost, 
1062                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ),
1063                              ctl->server.plugin, &ai0)) == -1)
1064         {
1065             char        errbuf[BUFSIZ];
1066             int err_no = errno;
1067             /*
1068              * Avoid generating a bogus error every poll cycle when we're
1069              * in daemon mode but the connection to the outside world
1070              * is down.
1071              */
1072             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
1073                   && run.poll_interval))
1074             {
1075                 report_build(stderr, GT_("%s connection to %s failed"), 
1076                              ctl->server.base_protocol->name, ctl->server.pollname);
1077                     strlcpy(errbuf, strerror(err_no), sizeof(errbuf));
1078                 report_complete(stderr, ": %s\n", errbuf);
1079
1080 #ifdef __UNUSED__
1081                 /* 
1082                  * Don't use this.  It was an attempt to address Debian bug
1083                  * #47143 (Notify user by mail when pop server nonexistent).
1084                  * Trouble is, that doesn't work; you trip over the case 
1085                  * where your SLIP or PPP link is down...
1086                  */
1087                 /* warn the system administrator */
1088                 if (open_warning_by_mail(ctl) == 0)
1089                 {
1090                     stuff_warning(iana_charset, ctl,
1091                          GT_("Subject: Fetchmail unreachable-server warning."));
1092                     stuff_warning(NULL, ctl, "");
1093                     stuff_warning(NULL, ctl, GT_("Fetchmail could not reach the mail server %s:"),
1094                                   ctl->server.pollname);
1095                     stuff_warning(NULL, ctl, errbuf, ctl->server.pollname);
1096                     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1097                 }
1098 #endif
1099             }
1100             err = PS_SOCKET;
1101             set_timeout(0);
1102             phase = oldphase;
1103             goto closeUp;
1104         }
1105
1106 #ifdef SSL_ENABLE
1107         /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen 
1108          * because the socket can be closed.
1109          */
1110         mailserver_socket_temp = mailserver_socket;
1111         set_timeout(mytimeout);
1112
1113         /* perform initial SSL handshake on open connection */
1114         if (ctl->use_ssl &&
1115                 SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
1116                     ctl->sslproto, ctl->sslcertck,
1117                     ctl->sslcertfile, ctl->sslcertpath,
1118                     ctl->sslfingerprint, ctl->sslcommonname ?
1119                     ctl->sslcommonname : realhost, ctl->server.pollname,
1120                     &ctl->remotename) == -1)
1121         {
1122             report(stderr, GT_("SSL connection failed.\n"));
1123             err = PS_SOCKET;
1124             goto cleanUp;
1125         }
1126         
1127         /* Fetchmail didn't hang on SSLOpen, 
1128          * then no need to set mailserver_socket_temp 
1129          */
1130         mailserver_socket_temp = -1;
1131 #endif
1132         
1133         /* A timeout is still defined before SSLOpen, 
1134          * then Fetchmail hanging on SSLOpen is handled.
1135          */
1136         set_timeout(0);
1137         phase = oldphase;
1138 #ifdef KERBEROS_V4
1139         if (ctl->server.authenticate == A_KERBEROS_V4 && (strcasecmp(proto->name,"IMAP") != 0))
1140         {
1141             set_timeout(mytimeout);
1142             err = kerberos_auth(mailserver_socket, ctl->server.truename,
1143                                ctl->server.principal);
1144             set_timeout(0);
1145             if (err != 0)
1146                 goto cleanUp;
1147         }
1148 #endif /* KERBEROS_V4 */
1149
1150 #ifdef KERBEROS_V5
1151         if (ctl->server.authenticate == A_KERBEROS_V5)
1152         {
1153             set_timeout(mytimeout);
1154             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1155             set_timeout(0);
1156             if (err != 0)
1157                 goto cleanUp;
1158         }
1159 #endif /* KERBEROS_V5 */
1160
1161         /* accept greeting message from mail server */
1162         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1163         if (err != 0)
1164             goto cleanUp;
1165
1166         /* try to get authorized to fetch mail */
1167         stage = STAGE_GETAUTH;
1168         if (ctl->server.base_protocol->getauth)
1169         {
1170             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1171
1172             if (err != 0)
1173             {
1174                 if (err == PS_LOCKBUSY)
1175                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1176                           ctl->remotename,
1177                           ctl->server.truename);
1178                 else if (err == PS_SERVBUSY)
1179                     report(stderr, GT_("Server busy error on %s@%s\n"),
1180                           ctl->remotename,
1181                           ctl->server.truename);
1182                 else if (err == PS_AUTHFAIL)
1183                 {
1184                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1185                            ctl->remotename,
1186                            ctl->server.truename,
1187                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1188                         );
1189
1190                     /*
1191                      * If we're running in background, try to mail the
1192                      * calling user a heads-up about the authentication 
1193                      * failure once it looks like this isn't a fluke 
1194                      * due to the server being temporarily inaccessible.
1195                      * When we get third succesive failure, we notify the user
1196                      * but only if we haven't already managed to get
1197                      * authorization.  After that, once we get authorization
1198                      * we let the user know service is restored.
1199                      */
1200                     if (run.poll_interval
1201                         && !ctl->wehavesentauthnote
1202                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1203                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1204                         && !open_warning_by_mail(ctl))
1205                     {
1206                         ctl->wehavesentauthnote = 1;
1207                         stuff_warning(iana_charset, ctl,
1208                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1209                             ctl->remotename, ctl->server.truename);
1210                         stuff_warning(NULL, ctl, "%s", "");
1211                         stuff_warning(NULL, ctl,
1212                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1213                                       ctl->remotename,
1214                                       ctl->server.truename);
1215                         if (ctl->wehaveauthed) {
1216                             stuff_warning(NULL, ctl, GT_("\
1217 The attempt to get authorization failed.\n\
1218 Since we have already succeeded in getting authorization for this\n\
1219 connection, this is probably another failure mode (such as busy server)\n\
1220 that fetchmail cannot distinguish because the server didn't send a useful\n\
1221 error message."));
1222                             stuff_warning(NULL, ctl, GT_("\
1223 \n\
1224 However, if you HAVE changed your account details since starting the\n\
1225 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1226 of fetchmail, and then restart the daemon.\n\
1227 \n\
1228 The fetchmail daemon will continue running and attempt to connect\n\
1229 at each cycle.  No future notifications will be sent until service\n\
1230 is restored."));
1231                         } else {
1232                             stuff_warning(NULL, ctl, GT_("\
1233 The attempt to get authorization failed.\n\
1234 This probably means your password is invalid, but some servers have\n\
1235 other failure modes that fetchmail cannot distinguish from this\n\
1236 because they don't send useful error messages on login failure.\n\
1237 \n\
1238 The fetchmail daemon will continue running and attempt to connect\n\
1239 at each cycle.  No future notifications will be sent until service\n\
1240 is restored."));
1241                         }
1242                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1243                     }
1244                 }
1245                 else if (err == PS_REPOLL)
1246                 {
1247                   if (outlevel >= O_VERBOSE)
1248                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1249                            ctl->remotename,
1250                            ctl->server.truename);
1251                 }
1252                 else
1253                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1254                            ctl->remotename,
1255                            ctl->server.truename);
1256                     
1257                 goto cleanUp;
1258             }
1259             else
1260             {
1261                 /*
1262                  * This connection has given us authorization at least once.
1263                  *
1264                  * There are dodgy server (clubinternet.fr for example) that
1265                  * give spurious authorization failures on patently good
1266                  * account/password details, then 5 minutes later let you in!
1267                  *
1268                  * This is meant to build in some tolerance of such nasty bits
1269                  * of work.
1270                  */
1271                 ctl->wehaveauthed = 1;
1272                 /*if (ctl->authfailcount >= 3)*/
1273                 if (ctl->wehavesentauthnote)
1274                 {
1275                     ctl->wehavesentauthnote = 0;
1276                     report(stderr,
1277                            GT_("Authorization OK on %s@%s\n"),
1278                            ctl->remotename,
1279                            ctl->server.truename);
1280                     if (!open_warning_by_mail(ctl))
1281                     {
1282                         stuff_warning(iana_charset, ctl,
1283                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1284                                       ctl->remotename, ctl->server.truename);
1285                         stuff_warning(NULL, ctl, "%s", "");
1286                         stuff_warning(NULL, ctl,
1287                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1288                                       ctl->remotename,
1289                                       ctl->server.truename);
1290                         stuff_warning(NULL, ctl, 
1291                                       GT_("Service has been restored.\n"));
1292                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1293                     
1294                     }
1295                 }
1296                 /*
1297                  * Reporting only after the first three
1298                  * consecutive failures, or ten consecutive
1299                  * failures after we have managed to get
1300                  * authorization.
1301                  */
1302                 ctl->authfailcount = 0;
1303             }
1304         }
1305
1306         ctl->errcount = fetches = 0;
1307
1308         /* now iterate over each folder selected */
1309         for (idp = ctl->mailboxes; idp; idp = idp->next)
1310         {
1311             ctl->folder = idp->id;
1312             pass = 0;
1313             do {
1314                 dispatches = 0;
1315                 ++pass;
1316
1317                 /* reset timeout, in case we did an IDLE */
1318                 mytimeout = ctl->server.timeout;
1319
1320                 if (outlevel >= O_DEBUG)
1321                 {
1322                     if (idp->id)
1323                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1324                     else
1325                         report(stdout, GT_("selecting or re-polling default folder\n"));
1326                 }
1327
1328                 /* compute # of messages and number of new messages waiting */
1329                 stage = STAGE_GETRANGE;
1330                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1331                 if (err != 0)
1332                     goto cleanUp;
1333
1334                 /* show user how many messages we downloaded */
1335                 if (idp->id)
1336                     (void) snprintf(buf, sizeof(buf),
1337                                    GT_("%s at %s (folder %s)"),
1338                                    ctl->remotename, ctl->server.pollname, idp->id);
1339                 else
1340                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1341                                    ctl->remotename, ctl->server.pollname);
1342                 if (outlevel > O_SILENT)
1343                 {
1344                     if (count == -1)            /* only used for ETRN */
1345                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1346                     else if (count != 0)
1347                     {
1348                         if (newm != -1 && (count - newm) > 0)
1349                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1350                                   count,
1351                                   count - newm, 
1352                                   ngettext("seen", "seen", (unsigned long)count-newm),
1353                                   buf);
1354                         else
1355                             report_build(stdout, ngettext("%d message for %s",
1356                                                           "%d messages for %s",
1357                                                           count), 
1358                                   count, buf);
1359                         if (bytes == -1)
1360                             report_complete(stdout, ".\n");
1361                         else
1362                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1363                     }
1364                     else
1365                     {
1366                         /* these are pointless in normal daemon mode */
1367                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1368                             report(stdout, GT_("No mail for %s\n"), buf); 
1369                     }
1370                 }
1371
1372                 /* very important, this is where we leave the do loop */ 
1373                 if (count == 0)
1374                     break;
1375
1376                 if (check_only)
1377                 {
1378                     if (newm == -1 || ctl->fetchall)
1379                         newm = count;
1380                     fetches = newm;     /* set error status correctly */
1381                     /*
1382                      * There used to be a `goto noerror' here, but this
1383                      * prevented checking of multiple folders.  This
1384                      * comment is a reminder in case I introduced some
1385                      * subtle bug by removing it...
1386                      */
1387                 }
1388                 else if (count > 0)
1389                 {    
1390                     int         i;
1391
1392                     /*
1393                      * Don't trust the message count passed by the server.
1394                      * Without this check, it might be possible to do a
1395                      * DNS-spoofing attack that would pass back a ridiculous 
1396                      * count, and allocate a malloc area that would overlap
1397                      * a portion of the stack.
1398                      */
1399                     if ((unsigned)count > INT_MAX/sizeof(int))
1400                     {
1401                         report(stderr, GT_("bogus message count!"));
1402                         err = PS_PROTOCOL;
1403                         goto cleanUp;
1404                     }
1405
1406                     /* 
1407                      * We need the size of each message before it's
1408                      * loaded in order to pass it to the ESMTP SIZE
1409                      * option.  If the protocol has a getsizes method,
1410                      * we presume this means it doesn't get reliable
1411                      * sizes from message fetch responses.
1412                      *
1413                      * If the protocol supports getting sizes of subset of
1414                      * messages, we skip this step now.
1415                      */
1416                     if (proto->getsizes &&
1417                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1418                     {
1419                         xfree(msgsizes);
1420                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1421                         for (i = 0; i < count; i++)
1422                             msgsizes[i] = 0;
1423
1424                         stage = STAGE_GETSIZES;
1425                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1426                         if (err != 0)
1427                             goto cleanUp;
1428
1429                         if (bytes == -1)
1430                         {
1431                             bytes = 0;
1432                             for (i = 0; i < count; i++)
1433                                 bytes += msgsizes[i];
1434                         }
1435                     }
1436
1437                     /* read, forward, and delete messages */
1438                     stage = STAGE_FETCH;
1439
1440                     /* fetch in lockstep mode */
1441                     err = fetch_messages(mailserver_socket, ctl, 
1442                                          count, &msgsizes,
1443                                          maxfetch,
1444                                          &fetches, &dispatches, &deletions);
1445                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1446                         goto cleanUp;
1447
1448                     if (!check_only && ctl->skipped
1449                         && run.poll_interval > 0 && !nodetach)
1450                     {
1451                         clean_skipped_list(&ctl->skipped);
1452                         send_size_warnings(ctl);
1453                     }
1454                 }
1455
1456                 /* end-of-mailbox processing before we repoll or switch to another one */
1457                 if (ctl->server.base_protocol->end_mailbox_poll)
1458                 {
1459                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1460                     if (tmperr) {
1461                         err = tmperr;
1462                         goto cleanUp;
1463                     }
1464                 }
1465                 /* Return now if we have reached the fetchlimit */
1466                 if (maxfetch && maxfetch <= fetches)
1467                     goto no_error;
1468             } while
1469                   /*
1470                    * Only repoll if we either had some actual forwards
1471                    * or are idling for new mails and had no errors.
1472                    * Otherwise it is far too easy to get into infinite loops.
1473                    */
1474                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1475         }
1476
1477         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1478
1479     no_error:
1480         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1481         stage = STAGE_LOGOUT;
1482         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1483         if (tmperr != PS_SUCCESS)
1484             err = tmperr;
1485         /*
1486          * Hmmmm...arguably this would be incorrect if we had fetches but
1487          * no dispatches (due to oversized messages, etc.)
1488          */
1489         else if (err == PS_SUCCESS && fetches == 0)
1490             err = PS_NOMAIL;
1491         /*
1492          * Close all SMTP delivery sockets.  For optimum performance
1493          * we'd like to hold them open til end of run, but (1) this
1494          * loses if our poll interval is longer than the MTA's
1495          * inactivity timeout, and (2) some MTAs (like smail) don't
1496          * deliver after each message, but rather queue up mail and
1497          * wait to actually deliver it until the input socket is
1498          * closed.
1499          *
1500          * don't send QUIT for ODMR case because we're acting as a
1501          * proxy between the SMTP server and client.
1502          */
1503         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1504         cleanupSockClose(mailserver_socket);
1505         goto closeUp;
1506
1507     cleanUp:
1508         /* we only get here on error */
1509         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1510         {
1511             stage = STAGE_LOGOUT;
1512             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1513         }
1514
1515         /* try to clean up all streams */
1516         release_sink(ctl);
1517         /*
1518          * Sending SMTP QUIT on signal is theoretically nice, but led
1519          * to a subtle bug.  If fetchmail was terminated by signal
1520          * while it was shipping message text, it would hang forever
1521          * waiting for a command acknowledge.  In theory we could
1522          * enable the QUIT only outside of the message send.  In
1523          * practice, we don't care.  All mailservers hang up on a
1524          * dropped TCP/IP connection anyway.
1525          */
1526         smtp_close(ctl, 0);
1527         if (mailserver_socket != -1) {
1528             cleanupSockClose(mailserver_socket);
1529         }
1530         /* If there was a connect timeout, the socket should be closed.
1531          * mailserver_socket_temp contains the socket to close.
1532          */
1533         if (mailserver_socket_temp != -1) {
1534             cleanupSockClose(mailserver_socket_temp);
1535             mailserver_socket_temp = -1;
1536         }
1537     }
1538
1539     /* no report on PS_AUTHFAIL */
1540     msg = NULL;
1541     switch (err)
1542     {
1543     case PS_SOCKET:
1544         msg = GT_("socket");
1545         break;
1546     case PS_SYNTAX:
1547         msg = GT_("missing or bad RFC822 header");
1548         break;
1549     case PS_IOERR:
1550         msg = GT_("MDA");
1551         break;
1552     case PS_ERROR:
1553         msg = GT_("client/server synchronization");
1554         break;
1555     case PS_PROTOCOL:
1556         msg = GT_("client/server protocol");
1557         break;
1558     case PS_LOCKBUSY:
1559         msg = GT_("lock busy on server");
1560         break;
1561     case PS_SMTP:
1562         msg = GT_("SMTP transaction");
1563         break;
1564     case PS_DNS:
1565         msg = GT_("DNS lookup");
1566         break;
1567     case PS_UNDEFINED:
1568         msg = GT_("undefined");
1569         break;
1570     }
1571     if (msg) {
1572         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1573                 || err == PS_SMTP)
1574             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1575                     msg, ctl->remotename, ctl->server.pollname,
1576                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1577         else
1578             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1579                     msg, ctl->remotename, ctl->server.pollname);
1580     }
1581
1582 closeUp:
1583     xfree(msgsizes);
1584     ctl->folder = NULL;
1585
1586     /* execute wrapup command, if any */
1587     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1588     {
1589         if (WIFSIGNALED(tmperr))
1590             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1591         else
1592             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1593         if (err == PS_SUCCESS)
1594             err = PS_SYNTAX;
1595     }
1596
1597     set_timeout(0); /* cancel any pending alarm */
1598     set_signal_handler(SIGALRM, alrmsave);
1599     return(err);
1600 }
1601
1602 /** retrieve messages from server using given protocol method table */
1603 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1604                 const struct method *proto /** protocol method table */)
1605 {
1606     int err;
1607
1608 #ifndef KERBEROS_V4
1609     if (ctl->server.authenticate == A_KERBEROS_V4)
1610     {
1611         report(stderr, GT_("Kerberos V4 support not linked.\n"));
1612         return(PS_ERROR);
1613     }
1614 #endif /* KERBEROS_V4 */
1615
1616 #ifndef KERBEROS_V5
1617     if (ctl->server.authenticate == A_KERBEROS_V5)
1618     {
1619         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1620         return(PS_ERROR);
1621     }
1622 #endif /* KERBEROS_V5 */
1623
1624     /* lacking methods, there are some options that may fail */
1625     if (!proto->is_old)
1626     {
1627         /* check for unsupported options */
1628         if (ctl->flush) {
1629             report(stderr,
1630                     GT_("Option --flush is not supported with %s\n"),
1631                     proto->name);
1632             return(PS_SYNTAX);
1633         }
1634         else if (ctl->fetchall) {
1635             report(stderr,
1636                     GT_("Option --all is not supported with %s\n"),
1637                     proto->name);
1638             return(PS_SYNTAX);
1639         }
1640     }
1641     if (!(proto->getsizes || proto->getpartialsizes)
1642             && NUM_SPECIFIED(ctl->limit))
1643     {
1644         report(stderr,
1645                 GT_("Option --limit is not supported with %s\n"),
1646                 proto->name);
1647         return(PS_SYNTAX);
1648     }
1649
1650     /*
1651      * If no expunge limit or we do expunges within the driver,
1652      * then just do one session, passing in any fetchlimit.
1653      */
1654     if ((ctl->keep && !ctl->flush) ||
1655         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1656         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1657     /*
1658      * There's an expunge limit, and it isn't handled in the driver itself.
1659      * OK; do multiple sessions, each fetching a limited # of messages.
1660      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1661      * (if it was nonzero).
1662      */
1663     else
1664     {
1665         int totalcount = 0; 
1666         int lockouts   = 0;
1667         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1668         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1669
1670         do {
1671             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1672                 expunge = fetchlimit - totalcount;
1673             err = do_session(ctl, proto, expunge);
1674             totalcount += expunge;
1675             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1676                 break;
1677             if (err != PS_LOCKBUSY)
1678                 lockouts = 0;
1679             else if (lockouts >= MAX_LOCKOUTS)
1680                 break;
1681             else /* err == PS_LOCKBUSY */
1682             {
1683                 /*
1684                  * Allow time for the server lock to release.  if we
1685                  * don't do this, we'll often hit a locked-mailbox
1686                  * condition and fail.
1687                  */
1688                 lockouts++;
1689                 sleep(3);
1690             }
1691         } while
1692             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1693
1694         return(err);
1695     }
1696 }
1697
1698
1699 /* driver.c ends here */