]> Pileus Git - ~andy/fetchmail/blob - driver.c
Simplification time.
[~andy/fetchmail] / driver.c
1 /*
2  * driver.c -- generic driver for mail fetch method protocols
3  *
4  * Copyright 1996 by Eric S. Raymond
5  * All rights reserved.
6  * For license terms, see the file COPYING in this directory.
7  */
8
9 #include  <config.h>
10 #include  <stdio.h>
11 #include  <setjmp.h>
12 #include  <errno.h>
13 #include  <ctype.h>
14 #include  <string.h>
15 #if defined(STDC_HEADERS)
16 #include  <stdlib.h>
17 #endif
18 #if defined(HAVE_UNISTD_H)
19 #include <unistd.h>
20 #endif
21 #if defined(HAVE_STDARG_H)
22 #include  <stdarg.h>
23 #else
24 #include  <varargs.h>
25 #endif
26 #if defined(HAVE_ALLOCA_H)
27 #include <alloca.h>
28 #endif
29 #include  <sys/time.h>
30 #include  <signal.h>
31
32 #ifdef HAVE_GETHOSTBYNAME
33 #include <netdb.h>
34 #include "mx.h"
35 #endif /* HAVE_GETHOSTBYNAME */
36
37 #ifdef KERBEROS_V4
38 #include <krb.h>
39 #include <des.h>
40 #include <netinet/in.h>
41 #include <netdb.h>
42 #endif /* KERBEROS_V4 */
43 #include  "socket.h"
44 #include  "fetchmail.h"
45 #include  "socket.h"
46 #include  "smtp.h"
47
48 /* BSD portability hack...I know, this is an ugly place to put it */
49 #if !defined(SIGCHLD) && defined(SIGCLD)
50 #define SIGCHLD SIGCLD
51 #endif
52
53 #define SMTP_PORT       25      /* standard SMTP service port */
54
55 int batchlimit;         /* how often to tear down the delivery connection */
56 int fetchlimit;         /* how often to tear down the server connection */
57 int batchcount;         /* count of messages sent in current batch */
58 int peek_capable;       /* can we peek for better error recovery? */
59
60 static const struct method *protocol;
61 static jmp_buf  restart;
62
63 char tag[TAGLEN];
64 static int tagnum;
65 #define GENSYM  (sprintf(tag, "a%04d", ++tagnum), tag)
66
67 static char *shroud;    /* string to shroud in debug output, if  non-NULL */
68 static int mytimeout;   /* value of nonreponse timeout */
69
70 static void vtalarm(int timeleft)
71 /* reset the nonresponse-timeout */
72 {
73     struct itimerval ntimeout;
74
75     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
76     ntimeout.it_value.tv_sec  = timeleft;
77     ntimeout.it_value.tv_usec = 0;
78     setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
79 }
80
81 static void vtalarm_handler (int signal)
82 /* handle server-timeout SIGVTALARM signal */
83 {
84     longjmp(restart, 1);
85 }
86
87 #ifdef HAVE_RES_SEARCH
88 #define MX_RETRIES      3
89
90 static int is_host_alias(const char *name, struct query *ctl)
91 /* determine whether name is a DNS alias of the hostname */
92 {
93     struct hostent      *he;
94     struct mxentry      *mxp, *mxrecords;
95
96     /*
97      * The first two checks are optimizations that will catch a good
98      * many cases.  (1) check against the hostname the user
99      * specified.  Odds are good this will either be the mailserver's
100      * FQDN or a suffix of it with the mailserver's domain's default
101      * host name omitted.  Then check the rest of the `also known as'
102      * cache accumulated by previous DNS checks.  This cache is primed
103      * by the aka list option.
104      *
105      * (2) check against the mailserver's FQDN, in case
106      * it's not the same as the declared hostname.
107      *
108      * Either of these on a mail address is definitive.  Only if the
109      * name doesn't match either is it time to call the bind library.
110      * If this happens odds are good we're looking at an MX name.
111      */
112     if (str_in_list(&ctl->server.lead_server->names, name))
113         return(TRUE);
114     else if (strcmp(name, ctl->server.canonical_name) == 0)
115         return(TRUE);
116
117     /*
118      * We know DNS service was up at the beginning of this poll cycle.
119      * If it's down, our nameserver has crashed.  We don't want to try
120      * delivering the current message or anything else from this
121      * mailbox until it's back up.
122      */
123     else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
124     {
125         if (strcmp(ctl->server.canonical_name, he->h_name) == 0)
126             goto match;
127         else
128             return(FALSE);
129     }
130     else
131         switch (h_errno)
132         {
133         case HOST_NOT_FOUND:    /* specified host is unknown */
134         case NO_ADDRESS:        /* valid, but does not have an IP address */
135             break;
136
137         case NO_RECOVERY:       /* non-recoverable name server error */
138         case TRY_AGAIN:         /* temporary error on authoritative server */
139         default:
140             if (outlevel != O_SILENT)
141                 putchar('\n');  /* terminate the progress message */
142             error(0, 0,
143                 "nameserver failure while looking for `%s' during poll of %s.",
144                 name, ctl->server.names->id);
145             ctl->errcount++;
146             longjmp(restart, 2);        /* try again next poll cycle */
147             break;
148         }
149
150     /*
151      * We're only here if DNS was OK but the gethostbyname() failed
152      * with a HOST_NOT_FOUND or NO_ADDRESS error.
153      * Search for a name match on MX records pointing to the server.
154      */
155     h_errno = 0;
156     if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
157     {
158         switch (h_errno)
159         {
160         case HOST_NOT_FOUND:    /* specified host is unknown */
161         case NO_ADDRESS:        /* valid, but does not have an IP address */
162             return(FALSE);
163             break;
164
165         case NO_RECOVERY:       /* non-recoverable name server error */
166         case TRY_AGAIN:         /* temporary error on authoritative server */
167         default:
168             error(0, 0,
169                 "nameserver failure while looking for `%s' during poll of %s.",
170                 name, ctl->server.names->id);
171             ctl->errcount++;
172             longjmp(restart, 2);        /* try again next poll cycle */
173             break;
174         }
175     }
176     else
177     {
178         for (mxp = mxrecords; mxp->name; mxp++)
179             if (strcmp(ctl->server.canonical_name, mxp->name) == 0)
180                 goto match;
181         return(FALSE);
182     match:;
183     }
184
185     /* add this name to relevant server's `also known as' list */
186     save_str(&ctl->server.lead_server->names, -1, name);
187     return(TRUE);
188 }
189
190 static void map_name(name, ctl, xmit_names)
191 /* add given name to xmit_names if it matches declared localnames */
192 const char *name;               /* name to map */
193 struct query *ctl;              /* list of permissible aliases */
194 struct idlist **xmit_names;     /* list of recipient names parsed out */
195 {
196     const char  *lname;
197
198     lname = idpair_find(&ctl->localnames, name);
199     if (!lname && ctl->wildcard)
200         lname = name;
201
202     if (lname != (char *)NULL)
203     {
204         if (outlevel == O_VERBOSE)
205             error(0, 0, "mapped %s to local %s", name, lname);
206         save_str(xmit_names, -1, lname);
207     }
208 }
209
210 void find_server_names(hdr, ctl, xmit_names)
211 /* parse names out of a RFC822 header into an ID list */
212 const char *hdr;                /* RFC822 header in question */
213 struct query *ctl;              /* list of permissible aliases */
214 struct idlist **xmit_names;     /* list of recipient names parsed out */
215 {
216     if (hdr == (char *)NULL)
217         return;
218     else
219     {
220         char    *cp, *lname;
221
222         if ((cp = nxtaddr(hdr)) != (char *)NULL)
223             do {
224                 char    *atsign;
225
226                 if ((atsign = strchr(cp, '@')))
227                 {
228                     struct idlist       *idp;
229
230                     /*
231                      * Does a trailing segment of the hostname match something
232                      * on the localdomains list?  If so, save the whole name
233                      * and keep going.
234                      */
235                     for (idp = ctl->server.localdomains; idp; idp = idp->next)
236                     {
237                         char    *rhs;
238
239                         rhs = atsign + 1 + (strlen(atsign) - strlen(idp->id));
240                         if ((rhs[-1] == '.' || rhs[-1] == '@')
241                                         && strcmp(rhs, idp->id) == 0)
242                         {
243                             if (outlevel == O_VERBOSE)
244                                 error(0, 0, "passed through %s matching %s", 
245                                       cp, idp->id);
246                             save_str(xmit_names, -1, cp);
247                             continue;
248                         }
249                     }
250
251                     /*
252                      * Check to see if the right-hand part is an alias
253                      * or MX equivalent of the mailserver.  If it's
254                      * not, skip this name.  If it is, we'll keep
255                      * going and try to find a mapping to a client name.
256                      */
257                     if (!is_host_alias(atsign+1, ctl))
258                         continue;
259                     atsign[0] = '\0';
260                 }
261
262                 map_name(cp, ctl, xmit_names);
263             } while
264                 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
265     }
266 }
267 #endif /* HAVE_RES_SEARCH */
268
269 static FILE *smtp_open(struct query *ctl)
270 /* try to open a socket to the appropriate SMTP server for this query */ 
271 {
272     struct query *lead;
273
274     lead = ctl->lead_smtp; /* go to the SMTP leader for this query */
275
276     /* maybe it's time to close the socket in order to force delivery */
277     if (batchlimit && lead->smtp_sockfp && batchcount++ == batchlimit)
278     {
279         fclose(lead->smtp_sockfp);
280         lead->smtp_sockfp = (FILE *)NULL;
281         batchcount = 0;
282     }
283
284     /* if no socket to this host is already set up, try to open one */
285     if (lead->smtp_sockfp == (FILE *)NULL)
286     {
287         if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
288             return((FILE *)NULL);
289         else if (SMTP_ok(lead->smtp_sockfp) != SM_OK
290                  || SMTP_helo(lead->smtp_sockfp, ctl->server.names->id) != SM_OK)
291         {
292             fclose(lead->smtp_sockfp);
293             lead->smtp_sockfp = (FILE *)NULL;
294         }
295     }
296
297     return(lead->smtp_sockfp);
298 }
299
300 static int gen_readmsg(sockfp, len, delimited, ctl, realname)
301 /* read message content and ship to SMTP or MDA */
302 FILE *sockfp;           /* to which the server is connected */
303 long len;               /* length of message */
304 int delimited;          /* does the protocol use a message delimiter? */
305 struct query *ctl;      /* query control record */
306 char *realname;         /* real name of host */
307 {
308     char buf [MSGBUFSIZE+1]; 
309     char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
310     char *fromptr, *toptr;
311     int n, oldlen, ch;
312     int inheaders, sizeticker;
313     FILE *sinkfp;
314     RETSIGTYPE (*sigchld)();
315 #ifdef HAVE_GETHOSTBYNAME
316     char rbuf[HOSTLEN + USERNAMELEN + 4]; 
317 #endif /* HAVE_GETHOSTBYNAME */
318
319     /* read the message content from the server */
320     inheaders = 1;
321     headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
322     sizeticker = 0;
323     oldlen = 0;
324     while (delimited || len > 0)
325     {
326         buf[0] = '\0';
327         do {
328             if (!SockGets(buf+strlen(buf), sizeof(buf)-strlen(buf)-1, sockfp))
329                 return(PS_SOCKET);
330             vtalarm(ctl->server.timeout);
331         } while
332             /* we may need to grab RFC822 continuations */
333             (inheaders && (ch = SockPeek(sockfp)) == ' ' || ch == '\t');
334
335         /* compute length *before* squeezing out CRs */
336         n = strlen(buf);
337
338         /* write the message size dots */
339         if (n > 0)
340         {
341             sizeticker += n;
342             while (sizeticker >= SIZETICKER)
343             {
344                 if (outlevel > O_SILENT)
345                     error_build(".");
346                 sizeticker -= SIZETICKER;
347             }
348         }
349         len -= n;
350         bufp = buf;
351         if (buf[0] == '\r' && buf[1] == '\n')
352             inheaders = 0;
353         if (delimited && *bufp == '.') {
354             bufp++;
355             if (*bufp == 0)
356                 break;  /* end of message */
357         }
358      
359         if (inheaders)
360         {
361             if (!ctl->norewrite)
362                 reply_hack(bufp, realname);
363
364             if (!headers)
365             {
366                 oldlen = strlen(bufp);
367                 headers = xmalloc(oldlen + 1);
368                 (void) strcpy(headers, bufp);
369                 bufp = headers;
370             }
371             else
372             {
373                 int     newlen;
374
375                 newlen = oldlen + strlen(bufp);
376                 headers = realloc(headers, newlen + 1);
377                 if (headers == NULL)
378                     return(PS_IOERR);
379                 strcpy(headers + oldlen, bufp);
380                 bufp = headers + oldlen;
381                 oldlen = newlen;
382             }
383
384             if (!strncasecmp("From:", bufp, 5))
385                 fromhdr = bufp;
386             else if (!fromhdr && !strncasecmp("Resent-From:", bufp, 12))
387                 fromhdr = bufp;
388             else if (!fromhdr && !strncasecmp("Apparently-From:", bufp, 16))
389                 fromhdr = bufp;
390             else if (!strncasecmp("To:", bufp, 3))
391                 tohdr = bufp;
392             else if (!strncasecmp("Apparently-To:", bufp, 14))
393                 envto = bufp;
394             else if (!strncasecmp(ctl->server.envelope, bufp, 14))
395                 envto = bufp;
396             else if (!strncasecmp("Cc:", bufp, 3))
397                 cchdr = bufp;
398             else if (!strncasecmp("Bcc:", bufp, 4))
399                 bcchdr = bufp;
400 #ifdef HAVE_RES_SEARCH
401             else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
402             {
403                 char *ok;
404
405                 /*
406                  * Try to extract the real envelope addressee.  We look here
407                  * specifically for the mailserver's Received line.
408                  * Note: this will only work for sendmail, or an MTA that
409                  * shares sendmail's convention for embedding the envelope
410                  * address in the Received line.  Sendmail itself only
411                  * does this when the mail has a single recipient.
412                  */
413                 if ((ok = strstr(bufp, "by ")) == (char *)NULL)
414                     ok = (char *)NULL;
415                 else
416                 {
417                     char        *sp, *tp;
418
419                     /* extract space-delimited token after "by " */
420                     tp = rbuf;
421                     for (sp = ok + 3; !isspace(*sp); sp++)
422                         *tp++ = *sp;
423                     *tp = '\0';
424
425                     /*
426                      * If it's a DNS name of the mail server, look for the
427                      * recipient name after a following "for".  Otherwise
428                      * punt.
429                      */
430                     if (is_host_alias(rbuf, ctl))
431                         ok = strstr(sp, "for ");
432                     else
433                         ok = (char *)NULL;
434                 }
435
436                 if (ok != 0)
437                 {
438                     char        *sp, *tp;
439
440                     tp = rbuf;
441                     sp = ok + 4;
442                     if (*sp == '<')
443                         sp++;
444                     while (*sp && *sp != '>' && *sp != '@' && *sp != ';')
445                         if (!isspace(*sp))
446                             *tp++ = *sp++;
447                         else
448                         {
449                             /* uh oh -- whitespace here can't be right! */
450                             ok = (char *)NULL;
451                             break;
452                         }
453                     *tp = '\0';
454                 }
455
456                 if (ok != 0)
457                 {
458                     received_for = alloca(strlen(rbuf)+1);
459                     strcpy(received_for, rbuf);
460                     if (outlevel == O_VERBOSE)
461                         error(0, 0, 
462                                 "found Received address `%s'",
463                                 received_for);
464                 }
465             }
466 #endif /* HAVE_RES_SEARCH */
467
468             continue;
469         }
470         else if (headers)       /* OK, we're at end of headers now */
471         {
472             char                *cp;
473             struct idlist       *idp, *xmit_names;
474             int                 good_addresses, bad_addresses;
475 #ifdef HAVE_RES_SEARCH
476             int                 no_local_matches = FALSE;
477 #endif /* HAVE_RES_SEARCH */
478
479             /* cons up a list of local recipients */
480             xmit_names = (struct idlist *)NULL;
481             bad_addresses = good_addresses = 0;
482 #ifdef HAVE_RES_SEARCH
483             /* is this a multidrop box? */
484             if (MULTIDROP(ctl))
485             {
486                 if (envto)          /* We have the actual envelope addressee */
487                     find_server_names(envto, ctl, &xmit_names);
488                 else if (received_for)
489                     /*
490                      * We have the Received for addressee.  
491                      * It has to be a mailserver address, or we
492                      * wouldn't have got here.
493                      */
494                     map_name(received_for, ctl, &xmit_names);
495                 else
496                 {
497                     /*
498                      * We haven't extracted the envelope address.
499                      * So check all the header addresses.
500                      */
501                     find_server_names(tohdr,  ctl, &xmit_names);
502                     find_server_names(cchdr,  ctl, &xmit_names);
503                     find_server_names(bcchdr, ctl, &xmit_names);
504                 }
505                 if (!xmit_names)
506                 {
507                     no_local_matches = TRUE;
508                     save_str(&xmit_names, -1, user);
509                     if (outlevel == O_VERBOSE)
510                         error(0, 0, 
511                                 "no local matches, forwarding to %s",
512                                 user);
513                 }
514             }
515             else        /* it's a single-drop box, use first localname */
516 #endif /* HAVE_RES_SEARCH */
517                 save_str(&xmit_names, -1, ctl->localnames->id);
518
519             /* time to address the message */
520             if (ctl->mda)       /* we have a declared MDA */
521             {
522                 int     length = 0;
523                 char    *names, *cmd;
524
525                 /*
526                  * We go through this in order to be able to handle very
527                  * long lists of users and (re)implement %s.
528                  */
529                 for (idp = xmit_names; idp; idp = idp->next)
530                     length += (strlen(idp->id) + 1);
531                 names = (char *)alloca(length);
532                 names[0] = '\0';
533                 for (idp = xmit_names; idp; idp = idp->next)
534                 {
535                     strcat(names, idp->id);
536                     strcat(names, " ");
537                 }
538                 cmd = (char *)alloca(strlen(ctl->mda) + length);
539                 sprintf(cmd, ctl->mda, names);
540                 if (outlevel == O_VERBOSE)
541                     error(0, 0, "about to deliver with: %s", cmd);
542
543 #ifdef HAVE_SETEUID
544                 /*
545                  * Arrange to run with user's permissions if we're root.
546                  * This will initialize the ownership of any files the
547                  * MDA creates properly.  (The seteuid call is available
548                  * under all BSDs and Linux)
549                  */
550                 seteuid(ctl->uid);
551 #endif /* HAVE_SETEUID */
552
553                 sinkfp = popen(cmd, "w");
554
555 #ifdef HAVE_SETEUID
556                 /* this will fail quietly if we didn't start as root */
557                 seteuid(0);
558 #endif /* HAVE_SETEUID */
559
560                 if (!sinkfp)
561                 {
562                     error(0, 0, "MDA open failed");
563                     return(PS_IOERR);
564                 }
565
566                 sigchld = signal(SIGCHLD, SIG_DFL);
567             }
568             else
569             {
570                 char    *ap;
571
572                 /* build a connection to the SMTP listener */
573                 if (!ctl->mda && ((sinkfp = smtp_open(ctl)) == NULL))
574                 {
575                     free_str_list(&xmit_names);
576                     error(0, 0, "SMTP connect failed");
577                     return(PS_SMTP);
578                 }
579
580                 /*
581                  * Try to get the SMTP listener to take the header
582                  * From address as MAIL FROM (this makes the logging
583                  * nicer).  If it won't, fall back on the calling-user
584                  * ID.  This won't affect replies, which use the header
585                  * From address anyway.
586                  */
587                 if (!fromhdr || !(ap = nxtaddr(fromhdr)))
588                 {
589                     if (SMTP_from(sinkfp, user) != SM_OK)
590                         return(PS_SMTP);        /* should never happen */
591                 }
592                 else if (SMTP_from(sinkfp, ap) != SM_OK)
593                     if (smtp_response == 571)
594                     {
595                         /*
596                          * SMTP listener explicitly refuses to deliver
597                          * mail coming from this address, probably due
598                          * to an anti-spam domain exclusion.  Respect
599                          * this.
600                          */
601                         sinkfp = (FILE *)NULL;
602                         goto skiptext;
603                     }
604                     else if (SMTP_from(sinkfp, user) != SM_OK)
605                         return(PS_SMTP);        /* should never happen */
606
607                 /* now list the recipient addressees */
608                 for (idp = xmit_names; idp; idp = idp->next)
609                     if (SMTP_rcpt(sinkfp, idp->id) == SM_OK)
610                         good_addresses++;
611                     else
612                     {
613                         bad_addresses++;
614                         idp->val.num = 0;
615                         error(0, 0, 
616                                 "SMTP listener doesn't like recipient address `%s'", idp->id);
617                     }
618                 if (!good_addresses && SMTP_rcpt(sinkfp, user) != SM_OK)
619                 {
620                     error(0, 0, 
621                             "can't even send to calling user!");
622                     return(PS_SMTP);
623                 }
624
625                 /* tell it we're ready to send data */
626                 SMTP_data(sinkfp);
627
628             skiptext:;
629             }
630
631             /* write all the headers */
632             if (ctl->mda)
633                 n = fwrite(headers, 1, oldlen, sinkfp);
634             else if (sinkfp)
635                 n = SockWrite(headers, 1, oldlen, sinkfp);
636
637             if (n < 0)
638             {
639                 free(headers);
640                 headers = NULL;
641                 error(0, errno, "writing RFC822 headers");
642                 if (ctl->mda)
643                 {
644                     pclose(sinkfp);
645                     signal(SIGCHLD, sigchld);
646                 }
647                 return(PS_IOERR);
648             }
649             else if (outlevel == O_VERBOSE)
650                 fputs("#", stderr);
651             free(headers);
652             headers = NULL;
653
654             /* write error notifications */
655 #ifdef HAVE_RES_SEARCH
656             if (no_local_matches || bad_addresses)
657 #else
658             if (bad_addresses)
659 #endif /* HAVE_RES_SEARCH */
660             {
661                 int     errlen = 0;
662                 char    errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
663
664                 errmsg = errhd;
665                 (void) strcpy(errhd, "X-Fetchmail-Warning: ");
666 #ifdef HAVE_RES_SEARCH
667                 if (no_local_matches)
668                 {
669                     strcat(errhd, "no recipient addresses matched declared local names");
670                     if (bad_addresses)
671                         strcat(errhd, "; ");
672                 }
673 #endif /* HAVE_RES_SEARCH */
674
675                 if (bad_addresses)
676                 {
677                     strcat(errhd, "SMTP listener rejected local recipient addresses: ");
678                     errlen = strlen(errhd);
679                     for (idp = xmit_names; idp; idp = idp->next)
680                         if (!idp->val.num)
681                             errlen += strlen(idp->id) + 2;
682
683                     errmsg = alloca(errlen+3);
684                     (void) strcpy(errmsg, errhd);
685                     for (idp = xmit_names; idp; idp = idp->next)
686                         if (!idp->val.num)
687                         {
688                             strcat(errmsg, idp->id);
689                             if (idp->next)
690                                 strcat(errmsg, ", ");
691                         }
692                 }
693
694                 strcat(errmsg, "\n");
695
696                 if (sinkfp)
697                     fputs(errmsg, sinkfp);
698             }
699
700             free_str_list(&xmit_names);
701         }
702
703         /* SMTP byte-stuffing */
704         if (*bufp == '.')
705             if (ctl->mda)
706                 fputs(".", sinkfp);
707             else if (sinkfp)
708                 SockWrite(bufp, 1, 1, sinkfp);
709
710         /* ship out the text line */
711         if (ctl->mda)
712             n = fwrite(bufp, 1, strlen(bufp), sinkfp);
713         else if (sinkfp)
714             n = SockWrite(bufp, 1, strlen(bufp), sinkfp);
715
716         if (n < 0)
717         {
718             error(0, errno, "writing message text");
719             if (ctl->mda)
720             {
721                 pclose(sinkfp);
722                 signal(SIGCHLD, sigchld);
723             }
724             return(PS_IOERR);
725         }
726         else if (outlevel == O_VERBOSE)
727             fputc('*', stderr);
728     }
729
730     if (outlevel == O_VERBOSE)
731         fputc('\n', stderr);
732
733     if (ctl->mda)
734     {
735         int rc;
736
737         /* close the delivery pipe, we'll reopen before next message */
738         rc = pclose(sinkfp);
739         signal(SIGCHLD, sigchld);
740         if (rc)
741         {
742             error(0, 0, "MDA exited abnormally or returned nonzero status");
743             return(PS_IOERR);
744         }
745     }
746     else if (sinkfp)
747     {
748         /* write message terminator */
749         if (SMTP_eom(sinkfp) != SM_OK)
750         {
751             error(0, 0, "SMTP listener refused delivery");
752             return(PS_SMTP);
753         }
754     }
755
756     return(0);
757 }
758
759 #ifdef KERBEROS_V4
760 int
761 kerberos_auth (socket, canonical) 
762 /* authenticate to the server host using Kerberos V4 */
763 int socket;             /* socket to server host */
764 const char *canonical;  /* server name */
765 {
766     char * host_primary;
767     KTEXT ticket;
768     MSG_DAT msg_data;
769     CREDENTIALS cred;
770     Key_schedule schedule;
771     int rem;
772   
773     ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
774     rem = (krb_sendauth (0L, socket, ticket, "pop",
775                          canonical,
776                          ((char *) (krb_realmofhost (canonical))),
777                          ((unsigned long) 0),
778                          (&msg_data),
779                          (&cred),
780                          (schedule),
781                          ((struct sockaddr_in *) 0),
782                          ((struct sockaddr_in *) 0),
783                          "KPOPV0.1"));
784     free (ticket);
785     if (rem != KSUCCESS)
786     {
787         error(0, 0, "kerberos error %s", (krb_get_err_text (rem)));
788         return (PS_ERROR);
789     }
790     return (0);
791 }
792 #endif /* KERBEROS_V4 */
793
794 int do_protocol(ctl, proto)
795 /* retrieve messages from server using given protocol method table */
796 struct query *ctl;              /* parsed options with merged-in defaults */
797 const struct method *proto;     /* protocol method table */
798 {
799     int ok, js, pst;
800     char *msg, *sp, *cp, realname[HOSTLEN];
801     void (*sigsave)();
802
803 #ifndef KERBEROS_V4
804     if (ctl->server.authenticate == A_KERBEROS)
805     {
806         error(0, 0, "Kerberos support not linked.");
807         return(PS_ERROR);
808     }
809 #endif /* KERBEROS_V4 */
810
811     /* lacking methods, there are some options that may fail */
812     if (!proto->is_old)
813     {
814         /* check for unsupported options */
815         if (ctl->flush) {
816             error(0, 0,
817                     "Option --flush is not supported with %s",
818                     proto->name);
819             return(PS_SYNTAX);
820         }
821         else if (ctl->fetchall) {
822             error(0, 0,
823                     "Option --all is not supported with %s",
824                     proto->name);
825             return(PS_SYNTAX);
826         }
827     }
828     if (!proto->getsizes && ctl->limit)
829     {
830         error(0, 0,
831                 "Option --limit is not supported with %s",
832                 proto->name);
833         return(PS_SYNTAX);
834     }
835
836     protocol = proto;
837     tagnum = 0;
838     tag[0] = '\0';      /* nuke any tag hanging out from previous query */
839     ok = 0;
840     error_init(poll_interval == 0 && !logfile);
841
842     /* set up the server-nonresponse timeout */
843     sigsave = signal(SIGVTALRM, vtalarm_handler);
844     vtalarm(mytimeout = ctl->server.timeout);
845
846     if ((js = setjmp(restart)) == 1)
847     {
848         error(0, 0,
849                 "timeout after %d seconds waiting for %s.",
850                 ctl->server.timeout, ctl->server.names->id);
851         ok = PS_ERROR;
852     }
853     else if (js == 2)
854     {
855         /* error message printed at point of longjmp */
856         ok = PS_ERROR;
857     }
858     else
859     {
860         char buf [POPBUFSIZE+1];
861         int *msgsizes, len, num, count, new, deletions = 0;
862         FILE *sockfp; 
863         /* execute pre-initialization command, if any */
864         if (ctl->preconnect && (ok = system(ctl->preconnect)))
865         {
866             sprintf(buf, "pre-connection command failed with status %d", ok);
867             error(0, 0, buf);
868             ok = PS_SYNTAX;
869             goto closeUp;
870         }
871
872         /* open a socket to the mail server */
873         if (!(sockfp = SockOpen(ctl->server.names->id,
874                      ctl->server.port ? ctl->server.port : protocol->port)))
875         {
876             if (errno != EHOSTUNREACH)
877                 error(0, errno, "connecting to host");
878             ok = PS_SOCKET;
879             goto closeUp;
880         }
881
882 #ifdef KERBEROS_V4
883         if (ctl->authenticate == A_KERBEROS)
884         {
885             ok = kerberos_auth(fileno(sockfp), ctl->server.canonical_name);
886             if (ok != 0)
887                 goto cleanUp;
888             vtalarm(ctl->server.timeout);
889         }
890 #endif /* KERBEROS_V4 */
891
892         /* accept greeting message from mail server */
893         ok = (protocol->parse_response)(sockfp, buf);
894         if (ok != 0)
895             goto cleanUp;
896         vtalarm(ctl->server.timeout);
897
898         /*
899          * Try to parse the host's actual name out of the greeting
900          * message.  We do this so that the progress messages will
901          * make sense even if the connection is indirected through
902          * ssh. *Do* use this for hacking reply headers, but *don't*
903          * use it for error logging, as the names in the log should
904          * correlate directly back to rc file entries.
905          *
906          * This assumes that the first space-delimited token found
907          * that contains at least two dots (with the characters on
908          * each side of the dot alphanumeric to exclude version
909          * numbers) is the hostname.  The hostname candidate may not
910          * contain @ -- if it does it's probably a mailserver
911          * maintainer's name.  If no such token is found, fall back on
912          * the .fetchmailrc id.
913          */
914         pst = 0;
915         for (cp = buf; *cp; cp++)
916         {
917             switch (pst)
918             {
919             case 0:             /* skip to end of current token */
920                 if (*cp == ' ')
921                     pst = 1;
922                 break;
923
924             case 1:             /* look for blank-delimited token */
925                 if (*cp != ' ')
926                 {
927                     sp = cp;
928                     pst = 2;
929                 }
930                 break;
931
932             case 2:             /* look for first dot */
933                 if (*cp == '@')
934                     pst = 0;
935                 else if (*cp == ' ')
936                     pst = 1;
937                 else if (*cp == '.' && isalpha(cp[1]) && isalpha(cp[-1]))
938                     pst = 3;
939                 break;
940
941             case 3:             /* look for second dot */
942                 if (*cp == '@')
943                     pst = 0;
944                 else if (*cp == ' ')
945                     pst = 1;
946                 else if (*cp == '.' && isalpha(cp[1]) && isalpha(cp[-1]))
947                     pst = 4;
948                 break;
949
950             case 4:             /* look for trailing space */
951                 if (*cp == '@')
952                     pst = 0;
953                 else if (*cp == ' ')
954                 {
955                     pst = 5;
956                     goto done;
957                 }
958                 break;
959             }
960         }
961     done:
962         if (pst == 5)
963         {
964             char        *tp = realname;
965
966             while (sp < cp)
967                 *tp++ = *sp++;
968             *tp = '\0';
969         }
970         else
971             strcpy(realname, ctl->server.names->id);
972
973         /* try to get authorized to fetch mail */
974         shroud = ctl->password;
975         ok = (protocol->getauth)(sockfp, ctl, buf);
976         shroud = (char *)NULL;
977         if (ok == PS_ERROR)
978             ok = PS_AUTHFAIL;
979         if (ok != 0)
980             goto cleanUp;
981         vtalarm(ctl->server.timeout);
982
983         /* compute number of messages and number of new messages waiting */
984         ok = (protocol->getrange)(sockfp, ctl, &count, &new);
985         if (ok != 0)
986             goto cleanUp;
987         vtalarm(ctl->server.timeout);
988
989         /* show user how many messages we downloaded */
990         if (outlevel > O_SILENT)
991             if (count == 0)
992                 error(0, 0, "No mail from %s@%s", 
993                         ctl->remotename,
994                         realname);
995             else
996             {
997                 if (new != -1 && (count - new) > 0)
998                     error(0, 0, "%d message%s (%d seen) from %s@%s.",
999                                 count, count > 1 ? "s" : "", count-new,
1000                                 ctl->remotename,
1001                                 realname);
1002                 else
1003                     error(0, 0, "%d message%s from %s@%s.", count, count > 1 ? "s" : "",
1004                                 ctl->remotename,
1005                                 realname);
1006             }
1007
1008         /* we may need to get sizes in order to check message limits */
1009         msgsizes = (int *)NULL;
1010         if (!ctl->fetchall && proto->getsizes && ctl->limit)
1011         {
1012             msgsizes = (int *)alloca(sizeof(int) * count);
1013
1014             ok = (proto->getsizes)(sockfp, count, msgsizes);
1015             if (ok != 0)
1016                 goto cleanUp;
1017             vtalarm(ctl->server.timeout);
1018         }
1019
1020
1021         if (check_only)
1022         {
1023             if (new == -1 || ctl->fetchall)
1024                 new = count;
1025             ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
1026             goto cleanUp;
1027         }
1028         else if (count > 0)
1029         {    
1030             /*
1031              * What forces this code is that in POP3 and IMAP2BIS you can't
1032              * fetch a message without having it marked `seen'.  In IMAP4,
1033              * on the other hand, you can (peek_capable is set to convey
1034              * this).
1035              *
1036              * The result of being unable to peek is that if there's
1037              * any kind of transient error (DNS lookup failure, or
1038              * sendmail refusing delivery due to process-table limits)
1039              * the message will be marked "seen" on the server without
1040              * having been delivered.  This is not a big problem if
1041              * fetchmail is running in foreground, because the user
1042              * will see a "skipped" message when it next runs and get
1043              * clued in.
1044              *
1045              * But in daemon mode this leads to the message being silently
1046              * ignored forever.  This is not acceptable.
1047              *
1048              * We compensate for this by checking the error count from the 
1049              * previous pass and forcing all messages to be considered new
1050              * if it's nonzero.
1051              */
1052             int force_retrieval = !peek_capable && (ctl->errcount > 0);
1053
1054             ctl->errcount = 0;
1055
1056             /* read, forward, and delete messages */
1057             for (num = 1; num <= count; num++)
1058             {
1059                 int     toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
1060                 int     fetch_it = ctl->fetchall ||
1061                     (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num))));
1062
1063                 /* we may want to reject this message if it's old */
1064                 if (!fetch_it)
1065                 {
1066                     if (outlevel > O_SILENT)
1067                     {
1068                         error_build("skipping message %d", num);
1069                         if (toolarge)
1070                             error_build(" (oversized, %d bytes)", msgsizes[num-1]);
1071                     }
1072                 }
1073                 else
1074                 {
1075                     /* request a message */
1076                     ok = (protocol->fetch)(sockfp, ctl, num, &len);
1077                     if (ok != 0)
1078                         goto cleanUp;
1079                     vtalarm(ctl->server.timeout);
1080
1081                     if (outlevel > O_SILENT)
1082                     {
1083                         error_build("reading message %d", num);
1084                         if (len > 0)
1085                             error_build(" (%d bytes)", len);
1086                         if (outlevel == O_VERBOSE)
1087                             error_complete(0, 0, "");
1088                         else
1089                             error_build(" ");
1090                     }
1091
1092                     /* read the message and ship it to the output sink */
1093                     ok = gen_readmsg(sockfp,
1094                                      len, 
1095                                      protocol->delimited,
1096                                      ctl,
1097                                      realname);
1098                     if (ok != 0)
1099                         goto cleanUp;
1100                     vtalarm(ctl->server.timeout);
1101
1102                     /* tell the server we got it OK and resynchronize */
1103                     if (protocol->trail)
1104                     {
1105                         ok = (protocol->trail)(sockfp, ctl, num);
1106                         if (ok != 0)
1107                             goto cleanUp;
1108                         vtalarm(ctl->server.timeout);
1109                     }
1110                 }
1111
1112                 /*
1113                  * At this point in flow of control, either we've bombed
1114                  * on a protocol error or had delivery refused by the SMTP
1115                  * server (unlikely -- I've never seen it) or we've seen
1116                  * `accepted for delivery' and the message is shipped.
1117                  * It's safe to mark the message seen and delete it on the
1118                  * server now.
1119                  */
1120
1121                 /* maybe we delete this message now? */
1122                 if (protocol->delete
1123                     && (fetch_it ? !ctl->keep : ctl->flush))
1124                 {
1125                     deletions++;
1126                     if (outlevel > O_SILENT) 
1127                         error_complete(0, 0, " flushed");
1128                     ok = (protocol->delete)(sockfp, ctl, num);
1129                     if (ok != 0)
1130                         goto cleanUp;
1131                     vtalarm(ctl->server.timeout);
1132                     delete_str(&ctl->newsaved, num);
1133                 }
1134                 else if (outlevel > O_SILENT) 
1135                     error_complete(0, 0, " not flushed");
1136
1137                 /* perhaps this as many as we're ready to handle */
1138                 if (ctl->fetchlimit && ctl->fetchlimit <= num)
1139                     break;
1140             }
1141
1142             ok = gen_transact(sockfp, protocol->exit_cmd);
1143             if (ok == 0)
1144                 ok = PS_SUCCESS;
1145             vtalarm(0);
1146             fclose(sockfp);
1147             goto closeUp;
1148         }
1149         else {
1150             ok = gen_transact(sockfp, protocol->exit_cmd);
1151             if (ok == 0)
1152                 ok = PS_NOMAIL;
1153             vtalarm(0);
1154             fclose(sockfp);
1155             goto closeUp;
1156         }
1157
1158     cleanUp:
1159         vtalarm(ctl->server.timeout);
1160         if (ok != 0 && ok != PS_SOCKET)
1161             gen_transact(sockfp, protocol->exit_cmd);
1162         vtalarm(0);
1163         fclose(sockfp);
1164     }
1165
1166     switch (ok)
1167     {
1168     case PS_SOCKET:
1169         msg = "socket";
1170         break;
1171     case PS_AUTHFAIL:
1172         msg = "authorization";
1173         break;
1174     case PS_SYNTAX:
1175         msg = "missing or bad RFC822 header";
1176         break;
1177     case PS_IOERR:
1178         msg = "MDA";
1179         break;
1180     case PS_ERROR:
1181         msg = "client/server synchronization";
1182         break;
1183     case PS_PROTOCOL:
1184         msg = "client/server protocol";
1185         break;
1186     case PS_SMTP:
1187         msg = "SMTP transaction";
1188         break;
1189     case PS_UNDEFINED:
1190         error(0, 0, "undefined");
1191         break;
1192     }
1193     if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
1194                 || ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
1195         error(0, 0, "%s error while fetching from %s", msg, ctl->server.names->id);
1196
1197 closeUp:
1198     signal(SIGVTALRM, sigsave);
1199     return(ok);
1200 }
1201
1202 #if defined(HAVE_STDARG_H)
1203 void gen_send(FILE *sockfp, char *fmt, ... )
1204 /* assemble command in printf(3) style and send to the server */
1205 #else
1206 void gen_send(sockfp, fmt, va_alist)
1207 /* assemble command in printf(3) style and send to the server */
1208 FILE *sockfp;           /* socket to which server is connected */
1209 const char *fmt;        /* printf-style format */
1210 va_dcl
1211 #endif
1212 {
1213     char buf [POPBUFSIZE+1];
1214     va_list ap;
1215
1216     if (protocol->tagged)
1217         (void) sprintf(buf, "%s ", GENSYM);
1218     else
1219         buf[0] = '\0';
1220
1221 #if defined(HAVE_STDARG_H)
1222     va_start(ap, fmt) ;
1223 #else
1224     va_start(ap);
1225 #endif
1226     vsprintf(buf + strlen(buf), fmt, ap);
1227     va_end(ap);
1228
1229     strcat(buf, "\r\n");
1230     SockWrite(buf, 1, strlen(buf), sockfp);
1231
1232     if (outlevel == O_VERBOSE)
1233     {
1234         char *cp;
1235
1236         if (shroud && (cp = strstr(buf, shroud)))
1237             memset(cp, '*', strlen(shroud));
1238         buf[strlen(buf)-1] = '\0';
1239         error(0, 0, "%s> %s", protocol->name, buf);
1240     }
1241 }
1242
1243 #if defined(HAVE_STDARG_H)
1244 int gen_transact(FILE *sockfp, char *fmt, ... )
1245 /* assemble command in printf(3) style, send to server, accept a response */
1246 #else
1247 int gen_transact(sockfp, fmt, va_alist)
1248 /* assemble command in printf(3) style, send to server, accept a response */
1249 FILE *sockfp;           /* socket to which server is connected */
1250 const char *fmt;        /* printf-style format */
1251 va_dcl
1252 #endif
1253 {
1254     int ok;
1255     char buf [POPBUFSIZE+1];
1256     va_list ap;
1257
1258     if (protocol->tagged)
1259         (void) sprintf(buf, "%s ", GENSYM);
1260     else
1261         buf[0] = '\0';
1262
1263 #if defined(HAVE_STDARG_H)
1264     va_start(ap, fmt) ;
1265 #else
1266     va_start(ap);
1267 #endif
1268     vsprintf(buf + strlen(buf), fmt, ap);
1269     va_end(ap);
1270
1271     strcat(buf, "\r\n");
1272     SockWrite(buf, 1, strlen(buf), sockfp);
1273
1274     if (outlevel == O_VERBOSE)
1275     {
1276         char *cp;
1277
1278         if (shroud && (cp = strstr(buf, shroud)))
1279             memset(cp, '*', strlen(shroud));
1280         buf[strlen(buf)-1] = '\0';
1281         error(0, 0, "%s> %s", protocol->name, buf);
1282     }
1283
1284     /* we presume this does its own response echoing */
1285     ok = (protocol->parse_response)(sockfp, buf);
1286     vtalarm(mytimeout);
1287
1288     return(ok);
1289 }
1290
1291 /* driver.c ends here */