123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- diff -ru exim-4.70.orig/src/expand.c exim-4.70/src/expand.c
- --- exim-4.70.orig/src/expand.c 2016-04-09 13:42:00.227625074 +0200
- +++ exim-4.70/src/expand.c 2016-04-09 13:42:37.183633096 +0200
- @@ -578,6 +578,7 @@
- { "sn8", vtype_filter_int, &filter_sn[8] },
- { "sn9", vtype_filter_int, &filter_sn[9] },
- #ifdef WITH_CONTENT_SCAN
- + { "spam_action", vtype_stringptr, &spam_action },
- { "spam_bar", vtype_stringptr, &spam_bar },
- { "spam_report", vtype_stringptr, &spam_report },
- { "spam_score", vtype_stringptr, &spam_score },
- diff -ru exim-4.70.orig/src/globals.c exim-4.70/src/globals.c
- --- exim-4.70.orig/src/globals.c 2016-04-09 13:42:00.219625073 +0200
- +++ exim-4.70/src/globals.c 2016-04-09 13:42:37.187633096 +0200
- @@ -1136,6 +1136,7 @@
- uschar *spamd_address = US"127.0.0.1 783";
- uschar *spam_bar = NULL;
- uschar *spam_report = NULL;
- +uschar *spam_action = NULL;
- uschar *spam_score = NULL;
- uschar *spam_score_int = NULL;
- #endif
- diff -ru exim-4.70.orig/src/globals.h exim-4.70/src/globals.h
- --- exim-4.70.orig/src/globals.h 2016-04-09 13:42:00.219625073 +0200
- +++ exim-4.70/src/globals.h 2016-04-09 13:42:37.187633096 +0200
- @@ -703,6 +703,7 @@
- extern uschar *spamd_address; /* address for the spamassassin daemon */
- extern uschar *spam_bar; /* the spam "bar" (textual representation of spam_score) */
- extern uschar *spam_report; /* the spamd report (multiline) */
- +extern uschar *spam_action; /* the spamd action */
- extern uschar *spam_score; /* the spam score (float) */
- extern uschar *spam_score_int; /* spam_score * 10 (int) */
- #endif
- diff -ru exim-4.70.orig/src/spam.c exim-4.70/src/spam.c
- --- exim-4.70.orig/src/spam.c 2016-04-09 13:42:00.231625075 +0200
- +++ exim-4.70/src/spam.c 2016-04-09 13:43:43.927647677 +0200
- @@ -16,6 +16,7 @@
- uschar spam_score_buffer[16];
- uschar spam_score_int_buffer[16];
- uschar spam_bar_buffer[128];
- +uschar spam_action_buffer[32];
- uschar spam_report_buffer[32600];
- uschar prev_user_name[128] = "";
- int spam_ok = 0;
- @@ -31,9 +32,11 @@
- int spamd_sock;
- uschar spamd_buffer[32600];
- int i, j, offset, result;
- + BOOL is_rspamd;
- uschar spamd_version[8];
- + uschar spamd_short_result[8];
- uschar spamd_score_char;
- - double spamd_threshold, spamd_score;
- + double spamd_threshold, spamd_score, spamd_reject_score;
- int spamd_report_offset;
- uschar *p,*q;
- int override = 0;
- @@ -122,8 +125,15 @@
- spamd_address_container *this_spamd =
- (spamd_address_container *)store_get(sizeof(spamd_address_container));
-
- + /* Check for spamd variant */
- + if( Ustrstr(address, "variant=rspamd") != NULL ) {
- + this_spamd->is_rspamd = TRUE;
- + }
- + else {
- + this_spamd->is_rspamd = FALSE;
- + }
- /* grok spamd address and port */
- - if( sscanf(CS address, "%s %u", this_spamd->tcp_addr, &(this_spamd->tcp_port)) != 2 ) {
- + if( sscanf(CS address, "%23s %hu", this_spamd->tcp_addr, &(this_spamd->tcp_port)) != 2 ) {
- log_write(0, LOG_MAIN,
- "spam acl condition: warning - invalid spamd address: '%s'", address);
- continue;
- @@ -165,6 +175,7 @@
- spamd_address_vector[current_server]->tcp_port,
- 5 ) > -1) {
- /* connection OK */
- + is_rspamd = spamd_address_vector[current_server]->is_rspamd;
- break;
- };
-
- @@ -197,12 +208,28 @@
- }
-
- server.sun_family = AF_UNIX;
- - Ustrcpy(server.sun_path, spamd_address_work);
- + p = Ustrstr(spamd_address_work, "variant=rspamd");
- + if( p != NULL ) {
- + is_rspamd = TRUE;
- + /* strip spaces */
- + p --;
- + while (p > spamd_address_work && isspace (*p)) {
- + p --;
- + }
- + Ustrncpy(server.sun_path, spamd_address_work, p - spamd_address_work + 1);
- + /* zero terminate */
- + server.sun_path[p - spamd_address_work + 1] = 0;
- + }
- + else {
- + is_rspamd = FALSE;
- + Ustrcpy(server.sun_path, spamd_address_work);
- + }
- +
-
- if (connect(spamd_sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: spamd: unable to connect to UNIX socket %s (%s)",
- - spamd_address_work, strerror(errno) );
- + server.sun_path, strerror(errno) );
- (void)fclose(mbox_file);
- (void)close(spamd_sock);
- return DEFER;
- @@ -210,22 +237,50 @@
-
- }
-
- + (void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK);
- /* now we are connected to spamd on spamd_sock */
- - (void)string_format(spamd_buffer,
- - sizeof(spamd_buffer),
- - "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n",
- - user_name,
- - mbox_size);
- -
- - /* send our request */
- - if (send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0) < 0) {
- + if (is_rspamd) {
- + /* rspamd variant */
- + const char *helo;
- + const char *fcrdns;
- + const char *authid;
- + uschar *req_str;
- +
- + req_str = string_sprintf("CHECK RSPAMC/1.3\r\nContent-length: %lu\r\n"
- + "Queue-Id: %s\r\nFrom: <%s>\r\nRecipient-Number: %d\r\n", mbox_size,
- + message_id, sender_address, recipients_count);
- + for (i = 0; i < recipients_count; i ++)
- + req_str = string_sprintf("%sRcpt: <%s>\r\n", req_str, recipients_list[i].address);
- + if ((helo = expand_string(US"$sender_helo_name")) != NULL && *helo != '\0')
- + req_str = string_sprintf("%sHelo: %s\r\n", req_str, helo);
- + if ((fcrdns = expand_string(US"$sender_host_name")) != NULL && *fcrdns != '\0')
- + req_str = string_sprintf("%sHostname: %s\r\n", req_str, fcrdns);
- + if (sender_host_address != NULL)
- + req_str = string_sprintf("%sIP: %s\r\n", req_str, sender_host_address);
- + if ((authid = expand_string(US"$authenticated_id")) != NULL && *authid != '\0')
- + req_str = string_sprintf("%sUser: %s\r\n", req_str, authid);
- + req_str = string_sprintf("%s\r\n", req_str);
- + wrote = send(spamd_sock, req_str, Ustrlen(req_str), 0);
- + }
- + else {
- + /* spamassassin variant */
- + (void)string_format(spamd_buffer,
- + sizeof(spamd_buffer),
- + "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n",
- + user_name,
- + mbox_size);
- + /* send our request */
- + wrote = send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0);
- + }
- + if(wrote == -1)
- + {
- (void)close(spamd_sock);
- log_write(0, LOG_MAIN|LOG_PANIC,
- - "spam acl condition: spamd send failed: %s", strerror(errno));
- + "spam acl condition: spamd send failed: %s", strerror(errno));
- (void)fclose(mbox_file);
- (void)close(spamd_sock);
- return DEFER;
- - };
- + }
-
- /* now send the file */
- /* spamd sometimes accepts connections but doesn't read data off
- @@ -304,7 +359,9 @@
- (void)fclose(mbox_file);
-
- /* we're done sending, close socket for writing */
- - shutdown(spamd_sock,SHUT_WR);
- + if (!is_rspamd) {
- + shutdown(spamd_sock,SHUT_WR);
- + }
-
- /* read spamd response using what's left of the timeout.
- */
- @@ -328,60 +385,93 @@
- /* reading done */
- (void)close(spamd_sock);
-
- - /* dig in the spamd output and put the report in a multiline header, if requested */
- - if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n",
- - spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
- -
- - /* try to fall back to pre-2.50 spamd output */
- - if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\n\r\n%n",
- - spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
- + if (!is_rspamd) {
- + /* dig in the spamd output and put the report in a multiline header, if requested */
- + if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n",
- + spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
- +
- + /* try to fall back to pre-2.50 spamd output */
- + if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\n\r\n%n",
- + spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
- + log_write(0, LOG_MAIN|LOG_PANIC,
- + "spam acl condition: cannot parse spamd output");
- + return DEFER;
- + };
- + };
- +
- + if( spamd_score >= spamd_threshold ) {
- + Ustrcpy(spam_action_buffer, "reject");
- + }
- + else {
- + Ustrcpy(spam_action_buffer, "no action");
- + }
- + }
- + else {
- + /* rspamd variant of reply */
- + int r;
- + if( (r = sscanf(CS spamd_buffer,"RSPAMD/%7s 0 EX_OK\r\nMetric: default; %7s %lf / %lf / %lf\r\n%n",
- + spamd_version,spamd_short_result,&spamd_score,&spamd_threshold,&spamd_reject_score,&spamd_report_offset)) != 5 ) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- - "spam acl condition: cannot parse spamd output");
- + "spam acl condition: cannot parse spamd output: %d", r);
- return DEFER;
- };
- - };
- + /* now parse action */
- + p = &spamd_buffer[spamd_report_offset];
- +
- + if( Ustrncmp(p, "Action: ", sizeof("Action: ") - 1) == 0 ) {
- + p += sizeof("Action: ") - 1;
- + q = &spam_action_buffer[0];
- + while (*p && *p != '\r' && (q - spam_action_buffer) < sizeof(spam_action_buffer) - 1) {
- + *q++ = *p++;
- + }
- + *q = '\0';
- + }
- + }
-
- /* Create report. Since this is a multiline string,
- we must hack it into shape first */
- p = &spamd_buffer[spamd_report_offset];
- q = spam_report_buffer;
- while (*p != '\0') {
- - /* skip \r */
- - if (*p == '\r') {
- - p++;
- - continue;
- - };
- - *q = *p;
- - q++;
- - if (*p == '\n') {
- - /* add an extra space after the newline to ensure
- - that it is treated as a header continuation line */
- - *q = ' ';
- - q++;
- - };
- - p++;
- + /* skip \r */
- + if (*p == '\r') {
- + p++;
- + continue;
- + };
- + *q = *p;
- + q++;
- + if (*p == '\n') {
- + /* add an extra space after the newline to ensure
- + that it is treated as a header continuation line */
- + *q = ' ';
- + q++;
- + };
- + p++;
- };
- /* NULL-terminate */
- *q = '\0';
- q--;
- /* cut off trailing leftovers */
- while (*q <= ' ') {
- - *q = '\0';
- - q--;
- + *q = '\0';
- + q--;
- };
- +
- + /* common spamd actions */
- spam_report = spam_report_buffer;
- + spam_action = spam_action_buffer;
-
- /* create spam bar */
- spamd_score_char = spamd_score > 0 ? '+' : '-';
- j = abs((int)(spamd_score));
- i = 0;
- if( j != 0 ) {
- - while((i < j) && (i <= MAX_SPAM_BAR_CHARS))
- - spam_bar_buffer[i++] = spamd_score_char;
- + while((i < j) && (i <= MAX_SPAM_BAR_CHARS))
- + spam_bar_buffer[i++] = spamd_score_char;
- }
- else{
- - spam_bar_buffer[0] = '/';
- - i = 1;
- + spam_bar_buffer[0] = '/';
- + i = 1;
- }
- spam_bar_buffer[i] = '\0';
- spam_bar = spam_bar_buffer;
- @@ -397,12 +487,12 @@
-
- /* compare threshold against score */
- if (spamd_score >= spamd_threshold) {
- - /* spam as determined by user's threshold */
- - spam_rc = OK;
- + /* spam as determined by user's threshold */
- + spam_rc = OK;
- }
- else {
- - /* not spam */
- - spam_rc = FAIL;
- + /* not spam */
- + spam_rc = FAIL;
- };
-
- /* remember user name and "been here" for it unless spamd_socket was expanded */
- diff -ru exim-4.70.orig/src/spam.h exim-4.70/src/spam.h
- --- exim-4.70.orig/src/spam.h 2016-04-09 13:42:00.235625076 +0200
- +++ exim-4.70/src/spam.h 2016-04-09 13:42:37.187633096 +0200
- @@ -24,7 +24,8 @@
-
- typedef struct spamd_address_container {
- uschar tcp_addr[24];
- - unsigned int tcp_port;
- + unsigned short int tcp_port;
- + int is_rspamd:1;
- } spamd_address_container;
-
- #endif
|