home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / linux / apache / contrib / patches / 1.2 / authMAC.patch next >
Encoding:
Internet Message Format  |  1998-06-11  |  4.9 KB

  1. From: John Holden <johnh@psych.usyd.edu.au>
  2. Date: 20 Apr 1998 01:03:49 -0000
  3. Purpose: Enhanced security - Checking IP/hardware address aginst ARP entry in kernel
  4.  
  5. I wanted to
  6. provide a tighter security model for local machines, I have enhanced the
  7. mod_access.c to allow a new entry in .htaccess as follows:-
  8.  
  9.     "only from ip_address MAC_address"
  10.  
  11. The 'only' is similar to 'allow' but will only accept a numeric IP address followed
  12. by the hardware MAC address. This is checked against the ARP entry from the kernel
  13. tables to see if the IP address is valid for the machine. This will not stop
  14. a determined person who could fake the MAC address on their machine. I considered
  15. changing the 'allow' syntax, but it started looking ugly.
  16.  
  17. *** OLDmod_access.c     Fri Apr 17 13:08:45 1998
  18. --- mod_access.c        Mon Apr 20 09:49:47 1998
  19. ***************
  20. *** 63,68 ****
  21. --- 63,77 ----
  22.   #include "http_log.h"
  23.   #include "http_request.h"
  24.   
  25. + #include <sys/file.h>
  26. + #include <sys/socket.h>
  27. + #include <sys/ioctl.h>
  28. + #include <netdb.h>
  29. + #include <netinet/in.h>
  30. + #include <net/if.h>
  31. + #include <netinet/if_ether.h>
  32.   typedef struct {
  33.       char *from;
  34.       int limited;
  35. ***************
  36. *** 125,130 ****
  37. --- 134,159 ----
  38.       return NULL;
  39.   }
  40.   
  41. + const char *only_cmd (cmd_parms *cmd, void *dv, char *from, char *ip, char *mac)
  42. + {
  43. +       access_dir_conf *d = (access_dir_conf *)dv;
  44. +       allowdeny *a;
  45. +       char *proto;
  46. +       if (strcasecmp (from, "from"))
  47. +               return "'only' must be followed by 'from'";
  48. +       if (!is_ip(ip))
  49. +               return "'only' must have numeric IP address";
  50. +       if (!is_hex(mac))
  51. +               return "'only' must have hex MAC address";
  52. +       a = (allowdeny *)push_array (d->allows);
  53. +       proto = palloc(cmd->pool, strlen(ip) + strlen(mac) + 2);
  54. +       sprintf(proto, "%s@%s", ip, mac);
  55. +       a->from = proto;
  56. +       a->limited = cmd->limited;
  57. +       return NULL;
  58. + }
  59.   static char its_an_allow;
  60.   
  61.   command_rec access_cmds[] = {
  62. ***************
  63. *** 132,137 ****
  64. --- 161,168 ----
  65.       "'allow,deny', 'deny,allow', or 'mutual-failure'" },
  66.   { "allow", allow_cmd, &its_an_allow, OR_LIMIT, ITERATE2,
  67.       "'from' followed by hostnames or IP-address wildcards" },
  68. + { "only", only_cmd, NULL, OR_LIMIT, TAKE3,
  69. +     "'only' followed by IP-address and MAC address" },
  70.   { "deny", allow_cmd, NULL, OR_LIMIT, ITERATE2,
  71.       "'from' followed by hostnames or IP-address wildcards" },
  72.   {NULL}
  73. ***************
  74. *** 174,179 ****  }
  75.   
  76. + static int is_hex(const char *hex)
  77. + {
  78. +     while (isxdigit(*hex))
  79. +         hex++;
  80. +     return (*hex == '\0');
  81. + }
  82. + static int is_ip_mac(const char *addr)
  83. + {
  84. +       while((*addr == '.') || isdigit(*addr))
  85. +               addr++;
  86. +       if(*addr++ != '@')
  87. +               return 0;
  88. +       return is_hex(addr);
  89. + }
  90. + static int match_ip_mac(const char *proto, const char *ipaddr)
  91. + {
  92. +       struct hostent *hp;
  93. +       struct sockaddr_in *sin;
  94. +       struct arpreq ar;
  95. +       unsigned char *ptr;
  96. +       char *p;
  97. +       static char addr[32];
  98. +       static char arp[32];
  99. +       int s, err;
  100. + /*
  101. + **    extract ip address from proto and test for exact match
  102. + */
  103. +       strncpy(addr, proto, sizeof addr);
  104. +       if((p = strchr(addr, '@')) == NULL)
  105. +               return 0;
  106. +       *p++ = '\0';                    /* truncate string */
  107. +       if(strcmp(addr, ipaddr))
  108. +               return 0;
  109. + /*
  110. + **    setup buffer
  111. + */
  112. +       bzero((caddr_t)&ar, sizeof ar);
  113. +       ar.arp_pa.sa_family = AF_INET;
  114. +       sin = (struct sockaddr_in *)&ar.arp_pa;
  115. +       sin->sin_family = AF_INET;
  116. + /*
  117. + **    convert address to binary
  118. + */
  119. +       if((sin->sin_addr.s_addr = inet_addr(addr)) == -1)
  120. +               return 0;
  121. + /*
  122. + **    get a socket and then collect ARP entry
  123. + */
  124. +       if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  125. +               return 0;
  126. +       err = ioctl(s, SIOCGARP, (caddr_t)&ar);
  127. +       close(s);
  128. +       if(err < 0)
  129. +               return 0;
  130. + /*
  131. + **    we may have an address. Is it complete ?
  132. + */
  133. +       if (!(ar.arp_flags & ATF_COM))
  134. +               return 0;
  135. + /*
  136. + **    convert to hex string
  137. + */
  138. +       ptr = (unsigned char *)ar.arp_ha.sa_data;
  139. +       sprintf(arp, "%02x%02x%02x%02x%02x%02x",
  140. +               ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
  141. + /*
  142. + **    try for MAC address match
  143. + */
  144. +       return (strcasecmp(p, arp) == 0);
  145. + }
  146.   int find_allowdeny (request_rec *r, array_header *a, int method)
  147.   {
  148.       allowdeny *ap = (allowdeny *)a->elts;
  149. ***************
  150. *** 212,217 ****
  151. --- 316,331 ----
  152.                 gothost = 1;
  153.             else
  154.                 gothost = 2;
  155. +       }
  156. +       if(is_ip_mac(ap[i].from))
  157. +       {
  158. +               if(gothost == 1)
  159. +               {
  160. +                       if(match_ip_mac(ap[i].from, r->connection->remote_ip));
  161. +                               return 1;
  162. +               }
  163. +               continue;
  164.         }
  165.   
  166.           if ((gothost == 2) && in_domain(ap[i].from, remotehost))
  167.  
  168. --- 205,283 ----
  169.       return (*host == '\0');
  170.