Main Page | Data Structures | Directories | File List | Data Fields

ip_acl.c

00001 /*
00002 ** Copyright (c) 2002  Hughes Technologies Pty Ltd.  All rights
00003 ** reserved.
00004 **
00005 ** Terms under which this software may be used or copied are
00006 ** provided in the  specific license associated with this product.
00007 **
00008 ** Hughes Technologies disclaims all warranties with regard to this
00009 ** software, including all implied warranties of merchantability and
00010 ** fitness, in no event shall Hughes Technologies be liable for any
00011 ** special, indirect or consequential damages or any damages whatsoever
00012 ** resulting from loss of use, data or profits, whether in an action of
00013 ** contract, negligence or other tortious action, arising out of or in
00014 ** connection with the use or performance of this software.
00015 **
00016 **
00017 ** $Id: ip_acl.c,v 1.2 2004/11/17 23:54:24 alexcv Exp $
00018 **
00019 */
00020 
00021 #include "config.h"
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #if defined(_WIN32)
00028 #else
00029 #include <unistd.h>
00030 #endif
00031 
00032 #include "httpd.h"
00033 #include "httpd_priv.h"
00034 
00035 
00036 /**************************************************************************
00037 ** GLOBAL VARIABLES
00038 **************************************************************************/
00039 
00040 
00041 /**************************************************************************
00042 ** PRIVATE ROUTINES
00043 **************************************************************************/
00044 
00045 static int scanCidr(val, result, length)
00046         char    *val;
00047         u_int   *result,
00048                 *length;
00049 {
00050         u_int   res, res1, res2, res3, res4, res5;
00051         char    *cp;
00052 
00053         cp = val;
00054         res1 = atoi(cp);
00055         cp = index(cp,'.');
00056         if (!cp)
00057                 return(-1);
00058         cp++;
00059         res2 = atoi(cp);
00060         cp = index(cp,'.');
00061         if (!cp)
00062                 return(-1);
00063         cp++;
00064         res3 = atoi(cp);
00065         cp = index(cp,'.');
00066         if (!cp)
00067                 return(-1);
00068         cp++;
00069         res4 = atoi(cp);
00070         cp = index(cp,'/');
00071         if (!cp)
00072         {
00073                 res5 = 32;
00074         }
00075         else
00076         {
00077                 cp++;
00078                 res5 = atoi(cp);
00079         }
00080 
00081         if (res1>255 || res2>255 || res3>255 || res4>255 || res5>32)
00082         {
00083                 return(-1);
00084         }
00085         res = (res1 << 24) + (res2 << 16) + (res3 << 8) + res4;
00086         *result = res;
00087         *length = res5;
00088         return(0);
00089 }
00090 
00091 
00092 static int _isInCidrBlock(httpd *server, request *r, int addr1, int len1,
00093                 int addr2, int len2)
00094 {
00095         int     count,
00096                 mask;
00097 
00098         /* if (addr1 == 0 && len1 == 0)
00099         {
00100                 return(1);
00101         }*/
00102 
00103         if(len2 < len1)
00104         {
00105                 _httpd_writeErrorLog(server, r, LEVEL_ERROR,
00106                     "IP Address must be more specific than network block");
00107                 return(0);
00108         }
00109 
00110         mask = count = 0;
00111         while(count < len1)
00112         {
00113                 mask = (mask << 1) + 1;
00114                 count++;
00115         }
00116         mask = mask << (32 - len1);
00117         if ( (addr1 & mask) == (addr2 & mask))
00118         {
00119                 return(1);
00120         }
00121         else
00122         {
00123                 return(0);
00124         }
00125 }
00126 
00127 
00128 /**************************************************************************
00129 ** PUBLIC ROUTINES
00130 **************************************************************************/
00131 
00132 httpAcl *httpdAddAcl(server, acl, cidr, action)
00133         httpd   *server;
00134         httpAcl *acl;
00135         char    *cidr;
00136         int     action;
00137 {
00138         httpAcl *cur;
00139         int     addr,
00140                 len;
00141 
00142         /*
00143         ** Check the ACL info is reasonable
00144         */
00145         if(scanCidr(cidr, &addr, &len) < 0)
00146         {
00147                 _httpd_writeErrorLog(server, NULL, LEVEL_ERROR,
00148                         "Invalid IP address format");
00149                 return(NULL);
00150         }
00151         if (action != HTTP_ACL_PERMIT && action != HTTP_ACL_DENY)
00152         {
00153                 _httpd_writeErrorLog(server, NULL, LEVEL_ERROR,
00154                         "Invalid acl action");
00155                 return(NULL);
00156         }
00157 
00158         /*
00159         ** Find a spot to put this ACE
00160         */      
00161         if (acl)
00162         {
00163                 cur = acl;
00164                 while(cur->next)
00165                 {
00166                         cur = cur->next;
00167                 }
00168                 cur->next = (httpAcl*)malloc(sizeof(httpAcl));
00169                 cur = cur->next;
00170         }
00171         else
00172         {
00173                 cur = (httpAcl*)malloc(sizeof(httpAcl));
00174                 acl = cur;
00175         }
00176 
00177         /*
00178         ** Add the details and return
00179         */
00180         cur->addr = addr;
00181         cur->len = len;
00182         cur->action = action;
00183         cur->next = NULL;
00184         return(acl);
00185 }
00186 
00187 
00188 int httpdCheckAcl(httpd *server, request *r, httpAcl *acl)
00189 {
00190         httpAcl *cur;
00191         int     addr, len,
00192                 res,
00193                 action;
00194 
00195 
00196         action = HTTP_ACL_DENY;
00197         scanCidr(r->clientAddr, &addr, &len);
00198         cur = acl;
00199         while(cur)
00200         {
00201                 res = _isInCidrBlock(server, r, cur->addr, cur->len, addr, len);
00202                 if (res == 1)
00203                 {
00204                         action = cur->action;
00205                         break;
00206                 }
00207                 cur = cur->next;
00208         }
00209         if (action == HTTP_ACL_DENY)
00210         {
00211                 _httpd_send403(r);
00212                 _httpd_writeErrorLog(server, r, LEVEL_ERROR,
00213                         "Access denied by ACL");
00214         }
00215         return(action);
00216 }
00217 
00218 
00219 void httpdSetDefaultAcl(server, acl)
00220         httpd   *server;
00221         httpAcl *acl;
00222 {
00223         server->defaultAcl = acl;
00224 }

Generated on Sun Apr 3 20:04:46 2005 for WifiDog by  doxygen 1.4.1