| /* |
| * OpenVPN -- An application to securely tunnel IP networks |
| * over a single UDP port, with support for SSL/TLS-based |
| * session authentication and key exchange, |
| * packet encryption, packet authentication, and |
| * packet compression. |
| * |
| * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> |
| * Copyright (C) 2008-2013 David Sommerseth <dazo@users.sourceforge.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. |
| */ |
| |
| /* |
| * 2004-01-28: Added Socks5 proxy support |
| * (Christof Meerwald, http://cmeerw.org) |
| */ |
| |
| #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" |
| #endif |
| |
| #include "syshead.h" |
| |
| #include "buffer.h" |
| #include "error.h" |
| #include "common.h" |
| #include "run_command.h" |
| #include "shaper.h" |
| #include "crypto.h" |
| #include "ssl.h" |
| #include "ssl_ncp.h" |
| #include "options.h" |
| #include "misc.h" |
| #include "socket.h" |
| #include "packet_id.h" |
| #include "pkcs11.h" |
| #include "win32.h" |
| #include "push.h" |
| #include "pool.h" |
| #include "proto.h" |
| #include "helper.h" |
| #include "manage.h" |
| #include "forward.h" |
| #include "ssl_verify.h" |
| #include "platform.h" |
| #include <ctype.h> |
| |
| #include "memdbg.h" |
| |
| const char title_string[] = |
| PACKAGE_STRING |
| #ifdef CONFIGURE_GIT_REVISION |
| " [git:" CONFIGURE_GIT_REVISION CONFIGURE_GIT_FLAGS "]" |
| #endif |
| " " TARGET_ALIAS |
| #if defined(ENABLE_CRYPTO_MBEDTLS) |
| " [SSL (mbed TLS)]" |
| #elif defined(ENABLE_CRYPTO_OPENSSL) |
| " [SSL (OpenSSL)]" |
| #else |
| " [SSL]" |
| #endif /* defined(ENABLE_CRYPTO_MBEDTLS) */ |
| #ifdef USE_COMP |
| #ifdef ENABLE_LZO |
| " [LZO]" |
| #endif |
| #ifdef ENABLE_LZ4 |
| " [LZ4]" |
| #endif |
| #ifdef ENABLE_COMP_STUB |
| " [COMP_STUB]" |
| #endif |
| #endif /* USE_COMP */ |
| #if EPOLL |
| " [EPOLL]" |
| #endif |
| #ifdef PRODUCT_TAP_DEBUG |
| " [TAPDBG]" |
| #endif |
| #ifdef ENABLE_PKCS11 |
| " [PKCS11]" |
| #endif |
| #if ENABLE_IP_PKTINFO |
| #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
| " [MH/PKTINFO]" |
| #elif defined(IP_RECVDSTADDR) |
| " [MH/RECVDA]" |
| #endif |
| #endif |
| " [AEAD]" |
| " built on " __DATE__ |
| ; |
| |
| #ifndef ENABLE_SMALL |
| |
| static const char usage_message[] = |
| "%s\n" |
| "\n" |
| "General Options:\n" |
| "--config file : Read configuration options from file.\n" |
| "--help : Show options.\n" |
| "--version : Show copyright and version information.\n" |
| "\n" |
| "Tunnel Options:\n" |
| "--local host : Local host name or ip address. Implies --bind.\n" |
| "--remote host [port] : Remote host name or ip address.\n" |
| "--remote-random : If multiple --remote options specified, choose one randomly.\n" |
| "--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" |
| "--proto-force p : only consider protocol p in list of connection profiles.\n" |
| " p = udp6, tcp6-server, or tcp6-client (ipv6)\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" |
| " (default=%d).\n" |
| "--connect-retry-max n : Maximum connection attempt retries, default infinite.\n" |
| "--http-proxy s p [up] [auth] : Connect to remote host\n" |
| " through an HTTP proxy at address s and port p.\n" |
| " If proxy authentication is required,\n" |
| " up is a file containing username/password on 2 lines, or\n" |
| " 'stdin' to prompt from console. Add auth='ntlm' if\n" |
| " the proxy requires NTLM authentication.\n" |
| "--http-proxy s p 'auto[-nct]' : Like the above directive, but automatically\n" |
| " determine auth method and query for username/password\n" |
| " if needed. auto-nct disables weak proxy auth methods.\n" |
| "--http-proxy-option type [parm] : Set extended HTTP proxy options.\n" |
| " Repeat to set multiple options.\n" |
| " VERSION version (default=1.0)\n" |
| " AGENT user-agent\n" |
| "--socks-proxy s [p] [up] : Connect to remote host through a Socks5 proxy at\n" |
| " address s and port p (default port = 1080).\n" |
| " If proxy authentication is required,\n" |
| " up is a file containing username/password on 2 lines, or\n" |
| " 'stdin' to prompt for console.\n" |
| "--socks-proxy-retry : Retry indefinitely on Socks proxy errors.\n" |
| "--resolv-retry n: If hostname resolve fails for --remote, retry\n" |
| " resolve for n seconds before failing (disabled by default).\n" |
| " Set n=\"infinite\" to retry indefinitely.\n" |
| "--float : Allow remote to change its IP address/port, such as through\n" |
| " DHCP (this is the default if --remote is not used).\n" |
| "--ipchange cmd : Run command cmd on remote ip address initial\n" |
| " setting or change -- execute as: cmd ip-address port#\n" |
| "--port port : TCP/UDP port # for both local and remote.\n" |
| "--lport port : TCP/UDP port # for local (default=%s). Implies --bind.\n" |
| "--rport port : TCP/UDP port # for remote (default=%s).\n" |
| "--bind : Bind to local address and port. (This is the default unless\n" |
| " --proto tcp-client" |
| " or --http-proxy" |
| " or --socks-proxy" |
| " is used).\n" |
| "--nobind : Do not bind to local address and port.\n" |
| "--dev tunX|tapX : tun/tap device (X can be omitted for dynamic device.\n" |
| "--dev-type dt : Which device type are we using? (dt = tun or tap) Use\n" |
| " this option only if the tun/tap device used with --dev\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" |
| "--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 |
| "--iproute cmd : Use this command instead of default " IPROUTE_PATH ".\n" |
| #endif |
| "--ifconfig l rn : TUN: configure device to use IP address l as a local\n" |
| " endpoint and rn as a remote endpoint. l & rn should be\n" |
| " swapped on the other peer. l & rn must be private\n" |
| " addresses outside of the subnets used by either peer.\n" |
| " TAP: configure device to use IP address l as a local\n" |
| " endpoint and rn as a subnet mask.\n" |
| "--ifconfig-ipv6 l r : configure device to use IPv6 address l as local\n" |
| " endpoint (as a /64) and r as remote endpoint\n" |
| "--ifconfig-noexec : Don't actually execute ifconfig/netsh command, instead\n" |
| " pass --ifconfig parms by environment to scripts.\n" |
| "--ifconfig-nowarn : Don't warn if the --ifconfig option on this side of the\n" |
| " connection doesn't match the remote side.\n" |
| "--route network [netmask] [gateway] [metric] :\n" |
| " Add route to routing table after connection\n" |
| " 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" |
| "--route-ipv6 network/bits [gateway] [metric] :\n" |
| " Add IPv6 route to routing table after connection\n" |
| " is established. Multiple routes can be specified.\n" |
| " gateway default: taken from --route-ipv6-gateway or 'remote'\n" |
| " in --ifconfig-ipv6\n" |
| "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n" |
| "--route-ipv6-gateway gw : Specify a default gateway for use with --route-ipv6.\n" |
| "--route-metric m : Specify a default metric for use with --route.\n" |
| "--route-delay n [w] : Delay n seconds after connection initiation before\n" |
| " adding routes (may be 0). If not specified, routes will\n" |
| " be added immediately after tun/tap open. On Windows, wait\n" |
| " up to w seconds for TUN/TAP adapter to come up.\n" |
| "--route-up cmd : Run command cmd after routes are added.\n" |
| "--route-pre-down cmd : Run command cmd before routes are removed.\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" |
| "--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" |
| " commands to redirect all outgoing IP traffic through the\n" |
| " VPN. Add 'local' flag if both " PACKAGE_NAME " servers are directly\n" |
| " connected via a common subnet, such as with WiFi.\n" |
| " Add 'def1' flag to set default route using using 0.0.0.0/1\n" |
| " and 128.0.0.0/1 rather than 0.0.0.0/0. Add 'bypass-dhcp'\n" |
| " flag to add a direct route to DHCP server, bypassing tunnel.\n" |
| " Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n" |
| "--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n" |
| " the default gateway. Useful when pushing private subnets.\n" |
| "--block-ipv6 : (Client) Instead sending IPv6 to the server generate\n" |
| " ICMPv6 host unreachable messages on the client.\n" |
| " (Server) Instead of forwarding IPv6 packets send\n" |
| " ICMPv6 host unreachable packets to the client.\n" |
| "--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT rule.\n" |
| "--push-peer-info : (client only) push client info to server.\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" |
| " these options to be ignored when unknown\n" |
| "--script-security level: Where level can be:\n" |
| " 0 -- strictly no calling of external programs\n" |
| " 1 -- (default) only call built-ins such as ifconfig\n" |
| " 2 -- allow calling of built-ins and scripts\n" |
| " 3 -- allow password to be passed to scripts via env\n" |
| "--shaper n : Restrict output to peer to n bytes per second.\n" |
| "--keepalive n m : Helper option for setting timeouts in server mode. Send\n" |
| " ping once every n seconds, restart if ping not received\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" |
| "--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" |
| " remote address.\n" |
| "--ping n : Ping remote once every n seconds over TCP/UDP port.\n" |
| #if ENABLE_IP_PKTINFO |
| "--multihome : Configure a multi-homed UDP server.\n" |
| #endif |
| "--fast-io : (experimental) Optimize TUN/TAP/UDP writes.\n" |
| "--remap-usr1 s : On SIGUSR1 signals, remap signal (s='SIGHUP' or 'SIGTERM').\n" |
| "--persist-tun : Keep tun/tap device open across SIGUSR1 or --ping-restart.\n" |
| "--persist-remote-ip : Keep remote IP address across SIGUSR1 or --ping-restart.\n" |
| "--persist-local-ip : Keep local IP address across SIGUSR1 or --ping-restart.\n" |
| "--persist-key : Don't re-read key files across SIGUSR1 or --ping-restart.\n" |
| #if PASSTOS_CAPABILITY |
| "--passtos : TOS passthrough (applies to IPv4 only).\n" |
| #endif |
| "--tun-mtu n : Take the tun/tap device MTU to be n and derive the\n" |
| " TCP/UDP MTU from it (default=%d).\n" |
| "--tun-mtu-extra n : Assume that tun/tap device might return as many\n" |
| " as n bytes more than the tun-mtu size on read\n" |
| " (default TUN=0 TAP=%d).\n" |
| "--link-mtu n : Take the TCP/UDP device MTU to be n and derive the tun MTU\n" |
| " from it.\n" |
| "--mtu-disc type : Should we do Path MTU discovery on TCP/UDP channel?\n" |
| " 'no' -- Never send DF (Don't Fragment) frames\n" |
| " 'maybe' -- Use per-route hints\n" |
| " 'yes' -- Always DF (Don't Fragment)\n" |
| "--mtu-test : Empirically measure and report MTU.\n" |
| #ifdef ENABLE_FRAGMENT |
| "--fragment max : Enable internal datagram fragmentation so that no UDP\n" |
| " datagrams are sent which are larger than max bytes.\n" |
| " Adds 4 bytes of overhead per datagram.\n" |
| #endif |
| "--mssfix [n] : Set upper bound on TCP MSS, default = tun-mtu size\n" |
| " or --fragment max value, whichever is lower.\n" |
| "--sndbuf size : Set the TCP/UDP send buffer size.\n" |
| "--rcvbuf size : Set the TCP/UDP receive buffer size.\n" |
| #if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK |
| "--mark value : Mark encrypted packets being sent with value. The mark value\n" |
| " can be matched in policy routing and packetfilter rules.\n" |
| "--bind-dev dev : Bind to the given device when making connection to a peer or\n" |
| " listening for connections. This allows sending encrypted packets\n" |
| " via a VRF present on the system.\n" |
| #endif |
| "--txqueuelen n : Set the tun/tap TX queue length to n (Linux only).\n" |
| #ifdef ENABLE_MEMSTATS |
| "--memstats file : Write live usage stats to memory mapped binary file.\n" |
| #endif |
| "--mlock : Disable Paging -- ensures key material and tunnel\n" |
| " data will never be written to disk.\n" |
| "--up cmd : Run command cmd after successful tun device open.\n" |
| " Execute as: cmd tun/tap-dev tun-mtu link-mtu \\\n" |
| " ifconfig-local-ip ifconfig-remote-ip\n" |
| " (pre --user or --group UID/GID change)\n" |
| "--up-delay : Delay tun/tap open and possible --up script execution\n" |
| " until after TCP/UDP connection establishment with peer.\n" |
| "--down cmd : Run command cmd after tun device close.\n" |
| " (post --user/--group UID/GID change and/or --chroot)\n" |
| " (command parameters are same as --up option)\n" |
| "--down-pre : Run --down command before TUN/TAP close.\n" |
| "--up-restart : Run up/down commands for all restarts including those\n" |
| " caused by --ping-restart or SIGUSR1\n" |
| "--user user : Set UID to user after initialization.\n" |
| "--group group : Set GID to group after initialization.\n" |
| "--chroot dir : Chroot to this directory after initialization.\n" |
| #ifdef ENABLE_SELINUX |
| "--setcon context: Apply this SELinux context after initialization.\n" |
| #endif |
| "--cd dir : Change to this directory before initialization.\n" |
| "--daemon [name] : Become a daemon after initialization.\n" |
| " The optional 'name' parameter will be passed\n" |
| " as the program name to the system logger.\n" |
| "--syslog [name] : Output to syslog, but do not become a daemon.\n" |
| " See --daemon above for a description of the 'name' parm.\n" |
| "--inetd [name] ['wait'|'nowait'] : Run as an inetd or xinetd server.\n" |
| " See --daemon above for a description of the 'name' parm.\n" |
| "--log file : Output log to file which is created/truncated on open.\n" |
| "--log-append file : Append log to file, or create file if nonexistent.\n" |
| "--suppress-timestamps : Don't log timestamps to stdout/stderr.\n" |
| "--machine-readable-output : Always log timestamp, message flags to stdout/stderr.\n" |
| "--writepid file : Write main process ID to file.\n" |
| "--nice n : Change process priority (>0 = lower, <0 = higher).\n" |
| "--echo [parms ...] : Echo parameters to log output.\n" |
| "--verb n : Set output verbosity to n (default=%d):\n" |
| " (Level 3 is recommended if you want a good summary\n" |
| " of what's happening without being swamped by output).\n" |
| " : 0 -- no output except fatal errors\n" |
| " : 1 -- startup info + connection initiated messages +\n" |
| " non-fatal encryption & net errors\n" |
| " : 2,3 -- show TLS negotiations & route info\n" |
| " : 4 -- show parameters\n" |
| " : 5 -- show 'RrWw' chars on console for each packet sent\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-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" |
| #ifdef ENABLE_DEBUG |
| "--gremlin mask : Special stress testing mode (for debugging only).\n" |
| #endif |
| #if defined(USE_COMP) |
| "--compress alg : Use compression algorithm alg\n" |
| "--allow-compression: Specify whether compression should be allowed\n" |
| #if defined(ENABLE_LZO) |
| "--comp-lzo : Use LZO compression -- may add up to 1 byte per\n" |
| " packet for incompressible data.\n" |
| "--comp-noadapt : Don't use adaptive compression when --comp-lzo\n" |
| " is specified.\n" |
| #endif |
| #endif |
| #ifdef ENABLE_MANAGEMENT |
| "--management ip port [pass] : Enable a TCP server on ip:port to handle\n" |
| " management functions. pass is a password file\n" |
| " or 'stdin' to prompt from console.\n" |
| #if UNIX_SOCK_SUPPORT |
| " To listen on a unix domain socket, specific the pathname\n" |
| " in place of ip and use 'unix' as the port number.\n" |
| #endif |
| "--management-client : Management interface will connect as a TCP client to\n" |
| " ip/port rather than listen as a TCP server.\n" |
| "--management-query-passwords : Query management channel for private key\n" |
| " and auth-user-pass passwords.\n" |
| "--management-query-proxy : Query management channel for proxy information.\n" |
| "--management-query-remote : Query management channel for --remote directive.\n" |
| "--management-hold : Start " PACKAGE_NAME " in a hibernating state, until a client\n" |
| " of the management interface explicitly starts it.\n" |
| "--management-signal : Issue SIGUSR1 when management disconnect event occurs.\n" |
| "--management-forget-disconnect : Forget passwords when management disconnect\n" |
| " event occurs.\n" |
| "--management-up-down : Report tunnel up/down events to management interface.\n" |
| "--management-log-cache n : Cache n lines of log file history for usage\n" |
| " by the management channel.\n" |
| #if UNIX_SOCK_SUPPORT |
| "--management-client-user u : When management interface is a unix socket, only\n" |
| " allow connections from user u.\n" |
| "--management-client-group g : When management interface is a unix socket, only\n" |
| " allow connections from group g.\n" |
| #endif |
| #ifdef MANAGEMENT_DEF_AUTH |
| "--management-client-auth : gives management interface client the responsibility\n" |
| " to authenticate clients after their client certificate\n" |
| " has been verified.\n" |
| #endif |
| #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" |
| " to its initialization function.\n" |
| #endif |
| "--vlan-tagging : Enable 802.1Q-based VLAN tagging.\n" |
| "--vlan-accept tagged|untagged|all : Set VLAN tagging mode. Default is 'all'.\n" |
| "--vlan-pvid v : Sets the Port VLAN Identifier. Defaults to 1.\n" |
| #if P2MP |
| "\n" |
| "Multi-Client Server options (when --mode server is used):\n" |
| "--server network netmask : Helper option to easily configure server mode.\n" |
| "--server-ipv6 network/bits : Configure IPv6 server mode.\n" |
| "--server-bridge [IP netmask pool-start-IP pool-end-IP] : Helper option to\n" |
| " easily configure ethernet bridging server mode.\n" |
| "--push \"option\" : Push a config file option back to the peer for remote\n" |
| " execution. Peer must specify --pull in its config file.\n" |
| "--push-reset : Don't inherit global push list for specific\n" |
| " client instance.\n" |
| "--ifconfig-pool start-IP end-IP [netmask] : Set aside a pool of subnets\n" |
| " to be dynamically allocated to connecting clients.\n" |
| "--ifconfig-pool-persist file [seconds] : Persist/unpersist ifconfig-pool\n" |
| " data to file, at seconds intervals (default=600).\n" |
| " If seconds=0, file will be treated as read-only.\n" |
| "--ifconfig-ipv6-pool base-IP/bits : set aside an IPv6 network block\n" |
| " to be dynamically allocated to connecting clients.\n" |
| "--ifconfig-push local remote-netmask : Push an ifconfig option to remote,\n" |
| " overrides --ifconfig-pool dynamic allocation.\n" |
| " Only valid in a client-specific config file.\n" |
| "--ifconfig-ipv6-push local/bits remote : Push an ifconfig-ipv6 option to\n" |
| " remote, overrides --ifconfig-ipv6-pool allocation.\n" |
| " Only valid in a client-specific config file.\n" |
| "--iroute network [netmask] : Route subnet to client.\n" |
| "--iroute-ipv6 network/bits : Route IPv6 subnet to client.\n" |
| " Sets up internal routes only.\n" |
| " Only valid in a client-specific config file.\n" |
| "--disable : Client is disabled.\n" |
| " Only valid in a client-specific config file.\n" |
| "--verify-client-cert [none|optional|require] : perform no, optional or\n" |
| " mandatory client certificate verification.\n" |
| " Default is to require the client to supply a certificate.\n" |
| "--username-as-common-name : For auth-user-pass authentication, use\n" |
| " the authenticated username as the common name,\n" |
| " rather than the common name from the client cert.\n" |
| "--auth-user-pass-verify cmd method: Query client for username/password and\n" |
| " run command cmd to verify. If method='via-env', pass\n" |
| " user/pass via environment, if method='via-file', pass\n" |
| " user/pass via temporary file.\n" |
| "--auth-gen-token [lifetime] Generate a random authentication token which is pushed\n" |
| " to each client, replacing the password. Useful when\n" |
| " 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" |
| " 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" |
| "--no-name-remapping : (DEPRECATED) Allow Common Name and X509 Subject to include\n" |
| " any printable character.\n" |
| "--client-to-client : Internally route client-to-client traffic.\n" |
| "--duplicate-cn : Allow multiple clients with the same common name to\n" |
| " concurrently connect.\n" |
| "--client-connect cmd : Run command cmd on client connection.\n" |
| "--client-disconnect cmd : Run command cmd on client disconnection.\n" |
| "--client-config-dir dir : Directory for custom client config files.\n" |
| "--ccd-exclusive : Refuse connection unless custom client config is found.\n" |
| "--tmp-dir dir : Temporary directory, used for --client-connect return file and plugin communication.\n" |
| "--hash-size r v : Set the size of the real address hash table to r and the\n" |
| " virtual address table to v.\n" |
| "--bcast-buffers n : Allocate n broadcast buffers.\n" |
| "--tcp-queue-limit n : Maximum number of queued TCP output packets.\n" |
| "--tcp-nodelay : Macro that sets TCP_NODELAY socket flag on the server\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" |
| "--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" |
| " older than n seconds. Run this check every t\n" |
| " seconds (defaults to n).\n" |
| "--explicit-exit-notify [n] : In UDP server mode send [RESTART] command on exit/restart to connected\n" |
| " clients. n = 1 - reconnect to same server,\n" |
| " 2 - advance to next server, default=1.\n" |
| #if PORT_SHARE |
| "--port-share host port [dir] : When run in TCP mode, proxy incoming HTTPS\n" |
| " sessions to a web server at host:port. dir specifies an\n" |
| " optional directory to write origin IP:port data.\n" |
| #endif |
| "\n" |
| "Client options (when connecting to a multi-client server):\n" |
| "--client : Helper option to easily configure client mode.\n" |
| "--auth-user-pass [up] : Authenticate with server using username/password.\n" |
| " up is a file containing the username on the first line,\n" |
| " and a password on the second. If either the password or both\n" |
| " the username and the password are omitted OpenVPN will prompt\n" |
| " for them from console.\n" |
| "--pull : Accept certain config file options from the peer as if they\n" |
| " were part of the local config file. Must be specified\n" |
| " when connecting to a '--mode server' remote host.\n" |
| "--pull-filter accept|ignore|reject t : Filter each option received from the\n" |
| " server if it starts with the text t. The action flag accept,\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" |
| "--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" |
| " challenge text t, with e indicating echo flag (0|1)\n" |
| "--connect-timeout n : when polling possible remote servers to connect to\n" |
| " in a round-robin fashion, spend no more than n seconds\n" |
| " waiting for a response before trying the next server.\n" |
| "--allow-recursive-routing : When this option is set, OpenVPN will not drop\n" |
| " incoming tun packets with same destination as host.\n" |
| #endif /* if P2MP */ |
| "--explicit-exit-notify [n] : On exit/restart, send exit signal to\n" |
| " server/remote. n = # of retries, default=1.\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] : 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" |
| " Set alg=none to disable encryption.\n" |
| "--data-ciphers list : List of ciphers that are allowed to be negotiated.\n" |
| "--ncp-disable : (DEPRECATED) Disable cipher negotiation.\n" |
| "--prng alg [nsl] : For PRNG, use digest algorithm alg, and\n" |
| " nonce_secret_len=nsl. Set alg=none to disable PRNG.\n" |
| #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH |
| "--keysize n : (DEPRECATED) Size of cipher key in bits (optional).\n" |
| " If unspecified, defaults to cipher-specific default.\n" |
| #endif |
| #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" |
| " Default n=%d t=%d\n" |
| "--replay-persist file : Persist replay-protection state across sessions\n" |
| " using file.\n" |
| "--test-crypto : Run a self-test of crypto features enabled.\n" |
| " For debugging only.\n" |
| #ifdef ENABLE_PREDICTION_RESISTANCE |
| "--use-prediction-resistance: Enable prediction resistance on the random\n" |
| " number generator.\n" |
| #endif |
| "\n" |
| "TLS Key Negotiation Options:\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 |
| "--capath dir : A directory of trusted certificates (CAs" |
| " and CRLs).\n" |
| #endif /* ENABLE_CRYPTO_MBEDTLS */ |
| "--dh file : File containing Diffie Hellman parameters\n" |
| " in .pem format (for --tls-server only).\n" |
| " Use \"openssl dhparam -out dh1024.pem 1024\" to generate.\n" |
| "--cert file : Local certificate in .pem format -- must be signed\n" |
| " by a Certificate Authority in --ca file.\n" |
| "--extra-certs file : one or more PEM certs that complete the cert chain.\n" |
| "--key file : Local private key in .pem format.\n" |
| "--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n" |
| " will accept from the peer. If version is unrecognized and 'or-highest'\n" |
| " is specified, require max TLS version supported by SSL implementation.\n" |
| "--tls-version-max <version> : sets the maximum TLS version we will use.\n" |
| #ifndef ENABLE_CRYPTO_MBEDTLS |
| "--pkcs12 file : PKCS#12 file containing local private key, local certificate\n" |
| " and optionally the root CA certificate.\n" |
| #endif |
| #ifdef ENABLE_X509ALTUSERNAME |
| "--x509-username-field : Field in x509 certificate containing the username.\n" |
| " Default is CN in the Subject field.\n" |
| #endif |
| "--verify-hash hash [algo] : Specify fingerprint for level-1 certificate.\n" |
| " Valid algo flags are SHA1 and SHA256. \n" |
| #ifdef _WIN32 |
| "--cryptoapicert select-string : Load the certificate and private key from the\n" |
| " 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" |
| " : 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" |
| "--tls-timeout n : Packet retransmit timeout on TLS control channel\n" |
| " if no ACK from remote within n seconds (default=%d).\n" |
| "--reneg-bytes n : Renegotiate data chan. key after n bytes sent and recvd.\n" |
| "--reneg-pkts n : Renegotiate data chan. key after n packets sent and recvd.\n" |
| "--reneg-sec max [min] : Renegotiate data chan. key after at most max (default=%d)\n" |
| " and at least min (defaults to 90%% of max on servers and equal\n" |
| " to max on clients).\n" |
| "--hand-window n : Data channel key exchange must finalize within n seconds\n" |
| " of handshake initiation by any peer (default=%d).\n" |
| "--tran-window n : Transition window -- old key can live this many seconds\n" |
| " after new key renegotiation begins (default=%d).\n" |
| "--single-session: Allow only one session (reset state on restart).\n" |
| "--tls-exit : Exit on TLS negotiation failure.\n" |
| "--tls-auth f [d]: Add an additional layer of authentication on top of the TLS\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" |
| "--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 (--tls-crypt-v2-genkey): use key to\n" |
| " encrypt generated client-specific key. (See --tls-crypt.)\n" |
| "--genkey tls-crypt-v2-client [keyfile] [base64 metadata]: Generate a\n" |
| " fresh tls-crypt-v2 client key, and store to\n" |
| " keyfile. If supplied, include metadata in wrapped key.\n" |
| "--genkey tls-crypt-v2-server [keyfile] [base64 metadata]: Generate a\n" |
| " fresh tls-crypt-v2 server key, and store to keyfile\n" |
| "--tls-crypt-v2-verify cmd : Run command cmd to verify the metadata of the\n" |
| " client-supplied tls-crypt-v2 client key\n" |
| "--askpass [file]: Get PEM password from controlling tty before we daemonize.\n" |
| "--auth-nocache : Don't cache --askpass or --auth-user-pass passwords.\n" |
| "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n" |
| "--tls-verify cmd: Run command cmd to verify the X509 name of a\n" |
| " pending TLS connection that has otherwise passed all other\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" |
| "--ns-cert-type t: (DEPRECATED) Require that peer certificate was signed with \n" |
| " an explicit nsCertType designation t = 'client' | 'server'.\n" |
| "--x509-track x : Save peer X509 attribute x in environment for use by\n" |
| " plugins and management interface.\n" |
| #ifdef HAVE_EXPORT_KEYING_MATERIAL |
| "--keying-material-exporter label len : Save Exported Keying Material (RFC5705)\n" |
| " of len bytes (min. 16 bytes) using label in environment for use by plugins.\n" |
| #endif |
| "--remote-cert-ku v ... : Require that the peer certificate was signed with\n" |
| " explicit key usage, you can specify more than one value.\n" |
| " value should be given in hex format.\n" |
| "--remote-cert-eku oid : Require that the peer certificate was signed with\n" |
| " explicit extended key usage. Extended key usage can be encoded\n" |
| " as an object identifier or OpenSSL string representation.\n" |
| "--remote-cert-tls t: Require that peer certificate was signed with explicit\n" |
| " key usage and extended key usage based on RFC3280 TLS rules.\n" |
| " t = 'client' | 'server'.\n" |
| #ifdef ENABLE_PKCS11 |
| "\n" |
| "PKCS#11 Options:\n" |
| "--pkcs11-providers provider ... : PKCS#11 provider to load.\n" |
| "--pkcs11-protected-authentication [0|1] ... : Use PKCS#11 protected authentication\n" |
| " path. Set for each provider.\n" |
| "--pkcs11-private-mode hex ... : PKCS#11 private key mode mask.\n" |
| " 0 : Try to determine automatically (default).\n" |
| " 1 : Use Sign.\n" |
| " 2 : Use SignRecover.\n" |
| " 4 : Use Decrypt.\n" |
| " 8 : Use Unwrap.\n" |
| "--pkcs11-cert-private [0|1] ... : Set if login should be performed before\n" |
| " certificate can be accessed. Set for each provider.\n" |
| "--pkcs11-pin-cache seconds : Number of seconds to cache PIN. The default is -1\n" |
| " cache until token is removed.\n" |
| "--pkcs11-id-management : Acquire identity from management interface.\n" |
| "--pkcs11-id serialized-id 'id' : Identity to use, get using standalone --show-pkcs11-ids\n" |
| #endif /* ENABLE_PKCS11 */ |
| "\n" |
| "SSL Library information:\n" |
| "--show-ciphers : Show cipher algorithms to use with --cipher option.\n" |
| "--show-digests : Show message digest algorithms to use with --auth option.\n" |
| "--show-engines : Show hardware crypto accelerator engines (if available).\n" |
| "--show-tls : Show all TLS ciphers (TLS used only as a control channel).\n" |
| #ifdef _WIN32 |
| "\n" |
| "Windows Specific:\n" |
| "--win-sys path : Pathname of Windows system directory. Default is the pathname\n" |
| " from SystemRoot environment variable.\n" |
| "--ip-win32 method : When using --ifconfig on Windows, set TAP-Windows adapter\n" |
| " IP address using method = manual, netsh, ipapi,\n" |
| " dynamic, or adaptive (default = adaptive).\n" |
| " Dynamic method allows two optional parameters:\n" |
| " offset: DHCP server address offset (> -256 and < 256).\n" |
| " If 0, use network address, if >0, take nth\n" |
| " address forward from network address, if <0,\n" |
| " take nth address backward from broadcast\n" |
| " address.\n" |
| " Default is 0.\n" |
| " lease-time: Lease time in seconds.\n" |
| " Default is one year.\n" |
| "--route-method : Which method to use for adding routes on Windows?\n" |
| " adaptive (default) -- Try ipapi then fall back to exe.\n" |
| " ipapi -- Use IP helper API.\n" |
| " exe -- Call the route.exe shell command.\n" |
| "--dhcp-option type [parm] : Set extended TAP-Windows properties, must\n" |
| " be used with --ip-win32 dynamic. For options\n" |
| " which allow multiple addresses,\n" |
| " --dhcp-option must be repeated.\n" |
| " DOMAIN name : Set DNS suffix\n" |
| " DOMAIN-SEARCH entry : Add entry to DNS domain search list\n" |
| " DNS addr : Set domain name server address(es) (IPv4 and IPv6)\n" |
| " NTP : Set NTP server address(es)\n" |
| " NBDD : Set NBDD server address(es)\n" |
| " WINS addr : Set WINS server address(es)\n" |
| " NBT type : Set NetBIOS over TCP/IP Node type\n" |
| " 1: B, 2: P, 4: M, 8: H\n" |
| " NBS id : Set NetBIOS scope ID\n" |
| " DISABLE-NBT : Disable Netbios-over-TCP/IP.\n" |
| "--dhcp-renew : Ask Windows to renew the TAP adapter lease on startup.\n" |
| "--dhcp-pre-release : Ask Windows to release the previous TAP adapter lease on\n" |
| " startup.\n" |
| "--register-dns : Run ipconfig /flushdns and ipconfig /registerdns\n" |
| " on connection initiation.\n" |
| "--tap-sleep n : Sleep for n seconds after TAP adapter open before\n" |
| " attempting to set adapter properties.\n" |
| "--pause-exit : When run from a console window, pause before exiting.\n" |
| "--service ex [0|1] : For use when " PACKAGE_NAME " is being instantiated by a\n" |
| " service, and should not be used directly by end-users.\n" |
| " ex is the name of an event object which, when\n" |
| " signaled, will cause " PACKAGE_NAME " to exit. A second\n" |
| " optional parameter controls the initial state of ex.\n" |
| "--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" |
| " wintun\n" |
| "--block-outside-dns : Block DNS on other network adapters to prevent DNS leaks\n" |
| "Windows Standalone Options:\n" |
| "\n" |
| "--show-adapters : Show all TAP-Windows adapters.\n" |
| "--show-net : Show " PACKAGE_NAME "'s view of routing table and net adapter list.\n" |
| "--show-valid-subnets : Show valid subnets for --dev tun emulation.\n" |
| "--allow-nonadmin [TAP-adapter] : Allow " PACKAGE_NAME " running without admin privileges\n" |
| " to access TAP adapter.\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)." |
| #ifdef ENABLE_FEATURE_TUN_PERSIST |
| "\n" |
| "Tun/tap config mode (available with linux 2.4+):\n" |
| "--mktun : Create a persistent tunnel.\n" |
| "--rmtun : Remove a persistent tunnel.\n" |
| "--dev tunX|tapX : tun/tap device\n" |
| "--dev-type dt : Device type. See tunnel options above for details.\n" |
| "--user user : User to set privilege to.\n" |
| "--group group : Group to set privilege to.\n" |
| #endif |
| #ifdef ENABLE_PKCS11 |
| "\n" |
| "PKCS#11 standalone options:\n" |
| #ifdef DEFAULT_PKCS11_MODULE |
| "--show-pkcs11-ids [provider] [cert_private] : Show PKCS#11 available ids.\n" |
| #else |
| "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n" |
| #endif |
| " --verb option can be added *BEFORE* this.\n" |
| #endif /* ENABLE_PKCS11 */ |
| "\n" |
| "General Standalone Options:\n" |
| #ifdef ENABLE_DEBUG |
| "--show-gateway : Show info about default gateway.\n" |
| #endif |
| ; |
| |
| #endif /* !ENABLE_SMALL */ |
| |
| /* |
| * This is where the options defaults go. |
| * Any option not explicitly set here |
| * will be set to 0. |
| */ |
| void |
| init_options(struct options *o, const bool init_gc) |
| { |
| CLEAR(*o); |
| if (init_gc) |
| { |
| gc_init(&o->gc); |
| o->gc_owned = true; |
| } |
| o->mode = MODE_POINT_TO_POINT; |
| o->topology = TOP_NET30; |
| 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_max = 300; |
| o->ce.connect_timeout = 120; |
| o->connect_retry_max = 0; |
| o->ce.local_port = o->ce.remote_port = OPENVPN_PORT; |
| o->verbosity = 1; |
| o->status_file_update_freq = 60; |
| o->status_file_version = 1; |
| o->ce.bind_local = true; |
| o->ce.tun_mtu = TUN_MTU_DEFAULT; |
| o->ce.link_mtu = LINK_MTU_DEFAULT; |
| o->ce.mtu_discover_type = -1; |
| o->ce.mssfix = MSSFIX_DEFAULT; |
| o->route_delay_window = 30; |
| o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; |
| o->resolve_in_advance = false; |
| o->proto_force = -1; |
| o->occ = true; |
| #ifdef ENABLE_MANAGEMENT |
| o->management_log_history_cache = 250; |
| o->management_echo_buffer_size = 100; |
| o->management_state_buffer_size = 100; |
| #endif |
| #ifdef ENABLE_FEATURE_TUN_PERSIST |
| o->persist_mode = 1; |
| #endif |
| #ifdef _WIN32 |
| #if 0 |
| o->tuntap_options.ip_win32_type = IPW32_SET_ADAPTIVE; |
| #else |
| o->tuntap_options.ip_win32_type = IPW32_SET_DHCP_MASQ; |
| #endif |
| o->tuntap_options.dhcp_lease_time = 31536000; /* one year */ |
| 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; |
| #endif |
| o->vlan_accept = VLAN_ALL; |
| o->vlan_pvid = 1; |
| o->real_hash_size = 256; |
| o->virtual_hash_size = 256; |
| o->n_bcast_buf = 256; |
| o->tcp_queue_limit = 64; |
| o->max_clients = 1024; |
| o->max_routes_per_client = 256; |
| o->stale_routes_check_interval = 0; |
| o->ifconfig_pool_persist_refresh_freq = 600; |
| #if P2MP |
| o->scheduled_exit_interval = 5; |
| #endif |
| o->ncp_enabled = true; |
| o->ncp_ciphers = "AES-256-GCM:AES-128-GCM"; |
| o->authname = "SHA1"; |
| o->prng_hash = "SHA1"; |
| o->prng_nonce_secret_len = 16; |
| o->replay = true; |
| o->replay_window = DEFAULT_SEQ_BACKTRACK; |
| o->replay_time = DEFAULT_TIME_BACKTRACK; |
| o->key_direction = KEY_DIRECTION_BIDIRECTIONAL; |
| #ifdef ENABLE_PREDICTION_RESISTANCE |
| o->use_prediction_resistance = false; |
| #endif |
| o->tls_timeout = 2; |
| o->renegotiate_bytes = -1; |
| o->renegotiate_seconds = 3600; |
| o->renegotiate_seconds_min = -1; |
| o->handshake_window = 60; |
| o->transition_window = 3600; |
| o->tls_cert_profile = NULL; |
| o->ecdh_curve = NULL; |
| #ifdef ENABLE_X509ALTUSERNAME |
| o->x509_username_field = X509_USERNAME_FIELD_DEFAULT; |
| #endif |
| #ifdef ENABLE_PKCS11 |
| o->pkcs11_pin_cache_period = -1; |
| #endif /* ENABLE_PKCS11 */ |
| |
| /* P2MP server context features */ |
| o->auth_token_generate = false; |
| |
| /* Set default --tmp-dir */ |
| #ifdef _WIN32 |
| /* On Windows, find temp dir via environment variables */ |
| o->tmp_dir = win_get_tempdir(); |
| #else |
| /* Non-windows platforms use $TMPDIR, and if not set, default to '/tmp' */ |
| o->tmp_dir = getenv("TMPDIR"); |
| if (!o->tmp_dir) |
| { |
| o->tmp_dir = "/tmp"; |
| } |
| #endif /* _WIN32 */ |
| o->allow_recursive_routing = false; |
| } |
| |
| void |
| uninit_options(struct options *o) |
| { |
| if (o->gc_owned) |
| { |
| gc_free(&o->gc); |
| } |
| } |
| |
| struct pull_filter |
| { |
| #define PUF_TYPE_UNDEF 0 /** undefined filter type */ |
| #define PUF_TYPE_ACCEPT 1 /** filter type to accept a matching option */ |
| #define PUF_TYPE_IGNORE 2 /** filter type to ignore a matching option */ |
| #define PUF_TYPE_REJECT 3 /** filter type to reject and trigger SIGUSR1 */ |
| int type; |
| int size; |
| char *pattern; |
| struct pull_filter *next; |
| }; |
| |
| struct pull_filter_list |
| { |
| struct pull_filter *head; |
| struct pull_filter *tail; |
| }; |
| |
| static const char * |
| pull_filter_type_name(int type) |
| { |
| if (type == PUF_TYPE_ACCEPT) |
| { |
| return "accept"; |
| } |
| if (type == PUF_TYPE_IGNORE) |
| { |
| return "ignore"; |
| } |
| if (type == PUF_TYPE_REJECT) |
| { |
| return "reject"; |
| } |
| else |
| { |
| return "???"; |
| } |
| } |
| |
| #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, \ |
| o->var ## _inline ? "[INLINE]" : \ |
| (o->var ? o->var : "[UNDEF]"), \ |
| "'%s'") |
| #define SHOW_INT(var) SHOW_PARM(var, o->var, "%d") |
| #define SHOW_UINT(var) SHOW_PARM(var, o->var, "%u") |
| #define SHOW_UNSIGNED(var) SHOW_PARM(var, o->var, "0x%08x") |
| #define SHOW_BOOL(var) SHOW_PARM(var, (o->var ? "ENABLED" : "DISABLED"), "%s"); |
| |
| #endif |
| |
| static void |
| setenv_connection_entry(struct env_set *es, |
| const struct connection_entry *e, |
| const int i) |
| { |
| setenv_str_i(es, "proto", proto2ascii(e->proto, e->af, false), i); |
| setenv_str_i(es, "local", e->local, i); |
| setenv_str_i(es, "local_port", e->local_port, i); |
| setenv_str_i(es, "remote", e->remote, i); |
| setenv_str_i(es, "remote_port", e->remote_port, i); |
| |
| if (e->http_proxy_options) |
| { |
| setenv_str_i(es, "http_proxy_server", e->http_proxy_options->server, i); |
| setenv_str_i(es, "http_proxy_port", e->http_proxy_options->port, i); |
| } |
| if (e->socks_proxy_server) |
| { |
| setenv_str_i(es, "socks_proxy_server", e->socks_proxy_server, i); |
| setenv_str_i(es, "socks_proxy_port", e->socks_proxy_port, i); |
| } |
| } |
| |
| void |
| setenv_settings(struct env_set *es, const struct options *o) |
| { |
| setenv_str(es, "config", o->config); |
| setenv_int(es, "verb", o->verbosity); |
| setenv_int(es, "daemon", o->daemon); |
| setenv_int(es, "daemon_log_redirect", o->log); |
| setenv_long_long(es, "daemon_start_time", time(NULL)); |
| setenv_int(es, "daemon_pid", platform_getpid()); |
| |
| if (o->connection_list) |
| { |
| int i; |
| for (i = 0; i < o->connection_list->len; ++i) |
| { |
| setenv_connection_entry(es, o->connection_list->array[i], i+1); |
| } |
| } |
| else |
| { |
| setenv_connection_entry(es, &o->ce, 1); |
| } |
| } |
| |
| static in_addr_t |
| get_ip_addr(const char *ip_string, int msglevel, bool *error) |
| { |
| unsigned int flags = GETADDR_HOST_ORDER; |
| bool succeeded = false; |
| in_addr_t ret; |
| |
| if (msglevel & M_FATAL) |
| { |
| flags |= GETADDR_FATAL; |
| } |
| |
| ret = getaddr(flags, ip_string, 0, &succeeded, NULL); |
| if (!succeeded && error) |
| { |
| *error = true; |
| } |
| return ret; |
| } |
| |
| /** |
| * Returns newly allocated string containing address part without "/nn". |
| * |
| * If gc != NULL, the allocated memory is registered in the supplied gc. |
| */ |
| static char * |
| get_ipv6_addr_no_netbits(const char *addr, struct gc_arena *gc) |
| { |
| const char *end = strchr(addr, '/'); |
| char *ret = NULL; |
| if (NULL == end) |
| { |
| ret = string_alloc(addr, gc); |
| } |
| else |
| { |
| size_t len = end - addr; |
| ret = gc_malloc(len + 1, true, gc); |
| memcpy(ret, addr, len); |
| } |
| return ret; |
| } |
| |
| static bool |
| ipv6_addr_safe_hexplusbits( const char *ipv6_prefix_spec ) |
| { |
| struct in6_addr t_addr; |
| unsigned int t_bits; |
| |
| return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, M_WARN ); |
| } |
| |
| static char * |
| string_substitute(const char *src, int from, int to, struct gc_arena *gc) |
| { |
| char *ret = (char *) gc_malloc(strlen(src) + 1, true, gc); |
| char *dest = ret; |
| char c; |
| |
| do |
| { |
| c = *src++; |
| if (c == from) |
| { |
| c = to; |
| } |
| *dest++ = c; |
| } |
| while (c); |
| return ret; |
| } |
| |
| static uint8_t * |
| parse_hash_fingerprint(const char *str, int nbytes, int msglevel, struct gc_arena *gc) |
| { |
| int i; |
| const char *cp = str; |
| uint8_t *ret = (uint8_t *) gc_malloc(nbytes, true, gc); |
| char term = 1; |
| int byte; |
| char bs[3]; |
| |
| for (i = 0; i < nbytes; ++i) |
| { |
| if (strlen(cp) < 2) |
| { |
| msg(msglevel, "format error in hash fingerprint: %s", str); |
| } |
| bs[0] = *cp++; |
| bs[1] = *cp++; |
| bs[2] = 0; |
| byte = 0; |
| if (sscanf(bs, "%x", &byte) != 1) |
| { |
| msg(msglevel, "format error in hash fingerprint hex byte: %s", str); |
| } |
| ret[i] = (uint8_t)byte; |
| term = *cp++; |
| if (term != ':' && term != 0) |
| { |
| msg(msglevel, "format error in hash fingerprint delimiter: %s", str); |
| } |
| if (term == 0) |
| { |
| break; |
| } |
| } |
| if (term != 0 || i != nbytes-1) |
| { |
| msg(msglevel, "hash fingerprint is different length than expected (%d bytes): %s", nbytes, str); |
| } |
| return ret; |
| } |
| |
| #ifdef _WIN32 |
| |
| #ifndef ENABLE_SMALL |
| |
| static void |
| show_dhcp_option_list(const char *name, const char * const*array, int len) |
| { |
| int i; |
| for (i = 0; i < len; ++i) |
| { |
| msg(D_SHOW_PARMS, " %s[%d] = %s", name, i, array[i] ); |
| } |
| } |
| |
| static void |
| show_dhcp_option_addrs(const char *name, const in_addr_t *array, int len) |
| { |
| struct gc_arena gc = gc_new(); |
| int i; |
| for (i = 0; i < len; ++i) |
| { |
| msg(D_SHOW_PARMS, " %s[%d] = %s", |
| name, |
| i, |
| print_in_addr_t(array[i], 0, &gc)); |
| } |
| gc_free(&gc); |
| } |
| |
| static void |
| show_tuntap_options(const struct tuntap_options *o) |
| { |
| SHOW_BOOL(ip_win32_defined); |
| SHOW_INT(ip_win32_type); |
| SHOW_INT(dhcp_masq_offset); |
| SHOW_INT(dhcp_lease_time); |
| SHOW_INT(tap_sleep); |
| SHOW_BOOL(dhcp_options); |
| SHOW_BOOL(dhcp_renew); |
| SHOW_BOOL(dhcp_pre_release); |
| SHOW_STR(domain); |
| SHOW_STR(netbios_scope); |
| SHOW_INT(netbios_node_type); |
| SHOW_BOOL(disable_nbt); |
| |
| show_dhcp_option_addrs("DNS", o->dns, o->dns_len); |
| show_dhcp_option_addrs("WINS", o->wins, o->wins_len); |
| show_dhcp_option_addrs("NTP", o->ntp, o->ntp_len); |
| show_dhcp_option_addrs("NBDD", o->nbdd, o->nbdd_len); |
| show_dhcp_option_list("DOMAIN-SEARCH", o->domain_search_list, o->domain_search_list_len); |
| } |
| |
| #endif /* ifndef ENABLE_SMALL */ |
| #endif /* ifdef _WIN32 */ |
| |
| #if defined(_WIN32) || defined(TARGET_ANDROID) |
| static void |
| dhcp_option_dns6_parse(const char *parm, struct in6_addr *dns6_list, int *len, int msglevel) |
| { |
| struct in6_addr addr; |
| if (*len >= N_DHCP_ADDR) |
| { |
| msg(msglevel, "--dhcp-option DNS: maximum of %d IPv6 dns servers can be specified", |
| N_DHCP_ADDR); |
| } |
| else if (get_ipv6_addr(parm, &addr, NULL, msglevel)) |
| { |
| dns6_list[(*len)++] = addr; |
| } |
| } |
| static void |
| dhcp_option_address_parse(const char *name, const char *parm, in_addr_t *array, int *len, int msglevel) |
| { |
| if (*len >= N_DHCP_ADDR) |
| { |
| msg(msglevel, "--dhcp-option %s: maximum of %d %s servers can be specified", |
| name, |
| N_DHCP_ADDR, |
| name); |
| } |
| else |
| { |
| if (ip_addr_dotted_quad_safe(parm)) /* FQDN -- IP address only */ |
| { |
| bool error = false; |
| const in_addr_t addr = get_ip_addr(parm, msglevel, &error); |
| if (!error) |
| { |
| array[(*len)++] = addr; |
| } |
| } |
| else |
| { |
| msg(msglevel, "dhcp-option parameter %s '%s' must be an IP address", name, parm); |
| } |
| } |
| } |
| |
| #endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */ |
| |
| static const char * |
| print_vlan_accept(enum vlan_acceptable_frames mode) |
| { |
| switch (mode) |
| { |
| case VLAN_ONLY_TAGGED: |
| return "tagged"; |
| |
| case VLAN_ONLY_UNTAGGED_OR_PRIORITY: |
| return "untagged"; |
| |
| case VLAN_ALL: |
| return "all"; |
| } |
| return NULL; |
| } |
| |
| #if P2MP |
| |
| #ifndef ENABLE_SMALL |
| |
| static void |
| show_p2mp_parms(const struct options *o) |
| { |
| struct gc_arena gc = gc_new(); |
| |
| msg(D_SHOW_PARMS, " server_network = %s", print_in_addr_t(o->server_network, 0, &gc)); |
| msg(D_SHOW_PARMS, " server_netmask = %s", print_in_addr_t(o->server_netmask, 0, &gc)); |
| msg(D_SHOW_PARMS, " server_network_ipv6 = %s", print_in6_addr(o->server_network_ipv6, 0, &gc) ); |
| SHOW_INT(server_netbits_ipv6); |
| msg(D_SHOW_PARMS, " server_bridge_ip = %s", print_in_addr_t(o->server_bridge_ip, 0, &gc)); |
| msg(D_SHOW_PARMS, " server_bridge_netmask = %s", print_in_addr_t(o->server_bridge_netmask, 0, &gc)); |
| msg(D_SHOW_PARMS, " server_bridge_pool_start = %s", print_in_addr_t(o->server_bridge_pool_start, 0, &gc)); |
| msg(D_SHOW_PARMS, " server_bridge_pool_end = %s", print_in_addr_t(o->server_bridge_pool_end, 0, &gc)); |
| if (o->push_list.head) |
| { |
| const struct push_entry *e = o->push_list.head; |
| while (e) |
| { |
| if (e->enable) |
| { |
| msg(D_SHOW_PARMS, " push_entry = '%s'", e->option); |
| } |
| e = e->next; |
| } |
| } |
| SHOW_BOOL(ifconfig_pool_defined); |
| msg(D_SHOW_PARMS, " ifconfig_pool_start = %s", print_in_addr_t(o->ifconfig_pool_start, 0, &gc)); |
| msg(D_SHOW_PARMS, " ifconfig_pool_end = %s", print_in_addr_t(o->ifconfig_pool_end, 0, &gc)); |
| msg(D_SHOW_PARMS, " ifconfig_pool_netmask = %s", print_in_addr_t(o->ifconfig_pool_netmask, 0, &gc)); |
| SHOW_STR(ifconfig_pool_persist_filename); |
| SHOW_INT(ifconfig_pool_persist_refresh_freq); |
| SHOW_BOOL(ifconfig_ipv6_pool_defined); |
| msg(D_SHOW_PARMS, " ifconfig_ipv6_pool_base = %s", print_in6_addr(o->ifconfig_ipv6_pool_base, 0, &gc)); |
| SHOW_INT(ifconfig_ipv6_pool_netbits); |
| SHOW_INT(n_bcast_buf); |
| SHOW_INT(tcp_queue_limit); |
| SHOW_INT(real_hash_size); |
| SHOW_INT(virtual_hash_size); |
| SHOW_STR(client_connect_script); |
| SHOW_STR(learn_address_script); |
| SHOW_STR(client_disconnect_script); |
| SHOW_STR(client_config_dir); |
| SHOW_BOOL(ccd_exclusive); |
| SHOW_STR(tmp_dir); |
| SHOW_BOOL(push_ifconfig_defined); |
| msg(D_SHOW_PARMS, " push_ifconfig_local = %s", print_in_addr_t(o->push_ifconfig_local, 0, &gc)); |
| msg(D_SHOW_PARMS, " push_ifconfig_remote_netmask = %s", print_in_addr_t(o->push_ifconfig_remote_netmask, 0, &gc)); |
| SHOW_BOOL(push_ifconfig_ipv6_defined); |
| msg(D_SHOW_PARMS, " push_ifconfig_ipv6_local = %s/%d", print_in6_addr(o->push_ifconfig_ipv6_local, 0, &gc), o->push_ifconfig_ipv6_netbits ); |
| msg(D_SHOW_PARMS, " push_ifconfig_ipv6_remote = %s", print_in6_addr(o->push_ifconfig_ipv6_remote, 0, &gc)); |
| SHOW_BOOL(enable_c2c); |
| SHOW_BOOL(duplicate_cn); |
| SHOW_INT(cf_max); |
| SHOW_INT(cf_per); |
| SHOW_INT(max_clients); |
| SHOW_INT(max_routes_per_client); |
| SHOW_STR(auth_user_pass_verify_script); |
| SHOW_BOOL(auth_user_pass_verify_script_via_file); |
| SHOW_BOOL(auth_token_generate); |
| SHOW_INT(auth_token_lifetime); |
| SHOW_STR_INLINE(auth_token_secret_file); |
| #if PORT_SHARE |
| SHOW_STR(port_share_host); |
| SHOW_STR(port_share_port); |
| #endif |
| SHOW_BOOL(vlan_tagging); |
| msg(D_SHOW_PARMS, " vlan_accept = %s", print_vlan_accept(o->vlan_accept)); |
| SHOW_INT(vlan_pvid); |
| |
| SHOW_BOOL(client); |
| SHOW_BOOL(pull); |
| SHOW_STR(auth_user_pass_file); |
| |
| gc_free(&gc); |
| } |
| |
| #endif /* ! ENABLE_SMALL */ |
| |
| static void |
| option_iroute(struct options *o, |
| const char *network_str, |
| const char *netmask_str, |
| int msglevel) |
| { |
| struct iroute *ir; |
| |
| ALLOC_OBJ_GC(ir, struct iroute, &o->gc); |
| ir->network = getaddr(GETADDR_HOST_ORDER, network_str, 0, NULL, NULL); |
| ir->netbits = -1; |
| |
| 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)) |
| { |
| msg(msglevel, "in --iroute %s %s : Bad network/subnet specification", |
| network_str, |
| netmask_str); |
| return; |
| } |
| } |
| |
| ir->next = o->iroutes; |
| o->iroutes = ir; |
| } |
| |
| static void |
| option_iroute_ipv6(struct options *o, |
| const char *prefix_str, |
| int msglevel) |
| { |
| struct iroute_ipv6 *ir; |
| |
| ALLOC_OBJ_GC(ir, struct iroute_ipv6, &o->gc); |
| |
| if (!get_ipv6_addr(prefix_str, &ir->network, &ir->netbits, msglevel )) |
| { |
| msg(msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification", |
| prefix_str); |
| return; |
| } |
| |
| ir->next = o->iroutes_ipv6; |
| o->iroutes_ipv6 = ir; |
| } |
| #endif /* P2MP */ |
| |
| #ifndef ENABLE_SMALL |
| static void |
| show_http_proxy_options(const struct http_proxy_options *o) |
| { |
| int i; |
| msg(D_SHOW_PARMS, "BEGIN http_proxy"); |
| SHOW_STR(server); |
| SHOW_STR(port); |
| SHOW_STR(auth_method_string); |
| SHOW_STR(auth_file); |
| SHOW_STR(http_version); |
| SHOW_STR(user_agent); |
| for (i = 0; i < MAX_CUSTOM_HTTP_HEADER && o->custom_headers[i].name; i++) |
| { |
| if (o->custom_headers[i].content) |
| { |
| msg(D_SHOW_PARMS, " custom_header[%d] = %s: %s", i, |
| o->custom_headers[i].name, o->custom_headers[i].content); |
| } |
| else |
| { |
| msg(D_SHOW_PARMS, " custom_header[%d] = %s", i, |
| o->custom_headers[i].name); |
| } |
| } |
| msg(D_SHOW_PARMS, "END http_proxy"); |
| } |
| #endif /* ifndef ENABLE_SMALL */ |
| |
| void |
| options_detach(struct options *o) |
| { |
| gc_detach(&o->gc); |
| o->routes = NULL; |
| o->client_nat = NULL; |
| clone_push_list(o); |
| } |
| |
| void |
| rol_check_alloc(struct options *options) |
| { |
| if (!options->routes) |
| { |
| options->routes = new_route_option_list(&options->gc); |
| } |
| } |
| |
| static void |
| rol6_check_alloc(struct options *options) |
| { |
| if (!options->routes_ipv6) |
| { |
| options->routes_ipv6 = new_route_ipv6_option_list(&options->gc); |
| } |
| } |
| |
| static void |
| cnol_check_alloc(struct options *options) |
| { |
| if (!options->client_nat) |
| { |
| options->client_nat = new_client_nat_list(&options->gc); |
| } |
| } |
| |
| #ifndef ENABLE_SMALL |
| static void |
| show_connection_entry(const struct connection_entry *o) |
| { |
| msg(D_SHOW_PARMS, " proto = %s", proto2ascii(o->proto, o->af, false)); |
| SHOW_STR(local); |
| SHOW_STR(local_port); |
| SHOW_STR(remote); |
| SHOW_STR(remote_port); |
| SHOW_BOOL(remote_float); |
| SHOW_BOOL(bind_defined); |
| SHOW_BOOL(bind_local); |
| SHOW_BOOL(bind_ipv6_only); |
| SHOW_INT(connect_retry_seconds); |
| SHOW_INT(connect_timeout); |
| |
| if (o->http_proxy_options) |
| { |
| show_http_proxy_options(o->http_proxy_options); |
| } |
| SHOW_STR(socks_proxy_server); |
| SHOW_STR(socks_proxy_port); |
| SHOW_INT(tun_mtu); |
| SHOW_BOOL(tun_mtu_defined); |
| SHOW_INT(link_mtu); |
| SHOW_BOOL(link_mtu_defined); |
| SHOW_INT(tun_mtu_extra); |
| SHOW_BOOL(tun_mtu_extra_defined); |
| |
| SHOW_INT(mtu_discover_type); |
| |
| #ifdef ENABLE_FRAGMENT |
| SHOW_INT(fragment); |
| #endif |
| SHOW_INT(mssfix); |
| |
| SHOW_INT(explicit_exit_notification); |
| |
| SHOW_STR_INLINE(tls_auth_file); |
| SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), |
| "%s"); |
| SHOW_STR_INLINE(tls_crypt_file); |
| SHOW_STR_INLINE(tls_crypt_v2_file); |
| } |
| |
| |
| static void |
| show_connection_entries(const struct options *o) |
| { |
| if (o->connection_list) |
| { |
| const struct connection_list *l = o->connection_list; |
| int i; |
| for (i = 0; i < l->len; ++i) |
| { |
| msg(D_SHOW_PARMS, "Connection profiles [%d]:", i); |
| show_connection_entry(l->array[i]); |
| } |
| } |
| else |
| { |
| msg(D_SHOW_PARMS, "Connection profiles [default]:"); |
| show_connection_entry(&o->ce); |
| } |
| msg(D_SHOW_PARMS, "Connection profiles END"); |
| } |
| |
| static void |
| show_pull_filter_list(const struct pull_filter_list *l) |
| { |
| struct pull_filter *f; |
| if (!l) |
| { |
| return; |
| } |
| |
| msg(D_SHOW_PARMS, " Pull filters:"); |
| for (f = l->head; f; f = f->next) |
| { |
| msg(D_SHOW_PARMS, " %s \"%s\"", pull_filter_type_name(f->type), f->pattern); |
| } |
| } |
| |
| #endif /* ifndef ENABLE_SMALL */ |
| |
| void |
| show_settings(const struct options *o) |
| { |
| #ifndef ENABLE_SMALL |
| msg(D_SHOW_PARMS, "Current Parameter Settings:"); |
| |
| SHOW_STR(config); |
| |
| SHOW_INT(mode); |
| |
| #ifdef ENABLE_FEATURE_TUN_PERSIST |
| SHOW_BOOL(persist_config); |
| SHOW_INT(persist_mode); |
| #endif |
| |
| SHOW_BOOL(show_ciphers); |
| SHOW_BOOL(show_digests); |
| SHOW_BOOL(show_engines); |
| SHOW_BOOL(genkey); |
| SHOW_STR(genkey_filename); |
| SHOW_STR(key_pass_file); |
| SHOW_BOOL(show_tls_ciphers); |
| |
| SHOW_INT(connect_retry_max); |
| show_connection_entries(o); |
| |
| SHOW_BOOL(remote_random); |
| |
| SHOW_STR(ipchange); |
| SHOW_STR(dev); |
| SHOW_STR(dev_type); |
| SHOW_STR(dev_node); |
| SHOW_STR(lladdr); |
| SHOW_INT(topology); |
| SHOW_STR(ifconfig_local); |
| SHOW_STR(ifconfig_remote_netmask); |
| SHOW_BOOL(ifconfig_noexec); |
| SHOW_BOOL(ifconfig_nowarn); |
| SHOW_STR(ifconfig_ipv6_local); |
| SHOW_INT(ifconfig_ipv6_netbits); |
| SHOW_STR(ifconfig_ipv6_remote); |
| |
| #ifdef ENABLE_FEATURE_SHAPER |
| SHOW_INT(shaper); |
| #endif |
| SHOW_INT(mtu_test); |
| |
| SHOW_BOOL(mlock); |
| |
| SHOW_INT(keepalive_ping); |
| SHOW_INT(keepalive_timeout); |
| SHOW_INT(inactivity_timeout); |
| SHOW_INT(ping_send_timeout); |
| SHOW_INT(ping_rec_timeout); |
| SHOW_INT(ping_rec_timeout_action); |
| SHOW_BOOL(ping_timer_remote); |
| SHOW_INT(remap_sigusr1); |
| SHOW_BOOL(persist_tun); |
| SHOW_BOOL(persist_local_ip); |
| SHOW_BOOL(persist_remote_ip); |
| SHOW_BOOL(persist_key); |
| |
| #if PASSTOS_CAPABILITY |
| SHOW_BOOL(passtos); |
| #endif |
| |
| SHOW_INT(resolve_retry_seconds); |
| SHOW_BOOL(resolve_in_advance); |
| |
| SHOW_STR(username); |
| SHOW_STR(groupname); |
| SHOW_STR(chroot_dir); |
| SHOW_STR(cd_dir); |
| #ifdef ENABLE_SELINUX |
| SHOW_STR(selinux_context); |
| #endif |
| SHOW_STR(writepid); |
| SHOW_STR(up_script); |
| SHOW_STR(down_script); |
| SHOW_BOOL(down_pre); |
| SHOW_BOOL(up_restart); |
| SHOW_BOOL(up_delay); |
| SHOW_BOOL(daemon); |
| SHOW_INT(inetd); |
| SHOW_BOOL(log); |
| SHOW_BOOL(suppress_timestamps); |
| SHOW_BOOL(machine_readable_output); |
| SHOW_INT(nice); |
| SHOW_INT(verbosity); |
| SHOW_INT(mute); |
| #ifdef ENABLE_DEBUG |
| SHOW_INT(gremlin); |
| #endif |
| SHOW_STR(status_file); |
| SHOW_INT(status_file_version); |
| SHOW_INT(status_file_update_freq); |
| |
| SHOW_BOOL(occ); |
| SHOW_INT(rcvbuf); |
| SHOW_INT(sndbuf); |
| #if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK |
| SHOW_INT(mark); |
| #endif |
| SHOW_INT(sockflags); |
| |
| 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); |
| SHOW_INT(route_default_metric); |
| SHOW_BOOL(route_noexec); |
| SHOW_INT(route_delay); |
| SHOW_INT(route_delay_window); |
| SHOW_BOOL(route_delay_defined); |
| SHOW_BOOL(route_nopull); |
| SHOW_BOOL(route_gateway_via_dhcp); |
| SHOW_BOOL(allow_pull_fqdn); |
| show_pull_filter_list(o->pull_filter_list); |
| |
| if (o->routes) |
| { |
| print_route_options(o->routes, D_SHOW_PARMS); |
| } |
| |
| if (o->client_nat) |
| { |
| print_client_nat_list(o->client_nat, D_SHOW_PARMS); |
| } |
| |
| #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); |
| #endif |
| #ifdef ENABLE_PLUGIN |
| if (o->plugin_list) |
| { |
| plugin_option_list_print(o->plugin_list, D_SHOW_PARMS); |
| } |
| #endif |
| |
| SHOW_STR_INLINE(shared_secret_file); |
| SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), "%s"); |
| SHOW_STR(ciphername); |
| SHOW_BOOL(ncp_enabled); |
| SHOW_STR(ncp_ciphers); |
| SHOW_STR(authname); |
| SHOW_STR(prng_hash); |
| SHOW_INT(prng_nonce_secret_len); |
| SHOW_INT(keysize); |
| #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(packet_id_file); |
| SHOW_BOOL(test_crypto); |
| #ifdef ENABLE_PREDICTION_RESISTANCE |
| SHOW_BOOL(use_prediction_resistance); |
| #endif |
| |
| SHOW_BOOL(tls_server); |
| SHOW_BOOL(tls_client); |
| 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"); |
| } |
| else |
| #endif |
| 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"); |
| } |
| else |
| #endif |
| SHOW_STR_INLINE(priv_key_file); |
| #ifndef ENABLE_CRYPTO_MBEDTLS |
| SHOW_STR_INLINE(pkcs12_file); |
| #endif |
| #ifdef ENABLE_CRYPTOAPI |
| SHOW_STR(cryptoapi_cert); |
| #endif |
| SHOW_STR(cipher_list); |
| 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); |
| SHOW_INT(ns_cert_type); |
| { |
| int i; |
| for (i = 0; i<MAX_PARMS; i++) |
| { |
| SHOW_INT(remote_cert_ku[i]); |
| } |
| } |
| SHOW_STR(remote_cert_eku); |
| SHOW_INT(ssl_flags); |
| |
| SHOW_INT(tls_timeout); |
| |
| SHOW_INT(renegotiate_bytes); |
| SHOW_INT(renegotiate_packets); |
| SHOW_INT(renegotiate_seconds); |
| |
| SHOW_INT(handshake_window); |
| SHOW_INT(transition_window); |
| |
| SHOW_BOOL(single_session); |
| SHOW_BOOL(push_peer_info); |
| SHOW_BOOL(tls_exit); |
| |
| SHOW_STR(tls_crypt_v2_metadata); |
| |
| #ifdef ENABLE_PKCS11 |
| { |
| int i; |
| for (i = 0; i<MAX_PARMS && o->pkcs11_providers[i] != NULL; i++) |
| { |
| SHOW_PARM(pkcs11_providers, o->pkcs11_providers[i], "%s"); |
| } |
| } |
| { |
| int i; |
| for (i = 0; i<MAX_PARMS; i++) |
| { |
| SHOW_PARM(pkcs11_protected_authentication, o->pkcs11_protected_authentication[i] ? "ENABLED" : "DISABLED", "%s"); |
| } |
| } |
| { |
| int i; |
| for (i = 0; i<MAX_PARMS; i++) |
| { |
| SHOW_PARM(pkcs11_private_mode, o->pkcs11_private_mode[i], "%08x"); |
| } |
| } |
| { |
| int i; |
| for (i = 0; i<MAX_PARMS; i++) |
| { |
| SHOW_PARM(pkcs11_cert_private, o->pkcs11_cert_private[i] ? "ENABLED" : "DISABLED", "%s"); |
| } |
| } |
| SHOW_INT(pkcs11_pin_cache_period); |
| SHOW_STR(pkcs11_id); |
| SHOW_BOOL(pkcs11_id_management); |
| #endif /* ENABLE_PKCS11 */ |
| |
| #if P2MP |
| show_p2mp_parms(o); |
| #endif |
| |
| #ifdef _WIN32 |
| SHOW_BOOL(show_net_up); |
| SHOW_INT(route_method); |
| SHOW_BOOL(block_outside_dns); |
| show_tuntap_options(&o->tuntap_options); |
| #endif |
| #endif /* ifndef ENABLE_SMALL */ |
| } |
| |
| #undef SHOW_PARM |
| #undef SHOW_STR |
| #undef SHOW_INT |
| #undef SHOW_BOOL |
| |
| #ifdef ENABLE_MANAGEMENT |
| |
| static struct http_proxy_options * |
| parse_http_proxy_override(const char *server, |
| const char *port, |
| const char *flags, |
| const int msglevel, |
| struct gc_arena *gc) |
| { |
| if (server && port) |
| { |
| struct http_proxy_options *ho; |
| ALLOC_OBJ_CLEAR_GC(ho, struct http_proxy_options, gc); |
| ho->server = string_alloc(server, gc); |
| ho->port = port; |
| if (flags && !strcmp(flags, "nct")) |
| { |
| ho->auth_retry = PAR_NCT; |
| } |
| else |
| { |
| ho->auth_retry = PAR_ALL; |
| } |
| ho->http_version = "1.0"; |
| ho->user_agent = "OpenVPN-Autoproxy/1.0"; |
| return ho; |
| } |
| else |
| { |
| return NULL; |
| } |
| } |
| |
| static void |
| options_postprocess_http_proxy_override(struct options *o) |
| { |
| const struct connection_list *l = o->connection_list; |
| int i; |
| bool succeed = false; |
| for (i = 0; i < l->len; ++i) |
| { |
| struct connection_entry *ce = l->array[i]; |
| if (ce->proto == PROTO_TCP_CLIENT || ce->proto == PROTO_TCP) |
| { |
| ce->http_proxy_options = o->http_proxy_override; |
| succeed = true; |
| } |
| } |
| if (succeed) |
| { |
| for (i = 0; i < l->len; ++i) |
| { |
| struct connection_entry *ce = l->array[i]; |
| if (ce->proto == PROTO_UDP) |
| { |
| ce->flags |= CE_DISABLED; |
| } |
| } |
| } |
| else |
| { |
| msg(M_WARN, "Note: option http-proxy-override ignored because no TCP-based connection profiles are defined"); |
| } |
| } |
| |
| #endif /* ifdef ENABLE_MANAGEMENT */ |
| |
| static struct connection_list * |
| alloc_connection_list_if_undef(struct options *options) |
| { |
| if (!options->connection_list) |
| { |
| ALLOC_OBJ_CLEAR_GC(options->connection_list, struct connection_list, &options->gc); |
| } |
| return options->connection_list; |
| } |
| |
| static struct connection_entry * |
| alloc_connection_entry(struct options *options, const int msglevel) |
| { |
| struct connection_list *l = alloc_connection_list_if_undef(options); |
| struct connection_entry *e; |
| |
| if (l->len >= CONNECTION_LIST_SIZE) |
| { |
| msg(msglevel, "Maximum number of 'connection' options (%d) exceeded", CONNECTION_LIST_SIZE); |
| return NULL; |
| } |
| ALLOC_OBJ_GC(e, struct connection_entry, &options->gc); |
| l->array[l->len++] = e; |
| return e; |
| } |
| |
| static struct remote_list * |
| alloc_remote_list_if_undef(struct options *options) |
| { |
| if (!options->remote_list) |
| { |
| ALLOC_OBJ_CLEAR_GC(options->remote_list, struct remote_list, &options->gc); |
| } |
| return options->remote_list; |
| } |
| |
| static struct remote_entry * |
| alloc_remote_entry(struct options *options, const int msglevel) |
| { |
| struct remote_list *l = alloc_remote_list_if_undef(options); |
| struct remote_entry *e; |
| |
| if (l->len >= CONNECTION_LIST_SIZE) |
| { |
| msg(msglevel, "Maximum number of 'remote' options (%d) exceeded", CONNECTION_LIST_SIZE); |
| return NULL; |
| } |
| ALLOC_OBJ_GC(e, struct remote_entry, &options->gc); |
| l->array[l->len++] = e; |
| return e; |
| } |
| |
| static struct pull_filter_list * |
| alloc_pull_filter_list(struct options *o) |
| { |
| if (!o->pull_filter_list) |
| { |
| ALLOC_OBJ_CLEAR_GC(o->pull_filter_list, struct pull_filter_list, &o->gc); |
| } |
| return o->pull_filter_list; |
| } |
| |
| static struct pull_filter * |
| alloc_pull_filter(struct options *o, const int msglevel) |
| { |
| struct pull_filter_list *l = alloc_pull_filter_list(o); |
| struct pull_filter *f; |
| |
| ALLOC_OBJ_CLEAR_GC(f, struct pull_filter, &o->gc); |
| if (l->head) |
| { |
| ASSERT(l->tail); |
| l->tail->next = f; |
| } |
| else |
| { |
| ASSERT(!l->tail); |
| l->head = f; |
| } |
| l->tail = f; |
| return f; |
| } |
| |
| static void |
| connection_entry_load_re(struct connection_entry *ce, const struct remote_entry *re) |
| { |
| if (re->remote) |
| { |
| ce->remote = re->remote; |
| } |
| if (re->remote_port) |
| { |
| ce->remote_port = re->remote_port; |
| } |
| if (re->proto >= 0) |
| { |
| ce->proto = re->proto; |
| } |
| if (re->af > 0) |
| { |
| ce->af = re->af; |
| } |
| } |
| |
| static void |
| connection_entry_preload_key(const char **key_file, bool *key_inline, |
| struct gc_arena *gc) |
| { |
| if (key_file && *key_file && !(*key_inline)) |
| { |
| struct buffer in = buffer_read_from_file(*key_file, gc); |
| if (!buf_valid(&in)) |
| { |
| msg(M_FATAL, "Cannot pre-load keyfile (%s)", *key_file); |
| } |
| |
| *key_file = (const char *) in.data; |
| *key_inline = true; |
| } |
| } |
| |
| static void |
| options_postprocess_verify_ce(const struct options *options, |
| const struct connection_entry *ce) |
| { |
| struct options defaults; |
| int dev = DEV_TYPE_UNDEF; |
| bool pull = false; |
| |
| init_options(&defaults, true); |
| |
| if (options->test_crypto) |
| { |
| notnull(options->shared_secret_file, "key file (--secret)"); |
| } |
| else |
| { |
| notnull(options->dev, "TUN/TAP device (--dev)"); |
| } |
| |
| /* |
| * Get tun/tap/null device type |
| */ |
| dev = dev_type_enum(options->dev, options->dev_type); |
| |
| /* |
| * If "proto tcp" is specified, make sure we know whether it is |
| * tcp-client or tcp-server. |
| */ |
| if (ce->proto == PROTO_TCP) |
| { |
| msg(M_USAGE, |
| "--proto tcp is ambiguous in this context. Please specify " |
| "--proto tcp-server or --proto tcp-client"); |
| } |
| |
| /* |
| * Sanity check on daemon/inetd modes |
| */ |
| |
| if (options->daemon && options->inetd) |
| { |
| msg(M_USAGE, "only one of --daemon or --inetd may be specified"); |
| } |
| |
| if (options->inetd && (ce->local || ce->remote)) |
| { |
| msg(M_USAGE, "--local or --remote cannot be used with --inetd"); |
| } |
| |
| if (options->inetd && ce->proto == PROTO_TCP_CLIENT) |
| { |
| msg(M_USAGE, "--proto tcp-client cannot be used with --inetd"); |
| } |
| |
| if (options->inetd == INETD_NOWAIT && ce->proto != PROTO_TCP_SERVER) |
| { |
| msg(M_USAGE, "--inetd nowait can only be used with --proto tcp-server"); |
| } |
| |
| if (options->inetd == INETD_NOWAIT |
| && !(options->tls_server || options->tls_client)) |
| { |
| msg(M_USAGE, "--inetd nowait can only be used in TLS mode"); |
| } |
| |
| if (options->inetd == INETD_NOWAIT && dev != DEV_TYPE_TAP) |
| { |
| msg(M_USAGE, "--inetd nowait only makes sense in --dev tap mode"); |
| } |
| |
| if (options->inetd) |
| { |
| msg(M_WARN, |
| "DEPRECATED OPTION: --inetd mode is deprecated and will be removed " |
| "in OpenVPN 2.6"); |
| } |
| |
| if (options->lladdr && dev != DEV_TYPE_TAP) |
| { |
| msg(M_USAGE, "--lladdr can only be used in --dev tap mode"); |
| } |
| |
| /* |
| * Sanity check on MTU parameters |
| */ |
| 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); |
| } |
| |
| if (!proto_is_udp(ce->proto) && options->mtu_test) |
| { |
| msg(M_USAGE, "--mtu-test only makes sense with --proto udp"); |
| } |
| |
| /* will we be pulling options from server? */ |
| #if P2MP |
| pull = options->pull; |
| #endif |
| |
| /* |
| * Sanity check on --local, --remote, and --ifconfig |
| */ |
| |
| if (proto_is_net(ce->proto) |
| && string_defined_equal(ce->local, ce->remote) |
| && string_defined_equal(ce->local_port, ce->remote_port)) |
| { |
| msg(M_USAGE, "--remote and --local addresses are the same"); |
| } |
| |
| if (string_defined_equal(ce->remote, options->ifconfig_local) |
| || string_defined_equal(ce->remote, options->ifconfig_remote_netmask)) |
| { |
| msg(M_USAGE, |
| "--local and --remote addresses must be distinct from --ifconfig " |
| "addresses"); |
| } |
| |
| if (string_defined_equal(ce->local, options->ifconfig_local) |
| || string_defined_equal(ce->local, options->ifconfig_remote_netmask)) |
| { |
| msg(M_USAGE, |
| "--local addresses must be distinct from --ifconfig addresses"); |
| } |
| |
| if (string_defined_equal(options->ifconfig_local, |
| options->ifconfig_remote_netmask)) |
| { |
| msg(M_USAGE, |
| "local and remote/netmask --ifconfig addresses must be different"); |
| } |
| |
| if (ce->bind_defined && !ce->bind_local) |
| { |
| msg(M_USAGE, "--bind and --nobind can't be used together"); |
| } |
| |
| if (ce->local && !ce->bind_local) |
| { |
| msg(M_USAGE, |
| "--local and --nobind don't make sense when used together"); |
| } |
| |
| if (ce->local_port_defined && !ce->bind_local) |
| { |
| msg(M_USAGE, |
| "--lport and --nobind don't make sense when used together"); |
| } |
| |
| if (!ce->remote && !ce->bind_local) |
| { |
| msg(M_USAGE, "--nobind doesn't make sense unless used with --remote"); |
| } |
| |
| /* |
| * Check for consistency of management options |
| */ |
| #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"); |
| } |
| |
| if ((options->management_client_user || options->management_client_group) |
| && !(options->management_flags & MF_UNIX_SOCK)) |
| { |
| msg(M_USAGE, "--management-client-(user|group) can only be used on unix domain sockets"); |
| } |
| |
| if (options->management_addr |
| && !(options->management_flags & MF_UNIX_SOCK) |
| && (!options->management_user_pass)) |
| { |
| msg(M_WARN, "WARNING: Using --management on a TCP port WITHOUT " |
| "passwords is STRONGLY discouraged and considered insecure"); |
| } |
| |
| #endif /* ifdef ENABLE_MANAGEMENT */ |
| |
| #if defined(ENABLE_MANAGEMENT) |
| 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"); |
| } |
| #endif |
| /* |
| * Windows-specific options. |
| */ |
| |
| #ifdef _WIN32 |
| if (dev == DEV_TYPE_TUN && !(pull || (options->ifconfig_local && options->ifconfig_remote_netmask))) |
| { |
| msg(M_USAGE, "On Windows, --ifconfig is required when --dev tun is used"); |
| } |
| |
| if ((options->tuntap_options.ip_win32_defined) |
| && !(pull || (options->ifconfig_local && options->ifconfig_remote_netmask))) |
| { |
| 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) |
| { |
| msg(M_USAGE, "--dhcp-option requires --ip-win32 dynamic or adaptive"); |
| } |
| |
| if (options->windows_driver == WINDOWS_DRIVER_WINTUN && dev != DEV_TYPE_TUN) |
| { |
| msg(M_USAGE, "--windows-driver wintun requires --dev tun"); |
| } |
| #endif /* ifdef _WIN32 */ |
| |
| /* |
| * Check that protocol options make sense. |
| */ |
| |
| #ifdef ENABLE_FRAGMENT |
| if (!proto_is_udp(ce->proto) && ce->fragment) |
| { |
| msg(M_USAGE, "--fragment can only be used with --proto udp"); |
| } |
| #endif |
| |
| if (!proto_is_udp(ce->proto) && ce->explicit_exit_notification) |
| { |
| msg(M_USAGE, |
| "--explicit-exit-notify can only be used with --proto udp"); |
| } |
| |
| if (!ce->remote && ce->proto == PROTO_TCP_CLIENT) |
| { |
| msg(M_USAGE, "--remote MUST be used in TCP Client mode"); |
| } |
| |
| if ((ce->http_proxy_options) && ce->proto != PROTO_TCP_CLIENT) |
| { |
| msg(M_USAGE, |
| "--http-proxy MUST be used in TCP Client mode (i.e. --proto " |
| "tcp-client)"); |
| } |
| |
| if ((ce->http_proxy_options) && !ce->http_proxy_options->server) |
| { |
| msg(M_USAGE, |
| "--http-proxy not specified but other http proxy options present"); |
| } |
| |
| if (ce->http_proxy_options && ce->socks_proxy_server) |
| { |
| msg(M_USAGE, |
| "--http-proxy can not be used together with --socks-proxy"); |
| } |
| |
| if (ce->socks_proxy_server && ce->proto == PROTO_TCP_SERVER) |
| { |
| msg(M_USAGE, "--socks-proxy can not be used in TCP Server mode"); |
| } |
| |
| if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1)) |
| { |
| msg(M_USAGE, "TCP server mode allows at most one --remote address"); |
| } |
| |
| /* |
| * Check consistency of --mode server options. |
| */ |
| if (options->mode == MODE_SERVER) |
| { |
| #ifdef TARGET_ANDROID |
| msg(M_FATAL, "--mode server not supported on Android"); |
| #endif |
| if (!(dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP)) |
| { |
| msg(M_USAGE, "--mode server only works with --dev tun or --dev tap"); |
| } |
| if (options->pull) |
| { |
| msg(M_USAGE, "--pull cannot be used with --mode server"); |
| } |
| if (options->pull_filter_list) |
| { |
| msg(M_WARN, "--pull-filter ignored for --mode server"); |
| } |
| 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"); |
| } |
| #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)"); |
| } |
| #endif |
| if (!options->tls_server) |
| { |
| msg(M_USAGE, "--mode server requires --tls-server"); |
| } |
| if (ce->remote) |
| { |
| msg(M_USAGE, "--remote cannot be used with --mode server"); |
| } |
| if (!ce->bind_local) |
| { |
| msg(M_USAGE, "--nobind cannot be used with --mode server"); |
| } |
| if (ce->http_proxy_options) |
| { |
| msg(M_USAGE, "--http-proxy cannot be used with --mode server"); |
| } |
| if (ce->socks_proxy_server) |
| { |
| msg(M_USAGE, "--socks-proxy cannot be used with --mode server"); |
| } |
| /* <connection> blocks force to have a remote embedded, so we check |
| * for the --remote and bail out if it is present |
| */ |
| if (options->connection_list->len >1 |
| || options->connection_list->array[0]->remote) |
| { |
| msg(M_USAGE, "<connection> cannot be used with --mode server"); |
| } |
| |
| if (options->shaper) |
| { |
| msg(M_USAGE, "--shaper cannot be used with --mode server"); |
| } |
| if (options->inetd) |
| { |
| msg(M_USAGE, "--inetd cannot be used with --mode server"); |
| } |
| if (options->ipchange) |
| { |
| msg(M_USAGE, |
| "--ipchange cannot be used with --mode server (use " |
| "--client-connect instead)"); |
| } |
| 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"); |
| } |
| if (!proto_is_udp(ce->proto) && (options->cf_max || options->cf_per)) |
| { |
| msg(M_USAGE, "--connect-freq only works with --mode server --proto udp. Try --max-clients instead."); |
| } |
| if (!(dev == DEV_TYPE_TAP || (dev == DEV_TYPE_TUN && options->topology == TOP_SUBNET)) && options->ifconfig_pool_netmask) |
| { |
| msg(M_USAGE, "The third parameter to --ifconfig-pool (netmask) is only valid in --dev tap mode"); |
| } |
| if (options->routes && (options->routes->flags & RG_ENABLE)) |
| { |
| msg(M_USAGE, "--redirect-gateway cannot be used with --mode server (however --push \"redirect-gateway\" is fine)"); |
| } |
| if (options->route_delay_defined) |
| { |
| msg(M_USAGE, "--route-delay cannot be used with --mode server"); |
| } |
| if (options->up_delay) |
| { |
| msg(M_USAGE, "--up-delay cannot be used with --mode server"); |
| } |
| if (!options->ifconfig_pool_defined |
| && !options->ifconfig_ipv6_pool_defined |
| && options->ifconfig_pool_persist_filename) |
| { |
| msg(M_USAGE, |
| "--ifconfig-pool-persist must be used with --ifconfig-pool or --ifconfig-ipv6-pool"); |
| } |
| if (options->ifconfig_ipv6_pool_defined && !options->ifconfig_ipv6_local) |
| { |
| msg(M_USAGE, "--ifconfig-ipv6-pool needs --ifconfig-ipv6"); |
| } |
| if (options->allow_recursive_routing) |
| { |
| msg(M_USAGE, "--allow-recursive-routing cannot be used with --mode server"); |
| } |
| if (options->auth_user_pass_file) |
| { |
| msg(M_USAGE, "--auth-user-pass cannot be used with --mode server (it should be used on the client side only)"); |
| } |
| if (options->ccd_exclusive && !options->client_config_dir) |
| { |
| msg(M_USAGE, "--ccd-exclusive must be used with --client-config-dir"); |
| } |
| if (options->auth_token_generate && !options->renegotiate_seconds) |
| { |
| msg(M_USAGE, "--auth-gen-token needs a non-infinite " |
| "--renegotiate_seconds setting"); |
| } |
| { |
| const bool ccnr = (options->auth_user_pass_verify_script |
| || PLUGIN_OPTION_LIST(options) |
| || MAN_CLIENT_AUTH_ENABLED(options)); |
| const char *postfix = "must be used with --management-client-auth, an --auth-user-pass-verify script, or plugin"; |
| if ((options->ssl_flags & (SSLF_CLIENT_CERT_NOT_REQUIRED|SSLF_CLIENT_CERT_OPTIONAL)) && !ccnr) |
| { |
| msg(M_USAGE, "--verify-client-cert none|optional %s", postfix); |
| } |
| if ((options->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && !ccnr) |
| { |
| msg(M_USAGE, "--username-as-common-name %s", postfix); |
| } |
| if ((options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) && !ccnr) |
| { |
| msg(M_USAGE, "--auth-user-pass-optional %s", postfix); |
| } |
| } |
| |
| if (options->vlan_tagging && dev != DEV_TYPE_TAP) |
| { |
| msg(M_USAGE, "--vlan-tagging must be used with --dev tap"); |
| } |
| if (!options->vlan_tagging) |
| { |
| if (options->vlan_accept != defaults.vlan_accept) |
| { |
| msg(M_USAGE, "--vlan-accept requires --vlan-tagging"); |
| } |
| if (options->vlan_pvid != defaults.vlan_pvid) |
| { |
| msg(M_USAGE, "--vlan-pvid requires --vlan-tagging"); |
| } |
| } |
| } |
| else |
| { |
| /* |
| * When not in server mode, err if parameters are |
| * specified which require --mode server. |
| */ |
| if (options->ifconfig_pool_defined || options->ifconfig_pool_persist_filename) |
| { |
| msg(M_USAGE, "--ifconfig-pool/--ifconfig-pool-persist requires --mode server"); |
| } |
| if (options->ifconfig_ipv6_pool_defined) |
| { |
| msg(M_USAGE, "--ifconfig-ipv6-pool requires --mode server"); |
| } |
| if (options->real_hash_size != defaults.real_hash_size |
| || options->virtual_hash_size != defaults.virtual_hash_size) |
| { |
| msg(M_USAGE, "--hash-size requires --mode server"); |
| } |
| if (options->learn_address_script) |
| { |
| msg(M_USAGE, "--learn-address requires --mode server"); |
| } |
| if (options->client_connect_script) |
| { |
| msg(M_USAGE, "--client-connect requires --mode server"); |
| } |
| if (options->client_disconnect_script) |
| { |
| msg(M_USAGE, "--client-disconnect requires --mode server"); |
| } |
| if (options->client_config_dir || options->ccd_exclusive) |
| { |
| msg(M_USAGE, "--client-config-dir/--ccd-exclusive requires --mode server"); |
| } |
| if (options->enable_c2c) |
| { |
| msg(M_USAGE, "--client-to-client requires --mode server"); |
| } |
| if (options->duplicate_cn) |
| { |
| msg(M_USAGE, "--duplicate-cn requires --mode server"); |
| } |
| if (options->cf_max || options->cf_per) |
| { |
| msg(M_USAGE, "--connect-freq requires --mode server"); |
| } |
| if (options->ssl_flags & (SSLF_CLIENT_CERT_NOT_REQUIRED|SSLF_CLIENT_CERT_OPTIONAL)) |
| { |
| msg(M_USAGE, "--verify-client-cert requires --mode server"); |
| } |
| if (options->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) |
| { |
| msg(M_USAGE, "--username-as-common-name requires --mode server"); |
| } |
| if (options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) |
| { |
| msg(M_USAGE, "--auth-user-pass-optional requires --mode server"); |
| } |
| if (options->ssl_flags & SSLF_OPT_VERIFY) |
| { |
| msg(M_USAGE, "--opt-verify requires --mode server"); |
| } |
| if (options->server_flags & SF_TCP_NODELAY_HELPER) |
| { |
| msg(M_WARN, "WARNING: setting tcp-nodelay on the client side will not " |
| "affect the server. To have TCP_NODELAY in both direction use " |
| "tcp-nodelay in the server configuration instead."); |
| } |
| if (options->auth_user_pass_verify_script) |
| { |
| msg(M_USAGE, "--auth-user-pass-verify requires --mode server"); |
| } |
| if (options->auth_token_generate) |
| { |
| msg(M_USAGE, "--auth-gen-token requires --mode server"); |
| } |
| #if PORT_SHARE |
| if (options->port_share_host || options->port_share_port) |
| { |
| msg(M_USAGE, "--port-share requires TCP server mode (--mode server --proto tcp-server)"); |
| } |
| #endif |
| |
| if (options->stale_routes_check_interval) |
| { |
| msg(M_USAGE, "--stale-routes-check requires --mode server"); |
| } |
| |
| if (options->vlan_tagging) |
| { |
| msg(M_USAGE, "--vlan-tagging requires --mode server"); |
| } |
| } |
| |
| if (options->keysize) |
| { |
| msg(M_WARN, "WARNING: --keysize is DEPRECATED and will be removed in OpenVPN 2.6"); |
| } |
| |
| /* |
| * 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 |
| +(options->shared_secret_file != NULL) > 1) |
| { |
| msg(M_USAGE, "specify only one of --tls-server, --tls-client, or --secret"); |
| } |
| |
| if (options->ssl_flags & (SSLF_CLIENT_CERT_NOT_REQUIRED|SSLF_CLIENT_CERT_OPTIONAL)) |
| { |
| msg(M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION " |
| "--verify-client-cert none|optional " |
| "may accept clients which do not present a certificate"); |
| } |
| |
| const int tls_version_max = |
| (options->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) |
| & SSLF_TLS_VERSION_MAX_MASK; |
| const int tls_version_min = |
| (options->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) |
| & SSLF_TLS_VERSION_MIN_MASK; |
| |
| if (tls_version_max > 0 && tls_version_max < tls_version_min) |
| { |
| msg(M_USAGE, "--tls-version-min bigger than --tls-version-max"); |
| } |
| |
| if (options->tls_server || options->tls_client) |
| { |
| #ifdef ENABLE_PKCS11 |
| if (options->pkcs11_providers[0]) |
| { |
| notnull(options->ca_file, "CA file (--ca)"); |
| |
| if (options->pkcs11_id_management && options->pkcs11_id != NULL) |
| { |
| msg(M_USAGE, "Parameter --pkcs11-id cannot be used when --pkcs11-id-management is also specified."); |
| } |
| if (!options->pkcs11_id_management && options->pkcs11_id == NULL) |
| { |
| msg(M_USAGE, "Parameter --pkcs11-id or --pkcs11-id-management should be specified."); |
| } |
| if (options->cert_file) |
| { |
| msg(M_USAGE, "Parameter --cert cannot be used when --pkcs11-provider is also specified."); |
| } |
| if (options->priv_key_file) |
| { |
| 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."); |
| } |
| if (options->management_flags & MF_EXTERNAL_CERT) |
| { |
| 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."); |
| } |
| #ifdef ENABLE_CRYPTOAPI |
| if (options->cryptoapi_cert) |
| { |
| msg(M_USAGE, "Parameter --cryptoapicert cannot be used when --pkcs11-provider is also specified."); |
| } |
| #endif |
| } |
| 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 if ((options->management_flags & MF_EXTERNAL_CERT)) |
| { |
| if (options->cert_file) |
| { |
| msg(M_USAGE, "--cert and --management-external-cert are mutually exclusive"); |
| } |
| else if (!(options->management_flags & MF_EXTERNAL_KEY)) |
| { |
| msg(M_USAGE, "--management-external-cert must be used with --management-external-key"); |
| } |
| } |
| else |
| #endif |
| #ifdef ENABLE_CRYPTOAPI |
| if (options->cryptoapi_cert) |
| { |
| if ((!(options->ca_file)) && (!(options->ca_path))) |
| { |
| msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)"); |
| } |
| if (options->cert_file) |
| { |
| msg(M_USAGE, "Parameter --cert cannot be used when --cryptoapicert is also specified."); |
| } |
| if (options->priv_key_file) |
| { |
| msg(M_USAGE, "Parameter --key cannot be used when --cryptoapicert is also specified."); |
| } |
| if (options->pkcs12_file) |
| { |
| 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."); |
| } |
| if (options->management_flags & MF_EXTERNAL_CERT) |
| { |
| msg(M_USAGE, "Parameter --management-external-cert cannot be used when --cryptoapicert is also specified."); |
| } |
| #endif |
| } |
| else |
| #endif /* ifdef ENABLE_CRYPTOAPI */ |
| if (options->pkcs12_file) |
| { |
| #ifdef ENABLE_CRYPTO_MBEDTLS |
| msg(M_USAGE, "Parameter --pkcs12 cannot be used with the mbed TLS version version of OpenVPN."); |
| #else |
| if (options->ca_path) |
| { |
| msg(M_USAGE, "Parameter --capath cannot be used when --pkcs12 is also specified."); |
| } |
| if (options->cert_file) |
| { |
| msg(M_USAGE, "Parameter --cert cannot be used when --pkcs12 is also specified."); |
| } |
| if (options->priv_key_file) |
| { |
| 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."); |
| } |
| if (options->management_flags & MF_EXTERNAL_CERT) |
| { |
| msg(M_USAGE, "Parameter --management-external-cert cannot be used when --pkcs12 is also specified."); |
| } |
| #endif |
| #endif /* ifdef ENABLE_CRYPTO_MBEDTLS */ |
| } |
| else |
| { |
| #ifdef ENABLE_CRYPTO_MBEDTLS |
| if (!(options->ca_file)) |
| { |
| msg(M_USAGE, "You must define CA file (--ca)"); |
| } |
| if (options->ca_path) |
| { |
| msg(M_USAGE, "Parameter --capath cannot be used with the mbed TLS version version of OpenVPN."); |
| } |
| #else /* ifdef ENABLE_CRYPTO_MBEDTLS */ |
| if ((!(options->ca_file)) && (!(options->ca_path))) |
| { |
| msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)"); |
| } |
| #endif |
| if (pull) |
| { |
| |
| 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 |
| |
| if (sum == 0) |
| { |
| #if P2MP |
| if (!options->auth_user_pass_file) |
| #endif |
| msg(M_USAGE, "No client-side authentication method is specified. You must use either --cert/--key, --pkcs12, or --auth-user-pass"); |
| } |
| else if (sum == 2) |
| { |
| } |
| else |
| { |
| 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 |
| if (!(options->management_flags & MF_EXTERNAL_KEY)) |
| #endif |
| notnull(options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)"); |
| } |
| } |
| if (ce->tls_auth_file && ce->tls_crypt_file) |
| { |
| msg(M_USAGE, "--tls-auth and --tls-crypt are mutually exclusive"); |
| } |
| if (options->tls_client && ce->tls_crypt_v2_file |
| && (ce->tls_auth_file || ce->tls_crypt_file)) |
| { |
| msg(M_USAGE, "--tls-crypt-v2, --tls-auth and --tls-crypt are mutually exclusive in client mode"); |
| } |
| } |
| else |
| { |
| /* |
| * Make sure user doesn't specify any TLS options |
| * when in non-TLS mode. |
| */ |
| |
| #define MUST_BE_UNDEF(parm) if (options->parm != defaults.parm) {msg(M_USAGE, err, #parm); \ |
| } |
| |
| const char err[] = "Parameter %s can only be specified in TLS-mode, i.e. where --tls-server or --tls-client is also specified."; |
| |
| MUST_BE_UNDEF(ca_file); |
| MUST_BE_UNDEF(ca_path); |
| MUST_BE_UNDEF(dh_file); |
| MUST_BE_UNDEF(cert_file); |
| MUST_BE_UNDEF(priv_key_file); |
| #ifndef ENABLE_CRYPTO_MBEDTLS |
| MUST_BE_UNDEF(pkcs12_file); |
| #endif |
| MUST_BE_UNDEF(cipher_list); |
| 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); |
| MUST_BE_UNDEF(renegotiate_packets); |
| MUST_BE_UNDEF(renegotiate_seconds); |
| MUST_BE_UNDEF(handshake_window); |
| MUST_BE_UNDEF(transition_window); |
| MUST_BE_UNDEF(tls_auth_file); |
| MUST_BE_UNDEF(tls_crypt_file); |
| MUST_BE_UNDEF(tls_crypt_v2_file); |
| MUST_BE_UNDEF(single_session); |
| MUST_BE_UNDEF(push_peer_info); |
| MUST_BE_UNDEF(tls_exit); |
| MUST_BE_UNDEF(crl_file); |
| MUST_BE_UNDEF(ns_cert_type); |
| MUST_BE_UNDEF(remote_cert_ku[0]); |
| MUST_BE_UNDEF(remote_cert_eku); |
| #ifdef ENABLE_PKCS11 |
| MUST_BE_UNDEF(pkcs11_providers[0]); |
| MUST_BE_UNDEF(pkcs11_private_mode[0]); |
| MUST_BE_UNDEF(pkcs11_id); |
| MUST_BE_UNDEF(pkcs11_id_management); |
| #endif |
| |
| if (pull) |
| { |
| msg(M_USAGE, err, "--pull"); |
| } |
| } |
| #undef MUST_BE_UNDEF |
| |
| #if P2MP |
| if (options->auth_user_pass_file && !options->pull) |
| { |
| msg(M_USAGE, "--auth-user-pass requires --pull"); |
| } |
| #endif |
| |
| uninit_options(&defaults); |
| } |
| |
| static void |
| options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) |
| { |
| const int dev = dev_type_enum(o->dev, o->dev_type); |
| |
| if (o->server_defined || o->server_bridge_defined || o->server_bridge_proxy_dhcp) |
| { |
| if (ce->proto == PROTO_TCP) |
| { |
| ce->proto = PROTO_TCP_SERVER; |
| } |
| } |
| |
| #if P2MP |
| if (o->client) |
| { |
| if (ce->proto == PROTO_TCP) |
| { |
| ce->proto = PROTO_TCP_CLIENT; |
| } |
| } |
| #endif |
| |
| if (ce->proto == PROTO_TCP_CLIENT && !ce->local |
| && !ce->local_port_defined && !ce->bind_defined) |
| { |
| ce->bind_local = false; |
| } |
| |
| if (ce->proto == PROTO_UDP && ce->socks_proxy_server && !ce->local |
| && !ce->local_port_defined && !ce->bind_defined) |
| { |
| ce->bind_local = false; |
| } |
| |
| if (!ce->bind_local) |
| { |
| ce->local_port = NULL; |
| } |
| |
| /* if protocol forcing is enabled, disable all protocols |
| * except for the forced one |
| */ |
| if (o->proto_force >= 0 && o->proto_force != ce->proto) |
| { |
| 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 (ce->socks_proxy_server && proto_is_udp(ce->proto) && ce->af != AF_INET) |
| { |
| if (ce->af == AF_INET6) |
| { |
| msg(M_INFO, "WARNING: '--proto udp6' is not compatible with " |
| "'--socks-proxy' today. Forcing IPv4 mode." ); |
| } |
| else |
| { |
| msg(M_INFO, "NOTICE: dual-stack mode for '--proto udp' does not " |
| "work correctly with '--socks-proxy' today. Forcing IPv4." ); |
| } |
| ce->af = AF_INET; |
| } |
| |
| /* |
| * Set MTU defaults |
| */ |
| { |
| if (!ce->tun_mtu_defined && !ce->link_mtu_defined) |
| { |
| ce->tun_mtu_defined = true; |
| } |
| if ((dev == DEV_TYPE_TAP) && !ce->tun_mtu_extra_defined) |
| { |
| ce->tun_mtu_extra_defined = true; |
| ce->tun_mtu_extra = TAP_MTU_EXTRA_DEFAULT; |
| } |
| } |
| |
| /* |
| * Set per-connection block tls-auth/crypt/crypto-v2 fields if undefined. |
| * |
| * At the end only one of these will be really set because the parser |
| * logic prevents configurations where more are set. |
| */ |
| if (!ce->tls_auth_file && !ce->tls_crypt_file && !ce->tls_crypt_v2_file) |
| { |
| ce->tls_auth_file = o->tls_auth_file; |
| ce->tls_auth_file_inline = o->tls_auth_file_inline; |
| ce->key_direction = o->key_direction; |
| |
| ce->tls_crypt_file = o->tls_crypt_file; |
| ce->tls_crypt_file_inline = o->tls_crypt_file_inline; |
| |
| ce->tls_crypt_v2_file = o->tls_crypt_v2_file; |
| ce->tls_crypt_v2_file_inline = o->tls_crypt_v2_file_inline; |
| } |
| |
| /* Pre-cache tls-auth/crypt(-v2) key file if persist-key was specified and |
| * keys were not already embedded in the config file. |
| */ |
| if (o->persist_key) |
| { |
| connection_entry_preload_key(&ce->tls_auth_file, |
| &ce->tls_auth_file_inline, &o->gc); |
| connection_entry_preload_key(&ce->tls_crypt_file, |
| &ce->tls_crypt_file_inline, &o->gc); |
| connection_entry_preload_key(&ce->tls_crypt_v2_file, |
| &ce->tls_crypt_v2_file_inline, &o->gc); |
| } |
| } |
| |
| #ifdef _WIN32 |
| /* If iservice is in use, we need def1 method for redirect-gateway */ |
| static void |
| remap_redirect_gateway_flags(struct options *opt) |
| { |
| if (opt->routes |
| && opt->route_method == ROUTE_METHOD_SERVICE |
| && opt->routes->flags & RG_REROUTE_GW |
| && !(opt->routes->flags & RG_DEF1)) |
| { |
| msg(M_INFO, "Flag 'def1' added to --redirect-gateway (iservice is in use)"); |
| opt->routes->flags |= RG_DEF1; |
| } |
| } |
| #endif |
| |
| static void |
| options_postprocess_mutate_invariant(struct options *options) |
| { |
| #ifdef _WIN32 |
| const int dev = dev_type_enum(options->dev, options->dev_type); |
| #endif |
| |
| /* |
| * In forking TCP server mode, you don't need to ifconfig |
| * the tap device (the assumption is that it will be bridged). |
| */ |
| if (options->inetd == INETD_NOWAIT) |
| { |
| options->ifconfig_noexec = true; |
| } |
| |
| #ifdef _WIN32 |
| /* 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)) |
| { |
| 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 */ |
| } |
| } |
| |
| if (options->ifconfig_noexec) |
| { |
| options->tuntap_options.ip_win32_type = IPW32_SET_MANUAL; |
| options->ifconfig_noexec = false; |
| } |
| |
| remap_redirect_gateway_flags(options); |
| |
| /* |
| * Check consistency of --mode server options. |
| */ |
| if (options->mode == MODE_SERVER) |
| { |
| /* |
| * We need to explicitly set --tap-sleep because |
| * we do not schedule event timers in the top-level context. |
| */ |
| options->tuntap_options.tap_sleep = 10; |
| if (options->route_delay_defined && options->route_delay) |
| { |
| options->tuntap_options.tap_sleep = options->route_delay; |
| } |
| options->route_delay_defined = false; |
| } |
| #endif /* ifdef _WIN32 */ |
| |
| #ifdef DEFAULT_PKCS11_MODULE |
| /* If p11-kit is present on the system then load its p11-kit-proxy.so |
| * by default if the user asks for PKCS#11 without otherwise specifying |
| * the module to use. */ |
| if (!options->pkcs11_providers[0] |
| && (options->pkcs11_id || options->pkcs11_id_management)) |
| { |
| options->pkcs11_providers[0] = DEFAULT_PKCS11_MODULE; |
| } |
| #endif |
| } |
| |
| static void |
| options_postprocess_verify(const struct options *o) |
| { |
| if (o->connection_list) |
| { |
| int i; |
| for (i = 0; i < o->connection_list->len; ++i) |
| { |
| options_postprocess_verify_ce(o, o->connection_list->array[i]); |
| } |
| } |
| else |
| { |
| options_postprocess_verify_ce(o, &o->ce); |
| } |
| } |
| |
| static void |
| options_postprocess_cipher(struct options *o) |
| { |
| if (!o->pull && !(o->mode == MODE_SERVER)) |
| { |
| /* we are in the classic P2P mode */ |
| o->ncp_enabled = false; |
| msg( M_WARN, "Cipher negotiation is disabled since neither " |
| "P2MP client nor server mode is enabled"); |
| |
| /* If the cipher is not set, use the old default of BF-CBC. We will |
| * warn that this is deprecated on cipher initialisation, no need |
| * to warn here as well */ |
| if (!o->ciphername) |
| { |
| o->ciphername = "BF-CBC"; |
| } |
| return; |
| } |
| |
| /* pull or P2MP mode */ |
| if (!o->ciphername) |
| { |
| if (!o->ncp_enabled) |
| { |
| msg(M_USAGE, "--ncp-disable needs an explicit --cipher or " |
| "--data-ciphers-fallback config option"); |
| } |
| |
| msg(M_WARN, "--cipher is not set. Previous OpenVPN version 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."); |
| |
| /* We still need to set the ciphername to BF-CBC since various other |
| * parts of OpenVPN assert that the ciphername is set */ |
| o->ciphername = "BF-CBC"; |
| } |
| else if (!o->enable_ncp_fallback |
| && !tls_item_in_cipher_list(o->ciphername, o->ncp_ciphers)) |
| { |
| msg(M_WARN, "DEPRECATED OPTION: --cipher set to '%s' but missing in" |
| " --data-ciphers (%s). Future OpenVPN version will " |
| "ignore --cipher for cipher negotiations. " |
| "Add '%s' to --data-ciphers or change --cipher '%s' to " |
| "--data-ciphers-fallback '%s' to silence this warning.", |
| o->ciphername, o->ncp_ciphers, o->ciphername, |
| o->ciphername, o->ciphername); |
| o->enable_ncp_fallback = true; |
| |
| /* Append the --cipher to ncp_ciphers to allow it in NCP */ |
| size_t newlen = strlen(o->ncp_ciphers) + 1 + strlen(o->ciphername) + 1; |
| char *ncp_ciphers = gc_malloc(newlen, false, &o->gc); |
| |
| ASSERT(openvpn_snprintf(ncp_ciphers, newlen, "%s:%s", o->ncp_ciphers, |
| o->ciphername)); |
| o->ncp_ciphers = ncp_ciphers; |
| } |
| } |
| |
| static void |
| options_postprocess_mutate(struct options *o) |
| { |
| int i; |
| /* |
| * Process helper-type options which map to other, more complex |
| * sequences of options. |
| */ |
| helper_client_server(o); |
| helper_keepalive(o); |
| helper_tcp_nodelay(o); |
| |
| options_postprocess_cipher(o); |
| options_postprocess_mutate_invariant(o); |
| |
| if (o->ncp_enabled) |
| { |
| o->ncp_ciphers = mutate_ncp_cipher_list(o->ncp_ciphers, &o->gc); |
| if (o->ncp_ciphers == NULL) |
| { |
| msg(M_USAGE, "NCP cipher list contains unsupported ciphers or is too long."); |
| } |
| } |
| |
| if (o->remote_list && !o->connection_list) |
| { |
| /* |
| * Convert remotes into connection list |
| */ |
| const struct remote_list *rl = o->remote_list; |
| for (i = 0; i < rl->len; ++i) |
| { |
| const |