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