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