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-2010 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 #elif defined(_MSC_VER)
30 #include "config-msvc.h"
35 #if defined(ENABLE_PF)
41 #include "pf-inline.h"
44 pf_destroy (struct pf_set
*pfs
)
48 if (pfs
->cns
.hash_table
)
49 hash_free (pfs
->cns
.hash_table
);
52 struct pf_cn_elem
*l
= pfs
->cns
.list
;
55 struct pf_cn_elem
*next
= l
->next
;
62 struct pf_subnet
*l
= pfs
->sns
.list
;
65 struct pf_subnet
*next
= l
->next
;
75 add_client (const char *line
, const char *prefix
, const int line_num
, struct pf_cn_elem
***next
, const bool exclude
)
78 ALLOC_OBJ_CLEAR (e
, struct pf_cn_elem
);
79 e
->rule
.exclude
= exclude
;
80 e
->rule
.cn
= string_alloc (line
, NULL
);
87 add_subnet (const char *line
, const char *prefix
, const int line_num
, struct pf_subnet
***next
, const bool exclude
)
89 struct in_addr network
;
90 in_addr_t netmask
= 0;
92 if (strcmp (line
, "unknown"))
95 char *div
= strchr (line
, '/');
100 if (sscanf (div
, "%d", &netbits
) != 1)
102 msg (D_PF_INFO
, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix
, line_num
, div
);
105 if (netbits
< 0 || netbits
> 32)
107 msg (D_PF_INFO
, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix
, line_num
, div
);
112 if (openvpn_inet_aton (line
, &network
) != OIA_IP
)
114 msg (D_PF_INFO
, "PF: %s/%d: bad network address: '%s'", prefix
, line_num
, line
);
117 netmask
= netbits_to_netmask (netbits
);
118 if ((network
.s_addr
& htonl (netmask
)) != network
.s_addr
)
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
);
126 /* match special "unknown" tag for addresses unrecognized by mroute */
127 network
.s_addr
= htonl(0);
128 netmask
= IPV4_NETMASK_HOST
;
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
;
144 cn_hash_function (const void *key
, uint32_t iv
)
146 return hash_func ((uint8_t *)key
, strlen ((char *)key
) + 1, iv
);
150 cn_compare_function (const void *key1
, const void *key2
)
152 return !strcmp((const char *)key1
, (const char *)key2
);
156 genhash (struct pf_cn_set
*cns
, const char *prefix
, const int n_clients
)
158 struct pf_cn_elem
*e
;
160 int n_buckets
= n_clients
;
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
)
167 if (!hash_add (cns
->hash_table
, e
->rule
.cn
, &e
->rule
, false))
169 msg (D_PF_INFO
, "PF: %s: duplicate common name in [clients] section: '%s'", prefix
, e
->rule
.cn
);
177 static struct pf_set
*
178 pf_init (const struct buffer_list
*bl
, const char *prefix
, const bool allow_kill
)
180 # define MODE_UNDEF 0
181 # define MODE_CLIENTS 1
182 # define MODE_SUBNETS 2
183 int mode
= MODE_UNDEF
;
188 struct pf_set
*pfs
= NULL
;
189 char line
[PF_MAX_LINE_LEN
];
191 ALLOC_OBJ_CLEAR (pfs
, struct pf_set
);
194 struct pf_cn_elem
**cl
= &pfs
->cns
.list
;
195 struct pf_subnet
**sl
= &pfs
->sns
.list
;
196 struct buffer_entry
*be
;
198 for (be
= bl
->head
; be
!= NULL
; be
= be
->next
)
201 strncpynt (line
, BSTR(&be
->buf
), sizeof(line
));
202 rm_trailing_chars (line
, "\r\n\t ");
203 if (line
[0] == '\0' || line
[0] == '#')
205 else if (line
[0] == '+' || line
[0] == '-')
207 bool exclude
= (line
[0] == '-');
211 msg (D_PF_INFO
, "PF: %s/%d: no data after +/-: '%s'", prefix
, line_num
, line
);
214 else if (mode
== MODE_CLIENTS
)
216 if (add_client (&line
[1], prefix
, line_num
, &cl
, exclude
))
221 else if (mode
== MODE_SUBNETS
)
223 if (add_subnet (&line
[1], prefix
, line_num
, &sl
, exclude
))
228 else if (mode
== MODE_UNDEF
)
235 else if (line
[0] == '[')
237 if (!strcasecmp (line
, "[clients accept]"))
240 pfs
->cns
.default_allow
= true;
242 else if (!strcasecmp (line
, "[clients drop]"))
245 pfs
->cns
.default_allow
= false;
247 else if (!strcasecmp (line
, "[subnets accept]"))
250 pfs
->sns
.default_allow
= true;
252 else if (!strcasecmp (line
, "[subnets drop]"))
255 pfs
->sns
.default_allow
= false;
257 else if (!strcasecmp (line
, "[end]"))
259 else if (allow_kill
&& !strcasecmp (line
, "[kill]"))
264 msg (D_PF_INFO
, "PF: %s/%d unknown tag: '%s'", prefix
, line_num
, line
);
270 msg (D_PF_INFO
, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix
, line_num
, line
);
275 msg (D_PF_INFO
, "PF: %s: missing [end]", prefix
);
279 msg (D_PF_INFO
, "PF: %s: cannot open", prefix
);
288 if (!genhash (&pfs
->cns
, prefix
, n_clients
))
292 msg (D_PF_INFO
, "PF: %s rejected due to %d error(s)", prefix
, n_errors
);
303 ALLOC_OBJ_CLEAR (pfs
, struct pf_set
);
309 static struct pf_set
*
310 pf_init_from_file (const char *fn
)
312 struct buffer_list
*bl
= buffer_list_file (fn
, PF_MAX_LINE_LEN
);
315 struct pf_set
*pfs
= pf_init (bl
, fn
, true);
316 buffer_list_free (bl
);
321 msg (D_PF_INFO
|M_ERRNO
, "PF: %s: cannot open", fn
);
330 drop_accept (const bool accept
)
332 return accept
? "ACCEPT" : "DROP";
336 pct_name (const int type
)
350 pf_cn_test_print (const char *prefix
,
355 const struct pf_cn
*rule
)
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
));
366 dmsg (D_PF_DEBUG
, "PF: %s/%s/%s %s %s",
367 prefix
, prefix2
, pct_name (type
),
368 cn
, drop_accept (allow
));
373 pf_addr_test_print (const char *prefix
,
375 const struct context
*src
,
376 const struct mroute_addr
*dest
,
378 const struct ipv4_subnet
*rule
)
380 struct gc_arena gc
= gc_new ();
383 dmsg (D_PF_DEBUG
, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
386 tls_common_name (src
->c2
.tls_multi
, false),
387 mroute_addr_print_ex (dest
, MAPF_SHOW_ARP
, &gc
),
389 print_in_addr_t (rule
->network
, 0, &gc
),
390 print_in_addr_t (rule
->netmask
, 0, &gc
),
391 drop_accept (!rule
->exclude
));
395 dmsg (D_PF_DEBUG
, "PF: %s/%s %s %s %s",
398 tls_common_name (src
->c2
.tls_multi
, false),
399 mroute_addr_print_ex (dest
, MAPF_SHOW_ARP
, &gc
),
400 drop_accept (allow
));
407 static inline struct pf_cn
*
408 lookup_cn_rule (struct hash
*h
, const char *cn
, const uint32_t cn_hash
)
410 struct hash_element
*he
= hash_lookup_fast (h
, hash_bucket (h
, cn_hash
), cn
, cn_hash
);
412 return (struct pf_cn
*) he
->value
;
418 pf_cn_test (struct pf_set
*pfs
, const struct tls_multi
*tm
, const int type
, const char *prefix
)
420 if (pfs
&& !pfs
->kill
)
424 if (tls_common_name_hash (tm
, &cn
, &cn_hash
))
426 const struct pf_cn
*rule
= lookup_cn_rule (pfs
->cns
.hash_table
, cn
, cn_hash
);
430 if (check_debug_level (D_PF_DEBUG
))
431 pf_cn_test_print ("PF_CN_MATCH", type
, prefix
, cn
, !rule
->exclude
, rule
);
441 if (check_debug_level (D_PF_DEBUG
))
442 pf_cn_test_print ("PF_CN_DEFAULT", type
, prefix
, cn
, pfs
->cns
.default_allow
, NULL
);
444 if (pfs
->cns
.default_allow
)
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
);
459 pf_addr_test_dowork (const struct context
*src
, const struct mroute_addr
*dest
, const char *prefix
)
461 struct pf_set
*pfs
= src
->c2
.pf
.pfs
;
462 if (pfs
&& !pfs
->kill
)
464 const in_addr_t addr
= in_addr_t_from_mroute_addr (dest
);
465 const struct pf_subnet
*se
= pfs
->sns
.list
;
468 if ((addr
& se
->rule
.netmask
) == se
->rule
.network
)
471 if (check_debug_level (D_PF_DEBUG
))
472 pf_addr_test_print ("PF_ADDR_MATCH", prefix
, src
, dest
, !se
->rule
.exclude
, &se
->rule
);
474 return !se
->rule
.exclude
;
479 if (check_debug_level (D_PF_DEBUG
))
480 pf_addr_test_print ("PF_ADDR_DEFAULT", prefix
, src
, dest
, pfs
->sns
.default_allow
, NULL
);
482 return pfs
->sns
.default_allow
;
487 if (check_debug_level (D_PF_DEBUG
))
488 pf_addr_test_print ("PF_ADDR_FAULT", prefix
, src
, dest
, false, NULL
);
496 pf_check_reload (struct context
*c
)
498 const int slow_wakeup
= 15;
499 const int fast_wakeup
= 1;
500 const int wakeup_transition
= 60;
501 bool reloaded
= false;
505 && event_timeout_trigger (&c
->c2
.pf
.reload
, &c
->c2
.timeval
, ETT_DEFAULT
))
508 if (!platform_stat (c
->c2
.pf
.filename
, &s
))
510 if (s
.st_mtime
> c
->c2
.pf
.file_last_mod
)
512 struct pf_set
*pfs
= pf_init_from_file (c
->c2
.pf
.filename
);
516 pf_destroy (c
->c2
.pf
.pfs
);
519 if (pf_kill_test (pfs
))
521 c
->sig
->signal_received
= SIGTERM
;
522 c
->sig
->signal_text
= "pf-kill";
525 c
->c2
.pf
.file_last_mod
= s
.st_mtime
;
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
++;
538 if (reloaded
&& check_debug_level (D_PF_DEBUG
))
539 pf_context_print (&c
->c2
.pf
, "pf_check_reload", D_PF_DEBUG
);
546 pf_load_from_buffer_list (struct context
*c
, const struct buffer_list
*config
)
548 struct pf_set
*pfs
= pf_init (config
, "[SERVER-PF]", false);
552 pf_destroy (c
->c2
.pf
.pfs
);
562 pf_init_context (struct context
*c
)
564 struct gc_arena gc
= gc_new ();
566 if (plugin_defined (c
->plugins
, OPENVPN_PLUGIN_ENABLE_PF
))
568 const char *pf_file
= create_temp_file (c
->options
.tmp_dir
, "pf", &gc
);
570 setenv_str (c
->c2
.es
, "pf_file", pf_file
);
572 if (plugin_call (c
->plugins
, OPENVPN_PLUGIN_ENABLE_PF
, NULL
, NULL
, c
->c2
.es
) == OPENVPN_PLUGIN_FUNC_SUCCESS
)
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;
578 if (check_debug_level (D_PF_DEBUG
))
579 pf_context_print (&c
->c2
.pf
, "pf_init_context#1", D_PF_DEBUG
);
584 msg (M_WARN
, "WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled");
590 if (!c
->c2
.pf
.enabled
&& management_enable_pf (management
))
592 c
->c2
.pf
.enabled
= true;
594 if (check_debug_level (D_PF_DEBUG
))
595 pf_context_print (&c
->c2
.pf
, "pf_init_context#2", D_PF_DEBUG
);
603 pf_destroy_context (struct pf_context
*pfc
)
608 platform_unlink (pfc
->filename
);
612 pf_destroy (pfc
->pfs
);
618 pf_subnet_set_print (const struct pf_subnet_set
*s
, const int lev
)
620 struct gc_arena gc
= gc_new ();
625 msg (lev
, " ----- struct pf_subnet_set -----");
626 msg (lev
, " default_allow=%s", drop_accept (s
->default_allow
));
628 for (e
= s
->list
; e
!= NULL
; e
= e
->next
)
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
));
640 pf_cn_set_print (const struct pf_cn_set
*s
, const int lev
)
644 struct hash_iterator hi
;
645 struct hash_element
*he
;
647 msg (lev
, " ----- struct pf_cn_set -----");
648 msg (lev
, " default_allow=%s", drop_accept (s
->default_allow
));
652 hash_iterator_init (s
->hash_table
, &hi
);
653 while ((he
= hash_iterator_next (&hi
)))
655 struct pf_cn
*e
= (struct pf_cn
*)he
->value
;
658 drop_accept (!e
->exclude
));
661 msg (lev
, " ----------");
664 struct pf_cn_elem
*ce
;
665 for (ce
= s
->list
; ce
!= NULL
; ce
= ce
->next
)
667 struct pf_cn
*e
= lookup_cn_rule (s
->hash_table
, ce
->rule
.cn
, cn_hash_function (ce
->rule
.cn
, 0));
672 drop_accept (!e
->exclude
));
676 msg (lev
, " %s LOOKUP FAILED", ce
->rule
.cn
);
685 pf_set_print (const struct pf_set
*pfs
, const int lev
)
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
);
697 pf_context_print (const struct pf_context
*pfc
, const char *prefix
, const int lev
)
699 msg (lev
, "----- %s : struct pf_context -----", prefix
);
702 msg (lev
, "enabled=%d", pfc
->enabled
);
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
);
709 pf_set_print (pfc
->pfs
, lev
);
711 msg (lev
, "--------------------");