1 /*
2 * Copyright (C) 2014, 2015 Red Hat
3 *
4 * This file is part of ocserv.
5 *
6 * ocserv is free software: you can redistribute it and/or modify it
7 * 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 * ocserv is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/select.h>
28 #include <sys/wait.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <sys/socket.h>
32 #include <netdb.h>
33 #include <system.h>
34 #include <errno.h>
35 #include <sys/ioctl.h>
36 #include <sys/un.h>
37 #include <common.h>
38 #include <syslog.h>
39 #include <vpn.h>
40 #include <tlslib.h>
41 #include <main.h>
42 #include <main-ban.h>
43 #include <arpa/inet.h>
44 #include <ccan/hash/hash.h>
45 #include <ccan/htable/htable.h>
46 #include <ifaddrs.h>
47 #include <sys/socket.h>
48
49 static bool if_address_test_local(main_server_st * s, struct sockaddr_storage *addr);
50
rehash(const void * _e,void * unused)51 static size_t rehash(const void *_e, void *unused)
52 {
53 ban_entry_st *e = (void*)_e;
54 return hash_any(e->ip.ip, e->ip.size, 0);
55 }
56
57 /* The first argument is the entry from the hash, and
58 * the second is the entry from check_if_banned().
59 */
ban_entry_cmp(const void * _c1,void * _c2)60 static bool ban_entry_cmp(const void *_c1, void *_c2)
61 {
62 const struct ban_entry_st *c1 = _c1;
63 struct ban_entry_st *c2 = _c2;
64
65 if (c1->ip.size == c2->ip.size && memcmp(c1->ip.ip, c2->ip.ip, c1->ip.size) == 0)
66 return 1;
67 return 0;
68 }
69
70
main_ban_db_init(main_server_st * s)71 void *main_ban_db_init(main_server_st *s)
72 {
73 struct htable *db = talloc(s, struct htable);
74 if (db == NULL) {
75 fprintf(stderr, "error initializing ban DB\n");
76 exit(1);
77 }
78
79 htable_init(db, rehash, NULL);
80 s->ban_db = db;
81
82 return db;
83 }
84
main_ban_db_deinit(main_server_st * s)85 void main_ban_db_deinit(main_server_st *s)
86 {
87 struct htable *db = s->ban_db;
88
89 if (db != NULL) {
90 htable_clear(db);
91 talloc_free(db);
92 }
93 }
94
95 #define IS_BANNED(main, entry) (entry->score >= GETCONFIG(main)->max_ban_score)
96
main_ban_db_elems(main_server_st * s)97 unsigned main_ban_db_elems(main_server_st *s)
98 {
99 struct htable *db = s->ban_db;
100 ban_entry_st *t;
101 struct htable_iter iter;
102 time_t now = time(0);
103 unsigned banned = 0;
104
105 if (db == NULL || GETCONFIG(s)->max_ban_score == 0)
106 return 0;
107
108 t = htable_first(db, &iter);
109 while (t != NULL) {
110 if (t->expires > now && IS_BANNED(s, t)) {
111 banned++;
112 }
113 t = htable_next(db, &iter);
114 }
115 return banned;
116 }
117
massage_ipv6_address(ban_entry_st * t)118 static void massage_ipv6_address(ban_entry_st *t)
119 {
120 if (t->ip.size == 16) {
121 memset(&t->ip.ip[8], 0, 8);
122 }
123 }
124
125 /* returns -1 if the user is already banned, and zero otherwise */
126 static
add_ip_to_ban_list(main_server_st * s,const unsigned char * ip,unsigned ip_size,unsigned score)127 int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_size, unsigned score)
128 {
129 struct htable *db = s->ban_db;
130 struct ban_entry_st *e;
131 ban_entry_st t;
132 time_t now = time(0);
133 time_t expiration = now + GETCONFIG(s)->min_reauth_time;
134 int ret = 0;
135 char str_ip[MAX_IP_STR];
136 const char *p_str_ip = NULL;
137 unsigned print_msg;
138
139 if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL || (ip_size != 4 && ip_size != 16))
140 return 0;
141
142 memcpy(t.ip.ip, ip, ip_size);
143 t.ip.size = ip_size;
144
145 /* In IPv6 treat a /64 as a single address */
146 massage_ipv6_address(&t);
147
148 e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
149 if (e == NULL) { /* new entry */
150 e = talloc_zero(db, ban_entry_st);
151 if (e == NULL) {
152 return 0;
153 }
154
155 memcpy(&e->ip, &t.ip, sizeof(e->ip));
156 e->last_reset = now;
157
158 if (htable_add(db, rehash(e, NULL), e) == 0) {
159 mslog(s, NULL, LOG_INFO,
160 "could not add ban entry to hash table");
161 goto fail;
162 }
163 } else {
164 if (now > e->last_reset + GETCONFIG(s)->ban_reset_time) {
165 e->score = 0;
166 e->last_reset = now;
167 }
168 }
169
170 /* if the user is already banned, don't increase the expiration time
171 * on further attempts, or the user will never be unbanned if he
172 * periodically polls the server */
173 if (e->score < GETCONFIG(s)->max_ban_score) {
174 e->expires = expiration;
175 print_msg = 1;
176 } else
177 print_msg = 0;
178
179 /* prevent overflow */
180 e->score = (e->score + score) > e->score ? (e->score + score) : (e->score);
181
182 if (ip_size == 4)
183 p_str_ip = inet_ntop(AF_INET, ip, str_ip, sizeof(str_ip));
184 else
185 p_str_ip = inet_ntop(AF_INET6, ip, str_ip, sizeof(str_ip));
186
187 if (GETCONFIG(s)->max_ban_score > 0 && IS_BANNED(s, e)) {
188 if (print_msg && p_str_ip) {
189 char date[256];
190 struct tm tm;
191 if ((localtime_r(&e->expires, &tm) == NULL) || (strftime(date, sizeof(date), "%a %b %e %H:%M:%S %Y", &tm) == 0)) {
192 date[0] = 0;
193 }
194 mslog(s, NULL, LOG_INFO, "added IP '%s' (with score %d) to ban list, will be reset at: %s", str_ip, e->score, date);
195 }
196 ret = -1;
197 } else {
198 if (p_str_ip) {
199 mslog(s, NULL, LOG_DEBUG, "added %d points (total %d) for IP '%s' to ban list", score, e->score, str_ip);
200 }
201 ret = 0;
202 }
203
204 return ret;
205 fail:
206 talloc_free(e);
207 return ret;
208 }
209
add_str_ip_to_ban_list(main_server_st * s,const char * ip,unsigned score)210 int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
211 {
212 struct htable *db = s->ban_db;
213 ban_entry_st t;
214 int ret = 0;
215
216 if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL || ip[0] == 0)
217 return 0;
218
219 if (strchr(ip, ':') != 0) {
220 ret = inet_pton(AF_INET6, ip, t.ip.ip);
221 t.ip.size = 16;
222 } else {
223 ret = inet_pton(AF_INET, ip, t.ip.ip);
224 t.ip.size = 4;
225 }
226 if (ret != 1) {
227 mslog(s, NULL, LOG_INFO,
228 "could not read IP: %s", ip);
229 return 0;
230 }
231
232 return add_ip_to_ban_list(s, t.ip.ip, t.ip.size, score);
233 }
234
235 /* returns non-zero if there is an IP removed */
remove_ip_from_ban_list(main_server_st * s,const uint8_t * ip,unsigned size)236 int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size)
237 {
238 struct htable *db = s->ban_db;
239 struct ban_entry_st *e;
240 ban_entry_st t;
241 char txt_ip[MAX_IP_STR];
242
243 if (db == NULL || ip == NULL || size == 0)
244 return 0;
245
246 if (size == 4 || size == 16) {
247 if (inet_ntop(size==16?AF_INET6:AF_INET, ip, txt_ip, sizeof(txt_ip)) != NULL) {
248 mslog(s, NULL, LOG_INFO,
249 "unbanning IP '%s'", txt_ip);
250 }
251
252 t.ip.size = size;
253 memcpy(&t.ip.ip, ip, size);
254
255 /* In IPv6 treat a /64 as a single address */
256 massage_ipv6_address(&t);
257
258 e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
259 if (e != NULL) { /* new entry */
260 e->score = 0;
261 e->expires = 0;
262 return 1;
263 }
264 }
265
266 return 0;
267 }
268
check_if_banned(main_server_st * s,struct sockaddr_storage * addr,socklen_t addr_size)269 unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, socklen_t addr_size)
270 {
271 struct htable *db = s->ban_db;
272 time_t now;
273 ban_entry_st t, *e;
274 unsigned in_size;
275 char txt[MAX_IP_STR];
276
277 if (db == NULL || GETCONFIG(s)->max_ban_score == 0)
278 return 0;
279
280 (void)(txt);
281
282 if (if_address_test_local(s, addr)) {
283 mslog(s, NULL, LOG_DEBUG, "Not applying ban to local IP: %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
284 return 0;
285 }
286
287 in_size = SA_IN_SIZE(addr_size);
288 if (in_size != 4 && in_size != 16) {
289 mslog(s, NULL, LOG_ERR, "unknown address type for %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
290 return 0;
291 }
292
293 memcpy(t.ip.ip, SA_IN_P_GENERIC(addr, addr_size), SA_IN_SIZE(addr_size));
294 t.ip.size = SA_IN_SIZE(addr_size);
295
296 /* In IPv6 treat a /64 as a single address */
297 massage_ipv6_address(&t);
298
299 /* add its current connection points */
300 add_ip_to_ban_list(s, t.ip.ip, t.ip.size, GETCONFIG(s)->ban_points_connect);
301
302 now = time(0);
303 e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
304 if (e != NULL) {
305 if (now > e->expires)
306 return 0;
307
308 if (e->score >= GETCONFIG(s)->max_ban_score) {
309 mslog(s, NULL, LOG_INFO, "rejected connection from banned IP: %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
310 return 1;
311 }
312 }
313 return 0;
314 }
315
cleanup_banned_entries(main_server_st * s)316 void cleanup_banned_entries(main_server_st *s)
317 {
318 struct htable *db = s->ban_db;
319 ban_entry_st *t;
320 struct htable_iter iter;
321 time_t now = time(0);
322
323 if (db == NULL)
324 return;
325
326 t = htable_first(db, &iter);
327 while (t != NULL) {
328 if (now >= t->expires && now > t->last_reset + GETCONFIG(s)->ban_reset_time) {
329 htable_delval(db, &iter);
330 talloc_free(t);
331 }
332 t = htable_next(db, &iter);
333
334 }
335 }
336
if_address_init(main_server_st * s)337 int if_address_init(main_server_st *s)
338 {
339 struct ifaddrs * ifaddr = NULL, *ifa;
340 if_address_st * local_if_addresses = NULL;
341 int retval = 0;
342 unsigned count = 0;
343 s->if_addresses_count = 0;
344 s->if_addresses = NULL;
345
346 if (getifaddrs(&ifaddr) < 0) {
347 int err = errno;
348 fprintf(stderr, "Failed to read local if address list: %s", strerror(err));
349 goto cleanup;
350 }
351
352 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
353 if (ifa->ifa_addr == NULL) {
354 continue;
355 }
356 count ++;
357 }
358
359 local_if_addresses = talloc_array(s, if_address_st, count);
360 if (local_if_addresses == NULL) {
361 fprintf(stderr, "Failed to allocate");
362 goto cleanup;
363 }
364
365 count = 0;
366
367 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
368 sa_family_t family;
369 if (ifa->ifa_addr == NULL) {
370 continue;
371 }
372 family = ifa->ifa_addr->sa_family;
373 if (family == AF_INET || family == AF_INET6) {
374 memcpy(&local_if_addresses[count].if_addr, ifa->ifa_addr, sizeof(struct sockaddr));
375 memcpy(&local_if_addresses[count].if_netmask, ifa->ifa_netmask, sizeof(struct sockaddr));
376 count++;
377 }
378 }
379
380 s->if_addresses = local_if_addresses;
381 s->if_addresses_count = count;
382 local_if_addresses = NULL;
383
384 retval = 1;
385
386 cleanup:
387 if (ifaddr != NULL)
388 freeifaddrs(ifaddr);
389
390 if (local_if_addresses != NULL)
391 talloc_free(local_if_addresses);
392
393 return retval;
394 }
395
test_local_ipv4(struct sockaddr_in * remote,struct sockaddr_in * local,struct sockaddr_in * network)396 static bool test_local_ipv4(struct sockaddr_in * remote, struct sockaddr_in * local, struct sockaddr_in * network)
397 {
398 uint32_t l = local->sin_addr.s_addr & network->sin_addr.s_addr;
399 uint32_t r = remote->sin_addr.s_addr & network->sin_addr.s_addr;
400 if (l != r)
401 return false;
402 else
403 return true;
404 }
405
test_local_ipv6(struct sockaddr_in6 * remote,struct sockaddr_in6 * local,struct sockaddr_in6 * network)406 static bool test_local_ipv6(struct sockaddr_in6 * remote, struct sockaddr_in6 * local, struct sockaddr_in6 * network)
407 {
408 unsigned index = 0;
409
410 for (index = 0; index < 4; index ++) {
411 uint32_t l = local->sin6_addr.__u6_addr.__u6_addr32[index] & network->sin6_addr.__u6_addr.__u6_addr32[index];
412 uint32_t r = remote->sin6_addr.__u6_addr.__u6_addr32[index] & network->sin6_addr.__u6_addr.__u6_addr32[index];
413 if (l != r)
414 return false;
415 }
416 return true;
417 }
418
if_address_test_local(main_server_st * s,struct sockaddr_storage * addr)419 static bool if_address_test_local(main_server_st * s, struct sockaddr_storage *addr)
420 {
421 unsigned index;
422 for (index = 0; index < s->if_addresses_count; index ++)
423 {
424 if_address_st * ifa = &s->if_addresses[index];
425 if (ifa->if_addr.sa_family != addr->ss_family)
426 continue;
427
428 switch (addr->ss_family) {
429 case AF_INET:
430 if (test_local_ipv4((struct sockaddr_in *)addr, (struct sockaddr_in *)&ifa->if_addr, (struct sockaddr_in *)&ifa->if_netmask))
431 return true;
432 break;
433 case AF_INET6:
434 if (test_local_ipv6((struct sockaddr_in6 *)addr, (struct sockaddr_in6 *)&ifa->if_addr, (struct sockaddr_in6 *)&ifa->if_netmask))
435 return true;
436 break;
437 default:
438 break;
439 }
440 }
441 return false;
442 }
443
if_address_cleanup(main_server_st * s)444 void if_address_cleanup(main_server_st * s)
445 {
446 if (s->if_addresses)
447 talloc_free(s->if_addresses);
448
449 s->if_addresses = NULL;
450 s->if_addresses_count = 0;
451 }
452