home *** CD-ROM | disk | FTP | other *** search
- From: John Holden <johnh@psych.usyd.edu.au>
- Date: 20 Apr 1998 01:03:49 -0000
- Purpose: Enhanced security - Checking IP/hardware address aginst ARP entry in kernel
-
- 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.
-
- *** 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');
-