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