By default, OpenVPN 2.5 still allowed a server to enable compression by
pushing compression related options.
+PF (Packet Filtering) support has been removed
+ The built-in PF functionality has been removed from the code base. This
+ feature wasn't really easy to use and was long unmaintained.
+ This implies that also ``--management-client-pf`` and any other compile
+ time or run time related option do not exist any longer.
+
User-visible Changes
--------------------
[enable_iproute2="no"]
)
-AC_ARG_ENABLE(
- [pf],
- [AS_HELP_STRING([--disable-pf], [disable internal packet filter @<:@default=yes@:>@])],
- ,
- [enable_pf="yes"]
-)
-
AC_ARG_ENABLE(
[plugin-auth-pam],
[AS_HELP_STRING([--disable-plugin-auth-pam], [disable auth-pam plugin @<:@default=platform specific@:>@])],
test "${enable_small}" = "yes" && AC_DEFINE([ENABLE_SMALL], [1], [Enable smaller executable size])
test "${enable_fragment}" = "yes" && AC_DEFINE([ENABLE_FRAGMENT], [1], [Enable internal fragmentation support])
test "${enable_port_share}" = "yes" && AC_DEFINE([ENABLE_PORT_SHARE], [1], [Enable TCP Server port sharing])
-test "${enable_pf}" = "yes" && AC_DEFINE([ENABLE_PF], [1], [Enable internal packet filter])
test "${enable_strict_options}" = "yes" && AC_DEFINE([ENABLE_STRICT_OPTIONS_CHECK], [1], [Enable strict options check between peers])
test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes])
success/failure via :code:`auth_control_file` when using deferred auth
method and pending authentification via :code:`pending_auth_file`.
-
- * :code:`OPENVPN_PLUGIN_ENABLE_PF` plugin hook to pass filtering rules
- via ``pf_file``
-
--use-prediction-resistance
Enable prediction resistance on mbed TLS's RNG.
* New Client Connection:
*
* FUNC: openvpn_plugin_client_constructor_v1
- * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_ENABLE_PF
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_TLS_VERIFY (called once for every cert
* in the server chain)
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
*
* For each "TLS soft reset", according to reneg-sec option (or similar):
*
- * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_ENABLE_PF
- *
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_TLS_VERIFY (called once for every cert
* in the server chain)
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
#define OPENVPN_PLUGIN_LEARN_ADDRESS 8
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2 9
#define OPENVPN_PLUGIN_TLS_FINAL 10
-#define OPENVPN_PLUGIN_ENABLE_PF 11
+/*#define OPENVPN_PLUGIN_ENABLE_PF 11 *REMOVED FEATURE* */
#define OPENVPN_PLUGIN_ROUTE_PREDOWN 12
#define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER 13
#define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2 14
*
* OpenVPN will delete the auth_control_file after it goes out of scope.
*
- * If an OPENVPN_PLUGIN_ENABLE_PF handler is defined and returns success
- * for a particular client instance, packet filtering will be enabled for that
- * instance. OpenVPN will then attempt to read the packet filter configuration
- * from the temporary file named by the environmental variable pf_file. This
- * file may be generated asynchronously and may be dynamically updated during the
- * client session, however the client will be blocked from sending or receiving
- * VPN tunnel packets until the packet filter file has been generated. OpenVPN
- * will periodically test the packet filter file over the life of the client
- * instance and reload when modified. OpenVPN will delete the packet filter file
- * when the client instance goes out of scope.
- *
- * Packet filter file grammar:
- *
- * [CLIENTS DROP|ACCEPT]
- * {+|-}common_name1
- * {+|-}common_name2
- * . . .
- * [SUBNETS DROP|ACCEPT]
- * {+|-}subnet1
- * {+|-}subnet2
- * . . .
- * [END]
- *
- * Subnet: IP-ADDRESS | IP-ADDRESS/NUM_NETWORK_BITS
- *
- * CLIENTS refers to the set of clients (by their common-name) which
- * this instance is allowed ('+') to connect to, or is excluded ('-')
- * from connecting to. Note that in the case of client-to-client
- * connections, such communication must be allowed by the packet filter
- * configuration files of both clients.
- *
- * SUBNETS refers to IP addresses or IP address subnets which this
- * instance may connect to ('+') or is excluded ('-') from connecting
- * to.
- *
- * DROP or ACCEPT defines default policy when there is no explicit match
- * for a common-name or subnet. The [END] tag must exist. A special
- * purpose tag called [KILL] will immediately kill the client instance.
- * A given client or subnet rule applies to both incoming and outgoing
- * packets.
- *
* See plugin/defer/simple.c for an example on using asynchronous
- * authentication and client-specific packet filtering.
+ * authentication.
*/
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v2)
(openvpn_plugin_handle_t handle,
*
* OpenVPN will delete the auth_control_file after it goes out of scope.
*
- * If an OPENVPN_PLUGIN_ENABLE_PF handler is defined and returns success
- * for a particular client instance, packet filtering will be enabled for that
- * instance. OpenVPN will then attempt to read the packet filter configuration
- * from the temporary file named by the environmental variable pf_file. This
- * file may be generated asynchronously and may be dynamically updated during the
- * client session, however the client will be blocked from sending or receiving
- * VPN tunnel packets until the packet filter file has been generated. OpenVPN
- * will periodically test the packet filter file over the life of the client
- * instance and reload when modified. OpenVPN will delete the packet filter file
- * when the client instance goes out of scope.
- *
- * Packet filter file grammar:
- *
- * [CLIENTS DROP|ACCEPT]
- * {+|-}common_name1
- * {+|-}common_name2
- * . . .
- * [SUBNETS DROP|ACCEPT]
- * {+|-}subnet1
- * {+|-}subnet2
- * . . .
- * [END]
- *
- * Subnet: IP-ADDRESS | IP-ADDRESS/NUM_NETWORK_BITS
- *
- * CLIENTS refers to the set of clients (by their common-name) which
- * this instance is allowed ('+') to connect to, or is excluded ('-')
- * from connecting to. Note that in the case of client-to-client
- * connections, such communication must be allowed by the packet filter
- * configuration files of both clients.
- *
- * SUBNETS refers to IP addresses or IP address subnets which this
- * instance may connect to ('+') or is excluded ('-') from connecting
- * to.
- *
- * DROP or ACCEPT defines default policy when there is no explicit match
- * for a common-name or subnet. The [END] tag must exist. A special
- * purpose tag called [KILL] will immediately kill the client instance.
- * A given client or subnet rule applies to both incoming and outgoing
- * packets.
- *
* See sample/sample-plugins/defer/simple.c for an example on using
- * asynchronous authentication and client-specific packet filtering.
+ * asynchronous authentication.
*/
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v3)
(const int version,
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
- /* ENABLE_PF should only be called if we're actually willing to do PF */
- if (context->test_packet_filter)
- {
- ret->type_mask |= OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ENABLE_PF);
- }
-
ret->handle = (openvpn_plugin_handle_t *) context;
plugin_log(PLOG_NOTE, MODULE, "initialization succeeded");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
exit(0);
}
-static int
-tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
-{
- if (!context->test_packet_filter) /* no PF testing, nothing to do */
- {
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
-
- if (pcc->generated_pf_file) /* we already have created a file */
- {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
-
- const char *pff = get_env("pf_file", envp);
- const char *cn = get_env("username", envp);
- if (!pff || !cn) /* required vars missing */
- {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
-
- pcc->generated_pf_file = true;
-
- /* the PF API is, basically
- * - OpenVPN sends a filename (pf_file) to the plugin
- * - OpenVPN main loop will check every second if that file shows up
- * - when it does, it will be read & used for the pf config
- * the pre-created file needs to be removed in ...ENABLE_PF
- * to make deferred PF setup work
- *
- * the regular PF hook does not know the client username or CN, so
- * this is deferred to the TLS_FINAL hook which knows these things
- */
-
- /* do the double fork dance (see above for more verbose comments)
- */
- pid_t p1 = fork();
- if (p1 < 0) /* Fork failed */
- {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
- if (p1 > 0) /* parent process */
- {
- waitpid(p1, NULL, 0);
- return OPENVPN_PLUGIN_FUNC_SUCCESS; /* no _DEFERRED here! */
- }
-
- /* first gen child process, fork() again and exit() right away */
- pid_t p2 = fork();
- if (p2 < 0)
- {
- plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "BACKGROUND: fork(2) failed");
- exit(1);
- }
-
- if (p2 != 0) /* new parent: exit right away */
- {
- exit(0);
- }
-
- /* (grand-)child process
- * - never call "return" now (would mess up openvpn)
- * - return status is communicated by file
- * - then exit()
- */
-
- /* at this point, the plugin can take its time, because OpenVPN will
- * no longer block waiting for the call to finish
- *
- * in this example, we build a PF file by copying over a file
- * named "<username>.pf" to the OpenVPN-provided pf file name
- *
- * a real example could do a LDAP lookup, a REST call, ...
- */
- plugin_log(PLOG_NOTE, MODULE, "in async/deferred tls_final handler, sleep(%d)", context->test_packet_filter);
- sleep(context->test_packet_filter);
-
- char buf[256];
- snprintf(buf, sizeof(buf), "%s.pf", cn );
-
- /* there is a small race condition here - OpenVPN could detect our
- * file while we have only written half of it. So "perfect" code
- * needs to create this with a temp file name, and then rename() it
- * after it has been written. But I am lazy.
- */
-
- int w_fd = open( pff, O_WRONLY|O_CREAT, 0600 );
- if (w_fd < 0)
- {
- plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "can't write to '%s'", pff);
- exit(0);
- }
-
- int r_fd = open( buf, O_RDONLY );
- if (r_fd < 0)
- {
- plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "can't read '%s', creating empty pf file", buf);
- close(w_fd);
- exit(0);
- }
-
- char data[1024];
-
- int r;
- do
- {
- r = read(r_fd, data, sizeof(data));
- if (r < 0)
- {
- plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "error reading '%s'", buf);
- close(r_fd);
- close(w_fd);
- exit(0);
- }
- int w = write(w_fd, data, r);
- if (w < 0 || w != r)
- {
- plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "error writing %d bytes to '%s'", r, pff);
- close(r_fd);
- close(w_fd);
- exit(0);
- }
- }
- while(r > 0);
-
- plugin_log(PLOG_NOTE, MODULE, "copied PF config from '%s' to '%s', job done", buf, pff);
- exit(0);
-}
-
OPENVPN_EXPORT int
openvpn_plugin_func_v3(const int v3structver,
struct openvpn_plugin_args_func_in const *args,
case OPENVPN_PLUGIN_TLS_FINAL:
plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_TLS_FINAL");
- return tls_final(context, pcc, argv, envp);
-
- case OPENVPN_PLUGIN_ENABLE_PF:
- plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_ENABLE_PF");
-
- /* OpenVPN pre-creates the file, which gets in the way of
- * deferred pf setup - so remove it here, and re-create
- * it in the background handler (in tls_final()) when ready
- */
- const char *pff = get_env("pf_file", envp);
- if (pff)
- {
- (void) unlink(pff);
- }
- return OPENVPN_PLUGIN_FUNC_SUCCESS; /* must succeed */
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
default:
plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_?");
otime.c otime.h \
packet_id.c packet_id.h \
perf.c perf.h \
- pf.c pf.h \
ping.c ping.h \
plugin.c plugin.h \
pool.c pool.h \
#define D_ROUTE_QUOTA LOGLEV(3, 42, 0) /* show route quota exceeded messages */
#define D_OSBUF LOGLEV(3, 43, 0) /* show socket/tun/tap buffer sizes */
#define D_PS_PROXY LOGLEV(3, 44, 0) /* messages related to --port-share option */
-#define D_PF_INFO LOGLEV(3, 45, 0) /* packet filter informational messages */
#define D_IFCONFIG LOGLEV(3, 0, 0) /* show ifconfig info (don't mute) */
#define D_SHOW_PARMS LOGLEV(4, 50, 0) /* show all parameters on program initiation */
#define D_DHCP_OPT LOGLEV(4, 53, 0) /* show DHCP options binary string */
#define D_MBUF LOGLEV(4, 54, 0) /* mbuf.[ch] routines */
#define D_PACKET_TRUNC_ERR LOGLEV(4, 55, 0) /* PACKET_TRUNCATION_CHECK */
-#define D_PF_DROPPED LOGLEV(4, 56, 0) /* packet filter dropped a packet */
#define D_MULTI_DROPPED LOGLEV(4, 57, 0) /* show point-to-multipoint packet drops */
#define D_MULTI_MEDIUM LOGLEV(4, 58, 0) /* show medium frequency multi messages */
#define D_X509_ATTR LOGLEV(4, 59, 0) /* show x509-track attributes on connection */
#define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_parse_cmd */
#define D_CRYPTO_DEBUG LOGLEV(7, 70, M_DEBUG) /* show detailed info from crypto.c routines */
#define D_PID_DEBUG LOGLEV(7, 70, M_DEBUG) /* show packet-id debugging info */
-#define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */
-#define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */
#define D_PUSH_DEBUG LOGLEV(7, 73, M_DEBUG) /* show push/pull debugging info */
#define D_VLAN_DEBUG LOGLEV(7, 74, M_DEBUG) /* show VLAN tagging/untagging debug info */
#include "mss.h"
#include "event.h"
#include "occ.h"
-#include "pf.h"
#include "ping.h"
#include "ps.h"
#include "dhcp.h"
check_push_request(c);
}
-#ifdef PLUGIN_PF
- if (c->c2.pf.enabled
- && event_timeout_trigger(&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT))
- {
- pf_check_reload(c);
- }
-#endif
-
/* process --route options */
if (event_timeout_trigger(&c->c2.route_wakeup, &c->c2.timeval, ETT_DEFAULT))
{
}
#endif
-#ifdef ENABLE_PF
- if (child)
- {
- pf_init_context(c);
- }
-#endif
-
/* Check for signals */
if (IS_SIG(c))
{
}
#endif
-#ifdef ENABLE_PF
- pf_destroy_context(&c->c2.pf);
-#endif
-
#ifdef ENABLE_PLUGIN
/* call plugin close functions and unload */
do_close_plugins(c);
msg(M_CLIENT, " to the client and wait for a final client-auth/client-deny");
msg(M_CLIENT, "client-kill CID [M] : Kill client instance CID with message M (def=RESTART)");
msg(M_CLIENT, "env-filter [level] : Set env-var filter level");
-#ifdef MANAGEMENT_PF
- msg(M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
-#endif
msg(M_CLIENT, "rsa-sig : Enter a signature in response to >RSA_SIGN challenge");
msg(M_CLIENT, " Enter signature base64 on subsequent lines followed by END");
msg(M_CLIENT, "pk-sig : Enter a signature in response to >PK_SIGN challenge");
}
break;
-#ifdef MANAGEMENT_PF
- case IEC_CLIENT_PF:
- if (man->persist.callback.client_pf)
- {
- const bool status = (*man->persist.callback.client_pf)
- (man->persist.callback.arg,
- man->connection.in_extra_cid,
- man->connection.in_extra);
- man->connection.in_extra = NULL;
- if (status)
- {
- msg(M_CLIENT, "SUCCESS: client-pf command succeeded");
- }
- else
- {
- msg(M_CLIENT, "ERROR: client-pf command failed");
- }
- }
- else
- {
- msg(M_CLIENT, "ERROR: The client-pf command is not supported by the current daemon mode");
- }
- break;
-
-#endif /* ifdef MANAGEMENT_PF */
case IEC_PK_SIGN:
man->connection.ext_key_state = EKS_READY;
buffer_list_free(man->connection.ext_key_input);
msg(M_CLIENT, "SUCCESS: env_filter_level=%d", level);
}
-#ifdef MANAGEMENT_PF
-
-static void
-man_client_pf(struct management *man, const char *cid_str)
-{
- struct man_connection *mc = &man->connection;
- mc->in_extra_cid = 0;
- mc->in_extra_kid = 0;
- if (parse_cid(cid_str, &mc->in_extra_cid))
- {
- mc->in_extra_cmd = IEC_CLIENT_PF;
- in_extra_reset(mc, IER_NEW);
- }
-}
-
-#endif /* MANAGEMENT_PF */
static void
man_pk_sig(struct management *man, const char *cmd_name)
man_client_pending_auth(man, p[1], p[2], p[3]);
}
}
-#ifdef MANAGEMENT_PF
- else if (streq(p[0], "client-pf"))
- {
- if (man_need(man, p, 1, 0))
- {
- man_client_pf(man, p[1]);
- }
- }
-#endif
else if (streq(p[0], "rsa-sig"))
{
man_pk_sig(man, "rsa-sig");
const char *extra,
unsigned int timeout);
char *(*get_peer_info) (void *arg, const unsigned long cid);
-#ifdef MANAGEMENT_PF
- bool (*client_pf)(void *arg,
- const unsigned long cid,
- struct buffer_list *pf_config); /* ownership transferred */
-#endif
bool (*proxy_cmd)(void *arg, const char **p);
bool (*remote_cmd) (void *arg, const char **p);
#ifdef TARGET_ANDROID
#define IEC_UNDEF 0
#define IEC_CLIENT_AUTH 1
-#define IEC_CLIENT_PF 2
+/* #define IEC_CLIENT_PF 2 *REMOVED FEATURE* */
#define IEC_RSA_SIGN 3
#define IEC_CERTIFICATE 4
#define IEC_PK_SIGN 5
#define MF_FORGET_DISCONNECT (1<<4)
#define MF_CONNECT_AS_CLIENT (1<<5)
#define MF_CLIENT_AUTH (1<<6)
-#ifdef MANAGEMENT_PF
-#define MF_CLIENT_PF (1<<7)
-#endif
+/* #define MF_CLIENT_PF (1<<7) *REMOVED FEATURE* */
#define MF_UNIX_SOCK (1<<8)
#define MF_EXTERNAL_KEY (1<<9)
#define MF_EXTERNAL_KEY_NOPADDING (1<<10)
return BOOL_CAST(man->settings.flags & MF_QUERY_PROXY);
}
-#ifdef MANAGEMENT_PF
-static inline bool
-management_enable_pf(const struct management *man)
-{
- return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF);
-}
-#endif
static inline bool
management_enable_def_auth(const struct management *man)
return (addr.s6_addr[0] == 0xff);
}
-#ifdef ENABLE_PF
-
-static unsigned int
-mroute_extract_addr_arp(struct mroute_addr *src,
- struct mroute_addr *dest,
- const struct buffer *buf)
-{
- unsigned int ret = 0;
- if (BLEN(buf) >= (int) sizeof(struct openvpn_arp))
- {
- const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR(buf);
- if (arp->mac_addr_type == htons(0x0001)
- && arp->proto_addr_type == htons(0x0800)
- && arp->mac_addr_size == 0x06
- && arp->proto_addr_size == 0x04)
- {
- mroute_get_in_addr_t(src, arp->ip_src, MR_ARP);
- mroute_get_in_addr_t(dest, arp->ip_dest, MR_ARP);
-
- /* multicast packet? */
- if (mroute_is_mcast(arp->ip_dest))
- {
- ret |= MROUTE_EXTRACT_MCAST;
- }
-
- ret |= MROUTE_EXTRACT_SUCCEEDED;
- }
- }
- return ret;
-}
-
-#endif /* ifdef ENABLE_PF */
unsigned int
mroute_extract_addr_ip(struct mroute_addr *src, struct mroute_addr *dest,
unsigned int
mroute_extract_addr_ether(struct mroute_addr *src,
struct mroute_addr *dest,
- struct mroute_addr *esrc,
- struct mroute_addr *edest,
uint16_t vid,
const struct buffer *buf)
{
ret |= MROUTE_EXTRACT_SUCCEEDED;
-#ifdef ENABLE_PF
- if (esrc || edest)
- {
- struct buffer b = *buf;
- if (!buf_advance(&b, sizeof(struct openvpn_ethhdr)))
- {
- return 0;
- }
-
- uint16_t proto = eth->proto;
- if (proto == htons(OPENVPN_ETH_P_8021Q))
- {
- if (!buf_advance(&b, SIZE_ETH_TO_8021Q_HDR))
- {
- /* It's an 802.1Q packet, but doesn't have a full header,
- * so something went wrong */
- return 0;
- }
-
- const struct openvpn_8021qhdr *tag;
- tag = (const struct openvpn_8021qhdr *)BPTR(buf);
- proto = tag->proto;
- }
-
- switch (ntohs(proto))
- {
- case OPENVPN_ETH_P_IPV4:
- ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT);
- break;
-
- case OPENVPN_ETH_P_ARP:
- ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT);
- break;
- }
- }
-#endif /* ifdef ENABLE_PF */
}
return ret;
}
unsigned int mroute_extract_addr_ether(struct mroute_addr *src,
struct mroute_addr *dest,
- struct mroute_addr *esrc,
- struct mroute_addr *edest,
uint16_t vid,
const struct buffer *buf);
static inline unsigned int
mroute_extract_addr_from_packet(struct mroute_addr *src,
struct mroute_addr *dest,
- struct mroute_addr *esrc,
- struct mroute_addr *edest,
uint16_t vid,
const struct buffer *buf,
int tunnel_type)
}
else if (tunnel_type == DEV_TYPE_TAP)
{
- ret = mroute_extract_addr_ether(src, dest, esrc, edest, vid, buf);
+ ret = mroute_extract_addr_ether(src, dest, vid, buf);
}
return ret;
}
#include "push.h"
#include "run_command.h"
#include "otime.h"
-#include "pf.h"
#include "gremlin.h"
#include "mstats.h"
#include "ssl_verify.h"
set_prefix(mi);
}
-static const char *
-mi_prefix(const struct multi_instance *mi)
-{
- if (mi && mi->msg_prefix[0])
- {
- return mi->msg_prefix;
- }
- else
- {
- return "UNDEF_I";
- }
-}
-
/*
* Tell the route helper about deleted iroutes so
* that it can update its mask of currently used
mi = (struct multi_instance *) he->value;
if (mi != sender_instance && !mi->halt)
{
-#ifdef ENABLE_PF
- if (sender_instance)
- {
- if (!pf_c2c_test(&sender_instance->context.c2.pf,
- sender_instance->context.c2.tls_multi,
- &mi->context.c2.pf,
- mi->context.c2.tls_multi,
- "bcast_c2c"))
- {
- msg(D_PF_DROPPED_BCAST, "PF: client[%s] -> client[%s] packet dropped by BCAST packet filter",
- mi_prefix(sender_instance),
- mi_prefix(mi));
- continue;
- }
- }
- if (sender_addr)
- {
- if (!pf_addr_test(&mi->context.c2.pf, &mi->context,
- sender_addr, "bcast_src_addr"))
- {
- struct gc_arena gc = gc_new();
- msg(D_PF_DROPPED_BCAST, "PF: addr[%s] -> client[%s] packet dropped by BCAST packet filter",
- mroute_addr_print_ex(sender_addr, MAPF_SHOW_ARP, &gc),
- mi_prefix(mi));
- gc_free(&gc);
- continue;
- }
- }
-#endif /* ifdef ENABLE_PF */
if (vid != 0 && vid != mi->context.options.vlan_pvid)
{
continue;
/* extract packet source and dest addresses */
mroute_flags = mroute_extract_addr_from_packet(&src,
&dest,
- NULL,
- NULL,
0,
&c->c2.to_tun,
DEV_TYPE_TUN);
/* if dest addr is a known client, route to it */
if (mi)
{
-#ifdef ENABLE_PF
- if (!pf_c2c_test(&c->c2.pf, c->c2.tls_multi,
- &mi->context.c2.pf,
- mi->context.c2.tls_multi,
- "tun_c2c"))
- {
- msg(D_PF_DROPPED, "PF: client -> client[%s] packet dropped by TUN packet filter",
- mi_prefix(mi));
- }
- else
-#endif
{
multi_unicast(m, &c->c2.to_tun, mi);
register_activity(c, BLEN(&c->c2.to_tun));
}
}
}
-#ifdef ENABLE_PF
- if (c->c2.to_tun.len && !pf_addr_test(&c->c2.pf, c, &dest,
- "tun_dest_addr"))
- {
- msg(D_PF_DROPPED, "PF: client -> addr[%s] packet dropped by TUN packet filter",
- mroute_addr_print_ex(&dest, MAPF_SHOW_ARP, &gc));
- c->c2.to_tun.len = 0;
- }
-#endif
}
else if (TUNNEL_TYPE(m->top.c1.tuntap) == DEV_TYPE_TAP)
{
uint16_t vid = 0;
-#ifdef ENABLE_PF
- struct mroute_addr edest;
- mroute_addr_reset(&edest);
-#endif
if (m->top.options.vlan_tagging)
{
/* extract packet source and dest addresses */
mroute_flags = mroute_extract_addr_from_packet(&src,
&dest,
- NULL,
-#ifdef ENABLE_PF
- &edest,
-#else
- NULL,
-#endif
vid,
&c->c2.to_tun,
DEV_TYPE_TAP);
/* if dest addr is a known client, route to it */
if (mi)
{
-#ifdef ENABLE_PF
- if (!pf_c2c_test(&c->c2.pf, c->c2.tls_multi,
- &mi->context.c2.pf,
- mi->context.c2.tls_multi,
- "tap_c2c"))
- {
- msg(D_PF_DROPPED, "PF: client -> client[%s] packet dropped by TAP packet filter",
- mi_prefix(mi));
- }
- else
-#endif
{
multi_unicast(m, &c->c2.to_tun, mi);
register_activity(c, BLEN(&c->c2.to_tun));
}
}
}
-#ifdef ENABLE_PF
- if (c->c2.to_tun.len && !pf_addr_test(&c->c2.pf, c,
- &edest,
- "tap_dest_addr"))
- {
- msg(D_PF_DROPPED, "PF: client -> addr[%s] packet dropped by TAP packet filter",
- mroute_addr_print_ex(&edest, MAPF_SHOW_ARP, &gc));
- c->c2.to_tun.len = 0;
- }
-#endif
}
else
{
const int dev_type = TUNNEL_TYPE(m->top.c1.tuntap);
int16_t vid = 0;
-#ifdef ENABLE_PF
- struct mroute_addr esrc, *e1, *e2;
- if (dev_type == DEV_TYPE_TUN)
- {
- e1 = NULL;
- e2 = &src;
- }
- else
- {
- e1 = e2 = &esrc;
- mroute_addr_reset(&esrc);
- }
-#endif
#ifdef MULTI_DEBUG_EVENT_LOOP
printf("TUN -> TCP/UDP [%d]\n", BLEN(&m->top.c2.buf));
mroute_flags = mroute_extract_addr_from_packet(&src,
&dest,
-#ifdef ENABLE_PF
- e1,
-#else
- NULL,
-#endif
- NULL,
vid,
&m->top.c2.buf,
dev_type);
if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))
{
/* for now, treat multicast as broadcast */
-#ifdef ENABLE_PF
- multi_bcast(m, &m->top.c2.buf, NULL, e2, vid);
-#else
multi_bcast(m, &m->top.c2.buf, NULL, NULL, vid);
-#endif
}
else
{
set_prefix(m->pending);
-#ifdef ENABLE_PF
- if (!pf_addr_test(&c->c2.pf, c, e2, "tun_tap_src_addr"))
- {
- msg(D_PF_DROPPED, "PF: addr[%s] -> client packet dropped by packet filter",
- mroute_addr_print_ex(&src, MAPF_SHOW_ARP, &gc));
- buf_reset_len(&c->c2.buf);
- }
- else
-#endif
{
if (multi_output_queue_ready(m, m->pending))
{
#endif /* ifdef ENABLE_MANAGEMENT */
-#ifdef MANAGEMENT_PF
-static bool
-management_client_pf(void *arg,
- const unsigned long cid,
- struct buffer_list *pf_config) /* ownership transferred */
-{
- struct multi_context *m = (struct multi_context *) arg;
- struct multi_instance *mi = lookup_by_cid(m, cid);
- bool ret = false;
-
- if (mi && pf_config)
- {
- ret = pf_load_from_buffer_list(&mi->context, pf_config);
- }
-
- buffer_list_free(pf_config);
- return ret;
-}
-#endif /* ifdef MANAGEMENT_PF */
void
init_management_callback_multi(struct multi_context *m)
cb.client_auth = management_client_auth;
cb.client_pending_auth = management_client_pending_auth;
cb.get_peer_info = management_get_peer_info;
-#ifdef MANAGEMENT_PF
- cb.client_pf = management_client_pf;
-#endif
management_set_callback(management, &cb);
}
#endif /* ifdef ENABLE_MANAGEMENT */
#include "sig.h"
#include "misc.h"
#include "mbuf.h"
-#include "pf.h"
#include "pool.h"
#include "plugin.h"
#include "manage.h"
int scheduled_exit_signal;
/* packet filter */
-#ifdef ENABLE_PF
- struct pf_context pf;
-#endif
#ifdef ENABLE_MANAGEMENT
struct man_def_auth_context mda_context;
<ClCompile Include="otime.c" />
<ClCompile Include="packet_id.c" />
<ClCompile Include="perf.c" />
- <ClCompile Include="pf.c" />
<ClCompile Include="ping.c" />
<ClCompile Include="pkcs11.c" />
<ClCompile Include="pkcs11_openssl.c" />
<ClInclude Include="otime.h" />
<ClInclude Include="packet_id.h" />
<ClInclude Include="perf.h" />
- <ClInclude Include="pf.h" />
<ClInclude Include="ping.h" />
<ClInclude Include="pkcs11.h" />
<ClInclude Include="pkcs11_backend.h" />
<ClCompile Include="perf.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="pf.c">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="ping.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="perf.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="pf.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="ping.h">
<Filter>Header Files</Filter>
</ClInclude>
"--management-client-auth : gives management interface client the responsibility\n"
" to authenticate clients after their client certificate\n"
" has been verified.\n"
-#ifdef MANAGEMENT_PF
- "--management-client-pf : management interface clients must specify a packet\n"
- " filter file for each connecting client.\n"
-#endif
#endif /* ifdef ENABLE_MANAGEMENT */
#ifdef ENABLE_PLUGIN
"--plugin m [str]: Load plug-in module m passing str as an argument\n"
options->management_flags |= MF_CLIENT_AUTH;
}
#endif /* ifdef ENABLE_MANAGEMENT */
-#ifdef MANAGEMENT_PF
- else if (streq(p[0], "management-client-pf") && !p[1])
- {
- VERIFY_PERMISSION(OPT_P_GENERAL);
- options->management_flags |= (MF_CLIENT_PF | MF_CLIENT_AUTH);
- }
-#endif
else if (streq(p[0], "management-log-cache") && p[1] && !p[2])
{
int cache;
+++ /dev/null
-/*
- * OpenVPN -- An application to securely tunnel IP networks
- * over a single TCP/UDP port, with support for SSL/TLS-based
- * session authentication and key exchange,
- * packet encryption, packet authentication, and
- * packet compression.
- *
- * Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* packet filter functions */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#elif defined(_MSC_VER)
-#include "config-msvc.h"
-#endif
-
-#include "syshead.h"
-
-#if defined(ENABLE_PF)
-
-#include "init.h"
-#include "memdbg.h"
-#include "pf.h"
-#include "ssl_verify.h"
-
-
-static void
-pf_destroy(struct pf_set *pfs)
-{
- if (pfs)
- {
- if (pfs->cns.hash_table)
- {
- hash_free(pfs->cns.hash_table);
- }
-
- {
- struct pf_cn_elem *l = pfs->cns.list;
- while (l)
- {
- struct pf_cn_elem *next = l->next;
- free(l->rule.cn);
- free(l);
- l = next;
- }
- }
- {
- struct pf_subnet *l = pfs->sns.list;
- while (l)
- {
- struct pf_subnet *next = l->next;
- free(l);
- l = next;
- }
- }
- free(pfs);
- }
-}
-
-static bool
-add_client(const char *line, const char *prefix, const int line_num, struct pf_cn_elem ***next, const bool exclude)
-{
- struct pf_cn_elem *e;
- ALLOC_OBJ_CLEAR(e, struct pf_cn_elem);
- e->rule.exclude = exclude;
- e->rule.cn = string_alloc(line, NULL);
- **next = e;
- *next = &e->next;
- return true;
-}
-
-static bool
-add_subnet(const char *line, const char *prefix, const int line_num, struct pf_subnet ***next, const bool exclude)
-{
- struct in_addr network;
- in_addr_t netmask = 0;
-
- if (strcmp(line, "unknown"))
- {
- int netbits = 32;
- char *div = strchr(line, '/');
-
- if (div)
- {
- *div++ = '\0';
- if (sscanf(div, "%d", &netbits) != 1)
- {
- msg(D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div);
- return false;
- }
- if (netbits < 0 || netbits > 32)
- {
- msg(D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div);
- return false;
- }
- }
-
- if (openvpn_inet_aton(line, &network) != OIA_IP)
- {
- msg(D_PF_INFO, "PF: %s/%d: bad network address: '%s'", prefix, line_num, line);
- return false;
- }
- netmask = netbits_to_netmask(netbits);
- if ((network.s_addr & htonl(netmask)) != network.s_addr)
- {
- network.s_addr &= htonl(netmask);
- msg(M_WARN, "WARNING: PF: %s/%d: incorrect subnet %s/%d changed to %s/%d", prefix, line_num, line, netbits, inet_ntoa(network), netbits);
- }
- }
- else
- {
- /* match special "unknown" tag for addresses unrecognized by mroute */
- network.s_addr = htonl(0);
- netmask = IPV4_NETMASK_HOST;
- }
-
- {
- struct pf_subnet *e;
- ALLOC_OBJ_CLEAR(e, struct pf_subnet);
- e->rule.exclude = exclude;
- e->rule.network = ntohl(network.s_addr);
- e->rule.netmask = netmask;
- **next = e;
- *next = &e->next;
- return true;
- }
-}
-
-static uint32_t
-cn_hash_function(const void *key, uint32_t iv)
-{
- return hash_func((uint8_t *)key, strlen((char *)key) + 1, iv);
-}
-
-static bool
-cn_compare_function(const void *key1, const void *key2)
-{
- return !strcmp((const char *)key1, (const char *)key2);
-}
-
-static bool
-genhash(struct pf_cn_set *cns, const char *prefix, const int n_clients)
-{
- struct pf_cn_elem *e;
- bool status = true;
- int n_buckets = n_clients;
-
- if (n_buckets < 16)
- {
- n_buckets = 16;
- }
- cns->hash_table = hash_init(n_buckets, 0, cn_hash_function, cn_compare_function);
- for (e = cns->list; e != NULL; e = e->next)
- {
- if (!hash_add(cns->hash_table, e->rule.cn, &e->rule, false))
- {
- msg(D_PF_INFO, "PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn);
- status = false;
- }
- }
-
- return status;
-}
-
-static struct pf_set *
-pf_init(const struct buffer_list *bl, const char *prefix, const bool allow_kill)
-{
-#define MODE_UNDEF 0
-#define MODE_CLIENTS 1
-#define MODE_SUBNETS 2
- int mode = MODE_UNDEF;
- int line_num = 0;
- int n_clients = 0;
- int n_subnets = 0;
- int n_errors = 0;
- struct pf_set *pfs = NULL;
- char line[PF_MAX_LINE_LEN];
-
- ALLOC_OBJ_CLEAR(pfs, struct pf_set);
- if (bl)
- {
- struct pf_cn_elem **cl = &pfs->cns.list;
- struct pf_subnet **sl = &pfs->sns.list;
- struct buffer_entry *be;
-
- for (be = bl->head; be != NULL; be = be->next)
- {
- ++line_num;
- strncpynt(line, BSTR(&be->buf), sizeof(line));
- rm_trailing_chars(line, "\r\n\t ");
- if (line[0] == '\0' || line[0] == '#')
- {
- }
- else if (line[0] == '+' || line[0] == '-')
- {
- bool exclude = (line[0] == '-');
-
- if (line[1] =='\0')
- {
- msg(D_PF_INFO, "PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line);
- ++n_errors;
- }
- else if (mode == MODE_CLIENTS)
- {
- if (add_client(&line[1], prefix, line_num, &cl, exclude))
- {
- ++n_clients;
- }
- else
- {
- ++n_errors;
- }
- }
- else if (mode == MODE_SUBNETS)
- {
- if (add_subnet(&line[1], prefix, line_num, &sl, exclude))
- {
- ++n_subnets;
- }
- else
- {
- ++n_errors;
- }
- }
- else if (mode == MODE_UNDEF)
- {
- }
- else
- {
- ASSERT(0);
- }
- }
- else if (line[0] == '[')
- {
- if (!strcasecmp(line, "[clients accept]"))
- {
- mode = MODE_CLIENTS;
- pfs->cns.default_allow = true;
- }
- else if (!strcasecmp(line, "[clients drop]"))
- {
- mode = MODE_CLIENTS;
- pfs->cns.default_allow = false;
- }
- else if (!strcasecmp(line, "[subnets accept]"))
- {
- mode = MODE_SUBNETS;
- pfs->sns.default_allow = true;
- }
- else if (!strcasecmp(line, "[subnets drop]"))
- {
- mode = MODE_SUBNETS;
- pfs->sns.default_allow = false;
- }
- else if (!strcasecmp(line, "[end]"))
- {
- goto done;
- }
- else if (allow_kill && !strcasecmp(line, "[kill]"))
- {
- goto kill;
- }
- else
- {
- mode = MODE_UNDEF;
- msg(D_PF_INFO, "PF: %s/%d unknown tag: '%s'", prefix, line_num, line);
- ++n_errors;
- }
- }
- else
- {
- msg(D_PF_INFO, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line);
- ++n_errors;
- }
- }
- ++n_errors;
- msg(D_PF_INFO, "PF: %s: missing [end]", prefix);
- }
- else
- {
- msg(D_PF_INFO, "PF: %s: cannot open", prefix);
- ++n_errors;
- }
-
-done:
- if (bl)
- {
- if (!n_errors)
- {
- if (!genhash(&pfs->cns, prefix, n_clients))
- {
- ++n_errors;
- }
- }
- if (n_errors)
- {
- msg(D_PF_INFO, "PF: %s rejected due to %d error(s)", prefix, n_errors);
- }
- }
- if (n_errors)
- {
- pf_destroy(pfs);
- pfs = NULL;
- }
- return pfs;
-
-kill:
- pf_destroy(pfs);
- ALLOC_OBJ_CLEAR(pfs, struct pf_set);
- pfs->kill = true;
- return pfs;
-}
-
-#ifdef PLUGIN_PF
-static struct pf_set *
-pf_init_from_file(const char *fn)
-{
- struct buffer_list *bl = buffer_list_file(fn, PF_MAX_LINE_LEN);
- if (bl)
- {
- struct pf_set *pfs = pf_init(bl, fn, true);
- buffer_list_free(bl);
- return pfs;
- }
- else
- {
- msg(D_PF_INFO|M_ERRNO, "PF: %s: cannot open", fn);
- return NULL;
- }
-}
-#endif
-
-#ifdef ENABLE_DEBUG
-
-static const char *
-drop_accept(const bool accept)
-{
- return accept ? "ACCEPT" : "DROP";
-}
-
-static const char *
-pct_name(const int type)
-{
- switch (type)
- {
- case PCT_SRC:
- return "SRC";
-
- case PCT_DEST:
- return "DEST";
-
- default:
- return "???";
- }
-}
-
-static void
-pf_cn_test_print(const char *prefix,
- const int type,
- const char *prefix2,
- const char *cn,
- const bool allow,
- const struct pf_cn *rule)
-{
- if (rule)
- {
- dmsg(D_PF_DEBUG, "PF: %s/%s/%s %s %s rule=[%s %s]",
- prefix, prefix2, pct_name(type),
- cn, drop_accept(allow),
- rule->cn, drop_accept(!rule->exclude));
- }
- else
- {
- dmsg(D_PF_DEBUG, "PF: %s/%s/%s %s %s",
- prefix, prefix2, pct_name(type),
- cn, drop_accept(allow));
- }
-}
-
-static void
-pf_addr_test_print(const char *prefix,
- const char *prefix2,
- const struct context *src,
- const struct mroute_addr *dest,
- const bool allow,
- const struct ipv4_subnet *rule)
-{
- struct gc_arena gc = gc_new();
- if (rule)
- {
- dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
- prefix,
- prefix2,
- tls_common_name(src->c2.tls_multi, false),
- mroute_addr_print_ex(dest, MAPF_SHOW_ARP, &gc),
- drop_accept(allow),
- print_in_addr_t(rule->network, 0, &gc),
- print_in_addr_t(rule->netmask, 0, &gc),
- drop_accept(!rule->exclude));
- }
- else
- {
- dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s",
- prefix,
- prefix2,
- tls_common_name(src->c2.tls_multi, false),
- mroute_addr_print_ex(dest, MAPF_SHOW_ARP, &gc),
- drop_accept(allow));
- }
- gc_free(&gc);
-}
-
-#endif /* ifdef ENABLE_DEBUG */
-
-static inline struct pf_cn *
-lookup_cn_rule(struct hash *h, const char *cn, const uint32_t cn_hash)
-{
- struct hash_element *he = hash_lookup_fast(h, hash_bucket(h, cn_hash), cn, cn_hash);
- if (he)
- {
- return (struct pf_cn *) he->value;
- }
- else
- {
- return NULL;
- }
-}
-
-bool
-pf_cn_test(struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix)
-{
- if (pfs && !pfs->kill)
- {
- const char *cn;
- uint32_t cn_hash;
- if (tls_common_name_hash(tm, &cn, &cn_hash))
- {
- const struct pf_cn *rule = lookup_cn_rule(pfs->cns.hash_table, cn, cn_hash);
- if (rule)
- {
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_cn_test_print("PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule);
- }
-#endif
- if (!rule->exclude)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_cn_test_print("PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL);
- }
-#endif
- if (pfs->cns.default_allow)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- }
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_cn_test_print("PF_CN_FAULT", type, prefix, tls_common_name(tm, false), false, NULL);
- }
-#endif
- return false;
-}
-
-bool
-pf_addr_test_dowork(const struct context *src, const struct mroute_addr *dest, const char *prefix)
-{
- struct pf_set *pfs = src->c2.pf.pfs;
- if (pfs && !pfs->kill)
- {
- const in_addr_t addr = in_addr_t_from_mroute_addr(dest);
- const struct pf_subnet *se = pfs->sns.list;
- while (se)
- {
- if ((addr & se->rule.netmask) == se->rule.network)
- {
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_addr_test_print("PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule);
- }
-#endif
- return !se->rule.exclude;
- }
- se = se->next;
- }
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_addr_test_print("PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL);
- }
-#endif
- return pfs->sns.default_allow;
- }
- else
- {
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_addr_test_print("PF_ADDR_FAULT", prefix, src, dest, false, NULL);
- }
-#endif
- return false;
- }
-}
-
-#ifdef PLUGIN_PF
-void
-pf_check_reload(struct context *c)
-{
- const int slow_wakeup = 15;
- const int fast_wakeup = 1;
- const int wakeup_transition = 60;
- bool reloaded = false;
-
- if (c->c2.pf.filename)
- {
- platform_stat_t s;
- if (!platform_stat(c->c2.pf.filename, &s))
- {
- if (s.st_mtime > c->c2.pf.file_last_mod)
- {
- struct pf_set *pfs = pf_init_from_file(c->c2.pf.filename);
- if (pfs)
- {
- if (c->c2.pf.pfs)
- {
- pf_destroy(c->c2.pf.pfs);
- }
- c->c2.pf.pfs = pfs;
- reloaded = true;
- if (pf_kill_test(pfs))
- {
- c->sig->signal_received = SIGTERM;
- c->sig->signal_text = "pf-kill";
- }
- }
- c->c2.pf.file_last_mod = s.st_mtime;
- }
- }
- {
- int wakeup = slow_wakeup;
- if (!c->c2.pf.pfs && c->c2.pf.n_check_reload < wakeup_transition)
- {
- wakeup = fast_wakeup;
- }
- event_timeout_init(&c->c2.pf.reload, wakeup, now);
- reset_coarse_timers(c);
- c->c2.pf.n_check_reload++;
- }
- }
-#ifdef ENABLE_DEBUG
- if (reloaded && check_debug_level(D_PF_DEBUG))
- {
- pf_context_print(&c->c2.pf, "pf_check_reload", D_PF_DEBUG);
- }
-#endif
-}
-#endif /* ifdef PLUGIN_PF */
-
-#ifdef MANAGEMENT_PF
-bool
-pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)
-{
- struct pf_set *pfs = pf_init(config, "[SERVER-PF]", false);
- if (pfs)
- {
- if (c->c2.pf.pfs)
- {
- pf_destroy(c->c2.pf.pfs);
- }
- c->c2.pf.pfs = pfs;
- return true;
- }
- else
- {
- return false;
- }
-}
-#endif
-
-void
-pf_init_context(struct context *c)
-{
-#ifdef PLUGIN_PF
- if (plugin_defined(c->plugins, OPENVPN_PLUGIN_ENABLE_PF))
- {
- c->c2.pf.filename = platform_create_temp_file(c->options.tmp_dir, "pf",
- &c->c2.gc);
- if (c->c2.pf.filename)
- {
- setenv_str(c->c2.es, "pf_file", c->c2.pf.filename);
-
- if (plugin_call(c->plugins, OPENVPN_PLUGIN_ENABLE_PF, NULL, NULL, c->c2.es) == OPENVPN_PLUGIN_FUNC_SUCCESS)
- {
- event_timeout_init(&c->c2.pf.reload, 1, now);
- c->c2.pf.enabled = true;
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_context_print(&c->c2.pf, "pf_init_context#1", D_PF_DEBUG);
- }
-#endif
- }
- }
- if (!c->c2.pf.enabled)
- {
- /* At some point in openvpn history, this code just printed a
- * warning and signalled itself (SIGUSR1, "plugin-pf-init-failed")
- * to terminate the client instance. This got broken at one of
- * the client auth state refactorings (leading to SIGSEGV crashes)
- * and due to "pf will be removed anyway" reasons the easiest way
- * to prevent crashes is to REQUIRE that plugins succeed - so if
- * the plugin fails, we cleanly abort OpenVPN
- *
- * see also: https://community.openvpn.net/openvpn/ticket/1377
- */
- msg(M_FATAL, "FATAL: failed to init PF plugin, must succeed.");
- return;
- }
- }
-#endif /* ifdef PLUGIN_PF */
-#ifdef MANAGEMENT_PF
- if (!c->c2.pf.enabled && management_enable_pf(management))
- {
- c->c2.pf.enabled = true;
-#ifdef ENABLE_DEBUG
- if (check_debug_level(D_PF_DEBUG))
- {
- pf_context_print(&c->c2.pf, "pf_init_context#2", D_PF_DEBUG);
- }
-#endif
- }
-#endif
-}
-
-void
-pf_destroy_context(struct pf_context *pfc)
-{
-#ifdef PLUGIN_PF
- if (pfc->filename)
- {
- platform_unlink(pfc->filename);
- }
-#endif
- if (pfc->pfs)
- {
- pf_destroy(pfc->pfs);
- }
-}
-
-#ifdef ENABLE_DEBUG
-
-static void
-pf_subnet_set_print(const struct pf_subnet_set *s, const int lev)
-{
- struct gc_arena gc = gc_new();
- if (s)
- {
- struct pf_subnet *e;
-
- msg(lev, " ----- struct pf_subnet_set -----");
- msg(lev, " default_allow=%s", drop_accept(s->default_allow));
-
- for (e = s->list; e != NULL; e = e->next)
- {
- msg(lev, " %s/%s %s",
- print_in_addr_t(e->rule.network, 0, &gc),
- print_in_addr_t(e->rule.netmask, 0, &gc),
- drop_accept(!e->rule.exclude));
- }
- }
- gc_free(&gc);
-}
-
-static void
-pf_cn_set_print(const struct pf_cn_set *s, const int lev)
-{
- if (s)
- {
- struct hash_iterator hi;
- struct hash_element *he;
-
- msg(lev, " ----- struct pf_cn_set -----");
- msg(lev, " default_allow=%s", drop_accept(s->default_allow));
-
- if (s->hash_table)
- {
- hash_iterator_init(s->hash_table, &hi);
- while ((he = hash_iterator_next(&hi)))
- {
- struct pf_cn *e = (struct pf_cn *)he->value;
- msg(lev, " %s %s",
- e->cn,
- drop_accept(!e->exclude));
- }
-
- msg(lev, " ----------");
-
- {
- struct pf_cn_elem *ce;
- for (ce = s->list; ce != NULL; ce = ce->next)
- {
- struct pf_cn *e = lookup_cn_rule(s->hash_table, ce->rule.cn, cn_hash_function(ce->rule.cn, 0));
- if (e)
- {
- msg(lev, " %s %s",
- e->cn,
- drop_accept(!e->exclude));
- }
- else
- {
- msg(lev, " %s LOOKUP FAILED", ce->rule.cn);
- }
- }
- }
- }
- }
-}
-
-static void
-pf_set_print(const struct pf_set *pfs, const int lev)
-{
- if (pfs)
- {
- msg(lev, " ----- struct pf_set -----");
- msg(lev, " kill=%d", pfs->kill);
- pf_subnet_set_print(&pfs->sns, lev);
- pf_cn_set_print(&pfs->cns, lev);
- }
-}
-
-void
-pf_context_print(const struct pf_context *pfc, const char *prefix, const int lev)
-{
- msg(lev, "----- %s : struct pf_context -----", prefix);
- if (pfc)
- {
- msg(lev, "enabled=%d", pfc->enabled);
-#ifdef PLUGIN_PF
- msg(lev, "filename='%s'", np(pfc->filename));
- msg(lev, "file_last_mod=%u", (unsigned int)pfc->file_last_mod);
- msg(lev, "n_check_reload=%u", pfc->n_check_reload);
- msg(lev, "reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (unsigned int)pfc->reload.last);
-#endif
- pf_set_print(pfc->pfs, lev);
- }
- msg(lev, "--------------------");
-}
-
-#endif /* ifdef ENABLE_DEBUG */
-
-#endif /* if defined(ENABLE_PF) */
+++ /dev/null
-/*
- * OpenVPN -- An application to securely tunnel IP networks
- * over a single TCP/UDP port, with support for SSL/TLS-based
- * session authentication and key exchange,
- * packet encryption, packet authentication, and
- * packet compression.
- *
- * Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* packet filter functions */
-
-#if defined(ENABLE_PF) && !defined(OPENVPN_PF_H)
-#define OPENVPN_PF_H
-
-#include "list.h"
-#include "mroute.h"
-
-#define PF_MAX_LINE_LEN 256
-
-#define PCT_SRC 1
-#define PCT_DEST 2
-
-struct context;
-
-struct ipv4_subnet {
- bool exclude;
- in_addr_t network;
- in_addr_t netmask;
-};
-
-struct pf_subnet {
- struct pf_subnet *next;
- struct ipv4_subnet rule;
-};
-
-struct pf_subnet_set {
- bool default_allow;
- struct pf_subnet *list;
-};
-
-struct pf_cn {
- bool exclude;
- char *cn;
-};
-
-struct pf_cn_elem {
- struct pf_cn_elem *next;
- struct pf_cn rule;
-};
-
-struct pf_cn_set {
- bool default_allow;
- struct pf_cn_elem *list;
- struct hash *hash_table;
-};
-
-struct pf_set {
- bool kill;
- struct pf_subnet_set sns;
- struct pf_cn_set cns;
-};
-
-struct pf_context {
- bool enabled;
- struct pf_set *pfs;
-#ifdef PLUGIN_PF
- const char *filename;
- time_t file_last_mod;
- unsigned int n_check_reload;
- struct event_timeout reload;
-#endif
-};
-
-void pf_init_context(struct context *c);
-
-void pf_destroy_context(struct pf_context *pfc);
-
-#ifdef PLUGIN_PF
-void pf_check_reload(struct context *c);
-
-#endif
-
-#ifdef MANAGEMENT_PF
-bool pf_load_from_buffer_list(struct context *c, const struct buffer_list *config);
-
-#endif
-
-#ifdef ENABLE_DEBUG
-void pf_context_print(const struct pf_context *pfc, const char *prefix, const int lev);
-
-#endif
-
-bool pf_addr_test_dowork(const struct context *src,
- const struct mroute_addr *dest, const char *prefix);
-
-static inline bool
-pf_addr_test(const struct pf_context *src_pf, const struct context *src,
- const struct mroute_addr *dest, const char *prefix)
-{
- if (src_pf->enabled)
- {
- return pf_addr_test_dowork(src, dest, prefix);
- }
- else
- {
- return true;
- }
-}
-
-/*
- * Inline functions
- */
-
-bool pf_cn_test(struct pf_set *pfs, const struct tls_multi *tm, const int type,
- const char *prefix);
-
-static inline bool
-pf_c2c_test(const struct pf_context *src_pf, const struct tls_multi *src,
- const struct pf_context *dest_pf, const struct tls_multi *dest,
- const char *prefix)
-{
- return (!src_pf->enabled || pf_cn_test(src_pf->pfs, dest, PCT_DEST, prefix))
- && (!dest_pf->enabled || pf_cn_test(dest_pf->pfs, src, PCT_SRC,
- prefix));
-}
-
-static inline bool
-pf_kill_test(const struct pf_set *pfs)
-{
- return pfs->kill;
-}
-
-#endif /* if defined(ENABLE_PF) && !defined(OPENVPN_PF_H) */
case OPENVPN_PLUGIN_TLS_FINAL:
return "PLUGIN_TLS_FINAL";
- case OPENVPN_PLUGIN_ENABLE_PF:
- return "PLUGIN_ENABLE_PF";
-
case OPENVPN_PLUGIN_ROUTE_PREDOWN:
return "PLUGIN_ROUTE_PREDOWN";
int i;
const char **envp;
const int n = plugin_n(pl);
- bool success = false;
bool error = false;
bool deferred = false;
switch (status)
{
case OPENVPN_PLUGIN_FUNC_SUCCESS:
- success = true;
break;
case OPENVPN_PLUGIN_FUNC_DEFERRED:
gc_free(&gc);
- if (type == OPENVPN_PLUGIN_ENABLE_PF && success)
- {
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- else if (error)
+ if (error)
{
return OPENVPN_PLUGIN_FUNC_ERROR;
}
struct cert_hash_set *cert_hash_set;
-#ifdef ENABLE_PF
- uint32_t common_name_hashval;
-#endif
-
bool verified; /* true if peer certificate was verified against CA */
/* not-yet-authenticated incoming client */
{
free(session->common_name);
session->common_name = NULL;
-#ifdef ENABLE_PF
- session->common_name_hashval = 0;
-#endif
}
if (common_name)
{
/* FIXME: Last alloc will never be freed */
session->common_name = string_alloc(common_name, NULL);
-#ifdef ENABLE_PF
- {
- const uint32_t len = (uint32_t) strlen(common_name);
- if (len)
- {
- session->common_name_hashval = hash_func((const uint8_t *)common_name, len+1, 0);
- }
- else
- {
- session->common_name_hashval = 0;
- }
- }
-#endif
}
}
*/
bool cert_hash_compare(const struct cert_hash_set *chs1, const struct cert_hash_set *chs2);
-#ifdef ENABLE_PF
-
-/**
- * Retrieve the given tunnel's common name and its hash value.
- *
- * @param multi The tunnel to use
- * @param cn Common name's string
- * @param cn_hash Common name's hash value
- *
- * @return true if the common name was set, false otherwise.
- */
-static inline bool
-tls_common_name_hash(const struct tls_multi *multi, const char **cn, uint32_t *cn_hash)
-{
- if (multi)
- {
- const struct tls_session *s = &multi->session[TM_ACTIVE];
- if (s->common_name && s->common_name[0] != '\0')
- {
- *cn = s->common_name;
- *cn_hash = s->common_name_hashval;
- return true;
- }
- }
- return false;
-}
-
-#endif
-
/**
* Verify the given username and password, using either an external script, a
* plugin, or the management interface.
#define ENABLE_PREDICTION_RESISTANCE
#endif /* ENABLE_CRYPTO_MBEDTLS */
-/*
- * Enable packet filter?
- */
-#if defined(ENABLE_PF) && defined(ENABLE_PLUGIN) && defined(HAVE_STAT)
-#define PLUGIN_PF
-#endif
-#if defined(ENABLE_PF) && defined(ENABLE_MANAGEMENT)
-#define MANAGEMENT_PF
-#endif
-#if !defined(PLUGIN_PF) && !defined(MANAGEMENT_PF)
-#undef ENABLE_PF
-#endif
-
/*
* Do we support Unix domain sockets?
*/