*** srvrsmtp.c.dist Tue Jul 1 13:30:01 2003 --- srvrsmtp.c Wed Sep 17 15:42:01 2003 *************** *** 202,207 **** --- 202,223 ---- static char *CurSmtpClient; /* who's at the other end of channel */ + /* kai's changes to defaults */ + #define MAXHELOCOMMANDS 2 /* max HELO/EHLO commands before slowdown */ + #define MAXVRFYCOMMANDS 1 /* max VRFY/EXPN commands before slowdown */ + #define MAXETRNCOMMANDS 1 /* max ETRN commands before slowdown */ + #define MAXRCPTCOMMANDS 4 /* max RCPT TO commands before slowdown */ + /* custom additions */ + #define MAXBADRCPTCOMMANDS 5 /* max bad RCPT TO commands before we terminate */ + #define MINRCPTDELAY 1 /* min time to sleep() between RCPT TO lines (default tarpit) + WARNING: busy mailers should set this rather low, as this + keeps sendmail processes (and resources) tied up for a longer time. + */ + #define ADDRCPTDELAY 0.75 /* add n seconds delay per RCPT line over MAXRCPTCOMMANDS */ + #define BADRCPTDELAY 15.00 /* add n seconds delay per BAD RCPT line over MAXBADRCPTCOMMANDS */ + /* end custom additions */ + + #ifndef MAXBADCOMMANDS # define MAXBADCOMMANDS 25 /* maximum number of bad commands */ #endif /* ! MAXBADCOMMANDS */ *************** *** 399,404 **** --- 415,423 ---- volatile unsigned int n_etrn = 0; /* count of ETRN */ volatile unsigned int n_noop = 0; /* count of NOOP/VERB/etc */ volatile unsigned int n_helo = 0; /* count of HELO/EHLO */ + /* kai's change */ + volatile unsigned int n_rcpt = 0; /* count of RCPT TO */ + /* end kai's change */ volatile int save_sevenbitinput; bool ok; #if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL *************** *** 2358,2363 **** --- 2377,2402 ---- goto rcpt_done; } + /* Kai's changes to thwart dictionary attack */ + checksmtpattack(&n_badrcpts, 2, true, "RCPT dictionary-crack", e); + n_badrcpts--; /* stupid checksmtpattack counts up */ + + /* we will only run into this on the RCPT TO: line AFTER + the last bad one */ + if (n_badrcpts >= MAXBADRCPTCOMMANDS) { + message("550 Too many bad RCPT TO commands; closing connection; stop trespassing and cracking usernames on this host", MyHostName); + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; + goto doquit; + } + + /* avoid relay spamming via tarpit */ + sleep(MINRCPTDELAY); + /* good RCPT TO:'s or bad ones, we count them here */ + checksmtpattack(&n_rcpt, MAXRCPTCOMMANDS ,true , "RCPT", e); + /* end Kai's changes */ + + if (e->e_sendmode != SM_DELIVER) e->e_flags |= EF_VRFYONLY; *************** *** 2532,2542 **** --- 2571,2592 ---- if (Errors > 0) goto rcpt_done; + /* Kai: a failed recipient will not make it past the next + function call, the function never returns: we are counting + a potential bad RCPT TO: here, then deduct it */ + n_badrcpts++; + /* end of mod */ + /* save in recipient list after ESMTP mods */ a = recipient(a, &e->e_sendqueue, 0, e); if (Errors > 0) goto rcpt_done; + /* Kai's mod */ + /* ok, nothing happened, RCPT ok */ + n_badrcpts--; + /* end of mod */ + /* no errors during parsing, but might be a duplicate */ e->e_to = a->q_paddr; if (!QS_IS_BADADDR(a->q_state)) *************** *** 3408,3413 **** --- 3458,3467 ---- char *cname; ENVELOPE *e; { + /* kai's change */ + int delay_time; + /* end change */ + if (maxcount <= 0) /* no limit */ return (time_t) 0; *************** *** 3430,3437 **** s -= *pcounter / maxcount; if (waitnow) { ! (void) sleep(s); ! return 0; } return s; } --- 3484,3515 ---- s -= *pcounter / maxcount; if (waitnow) { ! /* kai's change */ ! if (!strcmp(cname,"RCPT spam")) /* tarpit functionality */ ! { ! delay_time = 1 + (*pcounter - maxcount) * ADDRCPTDELAY; /* add 1 to offset int */ ! if (delay_time + MINRCPTDELAY > 240) ! delay_time = 240 - MINRCPTDELAY; ! /* no more than 4 minutes of delay to comply with RFC 1123 5.3.2: 5 min max. */ ! sleep(delay_time); ! return 0; ! } ! ! if (!strcmp(cname,"RCPT dictionary-crack")) /* tarpit functionality */ ! { ! delay_time = (*pcounter - maxcount) * BADRCPTDELAY ; /* add 1 to offset int */ ! if (delay_time + MINRCPTDELAY > 240) ! delay_time = 240 - MINRCPTDELAY; ! /* no more than 4 minutes of delay to comply with RFC 1123 5.3.2:5 min max. */ ! /* we can't really comply with this, as we may have waited previously because of the RCPT spam delay */ ! sleep(delay_time); ! return 0; ! } else ! { ! /* end of kai's change */ ! (void) sleep(s); ! return 0; ! } } return s; }