test.c #7

  • //
  • guest/
  • bryan_costales/
  • test.c
  • View
  • Commits
  • Open Download .zip Download (9 KB)
/************************************************************
** $Id: test.c,v 0.7 2003/12/29 16:45:38 bcx Exp bcx $
**
** Copyright Bryan Costales and Perforce Software, Inc. 2003
**
** This code is "open source" as defined by version 1.9 of
** the Open Source Definition from:
**
**	http://www.opensource.org/docs/definition.php.
**
** Tests run in this file can only be done before
** any threads are launched (i.e. from the main() routine).
** See the scripts in the tests directory for more details.
**
*************************************************************/
# define EXTERN extern
# include "slow.h"

/*
 * The following needed to be copied from milter.h in the
 * sendmail source for the routines in this file to work.
 */
# ifdef SMFIR_QUARANTINE 
#	define MAX_MACROS_ENTRIES 5
# else
#	define MAX_MACROS_ENTRIES 4
# endif
PRIV *Priv = NULL;
struct smfi_str
{
        unsigned int    ctx_id;         /* thread id */
        unsigned int    ctx_sd;         /* socket descriptor */
        int             ctx_dbg;        /* debug level */
        time_t          ctx_timeout;    /* timeout */
        int             ctx_state;      /* state */
        smfiDesc_ptr    ctx_smfi;       /* filter description */
        unsigned long   ctx_pflags;     /* protocol flags */
        char            **ctx_mac_ptr[MAX_MACROS_ENTRIES];
        char            *ctx_mac_buf[MAX_MACROS_ENTRIES];
        char            *ctx_reply;     /* reply code */
        void            *ctx_privdata;  /* private data */
} Ctx;

void
test_init(int setpriv)
{
	(void) memset(&Ctx, '\0', sizeof(Ctx));
	Ctx.ctx_id = 1;
	if (setpriv == TRUE)
	{
		Priv = malloc(sizeof(PRIV));
		(void) memset(Priv, '\0', sizeof(PRIV));
		Ctx.ctx_privdata = Priv;
	}
}

static void
buf_now(char *buf)
{
	time_t date;
	struct tm *t;

	test_init(TRUE);

	date = BUG_NOW;
	t = localtime(&date);
	(void) sprintf(buf, "%02d/%02d/%d.%02d:%02d:%02d",
		t->tm_mon + 1, t->tm_mday, t->tm_year + 1900,
		t->tm_hour, t->tm_min, t->tm_sec);
	return;
}

/*
** These various test routines all get a string for testing. 
** These are all passed using the -X command-line switch.
** Multilple arguments must be separated by commas, e.g. -X"a,b"
** All exit() after the individual test.
*/
void
test_connect(char *string)
{
	union {
		_SOCK_ADDR in;
		struct sockaddr_in sin;
	} n;
	unsigned long ip;
	char *host;
	char **argv;
	char buf[BUFSIZ];
	extern sfsistat xxfi_connect(SMFICTX *, char *, _SOCK_ADDR *);

	if (string == NULL)
	{
		(void) printf("Usage: -Dconnect -X \"hostname,ipaddr\"\n");
		exit(0);
	}

	CheckForged = FALSE;
	argv = mkargv(string, ',', FALSE);
	if (argv[0] == NULL || argv[1] == NULL)
	{
		(void) printf("Usage: -Dconnect -X \"hostname,ipaddr\"\n");
		exit(0);
	}

	if (((int)(ip = inet_network(argv[1]))) == -1)
	{
		(void) fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
		exit(0);
	}
	ip = revbytes(ip);
	test_init(FALSE);
	LookBackOne = TRUE;
	/*
	 * First test with no macros defined and no AF_INET.
	 * Should get flags=[NET]
	 */
	n.in.sa_family = 0;
	(void) memcpy( &n.sin.sin_addr, &ip, sizeof(PRIMARY_DATUM));
	host = strdup(argv[0]);
	(void) xxfi_connect(&Ctx, host, &n.in);

	/*
	 * Second test with no macros defined and AF_INET defined.
	 * Should get empty flags=
	 */
	n.in.sa_family = AF_INET;
	(void) memcpy( &n.sin.sin_addr, &ip, sizeof(PRIMARY_DATUM));
	host = strdup(argv[0]);
	(void) xxfi_connect(&Ctx, host, &n.in);

	/*
	 * Then test the ${client_resolve} macro.
	 * Should get flags=[FOR]
	 */
	(void) sprintf(buf, "{client_resolve}, forged");
	Ctx.ctx_mac_ptr[0] = mkargv(buf, ',', FALSE);
	Ctx.ctx_mac_buf[0] = buf;
	n.in.sa_family = AF_INET;
	(void) memcpy( &n.sin.sin_addr, &ip, sizeof(PRIMARY_DATUM));
	host = strdup(argv[0]);
	CheckForged = TRUE;
	(void) xxfi_connect(&Ctx, host, &n.in);
	Ctx.ctx_mac_ptr[0] = NULL;
	Ctx.ctx_mac_buf[0] = NULL;
	CheckForged = FALSE;

	/*
	 * Add the hostname to the list of MX hosts and
	 * try again.
	 * Should get <nil> for IP number, and flags=[MMX]
	 */
	MxHosts = push_list(argv[0], MxHosts, FALSE);
	n.in.sa_family = AF_INET;
	(void) memcpy( &n.sin.sin_addr, &ip, sizeof(PRIMARY_DATUM));
	host = strdup(argv[0]);
	(void) xxfi_connect(&Ctx, host, &n.in);

	exit(0);
}

