Stephen Boltinghouse (sbolting at nemonet.com) wrote:
> Take five minutes to read this and it WILL change your life.
>> [lotsa spamming blather removed]
Hello Everybody,
In our efforts to rid the net of spam, I have written a
little program called SAFT. Here it is for all to enjoy!
Let me know what you think.
Best regards,
Howard
------------------cut here for saft.c------------------------
/*
---------------------------------------------------------------
- SAFT (Sick And F--king Tired [of spam])
-
- I wrote this little gem to help fight against the onslaught
- of spam that has plagued the newsgroups. If your news reader
- has a way of piping news articles into an external program,
- then SAFT is the spam-buster for you! (SAFT has been tested
- on unix using the 'tin' newsreader. However, there should
- be little effort porting it to other operating systems.)
-
- Essentially, SAFT allows you to automatically construct and
- send a nasty-gram e-mail to the postmaster of the spammer's
- service provider. Since parasitic spammers usually forge
- their e-mail address (and various other fields), SAFT gets
- the service providers hostname from the "nntp-posting-host"
- field, which is seldom forged.
-
- SAFT reads the contents of the spam article from stdin.
- Therefor, your news reader must the ability to pipe the
- article into an external program (SAFT in this case).
-
- Two input files are required by SAFT. (SEE THE COMMENTS
- FOLLOWING THE CODE FOR AN EXAMPLE OF THESE TWO FILES.):
-
- saftnote.txt - This file contains the body of the message
- (form-letter) that will be sent to the
- spammer's postmaster. This file must be
- in the default directory (i.e. the
- directory where you are running your news
- reader.)
-
- saftmail - SAFT runs this script to send the e-mail to
- the spammer's postmaster. SAFT passes it the
- e-mail address of the postmaster as its only
- argument. It must be in the default
- directory, or in one of the directories in
- your path.
-
- SAFT creates one output file in the default directory:
-
- narc.txt - The first part of this file contains the text
- from the saftnote.txt file. Following that,
- is the text of the spammer's newsgroup article.
- The saftmail script should e-mail the text
- of this file to the postmaster.
-
- To make a SAFT executable file, do this at the unix command
- line:
-
- gcc saft.c
- mv a.out saft
-
- SAFT is PUBLIC DOMAIN software. I'm giving it out FREE with
- no obligation (and NO SUPPORT!). Give it out to ALL your
- friends! Hack at it and make it better (please e-mail me any
- improvements that you add!). Also, don't knock it; I wrote
- it less than a half day.
-
- Help take a bite out of spam!!!
-
- Howard Knight (HowardK at netcom.com)
-
---------------------------------------------------------------
*/
/*
#define HKFILTER
#define HKADMIN
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
static char nextline[4096];
/*
----------------------------------------------------------------------------
gethostfrompid
----------------------------------------------------------------------------
*/
static char gethostfrompid ( char *line, char *hostid )
{
struct hostent *hoststr;
char *pt;
unsigned char addr[4];
int i, len;
char tmpbuf[256];
/*
copy to temp buffer
*/
strcpy ( tmpbuf, line );
/*
get the first number
*/
pt = strtok ( tmpbuf, "." );
/*
loop through the 4 numbers and store them
in the addr array
*/
for ( i = 0; i < 4; i++ )
{
if ( !pt )
goto fail;
addr[i] = (unsigned char) atoi ( pt );
pt = strtok ( NULL, "." );
}
/*
get the host name, bail if error
*/
hoststr = gethostbyaddr ( addr, 4, PF_INET );
if ( !hoststr )
goto fail;
/*
copy name in input buffer
*/
strcpy ( hostid, hoststr->h_name );
printf ( "Lookup: %d.%d.%d.%d = %s\n",
(int) addr[0], (int) addr[1],
(int) addr[2], (int) addr[3], hostid );
return ( 1 );
fail:
printf ( "!!! Lookup of %s failed\n", line );
strcpy ( hostid, line );
return ( 0 );
}
/*
----------------------------------------------------------------------------
gethostname
----------------------------------------------------------------------------
*/
static char gethostname ( char *line, char *hostname )
{
char domain1[80], domain2[80];
char *pt;
int len, i;
char bAlpha = 0;
char tmpbuf[256];
/*
length of string
*/
len = strlen ( line );
/*
loop through all the chars
*/
for ( i = 0; i < len; i++ )
{
/*
if EOL char, terminate line and bail out of loop
*/
if ( line[i] == 10 )
{
line[i] = 0;
break;
}
/*
if not part of a pid address, set flag and bail
out of loop
*/
if ( line[i] != '.' && ( line[i] < '0' || line[i] > '9' ) )
{
bAlpha = 1;
break;
}
}
/*
if pid translate
*/
if ( bAlpha )
strcpy ( tmpbuf, line );
else
{
if ( !gethostfrompid ( line, tmpbuf ) )
{
strcpy ( hostname, tmpbuf );
return ( 1 );
}
}
/*
get first part of host name
*/
pt = strtok ( tmpbuf, "." );
if ( !pt )
return ( 0 );
strcpy ( domain1, pt );
/*
get second part
*/
pt = strtok ( NULL, "." );
if ( !pt )
return ( 0 );
strcpy ( domain2, pt );
/*
loop to get remaining parts
*/
for ( ;; )
{
pt = strtok ( NULL, "." );
if ( !pt )
break;
strcpy ( domain1, domain2 );
strcpy ( domain2, pt );
}
/*
copy name to input buffer
*/
sprintf ( hostname, "%s.%s", domain1, domain2 );
return ( 1 );
}
/*
----------------------------------------------------------------------------
main
----------------------------------------------------------------------------
*/
int main()
{
int linelen = 0;
int nextchar = 0;
FILE *pfout, *pfnote;
int iret;
char hostname[128];
int i;
char bGotHost = 0;
char bGotNNTP = 0;
char email[128];
char *p;
printf ( "\n" );
/*
open note file
*/
pfnote = fopen ( "saftnote.txt", "r" );
if ( !pfnote )
{
printf ( "!!! You must provide a saftnote.txt file.\n" );
return ( 1 );
}
/*
create output file
*/
pfout = fopen ( "narc.txt", "w" );
if ( !pfout )
return ( 1 );
/*
copy all of the characters from the note
file to the output file
*/
for ( ;; )
{
nextchar = fgetc ( pfnote );
if ( nextchar == EOF )
break;
fputc ( nextchar, pfout );
}
/*
done with the note file
*/
fclose ( pfnote );
/*
loop through all of the characters in stdin
*/
for ( ;; )
{
/*
get a char
*/
nextchar = getchar();
/*
if end of file, break out of loop
*/
if ( nextchar == EOF )
break;
/*
put the next char in our line buffer
*/
nextline[linelen] = nextchar;
linelen++;
/*
if end of line,
*/
if ( nextchar == 10 )
{
/*
write the record to the output file
*/
fwrite ( nextline, linelen, 1, pfout );
/*
if more than 21 chars
*/
if ( linelen > 21 )
{
/*
lowercase the line
*/
for ( i = 0; i < linelen; i++ )
nextline[i] = tolower ( nextline[i] );
/*
null terminate
*/
nextline[linelen] = '\0';
/*
if nntp-posting-host header field set flag and
move past the field name
*/
bGotNNTP = 0;
if ( strncmp ( nextline, "nntp-posting-host: ", 19 ) == 0 )
{
bGotNNTP = 1;
p = nextline + 19;
}
/*
if x-nntp-posting-host header field set flag and
move past the field name
*/
else if ( strncmp ( nextline, "x-nntp-posting-host: ", 21 ) == 0 )
{
bGotNNTP = 1;
p = nextline + 21;
}
/*
if we found the NNTP-posting-host field
*/
if ( bGotNNTP )
{
/*
if host was translated, set flag
*/
if ( gethostname ( p, hostname ) )
bGotHost = 1;
/*
bail out of program if can't translate
*/
else
{
printf ( "!!! Invalid NNTP-posting-host\n" );
fclose ( pfout );
return ( 1 );
}
} /* end of NNTP-posting-host processing */
} /* check for line length greater than 21 chars */
/*
reset line length for the next line
*/
linelen = 0;
} /* check for end-of-line */
} /* loop through all chars in stdin */
/*
close output file
*/
fclose ( pfout );
/*
bail if host wasn't found
*/
if ( !bGotHost )
{
printf ( "!!! No NNTP-posting-host\n" );
return ( 1 );
}
#ifdef HKFILTER
if ( strncmp ( hostname, "wavenet.com", 11 ) == 0 )
{
printf ( "!!! wavenet.com filter\n" );
return ( 0 );
}
#endif
/*
construct e-mail address to postmaster
*/
sprintf ( email, "postmaster@%s", hostname );
#ifdef HKADMIN
if ( strncmp ( hostname, "earthlink.net", 13 ) == 0 )
strcpy ( email, "postmaster at earthlink.net,sky at earthlink.net" );
else if ( strncmp ( hostname, "superlink.net", 13 ) == 0 )
strcpy ( email, "postmaster at superlink.net,jerryw at superlink.net" );
#endif
/*
run exec that will e-mail the postmaster
*/
printf ( "E-mailing: %s\n", email );
execlp ( "saftmail", "saftmail", email, 0, 0 );
/*
if we get here, we couldn't run saftmail
*/
printf ( "!!! Error running saftmail\n" );
return ( 0 );
}
/*
--------------- example of saftnote.txt -----------------------
Dear Postmaster,
The following abusive newsgroup article (spam) originated at
your site. I don't know if there's a way for you to trace the
person who is abusing your site, but this article may provide
you with a clue. Thanks for helping to rid the newsgroup of
these inapropriate spam articles.
Best regards,
Howard Knight
--------------- end of saftnote.txt ---------------------------
*/
/*
--------------- example of saftmail ---------------------------
mailx -s "ALERT: Your site is being abused!" $1 < narc.txt
--------------- end of saftmail -------------------------------
*/