]> git.netwichtig.de Git - user/henk/code/exim.git/blobdiff - src/src/receive.c
Make $acl_verify_message available in following conditions and modifiers
[user/henk/code/exim.git] / src / src / receive.c
index 7f814e64a6c5ec482435c5f004683c0b628f48e5..325544643b08c2e43bb1e05d07058614b9f5df12 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.13 2005/04/04 10:33:49 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -9,10 +9,15 @@
 
 /* Code for receiving a message and setting up spool files. */
 
-
 #include "exim.h"
 
-
+#ifdef EXPERIMENTAL_DOMAINKEYS
+#define RECEIVE_GETC dk_receive_getc
+#define RECEIVE_UNGETC dk_receive_ungetc
+#else
+#define RECEIVE_GETC receive_getc
+#define RECEIVE_UNGETC receive_ungetc
+#endif
 
 /*************************************************
 *                Local static variables          *
@@ -505,7 +510,7 @@ for (count = 0; count < recipients_count; count++)
     {
     if ((--recipients_count - count) > 0)
       memmove(recipients_list + count, recipients_list + count + 1,
-              (recipients_count - count)*sizeof(recipient_item));
+        (recipients_count - count)*sizeof(recipient_item));
     return TRUE;
     }
   }
@@ -565,7 +570,7 @@ if (!dot_ends)
   {
   register int last_ch = '\n';
 
-  for (; (ch = (receive_getc)()) != EOF; last_ch = ch)
+  for (; (ch = (RECEIVE_GETC)()) != EOF; last_ch = ch)
     {
     if (ch == 0) body_zerocount++;
     if (last_ch == '\r' && ch != '\n')
@@ -595,7 +600,7 @@ if (!dot_ends)
 
 ch_state = 1;
 
-while ((ch = (receive_getc)()) != EOF)
+while ((ch = (RECEIVE_GETC)()) != EOF)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
@@ -696,7 +701,7 @@ read_message_data_smtp(FILE *fout)
 int ch_state = 0;
 register int ch;
 
-while ((ch = (receive_getc)()) != EOF)
+while ((ch = (RECEIVE_GETC)()) != EOF)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
@@ -1003,6 +1008,146 @@ return s;
 
 
 
+/*************************************************
+*       Run the MIME ACL on a message            *
+*************************************************/
+
+/* This code is in a subroutine so that it can be used for both SMTP
+and non-SMTP messages. It is called with a non-NULL ACL pointer.
+
+Arguments:
+  acl                The ACL to run (acl_smtp_mime or acl_not_smtp_mime)
+  smtp_yield_ptr     Set FALSE to kill messages after dropped connection
+  smtp_reply_ptr     Where SMTP reply is being built
+  blackholed_by_ptr  Where "blackholed by" message is being built
+
+Returns:             TRUE to carry on; FALSE to abandon the message
+*/
+
+static BOOL
+run_mime_acl(uschar *acl, BOOL *smtp_yield_ptr, uschar **smtp_reply_ptr,
+  uschar **blackholed_by_ptr)
+{
+FILE *mbox_file;
+uschar rfc822_file_path[2048];
+unsigned long mbox_size;
+header_line *my_headerlist;
+uschar *user_msg, *log_msg;
+int mime_part_count_buffer = -1;
+int rc;
+
+memset(CS rfc822_file_path,0,2048);
+
+/* check if it is a MIME message */
+my_headerlist = header_list;
+while (my_headerlist != NULL) {
+  /* skip deleted headers */
+  if (my_headerlist->type == '*') {
+    my_headerlist = my_headerlist->next;
+    continue;
+  };
+  if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
+    DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
+    goto DO_MIME_ACL;
+  };
+  my_headerlist = my_headerlist->next;
+};
+
+DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
+return TRUE;
+
+DO_MIME_ACL:
+/* make sure the eml mbox file is spooled up */
+mbox_file = spool_mbox(&mbox_size);
+if (mbox_file == NULL) {
+  /* error while spooling */
+  log_write(0, LOG_MAIN|LOG_PANIC,
+         "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
+  Uunlink(spool_name);
+  unspool_mbox();
+  smtp_respond(451, TRUE, US"temporary local problem");
+  message_id[0] = 0;            /* Indicate no message accepted */
+  *smtp_reply_ptr = US"";       /* Indicate reply already sent */
+  return FALSE;                 /* Indicate skip to end of receive function */
+};
+
+mime_is_rfc822 = 0;
+
+MIME_ACL_CHECK:
+mime_part_count = -1;
+rc = mime_acl_check(acl, mbox_file, NULL, &user_msg, &log_msg);
+fclose(mbox_file);
+
+if (Ustrlen(rfc822_file_path) > 0) {
+  mime_part_count = mime_part_count_buffer;
+
+  if (unlink(CS rfc822_file_path) == -1) {
+    log_write(0, LOG_PANIC,
+         "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
+      goto END_MIME_ACL;
+  };
+};
+
+/* check if we must check any message/rfc822 attachments */
+if (rc == OK) {
+  uschar temp_path[1024];
+  int n;
+  struct dirent *entry;
+  DIR *tempdir;
+
+  snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id);
+
+ tempdir = opendir(CS temp_path);
+ n = 0;
+ do {
+   entry = readdir(tempdir);
+   if (entry == NULL) break;
+    if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
+      snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
+     debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
+     break;
+    };
+ } while (1);
+ closedir(tempdir);
+
+  if (entry != NULL) {
+    mbox_file = Ufopen(rfc822_file_path,"r");
+    if (mbox_file == NULL) {
+      log_write(0, LOG_PANIC,
+         "acl_smtp_mime: can't open RFC822 spool file, skipping.");
+      unlink(CS rfc822_file_path);
+      goto END_MIME_ACL;
+    };
+    /* set RFC822 expansion variable */
+    mime_is_rfc822 = 1;
+    mime_part_count_buffer = mime_part_count;
+    goto MIME_ACL_CHECK;
+  };
+};
+
+END_MIME_ACL:
+add_acl_headers(US"MIME");
+if (rc == DISCARD)
+  {
+  recipients_count = 0;
+  *blackholed_by_ptr = US"MIME ACL";
+  }
+else if (rc != OK)
+  {
+  Uunlink(spool_name);
+  unspool_mbox();
+  if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
+    *smtp_yield_ptr = FALSE;    /* No more messsages after dropped connection */
+  *smtp_reply_ptr = US"";       /* Indicate reply already sent */
+  message_id[0] = 0;            /* Indicate no message accepted */
+  return FALSE;                 /* Cause skip to end of receive function */
+  };
+
+return TRUE;
+}
+
+
+
 /*************************************************
 *                 Receive message                *
 *************************************************/
