1 /* $NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif 34 #include <sys/cdefs.h> 35 __RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); 36 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <sys/queue.h> 40 41 #ifdef HAVE_LIBUTIL_H 42 #include <libutil.h> 43 #endif 44 #ifdef HAVE_UTIL_H 45 #include <util.h> 46 #endif 47 #include <string.h> 48 #include <signal.h> 49 #include <netdb.h> 50 #include <stdio.h> 51 #include <stdbool.h> 52 #include <string.h> 53 #include <inttypes.h> 54 #include <syslog.h> 55 #include <ctype.h> 56 #include <limits.h> 57 #include <errno.h> 58 #include <poll.h> 59 #include <fcntl.h> 60 #include <err.h> 61 #include <stdlib.h> 62 #include <unistd.h> 63 #include <time.h> 64 #include <ifaddrs.h> 65 #include <netinet/in.h> 66 67 #include "bl.h" 68 #include "internal.h" 69 #include "conf.h" 70 #include "run.h" 71 #include "state.h" 72 #include "support.h" 73 74 static const char *configfile = _PATH_BLCONF; 75 static DB *state; 76 static const char *dbfile = _PATH_BLSTATE; 77 static sig_atomic_t readconf; 78 static sig_atomic_t done; 79 static int vflag; 80 81 static void 82 sigusr1(int n __unused) 83 { 84 debug++; 85 } 86 87 static void 88 sigusr2(int n __unused) 89 { 90 debug--; 91 } 92 93 static void 94 sighup(int n __unused) 95 { 96 readconf++; 97 } 98 99 static void 100 sigdone(int n __unused) 101 { 102 done++; 103 } 104 105 static __dead void 106 usage(int c) 107 { 108 if (c != '?') 109 warnx("Unknown option `%c'", (char)c); 110 fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] " 111 "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] " 112 "[-s <sockpath>] [-t <timeout>]\n", getprogname()); 113 exit(EXIT_FAILURE); 114 } 115 116 static int 117 getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl) 118 { 119 *rsl = sizeof(*rss); 120 memset(rss, 0, *rsl); 121 122 if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1) 123 return 0; 124 125 if (errno != ENOTCONN) { 126 (*lfun)(LOG_ERR, "getpeername failed (%m)"); 127 return -1; 128 } 129 130 if (bi->bi_slen == 0) { 131 (*lfun)(LOG_ERR, "unconnected socket with no peer in message"); 132 return -1; 133 } 134 135 switch (bi->bi_ss.ss_family) { 136 case AF_INET: 137 *rsl = sizeof(struct sockaddr_in); 138 break; 139 case AF_INET6: 140 *rsl = sizeof(struct sockaddr_in6); 141 break; 142 default: 143 (*lfun)(LOG_ERR, "bad client passed socket family %u", 144 (unsigned)bi->bi_ss.ss_family); 145 return -1; 146 } 147 148 if (*rsl != bi->bi_slen) { 149 (*lfun)(LOG_ERR, "bad client passed socket length %u != %u", 150 (unsigned)*rsl, (unsigned)bi->bi_slen); 151 return -1; 152 } 153 154 memcpy(rss, &bi->bi_ss, *rsl); 155 156 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 157 if (*rsl != rss->ss_len) { 158 (*lfun)(LOG_ERR, 159 "bad client passed socket internal length %u != %u", 160 (unsigned)*rsl, (unsigned)rss->ss_len); 161 return -1; 162 } 163 #endif 164 return 0; 165 } 166 167 static void 168 process(bl_t bl) 169 { 170 struct sockaddr_storage rss; 171 socklen_t rsl; 172 char rbuf[BUFSIZ]; 173 bl_info_t *bi; 174 struct conf c; 175 struct dbinfo dbi; 176 struct timespec ts; 177 178 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { 179 (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); 180 return; 181 } 182 183 if ((bi = bl_recv(bl)) == NULL) { 184 (*lfun)(LOG_ERR, "no message (%m)"); 185 return; 186 } 187 188 if (getremoteaddress(bi, &rss, &rsl) == -1) 189 goto out; 190 191 if (debug) { 192 sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); 193 (*lfun)(LOG_DEBUG, "processing type=%d fd=%d remote=%s msg=%s" 194 " uid=%lu gid=%lu", bi->bi_type, bi->bi_fd, rbuf, 195 bi->bi_msg, (unsigned long)bi->bi_uid, 196 (unsigned long)bi->bi_gid); 197 } 198 199 if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) { 200 (*lfun)(LOG_DEBUG, "no rule matched"); 201 goto out; 202 } 203 204 205 if (state_get(state, &c, &dbi) == -1) 206 goto out; 207 208 if (debug) { 209 char b1[128], b2[128]; 210 (*lfun)(LOG_DEBUG, "%s: initial db state for %s: count=%d/%d " 211 "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, 212 fmttime(b1, sizeof(b1), dbi.last), 213 fmttime(b2, sizeof(b2), ts.tv_sec)); 214 } 215 216 switch (bi->bi_type) { 217 case BL_ABUSE: 218 /* 219 * If the application has signaled abusive behavior, 220 * set the number of fails to be one less than the 221 * configured limit. Fallthrough to the normal BL_ADD 222 * processing, which will increment the failure count 223 * to the threshhold, and block the abusive address. 224 */ 225 if (c.c_nfail != -1) 226 dbi.count = c.c_nfail - 1; 227 /*FALLTHROUGH*/ 228 case BL_ADD: 229 dbi.count++; 230 dbi.last = ts.tv_sec; 231 if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { 232 /* 233 * No point in re-adding the rule. 234 * It might exist already due to latency in processing 235 * and removing the rule is the wrong thing to do as 236 * it allows a window to attack again. 237 */ 238 if (dbi.id[0] == '\0') { 239 int res = run_change("add", &c, 240 dbi.id, sizeof(dbi.id)); 241 if (res == -1) 242 goto out; 243 } 244 sockaddr_snprintf(rbuf, sizeof(rbuf), "%a", 245 (void *)&rss); 246 (*lfun)(LOG_INFO, 247 "blocked %s/%d:%d for %d seconds", 248 rbuf, c.c_lmask, c.c_port, c.c_duration); 249 } 250 break; 251 case BL_DELETE: 252 if (dbi.last == 0) 253 goto out; 254 dbi.count = 0; 255 dbi.last = 0; 256 break; 257 case BL_BADUSER: 258 /* ignore for now */ 259 break; 260 default: 261 (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type); 262 } 263 state_put(state, &c, &dbi); 264 265 out: 266 close(bi->bi_fd); 267 268 if (debug) { 269 char b1[128], b2[128]; 270 (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d " 271 "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, 272 fmttime(b1, sizeof(b1), dbi.last), 273 fmttime(b2, sizeof(b2), ts.tv_sec)); 274 } 275 } 276 277 static void 278 update_interfaces(void) 279 { 280 struct ifaddrs *oifas, *nifas; 281 282 if (getifaddrs(&nifas) == -1) 283 return; 284 285 oifas = ifas; 286 ifas = nifas; 287 288 if (oifas) 289 freeifaddrs(oifas); 290 } 291 292 static void 293 update(void) 294 { 295 struct timespec ts; 296 struct conf c; 297 struct dbinfo dbi; 298 unsigned int f, n; 299 char buf[128]; 300 void *ss = &c.c_ss; 301 302 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { 303 (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); 304 return; 305 } 306 307 again: 308 for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1; 309 f = 0, n++) 310 { 311 time_t when = c.c_duration + dbi.last; 312 if (debug > 1) { 313 char b1[64], b2[64]; 314 sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss); 315 (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d " 316 "last=%s " "now=%s", __func__, n, buf, dbi.count, 317 c.c_duration, fmttime(b1, sizeof(b1), dbi.last), 318 fmttime(b2, sizeof(b2), ts.tv_sec)); 319 } 320 if (c.c_duration == -1 || when >= ts.tv_sec) 321 continue; 322 if (dbi.id[0]) { 323 run_change("rem", &c, dbi.id, 0); 324 sockaddr_snprintf(buf, sizeof(buf), "%a", ss); 325 (*lfun)(LOG_INFO, "released %s/%d:%d after %d seconds", 326 buf, c.c_lmask, c.c_port, c.c_duration); 327 } 328 state_del(state, &c); 329 goto again; 330 } 331 } 332 333 static void 334 addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd, 335 const char *path) 336 { 337 bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog); 338 if (bl == NULL || !bl_isconnected(bl)) 339 exit(EXIT_FAILURE); 340 if (*nfd >= *maxfd) { 341 *maxfd += 10; 342 *blp = realloc(*blp, sizeof(**blp) * *maxfd); 343 if (*blp == NULL) 344 err(EXIT_FAILURE, "malloc"); 345 *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd); 346 if (*pfdp == NULL) 347 err(EXIT_FAILURE, "malloc"); 348 } 349 350 (*pfdp)[*nfd].fd = bl_getfd(bl); 351 (*pfdp)[*nfd].events = POLLIN; 352 (*blp)[*nfd] = bl; 353 *nfd += 1; 354 } 355 356 static void 357 uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c) 358 { 359 struct conf **list = *listp; 360 361 if (c->c_name[0] == '\0') 362 return; 363 for (size_t i = 0; i < *nlist; i++) { 364 if (strcmp(list[i]->c_name, c->c_name) == 0) 365 return; 366 } 367 if (*nlist == *mlist) { 368 *mlist += 10; 369 void *p = realloc(*listp, *mlist * sizeof(*list)); 370 if (p == NULL) 371 err(EXIT_FAILURE, "Can't allocate for rule list"); 372 list = *listp = p; 373 } 374 list[(*nlist)++] = c; 375 } 376 377 static void 378 rules_flush(void) 379 { 380 struct conf **list; 381 size_t nlist, mlist; 382 383 list = NULL; 384 mlist = nlist = 0; 385 for (size_t i = 0; i < rconf.cs_n; i++) 386 uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]); 387 for (size_t i = 0; i < lconf.cs_n; i++) 388 uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]); 389 390 for (size_t i = 0; i < nlist; i++) 391 run_flush(list[i]); 392 free(list); 393 } 394 395 static void 396 rules_restore(void) 397 { 398 struct conf c; 399 struct dbinfo dbi; 400 unsigned int f; 401 402 for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) { 403 if (dbi.id[0] == '\0') 404 continue; 405 (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); 406 } 407 } 408 409 int 410 main(int argc, char *argv[]) 411 { 412 int c, tout, flags, flush, restore, ret; 413 const char *spath, **blsock; 414 size_t nblsock, maxblsock; 415 416 setprogname(argv[0]); 417 418 spath = NULL; 419 blsock = NULL; 420 maxblsock = nblsock = 0; 421 flush = 0; 422 restore = 0; 423 tout = 0; 424 flags = O_RDWR|O_EXCL|O_CLOEXEC; 425 while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) { 426 switch (c) { 427 case 'C': 428 controlprog = optarg; 429 break; 430 case 'c': 431 configfile = optarg; 432 break; 433 case 'D': 434 dbfile = optarg; 435 break; 436 case 'd': 437 debug++; 438 break; 439 case 'f': 440 flush++; 441 break; 442 case 'P': 443 spath = optarg; 444 break; 445 case 'R': 446 rulename = optarg; 447 break; 448 case 'r': 449 restore++; 450 break; 451 case 's': 452 if (nblsock >= maxblsock) { 453 maxblsock += 10; 454 void *p = realloc(blsock, 455 sizeof(*blsock) * maxblsock); 456 if (p == NULL) 457 err(EXIT_FAILURE, 458 "Can't allocate memory for %zu sockets", 459 maxblsock); 460 blsock = p; 461 } 462 blsock[nblsock++] = optarg; 463 break; 464 case 't': 465 tout = atoi(optarg) * 1000; 466 break; 467 case 'v': 468 vflag++; 469 break; 470 default: 471 usage(c); 472 } 473 } 474 475 argc -= optind; 476 if (argc) 477 usage('?'); 478 479 signal(SIGHUP, sighup); 480 signal(SIGINT, sigdone); 481 signal(SIGQUIT, sigdone); 482 signal(SIGTERM, sigdone); 483 signal(SIGUSR1, sigusr1); 484 signal(SIGUSR2, sigusr2); 485 486 openlog(getprogname(), LOG_PID, LOG_DAEMON); 487 488 if (debug) { 489 lfun = dlog; 490 if (tout == 0) 491 tout = 5000; 492 } else { 493 if (tout == 0) 494 tout = 15000; 495 } 496 497 update_interfaces(); 498 conf_parse(configfile); 499 if (flush) { 500 rules_flush(); 501 if (!restore) 502 flags |= O_TRUNC; 503 } 504 505 struct pollfd *pfd = NULL; 506 bl_t *bl = NULL; 507 size_t nfd = 0; 508 size_t maxfd = 0; 509 510 for (size_t i = 0; i < nblsock; i++) 511 addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]); 512 free(blsock); 513 514 if (spath) { 515 FILE *fp = fopen(spath, "r"); 516 char *line; 517 if (fp == NULL) 518 err(EXIT_FAILURE, "Can't open `%s'", spath); 519 for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; 520 free(line)) 521 addfd(&pfd, &bl, &nfd, &maxfd, line); 522 fclose(fp); 523 } 524 if (nfd == 0) 525 addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK); 526 527 state = state_open(dbfile, flags, 0600); 528 if (state == NULL) 529 state = state_open(dbfile, flags | O_CREAT, 0600); 530 if (state == NULL) 531 return EXIT_FAILURE; 532 533 if (restore) { 534 if (!flush) 535 rules_flush(); 536 rules_restore(); 537 } 538 539 if (!debug) { 540 if (daemon(0, 0) == -1) 541 err(EXIT_FAILURE, "daemon failed"); 542 if (pidfile(NULL) == -1) 543 err(EXIT_FAILURE, "Can't create pidfile"); 544 } 545 546 for (size_t t = 0; !done; t++) { 547 if (readconf) { 548 readconf = 0; 549 conf_parse(configfile); 550 } 551 ret = poll(pfd, (nfds_t)nfd, tout); 552 if (debug) 553 (*lfun)(LOG_DEBUG, "received %d from poll()", ret); 554 switch (ret) { 555 case -1: 556 if (errno == EINTR) 557 continue; 558 (*lfun)(LOG_ERR, "poll (%m)"); 559 return EXIT_FAILURE; 560 case 0: 561 state_sync(state); 562 break; 563 default: 564 for (size_t i = 0; i < nfd; i++) 565 if (pfd[i].revents & POLLIN) 566 process(bl[i]); 567 } 568 if (t % 100 == 0) 569 state_sync(state); 570 if (t % 10000 == 0) 571 update_interfaces(); 572 update(); 573 } 574 state_close(state); 575 return 0; 576 } 577