diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 51 | ||||
-rw-r--r-- | src/config.c | 81 | ||||
-rw-r--r-- | src/config.h | 5 | ||||
-rw-r--r-- | src/dbase.c | 43 | ||||
-rw-r--r-- | src/dbase.h | 6 | ||||
-rw-r--r-- | src/kbs.c | 2 | ||||
-rw-r--r-- | src/kbsrc | 9 | ||||
-rw-r--r-- | src/pop3.c | 94 |
8 files changed, 262 insertions, 29 deletions
diff --git a/src/Makefile b/src/Makefile index e1ef0ce..15b4775 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ # # ------------------------------------------------------------------------- # -# $Id: Makefile,v 1.6 2003-12-12 01:15:38 ianc Exp $ +# $Id: Makefile,v 1.7 2004-01-26 02:01:49 ianc Exp $ # # CFLAGS assumes that gcc is being used - simply comment out if required @@ -54,3 +54,52 @@ depend: if test -e Makefile ; then rm -f Makefile.bak ; fi # DO NOT DELETE THIS LINE -- make depend depends on it + +kbs.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +kbs.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +kbs.o: /usr/include/limits.h /usr/include/sys/limits.h +kbs.o: /usr/include/machine/_limits.h /usr/include/sys/syslimits.h +kbs.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +kbs.o: /usr/include/stdarg.h /usr/include/time.h /usr/include/sys/timespec.h +kbs.o: /usr/include/errno.h global.h config.h pop3.h msg.h dbase.h rexp.h +kbs.o: dstring.h util.h +pop3.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +pop3.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +pop3.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdio.h +pop3.o: /usr/include/stdarg.h /usr/include/ctype.h /usr/include/runetype.h +pop3.o: /usr/include/unistd.h /usr/include/sys/types.h +pop3.o: /usr/include/machine/endian.h /usr/include/sys/select.h +pop3.o: /usr/include/sys/_sigset.h /usr/include/sys/_timeval.h +pop3.o: /usr/include/sys/timespec.h /usr/include/sys/unistd.h +pop3.o: /usr/include/sys/socket.h /usr/include/sys/_iovec.h +pop3.o: /usr/include/machine/param.h /usr/include/netinet/in.h +pop3.o: /usr/include/netinet6/in6.h /usr/include/netinet/tcp.h +pop3.o: /usr/include/netdb.h global.h pop3.h msg.h dstring.h util.h +config.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +config.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +config.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdio.h +config.o: /usr/include/errno.h /usr/include/ctype.h /usr/include/runetype.h +config.o: global.h config.h dstring.h dbase.h msg.h rexp.h util.h +rexp.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +rexp.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +rexp.o: /usr/include/regex.h global.h rexp.h config.h util.h +dbase.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +dbase.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +dbase.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdio.h +dbase.o: /usr/include/ctype.h /usr/include/runetype.h global.h dbase.h msg.h +dbase.o: rexp.h dstring.h config.h util.h +dstring.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +dstring.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +dstring.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdio.h +dstring.o: /usr/include/stdarg.h /usr/include/ctype.h /usr/include/runetype.h +dstring.o: /usr/include/sys/types.h /usr/include/machine/endian.h +dstring.o: /usr/include/sys/select.h /usr/include/sys/_sigset.h +dstring.o: /usr/include/sys/_timeval.h /usr/include/sys/timespec.h +dstring.o: /usr/include/sys/socket.h /usr/include/sys/_iovec.h +dstring.o: /usr/include/machine/param.h /usr/include/netinet/in.h +dstring.o: /usr/include/netinet6/in6.h /usr/include/netinet/tcp.h +dstring.o: /usr/include/netdb.h global.h dstring.h util.h +util.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +util.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +util.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdio.h +util.o: global.h util.h diff --git a/src/config.c b/src/config.c index 1c10591..66ea944 100644 --- a/src/config.c +++ b/src/config.c @@ -57,6 +57,8 @@ typedef enum { TOK_BlockSubject, TOK_SubjectMacro, TOK_Blacklist, + TOK_Include, + TOK_AllowTo, TOK_VarHostname, TOK_VarPort, TOK_VarUsername, @@ -128,6 +130,8 @@ static const Command cmd_table[]= {"block_subject", TOK_BlockSubject}, {"subject_macro", TOK_SubjectMacro}, {"blacklist", TOK_Blacklist}, + {"include", TOK_Include}, + {"allow_to", TOK_AllowTo}, /* Variables */ @@ -160,6 +164,7 @@ static const Command cmd_table[]= /* ---------------------------------------- REQUIRED PROTOS */ static Token GetToken(FILE *fp, DString *ret); +static int Parse(FILE *fp); /* ---------------------------------------- COMMAND HANDLER UTILS @@ -417,6 +422,22 @@ static int DoDomain(FILE *fp) DBBlockSubject(domain,re); break; + case TOK_AllowTo: + GetToken(fp,&ds); + + ds=ExpandRE(ds); + + if (!(re=RECompile(ds->text))) + { + DSAddCP(error,"Bad regular expression: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + DBAllowTo(domain,re); + break; + default: DSAddCP(error,"Unexpected string in domain command: "); DSAddDS(error,ds); @@ -576,6 +597,42 @@ static int DoBlacklist(FILE *fp) } +static int DoInclude(FILE *fp) +{ + FILE *inc; + DString ds; + Token tok; + int ret; + + ds=DSInit(); + + tok=GetToken(fp,&ds); + + if (tok==TOK_EOF) + { + DSAddCP(error,"Unexpected EOF in include command"); + DSFree(ds); + return FALSE; + } + + if (!(inc=fopen(ds->text,"r"))) + { + DSAddCP(error,"Couldn't open include file "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + DSFree(ds); + + ret=Parse(inc); + + fclose(inc); + + return ret; +} + + /* ---------------------------------------- PRVIVATE FUNCTIONS */ static int Getc(FILE *fp) @@ -752,6 +809,11 @@ static int Parse(FILE *fp) ok=FALSE; break; + case TOK_Include: + if (!DoInclude(fp)) + ok=FALSE; + break; + case TOK_Expression: DSAddCP(error,"Unknown command in config file: "); DSAddDS(error,txt); @@ -780,7 +842,7 @@ static int Parse(FILE *fp) /* ---------------------------------------- INTERFACES */ -int ConfigLoad(void) +int ConfigLoad(const char *path) { DString ds; FILE *fp; @@ -793,14 +855,19 @@ int ConfigLoad(void) password=CopyStr(""); log=CopyStr(""); - if (!getenv("HOME")) - return FALSE; - ds=DSInit(); - DSAddCP(ds,getenv("HOME")); - DSAddChar(ds,'/'); - DSAddCP(ds,".kbsrc"); + if (path) + DSAddCP(ds,path); + else + { + if (!getenv("HOME")) + return FALSE; + + DSAddCP(ds,getenv("HOME")); + DSAddChar(ds,'/'); + DSAddCP(ds,".kbsrc"); + } if ((fp=fopen(ds->text,"r"))) ret=Parse(fp); diff --git a/src/config.h b/src/config.h index 7f48a70..d545531 100644 --- a/src/config.h +++ b/src/config.h @@ -61,9 +61,10 @@ typedef enum /* ---------------------------------------- INTERFACES */ -/* Loads in config file. Returns FALSE for problems. +/* Loads in config file (the default name if path is NULL). Returns FALSE + for problems. */ -int ConfigLoad(void); +int ConfigLoad(const char *path); /* Returns a reason for config load failure diff --git a/src/dbase.c b/src/dbase.c index c3e83b7..e1caa04 100644 --- a/src/dbase.c +++ b/src/dbase.c @@ -49,9 +49,11 @@ struct Domain int no_user; int no_block; int no_allow; + int no_allow_to; char **user; RE_Expression *block; RE_Expression *allow; + RE_Expression *allow_to; Domain *next; Domain *prev; }; @@ -165,6 +167,7 @@ Domain *DBNewDomain(RE_Expression name) dom->user=NULL; dom->block=NULL; dom->allow=NULL; + dom->allow_to=NULL; if (tail) tail->next=dom; @@ -208,6 +211,15 @@ void DBBlockSubject(Domain *domain, RE_Expression re) } +void DBAllowTo(Domain *domain, RE_Expression re) +{ + domain->no_allow_to++; + domain->allow_to=Realloc(domain->allow_to, + sizeof(RE_Expression)*domain->no_allow_to); + domain->allow_to[domain->no_allow_to-1]=re; +} + + void DBTrustedUser(const char *username) { no_trusted_users++; @@ -254,7 +266,7 @@ int DBBlockMessage(const POP3Message *msg) (strncmp(msg->content_type,html,strlen(html))==0 || strcmp(msg->content_type,"UNKNOWN")==0)) { - DSAddCP(reason,"HTML message"); + DSAddCP(reason,"HTML message or unknown content type"); return TRUE; } @@ -293,6 +305,30 @@ int DBBlockMessage(const POP3Message *msg) } } + if (dom->no_allow_to) + { + int found=FALSE; + int f; + + for(f=0;f<dom->no_allow_to && !found;f++) + if (RESearch(dom->allow_to[f],msg->to)) + found=TRUE; + + if (!found) + { + if (show) + { + DSAddCP(reason,"disallowed to address - "); + DSAddCP(reason,msg->to); + } + else + DSAddCP(reason,"disallowed to address"); + + DSFree(ds); + return TRUE; + } + } + for(f=0;f<dom->no_user;f++) { int res; @@ -392,6 +428,11 @@ void DBClose(void) free(t->allow); + for(f=0;f<t->no_allow;f++) + REFree(t->allow_to[f]); + + free(t->allow_to); + free(t); } diff --git a/src/dbase.h b/src/dbase.h index 3c771af..1b3dfa6 100644 --- a/src/dbase.h +++ b/src/dbase.h @@ -70,6 +70,12 @@ void DBAllowSubject(Domain *domain, RE_Expression re); void DBBlockSubject(Domain *domain, RE_Expression re); +/* Sets the allowed 'To:' name for a domain. + re will be freed by the database when closed. +*/ +void DBAllowTo(Domain *domain, RE_Expression re); + + /* Adds a trusted username */ void DBTrustedUser(const char *username); @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) else name=argv[0]; - if (!ConfigLoad()) + if (!ConfigLoad(argv[1])) { fprintf(stderr,"%s: %s\n",name,ConfigError()); exit(EXIT_FAILURE); @@ -69,6 +69,12 @@ domain "." # block_user emailname + + # Only allow emails legitimately directed to us: + # + allow_to emailname@myisp.co.uk + + # Obviously, things like "credit card" will not be blocked from the bank # as that's in the trusted_domains. # @@ -94,9 +100,10 @@ domain "." block_subject ".* ?naked ?.*" block_subject ".* ?nigeria ?.*" + # Why would anyone sane want to use my username in a subject? # I know who I am! Note it's capitilised so nothing bizarre gets # done by the subject macros. # - block_subject "EMAILNAME@MY-ISP.CO.UK" + block_subject "EMAILNAME@MYISP.CO.UK" } @@ -57,6 +57,7 @@ static const char message_id[]=KBS_MSG_H; #define HDR_FROM 1 #define HDR_TO 2 #define HDR_CONTENT_TYPE 3 +#define HDR_DEBUG 4 /* ---------------------------------------- TYPES */ @@ -71,6 +72,7 @@ static int connected=FALSE; /* ---------------------------------------- PRIVATE FUNCTIONS */ +/* static void Chomp(char *p) { size_t l; @@ -87,6 +89,7 @@ static void Chomp(char *p) p[--l]=0; } } +*/ static char *ChompQuotesWS(char *p) @@ -182,13 +185,14 @@ static int Send(const char *cmd, ...) } +static char gc_buff[BLOCKSIZE]; +static ssize_t gc_len=0; +static int gc_ptr=0; + + static int GetChar(void) { - static char buff[BLOCKSIZE]; - static ssize_t len=0; - static int ptr=0; - - if (len==0 || ptr==len) + if (gc_len==0 || gc_ptr==gc_len) { struct timeval tv; fd_set set; @@ -205,13 +209,20 @@ static int GetChar(void) if (!FD_ISSET(sock,&set)) return -1; - if ((len=read(sock,buff,sizeof buff))<1) + if ((gc_len=read(sock,gc_buff,sizeof gc_buff))<1) return -1; - ptr=0; + gc_ptr=0; } - return buff[ptr++]; + return gc_buff[gc_ptr++]; +} + + +static void UnGetChar(int c) +{ + if (gc_ptr) + gc_buff[--gc_ptr]=c; } @@ -225,7 +236,8 @@ static int GetLine(DString t) while(!done && (ch=GetChar())!=-1) { - DSAddChar(t,ch); + if (ch!='\015' && ch!='\012') + DSAddChar(t,ch); if (last=='\015' && ch=='\012') done=TRUE; @@ -236,8 +248,6 @@ static int GetLine(DString t) if (ch==-1) return FALSE; - Chomp(t->text); - return TRUE; } @@ -263,14 +273,59 @@ static int GetResponse(DString ret) } +static int IsHeader(const DString line) +{ + const char *p; + + p=line->text; + + while(*p && !isspace(*p)) + { + if (*p==':') + return TRUE; + + p++; + } + + return FALSE; +} + + static int GetMultiLine(DString ret) { - int flag; + int done=FALSE; + int flag=TRUE; - if (GetLine(ret)) - flag=TRUE; - else - flag=FALSE; + while (!done) + { + if (GetLine(ret)) + { + if (IsHeader(ret)) + { + int ch; + + if ((ch=GetChar())!=-1) + { + if (ch!=' ' && ch!='\t') + done=TRUE; + + UnGetChar(ch); + } + else + { + flag=FALSE; + done=TRUE; + } + } + else + done=TRUE; + } + else + { + flag=FALSE; + done=TRUE; + } + } return flag; } @@ -289,15 +344,18 @@ static void ParseHeader(POP3Message *msg, char *line) {"To: ", HDR_TO}, {"Content-type: ", HDR_CONTENT_TYPE}, {"Content-Type: ", HDR_CONTENT_TYPE}, + /* {"Received: ", HDR_DEBUG}, */ {NULL, HDR_UNKNOWN} }; + const char *name; int f; int type=HDR_UNKNOWN; for(f=0;type==HDR_UNKNOWN && field[f].text;f++) if (strncmp(field[f].text,line,strlen(field[f].text))==0) { + name=field[f].text; type=field[f].type; line+=strlen(field[f].text); } @@ -341,6 +399,10 @@ static void ParseHeader(POP3Message *msg, char *line) msg->content_type=CopyStr(line); break; + case HDR_DEBUG: + printf("%s = '%s'\n",name,line); + break; + default: break; } |