28 #elif defined(_MSC_VER) 34 #if defined(ENABLE_PF) 43 pf_destroy(
struct pf_set *pfs)
47 if (pfs->cns.hash_table)
53 struct pf_cn_elem *l = pfs->cns.list;
56 struct pf_cn_elem *next = l->next;
63 struct pf_subnet *l = pfs->sns.list;
66 struct pf_subnet *next = l->next;
76 add_client(
const char *line,
const char *prefix,
const int line_num,
struct pf_cn_elem ***next,
const bool exclude)
80 e->rule.exclude = exclude;
88 add_subnet(
const char *line,
const char *prefix,
const int line_num,
struct pf_subnet ***next,
const bool exclude)
90 struct in_addr network;
93 if (strcmp(line,
"unknown"))
96 char *div = strchr(line,
'/');
101 if (sscanf(div,
"%d", &netbits) != 1)
103 msg(
D_PF_INFO,
"PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div);
106 if (netbits < 0 || netbits > 32)
108 msg(
D_PF_INFO,
"PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div);
115 msg(
D_PF_INFO,
"PF: %s/%d: bad network address: '%s'", prefix, line_num, line);
119 if ((network.s_addr & htonl(netmask)) != network.s_addr)
121 network.s_addr &= htonl(netmask);
122 msg(
M_WARN,
"WARNING: PF: %s/%d: incorrect subnet %s/%d changed to %s/%d", prefix, line_num, line, netbits, inet_ntoa(network), netbits);
128 network.s_addr = htonl(0);
135 e->rule.exclude = exclude;
136 e->rule.network = ntohl(network.s_addr);
137 e->rule.netmask = netmask;
145 cn_hash_function(
const void *
key, uint32_t iv)
147 return hash_func((uint8_t *)key, strlen((
char *)key) + 1, iv);
151 cn_compare_function(
const void *key1,
const void *
key2)
153 return !strcmp((
const char *)key1, (
const char *)key2);
157 genhash(
struct pf_cn_set *cns,
const char *prefix,
const int n_clients)
159 struct pf_cn_elem *e;
161 int n_buckets = n_clients;
167 cns->hash_table =
hash_init(n_buckets, 0, cn_hash_function, cn_compare_function);
168 for (e = cns->list; e != NULL; e = e->next)
170 if (!
hash_add(cns->hash_table, e->rule.cn, &e->rule,
false))
172 msg(
D_PF_INFO,
"PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn);
180 static struct pf_set *
181 pf_init(
const struct buffer_list *bl,
const char *prefix,
const bool allow_kill)
184 #define MODE_CLIENTS 1 185 #define MODE_SUBNETS 2 186 int mode = MODE_UNDEF;
191 struct pf_set *pfs = NULL;
192 char line[PF_MAX_LINE_LEN];
197 struct pf_cn_elem **cl = &pfs->cns.list;
198 struct pf_subnet **sl = &pfs->sns.list;
201 for (be = bl->
head; be != NULL; be = be->
next)
206 if (line[0] ==
'\0' || line[0] ==
'#')
209 else if (line[0] ==
'+' || line[0] ==
'-')
211 bool exclude = (line[0] ==
'-');
215 msg(
D_PF_INFO,
"PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line);
218 else if (mode == MODE_CLIENTS)
220 if (add_client(&line[1], prefix, line_num, &cl, exclude))
229 else if (mode == MODE_SUBNETS)
231 if (add_subnet(&line[1], prefix, line_num, &sl, exclude))
240 else if (mode == MODE_UNDEF)
248 else if (line[0] ==
'[')
253 pfs->cns.default_allow =
true;
258 pfs->cns.default_allow =
false;
260 else if (!
strcasecmp(line,
"[subnets accept]"))
263 pfs->sns.default_allow =
true;
268 pfs->sns.default_allow =
false;
274 else if (allow_kill && !
strcasecmp(line,
"[kill]"))
281 msg(
D_PF_INFO,
"PF: %s/%d unknown tag: '%s'", prefix, line_num, line);
287 msg(
D_PF_INFO,
"PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line);
305 if (!genhash(&pfs->cns, prefix, n_clients))
312 msg(
D_PF_INFO,
"PF: %s rejected due to %d error(s)", prefix, n_errors);
330 static struct pf_set *
331 pf_init_from_file(
const char *fn)
336 struct pf_set *pfs = pf_init(bl, fn,
true);
351 drop_accept(
const bool accept)
353 return accept ?
"ACCEPT" :
"DROP";
357 pct_name(
const int type)
373 pf_cn_test_print(
const char *prefix,
378 const struct pf_cn *rule)
383 prefix, prefix2, pct_name(type),
384 cn, drop_accept(allow),
385 rule->cn, drop_accept(!rule->exclude));
390 prefix, prefix2, pct_name(type),
391 cn, drop_accept(allow));
396 pf_addr_test_print(
const char *prefix,
401 const struct ipv4_subnet *rule)
414 drop_accept(!rule->exclude));
430 static inline struct pf_cn *
431 lookup_cn_rule(
struct hash *h,
const char *cn,
const uint32_t cn_hash)
436 return (
struct pf_cn *) he->
value;
445 pf_cn_test(
struct pf_set *pfs,
const struct tls_multi *tm,
const int type,
const char *prefix)
447 if (pfs && !pfs->kill)
451 if (tls_common_name_hash(tm, &cn, &cn_hash))
453 const struct pf_cn *rule = lookup_cn_rule(pfs->cns.hash_table, cn, cn_hash);
459 pf_cn_test_print(
"PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule);
476 pf_cn_test_print(
"PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL);
479 if (pfs->cns.default_allow)
493 pf_cn_test_print(
"PF_CN_FAULT", type, prefix,
tls_common_name(tm,
false),
false, NULL);
500 pf_addr_test_dowork(
const struct context *src,
const struct mroute_addr *dest,
const char *prefix)
502 struct pf_set *pfs = src->
c2.pf.pfs;
503 if (pfs && !pfs->kill)
506 const struct pf_subnet *se = pfs->sns.list;
509 if ((addr & se->rule.netmask) == se->rule.network)
514 pf_addr_test_print(
"PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule);
517 return !se->rule.exclude;
524 pf_addr_test_print(
"PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL);
527 return pfs->sns.default_allow;
534 pf_addr_test_print(
"PF_ADDR_FAULT", prefix, src, dest,
false, NULL);
543 pf_check_reload(
struct context *c)
545 const int slow_wakeup = 15;
546 const int fast_wakeup = 1;
547 const int wakeup_transition = 60;
548 bool reloaded =
false;
550 if (c->
c2.pf.filename)
555 if (s.st_mtime > c->
c2.pf.file_last_mod)
557 struct pf_set *pfs = pf_init_from_file(c->
c2.pf.filename);
562 pf_destroy(c->
c2.pf.pfs);
566 if (pf_kill_test(pfs))
572 c->
c2.pf.file_last_mod = s.st_mtime;
576 int wakeup = slow_wakeup;
577 if (!c->
c2.pf.pfs && c->
c2.pf.n_check_reload < wakeup_transition)
579 wakeup = fast_wakeup;
583 c->
c2.pf.n_check_reload++;
589 pf_context_print(&c->
c2.pf,
"pf_check_reload",
D_PF_DEBUG);
599 struct pf_set *pfs = pf_init(config,
"[SERVER-PF]",
false);
604 pf_destroy(c->
c2.pf.pfs);
617 pf_init_context(
struct context *c)
624 if (c->
c2.pf.filename)
631 c->
c2.pf.enabled =
true;
635 pf_context_print(&c->
c2.pf,
"pf_init_context#1",
D_PF_DEBUG);
640 if (!c->
c2.pf.enabled)
652 msg(
M_FATAL,
"FATAL: failed to init PF plugin, must succeed.");
658 if (!c->
c2.pf.enabled && management_enable_pf(
management))
660 c->
c2.pf.enabled =
true;
664 pf_context_print(&c->
c2.pf,
"pf_init_context#2",
D_PF_DEBUG);
672 pf_destroy_context(
struct pf_context *pfc)
682 pf_destroy(pfc->pfs);
689 pf_subnet_set_print(
const struct pf_subnet_set *s,
const int lev)
696 msg(lev,
" ----- struct pf_subnet_set -----");
697 msg(lev,
" default_allow=%s", drop_accept(s->default_allow));
699 for (e = s->list; e != NULL; e = e->next)
701 msg(lev,
" %s/%s %s",
704 drop_accept(!e->rule.exclude));
711 pf_cn_set_print(
const struct pf_cn_set *s,
const int lev)
718 msg(lev,
" ----- struct pf_cn_set -----");
719 msg(lev,
" default_allow=%s", drop_accept(s->default_allow));
726 struct pf_cn *e = (
struct pf_cn *)he->
value;
729 drop_accept(!e->exclude));
732 msg(lev,
" ----------");
735 struct pf_cn_elem *ce;
736 for (ce = s->list; ce != NULL; ce = ce->next)
738 struct pf_cn *e = lookup_cn_rule(s->hash_table, ce->rule.cn, cn_hash_function(ce->rule.cn, 0));
743 drop_accept(!e->exclude));
747 msg(lev,
" %s LOOKUP FAILED", ce->rule.cn);
756 pf_set_print(
const struct pf_set *pfs,
const int lev)
760 msg(lev,
" ----- struct pf_set -----");
761 msg(lev,
" kill=%d", pfs->kill);
762 pf_subnet_set_print(&pfs->sns, lev);
763 pf_cn_set_print(&pfs->cns, lev);
768 pf_context_print(
const struct pf_context *pfc,
const char *prefix,
const int lev)
770 msg(lev,
"----- %s : struct pf_context -----", prefix);
773 msg(lev,
"enabled=%d", pfc->enabled);
775 msg(lev,
"filename='%s'",
np(pfc->filename));
776 msg(lev,
"file_last_mod=%u", (
unsigned int)pfc->file_last_mod);
777 msg(lev,
"n_check_reload=%u", pfc->n_check_reload);
778 msg(lev,
"reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (
unsigned int)pfc->reload.last);
780 pf_set_print(pfc->pfs, lev);
782 msg(lev,
"--------------------");
static void strncpynt(char *dest, const char *src, size_t maxlen)
struct options options
Options loaded from command line or configuration file.
char * string_alloc(const char *str, struct gc_arena *gc)
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
void hash_free(struct hash *hash)
Contains all state information for one tunnel.
struct buffer_entry * head
static void gc_free(struct gc_arena *a)
static int plugin_call(const struct plugin_list *pl, const int type, const struct argv *av, struct plugin_return *pr, struct env_set *es)
Security parameter state for a single VPN tunnel.
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
static in_addr_t netbits_to_netmask(const int netbits)
int openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr)
const char * mroute_addr_print_ex(const struct mroute_addr *ma, const unsigned int flags, struct gc_arena *gc)
void setenv_str(struct env_set *es, const char *name, const char *value)
struct signal_info * sig
Internal error signaling object.
#define OPENVPN_PLUGIN_ENABLE_PF
struct gc_arena gc
Garbage collection arena for allocations done in the level 2 scope of this context_2 structure...
static bool check_debug_level(unsigned int level)
#define OPENVPN_PLUGIN_FUNC_SUCCESS
struct hash * hash_init(const int n_buckets, const uint32_t iv, uint32_t(*hash_function)(const void *key, uint32_t iv), bool(*compare_function)(const void *key1, const void *key2))
bool hash_add(struct hash *hash, const void *key, void *value, bool replace)
static const char * np(const char *str)
void rm_trailing_chars(char *str, const char *what_to_delete)
static struct gc_arena gc_new(void)
#define ALLOC_OBJ_CLEAR(dptr, type)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
void hash_iterator_init(struct hash *hash, struct hash_iterator *hi)
void reset_coarse_timers(struct context *c)
struct context_2 c2
Level 2 context.
struct hash_element * hash_iterator_next(struct hash_iterator *hi)
Container for bidirectional cipher and HMAC key material.
static struct hash_bucket * hash_bucket(struct hash *hash, uint32_t hv)
struct buffer_entry * next
uint32_t hash_func(const uint8_t *k, uint32_t length, uint32_t initval)
volatile int signal_received
bool plugin_defined(const struct plugin_list *pl, const int type)
struct hash_element * hash_lookup_fast(struct hash *hash, struct hash_bucket *bucket, const void *key, uint32_t hv)
struct plugin_list * plugins
List of plug-ins.
const char * tls_common_name(const struct tls_multi *multi, const bool null)
Returns the common name field for the given tunnel.
static in_addr_t in_addr_t_from_mroute_addr(const struct mroute_addr *addr)
Garbage collection arena used to keep track of dynamically allocated memory.
static SERVICE_STATUS status
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
#define IPV4_NETMASK_HOST
static void event_timeout_init(struct event_timeout *et, interval_t n, const time_t local_now)
Container for unidirectional cipher and HMAC key material.