#include "policyd.h"
/*
*
*
* Policy Daemon
*
* policy daemon is used in conjuction with postfix to combat spam.
*
* Copyright (C) 2004 Cami Sardinha (cami@mweb.co.za)
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
*/
/*
* function: throttle_rcpt
* purpose: throttle users based on envelope RCPT
* return: 0 for new record, 1 for update
*/
signed int
throttle_rcpt (unsigned int fd)
{
if(DEBUG > 0)
logmessage("DEBUG: fd: %d checking throttle-rcpt\n", fd);
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT _rcpt,_count_max,_count_cur,_time_limit,_date,_count_tot"
" FROM throttle_rcpt WHERE _rcpt='%s'", triplet_array[fd][2]);
if(db_charquery(fd) == -1) return(db_failure(fd, "throttle_rcpt"));
/* max messages is disabled in database, fall back to config default */
if(atol(mysqlchar_array[fd][1]) == 0)
snprintf(mysqlchar_array[fd][1], sizeof(mysqlchar_array[fd][1]),
"%d", RECIPIENTMSGLIMIT);
/* max time limit is disabled in database, fall back to config defaults */
if(atol(mysqlchar_array[fd][3]) == 0)
snprintf(mysqlchar_array[fd][3], sizeof(mysqlchar_array[fd][3]),
"%d", RECIPIENTTIMELIMIT);
/* prepare attributes & thresholds */
trcpt[fd] = atof(mysqlchar_array[fd][2]) / atof(mysqlchar_array[fd][1]) * 100;
/* percentage won, set attribute accordingly */
switch (trcpt[fd])
{
case 0 ... 49: tattrib_array[fd][0] = 'a'; break;
case 50 ... 89: tattrib_array[fd][0] = 'w'; break;
case 90 ... 1000: tattrib_array[fd][0] = 'p'; break;
default:
logmessage("fatal: throttle_rcpt(): invalid tresult: %d\n", trcpt[fd]);
}
/* user is not in the database */
if(strlen(mysqlchar_array[fd][0]) < 2)
{
logmessage("rcpt=%lu, throttle_rcpt=new(a), host=%s, from=%s, to=%s, "
"count=1/%d(1), threshold=0%\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host */
triplet_array[fd][1], /* from */
triplet_array[fd][2], /* to */
atol(mysqlchar_array[fd][1]) /* count_max */
);
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO throttle_rcpt (_date,_rcpt,_count_max,_time_limit) "
"VALUES (%d, '%s', %ld, %ld)",
timenow,
triplet_array[fd][2],
atol(mysqlchar_array[fd][1]),
atol(mysqlchar_array[fd][3]));
if(db_doquery(fd) == -1) return(db_failure(fd, "throttle_rcpt"));
/* recipient does not exist in the database, insert and allow */
return (0);
}
/* if time has expired, clear quota for message count */
if(timenow > (unsigned int)(atol(mysqlchar_array[fd][4])+atol(mysqlchar_array[fd][3])))
{
logmessage("rcpt=%lu, throttle_rcpt=clear(a), host=%s, from=%s, to=%s, "
"count=0/%d(%d), threshold=0%\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host */
triplet_array[fd][1], /* from */
triplet_array[fd][2], /* to */
atol(mysqlchar_array[fd][1]), /* count_max */
atol(mysqlchar_array[fd][5]) /* count_tot */
);
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"UPDATE throttle_rcpt SET"
" _count_cur=1,"
" _count_tot=_count_tot+1,"
" _abuse_tot=_abuse_tot+_abuse_cur,"
" _date=%d,"
" _abuse_cur=0"
" WHERE _rcpt='%s'",
timenow, triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "throttle_rcpt"));
/* counter reset because of expiry, allow mail */
return (0);
}
/* if the recipient is past his quota and the timeout has not expired */
/* then reject the message */
if(atol(mysqlchar_array[fd][2]) >= atol(mysqlchar_array[fd][1]))
{
logmessage("rcpt=%lu, throttle_rcpt=abuse(f), host=%s, from=%s, to=%s, "
"count=%d/%d(%d), threshold=%d%\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host */
triplet_array[fd][1], /* from */
triplet_array[fd][2], /* to */
atol(mysqlchar_array[fd][2]), /* count_cur */
atol(mysqlchar_array[fd][1]), /* count_max */
atol(mysqlchar_array[fd][5]), /* count_tot */
trcpt[fd] /* rcpt percentage */
);
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"UPDATE throttle_rcpt SET"
" _abuse_cur=1"
" WHERE _rcpt='%s'",
triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "throttle-rcpt"));
return (-7);
}
/* if the recipient has not reached his quota, increase count */
logmessage("rcpt=%lu, throttle_rcpt=update(%c), host=%s, from=%s, to=%s, "
"count=%d/%d(%d), threshold=%d%\n",
rcpt_count, /* recipient count */
tattrib_array[fd][0], /* attribute state */
host_array[fd][2], /* host */
triplet_array[fd][1], /* from */
triplet_array[fd][2], /* to */
atol(mysqlchar_array[fd][2])+1, /* count_cur */
atol(mysqlchar_array[fd][1]), /* count_max */
atol(mysqlchar_array[fd][5])+1, /* count_tot */
trcpt[fd] /* rcpt percentage */
);
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"UPDATE throttle_rcpt SET"
" _count_cur=_count_cur+1,"
" _abuse_cur=0"
" WHERE _rcpt='%s'",
triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "throttle_rcpt"));
return (0); /* never reached */
}
/* EOF */
syntax highlighted by Code2HTML, v. 0.9.1