jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 /* this implements allow/deny filters for IP address */ 00022 00023 #include "util.h" 00024 00025 access_t access_new(int order) 00026 { 00027 access_t access = (access_t) calloc(1, sizeof(struct access_st)); 00028 00029 access->order = order; 00030 00031 return access; 00032 } 00033 00034 void access_free(access_t access) 00035 { 00036 if(access->allow != NULL) free(access->allow); 00037 if(access->deny != NULL) free(access->deny); 00038 free(access); 00039 } 00040 00041 static int _access_calc_netsize(const char *mask, int defaultsize) 00042 { 00043 struct in_addr legacy_mask; 00044 int netsize; 00045 00046 #ifndef HAVE_INET_PTON 00047 if(strchr(mask, '.') && inet_aton(mask, &legacy_mask)) 00048 #else 00049 if(inet_pton(AF_INET, mask, &legacy_mask.s_addr) > 0) 00050 #endif 00051 { 00052 /* netmask has been given in dotted decimal form */ 00053 int temp = ntohl(legacy_mask.s_addr); 00054 netsize = 32; 00055 00056 while(netsize && temp%2==0) 00057 { 00058 netsize--; 00059 temp /= 2; 00060 } 00061 } else { 00062 /* numerical netsize */ 00063 netsize = j_atoi(mask, defaultsize); 00064 } 00065 00066 return netsize; 00067 } 00068 00070 static void _access_unmap_v4(struct sockaddr_in6 *src, struct sockaddr_in *dst) 00071 { 00072 memset(dst, 0, sizeof(struct sockaddr_in)); 00073 dst->sin_family = AF_INET; 00074 dst->sin_addr.s_addr = htonl((((int)src->sin6_addr.s6_addr[12]*256+src->sin6_addr.s6_addr[13])*256+src->sin6_addr.s6_addr[14])*256+(int)src->sin6_addr.s6_addr[15]); 00075 } 00076 00078 static int _access_check_match(struct sockaddr_storage *ip_1, struct sockaddr_storage *ip_2, int netsize) 00079 { 00080 struct sockaddr_in *sin_1; 00081 struct sockaddr_in *sin_2; 00082 struct sockaddr_in6 *sin6_1; 00083 struct sockaddr_in6 *sin6_2; 00084 int i; 00085 00086 sin_1 = (struct sockaddr_in *)ip_1; 00087 sin_2 = (struct sockaddr_in *)ip_2; 00088 sin6_1 = (struct sockaddr_in6 *)ip_1; 00089 sin6_2 = (struct sockaddr_in6 *)ip_2; 00090 00091 /* addresses of different families */ 00092 if(ip_1->ss_family != ip_2->ss_family) 00093 { 00094 /* maybe on of the addresses is just a IPv6 mapped IPv4 address */ 00095 if (ip_1->ss_family == AF_INET && ip_2->ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6_2->sin6_addr)) 00096 { 00097 struct sockaddr_storage t; 00098 struct sockaddr_in *temp; 00099 00100 temp = (struct sockaddr_in *)&t; 00101 00102 _access_unmap_v4(sin6_2, temp); 00103 if(netsize>96) 00104 netsize -= 96; 00105 00106 return _access_check_match(ip_1, &t, netsize); 00107 } 00108 00109 if (ip_1->ss_family == AF_INET6 && ip_2->ss_family == AF_INET && IN6_IS_ADDR_V4MAPPED(&sin6_1->sin6_addr)) 00110 { 00111 struct sockaddr_storage t; 00112 struct sockaddr_in *temp; 00113 00114 temp = (struct sockaddr_in *)&t; 00115 00116 _access_unmap_v4(sin6_1, temp); 00117 if(netsize>96) 00118 netsize -= 96; 00119 00120 return _access_check_match(&t, ip_2, netsize); 00121 } 00122 00123 return 0; 00124 } 00125 00126 /* IPv4? */ 00127 if(ip_1->ss_family == AF_INET) 00128 { 00129 int netmask; 00130 00131 if(netsize > 32) 00132 netsize = 32; 00133 00134 netmask = htonl(-1 << (32-netsize)); 00135 00136 return ((sin_1->sin_addr.s_addr&netmask) == (sin_2->sin_addr.s_addr&netmask)); 00137 } 00138 00139 /* IPv6? */ 00140 if(ip_1->ss_family == AF_INET6) 00141 { 00142 unsigned char bytemask; 00143 00144 if(netsize > 128) 00145 netsize = 128; 00146 00147 for(i=0; i<netsize/8; i++) 00148 if(sin6_1->sin6_addr.s6_addr[i] != sin6_2->sin6_addr.s6_addr[i]) 00149 return 0; 00150 00151 if(netsize%8 == 0) 00152 return 1; 00153 00154 bytemask = 0xff << (8 - netsize%8); 00155 00156 return ((sin6_1->sin6_addr.s6_addr[i]&bytemask) == (sin6_2->sin6_addr.s6_addr[i]&bytemask)); 00157 } 00158 00159 /* unknown address family */ 00160 return 0; 00161 } 00162 00163 int access_allow(access_t access, char *ip, char *mask) 00164 { 00165 struct sockaddr_storage ip_addr; 00166 int netsize; 00167 00168 if(j_inet_pton(ip, &ip_addr) <= 0) 00169 return 1; 00170 00171 netsize = _access_calc_netsize(mask, ip_addr.ss_family==AF_INET ? 32 : 128); 00172 00173 access->allow = (access_rule_t) realloc(access->allow, sizeof(struct access_rule_st) * (access->nallow + 1)); 00174 00175 memcpy(&access->allow[access->nallow].ip, &ip_addr, sizeof(ip_addr)); 00176 access->allow[access->nallow].mask = netsize; 00177 00178 access->nallow++; 00179 00180 return 0; 00181 } 00182 00183 int access_deny(access_t access, char *ip, char *mask) 00184 { 00185 struct sockaddr_storage ip_addr; 00186 int netsize; 00187 00188 if(j_inet_pton(ip, &ip_addr) <= 0) 00189 return 1; 00190 00191 netsize = _access_calc_netsize(mask, ip_addr.ss_family==AF_INET ? 32 : 128); 00192 00193 access->deny = (access_rule_t) realloc(access->deny, sizeof(struct access_rule_st) * (access->ndeny + 1)); 00194 00195 memcpy(&access->deny[access->ndeny].ip, &ip_addr, sizeof(ip_addr)); 00196 access->deny[access->ndeny].mask = netsize; 00197 00198 access->ndeny++; 00199 00200 return 0; 00201 } 00202 00203 int access_check(access_t access, char *ip) 00204 { 00205 struct sockaddr_storage addr; 00206 access_rule_t rule; 00207 int i, allow = 0, deny = 0; 00208 00209 if(j_inet_pton(ip, &addr) <= 0) 00210 return 0; 00211 00212 /* first, search the allow list */ 00213 for(i = 0; !allow && i < access->nallow; i++) 00214 { 00215 rule = &access->allow[i]; 00216 if(_access_check_match(&addr, &rule->ip, rule->mask)) 00217 allow = 1; 00218 } 00219 00220 /* now the deny list */ 00221 for(i = 0; !deny && i < access->ndeny; i++) 00222 { 00223 rule = &access->deny[i]; 00224 if(_access_check_match(&addr, &rule->ip, rule->mask)) 00225 deny = 1; 00226 } 00227 00228 /* allow then deny */ 00229 if(access->order == 0) 00230 { 00231 if(allow) 00232 return 1; 00233 00234 if(deny) 00235 return 0; 00236 00237 /* allow by default */ 00238 return 1; 00239 } 00240 00241 /* deny then allow */ 00242 if(deny) 00243 return 0; 00244 00245 if(allow) 00246 return 1; 00247 00248 /* deny by default */ 00249 return 0; 00250 }