You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

patch-exim-src_spam.c.diff.exim-4.85.diff 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. diff -ru exim-4.85.orig/src/expand.c exim-4.85/src/expand.c
  2. --- exim-4.85.orig/src/expand.c 2016-04-09 13:47:01.707691638 +0200
  3. +++ exim-4.85/src/expand.c 2016-04-09 13:47:29.771697969 +0200
  4. @@ -652,6 +652,7 @@
  5. { "sn8", vtype_filter_int, &filter_sn[8] },
  6. { "sn9", vtype_filter_int, &filter_sn[9] },
  7. #ifdef WITH_CONTENT_SCAN
  8. + { "spam_action", vtype_stringptr, &spam_action },
  9. { "spam_bar", vtype_stringptr, &spam_bar },
  10. { "spam_report", vtype_stringptr, &spam_report },
  11. { "spam_score", vtype_stringptr, &spam_score },
  12. Only in exim-4.85/src: expand.c.orig
  13. diff -ru exim-4.85.orig/src/globals.c exim-4.85/src/globals.c
  14. --- exim-4.85.orig/src/globals.c 2016-04-09 13:47:01.695691635 +0200
  15. +++ exim-4.85/src/globals.c 2016-04-09 13:47:29.771697969 +0200
  16. @@ -1276,6 +1276,7 @@
  17. uschar *spamd_address = US"127.0.0.1 783";
  18. uschar *spam_bar = NULL;
  19. uschar *spam_report = NULL;
  20. +uschar *spam_action = NULL;
  21. uschar *spam_score = NULL;
  22. uschar *spam_score_int = NULL;
  23. #endif
  24. Only in exim-4.85/src: globals.c.orig
  25. diff -ru exim-4.85.orig/src/globals.h exim-4.85/src/globals.h
  26. --- exim-4.85.orig/src/globals.h 2016-04-09 13:47:01.695691635 +0200
  27. +++ exim-4.85/src/globals.h 2016-04-09 13:47:29.771697969 +0200
  28. @@ -819,6 +819,7 @@
  29. extern uschar *spamd_address; /* address for the spamassassin daemon */
  30. extern uschar *spam_bar; /* the spam "bar" (textual representation of spam_score) */
  31. extern uschar *spam_report; /* the spamd report (multiline) */
  32. +extern uschar *spam_action; /* the spamd action */
  33. extern uschar *spam_score; /* the spam score (float) */
  34. extern uschar *spam_score_int; /* spam_score * 10 (int) */
  35. #endif
  36. Only in exim-4.85/src: globals.h.orig
  37. diff -ru exim-4.85.orig/src/spam.c exim-4.85/src/spam.c
  38. --- exim-4.85.orig/src/spam.c 2016-04-09 13:47:01.711691638 +0200
  39. +++ exim-4.85/src/spam.c 2016-04-09 13:52:12.611762892 +0200
  40. @@ -14,6 +14,7 @@
  41. uschar spam_score_buffer[16];
  42. uschar spam_score_int_buffer[16];
  43. uschar spam_bar_buffer[128];
  44. +uschar spam_action_buffer[32];
  45. uschar spam_report_buffer[32600];
  46. uschar prev_user_name[128] = "";
  47. int spam_ok = 0;
  48. @@ -32,9 +33,11 @@
  49. int spamd_sock = -1;
  50. uschar spamd_buffer[32600];
  51. int i, j, offset, result;
  52. + BOOL is_rspamd;
  53. uschar spamd_version[8];
  54. + uschar spamd_short_result[8];
  55. uschar spamd_score_char;
  56. - double spamd_threshold, spamd_score;
  57. + double spamd_threshold, spamd_score, spamd_reject_score;
  58. int spamd_report_offset;
  59. uschar *p,*q;
  60. int override = 0;
  61. @@ -128,8 +131,15 @@
  62. spamd_address_container *this_spamd =
  63. (spamd_address_container *)store_get(sizeof(spamd_address_container));
  64. + /* Check for spamd variant */
  65. + if( Ustrstr(address, "variant=rspamd") != NULL ) {
  66. + this_spamd->is_rspamd = TRUE;
  67. + }
  68. + else {
  69. + this_spamd->is_rspamd = FALSE;
  70. + }
  71. /* grok spamd address and port */
  72. - if (sscanf(CS address, "%23s %u", this_spamd->tcp_addr, &(this_spamd->tcp_port)) != 2)
  73. + if (sscanf(CS address, "%23s %hu", this_spamd->tcp_addr, &(this_spamd->tcp_port)) != 2)
  74. {
  75. log_write(0, LOG_MAIN,
  76. "spam acl condition: warning - invalid spamd address: '%s'", address);
  77. @@ -174,6 +184,7 @@
  78. spamd_address_vector[current_server]->tcp_port,
  79. 5 ) > -1) {
  80. /* connection OK */
  81. + is_rspamd = spamd_address_vector[current_server]->is_rspamd;
  82. break;
  83. };
  84. @@ -210,12 +221,28 @@
  85. }
  86. server.sun_family = AF_UNIX;
  87. - Ustrcpy(server.sun_path, spamd_address_work);
  88. + p = Ustrstr(spamd_address_work, "variant=rspamd");
  89. + if( p != NULL ) {
  90. + is_rspamd = TRUE;
  91. + /* strip spaces */
  92. + p --;
  93. + while (p > spamd_address_work && isspace (*p)) {
  94. + p --;
  95. + }
  96. + Ustrncpy(server.sun_path, spamd_address_work, p - spamd_address_work + 1);
  97. + /* zero terminate */
  98. + server.sun_path[p - spamd_address_work + 1] = 0;
  99. + }
  100. + else {
  101. + is_rspamd = FALSE;
  102. + Ustrcpy(server.sun_path, spamd_address_work);
  103. + }
  104. +
  105. if (connect(spamd_sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
  106. log_write(0, LOG_MAIN|LOG_PANIC,
  107. "malware acl condition: spamd: unable to connect to UNIX socket %s (%s)",
  108. - spamd_address_work, strerror(errno) );
  109. + server.sun_path, strerror(errno) );
  110. (void)fclose(mbox_file);
  111. (void)close(spamd_sock);
  112. return DEFER;
  113. @@ -231,22 +258,50 @@
  114. return DEFER;
  115. }
  116. + (void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK);
  117. /* now we are connected to spamd on spamd_sock */
  118. - (void)string_format(spamd_buffer,
  119. - sizeof(spamd_buffer),
  120. - "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n",
  121. - user_name,
  122. - mbox_size);
  123. -
  124. - /* send our request */
  125. - if (send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0) < 0) {
  126. + if (is_rspamd) {
  127. + /* rspamd variant */
  128. + const char *helo;
  129. + const char *fcrdns;
  130. + const char *authid;
  131. + uschar *req_str;
  132. +
  133. + req_str = string_sprintf("CHECK RSPAMC/1.3\r\nContent-length: %lu\r\n"
  134. + "Queue-Id: %s\r\nFrom: <%s>\r\nRecipient-Number: %d\r\n", mbox_size,
  135. + message_id, sender_address, recipients_count);
  136. + for (i = 0; i < recipients_count; i ++)
  137. + req_str = string_sprintf("%sRcpt: <%s>\r\n", req_str, recipients_list[i].address);
  138. + if ((helo = expand_string(US"$sender_helo_name")) != NULL && *helo != '\0')
  139. + req_str = string_sprintf("%sHelo: %s\r\n", req_str, helo);
  140. + if ((fcrdns = expand_string(US"$sender_host_name")) != NULL && *fcrdns != '\0')
  141. + req_str = string_sprintf("%sHostname: %s\r\n", req_str, fcrdns);
  142. + if (sender_host_address != NULL)
  143. + req_str = string_sprintf("%sIP: %s\r\n", req_str, sender_host_address);
  144. + if ((authid = expand_string(US"$authenticated_id")) != NULL && *authid != '\0')
  145. + req_str = string_sprintf("%sUser: %s\r\n", req_str, authid);
  146. + req_str = string_sprintf("%s\r\n", req_str);
  147. + wrote = send(spamd_sock, req_str, Ustrlen(req_str), 0);
  148. + }
  149. + else {
  150. + /* spamassassin variant */
  151. + (void)string_format(spamd_buffer,
  152. + sizeof(spamd_buffer),
  153. + "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n",
  154. + user_name,
  155. + mbox_size);
  156. + /* send our request */
  157. + wrote = send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0);
  158. + }
  159. + if(wrote == -1)
  160. + {
  161. (void)close(spamd_sock);
  162. log_write(0, LOG_MAIN|LOG_PANIC,
  163. - "spam acl condition: spamd send failed: %s", strerror(errno));
  164. + "spam acl condition: spamd send failed: %s", strerror(errno));
  165. (void)fclose(mbox_file);
  166. (void)close(spamd_sock);
  167. return DEFER;
  168. - };
  169. + }
  170. /* now send the file */
  171. /* spamd sometimes accepts connections but doesn't read data off
  172. @@ -349,60 +404,93 @@
  173. /* reading done */
  174. (void)close(spamd_sock);
  175. - /* dig in the spamd output and put the report in a multiline header, if requested */
  176. - if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n",
  177. - spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
  178. -
  179. - /* try to fall back to pre-2.50 spamd output */
  180. - if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\n\r\n%n",
  181. - spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
  182. + if (!is_rspamd) {
  183. + /* dig in the spamd output and put the report in a multiline header, if requested */
  184. + if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n",
  185. + spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
  186. +
  187. + /* try to fall back to pre-2.50 spamd output */
  188. + if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\n\r\n%n",
  189. + spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
  190. + log_write(0, LOG_MAIN|LOG_PANIC,
  191. + "spam acl condition: cannot parse spamd output");
  192. + return DEFER;
  193. + };
  194. + };
  195. +
  196. + if( spamd_score >= spamd_threshold ) {
  197. + Ustrcpy(spam_action_buffer, "reject");
  198. + }
  199. + else {
  200. + Ustrcpy(spam_action_buffer, "no action");
  201. + }
  202. + }
  203. + else {
  204. + /* rspamd variant of reply */
  205. + int r;
  206. + if( (r = sscanf(CS spamd_buffer,"RSPAMD/%7s 0 EX_OK\r\nMetric: default; %7s %lf / %lf / %lf\r\n%n",
  207. + spamd_version,spamd_short_result,&spamd_score,&spamd_threshold,&spamd_reject_score,&spamd_report_offset)) != 5 ) {
  208. log_write(0, LOG_MAIN|LOG_PANIC,
  209. - "spam acl condition: cannot parse spamd output");
  210. + "spam acl condition: cannot parse spamd output: %d", r);
  211. return DEFER;
  212. };
  213. - };
  214. + /* now parse action */
  215. + p = &spamd_buffer[spamd_report_offset];
  216. +
  217. + if( Ustrncmp(p, "Action: ", sizeof("Action: ") - 1) == 0 ) {
  218. + p += sizeof("Action: ") - 1;
  219. + q = &spam_action_buffer[0];
  220. + while (*p && *p != '\r' && (q - spam_action_buffer) < sizeof(spam_action_buffer) - 1) {
  221. + *q++ = *p++;
  222. + }
  223. + *q = '\0';
  224. + }
  225. + }
  226. /* Create report. Since this is a multiline string,
  227. we must hack it into shape first */
  228. p = &spamd_buffer[spamd_report_offset];
  229. q = spam_report_buffer;
  230. while (*p != '\0') {
  231. - /* skip \r */
  232. - if (*p == '\r') {
  233. - p++;
  234. - continue;
  235. - };
  236. - *q = *p;
  237. - q++;
  238. - if (*p == '\n') {
  239. - /* add an extra space after the newline to ensure
  240. - that it is treated as a header continuation line */
  241. - *q = ' ';
  242. - q++;
  243. - };
  244. - p++;
  245. + /* skip \r */
  246. + if (*p == '\r') {
  247. + p++;
  248. + continue;
  249. + };
  250. + *q = *p;
  251. + q++;
  252. + if (*p == '\n') {
  253. + /* add an extra space after the newline to ensure
  254. + that it is treated as a header continuation line */
  255. + *q = ' ';
  256. + q++;
  257. + };
  258. + p++;
  259. };
  260. /* NULL-terminate */
  261. *q = '\0';
  262. q--;
  263. /* cut off trailing leftovers */
  264. while (*q <= ' ') {
  265. - *q = '\0';
  266. - q--;
  267. + *q = '\0';
  268. + q--;
  269. };
  270. +
  271. + /* common spamd actions */
  272. spam_report = spam_report_buffer;
  273. + spam_action = spam_action_buffer;
  274. /* create spam bar */
  275. spamd_score_char = spamd_score > 0 ? '+' : '-';
  276. j = abs((int)(spamd_score));
  277. i = 0;
  278. if( j != 0 ) {
  279. - while((i < j) && (i <= MAX_SPAM_BAR_CHARS))
  280. - spam_bar_buffer[i++] = spamd_score_char;
  281. + while((i < j) && (i <= MAX_SPAM_BAR_CHARS))
  282. + spam_bar_buffer[i++] = spamd_score_char;
  283. }
  284. else{
  285. - spam_bar_buffer[0] = '/';
  286. - i = 1;
  287. + spam_bar_buffer[0] = '/';
  288. + i = 1;
  289. }
  290. spam_bar_buffer[i] = '\0';
  291. spam_bar = spam_bar_buffer;
  292. @@ -418,12 +506,12 @@
  293. /* compare threshold against score */
  294. if (spamd_score >= spamd_threshold) {
  295. - /* spam as determined by user's threshold */
  296. - spam_rc = OK;
  297. + /* spam as determined by user's threshold */
  298. + spam_rc = OK;
  299. }
  300. else {
  301. - /* not spam */
  302. - spam_rc = FAIL;
  303. + /* not spam */
  304. + spam_rc = FAIL;
  305. };
  306. /* remember expanded spamd_address if needed */
  307. Only in exim-4.85/src: spam.c.orig
  308. Only in exim-4.85/src: .spam.c.rej.swp
  309. diff -ru exim-4.85.orig/src/spam.h exim-4.85/src/spam.h
  310. --- exim-4.85.orig/src/spam.h 2016-04-09 13:47:01.715691640 +0200
  311. +++ exim-4.85/src/spam.h 2016-04-09 13:47:29.775697969 +0200
  312. @@ -22,7 +22,8 @@
  313. typedef struct spamd_address_container {
  314. uschar tcp_addr[24];
  315. - unsigned int tcp_port;
  316. + unsigned short int tcp_port;
  317. + int is_rspamd:1;
  318. } spamd_address_container;
  319. #endif