SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / bmi_spam.c
index bbb9a512a7901d3fdc3e909018c8cec7f64e135d..03e8defa6919fe405407a3fe65b054776b45a43d 100644 (file)
@@ -1,12 +1,12 @@
-/* $Cambridge: exim/src/src/bmi_spam.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
+
 /* Code for calling Brightmail AntiSpam.
    Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
    License: GPL */
+/* Copyright (c) The Exim Maintainers 2021 - 2022 */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #include "exim.h"
 #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -28,8 +28,8 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
   uschar *host_address;
   uschar *verdicts = NULL;
   int i,j;
-  
-  err = bmiInitSystem(BMI_VERSION, (char *)bmi_config_file, &system);
+
+  err = bmiInitSystem(BMI_VERSION, CS bmi_config_file, &system);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
     err_loc = bmiErrorGetLocation(err);
     err_type = bmiErrorGetType(err);
@@ -53,24 +53,24 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
     host_address = localhost;
   else
     host_address = sender_host_address;
-  err = bmiProcessConnection((char *)host_address, message);
+  err = bmiProcessConnection(CS host_address, message);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
     err_loc = bmiErrorGetLocation(err);
     err_type = bmiErrorGetType(err);
     log_write(0, LOG_PANIC,
-               "bmi error [loc %d type %d]: bmiProcessConnection() failed (IP %s).", (int)err_loc, (int)err_type, (char *)host_address);
+               "bmi error [loc %d type %d]: bmiProcessConnection() failed (IP %s).", (int)err_loc, (int)err_type, CS host_address);
     bmiFreeMessage(message);
     bmiFreeSystem(system);
     return NULL;
   };
 
   /* Send envelope sender address */
-  err = bmiProcessFROM((char *)sender_address, message);
+  err = bmiProcessFROM(CS sender_address, message);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
     err_loc = bmiErrorGetLocation(err);
     err_type = bmiErrorGetType(err);
     log_write(0, LOG_PANIC,
-               "bmi error [loc %d type %d]: bmiProcessFROM() failed (address %s).", (int)err_loc, (int)err_type, (char *)sender_address);
+               "bmi error [loc %d type %d]: bmiProcessFROM() failed (address %s).", (int)err_loc, (int)err_type, CS sender_address);
     bmiFreeMessage(message);
     bmiFreeSystem(system);
     return NULL;
@@ -80,7 +80,7 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
   for(i=0;i<recipients_count;i++) {
     recipient_item *r = recipients_list + i;
     BmiOptin *optin = NULL;
-    
+
     /* create optin object if optin string is given */
     if ((r->bmi_optin != NULL) && (Ustrlen(r->bmi_optin) > 1)) {
       debug_printf("passing bmiOptin string: %s\n", r->bmi_optin);
@@ -88,23 +88,23 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
       err = bmiOptinMset(optin, r->bmi_optin, ':');
       if (bmiErrorIsFatal(err) == BMI_TRUE) {
         log_write(0, LOG_PANIC|LOG_MAIN,
-                   "bmi warning: [loc %d type %d]: bmiOptinMSet() failed (address '%s', string '%s').", (int)err_loc, (int)err_type, (char *)r->address, (char *)r->bmi_optin);
+                   "bmi warning: [loc %d type %d]: bmiOptinMSet() failed (address '%s', string '%s').", (int)err_loc, (int)err_type, CS r->address, CS r->bmi_optin);
         if (optin != NULL)
           bmiOptinFree(optin);
         optin = NULL;
       };
     };
-    
-    err = bmiAccumulateTO((char *)r->address, optin, message);
-    
+
+    err = bmiAccumulateTO(CS r->address, optin, message);
+
     if (optin != NULL)
       bmiOptinFree(optin);
-    
+
     if (bmiErrorIsFatal(err) == BMI_TRUE) {
       err_loc = bmiErrorGetLocation(err);
       err_type = bmiErrorGetType(err);
       log_write(0, LOG_PANIC,
-                 "bmi error [loc %d type %d]: bmiAccumulateTO() failed (address %s).", (int)err_loc, (int)err_type, (char *)r->address);
+                 "bmi error [loc %d type %d]: bmiAccumulateTO() failed (address %s).", (int)err_loc, (int)err_type, CS r->address);
       bmiFreeMessage(message);
       bmiFreeSystem(system);
       return NULL;
@@ -120,7 +120,7 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
     bmiFreeSystem(system);
     return NULL;
   };
-  
+
   /* Send message headers */
   while (header_list != NULL) {
     /* skip deleted headers */
@@ -128,7 +128,7 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
       header_list = header_list->next;
       continue;
     };
