comparison src/context.cpp @ 153:8d7c439bb6fa

add auto whitelisting
author carl
date Sat, 07 Jul 2007 16:10:39 -0700
parents c7fc218686f5
children 89ce226e5383
comparison
equal deleted inserted replaced
152:c7fc218686f5 153:8d7c439bb6fa
19 #include <sys/socket.h> 19 #include <sys/socket.h>
20 #include <sys/un.h> 20 #include <sys/un.h>
21 21
22 static char* context_version="$Id$"; 22 static char* context_version="$Id$";
23 23
24 char *token_autowhite;
24 char *token_black; 25 char *token_black;
25 char *token_content; 26 char *token_content;
26 char *token_context; 27 char *token_context;
27 char *token_dccfrom; 28 char *token_dccfrom;
28 char *token_dccto; 29 char *token_dccto;
61 #ifndef HOST_NAME_MAX 62 #ifndef HOST_NAME_MAX
62 #define HOST_NAME_MAX 255 63 #define HOST_NAME_MAX 255
63 #endif 64 #endif
64 char myhostname[HOST_NAME_MAX+1]; 65 char myhostname[HOST_NAME_MAX+1];
65 66
67 pthread_mutex_t verifier_mutex; // protect the verifier map
66 verify_map verifiers; 68 verify_map verifiers;
69
70 pthread_mutex_t whitelister_mutex; // protect the
71 whitelister_map whitelisters;
72
67 string_set all_strings; // owns all the strings, only modified by the config loader thread 73 string_set all_strings; // owns all the strings, only modified by the config loader thread
68 const int maxlen = 1000; // used for snprintf buffers 74 const int maxlen = 1000; // used for snprintf buffers
69 const int maxage = 120; // smtp verify sockets older than this are ancient 75 const int maxsmtp_age = 120;// smtp verify sockets older than this are ancient
76 const int maxauto_age = 600;// auto whitelister delay before flushing to file
70 extern int NULL_SOCKET; 77 extern int NULL_SOCKET;
71 const time_t ERROR_SMTP_SOCKET_TIME = 600; // number of seconds between attempts to open a socket to an smtp server 78 const time_t ERROR_SMTP_SOCKET_TIME = 600; // number of seconds between attempts to open a socket to an smtp server
72 79
73 80
74 int SMTP::writer() { 81 int SMTP::writer() {
241 my_syslog(buf); 248 my_syslog(buf);
242 } 249 }
243 #endif 250 #endif
244 251
245 252
253 ////////////////////////////////////////////////
254 // smtp verifier so backup mx machines can see the valid users
255 //
246 VERIFY::VERIFY(char *h) { 256 VERIFY::VERIFY(char *h) {
247 host = h; 257 host = h;
248 last_err = 0; 258 last_err = 0;
249 pthread_mutex_init(&mutex, 0); 259 pthread_mutex_init(&mutex, 0);
250 } 260 }
259 ok = false; 269 ok = false;
260 } 270 }
261 else { 271 else {
262 conn = connections.front(); 272 conn = connections.front();
263 time_t now = time(NULL); 273 time_t now = time(NULL);
264 if ((now - conn->get_stamp()) > maxage) { 274 if ((now - conn->get_stamp()) > maxsmtp_age) {
265 // this connection is ancient, remove it 275 // this connection is ancient, remove it
266 connections.pop_front(); 276 connections.pop_front();
267 } 277 }
268 else { 278 else {
269 ok = false; 279 ok = false;
370 put_connection(conn); 380 put_connection(conn);
371 return (rc >= 500) ? false : true; 381 return (rc >= 500) ? false : true;
372 } 382 }
373 383
374 384
385 ////////////////////////////////////////////////
386 // setup a new smtp verify host
387 //
388 VERIFYP add_verify_host(char *host);
389 VERIFYP add_verify_host(char *host) {
390 VERIFYP rc = NULL;
391 pthread_mutex_lock(&verifier_mutex);
392 verify_map::iterator i = verifiers.find(host);
393 if (i == verifiers.end()) {
394 rc = new VERIFY(host);
395 verifiers[host] = rc;
396 }
397 else rc = (*i).second;
398 pthread_mutex_unlock(&verifier_mutex);
399 return rc;
400 }
401
402
403 ////////////////////////////////////////////////
404 // thread to check for verify hosts with old sockets that we can close
405 //
406 void* verify_closer(void *arg) {
407 while (true) {
408 sleep(maxsmtp_age);
409 pthread_mutex_lock(&verifier_mutex);
410 for (verify_map::iterator i=verifiers.begin(); i!=verifiers.end(); i++) {
411 VERIFYP v = (*i).second;
412 v->closer();
413 }
414 pthread_mutex_unlock(&verifier_mutex);
415 }
416 return NULL;
417 }
418
419
420 ////////////////////////////////////////////////
421 // automatic whitelister
422 //
423 WHITELISTER::WHITELISTER(char *f, int d) {
424 fn = f;
425 days = d;
426 pthread_mutex_init(&mutex, 0);
427 need = false;
428 }
429
430
431 void WHITELISTER::writer() {
432 pthread_mutex_lock(&mutex);
433 time_t limit = time(NULL) - days*86400;
434 for (autowhite_sent::iterator i=rcpts.begin(); i!=rcpts.end();) {
435 time_t when = (*i).second;
436 if (when < limit) {
437 autowhite_sent::iterator j = i;
438 j++;
439 rcpts.erase(i);
440 i = j;
441 need = true;
442 }
443 else i++;
444 }
445 if (need) {
446 // dump the file
447 ofstream os;
448 os.open(fn);
449 if (!os.fail()) {
450 for (autowhite_sent::iterator i=rcpts.begin(); i!=rcpts.end(); i++) {
451 char *who = (*i).first;
452 int when = (*i).second;
453 os << who << " " << when << endl;
454 }
455 }
456 os.close();
457 }
458 pthread_mutex_unlock(&mutex);
459 }
460
461
462 void WHITELISTER::sent(char *to) {
463 pthread_mutex_lock(&mutex);
464 need = true;
465 rcpts[to] = time(NULL);
466 pthread_mutex_unlock(&mutex);
467 }
468
469
470 bool WHITELISTER::is_white(char *from) {
471 bool rc = false;
472 pthread_mutex_lock(&mutex);
473 autowhite_sent::iterator i = rcpts.find(from);
474 if (i != rcpts.end()) {
475 time_t when = (*i).second;
476 time_t now = time(NULL);
477 rc = (when+(days*8640) > now);
478 }
479 pthread_mutex_unlock(&mutex);
480 return rc;
481 }
482
483
484 ////////////////////////////////////////////////
485 // setup a new auto whitelister file
486 //
487 WHITELISTERP add_whitelister_file(char *fn, int days);
488 WHITELISTERP add_whitelister_file(char *fn, int days) {
489 WHITELISTERP rc = NULL;
490 pthread_mutex_lock(&whitelister_mutex);
491 whitelister_map::iterator i = whitelisters.find(fn);
492 if (i == whitelisters.end()) {
493 rc = new WHITELISTER(fn, days);
494 whitelisters[fn] = rc;
495 }
496 else rc = (*i).second;
497 pthread_mutex_unlock(&whitelister_mutex);
498 return rc;
499 }
500
501
502 ////////////////////////////////////////////////
503 // thread to check for whitelister hosts with old sockets that we can close
504 //
505 void* whitelister_writer(void *arg) {
506 while (true) {
507 sleep(maxauto_age);
508 pthread_mutex_lock(&whitelister_mutex);
509 for (whitelister_map::iterator i=whitelisters.begin(); i!=whitelisters.end(); i++) {
510 WHITELISTERP v = (*i).second;
511 v->writer();
512 }
513 pthread_mutex_unlock(&whitelister_mutex);
514 }
515 return NULL;
516 }
517
518
375 DNSBL::DNSBL(char *n, char *s, char *m) { 519 DNSBL::DNSBL(char *n, char *s, char *m) {
376 name = n; 520 name = n;
377 suffix = s; 521 suffix = s;
378 message = m; 522 message = m;
379 } 523 }
472 616
473 CONTEXT::CONTEXT(CONTEXTP parent_, char *name_) { 617 CONTEXT::CONTEXT(CONTEXTP parent_, char *name_) {
474 parent = parent_; 618 parent = parent_;
475 name = name_; 619 name = name_;
476 verify_host = NULL; 620 verify_host = NULL;
621 verifier = NULL;
622 autowhite_file = NULL;
623 whitelister = NULL;
477 env_from_default = (parent) ? token_inherit : token_unknown; 624 env_from_default = (parent) ? token_inherit : token_unknown;
478 content_filtering = (parent) ? parent->content_filtering : false; 625 content_filtering = (parent) ? parent->content_filtering : false;
479 content_suffix = NULL; 626 content_suffix = NULL;
480 content_message = NULL; 627 content_message = NULL;
481 uribl_suffix = NULL; 628 uribl_suffix = NULL;
529 return false; 676 return false;
530 } 677 }
531 678
532 679
533 VERIFYP CONTEXT::find_verify(char *to) { 680 VERIFYP CONTEXT::find_verify(char *to) {
534 if (verify_host && (verify_host != token_myhostname) && cover_env_to(to)) { 681 if (verifier && (verify_host != token_myhostname) && cover_env_to(to))
535 verify_map::iterator i = verifiers.find(verify_host); 682 return verifier;
536 if (i == verifiers.end()) { 683 else if (parent)
537 if (debug_syslog) { 684 return parent->find_verify(to);
538 char buf[maxlen]; 685 else
539 snprintf(buf, maxlen, "cannot find struc for %s", verify_host); 686 return NULL;
540 my_syslog(buf); 687 }
541 } 688
542 return NULL; 689
543 } 690 WHITELISTERP CONTEXT::find_autowhite(char *to) {
544 VERIFYP v = (*i).second; 691 if (whitelister && cover_env_to(to))
545 692 return whitelister;
546 return v; 693 else if (parent)
547 } 694 return parent->find_autowhite(to);
548 else if (parent) return parent->find_verify(to); 695 else
549 else return NULL; 696 return NULL;
550 } 697 }
551 698
552 699
553 int CONTEXT::find_rate(char *user) { 700 int CONTEXT::find_rate(char *user) {
554 if (rcpt_per_hour.empty()) return default_rcpt_rate; 701 if (rcpt_per_hour.empty()) return default_rcpt_rate;
556 return (i == rcpt_per_hour.end()) ? default_rcpt_rate : (*i).second; 703 return (i == rcpt_per_hour.end()) ? default_rcpt_rate : (*i).second;
557 } 704 }
558 705
559 706
560 char *CONTEXT::find_from(char *from) { 707 char *CONTEXT::find_from(char *from) {
708 if (whitelister && whitelister->is_white(from)) return token_white;
561 char *rc = env_from_default; 709 char *rc = env_from_default;
562 string_map::iterator i = env_from.find(from); 710 string_map::iterator i = env_from.find(from);
563 if (i != env_from.end()) rc = (*i).second; // found user@domain key 711 if (i != env_from.end()) rc = (*i).second; // found user@domain key
564 else { 712 else {
565 char *x = strchr(from, '@'); 713 char *x = strchr(from, '@');
771 } 919 }
772 printf("%s }; \n", indent); 920 printf("%s }; \n", indent);
773 921
774 if (verify_host) { 922 if (verify_host) {
775 printf("%s verify %s; \n", indent, verify_host); 923 printf("%s verify %s; \n", indent, verify_host);
924 }
925
926 if (autowhite_file && whitelister) {
927 printf("%s autowhite %d %s; \n", indent, whitelister->get_days(), autowhite_file);
776 } 928 }
777 929
778 for (context_map::iterator i=children.begin(); i!=children.end(); i++) { 930 for (context_map::iterator i=children.begin(); i!=children.end(); i++) {
779 CONTEXTP c = (*i).second; 931 CONTEXTP c = (*i).second;
780 c->dump(false, level+1); 932 c->dump(false, level+1);
1098 bool parse_verify(TOKEN &tok, CONFIG &dc, CONTEXT &me); 1250 bool parse_verify(TOKEN &tok, CONFIG &dc, CONTEXT &me);
1099 bool parse_verify(TOKEN &tok, CONFIG &dc, CONTEXT &me) { 1251 bool parse_verify(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
1100 char *host = tok.next(); 1252 char *host = tok.next();
1101 if (!tsa(tok, token_semi)) return false; 1253 if (!tsa(tok, token_semi)) return false;
1102 me.set_verify(host); 1254 me.set_verify(host);
1103 add_verify_host(host); 1255 me.set_verifier(add_verify_host(host));
1256 return true;
1257 }
1258
1259
1260 ////////////////////////////////////////////////
1261 //
1262 bool parse_autowhite(TOKEN &tok, CONFIG &dc, CONTEXT &me);
1263 bool parse_autowhite(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
1264 int days = tok.nextint();
1265 char *fn = tok.next();
1266 if (!tsa(tok, token_semi)) return false;
1267 me.set_autowhite(fn);
1268 me.set_whitelister(add_whitelister_file(fn, days));
1104 return true; 1269 return true;
1105 } 1270 }
1106 1271
1107 1272
1108 //////////////////////////////////////////////// 1273 ////////////////////////////////////////////////
1231 if (!parse_envto(tok, dc, *con)) return false; 1396 if (!parse_envto(tok, dc, *con)) return false;
1232 } 1397 }
1233 else if (have == token_verify) { 1398 else if (have == token_verify) {
1234 if (!parse_verify(tok, dc, *con)) return false; 1399 if (!parse_verify(tok, dc, *con)) return false;
1235 } 1400 }
1401 else if (have == token_autowhite) {
1402 if (!parse_autowhite(tok, dc, *con)) return false;
1403 }
1236 else if (have == token_envfrom) { 1404 else if (have == token_envfrom) {
1237 if (!parse_envfrom(tok, dc, *con)) return false; 1405 if (!parse_envfrom(tok, dc, *con)) return false;
1238 } 1406 }
1239 else if (have == token_rate) { 1407 else if (have == token_rate) {
1240 if (parent || dc.default_context) tok.token_error("rate limit ignored in non default context"); 1408 if (parent || dc.default_context) tok.token_error("rate limit ignored in non default context");
1284 return (dc.default_context) ? true : false; 1452 return (dc.default_context) ? true : false;
1285 } 1453 }
1286 1454
1287 1455
1288 //////////////////////////////////////////////// 1456 ////////////////////////////////////////////////
1289 // setup a new smtp verify host
1290 //
1291 void add_verify_host(char *host) {
1292 verify_map::iterator i = verifiers.find(host);
1293 if (i == verifiers.end()) {
1294 VERIFYP v = new VERIFY(host);
1295 verifiers[host] = v;
1296 }
1297 }
1298
1299
1300 ////////////////////////////////////////////////
1301 // thread to check for verify hosts with old sockets that we can close
1302 //
1303 void* verify_closer(void *arg) {
1304 while (true) {
1305 sleep(maxage);
1306 for (verify_map::iterator i=verifiers.begin(); i!=verifiers.end(); i++) {
1307 VERIFYP v = (*i).second;
1308 v->closer();
1309 }
1310 }
1311 return NULL;
1312 }
1313
1314
1315 ////////////////////////////////////////////////
1316 // init the tokens 1457 // init the tokens
1317 // 1458 //
1318 void token_init() { 1459 void token_init() {
1460 token_autowhite = register_string("autowhite");
1319 token_black = register_string("black"); 1461 token_black = register_string("black");
1320 token_cctld = register_string("cctld"); 1462 token_cctld = register_string("cctld");
1321 token_content = register_string("content"); 1463 token_content = register_string("content");
1322 token_context = register_string("context"); 1464 token_context = register_string("context");
1323 token_dccfrom = register_string("dcc_from"); 1465 token_dccfrom = register_string("dcc_from");