Mercurial > dnsbl
comparison src/dnsbl.cpp @ 163:97d7da45fe2a
spamassassin changes
author | carl |
---|---|
date | Sun, 26 Aug 2007 19:03:17 -0700 |
parents | c4bce911c276 |
children | 5809bcdc325b |
comparison
equal
deleted
inserted
replaced
162:c4bce911c276 | 163:97d7da45fe2a |
---|---|
11 -p port The port through which the MTA will connect to this milter. | 11 -p port The port through which the MTA will connect to this milter. |
12 -t sec The timeout value. | 12 -t sec The timeout value. |
13 -c Check the config, and print a copy to stdout. Don't start the | 13 -c Check the config, and print a copy to stdout. Don't start the |
14 milter or do anything with the socket. | 14 milter or do anything with the socket. |
15 -s Stress test by loading and deleting the current config in a loop. | 15 -s Stress test by loading and deleting the current config in a loop. |
16 -d increase debug level | 16 -d level set the debug level |
17 -e f|t Print the results of looking up from address f and to address | 17 -e f|t Print the results of looking up from address f and to address |
18 t in the current config | 18 t in the current config |
19 | 19 |
20 */ | 20 */ |
21 | 21 |
63 | 63 |
64 | 64 |
65 extern "C" { | 65 extern "C" { |
66 #include <libmilter/mfapi.h> | 66 #include <libmilter/mfapi.h> |
67 sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr); | 67 sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr); |
68 sfsistat mlfi_helo(SMFICTX * ctx, char *helohost); | |
68 sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv); | 69 sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv); |
69 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv); | 70 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv); |
71 sfsistat mlfi_header(SMFICTX* ctx, char* headerf, char* headerv); | |
70 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len); | 72 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len); |
71 sfsistat mlfi_eom(SMFICTX *ctx); | 73 sfsistat mlfi_eom(SMFICTX *ctx); |
72 sfsistat mlfi_abort(SMFICTX *ctx); | 74 sfsistat mlfi_abort(SMFICTX *ctx); |
73 sfsistat mlfi_close(SMFICTX *ctx); | 75 sfsistat mlfi_close(SMFICTX *ctx); |
74 void sig_chld(int signo); | 76 void sig_chld(int signo); |
241 pc = config; | 243 pc = config; |
242 pc->reference_count++; | 244 pc->reference_count++; |
243 pthread_mutex_unlock(&config_mutex); | 245 pthread_mutex_unlock(&config_mutex); |
244 get_fd(); | 246 get_fd(); |
245 ip = 0; | 247 ip = 0; |
248 helo = NULL; | |
246 mailaddr = NULL; | 249 mailaddr = NULL; |
247 queueid = NULL; | 250 queueid = NULL; |
248 authenticated = NULL; | 251 authenticated = NULL; |
249 have_whites = false; | 252 have_whites = false; |
250 only_whites = true; | 253 only_whites = true; |
262 pthread_mutex_lock(&config_mutex); | 265 pthread_mutex_lock(&config_mutex); |
263 pc->reference_count--; | 266 pc->reference_count--; |
264 bool last = (!pc->reference_count) && (pc != config); | 267 bool last = (!pc->reference_count) && (pc != config); |
265 pthread_mutex_unlock(&config_mutex); | 268 pthread_mutex_unlock(&config_mutex); |
266 if (last) delete pc; // free this config, since we were the last reference to it | 269 if (last) delete pc; // free this config, since we were the last reference to it |
270 if (helo) free(helo); | |
267 reset(true); | 271 reset(true); |
268 } | 272 } |
269 | 273 |
270 void mlfiPriv::reset(bool final) { | 274 void mlfiPriv::reset(bool final) { |
271 if (mailaddr) free(mailaddr); | 275 if (mailaddr) free(mailaddr); |
272 if (queueid) free(queueid); | 276 if (queueid) free(queueid); |
273 if (authenticated) free(authenticated); | 277 if (authenticated) free(authenticated); |
274 discard(env_to); | 278 discard(env_to); |
275 if (memory) delete memory; | 279 if (memory) delete memory; |
276 if (scanner) delete scanner; | 280 if (scanner) delete scanner; |
281 if (assassin) delete assassin; | |
277 if (!final) { | 282 if (!final) { |
278 mailaddr = NULL; | 283 mailaddr = NULL; |
279 queueid = NULL; | 284 queueid = NULL; |
280 authenticated = NULL; | 285 authenticated = NULL; |
281 have_whites = false; | 286 have_whites = false; |
282 only_whites = true; | 287 only_whites = true; |
283 memory = NULL; | 288 memory = NULL; |
284 scanner = NULL; | 289 scanner = NULL; |
290 assassin = NULL; | |
285 content_suffix = NULL; | 291 content_suffix = NULL; |
286 content_message = NULL; | 292 content_message = NULL; |
287 uribl_suffix = NULL; | 293 uribl_suffix = NULL; |
288 uribl_message = NULL; | 294 uribl_message = NULL; |
289 content_host_ignore = NULL; | 295 content_host_ignore = NULL; |
423 syslog(LOG_NOTICE, "%s", text); | 429 syslog(LOG_NOTICE, "%s", text); |
424 pthread_mutex_unlock(&syslog_mutex); | 430 pthread_mutex_unlock(&syslog_mutex); |
425 } | 431 } |
426 else { | 432 else { |
427 printf("%s \n", text); | 433 printf("%s \n", text); |
434 } | |
435 } | |
436 | |
437 void my_syslog(mlfiPriv *priv, string text) { | |
438 if (debug_syslog > 3) { | |
439 char buf[maxlen]; | |
440 strncpy(buf, text.c_str(), sizeof(buf)); | |
441 buf[maxlen-1] = '\0'; // ensure null termination | |
442 my_syslog(priv, buf); | |
428 } | 443 } |
429 } | 444 } |
430 | 445 |
431 void my_syslog(char *text) { | 446 void my_syslog(char *text) { |
432 my_syslog(NULL, text); | 447 my_syslog(NULL, text); |
925 // allocate some private memory | 940 // allocate some private memory |
926 mlfiPriv *priv = new mlfiPriv; | 941 mlfiPriv *priv = new mlfiPriv; |
927 if (hostaddr->sa_family == AF_INET) { | 942 if (hostaddr->sa_family == AF_INET) { |
928 priv->ip = ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr; | 943 priv->ip = ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr; |
929 } | 944 } |
930 | |
931 // save the private data | 945 // save the private data |
932 smfi_setpriv(ctx, (void*)priv); | 946 smfi_setpriv(ctx, (void*)priv); |
933 | 947 |
934 // continue processing | 948 // continue processing |
949 return SMFIS_CONTINUE; | |
950 } | |
951 | |
952 sfsistat mlfi_helo(SMFICTX * ctx, char *helohost) | |
953 { | |
954 mlfiPriv &priv = *MLFIPRIV; | |
955 priv.helo = strdup(helohost); | |
935 return SMFIS_CONTINUE; | 956 return SMFIS_CONTINUE; |
936 } | 957 } |
937 | 958 |
938 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from) | 959 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from) |
939 { | 960 { |
940 mlfiPriv &priv = *MLFIPRIV; | 961 mlfiPriv &priv = *MLFIPRIV; |
941 priv.mailaddr = to_lower_string(from[0]); | 962 priv.mailaddr = to_lower_string(from[0]); |
963 priv.queueid = strdup(smfi_getsymval(ctx, "i")); | |
942 priv.authenticated = smfi_getsymval(ctx, "{auth_authen}"); | 964 priv.authenticated = smfi_getsymval(ctx, "{auth_authen}"); |
943 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); | 965 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); |
966 priv.assassin = new SpamAssassin; | |
967 priv.assassin->mlfi_connect(&priv, priv.ip); | |
968 priv.assassin->mlfi_helo(priv.helo); | |
969 priv.assassin->mlfi_envfrom(priv.mailaddr, priv.queueid); | |
944 return SMFIS_CONTINUE; | 970 return SMFIS_CONTINUE; |
945 } | 971 } |
946 | 972 |
947 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) | 973 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) |
948 { | 974 { |
949 DNSBLP rejectlist = NULL; // list that caused the reject | 975 DNSBLP rejectlist = NULL; // list that caused the reject |
950 mlfiPriv &priv = *MLFIPRIV; | 976 mlfiPriv &priv = *MLFIPRIV; |
951 CONFIG &dc = *priv.pc; | 977 CONFIG &dc = *priv.pc; |
952 if (!priv.queueid) priv.queueid = strdup(smfi_getsymval(ctx, "i")); | |
953 char *rcptaddr = rcpt[0]; | 978 char *rcptaddr = rcpt[0]; |
954 char *loto = to_lower_string(rcptaddr); | 979 char *loto = to_lower_string(rcptaddr); |
980 priv.assassin->mlfi_envrcpt(ctx, loto); | |
955 // priv.mailaddr sending original message to loto | 981 // priv.mailaddr sending original message to loto |
956 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); | 982 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); |
957 VERIFYP ver = con.find_verify(loto); | 983 VERIFYP ver = con.find_verify(loto); |
958 char *fromvalue = con.find_from(priv.mailaddr); | 984 char *fromvalue = con.find_from(priv.mailaddr); |
959 // loto sending a reply back to priv.mailaddr | 985 // loto sending a reply back to priv.mailaddr |
1048 priv.have_whites = true; | 1074 priv.have_whites = true; |
1049 } | 1075 } |
1050 return SMFIS_CONTINUE; | 1076 return SMFIS_CONTINUE; |
1051 } | 1077 } |
1052 | 1078 |
1079 sfsistat mlfi_header(SMFICTX* ctx, char* headerf, char* headerv) | |
1080 { | |
1081 mlfiPriv &priv = *MLFIPRIV; | |
1082 if (priv.authenticated) return SMFIS_CONTINUE; | |
1083 if (priv.only_whites) return SMFIS_CONTINUE; | |
1084 priv.assassin->mlfi_header(headerf, headerv); | |
1085 return SMFIS_CONTINUE; | |
1086 } | |
1087 | |
1088 sfsistat mlfi_eoh(SMFICTX* ctx) | |
1089 { | |
1090 mlfiPriv &priv = *MLFIPRIV; | |
1091 if (priv.authenticated) return SMFIS_CONTINUE; | |
1092 if (priv.only_whites) return SMFIS_CONTINUE; | |
1093 priv.assassin->mlfi_eoh(); | |
1094 return SMFIS_CONTINUE; | |
1095 } | |
1096 | |
1053 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len) | 1097 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len) |
1054 { | 1098 { |
1055 mlfiPriv &priv = *MLFIPRIV; | 1099 mlfiPriv &priv = *MLFIPRIV; |
1056 if (priv.authenticated) return SMFIS_CONTINUE; | 1100 if (priv.authenticated) return SMFIS_CONTINUE; |
1057 if (priv.only_whites) return SMFIS_CONTINUE; | 1101 if (priv.only_whites) return SMFIS_CONTINUE; |
1102 priv.assassin->mlfi_body(data, len); | |
1058 priv.scanner->scan(data, len); | 1103 priv.scanner->scan(data, len); |
1059 return SMFIS_CONTINUE; | 1104 return SMFIS_CONTINUE; |
1060 } | 1105 } |
1061 | 1106 |
1062 sfsistat mlfi_eom(SMFICTX *ctx) | 1107 sfsistat mlfi_eom(SMFICTX *ctx) |
1068 int ip; | 1113 int ip; |
1069 status st; | 1114 status st; |
1070 // process end of message | 1115 // process end of message |
1071 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; | 1116 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; |
1072 else { | 1117 else { |
1118 int score = priv.assassin->mlfi_eom(); | |
1073 // assert env_to not empty | 1119 // assert env_to not empty |
1074 char buf[maxlen]; | 1120 char buf[maxlen]; |
1075 char *msg = NULL; | 1121 char *msg = NULL; |
1076 string_set alive; | 1122 string_set alive; |
1077 bool random = false; | 1123 bool random = false; |
1078 int limit = 0; | 1124 int limit = 0; |
1079 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { | 1125 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { |
1080 char *rcpt = (*i).first; | 1126 char *rcpt = (*i).first; |
1081 CONTEXT &con = *((*i).second); | 1127 CONTEXT &con = *((*i).second); |
1082 if (!con.acceptable_content(*priv.memory, msg)) { | 1128 if (!con.acceptable_content(*priv.memory, score, msg)) { |
1083 // bad html tags or excessive hosts | 1129 // bad html tags or excessive hosts or high spam assassin score |
1084 smfi_delrcpt(ctx, rcpt); | 1130 smfi_delrcpt(ctx, rcpt); |
1085 } | 1131 } |
1086 else { | 1132 else { |
1087 alive.insert(rcpt); | 1133 alive.insert(rcpt); |
1088 random |= con.get_host_random(); | 1134 random |= con.get_host_random(); |
1150 { | 1196 { |
1151 "DNSBL", // filter name | 1197 "DNSBL", // filter name |
1152 SMFI_VERSION, // version code -- do not change | 1198 SMFI_VERSION, // version code -- do not change |
1153 SMFIF_DELRCPT, // flags | 1199 SMFIF_DELRCPT, // flags |
1154 mlfi_connect, // connection info filter | 1200 mlfi_connect, // connection info filter |
1155 NULL, // SMTP HELO command filter | 1201 mlfi_helo, // SMTP HELO command filter |
1156 mlfi_envfrom, // envelope sender filter | 1202 mlfi_envfrom, // envelope sender filter |
1157 mlfi_envrcpt, // envelope recipient filter | 1203 mlfi_envrcpt, // envelope recipient filter |
1158 NULL, // header filter | 1204 mlfi_header, // header filter |
1159 NULL, // end of header | 1205 mlfi_eoh, // end of header |
1160 mlfi_body, // body block filter | 1206 mlfi_body, // body block filter |
1161 mlfi_eom, // end of message | 1207 mlfi_eom, // end of message |
1162 mlfi_abort, // message aborted | 1208 mlfi_abort, // message aborted |
1163 mlfi_close, // connection cleanup | 1209 mlfi_close, // connection cleanup |
1164 }; | 1210 }; |
1190 //////////////////////////////////////////////// | 1236 //////////////////////////////////////////////// |
1191 // thread to watch the old config files for changes | 1237 // thread to watch the old config files for changes |
1192 // and reload when needed. | 1238 // and reload when needed. |
1193 // we also clear the SMTP AUTH recipient counts hourly | 1239 // we also clear the SMTP AUTH recipient counts hourly |
1194 // | 1240 // |
1195 void* config_loader(void *arg); | 1241 extern "C" {void* config_loader(void *arg);} |
1196 void* config_loader(void *arg) { | 1242 void* config_loader(void *arg) { |
1197 int loop = 0; | 1243 int loop = 0; |
1198 typedef set<CONFIG *> configp_set; | |
1199 while (loader_run) { | 1244 while (loader_run) { |
1200 sleep(180); // look for modifications every 3 minutes | 1245 sleep(180); // look for modifications every 3 minutes |
1201 if (!loader_run) break; | 1246 if (!loader_run) break; |
1202 loop++; | 1247 loop++; |
1203 if (loop == 20) { | 1248 if (loop == 20) { |
1227 pthread_mutex_lock(&config_mutex); | 1272 pthread_mutex_lock(&config_mutex); |
1228 CONFIG *pc = config; | 1273 CONFIG *pc = config; |
1229 bool last = pc && (!pc->reference_count); | 1274 bool last = pc && (!pc->reference_count); |
1230 config = newc; | 1275 config = newc; |
1231 pthread_mutex_unlock(&config_mutex); | 1276 pthread_mutex_unlock(&config_mutex); |
1232 if (last) delete pc; // there were no references to this config | 1277 if (last) delete pc; // there were no references to this config |
1233 } | 1278 } |
1234 else { | 1279 else { |
1235 // failed to load new config | 1280 // failed to load new config |
1236 my_syslog("failed to load new configuration"); | 1281 my_syslog("failed to load new configuration"); |
1237 system("echo 'failed to load new dnsbl configuration from /etc/dnsbl' | mail -s 'error in /etc/dnsbl configuration' root"); | 1282 system("echo 'failed to load new dnsbl configuration from /etc/dnsbl' | mail -s 'error in /etc/dnsbl configuration' root"); |
1266 | 1311 |
1267 | 1312 |
1268 void setup_socket(char *sock); | 1313 void setup_socket(char *sock); |
1269 void setup_socket(char *sock) { | 1314 void setup_socket(char *sock) { |
1270 unlink(sock); | 1315 unlink(sock); |
1271 // sockaddr_un addr; | |
1272 // memset(&addr, '\0', sizeof addr); | |
1273 // addr.sun_family = AF_UNIX; | |
1274 // strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1); | |
1275 // int s = socket(AF_UNIX, SOCK_STREAM, 0); | |
1276 // bind(s, (sockaddr*)&addr, sizeof(addr)); | |
1277 // close(s); | |
1278 } | 1316 } |
1279 | 1317 |
1280 | 1318 |
1281 /* | 1319 /* |
1282 * The signal handler function -- only gets called when a SIGCHLD | 1320 * The signal handler function -- only gets called when a SIGCHLD |