Merge from EXISCAN branch.
[exim.git] / src / src / receive.c
index 0ed05f1db213f8cacc59c62d4c7ea48991f05646..7b97b4b22ea7dbc3639c89a5940642d527d69913 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.5 2004/11/25 13:54:31 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.6 2004/12/16 15:11:47 tom Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -470,6 +470,11 @@ if (recipients_count >= recipients_list_max)
 
 recipients_list[recipients_count].address = recipient;
 recipients_list[recipients_count].pno = pno;
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+recipients_list[recipients_count].bmi_optin = bmi_current_optin;
+/* reset optin string pointer for next recipient */
+bmi_current_optin = NULL;
+#endif
 recipients_list[recipients_count++].errors_to = NULL;
 }
 
@@ -918,6 +923,21 @@ for (h = acl_warn_headers; h != NULL; h = next)
     DEBUG(D_receive|D_acl) debug_printf("  (after Received:)");
     break;
 
+    case htype_add_rfc:
+    /* add header before any header which is NOT Received: or Resent- */
+    last_received = header_list;
+    while ( (last_received->next != NULL) &&
+            ( (header_testname(last_received->next, US"Received", 8, FALSE)) ||
+              (header_testname_incomplete(last_received->next, US"Resent-", 7, FALSE)) ) )
+              last_received = last_received->next;
+    /* last_received now points to the last Received: or Resent-* header
+       in an uninterrupted chain of those header types (seen from the beginning
+       of all headers. Our current header must follow it. */
+    h->next = last_received->next;
+    last_received->next = h;
+    DEBUG(D_receive|D_acl) debug_printf("  (before any non-Received: or Resent-*: header)");        
+    break;
+
     default:
     h->next = NULL;
     header_last->next = h;
@@ -2716,6 +2736,130 @@ 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 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 */
+        }; 
+      }
+    NO_MIME_ACL:      
+#endif /* WITH_CONTENT_SCAN */
+
+
     if (acl_smtp_data != NULL && recipients_count > 0)
       {
       uschar *user_msg, *log_msg;
@@ -2729,6 +2873,9 @@ else
       else if (rc != OK)
         {
         Uunlink(spool_name);
+#ifdef WITH_CONTENT_SCAN
+        unspool_mbox();
+#endif
         if (smtp_handle_acl_fail(ACL_WHERE_DATA, rc, user_msg, log_msg) != 0)
           smtp_yield = FALSE;    /* No more messsages after dropped connection */
         smtp_reply = US"";       /* Indicate reply already sent */
@@ -2779,6 +2926,10 @@ else
   enable_dollar_recipients = FALSE;
   }
 
+#ifdef WITH_CONTENT_SCAN
+unspool_mbox();
+#endif
+
 /* The final check on the message is to run the scan_local() function. The
 version supplied with Exim always accepts, but this is a hook for sysadmins to
 supply their own checking code. The local_scan() function is run even when all
@@ -2949,6 +3100,14 @@ signal(SIGINT, SIG_IGN);
 
 deliver_firsttime = TRUE;
 
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+if (bmi_run == 1) {
+  /* rewind data file */
+  lseek(data_fd, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
+  bmi_verdicts = bmi_process_message(header_list, data_fd);
+};
+#endif
+
 /* Update the timstamp in our Received: header to account for any time taken by
 an ACL or by local_scan(). The new time is the time that all reception
 processing is complete. */
@@ -3235,12 +3394,29 @@ if (smtp_input)
     {
     if (smtp_reply == NULL)
       {
+#ifndef WITH_CONTENT_SCAN
       smtp_printf("250 OK id=%s\r\n", message_id);
+#else      
+        if (fake_reject)
+          smtp_respond(550,TRUE,fake_reject_text);
+        else  
+          smtp_printf("250 OK id=%s\r\n", message_id);      
+#endif     
       if (host_checking)
         fprintf(stdout,
           "\n**** SMTP testing: that is not a real message id!\n\n");
       }
+#ifndef WITH_CONTENT_SCAN
     else if (smtp_reply[0] != 0) smtp_printf("%.1024s\r\n", smtp_reply);
+#else
+    else if (smtp_reply[0] != 0)
+      {
+        if (fake_reject && (smtp_reply[0] == '2'))
+          smtp_respond(550,TRUE,fake_reject_text);
+        else 
+          smtp_printf("%.1024s\r\n", smtp_reply);
+      };
+#endif
     }
 
   /* For batched SMTP, generate an error message on failure, and do