X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/5df838645bcdb135355205a115bf918c85987caf..f0be4dfa19120173aa76001d31b2cd90284ecd07:/src/src/spam.c diff --git a/src/src/spam.c b/src/src/spam.c index fa3a4fb68..3ffc514f0 100644 --- a/src/src/spam.c +++ b/src/src/spam.c @@ -4,7 +4,7 @@ /* Copyright (c) Tom Kistner 2003 - 2015 * License: GPL - * Copyright (c) The Exim Maintainers 2016 + * Copyright (c) The Exim Maintainers 2016 - 2018 */ /* Code for calling spamassassin's spamd. Called from acl.c. */ @@ -137,7 +137,7 @@ spamd_get_server(spamd_address_container ** spamds, int num_servers) { unsigned int i; spamd_address_container * sd; -long rnd, weights; +long weights; unsigned pri; static BOOL srandomed = FALSE; @@ -170,7 +170,7 @@ for (weights = 0, i = 0; i < num_servers; i++) if (weights == 0) /* all servers failed */ return -1; -for (rnd = random() % weights, i = 0; i < num_servers; i++) +for (long rnd = random() % weights, i = 0; i < num_servers; i++) { sd = spamds[i]; if (!sd->is_failed && sd->priority == pri) @@ -193,7 +193,7 @@ uschar *user_name; uschar user_name_buffer[128]; unsigned long mbox_size; FILE *mbox_file; -int spamd_sock = -1; +client_conn_ctx spamd_cctx = {.sock = -1}; uschar spamd_buffer[32600]; int i, j, offset, result; uschar spamd_version[8]; @@ -343,14 +343,15 @@ start = time(NULL); for (;;) { - if ( (spamd_sock = ip_streamsocket(sd->hostspec, &errstr, 5)) >= 0 + /*XXX could potentially use TFO early-data here */ + if ( (spamd_cctx.sock = ip_streamsocket(sd->hostspec, &errstr, 5)) >= 0 || sd->retry <= 0 ) break; DEBUG(D_acl) debug_printf_indent("spamd: server %s: retry conn\n", sd->hostspec); while (sd->retry > 0) sd->retry = sleep(sd->retry); } - if (spamd_sock >= 0) + if (spamd_cctx.sock >= 0) break; log_write(0, LOG_MAIN, "%s spamd: %s", loglabel, errstr); @@ -366,33 +367,32 @@ start = time(NULL); } } -(void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK); -/* now we are connected to spamd on spamd_sock */ +(void)fcntl(spamd_cctx.sock, F_SETFL, O_NONBLOCK); +/* now we are connected to spamd on spamd_cctx.sock */ if (sd->is_rspamd) { - uschar * req_str = NULL; - int size = 0, len = 0; + gstring * req_str; const uschar * s; - req_str = string_append(req_str, &size, &len, 8, + req_str = string_append(NULL, 8, "CHECK RSPAMC/1.3\r\nContent-length: ", string_sprintf("%lu\r\n", mbox_size), "Queue-Id: ", message_id, "\r\nFrom: <", sender_address, ">\r\nRecipient-Number: ", string_sprintf("%d\r\n", recipients_count)); - for (i = 0; i < recipients_count; i ++) - req_str = string_append(req_str, &size, &len, 3, + for (int i = 0; i < recipients_count; i++) + req_str = string_append(req_str, 3, "Rcpt: <", recipients_list[i].address, ">\r\n"); if ((s = expand_string(US"$sender_helo_name")) && *s) - req_str = string_append(req_str, &size, &len, 3, "Helo: ", s, "\r\n"); + req_str = string_append(req_str, 3, "Helo: ", s, "\r\n"); if ((s = expand_string(US"$sender_host_name")) && *s) - req_str = string_append(req_str, &size, &len, 3, "Hostname: ", s, "\r\n"); + req_str = string_append(req_str, 3, "Hostname: ", s, "\r\n"); if (sender_host_address) - req_str = string_append(req_str, &size, &len, 3, "IP: ", sender_host_address, "\r\n"); + req_str = string_append(req_str, 3, "IP: ", sender_host_address, "\r\n"); if ((s = expand_string(US"$authenticated_id")) && *s) - req_str = string_append(req_str, &size, &len, 3, "User: ", s, "\r\n"); - req_str = string_catn(req_str, &size, &len, "\r\n", 2); - wrote = send(spamd_sock, req_str, len, 0); + req_str = string_append(req_str, 3, "User: ", s, "\r\n"); + req_str = string_catn(req_str, US"\r\n", 2); + wrote = send(spamd_cctx.sock, req_str->s, req_str->ptr, 0); } else { /* spamassassin variant */ @@ -402,12 +402,12 @@ else user_name, mbox_size); /* send our request */ - wrote = send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0); + wrote = send(spamd_cctx.sock, spamd_buffer, Ustrlen(spamd_buffer), 0); } if (wrote == -1) { - (void)close(spamd_sock); + (void)close(spamd_cctx.sock); log_write(0, LOG_MAIN|LOG_PANIC, "%s spamd %s send failed: %s", loglabel, callout_address, strerror(errno)); goto defer; @@ -424,10 +424,10 @@ if (wrote == -1) * broken in more recent versions (up to 10.4). */ #ifndef NO_POLL_H -pollfd.fd = spamd_sock; +pollfd.fd = spamd_cctx.sock; pollfd.events = POLLOUT; #endif -(void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK); +(void)fcntl(spamd_cctx.sock, F_SETFL, O_NONBLOCK); do { read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file); @@ -443,8 +443,8 @@ again: select_tv.tv_sec = 1; select_tv.tv_usec = 0; FD_ZERO(&select_fd); - FD_SET(spamd_sock, &select_fd); - result = select(spamd_sock+1, NULL, &select_fd, NULL, &select_tv); + FD_SET(spamd_cctx.sock, &select_fd); + result = select(spamd_cctx.sock+1, NULL, &select_fd, NULL, &select_tv); #endif /* End Erik's patch */ @@ -462,16 +462,16 @@ again: log_write(0, LOG_MAIN|LOG_PANIC, "%s timed out writing spamd %s, socket", loglabel, callout_address); } - (void)close(spamd_sock); + (void)close(spamd_cctx.sock); goto defer; } - wrote = send(spamd_sock,spamd_buffer + offset,read - offset,0); + wrote = send(spamd_cctx.sock,spamd_buffer + offset,read - offset,0); if (wrote == -1) { log_write(0, LOG_MAIN|LOG_PANIC, "%s %s on spamd %s socket", loglabel, callout_address, strerror(errno)); - (void)close(spamd_sock); + (void)close(spamd_cctx.sock); goto defer; } if (offset + wrote != read) @@ -487,7 +487,7 @@ if (ferror(mbox_file)) { log_write(0, LOG_MAIN|LOG_PANIC, "%s error reading spool file: %s", loglabel, strerror(errno)); - (void)close(spamd_sock); + (void)close(spamd_cctx.sock); goto defer; } @@ -495,12 +495,12 @@ if (ferror(mbox_file)) /* we're done sending, close socket for writing */ if (!sd->is_rspamd) - shutdown(spamd_sock,SHUT_WR); + shutdown(spamd_cctx.sock,SHUT_WR); /* read spamd response using what's left of the timeout. */ memset(spamd_buffer, 0, sizeof(spamd_buffer)); offset = 0; -while ((i = ip_recv(spamd_sock, +while ((i = ip_recv(&spamd_cctx, spamd_buffer + offset, sizeof(spamd_buffer) - offset - 1, sd->timeout - time(NULL) + start)) > 0) @@ -512,12 +512,12 @@ if (i <= 0 && errno != 0) { log_write(0, LOG_MAIN|LOG_PANIC, "%s error reading from spamd %s, socket: %s", loglabel, callout_address, strerror(errno)); - (void)close(spamd_sock); + (void)close(spamd_cctx.sock); return DEFER; } /* reading done */ -(void)close(spamd_sock); +(void)close(spamd_cctx.sock); if (sd->is_rspamd) { /* rspamd variant of reply */