/*********************************************************** * Tune the slowmilter program * * $Id: slow.h,v 1.8 2003/12/15 15:03:33 bcx Exp bcx $ * * Copyright Bryan Costales 2003 * Placed into the pubic domain 2003 ***********************************************************/ # ifdef HAVE_CONFIG_H # include "config.h" # else Error: config.h required. # endif # if HAVE_CTYPE_H # include <ctype.h> # endif # if HAVE_ERRNO_H # include <errno.h> # endif # if HAVE_FCNTL_H # include <fcntl.h> # endif # ifdef sun # include <libgen.h> # endif # if HAVE_MEMORY_H # include <memory.h> # endif # if HAVE_STDIO_H # include <stdio.h> # endif # if HAVE_STDLIB_H # include <stdlib.h> # endif # if HAVE_STRING_H # include <string.h> # endif # if HAVE_SYS_SOCKET_H # include <sys/socket.h> # endif # if HAVE_SYS_STAT_H # include <sys/stat.h> # endif # if HAVE_SYS_TYPES_H # include <sys/types.h> # endif # if HAVE_SYSEXITS_H # include <sysexits.h> # endif # if HAVE_SYSLOG_H # include <syslog.h> # endif # if TM_IN_SYS_TIME # include <sys/time.h> # else # include <time.h> # endif # if TIME_WITH_SYS_TIME && TM_IN_SYS_TIME # include <time.h> # endif # if HAVE_UNISTD_H # include <unistd.h> # endif # if HAVE_NETDB_H # include <netdb.h> # endif # if HAVE_NETINET_IN_H # include <netinet/in.h> # endif # if HAVE_SYS_PARAM_H # include <sys/param.h> # endif # if HAVE_ARPA_INET_H # include <arpa/inet.h> # endif # if HAVE_ARPA_NAMESER_H # include <arpa/nameser.h> # endif # if HAVE_REGEX_H # include <regex.h> # endif # if HAVE_PTHREAD_H # include <pthread.h> # endif # include <resolv.h> # include <db.h> # include <libmilter/mfapi.h> # ifndef TRUE # define TRUE (1) # endif # ifndef FALSE # define FALSE (0) # endif # define bool int /******************************************************** ** Definitions used for MX lookups. */ # define MAXMXHOSTS 100 # ifndef HFIXEDSZ # define HFIXEDSZ 12 /* sizeof(HEADER) */ # endif typedef union { HEADER qb1; u_char qb2[PACKETSZ]; } QBUF; # ifndef INT16SZ # define INT16SZ 2 # endif # ifndef INT32SZ # define INT32SZ 4 # endif # ifndef MAXHOSTNAMELEN # define MAXHOSTNAMELEN 128 # endif # if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * # else # define RES_UNC_T u_char * # endif EXTERN char **MxHosts; EXTERN char *LocalHostName; EXTERN bool Verbose; /******************************************************** ** Definition of the Database keys and data. */ /* * This defines what is stored in the database. * Be sure to bump the version when you add new items * to the SECONDARY_DATUM below. */ # define DBVERSION 1 EXTERN time_t DBVersion; typedef unsigned long BITMAP; # define isbitset(bit, word) (((word) & (bit)) != 0) # define set_bit(bit, word) ((word) |= (bit)) # define DATABASE_VERSION (1) /* first datum is a flag */ /* * The primary database has binary IP numbers as keys. * IP==0 is special because its data is the version of the database. * The data is an array of dates in unix time_t format. */ typedef unsigned long PRIMARY_KEY; /* IPv4 IP number in numeric binary */ typedef time_t PRIMARY_DATUM; /* A unit of date/time in binary */ typedef PRIMARY_DATUM **PRIMARY_DATA; /* FIFO list of date/times */ /* * The secondary database has a combined key made up of an IP number * and a time_t date. That combined key documents a single event. * The data is a SECONDARY_DATUM structure (see below). */ typedef struct { PRIMARY_KEY ip; PRIMARY_DATUM date; } SECONDARY_KEY; # define MAX_MESSAGE_ID (256) typedef struct { BITMAP eventmap; /* See the BIT_ definitions below */ unsigned int envrcpts; /* excess envelope recipients */ unsigned int headrcpts; /* excess header recipients */ unsigned int honeyrcpts; /* total honey pot recipients */ unsigned int badrcpts; /* total bad recipients */ char msgid[MAX_MESSAGE_ID]; } SECONDARY_DATUM; /******************************************************** ** Should we log? And if so, how? */ EXTERN bool DoLog; EXTERN bool LogEvents; EXTERN char *LogPrefix; /******************************************************** ** Types of special dadabase records. Must not be zero ** nor greater than MAX_TYPE_RECORD. */ # define TYPE_RECORD_WHITELIST (1) /* whitelisted IP */ # define TYPE_RECORD_ALIAS (2) /* See actual IP */ # define MAX_TYPE_RECORD (255) /******************************************************** ** Debugging and regression testiong. */ EXTERN unsigned int Debugbits; # define isdebug(tok) isbitset(tok, Debugbits) # define anydebug() (Debugbits != 0) # define BUG_MX (0x00000001) /* debug bitmap */ # define BUG_DB (0x00000002) /* debug bitmap */ # define BUG_PUSHN (0x00000004) /* debug bitmap */ # define BUG_XXX (0x00000008) /* debug bitmap */ /* unused */ # define BUG_SOURCE (0x00000010) /* debug bitmap */ # define BUG_HEADERS (0x00000020) /* debug bitmap */ # define BUG_CONNECT (0x00000040) /* debug bitmap */ # define BUG_HELO (0x00000080) /* debug bitmap */ # define BUG_MAILFROM (0x00000100) /* debug bitmap */ # define BUG_RCPTTO (0x00000200) /* debug bitmap */ # define BUG_HEADER (0x00000400) /* debug bitmap */ # define BUG_EOM (0x00000800) /* debug bitmap */ # define BUG_EOH (0x00001000) /* debug bitmap */ # define BUG_CLOSE (0x00002000) /* debug bitmap */ # define BUG_ABORT (0x00004000) /* debug bitmap */ # define BUG_EDIT (0x00008000) /* debug bitmap */ # define BUG_ADD (0x00010000) /* debug bitmap */ # define BUG_RBL (0x00020000) /* debug bitmap */ # define BUG_DELETE (0x00040000) /* debug bitmap */ /******************************************************** ** The various modes of this program. */ # define MODE_RUN_AS_MILTER (0) # define MODE_DUMP_DATABASE (1) # define MODE_ADD_BY_HAND (2) # define MODE_GARBAGE_COLLECT (3) # define MODE_BOOTSTRAP (4) /******************************************************** ** Defaults that can be reset with -D when compiling. */ EXTERN char *ListenPort; # ifndef LISTENPORT # define LISTENPORT "inet:99@localhost" /* how to listen */ # endif EXTERN char *PrimaryDatabaseLoc; EXTERN DB *Dp1; /* The primary database */ # ifndef PRIMARYDBFILE # define PRIMARYDBFILE "/etc/mail/milter/slow/ip.db" # endif EXTERN char *SecondaryDatabaseLoc; EXTERN DB *Dp2; /* The secondary database */ # ifndef SECONDARYDBFILE # define SECONDARYDBFILE "/etc/mail/milter/slow/events.db" # endif # ifndef CFFILE # define CFFILE "/etc/mail/milter/slow/slow.conf" /* configuration file */ # endif /******************************************************** ** Defaults that can be overridden in the ** configuration file. */ EXTERN char *XTrackHeader; #define X_TRACK_HEADER NULL EXTERN bool LookBackOne; EXTERN bool AllowWhiteListIPs; EXTERN int MaxHeaderRcpts; # define MAX_HEADER_RCPTS (200) # define BIT_TOO_MANY_HDR_RCPTS (0x00000001) /* database bitmap */ EXTERN int MaxRcptsPerEnvelope; # define MAX_RCPTS_PER_ENV (200) # define BIT_TOO_MANY_ENV_RCPTS (0x00000002) /* database bitmap */ EXTERN char **HoneyHosts; EXTERN char *HoneyFile; # define BIT_GOT_HONEYPOT (0x00000004) /* database bitmap */ EXTERN bool CheckMessageId; # define BIT_BAD_MSG_ID (0x00000008) /* database bitmap */ EXTERN bool CheckFromHeader; # define BIT_BAD_FROM_HEAD (0x00000010) /* database bitmap */ EXTERN bool CheckSenderHost; # define BIT_BAD_HOST (0x00000020) /* database bitmap */ EXTERN char **RBLList; # define DEFAULT_RBL_LIST NULL # define BIT_RBL_BAD (0x00000040) /* database bitmap */ EXTERN bool MilterAbort; # define BIT_MILTER_ABORTED (0x00000080) /* database bitmap */ EXTERN bool AdvanceWrite; # define BIT_ADVANCEWRITE (0x00000100) /* database bitmap */ EXTERN bool CheckForged; # define BIT_FORGED (0x00000200) /* database bitmap */ # define BIT_FROMMX (0x00000400) /* database bitmap */ # define BIT_NOTINET (0x00000800) /* database bitmap */ /******************************************************** ** Global variables set by main() and read-only by ** all the threads. */ EXTERN char *Prog; /* Basename of the milter invocation */ /******************************************************** ** Pattern for the context specific data */ typedef struct priv { PRIMARY_DATUM ip; /* IPv4 number in binary */ char *iptxt; /* IPv4 number in human readable text */ BITMAP bits; /* Bit map of binary events */ int envrcpts; /* Number good recipients */ int badrcpts; /* Number bad recipients */ int honeyrcpts; /* Number honeypot recipients */ int nhdrrcpts; /* Number of header recipients */ char **hdrrcpts; /* List of header recipients */ char *midstr; /* Found a Message-ID header */ } PRIV; /********************************************* ** Misc. sizes and limits. */ # define MAX_FAILS_M (5) /* how many times should malloc() fail? */ /* ** Information used by the "slowedit find" command. */ # define SLOWLOGICNONE 0 # define SLOWLOGICEQUAL 1 # define SLOWLOGICGREATER 2 # define SLOWLOGICLESSTHAN 3 # define SLOWBLOGICAND 0 # define SLOWBLOGICOR 1 typedef struct { int relation; int value; } LOGICITEM; typedef struct { # define SLOWSETBITS (0) /* set by foo=set */ # define SLOWONLYBITS (1) /* set by foo=only */ # define SLOWCLEARBITS (2) /* set by foo=clear */ BITMAP bits[4]; int andor; /* logical AND or OR of the above */ LOGICITEM envrcpts; LOGICITEM hdrrcpts; LOGICITEM honeyrcpts; LOGICITEM bad; # if HAVE_REGEX_H && HAVE_REGCOMP regex_t *reg; # else char *reg; # endif } LOGICSTRUCT; /********************************************* ** Function prototypes */ /* in main.c */ sfsistat push_to_db(SMFICTX *, PRIV *, int); /* in readconf.c */ void setdefaults(void); /* in readconf.c */ void readconf(char *, char *); /* in readconf.c */ /* in util.c */ void milterr(char *, char *, int, int, int, char *, char *); char **push_list(char *, char **, int); char **free_list(char **); char **mkargv(char *, int, int); void print_list(char *, char **, FILE *); bool is_in_list(char *, char **); void read_honey(void); void set_debug(char *); char *cleanup(char *string); void *try_alloc(char *, int, size_t, int); void *try_strdup(char *, int, char *, int); void *try_realloc(char *, int, void *, size_t, int); unsigned long revbytes(unsigned long); time_t parse_date(char *); /* in database.c */ void init_database_mutex(void); DB *open_database(char *, int); void close_database(DB *); int put_ip_database(DB *, PRIMARY_KEY, PRIMARY_DATUM, bool, int); int del_ip_database(DB *, DB *, PRIMARY_KEY, time_t, int); int get_db_version(DB *, int); PRIMARY_DATUM *get_ip_database(DB *, PRIMARY_KEY, int *, int); int put_event_database(DB *, SECONDARY_KEY *, SECONDARY_DATUM *); int del_event_database(DB *, SECONDARY_KEY *); SECONDARY_DATUM *get_event_database(DB *, SECONDARY_KEY *, bool); int dump_database(DB *, DB *, FILE *); char *event_to_str(char *, time_t, SECONDARY_DATUM *, int); /* in mx.c */ char **getmx(char *, char **); int rbl_lookup(char *, char *, int); /* in header.c */ char **header_recipient(char **, char *); char *deRFC822(char *); PRIMARY_KEY header_received(char *); bool header_messageid(char *); /* regression testing in test.c */ void test_init(int); void test_connect(char *); void test_helo(char *); void test_mailfrom(char *); void test_rcptto(char *); void test_header(char *); void test_eoh(char *); void test_eom(char *); void test_close(char *); void test_abort(char *); void test_db(char *); void test_add(char *); void test_delete(char *); void test_rbl(char *); /* in edit.c */ bool slowedit(int, int, char **); bool slowadd(char *,int, int, char **); bool slowlist(char *,int, int, char **); bool slowfind(char *,int, int, char **); bool slowdelete(char *,int, int, char **); bool slowalias(char *,int, int, char **); bool slowwhite(char *,int, int, char **); bool slowtrim(char *,int, int, char **); bool is_envent(char *); bool slowsetpriv(char *,char *); LOGICSTRUCT *slowlogicparse(char *); void show_events(char *); /* in compat.c */ # ifndef HAVE_BASENAME char *basename(char *); # endif # ifndef HAVE_CUSERID char *cuserid(char *); # endif # ifndef HAVE_MEMSET # define memset(a,b,c) bzero(a,c) # endif # ifndef HAVE_MEMCPY # define memcpy(a,b,c) bcopy(b,a,c) # endif # ifndef HAVE_STRERROR char *strerror(int); # endif # ifndef HAVE_STRCHR char *strchr(char *, int); # endif # ifndef HAVE_STRRCHR char *strrchr(char *, int); # endif
# | 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. |