comparison src/dnsbl.cpp @ 75:1142e46be550

start coding on new config syntax
author carl
date Wed, 13 Jul 2005 23:04:14 -0700
parents b7449114ebb0
children 81f1e400e8ab
comparison
equal deleted inserted replaced
74:b7449114ebb0 75:1142e46be550
89 void sig_chld(int signo); 89 void sig_chld(int signo);
90 } 90 }
91 91
92 bool debug_syslog = false; 92 bool debug_syslog = false;
93 bool syslog_opened = false; 93 bool syslog_opened = false;
94 bool loader_run = true; // used to stop the config loader thread 94 bool use_syslog = true; // false to printf
95 CONFIG * config = NULL; // protected by the config_mutex 95 bool loader_run = true; // used to stop the config loader thread
96 int generation = 0; // protected by the config_mutex 96 CONFIG * config = NULL; // protected by the config_mutex
97 int generation = 0; // protected by the config_mutex
97 98
98 pthread_mutex_t config_mutex; 99 pthread_mutex_t config_mutex;
99 pthread_mutex_t syslog_mutex; 100 pthread_mutex_t syslog_mutex;
100 pthread_mutex_t resolve_mutex; 101 pthread_mutex_t resolve_mutex;
101 pthread_mutex_t fd_pool_mutex; 102 pthread_mutex_t fd_pool_mutex;
380 char buf[1000]; 381 char buf[1000];
381 if (priv) { 382 if (priv) {
382 snprintf(buf, sizeof(buf), "%s: %s", priv->queueid, text); 383 snprintf(buf, sizeof(buf), "%s: %s", priv->queueid, text);
383 text = buf; 384 text = buf;
384 } 385 }
385 pthread_mutex_lock(&syslog_mutex); 386 if (use_syslog) {
386 if (!syslog_opened) { 387 pthread_mutex_lock(&syslog_mutex);
387 openlog("dnsbl", LOG_PID, LOG_MAIL); 388 if (!syslog_opened) {
388 syslog_opened = true; 389 openlog("dnsbl", LOG_PID, LOG_MAIL);
389 } 390 syslog_opened = true;
390 syslog(LOG_NOTICE, "%s", text); 391 }
391 pthread_mutex_unlock(&syslog_mutex); 392 syslog(LOG_NOTICE, "%s", text);
393 pthread_mutex_unlock(&syslog_mutex);
394 }
395 else {
396 printf("%s \n", text);
397 }
392 } 398 }
393 399
394 void my_syslog(char *text) { 400 void my_syslog(char *text) {
395 my_syslog(NULL, text); 401 my_syslog(NULL, text);
396 } 402 }
582 // 588 //
583 bool check_single(mlfiPriv &priv, int ip, char *suffix); 589 bool check_single(mlfiPriv &priv, int ip, char *suffix);
584 bool check_single(mlfiPriv &priv, int ip, char *suffix) { 590 bool check_single(mlfiPriv &priv, int ip, char *suffix) {
585 // make a dns question 591 // make a dns question
586 const u_char *src = (const u_char *)&ip; 592 const u_char *src = (const u_char *)&ip;
587 if (src[0] == 127) return oksofar; // don't do dns lookups on localhost 593 if (src[0] == 127) return false; // don't do dns lookups on localhost
588 #ifdef NS_MAXDNAME 594 #ifdef NS_MAXDNAME
589 char question[NS_MAXDNAME]; 595 char question[NS_MAXDNAME];
590 #else 596 #else
591 char question[1000]; 597 char question[1000];
592 #endif 598 #endif
608 //////////////////////////////////////////////// 614 ////////////////////////////////////////////////
609 // check the dnsbls specified for this recipient 615 // check the dnsbls specified for this recipient
610 // 616 //
611 bool check_dnsbl(mlfiPriv &priv, dnsblp_list &dnsbll, DNSBLP &rejectlist); 617 bool check_dnsbl(mlfiPriv &priv, dnsblp_list &dnsbll, DNSBLP &rejectlist);
612 bool check_dnsbl(mlfiPriv &priv, dnsblp_list &dnsbll, DNSBLP &rejectlist) { 618 bool check_dnsbl(mlfiPriv &priv, dnsblp_list &dnsbll, DNSBLP &rejectlist) {
613 if (priv.authenticated) return oksofar; 619 if (priv.authenticated) return false;
614 for (dnsblp_list::iterator i=dnsbll.begin(); i!=dnsbll.end(); i++) { 620 for (dnsblp_list::iterator i=dnsbll.begin(); i!=dnsbll.end(); i++) {
615 DNSBLP dp = *i; // non null by construction 621 DNSBLP dp = *i; // non null by construction
616 bool st; 622 bool st;
617 map<DNSBLP, bool>::iterator f = priv.checked.find(dp); 623 map<DNSBLP, bool>::iterator f = priv.checked.find(dp);
618 if (f == priv.checked.end()) { 624 if (f == priv.checked.end()) {
634 //////////////////////////////////////////////// 640 ////////////////////////////////////////////////
635 // check the hosts from the body against the content dnsbl 641 // check the hosts from the body against the content dnsbl
636 // 642 //
637 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&host, int ip); 643 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&host, int ip);
638 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&host, int ip) { 644 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&host, int ip) {
639 CONFIG &dc = *priv.pc; 645 CONFIG &dc = *priv.pc;
640 string_set &hosts = priv.memory->get_hosts(); 646 string_set &hosts = priv.memory->get_hosts();
641 string_set &ignore = dc.get_content_host_ignore(); 647 string_set &ignore = dc.get_content_host_ignore();
648 char *suffix = dc.get_content_suffix();
642 649
643 int count = 0; 650 int count = 0;
644 int cnt = hosts.size(); // number of hosts we could look at 651 int cnt = hosts.size(); // number of hosts we could look at
645 int_set ips; 652 int_set ips;
646 ns_map nameservers; 653 ns_map nameservers;
678 } 685 }
679 if (ip) { 686 if (ip) {
680 int_set::iterator i = ips.find(ip); 687 int_set::iterator i = ips.find(ip);
681 if (i == ips.end()) { 688 if (i == ips.end()) {
682 ips.insert(ip); 689 ips.insert(ip);
683 if (check_single(priv, ip, dc.get_content_suffix())) { 690 if (check_single(priv, ip, suffix)) {
684 return true; 691 return true;
685 } 692 }
686 } 693 }
687 } 694 }
688 } 695 }
711 } 718 }
712 if (ip) { 719 if (ip) {
713 int_set::iterator i = ips.find(ip); 720 int_set::iterator i = ips.find(ip);
714 if (i == ips.end()) { 721 if (i == ips.end()) {
715 ips.insert(ip); 722 ips.insert(ip);
716 if (check_single(priv, ip, dc.get_content_suffix())) { 723 if (check_single(priv, ip, suffix)) {
717 string_map::iterator j = nameservers.ns_host.find(host); 724 string_map::iterator j = nameservers.ns_host.find(host);
718 if (j != nameservers.ns_host.end()) { 725 if (j != nameservers.ns_host.end()) {
719 char *refer = (*j).second; 726 char *refer = (*j).second;
720 char buf[1000]; 727 char buf[1000];
721 snprintf(buf, sizeof(buf), "%s with nameserver %s", refer, host); 728 snprintf(buf, sizeof(buf), "%s with nameserver %s", refer, host);
732 return false; 739 return false;
733 } 740 }
734 741
735 742
736 //////////////////////////////////////////////// 743 ////////////////////////////////////////////////
744 // this email address is passed in from sendmail, and will
745 // always be enclosed in <>. It may have mixed case, just
746 // as the mail client sent it. We dup the string and convert
747 // the duplicate to lower case.
748 //
749 char *to_lower_string(char *email);
750 char *to_lower_string(char *email) {
751 int n = strlen(email)-2;
752 if (n < 1) return strdup(email);
753 char *key = strdup(email+1);
754 key[n] = '\0';
755 for (int i=0; i<n; i++) key[i] = tolower(key[i]);
756 return key;
757 }
758
759
760 ////////////////////////////////////////////////
737 // start of sendmail milter interfaces 761 // start of sendmail milter interfaces
738 // 762 //
739 sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) 763 sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
740 { 764 {
741 // allocate some private memory 765 // allocate some private memory
752 } 776 }
753 777
754 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from) 778 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from)
755 { 779 {
756 mlfiPriv &priv = *MLFIPRIV; 780 mlfiPriv &priv = *MLFIPRIV;
757 priv.mailaddr = strdup(from[0]); 781 priv.mailaddr = to_lower_string(from[0]);
758 priv.authenticated = (smfi_getsymval(ctx, "{auth_authen}") != NULL); 782 priv.authenticated = (smfi_getsymval(ctx, "{auth_authen}") != NULL);
759 return SMFIS_CONTINUE; 783 return SMFIS_CONTINUE;
760 } 784 }
761 785
762 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) 786 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt)
763 { 787 {
764 DNSBLP rejectlist = NULL; // list that caused the reject 788 DNSBLP rejectlist = NULL; // list that caused the reject
765 mlfiPriv &priv = *MLFIPRIV; 789 mlfiPriv &priv = *MLFIPRIV;
766 CONFIG &dc = *priv.pc; 790 CONFIG &dc = *priv.pc;
767 if (!priv.queueid) priv.queueid = strdup(smfi_getsymval(ctx, "i")); 791 if (!priv.queueid) priv.queueid = strdup(smfi_getsymval(ctx, "i"));
768 char *rcptaddr = rcpt[0]; 792 char *rcptaddr = rcpt[0];
769 CONTEXT &con = *(dc.find_context(rcptaddr, priv.mailaddr)); 793 char *loto = to_lower_string(rcptaddr);
794 CONTEXT con = *(dc.find_context(loto)->find_context(priv.mailaddr));
770 char *fromvalue = con.find_from(priv.mailaddr); 795 char *fromvalue = con.find_from(priv.mailaddr);
796 free(loto);
771 status st; 797 status st;
772 if (fromvalue == token_black) { 798 if (fromvalue == token_black) {
773 st = black; 799 st = black;
774 } 800 }
775 else if (fromvalue == token_white) { 801 else if (fromvalue == token_white) {
984 1010
985 1011
986 void usage(char *prog); 1012 void usage(char *prog);
987 void usage(char *prog) 1013 void usage(char *prog)
988 { 1014 {
989 fprintf(stderr, "Usage: %s [-d] [-c] -r port -p sm-sock-addr [-t timeout]\n", prog); 1015 fprintf(stderr, "Usage: %s [-d] [-c] [-s] [-e from|to] -r port -p sm-sock-addr [-t timeout]\n", prog);
990 fprintf(stderr, "where port is for the connection to our own dns resolver processes\n"); 1016 fprintf(stderr, "where port is for the connection to our own dns resolver processes\n");
991 fprintf(stderr, " and should be local-domain-socket-file-name\n"); 1017 fprintf(stderr, " and should be local-domain-socket-file-name\n");
992 fprintf(stderr, "where sm-sock-addr is for the connection to sendmail\n"); 1018 fprintf(stderr, "where sm-sock-addr is for the connection to sendmail\n");
993 fprintf(stderr, " and should be one of\n"); 1019 fprintf(stderr, " and should be one of\n");
994 fprintf(stderr, " inet:port@ip-address\n"); 1020 fprintf(stderr, " inet:port@ip-address\n");
995 fprintf(stderr, " local:local-domain-socket-file-name\n"); 1021 fprintf(stderr, " local:local-domain-socket-file-name\n");
996 fprintf(stderr, "-c will load and dump the config to stdout\n"); 1022 fprintf(stderr, "-c will load and dump the config to stdout\n");
1023 fprintf(stderr, "-s will stress test the config loading code by repeating the load/free cycle\n");
1024 fprintf(stderr, " in an infinte loop.\n");
997 fprintf(stderr, "-d will add some syslog debug messages\n"); 1025 fprintf(stderr, "-d will add some syslog debug messages\n");
1026 fprintf(stderr, "-e will print the results of looking up the from and to addresses in the\n");
1027 fprintf(stderr, " current config. The | character is used to separate the from and to\n");
1028 fprintf(stderr, " addresses in the argument to the -e switch\n");
998 } 1029 }
999 1030
1000 1031
1001 1032
1002 void setup_socket(char *sock); 1033 void setup_socket(char *sock);
1028 1059
1029 int main(int argc, char**argv) 1060 int main(int argc, char**argv)
1030 { 1061 {
1031 token_init(); 1062 token_init();
1032 bool check = false; 1063 bool check = false;
1064 bool stress = false;
1033 bool setconn = false; 1065 bool setconn = false;
1034 bool setreso = false; 1066 bool setreso = false;
1067 char *email = NULL;
1035 int c; 1068 int c;
1036 const char *args = "r:p:t:hcd"; 1069 const char *args = "r:p:t:e:cdhs";
1037 extern char *optarg; 1070 extern char *optarg;
1038 1071
1039 // Process command line options 1072 // Process command line options
1040 while ((c = getopt(argc, argv, args)) != -1) { 1073 while ((c = getopt(argc, argv, args)) != -1) {
1041 switch (c) { 1074 switch (c) {
1072 fprintf(stderr, "smfi_settimeout failed\n"); 1105 fprintf(stderr, "smfi_settimeout failed\n");
1073 exit(EX_SOFTWARE); 1106 exit(EX_SOFTWARE);
1074 } 1107 }
1075 break; 1108 break;
1076 1109
1110 case 'e':
1111 if (email) free(email);
1112 email = strdup(optarg);
1113 break;
1114
1077 case 'c': 1115 case 'c':
1078 check = true; 1116 check = true;
1117 break;
1118
1119 case 's':
1120 stress = true;
1079 break; 1121 break;
1080 1122
1081 case 'd': 1123 case 'd':
1082 debug_syslog = true; 1124 debug_syslog = true;
1083 break; 1125 break;
1088 exit(EX_USAGE); 1130 exit(EX_USAGE);
1089 } 1131 }
1090 } 1132 }
1091 1133
1092 if (check) { 1134 if (check) {
1135 use_syslog = false;
1093 CONFIG *conf = new_conf(); 1136 CONFIG *conf = new_conf();
1094 if (conf) { 1137 if (conf) {
1095 conf->dump(); 1138 conf->dump();
1096 delete conf; 1139 delete conf;
1097 return 0; 1140 return 0;
1098 } 1141 }
1099 else { 1142 else {
1100 return 1; // config failed to load 1143 return 1; // config failed to load
1101 } 1144 }
1145 }
1146
1147 if (stress) {
1148 fprintf(stdout, "stress testing\n");
1149 while (1) {
1150 for (int i=0; i<10; i++) {
1151 CONFIG *conf = new_conf();
1152 if (conf) delete conf;
1153 }
1154 fprintf(stdout, ".");
1155 fflush(stdout);
1156 sleep(1);
1157 }
1158 }
1159
1160 if (email) {
1161 char *x = strchr(email, '|');
1162 if (x) {
1163 *x = '\0';
1164 char *from = strdup(email);
1165 char *to = strdup(x+1);
1166 use_syslog = false;
1167 CONFIG *conf = new_conf();
1168 if (conf) {
1169 CONTEXTP con = conf->find_context(to);
1170 const int maxlen = 1000;
1171 char buf[maxlen];
1172 fprintf(stdout, "envelope to <%s> finds context %s\n", to, con->get_full_name(buf,maxlen));
1173 CONTEXTP fc = con->find_context(from);
1174 fprintf(stdout, "envelope from <%s> finds context %s\n", from, fc->get_full_name(buf,maxlen));
1175 char *st = fc->find_from(from);
1176 fprintf(stdout, "envelope from <%s> finds status %s\n", from, st);
1177 delete conf;
1178 }
1179 }
1180 return 0;
1102 } 1181 }
1103 1182
1104 if (!setconn) { 1183 if (!setconn) {
1105 fprintf(stderr, "%s: Missing required -p argument\n", argv[0]); 1184 fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
1106 usage(argv[0]); 1185 usage(argv[0]);