Deleted Added
full compact
collect.c (141858) collect.c (147078)
1/*
2 * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
1/*
2 * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
16SM_RCSID("@(#)$Id: collect.c,v 8.260 2004/11/30 23:29:15 ca Exp $")
16SM_RCSID("@(#)$Id: collect.c,v 8.261 2005/02/16 23:38:51 ca Exp $")
17
18static void collecttimeout __P((int));
19static void eatfrom __P((char *volatile, ENVELOPE *));
20static void collect_doheader __P((ENVELOPE *));
21static SM_FILE_T *collect_dfopen __P((ENVELOPE *));
22static SM_FILE_T *collect_eoh __P((ENVELOPE *, int, int));
23
24/*
25** COLLECT_EOH -- end-of-header processing in collect()
26**
27** Called by collect() when it encounters the blank line
28** separating the header from the message body, or when it
29** encounters EOF in a message that contains only a header.
30**
31** Parameters:
32** e -- envelope
33** numhdrs -- number of headers
34** hdrslen -- length of headers
35**
36** Results:
37** NULL, or handle to open data file
38**
39** Side Effects:
40** end-of-header check ruleset is invoked.
41** envelope state is updated.
42** headers may be added and deleted.
43** selects the queue.
44** opens the data file.
45*/
46
47static SM_FILE_T *
48collect_eoh(e, numhdrs, hdrslen)
49 ENVELOPE *e;
50 int numhdrs;
51 int hdrslen;
52{
53 char hnum[16];
54 char hsize[16];
55
56 /* call the end-of-header check ruleset */
57 (void) sm_snprintf(hnum, sizeof hnum, "%d", numhdrs);
58 (void) sm_snprintf(hsize, sizeof hsize, "%d", hdrslen);
59 if (tTd(30, 10))
60 sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n",
61 hnum, hsize);
62 (void) rscheck("check_eoh", hnum, hsize, e, RSF_UNSTRUCTURED|RSF_COUNT,
63 3, NULL, e->e_id);
64
65 /*
66 ** Process the header,
67 ** select the queue, open the data file.
68 */
69
70 collect_doheader(e);
71 return collect_dfopen(e);
72}
73
74/*
75** COLLECT_DOHEADER -- process header in collect()
76**
77** Called by collect() after it has finished parsing the header,
78** but before it selects the queue and creates the data file.
79** The results of processing the header will affect queue selection.
80**
81** Parameters:
82** e -- envelope
83**
84** Results:
85** none.
86**
87** Side Effects:
88** envelope state is updated.
89** headers may be added and deleted.
90*/
91
92static void
93collect_doheader(e)
94 ENVELOPE *e;
95{
96 /*
97 ** Find out some information from the headers.
98 ** Examples are who is the from person & the date.
99 */
100
101 eatheader(e, true, false);
102
103 if (GrabTo && e->e_sendqueue == NULL)
104 usrerr("No recipient addresses found in header");
105
106 /*
107 ** If we have a Return-Receipt-To:, turn it into a DSN.
108 */
109
110 if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL)
111 {
112 ADDRESS *q;
113
114 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
115 if (!bitset(QHASNOTIFY, q->q_flags))
116 q->q_flags |= QHASNOTIFY|QPINGONSUCCESS;
117 }
118
119 /*
120 ** Add an appropriate recipient line if we have none.
121 */
122
123 if (hvalue("to", e->e_header) != NULL ||
124 hvalue("cc", e->e_header) != NULL ||
125 hvalue("apparently-to", e->e_header) != NULL)
126 {
127 /* have a valid recipient header -- delete Bcc: headers */
128 e->e_flags |= EF_DELETE_BCC;
129 }
130 else if (hvalue("bcc", e->e_header) == NULL)
131 {
132 /* no valid recipient headers */
133 register ADDRESS *q;
134 char *hdr = NULL;
135
136 /* create a recipient field */
137 switch (NoRecipientAction)
138 {
139 case NRA_ADD_APPARENTLY_TO:
140 hdr = "Apparently-To";
141 break;
142
143 case NRA_ADD_TO:
144 hdr = "To";
145 break;
146
147 case NRA_ADD_BCC:
148 addheader("Bcc", " ", 0, e);
149 break;
150
151 case NRA_ADD_TO_UNDISCLOSED:
152 addheader("To", "undisclosed-recipients:;", 0, e);
153 break;
154 }
155
156 if (hdr != NULL)
157 {
158 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
159 {
160 if (q->q_alias != NULL)
161 continue;
162 if (tTd(30, 3))
163 sm_dprintf("Adding %s: %s\n",
164 hdr, q->q_paddr);
165 addheader(hdr, q->q_paddr, 0, e);
166 }
167 }
168 }
169}
170
171/*
172** COLLECT_DFOPEN -- open the message data file
173**
174** Called by collect() after it has finished processing the header.
175** Queue selection occurs at this point, possibly based on the
176** envelope's recipient list and on header information.
177**
178** Parameters:
179** e -- envelope
180**
181** Results:
182** NULL, or a pointer to an open data file,
183** into which the message body will be written by collect().
184**
185** Side Effects:
186** Calls syserr, sets EF_FATALERRS and returns NULL
187** if there is insufficient disk space.
188** Aborts process if data file could not be opened.
189** Otherwise, the queue is selected,
190** e->e_{dfino,dfdev,msgsize,flags} are updated,
191** and a pointer to an open data file is returned.
192*/
193
194static SM_FILE_T *
195collect_dfopen(e)
196 ENVELOPE *e;
197{
198 MODE_T oldumask = 0;
199 int dfd;
200 struct stat stbuf;
201 SM_FILE_T *df;
202 char *dfname;
203
204 if (!setnewqueue(e))
205 return NULL;
206
207 dfname = queuename(e, DATAFL_LETTER);
208 if (bitset(S_IWGRP, QueueFileMode))
209 oldumask = umask(002);
210 df = bfopen(dfname, QueueFileMode, DataFileBufferSize,
211 SFF_OPENASROOT);
212 if (bitset(S_IWGRP, QueueFileMode))
213 (void) umask(oldumask);
214 if (df == NULL)
215 {
216 syserr("@Cannot create %s", dfname);
217 e->e_flags |= EF_NO_BODY_RETN;
218 flush_errors(true);
219 finis(false, true, ExitStat);
220 /* NOTREACHED */
221 }
222 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
223 if (dfd < 0 || fstat(dfd, &stbuf) < 0)
224 e->e_dfino = -1;
225 else
226 {
227 e->e_dfdev = stbuf.st_dev;
228 e->e_dfino = stbuf.st_ino;
229 }
230 e->e_flags |= EF_HAS_DF;
231 return df;
232}
233
234/*
235** COLLECT -- read & parse message header & make temp file.
236**
237** Creates a temporary file name and copies the standard
238** input to that file. Leading UNIX-style "From" lines are
239** stripped off (after important information is extracted).
240**
241** Parameters:
242** fp -- file to read.
243** smtpmode -- if set, we are running SMTP: give an RFC821
244** style message to say we are ready to collect
245** input, and never ignore a single dot to mean
246** end of message.
247** hdrp -- the location to stash the header.
248** e -- the current envelope.
249** rsetsize -- reset e_msgsize?
250**
251** Returns:
252** none.
253**
254** Side Effects:
255** If successful,
256** - Data file is created and filled, and e->e_dfp is set.
257** - The from person may be set.
258** If the "enough disk space" check fails,
259** - syserr is called.
260** - e->e_dfp is NULL.
261** - e->e_flags & EF_FATALERRS is set.
262** - collect() returns.
263** If data file cannot be created, the process is terminated.
264*/
265
266static jmp_buf CtxCollectTimeout;
267static bool volatile CollectProgress;
268static SM_EVENT *volatile CollectTimeout = NULL;
269
270/* values for input state machine */
271#define IS_NORM 0 /* middle of line */
272#define IS_BOL 1 /* beginning of line */
273#define IS_DOT 2 /* read a dot at beginning of line */
274#define IS_DOTCR 3 /* read ".\r" at beginning of line */
275#define IS_CR 4 /* read a carriage return */
276
277/* values for message state machine */
278#define MS_UFROM 0 /* reading Unix from line */
279#define MS_HEADER 1 /* reading message header */
280#define MS_BODY 2 /* reading message body */
281#define MS_DISCARD 3 /* discarding rest of message */
282
283void
284collect(fp, smtpmode, hdrp, e, rsetsize)
285 SM_FILE_T *fp;
286 bool smtpmode;
287 HDR **hdrp;
288 register ENVELOPE *e;
289 bool rsetsize;
290{
291 register SM_FILE_T *volatile df;
292 volatile bool ignrdot;
293 volatile int dbto;
294 register char *volatile bp;
295 volatile int c;
296 volatile bool inputerr;
297 bool headeronly;
298 char *volatile buf;
299 volatile int buflen;
300 volatile int istate;
301 volatile int mstate;
302 volatile int hdrslen;
303 volatile int numhdrs;
304 volatile int afd;
305 unsigned char *volatile pbp;
306 unsigned char peekbuf[8];
307 char bufbuf[MAXLINE];
308
309 df = NULL;
310 ignrdot = smtpmode ? false : IgnrDot;
311 dbto = smtpmode ? (int) TimeOuts.to_datablock : 0;
312 c = SM_IO_EOF;
313 inputerr = false;
314 headeronly = hdrp != NULL;
315 hdrslen = 0;
316 numhdrs = 0;
317 HasEightBits = false;
318 buf = bp = bufbuf;
319 buflen = sizeof bufbuf;
320 pbp = peekbuf;
321 istate = IS_BOL;
322 mstate = SaveFrom ? MS_HEADER : MS_UFROM;
323 CollectProgress = false;
324
325 /*
326 ** Tell ARPANET to go ahead.
327 */
328
329 if (smtpmode)
330 message("354 Enter mail, end with \".\" on a line by itself");
331
332 if (tTd(30, 2))
333 sm_dprintf("collect\n");
334
335 /*
336 ** Read the message.
337 **
338 ** This is done using two interleaved state machines.
339 ** The input state machine is looking for things like
340 ** hidden dots; the message state machine is handling
341 ** the larger picture (e.g., header versus body).
342 */
343
344 if (dbto != 0)
345 {
346 /* handle possible input timeout */
347 if (setjmp(CtxCollectTimeout) != 0)
348 {
349 if (LogLevel > 2)
350 sm_syslog(LOG_NOTICE, e->e_id,
351 "timeout waiting for input from %s during message collect",
352 CURHOSTNAME);
353 errno = 0;
354 if (smtpmode)
355 {
356 /*
357 ** Override e_message in usrerr() as this
358 ** is the reason for failure that should
359 ** be logged for undelivered recipients.
360 */
361
362 e->e_message = NULL;
363 }
364 usrerr("451 4.4.1 timeout waiting for input during message collect");
365 goto readerr;
366 }
367 CollectTimeout = sm_setevent(dbto, collecttimeout, dbto);
368 }
369
370 if (rsetsize)
371 e->e_msgsize = 0;
372 for (;;)
373 {
374 if (tTd(30, 35))
375 sm_dprintf("top, istate=%d, mstate=%d\n", istate,
376 mstate);
377 for (;;)
378 {
379 if (pbp > peekbuf)
380 c = *--pbp;
381 else
382 {
383 while (!sm_io_eof(fp) && !sm_io_error(fp))
384 {
385 errno = 0;
386 c = sm_io_getc(fp, SM_TIME_DEFAULT);
387 if (c == SM_IO_EOF && errno == EINTR)
388 {
389 /* Interrupted, retry */
390 sm_io_clearerr(fp);
391 continue;
392 }
393 break;
394 }
395 CollectProgress = true;
396 if (TrafficLogFile != NULL && !headeronly)
397 {
398 if (istate == IS_BOL)
399 (void) sm_io_fprintf(TrafficLogFile,
400 SM_TIME_DEFAULT,
401 "%05d <<< ",
402 (int) CurrentPid);
403 if (c == SM_IO_EOF)
404 (void) sm_io_fprintf(TrafficLogFile,
405 SM_TIME_DEFAULT,
406 "[EOF]\n");
407 else
408 (void) sm_io_putc(TrafficLogFile,
409 SM_TIME_DEFAULT,
410 c);
411 }
412 if (c == SM_IO_EOF)
413 goto readerr;
414 if (SevenBitInput)
415 c &= 0x7f;
416 else
417 HasEightBits |= bitset(0x80, c);
418 }
419 if (tTd(30, 94))
420 sm_dprintf("istate=%d, c=%c (0x%x)\n",
421 istate, (char) c, c);
422 switch (istate)
423 {
424 case IS_BOL:
425 if (c == '.')
426 {
427 istate = IS_DOT;
428 continue;
429 }
430 break;
431
432 case IS_DOT:
433 if (c == '\n' && !ignrdot &&
434 !bitset(EF_NL_NOT_EOL, e->e_flags))
435 goto readerr;
436 else if (c == '\r' &&
437 !bitset(EF_CRLF_NOT_EOL, e->e_flags))
438 {
439 istate = IS_DOTCR;
440 continue;
441 }
442 else if (ignrdot ||
443 (c != '.' &&
444 OpMode != MD_SMTP &&
445 OpMode != MD_DAEMON &&
446 OpMode != MD_ARPAFTP))
447
448 {
449 SM_ASSERT(pbp < peekbuf + sizeof(peekbuf));
450 *pbp++ = c;
451 c = '.';
452 }
453 break;
454
455 case IS_DOTCR:
456 if (c == '\n' && !ignrdot)
457 goto readerr;
458 else
459 {
460 /* push back the ".\rx" */
461 SM_ASSERT(pbp < peekbuf + sizeof(peekbuf));
462 *pbp++ = c;
463 if (OpMode != MD_SMTP &&
464 OpMode != MD_DAEMON &&
465 OpMode != MD_ARPAFTP)
466 {
467 SM_ASSERT(pbp < peekbuf +
468 sizeof(peekbuf));
469 *pbp++ = '\r';
470 c = '.';
471 }
472 else
473 c = '\r';
474 }
475 break;
476
477 case IS_CR:
478 if (c == '\n')
479 istate = IS_BOL;
480 else
481 {
482 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT,
483 c);
484 c = '\r';
485 istate = IS_NORM;
486 }
487 goto bufferchar;
488 }
489
490 if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags))
491 {
492 istate = IS_CR;
493 continue;
494 }
495 else if (c == '\n' && !bitset(EF_NL_NOT_EOL,
496 e->e_flags))
497 istate = IS_BOL;
498 else
499 istate = IS_NORM;
500
501bufferchar:
502 if (!headeronly)
503 {
504 /* no overflow? */
505 if (e->e_msgsize >= 0)
506 {
507 e->e_msgsize++;
508 if (MaxMessageSize > 0 &&
509 !bitset(EF_TOOBIG, e->e_flags) &&
510 e->e_msgsize > MaxMessageSize)
511 e->e_flags |= EF_TOOBIG;
512 }
513 }
514 switch (mstate)
515 {
516 case MS_BODY:
517 /* just put the character out */
518 if (!bitset(EF_TOOBIG, e->e_flags))
519 (void) sm_io_putc(df, SM_TIME_DEFAULT,
520 c);
521
522 /* FALLTHROUGH */
523
524 case MS_DISCARD:
525 continue;
526 }
527
528 SM_ASSERT(mstate == MS_UFROM || mstate == MS_HEADER);
529
530 /* header -- buffer up */
531 if (bp >= &buf[buflen - 2])
532 {
533 char *obuf;
534
535 /* out of space for header */
536 obuf = buf;
537 if (buflen < MEMCHUNKSIZE)
538 buflen *= 2;
539 else
540 buflen += MEMCHUNKSIZE;
541 buf = xalloc(buflen);
542 memmove(buf, obuf, bp - obuf);
543 bp = &buf[bp - obuf];
544 if (obuf != bufbuf)
545 sm_free(obuf); /* XXX */
546 }
547
548 /*
549 ** XXX Notice: the logic here is broken.
550 ** An input to sendmail that doesn't contain a
551 ** header but starts immediately with the body whose
552 ** first line contain characters which match the
553 ** following "if" will cause problems: those
554 ** characters will NOT appear in the output...
555 ** Do we care?
556 */
557
558 if (c >= 0200 && c <= 0237)
559 {
560#if 0 /* causes complaints -- figure out something for 8.n+1 */
561 usrerr("Illegal character 0x%x in header", c);
562#else /* 0 */
563 /* EMPTY */
564#endif /* 0 */
565 }
566 else if (c != '\0')
567 {
568 *bp++ = c;
569 ++hdrslen;
570 if (!headeronly &&
571 MaxHeadersLength > 0 &&
572 hdrslen > MaxHeadersLength)
573 {
574 sm_syslog(LOG_NOTICE, e->e_id,
575 "headers too large (%d max) from %s during message collect",
576 MaxHeadersLength,
577 CURHOSTNAME);
578 errno = 0;
579 e->e_flags |= EF_CLRQUEUE;
580 e->e_status = "5.6.0";
581 usrerrenh(e->e_status,
582 "552 Headers too large (%d max)",
583 MaxHeadersLength);
584 mstate = MS_DISCARD;
585 }
586 }
587 if (istate == IS_BOL)
588 break;
589 }
590 *bp = '\0';
591
592nextstate:
593 if (tTd(30, 35))
594 sm_dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
595 istate, mstate, buf);
596 switch (mstate)
597 {
598 case MS_UFROM:
599 mstate = MS_HEADER;
600#ifndef NOTUNIX
601 if (strncmp(buf, "From ", 5) == 0)
602 {
603 bp = buf;
604 eatfrom(buf, e);
605 continue;
606 }
607#endif /* ! NOTUNIX */
608 /* FALLTHROUGH */
609
610 case MS_HEADER:
611 if (!isheader(buf))
612 {
613 mstate = MS_BODY;
614 goto nextstate;
615 }
616
617 /* check for possible continuation line */
618 do
619 {
620 sm_io_clearerr(fp);
621 errno = 0;
622 c = sm_io_getc(fp, SM_TIME_DEFAULT);
623 } while (c == SM_IO_EOF && errno == EINTR);
624 if (c != SM_IO_EOF)
625 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c);
626 if (c == ' ' || c == '\t')
627 {
628 /* yep -- defer this */
629 continue;
630 }
631
632 /* trim off trailing CRLF or NL */
633 SM_ASSERT(bp > buf);
634 if (*--bp != '\n' || *--bp != '\r')
635 bp++;
636 *bp = '\0';
637
638 if (bitset(H_EOH, chompheader(buf,
639 CHHDR_CHECK | CHHDR_USER,
640 hdrp, e)))
641 {
642 mstate = MS_BODY;
643 goto nextstate;
644 }
645 numhdrs++;
646 break;
647
648 case MS_BODY:
649 if (tTd(30, 1))
650 sm_dprintf("EOH\n");
651
652 if (headeronly)
653 goto readerr;
654
655 df = collect_eoh(e, numhdrs, hdrslen);
656 if (df == NULL)
657 e->e_flags |= EF_TOOBIG;
658
659 bp = buf;
660
661 /* toss blank line */
662 if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) &&
663 bp[0] == '\r' && bp[1] == '\n') ||
664 (!bitset(EF_NL_NOT_EOL, e->e_flags) &&
665 bp[0] == '\n'))
666 {
667 break;
668 }
669
670 /* if not a blank separator, write it out */
671 if (!bitset(EF_TOOBIG, e->e_flags))
672 {
673 while (*bp != '\0')
674 (void) sm_io_putc(df, SM_TIME_DEFAULT,
675 *bp++);
676 }
677 break;
678 }
679 bp = buf;
680 }
681
682readerr:
683 if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp))
684 {
685 const char *errmsg;
686
687 if (sm_io_eof(fp))
688 errmsg = "unexpected close";
689 else
690 errmsg = sm_errstring(errno);
691 if (tTd(30, 1))
692 sm_dprintf("collect: premature EOM: %s\n", errmsg);
693 if (LogLevel > 1)
694 sm_syslog(LOG_WARNING, e->e_id,
695 "collect: premature EOM: %s", errmsg);
696 inputerr = true;
697 }
698
699 /* reset global timer */
700 if (CollectTimeout != NULL)
701 sm_clrevent(CollectTimeout);
702
703 if (headeronly)
704 return;
705
706 if (mstate != MS_BODY)
707 {
708 /* no body or discard, so we never opened the data file */
709 SM_ASSERT(df == NULL);
710 df = collect_eoh(e, numhdrs, hdrslen);
711 }
712
713 if (df == NULL)
714 {
715 /* skip next few clauses */
716 /* EMPTY */
717 }
718 else if (sm_io_flush(df, SM_TIME_DEFAULT) != 0 || sm_io_error(df))
719 {
720 dferror(df, "sm_io_flush||sm_io_error", e);
721 flush_errors(true);
722 finis(true, true, ExitStat);
723 /* NOTREACHED */
724 }
725 else if (SuperSafe == SAFE_NO ||
726 SuperSafe == SAFE_INTERACTIVE ||
727 (SuperSafe == SAFE_REALLY_POSTMILTER && smtpmode))
728 {
729 /* skip next few clauses */
730 /* EMPTY */
17
18static void collecttimeout __P((int));
19static void eatfrom __P((char *volatile, ENVELOPE *));
20static void collect_doheader __P((ENVELOPE *));
21static SM_FILE_T *collect_dfopen __P((ENVELOPE *));
22static SM_FILE_T *collect_eoh __P((ENVELOPE *, int, int));
23
24/*
25** COLLECT_EOH -- end-of-header processing in collect()
26**
27** Called by collect() when it encounters the blank line
28** separating the header from the message body, or when it
29** encounters EOF in a message that contains only a header.
30**
31** Parameters:
32** e -- envelope
33** numhdrs -- number of headers
34** hdrslen -- length of headers
35**
36** Results:
37** NULL, or handle to open data file
38**
39** Side Effects:
40** end-of-header check ruleset is invoked.
41** envelope state is updated.
42** headers may be added and deleted.
43** selects the queue.
44** opens the data file.
45*/
46
47static SM_FILE_T *
48collect_eoh(e, numhdrs, hdrslen)
49 ENVELOPE *e;
50 int numhdrs;
51 int hdrslen;
52{
53 char hnum[16];
54 char hsize[16];
55
56 /* call the end-of-header check ruleset */
57 (void) sm_snprintf(hnum, sizeof hnum, "%d", numhdrs);
58 (void) sm_snprintf(hsize, sizeof hsize, "%d", hdrslen);
59 if (tTd(30, 10))
60 sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n",
61 hnum, hsize);
62 (void) rscheck("check_eoh", hnum, hsize, e, RSF_UNSTRUCTURED|RSF_COUNT,
63 3, NULL, e->e_id);
64
65 /*
66 ** Process the header,
67 ** select the queue, open the data file.
68 */
69
70 collect_doheader(e);
71 return collect_dfopen(e);
72}
73
74/*
75** COLLECT_DOHEADER -- process header in collect()
76**
77** Called by collect() after it has finished parsing the header,
78** but before it selects the queue and creates the data file.
79** The results of processing the header will affect queue selection.
80**
81** Parameters:
82** e -- envelope
83**
84** Results:
85** none.
86**
87** Side Effects:
88** envelope state is updated.
89** headers may be added and deleted.
90*/
91
92static void
93collect_doheader(e)
94 ENVELOPE *e;
95{
96 /*
97 ** Find out some information from the headers.
98 ** Examples are who is the from person & the date.
99 */
100
101 eatheader(e, true, false);
102
103 if (GrabTo && e->e_sendqueue == NULL)
104 usrerr("No recipient addresses found in header");
105
106 /*
107 ** If we have a Return-Receipt-To:, turn it into a DSN.
108 */
109
110 if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL)
111 {
112 ADDRESS *q;
113
114 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
115 if (!bitset(QHASNOTIFY, q->q_flags))
116 q->q_flags |= QHASNOTIFY|QPINGONSUCCESS;
117 }
118
119 /*
120 ** Add an appropriate recipient line if we have none.
121 */
122
123 if (hvalue("to", e->e_header) != NULL ||
124 hvalue("cc", e->e_header) != NULL ||
125 hvalue("apparently-to", e->e_header) != NULL)
126 {
127 /* have a valid recipient header -- delete Bcc: headers */
128 e->e_flags |= EF_DELETE_BCC;
129 }
130 else if (hvalue("bcc", e->e_header) == NULL)
131 {
132 /* no valid recipient headers */
133 register ADDRESS *q;
134 char *hdr = NULL;
135
136 /* create a recipient field */
137 switch (NoRecipientAction)
138 {
139 case NRA_ADD_APPARENTLY_TO:
140 hdr = "Apparently-To";
141 break;
142
143 case NRA_ADD_TO:
144 hdr = "To";
145 break;
146
147 case NRA_ADD_BCC:
148 addheader("Bcc", " ", 0, e);
149 break;
150
151 case NRA_ADD_TO_UNDISCLOSED:
152 addheader("To", "undisclosed-recipients:;", 0, e);
153 break;
154 }
155
156 if (hdr != NULL)
157 {
158 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
159 {
160 if (q->q_alias != NULL)
161 continue;
162 if (tTd(30, 3))
163 sm_dprintf("Adding %s: %s\n",
164 hdr, q->q_paddr);
165 addheader(hdr, q->q_paddr, 0, e);
166 }
167 }
168 }
169}
170
171/*
172** COLLECT_DFOPEN -- open the message data file
173**
174** Called by collect() after it has finished processing the header.
175** Queue selection occurs at this point, possibly based on the
176** envelope's recipient list and on header information.
177**
178** Parameters:
179** e -- envelope
180**
181** Results:
182** NULL, or a pointer to an open data file,
183** into which the message body will be written by collect().
184**
185** Side Effects:
186** Calls syserr, sets EF_FATALERRS and returns NULL
187** if there is insufficient disk space.
188** Aborts process if data file could not be opened.
189** Otherwise, the queue is selected,
190** e->e_{dfino,dfdev,msgsize,flags} are updated,
191** and a pointer to an open data file is returned.
192*/
193
194static SM_FILE_T *
195collect_dfopen(e)
196 ENVELOPE *e;
197{
198 MODE_T oldumask = 0;
199 int dfd;
200 struct stat stbuf;
201 SM_FILE_T *df;
202 char *dfname;
203
204 if (!setnewqueue(e))
205 return NULL;
206
207 dfname = queuename(e, DATAFL_LETTER);
208 if (bitset(S_IWGRP, QueueFileMode))
209 oldumask = umask(002);
210 df = bfopen(dfname, QueueFileMode, DataFileBufferSize,
211 SFF_OPENASROOT);
212 if (bitset(S_IWGRP, QueueFileMode))
213 (void) umask(oldumask);
214 if (df == NULL)
215 {
216 syserr("@Cannot create %s", dfname);
217 e->e_flags |= EF_NO_BODY_RETN;
218 flush_errors(true);
219 finis(false, true, ExitStat);
220 /* NOTREACHED */
221 }
222 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
223 if (dfd < 0 || fstat(dfd, &stbuf) < 0)
224 e->e_dfino = -1;
225 else
226 {
227 e->e_dfdev = stbuf.st_dev;
228 e->e_dfino = stbuf.st_ino;
229 }
230 e->e_flags |= EF_HAS_DF;
231 return df;
232}
233
234/*
235** COLLECT -- read & parse message header & make temp file.
236**
237** Creates a temporary file name and copies the standard
238** input to that file. Leading UNIX-style "From" lines are
239** stripped off (after important information is extracted).
240**
241** Parameters:
242** fp -- file to read.
243** smtpmode -- if set, we are running SMTP: give an RFC821
244** style message to say we are ready to collect
245** input, and never ignore a single dot to mean
246** end of message.
247** hdrp -- the location to stash the header.
248** e -- the current envelope.
249** rsetsize -- reset e_msgsize?
250**
251** Returns:
252** none.
253**
254** Side Effects:
255** If successful,
256** - Data file is created and filled, and e->e_dfp is set.
257** - The from person may be set.
258** If the "enough disk space" check fails,
259** - syserr is called.
260** - e->e_dfp is NULL.
261** - e->e_flags & EF_FATALERRS is set.
262** - collect() returns.
263** If data file cannot be created, the process is terminated.
264*/
265
266static jmp_buf CtxCollectTimeout;
267static bool volatile CollectProgress;
268static SM_EVENT *volatile CollectTimeout = NULL;
269
270/* values for input state machine */
271#define IS_NORM 0 /* middle of line */
272#define IS_BOL 1 /* beginning of line */
273#define IS_DOT 2 /* read a dot at beginning of line */
274#define IS_DOTCR 3 /* read ".\r" at beginning of line */
275#define IS_CR 4 /* read a carriage return */
276
277/* values for message state machine */
278#define MS_UFROM 0 /* reading Unix from line */
279#define MS_HEADER 1 /* reading message header */
280#define MS_BODY 2 /* reading message body */
281#define MS_DISCARD 3 /* discarding rest of message */
282
283void
284collect(fp, smtpmode, hdrp, e, rsetsize)
285 SM_FILE_T *fp;
286 bool smtpmode;
287 HDR **hdrp;
288 register ENVELOPE *e;
289 bool rsetsize;
290{
291 register SM_FILE_T *volatile df;
292 volatile bool ignrdot;
293 volatile int dbto;
294 register char *volatile bp;
295 volatile int c;
296 volatile bool inputerr;
297 bool headeronly;
298 char *volatile buf;
299 volatile int buflen;
300 volatile int istate;
301 volatile int mstate;
302 volatile int hdrslen;
303 volatile int numhdrs;
304 volatile int afd;
305 unsigned char *volatile pbp;
306 unsigned char peekbuf[8];
307 char bufbuf[MAXLINE];
308
309 df = NULL;
310 ignrdot = smtpmode ? false : IgnrDot;
311 dbto = smtpmode ? (int) TimeOuts.to_datablock : 0;
312 c = SM_IO_EOF;
313 inputerr = false;
314 headeronly = hdrp != NULL;
315 hdrslen = 0;
316 numhdrs = 0;
317 HasEightBits = false;
318 buf = bp = bufbuf;
319 buflen = sizeof bufbuf;
320 pbp = peekbuf;
321 istate = IS_BOL;
322 mstate = SaveFrom ? MS_HEADER : MS_UFROM;
323 CollectProgress = false;
324
325 /*
326 ** Tell ARPANET to go ahead.
327 */
328
329 if (smtpmode)
330 message("354 Enter mail, end with \".\" on a line by itself");
331
332 if (tTd(30, 2))
333 sm_dprintf("collect\n");
334
335 /*
336 ** Read the message.
337 **
338 ** This is done using two interleaved state machines.
339 ** The input state machine is looking for things like
340 ** hidden dots; the message state machine is handling
341 ** the larger picture (e.g., header versus body).
342 */
343
344 if (dbto != 0)
345 {
346 /* handle possible input timeout */
347 if (setjmp(CtxCollectTimeout) != 0)
348 {
349 if (LogLevel > 2)
350 sm_syslog(LOG_NOTICE, e->e_id,
351 "timeout waiting for input from %s during message collect",
352 CURHOSTNAME);
353 errno = 0;
354 if (smtpmode)
355 {
356 /*
357 ** Override e_message in usrerr() as this
358 ** is the reason for failure that should
359 ** be logged for undelivered recipients.
360 */
361
362 e->e_message = NULL;
363 }
364 usrerr("451 4.4.1 timeout waiting for input during message collect");
365 goto readerr;
366 }
367 CollectTimeout = sm_setevent(dbto, collecttimeout, dbto);
368 }
369
370 if (rsetsize)
371 e->e_msgsize = 0;
372 for (;;)
373 {
374 if (tTd(30, 35))
375 sm_dprintf("top, istate=%d, mstate=%d\n", istate,
376 mstate);
377 for (;;)
378 {
379 if (pbp > peekbuf)
380 c = *--pbp;
381 else
382 {
383 while (!sm_io_eof(fp) && !sm_io_error(fp))
384 {
385 errno = 0;
386 c = sm_io_getc(fp, SM_TIME_DEFAULT);
387 if (c == SM_IO_EOF && errno == EINTR)
388 {
389 /* Interrupted, retry */
390 sm_io_clearerr(fp);
391 continue;
392 }
393 break;
394 }
395 CollectProgress = true;
396 if (TrafficLogFile != NULL && !headeronly)
397 {
398 if (istate == IS_BOL)
399 (void) sm_io_fprintf(TrafficLogFile,
400 SM_TIME_DEFAULT,
401 "%05d <<< ",
402 (int) CurrentPid);
403 if (c == SM_IO_EOF)
404 (void) sm_io_fprintf(TrafficLogFile,
405 SM_TIME_DEFAULT,
406 "[EOF]\n");
407 else
408 (void) sm_io_putc(TrafficLogFile,
409 SM_TIME_DEFAULT,
410 c);
411 }
412 if (c == SM_IO_EOF)
413 goto readerr;
414 if (SevenBitInput)
415 c &= 0x7f;
416 else
417 HasEightBits |= bitset(0x80, c);
418 }
419 if (tTd(30, 94))
420 sm_dprintf("istate=%d, c=%c (0x%x)\n",
421 istate, (char) c, c);
422 switch (istate)
423 {
424 case IS_BOL:
425 if (c == '.')
426 {
427 istate = IS_DOT;
428 continue;
429 }
430 break;
431
432 case IS_DOT:
433 if (c == '\n' && !ignrdot &&
434 !bitset(EF_NL_NOT_EOL, e->e_flags))
435 goto readerr;
436 else if (c == '\r' &&
437 !bitset(EF_CRLF_NOT_EOL, e->e_flags))
438 {
439 istate = IS_DOTCR;
440 continue;
441 }
442 else if (ignrdot ||
443 (c != '.' &&
444 OpMode != MD_SMTP &&
445 OpMode != MD_DAEMON &&
446 OpMode != MD_ARPAFTP))
447
448 {
449 SM_ASSERT(pbp < peekbuf + sizeof(peekbuf));
450 *pbp++ = c;
451 c = '.';
452 }
453 break;
454
455 case IS_DOTCR:
456 if (c == '\n' && !ignrdot)
457 goto readerr;
458 else
459 {
460 /* push back the ".\rx" */
461 SM_ASSERT(pbp < peekbuf + sizeof(peekbuf));
462 *pbp++ = c;
463 if (OpMode != MD_SMTP &&
464 OpMode != MD_DAEMON &&
465 OpMode != MD_ARPAFTP)
466 {
467 SM_ASSERT(pbp < peekbuf +
468 sizeof(peekbuf));
469 *pbp++ = '\r';
470 c = '.';
471 }
472 else
473 c = '\r';
474 }
475 break;
476
477 case IS_CR:
478 if (c == '\n')
479 istate = IS_BOL;
480 else
481 {
482 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT,
483 c);
484 c = '\r';
485 istate = IS_NORM;
486 }
487 goto bufferchar;
488 }
489
490 if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags))
491 {
492 istate = IS_CR;
493 continue;
494 }
495 else if (c == '\n' && !bitset(EF_NL_NOT_EOL,
496 e->e_flags))
497 istate = IS_BOL;
498 else
499 istate = IS_NORM;
500
501bufferchar:
502 if (!headeronly)
503 {
504 /* no overflow? */
505 if (e->e_msgsize >= 0)
506 {
507 e->e_msgsize++;
508 if (MaxMessageSize > 0 &&
509 !bitset(EF_TOOBIG, e->e_flags) &&
510 e->e_msgsize > MaxMessageSize)
511 e->e_flags |= EF_TOOBIG;
512 }
513 }
514 switch (mstate)
515 {
516 case MS_BODY:
517 /* just put the character out */
518 if (!bitset(EF_TOOBIG, e->e_flags))
519 (void) sm_io_putc(df, SM_TIME_DEFAULT,
520 c);
521
522 /* FALLTHROUGH */
523
524 case MS_DISCARD:
525 continue;
526 }
527
528 SM_ASSERT(mstate == MS_UFROM || mstate == MS_HEADER);
529
530 /* header -- buffer up */
531 if (bp >= &buf[buflen - 2])
532 {
533 char *obuf;
534
535 /* out of space for header */
536 obuf = buf;
537 if (buflen < MEMCHUNKSIZE)
538 buflen *= 2;
539 else
540 buflen += MEMCHUNKSIZE;
541 buf = xalloc(buflen);
542 memmove(buf, obuf, bp - obuf);
543 bp = &buf[bp - obuf];
544 if (obuf != bufbuf)
545 sm_free(obuf); /* XXX */
546 }
547
548 /*
549 ** XXX Notice: the logic here is broken.
550 ** An input to sendmail that doesn't contain a
551 ** header but starts immediately with the body whose
552 ** first line contain characters which match the
553 ** following "if" will cause problems: those
554 ** characters will NOT appear in the output...
555 ** Do we care?
556 */
557
558 if (c >= 0200 && c <= 0237)
559 {
560#if 0 /* causes complaints -- figure out something for 8.n+1 */
561 usrerr("Illegal character 0x%x in header", c);
562#else /* 0 */
563 /* EMPTY */
564#endif /* 0 */
565 }
566 else if (c != '\0')
567 {
568 *bp++ = c;
569 ++hdrslen;
570 if (!headeronly &&
571 MaxHeadersLength > 0 &&
572 hdrslen > MaxHeadersLength)
573 {
574 sm_syslog(LOG_NOTICE, e->e_id,
575 "headers too large (%d max) from %s during message collect",
576 MaxHeadersLength,
577 CURHOSTNAME);
578 errno = 0;
579 e->e_flags |= EF_CLRQUEUE;
580 e->e_status = "5.6.0";
581 usrerrenh(e->e_status,
582 "552 Headers too large (%d max)",
583 MaxHeadersLength);
584 mstate = MS_DISCARD;
585 }
586 }
587 if (istate == IS_BOL)
588 break;
589 }
590 *bp = '\0';
591
592nextstate:
593 if (tTd(30, 35))
594 sm_dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
595 istate, mstate, buf);
596 switch (mstate)
597 {
598 case MS_UFROM:
599 mstate = MS_HEADER;
600#ifndef NOTUNIX
601 if (strncmp(buf, "From ", 5) == 0)
602 {
603 bp = buf;
604 eatfrom(buf, e);
605 continue;
606 }
607#endif /* ! NOTUNIX */
608 /* FALLTHROUGH */
609
610 case MS_HEADER:
611 if (!isheader(buf))
612 {
613 mstate = MS_BODY;
614 goto nextstate;
615 }
616
617 /* check for possible continuation line */
618 do
619 {
620 sm_io_clearerr(fp);
621 errno = 0;
622 c = sm_io_getc(fp, SM_TIME_DEFAULT);
623 } while (c == SM_IO_EOF && errno == EINTR);
624 if (c != SM_IO_EOF)
625 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c);
626 if (c == ' ' || c == '\t')
627 {
628 /* yep -- defer this */
629 continue;
630 }
631
632 /* trim off trailing CRLF or NL */
633 SM_ASSERT(bp > buf);
634 if (*--bp != '\n' || *--bp != '\r')
635 bp++;
636 *bp = '\0';
637
638 if (bitset(H_EOH, chompheader(buf,
639 CHHDR_CHECK | CHHDR_USER,
640 hdrp, e)))
641 {
642 mstate = MS_BODY;
643 goto nextstate;
644 }
645 numhdrs++;
646 break;
647
648 case MS_BODY:
649 if (tTd(30, 1))
650 sm_dprintf("EOH\n");
651
652 if (headeronly)
653 goto readerr;
654
655 df = collect_eoh(e, numhdrs, hdrslen);
656 if (df == NULL)
657 e->e_flags |= EF_TOOBIG;
658
659 bp = buf;
660
661 /* toss blank line */
662 if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) &&
663 bp[0] == '\r' && bp[1] == '\n') ||
664 (!bitset(EF_NL_NOT_EOL, e->e_flags) &&
665 bp[0] == '\n'))
666 {
667 break;
668 }
669
670 /* if not a blank separator, write it out */
671 if (!bitset(EF_TOOBIG, e->e_flags))
672 {
673 while (*bp != '\0')
674 (void) sm_io_putc(df, SM_TIME_DEFAULT,
675 *bp++);
676 }
677 break;
678 }
679 bp = buf;
680 }
681
682readerr:
683 if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp))
684 {
685 const char *errmsg;
686
687 if (sm_io_eof(fp))
688 errmsg = "unexpected close";
689 else
690 errmsg = sm_errstring(errno);
691 if (tTd(30, 1))
692 sm_dprintf("collect: premature EOM: %s\n", errmsg);
693 if (LogLevel > 1)
694 sm_syslog(LOG_WARNING, e->e_id,
695 "collect: premature EOM: %s", errmsg);
696 inputerr = true;
697 }
698
699 /* reset global timer */
700 if (CollectTimeout != NULL)
701 sm_clrevent(CollectTimeout);
702
703 if (headeronly)
704 return;
705
706 if (mstate != MS_BODY)
707 {
708 /* no body or discard, so we never opened the data file */
709 SM_ASSERT(df == NULL);
710 df = collect_eoh(e, numhdrs, hdrslen);
711 }
712
713 if (df == NULL)
714 {
715 /* skip next few clauses */
716 /* EMPTY */
717 }
718 else if (sm_io_flush(df, SM_TIME_DEFAULT) != 0 || sm_io_error(df))
719 {
720 dferror(df, "sm_io_flush||sm_io_error", e);
721 flush_errors(true);
722 finis(true, true, ExitStat);
723 /* NOTREACHED */
724 }
725 else if (SuperSafe == SAFE_NO ||
726 SuperSafe == SAFE_INTERACTIVE ||
727 (SuperSafe == SAFE_REALLY_POSTMILTER && smtpmode))
728 {
729 /* skip next few clauses */
730 /* EMPTY */
731 /* Note: updfs() is not called in this case! */
731 }
732 else if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL)
733 {
734 int save_errno = errno;
735
736 if (save_errno == EEXIST)
737 {
738 char *dfile;
739 struct stat st;
740 int dfd;
741
742 dfile = queuename(e, DATAFL_LETTER);
743 if (stat(dfile, &st) < 0)
744 st.st_size = -1;
745 errno = EEXIST;
746 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
747 dfile, (long) st.st_size);
748 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
749 if (dfd >= 0)
750 dumpfd(dfd, true, true);
751 }
752 errno = save_errno;
753 dferror(df, "bfcommit", e);
754 flush_errors(true);
755 finis(save_errno != EEXIST, true, ExitStat);
756 }
757 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
758 {
759 dferror(df, "sm_io_getinfo", e);
760 flush_errors(true);
761 finis(true, true, ExitStat);
762 /* NOTREACHED */
763 }
764 else if (fsync(afd) < 0)
765 {
766 dferror(df, "fsync", e);
767 flush_errors(true);
768 finis(true, true, ExitStat);
769 /* NOTREACHED */
770 }
771 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
772 {
773 dferror(df, "sm_io_close", e);
774 flush_errors(true);
775 finis(true, true, ExitStat);
776 /* NOTREACHED */
777 }
778 else
779 {
780 /* everything is happily flushed to disk */
781 df = NULL;
782
783 /* remove from available space in filesystem */
732 }
733 else if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL)
734 {
735 int save_errno = errno;
736
737 if (save_errno == EEXIST)
738 {
739 char *dfile;
740 struct stat st;
741 int dfd;
742
743 dfile = queuename(e, DATAFL_LETTER);
744 if (stat(dfile, &st) < 0)
745 st.st_size = -1;
746 errno = EEXIST;
747 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
748 dfile, (long) st.st_size);
749 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
750 if (dfd >= 0)
751 dumpfd(dfd, true, true);
752 }
753 errno = save_errno;
754 dferror(df, "bfcommit", e);
755 flush_errors(true);
756 finis(save_errno != EEXIST, true, ExitStat);
757 }
758 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
759 {
760 dferror(df, "sm_io_getinfo", e);
761 flush_errors(true);
762 finis(true, true, ExitStat);
763 /* NOTREACHED */
764 }
765 else if (fsync(afd) < 0)
766 {
767 dferror(df, "fsync", e);
768 flush_errors(true);
769 finis(true, true, ExitStat);
770 /* NOTREACHED */
771 }
772 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
773 {
774 dferror(df, "sm_io_close", e);
775 flush_errors(true);
776 finis(true, true, ExitStat);
777 /* NOTREACHED */
778 }
779 else
780 {
781 /* everything is happily flushed to disk */
782 df = NULL;
783
784 /* remove from available space in filesystem */
784 updfs(e, false, true);
785 updfs(e, 0, 1, "collect");
785 }
786
787 /* An EOF when running SMTP is an error */
788 if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
789 {
790 char *host;
791 char *problem;
792 ADDRESS *q;
793
794 host = RealHostName;
795 if (host == NULL)
796 host = "localhost";
797
798 if (sm_io_eof(fp))
799 problem = "unexpected close";
800 else if (sm_io_error(fp))
801 problem = "I/O error";
802 else
803 problem = "read timeout";
804 if (LogLevel > 0 && sm_io_eof(fp))
805 sm_syslog(LOG_NOTICE, e->e_id,
806 "collect: %s on connection from %.100s, sender=%s",
807 problem, host,
808 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
809 if (sm_io_eof(fp))
810 usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
811 problem, host,
812 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
813 else
814 syserr("451 4.4.1 collect: %s on connection from %s, from=%s",
815 problem, host,
816 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
817
818 /* don't return an error indication */
819 e->e_to = NULL;
820 e->e_flags &= ~EF_FATALERRS;
821 e->e_flags |= EF_CLRQUEUE;
822
823 /* Don't send any message notification to sender */
824 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
825 {
826 if (QS_IS_DEAD(q->q_state))
827 continue;
828 q->q_state = QS_FATALERR;
829 }
830
831 finis(true, true, ExitStat);
832 /* NOTREACHED */
833 }
834
835 /* Log collection information. */
836 if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
837 {
838 logsender(e, e->e_msgid);
839 e->e_flags &= ~EF_LOGSENDER;
840 }
841
842 /* check for message too large */
843 if (bitset(EF_TOOBIG, e->e_flags))
844 {
845 e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE;
846 if (!bitset(EF_FATALERRS, e->e_flags))
847 {
848 e->e_status = "5.2.3";
849 usrerrenh(e->e_status,
850 "552 Message exceeds maximum fixed size (%ld)",
851 MaxMessageSize);
852 if (LogLevel > 6)
853 sm_syslog(LOG_NOTICE, e->e_id,
854 "message size (%ld) exceeds maximum (%ld)",
855 e->e_msgsize, MaxMessageSize);
856 }
857 }
858
859 /* check for illegal 8-bit data */
860 if (HasEightBits)
861 {
862 e->e_flags |= EF_HAS8BIT;
863 if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
864 !bitset(EF_IS_MIME, e->e_flags))
865 {
866 e->e_status = "5.6.1";
867 usrerrenh(e->e_status, "554 Eight bit data not allowed");
868 }
869 }
870 else
871 {
872 /* if it claimed to be 8 bits, well, it lied.... */
873 if (e->e_bodytype != NULL &&
874 sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0)
875 e->e_bodytype = "7BIT";
876 }
877
878 if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags))
879 {
880 char *dfname = queuename(e, DATAFL_LETTER);
881 if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
882 SM_IO_RDONLY_B, NULL)) == NULL)
883 {
884 /* we haven't acked receipt yet, so just chuck this */
885 syserr("@Cannot reopen %s", dfname);
886 finis(true, true, ExitStat);
887 /* NOTREACHED */
888 }
889 }
890 else
891 e->e_dfp = df;
892
893 /* collect statistics */
894 if (OpMode != MD_VERIFY)
895 {
896 /*
897 ** Recalculate e_msgpriority, it is done at in eatheader()
898 ** which is called (in 8.12) after the header is collected,
899 ** hence e_msgsize is (most likely) incorrect.
900 */
901
902 e->e_msgpriority = e->e_msgsize
903 - e->e_class * WkClassFact
904 + e->e_nrcpts * WkRecipFact;
905 markstats(e, (ADDRESS *) NULL, STATS_NORMAL);
906 }
907}
908
909static void
910collecttimeout(timeout)
911 int timeout;
912{
913 int save_errno = errno;
914
915 /*
916 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
917 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
918 ** DOING.
919 */
920
921 if (CollectProgress)
922 {
923 /* reset the timeout */
924 CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout,
925 timeout);
926 CollectProgress = false;
927 }
928 else
929 {
930 /* event is done */
931 CollectTimeout = NULL;
932 }
933
934 /* if no progress was made or problem resetting event, die now */
935 if (CollectTimeout == NULL)
936 {
937 errno = ETIMEDOUT;
938 longjmp(CtxCollectTimeout, 1);
939 }
940 errno = save_errno;
941}
942/*
943** DFERROR -- signal error on writing the data file.
944**
945** Called by collect(). Collect() always terminates the process
946** immediately after calling dferror(), which means that the SMTP
947** session will be terminated, which means that any error message
948** issued by dferror must be a 421 error, as per RFC 821.
949**
950** Parameters:
951** df -- the file pointer for the data file.
952** msg -- detailed message.
953** e -- the current envelope.
954**
955** Returns:
956** none.
957**
958** Side Effects:
959** Gives an error message.
960** Arranges for following output to go elsewhere.
961*/
962
963void
964dferror(df, msg, e)
965 SM_FILE_T *volatile df;
966 char *msg;
967 register ENVELOPE *e;
968{
969 char *dfname;
970
971 dfname = queuename(e, DATAFL_LETTER);
972 setstat(EX_IOERR);
973 if (errno == ENOSPC)
974 {
975#if STAT64 > 0
976 struct stat64 st;
977#else /* STAT64 > 0 */
978 struct stat st;
979#endif /* STAT64 > 0 */
980 long avail;
981 long bsize;
982
983 e->e_flags |= EF_NO_BODY_RETN;
984
985 if (
986#if STAT64 > 0
987 fstat64(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
988#else /* STAT64 > 0 */
989 fstat(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
990#endif /* STAT64 > 0 */
991 < 0)
992 st.st_size = 0;
993 (void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname,
994 SM_IO_WRONLY_B, NULL, df);
995 if (st.st_size <= 0)
996 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
997 "\n*** Mail could not be accepted");
998 else
999 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1000 "\n*** Mail of at least %llu bytes could not be accepted\n",
1001 (ULONGLONG_T) st.st_size);
1002 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1003 "*** at %s due to lack of disk space for temp file.\n",
1004 MyHostName);
1005 avail = freediskspace(qid_printqueue(e->e_qgrp, e->e_qdir),
1006 &bsize);
1007 if (avail > 0)
1008 {
1009 if (bsize > 1024)
1010 avail *= bsize / 1024;
1011 else if (bsize < 1024)
1012 avail /= 1024 / bsize;
1013 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1014 "*** Currently, %ld kilobytes are available for mail temp files.\n",
1015 avail);
1016 }
1017#if 0
1018 /* Wrong response code; should be 421. */
1019 e->e_status = "4.3.1";
1020 usrerrenh(e->e_status, "452 Out of disk space for temp file");
1021#else /* 0 */
1022 syserr("421 4.3.1 Out of disk space for temp file");
1023#endif /* 0 */
1024 }
1025 else
1026 syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)",
1027 dfname, msg, (int) geteuid(), (int) getegid());
1028 if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
1029 SM_IO_WRONLY, NULL, df) == NULL)
1030 sm_syslog(LOG_ERR, e->e_id,
1031 "dferror: sm_io_reopen(\"/dev/null\") failed: %s",
1032 sm_errstring(errno));
1033}
1034/*
1035** EATFROM -- chew up a UNIX style from line and process
1036**
1037** This does indeed make some assumptions about the format
1038** of UNIX messages.
1039**
1040** Parameters:
1041** fm -- the from line.
1042** e -- envelope
1043**
1044** Returns:
1045** none.
1046**
1047** Side Effects:
1048** extracts what information it can from the header,
1049** such as the date.
1050*/
1051
1052#ifndef NOTUNIX
1053
1054static char *DowList[] =
1055{
1056 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
1057};
1058
1059static char *MonthList[] =
1060{
1061 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1062 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
1063 NULL
1064};
1065
1066static void
1067eatfrom(fm, e)
1068 char *volatile fm;
1069 register ENVELOPE *e;
1070{
1071 register char *p;
1072 register char **dt;
1073
1074 if (tTd(30, 2))
1075 sm_dprintf("eatfrom(%s)\n", fm);
1076
1077 /* find the date part */
1078 p = fm;
1079 while (*p != '\0')
1080 {
1081 /* skip a word */
1082 while (*p != '\0' && *p != ' ')
1083 p++;
1084 while (*p == ' ')
1085 p++;
1086 if (strlen(p) < 17)
1087 {
1088 /* no room for the date */
1089 return;
1090 }
1091 if (!(isascii(*p) && isupper(*p)) ||
1092 p[3] != ' ' || p[13] != ':' || p[16] != ':')
1093 continue;
1094
1095 /* we have a possible date */
1096 for (dt = DowList; *dt != NULL; dt++)
1097 if (strncmp(*dt, p, 3) == 0)
1098 break;
1099 if (*dt == NULL)
1100 continue;
1101
1102 for (dt = MonthList; *dt != NULL; dt++)
1103 {
1104 if (strncmp(*dt, &p[4], 3) == 0)
1105 break;
1106 }
1107 if (*dt != NULL)
1108 break;
1109 }
1110
1111 if (*p != '\0')
1112 {
1113 char *q, buf[25];
1114
1115 /* we have found a date */
1116 (void) sm_strlcpy(buf, p, sizeof(buf));
1117 q = arpadate(buf);
1118 macdefine(&e->e_macro, A_TEMP, 'a', q);
1119 }
1120}
1121#endif /* ! NOTUNIX */
786 }
787
788 /* An EOF when running SMTP is an error */
789 if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
790 {
791 char *host;
792 char *problem;
793 ADDRESS *q;
794
795 host = RealHostName;
796 if (host == NULL)
797 host = "localhost";
798
799 if (sm_io_eof(fp))
800 problem = "unexpected close";
801 else if (sm_io_error(fp))
802 problem = "I/O error";
803 else
804 problem = "read timeout";
805 if (LogLevel > 0 && sm_io_eof(fp))
806 sm_syslog(LOG_NOTICE, e->e_id,
807 "collect: %s on connection from %.100s, sender=%s",
808 problem, host,
809 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
810 if (sm_io_eof(fp))
811 usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
812 problem, host,
813 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
814 else
815 syserr("451 4.4.1 collect: %s on connection from %s, from=%s",
816 problem, host,
817 shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
818
819 /* don't return an error indication */
820 e->e_to = NULL;
821 e->e_flags &= ~EF_FATALERRS;
822 e->e_flags |= EF_CLRQUEUE;
823
824 /* Don't send any message notification to sender */
825 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
826 {
827 if (QS_IS_DEAD(q->q_state))
828 continue;
829 q->q_state = QS_FATALERR;
830 }
831
832 finis(true, true, ExitStat);
833 /* NOTREACHED */
834 }
835
836 /* Log collection information. */
837 if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
838 {
839 logsender(e, e->e_msgid);
840 e->e_flags &= ~EF_LOGSENDER;
841 }
842
843 /* check for message too large */
844 if (bitset(EF_TOOBIG, e->e_flags))
845 {
846 e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE;
847 if (!bitset(EF_FATALERRS, e->e_flags))
848 {
849 e->e_status = "5.2.3";
850 usrerrenh(e->e_status,
851 "552 Message exceeds maximum fixed size (%ld)",
852 MaxMessageSize);
853 if (LogLevel > 6)
854 sm_syslog(LOG_NOTICE, e->e_id,
855 "message size (%ld) exceeds maximum (%ld)",
856 e->e_msgsize, MaxMessageSize);
857 }
858 }
859
860 /* check for illegal 8-bit data */
861 if (HasEightBits)
862 {
863 e->e_flags |= EF_HAS8BIT;
864 if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
865 !bitset(EF_IS_MIME, e->e_flags))
866 {
867 e->e_status = "5.6.1";
868 usrerrenh(e->e_status, "554 Eight bit data not allowed");
869 }
870 }
871 else
872 {
873 /* if it claimed to be 8 bits, well, it lied.... */
874 if (e->e_bodytype != NULL &&
875 sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0)
876 e->e_bodytype = "7BIT";
877 }
878
879 if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags))
880 {
881 char *dfname = queuename(e, DATAFL_LETTER);
882 if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
883 SM_IO_RDONLY_B, NULL)) == NULL)
884 {
885 /* we haven't acked receipt yet, so just chuck this */
886 syserr("@Cannot reopen %s", dfname);
887 finis(true, true, ExitStat);
888 /* NOTREACHED */
889 }
890 }
891 else
892 e->e_dfp = df;
893
894 /* collect statistics */
895 if (OpMode != MD_VERIFY)
896 {
897 /*
898 ** Recalculate e_msgpriority, it is done at in eatheader()
899 ** which is called (in 8.12) after the header is collected,
900 ** hence e_msgsize is (most likely) incorrect.
901 */
902
903 e->e_msgpriority = e->e_msgsize
904 - e->e_class * WkClassFact
905 + e->e_nrcpts * WkRecipFact;
906 markstats(e, (ADDRESS *) NULL, STATS_NORMAL);
907 }
908}
909
910static void
911collecttimeout(timeout)
912 int timeout;
913{
914 int save_errno = errno;
915
916 /*
917 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
918 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
919 ** DOING.
920 */
921
922 if (CollectProgress)
923 {
924 /* reset the timeout */
925 CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout,
926 timeout);
927 CollectProgress = false;
928 }
929 else
930 {
931 /* event is done */
932 CollectTimeout = NULL;
933 }
934
935 /* if no progress was made or problem resetting event, die now */
936 if (CollectTimeout == NULL)
937 {
938 errno = ETIMEDOUT;
939 longjmp(CtxCollectTimeout, 1);
940 }
941 errno = save_errno;
942}
943/*
944** DFERROR -- signal error on writing the data file.
945**
946** Called by collect(). Collect() always terminates the process
947** immediately after calling dferror(), which means that the SMTP
948** session will be terminated, which means that any error message
949** issued by dferror must be a 421 error, as per RFC 821.
950**
951** Parameters:
952** df -- the file pointer for the data file.
953** msg -- detailed message.
954** e -- the current envelope.
955**
956** Returns:
957** none.
958**
959** Side Effects:
960** Gives an error message.
961** Arranges for following output to go elsewhere.
962*/
963
964void
965dferror(df, msg, e)
966 SM_FILE_T *volatile df;
967 char *msg;
968 register ENVELOPE *e;
969{
970 char *dfname;
971
972 dfname = queuename(e, DATAFL_LETTER);
973 setstat(EX_IOERR);
974 if (errno == ENOSPC)
975 {
976#if STAT64 > 0
977 struct stat64 st;
978#else /* STAT64 > 0 */
979 struct stat st;
980#endif /* STAT64 > 0 */
981 long avail;
982 long bsize;
983
984 e->e_flags |= EF_NO_BODY_RETN;
985
986 if (
987#if STAT64 > 0
988 fstat64(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
989#else /* STAT64 > 0 */
990 fstat(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
991#endif /* STAT64 > 0 */
992 < 0)
993 st.st_size = 0;
994 (void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname,
995 SM_IO_WRONLY_B, NULL, df);
996 if (st.st_size <= 0)
997 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
998 "\n*** Mail could not be accepted");
999 else
1000 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1001 "\n*** Mail of at least %llu bytes could not be accepted\n",
1002 (ULONGLONG_T) st.st_size);
1003 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1004 "*** at %s due to lack of disk space for temp file.\n",
1005 MyHostName);
1006 avail = freediskspace(qid_printqueue(e->e_qgrp, e->e_qdir),
1007 &bsize);
1008 if (avail > 0)
1009 {
1010 if (bsize > 1024)
1011 avail *= bsize / 1024;
1012 else if (bsize < 1024)
1013 avail /= 1024 / bsize;
1014 (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
1015 "*** Currently, %ld kilobytes are available for mail temp files.\n",
1016 avail);
1017 }
1018#if 0
1019 /* Wrong response code; should be 421. */
1020 e->e_status = "4.3.1";
1021 usrerrenh(e->e_status, "452 Out of disk space for temp file");
1022#else /* 0 */
1023 syserr("421 4.3.1 Out of disk space for temp file");
1024#endif /* 0 */
1025 }
1026 else
1027 syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)",
1028 dfname, msg, (int) geteuid(), (int) getegid());
1029 if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
1030 SM_IO_WRONLY, NULL, df) == NULL)
1031 sm_syslog(LOG_ERR, e->e_id,
1032 "dferror: sm_io_reopen(\"/dev/null\") failed: %s",
1033 sm_errstring(errno));
1034}
1035/*
1036** EATFROM -- chew up a UNIX style from line and process
1037**
1038** This does indeed make some assumptions about the format
1039** of UNIX messages.
1040**
1041** Parameters:
1042** fm -- the from line.
1043** e -- envelope
1044**
1045** Returns:
1046** none.
1047**
1048** Side Effects:
1049** extracts what information it can from the header,
1050** such as the date.
1051*/
1052
1053#ifndef NOTUNIX
1054
1055static char *DowList[] =
1056{
1057 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
1058};
1059
1060static char *MonthList[] =
1061{
1062 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1063 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
1064 NULL
1065};
1066
1067static void
1068eatfrom(fm, e)
1069 char *volatile fm;
1070 register ENVELOPE *e;
1071{
1072 register char *p;
1073 register char **dt;
1074
1075 if (tTd(30, 2))
1076 sm_dprintf("eatfrom(%s)\n", fm);
1077
1078 /* find the date part */
1079 p = fm;
1080 while (*p != '\0')
1081 {
1082 /* skip a word */
1083 while (*p != '\0' && *p != ' ')
1084 p++;
1085 while (*p == ' ')
1086 p++;
1087 if (strlen(p) < 17)
1088 {
1089 /* no room for the date */
1090 return;
1091 }
1092 if (!(isascii(*p) && isupper(*p)) ||
1093 p[3] != ' ' || p[13] != ':' || p[16] != ':')
1094 continue;
1095
1096 /* we have a possible date */
1097 for (dt = DowList; *dt != NULL; dt++)
1098 if (strncmp(*dt, p, 3) == 0)
1099 break;
1100 if (*dt == NULL)
1101 continue;
1102
1103 for (dt = MonthList; *dt != NULL; dt++)
1104 {
1105 if (strncmp(*dt, &p[4], 3) == 0)
1106 break;
1107 }
1108 if (*dt != NULL)
1109 break;
1110 }
1111
1112 if (*p != '\0')
1113 {
1114 char *q, buf[25];
1115
1116 /* we have found a date */
1117 (void) sm_strlcpy(buf, p, sizeof(buf));
1118 q = arpadate(buf);
1119 macdefine(&e->e_macro, A_TEMP, 'a', q);
1120 }
1121}
1122#endif /* ! NOTUNIX */