Penetration Testing mailing list archives

Re: [PEN-TEST] Sendmail: Keeping a copy of relayed email


From: "José M. Fandiño" <jm.fandino () FADESA ES>
Date: Wed, 30 Aug 2000 10:00:56 +0200

Hello,

I found this code, but I don't know the author.
It's working in sendmail 8.9.3

regards,


David Taylor wrote:
My problem is - I want to keep a copy of the incoming email that I relay
off my machine.



--
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS d- s+: a- C+++ UL++++$ P+ L+++ E--- W++ N+ o K- w---
O+ M+ V- PS PE+ Y PGP+>+++ t+ 5 X+++ R- tv@ b+++ DI-- D+++
G e- h++ !r !z
------END GEEK CODE BLOCK------
/* ------------------------------------------------------------
 *      "LogAll" feature to log any message through this MTA
 *      (c) /ARX cleanware 1998
 */
{
#define LOGALLHEADER    "X-Logged"
#define LOGALLLEVEL     12

        char logallrcsid[] =
                "$Id: logall.c,v 1.11 1998/09/19 10:12:04 root Exp root $";
/*
 *      $Log: logall.c,v $
 *      Revision 1.11  1998/09/19 10:12:04  root
 *      published
 *
 *      Revision 1.7  1998/09/17 07:12:49  root
 *      clobbered qtimestr
 *
 *      ABSTRACT
 *      This routine logs every message in a mail folder
 *      before it is actually transmitted. The log is
 *      "envelope-oriented" which means it logs every message
 *      once - not for every recipient. You must also see
 *      the sendmail syslog for actual delivery. The log
 *      includes full message bodys.
 *
 *      IMPLEMENTATION
 *      The logging code is compiled into the sendmail binary
 *      with the documented and often overlooked checkcompat()
 *      routine:
 *      see "Bryan Costales & Eric Allman: sendmail 2nd Edition
 *              §20 `The checkcompat() Cookbook' p.285ff"
 *      To check whether a message was already logged it adds
 *      a new header "X-Logged" to the message with the logging
 *      host, the envelope id and queued date/time as values.
 *      As long as this info doesn't change the message is no
 *      more logged.
 *
 *      CONFIGURATION
 *      The logfile is configuerd in a new macro:
 *      D{LogAll}path
 *      where path is the full pathname of the logfile, which
 *      should be mode 600. REMEMBER THIS IS A FULL BODY LOG.
 *      So be prepared for a huge file on site with much traffic.
 *      The file must exist and every mail is appended to it.
 *      The macro should be inserted into a m4-config-file for
 *      example like this:
 *
 *              LOCAL_CONFIG
 *              D{LogAll}/var/log/mail.log
 *
 *      INSTALLATION
 *      This source fragment must be included into the source-file:
 *      .../sendmail-8.x.y/src/conf.c
 *      at the following position (with the full path name of its
 *      current location - here "/root/adm/mail/sendmail/logall.c"):
 *
 *>>old         if (tTd(49, 1))
 *>>old                 printf("checkcompat(to=%s, from=%s)\n",             
 *>>old                         to->q_paddr, e->e_from.q_paddr);           
 *>>old
 *>>new         #include "/root/adm/mail/sendmail/logall.c"
 *>>old
 *>>old         # ifdef EXAMPLE_CODE
 *
 *      the sendmail binary must be remaked and reinstalled at
 *      its proper position (normally /usr/sbin/sendmail).
 *
 *      MANAGEMENT
 *      Since the logfile produced by LogAll is a standard Unix-mailfolder,
 *      the logged mails can be managed with every Unix mail-reader or MUA.
 *      The mails inside the log can be deleted, remailed, read with any
 *      mail user agent. If the logfile is the standard mail folder of a
 *      special "LogAll-user" this is especially easy and even "mail" can
 *      or a Windows-based IMAP-client can manage the logfile.
 *
 *      COMPATIBILITY
 *      LogAll is tested with sendmail-8.8.5 and sendmail-8.9.1
 *      under Linux 2.0.29.
 *
 *      AUTHOR
 *      Axel Reinhold - arx () hof baynet de
 *
 *      LICENSE/WARRANTY
 *      The software is provided "AS IS" without warranties of any kind,
 *      either expressed or implied, including, but not limited to the
 *      implied warranties of merchantability and fitness for a particular
 *      purpose. The entire risc of the software is with you. In no event
 *      we will be liable for any damages, including any lost profits,
 *      lost savings or other incidental damages arising out of the use
 *      or inability to use the software, even if we have been advised
 *      of the possibility of such damages, or for any claim by another party.
 *   ------------------------------------------------------------
 */

        int mid;                        /* sendmail macro id                */
        char *logall = NULL;            /* log file path from macro LogAll  */
        char bfpath[512];               /* body file path                   */
        char *hlogged = LOGALLHEADER;   /* header field                     */
        char hlogval[MAXLINE];          /* header value                     */
        char *hlogvalp;                 /* header value pointer             */
        char qtimestr[80];              /* queued time string from asctime  */
        FILE *lf, *bf;                  /* log and body files               */
        ADDRESS *a;                     /* address structure                */
        HDR *h;                         /* header structure                 */
        int toflag = 0;                 /* to header flag                   */
        int fromflag = 0;               /* from header flag                 */
        long bfpos;                     /* remember file pos                */
        size_t b_read;                  /* bytes read counter               */
        unsigned char b_buf[512];       /* buffer for read/write body       */

        mid = macid("{LogAll}", NULL);  /* get our config macro             */
        logall = macvalue(mid, e);      /* to check whether and where to log*/

        /* Use logging if macro is set and we can open the logfile          */
        if ((logall!=NULL) && ((lf = fopen(logall, "a"))!=NULL)) {
            if (tTd(49, 1))             /* debug use of logging             */
                printf("checkcompat: LogAll=%s e_id=%s\n", logall, e->e_id);

            /* construct the "X-Logged" header field */
            strcpy(qtimestr, asctime(localtime(&e->e_ctime))); /* get time  */
            if (qtimestr[strlen(qtimestr)-1]=='\n')     /* remove trailing  */
                qtimestr[strlen(qtimestr)-1]='\0';      /* line-feed asctime*/
            sprintf(hlogval, "Logged by %s as %s at %s",
                MyHostName, e->e_id, qtimestr);         /* our header field */

            /* add the header if it doesn't already exist                   */
            hlogvalp = hvalue(hlogged, e->e_header);    /* get actual field */
            if (hlogvalp==NULL) addheader(hlogged, hlogval, &e->e_header);

            /* Log the message if our header didn't exist or was not from us*/
            if ((hlogvalp==NULL) || (strcmp(hlogvalp, hlogval)!=0)) {

                /* lock the logfile exclusive                               */
                if (lockfile(fileno(lf), logall, NULL, LOCK_EX)) ;
                fseek(lf, 0, SEEK_END); /* go the eof for appending message */

                /* syslog the usage of LogAll                               */
                if (LogLevel >= LOGALLLEVEL) sm_syslog(LOG_INFO, e->e_id,
                        "LogAll to %s at %s", logall, qtimestr);

                /* print the Unix From line to separate messages in log file*/
                fprintf(lf, "From %s %s\n", e->e_from.q_user, qtimestr);

                /* scan all headers                                         */
                for (h = e->e_header; h != NULL; h = h->h_link) {

                        /* check if our header is from us and recent        */
                        /* if not change the field value to our field       */
                        if (strcasecmp(h->h_field, hlogged)==0) {
                                if (hlogvalp!=NULL) {
                                        h->h_value =
                                         realloc(h->h_value, strlen(hlogval)+1);
                                        strcpy(h->h_value, hlogval);
                                        }
                                h->h_flags &= ~H_DEFAULT;       /* set flag */
                                }

                        /* log the header if appropiate                     */
                        if ((h->h_value!=NULL) && ((h->h_flags & H_RESENT)==0)) {
                                fprintf(lf, "%s: %s\n", h->h_field, h->h_value);
                                }

                        if (h->h_flags & H_RCPT) toflag = 1;    /* to-header*/

                        }
                if (!toflag) {  /* if no to-header construct from envelope  */
                        fprintf(lf, "To:");
                        for (a = e->e_sendqueue; a != NULL; a = a->q_next)
                                fprintf(lf, " %s", a->q_paddr);
                        fprintf(lf, "\n");
                        }
                fprintf(lf, "\n");      /* separate headers from body       */

                /* now add the body from temp file or queued data file      */
                sprintf(bfpath, "%s/df%s", QueueDir, e->e_id); /* body file */
                if (e->e_dfp != NULL) { /* if body temp file is open use it */
                        bfpos = ftell(e->e_dfp);/* remember old position    */
                        rewind(e->e_dfp);       /* read from beginning      */
                        while ((b_read = fread(b_buf, 1L, sizeof(b_buf), e->e_dfp)) != 0)
                                fwrite(b_buf, 1L, b_read, lf);
                        fseek(e->e_dfp, bfpos, SEEK_SET); /* set old pos    */
                        }
                else if ((bf = fopen(bfpath, "r")) != NULL) { /* body file  */
                        while ((b_read = fread(b_buf, 1, sizeof(b_buf), bf)) != 0)
                                fwrite(b_buf, 1, b_read, lf);
                        fclose(bf);
                        }
                else    { /* no body could be opened                        */
                        if (tTd(49, 1))
                            printf("checkcompat: fopen(%s) failed\n", bfpath);
                        }
                fprintf(lf, "\n");

                if (lockfile(fileno(lf), logall, NULL, LOCK_UN)) ; /* unlock*/
                }
            fclose(lf);
            }

/*   ------------------------------------------------------------
 *      LogAll End
 *   ------------------------------------------------------------
 */
}

Current thread: