Search
j0ke.net Open Build Service
>
Projects
>
server:mail
>
qmail-spp-plugins
> helodnscheck2.c
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File helodnscheck2.c of Package qmail-spp-plugins
/* * Copyright (C) 2007 Jason Frisvold <friz@godshell.com> * Original Copyright (C) 2003-2004 Perolo Silantico <per.sil@gmx.it> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *** * 2011-06-16 Modified to work in dualstack environment * (IPv6 support) Carsten Schoene <cs@linux-administrator.com> * 1/16 Modified original version to check helo/ehlo instead of mail from *** * * $Id$ * */ /* (2008) modifyed by Bing Ren <bingtimren (at) gmail.com> to further check if the TCPREMOTEIP variable (mostly set by tcpserver) match any of the IP addresses the HELO resolves to depending on the environment variable HELO_DNS_CHECK, deny, log and/or add a header if HELO don't solve to an address or the addresses don't contain the TCPREMOTEIP [default] - deny if HELO don't solve to a record P - passthrough, don't deny even HELO don't solve to A record (of course, use with L and/or H) D - deny if TCPREMOTEIP not contained in the addresses solved L - log H - add header "X-Helo-Check" R - if "RELAYCLIENT" is set, don't do anything the above can be combined, so DL means deny & log if TCPREMOTEIP is not set, log but allow */ #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <arpa/nameser.h> #include <resolv.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <netdb.h> void block_permanent(const char* message) { /* Bing Ren: the original helodnscheck print command "E", however, if the spam connection ignore the 553 error and continue send further commands, qmail-spp simply accept message and deliver it! */ printf("R553 sorry, %s (#5.7.1)\n", message); fprintf(stderr, "helo-dns-check: blocked with: %s\n", message); } void block_temporary(const char* message) { printf("E451 %s (#4.3.0)\n", message); fprintf(stderr, "helo-dns-check: temporary failure: %s\n", message); } int main(void) { unsigned char dns_answer[1023]; unsigned char print_address[1023]; char *helo_domain = getenv("SMTPHELOHOST"); char *no_helo_check = getenv("NOHELODNSCHECK"); char *remote_ip = getenv("TCPREMOTEIP"); char *action = getenv("HELO_DNS_CHECK"); struct hostent* result; int fIPv4 = 0; if (!action) { action = ""; }; if (!remote_ip) { remote_ip = ""; }; if (strpbrk(action,"R") && getenv("RELAYCLIENT")) return 0; if (no_helo_check) { return 0; } if (!helo_domain) { block_permanent("no HELO/EHLO hostname has been sent."); return 0; } fIPv4 = (NULL == strchr(remote_ip, ':')); /* init DNS library */ res_init(); /* check A record */ if (!fIPv4) { _res.options |= RES_USE_INET6; } result = gethostbyname(helo_domain); /* check if there is any result */ if (!result) { if (h_errno == HOST_NOT_FOUND) { if (strpbrk(action,"H")) printf("HX-Helo-Check: HELO [%s] from [%s] doesn't solve\n", helo_domain, remote_ip); if (strpbrk(action,"L")) fprintf(stderr, "helo-dns-check: HELO [%s] from [%s] doesn't solve\n", helo_domain, remote_ip); if (!strpbrk(action,"P")) block_permanent("invalid host name in HELO/EHLO command."); } else { fprintf(stderr, "HELO DNS CHECK temporary failed, but let it go.\n"); }; return 0; }; int count=0; char* addr; /* print debug information */ /* fprintf(stderr, "dbg: result->h_name %s\n", result->h_name); fprintf(stderr, "dbg: result->h_aliases:\n"); char* alias; while (result->h_aliases[count]) { alias=result->h_aliases[count]; fprintf(stderr, "dbg: [%d] %s\n", count, alias); count++; }; fprintf(stderr, "dbg: result->h_addrtype %d\n", result->h_addrtype); fprintf(stderr, "dbg: result->h_length %d\n", result->h_length); fprintf(stderr, "dbg: result->h_addr_list:\n"); count=0; while (result->h_addr_list[count]) { addr=result->h_addr_list[count]; inet_ntop(AF_INET, addr, print_address, 1000); fprintf(stderr, "dbg: [%d] %s\n", count, print_address); count++; }; if (*remote_ip) { fprintf(stderr, "dbg: remote host %s\n", remote_ip); } else { fprintf(stderr, "dbg: no remote ip $TCPREMOTEIP\n"); }; */ /* check A record of host */ if (!strpbrk(action,"DLH")) return 0; if (!(*remote_ip)) { fprintf(stderr, "helo-dns-check: TCPREMOTEIP not set, let it go.\n"); return 0; }; int found=0; count=0; while (result->h_addr_list[count] && (found==0)) { addr=result->h_addr_list[count]; if (!fIPv4) { inet_ntop(AF_INET6, addr, print_address, 1000); } else { inet_ntop(AF_INET, addr, print_address, 1000); } if (strcmp(print_address, remote_ip) == 0) { found = 1; }; count++; }; /* fprintf(stderr, "dbg: found = %d\n", found); */ if (found == 1) return 0; if (strpbrk(action,"H")) printf("HX-Helo-Check: HELO [%s] doesn't match IP [%s]\n", helo_domain, remote_ip); if (strpbrk(action,"L")) fprintf(stderr, "helo-dns-check: HELO [%s] doesn't match IP [%s]\n", helo_domain, remote_ip); if (strpbrk(action,"D") && (!strpbrk(action,"P"))) block_permanent("HELO/EHLO command must provide FQDN that match your IP address."); return 0; }