source: trunk/third/sendmail/sendmail/envelope.c @ 19204

Revision 19204, 30.6 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
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
16SM_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
28void
29clrsessenvelope(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
72ENVELOPE *
73newenvelope(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
157void
158dropenvelope(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
496simpledrop:
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
624void
625clearenvelope(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
716void
717initsys(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
800void
801settime(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
844void
845openxscript(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
891void
892closexscript(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
943void
944setsender(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
1206struct eflags
1207{
1208        char            *ef_name;
1209        unsigned long   ef_bit;
1210};
1211
1212static 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
1245void
1246printenvflags(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}
Note: See TracBrowser for help on using the repository browser.