void
test_helo(char *string)
{
	char buf[BUFSIZ];
	extern sfsistat xxfi_helo(SMFICTX *, char *);

	test_init(TRUE);

	/*
	 * Test the ${illegalpipe} macro.
	 * Should get flags=[PIP]
	 */
	AdvanceWrite = TRUE;
	(void) sprintf(buf, "{illegalpipe}, true");
	Ctx.ctx_mac_ptr[0] = mkargv(buf, ',', FALSE);
	Ctx.ctx_mac_buf[0] = buf;
	(void) xxfi_helo( &Ctx, string);
	Ctx.ctx_mac_ptr[0] = NULL;
	Ctx.ctx_mac_buf[0] = NULL;

	exit(0);
}

void
test_mailfrom(char *string)
{
	char **argv;
	extern sfsistat xxfi_envfrom(SMFICTX *, char **);

	if (string == NULL)
	{
		(void) printf("Usage: -Dmailfrom -X \"sender@domain\"\n");
		exit(0);
	}
	test_init(TRUE);
	CheckSenderHost = TRUE;

	/*
	 * Test the envelope recipient's host.
	 * Should get flags=[FRM] for a bad host name.
	 */
	argv = mkargv(string, ',', FALSE);
	(void) xxfi_envfrom( &Ctx, argv);
	exit(0);
}

void
test_rcptto(char *string)
{
	char **argv;
	char *addr;
	extern sfsistat xxfi_envto(SMFICTX *, char **);

	if (string == NULL)
	{
		(void) printf("Usage: -Drcptto -X \"recipient@domain\"\n");
		exit(0);
	}
	test_init(TRUE);
	CheckFromHeader = TRUE;

	/*
	 * Should get flags=[HON] for a honey addr
	 */
	addr = strdup("bob@x.y.z.0.1.2.com");
	HoneyHosts = mkargv(addr, ',', FALSE);
	(void) xxfi_envto(&Ctx, HoneyHosts);

	/*
	 * Test the envelope recipient's host.
	 * Three times to get the count to 3.
	 */
	argv = mkargv(string, ',', FALSE);
	(void) xxfi_envto(&Ctx, argv);
	(void) xxfi_envto(&Ctx, argv);
	(void) xxfi_envto(&Ctx, argv);
	exit(0);
}

/*
 * Note that the .foo domain prevents these names from
 * being found in the actual MX list.
 */
static char *Received = "from spamhost.foo (bay2-f58.bay2.somehost.gov [65.54.247.58])\n\tby ourmx.foo (8.13.1/8.13.1) with ESMTP id h9VJ49rM005383\n\tfor <user@ourhost.foo>; Fri, 31 Oct 2003 11:04:09 -0800 (PST)";

void
test_header(char *string)
{
	char *addr;
	char *received;
	extern sfsistat xxfi_header(SMFICTX *, char *, char *);

	/* string is ignored */

	test_init(TRUE);

	/*
	 * Does it recognize the XTrackHeader?
	 */
	XTrackHeader = strdup("X-test-x-track");
	(void) xxfi_header(&Ctx, XTrackHeader, "testing");

	/*
	 * A Received: header not from one of our 
	 * MX servers, then one from one of our MX servers.
	 */
	LookBackOne = TRUE;
	Priv->ip = 0;
	received = strdup(Received);
	(void) xxfi_header(&Ctx, "Received", received);
	addr = strdup("ourmx.foo");
	MxHosts = push_list(addr, MxHosts, FALSE);
	received = strdup(Received);
	(void) xxfi_header(&Ctx, "Received", received);

	/*
	 * A dozen vairations on recipient headers.
	 */
	addr = strdup("(John Doe) doe@ourhost.gov");
	(void) xxfi_header(&Ctx, "Cc", addr);
	addr = strdup("\"John Doe\" <doe@ourhost.gov>");
	(void) xxfi_header(&Ctx, "Cc", addr);
	addr = strdup("doe");
	(void) xxfi_header(&Ctx, "Bcc", addr);
	addr = strdup("doe@ourhost.gov (John Doe)");
	(void) xxfi_header(&Ctx, "Cc", addr);
	addr = strdup("<<<doe@ourhost.gov>>>");
	(void) xxfi_header(&Ctx, "Bcc", addr);
	addr = strdup("andy@ourhost.gov, <bob@ourhost.gov>, (Carl) carl@ourhost.gov");
	(void) xxfi_header(&Ctx, "To", addr);

	/*
	 * Next check the Message-ID header.
	 */
	addr = strdup("<a@b>");
	(void) xxfi_header(&Ctx, "Message-Id", addr);
	addr = strdup("<ab>");
	(void) xxfi_header(&Ctx, "Message-Id", addr);
	addr = strdup("<@b>");
	(void) xxfi_header(&Ctx, "Message-Id", addr);
	addr = strdup("<a@>");
	(void) xxfi_header(&Ctx, "Message-Id", addr);
	addr = strdup("a@b");
	(void) xxfi_header(&Ctx, "Message-Id", addr);

	/*
	 * Lastly check the From: header.
	 */
	CheckFromHeader = TRUE;
	addr = strdup("a");
	(void) xxfi_header(&Ctx, "From", addr);
	addr = strdup("a@");
	(void) xxfi_header(&Ctx, "From", addr);
	addr = strdup("a@host.foo");
	(void) xxfi_header(&Ctx, "From", addr);

	exit(0);
}


