diff -u orig/tcprules.1 ./tcprules.1 --- orig/tcprules.1 Sun Jan 18 02:17:43 1998 +++ ./tcprules.1 Mon May 4 23:48:31 1998 @@ -156,6 +156,13 @@ .B 10.2.:ins and .BR 10.3.:ins . +.SH "HOST NAMES" +.B tcprules +can contain domains as well as addresses; search for a +match is based on do.ma.in, + .ma.in, + .in, + . (period used as 'default') .SH "INSTRUCTIONS" The instructions in a rule must begin with either .B allow diff -u orig/tcprules.c ./tcprules.c --- orig/tcprules.c Sun Jan 18 02:17:43 1998 +++ ./tcprules.c Tue May 5 11:00:02 1998 @@ -58,7 +58,16 @@ unsigned long bot; unsigned long top; - if (byte_chr(address.s,address.len,'@') == address.len) { + for (i = 0; i < address.len; i++) { + if (address.s[i] == '-') continue; + if (address.s[i] == '.') continue; + if (address.s[i] == '@') continue; + if (address.s[i] >= '0') + if (address.s[i] <= '9') continue; + i = address.len + 1; + } + + if (i == address.len) { i = byte_chr(address.s,address.len,'-'); if (i < address.len) { left = byte_rchr(address.s,i,'.'); diff -u orig/tcpserver.1 ./tcpserver.1 --- orig/tcpserver.1 Sun Jan 18 02:17:43 1998 +++ ./tcpserver.1 Mon May 4 23:48:35 1998 @@ -7,6 +7,9 @@ .B \-qQvdDoOpPhHrR1 ] [ +.B \-NnAa +] +[ .B \-c\fIlimit ] [ @@ -179,6 +182,25 @@ .B \-P (Default.) Not paranoid. +.TP +.B \-a +'deny' connections from an address with no hostname +.TP +.B \-A +'deny' connections from an address which is 'paranoid' +The environment variable +.BR TCPPARANOID +is set if the connection is +considered to be 'paranoid' (allows programs to tell the difference +when +.BR TCPREMOTEHOST +is not set). +.TP +.B \-n +Do domain name lookups in tcprules file after ip lookup. +.TP +.B \-N +Do domain name lookups in tcprules file before IP lookup .TP .B \-h (Default.) diff -u orig/tcpserver.c ./tcpserver.c --- orig/tcpserver.c Sun Jan 18 02:17:43 1998 +++ ./tcpserver.c Mon May 4 23:22:21 1998 @@ -27,6 +27,9 @@ #include "env.h" #include "cdb.h" +#define TCPPARANOID /* if TCPPARANOID options are to be used */ +#define TCPREMOTEHOSTRULES /* if want remote host checked in rules() */ + #define FATAL "tcpserver: fatal: " #define DROP "tcpserver: warning: dropping connection, " int verbosity = 1; @@ -90,6 +93,16 @@ char *fnrules = 0; int flagdeny = 0; +#ifdef TCPREMOTEHOSTRULES +stralloc tcpremotehost = {0}; +int domainchecking = 0; +#endif +#ifdef TCPPARANOID +char *connectionstatus; +int blockingparanoid = 0; +int blockingnohost = 0; +#endif + void printenv() { char *tcplocalhost; @@ -101,10 +114,17 @@ tcpremotehost = env_get("TCPREMOTEHOST"); if (!tcplocalhost) tcplocalhost = ""; +#ifdef TCPPARANOID + if (!tcpremotehost) tcpremotehost = env_get("TCPPARANOID"); +#endif if (!tcpremotehost) tcpremotehost = ""; if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem(); +#ifdef TCPPARANOID + if (!stralloc_cats(&tmp,connectionstatus)) drop_nomem(); +#else if (!stralloc_cats(&tmp,flagdeny ? "deny " : "ok ")) drop_nomem(); +#endif if (!stralloc_catb(&tmp,strnum,fmt_ulong(strnum,getpid()))) drop_nomem(); if (!stralloc_cats(&tmp," ")) drop_nomem(); safeappend(&tmp,tcplocalhost); @@ -184,7 +204,11 @@ while ((next0 = byte_chr(data,datalen,0)) < datalen) { switch(data[0]) { +#ifdef TCPPARANOID + case 'D': connectionstatus = "deny "; flagdeny = 1; break; +#else case 'D': flagdeny = 1; break; +#endif case '+': if (!env_put(data + 1)) drop_nomem(); break; } data += next0 + 1; datalen -= next0 + 1; @@ -192,6 +216,36 @@ return 1; } +#ifdef TCPREMOTEHOSTRULES +int tcp_domain_check() +{ + if (tcpremotehost.len) { + unsigned int i = 0; + + if (tcpremoteinfo) { + if (!stralloc_copys(&tmp,tcpremoteinfo)) drop_nomem(); + if (!stralloc_cats(&tmp,"@")) drop_nomem(); + if (!stralloc_cats(&tmp,tcpremotehost.s)) drop_nomem(); + if (dorule()) return 1; + } + + if (!stralloc_copys(&tmp,tcpremotehost.s)) drop_nomem(); + if (dorule()) return 1; + while (++i < tcpremotehost.len) + if (tcpremotehost.s[i] == '.') { + if (!stralloc_copys(&tmp,tcpremotehost.s+i)) + drop_nomem(); + if (dorule()) return 1; + } + } + /* We use .' to indicate a valid host default (blank for IP address) */ + /* so that if the host isn't set we can act differently on an IP address */ + if (!stralloc_copys(&tmp, ".")) drop_nomem(); + if (dorule()) return 1; + return 0; +} +#endif + void rules() { if (!fnrules) return; @@ -199,6 +253,10 @@ fdrules = open_read(fnrules); if (fdrules == -1) drop_rules(); +#ifdef TCPREMOTEHOSTRULES + if (domainchecking == -1) tcp_domain_check(); +#endif + if (tcpremoteinfo) { if (!stralloc_copys(&tmp,tcpremoteinfo)) drop_nomem(); if (!stralloc_cats(&tmp,"@")) drop_nomem(); @@ -214,6 +272,11 @@ --tmp.len; } +#ifdef TCPREMOTEHOSTRULES + if (domainchecking == 1) tcp_domain_check(); + tmp.len = 0; +#endif + dorule(); done: @@ -246,7 +309,12 @@ struct servent *se; int j; +#if defined(TCPREMOTEHOSTS) || defined(TCPPARANOID) + /* okay the defines mean the options might not actually work - so what? */ + while ((opt = getopt(argc,argv,"dDvqQhHrR1x:t:u:g:l:b:c:pPoOnNaA")) != opteof) +#else while ((opt = getopt(argc,argv,"dDvqQhHrR1x:t:u:g:l:b:c:pPoO")) != opteof) +#endif switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; @@ -269,6 +337,14 @@ case 'u': scan_ulong(optarg,&uid); break; case '1': flag1 = 1; break; case 'l': forcelocal = optarg; break; +#ifdef TCPREMOTEHOSTRULES + case 'n': domainchecking = 1; break; + case 'N': domainchecking = -1; break; +#endif +#ifdef TCPPARANOID + case 'a': blockingnohost = 1; break; + case 'A': blockingparanoid = 1; break; +#endif default: usage(); } argc -= optind; @@ -362,6 +438,9 @@ if (!env_unset("TCPLOCALHOST")) die_nomem(); if (!env_unset("TCPREMOTEHOST")) die_nomem(); if (!env_unset("TCPREMOTEINFO")) die_nomem(); +#ifdef TCPPARANOID + if (!env_unset("TCPPARANOID")) die_nomem(); +#endif if (forcelocal) if (!env_put2("TCPLOCALHOST",forcelocal)) die_nomem(); @@ -376,6 +455,9 @@ sig_childblock(); for (;;) { +#ifdef TCPPARANOID + int tcpremotehostset = 0; +#endif while (numchildren >= limit) sig_pause(); sig_childunblock(); @@ -433,6 +515,9 @@ } if (flagremotehost) +#ifdef TCPREMOTEHOSTRULES +#define tmp tcpremotehost +#endif switch(dns_ptr(&tmp,&ipremote)) { case DNS_MEM: drop_nomem(); case 0: @@ -447,6 +532,11 @@ if (!stralloc_0(&tmp)) drop_nomem(); case_lowers(tmp.s); if (!env_put2("TCPREMOTEHOST",tmp.s)) drop_nomem(); +#ifdef TCPPARANOID + tcpremotehostset = 1; + break; + default: tmp.len = 0; /* reset it, for nohost checking */ +#endif } if (flagremoteinfo) { tcpremoteinfo = remoteinfo_get(&ipremote,portremote,&iplocal,portlocal,(int) timeout); @@ -454,6 +544,23 @@ if (!env_put2("TCPREMOTEINFO",tcpremoteinfo)) drop_nomem(); } +#ifdef TCPPARANOID + connectionstatus = "ok "; + if (!tcpremotehostset) + if (tmp.len) { + if (!stralloc_0(&tmp)) drop_nomem(); + case_lowers(tmp.s); + if (!env_put2("TCPPARANOID", tmp.s)) drop_nomem(); + if (blockingparanoid) connectionstatus = "deny-paranoid "; + else connectionstatus = "ok-paranoid "; + } + else if (blockingnohost) connectionstatus = "deny-nohost "; + + if (str_diffn(connectionstatus, "ok", 2)) flagdeny = 1; else +#endif +#ifdef TCPREMOTEHOSTRULES +#undef tmp +#endif rules(); printenv(); if (flagdeny) _exit(100); .