# include <stdio.h> # include <stdlib.h> # include <strings.h> # include <ctype.h> # include <errno.h> # include <syslog.h> # define EXTERN extern # include "slow.h" void milterr(char *prog, char *file, int line, int log, int err, char *what, char *why) { if (isdebug(BUG_SOURCE)) { # if HAVE_SYSLOG && HAVE_SYSLOG_H if (DoLog == TRUE && log == TRUE) (void)syslog(LOG_INFO, "%s: %s(line %d): %s: %s: %s", prog==NULL?"milter":prog, file==NULL?"":file, line, what==NULL?"":what, why==NULL?"":why, err==0?"Warning":strerror(err)); else # else if (log == FALSE) # endif (void)fprintf(stderr, "%s: %s(line %d): %s: %s: %s\n", prog==NULL?"milter":prog, file==NULL?"":file, line, what==NULL?"":what, why==NULL?"":why, err==0?"Warning":strerror(err)); } else { # if HAVE_SYSLOG && HAVE_SYSLOG_H if (DoLog == TRUE && log == TRUE) (void)syslog(LOG_INFO, "%s: %s: %s: %s", prog==NULL?"milter":prog, what==NULL?"":what, why==NULL?"":why, err==0?"Warning":strerror(err)); else # else if (log == FALSE) # endif (void)fprintf(stderr, "%s: %s: %s: %s\n", prog==NULL?"milter":prog, what==NULL?"":what, why==NULL?"":why, err==0?"Warning":strerror(err)); } if (log == TRUE) /* running multi-threaded */ (void) smfi_stop(); else exit(err); } void print_list(char *title, char **list, FILE *fp) { char **l; if (list == NULL || fp == NULL) return; for (l = list; *l != NULL; ++l) (void) fprintf(fp, "%s: %s\n", title==NULL?"<nil>":title, *l); return; } char ** free_list(char **list) { char **l; if (list == NULL) return NULL; for (l = list; *l != NULL; ++l) (void) free(*l); (void) free(list); return NULL; } char ** push_list(char *name, char **list, int log) { char **l; int num; if (name == NULL) return list; if (isdebug(BUG_PUSHN)) { (void) printf("push_list(%s):\n", name); } if (list == NULL) { list = try_alloc(__FILE__, __LINE__, sizeof(char *) * 2, log); if (list == NULL) return NULL; list[0] = try_strdup(__FILE__, __LINE__, name, log); if (list[0] == NULL) return NULL; list[1] = NULL; if (isdebug(BUG_PUSHN)) { (void) printf(" added\t%s\n", list[0]); (void) printf("\tNULL\n"); } return list; } num = 0; for (l = list; *l != NULL; ++l) { if (isdebug(BUG_PUSHN)) { (void) printf("\t%s\n", *l); } ++num; } list = try_realloc(__FILE__, __LINE__, list, sizeof(char *) * (num + 2), log); if (list == NULL) return NULL; list[num] = try_strdup(__FILE__, __LINE__, name, log); if (list[num] == NULL) return NULL; list[++num] = NULL; if (isdebug(BUG_PUSHN)) { (void) printf(" added\t%s\n", list[num-1]); (void) printf("\tNULL\n"); } return list; } /* * Only run before going multi-threaded. */ void read_honey(void) { FILE *fp; char buf[BUFSIZ]; char *cp; int nhosts; if (HoneyHosts != NULL) { milterr(Prog, __FILE__, __LINE__, FALSE, 0, HoneyFile, "Already initialized"); } fp = fopen(HoneyFile, "r"); if (fp == NULL) { milterr(Prog, __FILE__, __LINE__, FALSE, errno, "Open to read", HoneyFile); } nhosts = 0; while (fgets(buf, BUFSIZ, fp) != NULL) { if (*buf == '#' || *buf == '\n') continue; if ((cp = strchr(buf, '\n')) != NULL) *cp = '\0'; HoneyHosts = push_list(buf, HoneyHosts, FALSE); } if (ferror(fp)) { milterr(Prog, __FILE__, __LINE__, FALSE, errno, "While reading", HoneyFile); } (void) fclose(fp); return; } bool is_in_list(char *what, char **list) { char **h; int len; if (what == NULL || list == NULL) return FALSE; if ((len = strlen(what)) == 0) return FALSE; for (h = list; *h != NULL; ++h) { if (strncasecmp(what, *h, len) == 0) return TRUE; } return FALSE; } typedef struct debugcat { char *name; unsigned int bit; } DEBUGCAT; static DEBUGCAT Debugcats[] = { {"mx", BUG_MX}, {"db", BUG_DB}, {"push_list", BUG_PUSHN}, {"source", BUG_SOURCE}, {"connect", BUG_CONNECT}, {"helo", BUG_HELO}, {"mailfrom", BUG_MAILFROM}, {"rcptto", BUG_RCPTTO}, {"header", BUG_HEADER}, {"eoh", BUG_EOH}, {"eom", BUG_EOM}, {"close", BUG_CLOSE}, {"abort", BUG_ABORT}, {"edit", BUG_EDIT}, {"add", BUG_ADD}, {"rbl", BUG_RBL}, {"delete", BUG_DELETE}, {NULL, 0}, }; void set_debug(char *catagory) { DEBUGCAT *d; int len; if (catagory == NULL) return; if ((len = strlen(catagory)) == 0) return; for (d = Debugcats; d->name != NULL; ++d) { if (strncasecmp(catagory, d->name, len) == 0) { set_bit(d->bit, Debugbits); return; } } (void) fprintf(stderr, "-D%s: unknown debugging catagory\n", catagory); /* * No threads are running at this time so we * can just exit. */ exit (EINVAL); return; } char ** mkargv(char *string, int delim, int log) { char **argv; char *cp, *sp; int save; if (string == NULL) return NULL; argv = NULL; if (delim == 0) { return (push_list(cleanup(string), argv, log)); } for (cp = string; *cp != '\0'; ++cp) { if (delim == ' ') sp = strpbrk(cp, " \t\r\n"); else sp = strchr(cp, delim); if (sp != NULL) { save = *sp; *sp = '\0'; argv = push_list(cleanup(cp), argv, log); *sp = save; cp = sp; continue; } return (push_list(cleanup(cp), argv, log)); } return argv; } char * cleanup(char *string) { char *cp, *ep; for (cp = string; ;++cp) { if (! isspace((int)*cp)) break; } for (ep = cp + strlen(cp) -1; ; --ep) { if (!isspace((int)*ep)) break; } if (ep <= cp) return cp; *(ep +1) = '\0'; return cp; } /* ** Bullet proof (or let's say more resilient) ** memory allocation routines. */ void * try_alloc(char *file, int line, size_t bytes, int log) { void *r = NULL; int cnt = 0; if (bytes <= 0) bytes = 1; while (r == NULL) { if ((r = malloc(bytes)) != NULL) break; (void)sleep(++cnt); if (cnt >= MAX_FAILS_M) { milterr(Prog, file, line, log, errno, "ABORTED", "Allocate memory"); return NULL; } } return r; } void * try_strdup(char *file, int line, char *string, int log) { void *r; if (string == NULL) return NULL; r = try_alloc(file, line, strlen(string) +1, log); (void)strcpy(r, string); return r; } void * try_realloc(char *file, int line, void *ptr, size_t len, int log) { void *r = NULL; int cnt = 0; if (ptr == NULL) return NULL; if (len <= 0) len = 1; while (r == NULL) { if ((r = realloc(ptr, len)) != NULL) break; (void)sleep(++cnt); if (cnt >= MAX_FAILS_M) { milterr(Prog, file, line, log, errno, "ABORTED", "Allocate memory"); return NULL; } } return r; } unsigned long revbytes(unsigned long p) { unsigned char *s; int x; union { char a[SIZEOF_LONG]; unsigned long addr; } dest; s = (unsigned char *)&(p); for (x = SIZEOF_LONG -1; x >= 0; --x, ++s) dest.a[x] = *s; p = dest.addr; return p; } /* ** Converts a date that is in the form: ** 10/12/2003 09:42:05 ** ** Into a single time_t variable. */ time_t parse_date(char *date) { struct tm tt; time_t t; char *cp, *ep; long val; extern int errno; if (date == NULL) { errno = EINVAL; return 0; } (void) memset((char *)&tt, '\0', sizeof(struct tm)); errno = 0; cp = date; /* The month where tm_mon is base 0 */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; tt.tm_mon = val - 1; cp = ep+1; errno = 0; /* the day 1-31 */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; tt.tm_mday = val; cp = ep+1; errno = 0; /* the year tm_year is years since 1900 */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; if (val < 99) /* a 2 digit year? */ tt.tm_year = val + 100; else tt.tm_year = val - 1900; cp = ep+1; errno = 0; /* the hour is based on a 24 hour day */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; tt.tm_hour = val; cp = ep+1; errno = 0; /* the minutes */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; tt.tm_min = val; cp = ep+1; errno = 0; /* the minutes */ val = strtol(cp, &ep, 10); if (val == 0 && errno != 0) return 0; tt.tm_sec = val; cp = ep+1; errno = 0; if ((t = mktime(&tt)) == -1) return 0; return t; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 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. |
||
#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. |