17dd7cddfSDavid du Colombier #include "common.h" 27dd7cddfSDavid du Colombier #include "smtpd.h" 37dd7cddfSDavid du Colombier #include "ip.h" 47dd7cddfSDavid du Colombier 57dd7cddfSDavid du Colombier enum { 67dd7cddfSDavid du Colombier NORELAY = 0, 77dd7cddfSDavid du Colombier DNSVERIFY, 87dd7cddfSDavid du Colombier SAVEBLOCK, 97dd7cddfSDavid du Colombier DOMNAME, 107dd7cddfSDavid du Colombier OURNETS, 117dd7cddfSDavid du Colombier OURDOMS, 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier IP = 0, 147dd7cddfSDavid du Colombier STRING, 157dd7cddfSDavid du Colombier }; 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier 187dd7cddfSDavid du Colombier typedef struct Keyword Keyword; 197dd7cddfSDavid du Colombier 207dd7cddfSDavid du Colombier struct Keyword { 217dd7cddfSDavid du Colombier char *name; 227dd7cddfSDavid du Colombier int code; 237dd7cddfSDavid du Colombier }; 247dd7cddfSDavid du Colombier 257dd7cddfSDavid du Colombier static Keyword options[] = { 267dd7cddfSDavid du Colombier "norelay", NORELAY, 277dd7cddfSDavid du Colombier "verifysenderdom", DNSVERIFY, 287dd7cddfSDavid du Colombier "saveblockedmsg", SAVEBLOCK, 297dd7cddfSDavid du Colombier "defaultdomain", DOMNAME, 307dd7cddfSDavid du Colombier "ournets", OURNETS, 317dd7cddfSDavid du Colombier "ourdomains", OURDOMS, 327dd7cddfSDavid du Colombier 0, NONE, 337dd7cddfSDavid du Colombier }; 347dd7cddfSDavid du Colombier 357dd7cddfSDavid du Colombier static Keyword actions[] = { 367dd7cddfSDavid du Colombier "allow", ACCEPT, 377dd7cddfSDavid du Colombier "accept", ACCEPT, 387dd7cddfSDavid du Colombier "block", BLOCKED, 397dd7cddfSDavid du Colombier "deny", DENIED, 407dd7cddfSDavid du Colombier "dial", DIALUP, 417dd7cddfSDavid du Colombier "relay", RELAY, 427dd7cddfSDavid du Colombier 0, NONE, 437dd7cddfSDavid du Colombier }; 447dd7cddfSDavid du Colombier 457dd7cddfSDavid du Colombier static char* getline(Biobuf*); 467dd7cddfSDavid du Colombier 477dd7cddfSDavid du Colombier static int 487dd7cddfSDavid du Colombier findkey(char *val, Keyword *p) 497dd7cddfSDavid du Colombier { 507dd7cddfSDavid du Colombier 517dd7cddfSDavid du Colombier for(; p->name; p++) 527dd7cddfSDavid du Colombier if(strcmp(val, p->name) == 0) 537dd7cddfSDavid du Colombier break; 547dd7cddfSDavid du Colombier return p->code; 557dd7cddfSDavid du Colombier } 567dd7cddfSDavid du Colombier 577dd7cddfSDavid du Colombier void 587dd7cddfSDavid du Colombier getconf(void) 597dd7cddfSDavid du Colombier { 607dd7cddfSDavid du Colombier Biobuf *bp; 617dd7cddfSDavid du Colombier char *cp, *p; 627dd7cddfSDavid du Colombier String *s; 637dd7cddfSDavid du Colombier char buf[512]; 64*59cc4ca5SDavid du Colombier /* 65*59cc4ca5SDavid du Colombier ** let it fail on unix 66*59cc4ca5SDavid du Colombier ** 67*59cc4ca5SDavid du Colombier ** 68*59cc4ca5SDavid du Colombier ** if(hisaddr && *hisaddr){ 69*59cc4ca5SDavid du Colombier ** sprint(buf, "/mail/ratify/trusted/ip/%s#32\n", hisaddr); 70*59cc4ca5SDavid du Colombier ** if(access(buf,0) >= 0) 71*59cc4ca5SDavid du Colombier ** trusted++; 72*59cc4ca5SDavid du Colombier ** } 73*59cc4ca5SDavid du Colombier */ 747dd7cddfSDavid du Colombier 757dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/smtpd.conf", UPASLIB); 767dd7cddfSDavid du Colombier bp = sysopen(buf, "r", 0); 777dd7cddfSDavid du Colombier if(bp == 0) 787dd7cddfSDavid du Colombier return; 797dd7cddfSDavid du Colombier 807dd7cddfSDavid du Colombier for(;;){ 817dd7cddfSDavid du Colombier cp = getline(bp); 827dd7cddfSDavid du Colombier if(cp == 0) 837dd7cddfSDavid du Colombier break; 847dd7cddfSDavid du Colombier p = cp+strlen(cp)+1; 857dd7cddfSDavid du Colombier switch(findkey(cp, options)){ 867dd7cddfSDavid du Colombier case NORELAY: 877dd7cddfSDavid du Colombier if(fflag == 0 && strcmp(p, "on") == 0) 887dd7cddfSDavid du Colombier fflag++; 897dd7cddfSDavid du Colombier break; 907dd7cddfSDavid du Colombier case DNSVERIFY: 917dd7cddfSDavid du Colombier if(rflag == 0 && strcmp(p, "on") == 0) 927dd7cddfSDavid du Colombier rflag++; 937dd7cddfSDavid du Colombier break; 947dd7cddfSDavid du Colombier case SAVEBLOCK: 957dd7cddfSDavid du Colombier if(sflag == 0 && strcmp(p, "on") == 0) 967dd7cddfSDavid du Colombier sflag++; 977dd7cddfSDavid du Colombier break; 987dd7cddfSDavid du Colombier case DOMNAME: 997dd7cddfSDavid du Colombier if(dom == 0) 1007dd7cddfSDavid du Colombier dom = strdup(p); 1017dd7cddfSDavid du Colombier break; 1027dd7cddfSDavid du Colombier case OURNETS: 1037dd7cddfSDavid du Colombier if (trusted == 0) 1047dd7cddfSDavid du Colombier trusted = cidrcheck(p); 1057dd7cddfSDavid du Colombier break; 1067dd7cddfSDavid du Colombier case OURDOMS: 1077dd7cddfSDavid du Colombier while(*p){ 1087dd7cddfSDavid du Colombier s = s_new(); 1097dd7cddfSDavid du Colombier s_append(s, p); 1107dd7cddfSDavid du Colombier listadd(&ourdoms, s); 1117dd7cddfSDavid du Colombier p += strlen(p)+1; 1127dd7cddfSDavid du Colombier } 1137dd7cddfSDavid du Colombier break; 1147dd7cddfSDavid du Colombier default: 1157dd7cddfSDavid du Colombier break; 1167dd7cddfSDavid du Colombier } 1177dd7cddfSDavid du Colombier } 1187dd7cddfSDavid du Colombier sysclose(bp); 1197dd7cddfSDavid du Colombier } 1207dd7cddfSDavid du Colombier 1217dd7cddfSDavid du Colombier /* 1227dd7cddfSDavid du Colombier * match a user name. the only meta-char is '*' which matches all 1237dd7cddfSDavid du Colombier * characters. we only allow it as "*", which matches anything or 1247dd7cddfSDavid du Colombier * an * at the end of the name (e.g., "username*") which matches 1257dd7cddfSDavid du Colombier * trailing characters. 1267dd7cddfSDavid du Colombier */ 1277dd7cddfSDavid du Colombier static int 1287dd7cddfSDavid du Colombier usermatch(char *pathuser, char *specuser) 1297dd7cddfSDavid du Colombier { 1307dd7cddfSDavid du Colombier int n; 1317dd7cddfSDavid du Colombier 1327dd7cddfSDavid du Colombier n = strlen(specuser)-1; 1337dd7cddfSDavid du Colombier if(specuser[n] == '*'){ 1347dd7cddfSDavid du Colombier if(n == 0) /* match everything */ 1357dd7cddfSDavid du Colombier return 0; 1367dd7cddfSDavid du Colombier return strncmp(pathuser, specuser, n); 1377dd7cddfSDavid du Colombier } 1387dd7cddfSDavid du Colombier return strcmp(pathuser, specuser); 1397dd7cddfSDavid du Colombier } 1407dd7cddfSDavid du Colombier 1417dd7cddfSDavid du Colombier static int 1427dd7cddfSDavid du Colombier dommatch(char *pathdom, char *specdom) 1437dd7cddfSDavid du Colombier { 1447dd7cddfSDavid du Colombier int n; 1457dd7cddfSDavid du Colombier 1467dd7cddfSDavid du Colombier if (*specdom == '*'){ 1477dd7cddfSDavid du Colombier if (specdom[1] == '.' && specdom[2]){ 1487dd7cddfSDavid du Colombier specdom += 2; 1497dd7cddfSDavid du Colombier n = strlen(pathdom)-strlen(specdom); 1507dd7cddfSDavid du Colombier if(n == 0 || (n > 0 && pathdom[n-1] == '.')) 1517dd7cddfSDavid du Colombier return strcmp(pathdom+n, specdom); 1527dd7cddfSDavid du Colombier return n; 1537dd7cddfSDavid du Colombier } 1547dd7cddfSDavid du Colombier } 1557dd7cddfSDavid du Colombier return strcmp(pathdom, specdom); 1567dd7cddfSDavid du Colombier } 1577dd7cddfSDavid du Colombier 1587dd7cddfSDavid du Colombier /* 1597dd7cddfSDavid du Colombier * match path components to prohibited domain & user specifications. patterns include: 1607dd7cddfSDavid du Colombier * domain, domain! or domain!* - all users in domain 1617dd7cddfSDavid du Colombier * *.domain, *.domain! or *.domain!* - all users in domain and its subdomains 1627dd7cddfSDavid du Colombier * !user or *!user - user in all domains 1637dd7cddfSDavid du Colombier * domain!user - user in domain 1647dd7cddfSDavid du Colombier * *.domain!user - user in domain and its subdomains 1657dd7cddfSDavid du Colombier * 1667dd7cddfSDavid du Colombier * if "user" has a trailing '*', it matches all user names beginning with "user" 1677dd7cddfSDavid du Colombier * 1687dd7cddfSDavid du Colombier * there are special semantics for the "domain, domain! or domain!*" specifications: 1697dd7cddfSDavid du Colombier * the first two forms match when the domain is anywhere in at list of source-routed 1707dd7cddfSDavid du Colombier * domains while the latter matches only when the domain is the last hop. the same is 1717dd7cddfSDavid du Colombier * true for the *.domain!* form of the pattern. 1727dd7cddfSDavid du Colombier */ 1737dd7cddfSDavid du Colombier static int 1747dd7cddfSDavid du Colombier accountmatch(char *spec, List *doms, char *user) 1757dd7cddfSDavid du Colombier { 1767dd7cddfSDavid du Colombier char *cp, *p; 1777dd7cddfSDavid du Colombier int i, n; 1787dd7cddfSDavid du Colombier Link *l; 1797dd7cddfSDavid du Colombier 1807dd7cddfSDavid du Colombier static char *dangerous[] = { "*", "!", "*!", "!*", "*!*", 0 }; 1817dd7cddfSDavid du Colombier 1827dd7cddfSDavid du Colombier for(; *spec; spec += n){ 1837dd7cddfSDavid du Colombier n = strlen(spec)+1; 1847dd7cddfSDavid du Colombier 1857dd7cddfSDavid du Colombier /* rule out dangerous patterns */ 1867dd7cddfSDavid du Colombier for (i = 0; dangerous[i]; i++) 1877dd7cddfSDavid du Colombier if(strcmp(spec, dangerous[i])== 0) 1887dd7cddfSDavid du Colombier break; 1897dd7cddfSDavid du Colombier if(dangerous[i]) 1907dd7cddfSDavid du Colombier continue; 1917dd7cddfSDavid du Colombier 1927dd7cddfSDavid du Colombier p = 0; 1937dd7cddfSDavid du Colombier cp = strchr(spec, '!'); 1947dd7cddfSDavid du Colombier if(cp){ 1957dd7cddfSDavid du Colombier *cp++ = 0; 1967dd7cddfSDavid du Colombier if(*cp) 197*59cc4ca5SDavid du Colombier if(strcmp(cp, "*")) /* rule out "!*" */ 1987dd7cddfSDavid du Colombier p = cp; 1997dd7cddfSDavid du Colombier } 2007dd7cddfSDavid du Colombier 2017dd7cddfSDavid du Colombier if(p == 0){ /* no user field - domain match only */ 2027dd7cddfSDavid du Colombier for(l = doms->first; l; l = l->next) 2037dd7cddfSDavid du Colombier if(dommatch(s_to_c(l->p), spec) == 0) 2047dd7cddfSDavid du Colombier return 1; 2057dd7cddfSDavid du Colombier } else { 2067dd7cddfSDavid du Colombier /* check for "!user", "*!user" or "domain!user" */ 2077dd7cddfSDavid du Colombier if(usermatch(user, p) == 0){ 2087dd7cddfSDavid du Colombier if(*spec == 0 || strcmp(spec, "*") == 0) 2097dd7cddfSDavid du Colombier return 1; 2107dd7cddfSDavid du Colombier if(doms->last && dommatch(s_to_c(doms->last->p), spec) == 0) 2117dd7cddfSDavid du Colombier return 1; 2127dd7cddfSDavid du Colombier } 2137dd7cddfSDavid du Colombier } 2147dd7cddfSDavid du Colombier } 2157dd7cddfSDavid du Colombier return 0; 2167dd7cddfSDavid du Colombier } 2177dd7cddfSDavid du Colombier 2187dd7cddfSDavid du Colombier /* 2197dd7cddfSDavid du Colombier * we risk reparsing the file of blocked addresses if there are 2207dd7cddfSDavid du Colombier * multiple senders or if the peer does a transaction and then a RSET 2217dd7cddfSDavid du Colombier * followed by another transaction. we believe this happens rarely, 2227dd7cddfSDavid du Colombier * but we cache the last sender to try to minimize the overhead. we 2237dd7cddfSDavid du Colombier * also cache whether we rejected a previous transaction based on 2247dd7cddfSDavid du Colombier * ip address, since this never changes. 2257dd7cddfSDavid du Colombier */ 2267dd7cddfSDavid du Colombier int 2277dd7cddfSDavid du Colombier blocked(String *path) 2287dd7cddfSDavid du Colombier { 2297dd7cddfSDavid du Colombier char buf[512], *cp, *p, *user; 2307dd7cddfSDavid du Colombier Biobuf *bp; 2317dd7cddfSDavid du Colombier int action, type, ipallow; 2327dd7cddfSDavid du Colombier List doms; 2337dd7cddfSDavid du Colombier String *s, *lpath; 2347dd7cddfSDavid du Colombier 2357dd7cddfSDavid du Colombier static String *lastsender; 2367dd7cddfSDavid du Colombier static int lastret, blockedbyip; 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier if(debug) 2397dd7cddfSDavid du Colombier fprint(2, "blocked(%s)\n", s_to_c(path)); 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier if(blockedbyip) 2427dd7cddfSDavid du Colombier return lastret; 2437dd7cddfSDavid du Colombier 2447dd7cddfSDavid du Colombier if(lastsender){ 2457dd7cddfSDavid du Colombier if(strcmp(s_to_c(lastsender), s_to_c(path)) == 0) 2467dd7cddfSDavid du Colombier return lastret; 2477dd7cddfSDavid du Colombier s_free(lastsender); 2487dd7cddfSDavid du Colombier lastsender = 0; 2497dd7cddfSDavid du Colombier } 2507dd7cddfSDavid du Colombier 2517dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/blocked", UPASLIB); 2527dd7cddfSDavid du Colombier bp = sysopen(buf, "r", 0); 2537dd7cddfSDavid du Colombier if(bp == 0) 2547dd7cddfSDavid du Colombier return ACCEPT; 2557dd7cddfSDavid du Colombier 2567dd7cddfSDavid du Colombier lpath = s_copy(s_to_c(s_restart(path))); /* convert to LC */ 2577dd7cddfSDavid du Colombier for(cp = s_to_c(lpath); *cp; cp++) 2587dd7cddfSDavid du Colombier *cp = tolower(*cp); 2597dd7cddfSDavid du Colombier 2607dd7cddfSDavid du Colombier /* parse the path into a list of domains and a user */ 2617dd7cddfSDavid du Colombier doms.first = doms.last = 0; 2627dd7cddfSDavid du Colombier p = s_to_c(lpath); 2637dd7cddfSDavid du Colombier while (cp = strchr(p, '!')){ 2647dd7cddfSDavid du Colombier *cp = 0; 2657dd7cddfSDavid du Colombier s = s_new(); 2667dd7cddfSDavid du Colombier s_append(s, p); 2677dd7cddfSDavid du Colombier *cp = '!'; 2687dd7cddfSDavid du Colombier listadd(&doms, s); 2697dd7cddfSDavid du Colombier p = cp+1; 2707dd7cddfSDavid du Colombier } 2717dd7cddfSDavid du Colombier user = p; 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier /* 2747dd7cddfSDavid du Colombier * line format: [*]VERB param 1, ... param n, where '*' indicates 2757dd7cddfSDavid du Colombier * params are path names; if not present, params are ip addresses in 2767dd7cddfSDavid du Colombier * CIDR format. 2777dd7cddfSDavid du Colombier */ 2787dd7cddfSDavid du Colombier ipallow = 0; 2797dd7cddfSDavid du Colombier for(;;){ 2807dd7cddfSDavid du Colombier action = ACCEPT; 2817dd7cddfSDavid du Colombier cp = getline(bp); 2827dd7cddfSDavid du Colombier if(cp == 0) 2837dd7cddfSDavid du Colombier break; 2847dd7cddfSDavid du Colombier type = *cp; 2857dd7cddfSDavid du Colombier if(type == '*') { 2867dd7cddfSDavid du Colombier cp++; 2877dd7cddfSDavid du Colombier if(*cp == 0) 2887dd7cddfSDavid du Colombier cp++; 2897dd7cddfSDavid du Colombier } 2907dd7cddfSDavid du Colombier action = findkey(cp, actions); 2917dd7cddfSDavid du Colombier if (action == NONE) 2927dd7cddfSDavid du Colombier continue; 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier cp += strlen(cp)+1; 2957dd7cddfSDavid du Colombier if(type == '*') { 2967dd7cddfSDavid du Colombier if(accountmatch(cp, &doms, user)) 2977dd7cddfSDavid du Colombier break; 2987dd7cddfSDavid du Colombier } else { 2997dd7cddfSDavid du Colombier /* 3007dd7cddfSDavid du Colombier * An ACCEPT match on IP addresses overrides all later 3017dd7cddfSDavid du Colombier * blocks on IP address but not blocks on domain or user names 3027dd7cddfSDavid du Colombier */ 3037dd7cddfSDavid du Colombier if(ipallow == 0 && cidrcheck(cp)) 3047dd7cddfSDavid du Colombier if(action == ACCEPT) 3057dd7cddfSDavid du Colombier ipallow = 1; 3067dd7cddfSDavid du Colombier else { 3077dd7cddfSDavid du Colombier blockedbyip = 1; 3087dd7cddfSDavid du Colombier break; 3097dd7cddfSDavid du Colombier } 3107dd7cddfSDavid du Colombier } 3117dd7cddfSDavid du Colombier } 3127dd7cddfSDavid du Colombier sysclose(bp); 3137dd7cddfSDavid du Colombier listfree(&doms); 3147dd7cddfSDavid du Colombier lastsender = s_copy(s_to_c(s_restart(path))); 3157dd7cddfSDavid du Colombier s_free(lpath); 3167dd7cddfSDavid du Colombier lastret = action; 3177dd7cddfSDavid du Colombier return action; 3187dd7cddfSDavid du Colombier } 3197dd7cddfSDavid du Colombier 3207dd7cddfSDavid du Colombier /* 3217dd7cddfSDavid du Colombier * get a canonicalized line: a string of null-terminated lower-case 3227dd7cddfSDavid du Colombier * tokens with a two null bytes at the end. 3237dd7cddfSDavid du Colombier */ 3247dd7cddfSDavid du Colombier static char* 3257dd7cddfSDavid du Colombier getline(Biobuf *bp) 3267dd7cddfSDavid du Colombier { 3277dd7cddfSDavid du Colombier char c, *cp, *p, *q; 3287dd7cddfSDavid du Colombier int n; 3297dd7cddfSDavid du Colombier 3307dd7cddfSDavid du Colombier static char *buf; 3317dd7cddfSDavid du Colombier static int bufsize; 3327dd7cddfSDavid du Colombier 3337dd7cddfSDavid du Colombier for(;;){ 3347dd7cddfSDavid du Colombier cp = Brdline(bp, '\n'); 3357dd7cddfSDavid du Colombier if(cp == 0) 3367dd7cddfSDavid du Colombier return 0; 3377dd7cddfSDavid du Colombier n = Blinelen(bp); 3387dd7cddfSDavid du Colombier cp[n-1] = 0; 3397dd7cddfSDavid du Colombier if(buf == 0 || bufsize < n+1){ 3407dd7cddfSDavid du Colombier bufsize += 512; 3417dd7cddfSDavid du Colombier if(bufsize < n+1) 3427dd7cddfSDavid du Colombier bufsize = n+1; 3437dd7cddfSDavid du Colombier buf = realloc(buf, bufsize); 3447dd7cddfSDavid du Colombier if(buf == 0) 3457dd7cddfSDavid du Colombier break; 3467dd7cddfSDavid du Colombier } 3477dd7cddfSDavid du Colombier q = buf; 3487dd7cddfSDavid du Colombier for (p = cp; *p; p++){ 3497dd7cddfSDavid du Colombier c = *p; 3507dd7cddfSDavid du Colombier if(c == '\\' && p[1]) /* we don't allow \<newline> */ 3517dd7cddfSDavid du Colombier c = *++p; 3527dd7cddfSDavid du Colombier else 3537dd7cddfSDavid du Colombier if(c == '#') 3547dd7cddfSDavid du Colombier break; 3557dd7cddfSDavid du Colombier else 3567dd7cddfSDavid du Colombier if(c == ' ' || c == '\t' || c == ',') 3577dd7cddfSDavid du Colombier if(q == buf || q[-1] == 0) 3587dd7cddfSDavid du Colombier continue; 3597dd7cddfSDavid du Colombier else 3607dd7cddfSDavid du Colombier c = 0; 3617dd7cddfSDavid du Colombier *q++ = tolower(c); 3627dd7cddfSDavid du Colombier } 3637dd7cddfSDavid du Colombier if(q != buf){ 3647dd7cddfSDavid du Colombier if(q[-1]) 3657dd7cddfSDavid du Colombier *q++ = 0; 3667dd7cddfSDavid du Colombier *q = 0; 3677dd7cddfSDavid du Colombier break; 3687dd7cddfSDavid du Colombier } 3697dd7cddfSDavid du Colombier } 3707dd7cddfSDavid du Colombier return buf; 3717dd7cddfSDavid du Colombier } 3727dd7cddfSDavid du Colombier 3737dd7cddfSDavid du Colombier int 3747dd7cddfSDavid du Colombier forwarding(String *path) 3757dd7cddfSDavid du Colombier { 3767dd7cddfSDavid du Colombier char *cp, *s; 3777dd7cddfSDavid du Colombier String *lpath; 3787dd7cddfSDavid du Colombier Link *l; 3797dd7cddfSDavid du Colombier 3807dd7cddfSDavid du Colombier if(debug) 3817dd7cddfSDavid du Colombier fprint(2, "forwarding(%s)\n", s_to_c(path)); 3827dd7cddfSDavid du Colombier 3837dd7cddfSDavid du Colombier /* first check if they want loopback */ 3847dd7cddfSDavid du Colombier 3857dd7cddfSDavid du Colombier lpath = s_copy(s_to_c(s_restart(path))); 3867dd7cddfSDavid du Colombier if(hisaddr && *hisaddr){ 3877dd7cddfSDavid du Colombier cp = s_to_c(lpath); 3887dd7cddfSDavid du Colombier if(strncmp(cp, "[]!", 3) == 0){ 3897dd7cddfSDavid du Colombier found: 3907dd7cddfSDavid du Colombier s_append(path, "["); 3917dd7cddfSDavid du Colombier s_append(path, hisaddr); 3927dd7cddfSDavid du Colombier s_append(path, "]!"); 3937dd7cddfSDavid du Colombier s_append(path, cp+3); 3947dd7cddfSDavid du Colombier s_terminate(path); 3957dd7cddfSDavid du Colombier s_free(lpath); 3967dd7cddfSDavid du Colombier return 0; 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier cp = strchr(cp,'!'); /* skip our domain and check next */ 3997dd7cddfSDavid du Colombier if(cp++ && strncmp(cp, "[]!", 3) == 0) 4007dd7cddfSDavid du Colombier goto found; 4017dd7cddfSDavid du Colombier } 4027dd7cddfSDavid du Colombier /* if mail is from a trusted subnet, allow it to forward*/ 4037dd7cddfSDavid du Colombier if(trusted) { 4047dd7cddfSDavid du Colombier s_free(lpath); 4057dd7cddfSDavid du Colombier return 0; 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier 4087dd7cddfSDavid du Colombier /* sender is untrusted; ensure receiver is in one of our domains */ 4097dd7cddfSDavid du Colombier for(cp = s_to_c(lpath); *cp; cp++) /* convert receiver lc */ 4107dd7cddfSDavid du Colombier *cp = tolower(*cp); 4117dd7cddfSDavid du Colombier 4127dd7cddfSDavid du Colombier for(s = s_to_c(lpath); cp = strchr(s, '!'); s = cp+1){ 4137dd7cddfSDavid du Colombier *cp = 0; 4147dd7cddfSDavid du Colombier if(strchr(s, '.')){ 4157dd7cddfSDavid du Colombier for(l = ourdoms.first; l; l = l->next){ 4167dd7cddfSDavid du Colombier if(dommatch(s, s_to_c(l->p)) == 0) 4177dd7cddfSDavid du Colombier break; 4187dd7cddfSDavid du Colombier } 4197dd7cddfSDavid du Colombier if(l == 0){ 4207dd7cddfSDavid du Colombier *cp = '!'; 4217dd7cddfSDavid du Colombier s_free(lpath); 4227dd7cddfSDavid du Colombier return 1; 4237dd7cddfSDavid du Colombier } 4247dd7cddfSDavid du Colombier } 4257dd7cddfSDavid du Colombier *cp = '!'; 4267dd7cddfSDavid du Colombier } 4277dd7cddfSDavid du Colombier s_free(lpath); 4287dd7cddfSDavid du Colombier return 0; 4297dd7cddfSDavid du Colombier } 4307dd7cddfSDavid du Colombier 4317dd7cddfSDavid du Colombier int 4327dd7cddfSDavid du Colombier cidrcheck(char *cp) 4337dd7cddfSDavid du Colombier { 4347dd7cddfSDavid du Colombier char *p; 4357dd7cddfSDavid du Colombier ulong a, m; 4367dd7cddfSDavid du Colombier uchar addr[IPv4addrlen]; 4377dd7cddfSDavid du Colombier uchar mask[IPv4addrlen]; 4387dd7cddfSDavid du Colombier 4397dd7cddfSDavid du Colombier if(peerip == 0) 4407dd7cddfSDavid du Colombier return 0; 4417dd7cddfSDavid du Colombier 4427dd7cddfSDavid du Colombier /* parse a list of CIDR addresses comparing each to the peer IP addr */ 4437dd7cddfSDavid du Colombier while(cp && *cp){ 4447dd7cddfSDavid du Colombier v4parsecidr(addr, mask, cp); 4457dd7cddfSDavid du Colombier a = nhgetl(addr); 4467dd7cddfSDavid du Colombier m = nhgetl(mask); 4477dd7cddfSDavid du Colombier /* 4487dd7cddfSDavid du Colombier * if a mask isn't specified, we build a minimal mask 4497dd7cddfSDavid du Colombier * instead of using the default mask for that net. in this 4507dd7cddfSDavid du Colombier * case we never allow a class A mask (0xff000000). 4517dd7cddfSDavid du Colombier */ 4527dd7cddfSDavid du Colombier if(strchr(cp, '/') == 0){ 4537dd7cddfSDavid du Colombier m = 0xff000000; 4547dd7cddfSDavid du Colombier p = cp; 4557dd7cddfSDavid du Colombier for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.')) 4567dd7cddfSDavid du Colombier m = (m>>8)|0xff000000; 4577dd7cddfSDavid du Colombier 4587dd7cddfSDavid du Colombier /* force at least a class B */ 4597dd7cddfSDavid du Colombier m |= 0xffff0000; 4607dd7cddfSDavid du Colombier } 4617dd7cddfSDavid du Colombier if((peerip&m) == a) 4627dd7cddfSDavid du Colombier return 1; 4637dd7cddfSDavid du Colombier cp += strlen(cp)+1; 4647dd7cddfSDavid du Colombier } 4657dd7cddfSDavid du Colombier return 0; 4667dd7cddfSDavid du Colombier } 4677dd7cddfSDavid du Colombier 4687dd7cddfSDavid du Colombier char* 4697dd7cddfSDavid du Colombier dumpfile(char *sender) 4707dd7cddfSDavid du Colombier { 4717dd7cddfSDavid du Colombier int i, fd; 4727dd7cddfSDavid du Colombier ulong h; 4737dd7cddfSDavid du Colombier static char buf[512]; 4747dd7cddfSDavid du Colombier char *cp; 4757dd7cddfSDavid du Colombier 4767dd7cddfSDavid du Colombier if (sflag == 1){ 4777dd7cddfSDavid du Colombier cp = ctime(time(0)); 4787dd7cddfSDavid du Colombier cp[7] = 0; 4797dd7cddfSDavid du Colombier if(cp[8] == ' ') 4807dd7cddfSDavid du Colombier sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]); 4817dd7cddfSDavid du Colombier else 4827dd7cddfSDavid du Colombier sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]); 4837dd7cddfSDavid du Colombier cp = buf+strlen(buf); 4847dd7cddfSDavid du Colombier if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0) 4857dd7cddfSDavid du Colombier return "/dev/null"; 4867dd7cddfSDavid du Colombier h = 0; 4877dd7cddfSDavid du Colombier while(*sender) 4887dd7cddfSDavid du Colombier h = h*257 + *sender++; 4897dd7cddfSDavid du Colombier for(i = 0; i < 50; i++){ 4907dd7cddfSDavid du Colombier h += lrand(); 4917dd7cddfSDavid du Colombier sprint(cp, "/%lud", h); 4927dd7cddfSDavid du Colombier if(access(buf, 0) >= 0) 4937dd7cddfSDavid du Colombier continue; 494*59cc4ca5SDavid du Colombier fd = syscreate(buf, ORDWR, 0666); 4957dd7cddfSDavid du Colombier if(fd >= 0){ 4967dd7cddfSDavid du Colombier if(debug) 4977dd7cddfSDavid du Colombier fprint(2, "saving in %s\n", buf); 4987dd7cddfSDavid du Colombier close(fd); 4997dd7cddfSDavid du Colombier return buf; 5007dd7cddfSDavid du Colombier } 5017dd7cddfSDavid du Colombier } 5027dd7cddfSDavid du Colombier } 5037dd7cddfSDavid du Colombier return "/dev/null"; 5047dd7cddfSDavid du Colombier } 505