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