Newsgroups: comp.mail.sendmail
Subject: Spam Suppression Program Addon
Date: 6 Nov 1998 00:22:38 GMT
Organization: NCR Corporation, San Diego, CA
Message-ID: <71tfge$3eb@rap.SanDiegoCA.NCR.COM>


This tool does a number of simple checks on incoming mail.
It has been in use since: 
-rwxr-xr-t  1 abuse       24576 Oct  2  1997 /usr/misc/mailapps/bin/ckaddr

The new regular expression addition, and the fact that ".*stocknews.*"
pissed me off, prompted me to post this to all sendmail admins. It checks
only the login part of the address, sendmail V8 should handle all domain
checks. On the command line, you will need to quote the address thus:
./ckaddr "ajsdfjstocknewsklsjldfa<@worldnet.att.net>"

The program will either echo back the address with no changes, or it
will print "BADADDR".

Program tested on NCR's MPRAS, SunOS, Solaris Intel, and Solaris Sparc.
Installed on my Sendmail V8, amongst *other* things.

Multiple @'s not allowed, Characters   :, $, %,  not allowed.

***************************************************************************
COPYRIGHT 1998 <Richard "Rick" Hernandez, NCR Corporation>
All rights reserved,

You have a right to use, modify, or distribute this software for any
non-commercial use provided that you keep this copyright notice and
this list of provisions with the software.

You are explicitly prohibited from using this software in any commercial
product without the consent of the author.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR, OR NCR CORPORATION, BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

rick@pobox.com
***************************************************************************
Configuration additions

Manually add to sendmail.cf in your check_mail ruleset or
add to Local_check_mail in m4 parlance.
***************************************************************************

Kckaddr program /etc/ckaddr

R$+<@$+>    $: $( ckaddr $1<@$2> $)
RBADADDR    $#error $:access denied see http://dontgiveadam

***************************************************************************
# The makefile
***************************************************************************

SHELL = /bin/sh

# SunOS
CFLAGS = -g -DBLOCKFILE=\"/etc/regblock.db\" -DSunOS
LIBS   =

# SVR4
#CFLAGS = -g -DBLOCKFILE=\"/etc/mail/regblock.db\"
#LIBS   = -lgen

addon:	addon.o
	$(CC) $(CFLAGS) -o addon addon.c $(LIBS)

***************************************************************************
# The source code
***************************************************************************

/* Currently checking only the name before the '<@' sign */

/*
** split address on "." and "@" and "%"
** if numbers in any of the split pieces print "BADADDR"
** else print address
** always return(0)
*/

#include <stdio.h>
#include <string.h>
#ifndef SunOS
#include <libgen.h>
extern char *__loc1;
#endif

void exit();
char buf[BUFSIZ];

int
regblocker(address)
char *address;
{
char *p, *q;
char retbuf[BUFSIZ];
FILE *fp;
	if ((fp = fopen(BLOCKFILE, "r")) != NULL) {
		while (fgets(retbuf, sizeof(retbuf), fp)) {
			if (p = strchr(retbuf, '\n')) *p = '\0';
#ifdef SunOS
			if ((re_comp(retbuf)) == NULL) {
				if (re_exec(retbuf)) return(1);
			}
#else
			if ((p = regcmp(retbuf, (char *)0)) != NULL) {
				q = regex(p, address, retbuf);
				free(p);
				if (q) return(1);
			}
#endif
		}
		fclose(fp);
	}
	return(0);
}


void
check(arg)
char *arg;
{
int i;

	if (regblocker(arg)) {
		(void) printf("BADADDR\n");
		exit(0);
	}
	for (i=0;arg[i] != '\0';i++) {
		if (arg[i] > 072 || arg[i] < 060) return;
	}
	(void) printf("BADADDR\n");
	exit(0);
}

int
main(argc,argv)
int argc;
char **argv;
{
int i,j;
char *atsign;
char sbuf[BUFSIZ];

	if (argc != 2) return(0);

	/* just return the address if longer than BUFSIZ */
	if (strlen(argv[1]) > BUFSIZ) {
		(void) printf("%s\n", argv[1]);
		return(0);
	}

	(void) strcpy(buf,argv[1]);

	if ( strchr(buf, '$') ) (void) printf("BADADDR\n");
	if ( strchr(buf, '%') ) (void) printf("BADADDR\n");

	/* check for more than one @ sign */
	atsign = strstr(buf, "@<@");
	if (atsign != NULL && *atsign != '\0') {
		(void) printf("BADADDR\n");
		exit(0);
	}
	/* before check, skip first character, @host.domain... is legal */
	atsign = strchr(buf+1, '@');
	if (atsign != NULL && *atsign != '\0') {
		atsign++;
		if (*atsign != '\0') {
			atsign = strchr(atsign, '@');
			if (atsign != NULL) {
				(void) printf("BADADDR\n");
				exit(0);
			}
		}
	}

	/* Check for single character .<@host.domain> */
	for (i=0; buf[i] != '<'; i++);
	if (i == 1) {
		(void) printf("BADADDR\n");
		exit(0);
	}

	/* Check for all numeric login */
	/* yes there is an easier way but future expansion may require this */
	for (i=0,j=0;buf[i] != '\0';i++) {
		switch(buf[i]) {
		case '<':
			if (j != 0) {
				sbuf[j] = '\0';
				check(sbuf);
				j = 0;
				(void) printf("%s\n", argv[1]);
				return(0);
			}
			break;
		default:
			sbuf[j] = buf[i];
			j++;
		}
	}
	sbuf[j] = '\0';
	check(sbuf);
	(void) printf("%s\n", argv[1]);

return(0);
}

--
"I'm paid to have opinions, This isn't one of them." Rick Hernandez
email:  rick@pobox.com  web:  http://www.pobox.com/~rick

