Просмотр исходного кода

Applied ACL patch from Kaspersky Labs and corrected host list parsing.

Eric Stanley 14 лет назад
Родитель
Сommit
c622fd6453
7 измененных файлов с 590 добавлено и 106 удалено
  1. 65 0
      include/acl.h
  2. 6 6
      include/dh.h
  3. 6 2
      include/nrpe.h
  4. 3 1
      sample-config/nrpe.cfg.in
  5. 2 2
      src/Makefile.in
  6. 469 0
      src/acl.c
  7. 39 95
      src/nrpe.c

+ 65 - 0
include/acl.h

@@ -0,0 +1,65 @@
+/*-
+ * acl.c - header file for acl.c
+ * Copyright (c) 2011 Kaspersky Lab ZAO
+ * Last Modified: 08-10-2011 by Konstantin Malov with Oleg Koreshkov's help 
+ *
+ * License: GPL
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef ACL_H_INCLUDED
+#define ACL_H_INCLUDED 1
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#define CHAR_TO_NUMBER(c)   ((c) - '0')
+
+struct ip_acl {
+        struct in_addr  addr;
+        struct in_addr  mask;
+        struct ip_acl   *next;
+};
+
+struct dns_acl {
+        char domain[255];
+        struct dns_acl *next;
+};
+
+/* Poiters to head ACL structs */
+static struct ip_acl *ip_acl_head, *ip_acl_prev;
+static struct dns_acl *dns_acl_head, *dns_acl_prev;
+
+/* Functions */
+void parse_allowed_hosts(char *allowed_hosts);
+int add_ipv4_to_acl(char *ipv4);
+int add_domain_to_acl(char *domain);
+int is_an_allowed_host(struct in_addr);
+unsigned int prefix_from_mask(struct in_addr mask);
+void show_acl_lists(void);
+
+#endif /* ACL_H_INCLUDED */

+ 6 - 6
include/dh.h

@@ -4,12 +4,12 @@
 DH *get_dh512()
 	{
 	static unsigned char dh512_p[]={
-		0xA0,0xC9,0x8F,0x6D,0x75,0x7A,0x4E,0xED,0xED,0x80,0x11,0x32,
-		0x77,0x14,0xEA,0xE0,0xE7,0x38,0x55,0x01,0x03,0x02,0xC5,0x34,
-		0xCA,0x2D,0xA7,0xFA,0x2E,0x1C,0x5F,0xD9,0xF4,0xDA,0x54,0x40,
-		0xD7,0xB4,0x7B,0x00,0xE5,0x19,0x30,0x69,0xC5,0x93,0x52,0x09,
-		0xB7,0x2D,0x5B,0xAB,0x27,0x0C,0x0D,0xAA,0xCE,0x56,0xB7,0x4D,
-		0xE9,0x8A,0xFB,0x43,
+		0x96,0x9A,0x23,0x95,0x6A,0xBA,0x24,0x9C,0xE6,0x46,0x5B,0xFF,
+		0xFE,0x76,0xEA,0xCF,0xA5,0xCF,0xE0,0xD8,0x94,0xDB,0x77,0x78,
+		0xC4,0x22,0xE8,0xC6,0x36,0x4B,0xDF,0x34,0xE1,0xA7,0x12,0x66,
+		0x6A,0x43,0x46,0x81,0x8D,0xFB,0xF3,0xE5,0xDC,0x13,0x19,0x3F,
+		0x90,0xFD,0x21,0x1C,0x2E,0x1F,0xCF,0xEF,0x5B,0x3F,0x25,0x75,
+		0x09,0xBB,0xF2,0x3B,
 		};
 	static unsigned char dh512_g[]={
 		0x02,

+ 6 - 2
include/nrpe.h

@@ -2,7 +2,7 @@
  *
  * NRPE.H - NRPE Include File
  * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
- * Last Modified: 11-23-2007
+ * Last Modified: 08-10-2011 by Konstantin Malov
  *
  * License:
  *
@@ -22,6 +22,11 @@
  *
  ************************************************************************/
 
+ /*
+  * 08-10-2011 IPv4 subnetworks support added.
+  * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c
+  *
+  */
 
 /**************** COMMAND STRUCTURE DEFINITION **********/
 
@@ -47,7 +52,6 @@ int write_pid_file(void);
 int remove_pid_file(void);
 
 void free_memory(void);
-int is_an_allowed_host(char *);
 int validate_request(packet *);
 int contains_nasty_metachars(char *);
 int process_macros(char *,char *,int);

+ 3 - 1
sample-config/nrpe.cfg.in

@@ -67,7 +67,9 @@ nrpe_group=@nrpe_group@
 
 # ALLOWED HOST ADDRESSES
 # This is an optional comma-delimited list of IP address or hostnames 
-# that are allowed to talk to the NRPE daemon.
+# that are allowed to talk to the NRPE daemon. Network addresses with a bit mask
+# (i.e. 192.168.1.0/24) are also supported. Hostname wildcards are not currently 
+# supported.
 #
 # Note: The daemon only does rudimentary checking of the client's IP
 # address.  I would highly recommend adding entries in your /etc/hosts.allow

+ 2 - 2
src/Makefile.in

@@ -33,8 +33,8 @@ SNPRINTF_O=@SNPRINTF_O@
 
 all: nrpe check_nrpe
 
-nrpe: nrpe.c utils.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h $(SNPRINTF_O)
-	$(CC) $(CFLAGS) -o $@ nrpe.c utils.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS)
+nrpe: nrpe.c utils.c acl.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/acl.h $(SNPRINTF_O)
+	$(CC) $(CFLAGS) -o $@ nrpe.c utils.c acl.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS)
 
 check_nrpe: check_nrpe.c utils.c $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h
 	$(CC) $(CFLAGS) -o $@ check_nrpe.c utils.c $(LDFLAGS) $(SOCKETLIBS) $(OTHERLIBS)

