Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package openvpn for openSUSE:Factory checked in at 2021-06-11 22:30:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openvpn (Old) and /work/SRC/openSUSE:Factory/.openvpn.new.32437 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openvpn" Fri Jun 11 22:30:28 2021 rev:92 rq:898085 version:2.4.11 Changes: -------- --- /work/SRC/openSUSE:Factory/openvpn/openvpn.changes 2021-04-26 16:38:42.369987943 +0200 +++ /work/SRC/openSUSE:Factory/.openvpn.new.32437/openvpn.changes 2021-06-11 22:30:52.330150807 +0200 @@ -1,0 +2,17 @@ +Mon May 31 15:29:08 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 2.4.11 (bsc#1185279): + * CVE-2020-15078 see https://community.openvpn.net/openvpn/wiki/SecurityAnnouncements + + * This bug allows - under very specific circumstances - to trick a server using + delayed authentication (plugin or management) into returning a PUSH_REPLY + before the AUTH_FAILED message, which can possibly be used to gather + information about a VPN setup. + * In combination with "--auth-gen-token" or an user-specific token auth + solution it can be possible to get access to a VPN with an + otherwise-invalid account. + * Fix potential NULL ptr crash if compiled with DMALLOC +- drop sysv5 init support, it hasn't build successfully in ages + and is build-disabled in devel project + +------------------------------------------------------------------- Old: ---- openvpn-2.4.10.tar.xz openvpn-2.4.10.tar.xz.asc openvpn.init openvpn.sysconfig New: ---- openvpn-2.4.11.tar.xz openvpn-2.4.11.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openvpn.spec ++++++ --- /var/tmp/diff_new_pack.8RVvjF/_old 2021-06-11 22:30:52.990151951 +0200 +++ /var/tmp/diff_new_pack.8RVvjF/_new 2021-06-11 22:30:52.990151951 +0200 @@ -20,16 +20,11 @@ %if ! %{defined _fillupdir} %define _fillupdir %{_localstatedir}/adm/fillup-templates %endif -%if 0%{?suse_version} > 1210 -%define with_systemd 1 -%else -%define with_systemd 0 -%endif %if ! %{defined _rundir} %define _rundir %{_localstatedir}/run %endif Name: openvpn -Version: 2.4.10 +Version: 2.4.11 Release: 0 Summary: Full-featured SSL VPN solution using a TUN/TAP Interface License: LGPL-2.1-only AND SUSE-GPL-2.0-with-openssl-exception @@ -37,11 +32,9 @@ URL: http://openvpn.net/ Source: https://swupdate.openvpn.org/community/releases/openvpn-%{version}.tar.xz Source1: https://swupdate.openvpn.org/community/releases/openvpn-%{version}.tar.xz.asc -Source2: %{name}.init Source3: %{name}.README.SUSE Source4: client-netconfig.up Source5: client-netconfig.down -Source6: %{name}.sysconfig Source7: %{name}.keyring Source8: %{name}.service Source9: %{name}.target @@ -59,18 +52,14 @@ BuildRequires: p11-kit-devel BuildRequires: pam-devel BuildRequires: pkcs11-helper-devel >= 1.11 +BuildRequires: pkgconfig BuildRequires: xz +BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(systemd) Requires: iproute2 Requires: pkcs11-helper >= 1.11 Requires: sysvinit-tools -%if %{with_systemd} -BuildRequires: pkgconfig(libsystemd) -BuildRequires: pkgconfig(systemd) %systemd_ordering -%else -PreReq: %fillup_prereq -PreReq: %insserv_prereq -%endif %description OpenVPN is a full-featured SSL VPN solution which can accommodate a wide @@ -143,13 +132,12 @@ %patch8 -p1 %patch9 -p1 -sed -e "s|\" __DATE__|$(date '+%b %e %Y' -r version.m4)\"|g" \ +sed -e "s|\" __DATE__|$(date '+%%b %%e %%Y' -r version.m4)\"|g" \ -i src/openvpn/options.c sed -e "s|@PLUGIN_LIBDIR@|%{_libdir}/openvpn/plugins|g" \ -e "s|@PLUGIN_DOCDIR@|%{_defaultdocdir}/%{name}|g" \ -i doc/openvpn.8 -sed -e "s|%{_localstatedir}/run|%{_rundir}|g" < \ - $RPM_SOURCE_DIR/%{name}.service > %{name}.service +sed -e "s|%{_localstatedir}/run|%{_rundir}|g" < %{SOURCE8} > %{name}.service # %%doc items shouldn't be executable. find contrib sample -type f -exec chmod a-x \{\} \; @@ -157,19 +145,21 @@ %build export CFLAGS="%{optflags} $(getconf LFS_CFLAGS) -W -Wall -fno-strict-aliasing" export LDFLAGS +%if 0%{?suse_version} >= 1550 +# usrmerge +export IPROUTE="%{_sbindir}/ip" +%endif %configure \ --enable-iproute2 \ --enable-x509-alt-username \ --enable-pkcs11 \ -%if %{with_systemd} --enable-systemd \ -%endif --enable-plugins \ --enable-plugin-down-root \ --enable-plugin-auth-pam \ CFLAGS="$CFLAGS $(getconf LFS_CFLAGS) -fPIE $PLUGIN_DEFS" \ LDFLAGS="$LDFLAGS -pie -lpam -rdynamic -Wl,-rpath,%{_libdir}/%{name}/plugins" -make %{?_smp_mflags} +%make_build %install %make_install @@ -177,40 +167,28 @@ mkdir -p %{buildroot}/%{_sysconfdir}/openvpn mkdir -p %{buildroot}/%{_rundir}/openvpn mkdir -p %{buildroot}/%{_datadir}/openvpn -%if %{with_systemd} rm %{buildroot}%{_libdir}/systemd/system/openvpn-client@.service rm %{buildroot}%{_libdir}/systemd/system/openvpn-server@.service #use one proveded by suse rm %{buildroot}%{_libdir}/tmpfiles.d/openvpn.conf install -D -m 644 %{name}.service %{buildroot}/%{_unitdir}/%{name}@.service -install -D -m 644 $RPM_SOURCE_DIR/%{name}.target %{buildroot}/%{_unitdir}/%{name}.target -install -D -m 755 $RPM_SOURCE_DIR/rc%{name} %{buildroot}%{_sbindir}/rc%{name} +install -D -m 644 %{SOURCE9} %{buildroot}/%{_unitdir}/%{name}.target +install -D -m 755 %{SOURCE11} %{buildroot}%{_sbindir}/rc%{name} # tmpfiles.d mkdir -p %{buildroot}%{_tmpfilesdir} -install -m 0644 $RPM_SOURCE_DIR/%{name}-tmpfile.conf %{buildroot}%{_tmpfilesdir}/%{name}.conf -%else -install -D -m 755 $RPM_SOURCE_DIR/openvpn.init %{buildroot}/%{_sysconfdir}/init.d/openvpn -ln -sv %{_sysconfdir}/init.d/openvpn %{buildroot}/%{_sbindir}/rcopenvpn -# the /etc/sysconfig/openvpn template only with sysvinit, no needed with systemd -install -d -m0755 %{buildroot}%{_fillupdir} -install -m0600 $RPM_SOURCE_DIR/openvpn.sysconfig \ - %{buildroot}%{_fillupdir}/sysconfig.openvpn -%endif -cp -p $RPM_SOURCE_DIR/openvpn.README.SUSE README.SUSE -install -m 755 $RPM_SOURCE_DIR/client-netconfig.up sample/sample-scripts/client-netconfig.up -install -m 755 $RPM_SOURCE_DIR/client-netconfig.down sample/sample-scripts/client-netconfig.down +install -m 0644 %{SOURCE10} %{buildroot}%{_tmpfilesdir}/%{name}.conf +cp -p %{SOURCE3} README.SUSE +install -m 755 %{SOURCE4} sample/sample-scripts/client-netconfig.up +install -m 755 %{SOURCE5} sample/sample-scripts/client-netconfig.down # we install docs via spec into _defaultdocdir/name/management-notes.txt rm -rf %{buildroot}%{_datadir}/doc/{OpenVPN,%{name}} find sample -name .gitignore | xargs rm -f %pre -%if %{with_systemd} %service_add_pre %{name}.target -%endif %post -%if %{with_systemd} %tmpfiles_create %{_tmpfilesdir}/%{name}.conf %service_add_post %{name}.target # try to migrate openvpn.service autostart to openvpn@<CONF>.service @@ -247,23 +225,12 @@ fi fi rm -f %{_sysconfdir}/sysconfig/openvpn || : -%else -%{?fillup_and_insserv:%fillup_and_insserv} -%endif %preun -%if %{with_systemd} %service_del_preun %{name}.target -%else -%{?stop_on_removal:%stop_on_removal openvpn} -%endif %postun -%if %{with_systemd} %service_del_postun %{name}.target -%else -%{?insserv_cleanup:%insserv_cleanup} -%endif %files %license COPYING @@ -277,17 +244,11 @@ %doc doc/management-notes.txt %{_mandir}/man8/openvpn.8%{?ext_man} %config(noreplace) %{_sysconfdir}/openvpn/ -%if %{with_systemd} %dir %{_tmpfilesdir} %{_unitdir}/%{name}@.service %{_unitdir}/%{name}.target %{_tmpfilesdir}/%{name}.conf %dir %attr(0750,root,root) %ghost %{_rundir}/openvpn/ -%else -%config %{_sysconfdir}/init.d/openvpn -%{_fillupdir}/sysconfig.openvpn -%dir %attr(750,root,root) %{_rundir}/openvpn/ -%endif %{_sbindir}/rcopenvpn %{_sbindir}/openvpn ++++++ openvpn-2.4.10.tar.xz -> openvpn-2.4.11.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/ChangeLog new/openvpn-2.4.11/ChangeLog --- old/openvpn-2.4.10/ChangeLog 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/ChangeLog 2021-04-21 07:11:52.000000000 +0200 @@ -1,6 +1,23 @@ OpenVPN Change Log Copyright (C) 2002-2018 OpenVPN Inc <sa...@openvpn.net> +2021.04.20 -- Version 2.4.11 + +Arne Schwabe (1): + Ensure key state is authenticated before sending push reply + +Gert Doering (2): + clean up / rewrite sample-plugins/defer/simple.c + Fix potential NULL ptr crash if compiled with DMALLOC + +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. + + 2020.12.09 -- Version 2.4.10 Antonio Quartulli (1): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/Changes.rst new/openvpn-2.4.11/Changes.rst --- old/openvpn-2.4.10/Changes.rst 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/Changes.rst 2021-04-21 07:11:52.000000000 +0200 @@ -321,6 +321,31 @@ i386/i686 builds on RHEL5. +Version 2.4.11 +============= +This is primarily a maintenance release with minor bugfixes and improvements. + +Bug fixes +--------- +- CVE-2020-15078 + see https://community.openvpn.net/openvpn/wiki/SecurityAnnouncements + + This bug allows - under very specific circumstances - to trick a + server using delayed authentication (plugin or management) into + returning a PUSH_REPLY before the AUTH_FAILED message, which can + possibly be used to gather information about a VPN setup. + + In combination with "--auth-gen-token" or an user-specific token auth + solution it can be possible to get access to a VPN with an + otherwise-invalid account. + +- Fix potential NULL ptr crash if compiled with DMALLOC + +Enhancements +------------ + - multiple patches to improve "sample defer plugin" + documentation + + Version 2.4.10 ============= This is primarily a maintenance release with minor bugfixes and improvements. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/configure new/openvpn-2.4.11/configure --- old/openvpn-2.4.10/configure 2020-12-09 12:26:34.000000000 +0100 +++ new/openvpn-2.4.11/configure 2021-04-21 07:12:02.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OpenVPN 2.4.10. +# Generated by GNU Autoconf 2.69 for OpenVPN 2.4.11. # # Report bugs to <openvpn-us...@lists.sourceforge.net>. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='OpenVPN' PACKAGE_TARNAME='openvpn' -PACKAGE_VERSION='2.4.10' -PACKAGE_STRING='OpenVPN 2.4.10' +PACKAGE_VERSION='2.4.11' +PACKAGE_STRING='OpenVPN 2.4.11' PACKAGE_BUGREPORT='openvpn-us...@lists.sourceforge.net' PACKAGE_URL='' @@ -1455,7 +1455,7 @@ # 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.4.10 to adapt to many kinds of systems. +\`configure' configures OpenVPN 2.4.11 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1525,7 +1525,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenVPN 2.4.10:";; + short | recursive ) echo "Configuration of OpenVPN 2.4.11:";; esac cat <<\_ACEOF @@ -1736,7 +1736,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenVPN configure 2.4.10 +OpenVPN configure 2.4.11 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2575,7 +2575,7 @@ 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.4.10, which was +It was created by OpenVPN $as_me 2.4.11, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2939,13 +2939,13 @@ fi -$as_echo "#define OPENVPN_VERSION_RESOURCE 2,4,10,0" >>confdefs.h +$as_echo "#define OPENVPN_VERSION_RESOURCE 2,4,11,0" >>confdefs.h OPENVPN_VERSION_MAJOR=2 OPENVPN_VERSION_MINOR=4 -OPENVPN_VERSION_PATCH=.10 +OPENVPN_VERSION_PATCH=.11 $as_echo "#define OPENVPN_VERSION_MAJOR 2" >>confdefs.h @@ -2954,7 +2954,7 @@ $as_echo "#define OPENVPN_VERSION_MINOR 4" >>confdefs.h -$as_echo "#define OPENVPN_VERSION_PATCH \".10\"" >>confdefs.h +$as_echo "#define OPENVPN_VERSION_PATCH \".11\"" >>confdefs.h ac_aux_dir= @@ -3478,7 +3478,7 @@ # Define the identity of the package. PACKAGE='openvpn' - VERSION='2.4.10' + VERSION='2.4.11' cat >>confdefs.h <<_ACEOF @@ -18813,7 +18813,7 @@ # 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.4.10, which was +This file was extended by OpenVPN $as_me 2.4.11, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18879,7 +18879,7 @@ 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.4.10 +OpenVPN config.status 2.4.11 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/include/openvpn-plugin.h new/openvpn-2.4.11/include/openvpn-plugin.h --- old/openvpn-2.4.10/include/openvpn-plugin.h 2020-12-09 12:26:48.000000000 +0100 +++ new/openvpn-2.4.11/include/openvpn-plugin.h 2021-04-21 07:12:16.000000000 +0200 @@ -55,7 +55,7 @@ */ #define OPENVPN_VERSION_MAJOR 2 #define OPENVPN_VERSION_MINOR 4 -#define OPENVPN_VERSION_PATCH ".10" +#define OPENVPN_VERSION_PATCH ".11" /* * Plug-in types. These types correspond to the set of script callbacks @@ -667,12 +667,12 @@ * 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 * @@ -733,8 +733,8 @@ * 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/include/openvpn-plugin.h.in new/openvpn-2.4.11/include/openvpn-plugin.h.in --- old/openvpn-2.4.10/include/openvpn-plugin.h.in 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/include/openvpn-plugin.h.in 2021-04-21 07:11:52.000000000 +0200 @@ -666,12 +666,12 @@ * 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 * @@ -732,8 +732,8 @@ * 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/sample/sample-plugins/defer/simple.c new/openvpn-2.4.11/sample/sample-plugins/defer/simple.c --- old/openvpn-2.4.10/sample/sample-plugins/defer/simple.c 2020-12-09 12:26:23.000000000 +0100 +++ new/openvpn-2.4.11/sample/sample-plugins/defer/simple.c 2021-04-21 07:11:49.000000000 +0200 @@ -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 @@ 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 @@ } } -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_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); + + /* 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; - return (openvpn_plugin_handle_t) context; +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 username/password from envp string array */ + const char *username = get_env("username", envp); + const char *password = get_env("password", envp); - /* get auth_control_file filename from envp string array*/ - const char *auth_control_file = get_env("auth_control_file", envp); + /* get auth_control_file filename from envp string array*/ + const char *auth_control_file = get_env("auth_control_file", envp); - printf("DEFER u='%s' p='%s' acf='%s'\n", + 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_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_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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/src/openvpn/buffer.c new/openvpn-2.4.11/src/openvpn/buffer.c --- old/openvpn-2.4.10/src/openvpn/buffer.c 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/src/openvpn/buffer.c 2021-04-21 07:11:52.000000000 +0200 @@ -647,7 +647,6 @@ */ #ifdef DMALLOC ret = openvpn_dmalloc(file, line, n); - memset(ret, 0, n); #else ret = calloc(1, n); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/src/openvpn/push.c new/openvpn-2.4.11/src/openvpn/push.c --- old/openvpn-2.4.10/src/openvpn/push.c 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/src/openvpn/push.c 2021-04-21 07:11:52.000000000 +0200 @@ -652,6 +652,7 @@ process_incoming_push_request(struct context *c) { int ret = PUSH_MSG_ERROR; + struct key_state *ks = &c->c2.tls_multi->session[TM_ACTIVE].key[KS_PRIMARY]; #ifdef ENABLE_ASYNC_PUSH c->c2.push_request_received = true; @@ -662,7 +663,12 @@ send_auth_failed(c, client_reason); ret = PUSH_MSG_AUTH_FAILURE; } - else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED) + else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED + && ks->authenticated + #ifdef ENABLE_DEF_AUTH + && !ks->auth_deferred + #endif + ) { time_t now; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openvpn-2.4.10/version.m4 new/openvpn-2.4.11/version.m4 --- old/openvpn-2.4.10/version.m4 2020-12-09 12:26:25.000000000 +0100 +++ new/openvpn-2.4.11/version.m4 2021-04-21 07:11:52.000000000 +0200 @@ -3,12 +3,12 @@ define([PRODUCT_TARNAME], [openvpn]) define([PRODUCT_VERSION_MAJOR], [2]) define([PRODUCT_VERSION_MINOR], [4]) -define([PRODUCT_VERSION_PATCH], [.10]) +define([PRODUCT_VERSION_PATCH], [.11]) 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-us...@lists.sourceforge.net]) -define([PRODUCT_VERSION_RESOURCE], [2,4,10,0]) +define([PRODUCT_VERSION_RESOURCE], [2,4,11,0]) dnl define the TAP version define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap0901]) define([PRODUCT_TAP_WIN_MIN_MAJOR], [9]) ++++++ openvpn.keyring ++++++ ++++ 623 lines (skipped) ++++ between openvpn.keyring ++++ and /work/SRC/openSUSE:Factory/.openvpn.new.32437/openvpn.keyring