/************************************************************ ** $Id: readconf.c,v 0.8 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. ** ** Entry points defined in this file: ** ** setdefaults(): ** Set the defaults for all global variables. ** readconf(): ** Opens, reads, and closes the configuration file. *************************************************************/ # define EXTERN # include "slow.h" void setdefaults(void) { /* * Global variables, not resetable by the config file. */ LogPrefix = ""; /* * Global variables, can be reset by the config file. */ ListenPort = LISTENPORT; PrimaryDatabaseLoc = PRIMARYDBFILE; SecondaryDatabaseLoc = SECONDARYDBFILE; MaxHeaderRcpts = MAX_HEADER_RCPTS; MaxRcptsPerEnvelope = MAX_RCPTS_PER_ENV; CheckMessageId = TRUE; CheckFromHeader = TRUE; CheckSenderHost = FALSE; LookBackOne = FALSE; AllowWhiteListIPs = TRUE; RBLList = DEFAULT_RBL_LIST; MilterAbort = TRUE; AdvanceWrite = TRUE; CheckForged = TRUE; HoneyFile = NULL; HoneyHosts = NULL; MxHosts = NULL; LocalHostName = NULL; XTrackHeader = X_TRACK_HEADER; DoLog = TRUE; LogEvents = TRUE; AddIPAliases = FALSE; RunAsUser = NULL; RunAsGroup = NULL; } typedef struct { char *token; /* the config file keyword */ int index; /* for switch() statement */ bool set; /* already set from config file if TRUE */ } CFLINES; CFLINES Cflines[] = { # define I_PSOC 1 {"ListenPort", I_PSOC, 0 }, # define I_PRIDBFILE 2 {"PrimaryDatabaseLoc", I_PRIDBFILE, 0 }, # define I_SECDBFILE 3 {"SecondaryDatabaseLoc", I_SECDBFILE, 0 }, # define I_MAXRPERHDR 4 {"MaxHeaderRcpts", I_MAXRPERHDR, 0 }, # define I_MAXRPERE 5 {"MaxRcptsPerEnvelope", I_MAXRPERE, 0 }, # define I_CHK_MID 6 {"CheckMessageId", I_CHK_MID, 0 }, # define I_CHKFROMHDR 7 {"CheckFromHeader", I_CHKFROMHDR, 0 }, # define I_CHKSENDHOST 8 {"CheckSenderHost", I_CHKSENDHOST, 0 }, # define I_ALLOWWHITE 9 {"AllowWhiteListIPs", I_ALLOWWHITE, 0 }, # define I_LOOKBACK 10 {"LookBackOne", I_LOOKBACK, 0 }, # define I_MILABORT 11 {"MilterAbort", I_MILABORT, 0 }, # define I_ADVWRITE 12 {"AdvanceWrite", I_ADVWRITE, 0 }, # define I_FORGED 13 {"CheckForged", I_FORGED, 0 }, # define I_HONEY 14 {"HoneyFile", I_HONEY, 0 }, # define I_MYNAME 15 {"LocalHostName", I_MYNAME, 0 }, # define I_XHEADER 16 {"XTrackHeader", I_XHEADER, 0 }, # define I_DOLOG 17 {"DoLog", I_DOLOG, 0 }, # define I_LOGEVENTS 18 {"LogEvents", I_LOGEVENTS, 0 }, # define I_RBLLIST 19 {"RBLList", I_RBLLIST, 0 }, # define I_ADDMX 20 {"AddMXhosts", I_ADDMX, 0 }, # define I_ADDIPALIAS 21 {"AddIPAliases", I_ADDIPALIAS, 0 }, # define I_RUNASUSER 22 {"RunAsUser", I_RUNASUSER, 0 }, # define I_RUNASGROUP 23 {"RunAsGroup", I_RUNASGROUP, 0 }, { NULL, 0, 0 }, }; static bool truefalse(char *tf) { if (tf == NULL) return TRUE; switch((int)*tf) { case 'Y': case 'y': case 'T': case 't': return TRUE; break; } return FALSE; } void readconf(char *prog, char *cffile) { FILE *fp; char buf[BUFSIZ]; CFLINES *cl; char **t, **p; int line = 0; extern int errno; fp = fopen(cffile, "r"); if (fp == NULL) milterr(Prog, __FILE__, __LINE__, FALSE, errno, "Open config file", cffile); /* Use file(line) to show errors in the config file */ set_bit(BUG_SOURCE, Debugbits); while (fgets(buf, BUFSIZ, fp) != NULL) { char *cp, *ep, *xp; int ch; ++line; cp = strrchr(buf, '\n'); if (cp != NULL) *cp = '\0'; for (cp = buf; *cp != '\0'; ++cp) { if (! isspace((int)*cp)) break; } if (*cp == '\0' || *cp == '#') continue; /* empty line */ for (ep = cp; *ep != '\0'; ++ep) { if (isspace((int)*ep) || *ep == '=') break; } if (*ep == '\0') milterr(Prog, cffile, line, FALSE, EINVAL, "Missing \"=\" from", buf); ch = *ep; *ep = '\0'; for (cl = Cflines; cl->token != NULL; ++cl) { if (strcasecmp(cl->token, cp) == 0) break; } *ep = ch; if (cl->token == NULL) milterr(Prog, cffile, line, FALSE, EINVAL, "Unrecognized token", cp); if ((cl->set)++ != 0) milterr(Prog, cffile, line, FALSE, EINVAL, "Repeated definition", buf); cp = strchr(buf, '='); if (cp == NULL) milterr(Prog, cffile, line, FALSE, EINVAL, "Missing \"=\" from", buf); for (++cp; *cp != '\0'; ++cp) { if (! isspace((int)*cp)) break; } if (*cp == '\0') milterr(Prog, cffile, line, FALSE, EINVAL, "Nothing after \"=\" in", buf); switch(cl->index) { /* * Should be in the form inet:port@host */ case I_PSOC: ListenPort = try_strdup(__FILE__, __LINE__, cp, FALSE); if (ListenPort == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", cp); if (strncasecmp(ListenPort, "inet:", 5) != 0) milterr(Prog, cffile, line, FALSE, EINVAL, cp, "Must start with \"inet:\""); break; /* * For security these should be full path names. * Should we enforce that? */ case I_PRIDBFILE: PrimaryDatabaseLoc = try_strdup(__FILE__, __LINE__, cp, FALSE); if (PrimaryDatabaseLoc == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; case I_SECDBFILE: SecondaryDatabaseLoc = try_strdup(__FILE__, __LINE__, cp, FALSE); if (SecondaryDatabaseLoc == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; case I_MAXRPERHDR: MaxHeaderRcpts = atoi(cp); if (MaxHeaderRcpts <= 0) milterr(Prog, cffile, line, FALSE, EINVAL, "Must be positive", buf); break; case I_MAXRPERE: MaxRcptsPerEnvelope = atoi(cp); if (MaxRcptsPerEnvelope <= 0) milterr(Prog, cffile, line, FALSE, EINVAL, "Must be positive", buf); break; case I_CHK_MID: CheckMessageId = truefalse(cp); break; case I_CHKFROMHDR: CheckFromHeader = truefalse(cp); break; case I_CHKSENDHOST: # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME CheckSenderHost = truefalse(cp); # else fprintf(stderr, "CheckSenderHost requires getipnodebyname(). Upgrade your OS.\n"); # endif break; case I_LOOKBACK: LookBackOne = truefalse(cp); break; case I_ALLOWWHITE: AllowWhiteListIPs = truefalse(cp); break; case I_MILABORT: MilterAbort = truefalse(cp); break; case I_ADVWRITE: AdvanceWrite = truefalse(cp); break; case I_FORGED: CheckForged = truefalse(cp); break; /* * The list of honeypot addresses. */ case I_HONEY: HoneyFile = try_strdup(__FILE__, __LINE__, cp, FALSE); if (HoneyFile == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; case I_MYNAME: LocalHostName = try_strdup(__FILE__, __LINE__, cp, FALSE); if (LocalHostName == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; case I_XHEADER: XTrackHeader = try_strdup(__FILE__, __LINE__, cp, FALSE); if (XTrackHeader == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); if (strchr(XTrackHeader, ':') != NULL) milterr(Prog, cffile, line, FALSE, EINVAL, "Must not contain a colon", cp); break; case I_DOLOG: DoLog = truefalse(cp); break; case I_LOGEVENTS: LogEvents = truefalse(cp); break; case I_ADDIPALIAS: # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME AddIPAliases = truefalse(cp); # else fprintf(stderr, "AddIPAliases requires getipnodebyaddr(). Upgrade your OS.\n"); # endif break; case I_RBLLIST: RBLList = mkargv(cp, ',', FALSE); if (RBLList == NULL) milterr(Prog, cffile, line, FALSE, EINVAL, "Could not parse", cp); xp = try_strdup(__FILE__, __LINE__, "127.0.0.2", FALSE); for (p = RBLList; *p != NULL; ++p) { if (rbl_lookup(*p, xp, FALSE) == 0) continue; (void) printf("Warning: lookup of %s at %s should have failed, but did not.\n", xp, *p); } (void) free(xp); break; case I_ADDMX: t = mkargv(cp, ',', FALSE); if (t == NULL) milterr(Prog, cffile, line, FALSE, EINVAL, "Could not parse", cp); for (p = t; *p != NULL; ++p) { MxHosts = push_list(*p, MxHosts, FALSE); } break; case I_RUNASUSER: RunAsUser = try_strdup(__FILE__, __LINE__, cp, FALSE); if (RunAsUser == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; case I_RUNASGROUP: RunAsGroup = try_strdup(__FILE__, __LINE__, cp, FALSE); if (RunAsGroup == NULL) milterr(Prog, cffile, line, FALSE, errno, "Memory allocation", buf); break; } } if (ferror(fp)) milterr(Prog, __FILE__, __LINE__, FALSE, errno, "Read config file", cffile); (void) fclose(fp); Debugbits ^= BUG_SOURCE; return; }
# | 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. |