1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 # include "sendmail.h"
10 
11 #ifndef lint
12 #ifdef SMTP
13 static char sccsid[] = "@(#)usersmtp.c	6.26 (Berkeley) 04/18/93 (with SMTP)";
14 #else
15 static char sccsid[] = "@(#)usersmtp.c	6.26 (Berkeley) 04/18/93 (without SMTP)";
16 #endif
17 #endif /* not lint */
18 
19 # include <sysexits.h>
20 # include <errno.h>
21 
22 # ifdef SMTP
23 
24 /*
25 **  USERSMTP -- run SMTP protocol from the user end.
26 **
27 **	This protocol is described in RFC821.
28 */
29 
30 #define REPLYTYPE(r)	((r) / 100)		/* first digit of reply code */
31 #define REPLYCLASS(r)	(((r) / 10) % 10)	/* second digit of reply code */
32 #define SMTPCLOSING	421			/* "Service Shutting Down" */
33 
34 char	SmtpMsgBuffer[MAXLINE];		/* buffer for commands */
35 char	SmtpReplyBuffer[MAXLINE];	/* buffer for replies */
36 char	SmtpError[MAXLINE] = "";	/* save failure error messages */
37 int	SmtpPid;			/* pid of mailer */
38 
39 #ifdef __STDC__
40 extern	smtpmessage(char *f, MAILER *m, MCI *mci, ...);
41 #endif
42 /*
43 **  SMTPINIT -- initialize SMTP.
44 **
45 **	Opens the connection and sends the initial protocol.
46 **
47 **	Parameters:
48 **		m -- mailer to create connection to.
49 **		pvp -- pointer to parameter vector to pass to
50 **			the mailer.
51 **
52 **	Returns:
53 **		none.
54 **
55 **	Side Effects:
56 **		creates connection and sends initial protocol.
57 */
58 
59 smtpinit(m, mci, e)
60 	struct mailer *m;
61 	register MCI *mci;
62 	ENVELOPE *e;
63 {
64 	register int r;
65 	register char *p;
66 	extern STAB *stab();
67 
68 	if (tTd(17, 1))
69 	{
70 		printf("smtpinit ");
71 		mci_dump(mci);
72 	}
73 
74 	/*
75 	**  Open the connection to the mailer.
76 	*/
77 
78 	SmtpError[0] = '\0';
79 	CurHostName = mci->mci_host;		/* XXX UGLY XXX */
80 	switch (mci->mci_state)
81 	{
82 	  case MCIS_ACTIVE:
83 		/* need to clear old information */
84 		smtprset(m, mci, e);
85 		/* fall through */
86 
87 	  case MCIS_OPEN:
88 		return;
89 
90 	  case MCIS_ERROR:
91 	  case MCIS_SSD:
92 		/* shouldn't happen */
93 		smtpquit(m, mci, e);
94 		/* fall through */
95 
96 	  case MCIS_CLOSED:
97 		syserr("451 smtpinit: state CLOSED");
98 		return;
99 
100 	  case MCIS_OPENING:
101 		break;
102 	}
103 
104 	mci->mci_state = MCIS_OPENING;
105 
106 	/*
107 	**  Get the greeting message.
108 	**	This should appear spontaneously.  Give it five minutes to
109 	**	happen.
110 	*/
111 
112 	SmtpPhase = mci->mci_phase = "greeting wait";
113 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
114 	r = reply(m, mci, e, TimeOuts.to_initial);
115 	if (r < 0 || REPLYTYPE(r) != 2)
116 		goto tempfail1;
117 
118 	/*
119 	**  Send the HELO command.
120 	**	My mother taught me to always introduce myself.
121 	*/
122 
123 	smtpmessage("HELO %s", m, mci, MyHostName);
124 	SmtpPhase = mci->mci_phase = "HELO wait";
125 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
126 	r = reply(m, mci, e, TimeOuts.to_helo);
127 	if (r < 0)
128 		goto tempfail1;
129 	else if (REPLYTYPE(r) == 5)
130 		goto unavailable;
131 	else if (REPLYTYPE(r) != 2)
132 		goto tempfail1;
133 
134 	/*
135 	**  Check to see if we actually ended up talking to ourself.
136 	**  This means we didn't know about an alias or MX, or we managed
137 	**  to connect to an echo server.
138 	*/
139 
140 	p = strchr(&SmtpReplyBuffer[4], ' ');
141 	if (p != NULL)
142 		*p == '\0';
143 	if (strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
144 	{
145 		syserr("553 %s config error: mail loops back to myself",
146 			MyHostName);
147 		mci->mci_exitstat = EX_CONFIG;
148 		mci->mci_errno = 0;
149 		smtpquit(m, mci, e);
150 		return;
151 	}
152 
153 	/*
154 	**  If this is expected to be another sendmail, send some internal
155 	**  commands.
156 	*/
157 
158 	if (bitnset(M_INTERNAL, m->m_flags))
159 	{
160 		/* tell it to be verbose */
161 		smtpmessage("VERB", m, mci);
162 		r = reply(m, mci, e, TimeOuts.to_miscshort);
163 		if (r < 0)
164 			goto tempfail2;
165 	}
166 
167 	mci->mci_state = MCIS_OPEN;
168 	return;
169 
170   tempfail1:
171   tempfail2:
172 	mci->mci_exitstat = EX_TEMPFAIL;
173 	if (mci->mci_errno == 0)
174 		mci->mci_errno = errno;
175 	if (mci->mci_state != MCIS_CLOSED)
176 		smtpquit(m, mci, e);
177 	return;
178 
179   unavailable:
180 	mci->mci_exitstat = EX_UNAVAILABLE;
181 	mci->mci_errno = errno;
182 	smtpquit(m, mci, e);
183 	return;
184 }
185 
186 smtpmailfrom(m, mci, e)
187 	struct mailer *m;
188 	MCI *mci;
189 	ENVELOPE *e;
190 {
191 	int r;
192 	char buf[MAXNAME];
193 
194 	if (tTd(17, 2))
195 		printf("smtpmailfrom: CurHost=%s\n", CurHostName);
196 
197 	/*
198 	**  Send the MAIL command.
199 	**	Designates the sender.
200 	*/
201 
202 	mci->mci_state = MCIS_ACTIVE;
203 
204 	if (bitset(EF_RESPONSE, e->e_flags))
205 		(void) strcpy(buf, "");
206 	else
207 		expand("\201g", buf, &buf[sizeof buf - 1], e);
208 	if (e->e_from.q_mailer == LocalMailer ||
209 	    !bitnset(M_FROMPATH, m->m_flags))
210 	{
211 		smtpmessage("MAIL From:<%s>", m, mci, buf);
212 	}
213 	else
214 	{
215 		smtpmessage("MAIL From:<@%s%c%s>", m, mci, MyHostName,
216 			buf[0] == '@' ? ',' : ':', buf);
217 	}
218 	SmtpPhase = mci->mci_phase = "MAIL wait";
219 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
220 	r = reply(m, mci, e, TimeOuts.to_mail);
221 	if (r < 0 || REPLYTYPE(r) == 4)
222 	{
223 		mci->mci_exitstat = EX_TEMPFAIL;
224 		mci->mci_errno = errno;
225 		smtpquit(m, mci, e);
226 		return EX_TEMPFAIL;
227 	}
228 	else if (r == 250)
229 	{
230 		mci->mci_exitstat = EX_OK;
231 		return EX_OK;
232 	}
233 	else if (r == 552)
234 	{
235 		/* signal service unavailable */
236 		mci->mci_exitstat = EX_UNAVAILABLE;
237 		smtpquit(m, mci, e);
238 		return EX_UNAVAILABLE;
239 	}
240 
241 #ifdef LOG
242 	if (LogLevel > 1)
243 	{
244 		syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s",
245 			e->e_id, SmtpReplyBuffer);
246 	}
247 #endif
248 
249 	/* protocol error -- close up */
250 	smtpquit(m, mci, e);
251 	mci->mci_exitstat = EX_PROTOCOL;
252 	return EX_PROTOCOL;
253 }
254 /*
255 **  SMTPRCPT -- designate recipient.
256 **
257 **	Parameters:
258 **		to -- address of recipient.
259 **		m -- the mailer we are sending to.
260 **		mci -- the connection info for this transaction.
261 **		e -- the envelope for this transaction.
262 **
263 **	Returns:
264 **		exit status corresponding to recipient status.
265 **
266 **	Side Effects:
267 **		Sends the mail via SMTP.
268 */
269 
270 smtprcpt(to, m, mci, e)
271 	ADDRESS *to;
272 	register MAILER *m;
273 	MCI *mci;
274 	ENVELOPE *e;
275 {
276 	register int r;
277 
278 	smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
279 
280 	SmtpPhase = mci->mci_phase = "RCPT wait";
281 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
282 	r = reply(m, mci, e, TimeOuts.to_rcpt);
283 	if (r < 0 || REPLYTYPE(r) == 4)
284 		return (EX_TEMPFAIL);
285 	else if (REPLYTYPE(r) == 2)
286 		return (EX_OK);
287 	else if (r == 550 || r == 551 || r == 553)
288 		return (EX_NOUSER);
289 	else if (r == 552 || r == 554)
290 		return (EX_UNAVAILABLE);
291 
292 #ifdef LOG
293 	if (LogLevel > 1)
294 	{
295 		syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
296 			e->e_id, SmtpReplyBuffer);
297 	}
298 #endif
299 
300 	return (EX_PROTOCOL);
301 }
302 /*
303 **  SMTPDATA -- send the data and clean up the transaction.
304 **
305 **	Parameters:
306 **		m -- mailer being sent to.
307 **		e -- the envelope for this message.
308 **
309 **	Returns:
310 **		exit status corresponding to DATA command.
311 **
312 **	Side Effects:
313 **		none.
314 */
315 
316 smtpdata(m, mci, e)
317 	struct mailer *m;
318 	register MCI *mci;
319 	register ENVELOPE *e;
320 {
321 	register int r;
322 
323 	/*
324 	**  Send the data.
325 	**	First send the command and check that it is ok.
326 	**	Then send the data.
327 	**	Follow it up with a dot to terminate.
328 	**	Finally get the results of the transaction.
329 	*/
330 
331 	/* send the command and check ok to proceed */
332 	smtpmessage("DATA", m, mci);
333 	SmtpPhase = mci->mci_phase = "DATA wait";
334 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
335 	r = reply(m, mci, e, TimeOuts.to_datainit);
336 	if (r < 0 || REPLYTYPE(r) == 4)
337 	{
338 		smtpquit(m, mci, e);
339 		return (EX_TEMPFAIL);
340 	}
341 	else if (r == 554)
342 	{
343 		smtprset(m, mci, e);
344 		return (EX_UNAVAILABLE);
345 	}
346 	else if (r != 354)
347 	{
348 #ifdef LOG
349 		if (LogLevel > 1)
350 		{
351 			syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
352 				e->e_id, SmtpReplyBuffer);
353 		}
354 #endif
355 		smtprset(m, mci, e);
356 		return (EX_PROTOCOL);
357 	}
358 
359 	/* now output the actual message */
360 	(*e->e_puthdr)(mci->mci_out, m, e);
361 	putline("\n", mci->mci_out, m);
362 	(*e->e_putbody)(mci->mci_out, m, e);
363 
364 	/* terminate the message */
365 	fprintf(mci->mci_out, ".%s", m->m_eol);
366 	if (Verbose)
367 		nmessage(">>> .");
368 
369 	/* check for the results of the transaction */
370 	SmtpPhase = mci->mci_phase = "result wait";
371 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
372 	r = reply(m, mci, e, TimeOuts.to_datafinal);
373 	if (r < 0)
374 	{
375 		smtpquit(m, mci, e);
376 		return (EX_TEMPFAIL);
377 	}
378 	mci->mci_state = MCIS_OPEN;
379 	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
380 	if (REPLYTYPE(r) == 4)
381 		return (EX_TEMPFAIL);
382 	else if (r == 250)
383 		return (EX_OK);
384 	else if (r == 552 || r == 554)
385 		return (EX_UNAVAILABLE);
386 #ifdef LOG
387 	if (LogLevel > 1)
388 	{
389 		syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
390 			e->e_id, SmtpReplyBuffer);
391 	}
392 #endif
393 	return (EX_PROTOCOL);
394 }
395 /*
396 **  SMTPQUIT -- close the SMTP connection.
397 **
398 **	Parameters:
399 **		m -- a pointer to the mailer.
400 **
401 **	Returns:
402 **		none.
403 **
404 **	Side Effects:
405 **		sends the final protocol and closes the connection.
406 */
407 
408 smtpquit(m, mci, e)
409 	register MAILER *m;
410 	register MCI *mci;
411 	ENVELOPE *e;
412 {
413 	int i;
414 
415 	/* send the quit message if we haven't gotten I/O error */
416 	if (mci->mci_state != MCIS_ERROR)
417 	{
418 		smtpmessage("QUIT", m, mci);
419 		(void) reply(m, mci, e, TimeOuts.to_quit);
420 		if (mci->mci_state == MCIS_CLOSED)
421 			return;
422 	}
423 
424 	/* now actually close the connection and pick up the zombie */
425 	i = endmailer(mci, e, m->m_argv);
426 	if (i != EX_OK)
427 		syserr("451 smtpquit %s: stat %d", m->m_argv[0], i);
428 }
429 /*
430 **  SMTPRSET -- send a RSET (reset) command
431 */
432 
433 smtprset(m, mci, e)
434 	register MAILER *m;
435 	register MCI *mci;
436 	ENVELOPE *e;
437 {
438 	int r;
439 
440 	smtpmessage("RSET", m, mci);
441 	r = reply(m, mci, e, TimeOuts.to_rset);
442 	if (r < 0)
443 		mci->mci_state = MCIS_ERROR;
444 	else if (REPLYTYPE(r) == 2)
445 	{
446 		mci->mci_state = MCIS_OPEN;
447 		return;
448 	}
449 	smtpquit(m, mci, e);
450 }
451 /*
452 **  SMTPPROBE -- check the connection state
453 */
454 
455 smtpprobe(mci)
456 	register MCI *mci;
457 {
458 	int r;
459 	MAILER *m = mci->mci_mailer;
460 	extern ENVELOPE BlankEnvelope;
461 	ENVELOPE *e = &BlankEnvelope;
462 
463 	smtpmessage("RSET", m, mci);
464 	r = reply(m, mci, e, TimeOuts.to_miscshort);
465 	if (r < 0 || REPLYTYPE(r) != 2)
466 		smtpquit(m, mci, e);
467 	return r;
468 }
469 /*
470 **  REPLY -- read arpanet reply
471 **
472 **	Parameters:
473 **		m -- the mailer we are reading the reply from.
474 **		mci -- the mailer connection info structure.
475 **		e -- the current envelope.
476 **		timeout -- the timeout for reads.
477 **
478 **	Returns:
479 **		reply code it reads.
480 **
481 **	Side Effects:
482 **		flushes the mail file.
483 */
484 
485 reply(m, mci, e, timeout)
486 	MAILER *m;
487 	MCI *mci;
488 	ENVELOPE *e;
489 {
490 	register char *bufp;
491 	register int r;
492 	char junkbuf[MAXLINE];
493 
494 	if (mci->mci_out != NULL)
495 		(void) fflush(mci->mci_out);
496 
497 	if (tTd(18, 1))
498 		printf("reply\n");
499 
500 	/*
501 	**  Read the input line, being careful not to hang.
502 	*/
503 
504 	for (bufp = SmtpReplyBuffer;; bufp = junkbuf)
505 	{
506 		register char *p;
507 		extern time_t curtime();
508 
509 		/* actually do the read */
510 		if (e->e_xfp != NULL)
511 			(void) fflush(e->e_xfp);	/* for debugging */
512 
513 		/* if we are in the process of closing just give the code */
514 		if (mci->mci_state == MCIS_CLOSED)
515 			return (SMTPCLOSING);
516 
517 		if (mci->mci_out != NULL)
518 			fflush(mci->mci_out);
519 
520 		/* get the line from the other side */
521 		p = sfgets(bufp, MAXLINE, mci->mci_in, timeout);
522 		mci->mci_lastuse = curtime();
523 
524 		if (p == NULL)
525 		{
526 			extern char MsgBuf[];		/* err.c */
527 
528 			/* if the remote end closed early, fake an error */
529 			if (errno == 0)
530 # ifdef ECONNRESET
531 				errno = ECONNRESET;
532 # else /* ECONNRESET */
533 				errno = EPIPE;
534 # endif /* ECONNRESET */
535 
536 			mci->mci_errno = errno;
537 			mci->mci_exitstat = EX_TEMPFAIL;
538 			message("451 %s: reply: read error from %s",
539 				e->e_id == NULL ? "NOQUEUE" : e->e_id,
540 				mci->mci_host);
541 			/* if debugging, pause so we can see state */
542 			if (tTd(18, 100))
543 				pause();
544 # ifdef LOG
545 			if (LogLevel > 1)
546 				syslog(LOG_INFO, "%s", &MsgBuf[4]);
547 # endif /* LOG */
548 			mci->mci_state = MCIS_ERROR;
549 			smtpquit(m, mci, e);
550 			return (-1);
551 		}
552 		fixcrlf(bufp, TRUE);
553 
554 		if (e->e_xfp != NULL && strchr("45", bufp[0]) != NULL)
555 		{
556 			/* serious error -- log the previous command */
557 			if (SmtpMsgBuffer[0] != '\0')
558 				fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
559 			SmtpMsgBuffer[0] = '\0';
560 
561 			/* now log the message as from the other side */
562 			fprintf(e->e_xfp, "<<< %s\n", bufp);
563 		}
564 
565 		/* display the input for verbose mode */
566 		if (Verbose)
567 			nmessage("%s", bufp);
568 
569 		/* if continuation is required, we can go on */
570 		if (bufp[3] == '-')
571 			continue;
572 
573 		/* ignore improperly formated input */
574 		if (!(isascii(bufp[0]) && isdigit(bufp[0])))
575 			continue;
576 
577 		/* decode the reply code */
578 		r = atoi(bufp);
579 
580 		/* extra semantics: 0xx codes are "informational" */
581 		if (r >= 100)
582 			break;
583 	}
584 
585 	/*
586 	**  Now look at SmtpReplyBuffer -- only care about the first
587 	**  line of the response from here on out.
588 	*/
589 
590 	/* save temporary failure messages for posterity */
591 	if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
592 		(void) strcpy(SmtpError, SmtpReplyBuffer);
593 
594 	/* reply code 421 is "Service Shutting Down" */
595 	if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
596 	{
597 		/* send the quit protocol */
598 		mci->mci_state = MCIS_SSD;
599 		smtpquit(m, mci, e);
600 	}
601 
602 	return (r);
603 }
604 /*
605 **  SMTPMESSAGE -- send message to server
606 **
607 **	Parameters:
608 **		f -- format
609 **		m -- the mailer to control formatting.
610 **		a, b, c -- parameters
611 **
612 **	Returns:
613 **		none.
614 **
615 **	Side Effects:
616 **		writes message to mci->mci_out.
617 */
618 
619 /*VARARGS1*/
620 #ifdef __STDC__
621 smtpmessage(char *f, MAILER *m, MCI *mci, ...)
622 #else
623 smtpmessage(f, m, mci, va_alist)
624 	char *f;
625 	MAILER *m;
626 	MCI *mci;
627 	va_dcl
628 #endif
629 {
630 	VA_LOCAL_DECL
631 
632 	VA_START(mci);
633 	(void) vsprintf(SmtpMsgBuffer, f, ap);
634 	VA_END;
635 
636 	if (tTd(18, 1) || Verbose)
637 		nmessage(">>> %s", SmtpMsgBuffer);
638 	if (mci->mci_out != NULL)
639 	{
640 		fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
641 			m == NULL ? "\r\n" : m->m_eol);
642 	}
643 	else if (tTd(18, 1))
644 	{
645 		printf("smtpmessage: NULL mci_out\n");
646 	}
647 }
648 
649 # endif /* SMTP */
650