Skip to content

Commit

Permalink
[targrey] Part 7.5: Implement fall-back mechanism for ACLs with "tarp…
Browse files Browse the repository at this point in the history
…it" (Needs to reconsider several small design decisions)
  • Loading branch information
Ryo Onodera committed Sep 2, 2009
1 parent 6235779 commit b0a0392
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 38 deletions.
4 changes: 3 additions & 1 deletion acl.c
Expand Up @@ -562,7 +562,9 @@ acl_tarpit_filter(ad, stage, ap, priv)
struct mlfi_priv *priv;
{
ap->ap_tarpit = ad->time;
return 1;
return pending_check_tarpit(SA(&priv->priv_addr), priv->priv_addrlen,
priv->priv_from, priv->priv_cur_rcpt,
ad->time);
}


Expand Down
8 changes: 5 additions & 3 deletions dump.c
Expand Up @@ -280,12 +280,14 @@ dump_perform(final)
dump_header(dump);
greylisted_count = pending_textdump(dump);

done = greylisted_count.pending + greylisted_count.autowhite;
done = greylisted_count.pending + greylisted_count.autowhite +
greylisted_count.tarpit;

fprintf(dump, "#\n# Summary: %d records, %d greylisted, "
"%d whitelisted\n#\n", done,
"%d whitelisted, %d tarpitted\n#\n", done,
greylisted_count.pending,
greylisted_count.autowhite);
greylisted_count.autowhite,
greylisted_count.tarpit);

