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