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
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 */
29 #if defined(ENABLE_PF)
35 #include "pf-inline.h"
38 pf_destroy (struct pf_set
*pfs
)
42 if (pfs
->cns
.hash_table
)
43 hash_free (pfs
->cns
.hash_table
);
46 struct pf_cn_elem
*l
= pfs
->cns
.list
;
49 struct pf_cn_elem
*next
= l
->next
;
56 struct pf_subnet
*l
= pfs
->sns
.list
;
59 struct pf_subnet
*next
= l
->next
;
69 add_client (const char *line
, const char *prefix
, const int line_num
, struct pf_cn_elem
***next
, const bool exclude
)
72 ALLOC_OBJ_CLEAR (e
, struct pf_cn_elem
);
73 e
->rule
.exclude
= exclude
;
74 e
->rule
.cn
= string_alloc (line
, NULL
);
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"))
89 char *div
= strchr (line
, '/');
94 if (sscanf (div
, "%d", &netbits
) != 1)
96 msg (D_PF_INFO
, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix
, line_num
, div
);
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
);
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
);
111 netmask
= netbits_to_netmask (netbits
);
115 /* match special "unknown" tag for addresses unrecognized by mroute */
116 network
.s_addr
= htonl(0);
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
;
133 cn_hash_function (const void *key
, uint32_t iv
)
135 return hash_func ((uint8_t *)key
, strlen ((char *)key
) + 1, iv
);
139 cn_compare_function (const void *key1
, const void *key2
)
141 return !strcmp((const char *)key1
, (const char *)key2
);
145 genhash (struct pf_cn_set
*cns
, const char *prefix
, const int n_clients
)
147 struct pf_cn_elem
*e
;
149 int n_buckets
= n_clients
;
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
);
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
;
177 struct pf_set
*pfs
= NULL
;
178 char line
[PF_MAX_LINE_LEN
];
180 ALLOC_OBJ_CLEAR (pfs
, struct pf_set
);
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
)
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] == '-');
200 msg (D_PF_INFO
, "PF: %s/%d: no data after +/-: '%s'", prefix
, line_num
, line
);
203 else if (mode
== MODE_CLIENTS
)
205 if (add_client (&line
[1], prefix
, line_num
, &cl
, exclude
))
210 else if (mode
== MODE_SUBNETS
)
212 if (add_subnet (&line
[1], prefix
, line_num
, &sl
, exclude
))
217 else if (mode
== MODE_UNDEF
)
224 else if (line
[0] == '[')
226 if (!strcasecmp (line
, "[clients accept]"))
229 pfs
->cns
.default_allow
= true;
231 else if (!strcasecmp (line
, "[clients drop]"))
234 pfs
->cns
.default_allow
= false;
236 else if (!strcasecmp (line
, "[subnets accept]"))
239 pfs
->sns
.default_allow
= true;
241 else if (!strcasecmp (line
, "[subnets drop]"))
244 pfs
->sns
.default_allow
= false;
246 else if (!strcasecmp (line
, "[end]"))
248 else if (allow_kill
&& !strcasecmp (line
, "[kill]"))
253 msg (D_PF_INFO
, "PF: %s/%d unknown tag: '%s'", prefix
, line_num
, line
);
259 msg (D_PF_INFO
, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix
, line_num
, line
);
264 msg (D_PF_INFO
, "PF: %s: missing [end]", prefix
);
268 msg (D_PF_INFO
, "PF: %s: cannot open", prefix
);
277 if (!genhash (&pfs
->cns
, prefix
, n_clients
))
281 msg (D_PF_INFO
, "PF: %s rejected due to %d error(s)", prefix
, n_errors
);
292 ALLOC_OBJ_CLEAR (pfs
, struct pf_set
);
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
);
304 struct pf_set
*pfs
= pf_init (bl
, fn
, true);
305 buffer_list_free (bl
);
310 msg (D_PF_INFO
|M_ERRNO
, "PF: %s: cannot open", fn
);
319 drop_accept (const bool accept
)
321 return accept
? "ACCEPT" : "DROP";
325 pct_name (const int type
)
339 pf_cn_test_print (const char *prefix
,
344 const struct pf_cn
*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
));
355 dmsg (D_PF_DEBUG
, "PF: %s/%s/%s %s %s",
356 prefix
, prefix2
, pct_name (type
),
357 cn
, drop_accept (allow
));
362 pf_addr_test_print (const char *prefix
,
364 const struct context
*src
,
365 const struct mroute_addr
*dest
,
367 const struct ipv4_subnet
*rule
)
369 struct gc_arena gc
= gc_new ();
372 dmsg (D_PF_DEBUG
, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
375 tls_common_name (src
->c2
.tls_multi
, false),
376 mroute_addr_print_ex (dest
, MAPF_SHOW_ARP
, &gc
),
378 print_in_addr_t (rule
->network
, 0, &gc
),
379 print_in_addr_t (rule
->netmask
, 0, &gc
),
380 drop_accept (!rule
->exclude
));
384 dmsg (D_PF_DEBUG
, "PF: %s/%s %s %s %s",
387 tls_common_name (src
->c2
.tls_multi
, false),
388 mroute_addr_print_ex (dest
, MAPF_SHOW_ARP
, &gc
),
389 drop_accept (allow
));
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
);
401 return (struct pf_cn
*) he
->value
;
407 pf_cn_test (struct pf_set
*pfs
, const struct tls_multi
*tm
, const int type
, const char *prefix
)
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
);
419 if (check_debug_level (D_PF_DEBUG
))
420 pf_cn_test_print ("PF_CN_MATCH", type
, prefix
, cn
, !rule
->exclude
, rule
);
430 if (check_debug_level (D_PF_DEBUG
))
431 pf_cn_test_print ("PF_CN_DEFAULT", type
, prefix
, cn
, pfs
->cns
.default_allow
, NULL
);
433 if (pfs
->cns
.default_allow
)
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
);
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
;
457 if ((addr
& se
->rule
.netmask
) == se
->rule
.network
)
460 if (check_debug_level (D_PF_DEBUG
))
461 pf_addr_test_print ("PF_ADDR_MATCH", prefix
, src
, dest
, !se
->rule
.exclude
, &se
->rule
);
463 return !se
->rule
.exclude
;
468 if (check_debug_level (D_PF_DEBUG
))
469 pf_addr_test_print ("PF_ADDR_DEFAULT", prefix
, src
, dest
, pfs
->sns
.default_allow
, NULL
);
471 return pfs
->sns
.default_allow
;
476 if (check_debug_level (D_PF_DEBUG
))
477 pf_addr_test_print ("PF_ADDR_FAULT", prefix
, src
, dest
, false, NULL
);
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;
494 && event_timeout_trigger (&c
->c2
.pf
.reload
, &c
->c2
.timeval
, ETT_DEFAULT
))
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
);
505 pf_destroy (c
->c2
.pf
.pfs
);
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
++;
527 if (reloaded
&& check_debug_level (D_PF_DEBUG
))
528 pf_context_print (&c
->c2
.pf
, "pf_check_reload", D_PF_DEBUG
);
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);
541 pf_destroy (c
->c2
.pf
.pfs
);
551 pf_init_context (struct context
*c
)
553 struct gc_arena gc
= gc_new ();
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;
567 if (check_debug_level (D_PF_DEBUG
))
568 pf_context_print (&c
->c2
.pf
, "pf_init_context#1", D_PF_DEBUG
);
573 msg (M_WARN
, "WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled");
578 if (!c
->c2
.pf
.enabled
&& management_enable_pf (management
))
580 c
->c2
.pf
.enabled
= true;
582 if (check_debug_level (D_PF_DEBUG
))
583 pf_context_print (&c
->c2
.pf
, "pf_init_context#2", D_PF_DEBUG
);
591 pf_destroy_context (struct pf_context
*pfc
)
596 delete_file (pfc
->filename
);
597 free (pfc
->filename
);
601 pf_destroy (pfc
->pfs
);
607 pf_subnet_set_print (const struct pf_subnet_set
*s
, const int lev
)
609 struct gc_arena gc
= gc_new ();
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
));
629 pf_cn_set_print (const struct pf_cn_set
*s
, const int lev
)
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
));
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
;
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));
661 drop_accept (!e
->exclude
));
665 msg (lev
, " %s LOOKUP FAILED", ce
->rule
.cn
);
674 pf_set_print (const struct pf_set
*pfs
, const int lev
)
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
);
686 pf_context_print (const struct pf_context
*pfc
, const char *prefix
, const int lev
)
688 msg (lev
, "----- %s : struct pf_context -----", prefix
);
691 msg (lev
, "enabled=%d", pfc
->enabled
);
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
);
698 pf_set_print (pfc
->pfs
, lev
);
700 msg (lev
, "--------------------");