Mercurial > dnsbl
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]); |