httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Slemko <ma...@znep.com>
Subject mod_access/2079: Enhanced security - Checking IP/hardware address aginst ARP entry in kernel (fwd)
Date Mon, 20 Apr 1998 01:14:47 GMT
Someone, please, tell me why you would want to check for MAC addresses in
your web server?

If you want to force a mapping, why not just lock it into your ARP table?

---------- Forwarded message ----------
Date: 20 Apr 1998 01:03:49 -0000
From: John Holden <johnh@psych.usyd.edu.au>
To: apbugs@hyperreal.org
Subject: mod_access/2079: Enhanced security - Checking IP/hardware address aginst ARP entry
in kernel


>Number:         2079
>Category:       mod_access
>Synopsis:       Enhanced security - Checking IP/hardware address aginst ARP entry in kernel
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache
>State:          open
>Class:          change-request
>Submitter-Id:   apache
>Arrival-Date:   Sun Apr 19 18:10:00 PDT 1998
>Last-Modified:
>Originator:     johnh@psych.usyd.edu.au
>Organization:
apache
>Release:        1.2.6
>Environment:
DUNIX
>Description:
This is NOT a bug. I'm summiting it as it may be usefull to others. I wanted to
provide a tighter security model for local machines, I have enhanced the
mod_access.c to allow a new entry in .htaccess as follows:-

	"only from ip_address MAC_address"

The 'only' is similar to 'allow' but will only accept a numeric IP address followed
by the hardware MAC address. This is checked against the ARP entry from the kernel
tables to see if the IP address is valid for the machine. This will not stop
a determined person who could fake the MAC address on their machine. I considered
changing the 'allow' syntax, but it started looking ugly.
>How-To-Repeat:

>Fix:
diff -c follows :-
*** OLDmod_access.c     Fri Apr 17 13:08:45 1998
--- mod_access.c        Mon Apr 20 09:49:47 1998
***************
*** 63,68 ****
--- 63,77 ----
  #include "http_log.h"
  #include "http_request.h"
  
+ #include <sys/file.h>
+ #include <sys/socket.h>
+ #include <sys/ioctl.h>
+ 
+ #include <netdb.h>
+ #include <netinet/in.h>
+ #include <net/if.h>
+ #include <netinet/if_ether.h>
+ 
  typedef struct {
      char *from;
      int limited;
***************
*** 125,130 ****
--- 134,159 ----
      return NULL;
  }
  
+ const char *only_cmd (cmd_parms *cmd, void *dv, char *from, char *ip, char *mac)
+ {
+       access_dir_conf *d = (access_dir_conf *)dv;
+       allowdeny *a;
+       char *proto;
+ 
+       if (strcasecmp (from, "from"))
+               return "'only' must be followed by 'from'";
+       if (!is_ip(ip))
+               return "'only' must have numeric IP address";
+       if (!is_hex(mac))
+               return "'only' must have hex MAC address";
+       a = (allowdeny *)push_array (d->allows);
+       proto = palloc(cmd->pool, strlen(ip) + strlen(mac) + 2);
+       sprintf(proto, "%s@%s", ip, mac);
+       a->from = proto;
+       a->limited = cmd->limited;
+       return NULL;
+ }
+ 
  static char its_an_allow;
  
  command_rec access_cmds[] = {
***************
*** 132,137 ****
--- 161,168 ----
      "'allow,deny', 'deny,allow', or 'mutual-failure'" },
  { "allow", allow_cmd, &its_an_allow, OR_LIMIT, ITERATE2,
      "'from' followed by hostnames or IP-address wildcards" },
+ { "only", only_cmd, NULL, OR_LIMIT, TAKE3,
+     "'only' followed by IP-address and MAC address" },
  { "deny", allow_cmd, NULL, OR_LIMIT, ITERATE2,
      "'from' followed by hostnames or IP-address wildcards" },
  {NULL}
***************
*** 174,179 ****  }
  
+ static int is_hex(const char *hex)
+ {
+     while (isxdigit(*hex))
+         hex++;
+     return (*hex == '\0');
+ }
+ 
+ static int is_ip_mac(const char *addr)
+ {
+       while((*addr == '.') || isdigit(*addr))
+               addr++;
+       if(*addr++ != '@')
+               return 0;
+       return is_hex(addr);
+ }
+ 
+ static int match_ip_mac(const char *proto, const char *ipaddr)
+ {
+       struct hostent *hp;
+       struct sockaddr_in *sin;
+       struct arpreq ar;
+       unsigned char *ptr;
+       char *p;
+       static char addr[32];
+       static char arp[32];
+       int s, err;
+ /*
+ **    extract ip address from proto and test for exact match
+ */
+       strncpy(addr, proto, sizeof addr);
+       if((p = strchr(addr, '@')) == NULL)
+               return 0;
+       *p++ = '\0';                    /* truncate string */
+       if(strcmp(addr, ipaddr))
+               return 0;
+ /*
+ **    setup buffer
+ */
+       bzero((caddr_t)&ar, sizeof ar);
+       ar.arp_pa.sa_family = AF_INET;
+       sin = (struct sockaddr_in *)&ar.arp_pa;
+       sin->sin_family = AF_INET;
+ /*
+ **    convert address to binary
+ */
+       if((sin->sin_addr.s_addr = inet_addr(addr)) == -1)
+               return 0;
+ /*
+ **    get a socket and then collect ARP entry
+ */
+       if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+               return 0;
+       err = ioctl(s, SIOCGARP, (caddr_t)&ar);
+       close(s);
+       if(err < 0)
+               return 0;
+ /*
+ **    we may have an address. Is it complete ?
+ */
+       if (!(ar.arp_flags & ATF_COM))
+               return 0;
+ /*
+ **    convert to hex string
+ */
+       ptr = (unsigned char *)ar.arp_ha.sa_data;
+       sprintf(arp, "%02x%02x%02x%02x%02x%02x",
+               ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
+ /*
+ **    try for MAC address match
+ */
+       return (strcasecmp(p, arp) == 0);
+ }
+ 
  int find_allowdeny (request_rec *r, array_header *a, int method)
  {
      allowdeny *ap = (allowdeny *)a->elts;
***************
*** 212,217 ****
--- 316,331 ----
                gothost = 1;
            else
                gothost = 2;
+       }
+ 
+       if(is_ip_mac(ap[i].from))
+       {
+               if(gothost == 1)
+               {
+                       if(match_ip_mac(ap[i].from, r->connection->remote_ip));
+                               return 1;
+               }
+               continue;
        }
  
          if ((gothost == 2) && in_domain(ap[i].from, remotehost))

--- 205,283 ----
      return (*host == '\0');
%0
>Audit-Trail:
>Unformatted:
[In order for any reply to be added to the PR database, ]
[you need to include <apbugs@Apache.Org> in the Cc line ]
[and leave the subject line UNCHANGED.  This is not done]
[automatically because of the potential for mail loops. ]




Mime
View raw message