"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/spam.c" between
exim-4.91.tar.xz and exim-4.92.tar.xz

About: Exim is a message transfer agent (MTA).

spam.c  (exim-4.91.tar.xz):spam.c  (exim-4.92.tar.xz)
skipping to change at line 192 skipping to change at line 192
int int
spam(const uschar **listptr) spam(const uschar **listptr)
{ {
int sep = 0; int sep = 0;
const uschar *list = *listptr; const uschar *list = *listptr;
uschar *user_name; uschar *user_name;
uschar user_name_buffer[128]; uschar user_name_buffer[128];
unsigned long mbox_size; unsigned long mbox_size;
FILE *mbox_file; FILE *mbox_file;
int spamd_sock = -1; client_conn_ctx spamd_cctx = {.sock = -1};
uschar spamd_buffer[32600]; uschar spamd_buffer[32600];
int i, j, offset, result; int i, j, offset, result;
uschar spamd_version[8]; uschar spamd_version[8];
uschar spamd_short_result[8]; uschar spamd_short_result[8];
uschar spamd_score_char; uschar spamd_score_char;
double spamd_threshold, spamd_score, spamd_reject_score; double spamd_threshold, spamd_score, spamd_reject_score;
int spamd_report_offset; int spamd_report_offset;
uschar *p,*q; uschar *p,*q;
int override = 0; int override = 0;
time_t start; time_t start;
skipping to change at line 343 skipping to change at line 343
sd = spamd_address_vector[current_server]; sd = spamd_address_vector[current_server];
for(;;) for(;;)
{ {
uschar * errstr; uschar * errstr;
DEBUG(D_acl) debug_printf_indent("spamd: trying server %s\n", sd->hostspec); DEBUG(D_acl) debug_printf_indent("spamd: trying server %s\n", sd->hostspec);
for (;;) for (;;)
{ {
/*XXX could potentially use TFO early-data here */ /*XXX could potentially use TFO early-data here */
if ( (spamd_sock = ip_streamsocket(sd->hostspec, &errstr, 5)) >= 0 if ( (spamd_cctx.sock = ip_streamsocket(sd->hostspec, &errstr, 5)) >= 0
|| sd->retry <= 0 || sd->retry <= 0
) )
break; break;
DEBUG(D_acl) debug_printf_indent("spamd: server %s: retry conn\n", sd->hos tspec); DEBUG(D_acl) debug_printf_indent("spamd: server %s: retry conn\n", sd->hos tspec);
while (sd->retry > 0) sd->retry = sleep(sd->retry); while (sd->retry > 0) sd->retry = sleep(sd->retry);
} }
if (spamd_sock >= 0) if (spamd_cctx.sock >= 0)
break; break;
log_write(0, LOG_MAIN, "%s spamd: %s", loglabel, errstr); log_write(0, LOG_MAIN, "%s spamd: %s", loglabel, errstr);
sd->is_failed = TRUE; sd->is_failed = TRUE;
current_server = spamd_get_server(spamd_address_vector, num_servers); current_server = spamd_get_server(spamd_address_vector, num_servers);
if (current_server < 0) if (current_server < 0)
{ {
log_write(0, LOG_MAIN|LOG_PANIC, "%s all spamd servers failed", loglabel); log_write(0, LOG_MAIN|LOG_PANIC, "%s all spamd servers failed", loglabel);
goto defer; goto defer;
} }
sd = spamd_address_vector[current_server]; sd = spamd_address_vector[current_server];
} }
} }
(void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK); (void)fcntl(spamd_cctx.sock, F_SETFL, O_NONBLOCK);
/* now we are connected to spamd on spamd_sock */ /* now we are connected to spamd on spamd_cctx.sock */
if (sd->is_rspamd) if (sd->is_rspamd)
{ {
gstring * req_str; gstring * req_str;
const uschar * s; const uschar * s;
req_str = string_append(NULL, 8, req_str = string_append(NULL, 8,
"CHECK RSPAMC/1.3\r\nContent-length: ", string_sprintf("%lu\r\n", mbox_size) , "CHECK RSPAMC/1.3\r\nContent-length: ", string_sprintf("%lu\r\n", mbox_size) ,
"Queue-Id: ", message_id, "Queue-Id: ", message_id,
"\r\nFrom: <", sender_address, "\r\nFrom: <", sender_address,
">\r\nRecipient-Number: ", string_sprintf("%d\r\n", recipients_count)); ">\r\nRecipient-Number: ", string_sprintf("%d\r\n", recipients_count));
skipping to change at line 391 skipping to change at line 391
"Rcpt: <", recipients_list[i].address, ">\r\n"); "Rcpt: <", recipients_list[i].address, ">\r\n");
if ((s = expand_string(US"$sender_helo_name")) && *s) if ((s = expand_string(US"$sender_helo_name")) && *s)
req_str = string_append(req_str, 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) if ((s = expand_string(US"$sender_host_name")) && *s)
req_str = string_append(req_str, 3, "Hostname: ", s, "\r\n"); req_str = string_append(req_str, 3, "Hostname: ", s, "\r\n");
if (sender_host_address) if (sender_host_address)
req_str = string_append(req_str, 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) if ((s = expand_string(US"$authenticated_id")) && *s)
req_str = string_append(req_str, 3, "User: ", s, "\r\n"); req_str = string_append(req_str, 3, "User: ", s, "\r\n");
req_str = string_catn(req_str, US"\r\n", 2); req_str = string_catn(req_str, US"\r\n", 2);
wrote = send(spamd_sock, req_str->s, req_str->ptr, 0); wrote = send(spamd_cctx.sock, req_str->s, req_str->ptr, 0);
} }
else else
{ /* spamassassin variant */ { /* spamassassin variant */
(void)string_format(spamd_buffer, (void)string_format(spamd_buffer,
sizeof(spamd_buffer), sizeof(spamd_buffer),
"REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n", "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n",
user_name, user_name,
mbox_size); mbox_size);
/* send our request */ /* 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) if (wrote == -1)
{ {
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s spamd %s send failed: %s", loglabel, callout_address, strerror(errno) ); "%s spamd %s send failed: %s", loglabel, callout_address, strerror(errno) );
goto defer; goto defer;
} }
/* now send the file */ /* now send the file */
/* spamd sometimes accepts connections but doesn't read data off /* spamd sometimes accepts connections but doesn't read data off
* the connection. We make the file descriptor non-blocking so * the connection. We make the file descriptor non-blocking so
* that the write will only write sufficient data without blocking * that the write will only write sufficient data without blocking
* and we poll the descriptor to make sure that we can write without * and we poll the descriptor to make sure that we can write without
* blocking. Short writes are gracefully handled and if the whole * blocking. Short writes are gracefully handled and if the whole
* transaction takes too long it is aborted. * transaction takes too long it is aborted.
* Note: poll() is not supported in OSX 10.2 and is reported to be * Note: poll() is not supported in OSX 10.2 and is reported to be
* broken in more recent versions (up to 10.4). * broken in more recent versions (up to 10.4).
*/ */
#ifndef NO_POLL_H #ifndef NO_POLL_H
pollfd.fd = spamd_sock; pollfd.fd = spamd_cctx.sock;
pollfd.events = POLLOUT; pollfd.events = POLLOUT;
#endif #endif
(void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK); (void)fcntl(spamd_cctx.sock, F_SETFL, O_NONBLOCK);
do do
{ {
read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file); read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file);
if (read > 0) if (read > 0)
{ {
offset = 0; offset = 0;
again: again:
#ifndef NO_POLL_H #ifndef NO_POLL_H
result = poll(&pollfd, 1, 1000); result = poll(&pollfd, 1, 1000);
/* Patch posted by Erik ? for OS X and applied by PH */ /* Patch posted by Erik ? for OS X and applied by PH */
#else #else
select_tv.tv_sec = 1; select_tv.tv_sec = 1;
select_tv.tv_usec = 0; select_tv.tv_usec = 0;
FD_ZERO(&select_fd); FD_ZERO(&select_fd);
FD_SET(spamd_sock, &select_fd); FD_SET(spamd_cctx.sock, &select_fd);
result = select(spamd_sock+1, NULL, &select_fd, NULL, &select_tv); result = select(spamd_cctx.sock+1, NULL, &select_fd, NULL, &select_tv);
#endif #endif
/* End Erik's patch */ /* End Erik's patch */
if (result == -1 && errno == EINTR) if (result == -1 && errno == EINTR)
goto again; goto again;
else if (result < 1) else if (result < 1)
{ {
if (result == -1) if (result == -1)
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s %s on spamd %s socket", loglabel, callout_address, strerror(errno)) ; "%s %s on spamd %s socket", loglabel, callout_address, strerror(errno)) ;
else else
{ {
if (time(NULL) - start < sd->timeout) if (time(NULL) - start < sd->timeout)
goto again; goto again;
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s timed out writing spamd %s, socket", loglabel, callout_address); "%s timed out writing spamd %s, socket", loglabel, callout_address);
} }
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
goto defer; 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) if (wrote == -1)
{ {
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s %s on spamd %s socket", loglabel, callout_address, strerror(errno)) ; "%s %s on spamd %s socket", loglabel, callout_address, strerror(errno)) ;
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
goto defer; goto defer;
} }
if (offset + wrote != read) if (offset + wrote != read)
{ {
offset += wrote; offset += wrote;
goto again; goto again;
} }
} }
} }
while (!feof(mbox_file) && !ferror(mbox_file)); while (!feof(mbox_file) && !ferror(mbox_file));
if (ferror(mbox_file)) if (ferror(mbox_file))
{ {
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s error reading spool file: %s", loglabel, strerror(errno)); "%s error reading spool file: %s", loglabel, strerror(errno));
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
goto defer; goto defer;
} }
(void)fclose(mbox_file); (void)fclose(mbox_file);
/* we're done sending, close socket for writing */ /* we're done sending, close socket for writing */
if (!sd->is_rspamd) 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. */ /* read spamd response using what's left of the timeout. */
memset(spamd_buffer, 0, sizeof(spamd_buffer)); memset(spamd_buffer, 0, sizeof(spamd_buffer));
offset = 0; offset = 0;
while ((i = ip_recv(spamd_sock, while ((i = ip_recv(&spamd_cctx,
spamd_buffer + offset, spamd_buffer + offset,
sizeof(spamd_buffer) - offset - 1, sizeof(spamd_buffer) - offset - 1,
sd->timeout - time(NULL) + start)) > 0) sd->timeout - time(NULL) + start)) > 0)
offset += i; offset += i;
spamd_buffer[offset] = '\0'; /* guard byte */ spamd_buffer[offset] = '\0'; /* guard byte */
/* error handling */ /* error handling */
if (i <= 0 && errno != 0) if (i <= 0 && errno != 0)
{ {
log_write(0, LOG_MAIN|LOG_PANIC, log_write(0, LOG_MAIN|LOG_PANIC,
"%s error reading from spamd %s, socket: %s", loglabel, callout_address, strerror(errno)); "%s error reading from spamd %s, socket: %s", loglabel, callout_address, strerror(errno));
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
return DEFER; return DEFER;
} }
/* reading done */ /* reading done */
(void)close(spamd_sock); (void)close(spamd_cctx.sock);
if (sd->is_rspamd) if (sd->is_rspamd)
{ /* rspamd variant of reply */ { /* rspamd variant of reply */
int r; int r;
if ( (r = sscanf(CS spamd_buffer, if ( (r = sscanf(CS spamd_buffer,
"RSPAMD/%7s 0 EX_OK\r\nMetric: default; %7s %lf / %lf / %lf\r\n%n", "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_version, spamd_short_result, &spamd_score, &spamd_threshold,
&spamd_reject_score, &spamd_report_offset)) != 5 &spamd_reject_score, &spamd_report_offset)) != 5
|| spamd_report_offset >= offset /* verify within buffer */ || spamd_report_offset >= offset /* verify within buffer */
) )
 End of changes. 18 change blocks. 
20 lines changed or deleted 20 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)