1 | /* |
---|
2 | * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. |
---|
3 | * All rights reserved. |
---|
4 | * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. |
---|
5 | * Copyright (c) 1988, 1993 |
---|
6 | * The Regents of the University of California. All rights reserved. |
---|
7 | * |
---|
8 | * By using this file, you agree to the terms and conditions set |
---|
9 | * forth in the LICENSE file which can be found at the top level of |
---|
10 | * the sendmail distribution. |
---|
11 | * |
---|
12 | */ |
---|
13 | |
---|
14 | #include <sendmail.h> |
---|
15 | |
---|
16 | SM_RCSID("@(#)$Id: envelope.c,v 1.1.1.1 2003-04-08 15:08:35 zacheiss Exp $") |
---|
17 | |
---|
18 | /* |
---|
19 | ** CLRSESSENVELOPE -- clear session oriented data in an envelope |
---|
20 | ** |
---|
21 | ** Parameters: |
---|
22 | ** e -- the envelope to clear. |
---|
23 | ** |
---|
24 | ** Returns: |
---|
25 | ** none. |
---|
26 | */ |
---|
27 | |
---|
28 | void |
---|
29 | clrsessenvelope(e) |
---|
30 | ENVELOPE *e; |
---|
31 | { |
---|
32 | #if SASL |
---|
33 | macdefine(&e->e_macro, A_PERM, macid("{auth_type}"), ""); |
---|
34 | macdefine(&e->e_macro, A_PERM, macid("{auth_authen}"), ""); |
---|
35 | macdefine(&e->e_macro, A_PERM, macid("{auth_author}"), ""); |
---|
36 | macdefine(&e->e_macro, A_PERM, macid("{auth_ssf}"), ""); |
---|
37 | #endif /* SASL */ |
---|
38 | #if STARTTLS |
---|
39 | macdefine(&e->e_macro, A_PERM, macid("{cert_issuer}"), ""); |
---|
40 | macdefine(&e->e_macro, A_PERM, macid("{cert_subject}"), ""); |
---|
41 | macdefine(&e->e_macro, A_PERM, macid("{cipher_bits}"), ""); |
---|
42 | macdefine(&e->e_macro, A_PERM, macid("{cipher}"), ""); |
---|
43 | macdefine(&e->e_macro, A_PERM, macid("{tls_version}"), ""); |
---|
44 | macdefine(&e->e_macro, A_PERM, macid("{verify}"), ""); |
---|
45 | # if _FFR_TLS_1 |
---|
46 | macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), ""); |
---|
47 | macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), ""); |
---|
48 | macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), ""); |
---|
49 | # endif /* _FFR_TLS_1 */ |
---|
50 | #endif /* STARTTLS */ |
---|
51 | } |
---|
52 | |
---|
53 | /* |
---|
54 | ** NEWENVELOPE -- fill in a new envelope |
---|
55 | ** |
---|
56 | ** Supports inheritance. |
---|
57 | ** |
---|
58 | ** Parameters: |
---|
59 | ** e -- the new envelope to fill in. |
---|
60 | ** parent -- the envelope to be the parent of e. |
---|
61 | ** rpool -- either NULL, or a pointer to a resource pool |
---|
62 | ** from which envelope memory is allocated, and |
---|
63 | ** to which envelope resources are attached. |
---|
64 | ** |
---|
65 | ** Returns: |
---|
66 | ** e. |
---|
67 | ** |
---|
68 | ** Side Effects: |
---|
69 | ** none. |
---|
70 | */ |
---|
71 | |
---|
72 | ENVELOPE * |
---|
73 | newenvelope(e, parent, rpool) |
---|
74 | register ENVELOPE *e; |
---|
75 | register ENVELOPE *parent; |
---|
76 | SM_RPOOL_T *rpool; |
---|
77 | { |
---|
78 | /* |
---|
79 | ** This code used to read: |
---|
80 | ** if (e == parent && e->e_parent != NULL) |
---|
81 | ** parent = e->e_parent; |
---|
82 | ** So if e == parent && e->e_parent == NULL then we would |
---|
83 | ** set e->e_parent = e, which creates a loop in the e_parent chain. |
---|
84 | ** This meant macvalue() could go into an infinite loop. |
---|
85 | */ |
---|
86 | |
---|
87 | if (e == parent) |
---|
88 | parent = e->e_parent; |
---|
89 | clearenvelope(e, true, rpool); |
---|
90 | if (e == CurEnv) |
---|
91 | memmove((char *) &e->e_from, |
---|
92 | (char *) &NullAddress, |
---|
93 | sizeof e->e_from); |
---|
94 | else |
---|
95 | memmove((char *) &e->e_from, |
---|
96 | (char *) &CurEnv->e_from, |
---|
97 | sizeof e->e_from); |
---|
98 | e->e_parent = parent; |
---|
99 | assign_queueid(e); |
---|
100 | e->e_ctime = curtime(); |
---|
101 | if (parent != NULL) |
---|
102 | { |
---|
103 | e->e_msgpriority = parent->e_msgsize; |
---|
104 | #if _FFR_QUARANTINE |
---|
105 | if (parent->e_quarmsg == NULL) |
---|
106 | { |
---|
107 | e->e_quarmsg = NULL; |
---|
108 | macdefine(&e->e_macro, A_PERM, |
---|
109 | macid("{quarantine}"), ""); |
---|
110 | } |
---|
111 | else |
---|
112 | { |
---|
113 | e->e_quarmsg = sm_rpool_strdup_x(rpool, |
---|
114 | parent->e_quarmsg); |
---|
115 | macdefine(&e->e_macro, A_PERM, |
---|
116 | macid("{quarantine}"), e->e_quarmsg); |
---|
117 | } |
---|
118 | #endif /* _FFR_QUARANTINE */ |
---|
119 | } |
---|
120 | e->e_puthdr = putheader; |
---|
121 | e->e_putbody = putbody; |
---|
122 | if (CurEnv->e_xfp != NULL) |
---|
123 | (void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT); |
---|
124 | |
---|
125 | return e; |
---|
126 | } |
---|
127 | |
---|
128 | /* values for msg_timeout, see also IS_* below for usage (bit layout) */ |
---|
129 | #define MSG_T_O 0x01 /* normal timeout */ |
---|
130 | #define MSG_T_O_NOW 0x02 /* NOW timeout */ |
---|
131 | #define MSG_NOT_BY 0x04 /* Deliver-By time exceeded, mode R */ |
---|
132 | #define MSG_WARN 0x10 /* normal queue warning */ |
---|
133 | #define MSG_WARN_BY 0x20 /* Deliver-By time exceeded, mode N */ |
---|
134 | |
---|
135 | #define IS_MSG_ERR(x) (((x) & 0x0f) != 0) /* return an error */ |
---|
136 | |
---|
137 | /* immediate return */ |
---|
138 | #define IS_IMM_RET(x) (((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0) |
---|
139 | #define IS_MSG_WARN(x) (((x) & 0xf0) != 0) /* return a warning */ |
---|
140 | |
---|
141 | /* |
---|
142 | ** DROPENVELOPE -- deallocate an envelope. |
---|
143 | ** |
---|
144 | ** Parameters: |
---|
145 | ** e -- the envelope to deallocate. |
---|
146 | ** fulldrop -- if set, do return receipts. |
---|
147 | ** split -- if true, split by recipient if message is queued up |
---|
148 | ** |
---|
149 | ** Returns: |
---|
150 | ** none. |
---|
151 | ** |
---|
152 | ** Side Effects: |
---|
153 | ** housekeeping necessary to dispose of an envelope. |
---|
154 | ** Unlocks this queue file. |
---|
155 | */ |
---|
156 | |
---|
157 | void |
---|
158 | dropenvelope(e, fulldrop, split) |
---|
159 | register ENVELOPE *e; |
---|
160 | bool fulldrop; |
---|
161 | bool split; |
---|
162 | { |
---|
163 | bool panic = false; |
---|
164 | bool queueit = false; |
---|
165 | int msg_timeout = 0; |
---|
166 | bool failure_return = false; |
---|
167 | bool delay_return = false; |
---|
168 | bool success_return = false; |
---|
169 | bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags); |
---|
170 | bool done = false; |
---|
171 | register ADDRESS *q; |
---|
172 | char *id = e->e_id; |
---|
173 | time_t now; |
---|
174 | char buf[MAXLINE]; |
---|
175 | |
---|
176 | if (tTd(50, 1)) |
---|
177 | { |
---|
178 | sm_dprintf("dropenvelope %p: id=", e); |
---|
179 | xputs(e->e_id); |
---|
180 | sm_dprintf(", flags="); |
---|
181 | printenvflags(e); |
---|
182 | if (tTd(50, 10)) |
---|
183 | { |
---|
184 | sm_dprintf("sendq="); |
---|
185 | printaddr(e->e_sendqueue, true); |
---|
186 | } |
---|
187 | } |
---|
188 | |
---|
189 | if (LogLevel > 84) |
---|
190 | sm_syslog(LOG_DEBUG, id, |
---|
191 | "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d", |
---|
192 | e->e_flags, OpMode, (int) CurrentPid); |
---|
193 | |
---|
194 | /* we must have an id to remove disk files */ |
---|
195 | if (id == NULL) |
---|
196 | return; |
---|
197 | |
---|
198 | /* if verify-only mode, we can skip most of this */ |
---|
199 | if (OpMode == MD_VERIFY) |
---|
200 | goto simpledrop; |
---|
201 | |
---|
202 | if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) |
---|
203 | logsender(e, NULL); |
---|
204 | e->e_flags &= ~EF_LOGSENDER; |
---|
205 | |
---|
206 | /* post statistics */ |
---|
207 | poststats(StatFile); |
---|
208 | |
---|
209 | /* |
---|
210 | ** Extract state information from dregs of send list. |
---|
211 | */ |
---|
212 | |
---|
213 | now = curtime(); |
---|
214 | if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) |
---|
215 | msg_timeout = MSG_T_O; |
---|
216 | if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 && |
---|
217 | now >= e->e_ctime + e->e_deliver_by && |
---|
218 | !bitset(EF_RESPONSE, e->e_flags)) |
---|
219 | { |
---|
220 | msg_timeout = MSG_NOT_BY; |
---|
221 | e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; |
---|
222 | } |
---|
223 | else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && |
---|
224 | !bitset(EF_RESPONSE, e->e_flags)) |
---|
225 | { |
---|
226 | msg_timeout = MSG_T_O_NOW; |
---|
227 | e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; |
---|
228 | } |
---|
229 | |
---|
230 | e->e_flags &= ~EF_QUEUERUN; |
---|
231 | for (q = e->e_sendqueue; q != NULL; q = q->q_next) |
---|
232 | { |
---|
233 | if (QS_IS_UNDELIVERED(q->q_state)) |
---|
234 | queueit = true; |
---|
235 | |
---|
236 | /* see if a notification is needed */ |
---|
237 | if (bitset(QPINGONFAILURE, q->q_flags) && |
---|
238 | ((IS_MSG_ERR(msg_timeout) && |
---|
239 | QS_IS_UNDELIVERED(q->q_state)) || |
---|
240 | QS_IS_BADADDR(q->q_state) || |
---|
241 | IS_IMM_RET(msg_timeout))) |
---|
242 | { |
---|
243 | failure_return = true; |
---|
244 | if (!done && q->q_owner == NULL && |
---|
245 | !emptyaddr(&e->e_from)) |
---|
246 | { |
---|
247 | (void) sendtolist(e->e_from.q_paddr, NULLADDR, |
---|
248 | &e->e_errorqueue, 0, e); |
---|
249 | done = true; |
---|
250 | } |
---|
251 | } |
---|
252 | else if ((bitset(QPINGONSUCCESS, q->q_flags) && |
---|
253 | ((QS_IS_SENT(q->q_state) && |
---|
254 | bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) || |
---|
255 | bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) || |
---|
256 | bitset(QBYTRACE, q->q_flags) || |
---|
257 | bitset(QBYNRELAY, q->q_flags)) |
---|
258 | { |
---|
259 | success_return = true; |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | if (e->e_class < 0) |
---|
264 | e->e_flags |= EF_NO_BODY_RETN; |
---|
265 | |
---|
266 | /* |
---|
267 | ** See if the message timed out. |
---|
268 | */ |
---|
269 | |
---|
270 | if (!queueit) |
---|
271 | /* EMPTY */ |
---|
272 | /* nothing to do */ ; |
---|
273 | else if (IS_MSG_ERR(msg_timeout)) |
---|
274 | { |
---|
275 | if (failure_return) |
---|
276 | { |
---|
277 | if (msg_timeout == MSG_NOT_BY) |
---|
278 | { |
---|
279 | (void) sm_snprintf(buf, sizeof buf, |
---|
280 | "delivery time expired %lds", |
---|
281 | e->e_deliver_by); |
---|
282 | } |
---|
283 | else |
---|
284 | { |
---|
285 | (void) sm_snprintf(buf, sizeof buf, |
---|
286 | "Cannot send message for %s", |
---|
287 | pintvl(TimeOuts.to_q_return[e->e_timeoutclass], |
---|
288 | false)); |
---|
289 | } |
---|
290 | |
---|
291 | /* don't free, allocated from e_rpool */ |
---|
292 | e->e_message = sm_rpool_strdup_x(e->e_rpool, buf); |
---|
293 | message(buf); |
---|
294 | e->e_flags |= EF_CLRQUEUE; |
---|
295 | } |
---|
296 | if (msg_timeout == MSG_NOT_BY) |
---|
297 | { |
---|
298 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
299 | "Delivery time (%lds) expired\n", |
---|
300 | e->e_deliver_by); |
---|
301 | } |
---|
302 | else |
---|
303 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
304 | "Message could not be delivered for %s\n", |
---|
305 | pintvl(TimeOuts.to_q_return[e->e_timeoutclass], |
---|
306 | false)); |
---|
307 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
308 | "Message will be deleted from queue\n"); |
---|
309 | for (q = e->e_sendqueue; q != NULL; q = q->q_next) |
---|
310 | { |
---|
311 | if (QS_IS_UNDELIVERED(q->q_state)) |
---|
312 | { |
---|
313 | q->q_state = QS_BADADDR; |
---|
314 | if (msg_timeout == MSG_NOT_BY) |
---|
315 | q->q_status = "5.4.7"; |
---|
316 | else |
---|
317 | q->q_status = "4.4.7"; |
---|
318 | } |
---|
319 | } |
---|
320 | } |
---|
321 | else |
---|
322 | { |
---|
323 | if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && |
---|
324 | now >= e->e_ctime + |
---|
325 | TimeOuts.to_q_warning[e->e_timeoutclass]) |
---|
326 | msg_timeout = MSG_WARN; |
---|
327 | else if (IS_DLVR_NOTIFY(e) && |
---|
328 | e->e_deliver_by > 0 && |
---|
329 | now >= e->e_ctime + e->e_deliver_by) |
---|
330 | msg_timeout = MSG_WARN_BY; |
---|
331 | |
---|
332 | if (IS_MSG_WARN(msg_timeout)) |
---|
333 | { |
---|
334 | if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && |
---|
335 | e->e_class >= 0 && |
---|
336 | e->e_from.q_paddr != NULL && |
---|
337 | strcmp(e->e_from.q_paddr, "<>") != 0 && |
---|
338 | sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && |
---|
339 | (strlen(e->e_from.q_paddr) <= 8 || |
---|
340 | sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], |
---|
341 | "-request") != 0)) |
---|
342 | { |
---|
343 | for (q = e->e_sendqueue; q != NULL; |
---|
344 | q = q->q_next) |
---|
345 | { |
---|
346 | if (QS_IS_UNDELIVERED(q->q_state) |
---|
347 | #if _FFR_NODELAYDSN_ON_HOLD |
---|
348 | && !bitnset(M_HOLD, |
---|
349 | q->q_mailer->m_flags) |
---|
350 | #endif /* _FFR_NODELAYDSN_ON_HOLD */ |
---|
351 | ) |
---|
352 | { |
---|
353 | if (msg_timeout == |
---|
354 | MSG_WARN_BY && |
---|
355 | (bitset(QPINGONDELAY, |
---|
356 | q->q_flags) || |
---|
357 | !bitset(QHASNOTIFY, |
---|
358 | q->q_flags)) |
---|
359 | ) |
---|
360 | { |
---|
361 | q->q_flags |= QBYNDELAY; |
---|
362 | delay_return = true; |
---|
363 | } |
---|
364 | if (bitset(QPINGONDELAY, |
---|
365 | q->q_flags)) |
---|
366 | { |
---|
367 | q->q_flags |= QDELAYED; |
---|
368 | delay_return = true; |
---|
369 | } |
---|
370 | } |
---|
371 | } |
---|
372 | } |
---|
373 | if (delay_return) |
---|
374 | { |
---|
375 | if (msg_timeout == MSG_WARN_BY) |
---|
376 | { |
---|
377 | (void) sm_snprintf(buf, sizeof buf, |
---|
378 | "Warning: Delivery time (%lds) exceeded", |
---|
379 | e->e_deliver_by); |
---|
380 | } |
---|
381 | else |
---|
382 | (void) sm_snprintf(buf, sizeof buf, |
---|
383 | "Warning: could not send message for past %s", |
---|
384 | pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], |
---|
385 | false)); |
---|
386 | |
---|
387 | /* don't free, allocated from e_rpool */ |
---|
388 | e->e_message = sm_rpool_strdup_x(e->e_rpool, |
---|
389 | buf); |
---|
390 | message(buf); |
---|
391 | e->e_flags |= EF_WARNING; |
---|
392 | } |
---|
393 | if (msg_timeout == MSG_WARN_BY) |
---|
394 | { |
---|
395 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
396 | "Warning: Delivery time (%lds) exceeded\n", |
---|
397 | e->e_deliver_by); |
---|
398 | } |
---|
399 | else |
---|
400 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
401 | "Warning: message still undelivered after %s\n", |
---|
402 | pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], |
---|
403 | false)); |
---|
404 | (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, |
---|
405 | "Will keep trying until message is %s old\n", |
---|
406 | pintvl(TimeOuts.to_q_return[e->e_timeoutclass], |
---|
407 | false)); |
---|
408 | } |
---|
409 | } |
---|
410 | |
---|
411 | if (tTd(50, 2)) |
---|
412 | sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n", |
---|
413 | failure_return, delay_return, success_return, queueit); |
---|
414 | |
---|
415 | /* |
---|
416 | ** If we had some fatal error, but no addresses are marked as |
---|
417 | ** bad, mark them _all_ as bad. |
---|
418 | */ |
---|
419 | |
---|
420 | if (bitset(EF_FATALERRS, e->e_flags) && !failure_return) |
---|
421 | { |
---|
422 | for (q = e->e_sendqueue; q != NULL; q = q->q_next) |
---|
423 | { |
---|
424 | if ((QS_IS_OK(q->q_state) || |
---|
425 | QS_IS_VERIFIED(q->q_state)) && |
---|
426 | bitset(QPINGONFAILURE, q->q_flags)) |
---|
427 | { |
---|
428 | failure_return = true; |
---|
429 | q->q_state = QS_BADADDR; |
---|
430 | } |
---|
431 | } |
---|
432 | } |
---|
433 | |
---|
434 | /* |
---|
435 | ** Send back return receipts as requested. |
---|
436 | */ |
---|
437 | |
---|
438 | if (success_return && !failure_return && !delay_return && fulldrop && |
---|
439 | !bitset(PRIV_NORECEIPTS, PrivacyFlags) && |
---|
440 | strcmp(e->e_from.q_paddr, "<>") != 0) |
---|
441 | { |
---|
442 | auto ADDRESS *rlist = NULL; |
---|
443 | |
---|
444 | if (tTd(50, 8)) |
---|
445 | sm_dprintf("dropenvelope(%s): sending return receipt\n", |
---|
446 | id); |
---|
447 | e->e_flags |= EF_SENDRECEIPT; |
---|
448 | (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e); |
---|
449 | (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e); |
---|
450 | } |
---|
451 | e->e_flags &= ~EF_SENDRECEIPT; |
---|
452 | |
---|
453 | /* |
---|
454 | ** Arrange to send error messages if there are fatal errors. |
---|
455 | */ |
---|
456 | |
---|
457 | if ((failure_return || delay_return) && e->e_errormode != EM_QUIET) |
---|
458 | { |
---|
459 | if (tTd(50, 8)) |
---|
460 | sm_dprintf("dropenvelope(%s): saving mail\n", id); |
---|
461 | panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); |
---|
462 | } |
---|
463 | |
---|
464 | /* |
---|
465 | ** Arrange to send warning messages to postmaster as requested. |
---|
466 | */ |
---|
467 | |
---|
468 | if ((failure_return || pmnotify) && |
---|
469 | PostMasterCopy != NULL && |
---|
470 | !bitset(EF_RESPONSE, e->e_flags) && |
---|
471 | e->e_class >= 0) |
---|
472 | { |
---|
473 | auto ADDRESS *rlist = NULL; |
---|
474 | char pcopy[MAXNAME]; |
---|
475 | |
---|
476 | if (failure_return) |
---|
477 | { |
---|
478 | expand(PostMasterCopy, pcopy, sizeof pcopy, e); |
---|
479 | |
---|
480 | if (tTd(50, 8)) |
---|
481 | sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n", |
---|
482 | id, pcopy); |
---|
483 | (void) sendtolist(pcopy, NULLADDR, &rlist, 0, e); |
---|
484 | } |
---|
485 | if (pmnotify) |
---|
486 | (void) sendtolist("postmaster", NULLADDR, |
---|
487 | &rlist, 0, e); |
---|
488 | (void) returntosender(e->e_message, rlist, |
---|
489 | RTSF_PM_BOUNCE|RTSF_NO_BODY, e); |
---|
490 | } |
---|
491 | |
---|
492 | /* |
---|
493 | ** Instantiate or deinstantiate the queue. |
---|
494 | */ |
---|
495 | |
---|
496 | simpledrop: |
---|
497 | if (tTd(50, 8)) |
---|
498 | sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n", |
---|
499 | id, queueit); |
---|
500 | if (!queueit || bitset(EF_CLRQUEUE, e->e_flags)) |
---|
501 | { |
---|
502 | if (tTd(50, 1)) |
---|
503 | { |
---|
504 | sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=", |
---|
505 | e->e_id, queueit); |
---|
506 | printenvflags(e); |
---|
507 | } |
---|
508 | if (!panic) |
---|
509 | (void) xunlink(queuename(e, DATAFL_LETTER)); |
---|
510 | #if _FFR_QUARANTINE |
---|
511 | if (panic && QueueMode == QM_LOST) |
---|
512 | { |
---|
513 | /* |
---|
514 | ** leave the Qf file behind as |
---|
515 | ** the delivery attempt failed. |
---|
516 | */ |
---|
517 | |
---|
518 | /* EMPTY */ |
---|
519 | } |
---|
520 | else |
---|
521 | #endif /* _FFR_QUARANTINE */ |
---|
522 | if (xunlink(queuename(e, ANYQFL_LETTER)) == 0) |
---|
523 | { |
---|
524 | /* add to available space in filesystem */ |
---|
525 | updfs(e, true, !panic); |
---|
526 | } |
---|
527 | |
---|
528 | if (e->e_ntries > 0 && LogLevel > 9) |
---|
529 | sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d", |
---|
530 | pintvl(curtime() - e->e_ctime, true), |
---|
531 | e->e_ntries); |
---|
532 | } |
---|
533 | else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) |
---|
534 | { |
---|
535 | if (!split) |
---|
536 | queueup(e, false, true); |
---|
537 | else |
---|
538 | { |
---|
539 | ENVELOPE *oldsib; |
---|
540 | ENVELOPE *ee; |
---|
541 | |
---|
542 | /* |
---|
543 | ** Save old sibling and set it to NULL to avoid |
---|
544 | ** queueing up the same envelopes again. |
---|
545 | ** This requires that envelopes in that list have |
---|
546 | ** been take care of before (or at some other place). |
---|
547 | */ |
---|
548 | |
---|
549 | oldsib = e->e_sibling; |
---|
550 | e->e_sibling = NULL; |
---|
551 | if (!split_by_recipient(e) && |
---|
552 | bitset(EF_FATALERRS, e->e_flags)) |
---|
553 | { |
---|
554 | syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d", |
---|
555 | e->e_id, queuename(e, DATAFL_LETTER), |
---|
556 | (int) geteuid()); |
---|
557 | } |
---|
558 | for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) |
---|
559 | queueup(ee, false, true); |
---|
560 | queueup(e, false, true); |
---|
561 | |
---|
562 | /* clean up */ |
---|
563 | for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) |
---|
564 | { |
---|
565 | /* now unlock the job */ |
---|
566 | if (tTd(50, 8)) |
---|
567 | sm_dprintf("dropenvelope(%s): unlocking job\n", |
---|
568 | ee->e_id); |
---|
569 | closexscript(ee); |
---|
570 | unlockqueue(ee); |
---|
571 | |
---|
572 | /* this envelope is marked unused */ |
---|
573 | if (ee->e_dfp != NULL) |
---|
574 | { |
---|
575 | (void) sm_io_close(ee->e_dfp, |
---|
576 | SM_TIME_DEFAULT); |
---|
577 | ee->e_dfp = NULL; |
---|
578 | } |
---|
579 | ee->e_id = NULL; |
---|
580 | ee->e_flags &= ~EF_HAS_DF; |
---|
581 | } |
---|
582 | e->e_sibling = oldsib; |
---|
583 | } |
---|
584 | } |
---|
585 | |
---|
586 | /* now unlock the job */ |
---|
587 | if (tTd(50, 8)) |
---|
588 | sm_dprintf("dropenvelope(%s): unlocking job\n", id); |
---|
589 | closexscript(e); |
---|
590 | unlockqueue(e); |
---|
591 | |
---|
592 | /* make sure that this envelope is marked unused */ |
---|
593 | if (e->e_dfp != NULL) |
---|
594 | { |
---|
595 | (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); |
---|
596 | e->e_dfp = NULL; |
---|
597 | } |
---|
598 | e->e_id = NULL; |
---|
599 | e->e_flags &= ~EF_HAS_DF; |
---|
600 | } |
---|
601 | /* |
---|
602 | ** CLEARENVELOPE -- clear an envelope without unlocking |
---|
603 | ** |
---|
604 | ** This is normally used by a child process to get a clean |
---|
605 | ** envelope without disturbing the parent. |
---|
606 | ** |
---|
607 | ** Parameters: |
---|
608 | ** e -- the envelope to clear. |
---|
609 | ** fullclear - if set, the current envelope is total |
---|
610 | ** garbage and should be ignored; otherwise, |
---|
611 | ** release any resources it may indicate. |
---|
612 | ** rpool -- either NULL, or a pointer to a resource pool |
---|
613 | ** from which envelope memory is allocated, and |
---|
614 | ** to which envelope resources are attached. |
---|
615 | ** |
---|
616 | ** Returns: |
---|
617 | ** none. |
---|
618 | ** |
---|
619 | ** Side Effects: |
---|
620 | ** Closes files associated with the envelope. |
---|
621 | ** Marks the envelope as unallocated. |
---|
622 | */ |
---|
623 | |
---|
624 | void |
---|
625 | clearenvelope(e, fullclear, rpool) |
---|
626 | register ENVELOPE *e; |
---|
627 | bool fullclear; |
---|
628 | SM_RPOOL_T *rpool; |
---|
629 | { |
---|
630 | register HDR *bh; |
---|
631 | register HDR **nhp; |
---|
632 | extern ENVELOPE BlankEnvelope; |
---|
633 | char **p; |
---|
634 | |
---|
635 | if (!fullclear) |
---|
636 | { |
---|
637 | /* clear out any file information */ |
---|
638 | if (e->e_xfp != NULL) |
---|
639 | (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); |
---|
640 | if (e->e_dfp != NULL) |
---|
641 | (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); |
---|
642 | e->e_xfp = e->e_dfp = NULL; |
---|
643 | } |
---|
644 | |
---|
645 | /* |
---|
646 | ** Copy BlankEnvelope into *e. |
---|
647 | ** It is not safe to simply copy pointers to strings; |
---|
648 | ** the strings themselves must be copied (or set to NULL). |
---|
649 | ** The problem is that when we assign a new string value to |
---|
650 | ** a member of BlankEnvelope, we free the old string. |
---|
651 | ** We did not need to do this copying in sendmail 8.11 :-( |
---|
652 | ** and it is a potential performance hit. Reference counted |
---|
653 | ** strings are one way out. |
---|
654 | */ |
---|
655 | |
---|
656 | *e = BlankEnvelope; |
---|
657 | e->e_message = NULL; |
---|
658 | #if _FFR_QUARANTINE |
---|
659 | e->e_qfletter = '\0'; |
---|
660 | e->e_quarmsg = NULL; |
---|
661 | macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), ""); |
---|
662 | #endif /* _FFR_QUARANTINE */ |
---|
663 | |
---|
664 | /* |
---|
665 | ** Copy the macro table. |
---|
666 | ** We might be able to avoid this by zeroing the macro table |
---|
667 | ** and always searching BlankEnvelope.e_macro after e->e_macro |
---|
668 | ** in macvalue(). |
---|
669 | */ |
---|
670 | |
---|
671 | for (p = &e->e_macro.mac_table[0]; |
---|
672 | p <= &e->e_macro.mac_table[MAXMACROID]; |
---|
673 | ++p) |
---|
674 | { |
---|
675 | if (*p != NULL) |
---|
676 | *p = sm_rpool_strdup_x(rpool, *p); |
---|
677 | } |
---|
678 | |
---|
679 | /* |
---|
680 | ** XXX There are many strings in the envelope structure |
---|
681 | ** XXX that we are not attempting to copy here. |
---|
682 | ** XXX Investigate this further. |
---|
683 | */ |
---|
684 | |
---|
685 | e->e_rpool = rpool; |
---|
686 | e->e_macro.mac_rpool = rpool; |
---|
687 | if (Verbose) |
---|
688 | set_delivery_mode(SM_DELIVER, e); |
---|
689 | bh = BlankEnvelope.e_header; |
---|
690 | nhp = &e->e_header; |
---|
691 | while (bh != NULL) |
---|
692 | { |
---|
693 | *nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof *bh); |
---|
694 | memmove((char *) *nhp, (char *) bh, sizeof *bh); |
---|
695 | bh = bh->h_link; |
---|
696 | nhp = &(*nhp)->h_link; |
---|
697 | } |
---|
698 | } |
---|
699 | /* |
---|
700 | ** INITSYS -- initialize instantiation of system |
---|
701 | ** |
---|
702 | ** In Daemon mode, this is done in the child. |
---|
703 | ** |
---|
704 | ** Parameters: |
---|
705 | ** e -- the envelope to use. |
---|
706 | ** |
---|
707 | ** Returns: |
---|
708 | ** none. |
---|
709 | ** |
---|
710 | ** Side Effects: |
---|
711 | ** Initializes the system macros, some global variables, |
---|
712 | ** etc. In particular, the current time in various |
---|
713 | ** forms is set. |
---|
714 | */ |
---|
715 | |
---|
716 | void |
---|
717 | initsys(e) |
---|
718 | register ENVELOPE *e; |
---|
719 | { |
---|
720 | char buf[10]; |
---|
721 | #ifdef TTYNAME |
---|
722 | static char ybuf[60]; /* holds tty id */ |
---|
723 | register char *p; |
---|
724 | extern char *ttyname(); |
---|
725 | #endif /* TTYNAME */ |
---|
726 | |
---|
727 | /* |
---|
728 | ** Give this envelope a reality. |
---|
729 | ** I.e., an id, a transcript, and a creation time. |
---|
730 | ** We don't select the queue until all of the recipients are known. |
---|
731 | */ |
---|
732 | |
---|
733 | openxscript(e); |
---|
734 | e->e_ctime = curtime(); |
---|
735 | #if _FFR_QUARANTINE |
---|
736 | e->e_qfletter = '\0'; |
---|
737 | #endif /* _FFR_QUARANTINE */ |
---|
738 | #if _FFR_QUEUEDELAY |
---|
739 | e->e_queuealg = QueueAlg; |
---|
740 | e->e_queuedelay = QueueInitDelay; |
---|
741 | #endif /* _FFR_QUEUEDELAY */ |
---|
742 | |
---|
743 | /* |
---|
744 | ** Set OutChannel to something useful if stdout isn't it. |
---|
745 | ** This arranges that any extra stuff the mailer produces |
---|
746 | ** gets sent back to the user on error (because it is |
---|
747 | ** tucked away in the transcript). |
---|
748 | */ |
---|
749 | |
---|
750 | if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && |
---|
751 | e->e_xfp != NULL) |
---|
752 | OutChannel = e->e_xfp; |
---|
753 | |
---|
754 | /* |
---|
755 | ** Set up some basic system macros. |
---|
756 | */ |
---|
757 | |
---|
758 | /* process id */ |
---|
759 | (void) sm_snprintf(buf, sizeof buf, "%d", (int) CurrentPid); |
---|
760 | macdefine(&e->e_macro, A_TEMP, 'p', buf); |
---|
761 | |
---|
762 | /* hop count */ |
---|
763 | (void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount); |
---|
764 | macdefine(&e->e_macro, A_TEMP, 'c', buf); |
---|
765 | |
---|
766 | /* time as integer, unix time, arpa time */ |
---|
767 | settime(e); |
---|
768 | |
---|
769 | /* Load average */ |
---|
770 | sm_getla(); |
---|
771 | |
---|
772 | #ifdef TTYNAME |
---|
773 | /* tty name */ |
---|
774 | if (macvalue('y', e) == NULL) |
---|
775 | { |
---|
776 | p = ttyname(2); |
---|
777 | if (p != NULL) |
---|
778 | { |
---|
779 | if (strrchr(p, '/') != NULL) |
---|
780 | p = strrchr(p, '/') + 1; |
---|
781 | (void) sm_strlcpy(ybuf, sizeof ybuf, p); |
---|
782 | macdefine(&e->e_macro, A_PERM, 'y', ybuf); |
---|
783 | } |
---|
784 | } |
---|
785 | #endif /* TTYNAME */ |
---|
786 | } |
---|
787 | /* |
---|
788 | ** SETTIME -- set the current time. |
---|
789 | ** |
---|
790 | ** Parameters: |
---|
791 | ** e -- the envelope in which the macros should be set. |
---|
792 | ** |
---|
793 | ** Returns: |
---|
794 | ** none. |
---|
795 | ** |
---|
796 | ** Side Effects: |
---|
797 | ** Sets the various time macros -- $a, $b, $d, $t. |
---|
798 | */ |
---|
799 | |
---|
800 | void |
---|
801 | settime(e) |
---|
802 | register ENVELOPE *e; |
---|
803 | { |
---|
804 | register char *p; |
---|
805 | auto time_t now; |
---|
806 | char buf[30]; |
---|
807 | register struct tm *tm; |
---|
808 | |
---|
809 | now = curtime(); |
---|
810 | tm = gmtime(&now); |
---|
811 | (void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d", |
---|
812 | tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, |
---|
813 | tm->tm_hour, tm->tm_min); |
---|
814 | macdefine(&e->e_macro, A_TEMP, 't', buf); |
---|
815 | (void) sm_strlcpy(buf, ctime(&now), sizeof buf); |
---|
816 | p = strchr(buf, '\n'); |
---|
817 | if (p != NULL) |
---|
818 | *p = '\0'; |
---|
819 | macdefine(&e->e_macro, A_TEMP, 'd', buf); |
---|
820 | macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf)); |
---|
821 | if (macvalue('a', e) == NULL) |
---|
822 | macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e)); |
---|
823 | } |
---|
824 | /* |
---|
825 | ** OPENXSCRIPT -- Open transcript file |
---|
826 | ** |
---|
827 | ** Creates a transcript file for possible eventual mailing or |
---|
828 | ** sending back. |
---|
829 | ** |
---|
830 | ** Parameters: |
---|
831 | ** e -- the envelope to create the transcript in/for. |
---|
832 | ** |
---|
833 | ** Returns: |
---|
834 | ** none |
---|
835 | ** |
---|
836 | ** Side Effects: |
---|
837 | ** Creates the transcript file. |
---|
838 | */ |
---|
839 | |
---|
840 | #ifndef O_APPEND |
---|
841 | # define O_APPEND 0 |
---|
842 | #endif /* ! O_APPEND */ |
---|
843 | |
---|
844 | void |
---|
845 | openxscript(e) |
---|
846 | register ENVELOPE *e; |
---|
847 | { |
---|
848 | register char *p; |
---|
849 | |
---|
850 | if (e->e_xfp != NULL) |
---|
851 | return; |
---|
852 | |
---|
853 | #if 0 |
---|
854 | if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags)) |
---|
855 | syserr("openxscript: job not locked"); |
---|
856 | #endif /* 0 */ |
---|
857 | |
---|
858 | p = queuename(e, XSCRPT_LETTER); |
---|
859 | e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize, |
---|
860 | SFF_NOTEXCL|SFF_OPENASROOT); |
---|
861 | |
---|
862 | if (e->e_xfp == NULL) |
---|
863 | { |
---|
864 | syserr("Can't create transcript file %s", p); |
---|
865 | e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, |
---|
866 | SM_PATH_DEVNULL, SM_IO_RDWR, NULL); |
---|
867 | if (e->e_xfp == NULL) |
---|
868 | syserr("!Can't open %s", SM_PATH_DEVNULL); |
---|
869 | } |
---|
870 | (void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0); |
---|
871 | if (tTd(46, 9)) |
---|
872 | { |
---|
873 | sm_dprintf("openxscript(%s):\n ", p); |
---|
874 | dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true, |
---|
875 | false); |
---|
876 | } |
---|
877 | } |
---|
878 | /* |
---|
879 | ** CLOSEXSCRIPT -- close the transcript file. |
---|
880 | ** |
---|
881 | ** Parameters: |
---|
882 | ** e -- the envelope containing the transcript to close. |
---|
883 | ** |
---|
884 | ** Returns: |
---|
885 | ** none. |
---|
886 | ** |
---|
887 | ** Side Effects: |
---|
888 | ** none. |
---|
889 | */ |
---|
890 | |
---|
891 | void |
---|
892 | closexscript(e) |
---|
893 | register ENVELOPE *e; |
---|
894 | { |
---|
895 | if (e->e_xfp == NULL) |
---|
896 | return; |
---|
897 | #if 0 |
---|
898 | if (e->e_lockfp == NULL) |
---|
899 | syserr("closexscript: job not locked"); |
---|
900 | #endif /* 0 */ |
---|
901 | (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); |
---|
902 | e->e_xfp = NULL; |
---|
903 | } |
---|
904 | /* |
---|
905 | ** SETSENDER -- set the person who this message is from |
---|
906 | ** |
---|
907 | ** Under certain circumstances allow the user to say who |
---|
908 | ** s/he is (using -f or -r). These are: |
---|
909 | ** 1. The user's uid is zero (root). |
---|
910 | ** 2. The user's login name is in an approved list (typically |
---|
911 | ** from a network server). |
---|
912 | ** 3. The address the user is trying to claim has a |
---|
913 | ** "!" character in it (since #2 doesn't do it for |
---|
914 | ** us if we are dialing out for UUCP). |
---|
915 | ** A better check to replace #3 would be if the |
---|
916 | ** effective uid is "UUCP" -- this would require me |
---|
917 | ** to rewrite getpwent to "grab" uucp as it went by, |
---|
918 | ** make getname more nasty, do another passwd file |
---|
919 | ** scan, or compile the UID of "UUCP" into the code, |
---|
920 | ** all of which are reprehensible. |
---|
921 | ** |
---|
922 | ** Assuming all of these fail, we figure out something |
---|
923 | ** ourselves. |
---|
924 | ** |
---|
925 | ** Parameters: |
---|
926 | ** from -- the person we would like to believe this message |
---|
927 | ** is from, as specified on the command line. |
---|
928 | ** e -- the envelope in which we would like the sender set. |
---|
929 | ** delimptr -- if non-NULL, set to the location of the |
---|
930 | ** trailing delimiter. |
---|
931 | ** delimchar -- the character that will delimit the sender |
---|
932 | ** address. |
---|
933 | ** internal -- set if this address is coming from an internal |
---|
934 | ** source such as an owner alias. |
---|
935 | ** |
---|
936 | ** Returns: |
---|
937 | ** none. |
---|
938 | ** |
---|
939 | ** Side Effects: |
---|
940 | ** sets sendmail's notion of who the from person is. |
---|
941 | */ |
---|
942 | |
---|
943 | void |
---|
944 | setsender(from, e, delimptr, delimchar, internal) |
---|
945 | char *from; |
---|
946 | register ENVELOPE *e; |
---|
947 | char **delimptr; |
---|
948 | int delimchar; |
---|
949 | bool internal; |
---|
950 | { |
---|
951 | register char **pvp; |
---|
952 | char *realname = NULL; |
---|
953 | char *bp; |
---|
954 | char buf[MAXNAME + 2]; |
---|
955 | char pvpbuf[PSBUFSIZE]; |
---|
956 | extern char *FullName; |
---|
957 | |
---|
958 | if (tTd(45, 1)) |
---|
959 | sm_dprintf("setsender(%s)\n", from == NULL ? "" : from); |
---|
960 | |
---|
961 | /* may be set from earlier calls */ |
---|
962 | macdefine(&e->e_macro, A_PERM, 'x', ""); |
---|
963 | |
---|
964 | /* |
---|
965 | ** Figure out the real user executing us. |
---|
966 | ** Username can return errno != 0 on non-errors. |
---|
967 | */ |
---|
968 | |
---|
969 | if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || |
---|
970 | OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) |
---|
971 | realname = from; |
---|
972 | if (realname == NULL || realname[0] == '\0') |
---|
973 | realname = username(); |
---|
974 | |
---|
975 | if (ConfigLevel < 2) |
---|
976 | SuprErrs = true; |
---|
977 | |
---|
978 | macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); |
---|
979 | |
---|
980 | /* preset state for then clause in case from == NULL */ |
---|
981 | e->e_from.q_state = QS_BADADDR; |
---|
982 | e->e_from.q_flags = 0; |
---|
983 | if (from == NULL || |
---|
984 | parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, |
---|
985 | delimchar, delimptr, e, false) == NULL || |
---|
986 | QS_IS_BADADDR(e->e_from.q_state) || |
---|
987 | e->e_from.q_mailer == ProgMailer || |
---|
988 | e->e_from.q_mailer == FileMailer || |
---|
989 | e->e_from.q_mailer == InclMailer) |
---|
990 | { |
---|
991 | /* log garbage addresses for traceback */ |
---|
992 | if (from != NULL && LogLevel > 2) |
---|
993 | { |
---|
994 | char *p; |
---|
995 | char ebuf[MAXNAME * 2 + 2]; |
---|
996 | |
---|
997 | p = macvalue('_', e); |
---|
998 | if (p == NULL) |
---|
999 | { |
---|
1000 | char *host = RealHostName; |
---|
1001 | |
---|
1002 | if (host == NULL) |
---|
1003 | host = MyHostName; |
---|
1004 | (void) sm_snprintf(ebuf, sizeof ebuf, |
---|
1005 | "%.*s@%.*s", MAXNAME, |
---|
1006 | realname, MAXNAME, host); |
---|
1007 | p = ebuf; |
---|
1008 | } |
---|
1009 | sm_syslog(LOG_NOTICE, e->e_id, |
---|
1010 | "setsender: %s: invalid or unparsable, received from %s", |
---|
1011 | shortenstring(from, 83), p); |
---|
1012 | } |
---|
1013 | if (from != NULL) |
---|
1014 | { |
---|
1015 | if (!QS_IS_BADADDR(e->e_from.q_state)) |
---|
1016 | { |
---|
1017 | /* it was a bogus mailer in the from addr */ |
---|
1018 | e->e_status = "5.1.7"; |
---|
1019 | usrerrenh(e->e_status, |
---|
1020 | "553 Invalid sender address"); |
---|
1021 | } |
---|
1022 | SuprErrs = true; |
---|
1023 | } |
---|
1024 | if (from == realname || |
---|
1025 | parseaddr(from = realname, |
---|
1026 | &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ', |
---|
1027 | NULL, e, false) == NULL) |
---|
1028 | { |
---|
1029 | char nbuf[100]; |
---|
1030 | |
---|
1031 | SuprErrs = true; |
---|
1032 | expand("\201n", nbuf, sizeof nbuf, e); |
---|
1033 | from = sm_rpool_strdup_x(e->e_rpool, nbuf); |
---|
1034 | if (parseaddr(from, &e->e_from, RF_COPYALL, ' ', |
---|
1035 | NULL, e, false) == NULL && |
---|
1036 | parseaddr(from = "postmaster", &e->e_from, |
---|
1037 | RF_COPYALL, ' ', NULL, e, false) == NULL) |
---|
1038 | syserr("553 5.3.0 setsender: can't even parse postmaster!"); |
---|
1039 | } |
---|
1040 | } |
---|
1041 | else |
---|
1042 | FromFlag = true; |
---|
1043 | e->e_from.q_state = QS_SENDER; |
---|
1044 | if (tTd(45, 5)) |
---|
1045 | { |
---|
1046 | sm_dprintf("setsender: QS_SENDER "); |
---|
1047 | printaddr(&e->e_from, false); |
---|
1048 | } |
---|
1049 | SuprErrs = false; |
---|
1050 | |
---|
1051 | #if USERDB |
---|
1052 | if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) |
---|
1053 | { |
---|
1054 | register char *p; |
---|
1055 | |
---|
1056 | p = udbsender(e->e_from.q_user, e->e_rpool); |
---|
1057 | if (p != NULL) |
---|
1058 | from = p; |
---|
1059 | } |
---|
1060 | #endif /* USERDB */ |
---|
1061 | |
---|
1062 | if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) |
---|
1063 | { |
---|
1064 | SM_MBDB_T user; |
---|
1065 | |
---|
1066 | if (!internal) |
---|
1067 | { |
---|
1068 | /* if the user already given fullname don't redefine */ |
---|
1069 | if (FullName == NULL) |
---|
1070 | FullName = macvalue('x', e); |
---|
1071 | if (FullName != NULL) |
---|
1072 | { |
---|
1073 | if (FullName[0] == '\0') |
---|
1074 | FullName = NULL; |
---|
1075 | else |
---|
1076 | FullName = newstr(FullName); |
---|
1077 | } |
---|
1078 | } |
---|
1079 | |
---|
1080 | if (e->e_from.q_user[0] != '\0' && |
---|
1081 | sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK) |
---|
1082 | { |
---|
1083 | /* |
---|
1084 | ** Process passwd file entry. |
---|
1085 | */ |
---|
1086 | |
---|
1087 | /* extract home directory */ |
---|
1088 | if (*user.mbdb_homedir == '\0') |
---|
1089 | e->e_from.q_home = NULL; |
---|
1090 | else if (strcmp(user.mbdb_homedir, "/") == 0) |
---|
1091 | e->e_from.q_home = ""; |
---|
1092 | else |
---|
1093 | e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool, |
---|
1094 | user.mbdb_homedir); |
---|
1095 | macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home); |
---|
1096 | |
---|
1097 | /* extract user and group id */ |
---|
1098 | if (user.mbdb_uid != SM_NO_UID) |
---|
1099 | { |
---|
1100 | e->e_from.q_uid = user.mbdb_uid; |
---|
1101 | e->e_from.q_gid = user.mbdb_gid; |
---|
1102 | e->e_from.q_flags |= QGOODUID; |
---|
1103 | } |
---|
1104 | |
---|
1105 | /* extract full name from passwd file */ |
---|
1106 | if (FullName == NULL && !internal && |
---|
1107 | user.mbdb_fullname[0] != '\0' && |
---|
1108 | strcmp(user.mbdb_name, e->e_from.q_user) == 0) |
---|
1109 | { |
---|
1110 | FullName = newstr(user.mbdb_fullname); |
---|
1111 | } |
---|
1112 | } |
---|
1113 | else |
---|
1114 | { |
---|
1115 | e->e_from.q_home = NULL; |
---|
1116 | } |
---|
1117 | if (FullName != NULL && !internal) |
---|
1118 | macdefine(&e->e_macro, A_TEMP, 'x', FullName); |
---|
1119 | } |
---|
1120 | else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP) |
---|
1121 | { |
---|
1122 | if (e->e_from.q_home == NULL) |
---|
1123 | { |
---|
1124 | e->e_from.q_home = getenv("HOME"); |
---|
1125 | if (e->e_from.q_home != NULL) |
---|
1126 | { |
---|
1127 | if (*e->e_from.q_home == '\0') |
---|
1128 | e->e_from.q_home = NULL; |
---|
1129 | else if (strcmp(e->e_from.q_home, "/") == 0) |
---|
1130 | e->e_from.q_home++; |
---|
1131 | } |
---|
1132 | } |
---|
1133 | e->e_from.q_uid = RealUid; |
---|
1134 | e->e_from.q_gid = RealGid; |
---|
1135 | e->e_from.q_flags |= QGOODUID; |
---|
1136 | } |
---|
1137 | |
---|
1138 | /* |
---|
1139 | ** Rewrite the from person to dispose of possible implicit |
---|
1140 | ** links in the net. |
---|
1141 | */ |
---|
1142 | |
---|
1143 | pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL); |
---|
1144 | if (pvp == NULL) |
---|
1145 | { |
---|
1146 | /* don't need to give error -- prescan did that already */ |
---|
1147 | if (LogLevel > 2) |
---|
1148 | sm_syslog(LOG_NOTICE, e->e_id, |
---|
1149 | "cannot prescan from (%s)", |
---|
1150 | shortenstring(from, MAXSHORTSTR)); |
---|
1151 | finis(true, true, ExitStat); |
---|
1152 | } |
---|
1153 | (void) REWRITE(pvp, 3, e); |
---|
1154 | (void) REWRITE(pvp, 1, e); |
---|
1155 | (void) REWRITE(pvp, 4, e); |
---|
1156 | macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); |
---|
1157 | bp = buf + 1; |
---|
1158 | cataddr(pvp, NULL, bp, sizeof buf - 2, '\0'); |
---|
1159 | if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) |
---|
1160 | { |
---|
1161 | /* heuristic: route-addr: add angle brackets */ |
---|
1162 | (void) sm_strlcat(bp, ">", sizeof buf - 1); |
---|
1163 | *--bp = '<'; |
---|
1164 | } |
---|
1165 | e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp); |
---|
1166 | macdefine(&e->e_macro, A_PERM, 'f', e->e_sender); |
---|
1167 | |
---|
1168 | /* save the domain spec if this mailer wants it */ |
---|
1169 | if (e->e_from.q_mailer != NULL && |
---|
1170 | bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) |
---|
1171 | { |
---|
1172 | char **lastat; |
---|
1173 | |
---|
1174 | /* get rid of any pesky angle brackets */ |
---|
1175 | macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); |
---|
1176 | (void) REWRITE(pvp, 3, e); |
---|
1177 | (void) REWRITE(pvp, 1, e); |
---|
1178 | (void) REWRITE(pvp, 4, e); |
---|
1179 | macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); |
---|
1180 | |
---|
1181 | /* strip off to the last "@" sign */ |
---|
1182 | for (lastat = NULL; *pvp != NULL; pvp++) |
---|
1183 | if (strcmp(*pvp, "@") == 0) |
---|
1184 | lastat = pvp; |
---|
1185 | if (lastat != NULL) |
---|
1186 | { |
---|
1187 | e->e_fromdomain = copyplist(lastat, true, e->e_rpool); |
---|
1188 | if (tTd(45, 3)) |
---|
1189 | { |
---|
1190 | sm_dprintf("Saving from domain: "); |
---|
1191 | printav(e->e_fromdomain); |
---|
1192 | } |
---|
1193 | } |
---|
1194 | } |
---|
1195 | } |
---|
1196 | /* |
---|
1197 | ** PRINTENVFLAGS -- print envelope flags for debugging |
---|
1198 | ** |
---|
1199 | ** Parameters: |
---|
1200 | ** e -- the envelope with the flags to be printed. |
---|
1201 | ** |
---|
1202 | ** Returns: |
---|
1203 | ** none. |
---|
1204 | */ |
---|
1205 | |
---|
1206 | struct eflags |
---|
1207 | { |
---|
1208 | char *ef_name; |
---|
1209 | unsigned long ef_bit; |
---|
1210 | }; |
---|
1211 | |
---|
1212 | static struct eflags EnvelopeFlags[] = |
---|
1213 | { |
---|
1214 | { "OLDSTYLE", EF_OLDSTYLE }, |
---|
1215 | { "INQUEUE", EF_INQUEUE }, |
---|
1216 | { "NO_BODY_RETN", EF_NO_BODY_RETN }, |
---|
1217 | { "CLRQUEUE", EF_CLRQUEUE }, |
---|
1218 | { "SENDRECEIPT", EF_SENDRECEIPT }, |
---|
1219 | { "FATALERRS", EF_FATALERRS }, |
---|
1220 | { "DELETE_BCC", EF_DELETE_BCC }, |
---|
1221 | { "RESPONSE", EF_RESPONSE }, |
---|
1222 | { "RESENT", EF_RESENT }, |
---|
1223 | { "VRFYONLY", EF_VRFYONLY }, |
---|
1224 | { "WARNING", EF_WARNING }, |
---|
1225 | { "QUEUERUN", EF_QUEUERUN }, |
---|
1226 | { "GLOBALERRS", EF_GLOBALERRS }, |
---|
1227 | { "PM_NOTIFY", EF_PM_NOTIFY }, |
---|
1228 | { "METOO", EF_METOO }, |
---|
1229 | { "LOGSENDER", EF_LOGSENDER }, |
---|
1230 | { "NORECEIPT", EF_NORECEIPT }, |
---|
1231 | { "HAS8BIT", EF_HAS8BIT }, |
---|
1232 | { "NL_NOT_EOL", EF_NL_NOT_EOL }, |
---|
1233 | { "CRLF_NOT_EOL", EF_CRLF_NOT_EOL }, |
---|
1234 | { "RET_PARAM", EF_RET_PARAM }, |
---|
1235 | { "HAS_DF", EF_HAS_DF }, |
---|
1236 | { "IS_MIME", EF_IS_MIME }, |
---|
1237 | { "DONT_MIME", EF_DONT_MIME }, |
---|
1238 | { "DISCARD", EF_DISCARD }, |
---|
1239 | { "TOOBIG", EF_TOOBIG }, |
---|
1240 | { "SPLIT", EF_SPLIT }, |
---|
1241 | { "UNSAFE", EF_UNSAFE }, |
---|
1242 | { NULL, 0 } |
---|
1243 | }; |
---|
1244 | |
---|
1245 | void |
---|
1246 | printenvflags(e) |
---|
1247 | register ENVELOPE *e; |
---|
1248 | { |
---|
1249 | register struct eflags *ef; |
---|
1250 | bool first = true; |
---|
1251 | |
---|
1252 | (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%lx", e->e_flags); |
---|
1253 | for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++) |
---|
1254 | { |
---|
1255 | if (!bitset(ef->ef_bit, e->e_flags)) |
---|
1256 | continue; |
---|
1257 | if (first) |
---|
1258 | (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "<%s", |
---|
1259 | ef->ef_name); |
---|
1260 | else |
---|
1261 | (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ",%s", |
---|
1262 | ef->ef_name); |
---|
1263 | first = false; |
---|
1264 | } |
---|
1265 | if (!first) |
---|
1266 | (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n"); |
---|
1267 | } |
---|