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	5.23 (Berkeley) 07/12/92 (with SMTP)";
14 #else
15 static char sccsid[] = "@(#)usersmtp.c	5.23 (Berkeley) 07/12/92 (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 **  SMTPINIT -- initialize SMTP.
40 **
41 **	Opens the connection and sends the initial protocol.
42 **
43 **	Parameters:
44 **		m -- mailer to create connection to.
45 **		pvp -- pointer to parameter vector to pass to
46 **			the mailer.
47 **
48 **	Returns:
49 **		none.
50 **
51 **	Side Effects:
52 **		creates connection and sends initial protocol.
53 */
54 
55 jmp_buf	CtxGreeting;
56 
57 smtpinit(m, mci, e)
58 	struct mailer *m;
59 	register MCI *mci;
60 	ENVELOPE *e;
61 {
62 	register int r;
63 	EVENT *gte;
64 	static int greettimeout();
65 	extern STAB *stab();
66 	extern MCI *openmailer();
67 
68 	/*
69 	**  Open the connection to the mailer.
70 	*/
71 
72 	SmtpError[0] = '\0';
73 	switch (mci->mci_state)
74 	{
75 	  case MCIS_ACTIVE:
76 		/* need to clear old information */
77 		smtprset(m, mci, e);
78 		mci->mci_state = MCIS_OPEN;
79 
80 	  case MCIS_OPEN:
81 		return;
82 
83 	  case MCIS_ERROR:
84 	  case MCIS_SSD:
85 		/* shouldn't happen */
86 		smtpquit(m, mci, e);
87 
88 	  case MCIS_CLOSED:
89 		syserr("smtpinit: state CLOSED");
90 		return;
91 
92 	  case MCIS_OPENING:
93 		break;
94 	}
95 
96 	mci->mci_phase = "user open";
97 	mci->mci_state = MCIS_OPENING;
98 
99 	/*
100 	**  Get the greeting message.
101 	**	This should appear spontaneously.  Give it five minutes to
102 	**	happen.
103 	*/
104 
105 	if (setjmp(CtxGreeting) != 0)
106 		goto tempfail1;
107 	gte = setevent((time_t) 300, greettimeout, 0);
108 	mci->mci_phase = "greeting wait";
109 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
110 	r = reply(m, mci, e);
111 	clrevent(gte);
112 	if (r < 0 || REPLYTYPE(r) != 2)
113 		goto tempfail1;
114 
115 	/*
116 	**  Send the HELO command.
117 	**	My mother taught me to always introduce myself.
118 	*/
119 
120 	smtpmessage("HELO %s", m, mci, MyHostName);
121 	mci->mci_phase = "HELO wait";
122 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
123 	r = reply(m, mci, e);
124 	if (r < 0)
125 		goto tempfail1;
126 	else if (REPLYTYPE(r) == 5)
127 		goto unavailable;
128 	else if (REPLYTYPE(r) != 2)
129 		goto tempfail1;
130 
131 	/*
132 	**  If this is expected to be another sendmail, send some internal
133 	**  commands.
134 	*/
135 
136 	if (bitnset(M_INTERNAL, m->m_flags))
137 	{
138 		/* tell it to be verbose */
139 		smtpmessage("VERB", m, mci);
140 		r = reply(m, mci, e);
141 		if (r < 0)
142 			goto tempfail2;
143 	}
144 
145 	mci->mci_state = MCIS_OPEN;
146 	return;
147 
148   tempfail1:
149   tempfail2:
150 	mci->mci_exitstat = EX_TEMPFAIL;
151 	mci->mci_errno = errno;
152 	smtpquit(m, mci, e);
153 	return;
154 
155   unavailable:
156 	mci->mci_exitstat = EX_UNAVAILABLE;
157 	mci->mci_errno = errno;
158 	smtpquit(m, mci, e);
159 	return;
160 }
161 
162 smtpmailfrom(m, mci, e)
163 	struct mailer *m;
164 	MCI *mci;
165 	ENVELOPE *e;
166 {
167 	int r;
168 	char buf[MAXNAME];
169 
170 	/*
171 	**  Send the MAIL command.
172 	**	Designates the sender.
173 	*/
174 
175 	mci->mci_state = MCIS_ACTIVE;
176 
177 	expand("\001<", buf, &buf[sizeof buf - 1], e);
178 	if (e->e_from.q_mailer == LocalMailer ||
179 	    !bitnset(M_FROMPATH, m->m_flags))
180 	{
181 		smtpmessage("MAIL From:<%s>", m, mci, buf);
182 	}
183 	else
184 	{
185 		smtpmessage("MAIL From:<@%s%c%s>", m, mci, MyHostName,
186 			buf[0] == '@' ? ',' : ':', buf);
187 	}
188 	mci->mci_phase = "MAIL wait";
189 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
190 	r = reply(m, mci, e);
191 	if (r < 0 || REPLYTYPE(r) == 4)
192 	{
193 		mci->mci_exitstat = EX_TEMPFAIL;
194 		mci->mci_errno = errno;
195 		smtpquit(m, mci, e);
196 		return EX_TEMPFAIL;
197 	}
198 	else if (r == 250)
199 	{
200 		mci->mci_exitstat = EX_OK;
201 		return EX_OK;
202 	}
203 	else if (r == 552)
204 	{
205 		/* signal service unavailable */
206 		mci->mci_exitstat = EX_UNAVAILABLE;
207 		smtpquit(m, mci, e);
208 		return EX_UNAVAILABLE;
209 	}
210 
211 	/* protocol error -- close up */
212 	smtpquit(m, mci, e);
213 	mci->mci_exitstat = EX_PROTOCOL;
214 	return EX_PROTOCOL;
215 }
216 
217 
218 static
219 greettimeout()
220 {
221 	/* timeout reading the greeting message */
222 	longjmp(CtxGreeting, 1);
223 }
224 /*
225 **  SMTPRCPT -- designate recipient.
226 **
227 **	Parameters:
228 **		to -- address of recipient.
229 **		m -- the mailer we are sending to.
230 **
231 **	Returns:
232 **		exit status corresponding to recipient status.
233 **
234 **	Side Effects:
235 **		Sends the mail via SMTP.
236 */
237 
238 smtprcpt(to, m, mci, e)
239 	ADDRESS *to;
240 	register MAILER *m;
241 	MCI *mci;
242 	ENVELOPE *e;
243 {
244 	register int r;
245 
246 	smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
247 
248 	mci->mci_phase = "RCPT wait";
249 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
250 	r = reply(m, mci, e);
251 	if (r < 0 || REPLYTYPE(r) == 4)
252 		return (EX_TEMPFAIL);
253 	else if (REPLYTYPE(r) == 2)
254 		return (EX_OK);
255 	else if (r == 550 || r == 551 || r == 553)
256 		return (EX_NOUSER);
257 	else if (r == 552 || r == 554)
258 		return (EX_UNAVAILABLE);
259 	return (EX_PROTOCOL);
260 }
261 /*
262 **  SMTPDATA -- send the data and clean up the transaction.
263 **
264 **	Parameters:
265 **		m -- mailer being sent to.
266 **		e -- the envelope for this message.
267 **
268 **	Returns:
269 **		exit status corresponding to DATA command.
270 **
271 **	Side Effects:
272 **		none.
273 */
274 
275 smtpdata(m, mci, e)
276 	struct mailer *m;
277 	register MCI *mci;
278 	register ENVELOPE *e;
279 {
280 	register int r;
281 
282 	/*
283 	**  Send the data.
284 	**	First send the command and check that it is ok.
285 	**	Then send the data.
286 	**	Follow it up with a dot to terminate.
287 	**	Finally get the results of the transaction.
288 	*/
289 
290 	/* send the command and check ok to proceed */
291 	smtpmessage("DATA", m, mci);
292 	mci->mci_phase = "DATA wait";
293 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
294 	r = reply(m, mci, e);
295 	if (r < 0 || REPLYTYPE(r) == 4)
296 		return (EX_TEMPFAIL);
297 	else if (r == 554)
298 		return (EX_UNAVAILABLE);
299 	else if (r != 354)
300 		return (EX_PROTOCOL);
301 
302 	/* now output the actual message */
303 	(*e->e_puthdr)(mci->mci_out, m, e);
304 	putline("\n", mci->mci_out, m);
305 	(*e->e_putbody)(mci->mci_out, m, e);
306 
307 	/* terminate the message */
308 	fprintf(mci->mci_out, ".%s", m->m_eol);
309 	if (Verbose && !HoldErrs)
310 		nmessage(Arpa_Info, ">>> .");
311 
312 	/* check for the results of the transaction */
313 	mci->mci_phase = "result wait";
314 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
315 	r = reply(m, mci, e);
316 	if (r < 0)
317 		return (EX_TEMPFAIL);
318 	mci->mci_state = MCIS_OPEN;
319 	if (REPLYTYPE(r) == 4)
320 		return (EX_TEMPFAIL);
321 	else if (r == 250)
322 		return (EX_OK);
323 	else if (r == 552 || r == 554)
324 		return (EX_UNAVAILABLE);
325 	return (EX_PROTOCOL);
326 }
327 /*
328 **  SMTPQUIT -- close the SMTP connection.
329 **
330 **	Parameters:
331 **		m -- a pointer to the mailer.
332 **
333 **	Returns:
334 **		none.
335 **
336 **	Side Effects:
337 **		sends the final protocol and closes the connection.
338 */
339 
340 smtpquit(m, mci, e)
341 	register MAILER *m;
342 	register MCI *mci;
343 	ENVELOPE *e;
344 {
345 	int i;
346 
347 	/* send the quit message if we haven't gotten I/O error */
348 	if (mci->mci_state != MCIS_ERROR)
349 	{
350 		smtpmessage("QUIT", m, mci);
351 		(void) reply(m, mci, e);
352 		if (mci->mci_state == MCIS_CLOSED)
353 			return;
354 	}
355 
356 	/* now actually close the connection and pick up the zombie */
357 	i = endmailer(mci, m->m_argv[0]);
358 	if (i != EX_OK)
359 		syserr("smtpquit %s: stat %d", m->m_argv[0], i);
360 }
361 /*
362 **  SMTPRSET -- send a RSET (reset) command
363 */
364 
365 smtprset(m, mci, e)
366 	register MAILER *m;
367 	register MCI *mci;
368 	ENVELOPE *e;
369 {
370 	int r;
371 
372 	smtpmessage("RSET", m, mci);
373 	r = reply(m, mci, e);
374 	if (r < 0 || REPLYTYPE(r) == 4)
375 		return EX_TEMPFAIL;
376 	else if (REPLYTYPE(r) == 2)
377 		return EX_OK;
378 	else
379 		return EX_PROTOCOL;
380 }
381 /*
382 **  SMTPNOOP -- send a NOOP (no operation) command to check the connection state
383 */
384 
385 smtpnoop(mci)
386 	register MCI *mci;
387 {
388 	int r;
389 	MAILER *m = mci->mci_mailer;
390 	extern ENVELOPE BlankEnvelope;
391 	ENVELOPE *e = &BlankEnvelope;
392 
393 	smtpmessage("NOOP", m, mci);
394 	r = reply(m, mci, e);
395 	if (REPLYTYPE(r) != 2)
396 		smtpquit(m, mci, e);
397 	return r;
398 }
399 /*
400 **  REPLY -- read arpanet reply
401 **
402 **	Parameters:
403 **		m -- the mailer we are reading the reply from.
404 **
405 **	Returns:
406 **		reply code it reads.
407 **
408 **	Side Effects:
409 **		flushes the mail file.
410 */
411 
412 reply(m, mci, e)
413 	MAILER *m;
414 	MCI *mci;
415 	ENVELOPE *e;
416 {
417 	(void) fflush(mci->mci_out);
418 
419 	if (tTd(18, 1))
420 		printf("reply\n");
421 
422 	/*
423 	**  Read the input line, being careful not to hang.
424 	*/
425 
426 	for (;;)
427 	{
428 		register int r;
429 		register char *p;
430 		extern time_t curtime();
431 
432 		/* actually do the read */
433 		if (e->e_xfp != NULL)
434 			(void) fflush(e->e_xfp);	/* for debugging */
435 
436 		/* if we are in the process of closing just give the code */
437 		if (mci->mci_state == MCIS_CLOSED)
438 			return (SMTPCLOSING);
439 
440 		/* get the line from the other side */
441 		p = sfgets(SmtpReplyBuffer, sizeof SmtpReplyBuffer, mci->mci_in);
442 		mci->mci_lastuse = curtime();
443 
444 		if (p == NULL)
445 		{
446 			extern char MsgBuf[];		/* err.c */
447 			extern char Arpa_TSyserr[];	/* conf.c */
448 
449 			/* if the remote end closed early, fake an error */
450 			if (errno == 0)
451 # ifdef ECONNRESET
452 				errno = ECONNRESET;
453 # else ECONNRESET
454 				errno = EPIPE;
455 # endif ECONNRESET
456 
457 			message(Arpa_TSyserr, "reply: read error");
458 			/* if debugging, pause so we can see state */
459 			if (tTd(18, 100))
460 				pause();
461 # ifdef LOG
462 			syslog(LOG_INFO, "%s", &MsgBuf[4]);
463 # endif LOG
464 			mci->mci_state = MCIS_ERROR;
465 			smtpquit(m, mci, e);
466 			return (-1);
467 		}
468 		fixcrlf(SmtpReplyBuffer, TRUE);
469 
470 		if (e->e_xfp != NULL && index("45", SmtpReplyBuffer[0]) != NULL)
471 		{
472 			/* serious error -- log the previous command */
473 			if (SmtpMsgBuffer[0] != '\0')
474 				fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
475 			SmtpMsgBuffer[0] = '\0';
476 
477 			/* now log the message as from the other side */
478 			fprintf(e->e_xfp, "<<< %s\n", SmtpReplyBuffer);
479 		}
480 
481 		/* display the input for verbose mode */
482 		if (Verbose && !HoldErrs)
483 			nmessage(Arpa_Info, "%s", SmtpReplyBuffer);
484 
485 		/* if continuation is required, we can go on */
486 		if (SmtpReplyBuffer[3] == '-' || !isdigit(SmtpReplyBuffer[0]))
487 			continue;
488 
489 		/* decode the reply code */
490 		r = atoi(SmtpReplyBuffer);
491 
492 		/* extra semantics: 0xx codes are "informational" */
493 		if (r < 100)
494 			continue;
495 
496 		/* reply code 421 is "Service Shutting Down" */
497 		if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
498 		{
499 			/* send the quit protocol */
500 			mci->mci_state = MCIS_SSD;
501 			smtpquit(m, mci, e);
502 		}
503 
504 		/* save temporary failure messages for posterity */
505 		if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
506 			(void) strcpy(SmtpError, &SmtpReplyBuffer[4]);
507 
508 		return (r);
509 	}
510 }
511 /*
512 **  SMTPMESSAGE -- send message to server
513 **
514 **	Parameters:
515 **		f -- format
516 **		m -- the mailer to control formatting.
517 **		a, b, c -- parameters
518 **
519 **	Returns:
520 **		none.
521 **
522 **	Side Effects:
523 **		writes message to mci->mci_out.
524 */
525 
526 /*VARARGS1*/
527 smtpmessage(f, m, mci, a, b, c)
528 	char *f;
529 	MAILER *m;
530 	MCI *mci;
531 {
532 	(void) sprintf(SmtpMsgBuffer, f, a, b, c);
533 	if (tTd(18, 1) || (Verbose && !HoldErrs))
534 		nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer);
535 	if (mci->mci_out != NULL)
536 		fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
537 			m == NULL ? "\r\n" : m->m_eol);
538 }
539 
540 # endif SMTP
541