-    err = bmiAccumulateHeaders((const char *)header_list->text, header_list->slen, message);
+    err = bmiAccumulateHeaders(CCS header_list->text, header_list->slen, message);
     if (bmiErrorIsFatal(err) == BMI_TRUE) {
       err_loc = bmiErrorGetLocation(err);
       err_type = bmiErrorGetType(err);
@@ -150,13 +150,13 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
     bmiFreeSystem(system);
     return NULL;
   };
-  
+
   /* Send body */
   data_file = fdopen(data_fd,"r");
   do {
     j = fread(data_buffer, 1, sizeof(data_buffer), data_file);
     if (j > 0) {
-      err = bmiAccumulateBody((const char *)data_buffer, j, message);
+      err = bmiAccumulateBody(CCS data_buffer, j, message);
       if (bmiErrorIsFatal(err) == BMI_TRUE) {
         err_loc = bmiErrorGetLocation(err);
         err_type = bmiErrorGetType(err);
@@ -178,8 +178,8 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
     bmiFreeSystem(system);
     return NULL;
   };
-  
-  
+
+
   /* End message */
   err = bmiEndMessage(message);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
@@ -191,18 +191,21 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
     bmiFreeSystem(system);
     return NULL;
   };
-  
-  /* get store for the verdict string */
-  verdicts = store_get(1);
+
+  /* Get store for the verdict string.  Since we are processing message data, assume that
+  the verdict is tainted.  XXX this should use a growable-string  */
+
+  verdicts = store_get(1, GET_TAINTED);
   *verdicts = '\0';
-  
+
   for ( err = bmiAccessFirstVerdict(message, &verdict);
-        verdict != NULL;
+        verdict;
         err = bmiAccessNextVerdict(message, verdict, &verdict) ) {
     char *verdict_str;
 
     err = bmiCreateStrFromVerdict(verdict,&verdict_str);
-    if (!store_extend(verdicts, Ustrlen(verdicts)+1, Ustrlen(verdicts)+1+strlen(verdict_str)+1)) {
+    if (!store_extend(verdicts,
+         Ustrlen(verdicts)+1, Ustrlen(verdicts)+1+strlen(verdict_str)+1)) {
       /* can't allocate more store */
       return NULL;
     };
@@ -227,7 +230,7 @@ int bmi_get_delivery_status(uschar *base64_verdict) {
   BmiErrorType err_type;
   BmiVerdict *verdict = NULL;
   int rc = 1;   /* deliver by default */
-  
+
   /* always deliver when there is no verdict */
   if (base64_verdict == NULL)
     return 1;
@@ -249,7 +252,7 @@ int bmi_get_delivery_status(uschar *base64_verdict) {
   }
   else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
     /* deliver normally */
-    rc = 1;    
+    rc = 1;
   }
   else if (bmiVerdictAccessDestination(verdict) == NULL) {
     /* do not deliver */
@@ -259,7 +262,7 @@ int bmi_get_delivery_status(uschar *base64_verdict) {
     /* deliver to alternate location */
     rc = 1;
   };
-  
+
   bmiFreeVerdict(verdict);
   return rc;
 }
@@ -271,7 +274,7 @@ uschar *bmi_get_alt_location(uschar *base64_verdict) {
   BmiErrorType err_type;
   BmiVerdict *verdict = NULL;
   uschar *rc = NULL;
-  
+
   /* always deliver when there is no verdict */
   if (base64_verdict == NULL)
     return NULL;
@@ -285,7 +288,7 @@ uschar *bmi_get_alt_location(uschar *base64_verdict) {
                "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
     return NULL;
   };
-  
+
   err = bmiVerdictError(verdict);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
     /* deliver normally due to error */
@@ -293,7 +296,7 @@ uschar *bmi_get_alt_location(uschar *base64_verdict) {
   }
   else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
     /* deliver normally */
-    rc = NULL; 
+    rc = NULL;
   }
   else if (bmiVerdictAccessDestination(verdict) == NULL) {
     /* do not deliver */
@@ -301,11 +304,11 @@ uschar *bmi_get_alt_location(uschar *base64_verdict) {
   }
   else {
     /* deliver to alternate location */
-    rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1);
+    rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1, GET_TAINTED);
     Ustrcpy(rc, bmiVerdictAccessDestination(verdict));
     rc[strlen(bmiVerdictAccessDestination(verdict))] = '\0';
   };
-  
+
   bmiFreeVerdict(verdict);
   return rc;
 }
@@ -320,20 +323,20 @@ uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
   uschar *verdict_ptr;
   uschar *verdict_buffer = NULL;
   int sep = 0;
-  
+
   /* return nothing if there are no verdicts available */
   if (bmi_verdicts == NULL)
     return NULL;
-  
+
   /* allocate room for the b64 verdict string */
-  verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1);
-  
+  verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1, GET_TAINTED);
+
   /* loop through verdicts */
   verdict_ptr = bmi_verdicts;
