1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)envelope.c	8.2 (Berkeley) 07/11/93";
11 #endif /* not lint */
12 
13 #include "sendmail.h"
14 #include <sys/time.h>
15 #include <pwd.h>
16 
17 /*
18 **  NEWENVELOPE -- allocate a new envelope
19 **
20 **	Supports inheritance.
21 **
22 **	Parameters:
23 **		e -- the new envelope to fill in.
24 **		parent -- the envelope to be the parent of e.
25 **
26 **	Returns:
27 **		e.
28 **
29 **	Side Effects:
30 **		none.
31 */
32 
33 ENVELOPE *
34 newenvelope(e, parent)
35 	register ENVELOPE *e;
36 	register ENVELOPE *parent;
37 {
38 	extern putheader(), putbody();
39 	extern ENVELOPE BlankEnvelope;
40 
41 	if (e == parent && e->e_parent != NULL)
42 		parent = e->e_parent;
43 	clearenvelope(e, TRUE);
44 	if (e == CurEnv)
45 		bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
46 	else
47 		bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
48 	e->e_parent = parent;
49 	e->e_ctime = curtime();
50 	if (parent != NULL)
51 		e->e_msgpriority = parent->e_msgsize;
52 	e->e_puthdr = putheader;
53 	e->e_putbody = putbody;
54 	if (CurEnv->e_xfp != NULL)
55 		(void) fflush(CurEnv->e_xfp);
56 
57 	return (e);
58 }
59 /*
60 **  DROPENVELOPE -- deallocate an envelope.
61 **
62 **	Parameters:
63 **		e -- the envelope to deallocate.
64 **
65 **	Returns:
66 **		none.
67 **
68 **	Side Effects:
69 **		housekeeping necessary to dispose of an envelope.
70 **		Unlocks this queue file.
71 */
72 
73 void
74 dropenvelope(e)
75 	register ENVELOPE *e;
76 {
77 	bool queueit = FALSE;
78 	register ADDRESS *q;
79 	char *id = e->e_id;
80 	char buf[MAXLINE];
81 
82 	if (tTd(50, 1))
83 	{
84 		printf("dropenvelope %x: id=", e);
85 		xputs(e->e_id);
86 		printf(", flags=%o\n", e->e_flags);
87 		if (tTd(50, 10))
88 		{
89 			printf("sendq=");
90 			printaddr(e->e_sendqueue, TRUE);
91 		}
92 	}
93 
94 	/* we must have an id to remove disk files */
95 	if (id == NULL)
96 		return;
97 
98 #ifdef LOG
99 	if (LogLevel > 84)
100 		syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
101 				  id, e->e_flags, getpid());
102 #endif /* LOG */
103 
104 	/* post statistics */
105 	poststats(StatFile);
106 
107 	/*
108 	**  Extract state information from dregs of send list.
109 	*/
110 
111 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
112 	{
113 		if (bitset(QQUEUEUP, q->q_flags))
114 			queueit = TRUE;
115 	}
116 
117 	/*
118 	**  See if the message timed out.
119 	*/
120 
121 	if (!queueit)
122 		/* nothing to do */ ;
123 	else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
124 	{
125 		if (!bitset(EF_TIMEOUT, e->e_flags))
126 		{
127 			(void) sprintf(buf, "Cannot send message for %s",
128 				pintvl(TimeOuts.to_q_return, FALSE));
129 			if (e->e_message != NULL)
130 				free(e->e_message);
131 			e->e_message = newstr(buf);
132 			message(buf);
133 		}
134 		e->e_flags |= EF_TIMEOUT|EF_CLRQUEUE;
135 		fprintf(e->e_xfp, "421 Message timed out\n");
136 	}
137 	else if (TimeOuts.to_q_warning > 0 &&
138 	    curtime() > e->e_ctime + TimeOuts.to_q_warning)
139 	{
140 		if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
141 		    e->e_class >= 0 &&
142 		    strcmp(e->e_from.q_paddr, "<>") != 0)
143 		{
144 			(void) sprintf(buf,
145 				"warning: cannot send message for %s",
146 				pintvl(TimeOuts.to_q_warning, FALSE));
147 			if (e->e_message != NULL)
148 				free(e->e_message);
149 			e->e_message = newstr(buf);
150 			message(buf);
151 			e->e_flags |= EF_WARNING|EF_TIMEOUT;
152 		}
153 		fprintf(e->e_xfp,
154 			"Warning: message still undelivered after %s\n",
155 			pintvl(TimeOuts.to_q_warning, FALSE));
156 		fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
157 			pintvl(TimeOuts.to_q_return, FALSE));
158 	}
159 
160 	/*
161 	**  Send back return receipts as requested.
162 	*/
163 
164 	if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
165 	{
166 		auto ADDRESS *rlist = NULL;
167 
168 		(void) sendtolist(e->e_receiptto, (ADDRESS *) NULL, &rlist, e);
169 		(void) returntosender("Return receipt", rlist, FALSE, e);
170 	}
171 
172 	/*
173 	**  Arrange to send error messages if there are fatal errors.
174 	*/
175 
176 	if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) &&
177 	    e->e_errormode != EM_QUIET)
178 		savemail(e);
179 
180 	/*
181 	**  Instantiate or deinstantiate the queue.
182 	*/
183 
184 	if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
185 	    bitset(EF_CLRQUEUE, e->e_flags))
186 	{
187 		if (tTd(50, 2))
188 			printf("Dropping envelope\n");
189 		if (e->e_df != NULL)
190 			xunlink(e->e_df);
191 		xunlink(queuename(e, 'q'));
192 	}
193 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
194 	{
195 #ifdef QUEUE
196 		queueup(e, FALSE, FALSE);
197 #else /* QUEUE */
198 		syserr("554 dropenvelope: queueup");
199 #endif /* QUEUE */
200 	}
201 
202 	/* now unlock the job */
203 	closexscript(e);
204 	unlockqueue(e);
205 
206 	/* make sure that this envelope is marked unused */
207 	if (e->e_dfp != NULL)
208 		(void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
209 	e->e_dfp = NULL;
210 	e->e_id = e->e_df = NULL;
211 
212 #ifdef LOG
213 	if (LogLevel > 74)
214 		syslog(LOG_INFO, "%s: done", id);
215 #endif /* LOG */
216 }
217 /*
218 **  CLEARENVELOPE -- clear an envelope without unlocking
219 **
220 **	This is normally used by a child process to get a clean
221 **	envelope without disturbing the parent.
222 **
223 **	Parameters:
224 **		e -- the envelope to clear.
225 **		fullclear - if set, the current envelope is total
226 **			garbage and should be ignored; otherwise,
227 **			release any resources it may indicate.
228 **
229 **	Returns:
230 **		none.
231 **
232 **	Side Effects:
233 **		Closes files associated with the envelope.
234 **		Marks the envelope as unallocated.
235 */
236 
237 void
238 clearenvelope(e, fullclear)
239 	register ENVELOPE *e;
240 	bool fullclear;
241 {
242 	register HDR *bh;
243 	register HDR **nhp;
244 	extern ENVELOPE BlankEnvelope;
245 
246 	if (!fullclear)
247 	{
248 		/* clear out any file information */
249 		if (e->e_xfp != NULL)
250 			(void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
251 		if (e->e_dfp != NULL)
252 			(void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df);
253 		e->e_xfp = e->e_dfp = NULL;
254 	}
255 
256 	/* now clear out the data */
257 	STRUCTCOPY(BlankEnvelope, *e);
258 	if (Verbose)
259 		e->e_sendmode = SM_DELIVER;
260 	bh = BlankEnvelope.e_header;
261 	nhp = &e->e_header;
262 	while (bh != NULL)
263 	{
264 		*nhp = (HDR *) xalloc(sizeof *bh);
265 		bcopy((char *) bh, (char *) *nhp, sizeof *bh);
266 		bh = bh->h_link;
267 		nhp = &(*nhp)->h_link;
268 	}
269 }
270 /*
271 **  INITSYS -- initialize instantiation of system
272 **
273 **	In Daemon mode, this is done in the child.
274 **
275 **	Parameters:
276 **		none.
277 **
278 **	Returns:
279 **		none.
280 **
281 **	Side Effects:
282 **		Initializes the system macros, some global variables,
283 **		etc.  In particular, the current time in various
284 **		forms is set.
285 */
286 
287 void
288 initsys(e)
289 	register ENVELOPE *e;
290 {
291 	static char cbuf[5];			/* holds hop count */
292 	static char pbuf[10];			/* holds pid */
293 #ifdef TTYNAME
294 	static char ybuf[60];			/* holds tty id */
295 	register char *p;
296 #endif /* TTYNAME */
297 	extern char *ttyname();
298 	extern void settime();
299 	extern char Version[];
300 
301 	/*
302 	**  Give this envelope a reality.
303 	**	I.e., an id, a transcript, and a creation time.
304 	*/
305 
306 	openxscript(e);
307 	e->e_ctime = curtime();
308 
309 	/*
310 	**  Set OutChannel to something useful if stdout isn't it.
311 	**	This arranges that any extra stuff the mailer produces
312 	**	gets sent back to the user on error (because it is
313 	**	tucked away in the transcript).
314 	*/
315 
316 	if (OpMode == MD_DAEMON && !bitset(EF_QUEUERUN, e->e_flags) &&
317 	    e->e_xfp != NULL)
318 		OutChannel = e->e_xfp;
319 
320 	/*
321 	**  Set up some basic system macros.
322 	*/
323 
324 	/* process id */
325 	(void) sprintf(pbuf, "%d", getpid());
326 	define('p', pbuf, e);
327 
328 	/* hop count */
329 	(void) sprintf(cbuf, "%d", e->e_hopcount);
330 	define('c', cbuf, e);
331 
332 	/* time as integer, unix time, arpa time */
333 	settime(e);
334 
335 #ifdef TTYNAME
336 	/* tty name */
337 	if (macvalue('y', e) == NULL)
338 	{
339 		p = ttyname(2);
340 		if (p != NULL)
341 		{
342 			if (strrchr(p, '/') != NULL)
343 				p = strrchr(p, '/') + 1;
344 			(void) strcpy(ybuf, p);
345 			define('y', ybuf, e);
346 		}
347 	}
348 #endif /* TTYNAME */
349 }
350 /*
351 **  SETTIME -- set the current time.
352 **
353 **	Parameters:
354 **		none.
355 **
356 **	Returns:
357 **		none.
358 **
359 **	Side Effects:
360 **		Sets the various time macros -- $a, $b, $d, $t.
361 */
362 
363 void
364 settime(e)
365 	register ENVELOPE *e;
366 {
367 	register char *p;
368 	auto time_t now;
369 	static char tbuf[20];			/* holds "current" time */
370 	static char dbuf[30];			/* holds ctime(tbuf) */
371 	register struct tm *tm;
372 	extern char *arpadate();
373 	extern struct tm *gmtime();
374 
375 	now = curtime();
376 	tm = gmtime(&now);
377 	(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
378 			tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
379 	define('t', tbuf, e);
380 	(void) strcpy(dbuf, ctime(&now));
381 	p = strchr(dbuf, '\n');
382 	if (p != NULL)
383 		*p = '\0';
384 	define('d', dbuf, e);
385 	p = newstr(arpadate(dbuf));
386 	if (macvalue('a', e) == NULL)
387 		define('a', p, e);
388 	define('b', p, e);
389 }
390 /*
391 **  OPENXSCRIPT -- Open transcript file
392 **
393 **	Creates a transcript file for possible eventual mailing or
394 **	sending back.
395 **
396 **	Parameters:
397 **		e -- the envelope to create the transcript in/for.
398 **
399 **	Returns:
400 **		none
401 **
402 **	Side Effects:
403 **		Creates the transcript file.
404 */
405 
406 #ifndef O_APPEND
407 #define O_APPEND	0
408 #endif
409 
410 void
411 openxscript(e)
412 	register ENVELOPE *e;
413 {
414 	register char *p;
415 	int fd;
416 
417 	if (e->e_xfp != NULL)
418 		return;
419 	p = queuename(e, 'x');
420 	fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
421 	if (fd < 0)
422 	{
423 		syserr("Can't create transcript file %s", p);
424 		fd = open("/dev/null", O_WRONLY, 0644);
425 		if (fd < 0)
426 			syserr("!Can't open /dev/null");
427 	}
428 	e->e_xfp = fdopen(fd, "w");
429 }
430 /*
431 **  CLOSEXSCRIPT -- close the transcript file.
432 **
433 **	Parameters:
434 **		e -- the envelope containing the transcript to close.
435 **
436 **	Returns:
437 **		none.
438 **
439 **	Side Effects:
440 **		none.
441 */
442 
443 void
444 closexscript(e)
445 	register ENVELOPE *e;
446 {
447 	if (e->e_xfp == NULL)
448 		return;
449 	(void) xfclose(e->e_xfp, "closexscript", e->e_id);
450 	e->e_xfp = NULL;
451 }
452 /*
453 **  SETSENDER -- set the person who this message is from
454 **
455 **	Under certain circumstances allow the user to say who
456 **	s/he is (using -f or -r).  These are:
457 **	1.  The user's uid is zero (root).
458 **	2.  The user's login name is in an approved list (typically
459 **	    from a network server).
460 **	3.  The address the user is trying to claim has a
461 **	    "!" character in it (since #2 doesn't do it for
462 **	    us if we are dialing out for UUCP).
463 **	A better check to replace #3 would be if the
464 **	effective uid is "UUCP" -- this would require me
465 **	to rewrite getpwent to "grab" uucp as it went by,
466 **	make getname more nasty, do another passwd file
467 **	scan, or compile the UID of "UUCP" into the code,
468 **	all of which are reprehensible.
469 **
470 **	Assuming all of these fail, we figure out something
471 **	ourselves.
472 **
473 **	Parameters:
474 **		from -- the person we would like to believe this message
475 **			is from, as specified on the command line.
476 **		e -- the envelope in which we would like the sender set.
477 **		delimptr -- if non-NULL, set to the location of the
478 **			trailing delimiter.
479 **		internal -- set if this address is coming from an internal
480 **			source such as an owner alias.
481 **
482 **	Returns:
483 **		none.
484 **
485 **	Side Effects:
486 **		sets sendmail's notion of who the from person is.
487 */
488 
489 void
490 setsender(from, e, delimptr, internal)
491 	char *from;
492 	register ENVELOPE *e;
493 	char **delimptr;
494 	bool internal;
495 {
496 	register char **pvp;
497 	char *realname = NULL;
498 	register struct passwd *pw;
499 	char delimchar;
500 	char buf[MAXNAME];
501 	char pvpbuf[PSBUFSIZE];
502 	extern struct passwd *getpwnam();
503 	extern char *FullName;
504 
505 	if (tTd(45, 1))
506 		printf("setsender(%s)\n", from == NULL ? "" : from);
507 
508 	/*
509 	**  Figure out the real user executing us.
510 	**	Username can return errno != 0 on non-errors.
511 	*/
512 
513 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP)
514 		realname = from;
515 	if (realname == NULL || realname[0] == '\0')
516 		realname = username();
517 
518 	if (ConfigLevel < 2)
519 		SuprErrs = TRUE;
520 
521 	delimchar = internal ? '\0' : ' ';
522 	if (from == NULL ||
523 	    parseaddr(from, &e->e_from, 1, delimchar, delimptr, e) == NULL)
524 	{
525 		/* log garbage addresses for traceback */
526 # ifdef LOG
527 		if (from != NULL && LogLevel > 2)
528 		{
529 			char *p;
530 			char ebuf[MAXNAME * 2 + 2];
531 
532 			p = macvalue('_', e);
533 			if (p == NULL)
534 			{
535 				char *host = RealHostName;
536 				if (host == NULL)
537 					host = MyHostName;
538 				(void) sprintf(ebuf, "%s@%s", realname, host);
539 				p = ebuf;
540 			}
541 			syslog(LOG_NOTICE,
542 				"from=%s unparseable, received from %s",
543 				from, p);
544 		}
545 # endif /* LOG */
546 		if (from != NULL)
547 			SuprErrs = TRUE;
548 		if (from == realname ||
549 		    parseaddr(from = newstr(realname), &e->e_from, 1, ' ', NULL, e) == NULL)
550 		{
551 			SuprErrs = TRUE;
552 			if (parseaddr("postmaster", &e->e_from, 1, ' ', NULL, e) == NULL)
553 				syserr("553 setsender: can't even parse postmaster!");
554 		}
555 	}
556 	else
557 		FromFlag = TRUE;
558 	e->e_from.q_flags |= QDONTSEND;
559 	if (tTd(45, 5))
560 	{
561 		printf("setsender: QDONTSEND ");
562 		printaddr(&e->e_from, FALSE);
563 	}
564 	SuprErrs = FALSE;
565 
566 	pvp = NULL;
567 	if (e->e_from.q_mailer == LocalMailer)
568 	{
569 # ifdef USERDB
570 		register char *p;
571 		extern char *udbsender();
572 # endif
573 
574 		if (!internal)
575 		{
576 			/* if the user has given fullname already, don't redefine */
577 			if (FullName == NULL)
578 				FullName = macvalue('x', e);
579 			if (FullName != NULL && FullName[0] == '\0')
580 				FullName = NULL;
581 
582 # ifdef USERDB
583 			p = udbsender(from);
584 
585 			if (p != NULL)
586 			{
587 				/*
588 				**  We have an alternate address for the sender
589 				*/
590 
591 				pvp = prescan(p, '\0', pvpbuf, NULL);
592 			}
593 # endif /* USERDB */
594 		}
595 
596 		if ((pw = getpwnam(e->e_from.q_user)) != NULL)
597 		{
598 			/*
599 			**  Process passwd file entry.
600 			*/
601 
602 
603 			/* extract home directory */
604 			e->e_from.q_home = newstr(pw->pw_dir);
605 			define('z', e->e_from.q_home, e);
606 
607 			/* extract user and group id */
608 			e->e_from.q_uid = pw->pw_uid;
609 			e->e_from.q_gid = pw->pw_gid;
610 
611 			/* extract full name from passwd file */
612 			if (FullName == NULL && pw->pw_gecos != NULL &&
613 			    strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
614 			    !internal)
615 			{
616 				buildfname(pw->pw_gecos, e->e_from.q_user, buf);
617 				if (buf[0] != '\0')
618 					FullName = newstr(buf);
619 			}
620 		}
621 		if (FullName != NULL && !internal)
622 			define('x', FullName, e);
623 	}
624 	else if (!internal)
625 	{
626 		if (e->e_from.q_home == NULL)
627 			e->e_from.q_home = getenv("HOME");
628 		e->e_from.q_uid = getuid();
629 		e->e_from.q_gid = getgid();
630 	}
631 
632 	/*
633 	**  Rewrite the from person to dispose of possible implicit
634 	**	links in the net.
635 	*/
636 
637 	if (pvp == NULL)
638 		pvp = prescan(from, '\0', pvpbuf, NULL);
639 	if (pvp == NULL)
640 	{
641 		/* don't need to give error -- prescan did that already */
642 # ifdef LOG
643 		if (LogLevel > 2)
644 			syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
645 # endif
646 		finis();
647 	}
648 	(void) rewrite(pvp, 3, e);
649 	(void) rewrite(pvp, 1, e);
650 	(void) rewrite(pvp, 4, e);
651 	cataddr(pvp, NULL, buf, sizeof buf, '\0');
652 	e->e_sender = newstr(buf);
653 	define('f', e->e_sender, e);
654 
655 	/* save the domain spec if this mailer wants it */
656 	if (!internal && e->e_from.q_mailer != NULL &&
657 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
658 	{
659 		extern char **copyplist();
660 
661 		while (*pvp != NULL && strcmp(*pvp, "@") != 0)
662 			pvp++;
663 		if (*pvp != NULL)
664 			e->e_fromdomain = copyplist(pvp, TRUE);
665 	}
666 }
667