home *** CD-ROM | disk | FTP | other *** search
- Date: Tue, 21 Apr 1998 12:47:50 +1000
- From: John Holden <johnh@psychvax.psych.usyd.edu.au>
- To: brian@hyperreal.org
- Subject: Re: mod_access/2079: Enhanced security - Checking IP/hardware address aginst ARP entry in kernel
- Cc: apbugs@Apache.Org
-
-
- > It'd be great if you could hack up a patch for 1.3
-
- I have grafted the required changes to allow for ip/mac address checks in
- V1.3. I have allowed an expanded syntax the mac address :-
-
- only from 123.123.123 0123456789av
- or
- only from 123.123.123 01-23-45-67-89-ab
- or
- only from 123.123.123 01:23:45:67:89:ab
-
- There may be more work required for different UNix kernels or Windows, for
- the ARP lookup.
-
- The general .htaccess handling is FAR more efficient that version 1.2.6.
- We mere mortals appreciate the excellent work!
-
- regards John
-
- diff -c patch follows :-
- :r /user9/t
-
- *** src/modules/standard/OLDmod_access.c Sat Apr 11 22:00:43 1998
- --- src/modules/standard/mod_access.c Tue Apr 21 12:23:11 1998
- ***************
- *** 68,78 ****
- --- 68,88 ----
- #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>
- +
- enum allowdeny_type {
- T_ENV,
- T_ALL,
- T_IP,
- T_HOST,
- + T_ONLY,
- T_FAIL
- };
-
- ***************
- *** 84,89 ****
- --- 94,103 ----
- unsigned long net;
- unsigned long mask;
- } ip;
- + struct {
- + unsigned long ipaddr;
- + unsigned char macaddr[6];
- + } ip_mac;
- } x;
- enum allowdeny_type type;
- } allowdeny;
- ***************
- *** 143,148 ****
- --- 157,214 ----
- return (*host == '\0');
- }
-
- + /*
- + ** get mac address in 12 digit hex form. Allow :-
- + ** 0123456789ab or 01:23:45:67:89:ab or 01-23-45-67-89-ab
- + */
- +
- + static int cvt_hex (unsigned char *m, const char *mac)
- + {
- + unsigned int val, bin;
- + char c;
- + int c1, c2;
- +
- + for(c1 = 0; c1 < 6; c1++)
- + {
- + val = 0;
- + for(c2 = 0; c2 < 2; c2++)
- + {
- + c = *mac++;
- + if(c == '-' || c == ':')
- + c = *mac++;
- + if(isdigit(c))
- + bin = c - '0';
- + else if(c >= 'a' && c <= 'f')
- + bin = c - 'a' + 10;
- + else if(c >= 'A' && c <= 'F')
- + bin = c - 'A' + 10;
- + else
- + return 0;
- + val = val * 0x10 + bin;
- + }
- + *m++ = val;
- + }
- + return 1;
- + }
- +
- + 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;
- +
- + if (strcasecmp (from, "from"))
- + return "'only' must be followed by 'from'";
- + a = (allowdeny *)ap_push_array (d->allows);
- + a->type = T_FAIL;
- + if(!is_ip(ip) || (a->x.ip_mac.ipaddr = inet_addr(ip)) == -1)
- + return "'only' must have numeric IP address";
- + if (!cvt_hex(a->x.ip_mac.macaddr, mac))
- + return "'only' must have 12 digit hex MAC address";
- + a->limited = cmd->limited;
- + a->type = T_ONLY;
- + return NULL;
- + }
- +
- static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where)
- {
- access_dir_conf *d = (access_dir_conf *) dv;
- ***************
- *** 263,268 ****
- --- 329,336 ----
- "'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}
- ***************
- *** 291,296 ****
- --- 359,406 ----
- return 0;
- }
-
- + static int match_mac(const unsigned long ip, const unsigned char *mac)
- + {
- + struct sockaddr_in *sin;
- + struct arpreq ar;
- + unsigned char *ptr;
- + int s, err;
- + /*
- + ** 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;
- + sin->sin_addr.s_addr = ip;
- + /*
- + ** 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;
- + /*
- + ** try for match
- + */
- + ptr = (unsigned char *)ar.arp_ha.sa_data;
- +
- + for(s = 0; s < 5; s++)
- + if(*ptr++ != *mac++)
- + return 0;
- + /*
- + ** A hit!
- + */
- + return 1;
- + }
- +
- static int find_allowdeny(request_rec *r, array_header *a, int method)
- {
- allowdeny *ap = (allowdeny *) a->elts;
- ***************
- *** 320,326 ****
- return 1;
- }
- break;
- !
- case T_HOST:
- if (!gothost) {
- remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
- --- 430,440 ----
- return 1;
- }
- break;
- ! case T_ONLY:
- ! if(r->connection->remote_addr.sin_addr.s_addr == ap[i].x.ip_mac.ipaddr)
- ! if(match_mac(ap[i].x.ip_mac.ipaddr, ap[i].x.ip_mac.macaddr))
- ! return 1;
- ! break;
- case T_HOST:
- if (!gothost) {
- remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
-
-