View | Details | Raw Unified | Return to bug 2862
Collapse All | Expand All

(-)Makefile.PL (-14 / +28 lines)
Lines 149-158 Link Here
149
my @datafiles = map { s,^rules/,,; $_ } (<rules/*.cf>);
149
my @datafiles = map { s,^rules/,,; $_ } (<rules/*.cf>);
150
my $datafiles = join(' ', (grep { /^[0-6][0-9]_/ } @datafiles), qw(user_prefs.template triplets.txt languages));
150
my $datafiles = join(' ', (grep { /^[0-6][0-9]_/ } @datafiles), qw(user_prefs.template triplets.txt languages));
151
151
152
# Only build spamd and spamc on non-Windows platforms
152
# Only build spamd on non-Windows platforms
153
my @SPAMD_EXE_FILES = ();
153
my @SPAMD_EXE_FILES = ();
154
if (!RUNNING_ON_WINDOWS) {
154
if (!RUNNING_ON_WINDOWS) {
155
  @SPAMD_EXE_FILES = ('spamd/spamc$(EXE_EXT)', 'spamd/spamd');
155
  @SPAMD_EXE_FILES = ('spamd/spamc$(EXE_EXT)', 'spamd/spamd');
156
} else {
157
  @SPAMD_EXE_FILES = ('spamd/spamc$(EXE_EXT)');
156
}
158
}
157
159
158
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
160
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
Lines 208-214 Link Here
208
        'spamd/libspamc.so', 'spamd/libsslspamc.so',
210
        'spamd/libspamc.so', 'spamd/libsslspamc.so',
209
        'spamd/binaries.mk', 'spamd/config.h', 'spamd/config.status',
211
        'spamd/binaries.mk', 'spamd/config.h', 'spamd/config.status',
210
        'spamd/config.cache', 'spamd/config.log', 'spamd/autom4te.cache',
212
        'spamd/config.cache', 'spamd/config.log', 'spamd/autom4te.cache',
211
        'qmail/qmail-spamc',
213
        'qmail/qmail-spamc', 'spamd/*.o', 'spamd/*.obj',
212
        't/do_net', 't/log',
214
        't/do_net', 't/log',
213
      )
215
      )
214
    },
216
    },
Lines 847-852 Link Here
847
    }
848
    }
848
  }
849
  }
849
850
851
  push(@code, "PREPROCESS    = \$(PERL) build/preprocessor");
852
    
853
  my($repository);
854
  $repository = uc($SELF->{INSTALLDIRS}) || 'SITE';
855
856
  foreach my $macro (qw(PREFIX SYSCONFDIR)) {
857
    push(@code, macro_def('I_' . $macro,
858
                    macro_ref($repository . $macro)));
859
  }
860
850
  clean_MY_globals($self);
861
  clean_MY_globals($self);
851
  return join("\n", @code);
862
  return join("\n", @code);
852
}
863
}
Lines 859-868 Link Here
859
  my($repository);
870
  my($repository);
860
  $repository = uc($SELF->{INSTALLDIRS}) || 'SITE';
871
  $repository = uc($SELF->{INSTALLDIRS}) || 'SITE';
861
872
862
  foreach my $macro (qw(PREFIX SYSCONFDIR)) {
863
    push(@code, macro_def('I_' . $macro,
864
                    macro_ref($repository . $macro)));
865
  }
866
  foreach my $macro (qw(DATA CONF LIB)) {
873
  foreach my $macro (qw(DATA CONF LIB)) {
867
    push(@code, macro_def('I_' . $macro . 'DIR',
874
    push(@code, macro_def('I_' . $macro . 'DIR',
868
                    macro_ref('INSTALL' . repository($repository) . $macro)));
875
                    macro_ref('INSTALL' . repository($repository) . $macro)));
Lines 881-888 Link Here
881
888
882
  $code .= <<'  EOD';
889
  $code .= <<'  EOD';
883
890
884
PREPROCESS    = $(PERL) build/preprocessor
885
886
FIXVARS		= -Mvars \
891
FIXVARS		= -Mvars \
887
		  -DVERSION="$(VERSION)" \
892
		  -DVERSION="$(VERSION)" \
888
		  -DPREFIX="$(I_PREFIX)" \
893
		  -DPREFIX="$(I_PREFIX)" \
Lines 911-934 Link Here
911
spamd/libspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
916
spamd/libspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
912
	$(MAKE) -f spamd/binaries.mk $@
917
	$(MAKE) -f spamd/binaries.mk $@
913
918
914
spamd/libspamc.dll: spamd/binaries.mk $(SPAMC_SOURCES)
915
	$(MAKE) -f spamd/binaries.mk $@
916
917
spamd/spamc$(EXE_EXT): spamd/binaries.mk $(SPAMC_SOURCES)
919
spamd/spamc$(EXE_EXT): spamd/binaries.mk $(SPAMC_SOURCES)
918
	$(MAKE) -f spamd/binaries.mk $@
920
	$(MAKE) -f spamd/binaries.mk $@
919
921
920
spamd/libsslspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
922
spamd/libsslspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
921
	$(MAKE) -f spamd/binaries.mk $@
923
	$(MAKE) -f spamd/binaries.mk $@
922
924
923
spamd/libsslspamc.dll: spamd/binaries.mk $(SPAMC_SOURCES)
924
	$(MAKE) -f spamd/binaries.mk $@
925
926
qmail/qmail-spamc: spamd/binaries.mk $(SPAMC_SOURCES)
925
qmail/qmail-spamc: spamd/binaries.mk $(SPAMC_SOURCES)
927
	$(MAKE) -f spamd/binaries.mk $@
926
	$(MAKE) -f spamd/binaries.mk $@
927
  EOD
928
928
929
  if (!($^O =~ /^(?:mswin|dos|os2)/oi)) {
930
    $code .= <<'  EOD';
929
spamd/binaries.mk: spamd/configure
931
spamd/binaries.mk: spamd/configure
930
	cd spamd; ./configure --prefix="$(I_PREFIX)" --sysconfdir="$(I_SYSCONFDIR)" --datadir="$(I_DATADIR)" --enable-ssl="$(ENABLE_SSL)"
932
	cd spamd; ./configure --prefix="$(I_PREFIX)" --sysconfdir="$(I_SYSCONFDIR)" --datadir="$(I_DATADIR)" --enable-ssl="$(ENABLE_SSL)"
933
  EOD
931
934
935
  } else {
936
    $code .= <<'  EOD';
937
spamd/binaries.mk: spamd/win32.config spamd/win32.mak
938
	$(PERL) -MFile::SPec -MFile::Copy \
939
	  -e "copy(q{spamd/win32.config}, q{spamd/config.h}); copy(q{spamd/win32.mak}, q{spamd/binaries.mk});"
940
  EOD
941
942
  }
943
944
  $code .= <<'  EOD';
932
conf__install:
945
conf__install:
933
	-$(MKPATH) $(B_CONFDIR)
946
	-$(MKPATH) $(B_CONFDIR)
934
	$(PERL) -MFile::Spec -MFile::Copy \
947
	$(PERL) -MFile::Spec -MFile::Copy \
(-)spamd/libspamc.c (-56 / +202 lines)
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);
(-)spamd/libspamc.h (-1 / +28 lines)
Lines 9-19 Link Here
9
#ifndef LIBSPAMC_H
9
#ifndef LIBSPAMC_H
10
#define LIBSPAMC_H 1
10
#define LIBSPAMC_H 1
11
11
12
#ifdef _WIN32
13
#include <winsock.h>
14
#else
15
#include <netdb.h>
12
#include <sys/types.h>
16
#include <sys/types.h>
13
#include <sys/socket.h>
17
#include <sys/socket.h>
14
#include <netinet/in.h>
18
#include <netinet/in.h>
15
#include <netdb.h>
19
#endif
16
#include <stdio.h>
20
#include <stdio.h>
21
22
#ifdef _WIN32
23
#define EX_OK        0
24
#define EX_USAGE        64
25
#define EX_DATAERR      65
26
#define EX_NOINPUT      66
27
#define EX_NOUSER       67
28
#define EX_NOHOST       68
29
#define EX_UNAVAILABLE  69
30
#define EX_SOFTWARE     70
31
#define EX_OSERR        71
32
#define EX_OSFILE       72
33
#define EX_CANTCREAT    73
34
#define EX_IOERR        74
35
#define EX_TEMPFAIL     75
36
#define EX_PROTOCOL     76
37
#define EX_NOPERM       77
38
#define EX_CONFIG       78
39
40
#define STDIN_FILENO 0
41
#define STDOUT_FILENO 1
42
43
#endif
17
44
18
#define EX_NOTSPAM		  0
45
#define EX_NOTSPAM		  0
19
#define EX_ISSPAM		  1
46
#define EX_ISSPAM		  1
(-)spamd/spamc.c (-24 / +57 lines)
Lines 9-25 Link Here
9
#include "libspamc.h"
8
#include "libspamc.h"
10
#include "utils.h"
9
#include "utils.h"
11
10
12
#include <unistd.h>
13
#include <stdlib.h>
11
#include <stdlib.h>
14
#include <stdio.h>
12
#include <stdio.h>
15
#include <string.h>
13
#include <string.h>
14
#ifdef _WIN32
15
#define syslog(x, y) fprintf(stderr, #y "\n")
16
#else
16
#include <syslog.h>
17
#include <syslog.h>
18
#include <unistd.h>
19
#include <netdb.h>
17
#include <sys/types.h>
20
#include <sys/types.h>
18
#include <sys/socket.h>
21
#include <sys/socket.h>
19
#include <netinet/in.h>
22
#include <netinet/in.h>
20
#include <netinet/tcp.h>
23
#include <netinet/tcp.h>
21
#include <netdb.h>
22
#include <arpa/inet.h>
24
#include <arpa/inet.h>
25
#endif
23
26
24
#ifdef HAVE_SYSEXITS_H
27
#ifdef HAVE_SYSEXITS_H
25
#include <sysexits.h>
28
#include <sysexits.h>
Lines 48-60 Link Here
48
     || (defined(__sgi))  /* IRIX */ \
51
     || (defined(__sgi))  /* IRIX */ \
49
     || (defined(__osf__)) /* Digital UNIX */ \
52
     || (defined(__osf__)) /* Digital UNIX */ \
50
     || (defined(hpux) || defined(__hpux)) /* HPUX */ \
53
     || (defined(hpux) || defined(__hpux)) /* HPUX */ \
51
     || (defined(_WIN32) || defined(__CYGWIN__)) /* CygWin, Win32 */
54
     || (defined(__CYGWIN__)) /* CygWin, Win32 */
52
55
53
extern int optind;
56
extern int optind;
54
extern char *optarg;
57
extern char *optarg;
55
58
56
#endif
59
#endif
57
60
61
#ifdef _WIN32
62
#include "getopt.h"
63
char* __progname = "spamc";
64
#endif
65
66
58
/* safe fallback defaults to on now - CRH */
67
/* safe fallback defaults to on now - CRH */
59
int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK;
68
int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK;
60
69
Lines 93-99 Link Here
93
{
102
{
94
  int opt, i, j;
103
  int opt, i, j;
95
104
96
  while(-1 != (opt = getopt(argc,argv,"-BcrRd:e:fhyp:t:s:u:xSHU:")))
105
  while(-1 != (opt = getopt(argc,argv,
106
#ifndef _WIN32
107
                            "-BcrRd:e:fhyp:t:s:u:xSHU:"
108
#else
109
                            "-BcrRd:fhyp:t:s:u:xSH"
110
#endif
111
)))
97
  {
112
  {
98
    switch(opt)
113
    switch(opt)
99
    {
114
    {
Lines 102-113 Link Here
102
        flags |= SPAMC_RANDOMIZE_HOSTS;
117
        flags |= SPAMC_RANDOMIZE_HOSTS;
103
        break;
118
        break;
104
      }
119
      }
120
#ifndef _WIN32
105
    case 'U':
121
    case 'U':
106
      {
122
      {
107
        ptrn->type       = TRANSPORT_UNIX;
123
        ptrn->type       = TRANSPORT_UNIX;
108
        ptrn->socketpath = optarg;
124
        ptrn->socketpath = optarg;
109
        break;
125
        break;
110
      }
126
      }
127
#endif
111
    case 'B':
128
    case 'B':
112
      {
129
      {
113
        flags = (flags & ~SPAMC_MODE_MASK) | SPAMC_BSMTP_MODE;
130
        flags = (flags & ~SPAMC_MODE_MASK) | SPAMC_BSMTP_MODE;
Lines 139-144 Link Here
139
	ptrn->hostname = optarg;	/* fix the ptr to point to this string */
156
	ptrn->hostname = optarg;	/* fix the ptr to point to this string */
140
	break;
157
	break;
141
      }
158
      }
159
#ifndef _WIN32
142
    case 'e':
160
    case 'e':
143
      {
161
      {
144
        if((exec_argv=malloc(sizeof(*exec_argv)*(argc-optind+2)))==NULL)
162
        if((exec_argv=malloc(sizeof(*exec_argv)*(argc-optind+2)))==NULL)
Lines 149-154 Link Here
149
        exec_argv[i]=NULL;
167
        exec_argv[i]=NULL;
150
        return EX_OK;
168
        return EX_OK;
151
      }
169
      }
170
#endif
152
    case 'p':
171
    case 'p':
153
      {
172
      {
154
	ptrn->port = atoi(optarg);
173
	ptrn->port = atoi(optarg);
Lines 190-195 Link Here
190
      syslog (LOG_ERR, "invalid usage");
209
      syslog (LOG_ERR, "invalid usage");
191
      /* NOTE: falls through to usage case below... */
210
      /* NOTE: falls through to usage case below... */
192
    }
211
    }
212
#ifndef _WIN32
213
    case 'e':
214
#endif
193
    case 'h':
215
    case 'h':
194
    case 1:
216
    case 1:
195
      {
217
      {
Lines 210-215 Link Here
210
        *fd=STDOUT_FILENO;
232
        *fd=STDOUT_FILENO;
211
        return;
233
        return;
212
    }
234
    }
235
#ifndef _WIN32
213
    if(pipe(fds)){
236
    if(pipe(fds)){
214
        syslog(LOG_ERR, "pipe creation failed: %m");
237
        syslog(LOG_ERR, "pipe creation failed: %m");
215
        exit(EX_OSERR);
238
        exit(EX_OSERR);
Lines 237-242 Link Here
237
    close(fds[0]); /* no point in leaving extra fds lying around */
260
    close(fds[0]); /* no point in leaving extra fds lying around */
238
    execv(exec_argv[0], exec_argv);
261
    execv(exec_argv[0], exec_argv);
239
    syslog(LOG_ERR, "exec failed: %m");
262
    syslog(LOG_ERR, "exec failed: %m");
263
#else
264
    fprintf(stderr, "exec failed: %d\n", errno);
265
#endif
240
    exit(EX_OSERR);
266
    exit(EX_OSERR);
241
}
267
}
242
268
Lines 256-263 Link Here
256
  do_libspamc_unit_tests();
282
  do_libspamc_unit_tests();
257
#endif
283
#endif
258
284
285
#ifndef _WIN32
259
  openlog ("spamc", LOG_CONS|LOG_PID, LOG_MAIL);
286
  openlog ("spamc", LOG_CONS|LOG_PID, LOG_MAIL);
260
  signal (SIGPIPE, SIG_IGN);
287
  signal (SIGPIPE, SIG_IGN);
288
#endif
261
289
262
  read_args(argc,argv, &max_size, &username, &trans);
290
  read_args(argc,argv, &max_size, &username, &trans);
263
291
Lines 274-279 Link Here
274
   * to our own buffer - then this won't arise as a problem.
302
   * to our own buffer - then this won't arise as a problem.
275
   */
303
   */
276
 
304
 
305
#ifndef _WIN32
277
  if(NULL == username)
306
  if(NULL == username)
278
  {
307
  {
279
  static char   userbuf[256];
308
  static char   userbuf[256];
Lines 289-294 Link Here
289
    userbuf[sizeof userbuf - 1] = '\0';
318
    userbuf[sizeof userbuf - 1] = '\0';
290
    username = userbuf;
319
    username = userbuf;
291
  }
320
  }
321
#endif
292
322
293
  if ((flags & SPAMC_RANDOMIZE_HOSTS) != 0) {
323
  if ((flags & SPAMC_RANDOMIZE_HOSTS) != 0) {
294
    /* we don't need strong randomness; this is just so we pick
324
    /* we don't need strong randomness; this is just so we pick
Lines 304-360 Link Here
304
   * we connect to the spam daemon. Mainly this involves lookup up the
334
   * we connect to the spam daemon. Mainly this involves lookup up the
305
   * hostname and getting the IP addresses to connect to.
335
   * hostname and getting the IP addresses to connect to.
306
   */
336
   */
307
  if ( (ret = transport_setup(&trans, flags)) != EX_OK )
337
  if ( (ret = transport_setup(&trans, flags)) == EX_OK ) {
308
    goto FAIL;
309
310
311
    out_fd=-1;
338
    out_fd=-1;
312
    m.type    = MESSAGE_NONE;
339
    m.type    = MESSAGE_NONE;
313
    m.max_len = max_size;
340
    m.max_len = max_size;
314
    m.timeout = timeout;
341
    m.timeout = timeout;
315
342
316
    ret=message_read(STDIN_FILENO, flags, &m);
343
    ret=message_read(STDIN_FILENO, flags, &m);
317
    if(ret!=EX_OK) goto FAIL;
344
    if(ret==EX_OK) {
318
    ret=message_filter(&trans, username, flags, &m);
345
    ret=message_filter(&trans, username, flags, &m);
319
    if(ret!=EX_OK) goto FAIL;
346
      if(ret==EX_OK) {
320
    get_output_fd(&out_fd);
347
    get_output_fd(&out_fd);
321
348
322
    if(message_write(out_fd, &m)<0) {
349
        if(message_write(out_fd, &m)>=0) {
323
      goto FAIL;
324
    }
325
350
326
    result = m.is_spam;
351
    result = m.is_spam;
327
    if ((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
352
    if ((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
328
      message_cleanup (&m);
353
      message_cleanup (&m);
329
      return result;
354
            ret = result;
330
    } else {
355
    } else {
331
      message_cleanup (&m);
356
      message_cleanup (&m);
357
          }
358
#ifdef _WIN32
359
          WSACleanup();
360
#endif
332
      return ret;
361
      return ret;
333
    }
362
    }
363
      }
364
    }
365
  }
334
366
335
FAIL:
367
 FAIL:
336
    get_output_fd(&out_fd);
368
    get_output_fd(&out_fd);
337
369
338
    result = m.is_spam;
370
    result = m.is_spam;
339
    if((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
371
    if((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
340
	/* probably, the write to stdout failed; we can still report exit code */
372
	/* probably, the write to stdout failed; we can still report exit code */
341
	message_cleanup (&m);
373
	message_cleanup (&m);
342
	return result;
374
      ret = result;      
343
344
    } else if(flags&SPAMC_CHECK_ONLY || flags&SPAMC_REPORT || flags&SPAMC_REPORT_IFSPAM) {
375
    } else if(flags&SPAMC_CHECK_ONLY || flags&SPAMC_REPORT || flags&SPAMC_REPORT_IFSPAM) {
345
        full_write(out_fd, "0/0\n", 4);
376
      full_write(out_fd, 1, "0/0\n", 4);
346
	message_cleanup (&m);
377
	message_cleanup (&m);
347
        return EX_NOTSPAM;
378
      ret = EX_NOTSPAM;      
348
349
    } else {
379
    } else {
350
        message_dump(STDIN_FILENO, out_fd, &m);
380
        message_dump(STDIN_FILENO, out_fd, &m);
351
	message_cleanup (&m);
381
	message_cleanup (&m);
352
        if (ret == EX_TOOBIG) {
382
        if (ret == EX_TOOBIG) {
353
          return 0;
383
        ret = 0;
354
        } else if (flags & SPAMC_SAFE_FALLBACK) {
384
        } else if (flags & SPAMC_SAFE_FALLBACK) {
355
	  return EX_OK;
385
        ret = EX_OK;
356
	} else {
357
	  return ret;
358
	}
386
	}
359
    }
387
    }
388
#ifdef _WIN32
389
    WSACleanup();
390
#endif
391
    return ret;
360
}
392
}
(-)spamd/spamd.raw (-2 / +12 lines)
Lines 141-146 Link Here
141
  'ssl'                         => \$opt{'ssl'},
141
  'ssl'                         => \$opt{'ssl'},
142
  'server-key=s'                => \$opt{'server-key'},
142
  'server-key=s'                => \$opt{'server-key'},
143
  'server-cert=s'               => \$opt{'server-cert'},
143
  'server-cert=s'               => \$opt{'server-cert'},
144
  'stdout=s'                    => \$opt{'stdout'},
144
145
145
  # will be stripped in future release
146
  # will be stripped in future release
146
  'add-from!'          => sub { warn "The --add-from option has been removed\n" },
147
  'add-from!'          => sub { warn "The --add-from option has been removed\n" },
Lines 280-286 Link Here
280
281
281
# Do whitelist later in tmp dir. Side effect: this will be done as -u user.
282
# Do whitelist later in tmp dir. Side effect: this will be done as -u user.
282
283
283
if ($log_facility ne 'stderr') {
284
if (($log_facility ne 'stderr') && ($log_facility ne 'null')) {
284
  eval {
285
  eval {
285
    setlogsock($log_socket);
286
    setlogsock($log_socket);
286
    syslog('debug', "spamd starting");  # required to actually open the socket
287
    syslog('debug', "spamd starting");  # required to actually open the socket
Lines 377-383 Link Here
377
  ) || die "Could not create INET socket: $! $@\n";
378
  ) || die "Could not create INET socket: $! $@\n";
378
}
379
}
379
380
380
$opt{'daemonize'} and daemonize();
381
if ($opt{'daemonize'}) {
382
  daemonize();
383
} else {
384
    if (defined($opt{'stdout'})) {
385
      STDOUT->autoflush(1);
386
      STDERR->autoflush(1);
387
      open STDOUT,">$opt{'stdout'}" or die "Could not redirect STDOUT: $!\n";
388
      open STDERR,'>&STDOUT' or die "Can't duplicate stdout: $!\n";
389
  }
390
}
381
391
382
if(defined($opt{'pidfile'})) {
392
if(defined($opt{'pidfile'})) {
383
  open PIDF,">$opt{'pidfile'}" or warn "Can't write to PID file: $!";
393
  open PIDF,">$opt{'pidfile'}" or warn "Can't write to PID file: $!";
(-)spamd/utils.c (-13 / +47 lines)
Lines 6-17 Link Here
6
 * "License".
6
 * "License".
7
 */
7
 */
8
8
9
#ifndef _WIN32
9
#include <unistd.h>
10
#include <unistd.h>
11
#include <sys/uio.h>
12
#else
13
typedef int ssize_t;
14
#endif
10
#include <errno.h>
15
#include <errno.h>
11
#include <signal.h>
16
#include <signal.h>
12
#include <sys/types.h>
17
#include <sys/types.h>
13
#include <sys/uio.h>
14
#include <unistd.h>
15
#include <stdio.h>
18
#include <stdio.h>
16
#include "utils.h"
19
#include "utils.h"
17
20
Lines 25-31 Link Here
25
/* Apr 24, 2003 sjf: made full_read and full_write void* params */
28
/* Apr 24, 2003 sjf: made full_read and full_write void* params */
26
29
27
/* -------------------------------------------------------------------------- */
30
/* -------------------------------------------------------------------------- */
28
31
#ifndef _WIN32
29
typedef void    sigfunc(int);   /* for signal handlers */
32
typedef void    sigfunc(int);   /* for signal handlers */
30
33
31
sigfunc* sig_catch(int sig, void (*f)(int))
34
sigfunc* sig_catch(int sig, void (*f)(int))
Lines 41-63 Link Here
41
static void catch_alrm(int x) {
44
static void catch_alrm(int x) {
42
  UNUSED_VARIABLE(x);
45
  UNUSED_VARIABLE(x);
43
}
46
}
47
#endif
44
48
45
ssize_t
49
ssize_t
46
fd_timeout_read (int fd, void *buf, size_t nbytes)
50
fd_timeout_read (int fd, char fdflag, void *buf, size_t nbytes)
47
{
51
{
48
  ssize_t nred;
52
  ssize_t nred;
53
  int origerr;
54
#ifndef _WIN32
49
  sigfunc* sig;
55
  sigfunc* sig;
50
56
51
  sig = sig_catch(SIGALRM, catch_alrm);
57
  sig = sig_catch(SIGALRM, catch_alrm);
52
  if (libspamc_timeout > 0) {
58
  if (libspamc_timeout > 0) {
53
    alarm(libspamc_timeout);
59
    alarm(libspamc_timeout);
54
  }
60
  }
61
#endif
55
62
56
  do {
63
  do {
64
    if (fdflag) {
57
    nred = read (fd, buf, nbytes);
65
    nred = read (fd, buf, nbytes);
58
  } while(nred < 0 && errno == EAGAIN);
66
      origerr = errno;
67
    } else {
68
      nred = recv (fd, buf, nbytes, 0);
69
#ifndef _WIN32
70
      origerr = errno;
71
#else
72
      origerr = WSAGetLastError();
73
#endif
74
    }
75
  } while(nred < 0 && origerr == EWOULDBLOCK);
59
76
60
  if(nred < 0 && errno == EINTR)
77
#ifndef _WIN32
78
  if(nred < 0 && origerr == EINTR)
61
    errno = ETIMEDOUT;
79
    errno = ETIMEDOUT;
62
80
63
  if (libspamc_timeout > 0) {
81
  if (libspamc_timeout > 0) {
Lines 66-71 Link Here
66
84
67
  /* restore old signal handler */
85
  /* restore old signal handler */
68
  sig_catch(SIGALRM, sig);
86
  sig_catch(SIGALRM, sig);
87
#endif
69
88
70
  return nred;
89
  return nred;
71
}
90
}
Lines 74-80 Link Here
74
ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
93
ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
75
{
94
{
76
  int nred;
95
  int nred;
77
  sigfunc* sig;
78
96
79
#ifndef SPAMC_SSL
97
#ifndef SPAMC_SSL
80
  UNUSED_VARIABLE(ssl);
98
  UNUSED_VARIABLE(ssl);
Lines 82-91 Link Here
82
  UNUSED_VARIABLE(nbytes);
100
  UNUSED_VARIABLE(nbytes);
83
#endif
101
#endif
84
102
103
#ifndef _WIN32
104
  sigfunc* sig;
105
85
  sig = sig_catch(SIGALRM, catch_alrm);
106
  sig = sig_catch(SIGALRM, catch_alrm);
86
  if (libspamc_timeout > 0) {
107
  if (libspamc_timeout > 0) {
87
    alarm(libspamc_timeout);
108
    alarm(libspamc_timeout);
88
  }
109
  }
110
#endif
89
111
90
  do {
112
  do {
91
#ifdef SPAMC_SSL
113
#ifdef SPAMC_SSL
Lines 93-100 Link Here
93
#else
115
#else
94
    nred = 0;			/* never used */
116
    nred = 0;			/* never used */
95
#endif
117
#endif
96
  } while(nred < 0 && errno == EAGAIN);
118
  } while(nred < 0 && errno == EWOULDBLOCK);
97
119
120
#ifndef _WIN32
98
  if(nred < 0 && errno == EINTR)
121
  if(nred < 0 && errno == EINTR)
99
    errno = ETIMEDOUT;
122
    errno = ETIMEDOUT;
100
123
Lines 104-109 Link Here
104
127
105
  /* restore old signal handler */
128
  /* restore old signal handler */
106
  sig_catch(SIGALRM, sig);
129
  sig_catch(SIGALRM, sig);
130
#endif
107
131
108
  return nred;
132
  return nred;
109
}
133
}
Lines 111-124 Link Here
111
/* -------------------------------------------------------------------------- */
135
/* -------------------------------------------------------------------------- */
112
136
113
int
137
int
114
full_read (int fd, void *vbuf, int min, int len)
138
full_read (int fd, char fdflag, void *vbuf, int min, int len)
115
{
139
{
116
  unsigned char *buf = (unsigned char *)vbuf;
140
  unsigned char *buf = (unsigned char *)vbuf;
117
  int total;
141
  int total;
118
  int thistime;
142
  int thistime;
119
143
120
  for (total = 0; total < min; ) {
144
  for (total = 0; total < min; ) {
121
    thistime = fd_timeout_read (fd, buf+total, len-total);
145
    thistime = fd_timeout_read (fd, fdflag, buf+total, len-total);
122
146
123
    if (thistime < 0) {
147
    if (thistime < 0) {
124
      return -1;
148
      return -1;
Lines 156-172 Link Here
156
}
180
}
157
181
158
int
182
int
159
full_write (int fd, const void *vbuf, int len)
183
full_write (int fd, char fdflag, const void *vbuf, int len)
160
{
184
{
161
  const unsigned char *buf = (const unsigned char *)vbuf;
185
  const unsigned char *buf = (const unsigned char *)vbuf;
162
  int total;
186
  int total;
163
  int thistime;
187
  int thistime;
188
  int origerr;
164
189
165
  for (total = 0; total < len; ) {
190
  for (total = 0; total < len; ) {
191
    if (fdflag) {
166
    thistime = write (fd, buf+total, len-total);
192
    thistime = write (fd, buf+total, len-total);
167
193
      origerr = errno;
194
    } else {
195
      thistime = send (fd, buf+total, len-total, 0);
196
#ifndef _WIN32
197
      origerr = errno;
198
#else
199
      origerr = WSAGetLastError();
200
#endif
201
    }
168
    if (thistime < 0) {
202
    if (thistime < 0) {
169
      if(EINTR == errno || EAGAIN == errno) continue;
203
      if(EINTR == origerr || EWOULDBLOCK == origerr) continue;
170
      return thistime;        /* always an error for writes */
204
      return thistime;        /* always an error for writes */
171
    }
205
    }
172
    total += thistime;
206
    total += thistime;
(-)spamd/utils.h (-3 / +55 lines)
Lines 15-27 Link Here
15
typedef int	SSL_CTX;
15
typedef int	SSL_CTX;
16
typedef int	SSL_METHOD;
16
typedef int	SSL_METHOD;
17
#endif
17
#endif
18
#ifdef _WIN32
19
#include <winsock.h>
20
typedef int ssize_t;
21
//
22
// BSD-compatible socket error codes for Win32
23
//
18
24
19
ssize_t fd_timeout_read (int fd, void *, size_t );  
25
#define EWOULDBLOCK             WSAEWOULDBLOCK 
26
#define EINPROGRESS             WSAEINPROGRESS 
27
#define EALREADY                WSAEALREADY 
28
#define ENOTSOCK                WSAENOTSOCK 
29
#define EDESTADDRREQ            WSAEDESTADDRREQ 
30
#define EMSGSIZE                WSAEMSGSIZE 
31
#define EPROTOTYPE              WSAEPROTOTYPE 
32
#define ENOPROTOOPT             WSAENOPROTOOPT 
33
#define EPROTONOSUPPORT         WSAEPROTONOSUPPORT 
34
#define ESOCKTNOSUPPORT         WSAESOCKTNOSUPPORT 
35
#define EOPNOTSUPP              WSAEOPNOTSUPP 
36
#define EPFNOSUPPORT            WSAEPFNOSUPPORT 
37
#define EAFNOSUPPORT            WSAEAFNOSUPPORT 
38
#define EADDRINUSE              WSAEADDRINUSE 
39
#define EADDRNOTAVAIL           WSAEADDRNOTAVAIL 
40
#define ENETDOWN                WSAENETDOWN 
41
#define ENETUNREACH             WSAENETUNREACH 
42
#define ENETRESET               WSAENETRESET 
43
#define ECONNABORTED            WSAECONNABORTED 
44
#define ECONNRESET              WSAECONNRESET 
45
#define ENOBUFS                 WSAENOBUFS 
46
#define EISCONN                 WSAEISCONN 
47
#define ENOTCONN                WSAENOTCONN 
48
#define ESHUTDOWN               WSAESHUTDOWN 
49
#define ETOOMANYREFS            WSAETOOMANYREFS 
50
#define ETIMEDOUT               WSAETIMEDOUT 
51
#define ECONNREFUSED            WSAECONNREFUSED 
52
#define ELOOP                   WSAELOOP 
53
// #define ENAMETOOLONG            WSAENAMETOOLONG
54
#define EHOSTDOWN               WSAEHOSTDOWN 
55
#define EHOSTUNREACH            WSAEHOSTUNREACH 
56
// #define ENOTEMPTY               WSAENOTEMPTY
57
#define EPROCLIM                WSAEPROCLIM 
58
#define EUSERS                  WSAEUSERS 
59
#define EDQUOT                  WSAEDQUOT 
60
#define ESTALE                  WSAESTALE 
61
#define EREMOTE                 WSAEREMOTE 
62
63
// NOTE: these are not errno constants in UNIX!
64
#define HOST_NOT_FOUND          WSAHOST_NOT_FOUND 
65
#define TRY_AGAIN               WSATRY_AGAIN 
66
#define NO_RECOVERY             WSANO_RECOVERY 
67
#define NO_DATA                 WSANO_DATA 
68
69
#endif
70
71
ssize_t fd_timeout_read (int fd, char fdflag, void *, size_t );  
20
int ssl_timeout_read (SSL *ssl, void *, int );  
72
int ssl_timeout_read (SSL *ssl, void *, int );  
21
73
22
/* these are fd-only, no SSL support */
74
/* these are fd-only, no SSL support */
23
int full_read(int fd, void *buf, int min, int len);
75
int full_read(int fd, char fdflag, void *buf, int min, int len);
24
int full_read_ssl(SSL *ssl, unsigned char *buf, int min, int len);
76
int full_read_ssl(SSL *ssl, unsigned char *buf, int min, int len);
25
int full_write(int fd, const void *buf, int len);
77
int full_write(int fd, char fdflag, const void *buf, int len);
26
78
27
#endif
79
#endif

Return to bug 2862