usersmtp.c revision 43730
1/*
2 * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4 * Copyright (c) 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13# include "sendmail.h"
14
15#ifndef lint
16#if SMTP
17static char sccsid[] = "@(#)usersmtp.c	8.111 (Berkeley) 2/3/1999 (with SMTP)";
18#else
19static char sccsid[] = "@(#)usersmtp.c	8.111 (Berkeley) 2/3/1999 (without SMTP)";
20#endif
21#endif /* not lint */
22
23# include <sysexits.h>
24# include <errno.h>
25
26# if SMTP
27
28/*
29**  USERSMTP -- run SMTP protocol from the user end.
30**
31**	This protocol is described in RFC821.
32*/
33
34#define REPLYTYPE(r)	((r) / 100)		/* first digit of reply code */
35#define REPLYCLASS(r)	(((r) / 10) % 10)	/* second digit of reply code */
36#define SMTPCLOSING	421			/* "Service Shutting Down" */
37
38char	SmtpMsgBuffer[MAXLINE];		/* buffer for commands */
39char	SmtpReplyBuffer[MAXLINE];	/* buffer for replies */
40char	SmtpError[MAXLINE] = "";	/* save failure error messages */
41bool	SmtpNeedIntro;			/* need "while talking" in transcript */
42
43extern void	smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
44extern int	reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));
45/*
46**  SMTPINIT -- initialize SMTP.
47**
48**	Opens the connection and sends the initial protocol.
49**
50**	Parameters:
51**		m -- mailer to create connection to.
52**		pvp -- pointer to parameter vector to pass to
53**			the mailer.
54**
55**	Returns:
56**		none.
57**
58**	Side Effects:
59**		creates connection and sends initial protocol.
60*/
61
62void
63smtpinit(m, mci, e)
64	MAILER *m;
65	register MCI *mci;
66	ENVELOPE *e;
67{
68	register int r;
69	register char *p;
70	extern void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
71	extern void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
72
73	if (tTd(18, 1))
74	{
75		printf("smtpinit ");
76		mci_dump(mci, FALSE);
77	}
78
79	/*
80	**  Open the connection to the mailer.
81	*/
82
83	SmtpError[0] = '\0';
84	CurHostName = mci->mci_host;		/* XXX UGLY XXX */
85	if (CurHostName == NULL)
86		CurHostName = MyHostName;
87	SmtpNeedIntro = TRUE;
88	switch (mci->mci_state)
89	{
90	  case MCIS_ACTIVE:
91		/* need to clear old information */
92		smtprset(m, mci, e);
93		/* fall through */
94
95	  case MCIS_OPEN:
96		return;
97
98	  case MCIS_ERROR:
99	  case MCIS_SSD:
100		/* shouldn't happen */
101		smtpquit(m, mci, e);
102		/* fall through */
103
104	  case MCIS_CLOSED:
105		syserr("451 smtpinit: state CLOSED");
106		return;
107
108	  case MCIS_OPENING:
109		break;
110	}
111
112	mci->mci_state = MCIS_OPENING;
113
114	/*
115	**  Get the greeting message.
116	**	This should appear spontaneously.  Give it five minutes to
117	**	happen.
118	*/
119
120	SmtpPhase = mci->mci_phase = "client greeting";
121	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
122	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
123	if (r < 0)
124		goto tempfail1;
125	if (REPLYTYPE(r) == 4)
126		goto tempfail2;
127	if (REPLYTYPE(r) != 2)
128		goto unavailable;
129
130	/*
131	**  Send the HELO command.
132	**	My mother taught me to always introduce myself.
133	*/
134
135	if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
136		mci->mci_flags |= MCIF_ESMTP;
137
138tryhelo:
139	if (bitnset(M_LMTP, m->m_flags))
140	{
141		smtpmessage("LHLO %s", m, mci, MyHostName);
142		SmtpPhase = mci->mci_phase = "client LHLO";
143	}
144	else if (bitset(MCIF_ESMTP, mci->mci_flags))
145	{
146		smtpmessage("EHLO %s", m, mci, MyHostName);
147		SmtpPhase = mci->mci_phase = "client EHLO";
148	}
149	else
150	{
151		smtpmessage("HELO %s", m, mci, MyHostName);
152		SmtpPhase = mci->mci_phase = "client HELO";
153	}
154	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
155	r = reply(m, mci, e, TimeOuts.to_helo, helo_options);
156	if (r < 0)
157		goto tempfail1;
158	else if (REPLYTYPE(r) == 5)
159	{
160		if (bitset(MCIF_ESMTP, mci->mci_flags) &&
161		    !bitnset(M_LMTP, m->m_flags))
162		{
163			/* try old SMTP instead */
164			mci->mci_flags &= ~MCIF_ESMTP;
165			goto tryhelo;
166		}
167		goto unavailable;
168	}
169	else if (REPLYTYPE(r) != 2)
170		goto tempfail2;
171
172	/*
173	**  Check to see if we actually ended up talking to ourself.
174	**  This means we didn't know about an alias or MX, or we managed
175	**  to connect to an echo server.
176	*/
177
178	p = strchr(&SmtpReplyBuffer[4], ' ');
179	if (p != NULL)
180		*p = '\0';
181	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
182	    !bitnset(M_LMTP, m->m_flags) &&
183	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
184	{
185		syserr("553 %s config error: mail loops back to me (MX problem?)",
186			CurHostName);
187		mci_setstat(mci, EX_CONFIG, NULL, NULL);
188		mci->mci_errno = 0;
189		smtpquit(m, mci, e);
190		return;
191	}
192
193	/*
194	**  If this is expected to be another sendmail, send some internal
195	**  commands.
196	*/
197
198	if (bitnset(M_INTERNAL, m->m_flags))
199	{
200		/* tell it to be verbose */
201		smtpmessage("VERB", m, mci);
202		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
203		if (r < 0)
204			goto tempfail1;
205	}
206
207	if (mci->mci_state != MCIS_CLOSED)
208	{
209		mci->mci_state = MCIS_OPEN;
210		return;
211	}
212
213	/* got a 421 error code during startup */
214
215  tempfail1:
216	if (mci->mci_errno == 0)
217		mci->mci_errno = errno;
218	mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
219	if (mci->mci_state != MCIS_CLOSED)
220		smtpquit(m, mci, e);
221	return;
222
223  tempfail2:
224	if (mci->mci_errno == 0)
225		mci->mci_errno = errno;
226	/* XXX should use code from other end iff ENHANCEDSTATUSCODES */
227	mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
228	if (mci->mci_state != MCIS_CLOSED)
229		smtpquit(m, mci, e);
230	return;
231
232  unavailable:
233	mci->mci_errno = errno;
234	mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
235	smtpquit(m, mci, e);
236	return;
237}
238/*
239**  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
240**
241**	Parameters:
242**		line -- the response line.
243**		firstline -- set if this is the first line of the reply.
244**		m -- the mailer.
245**		mci -- the mailer connection info.
246**		e -- the envelope.
247**
248**	Returns:
249**		none.
250*/
251
252void
253esmtp_check(line, firstline, m, mci, e)
254	char *line;
255	bool firstline;
256	MAILER *m;
257	register MCI *mci;
258	ENVELOPE *e;
259{
260	if (strstr(line, "ESMTP") != NULL)
261		mci->mci_flags |= MCIF_ESMTP;
262	if (strstr(line, "8BIT-OK") != NULL)
263		mci->mci_flags |= MCIF_8BITOK;
264}
265/*
266**  HELO_OPTIONS -- process the options on a HELO line.
267**
268**	Parameters:
269**		line -- the response line.
270**		firstline -- set if this is the first line of the reply.
271**		m -- the mailer.
272**		mci -- the mailer connection info.
273**		e -- the envelope.
274**
275**	Returns:
276**		none.
277*/
278
279void
280helo_options(line, firstline, m, mci, e)
281	char *line;
282	bool firstline;
283	MAILER *m;
284	register MCI *mci;
285	ENVELOPE *e;
286{
287	register char *p;
288
289	if (firstline)
290		return;
291
292	if (strlen(line) < (SIZE_T) 5)
293		return;
294	line += 4;
295	p = strchr(line, ' ');
296	if (p != NULL)
297		*p++ = '\0';
298	if (strcasecmp(line, "size") == 0)
299	{
300		mci->mci_flags |= MCIF_SIZE;
301		if (p != NULL)
302			mci->mci_maxsize = atol(p);
303	}
304	else if (strcasecmp(line, "8bitmime") == 0)
305	{
306		mci->mci_flags |= MCIF_8BITMIME;
307		mci->mci_flags &= ~MCIF_7BIT;
308	}
309	else if (strcasecmp(line, "expn") == 0)
310		mci->mci_flags |= MCIF_EXPN;
311	else if (strcasecmp(line, "dsn") == 0)
312		mci->mci_flags |= MCIF_DSN;
313}
314/*
315**  SMTPMAILFROM -- send MAIL command
316**
317**	Parameters:
318**		m -- the mailer.
319**		mci -- the mailer connection structure.
320**		e -- the envelope (including the sender to specify).
321*/
322
323int
324smtpmailfrom(m, mci, e)
325	MAILER *m;
326	MCI *mci;
327	ENVELOPE *e;
328{
329	int r;
330	char *bufp;
331	char *bodytype;
332	char buf[MAXNAME + 1];
333	char optbuf[MAXLINE];
334
335	if (tTd(18, 2))
336		printf("smtpmailfrom: CurHost=%s\n", CurHostName);
337
338	/* set up appropriate options to include */
339	bufp = optbuf;
340	if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
341		snprintf(optbuf, sizeof optbuf, " SIZE=%ld", e->e_msgsize);
342	else
343		strcpy(optbuf, "");
344	bufp = &optbuf[strlen(optbuf)];
345
346	bodytype = e->e_bodytype;
347	if (bitset(MCIF_8BITMIME, mci->mci_flags))
348	{
349		if (bodytype == NULL &&
350		    bitset(MM_MIME8BIT, MimeMode) &&
351		    bitset(EF_HAS8BIT, e->e_flags) &&
352		    !bitset(EF_DONT_MIME, e->e_flags) &&
353		    !bitnset(M_8BITS, m->m_flags))
354			bodytype = "8BITMIME";
355		if (bodytype != NULL &&
356		    SPACELEFT(optbuf, bufp) > strlen(bodytype) + 7)
357		{
358			snprintf(bufp, SPACELEFT(optbuf, bufp),
359				 " BODY=%s", bodytype);
360			bufp += strlen(bufp);
361		}
362	}
363	else if (bitnset(M_8BITS, m->m_flags) ||
364		 !bitset(EF_HAS8BIT, e->e_flags) ||
365		 bitset(MCIF_8BITOK, mci->mci_flags))
366	{
367		/* just pass it through */
368	}
369#if MIME8TO7
370	else if (bitset(MM_CVTMIME, MimeMode) &&
371		 !bitset(EF_DONT_MIME, e->e_flags) &&
372		 (!bitset(MM_PASS8BIT, MimeMode) ||
373		  bitset(EF_IS_MIME, e->e_flags)))
374	{
375		/* must convert from 8bit MIME format to 7bit encoded */
376		mci->mci_flags |= MCIF_CVT8TO7;
377	}
378#endif
379	else if (!bitset(MM_PASS8BIT, MimeMode))
380	{
381		/* cannot just send a 8-bit version */
382		extern char MsgBuf[];
383
384		usrerr("%s does not support 8BITMIME", CurHostName);
385		mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf);
386		return EX_DATAERR;
387	}
388
389	if (bitset(MCIF_DSN, mci->mci_flags))
390	{
391		if (e->e_envid != NULL &&
392		    SPACELEFT(optbuf, bufp) > strlen(e->e_envid) + 7)
393		{
394			snprintf(bufp, SPACELEFT(optbuf, bufp),
395				 " ENVID=%s", e->e_envid);
396			bufp += strlen(bufp);
397		}
398
399		/* RET= parameter */
400		if (bitset(EF_RET_PARAM, e->e_flags) &&
401		    SPACELEFT(optbuf, bufp) > 9)
402		{
403			snprintf(bufp, SPACELEFT(optbuf, bufp),
404				 " RET=%s",
405				 bitset(EF_NO_BODY_RETN, e->e_flags) ?
406					"HDRS" : "FULL");
407			bufp += strlen(bufp);
408		}
409	}
410
411	/*
412	**  Send the MAIL command.
413	**	Designates the sender.
414	*/
415
416	mci->mci_state = MCIS_ACTIVE;
417
418	if (bitset(EF_RESPONSE, e->e_flags) &&
419	    !bitnset(M_NO_NULL_FROM, m->m_flags))
420		(void) strcpy(buf, "");
421	else
422		expand("\201g", buf, sizeof buf, e);
423	if (buf[0] == '<')
424	{
425		/* strip off <angle brackets> (put back on below) */
426		bufp = &buf[strlen(buf) - 1];
427		if (*bufp == '>')
428			*bufp = '\0';
429		bufp = &buf[1];
430	}
431	else
432		bufp = buf;
433	if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) ||
434	    !bitnset(M_FROMPATH, m->m_flags))
435	{
436		smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
437	}
438	else
439	{
440		smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
441			*bufp == '@' ? ',' : ':', bufp, optbuf);
442	}
443	SmtpPhase = mci->mci_phase = "client MAIL";
444	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
445	r = reply(m, mci, e, TimeOuts.to_mail, NULL);
446	if (r < 0)
447	{
448		/* communications failure */
449		mci->mci_errno = errno;
450		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
451		smtpquit(m, mci, e);
452		return EX_TEMPFAIL;
453	}
454	else if (r == 421)
455	{
456		/* service shutting down */
457		mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
458		smtpquit(m, mci, e);
459		return EX_TEMPFAIL;
460	}
461	else if (REPLYTYPE(r) == 4)
462	{
463		mci_setstat(mci, EX_NOTSTICKY, smtptodsn(r), SmtpReplyBuffer);
464		return EX_TEMPFAIL;
465	}
466	else if (REPLYTYPE(r) == 2)
467	{
468		return EX_OK;
469	}
470	else if (r == 501)
471	{
472		/* syntax error in arguments */
473		mci_setstat(mci, EX_NOTSTICKY, "5.5.2", SmtpReplyBuffer);
474		return EX_DATAERR;
475	}
476	else if (r == 553)
477	{
478		/* mailbox name not allowed */
479		mci_setstat(mci, EX_NOTSTICKY, "5.1.3", SmtpReplyBuffer);
480		return EX_DATAERR;
481	}
482	else if (r == 552)
483	{
484		/* exceeded storage allocation */
485		mci_setstat(mci, EX_NOTSTICKY, "5.3.4", SmtpReplyBuffer);
486		if (bitset(MCIF_SIZE, mci->mci_flags))
487			e->e_flags |= EF_NO_BODY_RETN;
488		return EX_UNAVAILABLE;
489	}
490	else if (REPLYTYPE(r) == 5)
491	{
492		/* unknown error */
493		mci_setstat(mci, EX_NOTSTICKY, "5.0.0", SmtpReplyBuffer);
494		return EX_UNAVAILABLE;
495	}
496
497	if (LogLevel > 1)
498	{
499		sm_syslog(LOG_CRIT, e->e_id,
500			"%.100s: SMTP MAIL protocol error: %s",
501			CurHostName,
502			shortenstring(SmtpReplyBuffer, 403));
503	}
504
505	/* protocol error -- close up */
506	mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
507	smtpquit(m, mci, e);
508	return EX_PROTOCOL;
509}
510/*
511**  SMTPRCPT -- designate recipient.
512**
513**	Parameters:
514**		to -- address of recipient.
515**		m -- the mailer we are sending to.
516**		mci -- the connection info for this transaction.
517**		e -- the envelope for this transaction.
518**
519**	Returns:
520**		exit status corresponding to recipient status.
521**
522**	Side Effects:
523**		Sends the mail via SMTP.
524*/
525
526int
527smtprcpt(to, m, mci, e)
528	ADDRESS *to;
529	register MAILER *m;
530	MCI *mci;
531	ENVELOPE *e;
532{
533	register int r;
534	char *bufp;
535	char optbuf[MAXLINE];
536
537	strcpy(optbuf, "");
538	bufp = &optbuf[strlen(optbuf)];
539	if (bitset(MCIF_DSN, mci->mci_flags))
540	{
541		/* NOTIFY= parameter */
542		if (bitset(QHASNOTIFY, to->q_flags) &&
543		    bitset(QPRIMARY, to->q_flags) &&
544		    !bitnset(M_LOCALMAILER, m->m_flags))
545		{
546			bool firstone = TRUE;
547
548			strcat(bufp, " NOTIFY=");
549			if (bitset(QPINGONSUCCESS, to->q_flags))
550			{
551				strcat(bufp, "SUCCESS");
552				firstone = FALSE;
553			}
554			if (bitset(QPINGONFAILURE, to->q_flags))
555			{
556				if (!firstone)
557					strcat(bufp, ",");
558				strcat(bufp, "FAILURE");
559				firstone = FALSE;
560			}
561			if (bitset(QPINGONDELAY, to->q_flags))
562			{
563				if (!firstone)
564					strcat(bufp, ",");
565				strcat(bufp, "DELAY");
566				firstone = FALSE;
567			}
568			if (firstone)
569				strcat(bufp, "NEVER");
570			bufp += strlen(bufp);
571		}
572
573		/* ORCPT= parameter */
574		if (to->q_orcpt != NULL &&
575		    SPACELEFT(optbuf, bufp) > strlen(to->q_orcpt) + 7)
576		{
577			snprintf(bufp, SPACELEFT(optbuf, bufp),
578				 " ORCPT=%s", to->q_orcpt);
579			bufp += strlen(bufp);
580		}
581	}
582
583	smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
584
585	SmtpPhase = mci->mci_phase = "client RCPT";
586	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
587	r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
588	to->q_rstatus = newstr(SmtpReplyBuffer);
589	to->q_status = smtptodsn(r);
590	to->q_statmta = mci->mci_host;
591	if (r < 0 || REPLYTYPE(r) == 4)
592		return EX_TEMPFAIL;
593	else if (REPLYTYPE(r) == 2)
594		return EX_OK;
595	else if (r == 550)
596	{
597		to->q_status = "5.1.1";
598		return EX_NOUSER;
599	}
600	else if (r == 551)
601	{
602		to->q_status = "5.1.6";
603		return EX_NOUSER;
604	}
605	else if (r == 553)
606	{
607		to->q_status = "5.1.3";
608		return EX_NOUSER;
609	}
610	else if (REPLYTYPE(r) == 5)
611	{
612		return EX_UNAVAILABLE;
613	}
614
615	if (LogLevel > 1)
616	{
617		sm_syslog(LOG_CRIT, e->e_id,
618			"%.100s: SMTP RCPT protocol error: %s",
619			CurHostName,
620			shortenstring(SmtpReplyBuffer, 403));
621	}
622
623	mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
624	return EX_PROTOCOL;
625}
626/*
627**  SMTPDATA -- send the data and clean up the transaction.
628**
629**	Parameters:
630**		m -- mailer being sent to.
631**		mci -- the mailer connection information.
632**		e -- the envelope for this message.
633**
634**	Returns:
635**		exit status corresponding to DATA command.
636**
637**	Side Effects:
638**		none.
639*/
640
641static jmp_buf	CtxDataTimeout;
642static void	datatimeout __P((void));
643
644int
645smtpdata(m, mci, e)
646	MAILER *m;
647	register MCI *mci;
648	register ENVELOPE *e;
649{
650	register int r;
651	register EVENT *ev;
652	int rstat;
653	int xstat;
654	time_t timeout;
655
656	/*
657	**  Send the data.
658	**	First send the command and check that it is ok.
659	**	Then send the data.
660	**	Follow it up with a dot to terminate.
661	**	Finally get the results of the transaction.
662	*/
663
664	/* send the command and check ok to proceed */
665	smtpmessage("DATA", m, mci);
666	SmtpPhase = mci->mci_phase = "client DATA 354";
667	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
668	r = reply(m, mci, e, TimeOuts.to_datainit, NULL);
669	if (r < 0 || REPLYTYPE(r) == 4)
670	{
671		smtpquit(m, mci, e);
672		return EX_TEMPFAIL;
673	}
674	else if (REPLYTYPE(r) == 5)
675	{
676		smtprset(m, mci, e);
677		return EX_UNAVAILABLE;
678	}
679	else if (REPLYTYPE(r) != 3)
680	{
681		if (LogLevel > 1)
682		{
683			sm_syslog(LOG_CRIT, e->e_id,
684				"%.100s: SMTP DATA-1 protocol error: %s",
685				CurHostName,
686				shortenstring(SmtpReplyBuffer, 403));
687		}
688		smtprset(m, mci, e);
689		mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
690		return (EX_PROTOCOL);
691	}
692
693	/*
694	**  Set timeout around data writes.  Make it at least large
695	**  enough for DNS timeouts on all recipients plus some fudge
696	**  factor.  The main thing is that it should not be infinite.
697	*/
698
699	if (setjmp(CtxDataTimeout) != 0)
700	{
701		mci->mci_errno = errno;
702		mci->mci_state = MCIS_ERROR;
703		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
704		syserr("451 timeout writing message to %s", CurHostName);
705		smtpquit(m, mci, e);
706		return EX_TEMPFAIL;
707	}
708
709	timeout = e->e_msgsize / 16;
710	if (timeout < (time_t) 600)
711		timeout = (time_t) 600;
712	timeout += e->e_nrcpts * 300;
713	ev = setevent(timeout, datatimeout, 0);
714
715	/*
716	**  Output the actual message.
717	*/
718
719	(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
720	(*e->e_putbody)(mci, e, NULL);
721
722	/*
723	**  Cleanup after sending message.
724	*/
725
726	clrevent(ev);
727
728	if (ferror(mci->mci_out))
729	{
730		/* error during processing -- don't send the dot */
731		mci->mci_errno = EIO;
732		mci->mci_state = MCIS_ERROR;
733		mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
734		smtpquit(m, mci, e);
735		return EX_IOERR;
736	}
737
738	/* terminate the message */
739	fprintf(mci->mci_out, ".%s", m->m_eol);
740	if (TrafficLogFile != NULL)
741		fprintf(TrafficLogFile, "%05d >>> .\n", (int) getpid());
742	if (Verbose)
743		nmessage(">>> .");
744
745	/* check for the results of the transaction */
746	SmtpPhase = mci->mci_phase = "client DATA status";
747	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
748	if (bitnset(M_LMTP, m->m_flags))
749		return EX_OK;
750	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
751	if (r < 0)
752	{
753		smtpquit(m, mci, e);
754		return EX_TEMPFAIL;
755	}
756	mci->mci_state = MCIS_OPEN;
757	xstat = EX_NOTSTICKY;
758	if (r == 452)
759		rstat = EX_TEMPFAIL;
760	else if (REPLYTYPE(r) == 4)
761		rstat = xstat = EX_TEMPFAIL;
762	else if (REPLYCLASS(r) != 5)
763		rstat = xstat = EX_PROTOCOL;
764	else if (REPLYTYPE(r) == 2)
765		rstat = xstat = EX_OK;
766	else if (REPLYTYPE(r) == 5)
767		rstat = EX_UNAVAILABLE;
768	else
769		rstat = EX_PROTOCOL;
770	mci_setstat(mci, xstat, smtptodsn(r), SmtpReplyBuffer);
771	if (e->e_statmsg != NULL)
772		free(e->e_statmsg);
773	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
774	if (rstat != EX_PROTOCOL)
775		return rstat;
776	if (LogLevel > 1)
777	{
778		sm_syslog(LOG_CRIT, e->e_id,
779			"%.100s: SMTP DATA-2 protocol error: %s",
780			CurHostName,
781			shortenstring(SmtpReplyBuffer, 403));
782	}
783	return rstat;
784}
785
786
787static void
788datatimeout()
789{
790	longjmp(CtxDataTimeout, 1);
791}
792/*
793**  SMTPGETSTAT -- get status code from DATA in LMTP
794**
795**	Parameters:
796**		m -- the mailer to which we are sending the message.
797**		mci -- the mailer connection structure.
798**		e -- the current envelope.
799**
800**	Returns:
801**		The exit status corresponding to the reply code.
802*/
803
804int
805smtpgetstat(m, mci, e)
806	MAILER *m;
807	MCI *mci;
808	ENVELOPE *e;
809{
810	int r;
811	int stat;
812
813	/* check for the results of the transaction */
814	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
815	if (r < 0)
816	{
817		smtpquit(m, mci, e);
818		return EX_TEMPFAIL;
819	}
820	if (e->e_statmsg != NULL)
821		free(e->e_statmsg);
822	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
823	if (REPLYTYPE(r) == 4)
824		stat = EX_TEMPFAIL;
825	else if (REPLYCLASS(r) != 5)
826		stat = EX_PROTOCOL;
827	else if (REPLYTYPE(r) == 2)
828		stat = EX_OK;
829	else if (REPLYTYPE(r) == 5)
830		stat = EX_UNAVAILABLE;
831	else
832		stat = EX_PROTOCOL;
833	mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
834	if (LogLevel > 1 && stat == EX_PROTOCOL)
835	{
836		sm_syslog(LOG_CRIT, e->e_id,
837			"%.100s: SMTP DATA-3 protocol error: %s",
838			CurHostName,
839			shortenstring(SmtpReplyBuffer, 403));
840	}
841	return stat;
842}
843/*
844**  SMTPQUIT -- close the SMTP connection.
845**
846**	Parameters:
847**		m -- a pointer to the mailer.
848**		mci -- the mailer connection information.
849**		e -- the current envelope.
850**
851**	Returns:
852**		none.
853**
854**	Side Effects:
855**		sends the final protocol and closes the connection.
856*/
857
858void
859smtpquit(m, mci, e)
860	register MAILER *m;
861	register MCI *mci;
862	ENVELOPE *e;
863{
864	bool oldSuprErrs = SuprErrs;
865
866	/*
867	**	Suppress errors here -- we may be processing a different
868	**	job when we do the quit connection, and we don't want the
869	**	new job to be penalized for something that isn't it's
870	**	problem.
871	*/
872
873	SuprErrs = TRUE;
874
875	/* send the quit message if we haven't gotten I/O error */
876	if (mci->mci_state != MCIS_ERROR)
877	{
878		SmtpPhase = "client QUIT";
879		smtpmessage("QUIT", m, mci);
880		(void) reply(m, mci, e, TimeOuts.to_quit, NULL);
881		SuprErrs = oldSuprErrs;
882		if (mci->mci_state == MCIS_CLOSED)
883			return;
884	}
885
886	/* now actually close the connection and pick up the zombie */
887	(void) endmailer(mci, e, NULL);
888
889	SuprErrs = oldSuprErrs;
890}
891/*
892**  SMTPRSET -- send a RSET (reset) command
893*/
894
895void
896smtprset(m, mci, e)
897	register MAILER *m;
898	register MCI *mci;
899	ENVELOPE *e;
900{
901	int r;
902
903	SmtpPhase = "client RSET";
904	smtpmessage("RSET", m, mci);
905	r = reply(m, mci, e, TimeOuts.to_rset, NULL);
906	if (r < 0)
907		mci->mci_state = MCIS_ERROR;
908	else if (REPLYTYPE(r) == 2)
909	{
910		mci->mci_state = MCIS_OPEN;
911		return;
912	}
913	smtpquit(m, mci, e);
914}
915/*
916**  SMTPPROBE -- check the connection state
917*/
918
919int
920smtpprobe(mci)
921	register MCI *mci;
922{
923	int r;
924	MAILER *m = mci->mci_mailer;
925	extern ENVELOPE BlankEnvelope;
926	ENVELOPE *e = &BlankEnvelope;
927
928	SmtpPhase = "client probe";
929	smtpmessage("RSET", m, mci);
930	r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
931	if (r < 0 || REPLYTYPE(r) != 2)
932		smtpquit(m, mci, e);
933	return r;
934}
935/*
936**  REPLY -- read arpanet reply
937**
938**	Parameters:
939**		m -- the mailer we are reading the reply from.
940**		mci -- the mailer connection info structure.
941**		e -- the current envelope.
942**		timeout -- the timeout for reads.
943**		pfunc -- processing function called on each line of response.
944**			If null, no special processing is done.
945**
946**	Returns:
947**		reply code it reads.
948**
949**	Side Effects:
950**		flushes the mail file.
951*/
952
953int
954reply(m, mci, e, timeout, pfunc)
955	MAILER *m;
956	MCI *mci;
957	ENVELOPE *e;
958	time_t timeout;
959	void (*pfunc)();
960{
961	register char *bufp;
962	register int r;
963	bool firstline = TRUE;
964	char junkbuf[MAXLINE];
965
966	if (mci->mci_out != NULL)
967		(void) fflush(mci->mci_out);
968
969	if (tTd(18, 1))
970		printf("reply\n");
971
972	/*
973	**  Read the input line, being careful not to hang.
974	*/
975
976	bufp = SmtpReplyBuffer;
977	for (;;)
978	{
979		register char *p;
980
981		/* actually do the read */
982		if (e->e_xfp != NULL)
983			(void) fflush(e->e_xfp);	/* for debugging */
984
985		/* if we are in the process of closing just give the code */
986		if (mci->mci_state == MCIS_CLOSED)
987			return (SMTPCLOSING);
988
989		if (mci->mci_out != NULL)
990			fflush(mci->mci_out);
991
992		/* get the line from the other side */
993		p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
994		mci->mci_lastuse = curtime();
995
996		if (p == NULL)
997		{
998			bool oldholderrs;
999			extern char MsgBuf[];
1000
1001			/* if the remote end closed early, fake an error */
1002			if (errno == 0)
1003# ifdef ECONNRESET
1004				errno = ECONNRESET;
1005# else /* ECONNRESET */
1006				errno = EPIPE;
1007# endif /* ECONNRESET */
1008
1009			mci->mci_errno = errno;
1010			oldholderrs = HoldErrs;
1011			HoldErrs = TRUE;
1012			usrerr("451 reply: read error from %s", CurHostName);
1013
1014			/* errors on QUIT should not be persistent */
1015			if (strncmp(SmtpMsgBuffer, "QUIT", 4) != 0)
1016				mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
1017
1018			/* if debugging, pause so we can see state */
1019			if (tTd(18, 100))
1020				pause();
1021			mci->mci_state = MCIS_ERROR;
1022			smtpquit(m, mci, e);
1023#if XDEBUG
1024			{
1025				char wbuf[MAXLINE];
1026				char *p = wbuf;
1027				int wbufleft = sizeof wbuf;
1028
1029				if (e->e_to != NULL)
1030				{
1031					int plen;
1032
1033					snprintf(p, wbufleft, "%s... ",
1034						shortenstring(e->e_to, MAXSHORTSTR));
1035					plen = strlen(p);
1036					p += plen;
1037					wbufleft -= plen;
1038				}
1039				snprintf(p, wbufleft, "reply(%.100s) during %s",
1040					 CurHostName == NULL ? "NO_HOST" : CurHostName,
1041					 SmtpPhase);
1042				checkfd012(wbuf);
1043			}
1044#endif
1045			HoldErrs = oldholderrs;
1046			return (-1);
1047		}
1048		fixcrlf(bufp, TRUE);
1049
1050		/* EHLO failure is not a real error */
1051		if (e->e_xfp != NULL && (bufp[0] == '4' ||
1052		    (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
1053		{
1054			/* serious error -- log the previous command */
1055			if (SmtpNeedIntro)
1056			{
1057				/* inform user who we are chatting with */
1058				fprintf(CurEnv->e_xfp,
1059					"... while talking to %s:\n",
1060					CurHostName);
1061				SmtpNeedIntro = FALSE;
1062			}
1063			if (SmtpMsgBuffer[0] != '\0')
1064				fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
1065			SmtpMsgBuffer[0] = '\0';
1066
1067			/* now log the message as from the other side */
1068			fprintf(e->e_xfp, "<<< %s\n", bufp);
1069		}
1070
1071		/* display the input for verbose mode */
1072		if (Verbose)
1073			nmessage("050 %s", bufp);
1074
1075		/* ignore improperly formated input */
1076		if (!(isascii(bufp[0]) && isdigit(bufp[0])) ||
1077		    !(isascii(bufp[1]) && isdigit(bufp[1])) ||
1078		    !(isascii(bufp[2]) && isdigit(bufp[2])) ||
1079		    !(bufp[3] == ' ' || bufp[3] == '-' || bufp[3] == '\0'))
1080			continue;
1081
1082		/* process the line */
1083		if (pfunc != NULL)
1084			(*pfunc)(bufp, firstline, m, mci, e);
1085
1086		firstline = FALSE;
1087
1088		/* decode the reply code */
1089		r = atoi(bufp);
1090
1091		/* extra semantics: 0xx codes are "informational" */
1092		if (r < 100)
1093			continue;
1094
1095		/* if no continuation lines, return this line */
1096		if (bufp[3] != '-')
1097			break;
1098
1099		/* first line of real reply -- ignore rest */
1100		bufp = junkbuf;
1101	}
1102
1103	/*
1104	**  Now look at SmtpReplyBuffer -- only care about the first
1105	**  line of the response from here on out.
1106	*/
1107
1108	/* save temporary failure messages for posterity */
1109	if (SmtpReplyBuffer[0] == '4' &&
1110	    (bitnset(M_LMTP, m->m_flags) || SmtpError[0] == '\0'))
1111		snprintf(SmtpError, sizeof SmtpError, "%s", SmtpReplyBuffer);
1112
1113	/* reply code 421 is "Service Shutting Down" */
1114	if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
1115	{
1116		/* send the quit protocol */
1117		mci->mci_state = MCIS_SSD;
1118		smtpquit(m, mci, e);
1119	}
1120
1121	return (r);
1122}
1123/*
1124**  SMTPMESSAGE -- send message to server
1125**
1126**	Parameters:
1127**		f -- format
1128**		m -- the mailer to control formatting.
1129**		a, b, c -- parameters
1130**
1131**	Returns:
1132**		none.
1133**
1134**	Side Effects:
1135**		writes message to mci->mci_out.
1136*/
1137
1138/*VARARGS1*/
1139void
1140#ifdef __STDC__
1141smtpmessage(char *f, MAILER *m, MCI *mci, ...)
1142#else
1143smtpmessage(f, m, mci, va_alist)
1144	char *f;
1145	MAILER *m;
1146	MCI *mci;
1147	va_dcl
1148#endif
1149{
1150	VA_LOCAL_DECL
1151
1152	VA_START(mci);
1153	(void) vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap);
1154	VA_END;
1155
1156	if (tTd(18, 1) || Verbose)
1157		nmessage(">>> %s", SmtpMsgBuffer);
1158	if (TrafficLogFile != NULL)
1159		fprintf(TrafficLogFile, "%05d >>> %s\n",
1160			(int) getpid(), SmtpMsgBuffer);
1161	if (mci->mci_out != NULL)
1162	{
1163		fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
1164			m == NULL ? "\r\n" : m->m_eol);
1165	}
1166	else if (tTd(18, 1))
1167	{
1168		printf("smtpmessage: NULL mci_out\n");
1169	}
1170}
1171
1172# endif /* SMTP */
1173