1*7dd7cddfSDavid du Colombier #include "common.h" 2*7dd7cddfSDavid du Colombier #include "smtpd.h" 3*7dd7cddfSDavid du Colombier #include "ip.h" 4*7dd7cddfSDavid du Colombier 5*7dd7cddfSDavid du Colombier enum { 6*7dd7cddfSDavid du Colombier NORELAY = 0, 7*7dd7cddfSDavid du Colombier DNSVERIFY, 8*7dd7cddfSDavid du Colombier SAVEBLOCK, 9*7dd7cddfSDavid du Colombier DOMNAME, 10*7dd7cddfSDavid du Colombier OURNETS, 11*7dd7cddfSDavid du Colombier OURDOMS, 12*7dd7cddfSDavid du Colombier 13*7dd7cddfSDavid du Colombier IP = 0, 14*7dd7cddfSDavid du Colombier STRING, 15*7dd7cddfSDavid du Colombier }; 16*7dd7cddfSDavid du Colombier 17*7dd7cddfSDavid du Colombier 18*7dd7cddfSDavid du Colombier typedef struct Keyword Keyword; 19*7dd7cddfSDavid du Colombier 20*7dd7cddfSDavid du Colombier struct Keyword { 21*7dd7cddfSDavid du Colombier char *name; 22*7dd7cddfSDavid du Colombier int code; 23*7dd7cddfSDavid du Colombier }; 24*7dd7cddfSDavid du Colombier 25*7dd7cddfSDavid du Colombier static Keyword options[] = { 26*7dd7cddfSDavid du Colombier "norelay", NORELAY, 27*7dd7cddfSDavid du Colombier "verifysenderdom", DNSVERIFY, 28*7dd7cddfSDavid du Colombier "saveblockedmsg", SAVEBLOCK, 29*7dd7cddfSDavid du Colombier "defaultdomain", DOMNAME, 30*7dd7cddfSDavid du Colombier "ournets", OURNETS, 31*7dd7cddfSDavid du Colombier "ourdomains", OURDOMS, 32*7dd7cddfSDavid du Colombier 0, NONE, 33*7dd7cddfSDavid du Colombier }; 34*7dd7cddfSDavid du Colombier 35*7dd7cddfSDavid du Colombier static Keyword actions[] = { 36*7dd7cddfSDavid du Colombier "allow", ACCEPT, 37*7dd7cddfSDavid du Colombier "accept", ACCEPT, 38*7dd7cddfSDavid du Colombier "block", BLOCKED, 39*7dd7cddfSDavid du Colombier "deny", DENIED, 40*7dd7cddfSDavid du Colombier "dial", DIALUP, 41*7dd7cddfSDavid du Colombier "relay", RELAY, 42*7dd7cddfSDavid du Colombier 0, NONE, 43*7dd7cddfSDavid du Colombier }; 44*7dd7cddfSDavid du Colombier 45*7dd7cddfSDavid du Colombier static char* getline(Biobuf*); 46*7dd7cddfSDavid du Colombier 47*7dd7cddfSDavid du Colombier static int 48*7dd7cddfSDavid du Colombier findkey(char *val, Keyword *p) 49*7dd7cddfSDavid du Colombier { 50*7dd7cddfSDavid du Colombier 51*7dd7cddfSDavid du Colombier for(; p->name; p++) 52*7dd7cddfSDavid du Colombier if(strcmp(val, p->name) == 0) 53*7dd7cddfSDavid du Colombier break; 54*7dd7cddfSDavid du Colombier return p->code; 55*7dd7cddfSDavid du Colombier } 56*7dd7cddfSDavid du Colombier 57*7dd7cddfSDavid du Colombier void 58*7dd7cddfSDavid du Colombier getconf(void) 59*7dd7cddfSDavid du Colombier { 60*7dd7cddfSDavid du Colombier Biobuf *bp; 61*7dd7cddfSDavid du Colombier char *cp, *p; 62*7dd7cddfSDavid du Colombier String *s; 63*7dd7cddfSDavid du Colombier char buf[512]; 64*7dd7cddfSDavid du Colombier 65*7dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/smtpd.conf", UPASLIB); 66*7dd7cddfSDavid du Colombier bp = sysopen(buf, "r", 0); 67*7dd7cddfSDavid du Colombier if(bp == 0) 68*7dd7cddfSDavid du Colombier return; 69*7dd7cddfSDavid du Colombier 70*7dd7cddfSDavid du Colombier for(;;){ 71*7dd7cddfSDavid du Colombier cp = getline(bp); 72*7dd7cddfSDavid du Colombier if(cp == 0) 73*7dd7cddfSDavid du Colombier break; 74*7dd7cddfSDavid du Colombier p = cp+strlen(cp)+1; 75*7dd7cddfSDavid du Colombier switch(findkey(cp, options)){ 76*7dd7cddfSDavid du Colombier case NORELAY: 77*7dd7cddfSDavid du Colombier if(fflag == 0 && strcmp(p, "on") == 0) 78*7dd7cddfSDavid du Colombier fflag++; 79*7dd7cddfSDavid du Colombier break; 80*7dd7cddfSDavid du Colombier case DNSVERIFY: 81*7dd7cddfSDavid du Colombier if(rflag == 0 && strcmp(p, "on") == 0) 82*7dd7cddfSDavid du Colombier rflag++; 83*7dd7cddfSDavid du Colombier break; 84*7dd7cddfSDavid du Colombier case SAVEBLOCK: 85*7dd7cddfSDavid du Colombier if(sflag == 0 && strcmp(p, "on") == 0) 86*7dd7cddfSDavid du Colombier sflag++; 87*7dd7cddfSDavid du Colombier break; 88*7dd7cddfSDavid du Colombier case DOMNAME: 89*7dd7cddfSDavid du Colombier if(dom == 0) 90*7dd7cddfSDavid du Colombier dom = strdup(p); 91*7dd7cddfSDavid du Colombier break; 92*7dd7cddfSDavid du Colombier case OURNETS: 93*7dd7cddfSDavid du Colombier if (trusted == 0) 94*7dd7cddfSDavid du Colombier trusted = cidrcheck(p); 95*7dd7cddfSDavid du Colombier break; 96*7dd7cddfSDavid du Colombier case OURDOMS: 97*7dd7cddfSDavid du Colombier while(*p){ 98*7dd7cddfSDavid du Colombier s = s_new(); 99*7dd7cddfSDavid du Colombier s_append(s, p); 100*7dd7cddfSDavid du Colombier listadd(&ourdoms, s); 101*7dd7cddfSDavid du Colombier p += strlen(p)+1; 102*7dd7cddfSDavid du Colombier } 103*7dd7cddfSDavid du Colombier break; 104*7dd7cddfSDavid du Colombier default: 105*7dd7cddfSDavid du Colombier break; 106*7dd7cddfSDavid du Colombier } 107*7dd7cddfSDavid du Colombier } 108*7dd7cddfSDavid du Colombier sysclose(bp); 109*7dd7cddfSDavid du Colombier } 110*7dd7cddfSDavid du Colombier 111*7dd7cddfSDavid du Colombier /* 112*7dd7cddfSDavid du Colombier * match a user name. the only meta-char is '*' which matches all 113*7dd7cddfSDavid du Colombier * characters. we only allow it as "*", which matches anything or 114*7dd7cddfSDavid du Colombier * an * at the end of the name (e.g., "username*") which matches 115*7dd7cddfSDavid du Colombier * trailing characters. 116*7dd7cddfSDavid du Colombier */ 117*7dd7cddfSDavid du Colombier static int 118*7dd7cddfSDavid du Colombier usermatch(char *pathuser, char *specuser) 119*7dd7cddfSDavid du Colombier { 120*7dd7cddfSDavid du Colombier int n; 121*7dd7cddfSDavid du Colombier 122*7dd7cddfSDavid du Colombier n = strlen(specuser)-1; 123*7dd7cddfSDavid du Colombier if(specuser[n] == '*'){ 124*7dd7cddfSDavid du Colombier if(n == 0) /* match everything */ 125*7dd7cddfSDavid du Colombier return 0; 126*7dd7cddfSDavid du Colombier return strncmp(pathuser, specuser, n); 127*7dd7cddfSDavid du Colombier } 128*7dd7cddfSDavid du Colombier return strcmp(pathuser, specuser); 129*7dd7cddfSDavid du Colombier } 130*7dd7cddfSDavid du Colombier 131*7dd7cddfSDavid du Colombier static int 132*7dd7cddfSDavid du Colombier dommatch(char *pathdom, char *specdom) 133*7dd7cddfSDavid du Colombier { 134*7dd7cddfSDavid du Colombier int n; 135*7dd7cddfSDavid du Colombier 136*7dd7cddfSDavid du Colombier if (*specdom == '*'){ 137*7dd7cddfSDavid du Colombier if (specdom[1] == '.' && specdom[2]){ 138*7dd7cddfSDavid du Colombier specdom += 2; 139*7dd7cddfSDavid du Colombier n = strlen(pathdom)-strlen(specdom); 140*7dd7cddfSDavid du Colombier if(n == 0 || (n > 0 && pathdom[n-1] == '.')) 141*7dd7cddfSDavid du Colombier return strcmp(pathdom+n, specdom); 142*7dd7cddfSDavid du Colombier return n; 143*7dd7cddfSDavid du Colombier } 144*7dd7cddfSDavid du Colombier } 145*7dd7cddfSDavid du Colombier return strcmp(pathdom, specdom); 146*7dd7cddfSDavid du Colombier } 147*7dd7cddfSDavid du Colombier 148*7dd7cddfSDavid du Colombier /* 149*7dd7cddfSDavid du Colombier * match path components to prohibited domain & user specifications. patterns include: 150*7dd7cddfSDavid du Colombier * domain, domain! or domain!* - all users in domain 151*7dd7cddfSDavid du Colombier * *.domain, *.domain! or *.domain!* - all users in domain and its subdomains 152*7dd7cddfSDavid du Colombier * !user or *!user - user in all domains 153*7dd7cddfSDavid du Colombier * domain!user - user in domain 154*7dd7cddfSDavid du Colombier * *.domain!user - user in domain and its subdomains 155*7dd7cddfSDavid du Colombier * 156*7dd7cddfSDavid du Colombier * if "user" has a trailing '*', it matches all user names beginning with "user" 157*7dd7cddfSDavid du Colombier * 158*7dd7cddfSDavid du Colombier * there are special semantics for the "domain, domain! or domain!*" specifications: 159*7dd7cddfSDavid du Colombier * the first two forms match when the domain is anywhere in at list of source-routed 160*7dd7cddfSDavid du Colombier * domains while the latter matches only when the domain is the last hop. the same is 161*7dd7cddfSDavid du Colombier * true for the *.domain!* form of the pattern. 162*7dd7cddfSDavid du Colombier */ 163*7dd7cddfSDavid du Colombier static int 164*7dd7cddfSDavid du Colombier accountmatch(char *spec, List *doms, char *user) 165*7dd7cddfSDavid du Colombier { 166*7dd7cddfSDavid du Colombier char *cp, *p; 167*7dd7cddfSDavid du Colombier int i, n; 168*7dd7cddfSDavid du Colombier Link *l; 169*7dd7cddfSDavid du Colombier 170*7dd7cddfSDavid du Colombier static char *dangerous[] = { "*", "!", "*!", "!*", "*!*", 0 }; 171*7dd7cddfSDavid du Colombier 172*7dd7cddfSDavid du Colombier for(; *spec; spec += n){ 173*7dd7cddfSDavid du Colombier n = strlen(spec)+1; 174*7dd7cddfSDavid du Colombier 175*7dd7cddfSDavid du Colombier /* rule out dangerous patterns */ 176*7dd7cddfSDavid du Colombier for (i = 0; dangerous[i]; i++) 177*7dd7cddfSDavid du Colombier if(strcmp(spec, dangerous[i])== 0) 178*7dd7cddfSDavid du Colombier break; 179*7dd7cddfSDavid du Colombier if(dangerous[i]) 180*7dd7cddfSDavid du Colombier continue; 181*7dd7cddfSDavid du Colombier 182*7dd7cddfSDavid du Colombier p = 0; 183*7dd7cddfSDavid du Colombier cp = strchr(spec, '!'); 184*7dd7cddfSDavid du Colombier if(cp){ 185*7dd7cddfSDavid du Colombier *cp++ = 0; 186*7dd7cddfSDavid du Colombier if(*cp) 187*7dd7cddfSDavid du Colombier p = cp; 188*7dd7cddfSDavid du Colombier } 189*7dd7cddfSDavid du Colombier 190*7dd7cddfSDavid du Colombier if(p == 0){ /* no user field - domain match only */ 191*7dd7cddfSDavid du Colombier for(l = doms->first; l; l = l->next) 192*7dd7cddfSDavid du Colombier if(dommatch(s_to_c(l->p), spec) == 0) 193*7dd7cddfSDavid du Colombier return 1; 194*7dd7cddfSDavid du Colombier } else { 195*7dd7cddfSDavid du Colombier /* check for "!user", "*!user" or "domain!user" */ 196*7dd7cddfSDavid du Colombier if(usermatch(user, p) == 0){ 197*7dd7cddfSDavid du Colombier if(*spec == 0 || strcmp(spec, "*") == 0) 198*7dd7cddfSDavid du Colombier return 1; 199*7dd7cddfSDavid du Colombier if(doms->last && dommatch(s_to_c(doms->last->p), spec) == 0) 200*7dd7cddfSDavid du Colombier return 1; 201*7dd7cddfSDavid du Colombier } 202*7dd7cddfSDavid du Colombier } 203*7dd7cddfSDavid du Colombier } 204*7dd7cddfSDavid du Colombier return 0; 205*7dd7cddfSDavid du Colombier } 206*7dd7cddfSDavid du Colombier 207*7dd7cddfSDavid du Colombier /* 208*7dd7cddfSDavid du Colombier * we risk reparsing the file of blocked addresses if there are 209*7dd7cddfSDavid du Colombier * multiple senders or if the peer does a transaction and then a RSET 210*7dd7cddfSDavid du Colombier * followed by another transaction. we believe this happens rarely, 211*7dd7cddfSDavid du Colombier * but we cache the last sender to try to minimize the overhead. we 212*7dd7cddfSDavid du Colombier * also cache whether we rejected a previous transaction based on 213*7dd7cddfSDavid du Colombier * ip address, since this never changes. 214*7dd7cddfSDavid du Colombier */ 215*7dd7cddfSDavid du Colombier int 216*7dd7cddfSDavid du Colombier blocked(String *path) 217*7dd7cddfSDavid du Colombier { 218*7dd7cddfSDavid du Colombier char buf[512], *cp, *p, *user; 219*7dd7cddfSDavid du Colombier Biobuf *bp; 220*7dd7cddfSDavid du Colombier int action, type, ipallow; 221*7dd7cddfSDavid du Colombier List doms; 222*7dd7cddfSDavid du Colombier String *s, *lpath; 223*7dd7cddfSDavid du Colombier 224*7dd7cddfSDavid du Colombier static String *lastsender; 225*7dd7cddfSDavid du Colombier static int lastret, blockedbyip; 226*7dd7cddfSDavid du Colombier 227*7dd7cddfSDavid du Colombier if(debug) 228*7dd7cddfSDavid du Colombier fprint(2, "blocked(%s)\n", s_to_c(path)); 229*7dd7cddfSDavid du Colombier 230*7dd7cddfSDavid du Colombier if(blockedbyip) 231*7dd7cddfSDavid du Colombier return lastret; 232*7dd7cddfSDavid du Colombier 233*7dd7cddfSDavid du Colombier if(lastsender){ 234*7dd7cddfSDavid du Colombier if(strcmp(s_to_c(lastsender), s_to_c(path)) == 0) 235*7dd7cddfSDavid du Colombier return lastret; 236*7dd7cddfSDavid du Colombier s_free(lastsender); 237*7dd7cddfSDavid du Colombier lastsender = 0; 238*7dd7cddfSDavid du Colombier } 239*7dd7cddfSDavid du Colombier 240*7dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/blocked", UPASLIB); 241*7dd7cddfSDavid du Colombier bp = sysopen(buf, "r", 0); 242*7dd7cddfSDavid du Colombier if(bp == 0) 243*7dd7cddfSDavid du Colombier return ACCEPT; 244*7dd7cddfSDavid du Colombier 245*7dd7cddfSDavid du Colombier lpath = s_copy(s_to_c(s_restart(path))); /* convert to LC */ 246*7dd7cddfSDavid du Colombier for(cp = s_to_c(lpath); *cp; cp++) 247*7dd7cddfSDavid du Colombier *cp = tolower(*cp); 248*7dd7cddfSDavid du Colombier 249*7dd7cddfSDavid du Colombier /* parse the path into a list of domains and a user */ 250*7dd7cddfSDavid du Colombier doms.first = doms.last = 0; 251*7dd7cddfSDavid du Colombier p = s_to_c(lpath); 252*7dd7cddfSDavid du Colombier while (cp = strchr(p, '!')){ 253*7dd7cddfSDavid du Colombier *cp = 0; 254*7dd7cddfSDavid du Colombier s = s_new(); 255*7dd7cddfSDavid du Colombier s_append(s, p); 256*7dd7cddfSDavid du Colombier *cp = '!'; 257*7dd7cddfSDavid du Colombier listadd(&doms, s); 258*7dd7cddfSDavid du Colombier p = cp+1; 259*7dd7cddfSDavid du Colombier } 260*7dd7cddfSDavid du Colombier user = p; 261*7dd7cddfSDavid du Colombier 262*7dd7cddfSDavid du Colombier /* 263*7dd7cddfSDavid du Colombier * line format: [*]VERB param 1, ... param n, where '*' indicates 264*7dd7cddfSDavid du Colombier * params are path names; if not present, params are ip addresses in 265*7dd7cddfSDavid du Colombier * CIDR format. 266*7dd7cddfSDavid du Colombier */ 267*7dd7cddfSDavid du Colombier ipallow = 0; 268*7dd7cddfSDavid du Colombier for(;;){ 269*7dd7cddfSDavid du Colombier action = ACCEPT; 270*7dd7cddfSDavid du Colombier cp = getline(bp); 271*7dd7cddfSDavid du Colombier if(cp == 0) 272*7dd7cddfSDavid du Colombier break; 273*7dd7cddfSDavid du Colombier type = *cp; 274*7dd7cddfSDavid du Colombier if(type == '*') { 275*7dd7cddfSDavid du Colombier cp++; 276*7dd7cddfSDavid du Colombier if(*cp == 0) 277*7dd7cddfSDavid du Colombier cp++; 278*7dd7cddfSDavid du Colombier } 279*7dd7cddfSDavid du Colombier action = findkey(cp, actions); 280*7dd7cddfSDavid du Colombier if (action == NONE) 281*7dd7cddfSDavid du Colombier continue; 282*7dd7cddfSDavid du Colombier 283*7dd7cddfSDavid du Colombier cp += strlen(cp)+1; 284*7dd7cddfSDavid du Colombier if(type == '*') { 285*7dd7cddfSDavid du Colombier if(accountmatch(cp, &doms, user)) 286*7dd7cddfSDavid du Colombier break; 287*7dd7cddfSDavid du Colombier } else { 288*7dd7cddfSDavid du Colombier /* 289*7dd7cddfSDavid du Colombier * An ACCEPT match on IP addresses overrides all later 290*7dd7cddfSDavid du Colombier * blocks on IP address but not blocks on domain or user names 291*7dd7cddfSDavid du Colombier */ 292*7dd7cddfSDavid du Colombier if(ipallow == 0 && cidrcheck(cp)) 293*7dd7cddfSDavid du Colombier if(action == ACCEPT) 294*7dd7cddfSDavid du Colombier ipallow = 1; 295*7dd7cddfSDavid du Colombier else { 296*7dd7cddfSDavid du Colombier blockedbyip = 1; 297*7dd7cddfSDavid du Colombier break; 298*7dd7cddfSDavid du Colombier } 299*7dd7cddfSDavid du Colombier } 300*7dd7cddfSDavid du Colombier } 301*7dd7cddfSDavid du Colombier sysclose(bp); 302*7dd7cddfSDavid du Colombier listfree(&doms); 303*7dd7cddfSDavid du Colombier lastsender = s_copy(s_to_c(s_restart(path))); 304*7dd7cddfSDavid du Colombier s_free(lpath); 305*7dd7cddfSDavid du Colombier lastret = action; 306*7dd7cddfSDavid du Colombier return action; 307*7dd7cddfSDavid du Colombier } 308*7dd7cddfSDavid du Colombier 309*7dd7cddfSDavid du Colombier /* 310*7dd7cddfSDavid du Colombier * get a canonicalized line: a string of null-terminated lower-case 311*7dd7cddfSDavid du Colombier * tokens with a two null bytes at the end. 312*7dd7cddfSDavid du Colombier */ 313*7dd7cddfSDavid du Colombier static char* 314*7dd7cddfSDavid du Colombier getline(Biobuf *bp) 315*7dd7cddfSDavid du Colombier { 316*7dd7cddfSDavid du Colombier char c, *cp, *p, *q; 317*7dd7cddfSDavid du Colombier int n; 318*7dd7cddfSDavid du Colombier 319*7dd7cddfSDavid du Colombier static char *buf; 320*7dd7cddfSDavid du Colombier static int bufsize; 321*7dd7cddfSDavid du Colombier 322*7dd7cddfSDavid du Colombier for(;;){ 323*7dd7cddfSDavid du Colombier cp = Brdline(bp, '\n'); 324*7dd7cddfSDavid du Colombier if(cp == 0) 325*7dd7cddfSDavid du Colombier return 0; 326*7dd7cddfSDavid du Colombier n = Blinelen(bp); 327*7dd7cddfSDavid du Colombier cp[n-1] = 0; 328*7dd7cddfSDavid du Colombier if(buf == 0 || bufsize < n+1){ 329*7dd7cddfSDavid du Colombier bufsize += 512; 330*7dd7cddfSDavid du Colombier if(bufsize < n+1) 331*7dd7cddfSDavid du Colombier bufsize = n+1; 332*7dd7cddfSDavid du Colombier buf = realloc(buf, bufsize); 333*7dd7cddfSDavid du Colombier if(buf == 0) 334*7dd7cddfSDavid du Colombier break; 335*7dd7cddfSDavid du Colombier } 336*7dd7cddfSDavid du Colombier q = buf; 337*7dd7cddfSDavid du Colombier for (p = cp; *p; p++){ 338*7dd7cddfSDavid du Colombier c = *p; 339*7dd7cddfSDavid du Colombier if(c == '\\' && p[1]) /* we don't allow \<newline> */ 340*7dd7cddfSDavid du Colombier c = *++p; 341*7dd7cddfSDavid du Colombier else 342*7dd7cddfSDavid du Colombier if(c == '#') 343*7dd7cddfSDavid du Colombier break; 344*7dd7cddfSDavid du Colombier else 345*7dd7cddfSDavid du Colombier if(c == ' ' || c == '\t' || c == ',') 346*7dd7cddfSDavid du Colombier if(q == buf || q[-1] == 0) 347*7dd7cddfSDavid du Colombier continue; 348*7dd7cddfSDavid du Colombier else 349*7dd7cddfSDavid du Colombier c = 0; 350*7dd7cddfSDavid du Colombier *q++ = tolower(c); 351*7dd7cddfSDavid du Colombier } 352*7dd7cddfSDavid du Colombier if(q != buf){ 353*7dd7cddfSDavid du Colombier if(q[-1]) 354*7dd7cddfSDavid du Colombier *q++ = 0; 355*7dd7cddfSDavid du Colombier *q = 0; 356*7dd7cddfSDavid du Colombier break; 357*7dd7cddfSDavid du Colombier } 358*7dd7cddfSDavid du Colombier } 359*7dd7cddfSDavid du Colombier return buf; 360*7dd7cddfSDavid du Colombier } 361*7dd7cddfSDavid du Colombier 362*7dd7cddfSDavid du Colombier int 363*7dd7cddfSDavid du Colombier forwarding(String *path) 364*7dd7cddfSDavid du Colombier { 365*7dd7cddfSDavid du Colombier char *cp, *s; 366*7dd7cddfSDavid du Colombier String *lpath; 367*7dd7cddfSDavid du Colombier Link *l; 368*7dd7cddfSDavid du Colombier 369*7dd7cddfSDavid du Colombier if(debug) 370*7dd7cddfSDavid du Colombier fprint(2, "forwarding(%s)\n", s_to_c(path)); 371*7dd7cddfSDavid du Colombier 372*7dd7cddfSDavid du Colombier /* first check if they want loopback */ 373*7dd7cddfSDavid du Colombier 374*7dd7cddfSDavid du Colombier lpath = s_copy(s_to_c(s_restart(path))); 375*7dd7cddfSDavid du Colombier if(hisaddr && *hisaddr){ 376*7dd7cddfSDavid du Colombier cp = s_to_c(lpath); 377*7dd7cddfSDavid du Colombier if(strncmp(cp, "[]!", 3) == 0){ 378*7dd7cddfSDavid du Colombier found: 379*7dd7cddfSDavid du Colombier s_append(path, "["); 380*7dd7cddfSDavid du Colombier s_append(path, hisaddr); 381*7dd7cddfSDavid du Colombier s_append(path, "]!"); 382*7dd7cddfSDavid du Colombier s_append(path, cp+3); 383*7dd7cddfSDavid du Colombier s_terminate(path); 384*7dd7cddfSDavid du Colombier s_free(lpath); 385*7dd7cddfSDavid du Colombier return 0; 386*7dd7cddfSDavid du Colombier } 387*7dd7cddfSDavid du Colombier cp = strchr(cp,'!'); /* skip our domain and check next */ 388*7dd7cddfSDavid du Colombier if(cp++ && strncmp(cp, "[]!", 3) == 0) 389*7dd7cddfSDavid du Colombier goto found; 390*7dd7cddfSDavid du Colombier } 391*7dd7cddfSDavid du Colombier /* if mail is from a trusted subnet, allow it to forward*/ 392*7dd7cddfSDavid du Colombier if(trusted) { 393*7dd7cddfSDavid du Colombier s_free(lpath); 394*7dd7cddfSDavid du Colombier return 0; 395*7dd7cddfSDavid du Colombier } 396*7dd7cddfSDavid du Colombier 397*7dd7cddfSDavid du Colombier /* sender is untrusted; ensure receiver is in one of our domains */ 398*7dd7cddfSDavid du Colombier for(cp = s_to_c(lpath); *cp; cp++) /* convert receiver lc */ 399*7dd7cddfSDavid du Colombier *cp = tolower(*cp); 400*7dd7cddfSDavid du Colombier 401*7dd7cddfSDavid du Colombier for(s = s_to_c(lpath); cp = strchr(s, '!'); s = cp+1){ 402*7dd7cddfSDavid du Colombier *cp = 0; 403*7dd7cddfSDavid du Colombier if(strchr(s, '.')){ 404*7dd7cddfSDavid du Colombier for(l = ourdoms.first; l; l = l->next){ 405*7dd7cddfSDavid du Colombier if(dommatch(s, s_to_c(l->p)) == 0) 406*7dd7cddfSDavid du Colombier break; 407*7dd7cddfSDavid du Colombier } 408*7dd7cddfSDavid du Colombier if(l == 0){ 409*7dd7cddfSDavid du Colombier *cp = '!'; 410*7dd7cddfSDavid du Colombier s_free(lpath); 411*7dd7cddfSDavid du Colombier return 1; 412*7dd7cddfSDavid du Colombier } 413*7dd7cddfSDavid du Colombier } 414*7dd7cddfSDavid du Colombier *cp = '!'; 415*7dd7cddfSDavid du Colombier } 416*7dd7cddfSDavid du Colombier s_free(lpath); 417*7dd7cddfSDavid du Colombier return 0; 418*7dd7cddfSDavid du Colombier } 419*7dd7cddfSDavid du Colombier 420*7dd7cddfSDavid du Colombier int 421*7dd7cddfSDavid du Colombier cidrcheck(char *cp) 422*7dd7cddfSDavid du Colombier { 423*7dd7cddfSDavid du Colombier char *p; 424*7dd7cddfSDavid du Colombier ulong a, m; 425*7dd7cddfSDavid du Colombier uchar addr[IPv4addrlen]; 426*7dd7cddfSDavid du Colombier uchar mask[IPv4addrlen]; 427*7dd7cddfSDavid du Colombier 428*7dd7cddfSDavid du Colombier if(peerip == 0) 429*7dd7cddfSDavid du Colombier return 0; 430*7dd7cddfSDavid du Colombier 431*7dd7cddfSDavid du Colombier /* parse a list of CIDR addresses comparing each to the peer IP addr */ 432*7dd7cddfSDavid du Colombier while(cp && *cp){ 433*7dd7cddfSDavid du Colombier v4parsecidr(addr, mask, cp); 434*7dd7cddfSDavid du Colombier a = nhgetl(addr); 435*7dd7cddfSDavid du Colombier m = nhgetl(mask); 436*7dd7cddfSDavid du Colombier /* 437*7dd7cddfSDavid du Colombier * if a mask isn't specified, we build a minimal mask 438*7dd7cddfSDavid du Colombier * instead of using the default mask for that net. in this 439*7dd7cddfSDavid du Colombier * case we never allow a class A mask (0xff000000). 440*7dd7cddfSDavid du Colombier */ 441*7dd7cddfSDavid du Colombier if(strchr(cp, '/') == 0){ 442*7dd7cddfSDavid du Colombier m = 0xff000000; 443*7dd7cddfSDavid du Colombier p = cp; 444*7dd7cddfSDavid du Colombier for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.')) 445*7dd7cddfSDavid du Colombier m = (m>>8)|0xff000000; 446*7dd7cddfSDavid du Colombier 447*7dd7cddfSDavid du Colombier /* force at least a class B */ 448*7dd7cddfSDavid du Colombier m |= 0xffff0000; 449*7dd7cddfSDavid du Colombier } 450*7dd7cddfSDavid du Colombier if((peerip&m) == a) 451*7dd7cddfSDavid du Colombier return 1; 452*7dd7cddfSDavid du Colombier cp += strlen(cp)+1; 453*7dd7cddfSDavid du Colombier } 454*7dd7cddfSDavid du Colombier return 0; 455*7dd7cddfSDavid du Colombier } 456*7dd7cddfSDavid du Colombier 457*7dd7cddfSDavid du Colombier char* 458*7dd7cddfSDavid du Colombier dumpfile(char *sender) 459*7dd7cddfSDavid du Colombier { 460*7dd7cddfSDavid du Colombier int i, fd; 461*7dd7cddfSDavid du Colombier ulong h; 462*7dd7cddfSDavid du Colombier static char buf[512]; 463*7dd7cddfSDavid du Colombier char *cp; 464*7dd7cddfSDavid du Colombier 465*7dd7cddfSDavid du Colombier if (sflag == 1){ 466*7dd7cddfSDavid du Colombier cp = ctime(time(0)); 467*7dd7cddfSDavid du Colombier cp[7] = 0; 468*7dd7cddfSDavid du Colombier if(cp[8] == ' ') 469*7dd7cddfSDavid du Colombier sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]); 470*7dd7cddfSDavid du Colombier else 471*7dd7cddfSDavid du Colombier sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]); 472*7dd7cddfSDavid du Colombier cp = buf+strlen(buf); 473*7dd7cddfSDavid du Colombier if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0) 474*7dd7cddfSDavid du Colombier return "/dev/null"; 475*7dd7cddfSDavid du Colombier h = 0; 476*7dd7cddfSDavid du Colombier while(*sender) 477*7dd7cddfSDavid du Colombier h = h*257 + *sender++; 478*7dd7cddfSDavid du Colombier for(i = 0; i < 50; i++){ 479*7dd7cddfSDavid du Colombier h += lrand(); 480*7dd7cddfSDavid du Colombier sprint(cp, "/%lud", h); 481*7dd7cddfSDavid du Colombier if(access(buf, 0) >= 0) 482*7dd7cddfSDavid du Colombier continue; 483*7dd7cddfSDavid du Colombier fd = syscreate(buf, ORDWR, 0600); 484*7dd7cddfSDavid du Colombier if(fd >= 0){ 485*7dd7cddfSDavid du Colombier if(debug) 486*7dd7cddfSDavid du Colombier fprint(2, "saving in %s\n", buf); 487*7dd7cddfSDavid du Colombier close(fd); 488*7dd7cddfSDavid du Colombier return buf; 489*7dd7cddfSDavid du Colombier } 490*7dd7cddfSDavid du Colombier } 491*7dd7cddfSDavid du Colombier } 492*7dd7cddfSDavid du Colombier return "/dev/null"; 493*7dd7cddfSDavid du Colombier } 494