+ 469 - 0
src/acl.c

@@ -0,0 +1,469 @@
+/*-
+ * acl.c - a small library for nrpe.c. It adds IPv4 subnets support to ACL in nrpe.
+ * Copyright (c) 2011 Kaspersky Lab ZAO
+ * Last Modified: 08-10-2011 by Konstantin Malov with Oleg Koreshkov's help 
+ *
+ * Description:
+ * acl.c creates two linked lists. One is for IPv4 hosts and networks, another is for domain names.
+ * All connecting hosts (if allowed_hosts is defined) are checked in these two lists.
+ *
+ * Some notes:
+ * 1) IPv6 isn't supported in ACL.
+ * 2) Only ANCII names are supported in ACL.
+ *
+ * License: GPL
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "../include/acl.h"
+
+/* This function checks if a char argumnet from valid char range.
+ * Valid range is: ASCII only, a number or a letter, a space, a dot, a slash, a dash, a comma.
+ *
+ * Returns:
+ *      0 - char isn't from valid group
+ *  1 - char is a number
+ *  2 - char is a letter
+ *  3 - char is a space(' ')
+ *  4 - char is a dot('.')
+ *  5 - char is a slash('/')
+ *  6 - char is a dash('-')
+ *  7 - char is a comma(',')
+ */
+
+int isvalidchar(int c) {
+        if (!isascii(c))
+                return 0;
+
+        if (isdigit(c))
+                return 1;
+
+        if (isalpha(c))
+                return 2;
+
+        if (isspace(c))
+                return 3;
+
+        switch (c) {
+        case '.':
+                return 4;
+                break;
+        case '/':
+                return 5;
+                break;
+        case '-':
+                return 6;
+                break;
+        case ',':
+                return 7;
+                break;
+        default:
+                return 0;
+        }
+}
+
+/*
+ * Get substring from allowed_hosts from s position to e position.
+ */
+
+char * acl_substring(char *string, int s, int e) {
+    char *substring;
+    int len = e - s;
+
+        if (len < 0)
+                return NULL;
+
+    if ( (substring = malloc(len + 1)) == NULL)
+        return NULL;
+
+    memmove(substring, string + s, len + 1);
+    return substring;
+}
+
+/*
+ * Add IPv4 host or network to IP ACL. IPv4 format is X.X.X.X[/X].
+ * Host will be added to ACL only if it has passed IPv4 format check.
+ *
+ * Returns:
+ * 1 - on success
+ * 0 - on failure
+ *
+ * States for IPv4 format check:
+ *  0 - numbers(-> 1), dot(-> -1), slash(-> -1), other(-> -1)
+ *  1 - numbers(-> 1), dot(-> 2),  slash(-> -1), other(-> -1)
+ *  2 - numbers(-> 3), dot(-> -1), slash(-> -1), other(-> -1)
+ *  3 - numbers(-> 3), dot(-> 4),  slash(-> -1), other(-> -1)
+ *  4 - numbers(-> 5), dot(-> -1), slash(-> -1), other(-> -1)
+ *  5 - numbers(-> 5), dot(-> 6),  slash(-> -1), other(-> -1)
+ *  6 - numbers(-> 7), dot(-> -1), slash(-> -1), other(-> -1)
+ *  7 - numbers(-> 7), dor(-> -1), slash(-> 8),  other(-> -1)
+ *  8 - numbers(-> 9), dor(-> -1), slash(-> -1), other(-> -1)
+ *  9 - numbers(-> 9), dot(-> -1), slash(-> -1), other(-> -1)
+ *
+ *  Good states are 7(IPv4 host) and 9(IPv4 network)
+ */
+
+int add_ipv4_to_acl(char *ipv4) {
+        int state = 0;
+        int octet = 0;
+        int index = 0;  /* position in data array */
+        int data[5];    /* array to store ip octets and mask */
+        int len = strlen(ipv4);
+        int i, c;
+        unsigned long ip, mask;
+        struct ip_acl *ip_acl_curr;
+
+        /* Check for min and max IPv4 valid length */
+        if (len < 7 || len > 18)
+                return 0;
+
+        /* default mask for ipv4 */
+        data[4] = 32;
+
+        /* Basic IPv4 format check */
+        for (i = 0; i < len; i++) {
+                /* Return 0 on error state */
+                if (state == -1)
+                        return 0;
+
+                c = ipv4[i];
+
+                switch (c) {
+                case '0': case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                        octet = octet * 10 + CHAR_TO_NUMBER(c);
+                        switch (state) {
+                        case 0: case 2: case 4: case 6: case 8:
+                                state++;
+                                break;
+                        }
+                        break;
+                case '.':
+                        switch (state) {
+                        case 1: case 3: case 5:
+                                data[index++] = octet;
+                                octet = 0;
+                                state++;
+                                break;
+                        default:
+                                state = -1;
+                        }
+                        break;
+                case '/':
+                        switch (state) {
+                        case 7:
+                                data[index++] = octet;
+                                octet = 0;
+                                state++;
+                                break;
+                        default:
+                                state = -1;
+                        }
+                        break;
+                default:
+                        state = -1;
+                }
+        }
+
+        /* Exit state handling */
+        switch (state) {
+        case 7: case 9:
+                data[index] = octet;
+                break;
+        default:
+                /* Bad states */
+                return 0;
+        }
+
+        /*
+         * Final IPv4 format check.
+         */
+        for (i=0; i < 4; i++) {
+                if (data[i] < 0 || data[i] > 255) {
+                        syslog(LOG_ERR,"Invalid IPv4 address/network format(%s) in allowed_hosts option\n",ipv4);
+                        return 0;
+                }
+        }
+
+        if (data[4] < 0 || data[4] > 32) {
+                syslog(LOG_ERR,"Invalid IPv4 network mask format(%s) in allowed_hosts option\n",ipv4);
+                return 0;
+        }
+
+        /* Conver ip and mask to unsigned long */
+        ip = htonl((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]);
+        mask =  htonl(-1 << (32 - data[4]));
+
+        /* Wrong network address */
+        if ( (ip & mask) != ip) {
+                syslog(LOG_ERR,"IP address and mask do not match in %s\n",ipv4);
+                return 0;
+        }
+
+        /* Add addr to ip_acl list */
+        if ( (ip_acl_curr = malloc(sizeof(*ip_acl_curr))) == NULL) {
+                syslog(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
+                return 0;
+        }
+
+        /* Save result in ACL ip list */
+        ip_acl_curr->addr.s_addr = ip;
+        ip_acl_curr->mask.s_addr = mask;
+        ip_acl_curr->next = NULL;
+
+        if (ip_acl_head == NULL) {
+                ip_acl_head = ip_acl_curr;
+        } else {
+                ip_acl_prev->next = ip_acl_curr;
+        }
+        ip_acl_prev = ip_acl_curr;
+        return 1;
+}
+
+/*
+ * Add domain to DNS ACL list
+ * Domain will be added only if it has passed domain name check.
+ *
+ * In this case domain valid format is:
+ * 1) Domain names must use only alphanumeric characters and dashes (-).
+ * 2) Domain names mustn't begin or end with dashes (-).
+ * 3) Domain names mustn't have more than 63 characters.
+ *
+ * Return:
+ * 1 - for success
+ * 0 - for failure
+ *
+ * 0 - alpha(-> 1), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
+ * 1 - alpha(-> 1), number(-> 1), dot(-> 2),  dash(-> 6),  all other(-> -1)
+ * 2 - alpha(-> 3), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
+ * 3 - alpha(-> 4), number(-> 1), dot(-> 2),  dash(-> 6),  all other(-> -1)
+ * 4 - alpha(-> 5), number(-> 1), dot(-> 2),  dash(-> 6),  all other(-> -1)
+ * 5 - alpha(-> 1), number(-> 1), dot(-> 2),  dash(-> 6),  all other(-> -1)
+ * 6 - alpha(-> 1), number(-> 1), dot(-> 2),  dash(-> 6),  all other(-> -1)
+
+ * For real FQDN only 4 and 5 states are good for exit.
+ * I don't check if top domain exists (com, ru and etc.)
+ * But in real life NRPE could work in LAN,
+ * with local domain zones like .local or with names like 'mars' added to /etc/hosts.
+ * So 1 is good state too. And maybe this check is not necessary at all...
+ */
+
+int add_domain_to_acl(char *domain) {
+        int state = 0;
+        int len = strlen(domain);
+        int i, c;
+
+        struct dns_acl *dns_acl_curr;
+
+        if (len > 63)
+                return 0;
+
+        for (i = 0; i < len; i++) {
+                c = domain[i];
+                switch (isvalidchar(c)) {
+                case 1:
+                        state = 1;
+                        break;
+                case 2:
+                        switch (state) {
+                        case 0: case 1: case 5: case 6:
+                                state = 1;
+                                break;
+                        case 2: case 3: case 4:
+                                state++;
+                                break;
+                        }
+                        break;
+
+                case 4:
+                        switch (state) {
+                        case 0: case 2:
+                                state = -1;
+                                break;
+                        default:
+                                state = 2;
+                        }
+                        break;
+                case 6:
+                        switch (state) {
+                        case 0: case 2:
+                                state = -1;
+                                break;
+                        default:
+                                state = 6;
+                        }
+                        break;
+                default:
+                        /* Not valid chars */
+                        return 0;
+                }
+        }
+
+        /* Check exit code */
+        switch (state) {
+        case 1: case 4: case 5:
+                /* Add name to domain ACL list */
+                if ( (dns_acl_curr = malloc(sizeof(*dns_acl_curr))) == NULL) {
+                        syslog(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
+                        return 0;
+                }
+                strcpy(dns_acl_curr->domain, domain);
+                dns_acl_curr->next = NULL;
+
+                if (dns_acl_head == NULL)
+                        dns_acl_head = dns_acl_curr;
+                else
+                        dns_acl_prev->next = dns_acl_curr;
+
+                dns_acl_prev = dns_acl_curr;
+                return 1;
+        default:
+                return 0;
+        }
+}
+
+/* Checks connectiong host in ACL
+ *
+ * Returns:
+ * 1 - on success
+ * 0 - on failure
+ */
+
+int is_an_allowed_host(struct in_addr host) {
+        struct ip_acl *ip_acl_curr = ip_acl_head;
+        struct dns_acl *dns_acl_curr = dns_acl_head;
+        struct in_addr addr;
+        struct hostent *he;
+
+        while (ip_acl_curr != NULL) {
+                if ( (host.s_addr & ip_acl_curr->mask.s_addr) == ip_acl_curr->addr.s_addr)
+                        return 1;
+
+                ip_acl_curr = ip_acl_curr->next;
+        }
+
+        while(dns_acl_curr != NULL) {
+        he = gethostbyname(dns_acl_curr->domain);
+        if (he == NULL)
+                        return 0;
+
+                while (*he->h_addr_list) {
+                        memmove((char *)&addr,*he->h_addr_list++, sizeof(addr));
+                        if (addr.s_addr == host.s_addr)
+                                return 1;
+                }
+                dns_acl_curr = dns_acl_curr->next;
+        }
+        return 0;
+}
+
+/* The trim() function takes a source string and copies it to the destination string,
+ * stripped of leading and training whitespace. The destination string must be 
+ * allocated at least as large as the source string.
+ */
+
+void trim( char *src, char *dest) {
+	char *sptr, *dptr;
+
+	for( sptr = src; isblank( *sptr) && *sptr; sptr++); /* Jump past leading spaces */
+	for( dptr = dest; !isblank( *sptr) && *sptr; ) {
+		*dptr = *sptr;
+		sptr++;
+		dptr++;
+	}
+	*dptr = '\0';
+	return;
+}
+
+/* This function splits allowed_hosts to substrings with comma(,) as a delimeter.
+ * It doesn't check validness of ACL record (add_ipv4_to_acl() and add_domain_to_acl() do),
+ * just trims spaces from ACL records.
+ * After this it sends ACL records to add_ipv4_to_acl() or add_domain_to_acl().
+ */
+
+void parse_allowed_hosts(char *allowed_hosts) {
+	char *hosts = strdup( allowed_hosts);	/* Copy since strtok* modifes original */
+	char *saveptr;
+	char *tok;
+	const char *delim = ",";
+	char *trimmed_tok;
+
+	tok = strtok_r( hosts, delim, &saveptr);
+	while( tok) {
+		trimmed_tok = malloc( sizeof( char) * ( strlen( tok) + 1));
+		trim( tok, trimmed_tok);
+		if( strlen( trimmed_tok) > 0) {
+			if (!add_ipv4_to_acl(trimmed_tok) && !add_domain_to_acl(trimmed_tok)) {
+				syslog(LOG_ERR,"Can't add to ACL this record (%s). Check allowed_hosts option!\n",trimmed_tok);
+			}
+		}
+		free( trimmed_tok);
+		tok = strtok_r(( char *)0, delim, &saveptr);
+	}
+
+	free( hosts);
+}
+
+/*
+ * Converts mask in unsigned long format to two digit prefix
+ */
+
+unsigned int prefix_from_mask(struct in_addr mask) {
+        int prefix = 0;
+        unsigned long bit = 1;
+        int i;
+
+        for (i = 0; i < 32; i++) {
+                if (mask.s_addr & bit)
+                        prefix++;
+
+                bit = bit << 1;
+        }
+        return (prefix);
+}
+
+/*
+ * It shows all hosts in ACL lists
+ */
+
+void show_acl_lists(void) {
+        struct ip_acl *ip_acl_curr = ip_acl_head;
+        struct dns_acl *dns_acl_curr = dns_acl_head;
+
+        while (ip_acl_curr != NULL) {
+                printf(" IP ACL: %s/%u %u\n", inet_ntoa(ip_acl_curr->addr), prefix_from_mask(ip_acl_curr->mask), ip_acl_curr->addr.s_addr);
+                ip_acl_curr = ip_acl_curr->next;
+        }
+
+        while (dns_acl_curr != NULL) {
+                printf("DNS ACL: %s\n", dns_acl_curr->domain);
+                dns_acl_curr = dns_acl_curr->next;
+        }
+}

+ 39 - 95
src/nrpe.c

@@ -4,7 +4,7 @@
  * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
  * License: GPL
  *
- * Last Modified: 03-10-2008
+ * Last Modified: 08-10-2011 by Konstantin Malov 
  *
  * Command line: nrpe -c <config_file> [--inetd | --daemon]
  *
@@ -18,10 +18,17 @@
  * 
  ******************************************************************************/
 
+/*
+ * 08-10-2011 IPv4 subnetworks support added.
+ * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c.
+ * now allowed_hosts is parsed by parse_allowed_hosts() from acl.c.
+ */ 
+
 #include "../include/common.h"
 #include "../include/config.h"
 #include "../include/nrpe.h"
 #include "../include/utils.h"
+#include "../include/acl.h"
 
 #ifdef HAVE_SSL
 #include "../include/dh.h"
@@ -449,10 +456,10 @@ int read_config_file(char *filename){
                         strncpy(server_address,varvalue,sizeof(server_address) - 1);
                         server_address[sizeof(server_address)-1]='\0';
                         }
-
-                else if(!strcmp(varname,"allowed_hosts"))
-			allowed_hosts=strdup(varvalue);
-
+		else if(!strcmp(varname,"allowed_hosts")) {
+				allowed_hosts=strdup(varvalue);
+				parse_allowed_hosts(allowed_hosts);
+		}
 		else if(strstr(input_line,"command[")){
 			temp_buffer=strtok(varname,"[");
 			temp_buffer=strtok(NULL,"]");
@@ -868,30 +875,34 @@ void wait_for_connections(void){
 				if(debug==TRUE)
 					syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port);
 
-                                /* is this is a blessed machine? */
+				/* is this is a blessed machine? */
 				if(allowed_hosts){
-
-					if(!is_an_allowed_host(inet_ntoa(nptr->sin_addr))){
-
-                                               /* log error to syslog facility */
-                                               syslog(LOG_ERR,"Host %s is not allowed to talk to us!",inet_ntoa(nptr->sin_addr));
-
-                                               /* log info to syslog facility */
-					       if(debug==TRUE)
-						       syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));
-
-					       /* close socket prior to exiting */
-                                               close(new_sd);
-
-					       exit(STATE_OK);
-				               }
-                                       else{
-
-                                               /* log info to syslog facility */
-                                               if(debug==TRUE)
-                                                       syslog(LOG_DEBUG,"Host address is in allowed_hosts");
-				               }
-				        }
+                	switch(nptr->sin_family) {
+                    	case AF_INET:
+                        	if(!is_an_allowed_host(nptr->sin_addr)) {
+                            	/* log error to syslog facility */
+                            	syslog(LOG_ERR,"Host %s is not allowed to talk to us!",inet_ntoa(nptr->sin_addr));
+
+								/* log info to syslog facility */
+								if ( debug==TRUE )
+                                	syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));
+
+								/* close socket prior to exiting */
+								close(new_sd);
+								exit(STATE_OK);
+								} else {
+									/* log info to syslog facility */
+									if(debug==TRUE)
+										syslog(LOG_DEBUG,"Host address is in allowed_hosts");
+
+								}
+							break;
+                           
+						case AF_INET6:
+							syslog(LOG_DEBUG,"Connection from %s closed. We don't support AF_INET6 addreess family in ACL\n", inet_ntoa(nptr->sin_addr));
+							break;
+					}
+				}
 
 #ifdef HAVE_LIBWRAP
 
