1/* 2 * OpenVPN -- An application to securely tunnel IP networks 3 * over a single TCP/UDP port, with support for SSL/TLS-based 4 * session authentication and key exchange, 5 * packet encryption, packet authentication, and 6 * packet compression. 7 * 8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 12 * as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program (see the file COPYING included with this 21 * distribution); if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25/* packet filter functions */ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#elif defined(_MSC_VER) 30#include "config-msvc.h" 31#endif 32 33#include "syshead.h" 34 35#if defined(ENABLE_PF) 36 37#include "init.h" 38 39#include "memdbg.h" 40 41#include "pf-inline.h" 42 43static void 44pf_destroy (struct pf_set *pfs) 45{ 46 if (pfs) 47 { 48 if (pfs->cns.hash_table) 49 hash_free (pfs->cns.hash_table); 50 51 { 52 struct pf_cn_elem *l = pfs->cns.list; 53 while (l) 54 { 55 struct pf_cn_elem *next = l->next; 56 free (l->rule.cn); 57 free (l); 58 l = next; 59 } 60 } 61 { 62 struct pf_subnet *l = pfs->sns.list; 63 while (l) 64 { 65 struct pf_subnet *next = l->next; 66 free (l); 67 l = next; 68 } 69 } 70 free (pfs); 71 } 72} 73 74static bool 75add_client (const char *line, const char *prefix, const int line_num, struct pf_cn_elem ***next, const bool exclude) 76{ 77 struct pf_cn_elem *e; 78 ALLOC_OBJ_CLEAR (e, struct pf_cn_elem); 79 e->rule.exclude = exclude; 80 e->rule.cn = string_alloc (line, NULL); 81 **next = e; 82 *next = &e->next; 83 return true; 84} 85 86static bool 87add_subnet (const char *line, const char *prefix, const int line_num, struct pf_subnet ***next, const bool exclude) 88{ 89 struct in_addr network; 90 in_addr_t netmask = 0; 91 92 if (strcmp (line, "unknown")) 93 { 94 int netbits = 32; 95 char *div = strchr (line, '/'); 96 97 if (div) 98 { 99 *div++ = '\0'; 100 if (sscanf (div, "%d", &netbits) != 1) 101 { 102 msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div); 103 return false; 104 } 105 if (netbits < 0 || netbits > 32) 106 { 107 msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div); 108 return false; 109 } 110 } 111 112 if (openvpn_inet_aton (line, &network) != OIA_IP) 113 { 114 msg (D_PF_INFO, "PF: %s/%d: bad network address: '%s'", prefix, line_num, line); 115 return false; 116 } 117 netmask = netbits_to_netmask (netbits); 118 if ((network.s_addr & htonl (netmask)) != network.s_addr) 119 { 120 network.s_addr &= htonl (netmask); 121 msg (M_WARN, "WARNING: PF: %s/%d: incorrect subnet %s/%d changed to %s/%d", prefix, line_num, line, netbits, inet_ntoa (network), netbits); 122 } 123 } 124 else 125 { 126 /* match special "unknown" tag for addresses unrecognized by mroute */ 127 network.s_addr = htonl(0); 128 netmask = IPV4_NETMASK_HOST; 129 } 130 131 { 132 struct pf_subnet *e; 133 ALLOC_OBJ_CLEAR (e, struct pf_subnet); 134 e->rule.exclude = exclude; 135 e->rule.network = ntohl (network.s_addr); 136 e->rule.netmask = netmask; 137 **next = e; 138 *next = &e->next; 139 return true; 140 } 141} 142 143static uint32_t 144cn_hash_function (const void *key, uint32_t iv) 145{ 146 return hash_func ((uint8_t *)key, strlen ((char *)key) + 1, iv); 147} 148 149static bool 150cn_compare_function (const void *key1, const void *key2) 151{ 152 return !strcmp((const char *)key1, (const char *)key2); 153} 154 155static bool 156genhash (struct pf_cn_set *cns, const char *prefix, const int n_clients) 157{ 158 struct pf_cn_elem *e; 159 bool status = true; 160 int n_buckets = n_clients; 161 162 if (n_buckets < 16) 163 n_buckets = 16; 164 cns->hash_table = hash_init (n_buckets, 0, cn_hash_function, cn_compare_function); 165 for (e = cns->list; e != NULL; e = e->next) 166 { 167 if (!hash_add (cns->hash_table, e->rule.cn, &e->rule, false)) 168 { 169 msg (D_PF_INFO, "PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn); 170 status = false; 171 } 172 } 173 174 return status; 175} 176 177static struct pf_set * 178pf_init (const struct buffer_list *bl, const char *prefix, const bool allow_kill) 179{ 180# define MODE_UNDEF 0 181# define MODE_CLIENTS 1 182# define MODE_SUBNETS 2 183 int mode = MODE_UNDEF; 184 int line_num = 0; 185 int n_clients = 0; 186 int n_subnets = 0; 187 int n_errors = 0; 188 struct pf_set *pfs = NULL; 189 char line[PF_MAX_LINE_LEN]; 190 191 ALLOC_OBJ_CLEAR (pfs, struct pf_set); 192 if (bl) 193 { 194 struct pf_cn_elem **cl = &pfs->cns.list; 195 struct pf_subnet **sl = &pfs->sns.list; 196 struct buffer_entry *be; 197 198 for (be = bl->head; be != NULL; be = be->next) 199 { 200 ++line_num; 201 strncpynt (line, BSTR(&be->buf), sizeof(line)); 202 rm_trailing_chars (line, "\r\n\t "); 203 if (line[0] == '\0' || line[0] == '#') 204 ; 205 else if (line[0] == '+' || line[0] == '-') 206 { 207 bool exclude = (line[0] == '-'); 208 209 if (line[1] =='\0') 210 { 211 msg (D_PF_INFO, "PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line); 212 ++n_errors; 213 } 214 else if (mode == MODE_CLIENTS) 215 { 216 if (add_client (&line[1], prefix, line_num, &cl, exclude)) 217 ++n_clients; 218 else 219 ++n_errors; 220 } 221 else if (mode == MODE_SUBNETS) 222 { 223 if (add_subnet (&line[1], prefix, line_num, &sl, exclude)) 224 ++n_subnets; 225 else 226 ++n_errors; 227 } 228 else if (mode == MODE_UNDEF) 229 ; 230 else 231 { 232 ASSERT (0); 233 } 234 } 235 else if (line[0] == '[') 236 { 237 if (!strcasecmp (line, "[clients accept]")) 238 { 239 mode = MODE_CLIENTS; 240 pfs->cns.default_allow = true; 241 } 242 else if (!strcasecmp (line, "[clients drop]")) 243 { 244 mode = MODE_CLIENTS; 245 pfs->cns.default_allow = false; 246 } 247 else if (!strcasecmp (line, "[subnets accept]")) 248 { 249 mode = MODE_SUBNETS; 250 pfs->sns.default_allow = true; 251 } 252 else if (!strcasecmp (line, "[subnets drop]")) 253 { 254 mode = MODE_SUBNETS; 255 pfs->sns.default_allow = false; 256 } 257 else if (!strcasecmp (line, "[end]")) 258 goto done; 259 else if (allow_kill && !strcasecmp (line, "[kill]")) 260 goto kill; 261 else 262 { 263 mode = MODE_UNDEF; 264 msg (D_PF_INFO, "PF: %s/%d unknown tag: '%s'", prefix, line_num, line); 265 ++n_errors; 266 } 267 } 268 else 269 { 270 msg (D_PF_INFO, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line); 271 ++n_errors; 272 } 273 } 274 ++n_errors; 275 msg (D_PF_INFO, "PF: %s: missing [end]", prefix); 276 } 277 else 278 { 279 msg (D_PF_INFO, "PF: %s: cannot open", prefix); 280 ++n_errors; 281 } 282 283 done: 284 if (bl) 285 { 286 if (!n_errors) 287 { 288 if (!genhash (&pfs->cns, prefix, n_clients)) 289 ++n_errors; 290 } 291 if (n_errors) 292 msg (D_PF_INFO, "PF: %s rejected due to %d error(s)", prefix, n_errors); 293 } 294 if (n_errors) 295 { 296 pf_destroy (pfs); 297 pfs = NULL; 298 } 299 return pfs; 300 301 kill: 302 pf_destroy (pfs); 303 ALLOC_OBJ_CLEAR (pfs, struct pf_set); 304 pfs->kill = true; 305 return pfs; 306} 307 308#ifdef PLUGIN_PF 309static struct pf_set * 310pf_init_from_file (const char *fn) 311{ 312 struct buffer_list *bl = buffer_list_file (fn, PF_MAX_LINE_LEN); 313 if (bl) 314 { 315 struct pf_set *pfs = pf_init (bl, fn, true); 316 buffer_list_free (bl); 317 return pfs; 318 } 319 else 320 { 321 msg (D_PF_INFO|M_ERRNO, "PF: %s: cannot open", fn); 322 return NULL; 323 } 324} 325#endif 326 327#ifdef ENABLE_DEBUG 328 329static const char * 330drop_accept (const bool accept) 331{ 332 return accept ? "ACCEPT" : "DROP"; 333} 334 335static const char * 336pct_name (const int type) 337{ 338 switch (type) 339 { 340 case PCT_SRC: 341 return "SRC"; 342 case PCT_DEST: 343 return "DEST"; 344 default: 345 return "???"; 346 } 347} 348 349static void 350pf_cn_test_print (const char *prefix, 351 const int type, 352 const char *prefix2, 353 const char *cn, 354 const bool allow, 355 const struct pf_cn *rule) 356{ 357 if (rule) 358 { 359 dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s rule=[%s %s]", 360 prefix, prefix2, pct_name (type), 361 cn, drop_accept (allow), 362 rule->cn, drop_accept (!rule->exclude)); 363 } 364 else 365 { 366 dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s", 367 prefix, prefix2, pct_name (type), 368 cn, drop_accept (allow)); 369 } 370} 371 372static void 373pf_addr_test_print (const char *prefix, 374 const char *prefix2, 375 const struct context *src, 376 const struct mroute_addr *dest, 377 const bool allow, 378 const struct ipv4_subnet *rule) 379{ 380 struct gc_arena gc = gc_new (); 381 if (rule) 382 { 383 dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]", 384 prefix, 385 prefix2, 386 tls_common_name (src->c2.tls_multi, false), 387 mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc), 388 drop_accept (allow), 389 print_in_addr_t (rule->network, 0, &gc), 390 print_in_addr_t (rule->netmask, 0, &gc), 391 drop_accept (!rule->exclude)); 392 } 393 else 394 { 395 dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s", 396 prefix, 397 prefix2, 398 tls_common_name (src->c2.tls_multi, false), 399 mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc), 400 drop_accept (allow)); 401 } 402 gc_free (&gc); 403} 404 405#endif 406 407static inline struct pf_cn * 408lookup_cn_rule (struct hash *h, const char *cn, const uint32_t cn_hash) 409{ 410 struct hash_element *he = hash_lookup_fast (h, hash_bucket (h, cn_hash), cn, cn_hash); 411 if (he) 412 return (struct pf_cn *) he->value; 413 else 414 return NULL; 415} 416 417bool 418pf_cn_test (struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix) 419{ 420 if (!pfs->kill) 421 { 422 const char *cn; 423 uint32_t cn_hash; 424 if (tls_common_name_hash (tm, &cn, &cn_hash)) 425 { 426 const struct pf_cn *rule = lookup_cn_rule (pfs->cns.hash_table, cn, cn_hash); 427 if (rule) 428 { 429#ifdef ENABLE_DEBUG 430 if (check_debug_level (D_PF_DEBUG)) 431 pf_cn_test_print ("PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule); 432#endif 433 if (!rule->exclude) 434 return true; 435 else 436 return false; 437 } 438 else 439 { 440#ifdef ENABLE_DEBUG 441 if (check_debug_level (D_PF_DEBUG)) 442 pf_cn_test_print ("PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL); 443#endif 444 if (pfs->cns.default_allow) 445 return true; 446 else 447 return false; 448 } 449 } 450 } 451#ifdef ENABLE_DEBUG 452 if (check_debug_level (D_PF_DEBUG)) 453 pf_cn_test_print ("PF_CN_FAULT", type, prefix, tls_common_name (tm, false), false, NULL); 454#endif 455 return false; 456} 457 458bool 459pf_addr_test_dowork (const struct context *src, const struct mroute_addr *dest, const char *prefix) 460{ 461 struct pf_set *pfs = src->c2.pf.pfs; 462 if (pfs && !pfs->kill) 463 { 464 const in_addr_t addr = in_addr_t_from_mroute_addr (dest); 465 const struct pf_subnet *se = pfs->sns.list; 466 while (se) 467 { 468 if ((addr & se->rule.netmask) == se->rule.network) 469 { 470#ifdef ENABLE_DEBUG 471 if (check_debug_level (D_PF_DEBUG)) 472 pf_addr_test_print ("PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule); 473#endif 474 return !se->rule.exclude; 475 } 476 se = se->next; 477 } 478#ifdef ENABLE_DEBUG 479 if (check_debug_level (D_PF_DEBUG)) 480 pf_addr_test_print ("PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL); 481#endif 482 return pfs->sns.default_allow; 483 } 484 else 485 { 486#ifdef ENABLE_DEBUG 487 if (check_debug_level (D_PF_DEBUG)) 488 pf_addr_test_print ("PF_ADDR_FAULT", prefix, src, dest, false, NULL); 489#endif 490 return false; 491 } 492} 493 494#ifdef PLUGIN_PF 495void 496pf_check_reload (struct context *c) 497{ 498 const int slow_wakeup = 15; 499 const int fast_wakeup = 1; 500 const int wakeup_transition = 60; 501 bool reloaded = false; 502 503 if (c->c2.pf.enabled 504 && c->c2.pf.filename 505 && event_timeout_trigger (&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT)) 506 { 507 platform_stat_t s; 508 if (!platform_stat (c->c2.pf.filename, &s)) 509 { 510 if (s.st_mtime > c->c2.pf.file_last_mod) 511 { 512 struct pf_set *pfs = pf_init_from_file (c->c2.pf.filename); 513 if (pfs) 514 { 515 if (c->c2.pf.pfs) 516 pf_destroy (c->c2.pf.pfs); 517 c->c2.pf.pfs = pfs; 518 reloaded = true; 519 if (pf_kill_test (pfs)) 520 { 521 c->sig->signal_received = SIGTERM; 522 c->sig->signal_text = "pf-kill"; 523 } 524 } 525 c->c2.pf.file_last_mod = s.st_mtime; 526 } 527 } 528 { 529 int wakeup = slow_wakeup; 530 if (!c->c2.pf.pfs && c->c2.pf.n_check_reload < wakeup_transition) 531 wakeup = fast_wakeup; 532 event_timeout_init (&c->c2.pf.reload, wakeup, now); 533 reset_coarse_timers (c); 534 c->c2.pf.n_check_reload++; 535 } 536 } 537#ifdef ENABLE_DEBUG 538 if (reloaded && check_debug_level (D_PF_DEBUG)) 539 pf_context_print (&c->c2.pf, "pf_check_reload", D_PF_DEBUG); 540#endif 541} 542#endif 543 544#ifdef MANAGEMENT_PF 545bool 546pf_load_from_buffer_list (struct context *c, const struct buffer_list *config) 547{ 548 struct pf_set *pfs = pf_init (config, "[SERVER-PF]", false); 549 if (pfs) 550 { 551 if (c->c2.pf.pfs) 552 pf_destroy (c->c2.pf.pfs); 553 c->c2.pf.pfs = pfs; 554 return true; 555 } 556 else 557 return false; 558} 559#endif 560 561void 562pf_init_context (struct context *c) 563{ 564 struct gc_arena gc = gc_new (); 565#ifdef PLUGIN_PF 566 if (plugin_defined (c->plugins, OPENVPN_PLUGIN_ENABLE_PF)) 567 { 568 const char *pf_file = create_temp_file (c->options.tmp_dir, "pf", &gc); 569 if( pf_file ) { 570 setenv_str (c->c2.es, "pf_file", pf_file); 571 572 if (plugin_call (c->plugins, OPENVPN_PLUGIN_ENABLE_PF, NULL, NULL, c->c2.es) == OPENVPN_PLUGIN_FUNC_SUCCESS) 573 { 574 event_timeout_init (&c->c2.pf.reload, 1, now); 575 c->c2.pf.filename = string_alloc (pf_file, &c->c2.gc); 576 c->c2.pf.enabled = true; 577#ifdef ENABLE_DEBUG 578 if (check_debug_level (D_PF_DEBUG)) 579 pf_context_print (&c->c2.pf, "pf_init_context#1", D_PF_DEBUG); 580#endif 581 } 582 else 583 { 584 msg (M_WARN, "WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled"); 585 } 586 } 587 } 588#endif 589#ifdef MANAGEMENT_PF 590 if (!c->c2.pf.enabled && management_enable_pf (management)) 591 { 592 c->c2.pf.enabled = true; 593#ifdef ENABLE_DEBUG 594 if (check_debug_level (D_PF_DEBUG)) 595 pf_context_print (&c->c2.pf, "pf_init_context#2", D_PF_DEBUG); 596#endif 597 } 598#endif 599 gc_free (&gc); 600} 601 602void 603pf_destroy_context (struct pf_context *pfc) 604{ 605#ifdef PLUGIN_PF 606 if (pfc->filename) 607 { 608 platform_unlink (pfc->filename); 609 } 610#endif 611 if (pfc->pfs) 612 pf_destroy (pfc->pfs); 613} 614 615#ifdef ENABLE_DEBUG 616 617static void 618pf_subnet_set_print (const struct pf_subnet_set *s, const int lev) 619{ 620 struct gc_arena gc = gc_new (); 621 if (s) 622 { 623 struct pf_subnet *e; 624 625 msg (lev, " ----- struct pf_subnet_set -----"); 626 msg (lev, " default_allow=%s", drop_accept (s->default_allow)); 627 628 for (e = s->list; e != NULL; e = e->next) 629 { 630 msg (lev, " %s/%s %s", 631 print_in_addr_t (e->rule.network, 0, &gc), 632 print_in_addr_t (e->rule.netmask, 0, &gc), 633 drop_accept (!e->rule.exclude)); 634 } 635 } 636 gc_free (&gc); 637} 638 639static void 640pf_cn_set_print (const struct pf_cn_set *s, const int lev) 641{ 642 if (s) 643 { 644 struct hash_iterator hi; 645 struct hash_element *he; 646 647 msg (lev, " ----- struct pf_cn_set -----"); 648 msg (lev, " default_allow=%s", drop_accept (s->default_allow)); 649 650 if (s->hash_table) 651 { 652 hash_iterator_init (s->hash_table, &hi); 653 while ((he = hash_iterator_next (&hi))) 654 { 655 struct pf_cn *e = (struct pf_cn *)he->value; 656 msg (lev, " %s %s", 657 e->cn, 658 drop_accept (!e->exclude)); 659 } 660 661 msg (lev, " ----------"); 662 663 { 664 struct pf_cn_elem *ce; 665 for (ce = s->list; ce != NULL; ce = ce->next) 666 { 667 struct pf_cn *e = lookup_cn_rule (s->hash_table, ce->rule.cn, cn_hash_function (ce->rule.cn, 0)); 668 if (e) 669 { 670 msg (lev, " %s %s", 671 e->cn, 672 drop_accept (!e->exclude)); 673 } 674 else 675 { 676 msg (lev, " %s LOOKUP FAILED", ce->rule.cn); 677 } 678 } 679 } 680 } 681 } 682} 683 684static void 685pf_set_print (const struct pf_set *pfs, const int lev) 686{ 687 if (pfs) 688 { 689 msg (lev, " ----- struct pf_set -----"); 690 msg (lev, " kill=%d", pfs->kill); 691 pf_subnet_set_print (&pfs->sns, lev); 692 pf_cn_set_print (&pfs->cns, lev); 693 } 694} 695 696void 697pf_context_print (const struct pf_context *pfc, const char *prefix, const int lev) 698{ 699 msg (lev, "----- %s : struct pf_context -----", prefix); 700 if (pfc) 701 { 702 msg (lev, "enabled=%d", pfc->enabled); 703#ifdef PLUGIN_PF 704 msg (lev, "filename='%s'", np(pfc->filename)); 705 msg (lev, "file_last_mod=%u", (unsigned int)pfc->file_last_mod); 706 msg (lev, "n_check_reload=%u", pfc->n_check_reload); 707 msg (lev, "reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (unsigned int)pfc->reload.last); 708#endif 709 pf_set_print (pfc->pfs, lev); 710 } 711 msg (lev, "--------------------"); 712} 713 714#endif 715 716#endif 717