source: npl/mailserver/netqmail/helodnscheck2.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2* Copyright (C) 2007 Jason Frisvold <friz@godshell.com>
3* Original Copyright (C) 2003-2004 Perolo Silantico <per.sil@gmx.it>
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU General Public License
7* as published by the Free Software Foundation; either
8* version 2 of the License, or (at your option) any later
9* version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program; if not, write to the Free Software Foundation,
18* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19***
20* 1/16 Modified original version to check helo/ehlo instead of mail from
21***
22*
23* $Id$
24*
25*/
26
27/* (2008) modifyed by Bing Ren <bingtimren (at) gmail.com> to further check
28   if the TCPREMOTEIP variable (mostly set by tcpserver) match
29   any of the IP addresses the HELO resolves to
30
31   depending on the environment variable HELO_DNS_CHECK, deny, log and/or
32   add a header if HELO don't solve to an address or the addresses don't
33   contain the TCPREMOTEIP
34
35        [default] - deny if HELO don't solve to a record
36        P - passthrough, don't deny even HELO don't solve to A record
37            (of course, use with L and/or H)
38        D - deny if TCPREMOTEIP not contained in the addresses solved
39        L - log
40        H - add header "X-Helo-Check"
41        R - if "RELAYCLIENT" is set, don't do anything
42
43   the above can be combined, so DL means deny & log
44   if TCPREMOTEIP is not set, log but allow
45*/
46       
47
48#include <netinet/in.h>
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <arpa/inet.h>
52#include <arpa/nameser.h>
53#include <resolv.h>
54#include <string.h>
55#include <stdlib.h>
56#include <errno.h>
57#include <netdb.h>
58
59void block_permanent(const char* message) {
60
61/* Bing Ren: the original helodnscheck print command "E",
62   however, if the spam connection ignore the 553 error and
63   continue send further commands, qmail-spp simply accept
64   message and deliver it! */
65
66  printf("R553 sorry, %s (#5.7.1)\n", message);
67  fprintf(stderr, "helo-dns-check: blocked with: %s\n", message); 
68}
69
70void block_temporary(const char* message) {
71  printf("E451 %s (#4.3.0)\n", message);
72  fprintf(stderr, "helo-dns-check: temporary failure: %s\n", message); 
73}
74
75int main(void) {
76 unsigned char dns_answer[1023];
77 unsigned char print_address[1023];
78 char *helo_domain = getenv("SMTPHELOHOST");
79 char *no_helo_check = getenv("NOHELODNSCHECK");
80 char *remote_ip = getenv("TCPREMOTEIP");
81 char *action = getenv("HELO_DNS_CHECK");
82 struct hostent* result;
83
84  if (!action) {
85    action = "";
86  };
87
88  if (!remote_ip) {
89    remote_ip = "";
90  };
91
92  if (strpbrk(action,"R") && getenv("RELAYCLIENT"))
93     return 0;
94
95  if (no_helo_check) {
96     return 0;
97  }
98
99  if (!helo_domain) {
100    block_permanent("no HELO/EHLO hostname has been sent.");
101    return 0;
102  }
103
104
105  /* init DNS library */
106  res_init();
107
108  /* check A record */
109  result = gethostbyname(helo_domain);
110
111  /* check if there is any result */
112  if (!result) {
113    if (h_errno == HOST_NOT_FOUND) {
114
115       if (strpbrk(action,"H"))
116          printf("HX-Helo-Check: HELO [%s] from [%s] doesn't solve\n", helo_domain, remote_ip);
117
118       if (strpbrk(action,"L"))
119          fprintf(stderr, "helo-dns-check: HELO [%s] from [%s] doesn't solve\n", helo_domain, remote_ip);
120
121       if (!strpbrk(action,"P"))
122          block_permanent("invalid host name in HELO/EHLO command.");
123    }
124    else {
125       fprintf(stderr, "HELO DNS CHECK temporary failed, but let it go.\n");
126    };
127    return 0;
128  };
129
130  int count=0;
131  char* addr;
132
133  /* print debug information */
134  /*
135  fprintf(stderr, "dbg: result->h_name %s\n", result->h_name);
136  fprintf(stderr, "dbg: result->h_aliases:\n");
137  char* alias;
138  while (result->h_aliases[count]) {
139    alias=result->h_aliases[count];
140    fprintf(stderr, "dbg: [%d] %s\n", count, alias);
141    count++;
142  };
143
144  fprintf(stderr, "dbg: result->h_addrtype %d\n", result->h_addrtype);
145  fprintf(stderr, "dbg: result->h_length %d\n", result->h_length);
146  fprintf(stderr, "dbg: result->h_addr_list:\n");
147
148  count=0;
149  while (result->h_addr_list[count]) {
150     addr=result->h_addr_list[count];
151     inet_ntop(AF_INET, addr, print_address, 1000);
152     fprintf(stderr, "dbg: [%d] %s\n", count, print_address);
153     count++;
154  };
155   
156  if (*remote_ip) {
157     fprintf(stderr, "dbg: remote host %s\n", remote_ip);
158  } else {
159     fprintf(stderr, "dbg: no remote ip $TCPREMOTEIP\n");
160  };
161
162  */
163
164  /* check A record of host */
165
166  if (!strpbrk(action,"DLH"))
167     return 0;
168
169  if (!(*remote_ip)) {
170     fprintf(stderr, "helo-dns-check: TCPREMOTEIP not set, let it go.\n");
171     return 0;
172  };
173
174  int found=0;
175  count=0;
176  while (result->h_addr_list[count] && (found==0)) {
177     addr=result->h_addr_list[count];
178     inet_ntop(AF_INET, addr, print_address, 1000);
179     if (strcmp(print_address, remote_ip) == 0) {
180        found = 1;
181     };
182     count++;
183  };
184
185  /* fprintf(stderr, "dbg: found = %d\n", found);  */
186
187  if (found == 1)
188     return 0;
189
190  if (strpbrk(action,"H"))
191     printf("HX-Helo-Check: HELO [%s] doesn't match IP [%s]\n", helo_domain, remote_ip);
192
193  if (strpbrk(action,"L"))
194     fprintf(stderr, "helo-dns-check: HELO [%s] doesn't match IP [%s]\n", helo_domain, remote_ip);
195
196  if (strpbrk(action,"D") && (!strpbrk(action,"P")))
197     block_permanent("HELO/EHLO command must provide FQDN that match your IP address.");
198
199  return 0;
200
201}
202
Note: See TracBrowser for help on using the repository browser.