OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
Subject: Postfix 19991231 Patchlevel 08 available
From: Wietse Venema (wietseporcupine.org)
Date: Sun May 28 2000 - 21:22:10 CDT


This patch provides an emergency band-aid for the next wave of
MicroSoft email worms, fixes one bug, and makes external content
filtering a bit more robust.

  - Feature: specify "body_checks = regexp:/etc/postfix/body_checks"
    for an emergency content filter that looks at non-header lines
    one line at a time (including MIME headers inside the message
    body). This feature uses the same syntax as the header_checks
    patterns. Details in conf/sample-filter.cf.

    This feature is also available in Postfix snapshot 20000528.

  - Bugfix: the masquerade_exceptions feature was case sensitive.

  - Robustness: upon receipt of mail, Postfix maps MAILER-DAEMONmyorigin
    sender address back into the magic null string, which prevents
    mail from looping after processing by an external content filter.

A fully-patched version of the source code is being made available
via the usual FTP servers, primary site:

    ftp://ftp.porcupine.org/mirrors/postfix-release/official/

Files: postfix-19991231-pl08.tar.gz and postfix-19991231-pl08.tar.gz.sig.

Or, if you use a web browser,

    ftp://ftp.porcupine.org/mirrors/postfix-release/index.html

Happy Postfixing.

        Wietse

Prereq: "Postfix-19991231-pl07"
diff -cr --new-file /tmp/postfix-19991231-pl07/global/mail_version.h ./global/mail_version.h
*** /tmp/postfix-19991231-pl07/global/mail_version.h Thu Apr 13 14:47:12 2000
--- ./global/mail_version.h Sun May 28 18:53:10 2000
***************
*** 15,21 ****
    * Version of this program.
    */
  #define VAR_MAIL_VERSION "mail_version"
! #define DEF_MAIL_VERSION "Postfix-19991231-pl07"
  extern char *var_mail_version;
  
  /* LICENSE
--- 15,21 ----
    * Version of this program.
    */
  #define VAR_MAIL_VERSION "mail_version"
! #define DEF_MAIL_VERSION "Postfix-19991231-pl08"
  extern char *var_mail_version;
  
  /* LICENSE
diff -cr --new-file /tmp/postfix-19991231-pl07/HISTORY ./HISTORY
*** /tmp/postfix-19991231-pl07/HISTORY Thu May 11 20:40:06 2000
--- ./HISTORY Sun May 28 18:50:49 2000
***************
*** 3713,3715 ****
--- 3713,3734 ----
  
          Bugfix: Postfix would incorrectly reject domain names with
          adjacent - characters. File: util/valid_hostname.c.
+
+ 20000520
+
+ Robustness: upon receipt of mail, map the mailer-daemon
+ sender address back into the magic null string. File:
+ cleanup/cleanup_envelope.c.
+
+ 20000524
+
+ Bugfix: the code for masquerade_exceptions was case sensitive.
+ Reported by Eduard Vopicka. File: cleanup/cleanup_masquerade.c.
+
+ 20000528
+
+ Feature: specify "body_checks=regexp:/file/name" for a very
+ crude one line at a time message body content filter. This
+ feature uses the same filtering syntax as the header_checks
+ feature. File: cleanup/cleanup_message.c. See also the
+ conf/sample-filter.cf file.
diff -cr --new-file /tmp/postfix-19991231-pl07/RELEASE_NOTES ./RELEASE_NOTES
*** /tmp/postfix-19991231-pl07/RELEASE_NOTES Thu May 11 19:40:45 2000
--- ./RELEASE_NOTES Sun May 28 19:43:08 2000
***************
*** 1,3 ****
--- 1,11 ----
+ Major changes with postfix-19991231-pl08:
+ =========================================
+
+ Specify "body_checks = regexp:/etc/postfix/body_checks" for a quick
+ and dirty emergency content filter that looks at non-header lines
+ one line at a time (including MIME headers inside the message body).
+ Details in conf/sample-filter.cf.
+
  Incompatible changes with postfix-19991231-pl07:
  ================================================
  
diff -cr --new-file /tmp/postfix-19991231-pl07/cleanup/cleanup.c ./cleanup/cleanup.c
*** /tmp/postfix-19991231-pl07/cleanup/cleanup.c Thu Apr 13 13:39:10 2000
--- ./cleanup/cleanup.c Sun May 28 19:00:34 2000
***************
*** 60,65 ****
--- 60,74 ----
  /* this program. See the Postfix \fBmain.cf\fR file for syntax details
  /* and for default values. Use the \fBpostfix reload\fR command after
  /* a configuration change.
+ /* .SH Content filtering
+ /* .IP \fBbody_checks\fR
+ /* Lookup tables with content filters for message body lines.
+ /* These filters see physical lines one at a time, in chunks of
+ /* at most line_length_limit bytes.
+ /* .IP \fBheader_checks\fR
+ /* Lookup tables with content filters for message header lines.
+ /* These filters see logical headers one at a time, including headers
+ /* that span multiple lines.
  /* .SH Miscellaneous
  /* .ad
  /* .fi
***************
*** 175,180 ****
--- 184,190 ----
  char *var_masq_domains; /* masquerade domains */
  char *var_masq_exceptions; /* users not masqueraded */
  char *var_header_checks; /* any header checks */
