cosmetics
[tomato.git] / release / src / router / openvpn / pf.c
blob027eb695f67eb9fedf4ac2fe8bbd09da2d1fd40a
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.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
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.
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.
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
25 /* packet filter functions */
27 #include "syshead.h"
29 #if defined(ENABLE_PF)
31 #include "init.h"
33 #include "memdbg.h"
35 #include "pf-inline.h"
37 static void
38 pf_destroy (struct pf_set *pfs)
40 if (pfs)
42 if (pfs->cns.hash_table)
43 hash_free (pfs->cns.hash_table);
46 struct pf_cn_elem *l = pfs->cns.list;
47 while (l)
49 struct pf_cn_elem *next = l->next;
50 free (l->rule.cn);
51 free (l);
52 l = next;
56 struct pf_subnet *l = pfs->sns.list;
57 while (l)
59 struct pf_subnet *next = l->next;
60 free (l);
61 l = next;
64 free (pfs);
68 static bool
69 add_client (const char *line, const char *prefix, const int line_num, struct pf_cn_elem ***next, const bool exclude)
71 struct pf_cn_elem *e;
72 ALLOC_OBJ_CLEAR (e, struct pf_cn_elem);
73 e->rule.exclude = exclude;
74 e->rule.cn = string_alloc (line, NULL);
75 **next = e;
76 *next = &e->next;
77 return true;
80 static bool
81 add_subnet (const char *line, const char *prefix, const int line_num, struct pf_subnet ***next, const bool exclude)
83 struct in_addr network;
84 in_addr_t netmask = 0;
86 if (strcmp (line, "unknown"))
88 int netbits = 32;
89 char *div = strchr (line, '/');
91 if (div)
93 *div++ = '\0';
94 if (sscanf (div, "%d", &netbits) != 1)
96 msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div);
97 return false;
99 if (netbits < 0 || netbits > 32)
101 msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div);
102 return false;
106 if (openvpn_inet_aton (line, &network) != OIA_IP)
108 msg (D_PF_INFO, "PF: %s/%d: bad network address: '%s'", prefix, line_num, line);
109 return false;
111 netmask = netbits_to_netmask (netbits);
113 else
115 /* match special "unknown" tag for addresses unrecognized by mroute */
116 network.s_addr = htonl(0);
117 netmask = ~0;
121 struct pf_subnet *e;
122 ALLOC_OBJ_CLEAR (e, struct pf_subnet);
123 e->rule.exclude = exclude;
124 e->rule.network = ntohl (network.s_addr);
125 e->rule.netmask = netmask;
126 **next = e;
127 *next = &e->next;
128 return true;
132 static uint32_t
133 cn_hash_function (const void *key, uint32_t iv)
135 return hash_func ((uint8_t *)key, strlen ((char *)key) + 1, iv);
138 static bool
139 cn_compare_function (const void *key1, const void *key2)
141 return !strcmp((const char *)key1, (const char *)key2);
144 static bool
145 genhash (struct pf_cn_set *cns, const char *prefix, const int n_clients)
147 struct pf_cn_elem *e;
148 bool status = true;
149 int n_buckets = n_clients;
151 if (n_buckets < 16)
152 n_buckets = 16;
153 cns->hash_table = hash_init (n_buckets, 0, cn_hash_function, cn_compare_function);
154 for (e = cns->list; e != NULL; e = e->next)
156 if (!hash_add (cns->hash_table, e->rule.cn, &e->rule, false))
158 msg (D_PF_INFO, "PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn);
159 status = false;
163 return status;
166 static struct pf_set *
167 pf_init (const struct buffer_list *bl, const char *prefix, const bool allow_kill)
169 # define MODE_UNDEF 0
170 # define MODE_CLIENTS 1
171 # define MODE_SUBNETS 2
172 int mode = MODE_UNDEF;
173 int line_num = 0;
174 int n_clients = 0;
175 int n_subnets = 0;
176 int n_errors = 0;
177 struct pf_set *pfs = NULL;
178 char line[PF_MAX_LINE_LEN];
180 ALLOC_OBJ_CLEAR (pfs, struct pf_set);
181 if (bl)
183 struct pf_cn_elem **cl = &pfs->cns.list;
184 struct pf_subnet **sl = &pfs->sns.list;
185 struct buffer_entry *be;
187 for (be = bl->head; be != NULL; be = be->next)
189 ++line_num;
190 strncpynt (line, BSTR(&be->buf), sizeof(line));
191 rm_trailing_chars (line, "\r\n\t ");
192 if (line[0] == '\0' || line[0] == '#')
194 else if (line[0] == '+' || line[0] == '-')
196 bool exclude = (line[0] == '-');
198 if (line[1] =='\0')
200 msg (D_PF_INFO, "PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line);
201 ++n_errors;
203 else if (mode == MODE_CLIENTS)
205 if (add_client (&line[1], prefix, line_num, &cl, exclude))
206 ++n_clients;
207 else
208 ++n_errors;
210 else if (mode == MODE_SUBNETS)
212 if (add_subnet (&line[1], prefix, line_num, &sl, exclude))
213 ++n_subnets;
214 else
215 ++n_errors;
217 else if (mode == MODE_UNDEF)
219 else
221 ASSERT (0);
224 else if (line[0] == '[')
226 if (!strcasecmp (line, "[clients accept]"))
228 mode = MODE_CLIENTS;
229 pfs->cns.default_allow = true;
231 else if (!strcasecmp (line, "[clients drop]"))
233 mode = MODE_CLIENTS;
234 pfs->cns.default_allow = false;
236 else if (!strcasecmp (line, "[subnets accept]"))
238 mode = MODE_SUBNETS;
239 pfs->sns.default_allow = true;
241 else if (!strcasecmp (line, "[subnets drop]"))
243 mode = MODE_SUBNETS;
244 pfs->sns.default_allow = false;
246 else if (!strcasecmp (line, "[end]"))
247 goto done;
248 else if (allow_kill && !strcasecmp (line, "[kill]"))
249 goto kill;
250 else
252 mode = MODE_UNDEF;
253 msg (D_PF_INFO, "PF: %s/%d unknown tag: '%s'", prefix, line_num, line);
254 ++n_errors;
257 else
259 msg (D_PF_INFO, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line);
260 ++n_errors;
263 ++n_errors;
264 msg (D_PF_INFO, "PF: %s: missing [end]", prefix);
266 else
268 msg (D_PF_INFO, "PF: %s: cannot open", prefix);
269 ++n_errors;
272 done:
273 if (bl)
275 if (!n_errors)
277 if (!genhash (&pfs->cns, prefix, n_clients))
278 ++n_errors;
280 if (n_errors)
281 msg (D_PF_INFO, "PF: %s rejected due to %d error(s)", prefix, n_errors);
283 if (n_errors)
285 pf_destroy (pfs);
286 pfs = NULL;
288 return pfs;
290 kill:
291 pf_destroy (pfs);
292 ALLOC_OBJ_CLEAR (pfs, struct pf_set);
293 pfs->kill = true;
294 return pfs;
297 #ifdef PLUGIN_PF
298 static struct pf_set *
299 pf_init_from_file (const char *fn)
301 struct buffer_list *bl = buffer_list_file (fn, PF_MAX_LINE_LEN);
302 if (bl)
304 struct pf_set *pfs = pf_init (bl, fn, true);
305 buffer_list_free (bl);
306 return pfs;
308 else
310 msg (D_PF_INFO|M_ERRNO, "PF: %s: cannot open", fn);
311 return NULL;
314 #endif
316 #ifdef ENABLE_DEBUG
318 static const char *
319 drop_accept (const bool accept)
321 return accept ? "ACCEPT" : "DROP";
324 static const char *
325 pct_name (const int type)
327 switch (type)
329 case PCT_SRC:
330 return "SRC";
331 case PCT_DEST:
332 return "DEST";
333 default:
334 return "???";
338 static void
339 pf_cn_test_print (const char *prefix,
340 const int type,
341 const char *prefix2,
342 const char *cn,
343 const bool allow,
344 const struct pf_cn *rule)
346 if (rule)
348 dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s rule=[%s %s]",
349 prefix, prefix2, pct_name (type),
350 cn, drop_accept (allow),
351 rule->cn, drop_accept (!rule->exclude));
353 else
355 dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s",
356 prefix, prefix2, pct_name (type),
357 cn, drop_accept (allow));
361 static void
362 pf_addr_test_print (const char *prefix,
363 const char *prefix2,
364 const struct context *src,
365 const struct mroute_addr *dest,
366 const bool allow,
367 const struct ipv4_subnet *rule)
369 struct gc_arena gc = gc_new ();
370 if (rule)
372 dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
373 prefix,
374 prefix2,
375 tls_common_name (src->c2.tls_multi, false),
376 mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc),
377 drop_accept (allow),
378 print_in_addr_t (rule->network, 0, &gc),
379 print_in_addr_t (rule->netmask, 0, &gc),
380 drop_accept (!rule->exclude));
382 else
384 dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s",
385 prefix,
386 prefix2,
387 tls_common_name (src->c2.tls_multi, false),
388 mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc),
389 drop_accept (allow));
391 gc_free (&gc);
394 #endif
396 static inline struct pf_cn *
397 lookup_cn_rule (struct hash *h, const char *cn, const uint32_t cn_hash)
399 struct hash_element *he = hash_lookup_fast (h, hash_bucket (h, cn_hash), cn, cn_hash);
400 if (he)
401 return (struct pf_cn *) he->value;
402 else
403 return NULL;
406 bool
407 pf_cn_test (struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix)
409 if (!pfs->kill)
411 const char *cn;
412 uint32_t cn_hash;
413 if (tls_common_name_hash (tm, &cn, &cn_hash))
415 const struct pf_cn *rule = lookup_cn_rule (pfs->cns.hash_table, cn, cn_hash);
416 if (rule)
418 #ifdef ENABLE_DEBUG
419 if (check_debug_level (D_PF_DEBUG))
420 pf_cn_test_print ("PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule);
421 #endif
422 if (!rule->exclude)
423 return true;
424 else
425 return false;
427 else
429 #ifdef ENABLE_DEBUG
430 if (check_debug_level (D_PF_DEBUG))
431 pf_cn_test_print ("PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL);
432 #endif
433 if (pfs->cns.default_allow)
434 return true;
435 else
436 return false;
440 #ifdef ENABLE_DEBUG
441 if (check_debug_level (D_PF_DEBUG))
442 pf_cn_test_print ("PF_CN_FAULT", type, prefix, tls_common_name (tm, false), false, NULL);
443 #endif
444 return false;
447 bool
448 pf_addr_test_dowork (const struct context *src, const struct mroute_addr *dest, const char *prefix)
450 struct pf_set *pfs = src->c2.pf.pfs;
451 if (pfs && !pfs->kill)
453 const in_addr_t addr = in_addr_t_from_mroute_addr (dest);
454 const struct pf_subnet *se = pfs->sns.list;
455 while (se)
457 if ((addr & se->rule.netmask) == se->rule.network)
459 #ifdef ENABLE_DEBUG
460 if (check_debug_level (D_PF_DEBUG))
461 pf_addr_test_print ("PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule);
462 #endif
463 return !se->rule.exclude;
465 se = se->next;
467 #ifdef ENABLE_DEBUG
468 if (check_debug_level (D_PF_DEBUG))
469 pf_addr_test_print ("PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL);
470 #endif
471 return pfs->sns.default_allow;
473 else
475 #ifdef ENABLE_DEBUG
476 if (check_debug_level (D_PF_DEBUG))
477 pf_addr_test_print ("PF_ADDR_FAULT", prefix, src, dest, false, NULL);
478 #endif
479 return false;
483 #ifdef PLUGIN_PF
484 void
485 pf_check_reload (struct context *c)
487 const int slow_wakeup = 15;
488 const int fast_wakeup = 1;
489 const int wakeup_transition = 60;
490 bool reloaded = false;
492 if (c->c2.pf.enabled
493 && c->c2.pf.filename
494 && event_timeout_trigger (&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT))
496 struct stat s;
497 if (!stat (c->c2.pf.filename, &s))
499 if (s.st_mtime > c->c2.pf.file_last_mod)
501 struct pf_set *pfs = pf_init_from_file (c->c2.pf.filename);
502 if (pfs)
504 if (c->c2.pf.pfs)
505 pf_destroy (c->c2.pf.pfs);
506 c->c2.pf.pfs = pfs;
507 reloaded = true;
508 if (pf_kill_test (pfs))
510 c->sig->signal_received = SIGTERM;
511 c->sig->signal_text = "pf-kill";
514 c->c2.pf.file_last_mod = s.st_mtime;
518 int wakeup = slow_wakeup;
519 if (!c->c2.pf.pfs && c->c2.pf.n_check_reload < wakeup_transition)
520 wakeup = fast_wakeup;
521 event_timeout_init (&c->c2.pf.reload, wakeup, now);
522 reset_coarse_timers (c);
523 c->c2.pf.n_check_reload++;
526 #ifdef ENABLE_DEBUG
527 if (reloaded && check_debug_level (D_PF_DEBUG))
528 pf_context_print (&c->c2.pf, "pf_check_reload", D_PF_DEBUG);
529 #endif
531 #endif
533 #ifdef MANAGEMENT_PF
534 bool
535 pf_load_from_buffer_list (struct context *c, const struct buffer_list *config)
537 struct pf_set *pfs = pf_init (config, "[SERVER-PF]", false);
538 if (pfs)
540 if (c->c2.pf.pfs)
541 pf_destroy (c->c2.pf.pfs);
542 c->c2.pf.pfs = pfs;
543 return true;
545 else
546 return false;
548 #endif
550 void
551 pf_init_context (struct context *c)
553 struct gc_arena gc = gc_new ();
554 #ifdef PLUGIN_PF
555 if (plugin_defined (c->plugins, OPENVPN_PLUGIN_ENABLE_PF))
557 const char *pf_file = create_temp_filename (c->options.tmp_dir, "pf", &gc);
558 delete_file (pf_file);
559 setenv_str (c->c2.es, "pf_file", pf_file);
561 if (plugin_call (c->plugins, OPENVPN_PLUGIN_ENABLE_PF, NULL, NULL, c->c2.es) == OPENVPN_PLUGIN_FUNC_SUCCESS)
563 event_timeout_init (&c->c2.pf.reload, 1, now);
564 c->c2.pf.filename = string_alloc (pf_file, NULL);
565 c->c2.pf.enabled = true;
566 #ifdef ENABLE_DEBUG
567 if (check_debug_level (D_PF_DEBUG))
568 pf_context_print (&c->c2.pf, "pf_init_context#1", D_PF_DEBUG);
569 #endif
571 else
573 msg (M_WARN, "WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled");
576 #endif
577 #ifdef MANAGEMENT_PF
578 if (!c->c2.pf.enabled && management_enable_pf (management))
580 c->c2.pf.enabled = true;
581 #ifdef ENABLE_DEBUG
582 if (check_debug_level (D_PF_DEBUG))
583 pf_context_print (&c->c2.pf, "pf_init_context#2", D_PF_DEBUG);
584 #endif
586 #endif
587 gc_free (&gc);
590 void
591 pf_destroy_context (struct pf_context *pfc)
593 #ifdef PLUGIN_PF
594 if (pfc->filename)
596 delete_file (pfc->filename);
597 free (pfc->filename);
599 #endif
600 if (pfc->pfs)
601 pf_destroy (pfc->pfs);
604 #ifdef ENABLE_DEBUG
606 static void
607 pf_subnet_set_print (const struct pf_subnet_set *s, const int lev)
609 struct gc_arena gc = gc_new ();
610 if (s)
612 struct pf_subnet *e;
614 msg (lev, " ----- struct pf_subnet_set -----");
615 msg (lev, " default_allow=%s", drop_accept (s->default_allow));
617 for (e = s->list; e != NULL; e = e->next)
619 msg (lev, " %s/%s %s",
620 print_in_addr_t (e->rule.network, 0, &gc),
621 print_in_addr_t (e->rule.netmask, 0, &gc),
622 drop_accept (!e->rule.exclude));
625 gc_free (&gc);
628 static void
629 pf_cn_set_print (const struct pf_cn_set *s, const int lev)
631 if (s)
633 struct hash_iterator hi;
634 struct hash_element *he;
636 msg (lev, " ----- struct pf_cn_set -----");
637 msg (lev, " default_allow=%s", drop_accept (s->default_allow));
639 if (s->hash_table)
641 hash_iterator_init (s->hash_table, &hi, false);
642 while ((he = hash_iterator_next (&hi)))
644 struct pf_cn *e = (struct pf_cn *)he->value;
645 msg (lev, " %s %s",
646 e->cn,
647 drop_accept (!e->exclude));
650 msg (lev, " ----------");
653 struct pf_cn_elem *ce;
654 for (ce = s->list; ce != NULL; ce = ce->next)
656 struct pf_cn *e = lookup_cn_rule (s->hash_table, ce->rule.cn, cn_hash_function (ce->rule.cn, 0));
657 if (e)
659 msg (lev, " %s %s",
660 e->cn,
661 drop_accept (!e->exclude));
663 else
665 msg (lev, " %s LOOKUP FAILED", ce->rule.cn);
673 static void
674 pf_set_print (const struct pf_set *pfs, const int lev)
676 if (pfs)
678 msg (lev, " ----- struct pf_set -----");
679 msg (lev, " kill=%d", pfs->kill);
680 pf_subnet_set_print (&pfs->sns, lev);
681 pf_cn_set_print (&pfs->cns, lev);
685 void
686 pf_context_print (const struct pf_context *pfc, const char *prefix, const int lev)
688 msg (lev, "----- %s : struct pf_context -----", prefix);
689 if (pfc)
691 msg (lev, "enabled=%d", pfc->enabled);
692 #ifdef PLUGIN_PF
693 msg (lev, "filename='%s'", np(pfc->filename));
694 msg (lev, "file_last_mod=%u", (unsigned int)pfc->file_last_mod);
695 msg (lev, "n_check_reload=%u", pfc->n_check_reload);
696 msg (lev, "reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (unsigned int)pfc->reload.last);
697 #endif
698 pf_set_print (pfc->pfs, lev);
700 msg (lev, "--------------------");
703 #endif
705 #endif