/*
* Ensure that the data is really flushed to disk.
Expand Down
2 changes: 2 additions & 0 deletions dump_lex.l
Expand Up @@ -16,6 +16,7 @@ void_email "<>"
comment #.*$
blank [ \t]{1,}
auto [Aa][Uu][Tt][Oo]
tarpit [Tt][Aa][Rr][Pp][Ii][Tt]

%{
#include "config.h"
Expand Down Expand Up @@ -44,6 +45,7 @@ auto [Aa][Uu][Tt][Oo]

%%
{auto} { return AUTO; }
{tarpit} { return TARPIT; }
{blank}
{comment}
{ipaddr} {
Expand Down
25 changes: 20 additions & 5 deletions dump_yacc.y
@@ -1,4 +1,4 @@
%token IPADDR IP6ADDR EMAIL TIME AUTO GARBAGE
%token IPADDR IP6ADDR EMAIL TIME AUTO TARPIT GARBAGE

%{
#include "config.h"
Expand Down Expand Up @@ -41,18 +41,19 @@ void dump_error(char *);
%%
lines : lines greyentry '\n'
| lines autoentry '\n'
| lines tarpitentry '\n'
| lines '\n'
| error '\n' { yyerrok; }
|
;
greyentry : IPADDR EMAIL EMAIL TIME {
pending_get(SA(&$1), sizeof(struct sockaddr_in), $2,
$3, $4, T_PENDING);
$3, $4, 0, T_PENDING);
}
| IP6ADDR EMAIL EMAIL TIME {
#ifdef AF_INET6
pending_get(SA(&$1), sizeof(struct sockaddr_in6), $2,
$3, $4, T_PENDING);
$3, $4, 0, T_PENDING);
#else
printf("IPv6 is not supported, ignore line %d\n",
dump_line);
Expand All @@ -61,12 +62,26 @@ greyentry : IPADDR EMAIL EMAIL TIME {
;
autoentry : IPADDR EMAIL EMAIL TIME AUTO {
pending_get(SA(&$1), sizeof(struct sockaddr_in), $2,
$3, $4, T_AUTOWHITE);
$3, $4, 0, T_AUTOWHITE);
}
| IP6ADDR EMAIL EMAIL TIME AUTO {
#ifdef AF_INET6
pending_get(SA(&$1), sizeof(struct sockaddr_in6), $2,
$3, $4, T_AUTOWHITE);
$3, $4, 0, T_AUTOWHITE);
#else
printf("IPv6 is not supported, ignore line %d\n",
dump_line);
#endif
}
;
tarpitentry : IPADDR EMAIL EMAIL TIME TIME TARPIT {
pending_get(SA(&$1), sizeof(struct sockaddr_in), $2,
$3, $4, $5, T_TARPIT);
}
| IP6ADDR EMAIL EMAIL TIME TIME TARPIT {
#ifdef AF_INET6
pending_get(SA(&$1), sizeof(struct sockaddr_in6), $2,
$3, $4, $5, T_TARPIT);
#else
printf("IPv6 is not supported, ignore line %d\n",
dump_line);
Expand Down
3 changes: 2 additions & 1 deletion milter-greylist.c
Expand Up @@ -737,6 +737,7 @@ real_envrcpt(ctx, envrcpt)
priv->priv_total_tarpitted += sleep_duration;
priv->priv_after_tarpit = after_tarpit;

printf("sleeP! %ld\n", sleep_duration);
sleep(sleep_duration);
}
priv->priv_sr.sr_elapsed = 0;
Expand Down Expand Up @@ -1306,7 +1307,7 @@ real_close(ctx)
rcpt = priv->priv_rcpt.lh_first;
pending_force(SA(&priv->priv_addr), priv->priv_addrlen,
priv->priv_from, rcpt->r_addr,
priv->priv_sr.sr_autowhite, FORCE_REMOVE);
priv->priv_sr.sr_tarpit, FORCE_TARPIT);
}
smtp_reply_free(&priv->priv_sr);

Expand Down
161 changes: 137 additions & 24 deletions pending.c
Expand Up @@ -119,7 +119,8 @@ pending_timeout(pending, now)
long pt = pending->p_tv.tv_sec;
long nt = now->tv_sec;

if ((pending->p_type == T_PENDING && nt - pt > conf.c_timeout) ||
if (((pending->p_type == T_PENDING || pending->p_type == T_TARPIT)
&& nt - pt > conf.c_timeout) ||
(pending->p_type == T_AUTOWHITE && pt < nt)) {
if (conf.c_debug || conf.c_logexpired) {
mg_log(LOG_DEBUG,
Expand All @@ -137,12 +138,13 @@ pending_timeout(pending, now)

/* pending_lock must be locked */
struct pending *
pending_get(sa, salen, from, rcpt, date, tupletype)
pending_get(sa, salen, from, rcpt, date, tarpit, tupletype)
struct sockaddr *sa;
socklen_t salen;
char *from;
char *rcpt;
time_t date;
time_t tarpit;
tuple_t tupletype;
{
struct pending *pending;
Expand All @@ -155,6 +157,7 @@ pending_get(sa, salen, from, rcpt, date, tupletype)

bzero((void *)pending, sizeof(pending));
pending->p_tv.tv_sec = date;
pending->p_tarpit.tv_sec = tarpit;
pending->p_type = tupletype;

if ((pending->p_sa = malloc(salen)) == NULL) {
Expand Down Expand Up @@ -250,7 +253,7 @@ pending_put(pending, aw_date)
/*
* change greylist entry to autowhite
*/
pending->p_type=T_AUTOWHITE;
pending->p_type = T_AUTOWHITE;
pending->p_tv.tv_sec = aw_date;
} else {
/*
Expand Down Expand Up @@ -331,8 +334,8 @@ pending_check(sa, salen, from, rcpt, remaining, elapsed, queueid, delay, aw)
struct pending *next;
struct timeval tv;
time_t now;
time_t rest;
time_t accepted;
time_t rest = -1; //XXX
time_t accepted = 0; //XXX
int dirty = 0;
int first = 0;
struct pending_bucket *b;
Expand Down Expand Up @@ -431,6 +434,14 @@ pending_check(sa, salen, from, rcpt, remaining, elapsed, queueid, delay, aw)
}
break;

case T_TARPIT:
if (ip_match(sa, pending->p_sa, mask) &&
(strcmp(from, pending->p_from) == 0) &&
(strcmp(rcpt, pending->p_rcpt) == 0)) {
first = 1; // already the acl matched in the preceeding state. we need to tarpit in this case....
goto out;
}
break;
default: /* Error */
break;
}
Expand All @@ -442,7 +453,7 @@ pending_check(sa, salen, from, rcpt, remaining, elapsed, queueid, delay, aw)
*/
accepted = now + delay;
rest = 0;
pending = pending_get(sa, salen, from, rcpt, accepted, T_PENDING);
pending = pending_get(sa, salen, from, rcpt, accepted, 0, T_PENDING);
if (pending) {
++dirty;
peer_create(pending);
Expand All @@ -463,16 +474,86 @@ pending_check(sa, salen, from, rcpt, remaining, elapsed, queueid, delay, aw)
dump_flush();
}

if (rest <= 0)
if (first)
return T_CREATED;
else if (rest <= 0)
return T_PENDING;
else
return first ? T_CREATED : T_NONE;
return T_NONE;

out_aw:
PENDING_UNLOCK;
return T_AUTOWHITE;
}