-  while ((verdict_str = (const char *)string_nextinlist(&verdict_ptr, &sep,
+  while ((verdict_str = CCS string_nextinlist(&verdict_ptr, &sep,
                                           verdict_buffer,
                                           Ustrlen(bmi_verdicts)+1)) != NULL) {
-    
+
     /* create verdict from base64 string */
     err = bmiCreateVerdictFromStr(verdict_str, &verdict);
     if (bmiErrorIsFatal(err) == BMI_TRUE) {
@@ -343,16 +346,16 @@ uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
                  "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, verdict_str);
       return NULL;
     };
-    
+
     /* loop through rcpts for this verdict */
     for ( recipient = bmiVerdictAccessFirstRecipient(verdict);
           recipient != NULL;
           recipient = bmiVerdictAccessNextRecipient(verdict, recipient)) {
       uschar *rcpt_local_part;
       uschar *rcpt_domain;
-      
+
       /* compare address against our subject */
-      rcpt_local_part = (unsigned char *)bmiRecipientAccessAddress(recipient);
+      rcpt_local_part = US bmiRecipientAccessAddress(recipient);
       rcpt_domain = Ustrchr(rcpt_local_part,'@');
       if (rcpt_domain == NULL) {
         rcpt_domain = US"";
@@ -366,13 +369,13 @@ uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
            (strcmpic(rcpt_domain, bmi_domain) == 0) ) {
         /* found verdict */
         bmiFreeVerdict(verdict);
-        return (uschar *)verdict_str;
-      };   
+        return US verdict_str;
+      };
     };
-  
+
     bmiFreeVerdict(verdict);
   };
-  
+
   return NULL;
 }
 
@@ -383,7 +386,7 @@ uschar *bmi_get_base64_tracker_verdict(uschar *base64_verdict) {
   BmiErrorType err_type;
   BmiVerdict *verdict = NULL;
   uschar *rc = NULL;
-  
+
   /* always deliver when there is no verdict */
   if (base64_verdict == NULL)
     return NULL;
@@ -397,7 +400,7 @@ uschar *bmi_get_base64_tracker_verdict(uschar *base64_verdict) {
                "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
     return NULL;
   };
-  
+
   /* create old tracker string from verdict */
   err = bmiCreateOldStrFromVerdict(verdict, &rc);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
@@ -407,7 +410,7 @@ uschar *bmi_get_base64_tracker_verdict(uschar *base64_verdict) {
                "bmi error [loc %d type %d]: bmiCreateOldStrFromVerdict() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
     return NULL;
   };
-  
+
   bmiFreeVerdict(verdict);
   return rc;
 }
@@ -423,12 +426,12 @@ int bmi_check_rule(uschar *base64_verdict, uschar *option_list) {
   uschar *rule_ptr;
   uschar rule_buffer[32];
   int sep = 0;
-  
-  
+
+
   /* no verdict -> no rule fired */
   if (base64_verdict == NULL)
     return 0;
-  
+
   /* create verdict from base64 string */
   err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
@@ -438,22 +441,24 @@ int bmi_check_rule(uschar *base64_verdict, uschar *option_list) {
                "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
     return 0;
   };
-  
+
   err = bmiVerdictError(verdict);
   if (bmiErrorIsFatal(err) == BMI_TRUE) {
     /* error -> no rule fired */
     bmiFreeVerdict(verdict);
     return 0;
   }
-  
+
   /* loop through numbers */
+  /* option_list doesn't seem to be expanded so cannot be tainted.  If it ever is we
+  will trap here */
   rule_ptr = option_list;
   while ((rule_num = string_nextinlist(&rule_ptr, &sep,
-                                       rule_buffer, 32)) != NULL) {
+                                       rule_buffer, sizeof(rule_buffer)))) {
     int rule_int = -1;
-    
+
     /* try to translate to int */
-    sscanf(rule_num, "%d", &rule_int);
+    (void)sscanf(rule_num, "%d", &rule_int);
     if (rule_int > 0) {
       debug_printf("checking rule #%d\n", rule_int);
       /* check if rule fired on the message */