@@ -948,73 +959,6 @@ void wait_for_connections(void){
 	}
 
 
-
-/* checks to see if a given host is allowed to talk to us */
-int is_an_allowed_host(char *connecting_host){
-	char *temp_buffer=NULL;
-	char *temp_ptr=NULL;
-	int result=0;
-        struct hostent *myhost;
-	char **pptr=NULL;
-	char *save_connecting_host=NULL;
-	struct in_addr addr;
-	
-	/* make sure we have something */
-	if(connecting_host==NULL)
-		return 0;
-	if(allowed_hosts==NULL)
-		return 1;
-
-	if((temp_buffer=strdup(allowed_hosts))==NULL)
-		return 0;
-	
-	/* try and match IP addresses first */
-	for(temp_ptr=strtok(temp_buffer,",");temp_ptr!=NULL;temp_ptr=strtok(NULL,",")){
-
-		if(!strcmp(connecting_host,temp_ptr)){
-			result=1;
-			break;
-		        }
-	        }
-
-	/* try DNS lookups if needed */
-	if(result==0){
-
-		free(temp_buffer);
-		if((temp_buffer=strdup(allowed_hosts))==NULL)
-			return 0;
-
-		save_connecting_host=strdup(connecting_host);
-		for(temp_ptr=strtok(temp_buffer,",");temp_ptr!=NULL;temp_ptr=strtok(NULL,",")){
-
-			myhost=gethostbyname(temp_ptr);
-			if(myhost!=NULL){
-
-				/* check all addresses for the host... */
-				for(pptr=myhost->h_addr_list;*pptr!=NULL;pptr++){
-					memcpy(&addr, *pptr, sizeof(addr));
-					if(!strcmp(save_connecting_host, inet_ntoa(addr))){
-						result=1;
-						break;
-					        }
-				        }
-			        }
-
-			if(result==1)
-				break;
-		        }
-
-		strcpy(connecting_host, save_connecting_host);
-		free(save_connecting_host);
-	        }
-
-	free(temp_buffer);
-
-	return result;
-        }
-
-
-
 /* handles a client connection */
 void handle_connection(int sock){
         u_int32_t calculated_crc32;