int pending_check_tarpit(sa, salen, from, rcpt, tarpit)
struct sockaddr *sa;
socklen_t salen;
char *from;
char *rcpt;
time_t tarpit;
{
struct pending *pending;
struct pending *next;
struct timeval tv;
time_t now;
int dirty = 0;
struct pending_bucket *b;
ipaddr *mask = NULL;
int ret = 1;

(void)gettimeofday(&tv, NULL);
now = tv.tv_sec;

printf("pending_check_tarpit(): %s %d\n", rcpt, tarpit);
b = &pending_buckets[BUCKET_HASH(sa, from, rcpt, PENDING_BUCKETS)];
PENDING_LOCK;
for (pending = TAILQ_FIRST(&b->b_pending_head);
pending; pending = next) {
next = TAILQ_NEXT(pending, pb_list);
/*
* flag stale greylist and aw entries
*/
if (pending_timeout(pending, &tv)) {
++dirty;
continue;
}

switch (pending->p_sa->sa_family) {
case AF_INET:
mask = (ipaddr *)&conf.c_match_mask;
break;
#ifdef AF_INET6
case AF_INET6:
mask = (ipaddr *)&conf.c_match_mask6;
break;
#endif
}

/*
* Look for our entry.
*/
if (pending->p_type == T_TARPIT &&
ip_match(sa, pending->p_sa, mask) &&
(strcmp(from, pending->p_from) == 0) &&
(strcmp(rcpt, pending->p_rcpt) == 0)) {
if (tarpit < pending->p_tarpit.tv_sec)
ret = 1; /* shorter tarpit. client may pass this time.... */
else
ret = 0; /* longer or equal tarpit. client definitely fails this time too. so move to the next ACL */
break;
}
}

PENDING_UNLOCK;
if (dirty) {
dump_touch(dirty);
dump_flush();
}
/* not found in the database. therefore, try tarpitting for the first time. */
return ret;
}

void pending_force(sa, salen, from, rcpt, aw, force)
struct sockaddr *sa;
socklen_t salen;
Expand Down Expand Up @@ -515,13 +596,12 @@ void pending_force(sa, salen, from, rcpt, aw, force)
mask = (ipaddr *)&conf.c_match_mask6;
break;
#endif
}
}

/*
* Look for our entry.
*/
if (pending->p_type == T_PENDING &&
ip_match(sa, pending->p_sa, mask) &&
if (ip_match(sa, pending->p_sa, mask) &&
(strcmp(from, pending->p_from) == 0) &&
(strcmp(rcpt, pending->p_rcpt) == 0)) {
if (force == FORCE_AUTOWHITE) {
Expand All @@ -530,6 +610,14 @@ void pending_force(sa, salen, from, rcpt, aw, force)
pending_put(pending, date);
} else if (force == FORCE_REMOVE) {
pending_rem(pending);
} else if (force == FORCE_TARPIT) {
if (pending->p_type == T_TARPIT) {
if (aw < pending->p_tarpit.tv_sec)
pending->p_tarpit.tv_sec = aw;
} else {
pending->p_type = T_TARPIT;
pending->p_tarpit.tv_sec = aw;
}
}
++dirty;

Expand Down Expand Up @@ -557,12 +645,14 @@ pending_textdump(stream)

done.pending = 0;
done.autowhite = 0;
done.tarpit = 0;

gettimeofday(&now, NULL);

fprintf(stream, "\n\n#\n# stored tuples\n#\n");
fprintf(stream, "# Sender IP\t%s\t%s\tTime accepted\n",
"Sender e-mail", "Recipient e-mail");
fprintf(stream, "# Sender IP\t%s\t%s\tTime accepted\t"
"Unsuccessful shortest tarpit\n",
"Sender e-mail", "Recipient e-mail");

PENDING_LOCK;
for (pending = TAILQ_FIRST(&pending_head); pending; pending = next) {
Expand All @@ -572,26 +662,49 @@ pending_textdump(stream)
continue;

if (conf.c_dump_no_time_translation) {
fprintf(stream, "%s\t%s\t%s\t%ld %s\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
pending->p_type == T_AUTOWHITE ? "AUTO" : "");
if (pending->p_type == T_AUTOWHITE) {
fprintf(stream, "%s\t%s\t%s\t%ld AUTO\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec);
} else if (pending->p_type == T_PENDING) {
fprintf(stream, "%s\t%s\t%s\t%ld \n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec);
} else {
fprintf(stream, "%s\t%s\t%s\t%ld\t%ld TARPIT\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
(long)pending->p_tarpit.tv_sec);
}
} else {
ti = pending->p_tv.tv_sec;
localtime_r(&ti, &tm);
strftime(textdate, DATELEN, "%Y-%m-%d %T", &tm);

fprintf(stream, "%s\t%s\t%s\t%ld%s# %s\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
pending->p_type == T_AUTOWHITE ? " AUTO " : " ",
textdate);

if (pending->p_type == T_AUTOWHITE) {
fprintf(stream, "%s\t%s\t%s\t%ld AUTO # %s\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
textdate);
} else if (pending->p_type == T_PENDING) {
fprintf(stream, "%s\t%s\t%s\t%ld # %s\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
textdate);
} else {
fprintf(stream, "%s\t%s\t%s\t%ld\t%ld TARPIT # %s\n",
pending->p_addr, pending->p_from,
pending->p_rcpt, (long)pending->p_tv.tv_sec,
(long)pending->p_tarpit.tv_sec, textdate);
}
}

if (pending->p_type == T_AUTOWHITE)
done.autowhite++;
else
else if (pending->p_type == T_PENDING)
done.pending++;
else
done.tarpit++;
}
PENDING_UNLOCK;

Expand Down

0 comments on commit b0a0392

Please sign in to comment.