void
test_eoh(char *string)
{
	extern sfsistat xxfi_eoh(SMFICTX *);

	/* string is ignored */

	test_init(TRUE);

	CheckMessageId = TRUE;
	Priv->midstr = NULL;
	Priv->nhdrrcpts = 6;
	(void) xxfi_eoh(&Ctx);
	exit(0);
}

void
test_close(char *string)
{
	extern sfsistat xxfi_close(SMFICTX *);

	/* string is ignored */

	test_init(TRUE);
	(void) xxfi_close(&Ctx);
	(void) printf("close: priv = %x\n", (int)Ctx.ctx_privdata);
	exit(0);
}

void
test_abort(char *string)
{
	extern sfsistat xxfi_abort(SMFICTX *);

	/* string is ignored */

	test_init(TRUE);
	MilterAbort = TRUE;
	(void) smfi_setpriv(&Ctx, Priv);
	(void) xxfi_abort(&Ctx);
	(void) printf("abort: flags=%s\n",
		isbitset(BIT_MILTER_ABORTED, Priv->bits)?"[ABO]":"");     
	exit(0);
}

void
test_eom(char *string)
{
	char buf[BUFSIZ];
	extern sfsistat xxfi_eom(SMFICTX *);

	/* string is ignored */

	test_init(TRUE);
	(void) sprintf(buf, "{nbadrcpts}, 6");
	Ctx.ctx_mac_ptr[0] = mkargv(buf, ',', FALSE);
	Ctx.ctx_mac_buf[0] = buf;
	(void) xxfi_eom(&Ctx);
	(void) printf("eom: badrcpts=%d\n", Priv->badrcpts);

	exit(0);
}


void
test_now(char *str)
{
	char buf[BUFSIZ];

	buf_now(buf);
	printf("%s\n", buf);
	exit (0);
}
# Change User Description Committed
#7 4222 bryan_costales Massive rewrite to speed up the database writes.
Using a single database now with duplicate keys
where the keys are the IP numbers. Added a purge
command and removed the garbage command. Fixed
some leaking memory bugs and properly closed the
database in a few places were it was not
properly closed. Updated the docs to reflect
this and bumped both the database version and
release number. Running on a FreeBSD 3.x machine
and a Solaris 9 machine.
#6 4052 bryan_costales Implimented:
    whitelisting
    AddMXHost for MX servers that lie
    Converted to thread safe DNS routines
    garbage collection
    RunAsUser and RunAsGroup for root startups
    rebuild the database
    summarize by IP number
Finished all documentation.
Moved release from alpha to beta
#5 4030 bryan_costales Finished documenting the configuration file
Fixed a race condition and a core dump bug.
Added hooks for whitelisting and IP aliasing
Added support for Berkeley DB 4.2
Converted to htonl() and ntohl()

Known Bugs:
    ip.db cannot be shared over NFS
    IP tracking from MX hosts can fail
    A RunAsUser config option is needed.
#4 3998 bryan_costales Brought the whole distribution up to V0.9
Added a huge abount of documentation.
Added slowedit find
Created startup scripts to launch for testing
Fixed numerous bugs.
Fixed a few portablity issues.
Installed hooks for whitelisting and IP aliases.
#3 3957 bryan_costales Added rbl lookup support and testing for same.
Folded in support for smfi_stop().
Added lots of slowedit commands
Fixed a serious bug in MX lookups.
Added to documentation.
#2 3890 bryan_costales This is the 0.6 release. The following have been
added with the uses indicated:

    Source files: edit.c -- the slowedit functions
              compat.c -- missing system files
    Autoconf:     configure.ac, makefile.am config.h
              aclocal.m4 acinclude.m4 build/
    Documents:    doc/ -- html and man(1) documents
    Testing:      tests/ -- regressive testing
    TODO:          -- revised to show actual progress
#1 3838 bryan_costales This is pre-release 0.5 (rcs numbering) which includes:
    The milter source files and Makefile
    A regressive testing subdirectory with Makefile and /bin/sh scripts.
    A patches subdirectory with a patch file for V8.13 sendmail
All have been compiled and tested on a 64bit Sun Solaris 9 machine.