+ char *var_body_checks; /* any body checks */
  int var_dup_filter_limit; /* recipient dup filter */
  char *var_empty_addr; /* destination of bounced bounces */
  int var_delay_warn_time; /* delay that triggers warning */
***************
*** 189,194 ****
--- 199,205 ----
  MAPS *cleanup_send_canon_maps;
  MAPS *cleanup_rcpt_canon_maps;
  MAPS *cleanup_header_checks;
+ MAPS *cleanup_body_checks;
  MAPS *cleanup_virtual_maps;
  ARGV *cleanup_masq_domains;
  
***************
*** 420,425 ****
--- 431,439 ----
      if (*var_header_checks)
          cleanup_header_checks =
              maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
+ if (*var_body_checks)
+ cleanup_body_checks =
+ maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
  }
  
  /* pre_accept - see if tables have changed */
***************
*** 473,478 ****
--- 487,493 ----
          VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
          VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
          VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0,
+ VAR_BODY_CHECKS, DEF_BODY_CHECKS, &var_body_checks, 0, 0,
          VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
          VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
          VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0,
diff -cr --new-file /tmp/postfix-19991231-pl07/cleanup/cleanup.h ./cleanup/cleanup.h
*** /tmp/postfix-19991231-pl07/cleanup/cleanup.h Sat May 8 19:18:44 1999
--- ./cleanup/cleanup.h Sun May 28 20:50:09 2000
***************
*** 62,67 ****
--- 62,68 ----
  extern MAPS *cleanup_send_canon_maps;
  extern MAPS *cleanup_rcpt_canon_maps;
  extern MAPS *cleanup_header_checks;
+ extern MAPS *cleanup_body_checks;
  extern MAPS *cleanup_virtual_maps;
  extern ARGV *cleanup_masq_domains;
  
diff -cr --new-file /tmp/postfix-19991231-pl07/cleanup/cleanup_envelope.c ./cleanup/cleanup_envelope.c
*** /tmp/postfix-19991231-pl07/cleanup/cleanup_envelope.c Wed Jun 23 21:40:37 1999
--- ./cleanup/cleanup_envelope.c Sat May 20 13:00:01 2000
***************
*** 30,35 ****
--- 30,39 ----
  #include <string.h>
  #include <stdlib.h>
  
+ #ifdef STRCASECMP_IN_STRINGS_H
+ #include <strings.h>
+ #endif
+
  /* Utility library. */
  
  #include <msg.h>
***************
*** 45,50 ****
--- 49,56 ----
  #include <tok822.h>
  #include <mail_params.h>
  #include <ext_prop.h>
+ #include <mail_addr.h>
+ #include <canon_addr.h>
  
  /* Application-specific. */
  
***************
*** 106,111 ****
--- 112,123 ----
              cleanup_fullname = mystrdup(STR(cleanup_inbuf));
          } else if (type == REC_TYPE_FROM) {
              cleanup_rewrite_internal(clean_addr, STR(cleanup_inbuf));
+ if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "",
+ sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
+ canon_addr_internal(cleanup_temp1, MAIL_ADDR_MAIL_DAEMON);
+ if (strcasecmp(STR(clean_addr), STR(cleanup_temp1)) == 0)
+ vstring_strcpy(clean_addr, "");
+ }
              if (cleanup_send_canon_maps)
                  cleanup_map11_internal(clean_addr, cleanup_send_canon_maps,
                                  cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
diff -cr --new-file /tmp/postfix-19991231-pl07/cleanup/cleanup_masquerade.c ./cleanup/cleanup_masquerade.c
*** /tmp/postfix-19991231-pl07/cleanup/cleanup_masquerade.c Tue Jan 19 09:02:22 1999
--- ./cleanup/cleanup_masquerade.c Sun May 28 18:54:03 2000
***************
*** 99,105 ****
          masq_except_table = htable_create(5);
          ptr = saved_names = mystrdup(var_masq_exceptions);
          while ((name = mystrtok(&ptr, ", \t\r\n")) != 0)
! htable_enter(masq_except_table, name, (char *) 0);
          myfree(saved_names);
      }
  
--- 99,105 ----
          masq_except_table = htable_create(5);
          ptr = saved_names = mystrdup(var_masq_exceptions);
          while ((name = mystrtok(&ptr, ", \t\r\n")) != 0)
