#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: greylist_check
* purpose: check if triplet exists in mysql
* return: 0 for new record, 1 for update
*/
int
greylist_check(unsigned int fd)
{
if(DEBUG > 0)
logmessage("DEBUG: fd: %d checking greylist\n", fd);
/* set sane defaults */
mysql_array[fd][0] = -2;
mysql_optarray[fd][0] = OPTINOUTALL;
/* opt-in/opt-out? */
if(OPTINOUT == 1)
{
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT _optin FROM policy WHERE _rcpt='%s' OR _rcpt='@%s' ORDER BY _priority DESC LIMIT 1",
triplet_array[fd][2], host_array[fd][9]);
if(db_optquery(fd) == -1) return(db_failure(fd, "greylist"));
/* user is opted out */
if(mysql_optarray[fd][0] == 0)
{
logmessage("rcpt=%lu, greylist=optout, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3]); /* size */
return (0);
}
}
/* domain or mail address is in training mode? */
if(TRAINING_POLICY_TIMEOUT != 0)
{
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT COUNT(*) FROM policy_training WHERE _rcpt='%s' OR _rcpt='@%s'",
triplet_array[fd][2], host_array[fd][9]);
if(db_optquery(fd) == -1) return(db_failure(fd, "greylist"));
/* training policy is activated for domain or email address */
if(mysql_optarray[fd][0] >= 1)
mysql_optarray[fd][0] = 2;
}
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT _count,_datenew,_datelast FROM triplet WHERE _host='%s' AND _from='%s' AND _rcpt='%s'",
triplet_array[fd][0], triplet_array[fd][1], triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
/* update the greylist xheader */
if(GREYLIST_X_HEADER==1)
snprintf(xgreylist_array[fd], 128, "%s host: %s count: %d size: %s\n\n",
POSTFIX_X_HEADER, host_array[fd][2], mysql_array[fd][0], triplet_array[fd][3]);
/* triplet not found in greylist database */
if(mysql_array[fd][0]==-2)
{
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO triplet (_datenew,_datelast,_host,_from,_rcpt) VALUES (%d,%d,'%s','%s','%s')",
timenow, timenow, triplet_array[fd][0], triplet_array[fd][1], triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
/* auto black listing is enabled */
if(AUTO_BLACK_LISTING == 1)
{
/* perform query to see how many triplets there are for a host/network */
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT COUNT(*) FROM triplet WHERE _host='%s' AND _count = 0",
triplet_array[fd][0]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
if(DEBUG > 0)
logmessage("DEBUG: fd: %d unauth triplet: %d\n", fd, mysql_array[fd][0]);
/* host has more than allowed number of unauthenticated triplets */
if(mysql_array[fd][0] >= AUTO_BLACKLIST_NUMBER)
{
int expire=0;
/* never auto expire blacklist? */
if(AUTO_BLACKLIST_EXPIRE > 0)
expire=timenow+AUTO_BLACKLIST_EXPIRE;
/* blacklist netblock /24 */
if(BLACKLIST_NETBLOCK==1)
{ /* blacklist netblock */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO blacklist (_blacklist,_description,_expire) VALUES ('%s.%%','# autoblacklisted', %d)",
triplet_array[fd][0], expire);
} else { /* blacklist host ip */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO blacklist (_blacklist,_description,_expire) VALUES ('%s','# autoblacklisted',%d)",
host_array[fd][2], expire);
}
/* execute query */
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
logmessage("rcpt=%lu, greylist=abl, host=%s (%s), from=%s, to=%s, size=%s, expire=%d\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3], /* size */
expire); /* expiry date */
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"DELETE QUICK from triplet WHERE _host='%s'", triplet_array[fd][0]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
/* reject */
return (-1);
}
}
/* not in training mode, reject if this is the first attempt */
if((TRAINING_MODE == 0) && (mysql_optarray[fd][0] != 2))
{
logmessage("rcpt=%lu, greylist=new, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3]); /* size */
/* reject */
return (-1);
}
/* in training mode, always accept */
if((TRAINING_MODE == 1) || (mysql_optarray[fd][0] == 2))
{
logmessage("rcpt=%lu, greylist=new_train, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count,
host_array[fd][2], /* host */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* from */
triplet_array[fd][2], /* rcpt */
triplet_array[fd][3] /* size */
);
/* accept */
return (0);
}
} else { /* triplet exists in database */
/* has TRIPLET_TIME expired since triplet creation? */
if(timenow < (unsigned int)(mysql_array[fd][1]+TRIPLET_TIME))
{
/* not in training mode */
if((TRAINING_MODE == 0) && (mysql_optarray[fd][0] != 2))
{
logmessage("rcpt=%lu, greylist=abuse, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3]); /* size */
return (-1);
}
}
/* implement autowhitelisting */
if(AUTO_WHITE_LISTING==1)
{
/* expire auto-whitelisted hosts if enabled */
int expire=0;
if(AUTO_WHITELIST_EXPIRE > 0)
expire=timenow+AUTO_WHITELIST_EXPIRE;
/* save an sql lookup if awl == 1 */
if(AUTO_WHITELIST_NUMBER == 1)
goto awl;
/* check how many auth triplets there are for a host/network */
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"SELECT COUNT(*) FROM triplet WHERE _host='%s' AND _count > 0",
triplet_array[fd][0]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
if(DEBUG > 0)
logmessage("DEBUG: fd: %d whitelist result: %d\n", fd, mysql_array[fd][0]);
if(mysql_array[fd][0] >= AUTO_WHITELIST_NUMBER)
goto awl; /* auto whitelist network/host */
else
goto nawl; /* dont auto white list network */
awl:
if(AUTO_WHITELIST_NETBLOCK==1)
{
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO whitelist (_whitelist,_description,_expire) VALUES ('%s.%%','# autowhitelisted host',%d)",
triplet_array[fd][0], expire);
} else {
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"INSERT DELAYED INTO whitelist (_whitelist,_description,_expire) VALUES ('%s','# autowhitelisted host',%d)",
host_array[fd][2], expire);
}
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"DELETE QUICK from triplet WHERE _host='%s'", triplet_array[fd][0]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
logmessage("rcpt=%lu, greylist=awl, host=%s (%s), from=%s, to=%s, size=%s, expire=%d\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3], /* size */
expire); /* expiry date */
return(0);
}
nawl:
/* build up & execute query */
snprintf(mysqlquery_array[fd], 512,
"UPDATE triplet SET _datelast='%d',_count=_count+1 WHERE _host='%s' AND _from='%s' AND _rcpt='%s'",
timenow, triplet_array[fd][0], triplet_array[fd][1], triplet_array[fd][2]);
if(db_doquery(fd) == -1) return(db_failure(fd, "greylist"));
/* training mode */
if((TRAINING_MODE == 0) && (mysql_optarray[fd][0] != 2))
{
/* yes, it has.. update */
logmessage("rcpt=%lu, greylist=update, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3]); /* size */
}
/* training mode */
if((TRAINING_MODE == 1) || (mysql_optarray[fd][0] == 2))
{
/* yes, it has.. update */
logmessage("rcpt=%lu, greylist=update_train, host=%s (%s), from=%s, to=%s, size=%s\n",
rcpt_count, /* recipient count */
host_array[fd][2], /* host address */
host_array[fd][0], /* hostname */
triplet_array[fd][1], /* sender */
triplet_array[fd][2], /* recipient */
triplet_array[fd][3]); /* size */
}
return (0);
}
return (0); /* never reached */
}
/* EOF */
syntax highlighted by Code2HTML, v. 0.9.1