#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_check
* purpose: throttle users based on SASL info or envelope FROM
* return: 0 for new record, 1 for update
*/
int
throttle_check (unsigned int fd)
{
unsigned int tnum = 0;
unsigned int tresult = 0;
mysql_optarray[fd][0] = 0;
if(DEBUG > 0)
logmessage("DEBUG: fd: %d checking throttle\n", fd);
/* build up & execute query */
if(SENDER_THROTTLE_HOST == 1)
{
tnum = 1;
snprintf(mysqlquery_array[fd], 512,
"SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
" _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
" _log_warn, _log_panic, _abuse_tot"
" FROM throttle WHERE _from='%s' OR _from='%s' OR _from='%s' OR _from='%s'"
" ORDER BY _priority DESC LIMIT 1",
host_array[fd][2], host_array[fd][3], host_array[fd][4], host_array[fd][5]);
} else if((SENDER_THROTTLE_SASL == 1) && (triplet_array[fd][4][0] != 0x00)) {
tnum = 2;
snprintf(mysqlquery_array[fd], 512,
"SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
" _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
" _log_warn, _log_panic, _abuse_tot"
" FROM throttle WHERE _from='%s'", triplet_array[fd][4]);
} else {
tnum = 3;
snprintf(mysqlquery_array[fd], 512,
"SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
" _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
" _log_warn, _log_panic, _abuse_tot"
" FROM throttle WHERE _from='%s' OR _from='@%s'"
" ORDER BY _priority DESC LIMIT 1",
triplet_array[fd][1], host_array[fd][7]);
}
if(db_charquery(fd) == -1) return(db_failure(fd, "throttle"));
/* 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", SENDERMSGLIMIT);
/* max user quota is disabled in database, fall back to config defaults */
if(atol(mysqlchar_array[fd][5]) == 0)
snprintf(mysqlchar_array[fd][5], sizeof(mysqlchar_array[fd][5]),
"%d", SENDERQUOTALIMIT);
/* max time limit is disabled in database, fall back to config defaults */
if(atol(mysqlchar_array[fd][6]) == 0)
snprintf(mysqlchar_array[fd][6], sizeof(mysqlchar_array[fd][6]),
"%d", SENDERTIMELIMIT);
/* max message size is disabled in database, fall back to config defaults */
if(atol(mysqlchar_array[fd][7]) == 0)
snprintf(mysqlchar_array[fd][7], sizeof(mysqlchar_array[fd][7]),
"%d", SENDERMSGSIZE);
/* max rcpt limit is disabled in database, fall back to config defaults */
if(atol(mysqlchar_array[fd][9]) == 0)
snprintf(mysqlchar_array[fd][9], sizeof(mysqlchar_array[fd][9]),
"%d", SENDERRCPTLIMIT);
/* check postfix policy instance */
snprintf(mysqlquery_array[fd], 512,
"SELECT COUNT(_instance) from throttle_from_instance \
WHERE _instance='%s'", triplet_array[fd][6]);
if(db_optquery(fd) == -1) return(db_failure(fd, "throttle"));
/* is instance recorded? */
if(mysql_optarray[fd][0] == 0)
{
int expire=0;
/* its not, so record it */
if(SENDERTIMELIMIT > 0)
expire=timenow;
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO throttle_from_instance (_instance,_expire) VALUES ('%s',%d)",
triplet_array[fd][6], expire);
if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
instance_inc[fd] = 1;
} else {
instance_inc[fd] = 0;
}
/* prepare attributes & thresholds */
/* count, quota, rcpt */
tquota[fd] = atof(mysqlchar_array[fd][4]) / atof(mysqlchar_array[fd][5]) * 100;
tcount[fd] = atof(mysqlchar_array[fd][2]) / atof(mysqlchar_array[fd][1]) * 100;
trcpt[fd] = atof(mysqlchar_array[fd][10]) / atof(mysqlchar_array[fd][9]) * 100;
/* catch wierd ones */
if(DEBUG >= 4)
logmessage("DEBUG: fd: %d: tquota[fd]: %d, tcount[fd]: %d, trcpt[fd]: %d\n",
fd, tquota[fd], tcount[fd], trcpt[fd]);
/* highest percentage always wins.. mmm.. ugly stuff*/
if(tquota[fd] >= tcount[fd] && tquota[fd] >= trcpt[fd]) {
tresult = tquota[fd];
if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
if(tcount[fd] >= tquota[fd] && tcount[fd] >= trcpt[fd]) {
tresult = tcount[fd];
if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
if(trcpt[fd] >= tcount[fd] && trcpt[fd] >= tquota[fd]) {
tresult = trcpt[fd];
if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
if(DEBUG >= 4)
logmessage("DEBUG: fd: %d: tresult: %d\n", fd, tresult);
/* percentage won, set attribute accordingly */
switch (tresult)
{
case 0 ... 49: tattrib_array[fd][0] = 'a'; break;
case 50 ... 89: tattrib_array[fd][0] = 'w'; break;
case 90 ... 900000: tattrib_array[fd][0] = 'p'; break;
/* allow for big percentage overshoot */
default:
logmessage("fatal: throttle_check(): invalid tresult: %d\n", tresult);
return (-1);
}
/* we selectively choose which throttle module we want */
switch(tnum)
{
case 1:
return(throttle_host(fd));
case 2:
return(throttle_sasl(fd));
case 3:
return(throttle_from(fd));
default:
logmessage("fatal: throttle_check(): no tnum\n");
return (-1);
}
return (0); /* never reached */
}
/* EOF */
syntax highlighted by Code2HTML, v. 0.9.1