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