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 /*
34 * function: throttle_check
35 * purpose: throttle users based on SASL info or envelope FROM
36 * return: 0 for new record, 1 for update
37 */
38 int
throttle_check(unsigned int fd)39 throttle_check (unsigned int fd)
40 {
41 unsigned int tnum = 0;
42 unsigned int tresult = 0;
43
44 mysql_optarray[fd][0] = 0;
45
46 if(DEBUG > 0)
47 logmessage("DEBUG: fd: %d checking throttle\n", fd);
48
49 /* build up & execute query */
50 if(SENDER_THROTTLE_HOST == 1)
51 {
52 tnum = 1;
53 snprintf(mysqlquery_array[fd], 512,
54 "SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
55 " _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
56 " _log_warn, _log_panic, _abuse_tot"
57 " FROM throttle WHERE _from='%s' OR _from='%s' OR _from='%s' OR _from='%s'"
58 " ORDER BY _priority DESC LIMIT 1",
59 host_array[fd][2], host_array[fd][3], host_array[fd][4], host_array[fd][5]);
60
61 } else if((SENDER_THROTTLE_SASL == 1) && (triplet_array[fd][4][0] != 0x00)) {
62 tnum = 2;
63 snprintf(mysqlquery_array[fd], 512,
64 "SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
65 " _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
66 " _log_warn, _log_panic, _abuse_tot"
67 " FROM throttle WHERE _from='%s'", triplet_array[fd][4]);
68 } else {
69 tnum = 3;
70 snprintf(mysqlquery_array[fd], 512,
71 "SELECT _from,_count_max,_count_cur,_date,_quota_cur,_quota_max,"
72 " _time_limit,_mail_size,_count_tot,_rcpt_max,_rcpt_cur,_rcpt_tot,"
73 " _log_warn, _log_panic, _abuse_tot"
74 " FROM throttle WHERE _from='%s' OR _from='@%s'"
75 " ORDER BY _priority DESC LIMIT 1",
76 triplet_array[fd][1], host_array[fd][7]);
77 }
78 if(db_charquery(fd) == -1) return(db_failure(fd, "throttle"));
79
80 /* max messages is disabled in database, fall back to config default */
81 if(atol(mysqlchar_array[fd][1]) == 0)
82 snprintf(mysqlchar_array[fd][1], sizeof(mysqlchar_array[fd][1]),
83 "%d", SENDERMSGLIMIT);
84
85 /* max user quota is disabled in database, fall back to config defaults */
86 if(atol(mysqlchar_array[fd][5]) == 0)
87 snprintf(mysqlchar_array[fd][5], sizeof(mysqlchar_array[fd][5]),
88 "%d", SENDERQUOTALIMIT);
89
90 /* max time limit is disabled in database, fall back to config defaults */
91 if(atol(mysqlchar_array[fd][6]) == 0)
92 snprintf(mysqlchar_array[fd][6], sizeof(mysqlchar_array[fd][6]),
93 "%d", SENDERTIMELIMIT);
94
95 /* max message size is disabled in database, fall back to config defaults */
96 if(atol(mysqlchar_array[fd][7]) == 0)
97 snprintf(mysqlchar_array[fd][7], sizeof(mysqlchar_array[fd][7]),
98 "%d", SENDERMSGSIZE);
99
100 /* max rcpt limit is disabled in database, fall back to config defaults */
101 if(atol(mysqlchar_array[fd][9]) == 0)
102 snprintf(mysqlchar_array[fd][9], sizeof(mysqlchar_array[fd][9]),
103 "%d", SENDERRCPTLIMIT);
104
105 /* check postfix policy instance */
106 snprintf(mysqlquery_array[fd], 512,
107 "SELECT COUNT(_instance) from throttle_from_instance \
108 WHERE _instance='%s'", triplet_array[fd][6]);
109 if(db_optquery(fd) == -1) return(db_failure(fd, "throttle"));
110
111 /* is instance recorded? */
112 if(mysql_optarray[fd][0] == 0)
113 {
114 int expire=0;
115
116 /* its not, so record it */
117 if(SENDERTIMELIMIT > 0)
118 expire=timenow;
119
120 snprintf(mysqlquery_array[fd], 512,
121 "INSERT DELAYED INTO throttle_from_instance (_instance,_expire) VALUES ('%s',%d)",
122 triplet_array[fd][6], expire);
123 if(db_doquery(fd) == -1) return(db_failure(fd, "throttle"));
124
125 instance_inc[fd] = 1;
126 } else {
127 instance_inc[fd] = 0;
128 }
129
130 /* prepare attributes & thresholds */
131 /* count, quota, rcpt */
132 tquota[fd] = atof(mysqlchar_array[fd][4]) / atof(mysqlchar_array[fd][5]) * 100;
133 tcount[fd] = atof(mysqlchar_array[fd][2]) / atof(mysqlchar_array[fd][1]) * 100;
134 trcpt[fd] = atof(mysqlchar_array[fd][10]) / atof(mysqlchar_array[fd][9]) * 100;
135
136 /* catch wierd ones */
137 if(DEBUG >= 4)
138 logmessage("DEBUG: fd: %d: tquota[fd]: %d, tcount[fd]: %d, trcpt[fd]: %d\n",
139 fd, tquota[fd], tcount[fd], trcpt[fd]);
140
141 /* highest percentage always wins.. mmm.. ugly stuff*/
142 if(tquota[fd] >= tcount[fd] && tquota[fd] >= trcpt[fd]) {
143 tresult = tquota[fd];
144 if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
145
146 if(tcount[fd] >= tquota[fd] && tcount[fd] >= trcpt[fd]) {
147 tresult = tcount[fd];
148 if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
149
150 if(trcpt[fd] >= tcount[fd] && trcpt[fd] >= tquota[fd]) {
151 tresult = trcpt[fd];
152 if (DEBUG >= 4) logmessage("tquota[fd] won\n"); }
153
154 if(DEBUG >= 4)
155 logmessage("DEBUG: fd: %d: tresult: %d\n", fd, tresult);
156
157 /* percentage won, set attribute accordingly */
158 switch (tresult)
159 {
160
161 case 0 ... 49: tattrib_array[fd][0] = 'a'; break;
162 case 50 ... 89: tattrib_array[fd][0] = 'w'; break;
163 case 90 ... 900000: tattrib_array[fd][0] = 'p'; break;
164 /* allow for big percentage overshoot */
165
166 default:
167 logmessage("fatal: throttle_check(): invalid tresult: %d\n", tresult);
168 return (-1);
169 }
170
171 /* we selectively choose which throttle module we want */
172 switch(tnum)
173 {
174 case 1:
175 return(throttle_host(fd));
176
177 case 2:
178 return(throttle_sasl(fd));
179
180 case 3:
181 return(throttle_from(fd));
182
183 default:
184 logmessage("fatal: throttle_check(): no tnum\n");
185 return (-1);
186 }
187
188 return (0); /* never reached */
189 }
190
191 /* EOF */
192