* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
- * Copyright (C) 2008-2021 David Sommerseth <dazo@eurephia.org>
+ * Copyright (C) 2002-2023 OpenVPN Inc <sales@openvpn.net>
+ * Copyright (C) 2008-2023 David Sommerseth <dazo@eurephia.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
#ifdef HAVE_CONFIG_H
#include "config.h"
-#elif defined(_MSC_VER)
-#include "config-msvc.h"
#endif
#ifdef HAVE_CONFIG_VERSION_H
#include "config-version.h"
#include "forward.h"
#include "ssl_verify.h"
#include "platform.h"
+#include "xkey_common.h"
+#include "dco.h"
#include <ctype.h>
#include "memdbg.h"
#endif
#endif
" [AEAD]"
+#ifdef ENABLE_DCO
+ " [DCO]"
+#endif
+#ifdef CONFIGURE_GIT_REVISION
" built on " __DATE__
+#endif
;
#ifndef ENABLE_SMALL
"--remote-random-hostname : Add a random string to remote DNS name.\n"
"--mode m : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
"--proto p : Use protocol p for communicating with peer.\n"
- " p = udp (default), tcp-server, or tcp-client\n"
+ " p = udp (default), tcp-server, tcp-client\n"
+ " udp4, tcp4-server, tcp4-client\n"
+ " udp6, tcp6-server, tcp6-client\n"
"--proto-force p : only consider protocol p in list of connection profiles.\n"
- " p = udp6, tcp6-server, or tcp6-client (ipv6)\n"
+ " p = udp or tcp\n"
"--connect-retry n [m] : For client, number of seconds to wait between\n"
" connection retries (default=%d). On repeated retries\n"
" the wait time is exponentially increased to a maximum of m\n"
" does not begin with \"tun\" or \"tap\".\n"
"--dev-node node : Explicitly set the device node rather than using\n"
" /dev/net/tun, /dev/tun, /dev/tap, etc.\n"
+#if defined(ENABLE_DCO)
+ "--disable-dco : Do not attempt using Data Channel Offload.\n"
+#endif
"--lladdr hw : Set the link layer address of the tap device.\n"
"--topology t : Set --dev tun topology: 'net30', 'p2p', or 'subnet'.\n"
#ifdef ENABLE_IPROUTE
" is established. Multiple routes can be specified.\n"
" netmask default: 255.255.255.255\n"
" gateway default: taken from --route-gateway or --ifconfig\n"
- " Specify default by leaving blank or setting to \"nil\".\n"
+ " Specify default by leaving blank or setting to \"default\".\n"
"--route-ipv6 network/bits [gateway] [metric] :\n"
" Add IPv6 route to routing table after connection\n"
" is established. Multiple routes can be specified.\n"
"--route-noexec : Don't add routes automatically. Instead pass routes to\n"
" --route-up script using environmental variables.\n"
"--route-nopull : When used with --client or --pull, accept options pushed\n"
- " by server EXCEPT for routes and dhcp options.\n"
+ " by server EXCEPT for routes, dns, and dhcp options.\n"
"--allow-pull-fqdn : Allow client to pull DNS names from server for\n"
" --ifconfig, --route, and --route-gateway.\n"
"--redirect-gateway [flags]: Automatically execute routing\n"
"--setenv name value : Set a custom environmental variable to pass to script.\n"
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
" directives for future OpenVPN versions to be ignored.\n"
- "--ignore-unkown-option opt1 opt2 ...: Relax config file syntax. Allow\n"
+ "--ignore-unknown-option opt1 opt2 ...: Relax config file syntax. Allow\n"
" these options to be ignored when unknown\n"
"--script-security level: Where level can be:\n"
" 0 -- strictly no calling of external programs\n"
" for m seconds.\n"
"--inactive n [bytes] : Exit after n seconds of activity on tun/tap device\n"
" produces a combined in/out byte count < bytes.\n"
+ "--session-timeout n: Limit connection time to n seconds.\n"
"--ping-exit n : Exit if n seconds pass without reception of remote ping.\n"
"--ping-restart n: Restart if n seconds pass without reception of remote ping.\n"
"--ping-timer-rem: Run the --ping-exit/--ping-restart timer only if we have a\n"
" and received from TCP/UDP (caps) or tun/tap (lc)\n"
" : 6 to 11 -- debug messages of increasing verbosity\n"
"--mute n : Log at most n consecutive messages in the same category.\n"
- "--status file n : Write operational status to file every n seconds.\n"
+ "--status file [n] : Write operational status to file every n seconds.\n"
"--status-version [n] : Choose the status file format version number.\n"
" Currently, n can be 1, 2, or 3 (default=1).\n"
- "--disable-occ : Disable options consistency check between peers.\n"
+ "--disable-occ : (DEPRECATED) Disable options consistency check between peers.\n"
#ifdef ENABLE_DEBUG
"--gremlin mask : Special stress testing mode (for debugging only).\n"
#endif
" OTP based two-factor auth mechanisms are in use and\n"
" --reneg-* options are enabled. Optionally a lifetime in seconds\n"
" for generated tokens can be set.\n"
- "--opt-verify : Clients that connect with options that are incompatible\n"
+ "--opt-verify : (DEPRECATED) Clients that connect with options that are incompatible\n"
" with those of the server will be disconnected.\n"
"--auth-user-pass-optional : Allow connections by clients that don't\n"
" specify a username/password.\n"
" as well as pushes it to connecting clients.\n"
"--learn-address cmd : Run command cmd to validate client virtual addresses.\n"
"--connect-freq n s : Allow a maximum of n new connections per s seconds.\n"
+ "--connect-freq-initial n s : Allow a maximum of n replies for initial connections attempts per s seconds.\n"
"--max-clients n : Allow a maximum of n simultaneously connected clients.\n"
"--max-routes-per-client n : Allow a maximum of n internal routes per client.\n"
"--stale-routes-check n [t] : Remove routes with a last activity timestamp\n"
" ignore or reject causes the option to be allowed, removed or\n"
" rejected with error. May be specified multiple times, and\n"
" each filter is applied in the order of appearance.\n"
+ "--dns server <n> <option> <value> [value ...] : Configure option for DNS server #n\n"
+ " Valid options are :\n"
+ " address <addr[:port]> [addr[:port] ...] : server addresses 4/6\n"
+ " resolve-domains <domain> [domain ...] : split domains\n"
+ " dnssec <yes|no|optional> : option to use DNSSEC\n"
+ " type <DoH|DoT> : query server over HTTPS / TLS\n"
+ " sni <domain> : DNS server name indication\n"
+ "--dns search-domains <domain> [domain ...]:\n"
+ " Add domains to DNS domain search list\n"
"--auth-retry t : How to handle auth failures. Set t to\n"
" none (default), interact, or nointeract.\n"
"--static-challenge t e : Enable static challenge/response protocol using\n"
"\n"
"Data Channel Encryption Options (must be compatible between peers):\n"
"(These options are meaningful for both Static Key & TLS-mode)\n"
- "--secret f [d] : (DEPRECATED) Enable Static Key encryption mode (non-TLS).\n"
- " Use shared secret file f, generate with --genkey.\n"
- " The optional d parameter controls key directionality.\n"
- " If d is specified, use separate keys for each\n"
- " direction, set d=0 on one side of the connection,\n"
- " and d=1 on the other side.\n"
"--auth alg : Authenticate packets with HMAC using message\n"
" digest algorithm alg (default=%s).\n"
" (usually adds 16 or 20 bytes per packet)\n"
" Set alg=none to disable authentication.\n"
- "--cipher alg : Encrypt packets with cipher algorithm alg\n"
- " (default=%s).\n"
+ "--cipher alg : Encrypt packets with cipher algorithm alg.\n"
+ " You should usually use --data-ciphers instead.\n"
" Set alg=none to disable encryption.\n"
"--data-ciphers list : List of ciphers that are allowed to be negotiated.\n"
#ifndef ENABLE_CRYPTO_MBEDTLS
"--engine [name] : Enable OpenSSL hardware crypto engine functionality.\n"
#endif
- "--no-replay : (DEPRECATED) Disable replay protection.\n"
"--mute-replay-warnings : Silence the output of replay warnings to log file.\n"
"--replay-window n [t] : Use a replay protection sliding window of size n\n"
" and a time window of t seconds.\n"
"(These options are meaningful only for TLS-mode)\n"
"--tls-server : Enable TLS and assume server role during TLS handshake.\n"
"--tls-client : Enable TLS and assume client role during TLS handshake.\n"
- "--key-method m : (DEPRECATED) Data channel key exchange method. m should be a method\n"
- " number, such as 1 (default), 2, etc.\n"
"--ca file : Certificate authority file in .pem format containing\n"
" root certificate.\n"
#ifndef ENABLE_CRYPTO_MBEDTLS
" Windows Certificate System Store.\n"
#endif
"--tls-cipher l : A list l of allowable TLS ciphers separated by : (optional).\n"
- "--tls-ciphersuites l: A list of allowed TLS 1.3 cipher suites seperated by : (optional)\n"
+ "--tls-ciphersuites l: A list of allowed TLS 1.3 cipher suites separated by : (optional)\n"
" : Use --show-tls to see a list of supported TLS ciphers (suites).\n"
"--tls-cert-profile p : Set the allowed certificate crypto algorithm profile\n"
" (default=legacy).\n"
" control channel to protect against attacks on the TLS stack\n"
" and DoS attacks.\n"
" f (required) is a shared-secret key file.\n"
- " The optional d parameter controls key directionality,\n"
- " see --secret option for more info.\n"
+ " The optional d parameter controls key directionality.\n"
"--tls-crypt key : Add an additional layer of authenticated encryption on top\n"
" of the TLS control channel to hide the TLS certificate,\n"
" provide basic post-quantum security and protect against\n"
" attacks on the TLS stack and DoS attacks.\n"
" key (required) provides the pre-shared key file.\n"
- " see --secret option for more info.\n"
"--tls-crypt-v2 key : For clients: use key as a client-specific tls-crypt key.\n"
" For servers: use key to decrypt client-specific keys. For\n"
" key generation (--genkey tls-crypt-v2-client): use key to\n"
" tests of certification. cmd should return 0 to allow\n"
" TLS handshake to proceed, or 1 to fail. (cmd is\n"
" executed as 'cmd certificate_depth subject')\n"
- "--tls-export-cert [directory] : Get peer cert in PEM format and store it \n"
- " in an openvpn temporary file in [directory]. Peer cert is \n"
- " stored before tls-verify script execution and deleted after.\n"
"--verify-x509-name name: Accept connections only from a host with X509 subject\n"
" DN name. The remote host must also pass all other tests\n"
" of verification.\n"
+#ifndef ENABLE_CRYPTO_MBEDTLS
"--ns-cert-type t: (DEPRECATED) Require that peer certificate was signed with \n"
" an explicit nsCertType designation t = 'client' | 'server'.\n"
+#endif
"--x509-track x : Save peer X509 attribute x in environment for use by\n"
" plugins and management interface.\n"
#ifdef HAVE_EXPORT_KEYING_MATERIAL
"--show-net-up : Show " PACKAGE_NAME "'s view of routing table and net adapter list\n"
" after TAP adapter is up and routes have been added.\n"
"--windows-driver : Which tun driver to use?\n"
- " tap-windows6 (default)\n"
+ " ovpn-dco (default)\n"
+ " tap-windows6\n"
" wintun\n"
"--block-outside-dns : Block DNS on other network adapters to prevent DNS leaks\n"
"Windows Standalone Options:\n"
#endif /* ifdef _WIN32 */
"\n"
"Generate a new key :\n"
- "--genkey secret file : Generate a new random key of type and write to file\n"
- " (for use with --secret, --tls-auth or --tls-crypt)."
+ "--genkey tls-auth file : Generate a new random key of type and write to file\n"
+ " (for use with --tls-auth or --tls-crypt)."
#ifdef ENABLE_FEATURE_TUN_PERSIST
"\n"
"Tun/tap config mode (available with linux 2.4+):\n"
if (init_gc)
{
gc_init(&o->gc);
+ gc_init(&o->dns_options.gc);
o->gc_owned = true;
}
o->mode = MODE_POINT_TO_POINT;
o->ce.proto = PROTO_UDP;
o->ce.af = AF_UNSPEC;
o->ce.bind_ipv6_only = false;
- o->ce.connect_retry_seconds = 5;
+ o->ce.connect_retry_seconds = 1;
o->ce.connect_retry_seconds_max = 300;
o->ce.connect_timeout = 120;
o->connect_retry_max = 0;
o->status_file_version = 1;
o->ce.bind_local = true;
o->ce.tun_mtu = TUN_MTU_DEFAULT;
+ o->ce.occ_mtu = 0;
o->ce.link_mtu = LINK_MTU_DEFAULT;
+ o->ce.tls_mtu = TLS_MTU_DEFAULT;
o->ce.mtu_discover_type = -1;
- o->ce.mssfix = MSSFIX_DEFAULT;
+ o->ce.mssfix = 0;
+ o->ce.mssfix_default = true;
+ o->ce.mssfix_encap = true;
o->route_delay_window = 30;
o->resolve_retry_seconds = RESOLV_RETRY_INFINITE;
o->resolve_in_advance = false;
o->tuntap_options.dhcp_masq_offset = 0; /* use network address as internal DHCP server address */
o->route_method = ROUTE_METHOD_ADAPTIVE;
o->block_outside_dns = false;
- o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ o->windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
#endif
o->vlan_accept = VLAN_ALL;
o->vlan_pvid = 1;
o->n_bcast_buf = 256;
o->tcp_queue_limit = 64;
o->max_clients = 1024;
+ o->cf_initial_per = 10;
+ o->cf_initial_max = 100;
o->max_routes_per_client = 256;
o->stale_routes_check_interval = 0;
o->ifconfig_pool_persist_refresh_freq = 600;
o->scheduled_exit_interval = 5;
o->authname = "SHA1";
- o->replay = true;
o->replay_window = DEFAULT_SEQ_BACKTRACK;
o->replay_time = DEFAULT_TIME_BACKTRACK;
o->key_direction = KEY_DIRECTION_BIDIRECTIONAL;
}
#endif /* _WIN32 */
o->allow_recursive_routing = false;
+
+#ifndef ENABLE_DCO
+ o->tuntap_options.disable_dco = true;
+#endif /* ENABLE_DCO */
}
void
uninit_options(struct options *o)
{
+ if (o->connection_list)
+ {
+ CLEAR(*o->connection_list);
+ }
+ if (o->remote_list)
+ {
+ CLEAR(*o->remote_list);
+ }
if (o->gc_owned)
{
gc_free(&o->gc);
+ gc_free(&o->dns_options.gc);
}
}
struct pull_filter *tail;
};
+#ifndef ENABLE_SMALL
+
static const char *
pull_filter_type_name(int type)
{
}
}
-#ifndef ENABLE_SMALL
-
#define SHOW_PARM(name, value, format) msg(D_SHOW_PARMS, " " #name " = " format, (value))
#define SHOW_STR(var) SHOW_PARM(var, (o->var ? o->var : "[UNDEF]"), "'%s'")
#define SHOW_STR_INLINE(var) SHOW_PARM(var, \
"'%s'")
#define SHOW_INT(var) SHOW_PARM(var, o->var, "%d")
#define SHOW_UINT(var) SHOW_PARM(var, o->var, "%u")
+#define SHOW_INT64(var) SHOW_PARM(var, o->var, "%" PRIi64)
#define SHOW_UNSIGNED(var) SHOW_PARM(var, o->var, "0x%08x")
#define SHOW_BOOL(var) SHOW_PARM(var, (o->var ? "ENABLED" : "DISABLED"), "%s");
-#endif
+#endif /* ifndef ENABLE_SMALL */
static void
setenv_connection_entry(struct env_set *es,
{
setenv_connection_entry(es, &o->ce, 1);
}
+
+ if (!o->pull)
+ {
+ setenv_dns_options(&o->dns_options, es);
+ }
+}
+
+#ifndef _WIN32
+static void
+setenv_foreign_option(struct options *o, const char *argv[], int len, struct env_set *es)
+{
+ if (len > 0)
+ {
+ struct gc_arena gc = gc_new();
+ struct buffer name = alloc_buf_gc(OPTION_PARM_SIZE, &gc);
+ struct buffer value = alloc_buf_gc(OPTION_PARM_SIZE, &gc);
+ int i;
+ bool first = true;
+ bool good = true;
+
+ good &= buf_printf(&name, "foreign_option_%d", o->foreign_option_index + 1);
+ ++o->foreign_option_index;
+ for (i = 0; i < len; ++i)
+ {
+ if (argv[i])
+ {
+ if (!first)
+ {
+ good &= buf_printf(&value, " ");
+ }
+ good &= buf_printf(&value, "%s", argv[i]);
+ first = false;
+ }
+ }
+ if (good)
+ {
+ setenv_str(es, BSTR(&name), BSTR(&value));
+ }
+ else
+ {
+ msg(M_WARN, "foreign_option: name/value overflow");
+ }
+ gc_free(&gc);
+ }
}
+#endif /* ifndef _WIN32 */
static in_addr_t
get_ip_addr(const char *ip_string, int msglevel, bool *error)
ALLOC_OBJ_CLEAR_GC(ret, struct verify_hash_list, gc);
char term = 0;
- int byte;
+ unsigned int byte;
while (*cp && i < nbytes)
{
while ((line = strsep(&lines, "\n")))
{
/* ignore leading whitespace */
- while(isspace(*line))
+ while (isspace(*line))
{
line++;
}
#ifndef ENABLE_SMALL
static void
-show_dhcp_option_list(const char *name, const char * const*array, int len)
+show_dhcp_option_list(const char *name, const char *const *array, int len)
{
int i;
for (i = 0; i < len; ++i)
SHOW_INT(dhcp_masq_offset);
SHOW_INT(dhcp_lease_time);
SHOW_INT(tap_sleep);
- SHOW_BOOL(dhcp_options);
+ SHOW_UNSIGNED(dhcp_options);
SHOW_BOOL(dhcp_renew);
SHOW_BOOL(dhcp_pre_release);
SHOW_STR(domain);
}
}
+/*
+ * If DNS options are set use these for TUN/TAP options as well.
+ * Applies to DNS, DNS6 and DOMAIN-SEARCH.
+ * Existing options will be discarded.
+ */
+static void
+tuntap_options_copy_dns(struct options *o)
+{
+ struct tuntap_options *tt = &o->tuntap_options;
+ struct dns_options *dns = &o->dns_options;
+
+ if (dns->search_domains)
+ {
+ tt->domain_search_list_len = 0;
+ const struct dns_domain *domain = dns->search_domains;
+ while (domain && tt->domain_search_list_len < N_SEARCH_LIST_LEN)
+ {
+ tt->domain_search_list[tt->domain_search_list_len++] = domain->name;
+ domain = domain->next;
+ }
+ if (domain)
+ {
+ msg(M_WARN, "WARNING: couldn't copy all --dns search-domains to --dhcp-option");
+ }
+ tt->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
+ }
+
+ if (dns->servers)
+ {
+ tt->dns_len = 0;
+ tt->dns6_len = 0;
+ bool overflow = false;
+ const struct dns_server *server = dns->servers;
+ while (server)
+ {
+ for (int i = 0; i < server->addr_count; ++i)
+ {
+ if (server->addr[i].family == AF_INET)
+ {
+ if (tt->dns_len >= N_DHCP_ADDR)
+ {
+ overflow = true;
+ continue;
+ }
+ tt->dns[tt->dns_len++] = server->addr[i].in.a4.s_addr;
+ }
+ else
+ {
+ if (tt->dns6_len >= N_DHCP_ADDR)
+ {
+ overflow = true;
+ continue;
+ }
+ tt->dns6[tt->dns6_len++] = server->addr[i].in.a6;
+ }
+ }
+ server = server->next;
+ }
+ if (overflow)
+ {
+ msg(M_WARN, "WARNING: couldn't copy all --dns server addresses to --dhcp-option");
+ }
+ tt->dhcp_options |= DHCP_OPTIONS_DHCP_OPTIONAL;
+ }
+}
+#else /* if defined(_WIN32) || defined(TARGET_ANDROID) */
+static void
+foreign_options_copy_dns(struct options *o, struct env_set *es)
+{
+ const struct dns_domain *domain = o->dns_options.search_domains;
+ const struct dns_server *server = o->dns_options.servers;
+ if (!domain && !server)
+ {
+ return;
+ }
+
+ /* reset the index since we're starting all over again */
+ int opt_max = o->foreign_option_index;
+ o->foreign_option_index = 0;
+
+ for (int i = 1; i <= opt_max; ++i)
+ {
+ char name[32];
+ openvpn_snprintf(name, sizeof(name), "foreign_option_%d", i);
+
+ const char *env_str = env_set_get(es, name);
+ const char *value = strchr(env_str, '=') + 1;
+ if ((domain && strstr(value, "dhcp-option DOMAIN-SEARCH") == value)
+ || (server && strstr(value, "dhcp-option DNS") == value))
+ {
+ setenv_del(es, name);
+ }
+ else
+ {
+ setenv_foreign_option(o, &value, 1, es);
+ }
+ }
+
+ struct gc_arena gc = gc_new();
+
+ while (server)
+ {
+ for (int i = 0; i < server->addr_count; ++i)
+ {
+ if (server->addr[i].family == AF_INET)
+ {
+ const char *argv[] = {
+ "dhcp-option",
+ "DNS",
+ print_in_addr_t(server->addr[i].in.a4.s_addr, 0, &gc)
+ };
+ setenv_foreign_option(o, argv, 3, es);
+ }
+ else
+ {
+ const char *argv[] = {
+ "dhcp-option",
+ "DNS6",
+ print_in6_addr(server->addr[i].in.a6, 0, &gc)
+ };
+ setenv_foreign_option(o, argv, 3, es);
+ }
+ }
+ server = server->next;
+ }
+ while (domain)
+ {
+ const char *argv[] = { "dhcp-option", "DOMAIN-SEARCH", domain->name };
+ setenv_foreign_option(o, argv, 3, es);
+ domain = domain->next;
+ }
+
+ gc_free(&gc);
+
+ /* remove old leftover entries */
+ while (o->foreign_option_index < opt_max)
+ {
+ char name[32];
+ openvpn_snprintf(name, sizeof(name), "foreign_option_%d", opt_max--);
+ setenv_del(es, name);
+ }
+}
#endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */
+#ifndef ENABLE_SMALL
static const char *
print_vlan_accept(enum vlan_acceptable_frames mode)
{
return NULL;
}
-#ifndef ENABLE_SMALL
-
static void
show_p2mp_parms(const struct options *o)
{
SHOW_STR(client_connect_script);
SHOW_STR(learn_address_script);
SHOW_STR(client_disconnect_script);
+ SHOW_STR(client_crresponse_script);
SHOW_STR(client_config_dir);
SHOW_BOOL(ccd_exclusive);
SHOW_STR(tmp_dir);
SHOW_BOOL(duplicate_cn);
SHOW_INT(cf_max);
SHOW_INT(cf_per);
+ SHOW_INT(cf_initial_max);
+ SHOW_INT(cf_initial_per);
SHOW_INT(max_clients);
SHOW_INT(max_routes_per_client);
SHOW_STR(auth_user_pass_verify_script);
SHOW_BOOL(client);
SHOW_BOOL(pull);
- SHOW_STR(auth_user_pass_file);
+ SHOW_STR_INLINE(auth_user_pass_file);
gc_free(&gc);
}
ALLOC_OBJ_GC(ir, struct iroute, &o->gc);
ir->network = getaddr(GETADDR_HOST_ORDER, network_str, 0, NULL, NULL);
- ir->netbits = -1;
+ ir->netbits = 32; /* host route if no netmask given */
if (netmask_str)
{
const in_addr_t netmask = getaddr(GETADDR_HOST_ORDER, netmask_str, 0, NULL, NULL);
- if (!netmask_to_netbits(ir->network, netmask, &ir->netbits))
+ ir->netbits = netmask_to_netbits2(netmask);
+
+ if (ir->netbits < 0)
{
msg(msglevel, "in --iroute %s %s : Bad network/subnet specification",
network_str,
SHOW_BOOL(link_mtu_defined);
SHOW_INT(tun_mtu_extra);
SHOW_BOOL(tun_mtu_extra_defined);
+ SHOW_INT(tls_mtu);
SHOW_INT(mtu_discover_type);
SHOW_INT(fragment);
#endif
SHOW_INT(mssfix);
+ SHOW_BOOL(mssfix_encap);
+ SHOW_BOOL(mssfix_fixed);
SHOW_INT(explicit_exit_notification);
SHOW_STR(dev);
SHOW_STR(dev_type);
SHOW_STR(dev_node);
+#if defined(ENABLE_DCO)
+ SHOW_BOOL(tuntap_options.disable_dco);
+#endif
SHOW_STR(lladdr);
SHOW_INT(topology);
SHOW_STR(ifconfig_local);
SHOW_INT(keepalive_ping);
SHOW_INT(keepalive_timeout);
SHOW_INT(inactivity_timeout);
+ SHOW_INT(session_timeout);
+ SHOW_INT64(inactivity_minimum_bytes);
SHOW_INT(ping_send_timeout);
SHOW_INT(ping_rec_timeout);
SHOW_INT(ping_rec_timeout_action);
SHOW_BOOL(fast_io);
-#ifdef USE_COMP
SHOW_INT(comp.alg);
SHOW_INT(comp.flags);
-#endif
SHOW_STR(route_script);
SHOW_STR(route_default_gateway);
print_client_nat_list(o->client_nat, D_SHOW_PARMS);
}
+ show_dns_options(&o->dns_options);
+
#ifdef ENABLE_MANAGEMENT
SHOW_STR(management_addr);
SHOW_STR(management_port);
SHOW_STR(management_user_pass);
SHOW_INT(management_log_history_cache);
SHOW_INT(management_echo_buffer_size);
- SHOW_STR(management_write_peer_info_file);
SHOW_STR(management_client_user);
SHOW_STR(management_client_group);
SHOW_INT(management_flags);
#ifndef ENABLE_CRYPTO_MBEDTLS
SHOW_BOOL(engine);
#endif /* ENABLE_CRYPTO_MBEDTLS */
- SHOW_BOOL(replay);
SHOW_BOOL(mute_replay_warnings);
SHOW_INT(replay_window);
SHOW_INT(replay_time);
SHOW_STR_INLINE(ca_file);
SHOW_STR(ca_path);
SHOW_STR_INLINE(dh_file);
-#ifdef ENABLE_MANAGEMENT
if ((o->management_flags & MF_EXTERNAL_CERT))
{
- SHOW_PARM("cert_file","EXTERNAL_CERT","%s");
+ SHOW_PARM("cert_file", "EXTERNAL_CERT", "%s");
}
else
-#endif
- SHOW_STR_INLINE(cert_file);
+ {
+ SHOW_STR_INLINE(cert_file);
+ }
SHOW_STR_INLINE(extra_certs_file);
-#ifdef ENABLE_MANAGEMENT
if ((o->management_flags & MF_EXTERNAL_KEY))
{
- SHOW_PARM("priv_key_file","EXTERNAL_PRIVATE_KEY","%s");
+ SHOW_PARM("priv_key_file", "EXTERNAL_PRIVATE_KEY", "%s");
}
else
-#endif
- SHOW_STR_INLINE(priv_key_file);
+ {
+ SHOW_STR_INLINE(priv_key_file);
+ }
#ifndef ENABLE_CRYPTO_MBEDTLS
SHOW_STR_INLINE(pkcs12_file);
#endif
SHOW_STR(cipher_list_tls13);
SHOW_STR(tls_cert_profile);
SHOW_STR(tls_verify);
- SHOW_STR(tls_export_cert);
SHOW_INT(verify_x509_type);
SHOW_STR(verify_x509_name);
SHOW_STR_INLINE(crl_file);
struct connection_list *l = alloc_connection_list_if_undef(options);
struct connection_entry *e;
- if (l->len >= CONNECTION_LIST_SIZE)
+ if (l->len == l->capacity)
{
- msg(msglevel, "Maximum number of 'connection' options (%d) exceeded", CONNECTION_LIST_SIZE);
- return NULL;
+ int capacity = l->capacity + CONNECTION_LIST_SIZE;
+ struct connection_entry **ce = gc_realloc(l->array, capacity*sizeof(struct connection_entry *), &options->gc);
+ if (ce == NULL)
+ {
+ msg(msglevel, "Unable to process more connection options: out of memory. Number of entries = %d", l->len);
+ return NULL;
+ }
+ l->array = ce;
+ l->capacity = capacity;
}
ALLOC_OBJ_GC(e, struct connection_entry, &options->gc);
l->array[l->len++] = e;
struct remote_list *l = alloc_remote_list_if_undef(options);
struct remote_entry *e;
- if (l->len >= CONNECTION_LIST_SIZE)
+ if (l->len == l->capacity)
{
- msg(msglevel, "Maximum number of 'remote' options (%d) exceeded", CONNECTION_LIST_SIZE);
- return NULL;
+ int capacity = l->capacity + CONNECTION_LIST_SIZE;
+ struct remote_entry **re = gc_realloc(l->array, capacity*sizeof(struct remote_entry *), &options->gc);
+ if (re == NULL)
+ {
+ msg(msglevel, "Unable to process more remote options: out of memory. Number of entries = %d", l->len);
+ return NULL;
+ }
+ l->array = re;
+ l->capacity = capacity;
}
ALLOC_OBJ_GC(e, struct remote_entry, &options->gc);
l->array[l->len++] = e;
#ifndef ENABLE_CRYPTO_MBEDTLS
|| options->ca_path
#endif
- )
+ )
{
return;
}
- const char* const str = "You must define CA file (--ca)"
+ const char *const str = "You must define CA file (--ca)"
#ifndef ENABLE_CRYPTO_MBEDTLS
- " or CA path (--capath)"
+ " or CA path (--capath)"
#endif
- " and/or peer fingerprint verification (--peer-fingerprint)";
- msg(M_USAGE, str);
+ " and/or peer fingerprint verification (--peer-fingerprint)";
+ msg(M_USAGE, "%s", str);
}
static void
*/
if (options->ce.tun_mtu_defined && options->ce.link_mtu_defined)
{
- msg(M_USAGE,
- "only one of --tun-mtu or --link-mtu may be defined (note that "
- "--ifconfig implies --link-mtu %d)", LINK_MTU_DEFAULT);
+ msg(M_USAGE, "only one of --tun-mtu or --link-mtu may be defined");
}
if (!proto_is_udp(ce->proto) && options->mtu_test)
#ifdef ENABLE_MANAGEMENT
if (!options->management_addr
&& (options->management_flags
- || options->management_write_peer_info_file
|| options->management_log_history_cache != defaults.management_log_history_cache))
{
msg(M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified");
#endif /* ifdef ENABLE_MANAGEMENT */
-#if defined(ENABLE_MANAGEMENT)
+#if !defined(HAVE_XKEY_PROVIDER)
if ((tls_version_max() >= TLS_VER_1_3)
&& (options->management_flags & MF_EXTERNAL_KEY)
&& !(options->management_flags & (MF_EXTERNAL_KEY_NOPADDING))
)
{
- msg(M_ERR, "management-external-key with OpenSSL 1.1.1 requires "
- "the nopadding argument/support");
+ msg(M_FATAL, "management-external-key with TLS 1.3 or later requires "
+ "nopadding argument/support");
}
#endif
/*
msg(M_USAGE, "On Windows, --ip-win32 doesn't make sense unless --ifconfig is also used");
}
- if (options->tuntap_options.dhcp_options
- && options->windows_driver != WINDOWS_DRIVER_WINTUN
- && options->tuntap_options.ip_win32_type != IPW32_SET_DHCP_MASQ
- && options->tuntap_options.ip_win32_type != IPW32_SET_ADAPTIVE)
+ if (options->tuntap_options.dhcp_options & DHCP_OPTIONS_DHCP_REQUIRED)
{
- msg(M_USAGE, "--dhcp-option requires --ip-win32 dynamic or adaptive");
+ const char *prefix = "Some --dhcp-option or --dns options require DHCP server";
+ if (options->windows_driver != WINDOWS_DRIVER_TAP_WINDOWS6)
+ {
+ msg(M_USAGE, "%s, which is not supported by the selected %s driver",
+ prefix, print_windows_driver(options->windows_driver));
+ }
+ else if (options->tuntap_options.ip_win32_type != IPW32_SET_DHCP_MASQ
+ && options->tuntap_options.ip_win32_type != IPW32_SET_ADAPTIVE)
+ {
+ msg(M_USAGE, "%s, which requires --ip-win32 dynamic or adaptive",
+ prefix);
+ }
}
if (options->windows_driver == WINDOWS_DRIVER_WINTUN && dev != DEV_TYPE_TUN)
*/
if (options->mode == MODE_SERVER)
{
+#define USAGE_VALID_SERVER_PROTOS "--mode server currently only supports " \
+ "--proto values of udp, tcp-server, tcp4-server, or tcp6-server"
#ifdef TARGET_ANDROID
msg(M_FATAL, "--mode server not supported on Android");
#endif
}
if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCP_SERVER))
{
- msg(M_USAGE, "--mode server currently only supports "
- "--proto udp or --proto tcp-server or proto tcp6-server");
+ msg(M_USAGE, USAGE_VALID_SERVER_PROTOS);
}
#if PORT_SHARE
if ((options->port_share_host || options->port_share_port)
&& (ce->proto != PROTO_TCP_SERVER))
{
msg(M_USAGE, "--port-share only works in TCP server mode "
- "(--proto tcp-server or tcp6-server)");
+ "(--proto values of tcp-server, tcp4-server, or tcp6-server)");
}
#endif
if (!options->tls_server)
}
if (!(proto_is_dgram(ce->proto) || ce->proto == PROTO_TCP_SERVER))
{
- msg(M_USAGE,
- "--mode server currently only supports --proto udp or --proto "
- "tcp-server or --proto tcp6-server");
+ msg(M_USAGE, USAGE_VALID_SERVER_PROTOS);
}
if (!proto_is_udp(ce->proto) && (options->cf_max || options->cf_per))
{
msg(M_USAGE, "--auth-gen-token needs a non-infinite "
"--renegotiate_seconds setting");
}
+ if (options->auth_token_generate && options->auth_token_renewal
+ && options->auth_token_renewal < 2 * options->handshake_window)
+ {
+ msg(M_USAGE, "--auth-gen-token renewal time needs to be at least "
+ " two times --hand-window (%d).",
+ options->handshake_window);
+
+ }
{
const bool ccnr = (options->auth_user_pass_verify_script
|| PLUGIN_OPTION_LIST(options)
{
msg(M_USAGE, "--client-connect requires --mode server");
}
+ if (options->client_crresponse_script)
+ {
+ msg(M_USAGE, "--client-crresponse requires --mode server");
+ }
if (options->client_disconnect_script)
{
msg(M_USAGE, "--client-disconnect requires --mode server");
}
}
- /*
- * Check consistency of replay options
- */
- if (!options->replay
- && (options->replay_window != defaults.replay_window
- || options->replay_time != defaults.replay_time))
- {
- msg(M_USAGE, "--replay-window doesn't make sense when replay protection is disabled with --no-replay");
- }
-
/*
* SSL/TLS mode sanity checks.
*/
if (!options->tls_server && !options->tls_client)
{
- msg(M_INFO, "DEPRECATION: No tls-client or tls-server option in "
- "configuration detected. OpenVPN 2.7 will remove the "
- "functionality to run a VPN without TLS. "
- "See the examples section in the manual page for "
- "examples of a similar quick setup with peer-fingerprint.");
+ int msglevel = M_USAGE;
+ if (options->allow_deprecated_insecure_static_crypto)
+ {
+ msglevel = M_INFO;
+ }
+
+ msg(msglevel, "DEPRECATION: No tls-client or tls-server option in "
+ "configuration detected. OpenVPN 2.8 will remove the "
+ "functionality to run a VPN without TLS. "
+ "See the examples section in the manual page for "
+ "examples of a similar quick setup with peer-fingerprint."
+ "OpenVPN 2.7 allows using this configuration when using "
+ "--allow-deprecated-insecure-static-crypto but you should move"
+ "to a proper configuration using TLS as soon as possible."
+ );
}
if (options->ssl_flags & (SSLF_CLIENT_CERT_NOT_REQUIRED|SSLF_CLIENT_CERT_OPTIONAL))
{
check_ca_required(options);
#ifdef ENABLE_PKCS11
+ if (!options->pkcs11_providers[0] && options->pkcs11_id)
+ {
+ msg(M_WARN, "Option pkcs11-id is ignored as no pkcs11-providers are specified");
+ }
+ else if (!options->pkcs11_providers[0] && options->pkcs11_id_management)
+ {
+ msg(M_WARN, "Option pkcs11-id-management is ignored as no pkcs11-providers are specified");
+ }
+
if (options->pkcs11_providers[0])
{
if (options->pkcs11_id_management && options->pkcs11_id != NULL)
{
msg(M_USAGE, "Parameter --key cannot be used when --pkcs11-provider is also specified.");
}
-#ifdef ENABLE_MANAGEMENT
if (options->management_flags & MF_EXTERNAL_KEY)
{
msg(M_USAGE, "Parameter --management-external-key cannot be used when --pkcs11-provider is also specified.");
{
msg(M_USAGE, "Parameter --management-external-cert cannot be used when --pkcs11-provider is also specified.");
}
-#endif
if (options->pkcs12_file)
{
msg(M_USAGE, "Parameter --pkcs12 cannot be used when --pkcs11-provider is also specified.");
}
else
#endif /* ifdef ENABLE_PKCS11 */
-#ifdef ENABLE_MANAGEMENT
if ((options->management_flags & MF_EXTERNAL_KEY) && options->priv_key_file)
{
msg(M_USAGE, "--key and --management-external-key are mutually exclusive");
}
}
else
-#endif
#ifdef ENABLE_CRYPTOAPI
if (options->cryptoapi_cert)
{
{
msg(M_USAGE, "Parameter --pkcs12 cannot be used when --cryptoapicert is also specified.");
}
-#ifdef ENABLE_MANAGEMENT
if (options->management_flags & MF_EXTERNAL_KEY)
{
msg(M_USAGE, "Parameter --management-external-key cannot be used when --cryptoapicert is also specified.");
{
msg(M_USAGE, "Parameter --management-external-cert cannot be used when --cryptoapicert is also specified.");
}
-#endif
}
else
#endif /* ifdef ENABLE_CRYPTOAPI */
{
msg(M_USAGE, "Parameter --key cannot be used when --pkcs12 is also specified.");
}
-#ifdef ENABLE_MANAGEMENT
if (options->management_flags & MF_EXTERNAL_KEY)
{
msg(M_USAGE, "Parameter --management-external-key cannot be used when --pkcs12 is also specified.");
{
msg(M_USAGE, "Parameter --management-external-cert cannot be used when --pkcs12 is also specified.");
}
-#endif
#endif /* ifdef ENABLE_CRYPTO_MBEDTLS */
}
else
{
const int sum =
-#ifdef ENABLE_MANAGEMENT
((options->cert_file != NULL) || (options->management_flags & MF_EXTERNAL_CERT))
- +((options->priv_key_file != NULL) || (options->management_flags & MF_EXTERNAL_KEY));
-#else
- (options->cert_file != NULL) + (options->priv_key_file != NULL);
-#endif
+ + ((options->priv_key_file != NULL) || (options->management_flags & MF_EXTERNAL_KEY));
if (sum == 0)
{
if (!options->auth_user_pass_file)
{
msg(M_USAGE, "No client-side authentication method is "
- "specified. You must use either "
- "--cert/--key, --pkcs12, or "
- "--auth-user-pass");
+ "specified. You must use either "
+ "--cert/--key, --pkcs12, or "
+ "--auth-user-pass");
}
}
- else if (sum == 2)
- {
- }
- else
+ else if (sum != 2)
{
msg(M_USAGE, "If you use one of --cert or --key, you must use them both");
}
}
else
{
-#ifdef ENABLE_MANAGEMENT
if (!(options->management_flags & MF_EXTERNAL_CERT))
-#endif
- notnull(options->cert_file, "certificate file (--cert) or PKCS#12 file (--pkcs12)");
-#ifdef ENABLE_MANAGEMENT
+ {
+ notnull(options->cert_file, "certificate file (--cert) or PKCS#12 file (--pkcs12)");
+ }
if (!(options->management_flags & MF_EXTERNAL_KEY))
-#endif
- notnull(options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)");
+ {
+ notnull(options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)");
+ }
}
}
if (ce->tls_auth_file && ce->tls_crypt_file)
MUST_BE_UNDEF(cipher_list_tls13);
MUST_BE_UNDEF(tls_cert_profile);
MUST_BE_UNDEF(tls_verify);
- MUST_BE_UNDEF(tls_export_cert);
MUST_BE_UNDEF(verify_x509_name);
MUST_BE_UNDEF(tls_timeout);
MUST_BE_UNDEF(renegotiate_bytes);
ce->flags |= CE_DISABLED;
}
- /*
- * If --mssfix is supplied without a parameter, default
- * it to --fragment value, if --fragment is specified.
- */
- if (o->ce.mssfix_default)
- {
-#ifdef ENABLE_FRAGMENT
- if (ce->fragment)
- {
- ce->mssfix = ce->fragment;
- }
-#else
- msg(M_USAGE, "--mssfix must specify a parameter");
-#endif
- }
-
/* our socks code is not fully IPv6 enabled yet (TCP works, UDP not)
* so fall back to IPv4-only (trac #1221)
*/
}
}
+ /*
+ * If --mssfix is supplied without a parameter or not specified at all,
+ * default it to --fragment value, if --fragment is specified and otherwise
+ * to the default if tun-mtu is 1500
+ */
+ if (o->ce.mssfix_default)
+ {
+#ifdef ENABLE_FRAGMENT
+ if (ce->fragment)
+ {
+ ce->mssfix = ce->fragment;
+ }
+ else
+#endif
+ if (ce->tun_mtu_defined)
+ {
+ if (o->ce.tun_mtu == TUN_MTU_DEFAULT)
+ {
+ /* We want to only set mssfix default value if we use a default
+ * MTU Size, otherwise the different size of tun should either
+ * already solve the problem or mssfix might artifically make the
+ * payload packets smaller without mssfix 0 */
+ ce->mssfix = MSSFIX_DEFAULT;
+ ce->mssfix_encap = true;
+ }
+ else
+ {
+ /* We still apply the mssfix value but only adjust it to the
+ * size of the tun interface. */
+ ce->mssfix = ce->tun_mtu;
+ ce->mssfix_fixed = true;
+ }
+ }
+ }
+
/*
* Set per-connection block tls-auth/crypt/crypto-v2 fields if undefined.
*
msg(M_WARN, "NOTICE: --explicit-exit-notify ignored for --proto tcp");
ce->explicit_exit_notification = 0;
}
-
}
#ifdef _WIN32
}
#endif
+/*
+ * Save/Restore certain option defaults before --pull is applied.
+ */
+
static void
-options_postprocess_mutate_invariant(struct options *options)
+pre_connect_save(struct options *o)
{
-#ifdef _WIN32
- const int dev = dev_type_enum(options->dev, options->dev_type);
+ ALLOC_OBJ_CLEAR_GC(o->pre_connect, struct options_pre_connect, &o->gc);
+ o->pre_connect->tuntap_options = o->tuntap_options;
+ o->pre_connect->tuntap_options_defined = true;
+ o->pre_connect->foreign_option_index = o->foreign_option_index;
- /* when using wintun, kernel doesn't send DHCP requests, so don't use it */
- if (options->windows_driver == WINDOWS_DRIVER_WINTUN
- && (options->tuntap_options.ip_win32_type == IPW32_SET_DHCP_MASQ || options->tuntap_options.ip_win32_type == IPW32_SET_ADAPTIVE))
+ if (o->routes)
{
- options->tuntap_options.ip_win32_type = IPW32_SET_NETSH;
+ o->pre_connect->routes = clone_route_option_list(o->routes, &o->gc);
+ o->pre_connect->routes_defined = true;
}
-
- if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && !options->route_delay_defined)
+ if (o->routes_ipv6)
{
- /* delay may only be necessary when we perform DHCP handshake */
- const bool dhcp = (options->tuntap_options.ip_win32_type == IPW32_SET_DHCP_MASQ)
- || (options->tuntap_options.ip_win32_type == IPW32_SET_ADAPTIVE);
- if ((options->mode == MODE_POINT_TO_POINT) && dhcp)
- {
+ o->pre_connect->routes_ipv6 = clone_route_ipv6_option_list(o->routes_ipv6, &o->gc);
+ o->pre_connect->routes_ipv6_defined = true;
+ }
+ if (o->client_nat)
+ {
+ o->pre_connect->client_nat = clone_client_nat_option_list(o->client_nat, &o->gc);
+ o->pre_connect->client_nat_defined = true;
+ }
+
+ o->pre_connect->route_default_gateway = o->route_default_gateway;
+ o->pre_connect->route_ipv6_default_gateway = o->route_ipv6_default_gateway;
+
+ o->pre_connect->dns_options = clone_dns_options(o->dns_options, &o->gc);
+
+ /* NCP related options that can be overwritten by a push */
+ o->pre_connect->ciphername = o->ciphername;
+ o->pre_connect->authname = o->authname;
+
+ /* Ping related options should be reset to the config values on reconnect */
+ o->pre_connect->ping_rec_timeout = o->ping_rec_timeout;
+ o->pre_connect->ping_rec_timeout_action = o->ping_rec_timeout_action;
+ o->pre_connect->ping_send_timeout = o->ping_send_timeout;
+
+ /* Miscellaneous Options */
+ o->pre_connect->comp = o->comp;
+}
+
+void
+pre_connect_restore(struct options *o, struct gc_arena *gc)
+{
+ const struct options_pre_connect *pp = o->pre_connect;
+ if (pp)
+ {
+ CLEAR(o->tuntap_options);
+ if (pp->tuntap_options_defined)
+ {
+ o->tuntap_options = pp->tuntap_options;
+ }
+
+ if (pp->routes_defined)
+ {
+ rol_check_alloc(o);
+ copy_route_option_list(o->routes, pp->routes, gc);
+ }
+ else
+ {
+ o->routes = NULL;
+ }
+
+ if (pp->routes_ipv6_defined)
+ {
+ rol6_check_alloc(o);
+ copy_route_ipv6_option_list(o->routes_ipv6, pp->routes_ipv6, gc);
+ }
+ else
+ {
+ o->routes_ipv6 = NULL;
+ }
+
+ o->route_default_gateway = pp->route_default_gateway;
+ o->route_ipv6_default_gateway = pp->route_ipv6_default_gateway;
+
+ /* Free DNS options and reset them to pre-pull state */
+ gc_free(&o->dns_options.gc);
+ struct gc_arena dns_gc = gc_new();
+ o->dns_options = clone_dns_options(pp->dns_options, &dns_gc);
+ o->dns_options.gc = dns_gc;
+
+ if (pp->client_nat_defined)
+ {
+ cnol_check_alloc(o);
+ copy_client_nat_option_list(o->client_nat, pp->client_nat);
+ }
+ else
+ {
+ o->client_nat = NULL;
+ }
+
+ o->foreign_option_index = pp->foreign_option_index;
+
+ o->ciphername = pp->ciphername;
+ o->authname = pp->authname;
+
+ o->ping_rec_timeout = pp->ping_rec_timeout;
+ o->ping_rec_timeout_action = pp->ping_rec_timeout_action;
+ o->ping_send_timeout = pp->ping_send_timeout;
+
+ /* Miscellaneous Options */
+ o->comp = pp->comp;
+ }
+
+ o->push_continuation = 0;
+ o->push_option_types_found = 0;
+ o->imported_protocol_flags = 0;
+}
+
+static void
+options_postprocess_mutate_invariant(struct options *options)
+{
+#ifdef _WIN32
+ const int dev = dev_type_enum(options->dev, options->dev_type);
+
+ /* when using wintun/ovpn-dco, kernel doesn't send DHCP requests, so don't use it */
+ if ((options->windows_driver == WINDOWS_DRIVER_WINTUN
+ || options->windows_driver == WINDOWS_DRIVER_DCO)
+ && (options->tuntap_options.ip_win32_type == IPW32_SET_DHCP_MASQ
+ || options->tuntap_options.ip_win32_type == IPW32_SET_ADAPTIVE))
+ {
+ options->tuntap_options.ip_win32_type = IPW32_SET_NETSH;
+ }
+
+ if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && !options->route_delay_defined)
+ {
+ /* delay may only be necessary when we perform DHCP handshake */
+ const bool dhcp = (options->tuntap_options.ip_win32_type == IPW32_SET_DHCP_MASQ)
+ || (options->tuntap_options.ip_win32_type == IPW32_SET_ADAPTIVE);
+ if ((options->mode == MODE_POINT_TO_POINT) && dhcp)
+ {
options->route_delay_defined = true;
options->route_delay = 5; /* Vista sometimes has a race without this */
}
{
options_postprocess_verify_ce(o, &o->ce);
}
+
+ dns_options_verify(M_FATAL, &o->dns_options);
+
+ if (dco_enabled(o) && o->enable_c2c)
+ {
+ msg(M_WARN, "Note: --client-to-client has no effect when using data "
+ "channel offload: packets are always sent to the VPN "
+ "interface and then routed based on the system routing table");
+ }
}
/**
/* custom --data-ciphers set, keep list */
return;
}
- else if (cipher_valid("CHACHA20-POLY1305"))
+
+ /* check if crypto library supports chacha */
+ bool can_do_chacha = cipher_valid("CHACHA20-POLY1305");
+
+ if (can_do_chacha && dco_enabled(o))
+ {
+ /* also make sure that dco supports chacha */
+ can_do_chacha = tls_item_in_cipher_list("CHACHA20-POLY1305", dco_get_supported_ciphers());
+ }
+
+ if (can_do_chacha)
{
o->ncp_ciphers = "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305";
}
o->ciphername = "BF-CBC";
msg(M_INFO, "Note: --cipher is not set. OpenVPN versions before 2.5 "
- "defaulted to BF-CBC as fallback when cipher negotiation "
- "failed in this case. If you need this fallback please add "
- "'--data-ciphers-fallback 'BF-CBC' to your configuration "
- "and/or add BF-CBC to --data-ciphers.");
+ "defaulted to BF-CBC as fallback when cipher negotiation "
+ "failed in this case. If you need this fallback please add "
+ "'--data-ciphers-fallback BF-CBC' to your configuration "
+ "and/or add BF-CBC to --data-ciphers.");
}
else if (!o->enable_ncp_fallback
&& !tls_item_in_cipher_list(o->ciphername, o->ncp_ciphers))
}
/**
- * The option --compat-mode is used to set up default settings to values
+ * The option --compat-mode is used to set up default settings to values
* used on the specified openvpn version and earlier.
*
* This function is used in various "default option" paths to test if the
* user requested compatibility with a version before the one specified
- * as argument. This way some default settings can be automatically
- * altered to guarantee compatibility with the version specified by the
+ * as argument. This way some default settings can be automatically
+ * altered to guarantee compatibility with the version specified by the
* user via --compat-mode.
*
* @param version need compatibility with openvpn versions before the
{
/* TLS min version is not set */
int tls_ver_min = (o->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT)
- & SSLF_TLS_VERSION_MIN_MASK;
+ & SSLF_TLS_VERSION_MIN_MASK;
if (tls_ver_min == 0)
{
int tls_ver_max = (o->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT)
}
}
+ if (need_compatibility_before(o, 20400))
+ {
+ if (!o->ciphername)
+ {
+ /* If ciphername is not set default to BF-CBC when targeting these
+ * old versions that do not have NCP */
+ o->ciphername = "BF-CBC";
+ }
+ /* Versions < 2.4.0 additionally might be compiled with --enable-small and
+ * not have OCC strings required for "poor man's NCP" */
+ o->enable_ncp_fallback = true;
+ }
+
/* Versions < 2.5.0 do need --cipher in the list of accepted ciphers.
- * Version 2.4 might probably does not need it but NCP was not so
+ * Version 2.4 probably does not need it but NCP was not so
* good with 2.4 and ncp-disable might be more common on 2.4 peers.
- * Only do this iif --cipher is not explicitly (BF-CBC). This is not
- * 100% correct backwards compatible behaviour but 2.5 already behaved like
- * this */
+ * Only do this iff --cipher is set (explicitly or by compat mode
+ * < 2.4.0, see above). This is not 100% correct backwards compatible
+ * behaviour but 2.5 already behaved like this */
if (o->ciphername && need_compatibility_before(o, 20500)
&& !tls_item_in_cipher_list(o->ciphername, o->ncp_ciphers))
{
append_cipher_to_ncp_list(o, o->ciphername);
}
- /* Versions < 2.4.0 additionally might be compiled with --enable-small and
- * not have OCC strings required for "poor man's NCP" */
- if (o->ciphername && need_compatibility_before(o, 20400))
- {
- o->enable_ncp_fallback = true;
- }
-
#ifdef USE_COMP
/* Compression is deprecated and we do not want to announce support for it
* by default anymore, additionally DCO breaks with compression.
*
* Disable compression by default starting with 2.6.0 if no other
* compression related option has been explicitly set */
- if (!comp_non_stub_enabled(&o->comp) && !need_compatibility_before(o, 20600)
- && (o->comp.flags == 0))
+ if (!need_compatibility_before(o, 20600) && (o->comp.flags == 0))
{
- o->comp.flags = COMP_F_ALLOW_STUB_ONLY|COMP_F_ADVERTISE_STUBS_ONLY;
+ if (!comp_non_stub_enabled(&o->comp))
+ {
+ o->comp.flags = COMP_F_ALLOW_STUB_ONLY | COMP_F_ADVERTISE_STUBS_ONLY;
+ }
}
+#else /* ifdef USE_COMP */
+ o->comp.flags = COMP_F_ALLOW_NOCOMP_ONLY;
#endif
}
static void
-options_postprocess_mutate(struct options *o)
+options_postprocess_mutate(struct options *o, struct env_set *es)
{
int i;
/*
options_set_backwards_compatible_options(o);
options_postprocess_cipher(o);
- options_postprocess_mutate_invariant(o);
-
o->ncp_ciphers = mutate_ncp_cipher_list(o->ncp_ciphers, &o->gc);
if (o->ncp_ciphers == NULL)
{
o->verify_hash_no_ca = true;
}
+ if (o->config && streq(o->config, "stdin") && o->remap_sigusr1 == SIGHUP)
+ {
+ msg(M_USAGE, "Options 'config stdin' and 'remap-usr1 SIGHUP' are "
+ "incompatible with each other.");
+ }
+
+ if (dco_enabled(o))
+ {
+ /* check if any option should force disabling DCO */
+ o->tuntap_options.disable_dco = !dco_check_option(D_DCO, o)
+ || !dco_check_startup_option(D_DCO, o);
+ }
+#ifdef USE_COMP
+ if (dco_enabled(o))
+ {
+ o->comp.flags |= COMP_F_ALLOW_NOCOMP_ONLY;
+ }
+#endif
+
+#ifdef _WIN32
+ if (dco_enabled(o))
+ {
+ o->windows_driver = WINDOWS_DRIVER_DCO;
+ }
+ else
+ {
+ if (o->windows_driver == WINDOWS_DRIVER_DCO)
+ {
+ msg(M_WARN, "Option --windows-driver ovpn-dco is ignored because Data Channel Offload is disabled");
+ o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ }
+ else if (o->windows_driver == WINDOWS_DRIVER_UNSPECIFIED)
+ {
+ o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ }
+ }
+#else /* _WIN32 */
+ if (dco_enabled(o) && o->dev_node)
+ {
+ msg(M_WARN, "Note: ignoring --dev-node as it has no effect when using "
+ "data channel offload");
+ o->dev_node = NULL;
+ }
+#endif /* _WIN32 */
+
+ /* this depends on o->windows_driver, which is set above */
+ options_postprocess_mutate_invariant(o);
+
+ /* check that compression settings in the options are okay */
+ check_compression_settings_valid(&o->comp, M_USAGE);
+
/*
* Save certain parms before modifying options during connect, especially
* when using --pull
*/
+ if (o->pull)
+ {
+ dns_options_preprocess_pull(&o->dns_options);
+ }
+ else
+ {
+#if defined(_WIN32) || defined(TARGET_ANDROID)
+ tuntap_options_copy_dns(o);
+#else
+ foreign_options_copy_dns(o, es);
+#endif
+ }
+ if (o->auth_token_generate && !o->auth_token_renewal)
+ {
+ o->auth_token_renewal = o->renegotiate_seconds;
+ }
pre_connect_save(o);
}
options->extra_certs_file, R_OK,
"--extra-certs");
-#ifdef ENABLE_MANAGMENT
if (!(options->management_flags & MF_EXTERNAL_KEY))
-#endif
{
errs |= check_file_access_inline(options->priv_key_file_inline,
CHKACC_FILE|CHKACC_PRIVATE,
options->management_user_pass, R_OK,
"--management user/password file");
#endif /* ENABLE_MANAGEMENT */
- errs |= check_file_access(CHKACC_FILE|CHKACC_ACPTSTDIN|CHKACC_PRIVATE,
- options->auth_user_pass_file, R_OK,
- "--auth-user-pass");
+ errs |= check_file_access_inline(options->auth_user_pass_file_inline,
+ CHKACC_FILE|CHKACC_ACPTSTDIN|CHKACC_PRIVATE,
+ options->auth_user_pass_file, R_OK,
+ "--auth-user-pass");
/* ** System related ** */
errs |= check_file_access(CHKACC_FILE, options->chroot_dir,
R_OK|X_OK, "--chroot directory");
R_OK|W_OK, "--status");
/* ** Config related ** */
- errs |= check_file_access_chroot(options->chroot_dir, CHKACC_FILE, options->tls_export_cert,
- R_OK|W_OK|X_OK, "--tls-export-cert");
errs |= check_file_access_chroot(options->chroot_dir, CHKACC_FILE, options->client_config_dir,
R_OK|X_OK, "--client-config-dir");
errs |= check_file_access_chroot(options->chroot_dir, CHKACC_FILE, options->tmp_dir,
* options.
*/
void
-options_postprocess(struct options *options)
+options_postprocess(struct options *options, struct env_set *es)
{
- options_postprocess_mutate(options);
+ options_postprocess_mutate(options, es);
options_postprocess_verify(options);
#ifndef ENABLE_SMALL
options_postprocess_filechecks(options);
}
/*
- * Save/Restore certain option defaults before --pull is applied.
+ * Sanity check on options after more options were pulled from server.
+ * Also time to modify some options based on other options.
*/
-
-void
-pre_connect_save(struct options *o)
-{
- ALLOC_OBJ_CLEAR_GC(o->pre_connect, struct options_pre_connect, &o->gc);
- o->pre_connect->tuntap_options = o->tuntap_options;
- o->pre_connect->tuntap_options_defined = true;
- o->pre_connect->foreign_option_index = o->foreign_option_index;
-
- if (o->routes)
- {
- o->pre_connect->routes = clone_route_option_list(o->routes, &o->gc);
- o->pre_connect->routes_defined = true;
- }
- if (o->routes_ipv6)
- {
- o->pre_connect->routes_ipv6 = clone_route_ipv6_option_list(o->routes_ipv6, &o->gc);
- o->pre_connect->routes_ipv6_defined = true;
- }
- if (o->client_nat)
- {
- o->pre_connect->client_nat = clone_client_nat_option_list(o->client_nat, &o->gc);
- o->pre_connect->client_nat_defined = true;
- }
-
- o->pre_connect->route_default_gateway = o->route_default_gateway;
- o->pre_connect->route_ipv6_default_gateway = o->route_ipv6_default_gateway;
-
- /* NCP related options that can be overwritten by a push */
- o->pre_connect->ciphername = o->ciphername;
- o->pre_connect->authname = o->authname;
-
- /* Ping related options should be reset to the config values on reconnect */
- o->pre_connect->ping_rec_timeout = o->ping_rec_timeout;
- o->pre_connect->ping_rec_timeout_action = o->ping_rec_timeout_action;
- o->pre_connect->ping_send_timeout = o->ping_send_timeout;
-
- /* Miscellaneous Options */
-#ifdef USE_COMP
- o->pre_connect->comp = o->comp;
-#endif
-}
-
-void
-pre_connect_restore(struct options *o, struct gc_arena *gc)
+bool
+options_postprocess_pull(struct options *o, struct env_set *es)
{
- const struct options_pre_connect *pp = o->pre_connect;
- if (pp)
+ bool success = dns_options_verify(D_PUSH_ERRORS, &o->dns_options);
+ if (success)
{
- CLEAR(o->tuntap_options);
- if (pp->tuntap_options_defined)
- {
- o->tuntap_options = pp->tuntap_options;
- }
-
- if (pp->routes_defined)
- {
- rol_check_alloc(o);
- copy_route_option_list(o->routes, pp->routes, gc);
- }
- else
- {
- o->routes = NULL;
- }
-
- if (pp->routes_ipv6_defined)
- {
- rol6_check_alloc(o);
- copy_route_ipv6_option_list(o->routes_ipv6, pp->routes_ipv6, gc);
- }
- else
- {
- o->routes_ipv6 = NULL;
- }
-
- o->route_default_gateway = pp->route_default_gateway;
- o->route_ipv6_default_gateway = pp->route_ipv6_default_gateway;
-
- if (pp->client_nat_defined)
- {
- cnol_check_alloc(o);
- copy_client_nat_option_list(o->client_nat, pp->client_nat);
- }
- else
- {
- o->client_nat = NULL;
- }
-
- o->foreign_option_index = pp->foreign_option_index;
-
- o->ciphername = pp->ciphername;
- o->authname = pp->authname;
-
- o->ping_rec_timeout = pp->ping_rec_timeout;
- o->ping_rec_timeout_action = pp->ping_rec_timeout_action;
- o->ping_send_timeout = pp->ping_send_timeout;
-
- /* Miscellaneous Options */
-#ifdef USE_COMP
- o->comp = pp->comp;
+ dns_options_postprocess_pull(&o->dns_options);
+ setenv_dns_options(&o->dns_options, es);
+#if defined(_WIN32) || defined(TARGET_ANDROID)
+ tuntap_options_copy_dns(o);
+#else
+ foreign_options_copy_dns(o, es);
#endif
}
-
- o->push_continuation = 0;
- o->push_option_types_found = 0;
- o->data_channel_crypto_flags = 0;
+ return success;
}
/*
*
* --cipher
* --auth
- * --keysize
* --secret
- * --no-replay
*
* SSL Options:
*
buf_printf(&out, ",link-mtu %u",
(unsigned int) calc_options_string_link_mtu(o, frame));
- buf_printf(&out, ",tun-mtu %d", PAYLOAD_SIZE(frame));
+ if (o->ce.occ_mtu != 0)
+ {
+ buf_printf(&out, ",tun-mtu %d", o->ce.occ_mtu);
+ }
+ else
+ {
+ buf_printf(&out, ",tun-mtu %d", frame->tun_mtu);
+ }
+
buf_printf(&out, ",proto %s", proto_remote(o->ce.proto, remote));
bool p2p_nopull = o->mode == MODE_POINT_TO_POINT && !PULL_DEFINED(o);
NULL,
false,
NULL,
- ctx);
+ ctx,
+ NULL);
if (tt)
{
tt_local = true;
{
buf_printf(&out, ",secret");
}
- if (!o->replay)
- {
- buf_printf(&out, ",no-replay");
- }
#ifdef ENABLE_PREDICTION_RESISTANCE
if (o->use_prediction_resistance)
if (actual_n > 0)
{
actual[actual_n - 1] = 0;
-#ifndef ENABLE_STRICT_OPTIONS_CHECK
if (strncmp(actual, expected, 2))
{
msg(D_SHOW_OCC, "NOTE: Options consistency check may be skewed by version differences");
options_warning_safe_ml(D_SHOW_OCC, actual, expected, actual_n);
}
else
-#endif
- ret = !strcmp(actual, expected);
+ {
+ ret = !strcmp(actual, expected);
+ }
}
gc_free(&gc);
return ret;
void
options_warning_safe(char *actual, const char *expected, size_t actual_n)
{
- options_warning_safe_ml(M_WARN, actual, expected, actual_n);
+ options_warning_safe_ml(D_SHOW_OCC, actual, expected, actual_n);
}
const char *
}
char *
-options_string_extract_option(const char *options_string,const char *opt_name,
+options_string_extract_option(const char *options_string, const char *opt_name,
struct gc_arena *gc)
{
char *ret = NULL;
return ret;
}
-static void
-foreign_option(struct options *o, char *argv[], int len, struct env_set *es)
-{
- if (len > 0)
- {
- struct gc_arena gc = gc_new();
- struct buffer name = alloc_buf_gc(OPTION_PARM_SIZE, &gc);
- struct buffer value = alloc_buf_gc(OPTION_PARM_SIZE, &gc);
- int i;
- bool first = true;
- bool good = true;
-
- good &= buf_printf(&name, "foreign_option_%d", o->foreign_option_index + 1);
- ++o->foreign_option_index;
- for (i = 0; i < len; ++i)
- {
- if (argv[i])
- {
- if (!first)
- {
- good &= buf_printf(&value, " ");
- }
- good &= buf_printf(&value, "%s", argv[i]);
- first = false;
- }
- }
- if (good)
- {
- setenv_str(es, BSTR(&name), BSTR(&value));
- }
- else
- {
- msg(M_WARN, "foreign_option: name/value overflow");
- }
- gc_free(&gc);
- }
-}
-
#ifdef _WIN32
/**
* Parses --windows-driver config option
{
return WINDOWS_DRIVER_WINTUN;
}
+
+ else if (streq(str, "ovpn-dco"))
+ {
+ return WINDOWS_DRIVER_DCO;
+ }
else
{
- msg(msglevel, "--windows-driver must be tap-windows6 or wintun");
+ msg(msglevel, "--windows-driver must be tap-windows6, wintun "
+ "or ovpn-dco");
return WINDOWS_DRIVER_UNSPECIFIED;
}
}
-#endif
+#endif /* ifdef _WIN32 */
/*
* parse/print topology coding
o.ce.local_port, o.ce.remote_port,
TUN_MTU_DEFAULT, TAP_MTU_EXTRA_DEFAULT,
o.verbosity,
- o.authname, o.ciphername,
+ o.authname,
o.replay_window, o.replay_time,
o.tls_timeout, o.renegotiate_seconds,
o.handshake_window, o.transition_window);
}
#endif
+void
+show_dco_version(const unsigned int flags)
+{
+#ifdef ENABLE_DCO
+ struct gc_arena gc = gc_new();
+ msg(flags, "DCO version: %s", dco_version_string(&gc));
+ gc_free(&gc);
+#endif
+}
+
void
show_library_versions(const unsigned int flags)
{
#ifdef _WIN32
show_windows_version( M_INFO|M_NOPREFIX );
#endif
+ show_dco_version(M_INFO | M_NOPREFIX);
msg(M_INFO|M_NOPREFIX, "Originally developed by James Yonan");
- msg(M_INFO|M_NOPREFIX, "Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>");
+ msg(M_INFO|M_NOPREFIX, "Copyright (C) 2002-2023 OpenVPN Inc <sales@openvpn.net>");
#ifndef ENABLE_SMALL
#ifdef CONFIGURE_DEFINES
msg(M_INFO|M_NOPREFIX, "Compile time defines: %s", CONFIGURE_DEFINES);
unsigned int *option_types_found,
struct env_set *es)
{
- int i, j;
-
/* usage message */
if (argc <= 1)
{
/* config filename specified only? */
if (argc == 2 && strncmp(argv[1], "--", 2))
{
- char *p[MAX_PARMS];
+ char *p[MAX_PARMS+1];
CLEAR(p);
p[0] = "config";
p[1] = argv[1];
else
{
/* parse command line */
- for (i = 1; i < argc; ++i)
+ for (int i = 1; i < argc; ++i)
{
- char *p[MAX_PARMS];
+ char *p[MAX_PARMS+1];
CLEAR(p);
p[0] = argv[i];
if (strncmp(p[0], "--", 2))
p[0] += 2;
}
+ int j;
for (j = 1; j < MAX_PARMS; ++j)
{
if (i + j < argc)
return true;
}
+ /* skip leading spaces matching the behaviour of parse_line */
+ while (isspace(*line))
+ {
+ line++;
+ }
+
for (f = o->pull_filter_list->head; f; f = f->next)
{
if (f->type == PUF_TYPE_ACCEPT && strncmp(line, f->pattern, f->size) == 0)
#endif
}
-#ifdef USE_COMP
static void
show_compression_warning(struct compress_options *info)
{
}
}
}
-#endif
-bool key_is_external(const struct options *options)
+bool
+key_is_external(const struct options *options)
{
bool ret = false;
-#ifdef ENABLE_MANAGEMENT
ret = ret || (options->management_flags & MF_EXTERNAL_KEY);
-#endif
#ifdef ENABLE_PKCS11
ret = ret || (options->pkcs11_providers[0] != NULL);
#endif
print_default_gateway(M_INFO, &rgi, &rgi6);
openvpn_exit(OPENVPN_EXIT_STATUS_GOOD); /* exit point */
}
-#endif
-#if 0
- else if (streq(p[0], "foreign-option") && p[1])
- {
- VERIFY_PERMISSION(OPT_P_IPWIN32);
- foreign_option(options, p, 3, es);
- }
#endif
else if (streq(p[0], "echo") || streq(p[0], "parameter"))
{
VERIFY_PERMISSION(OPT_P_GENERAL);
options->management_flags |= MF_UP_DOWN;
}
- else if (streq(p[0], "management-client") && !p[2])
+ else if (streq(p[0], "management-client") && !p[1])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
options->management_flags |= MF_CONNECT_AS_CLIENT;
- options->management_write_peer_info_file = p[1];
}
-#ifdef ENABLE_MANAGEMENT
else if (streq(p[0], "management-external-key"))
{
VERIFY_PERMISSION(OPT_P_GENERAL);
{
options->management_flags |= MF_EXTERNAL_KEY_PKCS1PAD;
}
+ else if (streq(p[j], "pss"))
+ {
+ options->management_flags |= MF_EXTERNAL_KEY_PSSPAD;
+ }
+ else if (streq(p[j], "digest"))
+ {
+ options->management_flags |= MF_EXTERNAL_KEY_DIGEST;
+ }
else
{
msg(msglevel, "Unknown management-external-key flag: %s", p[j]);
VERIFY_PERMISSION(OPT_P_GENERAL);
options->management_flags |= MF_CLIENT_AUTH;
}
-#endif /* ifdef ENABLE_MANAGEMENT */
else if (streq(p[0], "management-log-cache") && p[1] && !p[2])
{
int cache;
options->windows_driver = parse_windows_driver(p[1], M_FATAL);
}
#endif
+ else if (streq(p[0], "disable-dco"))
+ {
+ options->tuntap_options.disable_dco = true;
+ }
else if (streq(p[0], "dev-node") && p[1] && !p[2])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
options->ce.link_mtu = positive_atoi(p[1]);
options->ce.link_mtu_defined = true;
}
- else if (streq(p[0], "tun-mtu") && p[1] && !p[2])
+ else if (streq(p[0], "tun-mtu") && p[1] && !p[3])
{
- VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION);
+ VERIFY_PERMISSION(OPT_P_PUSH_MTU|OPT_P_CONNECTION);
options->ce.tun_mtu = positive_atoi(p[1]);
options->ce.tun_mtu_defined = true;
+ if (p[2])
+ {
+ options->ce.occ_mtu = positive_atoi(p[2]);
+ }
+ else
+ {
+ options->ce.occ_mtu = 0;
+ }
+ }
+ else if (streq(p[0], "tun-mtu-max") && p[1] && !p[3])
+ {
+ VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION);
+ int max_mtu = positive_atoi(p[1]);
+ if (max_mtu < 68 || max_mtu > 65536)
+ {
+ msg(msglevel, "--tun-mtu-max value '%s' is invalid", p[1]);
+ }
+ else
+ {
+ options->ce.tun_mtu_max = max_mtu;
+ }
}
else if (streq(p[0], "tun-mtu-extra") && p[1] && !p[2])
{
options->ce.tun_mtu_extra = positive_atoi(p[1]);
options->ce.tun_mtu_extra_defined = true;
}
+ else if (streq(p[0], "max-packet-size") && p[1] && !p[2])
+ {
+ VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION);
+ int maxmtu = positive_atoi(p[1]);
+ options->ce.tls_mtu = constrain_int(maxmtu, TLS_CHANNEL_MTU_MIN, TLS_CHANNEL_BUF_SIZE);
+
+ if (maxmtu < TLS_CHANNEL_MTU_MIN || maxmtu > TLS_CHANNEL_BUF_SIZE)
+ {
+ msg(M_WARN, "Note: max-packet-size value outside of allowed "
+ "control channel packet size (%d to %d), will use %d "
+ "instead.", TLS_CHANNEL_MTU_MIN, TLS_CHANNEL_BUF_SIZE,
+ options->ce.tls_mtu);
+ }
+
+ /* also set mssfix maxmtu mtu */
+ options->ce.mssfix = maxmtu;
+ options->ce.mssfix_default = false;
+ options->ce.mssfix_encap = true;
+ }
#ifdef ENABLE_FRAGMENT
else if (streq(p[0], "mtu-dynamic"))
{
msg(msglevel, "--mtu-dynamic has been replaced by --fragment");
goto err;
}
- else if (streq(p[0], "fragment") && p[1] && !p[2])
+ else if (streq(p[0], "fragment") && p[1] && !p[3])
{
-/* VERIFY_PERMISSION (OPT_P_MTU); */
VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION);
options->ce.fragment = positive_atoi(p[1]);
+
+ if (options->ce.fragment < 68)
+ {
+ msg(msglevel, "--fragment needs to be at least 68");
+ goto err;
+ }
+
+ if (p[2] && streq(p[2], "mtu"))
+ {
+ options->ce.fragment_encap = true;
+ }
+ else if (p[2])
+ {
+ msg(msglevel, "Unknown parameter to --fragment: %s", p[2]);
+ }
}
-#endif
+#endif /* ifdef ENABLE_FRAGMENT */
else if (streq(p[0], "mtu-disc") && p[1] && !p[2])
{
VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION);
}
}
#ifdef TARGET_LINUX
- else if (streq (p[0], "bind-dev") && p[1])
+ else if (streq(p[0], "bind-dev") && p[1])
{
- VERIFY_PERMISSION (OPT_P_SOCKFLAGS);
+ VERIFY_PERMISSION(OPT_P_SOCKFLAGS);
options->bind_dev = p[1];
}
#endif
options->inactivity_timeout = positive_atoi(p[1]);
if (p[2])
{
- options->inactivity_minimum_bytes = positive_atoi(p[2]);
+ int64_t val = atoll(p[2]);
+ options->inactivity_minimum_bytes = (val < 0) ? 0 : val;
+ if (options->inactivity_minimum_bytes > INT_MAX)
+ {
+ msg(M_WARN, "WARNING: '--inactive' with a 'bytes' value"
+ " >2 Gbyte was silently ignored in older versions. If "
+ " your VPN exits unexpectedly with 'Inactivity timeout'"
+ " in %d seconds, revisit this value.",
+ options->inactivity_timeout );
+ }
}
}
+ else if (streq(p[0], "session-timeout") && p[1] && !p[2])
+ {
+ VERIFY_PERMISSION(OPT_P_TIMER);
+ options->session_timeout = positive_atoi(p[1]);
+ }
else if (streq(p[0], "proto") && p[1] && !p[2])
{
int proto;
if (p[3])
{
/* auto -- try to figure out proxy addr, port, and type automatically */
- /* semiauto -- given proxy addr:port, try to figure out type automatically */
- /* (auto|semiauto)-nct -- disable proxy auth cleartext protocols (i.e. basic auth) */
+ /* auto-nct -- disable proxy auth cleartext protocols (i.e. basic auth) */
if (streq(p[3], "auto"))
{
ho->auth_retry = PAR_ALL;
VERIFY_PERMISSION(OPT_P_GENERAL);
script_security_set(atoi(p[1]));
}
- else if (streq(p[0], "mssfix") && !p[2])
+ else if (streq(p[0], "mssfix") && !p[3])
{
VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION);
if (p[1])
{
- options->ce.mssfix = positive_atoi(p[1]);
+ int mssfix = positive_atoi(p[1]);
+ /* can be 0, but otherwise it needs to be high enough so we can
+ * substract room for headers. */
+ if (mssfix != 0
+ && (mssfix < TLS_CHANNEL_MTU_MIN || mssfix > UINT16_MAX))
+ {
+ msg(msglevel, "--mssfix value '%s' is invalid", p[1]);
+ goto err;
+ }
+
+ /* value specified, assume encapsulation is not
+ * included unless "mtu" follows later */
+ options->ce.mssfix = mssfix;
+ options->ce.mssfix_encap = false;
+ options->ce.mssfix_default = false;
}
else
{
+ /* Set MTU to default values */
options->ce.mssfix_default = true;
+ options->ce.mssfix_encap = true;
+ options->ce.mssfix_fixed = false;
}
+ if (p[2] && streq(p[2], "mtu"))
+ {
+ options->ce.mssfix_encap = true;
+ }
+ else if (p[2] && streq(p[2], "fixed"))
+ {
+ options->ce.mssfix_fixed = true;
+ }
+ else if (p[2])
+ {
+ msg(msglevel, "Unknown parameter to --mssfix: %s", p[2]);
+ }
}
else if (streq(p[0], "disable-occ") && !p[1])
{
{
VERIFY_PERMISSION(OPT_P_INSTANCE);
msg(D_PUSH, "PUSH_REMOVE '%s'", p[1]);
- push_remove_option(options,p[1]);
+ push_remove_option(options, p[1]);
}
else if (streq(p[0], "ifconfig-pool") && p[1] && p[2] && !p[4])
{
options->cf_max = cf_max;
options->cf_per = cf_per;
}
+ else if (streq(p[0], "connect-freq-initial") && p[1] && p[2] && !p[3])
+ {
+ long cf_max, cf_per;
+
+ VERIFY_PERMISSION(OPT_P_GENERAL);
+ char *e1, *e2;
+ cf_max = strtol(p[1], &e1, 10);
+ cf_per = strtol(p[2], &e2, 10);
+ if (cf_max < 0 || cf_per < 0 || *e1 != '\0' || *e2 != '\0')
+ {
+ msg(msglevel, "--connect-freq-initial parameters must be integers and >= 0");
+ goto err;
+ }
+ options->cf_initial_max = cf_max;
+ options->cf_initial_per = cf_per;
+ }
else if (streq(p[0], "max-clients") && p[1] && !p[2])
{
int max_clients;
else if (streq(p[0], "opt-verify") && !p[1])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
+ msg(M_INFO, "DEPRECATION: opt-verify is deprecated and will be removed "
+ "in OpenVPN 2.7");
options->ssl_flags |= SSLF_OPT_VERIFY;
}
else if (streq(p[0], "auth-user-pass-verify") && p[1])
&options->auth_user_pass_verify_script,
p[1], "auth-user-pass-verify", true);
}
- else if (streq(p[0], "auth-gen-token") && !p[3])
+ else if (streq(p[0], "auth-gen-token"))
{
VERIFY_PERMISSION(OPT_P_GENERAL);
options->auth_token_generate = true;
options->auth_token_lifetime = p[1] ? positive_atoi(p[1]) : 0;
- if (p[2])
+
+ for (int i = 2; i < MAX_PARMS && p[i] != NULL; i++)
{
- if (streq(p[2], "external-auth"))
+ /* the second parameter can be the renewal time */
+ if (i == 2 && positive_atoi(p[i]))
+ {
+ options->auth_token_renewal = positive_atoi(p[i]);
+ }
+ else if (streq(p[i], "external-auth"))
{
options->auth_token_call_auth = true;
}
else
{
- msg(msglevel, "Invalid argument to auth-gen-token: %s", p[2]);
+ msg(msglevel, "Invalid argument to auth-gen-token: %s (%d)", p[i], i);
}
}
set_user_script(options, &options->client_connect_script,
p[1], "client-connect", true);
}
+ else if (streq(p[0], "client-crresponse") && p[1])
+ {
+ VERIFY_PERMISSION(OPT_P_SCRIPT);
+ if (!no_more_than_n_args(msglevel, p, 2, NM_QUOTE_HINT))
+ {
+ goto err;
+ }
+ set_user_script(options, &options->client_crresponse_script,
+ p[1], "client-crresponse", true);
+ }
else if (streq(p[0], "client-disconnect") && p[1])
{
VERIFY_PERMISSION(OPT_P_SCRIPT);
}
else if (streq(p[0], "iroute") && p[1] && !p[3])
{
- const char *netmask = NULL;
-
VERIFY_PERMISSION(OPT_P_INSTANCE);
- if (p[2])
- {
- netmask = p[2];
- }
- option_iroute(options, p[1], netmask, msglevel);
+ option_iroute(options, p[1], p[2], msglevel);
}
else if (streq(p[0], "iroute-ipv6") && p[1] && !p[2])
{
}
else if (streq(p[0], "auth-user-pass") && !p[2])
{
- VERIFY_PERMISSION(OPT_P_GENERAL);
+ VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_INLINE);
if (p[1])
{
options->auth_user_pass_file = p[1];
+ options->auth_user_pass_file_inline = is_inline;
}
else
{
#ifdef _WIN32
VERIFY_PERMISSION(OPT_P_GENERAL);
HANDLE process = GetCurrentProcess();
- HANDLE handle = (HANDLE) atoll(p[1]);
+ HANDLE handle = (HANDLE) ((intptr_t) atoll(p[1]));
if (!DuplicateHandle(process, handle, process, &options->msg_channel, 0,
FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
{
const int index = ascii2ipset(p[1]);
struct tuntap_options *to = &options->tuntap_options;
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
if (index < 0)
{
to->ip_win32_defined = true;
}
#endif /* ifdef _WIN32 */
+ else if (streq(p[0], "dns") && p[1])
+ {
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
+
+ if (streq(p[1], "search-domains") && p[2])
+ {
+ dns_domain_list_append(&options->dns_options.search_domains, &p[2], &options->dns_options.gc);
+ }
+ else if (streq(p[1], "server") && p[2] && p[3] && p[4])
+ {
+ long priority;
+ if (!dns_server_priority_parse(&priority, p[2], pull_mode))
+ {
+ msg(msglevel, "--dns server: invalid priority value '%s'", p[2]);
+ goto err;
+ }
+
+ struct dns_server *server = dns_server_get(&options->dns_options.servers, priority, &options->dns_options.gc);
+
+ if (streq(p[3], "address") && p[4])
+ {
+ for (int i = 4; p[i]; ++i)
+ {
+ if (!dns_server_addr_parse(server, p[i]))
+ {
+ msg(msglevel, "--dns server %ld: malformed address or maximum exceeded '%s'", priority, p[i]);
+ goto err;
+ }
+ }
+ }
+ else if (streq(p[3], "resolve-domains"))
+ {
+ dns_domain_list_append(&server->domains, &p[4], &options->dns_options.gc);
+ }
+ else if (streq(p[3], "dnssec") && !p[5])
+ {
+ if (streq(p[4], "yes"))
+ {
+ server->dnssec = DNS_SECURITY_YES;
+ }
+ else if (streq(p[4], "no"))
+ {
+ server->dnssec = DNS_SECURITY_NO;
+ }
+ else if (streq(p[4], "optional"))
+ {
+ server->dnssec = DNS_SECURITY_OPTIONAL;
+ }
+ else
+ {
+ msg(msglevel, "--dns server %ld: malformed dnssec value '%s'", priority, p[4]);
+ goto err;
+ }
+ }
+ else if (streq(p[3], "transport") && !p[5])
+ {
+ if (streq(p[4], "plain"))
+ {
+ server->transport = DNS_TRANSPORT_PLAIN;
+ }
+ else if (streq(p[4], "DoH"))
+ {
+ server->transport = DNS_TRANSPORT_HTTPS;
+ }
+ else if (streq(p[4], "DoT"))
+ {
+ server->transport = DNS_TRANSPORT_TLS;
+ }
+ else
+ {
+ msg(msglevel, "--dns server %ld: malformed transport value '%s'", priority, p[4]);
+ goto err;
+ }
+ }
+ else if (streq(p[3], "sni") && !p[5])
+ {
+ server->sni = p[4];
+ }
+ else
+ {
+ msg(msglevel, "--dns server %ld: unknown option type '%s' or missing or unknown parameter", priority, p[3]);
+ goto err;
+ }
+ }
+ else
+ {
+ msg(msglevel, "--dns: unknown option type '%s' or missing or unknown parameter", p[1]);
+ goto err;
+ }
+ }
#if defined(_WIN32) || defined(TARGET_ANDROID)
else if (streq(p[0], "dhcp-option") && p[1])
{
struct tuntap_options *o = &options->tuntap_options;
- VERIFY_PERMISSION(OPT_P_IPWIN32);
- bool ipv6dns = false;
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
if ((streq(p[1], "DOMAIN") || streq(p[1], "ADAPTER_DOMAIN_SUFFIX"))
&& p[2] && !p[3])
{
o->domain = p[2];
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_OPTIONAL;
}
else if (streq(p[1], "NBS") && p[2] && !p[3])
{
o->netbios_scope = p[2];
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
else if (streq(p[1], "NBT") && p[2] && !p[3])
{
goto err;
}
o->netbios_node_type = t;
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
else if ((streq(p[1], "DNS") || streq(p[1], "DNS6")) && p[2] && !p[3]
- && (!strstr(p[2], ":") || ipv6_addr_safe(p[2])))
+ && (!strstr(p[2], ":") || ipv6_addr_safe(p[2])))
{
if (strstr(p[2], ":"))
{
- ipv6dns = true;
- foreign_option(options, p, 3, es);
dhcp_option_dns6_parse(p[2], o->dns6, &o->dns6_len, msglevel);
}
else
{
dhcp_option_address_parse("DNS", p[2], o->dns, &o->dns_len, msglevel);
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_OPTIONAL;
}
}
else if (streq(p[1], "WINS") && p[2] && !p[3])
{
dhcp_option_address_parse("WINS", p[2], o->wins, &o->wins_len, msglevel);
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_OPTIONAL;
}
else if (streq(p[1], "NTP") && p[2] && !p[3])
{
dhcp_option_address_parse("NTP", p[2], o->ntp, &o->ntp_len, msglevel);
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
else if (streq(p[1], "NBDD") && p[2] && !p[3])
{
dhcp_option_address_parse("NBDD", p[2], o->nbdd, &o->nbdd_len, msglevel);
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
else if (streq(p[1], "DOMAIN-SEARCH") && p[2] && !p[3])
{
msg(msglevel, "--dhcp-option %s: maximum of %d search entries can be specified",
p[1], N_SEARCH_LIST_LEN);
}
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
else if (streq(p[1], "DISABLE-NBT") && !p[2])
{
o->disable_nbt = 1;
+ o->dhcp_options |= DHCP_OPTIONS_DHCP_REQUIRED;
}
#if defined(TARGET_ANDROID)
else if (streq(p[1], "PROXY_HTTP") && p[3] && !p[4])
msg(msglevel, "--dhcp-option: unknown option type '%s' or missing or unknown parameter", p[1]);
goto err;
}
-
- /* flag that we have options to give to the TAP driver's DHCPv4 server
- * - skipped for "DNS6", as that's not a DHCPv4 option
- */
- if (!ipv6dns)
- {
- o->dhcp_options = true;
- }
}
#endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */
#ifdef _WIN32
else if (streq(p[0], "tap-sleep") && p[1] && !p[2])
{
int s;
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
s = atoi(p[1]);
if (s < 0 || s >= 256)
{
}
else if (streq(p[0], "dhcp-renew") && !p[1])
{
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
options->tuntap_options.dhcp_renew = true;
}
else if (streq(p[0], "dhcp-pre-release") && !p[1])
{
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
options->tuntap_options.dhcp_pre_release = true;
options->tuntap_options.dhcp_renew = true;
}
}
else if (streq(p[0], "register-dns") && !p[1])
{
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
options->tuntap_options.register_dns = true;
}
else if (streq(p[0], "block-outside-dns") && !p[1])
{
- VERIFY_PERMISSION(OPT_P_IPWIN32);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
options->block_outside_dns = true;
}
else if (streq(p[0], "rdns-internal") && !p[1])
}
else if (streq(p[0], "dhcp-option") && p[1] && !p[3])
{
- VERIFY_PERMISSION(OPT_P_IPWIN32);
- foreign_option(options, p, 3, es);
+ VERIFY_PERMISSION(OPT_P_DHCPDNS);
+ setenv_foreign_option(options, (const char **)p, 3, es);
}
else if (streq(p[0], "route-method") && p[1] && !p[2]) /* ignore when pushed to non-Windows OS */
{
options->passtos = true;
}
#endif
-#if defined(USE_COMP)
else if (streq(p[0], "allow-compression") && p[1] && !p[2])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
/* All lzo variants do not use swap */
options->comp.flags &= ~COMP_F_SWAP;
-#if defined(ENABLE_LZO)
+
if (p[1] && streq(p[1], "no"))
-#endif
{
options->comp.alg = COMP_ALG_STUB;
options->comp.flags &= ~COMP_F_ADAPTIVE;
}
-#if defined(ENABLE_LZO)
- else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
- {
- /* Also printed on a push to hint at configuration problems */
- msg(msglevel, "Cannot set comp-lzo to '%s', "
- "allow-compression is set to 'no'", p[1]);
- goto err;
- }
else if (p[1])
{
if (streq(p[1], "yes"))
options->comp.flags |= COMP_F_ADAPTIVE;
}
show_compression_warning(&options->comp);
-#endif /* if defined(ENABLE_LZO) */
}
else if (streq(p[0], "comp-noadapt") && !p[1])
{
else if (streq(p[0], "compress") && !p[2])
{
VERIFY_PERMISSION(OPT_P_COMP);
+ const char *alg = "stub";
if (p[1])
{
- if (streq(p[1], "stub"))
- {
- options->comp.alg = COMP_ALG_STUB;
- options->comp.flags |= (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
- }
- else if (streq(p[1], "stub-v2"))
- {
- options->comp.alg = COMP_ALGV2_UNCOMPRESSED;
- options->comp.flags |= COMP_F_ADVERTISE_STUBS_ONLY;
- }
- else if (streq(p[1], "migrate"))
- {
- options->comp.alg = COMP_ALG_UNDEF;
- options->comp.flags = COMP_F_MIGRATE;
-
- }
- else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
- {
- /* Also printed on a push to hint at configuration problems */
- msg(msglevel, "Cannot set compress to '%s', "
- "allow-compression is set to 'no'", p[1]);
- goto err;
- }
-#if defined(ENABLE_LZO)
- else if (streq(p[1], "lzo"))
- {
- options->comp.alg = COMP_ALG_LZO;
- options->comp.flags &= ~(COMP_F_ADAPTIVE | COMP_F_SWAP);
- }
-#endif
-#if defined(ENABLE_LZ4)
- else if (streq(p[1], "lz4"))
- {
- options->comp.alg = COMP_ALG_LZ4;
- options->comp.flags |= COMP_F_SWAP;
- }
- else if (streq(p[1], "lz4-v2"))
- {
- options->comp.alg = COMP_ALGV2_LZ4;
- }
-#endif
- else
- {
- msg(msglevel, "bad comp option: %s", p[1]);
- goto err;
- }
+ alg = p[1];
}
- else
+
+ if (streq(alg, "stub"))
{
options->comp.alg = COMP_ALG_STUB;
+ options->comp.flags |= (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
+ }
+ else if (streq(alg, "stub-v2"))
+ {
+ options->comp.alg = COMP_ALGV2_UNCOMPRESSED;
+ options->comp.flags |= COMP_F_ADVERTISE_STUBS_ONLY;
+ }
+ else if (streq(alg, "migrate"))
+ {
+ options->comp.alg = COMP_ALG_UNDEF;
+ options->comp.flags = COMP_F_MIGRATE;
+ }
+ else if (streq(alg, "lzo"))
+ {
+ options->comp.alg = COMP_ALG_LZO;
+ options->comp.flags &= ~(COMP_F_ADAPTIVE | COMP_F_SWAP);
+ }
+ else if (streq(alg, "lz4"))
+ {
+ options->comp.alg = COMP_ALG_LZ4;
options->comp.flags |= COMP_F_SWAP;
}
+ else if (streq(alg, "lz4-v2"))
+ {
+ options->comp.alg = COMP_ALGV2_LZ4;
+ }
+ else
+ {
+ msg(msglevel, "bad comp option: %s", alg);
+ goto err;
+ }
+
show_compression_warning(&options->comp);
}
-#endif /* USE_COMP */
else if (streq(p[0], "show-ciphers") && !p[1])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
}
}
}
+ else if (streq(p[0], "allow-deprecated-insecure-static-crypto"))
+ {
+ VERIFY_PERMISSION(OPT_P_GENERAL);
+ options->allow_deprecated_insecure_static_crypto = true;
+
+ }
else if (streq(p[0], "genkey") && !p[4])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
}
else if (streq(p[0], "key-derivation") && p[1])
{
+ /* NCP only option that is pushed by the server to enable EKM,
+ * should not be used by normal users in config files*/
VERIFY_PERMISSION(OPT_P_NCP)
#ifdef HAVE_EXPORT_KEYING_MATERIAL
if (streq(p[1], "tls-ekm"))
{
- options->data_channel_crypto_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
+ options->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
}
else
#endif
msg(msglevel, "Unknown key-derivation method %s", p[1]);
}
}
+ else if (streq(p[0], "protocol-flags") && p[1])
+ {
+ /* NCP only option that is pushed by the server to enable protocol
+ * features that are negotiated, should not be used by normal users
+ * in config files */
+ VERIFY_PERMISSION(OPT_P_NCP)
+ for (size_t j = 1; j < MAX_PARMS && p[j] != NULL; j++)
+ {
+ if (streq(p[j], "cc-exit"))
+ {
+ options->imported_protocol_flags |= CO_USE_CC_EXIT_NOTIFY;
+ }
+#ifdef HAVE_EXPORT_KEYING_MATERIAL
+ else if (streq(p[j], "tls-ekm"))
+ {
+ options->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
+ }
+ else if (streq(p[j], "dyn-tls-crypt"))
+ {
+ options->imported_protocol_flags |= CO_USE_DYNAMIC_TLS_CRYPT;
+ }
+#endif
+ else
+ {
+ msg(msglevel, "Unknown protocol-flags flag: %s", p[j]);
+ }
+ }
+ }
else if (streq(p[0], "prng") && p[1] && !p[3])
{
msg(M_WARN, "NOTICE: --prng option ignored (SSL library PRNG is used)");
else if (streq(p[0], "no-replay") && !p[1])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
- options->replay = false;
+ /* always error out, this breaks the connection */
+ msg(M_FATAL, "--no-replay was removed in OpenVPN 2.7. "
+ "Update your configuration.");
}
else if (streq(p[0], "replay-window") && !p[3])
{
#endif /* ENABLE_CRYPTO_MBEDTLS */
else if (streq(p[0], "providers") && p[1])
{
- for (size_t j = 1; j < MAX_PARMS && p[j] != NULL;j++)
+ for (size_t j = 1; j < MAX_PARMS && p[j] != NULL; j++)
{
options->providers.names[j] = p[j];
}
if (streq(p[0], "verify-hash"))
{
msg(M_WARN, "DEPRECATED OPTION: The option --verify-hash is deprecated. "
- "You should switch to the either use the level 1 certificate as "
- "--ca option, use --tls-verify or use --peer-fingerprint");
+ "You should switch to the either use the level 1 certificate as "
+ "--ca option, use --tls-verify or use --peer-fingerprint");
/* verify level 1 cert, i.e. the CA that signed the leaf cert */
verify_hash_depth = 1;
}
if (options->verify_hash && options->verify_hash_depth != verify_hash_depth)
{
msg(msglevel, "ERROR: Setting %s not allowed. --verify-hash and"
- " --peer-fingerprint are mutually exclusive", p[0]);
+ " --peer-fingerprint are mutually exclusive", p[0]);
goto err;
}
else if (p[2] && !streq(p[2], "SHA256"))
{
msg(msglevel, "invalid or unsupported hashing algorithm: %s "
- "(only SHA1 and SHA256 are supported)", p[2]);
+ "(only SHA1 and SHA256 are supported)", p[2]);
goto err;
}
}
listend->next = newlist;
}
}
-#ifdef ENABLE_CRYPTOAPI
+#if defined(ENABLE_CRYPTOAPI) && defined(HAVE_XKEY_PROVIDER)
else if (streq(p[0], "cryptoapicert") && p[1] && !p[2])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
string_substitute(p[1], ',', ' ', &options->gc),
"tls-verify", true);
}
-#ifndef ENABLE_CRYPTO_MBEDTLS
- else if (streq(p[0], "tls-export-cert") && p[1] && !p[2])
- {
- VERIFY_PERMISSION(OPT_P_GENERAL);
- options->tls_export_cert = p[1];
- }
-#endif
else if (streq(p[0], "compat-names"))
{
VERIFY_PERMISSION(OPT_P_GENERAL);
}
else if (streq(p[0], "ns-cert-type") && p[1] && !p[2])
{
+#ifdef ENABLE_CRYPTO_MBEDTLS
+ msg(msglevel, "--ns-cert-type is not available with mbedtls.");
+ goto err;
+#else
VERIFY_PERMISSION(OPT_P_GENERAL);
if (streq(p[1], "server"))
{
msg(msglevel, "--ns-cert-type must be 'client' or 'server'");
goto err;
}
+#endif /* ENABLE_CRYPTO_MBEDTLS */
}
else if (streq(p[0], "remote-cert-ku"))
{
options->ce.tls_crypt_v2_file = p[1];
options->ce.tls_crypt_v2_file_inline = is_inline;
}
+
+ if (p[2] && streq(p[2], "force-cookie"))
+ {
+ options->ce.tls_crypt_v2_force_cookie = true;
+ }
+ else if (p[2] && streq(p[2], "allow-noncookie"))
+ {
+ options->ce.tls_crypt_v2_force_cookie = false;
+ }
+ else if (p[2])
+ {
+ msg(msglevel, "Unsupported tls-crypt-v2 argument: %s", p[2]);
+ }
}
else if (streq(p[0], "tls-crypt-v2-verify") && p[1] && !p[2])
{
else
{
int i;
- int msglevel = msglevel_fc;
+ int msglevel_unknown = msglevel_fc;
/* Check if an option is in --ignore-unknown-option and
* set warning level to non fatal */
for (i = 0; options->ignore_unknown_option && options->ignore_unknown_option[i]; i++)
{
if (streq(p[0], options->ignore_unknown_option[i]))
{
- msglevel = M_WARN;
+ msglevel_unknown = M_WARN;
break;
}
}
if (file)
{
- msg(msglevel, "Unrecognized option or missing or extra parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION);
+ msg(msglevel_unknown, "Unrecognized option or missing or extra parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION);
}
else
{
- msg(msglevel, "Unrecognized option or missing or extra parameter(s): --%s (%s)", p[0], PACKAGE_VERSION);
+ msg(msglevel_unknown, "Unrecognized option or missing or extra parameter(s): --%s (%s)", p[0], PACKAGE_VERSION);
}
}
err: