Lines 10-27
Link Here
|
10 |
#include "libspamc.h" |
10 |
#include "libspamc.h" |
11 |
#include "utils.h" |
11 |
#include "utils.h" |
12 |
|
12 |
|
13 |
#include <unistd.h> |
|
|
14 |
#include <stdlib.h> |
13 |
#include <stdlib.h> |
15 |
#include <assert.h> |
14 |
#include <assert.h> |
16 |
#include <stdio.h> |
15 |
#include <stdio.h> |
17 |
#include <string.h> |
16 |
#include <string.h> |
|
|
17 |
#ifdef _WIN32 |
18 |
/* simple macro that works for single strings without %m */ |
19 |
#define syslog(x, y) fprintf(stderr, #y "\n") |
20 |
#define strcasecmp stricmp |
21 |
#define sleep Sleep |
22 |
#else |
18 |
#include <syslog.h> |
23 |
#include <syslog.h> |
|
|
24 |
#include <unistd.h> |
19 |
#include <sys/types.h> |
25 |
#include <sys/types.h> |
20 |
#include <sys/socket.h> |
26 |
#include <sys/socket.h> |
21 |
#include <netinet/in.h> |
27 |
#include <netinet/in.h> |
22 |
#include <sys/un.h> |
28 |
#include <sys/un.h> |
23 |
#include <netinet/tcp.h> |
29 |
#include <netinet/tcp.h> |
24 |
#include <arpa/inet.h> |
30 |
#include <arpa/inet.h> |
|
|
31 |
#endif |
25 |
|
32 |
|
26 |
#ifdef HAVE_SYSEXITS_H |
33 |
#ifdef HAVE_SYSEXITS_H |
27 |
#include <sysexits.h> |
34 |
#include <sysexits.h> |
Lines 173-183
Link Here
|
173 |
} |
180 |
} |
174 |
|
181 |
|
175 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
182 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
|
|
183 |
#ifndef _WIN32 |
176 |
syslog (DEBUG_LEVEL, "dbg: create socket(%s)", typename); |
184 |
syslog (DEBUG_LEVEL, "dbg: create socket(%s)", typename); |
|
|
185 |
#else |
186 |
fprintf (stderr, "dbg: create socket(%s)\n", typename); |
187 |
#endif |
177 |
#endif |
188 |
#endif |
178 |
|
189 |
|
179 |
if ( (*psock = socket(type, SOCK_STREAM, proto)) < 0 ) |
190 |
if ( (*psock = socket(type, SOCK_STREAM, proto)) |
180 |
{ |
191 |
#ifndef _WIN32 |
|
|
192 |
< 0 |
193 |
#else |
194 |
== INVALID_SOCKET |
195 |
#endif |
196 |
) { |
181 |
int origerr; |
197 |
int origerr; |
182 |
|
198 |
|
183 |
/*-------------------------------------------------------- |
199 |
/*-------------------------------------------------------- |
Lines 185-193
Link Here
|
185 |
* this is pretty much fatal. Translate the error reason |
201 |
* this is pretty much fatal. Translate the error reason |
186 |
* into something the user can understand. |
202 |
* into something the user can understand. |
187 |
*/ |
203 |
*/ |
|
|
204 |
#ifndef _WIN32 |
188 |
origerr = errno; /* take a copy before syslog() */ |
205 |
origerr = errno; /* take a copy before syslog() */ |
189 |
|
|
|
190 |
syslog (LOG_ERR, "socket(%s) to spamd failed: %m", typename); |
206 |
syslog (LOG_ERR, "socket(%s) to spamd failed: %m", typename); |
|
|
207 |
#else |
208 |
origerr = WSAGetLastError(); |
209 |
printf ("socket(%s) to spamd failed: %d\n", typename, origerr); |
210 |
#endif |
191 |
|
211 |
|
192 |
switch (origerr) |
212 |
switch (origerr) |
193 |
{ |
213 |
{ |
Lines 221-235
Link Here
|
221 |
if ( type == PF_INET |
241 |
if ( type == PF_INET |
222 |
&& setsockopt(*psock, 0, TCP_NODELAY, &one, sizeof one) != 0 ) |
242 |
&& setsockopt(*psock, 0, TCP_NODELAY, &one, sizeof one) != 0 ) |
223 |
{ |
243 |
{ |
224 |
switch(errno) |
244 |
int origerrno; |
|
|
245 |
#ifndef _WIN32 |
246 |
origerr = errno; |
247 |
#else |
248 |
origerrno = WSAGetLastError(); |
249 |
#endif |
250 |
switch(origerr) |
225 |
{ |
251 |
{ |
226 |
case EBADF: |
252 |
case EBADF: |
227 |
case ENOTSOCK: |
253 |
case ENOTSOCK: |
228 |
case ENOPROTOOPT: |
254 |
case ENOPROTOOPT: |
229 |
case EFAULT: |
255 |
case EFAULT: |
|
|
256 |
#ifndef _WIN32 |
230 |
syslog(LOG_ERR, |
257 |
syslog(LOG_ERR, |
231 |
"setsockopt(TCP_NODELAY) failed: %m"); |
258 |
"setsockopt(TCP_NODELAY) failed: %m"); |
232 |
close (*psock); |
259 |
#else |
|
|
260 |
fprintf(stderr, |
261 |
"setsockopt(TCP_NODELAY) failed: %d\n", origerr)); |
262 |
#endif |
263 |
closesocket (*psock); |
233 |
return EX_SOFTWARE; |
264 |
return EX_SOFTWARE; |
234 |
|
265 |
|
235 |
default: |
266 |
default: |
Lines 253-258
Link Here
|
253 |
static int |
284 |
static int |
254 |
try_to_connect_unix (struct transport *tp, int *sockptr) |
285 |
try_to_connect_unix (struct transport *tp, int *sockptr) |
255 |
{ |
286 |
{ |
|
|
287 |
#ifndef _WIN32 |
256 |
int mysock, status, origerr; |
288 |
int mysock, status, origerr; |
257 |
struct sockaddr_un addrbuf; |
289 |
struct sockaddr_un addrbuf; |
258 |
int ret; |
290 |
int ret; |
Lines 295-304
Link Here
|
295 |
|
326 |
|
296 |
syslog(LOG_ERR, "connect(AF_UNIX) to spamd %s failed: %m", |
327 |
syslog(LOG_ERR, "connect(AF_UNIX) to spamd %s failed: %m", |
297 |
addrbuf.sun_path); |
328 |
addrbuf.sun_path); |
298 |
|
329 |
closesocket(mysock); |
299 |
close(mysock); |
|
|
300 |
|
330 |
|
301 |
return translate_connect_errno(origerr); |
331 |
return translate_connect_errno(origerr); |
|
|
332 |
#else |
333 |
return EX_OSERR; |
334 |
#endif |
302 |
} |
335 |
} |
303 |
|
336 |
|
304 |
/* |
337 |
/* |
Lines 323-329
Link Here
|
323 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
356 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
324 |
for (numloops = 0; numloops < tp->nhosts; numloops++) |
357 |
for (numloops = 0; numloops < tp->nhosts; numloops++) |
325 |
{ |
358 |
{ |
326 |
syslog(LOG_ERR, "dbg: %d/%d: %s", |
359 |
#ifndef _WIN32 |
|
|
360 |
syslog(LOG_ERR, |
361 |
"dbg: %d/%d: %s", |
362 |
#else |
363 |
fprintf(stderr, |
364 |
"dbg: %d/%d: %s\n", |
365 |
#endif |
327 |
numloops+1, tp->nhosts, inet_ntoa(tp->hosts[numloops])); |
366 |
numloops+1, tp->nhosts, inet_ntoa(tp->hosts[numloops])); |
328 |
} |
367 |
} |
329 |
#endif |
368 |
#endif |
Lines 352-359
Link Here
|
352 |
ipaddr = inet_ntoa(addrbuf.sin_addr); |
391 |
ipaddr = inet_ntoa(addrbuf.sin_addr); |
353 |
|
392 |
|
354 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
393 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
355 |
syslog (DEBUG_LEVEL, |
394 |
#ifndef _WIN32 |
|
|
395 |
syslog(DEBUG_LEVEL, |
356 |
"dbg: connect(AF_INET) to spamd at %s (try #%d of %d)", |
396 |
"dbg: connect(AF_INET) to spamd at %s (try #%d of %d)", |
|
|
397 |
#else |
398 |
fprintf(stderr, |
399 |
"dbg: connect(AF_INET) to spamd at %s (try #%d of %d\)\n", |
400 |
#endif |
357 |
ipaddr, |
401 |
ipaddr, |
358 |
numloops+1, |
402 |
numloops+1, |
359 |
MAX_CONNECT_RETRIES); |
403 |
MAX_CONNECT_RETRIES); |
Lines 363-382
Link Here
|
363 |
|
406 |
|
364 |
if (status != 0) |
407 |
if (status != 0) |
365 |
{ |
408 |
{ |
|
|
409 |
#ifndef _WIN32 |
410 |
origerr = errno; |
366 |
syslog (LOG_ERR, |
411 |
syslog (LOG_ERR, |
367 |
"connect(AF_INET) to spamd at %s failed, retrying (#%d of %d): %m", |
412 |
"connect(AF_INET) to spamd at %s failed, retrying (#%d of %d): %m", |
368 |
ipaddr, numloops+1, MAX_CONNECT_RETRIES); |
413 |
ipaddr, numloops+1, MAX_CONNECT_RETRIES); |
369 |
|
414 |
#else |
370 |
close(mysock); |
415 |
origerr = WSAGetLastError(); |
|
|
416 |
fprintf (stderr, |
417 |
"connect(AF_INET) to spamd at %s failed, retrying (#%d of %d): %d\n", |
418 |
ipaddr, numloops+1, MAX_CONNECT_RETRIES, origerr); |
419 |
#endif |
420 |
closesocket(mysock); |
371 |
|
421 |
|
372 |
sleep(CONNECT_RETRY_SLEEP); |
422 |
sleep(CONNECT_RETRY_SLEEP); |
373 |
} |
423 |
} |
374 |
else |
424 |
else |
375 |
{ |
425 |
{ |
376 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
426 |
#ifdef DO_CONNECT_DEBUG_SYSLOGS |
|
|
427 |
#ifndef _WIN32 |
377 |
syslog(DEBUG_LEVEL, |
428 |
syslog(DEBUG_LEVEL, |
378 |
"dbg: connect(AF_INET) to spamd at %s done", |
429 |
"dbg: connect(AF_INET) to spamd at %s done", |
379 |
ipaddr); |
430 |
ipaddr); |
|
|
431 |
#else |
432 |
fprintf(stderr, |
433 |
"dbg: connect(AF_INET) to spamd at %s done\n", |
434 |
ipaddr); |
435 |
#endif |
380 |
#endif |
436 |
#endif |
381 |
*sockptr = mysock; |
437 |
*sockptr = mysock; |
382 |
|
438 |
|
Lines 384-390
Link Here
|
384 |
} |
440 |
} |
385 |
} |
441 |
} |
386 |
|
442 |
|
387 |
syslog (LOG_ERR, "connection attempt to spamd aborted after %d retries", |
443 |
#ifndef _WIN32 |
|
|
444 |
syslog (LOG_ERR, |
445 |
"connection attempt to spamd aborted after %d retries", |
446 |
#else |
447 |
fprintf(stderr, |
448 |
"connection attempt to spamd aborted after %d retries\n", |
449 |
#endif |
388 |
MAX_CONNECT_RETRIES); |
450 |
MAX_CONNECT_RETRIES); |
389 |
|
451 |
|
390 |
return translate_connect_errno(origerr); |
452 |
return translate_connect_errno(origerr); |
Lines 411-417
Link Here
|
411 |
message_read_raw(int fd, struct message *m){ |
473 |
message_read_raw(int fd, struct message *m){ |
412 |
clear_message(m); |
474 |
clear_message(m); |
413 |
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR; |
475 |
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR; |
414 |
m->raw_len=full_read(fd, m->raw, m->max_len+1, m->max_len+1); |
476 |
m->raw_len=full_read(fd, 1, m->raw, m->max_len+1, m->max_len+1); |
415 |
if(m->raw_len<=0){ |
477 |
if(m->raw_len<=0){ |
416 |
free(m->raw); m->raw=NULL; m->raw_len=0; |
478 |
free(m->raw); m->raw=NULL; m->raw_len=0; |
417 |
return EX_IOERR; |
479 |
return EX_IOERR; |
Lines 434-440
Link Here
|
434 |
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR; |
496 |
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR; |
435 |
|
497 |
|
436 |
/* Find the DATA line */ |
498 |
/* Find the DATA line */ |
437 |
m->raw_len=full_read(fd, m->raw, m->max_len+1, m->max_len+1); |
499 |
m->raw_len=full_read(fd, 1, m->raw, m->max_len+1, m->max_len+1); |
438 |
if(m->raw_len<=0){ |
500 |
if(m->raw_len<=0){ |
439 |
free(m->raw); m->raw=NULL; m->raw_len=0; |
501 |
free(m->raw); m->raw=NULL; m->raw_len=0; |
440 |
return EX_IOERR; |
502 |
return EX_IOERR; |
Lines 506-512
Link Here
|
506 |
return message_read_bsmtp(fd, m); |
568 |
return message_read_bsmtp(fd, m); |
507 |
|
569 |
|
508 |
default: |
570 |
default: |
509 |
syslog(LOG_ERR, "message_read: Unknown mode %d\n", flags&SPAMC_MODE_MASK); |
571 |
#ifndef _WIN32 |
|
|
572 |
syslog(LOG_ERR, "message_read: Unknown mode %d", |
573 |
#else |
574 |
fprintf(stderr, "message_read: Unknown mode %d\n", |
575 |
#endif |
576 |
flags&SPAMC_MODE_MASK); |
510 |
return EX_USAGE; |
577 |
return EX_USAGE; |
511 |
} |
578 |
} |
512 |
} |
579 |
} |
Lines 519-528
Link Here
|
519 |
|
586 |
|
520 |
if (m->priv->flags&SPAMC_CHECK_ONLY) { |
587 |
if (m->priv->flags&SPAMC_CHECK_ONLY) { |
521 |
if(m->is_spam==EX_ISSPAM || m->is_spam==EX_NOTSPAM){ |
588 |
if(m->is_spam==EX_ISSPAM || m->is_spam==EX_NOTSPAM){ |
522 |
return full_write(fd, m->out, m->out_len); |
589 |
return full_write(fd, 1, m->out, m->out_len); |
523 |
|
590 |
|
524 |
} else { |
591 |
} else { |
525 |
syslog(LOG_ERR, "oops! SPAMC_CHECK_ONLY is_spam: %d\n", m->is_spam); |
592 |
#ifndef _WIN32 |
|
|
593 |
syslog(LOG_ERR, "oops! SPAMC_CHECK_ONLY is_spam: %d", m->is_spam); |
594 |
#else |
595 |
fprintf(stderr, "oops! SPAMC_CHECK_ONLY is_spam: %d\n", m->is_spam); |
596 |
#endif |
526 |
return -1; |
597 |
return -1; |
527 |
} |
598 |
} |
528 |
} |
599 |
} |
Lines 530-546
Link Here
|
530 |
/* else we're not in CHECK_ONLY mode */ |
601 |
/* else we're not in CHECK_ONLY mode */ |
531 |
switch(m->type){ |
602 |
switch(m->type){ |
532 |
case MESSAGE_NONE: |
603 |
case MESSAGE_NONE: |
533 |
syslog(LOG_ERR, "Cannot write this message, it's MESSAGE_NONE!\n"); |
604 |
syslog(LOG_ERR, "Cannot write this message, it's MESSAGE_NONE!"); |
534 |
return -1; |
605 |
return -1; |
535 |
|
606 |
|
536 |
case MESSAGE_ERROR: |
607 |
case MESSAGE_ERROR: |
537 |
return full_write(fd, m->raw, m->raw_len); |
608 |
return full_write(fd, 1, m->raw, m->raw_len); |
538 |
|
609 |
|
539 |
case MESSAGE_RAW: |
610 |
case MESSAGE_RAW: |
540 |
return full_write(fd, m->out, m->out_len); |
611 |
return full_write(fd, 1, m->out, m->out_len); |
541 |
|
612 |
|
542 |
case MESSAGE_BSMTP: |
613 |
case MESSAGE_BSMTP: |
543 |
total=full_write(fd, m->pre, m->pre_len); |
614 |
total=full_write(fd, 1, m->pre, m->pre_len); |
544 |
for(i=0; i<m->out_len; ){ |
615 |
for(i=0; i<m->out_len; ){ |
545 |
jlimit = (off_t) (sizeof(buffer)/sizeof(*buffer)-4); |
616 |
jlimit = (off_t) (sizeof(buffer)/sizeof(*buffer)-4); |
546 |
for(j=0; i < (off_t) m->out_len && |
617 |
for(j=0; i < (off_t) m->out_len && |
Lines 557-568
Link Here
|
557 |
buffer[j++]=m->out[i++]; |
628 |
buffer[j++]=m->out[i++]; |
558 |
} |
629 |
} |
559 |
} |
630 |
} |
560 |
total+=full_write(fd, buffer, j); |
631 |
total+=full_write(fd, 1, buffer, j); |
561 |
} |
632 |
} |
562 |
return total+full_write(fd, m->post, m->post_len); |
633 |
return total+full_write(fd, 1, m->post, m->post_len); |
563 |
|
634 |
|
564 |
default: |
635 |
default: |
565 |
syslog(LOG_ERR, "Unknown message type %d\n", m->type); |
636 |
#ifndef _WIN32 |
|
|
637 |
syslog(LOG_ERR, "Unknown message type %d", m->type); |
638 |
#else |
639 |
fprintf(stderr, "Unknown message type %d\n", m->type); |
640 |
#endif |
566 |
return -1; |
641 |
return -1; |
567 |
} |
642 |
} |
568 |
} |
643 |
} |
Lines 574-582
Link Here
|
574 |
if(m!=NULL && m->type!=MESSAGE_NONE) { |
649 |
if(m!=NULL && m->type!=MESSAGE_NONE) { |
575 |
message_write(out_fd, m); |
650 |
message_write(out_fd, m); |
576 |
} |
651 |
} |
577 |
while((bytes=full_read(in_fd, buf, 8192, 8192))>0){ |
652 |
while((bytes=full_read(in_fd, 1, buf, 8192, 8192))>0){ |
578 |
if (bytes!=full_write(out_fd, buf, bytes)) { |
653 |
if (bytes!=full_write(out_fd, 1, buf, bytes)) { |
|
|
654 |
#ifndef _WIN32 |
579 |
syslog(LOG_ERR, "oops! message_dump of %d returned different", bytes); |
655 |
syslog(LOG_ERR, "oops! message_dump of %d returned different", bytes); |
|
|
656 |
#else |
657 |
fprintf(stderr, "oops! message_dump of %d returned different\n", bytes); |
658 |
#endif |
580 |
} |
659 |
} |
581 |
} |
660 |
} |
582 |
} |
661 |
} |
Lines 596-602
Link Here
|
596 |
if(flags&SPAMC_USE_SSL) { |
675 |
if(flags&SPAMC_USE_SSL) { |
597 |
bytesread = ssl_timeout_read (ssl, buf+len, 1); |
676 |
bytesread = ssl_timeout_read (ssl, buf+len, 1); |
598 |
} else { |
677 |
} else { |
599 |
bytesread = fd_timeout_read (sock, buf+len, 1); |
678 |
bytesread = fd_timeout_read (sock, 0, buf+len, 1); |
600 |
} |
679 |
} |
601 |
|
680 |
|
602 |
if(buf[len]=='\n') { |
681 |
if(buf[len]=='\n') { |
Lines 614-620
Link Here
|
614 |
} |
693 |
} |
615 |
} |
694 |
} |
616 |
|
695 |
|
|
|
696 |
#ifndef _WIN32 |
617 |
syslog(LOG_ERR, "spamd responded with line of %d bytes, dying", len); |
697 |
syslog(LOG_ERR, "spamd responded with line of %d bytes, dying", len); |
|
|
698 |
#else |
699 |
fprintf(stderr, "spamd responded with line of %d bytes, dying\n", len); |
700 |
#endif |
618 |
failureval = EX_TOOBIG; |
701 |
failureval = EX_TOOBIG; |
619 |
|
702 |
|
620 |
failure: |
703 |
failure: |
Lines 693-722
Link Here
|
693 |
m->score = _locale_safe_string_to_float (s_str, 20); |
776 |
m->score = _locale_safe_string_to_float (s_str, 20); |
694 |
m->threshold = _locale_safe_string_to_float (t_str, 20); |
777 |
m->threshold = _locale_safe_string_to_float (t_str, 20); |
695 |
|
778 |
|
|
|
779 |
/* set bounds on these to ensure no buffer overflow in the sprintf */ |
780 |
if (m->score > 1e10) |
781 |
m->score = 1e10; |
782 |
else if (m->score < -1e10) |
783 |
m->score = -1e10; |
784 |
if (m->threshold > 1e10) |
785 |
m->threshold = 1e10; |
786 |
else if (m->threshold < -1e10) |
787 |
m->threshold = -1e10; |
788 |
|
696 |
/* Format is "Spam: x; y / x" */ |
789 |
/* Format is "Spam: x; y / x" */ |
697 |
m->is_spam=strcasecmp("true", is_spam) == 0 ? EX_ISSPAM: EX_NOTSPAM; |
790 |
m->is_spam=strcasecmp("true", is_spam) == 0 ? EX_ISSPAM: EX_NOTSPAM; |
698 |
|
791 |
|
699 |
if(flags&SPAMC_CHECK_ONLY) { |
792 |
if(flags&SPAMC_CHECK_ONLY) { |
700 |
m->out_len=snprintf (m->out, m->max_len+EXPANSION_ALLOWANCE, |
793 |
m->out_len=sprintf (m->out, |
701 |
"%.1f/%.1f\n", m->score, m->threshold); |
794 |
"%.1f/%.1f\n", m->score, m->threshold); |
702 |
} |
795 |
} |
703 |
else if ((flags & SPAMC_REPORT_IFSPAM && m->is_spam == EX_ISSPAM) |
796 |
else if ((flags & SPAMC_REPORT_IFSPAM && m->is_spam == EX_ISSPAM) |
704 |
|| (flags & SPAMC_REPORT)) |
797 |
|| (flags & SPAMC_REPORT)) |
705 |
{ |
798 |
{ |
706 |
m->out_len=snprintf (m->out, m->max_len+EXPANSION_ALLOWANCE, |
799 |
m->out_len=sprintf (m->out, |
707 |
"%.1f/%.1f\n", m->score, m->threshold); |
800 |
"%.1f/%.1f\n", m->score, m->threshold); |
708 |
} |
801 |
} |
709 |
return EX_OK; |
802 |
return EX_OK; |
710 |
|
803 |
|
711 |
} else if(sscanf(buf, "Content-length: %d", &m->content_length) == 1) { |
804 |
} else if(sscanf(buf, "Content-length: %d", &m->content_length) == 1) { |
712 |
if (m->content_length < 0) { |
805 |
if (m->content_length < 0) { |
|
|
806 |
#ifndef _WIN32 |
713 |
syslog(LOG_ERR, "spamd responded with bad Content-length '%s'", buf); |
807 |
syslog(LOG_ERR, "spamd responded with bad Content-length '%s'", buf); |
|
|
808 |
#else |
809 |
fprintf(stderr, "spamd responded with bad Content-length '%s'\n", buf); |
810 |
#endif |
714 |
return EX_PROTOCOL; |
811 |
return EX_PROTOCOL; |
715 |
} |
812 |
} |
716 |
return EX_OK; |
813 |
return EX_OK; |
717 |
} |
814 |
} |
718 |
|
815 |
|
|
|
816 |
#ifndef _WIN32 |
719 |
syslog(LOG_ERR, "spamd responded with bad header '%s'", buf); |
817 |
syslog(LOG_ERR, "spamd responded with bad header '%s'", buf); |
|
|
818 |
#else |
819 |
fprintf(stderr, "spamd responded with bad header '%s'\n", buf); |
820 |
#endif |
720 |
return EX_PROTOCOL; |
821 |
return EX_PROTOCOL; |
721 |
} |
822 |
} |
722 |
|
823 |
|
Lines 733-739
Link Here
|
733 |
int response; |
834 |
int response; |
734 |
int failureval; |
835 |
int failureval; |
735 |
SSL_CTX* ctx; |
836 |
SSL_CTX* ctx; |
736 |
SSL* ssl; |
837 |
SSL* ssl = NULL; |
737 |
SSL_METHOD *meth; |
838 |
SSL_METHOD *meth; |
738 |
|
839 |
|
739 |
if (flags&SPAMC_USE_SSL) { |
840 |
if (flags&SPAMC_USE_SSL) { |
Lines 760-784
Link Here
|
760 |
|
861 |
|
761 |
/* Build spamd protocol header */ |
862 |
/* Build spamd protocol header */ |
762 |
if(flags & SPAMC_CHECK_ONLY) |
863 |
if(flags & SPAMC_CHECK_ONLY) |
763 |
len=snprintf(buf, bufsiz, "CHECK %s\r\n", PROTOCOL_VERSION); |
864 |
strcpy(buf, "CHECK "); |
764 |
else if(flags & SPAMC_REPORT_IFSPAM) |
865 |
else if(flags & SPAMC_REPORT_IFSPAM) |
765 |
len=snprintf(buf, bufsiz, "REPORT_IFSPAM %s\r\n", PROTOCOL_VERSION); |
866 |
strcpy(buf, "REPORT_IFSPAM "); |
766 |
else if(flags & SPAMC_REPORT) |
867 |
else if(flags & SPAMC_REPORT) |
767 |
len=snprintf(buf, bufsiz, "REPORT %s\r\n", PROTOCOL_VERSION); |
868 |
strcpy(buf, "REPORT "); |
768 |
else if(flags & SPAMC_SYMBOLS) |
869 |
else if(flags & SPAMC_SYMBOLS) |
769 |
len=snprintf(buf, bufsiz, "SYMBOLS %s\r\n", PROTOCOL_VERSION); |
870 |
strcpy(buf, "SYMBOLS "); |
770 |
else |
871 |
else |
771 |
len=snprintf(buf, bufsiz, "PROCESS %s\r\n", PROTOCOL_VERSION); |
872 |
strcpy(buf, "PROCESS "); |
772 |
|
873 |
|
773 |
if(len<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
874 |
len = strlen(buf); |
774 |
if(username!=NULL){ |
875 |
if(len+strlen(PROTOCOL_VERSION)+2 >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
775 |
len+=i=snprintf(buf+len, bufsiz-len, "User: %s\r\n", username); |
876 |
|
776 |
if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
877 |
strcat(buf, PROTOCOL_VERSION); |
|
|
878 |
strcat(buf, "\r\n"); |
879 |
len = strlen(buf); |
880 |
|
881 |
if(username!=NULL) { |
882 |
if (strlen(username)+8 >= (bufsiz - len)) { free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
883 |
strcpy(buf+len, "User: "); |
884 |
strcat(buf+len, username); |
885 |
strcat(buf+len, "\r\n"); |
886 |
len += strlen(buf+len); |
777 |
} |
887 |
} |
778 |
len+=i=snprintf(buf+len, bufsiz-len, "Content-length: %d\r\n", m->msg_len); |
888 |
if ((m->msg_len > 9999999) || ((len + 27) >= (bufsiz - len))) { |
779 |
if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
889 |
free(m->out); m->out=m->msg; m->out_len=m->msg_len; |
780 |
len+=i=snprintf(buf+len, bufsiz-len, "\r\n"); |
890 |
return EX_OSERR; |
781 |
if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; } |
891 |
} |
|
|
892 |
len += sprintf(buf+len, "Content-length: %d\r\n\r\n", m->msg_len); |
782 |
|
893 |
|
783 |
libspamc_timeout = m->timeout; |
894 |
libspamc_timeout = m->timeout; |
784 |
|
895 |
|
Lines 790-796
Link Here
|
790 |
if ( rc != EX_OK ) |
901 |
if ( rc != EX_OK ) |
791 |
{ |
902 |
{ |
792 |
free(m->out); m->out=m->msg; m->out_len=m->msg_len; |
903 |
free(m->out); m->out=m->msg; m->out_len=m->msg_len; |
793 |
return i; |
904 |
return EX_OSERR; |
794 |
} |
905 |
} |
795 |
|
906 |
|
796 |
if(flags&SPAMC_USE_SSL) { |
907 |
if(flags&SPAMC_USE_SSL) { |
Lines 808-815
Link Here
|
808 |
SSL_write(ssl, m->msg, m->msg_len); |
919 |
SSL_write(ssl, m->msg, m->msg_len); |
809 |
#endif |
920 |
#endif |
810 |
} else { |
921 |
} else { |
811 |
full_write(sock, buf, len); |
922 |
full_write(sock, 0, buf, len); |
812 |
full_write(sock, m->msg, m->msg_len); |
923 |
full_write(sock, 0, m->msg, m->msg_len); |
813 |
shutdown(sock, SHUT_WR); |
924 |
shutdown(sock, SHUT_WR); |
814 |
} |
925 |
} |
815 |
|
926 |
|
Lines 818-831
Link Here
|
818 |
if (failureval != EX_OK) { goto failure; } |
929 |
if (failureval != EX_OK) { goto failure; } |
819 |
|
930 |
|
820 |
if(sscanf(buf, "SPAMD/%18s %d %*s", versbuf, &response)!=2) { |
931 |
if(sscanf(buf, "SPAMD/%18s %d %*s", versbuf, &response)!=2) { |
|
|
932 |
#ifndef _WIN32 |
821 |
syslog(LOG_ERR, "spamd responded with bad string '%s'", buf); |
933 |
syslog(LOG_ERR, "spamd responded with bad string '%s'", buf); |
|
|
934 |
#else |
935 |
fprintf(stderr, "spamd responded with bad string '%s'\n", buf); |
936 |
#endif |
822 |
failureval = EX_PROTOCOL; goto failure; |
937 |
failureval = EX_PROTOCOL; goto failure; |
823 |
} |
938 |
} |
824 |
|
939 |
|
825 |
versbuf[19] = '\0'; |
940 |
versbuf[19] = '\0'; |
826 |
version = _locale_safe_string_to_float (versbuf, 20); |
941 |
version = _locale_safe_string_to_float (versbuf, 20); |
827 |
if (version < 1.0) { |
942 |
if (version < 1.0) { |
|
|
943 |
#ifndef _WIN32 |
828 |
syslog(LOG_ERR, "spamd responded with bad version string '%s'", versbuf); |
944 |
syslog(LOG_ERR, "spamd responded with bad version string '%s'", versbuf); |
|
|
945 |
#else |
946 |
fprintf(stderr, "spamd responded with bad version string '%s'\n", versbuf); |
947 |
#endif |
829 |
failureval = EX_PROTOCOL; goto failure; |
948 |
failureval = EX_PROTOCOL; goto failure; |
830 |
} |
949 |
} |
831 |
|
950 |
|
Lines 848-854
Link Here
|
848 |
len = 0; /* overwrite those headers */ |
967 |
len = 0; /* overwrite those headers */ |
849 |
|
968 |
|
850 |
if (flags&SPAMC_CHECK_ONLY) { |
969 |
if (flags&SPAMC_CHECK_ONLY) { |
851 |
close(sock); sock = -1; |
970 |
closesocket(sock); sock = -1; |
852 |
if (m->is_spam == EX_TOOBIG) { |
971 |
if (m->is_spam == EX_TOOBIG) { |
853 |
/* We should have gotten headers back... Damnit. */ |
972 |
/* We should have gotten headers back... Damnit. */ |
854 |
failureval = EX_PROTOCOL; goto failure; |
973 |
failureval = EX_PROTOCOL; goto failure; |
Lines 874-880
Link Here
|
874 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len, |
993 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len, |
875 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); |
994 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); |
876 |
} else{ |
995 |
} else{ |
877 |
len = full_read (sock, m->out+m->out_len, |
996 |
len = full_read (sock, 0, m->out+m->out_len, |
878 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len, |
997 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len, |
879 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); |
998 |
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); |
880 |
} |
999 |
} |
Lines 886-897
Link Here
|
886 |
m->out_len+=len; |
1005 |
m->out_len+=len; |
887 |
|
1006 |
|
888 |
shutdown(sock, SHUT_RD); |
1007 |
shutdown(sock, SHUT_RD); |
889 |
close(sock); sock = -1; |
1008 |
closesocket(sock); sock = -1; |
890 |
} |
1009 |
} |
891 |
libspamc_timeout = 0; |
1010 |
libspamc_timeout = 0; |
892 |
|
1011 |
|
893 |
if(m->out_len!=m->content_length) { |
1012 |
if(m->out_len!=m->content_length) { |
|
|
1013 |
#ifndef _WIN32 |
894 |
syslog(LOG_ERR, "failed sanity check, %d bytes claimed, %d bytes seen", |
1014 |
syslog(LOG_ERR, "failed sanity check, %d bytes claimed, %d bytes seen", |
|
|
1015 |
#else |
1016 |
fprintf(stderr, "failed sanity check, %d bytes claimed, %d bytes seen\n", |
1017 |
#endif |
895 |
m->content_length, m->out_len); |
1018 |
m->content_length, m->out_len); |
896 |
failureval = EX_PROTOCOL; goto failure; |
1019 |
failureval = EX_PROTOCOL; goto failure; |
897 |
} |
1020 |
} |
Lines 901-907
Link Here
|
901 |
failure: |
1024 |
failure: |
902 |
free(m->out); m->out=m->msg; m->out_len=m->msg_len; |
1025 |
free(m->out); m->out=m->msg; m->out_len=m->msg_len; |
903 |
if (sock != -1) { |
1026 |
if (sock != -1) { |
904 |
close(sock); |
1027 |
closesocket(sock); |
905 |
} |
1028 |
} |
906 |
libspamc_timeout = 0; |
1029 |
libspamc_timeout = 0; |
907 |
|
1030 |
|
Lines 936-942
Link Here
|
936 |
|
1059 |
|
937 |
FAIL: |
1060 |
FAIL: |
938 |
if(flags&SPAMC_CHECK_ONLY){ |
1061 |
if(flags&SPAMC_CHECK_ONLY){ |
939 |
full_write(out_fd, "0/0\n", 4); |
1062 |
full_write(out_fd, 1, "0/0\n", 4); |
940 |
message_cleanup(&m); |
1063 |
message_cleanup(&m); |
941 |
return EX_NOTSPAM; |
1064 |
return EX_NOTSPAM; |
942 |
} else { |
1065 |
} else { |
Lines 1032-1045
Link Here
|
1032 |
struct hostent *hp = 0; |
1155 |
struct hostent *hp = 0; |
1033 |
char **addrp; |
1156 |
char **addrp; |
1034 |
|
1157 |
|
|
|
1158 |
#ifdef _WIN32 |
1159 |
// Start Winsock up |
1160 |
WSADATA wsaData; |
1161 |
int nCode; |
1162 |
if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) { |
1163 |
printf("WSAStartup() returned error code %d\n", nCode); |
1164 |
return EX_OSERR; |
1165 |
} |
1166 |
|
1167 |
#endif |
1168 |
|
1035 |
assert(tp != 0); |
1169 |
assert(tp != 0); |
1036 |
|
1170 |
|
1037 |
switch ( tp->type ) |
1171 |
switch ( tp->type ) |
1038 |
{ |
1172 |
{ |
|
|
1173 |
#ifndef _WIN32 |
1039 |
case TRANSPORT_UNIX: |
1174 |
case TRANSPORT_UNIX: |
1040 |
assert(tp->socketpath != 0); |
1175 |
assert(tp->socketpath != 0); |
1041 |
return EX_OK; |
1176 |
return EX_OK; |
1042 |
|
1177 |
#endif |
1043 |
case TRANSPORT_LOCALHOST: |
1178 |
case TRANSPORT_LOCALHOST: |
1044 |
tp->hosts[0].s_addr = inet_addr("127.0.0.1"); |
1179 |
tp->hosts[0].s_addr = inet_addr("127.0.0.1"); |
1045 |
tp->nhosts = 1; |
1180 |
tp->nhosts = 1; |
Lines 1050-1056
Link Here
|
1050 |
{ |
1185 |
{ |
1051 |
int origherr = h_errno; /* take a copy before syslog() */ |
1186 |
int origherr = h_errno; /* take a copy before syslog() */ |
1052 |
|
1187 |
|
|
|
1188 |
#ifndef _WIN32 |
1053 |
syslog (LOG_ERR, "gethostbyname(%s) failed: h_errno=%d", |
1189 |
syslog (LOG_ERR, "gethostbyname(%s) failed: h_errno=%d", |
|
|
1190 |
#else |
1191 |
fprintf (stderr, "gethostbyname(%s) failed: h_errno=%d\n", |
1192 |
#endif |
1054 |
tp->hostname, origherr); |
1193 |
tp->hostname, origherr); |
1055 |
switch (origherr) |
1194 |
switch (origherr) |
1056 |
{ |
1195 |
{ |
Lines 1094-1100
Link Here
|
1094 |
for (addrp = hp->h_addr_list; *addrp; addrp++) |
1233 |
for (addrp = hp->h_addr_list; *addrp; addrp++) |
1095 |
{ |
1234 |
{ |
1096 |
if (tp->nhosts >= TRANSPORT_MAX_HOSTS-1) { |
1235 |
if (tp->nhosts >= TRANSPORT_MAX_HOSTS-1) { |
|
|
1236 |
#ifndef _WIN32 |
1097 |
syslog (LOG_ERR, "hit limit of %d hosts, ignoring remainder", TRANSPORT_MAX_HOSTS-1); |
1237 |
syslog (LOG_ERR, "hit limit of %d hosts, ignoring remainder", TRANSPORT_MAX_HOSTS-1); |
|
|
1238 |
#else |
1239 |
fprintf (stderr, "hit limit of %d hosts, ignoring remainder\n", TRANSPORT_MAX_HOSTS-1); |
1240 |
#endif |
1098 |
break; |
1241 |
break; |
1099 |
} |
1242 |
} |
1100 |
|
1243 |
|
Lines 1148-1160
Link Here
|
1148 |
char inputstr[99], cmpbuf1[99], cmpbuf2[99]; |
1291 |
char inputstr[99], cmpbuf1[99], cmpbuf2[99]; |
1149 |
float output; |
1292 |
float output; |
1150 |
|
1293 |
|
1151 |
snprintf (inputstr, 99, "%f", input); |
1294 |
/* sprintf instead of snprintf is safe here because it is only a controlled test */ |
|
|
1295 |
sprintf (inputstr, "%f", input); |
1152 |
output = _locale_safe_string_to_float (inputstr, 99); |
1296 |
output = _locale_safe_string_to_float (inputstr, 99); |
1153 |
if (input == output) { return; } |
1297 |
if (input == output) { return; } |
1154 |
|
1298 |
|
1155 |
/* could be a rounding error. print as string and compare those */ |
1299 |
/* could be a rounding error. print as string and compare those */ |
1156 |
snprintf (cmpbuf1, 98, "%f", input); |
1300 |
sprintf (cmpbuf1, "%f", input); |
1157 |
snprintf (cmpbuf2, 98, "%f", output); |
1301 |
sprintf (cmpbuf2, "%f", output); |
1158 |
if (!strcmp (cmpbuf1, cmpbuf2)) { return; } |
1302 |
if (!strcmp (cmpbuf1, cmpbuf2)) { return; } |
1159 |
|
1303 |
|
1160 |
printf ("FAIL: input=%f != output=%f\n", input, output); |
1304 |
printf ("FAIL: input=%f != output=%f\n", input, output); |