jabberd2  2.3.2
access.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 /* this implements allow/deny filters for IP address */
22 
23 #include "util.h"
24 
25 access_t access_new(int order)
26 {
27  access_t access = (access_t) calloc(1, sizeof(struct access_st));
28 
29  access->order = order;
30 
31  return access;
32 }
33 
34 void access_free(access_t access)
35 {
36  if(access->allow != NULL) free(access->allow);
37  if(access->deny != NULL) free(access->deny);
38  free(access);
39 }
40 
41 static int _access_calc_netsize(const char *mask, int defaultsize)
42 {
43  struct in_addr legacy_mask;
44  int netsize;
45 
46 #ifndef HAVE_INET_PTON
47  if(strchr(mask, '.') && inet_aton(mask, &legacy_mask))
48 #else
49  if(inet_pton(AF_INET, mask, &legacy_mask.s_addr) > 0)
50 #endif
51  {
52  /* netmask has been given in dotted decimal form */
53  int temp = ntohl(legacy_mask.s_addr);
54  netsize = 32;
55 
56  while(netsize && temp%2==0)
57  {
58  netsize--;
59  temp /= 2;
60  }
61  } else {
62  /* numerical netsize */
63  netsize = j_atoi(mask, defaultsize);
64  }
65 
66  return netsize;
67 }
68 
70 static void _access_unmap_v4(struct sockaddr_in6 *src, struct sockaddr_in *dst)
71 {
72  memset(dst, 0, sizeof(struct sockaddr_in));
73  dst->sin_family = AF_INET;
74  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]);
75 }
76 
78 static int _access_check_match(struct sockaddr_storage *ip_1, struct sockaddr_storage *ip_2, int netsize)
79 {
80  struct sockaddr_in *sin_1;
81  struct sockaddr_in *sin_2;
82  struct sockaddr_in6 *sin6_1;
83  struct sockaddr_in6 *sin6_2;
84  int i;
85 
86  sin_1 = (struct sockaddr_in *)ip_1;
87  sin_2 = (struct sockaddr_in *)ip_2;
88  sin6_1 = (struct sockaddr_in6 *)ip_1;
89  sin6_2 = (struct sockaddr_in6 *)ip_2;
90 
91  /* addresses of different families */
92  if(ip_1->ss_family != ip_2->ss_family)
93  {
94  /* maybe on of the addresses is just a IPv6 mapped IPv4 address */
95  if (ip_1->ss_family == AF_INET && ip_2->ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6_2->sin6_addr))
96  {
97  struct sockaddr_storage t;
98  struct sockaddr_in *temp;
99 
100  temp = (struct sockaddr_in *)&t;
101 
102  _access_unmap_v4(sin6_2, temp);
103  if(netsize>96)
104  netsize -= 96;
105 
106  return _access_check_match(ip_1, &t, netsize);
107  }
108 
109  if (ip_1->ss_family == AF_INET6 && ip_2->ss_family == AF_INET && IN6_IS_ADDR_V4MAPPED(&sin6_1->sin6_addr))
110  {
111  struct sockaddr_storage t;
112  struct sockaddr_in *temp;
113 
114  temp = (struct sockaddr_in *)&t;
115 
116  _access_unmap_v4(sin6_1, temp);
117  if(netsize>96)
118  netsize -= 96;
119 
120  return _access_check_match(&t, ip_2, netsize);
121  }
122 
123  return 0;
124  }
125 
126  /* IPv4? */
127  if(ip_1->ss_family == AF_INET)
128  {
129  int netmask;
130 
131  if(netsize > 32)
132  netsize = 32;
133 
134  netmask = htonl(-1 << (32-netsize));
135 
136  return ((sin_1->sin_addr.s_addr&netmask) == (sin_2->sin_addr.s_addr&netmask));
137  }
138 
139  /* IPv6? */
140  if(ip_1->ss_family == AF_INET6)
141  {
142  unsigned char bytemask;
143 
144  if(netsize > 128)
145  netsize = 128;
146 
147  for(i=0; i<netsize/8; i++)
148  if(sin6_1->sin6_addr.s6_addr[i] != sin6_2->sin6_addr.s6_addr[i])
149  return 0;
150 
151  if(netsize%8 == 0)
152  return 1;
153 
154  bytemask = 0xff << (8 - netsize%8);
155 
156  return ((sin6_1->sin6_addr.s6_addr[i]&bytemask) == (sin6_2->sin6_addr.s6_addr[i]&bytemask));
157  }
158 
159  /* unknown address family */
160  return 0;
161 }
162 
163 int access_allow(access_t access, const char *ip, const char *mask)
164 {
165  struct sockaddr_storage ip_addr;
166  int netsize;
167 
168  if(j_inet_pton(ip, &ip_addr) <= 0)
169  return 1;
170 
171  netsize = _access_calc_netsize(mask, ip_addr.ss_family==AF_INET ? 32 : 128);
172 
173  access->allow = (access_rule_t) realloc(access->allow, sizeof(struct access_rule_st) * (access->nallow + 1));
174 
175  memcpy(&access->allow[access->nallow].ip, &ip_addr, sizeof(ip_addr));
176  access->allow[access->nallow].mask = netsize;
177 
178  access->nallow++;
179 
180  return 0;
181 }
182 
183 int access_deny(access_t access, const char *ip, const char *mask)
184 {
185  struct sockaddr_storage ip_addr;
186  int netsize;
187 
188  if(j_inet_pton(ip, &ip_addr) <= 0)
189  return 1;
190 
191  netsize = _access_calc_netsize(mask, ip_addr.ss_family==AF_INET ? 32 : 128);
192 
193  access->deny = (access_rule_t) realloc(access->deny, sizeof(struct access_rule_st) * (access->ndeny + 1));
194 
195  memcpy(&access->deny[access->ndeny].ip, &ip_addr, sizeof(ip_addr));
196  access->deny[access->ndeny].mask = netsize;
197 
198  access->ndeny++;
199 
200  return 0;
201 }
202 
203 int access_check(access_t access, const char *ip)
204 {
205  struct sockaddr_storage addr;
206  access_rule_t rule;
207  int i, allow = 0, deny = 0;
208 
209  if(j_inet_pton(ip, &addr) <= 0)
210  return 0;
211 
212  /* first, search the allow list */
213  for(i = 0; !allow && i < access->nallow; i++)
214  {
215  rule = &access->allow[i];
216  if(_access_check_match(&addr, &rule->ip, rule->mask))
217  allow = 1;
218  }
219 
220  /* now the deny list */
221  for(i = 0; !deny && i < access->ndeny; i++)
222  {
223  rule = &access->deny[i];
224  if(_access_check_match(&addr, &rule->ip, rule->mask))
225  deny = 1;
226  }
227 
228  /* allow then deny */
229  if(access->order == 0)
230  {
231  if(allow)
232  return 1;
233 
234  if(deny)
235  return 0;
236 
237  /* allow by default */
238  return 1;
239  }
240 
241  /* deny then allow */
242  if(deny)
243  return 0;
244 
245  if(allow)
246  return 1;
247 
248  /* deny by default */
249  return 0;
250 }
uint8_t s6_addr[16]
IPv6 address.
Definition: util_compat.h:70
access_rule_t deny
Definition: util.h:243
struct sockaddr_storage ip
Definition: util.h:232
int nallow
Definition: util.h:241
int access_deny(access_t access, const char *ip, const char *mask)
Definition: access.c:183
int j_inet_pton(const char *src, struct sockaddr_storage *dst)
set the address of a struct sockaddr_storage (modeled after the stdlib function inet_pton) ...
Definition: inaddr.c:46
struct access_rule_st * access_rule_t
access_t access_new(int order)
Definition: access.c:25
int order
Definition: util.h:238
sa_family_t ss_family
address family
Definition: util_compat.h:99
static int _access_check_match(struct sockaddr_storage *ip_1, struct sockaddr_storage *ip_2, int netsize)
check if two ip addresses are within the same subnet
Definition: access.c:78
int j_atoi(const char *a, int def)
Definition: str.c:87
static int _access_calc_netsize(const char *mask, int defaultsize)
Definition: access.c:41
void access_free(access_t access)
Definition: access.c:34
int mask
Definition: util.h:233
int ndeny
Definition: util.h:244
#define IN6_IS_ADDR_V4MAPPED(a)
check if an IPv6 is just a mapped IPv4 address
Definition: util_compat.h:54
access_rule_t allow
Definition: util.h:240
static void _access_unmap_v4(struct sockaddr_in6 *src, struct sockaddr_in *dst)
convert a IPv6 mapped IPv4 address to a real IPv4 address
Definition: access.c:70
int access_allow(access_t access, const char *ip, const char *mask)
Definition: access.c:163
int access_check(access_t access, const char *ip)
Definition: access.c:203
structure that contains an IPv6 including some additional attributes (only defined if not contained i...
Definition: util_compat.h:79
struct access_st * access_t
#define AF_INET6
address family for IPv6
Definition: util_compat.h:42
struct in6_addr sin6_addr
IPv6 address.
Definition: util_compat.h:86