summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Schmidt <berni@debian.org>2021-02-24 19:54:12 +0100
committerBernhard Schmidt <berni@debian.org>2021-02-24 19:54:12 +0100
commit4ee98f284a93c3b855092d35ac21371d9dcad65b (patch)
treedc5a9759b8165b50d028db416367767b82f42f49
parent0816f633cec4254ccfd98901252eefe84b0e2648 (diff)
New upstream version 2.5.1upstream/2.5.1
-rw-r--r--ChangeLog43
-rw-r--r--Changes.rst74
-rwxr-xr-xconfigure26
-rw-r--r--doc/Makefile.am5
-rw-r--r--doc/Makefile.in4
-rw-r--r--doc/gui-notes.txt369
-rw-r--r--doc/man-sections/renegotiation.rst2
-rw-r--r--doc/man-sections/tls-options.rst6
-rw-r--r--doc/man-sections/vpn-network-options.rst9
-rw-r--r--doc/management-notes.txt10
-rw-r--r--doc/openvpn.817
-rw-r--r--doc/openvpn.8.html23
-rw-r--r--include/openvpn-plugin.h14
-rw-r--r--include/openvpn-plugin.h.in12
-rw-r--r--sample/sample-plugins/Makefile8
-rw-r--r--sample/sample-plugins/defer/simple.c399
-rw-r--r--src/openvpn/init.c4
-rw-r--r--src/openvpn/manage.c5
-rw-r--r--src/openvpn/misc.c9
-rw-r--r--src/openvpn/misc.h12
-rw-r--r--src/openvpn/options.c100
-rw-r--r--src/openvpn/pf.c13
-rw-r--r--src/openvpn/ps.c34
-rw-r--r--src/openvpn/ssl.c10
-rw-r--r--src/openvpn/ssl.h5
-rw-r--r--src/openvpn/tun.c47
-rw-r--r--src/openvpnserv/interactive.c2
-rw-r--r--version.m44
28 files changed, 1011 insertions, 255 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e06343..1b26873 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,49 @@
OpenVPN Change Log
Copyright (C) 2002-2020 OpenVPN Inc <sales@openvpn.net>
+2021.02.24 -- Version 2.5.1
+
+Arne Schwabe (5):
+ Fix auth-token not being updated if auth-nocache is set
+ Remove auth_user_pass.wait_for_push variable
+ Fix port-share option with TLS-Crypt v2
+ Zero initialise msghdr prior to calling sendmesg
+ Fix tls-auth mismatch OCC message when tls-cryptv2 is used.
+
+David Sommerseth (1):
+ build: Fix missing install of man page in certain environments
+
+Domagoj Pensa (3):
+ Fix too early argv freeing when registering DNS
+ Remove 1 second delay before running netsh
+ Skip DHCP renew with Wintun adapter
+
+Gert Doering (6):
+ Change travis build scripts to use https when fetching prerequisites.
+ Fix line number reporting on config file errors after <inline> segments
+ Clarify --block-ipv6 intent and direction.
+ Document common uses of 'echo' directive, re-enable logging for 'echo'.
+ Make OPENVPN_PLUGIN_ENABLE_PF failures FATAL
+ clean up / rewrite sample-plugins/defer/simple.c
+
+Greg Cox (5):
+ Fix naming error in sample-plugins/defer/simple.c
+ Documentation fixes around openvpn_plugin_func_v3 in openvpn-plugin.h.in
+ Update openvpn_plugin_func_v2 to _v3 in sample-plugins/defer/simple.c
+ More explicit versioning compatibility in sample-plugins/defer/simple.c
+ Explain structver usage in sample defer plugin.
+
+Richard Bonhomme (1):
+ Man page sections corrections
+
+Selva Nair (1):
+ Quote the domain name argument passed to the wmic command
+
+Steffan Karger (2):
+ tls-crypt-v2: fix server memory leak
+ tls-crypt-v2: also preload tls-crypt-v2 keys (if --persist-key)
+
+
2020.10.27 -- Version 2.5.0
(no changes relative to v2.5_rc3)
diff --git a/Changes.rst b/Changes.rst
index f67e1d7..6128275 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -1,5 +1,75 @@
-Overview of changes in 2.5
-==========================
+Overview of changes in 2.5.1
+============================
+
+New features
+------------
+- "echo msg" support, to enable the server to pushed messages that are
+ then displayed by the client-side GUI. See doc/gui-notes.txt and
+ doc/management-notes.txt.
+
+ Supported by the Windows GUI shipped in 2.5.1, not yet supported by
+ Tunnelblick and the Android GUI.
+
+User-visible Changes
+--------------------
+- make OPENVPN_PLUGIN_ENABLE_PF plugin failures FATAL - if a plugin offers
+ to set the "openvpn packet filter", and returns a failure when requested
+ to, OpenVPN 2.5.0 would crash trying to clean up not-yet-initialized
+ structure members. Since PF is going away in 2.6.0, this is just turning
+ the crash into a well-defined program abort, and no further effort has
+ been spent in rewriting the PF plugin error handling (see trac #1377).
+
+Documentation
+-------------
+- rework sample-plugins/defer/simple.c - this is an extensive rewrite
+ of the plugin to bring code quality to acceptable standards and add
+ documentation on the various plugin API aspects. Since it's just
+ example code, filed under "Documentation", not under "Bugfix".
+
+- various man page improvements.
+
+- clarify ``--block-ipv6`` intent and direction
+
+Bugfixes
+--------
+- fix installation of openvpn.8 manpage on systems without docutils.
+
+- Windows: fix DNS search list setup for domains with "-" chars.
+
+- Fix tls-auth mismatch OCC message when tls-cryptv2 is used.
+
+- Windows: Skip DHCP renew with Wintun adapter (Wintun does not support
+ DHCP, so this was just causing an - harmless - error and needless delay).
+
+- Windows: Remove 1 second delay before running netsh - speeds up
+ interface init for wintun setups not using the interactive service.
+
+- Windows: Fix too early argv freeing when registering DNS - this would
+ cause a client side crash on Windows if ``register-dns`` is used,
+ and the interactive service is not used.
+
+- Android: Zero initialise msghdr prior to calling sendmesg.
+
+- Fix line number reporting on config file errors after <inline> segments
+ (see Trac #1325).
+
+- Fix port-share option with TLS-Crypt v2.
+
+- tls-crypt-v2: also preload tls-crypt-v2 keys (if --persist-key), otherwise
+ dropping privs on the server would fail.
+
+- tls-crypt-v2: fix server memory leak (about 600 bytes per connecting
+ client with tls-crypt-v2)
+
+- rework handling of server-pushed ``--auth-token`` in combination with
+ ``--auth-nocache`` on reconnection / TLS renegotiation events. This
+ used to "forget" to update new incoming token after a reconnection event
+ (leading to failure to reauth some time later) and now works in all
+ tested cases.
+
+
+Overview of changes in 2.5.0
+============================
New features
------------
diff --git a/configure b/configure
index c843306..8c3e35e 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for OpenVPN 2.5.0.
+# Generated by GNU Autoconf 2.69 for OpenVPN 2.5.1.
#
# Report bugs to <openvpn-users@lists.sourceforge.net>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='OpenVPN'
PACKAGE_TARNAME='openvpn'
-PACKAGE_VERSION='2.5.0'
-PACKAGE_STRING='OpenVPN 2.5.0'
+PACKAGE_VERSION='2.5.1'
+PACKAGE_STRING='OpenVPN 2.5.1'
PACKAGE_BUGREPORT='openvpn-users@lists.sourceforge.net'
PACKAGE_URL=''
@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures OpenVPN 2.5.0 to adapt to many kinds of systems.
+\`configure' configures OpenVPN 2.5.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1536,7 +1536,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of OpenVPN 2.5.0:";;
+ short | recursive ) echo "Configuration of OpenVPN 2.5.1:";;
esac
cat <<\_ACEOF
@@ -1749,7 +1749,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-OpenVPN configure 2.5.0
+OpenVPN configure 2.5.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2588,7 +2588,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by OpenVPN $as_me 2.5.0, which was
+It was created by OpenVPN $as_me 2.5.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2952,13 +2952,13 @@ if test -z "${htmldir}"; then
fi
-$as_echo "#define OPENVPN_VERSION_RESOURCE 2,5,0,8" >>confdefs.h
+$as_echo "#define OPENVPN_VERSION_RESOURCE 2,5,1,0" >>confdefs.h
OPENVPN_VERSION_MAJOR=2
OPENVPN_VERSION_MINOR=5
-OPENVPN_VERSION_PATCH=.0
+OPENVPN_VERSION_PATCH=.1
$as_echo "#define OPENVPN_VERSION_MAJOR 2" >>confdefs.h
@@ -2967,7 +2967,7 @@ $as_echo "#define OPENVPN_VERSION_MAJOR 2" >>confdefs.h
$as_echo "#define OPENVPN_VERSION_MINOR 5" >>confdefs.h
-$as_echo "#define OPENVPN_VERSION_PATCH \".0\"" >>confdefs.h
+$as_echo "#define OPENVPN_VERSION_PATCH \".1\"" >>confdefs.h
ac_aux_dir=
@@ -3493,7 +3493,7 @@ fi
# Define the identity of the package.
PACKAGE='openvpn'
- VERSION='2.5.0'
+ VERSION='2.5.1'
cat >>confdefs.h <<_ACEOF
@@ -18946,7 +18946,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by OpenVPN $as_me 2.5.0, which was
+This file was extended by OpenVPN $as_me 2.5.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19012,7 +19012,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-OpenVPN config.status 2.5.0
+OpenVPN config.status 2.5.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 340dd55..e411f5f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -15,7 +15,7 @@ MAINTAINERCLEANFILES = \
SUBDIRS = doxygen
dist_doc_DATA = \
- management-notes.txt
+ management-notes.txt gui-notes.txt
dist_noinst_DATA = \
README.plugins interactive-service-notes.rst \
@@ -67,10 +67,11 @@ dist_html_DATA = openvpn.8.html
CLEANFILES = \
openvpn.8 openvpn.8.html
+endif
+
if WIN32
else
dist_man_MANS = openvpn.8
endif
-endif
dist-hook : openvpn.8 openvpn.8.html
diff --git a/doc/Makefile.in b/doc/Makefile.in
index beabdc0..3d1c968 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -441,7 +441,7 @@ MAINTAINERCLEANFILES = \
SUBDIRS = doxygen
dist_doc_DATA = \
- management-notes.txt
+ management-notes.txt gui-notes.txt
dist_noinst_DATA = README.plugins interactive-service-notes.rst \
openvpn.8.rst man-sections/advanced-options.rst \
@@ -468,7 +468,7 @@ dist_noinst_DATA = README.plugins interactive-service-notes.rst \
@HAVE_PYDOCUTILS_TRUE@CLEANFILES = \
@HAVE_PYDOCUTILS_TRUE@ openvpn.8 openvpn.8.html
-@HAVE_PYDOCUTILS_TRUE@@WIN32_FALSE@dist_man_MANS = openvpn.8
+@WIN32_FALSE@dist_man_MANS = openvpn.8
all: all-recursive
.SUFFIXES:
diff --git a/doc/gui-notes.txt b/doc/gui-notes.txt
new file mode 100644
index 0000000..e3bbf24
--- /dev/null
+++ b/doc/gui-notes.txt
@@ -0,0 +1,369 @@
+Management Interface "echo" protocol
+
+================================================================================
+THIS IS A PRELIMINARY VERSION OF THIS DOCUMENT. ALL INFORMATION IN IT
+IS SUBJECT TO CHANGE.
+================================================================================
+
+
+ CONTENTS
+ THE OPENVPN --ECHO OPTION
+ ENVIRONMENT COMMAND
+ MESSSAGE COMMANDS
+ PASSWORD COMMANDS
+ QUOTING
+ COMMMAND DETAILS
+
+
+=========================
+THE OPENVPN --ECHO OPTION
+=========================
+
+The OpenVPN --echo option causes commands to be sent out through the
+management interface, typically to a Graphic User Interface (GUI) such
+as "OpenVPN for Android", "Tunnelblick" (for macOS), or "Windows
+OpenVPN GUI". It can be included in a configuration file or on a
+command line, or can be pushed from the server.
+
+This document describes the commands that can be sent and how they are
+interpreted by various GUIs.
+
+ * OpenVPN does not process the commands in an --echo option; it only
+sends them out through the management interface.
+
+ * "echo" commands are processed by the GUI if, as, when, and in the
+order they are received. If no GUI is present the processing of
+commands may be delayed, the commands may never be processed, or only
+some commands may be processed. (That can happen if OpenVPN discards
+commands because its buffer for the commands fills up.)
+
+ * There is no mechanism for the GUI to acknowledge the receipt,
+success, or failure of a command.
+
+ * "echo" commands are stored by OpenVPN (within limits, see the next
+point) and sent only when the GUI requests them through the management
+interface. "echo" commands in the configuration file or the command
+line are typically requested and processed at the start of a
+connection attempt. "echo" commands that are pushed by the server are
+also typically asked for at the start of a connection attempt but can
+be sent at any time. They are processed in the middle of a connection
+attempt or after a connection is established, as the "push" options
+are received by the client from the server.
+
+ * OpenVPN's storage for echo commands is limited in size, so a large
+number of commands or commands with long messages may require that
+some commands be removed from the storage. If that happens, some of
+the commands may not be sent through the management interface when a
+GUI does connect to it or asks for the "echo" commands.
+
+ * On SIGUSR1 and SIGHUP connection restarts, "echo" commands that
+were sent through the management interface and have been saved by
+OpenVPN are sent again and will be re-processed by the GUI. (The
+message commands include a mechanism for muting (skipping) duplicate
+messages, see MESSAGE COMMANDS, below.)
+
+ * OpenVPN limits the number of separate arguments in each line of a
+configuration file. Arguments may be quoted to work around this
+limitation, see QUOTING, below.
+
+ * OpenVPN limits the size of each "echo" command sent over the
+management interface to 255 bytes, including overhead characters. To
+allow messages of arbitrary length, several message commands can be
+concatenated together before being displayed to the user, see MESSAGE
+COMMANDS, below.
+
+ * There no indication to the GUI of the source of the command
+(configuration file, command line option, or pushed from a server). It
+might be possible for the GUI to deduce that a command was pushed from
+a server because of timing or other management interface interactions.
+
+
+===================
+ENVIRONMENT COMMAND
+===================
+
+Typically, a GUI allows users to specify shell commands (typically
+scripts) to run at certain points in the connection/disconnection
+process, in addition to those provided by OpenVPN options such as
+"--up" and "--down".
+
+The "setenv" command can be used to set environment variables that are
+available to the scripts run by the GUI. Each "setenv" command
+specifies a value for one environment variable that is available to
+the scripts that the GUI runs.
+
+This is similar to Openvpn's "--setenv" option, which specifies an
+additional environment variable that is included in the environment
+variables that are available to the scripts that OpenVPN runs.
+
+
+=================
+MESSSAGE COMMANDS
+=================
+
+Four commands can be used to display a message to the user from the
+OpenVPN configuration or server:
+
+ msg
+ msg-n
+ msg-window
+ msg-notify
+
+"msg" and "msg-n" commands are concatenated to construct a message.
+When a "msg-window"or "msg-notify" command is received the message is
+displayed to the user.
+
+Identical messages (same title, text, and destination) received during
+one connection may be ignored or muted. Some GUIs may only show the
+first message for a connection, or the first message shown in a window
+and the first message shown as a notification.
+
+
+=================
+PASSWORD COMMANDS
+=================
+
+Three commands can be used to control the GUI's storage of usernames,
+passwords, and private keys:
+
+ disable-save-passwords
+ forget-passwords
+ save-passwords
+
+
+=======
+QUOTING
+=======
+
+ * In a configuration file, the rest of the line is parsed into
+separate arguments and then 'echo' and the arguments are passed, each
+separated by a single space, through the management interface. For
+example:
+
+ echo argument1 argument2
+ echo " argument1 argument2"
+
+will be sent through the management interface as
+
+ >ECHO:timestamp,argument1 argument2
+ >ECHO:timestamp, argument1 argument2
+
+ * In a command line option, the single argument following "--echo" is
+parsed similarly, so
+
+ --echo argument1 argument2
+ --echo " argument1 argument2"
+
+will be sent through the management interface as
+
+ >ECHO:timestamp,argument1 argument2
+ >ECHO:timestamp, argument1 argument2
+
+ * In a "push" option in a server configuration file, the single
+option following "push" is parsed similarly, so
+
+ push "echo argument1 argument2 argument3 argument4"
+ push "echo ' argument1 argument2 argument3 argument4'"
+
+will be sent through the management interface as
+
+ >ECHO:timestamp,argument1 argument2 argument3 argument4
+ >ECHO:timestamp, argument1 argument2 argument3 argument4
+
+
+================
+COMMMAND DETAILS
+================
+
+
+COMMAND -- disable-save-passwords
+---------------------------------
+
+Syntax: disable-save-passwords
+
+The GUI is instructed to not allow the user to save passwords or
+private keys for the configuration. The user is still allowed to save
+usernames. Any passwords or private keys that have been saved will be
+forgotten.
+
+This command will be effective at startup only if present in the
+configuration file or as a command line option. If pushed from the
+server, saving passwords will be disabled in password prompts only
+after the initial prompt has been shown to the user.
+
+ Android: ??????
+
+ Tunnelblick: Planned. This command will disable saving of
+passwords or private keys and forget any saved usernames, passwords,
+or private keys regardless of the normal (non-forced) global or
+per-configuration settings. A computer administrator can "force" this
+setting, overriding this command.
+
+ Windows OpenVPN GUI: Planned. This command will disable saving of
+passwords or private keys and forget any saved usernames, passwords,
+or private keys regardless of any global settings.
+
+
+COMMAND -- forget-passwords
+---------------------------
+
+Syntax: forget-passwords
+
+The GUI is instructed to forget any usernames, passwords, and private
+keys it has saved for the configuration. Useful when pushed from the
+server so that it is processed after authentication.
+
+ Android: ??????
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release 2.4.1 (GUI version 11.5.0)
+
+
+COMMAND -- msg
+--------------
+
+Syntax: msg text
+
+The text is appended to any previous text from "msg" or "msg-n"
+commands, and a newline is appended after that.
+
+A trailing newline will be removed from the completed message before
+it is displayed to the user.
+
+The text may include any UTF-8 character except a comma (","), CR
+(0x0D), LF (0x0A), or NUL (0x00).
+
+The text may not contain percent ("%") except in "percent encoding"
+sequences. To display a percent sign, use %25.
+
+The text may not contain commas (",") because of constraints imposed
+by OpenVPN. Commas should be encoded using "percent encoding" (URL
+encoding): a '%' character followed by two hexadecimal digits, the
+high- and then low-nibble of the ASCII code for the character to be
+shown. Examples: a comma is encoded as %2C or %2c; a percent sign is
+encoded as %25.
+
+Text containing comment characters # and ; must be enclosed in quotes to
+survive after option parsing by openvpn.
+
+The insertion of line endings (CR, LF) in the text is discouraged
+because it is OS dependent. Instead, use the "msg" command, which
+appends a line ending appropriate for the OS on which the GUI is
+running.
+
+ Android: Planned.
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release v2.4.11 / v2.5.1
+ (GUI version v11.22.0)
+
+COMMAND -- msg-n
+----------------
+
+Syntax: msg-n text
+
+The text is appended to any previous text from "msg"" or "msg-n""
+commands. (Like "msg" except that no newline is appended.)
+
+See "COMMAND -- msg" for details about "text".
+
+ Android: Planned.
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release v2.4.11 / v2.5.1
+ (GUI version v11.22.0)
+
+COMMAND -- msg-notify
+---------------------
+
+Syntax: msg-notify title
+
+The text from previous "msg" and/or "msg-n" commands is displayed to
+the user as a notification with title "title" and the previous text is
+forgotten.
+
+ Android: Planned.
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release v2.4.11 / v2.5.1
+ (GUI version v11.22.0)
+
+Note: The max length that will correctly display as a notification
+message is OS dependent.
+
+
+COMMAND -- msg-window title
+---------------------------
+
+Syntax: msg-window title
+
+The text from previous "msg" and/or "msg-n" commands is displayed to
+the user in a non-modal popup window with title "title" and the
+previous text is forgotten. How the title is displayed exactly is left
+to the implementation. Could be set as the window title or as a
+differently formatted text as the heading of the message, for example.
+
+ Android: Planned.
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release v2.4.11 / v2.5.1
+ (GUI version v11.22.0)
+
+
+COMMAND -- save-passwords
+-------------------------
+
+Syntax: save-passwords
+
+The GUI is instructed to allow the user to save usernames, passwords
+and private keys for the configuration.
+
+This command will be effective at startup only if present in the
+configuration file or as a command line option. If pushed from the
+server, saving passwords will be allowed in password prompts only
+after the initial prompt has been shown to the user.
+
+This command typically has the effect of presenting the password
+dialogs to the user with a "save password" checkbox checked. The user
+may still uncheck it during the dialog.
+
+ Android: ??????
+
+ Tunnelblick: Planned. Tunnelblick ignores this command. Usernames,
+passwords, and private keys may be saved by default, and this command
+will not override the separate Tunnelblick global or per-configuration
+settings used to disable saving them.
+
+ Windows OpenVPN GUI: Supported since release 2.4.1 (GUI version 11.5.0)
+
+
+COMMAND -- setenv
+-----------------
+
+Syntax: setenv name value
+
+Sets an environment variable that will be available to the scripts run
+by the GUI.
+
+This will set environment variable "OPENVPN_name" to value "value" for
+the scripts run by the GUI. "name" is changed to "OPENVPN_name" to
+prevent overwriting sensitive variables such as PATH. Variables are
+set in the order received, with later values replacing earlier ones
+for the same "name".
+
+Names may include only alphanumeric characters and underscores. A
+"setenv" command with an invalid name will be ignored.
+
+ Android: ??????
+
+ Tunnelblick: Planned.
+
+ Windows OpenVPN GUI: supported since release v2.4.7 (GUI version v11.12.0)
+The variables set by "setenv" are merged with those for the process
+environment. In case of duplicate names the one in the setenv list is
+chosen.
diff --git a/doc/man-sections/renegotiation.rst b/doc/man-sections/renegotiation.rst
index b817cfa..c548440 100644
--- a/doc/man-sections/renegotiation.rst
+++ b/doc/man-sections/renegotiation.rst
@@ -35,7 +35,7 @@ separate ephemeral encryption key which is rotated at regular intervals.
pseudo-uniform-randomized between ``min`` and ``max``.
With the default value of :code:`3600` this results in an effective per
- session value in the range of :code:`3240`..:code:`3600` seconds for
+ session value in the range of :code:`3240` .. :code:`3600` seconds for
servers, or just 3600 for clients.
When using dual-factor authentication, note that this default value may
diff --git a/doc/man-sections/tls-options.rst b/doc/man-sections/tls-options.rst
index 8c2db7c..f0b6d3d 100644
--- a/doc/man-sections/tls-options.rst
+++ b/doc/man-sections/tls-options.rst
@@ -422,13 +422,13 @@ certificates and keys: https://github.com/OpenVPN/easy-rsa
:code:`DEFAULT:!EXP:!LOW:!MEDIUM:!kDH:!kECDH:!DSS:!PSK:!SRP:!kRSA` when
using OpenSSL.
- The default for `--tls-ciphersuites` is to use the crypto library's
- default.
-
--tls-ciphersuites l
Same as ``--tls-cipher`` but for TLS 1.3 and up. mbed TLS has no
TLS 1.3 support yet and only the ``--tls-cipher`` setting is used.
+ The default for `--tls-ciphersuites` is to use the crypto library's
+ default.
+
--tls-client
Enable TLS and assume client role during TLS handshake.
diff --git a/doc/man-sections/vpn-network-options.rst b/doc/man-sections/vpn-network-options.rst
index 2668278..029834a 100644
--- a/doc/man-sections/vpn-network-options.rst
+++ b/doc/man-sections/vpn-network-options.rst
@@ -21,7 +21,8 @@ routing.
For this option to make sense you actually have to route traffic to the
tun interface. The following example config block would send all IPv6
traffic to OpenVPN and answer all requests with no route to host,
- effectively blocking IPv6.
+ effectively blocking IPv6 (to avoid IPv6 connections from dual-stacked
+ clients leaking around IPv4-only VPN services).
**Client config**
::
@@ -38,6 +39,12 @@ routing.
--push "redirect-gateway ipv6"
--block-ipv6
+ Note: this option does not influence traffic sent from the server
+ towards the client (neither on the server nor on the client side).
+ This is not seen as necessary, as such traffic can be most easily
+ avoided by not configuring IPv6 on the server tun, or setting up a
+ server-side firewall rule.
+
--dev device
TUN/TAP virtual network device which can be :code:`tunX`, :code:`tapX`,
:code:`null` or an arbitrary name string (:code:`X` can be omitted for
diff --git a/doc/management-notes.txt b/doc/management-notes.txt
index 61daaf0..50f0f56 100644
--- a/doc/management-notes.txt
+++ b/doc/management-notes.txt
@@ -137,6 +137,16 @@ history while simultaneously activating real-time updates:
The size of the echo buffer is currently hardcoded to 100
messages.
+
+Generally speaking, the OpenVPN Core does not understand echo
+messages at all (so a cooperating GUI and Server can use this
+mechanism for arbitrary information transport).
+
+This said, a few echo commands have been agreed upon between the
+community maintained OpenVPN Windows GUI and Tunnelblick for MacOS,
+and documentation of these can be found in doc/gui-notes.txt.
+
+
COMMAND -- exit, quit
---------------------
diff --git a/doc/openvpn.8 b/doc/openvpn.8
index a504ce9..57d94ea 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -2680,7 +2680,7 @@ The effective \fB\-\-reneg\-sec\fP value used is per session
pseudo\-uniform\-randomized between \fBmin\fP and \fBmax\fP\&.
.sp
With the default value of \fB3600\fP this results in an effective per
-session value in the range of \fB3240\fP\&..:code:\fI3600\fP seconds for
+session value in the range of \fB3240\fP .. \fB3600\fP seconds for
servers, or just 3600 for clients.
.sp
When using dual\-factor authentication, note that this default value may
@@ -3219,13 +3219,13 @@ The default for \fB\-\-tls\-cipher\fP is to use mbed TLS\(aqs default cipher lis
when using mbed TLS or
\fBDEFAULT:!EXP:!LOW:!MEDIUM:!kDH:!kECDH:!DSS:!PSK:!SRP:!kRSA\fP when
using OpenSSL.
-.sp
-The default for \fI\-\-tls\-ciphersuites\fP is to use the crypto library\(aqs
-default.
.TP
.BI \-\-tls\-ciphersuites \ l
Same as \fB\-\-tls\-cipher\fP but for TLS 1.3 and up. mbed TLS has no
TLS 1.3 support yet and only the \fB\-\-tls\-cipher\fP setting is used.
+.sp
+The default for \fI\-\-tls\-ciphersuites\fP is to use the crypto library\(aqs
+default.
.TP
.B \-\-tls\-client
Enable TLS and assume client role during TLS handshake.
@@ -4204,7 +4204,8 @@ otherwise will use \fBfe80::7\fP as source address.
For this option to make sense you actually have to route traffic to the
tun interface. The following example config block would send all IPv6
traffic to OpenVPN and answer all requests with no route to host,
-effectively blocking IPv6.
+effectively blocking IPv6 (to avoid IPv6 connections from dual\-stacked
+clients leaking around IPv4\-only VPN services).
.INDENT 7.0
.TP
.B \fBClient config\fP
@@ -4236,6 +4237,12 @@ Push a "valid" ipv6 config to the client and block on the server
.UNINDENT
.UNINDENT
.UNINDENT
+.sp
+Note: this option does not influence traffic sent from the server
+towards the client (neither on the server nor on the client side).
+This is not seen as necessary, as such traffic can be most easily
+avoided by not configuring IPv6 on the server tun, or setting up a
+server\-side firewall rule.
.TP
.BI \-\-dev \ device
TUN/TAP virtual network device which can be \fBtunX\fP, \fBtapX\fP,
diff --git a/doc/openvpn.8.html b/doc/openvpn.8.html
index b941476..6ca509d 100644
--- a/doc/openvpn.8.html
+++ b/doc/openvpn.8.html
@@ -2545,7 +2545,7 @@ reneg-sec max [min]
<p>The effective <tt class="docutils literal"><span class="pre">--reneg-sec</span></tt> value used is per session
pseudo-uniform-randomized between <tt class="docutils literal">min</tt> and <tt class="docutils literal">max</tt>.</p>
<p>With the default value of <code>3600</code> this results in an effective per
-session value in the range of <code>3240</code>..:code:<cite>3600</cite> seconds for
+session value in the range of <code>3240</code> .. <code>3600</code> seconds for
servers, or just 3600 for clients.</p>
<p>When using dual-factor authentication, note that this default value may
cause the end user to be challenged to reauthorize once per hour.</p>
@@ -2954,18 +2954,19 @@ interpretation.</p>
<p>For OpenSSL, the <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> is used for TLS 1.2 and below.</p>
<p>Use <tt class="docutils literal"><span class="pre">--show-tls</span></tt> to see a list of TLS ciphers supported by your crypto
library.</p>
-<p>The default for <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> is to use mbed TLS's default cipher list
+<p class="last">The default for <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> is to use mbed TLS's default cipher list
when using mbed TLS or
<code>DEFAULT:!EXP:!LOW:!MEDIUM:!kDH:!kECDH:!DSS:!PSK:!SRP:!kRSA</code> when
using OpenSSL.</p>
-<p class="last">The default for <cite>--tls-ciphersuites</cite> is to use the crypto library's
-default.</p>
</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--tls-ciphersuites <var>l</var></span></kbd></td>
</tr>
-<tr><td>&nbsp;</td><td>Same as <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> but for TLS 1.3 and up. mbed TLS has no
-TLS 1.3 support yet and only the <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> setting is used.</td></tr>
+<tr><td>&nbsp;</td><td><p class="first">Same as <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> but for TLS 1.3 and up. mbed TLS has no
+TLS 1.3 support yet and only the <tt class="docutils literal"><span class="pre">--tls-cipher</span></tt> setting is used.</p>
+<p class="last">The default for <cite>--tls-ciphersuites</cite> is to use the crypto library's
+default.</p>
+</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--tls-client</span></kbd></td>
<td>Enable TLS and assume client role during TLS handshake.</td></tr>
@@ -3783,8 +3784,9 @@ otherwise will use <code>fe80::7</code> as source address.</p>
<p>For this option to make sense you actually have to route traffic to the
tun interface. The following example config block would send all IPv6
traffic to OpenVPN and answer all requests with no route to host,
-effectively blocking IPv6.</p>
-<dl class="last docutils">
+effectively blocking IPv6 (to avoid IPv6 connections from dual-stacked
+clients leaking around IPv4-only VPN services).</p>
+<dl class="docutils">
<dt><strong>Client config</strong></dt>
<dd><pre class="first last literal-block">
--ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1
@@ -3801,6 +3803,11 @@ effectively blocking IPv6.</p>
</pre>
</dd>
</dl>
+<p class="last">Note: this option does not influence traffic sent from the server
+towards the client (neither on the server nor on the client side).
+This is not seen as necessary, as such traffic can be most easily
+avoided by not configuring IPv6 on the server tun, or setting up a
+server-side firewall rule.</p>
</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--dev <var>device</var></span></kbd></td>
diff --git a/include/openvpn-plugin.h b/include/openvpn-plugin.h
index f742f6b..0095745 100644
--- a/include/openvpn-plugin.h
+++ b/include/openvpn-plugin.h
@@ -53,7 +53,7 @@ extern "C" {
*/
#define OPENVPN_VERSION_MAJOR 2
#define OPENVPN_VERSION_MINOR 5
-#define OPENVPN_VERSION_PATCH ".0"
+#define OPENVPN_VERSION_PATCH ".1"
/*
* Plug-in types. These types correspond to the set of script callbacks
@@ -671,12 +671,12 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
* ARGUMENTS
*
* version : fixed value, defines the API version of the OpenVPN plug-in API. The plug-in
- * should validate that this value is matching the OPENVPN_PLUGIN_VERSION value.
+ * should validate that this value is matching the OPENVPN_PLUGINv3_STRUCTVER
+ * value.
*
- * handle : the openvpn_plugin_handle_t value which was returned by
- * openvpn_plugin_open.
+ * arguments : Structure with all arguments available to the plug-in.
*
- * return_list : used to return data back to OpenVPN.
+ * retptr : used to return data back to OpenVPN.
*
* RETURN VALUE
*
@@ -737,8 +737,8 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
* A given client or subnet rule applies to both incoming and outgoing
* packets.
*
- * See plugin/defer/simple.c for an example on using asynchronous
- * authentication and client-specific packet filtering.
+ * See sample/sample-plugins/defer/simple.c for an example on using
+ * asynchronous authentication and client-specific packet filtering.
*/
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v3)
(const int version,
diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in
index 64b2088..b73b745 100644
--- a/include/openvpn-plugin.h.in
+++ b/include/openvpn-plugin.h.in
@@ -670,12 +670,12 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
* ARGUMENTS
*
* version : fixed value, defines the API version of the OpenVPN plug-in API. The plug-in
- * should validate that this value is matching the OPENVPN_PLUGIN_VERSION value.
+ * should validate that this value is matching the OPENVPN_PLUGINv3_STRUCTVER
+ * value.
*
- * handle : the openvpn_plugin_handle_t value which was returned by
- * openvpn_plugin_open.
+ * arguments : Structure with all arguments available to the plug-in.
*
- * return_list : used to return data back to OpenVPN.
+ * retptr : used to return data back to OpenVPN.
*
* RETURN VALUE
*
@@ -736,8 +736,8 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
* A given client or subnet rule applies to both incoming and outgoing
* packets.
*
- * See plugin/defer/simple.c for an example on using asynchronous
- * authentication and client-specific packet filtering.
+ * See sample/sample-plugins/defer/simple.c for an example on using
+ * asynchronous authentication and client-specific packet filtering.
*/
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v3)
(const int version,
diff --git a/sample/sample-plugins/Makefile b/sample/sample-plugins/Makefile
index 1cf5e2c..f709998 100644
--- a/sample/sample-plugins/Makefile
+++ b/sample/sample-plugins/Makefile
@@ -210,7 +210,7 @@ OPENSSL_CFLAGS =
OPENSSL_LIBS = -lssl -lcrypto
OPENVPN_VERSION_MAJOR = 2
OPENVPN_VERSION_MINOR = 5
-OPENVPN_VERSION_PATCH = .0
+OPENVPN_VERSION_PATCH = .1
OPTIONAL_CRYPTO_CFLAGS =
OPTIONAL_CRYPTO_LIBS = -lssl -lcrypto
OPTIONAL_DL_LIBS = -ldl
@@ -231,10 +231,10 @@ P11KIT_LIBS =
PACKAGE = openvpn
PACKAGE_BUGREPORT = openvpn-users@lists.sourceforge.net
PACKAGE_NAME = OpenVPN
-PACKAGE_STRING = OpenVPN 2.5.0
+PACKAGE_STRING = OpenVPN 2.5.1
PACKAGE_TARNAME = openvpn
PACKAGE_URL =
-PACKAGE_VERSION = 2.5.0
+PACKAGE_VERSION = 2.5.1
PATH_SEPARATOR = :
PKCS11_HELPER_CFLAGS =
PKCS11_HELPER_LIBS = -lpthread -ldl -lcrypto -lpkcs11-helper
@@ -264,7 +264,7 @@ TAP_WIN_MIN_MINOR = 9
TEST_CFLAGS = -I$(top_srcdir)/include
TEST_LDFLAGS = -lssl -lcrypto -llzo2
TMPFILES_DIR =
-VERSION = 2.5.0
+VERSION = 2.5.1
abs_builddir = /home/samuli/opt/openvpninc/openvpn-release-scripts/release/openvpn/sample/sample-plugins
abs_srcdir = /home/samuli/opt/openvpninc/openvpn-release-scripts/release/openvpn/sample/sample-plugins
abs_top_builddir = /home/samuli/opt/openvpninc/openvpn-release-scripts/release/openvpn
diff --git a/sample/sample-plugins/defer/simple.c b/sample/sample-plugins/defer/simple.c
index 64338b4..6f08bed 100644
--- a/sample/sample-plugins/defer/simple.c
+++ b/sample/sample-plugins/defer/simple.c
@@ -54,13 +54,30 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "openvpn-plugin.h"
-/* bool definitions */
-#define bool int
-#define true 1
-#define false 0
+/* Pointers to functions exported from openvpn */
+static plugin_log_t plugin_log = NULL;
+
+/*
+ * Constants indicating minimum API and struct versions by the functions
+ * in this plugin. Consult openvpn-plugin.h, look for:
+ * OPENVPN_PLUGIN_VERSION and OPENVPN_PLUGINv3_STRUCTVER
+ *
+ * Strictly speaking, this sample code only requires plugin_log, a feature
+ * of structver version 1. However, '1' lines up with ancient versions
+ * of openvpn that are past end-of-support. As such, we are requiring
+ * structver '5' here to indicate a desire for modern openvpn, rather
+ * than a need for any particular feature found in structver beyond '1'.
+ */
+#define OPENVPN_PLUGIN_VERSION_MIN 3
+#define OPENVPN_PLUGIN_STRUCTVER_MIN 5
/*
* Our context, where we keep our state.
@@ -76,6 +93,9 @@ struct plugin_per_client_context {
bool generated_pf_file;
};
+/* module name for plugin_log() */
+static char *MODULE = "defer/simple";
+
/*
* Given an environmental variable name, search
* the envp array for its value, returning it
@@ -130,33 +150,52 @@ atoi_null0(const char *str)
}
}
-OPENVPN_EXPORT openvpn_plugin_handle_t
-openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
+/* Require a minimum OpenVPN Plugin API */
+OPENVPN_EXPORT int
+openvpn_plugin_min_version_required_v1()
+{
+ return OPENVPN_PLUGIN_VERSION_MIN;
+}
+
+/* use v3 functions so we can use openvpn's logging and base64 etc. */
+OPENVPN_EXPORT int
+openvpn_plugin_open_v3(const int v3structver,
+ struct openvpn_plugin_args_open_in const *args,
+ struct openvpn_plugin_args_open_return *ret)
{
+ const char **envp = args->envp; /* environment variables */
struct plugin_context *context;
- printf("FUNC: openvpn_plugin_open_v1\n");
+ if (v3structver < OPENVPN_PLUGIN_STRUCTVER_MIN)
+ {
+ fprintf(stderr, "%s: this plugin is incompatible with the running version of OpenVPN\n", MODULE);
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+
+ /* Save global pointers to functions exported from openvpn */
+ plugin_log = args->callbacks->plugin_log;
+
+ plugin_log(PLOG_NOTE, MODULE, "FUNC: openvpn_plugin_open_v3");
/*
* Allocate our context
*/
context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
- if (context == NULL)
+ if (!context)
{
- printf("PLUGIN: allocating memory for context failed\n");
- return NULL;
+ goto error;
}
context->test_deferred_auth = atoi_null0(get_env("test_deferred_auth", envp));
- printf("TEST_DEFERRED_AUTH %d\n", context->test_deferred_auth);
+ plugin_log(PLOG_NOTE, MODULE, "TEST_DEFERRED_AUTH %d", context->test_deferred_auth);
context->test_packet_filter = atoi_null0(get_env("test_packet_filter", envp));
- printf("TEST_PACKET_FILTER %d\n", context->test_packet_filter);
+ plugin_log(PLOG_NOTE, MODULE, "TEST_PACKET_FILTER %d", context->test_packet_filter);
/*
* Which callbacks to intercept.
*/
- *type_mask =
+ ret->type_mask =
OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP)
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN)
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ROUTE_UP)
@@ -166,157 +205,315 @@ openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT)
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
- |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL)
- |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ENABLE_PF);
+ |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
- return (openvpn_plugin_handle_t) context;
+ /* ENABLE_PF should only be called if we're actually willing to do PF */
+ if (context->test_packet_filter)
+ {
+ ret->type_mask |= OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ENABLE_PF);
+ }
+
+ ret->handle = (openvpn_plugin_handle_t *) context;
+ plugin_log(PLOG_NOTE, MODULE, "initialization succeeded");
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+
+error:
+ if (context)
+ {
+ free(context);
+ }
+ plugin_log(PLOG_NOTE, MODULE, "initialization failed");
+ return OPENVPN_PLUGIN_FUNC_ERROR;
}
static int
-auth_user_pass_verify(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
+auth_user_pass_verify(struct plugin_context *context,
+ struct plugin_per_client_context *pcc,
+ const char *argv[], const char *envp[])
{
- if (context->test_deferred_auth)
+ if (!context->test_deferred_auth)
{
- /* get username/password from envp string array */
- const char *username = get_env("username", envp);
- const char *password = get_env("password", envp);
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ }
- /* get auth_control_file filename from envp string array*/
- const char *auth_control_file = get_env("auth_control_file", envp);
+ /* get username/password from envp string array */
+ const char *username = get_env("username", envp);
+ const char *password = get_env("password", envp);
- printf("DEFER u='%s' p='%s' acf='%s'\n",
+ /* get auth_control_file filename from envp string array*/
+ const char *auth_control_file = get_env("auth_control_file", envp);
+
+ plugin_log(PLOG_NOTE, MODULE, "DEFER u='%s' p='%s' acf='%s'",
np(username),
np(password),
np(auth_control_file));
- /* Authenticate asynchronously in n seconds */
- if (auth_control_file)
- {
- char buf[256];
- int auth = 2;
- sscanf(username, "%d", &auth);
- snprintf(buf, sizeof(buf), "( sleep %d ; echo AUTH %s %d ; echo %d >%s ) &",
- context->test_deferred_auth,
- auth_control_file,
- auth,
- pcc->n_calls < auth,
- auth_control_file);
- printf("%s\n", buf);
- system(buf);
- pcc->n_calls++;
- return OPENVPN_PLUGIN_FUNC_DEFERRED;
- }
- else
- {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
+ /* Authenticate asynchronously in n seconds */
+ if (!auth_control_file)
+ {
+ return OPENVPN_PLUGIN_FUNC_ERROR;
}
- else
+
+ /* we do not want to complicate our lives with having to wait()
+ * for child processes (so they are not zombiefied) *and* we MUST NOT
+ * fiddle with signal handlers (= shared with openvpn main), so
+ * we use double-fork() trick.
+ */
+
+ /* fork, sleep, succeed (no "real" auth done = always succeed) */
+ pid_t p1 = fork();
+ if (p1 < 0) /* Fork failed */
{
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+ if (p1 > 0) /* parent process */
+ {
+ waitpid(p1, NULL, 0);
+ return OPENVPN_PLUGIN_FUNC_DEFERRED;
+ }
+
+ /* first gen child process, fork() again and exit() right away */
+ pid_t p2 = fork();
+ if (p2 < 0)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "BACKGROUND: fork(2) failed");
+ exit(1);
+ }
+
+ if (p2 != 0) /* new parent: exit right away */
+ {
+ exit(0);
+ }
+
+ /* (grand-)child process
+ * - never call "return" now (would mess up openvpn)
+ * - return status is communicated by file
+ * - then exit()
+ */
+
+ /* do mighty complicated work that will really take time here... */
+ plugin_log(PLOG_NOTE, MODULE, "in async/deferred handler, sleep(%d)", context->test_deferred_auth);
+ sleep(context->test_deferred_auth);
+
+ /* now signal success state to openvpn */
+ int fd = open(auth_control_file, O_WRONLY);
+ if (fd < 0)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "open('%s') failed", auth_control_file);
+ exit(1);
}
+
+ plugin_log(PLOG_NOTE, MODULE, "auth_user_pass_verify: done" );
+
+ if (write(fd, "1", 1) != 1)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "write to '%s' failed", auth_control_file );
+ }
+ close(fd);
+
+ exit(0);
}
static int
tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
{
- if (context->test_packet_filter)
+ if (!context->test_packet_filter) /* no PF testing, nothing to do */
{
- if (!pcc->generated_pf_file)
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ }
+
+ if (pcc->generated_pf_file) /* we already have created a file */
+ {
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+
+ const char *pff = get_env("pf_file", envp);
+ const char *cn = get_env("username", envp);
+ if (!pff || !cn) /* required vars missing */
+ {
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+
+ pcc->generated_pf_file = true;
+
+ /* the PF API is, basically
+ * - OpenVPN sends a filename (pf_file) to the plugin
+ * - OpenVPN main loop will check every second if that file shows up
+ * - when it does, it will be read & used for the pf config
+ * the pre-created file needs to be removed in ...ENABLE_PF
+ * to make deferred PF setup work
+ *
+ * the regular PF hook does not know the client username or CN, so
+ * this is deferred to the TLS_FINAL hook which knows these things
+ */
+
+ /* do the double fork dance (see above for more verbose comments)
+ */
+ pid_t p1 = fork();
+ if (p1 < 0) /* Fork failed */
+ {
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+ if (p1 > 0) /* parent process */
+ {
+ waitpid(p1, NULL, 0);
+ return OPENVPN_PLUGIN_FUNC_SUCCESS; /* no _DEFERRED here! */
+ }
+
+ /* first gen child process, fork() again and exit() right away */
+ pid_t p2 = fork();
+ if (p2 < 0)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "BACKGROUND: fork(2) failed");
+ exit(1);
+ }
+
+ if (p2 != 0) /* new parent: exit right away */
+ {
+ exit(0);
+ }
+
+ /* (grand-)child process
+ * - never call "return" now (would mess up openvpn)
+ * - return status is communicated by file
+ * - then exit()
+ */
+
+ /* at this point, the plugin can take its time, because OpenVPN will
+ * no longer block waiting for the call to finish
+ *
+ * in this example, we build a PF file by copying over a file
+ * named "<username>.pf" to the OpenVPN-provided pf file name
+ *
+ * a real example could do a LDAP lookup, a REST call, ...
+ */
+ plugin_log(PLOG_NOTE, MODULE, "in async/deferred tls_final handler, sleep(%d)", context->test_packet_filter);
+ sleep(context->test_packet_filter);
+
+ char buf[256];
+ snprintf(buf, sizeof(buf), "%s.pf", cn );
+
+ /* there is a small race condition here - OpenVPN could detect our
+ * file while we have only written half of it. So "perfect" code
+ * needs to create this with a temp file name, and then rename() it
+ * after it has been written. But I am lazy.
+ */
+
+ int w_fd = open( pff, O_WRONLY|O_CREAT, 0600 );
+ if (w_fd < 0)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "can't write to '%s'", pff);
+ exit(0);
+ }
+
+ int r_fd = open( buf, O_RDONLY );
+ if (r_fd < 0)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "can't read '%s', creating empty pf file", buf);
+ close(w_fd);
+ exit(0);
+ }
+
+ char data[1024];
+
+ int r;
+ do
+ {
+ r = read(r_fd, data, sizeof(data));
+ if (r < 0)
{
- const char *pff = get_env("pf_file", envp);
- const char *cn = get_env("username", envp);
- if (pff && cn)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "( sleep %d ; echo PF %s/%s ; cp \"%s.pf\" \"%s\" ) &",
- context->test_packet_filter, cn, pff, cn, pff);
- printf("%s\n", buf);
- system(buf);
- pcc->generated_pf_file = true;
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- else
- {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "error reading '%s'", buf);
+ close(r_fd);
+ close(w_fd);
+ exit(0);
}
- else
+ int w = write(w_fd, data, r);
+ if (w < 0 || w != r)
{
- return OPENVPN_PLUGIN_FUNC_ERROR;
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "error writing %d bytes to '%s'", r, pff);
+ close(r_fd);
+ close(w_fd);
+ exit(0);
}
}
- else
- {
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
+ while(r > 0);
+
+ plugin_log(PLOG_NOTE, MODULE, "copied PF config from '%s' to '%s', job done", buf, pff);
+ exit(0);
}
OPENVPN_EXPORT int
-openvpn_plugin_func_v2(openvpn_plugin_handle_t handle,
- const int type,
- const char *argv[],
- const char *envp[],
- void *per_client_context,
- struct openvpn_plugin_string_list **return_list)
+openvpn_plugin_func_v3(const int v3structver,
+ struct openvpn_plugin_args_func_in const *args,
+ struct openvpn_plugin_args_func_return *ret)
{
- struct plugin_context *context = (struct plugin_context *) handle;
- struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
- switch (type)
+ if (v3structver < OPENVPN_PLUGIN_STRUCTVER_MIN)
+ {
+ fprintf(stderr, "%s: this plugin is incompatible with the running version of OpenVPN\n", MODULE);
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+ const char **argv = args->argv;
+ const char **envp = args->envp;
+ struct plugin_context *context = (struct plugin_context *) args->handle;
+ struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) args->per_client_context;
+ switch (args->type)
{
case OPENVPN_PLUGIN_UP:
- printf("OPENVPN_PLUGIN_UP\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_UP");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_DOWN:
- printf("OPENVPN_PLUGIN_DOWN\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_DOWN");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_ROUTE_UP:
- printf("OPENVPN_PLUGIN_ROUTE_UP\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_ROUTE_UP");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_IPCHANGE:
- printf("OPENVPN_PLUGIN_IPCHANGE\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_IPCHANGE");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_TLS_VERIFY:
- printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_TLS_VERIFY");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
- printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY");
return auth_user_pass_verify(context, pcc, argv, envp);
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
- printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_CONNECT_V2");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
- printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_DISCONNECT");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_LEARN_ADDRESS:
- printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_LEARN_ADDRESS");
return OPENVPN_PLUGIN_FUNC_SUCCESS;
case OPENVPN_PLUGIN_TLS_FINAL:
- printf("OPENVPN_PLUGIN_TLS_FINAL\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_TLS_FINAL");
return tls_final(context, pcc, argv, envp);
case OPENVPN_PLUGIN_ENABLE_PF:
- printf("OPENVPN_PLUGIN_ENABLE_PF\n");
- if (context->test_packet_filter)
- {
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- else
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_ENABLE_PF");
+
+ /* OpenVPN pre-creates the file, which gets in the way of
+ * deferred pf setup - so remove it here, and re-create
+ * it in the background handler (in tls_final()) when ready
+ */
+ const char *pff = get_env("pf_file", envp);
+ if (pff)
{
- return OPENVPN_PLUGIN_FUNC_ERROR;
+ (void) unlink(pff);
}
+ return OPENVPN_PLUGIN_FUNC_SUCCESS; /* must succeed */
default:
- printf("OPENVPN_PLUGIN_?\n");
+ plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_?");
return OPENVPN_PLUGIN_FUNC_ERROR;
}
}
@@ -324,14 +521,14 @@ openvpn_plugin_func_v2(openvpn_plugin_handle_t handle,
OPENVPN_EXPORT void *
openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
{
- printf("FUNC: openvpn_plugin_client_constructor_v1\n");
+ plugin_log(PLOG_NOTE, MODULE, "FUNC: openvpn_plugin_client_constructor_v1");
return calloc(1, sizeof(struct plugin_per_client_context));
}
OPENVPN_EXPORT void
openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *per_client_context)
{
- printf("FUNC: openvpn_plugin_client_destructor_v1\n");
+ plugin_log(PLOG_NOTE, MODULE, "FUNC: openvpn_plugin_client_destructor_v1");
free(per_client_context);
}
@@ -339,6 +536,6 @@ OPENVPN_EXPORT void
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
{
struct plugin_context *context = (struct plugin_context *) handle;
- printf("FUNC: openvpn_plugin_close_v1\n");
+ plugin_log(PLOG_NOTE, MODULE, "FUNC: openvpn_plugin_close_v1");
free(context);
}
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 31ecadc..ed7e732 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1606,7 +1606,7 @@ initialization_sequence_completed(struct context *c, const unsigned int flags)
*/
if (c->options.mode == MODE_POINT_TO_POINT)
{
- delayed_auth_pass_purge();
+ ssl_clean_user_pass();
}
/* Test if errors */
@@ -2552,7 +2552,6 @@ key_schedule_free(struct key_schedule *ks, bool free_ssl_ctx)
if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx)
{
tls_ctx_free(&ks->ssl_ctx);
- free_key_ctx(&ks->tls_crypt_v2_server_key);
}
CLEAR(*ks);
}
@@ -3615,6 +3614,7 @@ do_close_free_key_schedule(struct context *c, bool free_ssl_ctx)
* always free the tls_auth/crypt key. If persist_key is true, the key will
* be reloaded from memory (pre-cached)
*/
+ free_key_ctx(&c->c1.ks.tls_crypt_v2_server_key);
free_key_ctx_bi(&c->c1.ks.tls_wrap_key);
CLEAR(c->c1.ks.tls_wrap_key);
buf_clear(&c->c1.ks.tls_crypt_v2_wkc);
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index ac14217..d86b6a7 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -2102,7 +2102,7 @@ man_io_error(struct management *man, const char *prefix)
static ssize_t
man_send_with_fd(int fd, void *ptr, size_t nbytes, int flags, int sendfd)
{
- struct msghdr msg;
+ struct msghdr msg = { 0 };
struct iovec iov[1];
union {
@@ -2134,7 +2134,7 @@ man_send_with_fd(int fd, void *ptr, size_t nbytes, int flags, int sendfd)
static ssize_t
man_recv_with_fd(int fd, void *ptr, size_t nbytes, int flags, int *recvfd)
{
- struct msghdr msghdr;
+ struct msghdr msghdr = { 0 };
struct iovec iov[1];
ssize_t n;
@@ -3613,7 +3613,6 @@ management_query_user_pass(struct management *man,
{
/* preserve caller's settings */
man->connection.up_query.nocache = up->nocache;
- man->connection.up_query.wait_for_push = up->wait_for_push;
*up = man->connection.up_query;
}
secure_memzero(&man->connection.up_query, sizeof(man->connection.up_query));
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 1038b38..c0c72dd 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -510,10 +510,15 @@ void
set_auth_token(struct user_pass *up, struct user_pass *tk, const char *token)
{
- if (token && strlen(token) && up && up->defined)
+ if (strlen(token) && (up->defined || tk->defined))
{
+ /* auth-token has no password, so it needs the username
+ * either already set or copied from up */
strncpynt(tk->password, token, USER_PASS_LEN);
- strncpynt(tk->username, up->username, USER_PASS_LEN);
+ if (up->defined)
+ {
+ strncpynt(tk->username, up->username, USER_PASS_LEN);
+ }
tk->defined = true;
}
diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h
index a03d94e..e4342b0 100644
--- a/src/openvpn/misc.h
+++ b/src/openvpn/misc.h
@@ -64,7 +64,6 @@ struct user_pass
{
bool defined;
bool nocache;
- bool wait_for_push; /* true if this object is waiting for a push-reply */
/* max length of username/password */
#ifdef ENABLE_PKCS11
@@ -145,6 +144,17 @@ void fail_user_pass(const char *prefix,
void purge_user_pass(struct user_pass *up, const bool force);
+/**
+ * Sets the auth-token to token if a username is available from either
+ * up or already present in tk. The method will also purge up if
+ * the auth-nocache option is active.
+ *
+ * @param up (non Auth-token) Username/password
+ * @param tk auth-token userpass to set
+ * @param token token to use as password for the
+ *
+ * @note all parameters to this function must not be null.
+ */
void set_auth_token(struct user_pass *up, struct user_pass *tk,
const char *token);
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 658ca53..0d99e99 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1983,6 +1983,23 @@ connection_entry_load_re(struct connection_entry *ce, const struct remote_entry
}
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)
{
@@ -2933,36 +2950,17 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce)
ce->tls_crypt_v2_file_inline = o->tls_crypt_v2_file_inline;
}
- /* pre-cache tls-auth/crypt key file if persist-key was specified and keys
- * were not already embedded in the config file
+ /* 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)
{
- if (ce->tls_auth_file && !ce->tls_auth_file_inline)
- {
- struct buffer in = buffer_read_from_file(ce->tls_auth_file, &o->gc);
- if (!buf_valid(&in))
- {
- msg(M_FATAL, "Cannot pre-load tls-auth keyfile (%s)",
- ce->tls_auth_file);
- }
-
- ce->tls_auth_file = (char *)in.data;
- ce->tls_auth_file_inline = true;
- }
-
- if (ce->tls_crypt_file && !ce->tls_crypt_file_inline)
- {
- struct buffer in = buffer_read_from_file(ce->tls_crypt_file, &o->gc);
- if (!buf_valid(&in))
- {
- msg(M_FATAL, "Cannot pre-load tls-crypt keyfile (%s)",
- ce->tls_crypt_file);
- }
-
- ce->tls_crypt_file = (char *)in.data;
- ce->tls_crypt_file_inline = true;
- }
+ 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);
}
}
@@ -3966,7 +3964,7 @@ options_warning_safe_scan2(const int msglevel,
if (strprefix(p1, "key-method ")
|| strprefix(p1, "keydir ")
|| strprefix(p1, "proto ")
- || strprefix(p1, "tls-auth ")
+ || streq(p1, "tls-auth")
|| strprefix(p1, "tun-ipv6")
|| strprefix(p1, "cipher "))
{
@@ -4661,7 +4659,8 @@ in_src_get(const struct in_src *is, char *line, const int size)
}
static char *
-read_inline_file(struct in_src *is, const char *close_tag, struct gc_arena *gc)
+read_inline_file(struct in_src *is, const char *close_tag,
+ int *num_lines, struct gc_arena *gc)
{
char line[OPTION_LINE_SIZE];
struct buffer buf = alloc_buf(8*OPTION_LINE_SIZE);
@@ -4670,6 +4669,7 @@ read_inline_file(struct in_src *is, const char *close_tag, struct gc_arena *gc)
while (in_src_get(is, line, sizeof(line)))
{
+ (*num_lines)++;
char *line_ptr = line;
/* Remove leading spaces */
while (isspace(*line_ptr))
@@ -4703,10 +4703,10 @@ read_inline_file(struct in_src *is, const char *close_tag, struct gc_arena *gc)
return ret;
}
-static bool
+static int
check_inline_file(struct in_src *is, char *p[], struct gc_arena *gc)
{
- bool is_inline = false;
+ int num_inline_lines = 0;
if (p[0] && !p[1])
{
@@ -4719,16 +4719,15 @@ check_inline_file(struct in_src *is, char *p[], struct gc_arena *gc)
p[0] = string_alloc(arg + 1, gc);
close_tag = alloc_buf(strlen(p[0]) + 4);
buf_printf(&close_tag, "</%s>", p[0]);
- p[1] = read_inline_file(is, BSTR(&close_tag), gc);
+ p[1] = read_inline_file(is, BSTR(&close_tag), &num_inline_lines, gc);
p[2] = NULL;
free_buf(&close_tag);
- is_inline = true;
}
}
- return is_inline;
+ return num_inline_lines;
}
-static bool
+static int
check_inline_file_via_fp(FILE *fp, char *p[], struct gc_arena *gc)
{
struct in_src is;
@@ -4737,7 +4736,7 @@ check_inline_file_via_fp(FILE *fp, char *p[], struct gc_arena *gc)
return check_inline_file(&is, p, gc);
}
-static bool
+static int
check_inline_file_via_buf(struct buffer *multiline, char *p[],
struct gc_arena *gc)
{
@@ -4808,13 +4807,12 @@ read_config_file(struct options *options,
}
if (parse_line(line + offset, p, SIZE(p)-1, file, line_num, msglevel, &options->gc))
{
- bool is_inline;
-
bypass_doubledash(&p[0]);
- is_inline = check_inline_file_via_fp(fp, p, &options->gc);
- add_option(options, p, is_inline, file, line_num, level,
+ int lines_inline = check_inline_file_via_fp(fp, p, &options->gc);
+ add_option(options, p, lines_inline, file, line_num, level,
msglevel, permission_mask, option_types_found,
es);
+ line_num += lines_inline;
}
}
if (fp != stdin)
@@ -4857,12 +4855,11 @@ read_config_string(const char *prefix,
++line_num;
if (parse_line(line, p, SIZE(p)-1, prefix, line_num, msglevel, &options->gc))
{
- bool is_inline;
-
bypass_doubledash(&p[0]);
- is_inline = check_inline_file_via_buf(&multiline, p, &options->gc);
- add_option(options, p, is_inline, prefix, line_num, 0, msglevel,
+ int lines_inline = check_inline_file_via_buf(&multiline, p, &options->gc);
+ add_option(options, p, lines_inline, prefix, line_num, 0, msglevel,
permission_mask, option_types_found, es);
+ line_num += lines_inline;
}
CLEAR(p);
}
@@ -5311,13 +5308,14 @@ add_option(struct options *options,
}
if (good)
{
-#if 0
- /* removed for now since ECHO can potentially include
- * security-sensitive strings */
- msg(M_INFO, "%s:%s",
- pull_mode ? "ECHO-PULL" : "ECHO",
- BSTR(&string));
-#endif
+ /* only message-related ECHO are logged, since other ECHOs
+ * can potentially include security-sensitive strings */
+ if (strncmp(p[1], "msg", 3) == 0)
+ {
+ msg(M_INFO, "%s:%s",
+ pull_mode ? "ECHO-PULL" : "ECHO",
+ BSTR(&string));
+ }
#ifdef ENABLE_MANAGEMENT
if (management)
{
diff --git a/src/openvpn/pf.c b/src/openvpn/pf.c
index f9bbfb5..3f472ef 100644
--- a/src/openvpn/pf.c
+++ b/src/openvpn/pf.c
@@ -639,8 +639,17 @@ pf_init_context(struct context *c)
}
if (!c->c2.pf.enabled)
{
- msg(M_WARN, "WARNING: failed to init PF plugin, rejecting client.");
- register_signal(c, SIGUSR1, "plugin-pf-init-failed");
+ /* At some point in openvpn history, this code just printed a
+ * warning and signalled itself (SIGUSR1, "plugin-pf-init-failed")
+ * to terminate the client instance. This got broken at one of
+ * the client auth state refactorings (leading to SIGSEGV crashes)
+ * and due to "pf will be removed anyway" reasons the easiest way
+ * to prevent crashes is to REQUIRE that plugins succeed - so if
+ * the plugin fails, we cleanly abort OpenVPN
+ *
+ * see also: https://community.openvpn.net/openvpn/ticket/1377
+ */
+ msg(M_FATAL, "FATAL: failed to init PF plugin, must succeed.");
return;
}
}
diff --git a/src/openvpn/ps.c b/src/openvpn/ps.c
index 2089e6b..5d76078 100644
--- a/src/openvpn/ps.c
+++ b/src/openvpn/ps.c
@@ -983,14 +983,38 @@ is_openvpn_protocol(const struct buffer *buf)
const int len = BLEN(buf);
if (len >= 3)
{
- return p[0] == 0
- && p[1] >= 14
- && (p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2 << P_OPCODE_SHIFT)
- || p[2] == (P_CONTROL_HARD_RESET_CLIENT_V3 << P_OPCODE_SHIFT));
+ int plen = (p[0] << 8) | p[1];
+
+ if (p[2] == (P_CONTROL_HARD_RESET_CLIENT_V3 << P_OPCODE_SHIFT))
+ {
+ /* WKc is at least 290 byte (not including metadata):
+ *
+ * 16 bit len + 256 bit HMAC + 2048 bit Kc = 2320 bit
+ *
+ * This is increased by the normal length of client handshake +
+ * tls-crypt overhead (32)
+ *
+ * For metadata tls-crypt-v2.txt does not explicitly specify
+ * an upper limit but we also have TLS_CRYPT_V2_MAX_WKC_LEN
+ * as 1024 bytes. We err on the safe side with 255 extra overhead
+ *
+ * We don't do the 2 byte check for tls-crypt-v2 because it is very
+ * unrealistic to have only 2 bytes available.
+ */
+ return (plen >= 336 && plen < (1024 + 255));
+ }
+ else
+ {
+ /* For non tls-crypt2 we assume the packet length to valid between
+ * 14 and 255 */
+ return plen >= 14 && plen <= 255
+ && (p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2 << P_OPCODE_SHIFT));
+ }
}
else if (len >= 2)
{
- return p[0] == 0 && p[1] >= 14;
+ int plen = (p[0] << 8) | p[1];
+ return plen >= 14 && plen <= 255;
}
else
{
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index c6ba812..d7494c2 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -434,8 +434,6 @@ ssl_set_auth_nocache(void)
{
passbuf.nocache = true;
auth_user_pass.nocache = true;
- /* wait for push-reply, because auth-token may still need the username */
- auth_user_pass.wait_for_push = true;
}
/*
@@ -2358,14 +2356,15 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)
}
/* if auth-nocache was specified, the auth_user_pass object reaches
* a "complete" state only after having received the push-reply
- * message.
+ * message. The push message might contain an auth-token that needs
+ * the username of auth_user_pass.
*
* For this reason, skip the purge operation here if no push-reply
* message has been received yet.
*
* This normally happens upon first negotiation only.
*/
- if (!auth_user_pass.wait_for_push)
+ if (!session->opt->pull)
{
purge_user_pass(&auth_user_pass, false);
}
@@ -4104,8 +4103,7 @@ done:
}
void
-delayed_auth_pass_purge(void)
+ssl_clean_user_pass(void)
{
- auth_user_pass.wait_for_push = false;
purge_user_pass(&auth_user_pass, false);
}
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index 005628f..97d721b 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -598,7 +598,10 @@ void extract_x509_field_test(void);
*/
bool is_hard_reset_method2(int op);
-void delayed_auth_pass_purge(void);
+/**
+ * Cleans the saved user/password unless auth-nocache is in use.
+ */
+void ssl_clean_user_pass(void);
/*
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 8315a42..1767420 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -5212,7 +5212,7 @@ netsh_command(const struct argv *a, int n, int msglevel)
for (i = 0; i < n; ++i)
{
bool status;
- management_sleep(1);
+ management_sleep(0);
netcmd_semaphore_lock();
argv_msg_prefix(M_INFO, a, "NETSH");
status = openvpn_execve_check(a, NULL, 0, "ERROR: netsh command failed");
@@ -5240,7 +5240,6 @@ ipconfig_register_dns(const struct env_set *es)
WIN_IPCONFIG_PATH_SUFFIX);
argv_msg(D_TUNTAP_INFO, &argv);
openvpn_execve_check(&argv, es, 0, err);
- argv_free(&argv);
argv_printf(&argv, "%s%s /registerdns",
get_win_sys_path(),
@@ -6160,35 +6159,35 @@ tuntap_set_ip_addr(struct tuntap *tt,
status,
strerror_win32(status, &gc));
}
- }
- /*
- * If the TAP-Windows driver is masquerading as a DHCP server
- * make sure the TCP/IP properties for the adapter are
- * set correctly.
- */
- if (dhcp_masq_post)
- {
- /* check dhcp enable status */
- if (dhcp_status(index) == DHCP_STATUS_DISABLED)
+ /*
+ * If the TAP-Windows driver is masquerading as a DHCP server
+ * make sure the TCP/IP properties for the adapter are
+ * set correctly.
+ */
+ if (dhcp_masq_post)
{
- msg(M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Windows TCP/IP properties are set to 'Obtain an IP address automatically'");
- }
+ /* check dhcp enable status */
+ if (dhcp_status(index) == DHCP_STATUS_DISABLED)
+ {
+ msg(M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Windows TCP/IP properties are set to 'Obtain an IP address automatically'");
+ }
- /* force an explicit DHCP lease renewal on TAP adapter? */
- if (tt->options.dhcp_pre_release)
- {
- dhcp_release(tt);
+ /* force an explicit DHCP lease renewal on TAP adapter? */
+ if (tt->options.dhcp_pre_release)
+ {
+ dhcp_release(tt);
+ }
+ if (tt->options.dhcp_renew)
+ {
+ dhcp_renew(tt);
+ }
}
- if (tt->options.dhcp_renew)
+ else
{
- dhcp_renew(tt);
+ fork_dhcp_action(tt);
}
}
- else
- {
- fork_dhcp_action(tt);
- }
if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_IPAPI)
{
diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c
index 65bb106..5d5cbfe 100644
--- a/src/openvpnserv/interactive.c
+++ b/src/openvpnserv/interactive.c
@@ -1104,7 +1104,7 @@ wmic_nicconfig_cmd(const wchar_t *action, const NET_IFINDEX if_index,
}
else
{
- fmt = L"wmic nicconfig where (InterfaceIndex=%ld) call %s %s";
+ fmt = L"wmic nicconfig where (InterfaceIndex=%ld) call %s \"%s\"";
}
size_t ncmdline = wcslen(fmt) + 20 + wcslen(action) /* max 20 for ifindex */
diff --git a/version.m4 b/version.m4
index 66be5d3..66832fc 100644
--- a/version.m4
+++ b/version.m4
@@ -3,12 +3,12 @@ define([PRODUCT_NAME], [OpenVPN])
define([PRODUCT_TARNAME], [openvpn])
define([PRODUCT_VERSION_MAJOR], [2])
define([PRODUCT_VERSION_MINOR], [5])
-define([PRODUCT_VERSION_PATCH], [.0])
+define([PRODUCT_VERSION_PATCH], [.1])
m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_MAJOR])
m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_MINOR], [[.]])
m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_PATCH], [[]])
define([PRODUCT_BUGREPORT], [openvpn-users@lists.sourceforge.net])
-define([PRODUCT_VERSION_RESOURCE], [2,5,0,8])
+define([PRODUCT_VERSION_RESOURCE], [2,5,1,0])
dnl define the TAP version
define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap0901])
define([PRODUCT_TAP_WIN_MIN_MAJOR], [9])