@@ -1197,6 +1342,12 @@ from the spool for delivery. */
 
 body_linecount = body_zerocount = 0;
 
+#ifdef EXPERIMENTAL_DOMAINKEYS
+/* Call into DK to set up the context. Check if DK is to be run are carried out
+   inside dk_exim_verify_init(). */
+dk_exim_verify_init();
+#endif
+
 /* Remember the time of reception. Exim uses time+pid for uniqueness of message
 ids, and fractions of a second are required. See the comments that precede the
 message id creation below. */
@@ -1245,7 +1396,7 @@ next->text. */
 
 for (;;)
   {
-  int ch = (receive_getc)();
+  int ch = (RECEIVE_GETC)();
 
   /* If we hit EOF on a SMTP connection, it's an error, since incoming
   SMTP must have a correct "." terminator. */
@@ -1309,7 +1460,7 @@ for (;;)
   if (ch == '\n')
     {
     if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE;
-      else if (first_line_ended_crlf) receive_ungetc(' ');
+      else if (first_line_ended_crlf) RECEIVE_UNGETC(' ');
     goto EOL;
     }
 
@@ -1324,13 +1475,13 @@ for (;;)
 
   if (ptr == 0 && ch == '.' && (smtp_input || dot_ends))
     {
-    ch = (receive_getc)();
+    ch = (RECEIVE_GETC)();
     if (ch == '\r')
       {
-      ch = (receive_getc)();
+      ch = (RECEIVE_GETC)();
       if (ch != '\n')
         {
-        receive_ungetc(ch);
+        RECEIVE_UNGETC(ch);
         ch = '\r';              /* Revert to CR */
         }
       }
@@ -1358,7 +1509,7 @@ for (;;)
 
   if (ch == '\r')
     {
-    ch = (receive_getc)();
+    ch = (RECEIVE_GETC)();
     if (ch == '\n')
       {
       if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE;
@@ -1368,7 +1519,7 @@ for (;;)
     /* Otherwise, put back the character after CR, and turn the bare CR
     into LF SP. */
 
-    ch = (receive_ungetc)(ch);
+    ch = (RECEIVE_UNGETC)(ch);
     next->text[ptr++] = '\n';
     message_size++;
     ch = ' ';
@@ -1443,14 +1594,14 @@ for (;;)
 
   if (ch != EOF)
     {
-    int nextch = (receive_getc)();
+    int nextch = (RECEIVE_GETC)();
     if (nextch == ' ' || nextch == '\t')
       {
       next->text[ptr++] = nextch;
       message_size++;
       continue;                      /* Iterate the loop */
       }
-    else if (nextch != EOF) (receive_ungetc)(nextch);   /* For next time */
+    else if (nextch != EOF) (RECEIVE_UNGETC)(nextch);   /* For next time */
     else ch = EOF;                   /* Cause main loop to exit at end */
     }
 
@@ -2738,128 +2889,18 @@ else
   if (smtp_input && !smtp_batched_input)
     {
 
-#ifdef WITH_CONTENT_SCAN
-     /* MIME ACL hook */
-    if (acl_smtp_mime != NULL && recipients_count > 0)
-      {
-      FILE *mbox_file;
-      uschar rfc822_file_path[2048];
-      unsigned long mbox_size;
-      header_line *my_headerlist;
-      uschar *user_msg, *log_msg;
-      int mime_part_count_buffer = -1;
-
-      memset(CS rfc822_file_path,0,2048);
-
-      /* check if it is a MIME message */
-      my_headerlist = header_list;
-      while (my_headerlist != NULL) {
-        /* skip deleted headers */
-        if (my_headerlist->type == '*') {
-          my_headerlist = my_headerlist->next;
-          continue;
-        };
-        if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
-          DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
-          goto DO_MIME_ACL;
-        };
-        my_headerlist = my_headerlist->next;
-      };
-
-      DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
-      goto NO_MIME_ACL;
-
-      DO_MIME_ACL:
-      /* make sure the eml mbox file is spooled up */
-      mbox_file = spool_mbox(&mbox_size);
-      if (mbox_file == NULL) {
-        /* error while spooling */
-        log_write(0, LOG_MAIN|LOG_PANIC,
-               "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
-        Uunlink(spool_name);
-        unspool_mbox();
-        smtp_respond(451, TRUE, US"temporary local problem");
-        message_id[0] = 0;            /* Indicate no message accepted */
-        smtp_reply = US"";            /* Indicate reply already sent */
-        goto TIDYUP;                  /* Skip to end of function */
-      };
-
-      mime_is_rfc822 = 0;
-
-      MIME_ACL_CHECK:
-      mime_part_count = -1;
-      rc = mime_acl_check(mbox_file, NULL, &user_msg, &log_msg);
-      fclose(mbox_file);
-
-      if (Ustrlen(rfc822_file_path) > 0) {
-        mime_part_count = mime_part_count_buffer;
-
-        if (unlink(CS rfc822_file_path) == -1) {
-          log_write(0, LOG_PANIC,
-               "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
-            goto END_MIME_ACL;
-        };
-      };
-
-      /* check if we must check any message/rfc822 attachments */
-      if (rc == OK) {
-        uschar temp_path[1024];
-        int n;
-        struct dirent *entry;
-        DIR *tempdir;
-
-        snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id);
-
-       tempdir = opendir(CS temp_path);
-       n = 0;
-       do {
-         entry = readdir(tempdir);
-         if (entry == NULL) break;
-          if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
-            snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
-           debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
-           break;
-          };
-       } while (1);
-       closedir(tempdir);
-
-        if (entry != NULL) {
-          mbox_file = Ufopen(rfc822_file_path,"r");
-          if (mbox_file == NULL) {
-            log_write(0, LOG_PANIC,
-               "acl_smtp_mime: can't open RFC822 spool file, skipping.");
-            unlink(CS rfc822_file_path);
-            goto END_MIME_ACL;
-          };
-          /* set RFC822 expansion variable */
-          mime_is_rfc822 = 1;
-          mime_part_count_buffer = mime_part_count;
-          goto MIME_ACL_CHECK;
-        };
-      };
-
-      END_MIME_ACL:
-      add_acl_headers(US"MIME");
-      if (rc == DISCARD)
-        {
-        recipients_count = 0;
-        blackholed_by = US"MIME ACL";
-        }
-      else if (rc != OK)
-        {
-        Uunlink(spool_name);
-        unspool_mbox();
-        if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
-          smtp_yield = FALSE;    /* No more messsages after dropped connection */
-        smtp_reply = US"";       /* Indicate reply already sent */
-        message_id[0] = 0;       /* Indicate no message accepted */
-        goto TIDYUP;             /* Skip to end of function */
-        };
-      }
+#ifdef EXPERIMENTAL_DOMAINKEYS
+    dk_exim_verify_finish();
+#endif
 
-    NO_MIME_ACL:
+#ifdef WITH_CONTENT_SCAN
+    if (acl_smtp_mime != NULL &&
+        !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by))
+      goto TIDYUP;
 #endif /* WITH_CONTENT_SCAN */
 
+    /* Check the recipients count again, as the MIME ACL might have changed
+    them. */
 
     if (acl_smtp_data != NULL && recipients_count > 0)
       {
@@ -2891,39 +2932,56 @@ else
   /* Handle non-SMTP and batch SMTP (i.e. non-interactive) messages. Note that
   we cannot take different actions for permanent and temporary rejections. */
 
-  else if (acl_not_smtp != NULL)
+  else
     {
-    uschar *user_msg, *log_msg;
-    rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg);
-    if (rc == DISCARD)
-      {
-      recipients_count = 0;
-      blackholed_by = US"non-SMTP ACL";
-      if (log_msg != NULL) blackhole_log_msg = string_sprintf(": %s", log_msg);
-      }
-    else if (rc != OK)
+
+#ifdef WITH_CONTENT_SCAN
+    if (acl_not_smtp_mime != NULL &&
+        !run_mime_acl(acl_not_smtp_mime, &smtp_yield, &smtp_reply,
+          &blackholed_by))
+      goto TIDYUP;
+#endif /* WITH_CONTENT_SCAN */
+
+    if (acl_not_smtp != NULL)
       {
-      Uunlink(spool_name);
-      log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s",
-        sender_address, log_msg);
-      if (user_msg == NULL) user_msg = US"local configuration problem";
-      if (smtp_batched_input)
+      uschar *user_msg, *log_msg;
+      rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg);
+      if (rc == DISCARD)
         {
-        moan_smtp_batch(NULL, "%d %s", 550, user_msg);
-        /* Does not return */
+        recipients_count = 0;
+        blackholed_by = US"non-SMTP ACL";
+        if (log_msg != NULL)
+          blackhole_log_msg = string_sprintf(": %s", log_msg);
         }
-      else
+      else if (rc != OK)
         {
-        fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
-        give_local_error(ERRMESS_LOCAL_ACL, user_msg,
-          US"message rejected by non-SMTP ACL: ", error_rc, data_file,
-            header_list);
-        /* Does not return */
+        Uunlink(spool_name);
+#ifdef WITH_CONTENT_SCAN
+        unspool_mbox();
+#endif
+        log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s",
+          sender_address, log_msg);
+        if (user_msg == NULL) user_msg = US"local configuration problem";
+        if (smtp_batched_input)
+          {
+          moan_smtp_batch(NULL, "%d %s", 550, user_msg);
+          /* Does not return */
+          }
+        else
+          {
+          fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
+          give_local_error(ERRMESS_LOCAL_ACL, user_msg,
+            US"message rejected by non-SMTP ACL: ", error_rc, data_file,
+              header_list);
+          /* Does not return */
+          }
         }
+      add_acl_headers(US"non-SMTP");
       }
-    add_acl_headers(US"non-SMTP");
     }
 
+  /* The applicable ACLs have been run */
+
   if (deliver_freeze) frozen_by = US"ACL";     /* for later logging */
   if (queue_only_policy) queued_by = US"ACL";