! htable_enter(masq_except_table, lowercase(name), (char *) 0);
          myfree(saved_names);
      }
  
***************
*** 116,122 ****
       */
      if (masq_except_table) {
          name = mystrndup(STR(addr), domain - 1 - STR(addr));
! excluded = (htable_locate(masq_except_table, name) != 0);
          myfree(name);
          if (excluded)
              return;
--- 116,122 ----
       */
      if (masq_except_table) {
          name = mystrndup(STR(addr), domain - 1 - STR(addr));
! excluded = (htable_locate(masq_except_table, lowercase(name)) != 0);
          myfree(name);
          if (excluded)
              return;
diff -cr --new-file /tmp/postfix-19991231-pl07/cleanup/cleanup_message.c ./cleanup/cleanup_message.c
*** /tmp/postfix-19991231-pl07/cleanup/cleanup_message.c Thu Apr 13 17:23:31 2000
--- ./cleanup/cleanup_message.c Sun May 28 21:20:35 2000
***************
*** 240,246 ****
  
          if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) {
              if (strcasecmp(value, "REJECT") == 0) {
! msg_warn("%s: reject: header %.100s", cleanup_queue_id, header);
                  cleanup_errs |= CLEANUP_STAT_CONT;
              }
          }
--- 240,246 ----
  
          if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) {
              if (strcasecmp(value, "REJECT") == 0) {
! msg_warn("%s: reject: header %.200s", cleanup_queue_id, header);
                  cleanup_errs |= CLEANUP_STAT_CONT;
              }
          }
***************
*** 460,465 ****
--- 460,487 ----
              if (in_header) {
                  vstring_strcpy(cleanup_header_buf, start);
              } else {
+
+ /*
+ * Crude message body content filter for emergencies. This
+ * code has several problems: it sees one line at a time, and
+ * therefore does not recognize multi-line MIME headers in
+ * the body; it looks at long lines only in chunks of
+ * line_length_limit (2048) characters; it is easily bypassed
+ * with encodings and with multi-line tricks.
+ */
+ if ((cleanup_flags & CLEANUP_FLAG_FILTER)
+ && cleanup_body_checks) {
+ char *body = vstring_str(cleanup_inbuf);
+ const char *value;
+
+ if ((value = maps_find(cleanup_body_checks, body, 0)) != 0) {
+ if (strcasecmp(value, "REJECT") == 0) {
+ msg_warn("%s: reject: body %.200s",
+ cleanup_queue_id, body);
+ cleanup_errs |= CLEANUP_STAT_CONT;
+ }
+ }
+ }
                  CLEANUP_OUT_BUF(type, cleanup_inbuf);
              }
          }
diff -cr --new-file /tmp/postfix-19991231-pl07/conf/sample-filter.cf ./conf/sample-filter.cf
*** /tmp/postfix-19991231-pl07/conf/sample-filter.cf Wed Dec 31 19:00:00 1969
--- ./conf/sample-filter.cf Sun May 28 18:57:56 2000
***************
*** 0 ****
--- 1,24 ----
+ # DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
+ # HERE JUST SERVES AS AN EXAMPLE.
+ #
+ # This file contains example settings for miscellaneous Postfix
+ # content filtering parameters.
+
+ # The header_checks parameter specifies an optional table with patterns
+ # that each logical message header is matched against, including
+ # headers that span multiple physical lines. Patterns are matched
+ # in the specified order, and the search stops upon the first match.
+ # When a pattern matches, and the associated action is REJECT, the
+ # entire message is rejected.
+ #
+ header_checks = regexp:/etc/postfix/header_checks
+
+ # The body_checks parameter specifies an optional table with patterns
+ # that each physical non-header line is matched against (including
+ # MIME headers inside the message body). Lines are matched one at
+ # a time. Long lines are matched in chunks of at most $line_length_limit
+ # characters. Patterns are matched in the specified order, and the
+ # search stops upon the first match. When a pattern matches, and
+ # the associated action is REJECT, the entire message is rejected.
+ #
+ body_checks = regexp:/etc/postfix/body_checks
diff -cr --new-file /tmp/postfix-19991231-pl07/global/mail_params.h ./global/mail_params.h
*** /tmp/postfix-19991231-pl07/global/mail_params.h Sun Apr 16 12:00:49 2000
--- ./global/mail_params.h Sun May 28 18:52:09 2000
***************
*** 661,666 ****
--- 661,670 ----
  #define DEF_HEADER_CHECKS ""
  extern char *var_header_checks;
  
+ #define VAR_BODY_CHECKS "body_checks"
+ #define DEF_BODY_CHECKS ""
+ extern char *var_body_checks;
+
   /*
    * Bounce service: truncate bounce message that exceed $bounce_size_limit.
    */