1 #include "policyd.h"
2
3
4 /*
5 *
6 *
7 * Policy Daemon
8 *
9 * policy daemon is used in conjuction with postfix to combat spam.
10 *
11 * Copyright (C) 2004 Cami Sardinha (cami@mweb.co.za)
12 *
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 *
29 *
30 */
31
32 /*
33 * function: throttle_sasl
34 * purpose: throttle users based on SASL info
35 * return: 0 for new record, 1 for update
36 */
37 int
throttle_sasl(unsigned int fd)38 throttle_sasl (unsigned int fd)
39 {
40
41 if(DEBUG > 0)
42 logmessage("DEBUG: fd: %d checking throttle-sasl\n", fd);
43
44 /* user is not in the database */
45 if(strlen(mysqlchar_array[fd][0]) < 2)
46 {
47 if(atol(triplet_array[fd][3]) >= atol(mysqlchar_array[fd][7]))
48 goto abuse;
49
50 logmessage("rcpt=%lu, throttle=new(a), host=%s, from=%s, to=%s, size=%d/%d, "
51 "quota=%d/%d, count=1/%d(1), rcpt=1/%d(1), threshold=0%|0%|0%, sasl_username=%s\n",
52 rcpt_count, /* recipient count */
53 host_array[fd][2], /* host */
54 triplet_array[fd][1], /* from */
55 triplet_array[fd][2], /* to */
56 atol(triplet_array[fd][3]), /* size_cur */
57 atol(mysqlchar_array[fd][7]), /* size_max */
58 atol(triplet_array[fd][3]), /* quota_cur */
59 atol(mysqlchar_array[fd][5]), /* quota_max */
60 atol(mysqlchar_array[fd][1]), /* count_max */
61 atol(mysqlchar_array[fd][9]), /* rcpt_max */
62 triplet_array[fd][4] /* sasl_username */
63 );
64
65 /* build up & execute query */
66 snprintf(mysqlquery_array[fd], 512,
67 "INSERT DELAYED INTO throttle "
68 "(_date,_from,_quota_cur,_quota_max,_rcpt_max,_mail_size,_count_max, _time_limit)"
69 " VALUES (%d, '%s', %d, %ld, %ld, %ld, %ld, %ld)",
70 timenow,
71 triplet_array[fd][4],
72 atoi(triplet_array[fd][3]),
73 atol(mysqlchar_array[fd][5]),
74 atol(mysqlchar_array[fd][9]),
75 atol(mysqlchar_array[fd][7]),
76 atol(mysqlchar_array[fd][1]),
77 atol(mysqlchar_array[fd][6]));
78 if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
79
80 /* sender does not exist in the database, insert and allow */
81 return (0);
82 }
83
84 /* if sender is sending a message bigger than allowed, reject */
85 if(atol(triplet_array[fd][3]) >= atol(mysqlchar_array[fd][7]))
86 {
87 abuse:
88 logmessage("rcpt=%lu, throttle=abuse(f), host=%s, from=%s, to=%s, size=%d/%d, "
89 "quota=%d/%d, count=%d/%d(%d), rcpt=%d/%d(%d), threshold=%d%|%d%|%d%, sasl_username=%s\n",
90 rcpt_count, /* recipient count */
91 host_array[fd][2], /* host */
92 triplet_array[fd][1], /* from */
93 triplet_array[fd][2], /* to */
94 atol(triplet_array[fd][3]), /* size_cur */
95 atol(mysqlchar_array[fd][7]), /* size_max */
96 atol(mysqlchar_array[fd][4]), /* quota_cur */
97 atol(mysqlchar_array[fd][5]), /* quota_max */
98 atol(mysqlchar_array[fd][2]), /* count_cur */
99 atol(mysqlchar_array[fd][1]), /* count_max */
100 atol(mysqlchar_array[fd][8]), /* count_tot */
101 atol(mysqlchar_array[fd][10]), /* rcpt_cur */
102 atol(mysqlchar_array[fd][9]), /* rcpt_max */
103 atol(mysqlchar_array[fd][11]), /* rcpt_tot */
104 tquota[fd], /* quota percentage */
105 tcount[fd], /* count percentage */
106 trcpt[fd], /* rcpt percentage */
107 triplet_array[fd][4] /* sasl_username */
108 );
109
110 return (-3);
111 }
112
113 /* if time has expired, clear quota for size+message count */
114 if(timenow > (unsigned int)(atol(mysqlchar_array[fd][6])+atol(mysqlchar_array[fd][3])))
115 {
116 logmessage("rcpt=%lu, throttle=clear(a), host=%s, from=%s, to=%s, size=%d/%d, "
117 "quota=%d/%d, count=1/%d(%d), rcpt=1/%d(%d), threshold=0%|0%|0%, sasl_username=%s\n",
118 rcpt_count, /* recipient count */
119 host_array[fd][2], /* host */
120 triplet_array[fd][1], /* from */
121 triplet_array[fd][2], /* to */
122 atol(triplet_array[fd][3]), /* size_cur */
123 atol(mysqlchar_array[fd][7]), /* size_max */
124 atoi(triplet_array[fd][3]), /* quota_cur */
125 atol(mysqlchar_array[fd][5]), /* quota_max */
126 atol(mysqlchar_array[fd][1]), /* count_max */
127 atol(mysqlchar_array[fd][8]), /* count_tot */
128 atol(mysqlchar_array[fd][9]), /* rcpt_max */
129 atol(mysqlchar_array[fd][11])+1, /* rcpt_tot */
130 triplet_array[fd][4] /* sasl_username */
131 );
132
133 /* build up & execute query */
134 snprintf(mysqlquery_array[fd], 512,
135 "UPDATE throttle SET"
136 " _rcpt_cur=1,"
137 " _rcpt_tot=_rcpt_tot+1,"
138 " _date=%d,"
139 " _quota_cur=%d,"
140 " _count_cur=1,"
141 " _count_tot=_count_tot+%d,"
142 " _abuse_tot=_abuse_tot+_abuse_cur,"
143 " _abuse_cur=0"
144 " WHERE _from='%s'",
145 timenow,
146 atoi(triplet_array[fd][3]),
147 instance_inc[fd],
148 triplet_array[fd][4]);
149 if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
150
151 /* counter reset because of expiry, allow mail */
152 return (0);
153 }
154
155 /* if the sender is past his quota and the timeout has not expired */
156 /* then reject the message */
157 if(atol(mysqlchar_array[fd][2]) >= atol(mysqlchar_array[fd][1]) || /* count */
158 atol(mysqlchar_array[fd][4]) >= atol(mysqlchar_array[fd][5]) || /* quota */
159 atol(mysqlchar_array[fd][10]) >= atol(mysqlchar_array[fd][9])) /* rcpt max */
160 {
161 if((instance_inc[fd] == 0) && (atol(mysqlchar_array[fd][10]) < atol(mysqlchar_array[fd][9])))
162 goto update;
163
164 logmessage("rcpt=%lu, throttle=abuse(f), host=%s, from=%s, to=%s, size=%d/%d, "
165 "quota=%d/%d, count=%d/%d(%d), rcpt=%d/%d(%d), threshold=%d%|%d%|%d%, sasl_username=%s\n",
166 rcpt_count, /* recipient count */
167 host_array[fd][2], /* host */
168 triplet_array[fd][1], /* from */
169 triplet_array[fd][2], /* to */
170 atol(triplet_array[fd][3]), /* size_cur */
171 atol(mysqlchar_array[fd][7]), /* size_max */
172 atol(mysqlchar_array[fd][4]), /* quota_cur */
173 atol(mysqlchar_array[fd][5]), /* quota_max */
174 atol(mysqlchar_array[fd][2]), /* count_cur */
175 atol(mysqlchar_array[fd][1]), /* count_max */
176 atol(mysqlchar_array[fd][8]), /* count_tot */
177 atol(mysqlchar_array[fd][10]), /* rcpt_cur */
178 atol(mysqlchar_array[fd][9]), /* rcpt_max */
179 atol(mysqlchar_array[fd][11]), /* rcpt_tot */
180 tquota[fd], /* quota percentage */
181 tcount[fd], /* count percentage */
182 trcpt[fd], /* rcpt percentage */
183 triplet_array[fd][4] /* sasl_username */
184 );
185
186 /* build up & execute query */
187 snprintf(mysqlquery_array[fd], 512,
188 "UPDATE throttle SET"
189 " _abuse_cur=1"
190 " WHERE _from='%s'",
191 triplet_array[fd][1]);
192 if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
193
194 return (-5);
195 }
196
197 update:
198
199 /* if the sender has not reached his quota, increase count */
200 logmessage("rcpt=%lu, throttle=update(%c), host=%s, from=%s, to=%s, size=%d/%d, "
201 "quota=%d/%d, count=%d/%d(%d), rcpt=%d/%d(%d), threshold=%d%|%d%|%d%, sasl_username=%s\n",
202 rcpt_count, /* recipient count */
203 tattrib_array[fd][0], /* attribute state */
204 host_array[fd][2], /* host */
205 triplet_array[fd][1], /* from */
206 triplet_array[fd][2], /* to */
207 atol(triplet_array[fd][3]), /* size_cur */
208 atol(mysqlchar_array[fd][7]), /* size_max */
209 atol(mysqlchar_array[fd][4])+atol(triplet_array[fd][3]), /* quota_cur */
210 atol(mysqlchar_array[fd][5]), /* quota_max */
211 atol(mysqlchar_array[fd][2])+instance_inc[fd], /* count_cur */
212 atol(mysqlchar_array[fd][1]), /* count_max */
213 atol(mysqlchar_array[fd][8])+instance_inc[fd], /* count_tot */
214 atol(mysqlchar_array[fd][10])+1, /* rcpt_cur */
215 atol(mysqlchar_array[fd][9]), /* rcpt_max */
216 atol(mysqlchar_array[fd][11])+1, /* rcpt_tot */
217 tquota[fd], /* quota percentage */
218 tcount[fd], /* count percentage */
219 trcpt[fd], /* rcpt percentage */
220 triplet_array[fd][4] /* sasl_username */
221 );
222
223 /* build up & execute query */
224 snprintf(mysqlquery_array[fd], 512,
225 "UPDATE throttle SET"
226 " _rcpt_cur=_rcpt_cur+1,"
227 " _rcpt_tot=_rcpt_tot+1,"
228 " _quota_cur=_quota_cur+%ld,"
229 " _count_cur=_count_cur+%d,"
230 " _count_tot=_count_tot+%d,"
231 " _abuse_cur=0"
232 " WHERE _from='%s'",
233 atol(triplet_array[fd][3]),
234 instance_inc[fd],
235 instance_inc[fd],
236 triplet_array[fd][4]);
237 if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
238
239 return (0); /* never reached */
240 }
241
242 /* EOF */
243