|
|
1.1 root 1: #include <pwd.h>
2: #include <sys/time.h>
3: #include "sendmail.h"
4: #include <sys/stat.h>
5:
6: SCCSID(@(#)envelope.c 4.2 8/21/83);
7:
8: /*
9: ** NEWENVELOPE -- allocate a new envelope
10: **
11: ** Supports inheritance.
12: **
13: ** Parameters:
14: ** e -- the new envelope to fill in.
15: **
16: ** Returns:
17: ** e.
18: **
19: ** Side Effects:
20: ** none.
21: */
22:
23: ENVELOPE *
24: newenvelope(e)
25: register ENVELOPE *e;
26: {
27: register HDR *bh;
28: register HDR **nhp;
29: register ENVELOPE *parent;
30: extern putheader(), putbody();
31: extern ENVELOPE BlankEnvelope;
32:
33: parent = CurEnv;
34: if (e == CurEnv)
35: parent = e->e_parent;
36: clear((char *) e, sizeof *e);
37: bmove((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
38: e->e_parent = parent;
39: e->e_ctime = curtime();
40: e->e_puthdr = putheader;
41: e->e_putbody = putbody;
42: bh = BlankEnvelope.e_header;
43: nhp = &e->e_header;
44: while (bh != NULL)
45: {
46: *nhp = (HDR *) xalloc(sizeof *bh);
47: bmove((char *) bh, (char *) *nhp, sizeof *bh);
48: bh = bh->h_link;
49: nhp = &(*nhp)->h_link;
50: }
51: if (CurEnv->e_xfp != NULL)
52: (void) fflush(CurEnv->e_xfp);
53:
54: return (e);
55: }
56: /*
57: ** DROPENVELOPE -- deallocate an envelope.
58: **
59: ** Parameters:
60: ** e -- the envelope to deallocate.
61: **
62: ** Returns:
63: ** none.
64: **
65: ** Side Effects:
66: ** housekeeping necessary to dispose of an envelope.
67: ** Unlocks this queue file.
68: */
69:
70: dropenvelope(e)
71: register ENVELOPE *e;
72: {
73: bool queueit = FALSE;
74: register ADDRESS *q;
75:
76: #ifdef DEBUG
77: if (tTd(50, 1))
78: {
79: printf("dropenvelope %x id=", e);
80: xputs(e->e_id);
81: printf(" flags=%o\n", e->e_flags);
82: }
83: #endif DEBUG
84: #ifdef LOG
85: if (LogLevel > 10)
86: syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
87: e->e_id == NULL ? "(none)" : e->e_id,
88: e->e_flags, getpid());
89: #endif LOG
90:
91: /* we must have an id to remove disk files */
92: if (e->e_id == NULL)
93: return;
94:
95: /*
96: ** Extract state information from dregs of send list.
97: */
98:
99: for (q = e->e_sendqueue; q != NULL; q = q->q_next)
100: {
101: if (bitset(QQUEUEUP, q->q_flags))
102: queueit = TRUE;
103: }
104:
105: /*
106: ** Send back return receipts as requested.
107: */
108:
109: if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
110: {
111: auto ADDRESS *rlist = NULL;
112:
113: sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist);
114: (void) returntosender("Return receipt", rlist, FALSE);
115: }
116:
117: /*
118: ** Arrange to send error messages if there are fatal errors.
119: */
120:
121: if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET)
122: savemail(e);
123:
124: /*
125: ** Instantiate or deinstantiate the queue.
126: */
127:
128: if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
129: bitset(EF_CLRQUEUE, e->e_flags))
130: {
131: if (e->e_dfp != NULL)
132: (void) fclose(e->e_dfp);
133: if (e->e_df != NULL)
134: xunlink(e->e_df);
135: xunlink(queuename(e, 'q'));
136: }
137: else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
138: {
139: #ifdef QUEUE
140: queueup(e, FALSE, FALSE);
141: #else QUEUE
142: syserr("dropenvelope: queueup");
143: #endif QUEUE
144: }
145:
146: /* now unlock the job */
147: closexscript(e);
148: unlockqueue(e);
149:
150: /* make sure that this envelope is marked unused */
151: e->e_id = e->e_df = NULL;
152: e->e_dfp = NULL;
153: }
154: /*
155: ** CLEARENVELOPE -- clear an envelope without unlocking
156: **
157: ** This is normally used by a child process to get a clean
158: ** envelope without disturbing the parent.
159: **
160: ** Parameters:
161: ** e -- the envelope to clear.
162: **
163: ** Returns:
164: ** none.
165: **
166: ** Side Effects:
167: ** Closes files associated with the envelope.
168: ** Marks the envelope as unallocated.
169: */
170:
171: clearenvelope(e)
172: register ENVELOPE *e;
173: {
174: /* clear out any file information */
175: if (e->e_xfp != NULL)
176: (void) fclose(e->e_xfp);
177: if (e->e_dfp != NULL)
178: (void) fclose(e->e_dfp);
179: e->e_xfp = e->e_dfp = NULL;
180:
181: /* now expunge names of objects */
182: e->e_df = e->e_id = NULL;
183:
184: /* and the flags which are now meaningless */
185: e->e_flags = 0;
186: }
187: /*
188: ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope
189: **
190: ** Parameters:
191: ** e -- the envelope to unlock.
192: **
193: ** Returns:
194: ** none
195: **
196: ** Side Effects:
197: ** unlocks the queue for `e'.
198: */
199:
200: unlockqueue(e)
201: ENVELOPE *e;
202: {
203: /* remove the transcript */
204: #ifdef DEBUG
205: # ifdef LOG
206: if (LogLevel > 19)
207: syslog(LOG_DEBUG, "%s: unlock", e->e_id);
208: # endif LOG
209: if (!tTd(51, 4))
210: #endif DEBUG
211: xunlink(queuename(e, 'x'));
212:
213: # ifdef QUEUE
214: /* last but not least, remove the lock */
215: xunlink(queuename(e, 'l'));
216: # endif QUEUE
217: }
218: /*
219: ** INITSYS -- initialize instantiation of system
220: **
221: ** In Daemon mode, this is done in the child.
222: **
223: ** Parameters:
224: ** none.
225: **
226: ** Returns:
227: ** none.
228: **
229: ** Side Effects:
230: ** Initializes the system macros, some global variables,
231: ** etc. In particular, the current time in various
232: ** forms is set.
233: */
234:
235: initsys()
236: {
237: static char cbuf[5]; /* holds hop count */
238: static char pbuf[10]; /* holds pid */
239: static char ybuf[10]; /* holds tty id */
240: register char *p;
241: extern char *ttyname();
242: extern char *macvalue();
243: extern char Version[];
244:
245: /*
246: ** Give this envelope a reality.
247: ** I.e., an id, a transcript, and a creation time.
248: */
249:
250: openxscript(CurEnv);
251: CurEnv->e_ctime = curtime();
252:
253: /*
254: ** Set OutChannel to something useful if stdout isn't it.
255: ** This arranges that any extra stuff the mailer produces
256: ** gets sent back to the user on error (because it is
257: ** tucked away in the transcript).
258: */
259:
260: if (OpMode == MD_DAEMON && QueueRun)
261: OutChannel = CurEnv->e_xfp;
262:
263: /*
264: ** Set up some basic system macros.
265: */
266:
267: /* process id */
268: (void) sprintf(pbuf, "%d", getpid());
269: define('p', pbuf, CurEnv);
270:
271: /* hop count */
272: (void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
273: define('c', cbuf, CurEnv);
274:
275: /* time as integer, unix time, arpa time */
276: settime();
277:
278: /* tty name */
279: if (macvalue('y', CurEnv) == NULL)
280: {
281: p = ttyname(2);
282: if (p != NULL)
283: {
284: if (rindex(p, '/') != NULL)
285: p = rindex(p, '/') + 1;
286: (void) strcpy(ybuf, p);
287: define('y', ybuf, CurEnv);
288: }
289: }
290: }
291: /*
292: ** SETTIME -- set the current time.
293: **
294: ** Parameters:
295: ** none.
296: **
297: ** Returns:
298: ** none.
299: **
300: ** Side Effects:
301: ** Sets the various time macros -- $a, $b, $d, $t.
302: */
303:
304: settime()
305: {
306: register char *p;
307: auto time_t now;
308: static char tbuf[20]; /* holds "current" time */
309: static char dbuf[30]; /* holds ctime(tbuf) */
310: register struct tm *tm;
311: extern char *arpadate();
312: extern struct tm *gmtime();
313: extern char *macvalue();
314:
315: now = curtime();
316: tm = gmtime(&now);
317: (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1,
318: tm->tm_mday, tm->tm_hour, tm->tm_min);
319: define('t', tbuf, CurEnv);
320: (void) strcpy(dbuf, ctime(&now));
321: *index(dbuf, '\n') = '\0';
322: if (macvalue('d', CurEnv) == NULL)
323: define('d', dbuf, CurEnv);
324: p = newstr(arpadate(dbuf));
325: if (macvalue('a', CurEnv) == NULL)
326: define('a', p, CurEnv);
327: define('b', p, CurEnv);
328: }
329: /*
330: ** QUEUENAME -- build a file name in the queue directory for this envelope.
331: **
332: ** Assigns an id code if one does not already exist.
333: ** This code is very careful to avoid trashing existing files
334: ** under any circumstances.
335: ** We first create an nf file that is only used when
336: ** assigning an id. This file is always empty, so that
337: ** we can never accidently truncate an lf file.
338: **
339: ** Parameters:
340: ** e -- envelope to build it in/from.
341: ** type -- the file type, used as the first character
342: ** of the file name.
343: **
344: ** Returns:
345: ** a pointer to the new file name (in a static buffer).
346: **
347: ** Side Effects:
348: ** Will create the lf and qf files if no id code is
349: ** already assigned. This will cause the envelope
350: ** to be modified.
351: */
352:
353: char *
354: queuename(e, type)
355: register ENVELOPE *e;
356: char type;
357: {
358: static char buf[MAXNAME];
359: static int pid = -1;
360: char c1 = 'A';
361: char c2 = 'A';
362:
363: if (e->e_id == NULL)
364: {
365: char qf[20];
366: char lf[20];
367: char nf[20];
368:
369: /* find a unique id */
370: if (pid != getpid())
371: {
372: /* new process -- start back at "AA" */
373: pid = getpid();
374: c1 = 'A';
375: c2 = 'A' - 1;
376: }
377: (void) sprintf(qf, "qfAA%05d", pid);
378: strcpy(lf, qf);
379: lf[0] = 'l';
380: strcpy(nf, qf);
381: nf[0] = 'n';
382:
383: while (c1 < '~' || c2 < 'Z')
384: {
385: int i;
386:
387: if (c2 >= 'Z')
388: {
389: c1++;
390: c2 = 'A' - 1;
391: }
392: qf[2] = lf[2] = nf[2] = c1;
393: qf[3] = lf[3] = nf[3] = ++c2;
394: # ifdef DEBUG
395: if (tTd(7, 20))
396: printf("queuename: trying \"%s\"\n", nf);
397: # endif DEBUG
398: # ifdef QUEUE
399: if (access(lf, 0) >= 0 || access(qf, 0) >= 0)
400: continue;
401: errno = 0;
402: i = creat(nf, FileMode);
403: if (i < 0)
404: {
405: (void) unlink(nf); /* kernel bug */
406: continue;
407: }
408: (void) close(i);
409: i = link(nf, lf);
410: (void) unlink(nf);
411: if (i < 0)
412: continue;
413: if (link(lf, qf) >= 0)
414: break;
415: (void) unlink(lf);
416: # else QUEUE
417: if (close(creat(qf, FileMode)) < 0)
418: continue;
419: # endif QUEUE
420: }
421: if (c1 >= '~' && c2 >= 'Z')
422: {
423: syserr("queuename: Cannot create \"%s\" in \"%s\"",
424: lf, QueueDir);
425: exit(EX_OSERR);
426: }
427: e->e_id = newstr(&qf[2]);
428: define('i', e->e_id, e);
429: # ifdef DEBUG
430: if (tTd(7, 1))
431: printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
432: # ifdef LOG
433: if (LogLevel > 16)
434: syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
435: # endif LOG
436: # endif DEBUG
437: }
438:
439: if (type == '\0')
440: return (NULL);
441: (void) sprintf(buf, "%cf%s", type, e->e_id);
442: # ifdef DEBUG
443: if (tTd(7, 2))
444: printf("queuename: %s\n", buf);
445: # endif DEBUG
446: return (buf);
447: }
448: /*
449: ** OPENXSCRIPT -- Open transcript file
450: **
451: ** Creates a transcript file for possible eventual mailing or
452: ** sending back.
453: **
454: ** Parameters:
455: ** e -- the envelope to create the transcript in/for.
456: **
457: ** Returns:
458: ** none
459: **
460: ** Side Effects:
461: ** Creates the transcript file.
462: */
463:
464: openxscript(e)
465: register ENVELOPE *e;
466: {
467: register char *p;
468:
469: # ifdef LOG
470: if (LogLevel > 19)
471: syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)");
472: # endif LOG
473: if (e->e_xfp != NULL)
474: return;
475: p = queuename(e, 'x');
476: e->e_xfp = fopen(p, "w");
477: if (e->e_xfp == NULL)
478: syserr("Can't create %s", p);
479: else
480: (void) chmod(p, 0644);
481: }
482: /*
483: ** CLOSEXSCRIPT -- close the transcript file.
484: **
485: ** Parameters:
486: ** e -- the envelope containing the transcript to close.
487: **
488: ** Returns:
489: ** none.
490: **
491: ** Side Effects:
492: ** none.
493: */
494:
495: closexscript(e)
496: register ENVELOPE *e;
497: {
498: if (e->e_xfp == NULL)
499: return;
500: (void) fclose(e->e_xfp);
501: e->e_xfp = NULL;
502: }
503: /*
504: ** SETSENDER -- set the person who this message is from
505: **
506: ** Under certain circumstances allow the user to say who
507: ** s/he is (using -f or -r). These are:
508: ** 1. The user's uid is zero (root).
509: ** 2. The user's login name is in an approved list (typically
510: ** from a network server).
511: ** 3. The address the user is trying to claim has a
512: ** "!" character in it (since #2 doesn't do it for
513: ** us if we are dialing out for UUCP).
514: ** A better check to replace #3 would be if the
515: ** effective uid is "UUCP" -- this would require me
516: ** to rewrite getpwent to "grab" uucp as it went by,
517: ** make getname more nasty, do another passwd file
518: ** scan, or compile the UID of "UUCP" into the code,
519: ** all of which are reprehensible.
520: **
521: ** Assuming all of these fail, we figure out something
522: ** ourselves.
523: **
524: ** Parameters:
525: ** from -- the person we would like to believe this message
526: ** is from, as specified on the command line.
527: **
528: ** Returns:
529: ** none.
530: **
531: ** Side Effects:
532: ** sets sendmail's notion of who the from person is.
533: */
534:
535: setsender(from)
536: char *from;
537: {
538: register char **pvp;
539: register struct passwd *pw = NULL;
540: char *realname = NULL;
541: char buf[MAXNAME];
542: extern char *macvalue();
543: extern char **prescan();
544: extern bool safefile();
545: extern char *FullName;
546:
547: # ifdef DEBUG
548: if (tTd(45, 1))
549: printf("setsender(%s)\n", from == NULL ? "" : from);
550: # endif DEBUG
551:
552: /*
553: ** Figure out the real user executing us.
554: ** Username can return errno != 0 on non-errors.
555: */
556:
557: if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
558: realname = from;
559: if (realname == NULL || realname[0] == '\0')
560: {
561: extern char *username();
562:
563: realname = username();
564: errno = 0;
565: }
566: if (realname == NULL || realname[0] == '\0')
567: {
568: extern struct passwd *getpwuid();
569:
570: pw = getpwuid(getruid());
571: if (pw != NULL)
572: realname = pw->pw_name;
573: }
574: if (realname == NULL || realname[0] == '\0')
575: {
576: syserr("Who are you?");
577: realname = "root";
578: }
579:
580: /*
581: ** Determine if this real person is allowed to alias themselves.
582: */
583:
584: if (from != NULL)
585: {
586: extern bool trusteduser();
587:
588: if (!trusteduser(realname) &&
589: # ifdef DEBUG
590: (!tTd(1, 9) || getuid() != geteuid()) &&
591: # endif DEBUG
592: index(from, '!') == NULL && getuid() != 0)
593: {
594: /* network sends -r regardless (why why why?) */
595: /* syserr("%s, you cannot use the -f flag", realname); */
596: from = NULL;
597: }
598: else if (strcmp(from, realname) != 0)
599: pw = NULL;
600: }
601:
602: SuprErrs = TRUE;
603: if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL)
604: {
605: from = newstr(realname);
606: (void) parseaddr(from, &CurEnv->e_from, 1, '\0');
607: }
608: else
609: FromFlag = TRUE;
610: CurEnv->e_from.q_flags |= QDONTSEND;
611: SuprErrs = FALSE;
612:
613: if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer)
614: {
615: extern struct passwd *getpwnam();
616:
617: pw = getpwnam(CurEnv->e_from.q_user);
618: }
619:
620: /*
621: ** Process passwd file entry.
622: */
623:
624: if (pw != NULL)
625: {
626: /* extract home directory */
627: CurEnv->e_from.q_home = newstr(pw->pw_dir);
628:
629: /* extract user and group id */
630: CurEnv->e_from.q_uid = pw->pw_uid;
631: CurEnv->e_from.q_gid = pw->pw_gid;
632:
633: /* run user's .mailcf file */
634: define('z', CurEnv->e_from.q_home, CurEnv);
635: expand("$z/.mailcf", buf, &buf[sizeof buf - 1], CurEnv);
636: if (safefile(buf, getruid(), S_IREAD))
637: readcf(buf, FALSE);
638:
639: /* if the user has given fullname already, don't redefine */
640: if (FullName == NULL)
641: FullName = macvalue('x', CurEnv);
642: if (FullName != NULL && FullName[0] == '\0')
643: FullName = NULL;
644:
645: /* extract full name from passwd file */
646: if (FullName == NULL && pw->pw_gecos != NULL &&
647: strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0)
648: {
649: buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
650: if (buf[0] != '\0')
651: FullName = newstr(buf);
652: }
653: if (FullName != NULL)
654: define('x', FullName, CurEnv);
655: }
656: else
657: {
658: #ifndef V6
659: if (CurEnv->e_from.q_home == NULL)
660: CurEnv->e_from.q_home = getenv("HOME");
661: #endif V6
662: CurEnv->e_from.q_uid = getuid();
663: CurEnv->e_from.q_gid = getgid();
664: }
665:
666: if (CurEnv->e_from.q_uid != 0)
667: {
668: DefUid = CurEnv->e_from.q_uid;
669: DefGid = CurEnv->e_from.q_gid;
670: }
671:
672: /*
673: ** Rewrite the from person to dispose of possible implicit
674: ** links in the net.
675: */
676:
677: pvp = prescan(from, '\0');
678: if (pvp == NULL)
679: {
680: syserr("cannot prescan from (%s)", from);
681: finis();
682: }
683: rewrite(pvp, 3);
684: rewrite(pvp, 1);
685: rewrite(pvp, 4);
686: cataddr(pvp, buf, sizeof buf);
687: define('f', newstr(buf), CurEnv);
688:
689: /* save the domain spec if this mailer wants it */
690: if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
691: {
692: extern char **copyplist();
693:
694: while (*pvp != NULL && strcmp(*pvp, "@") != 0)
695: pvp++;
696: if (*pvp != NULL)
697: CurEnv->e_fromdomain = copyplist(pvp, TRUE);
698: }
699: }
700: /*
701: ** TRUSTEDUSER -- tell us if this user is to be trusted.
702: **
703: ** Parameters:
704: ** user -- the user to be checked.
705: **
706: ** Returns:
707: ** TRUE if the user is in an approved list.
708: ** FALSE otherwise.
709: **
710: ** Side Effects:
711: ** none.
712: */
713:
714: bool
715: trusteduser(user)
716: char *user;
717: {
718: register char **ulist;
719: extern char *TrustedUsers[];
720:
721: for (ulist = TrustedUsers; *ulist != NULL; ulist++)
722: if (strcmp(*ulist, user) == 0)
723: return (TRUE);
724: return (FALSE);
725: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.