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