Re: [Openvpn-devel] new coverity release

2021-01-25 Thread Antonio Quartulli
Hi,

we used to push Coverity builds via Travis, however it seems it hasn't
been pushed in a while.

It'd be good to check what's wrong and get it going again.

Regards,

On 25/01/2021 21:53, Илья Шипицин wrote:
> Hello,
> 
> how are coverity builds scheduled ?
> shouldn't we start new one ?
> 
> https://community.synopsys.com/s/question/0D52H5NeWJfSAN/announcement-upcoming-coverity-scan-upgrade-to-coverity-202009-release
> 
> 
> 
> Ilya
> 
> 
> ___
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
> 

-- 
Antonio Quartulli


___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] new coverity release

2021-01-25 Thread Илья Шипицин
Hello,

how are coverity builds scheduled ?
shouldn't we start new one ?

https://community.synopsys.com/s/question/0D52H5NeWJfSAN/announcement-upcoming-coverity-scan-upgrade-to-coverity-202009-release


Ilya
___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH v2 04/11] Introduce management client state for AUTH_PENDING notifications

2021-01-25 Thread Arne Schwabe
This allows a UI client to display the correct state. Technically the
client is still waiting for PUSH_REPLY but for every practical concern
this is a different state as we are waiting for the pending
authentication to finish.

Signed-off-by: Arne Schwabe 
---
 src/openvpn/manage.c |  3 +++
 src/openvpn/manage.h |  2 ++
 src/openvpn/push.c   | 18 ++
 3 files changed, 23 insertions(+)

diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 98a9a4cc..df987f53 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -169,6 +169,9 @@ man_state_name(const int state)
 case OPENVPN_STATE_TCP_CONNECT:
 return "TCP_CONNECT";
 
+case OPENVPN_STATE_AUTH_PENDING:
+return "AUTH_PENDING";
+
 default:
 return "?";
 }
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index aaa3b848..2f94b10c 100644
--- a/src/openvpn/manage.h
+++ b/src/openvpn/manage.h
@@ -493,6 +493,8 @@ management_enable_def_auth(const struct management *man)
 #define OPENVPN_STATE_GET_CONFIG9  /* Downloading configuration from 
server */
 #define OPENVPN_STATE_RESOLVE   10 /* DNS lookup */
 #define OPENVPN_STATE_TCP_CONNECT   11 /* Connecting to TCP server */
+#define OPENVPN_STATE_AUTH_PENDING  12 /* Waiting in auth-pending mode
+* techhnically variant of GET_CONFIG */
 
 #define OPENVPN_STATE_CLIENT_BASE   7  /* Base index of client-only states */
 
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index e68fda9f..7d3cf806 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -248,12 +248,30 @@ parse_auth_pending_keywords(const struct buffer *buffer,
 if (!buf_advance(, strlen("AUTH_PENDING"))
 || !(buf_read_u8() == ',') || !BLEN())
 {
+#ifdef ENABLE_MANAGEMENT
+if (management)
+{
+management_set_state(management, OPENVPN_STATE_AUTH_PENDING,
+ "", NULL, NULL, NULL, NULL);
+}
+#endif
+
 return;
 }
 
 /* parse the keywords in the same way that push options are parsed */
 char line[OPTION_LINE_SIZE];
 
+#ifdef ENABLE_MANAGEMENT
+/* Need to do the management notification with the keywords before
+ * buf_parse is called, as it will insert \0 bytes into the buffer */
+if (management)
+{
+management_set_state(management, OPENVPN_STATE_AUTH_PENDING,
+ BSTR(), NULL, NULL, NULL, NULL);
+}
+#endif
+
 while (buf_parse(, ',', line, sizeof(line)))
 {
 if (sscanf(line, "timeout %u", server_timeout) != 1)
-- 
2.30.0



___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH v2 00/11] Pending authentication improvements

2021-01-25 Thread Arne Schwabe
This patchset brings a number of improvements:

 - Allow a tiemout that is different from the default 60s for
   pending authentication. 60s is a bit tight, especially when
   being redirected to a complicated web login process.
 - Make the server side auth-pending support no longer
   dependent on management interface but also allow scripts
   and plugins to utilise it.
 - Introduce deffered authentication support for scripts.
   Deferred authentication is a necessary requirement for
   pending authentication.

The branch is also available here: 
https://github.com/schwabe/openvpn/tree/schwabe/auth_pending

The v2 patches ae modified from the v1 if they contain a Patch v2 note in the 
commit message, otherwise
they are just rebased and resent with the patchset.

Arne Schwabe (11):
  Change pull request timeout use a timeout rather than a number
  Implement client side handling of AUTH_PENDING message
  Implement server side of AUTH_PENDING with extending timeout
  Introduce management client state for AUTH_PENDING notifications
  Change parameter of send_auth_pending_messages from context to
tls_multi
  Add S_EXITCODE flag for openvpn_run_script to report exit code
  Refactor extract_var_peer_info into standalone function and add
ssl_util.c
  Allow pending auth to be send from a auth plugin
  Implement deferred auth for scripts
  Implement --client-crresponse script options and plugin interface
  Add example script demonstrating TOTP via auth-pending

 Changes.rst  |  21 ++
 doc/man-sections/generic-options.rst |   3 +-
 doc/man-sections/script-options.rst  |  45 +++-
 doc/man-sections/server-options.rst  |   4 +
 doc/man-sections/tls-options.rst |   3 +
 doc/management-notes.txt |  39 +++-
 include/openvpn-plugin.h.in  |  15 +-
 sample/sample-scripts/totpauth.py| 107 +
 src/openvpn/Makefile.am  |   1 +
 src/openvpn/forward.c|  27 ++-
 src/openvpn/forward.h|   9 +
 src/openvpn/init.c   |   1 +
 src/openvpn/integer.h|  25 +++
 src/openvpn/manage.c |  26 ++-
 src/openvpn/manage.h |   5 +-
 src/openvpn/multi.c  |  29 +--
 src/openvpn/openvpn.h|   2 +-
 src/openvpn/openvpn.vcxproj  |   2 +
 src/openvpn/openvpn.vcxproj.filters  |   6 +
 src/openvpn/options.c|  15 ++
 src/openvpn/options.h|   1 +
 src/openvpn/platform.c   |  34 +++
 src/openvpn/platform.h   |   5 +-
 src/openvpn/push.c   | 153 -
 src/openvpn/push.h   |  23 +-
 src/openvpn/run_command.c|  25 ++-
 src/openvpn/run_command.h|  15 +-
 src/openvpn/ssl.c|  10 +-
 src/openvpn/ssl.h|   3 +
 src/openvpn/ssl_common.h |   4 +
 src/openvpn/ssl_ncp.c|  20 +-
 src/openvpn/ssl_util.c   |  59 +
 src/openvpn/ssl_util.h   |  49 +
 src/openvpn/ssl_verify.c | 311 ---
 src/openvpn/ssl_verify.h |  25 ++-
 tests/unit_tests/openvpn/Makefile.am |   3 +-
 36 files changed, 988 insertions(+), 137 deletions(-)
 create mode 100755 sample/sample-scripts/totpauth.py
 create mode 100644 src/openvpn/ssl_util.c
 create mode 100644 src/openvpn/ssl_util.h

-- 
2.30.0



___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH v2 05/11] Change parameter of send_auth_pending_messages from context to tls_multi

2021-01-25 Thread Arne Schwabe
This prepares send_auth_pending_messages to be used a in context that
does not have context c available but also does not need to schedule
an immediate sending of the message (auth plugin/script)

Patch V2: Adjust the comment of reschedule_multi_process to actually fit a
  function.

Signed-off-by: Arne Schwabe 
---
 src/openvpn/forward.c | 17 +
 src/openvpn/forward.h |  9 +
 src/openvpn/multi.c   |  4 +++-
 src/openvpn/push.c|  9 -
 src/openvpn/push.h|  4 +++-
 5 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 2e1e1490..fc28caf0 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -342,6 +342,14 @@ send_control_channel_string_dowork(struct tls_multi *multi,
 return stat;
 }
 
+void reschedule_multi_process(struct context *c)
+{
+
+interval_action(>c2.tmp_int);
+context_immediate_reschedule(c); /* ZERO-TIMEOUT */
+}
+
+
 bool
 send_control_channel_string(struct context *c, const char *str, int msglevel)
 {
@@ -349,15 +357,8 @@ send_control_channel_string(struct context *c, const char 
*str, int msglevel)
 {
 bool ret = send_control_channel_string_dowork(c->c2.tls_multi,
   str, msglevel);
-/*
- * Reschedule tls_multi_process.
- * NOTE: in multi-client mode, usually the below two statements are
- * insufficient to reschedule the client instance object unless
- * multi_schedule_context_wakeup(m, mi) is also called.
- */
+reschedule_multi_process(c);
 
-interval_action(>c2.tmp_int);
-context_immediate_reschedule(c); /* ZERO-TIMEOUT */
 return ret;
 }
 return true;
diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h
index a8b19f69..9ce3bc1c 100644
--- a/src/openvpn/forward.h
+++ b/src/openvpn/forward.h
@@ -317,6 +317,15 @@ bool
 send_control_channel_string_dowork(struct tls_multi *multi,
const char *str, int msglevel);
 
+
+/**
+ * Reschedule tls_multi_process.
+ * NOTE: in multi-client mode, usually calling the function is
+ * insufficient to reschedule the client instance object unless
+ * multi_schedule_context_wakeup(m, mi) is also called.
+ */
+void reschedule_multi_process(struct context *c);
+
 #define PIPV4_PASSTOS   (1<<0)
 #define PIP_MSSFIX  (1<<1) /* v4 and v6 */
 #define PIP_OUTGOING(1<<2)
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index ac5d3f5b..d10f188c 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -3904,7 +3904,9 @@ management_client_pending_auth(void *arg,
 if (mi)
 {
 /* sends INFO_PRE and AUTH_PENDING messages to client */
-bool ret = send_auth_pending_messages(>context, extra, timeout);
+bool ret = send_auth_pending_messages(mi->context.c2.tls_multi, extra,
+  timeout);
+reschedule_multi_process(>context);
 multi_schedule_context_wakeup(m, mi);
 return ret;
 }
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index 7d3cf806..320ad737 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -363,14 +363,13 @@ send_auth_failed(struct context *c, const char 
*client_reason)
 
 
 bool
-send_auth_pending_messages(struct context *c, const char *extra,
+send_auth_pending_messages(struct tls_multi *tls_multi, const char *extra,
unsigned int timeout)
 {
 struct key_state *ks = _multi->session[TM_ACTIVE].key[KS_PRIMARY];
 
 static const char info_pre[] = "INFO_PRE,";
 
-struct tls_multi *tls_multi = c->c2.tls_multi;
 const char *const peer_info = tls_multi->peer_info;
 unsigned int proto = extract_iv_proto(peer_info);
 
@@ -384,7 +383,7 @@ send_auth_pending_messages(struct context *c, const char 
*extra,
 struct gc_arena gc = gc_new();
 if ((proto & IV_PROTO_AUTH_PENDING_KW) == 0)
 {
-send_control_channel_string(c, "AUTH_PENDING", D_PUSH);
+send_control_channel_string_dowork(tls_multi, "AUTH_PENDING", D_PUSH);
 }
 else
 {
@@ -395,7 +394,7 @@ send_auth_pending_messages(struct context *c, const char 
*extra,
 struct buffer buf = alloc_buf_gc(len, );
 buf_printf(, auth_pre);
 buf_printf(, "%u", timeout);
-send_control_channel_string(c, BSTR(), D_PUSH);
+send_control_channel_string_dowork(tls_multi, BSTR(), D_PUSH);
 }
 
 size_t len = strlen(extra) + 1 + sizeof(info_pre);
@@ -408,7 +407,7 @@ send_auth_pending_messages(struct context *c, const char 
*extra,
 struct buffer buf = alloc_buf_gc(len, );
 buf_printf(, info_pre);
 buf_printf(, "%s", extra);
-send_control_channel_string(c, BSTR(), D_PUSH);
+send_control_channel_string_dowork(tls_multi, BSTR(), D_PUSH);
 
 ks->auth_deferred_expire = now + timeout;
 
diff --git 

[Openvpn-devel] [PATCH v2 10/11] Implement --client-crresponse script options and plugin interface

2021-01-25 Thread Arne Schwabe
This is allows scripts and pluginsto parse/react to a
CR_RESPONSE message

Patch V2: doc fixes, do not put script under ENABLE_PLUGIN

Signed-off-by: Arne Schwabe 
---
 doc/man-sections/script-options.rst | 28 -
 include/openvpn-plugin.h.in |  7 +++-
 src/openvpn/init.c  |  1 +
 src/openvpn/options.c   | 15 +++
 src/openvpn/options.h   |  1 +
 src/openvpn/push.c  |  4 ++
 src/openvpn/ssl_common.h|  1 +
 src/openvpn/ssl_verify.c| 65 -
 src/openvpn/ssl_verify.h| 23 ++
 9 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 50edd986..1d7118ae 100644
--- a/doc/man-sections/script-options.rst
+++ b/doc/man-sections/script-options.rst
@@ -52,6 +52,11 @@ Script Order of Execution
Executed in ``--mode server`` mode on new client connections, when the
client is still untrusted.
 
+#. ``--client-crresponse``
+
+Execute in ``--mode server`` whenever a client sends a
+:code:`CR_RESPONSE` message
+
 SCRIPT HOOKS
 
 
@@ -72,7 +77,7 @@ SCRIPT HOOKS
   double-quoted and/or escaped using a backslash, and should be separated
   by one or more spaces.
 
-  If ``method`` is set to :code:`via-env`, OpenVPN will call ``script``
+  If ``method`` is set to :code:`via-env`, OpenVPN will call ``cmd``
   with the environmental variables :code:`username` and :code:`password`
   set to the username/password strings provided by the client. *Beware*
   that this method is insecure on some platforms which make the environment
@@ -80,7 +85,7 @@ SCRIPT HOOKS
 
   If ``method`` is set to :code:`via-file`, OpenVPN will write the username
   and password to the first two lines of a temporary file. The filename
-  will be passed as an argument to ``script``, and the file will be
+  will be passed as an argument to ``cmd``, and the file will be
   automatically deleted by OpenVPN after the script returns. The location
   of the temporary file is controlled by the ``--tmp-dir`` option, and
   will default to the current directory if unspecified. For security,
@@ -123,6 +128,25 @@ SCRIPT HOOKS
   For a sample script that performs PAM authentication, see
   :code:`sample-scripts/auth-pam.pl` in the OpenVPN source distribution.
 
+--client-crresponse
+Executed when the client sends a text based challenge response.
+
+Valid syntax:
+::
+
+client-crresponse cmd
+
+  OpenVPN will write the response of the client into a temporary file.
+  The filename will be passed as an argument to ``cmd``, and the file will be
+  automatically deleted by OpenVPN after the script returns.
+
+  The response is passed as is from the client. The script needs to check
+  itself if the input is valid, e.g. if the input is valid base64 encoding.
+
+  The script can either directly write the result of the verification to
+  :code:`auth_control_file or further defer it. See ``--auth-user-pass-verify``
+  for details.
+
 --client-connect cmd
   Run command ``cmd`` on client connection.
 
diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in
index bb561643..62e3c3b7 100644
--- a/include/openvpn-plugin.h.in
+++ b/include/openvpn-plugin.h.in
@@ -84,6 +84,10 @@ extern "C" {
  * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_CLIENT_CONNECT_V2
  * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_LEARN_ADDRESS
  *
+ * The OPENVPN_PLUGIN_CLIENT_CRRESPONSE function is called when the client 
sends
+ * the CR_RESPONSE message, this is *typically* after OPENVPN_PLUGIN_TLS_FINAL
+ * but may also occur much later.
+ *
  * [Client session ensues]
  *
  * For each "TLS soft reset", according to reneg-sec option (or similar):
@@ -131,7 +135,8 @@ extern "C" {
 #define OPENVPN_PLUGIN_ROUTE_PREDOWN12
 #define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER 13
 #define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2  14
-#define OPENVPN_PLUGIN_N15
+#define OPENVPN_PLUGIN_CLIENT_CRRESPONSE15
+#define OPENVPN_PLUGIN_N16
 
 /*
  * Build a mask out of a set of plug-in types.
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index c3493c42..4e753657 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2948,6 +2948,7 @@ do_init_crypto_tls(struct context *c, const unsigned int 
flags)
 
 to.auth_user_pass_verify_script = options->auth_user_pass_verify_script;
 to.auth_user_pass_verify_script_via_file = 
options->auth_user_pass_verify_script_via_file;
+to.client_crresponse_script = options->client_crresponse_script;
 to.tmp_dir = options->tmp_dir;
 if (options->ccd_exclusive)
 {
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index b81137cf..2290bc12 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1284,6 +1284,7 @@ show_p2mp_parms(const struct options *o)
 SHOW_STR(client_connect_script);
  

[Openvpn-devel] [PATCH v2 07/11] Refactor extract_var_peer_info into standalone function and add ssl_util.c

2021-01-25 Thread Arne Schwabe
Our "natural" place for this function would be ssl.c but ssl.c has a lot of
dependencies on all kinds of other compilation units so including ssl.c into
unit tests is near impossible currently. Instead create a new file ssl_util.c
that holds small utility functions like this one.

Patch v2: add newline add the end of sll_util.h and ssl_util.c

Signed-off-by: Arne Schwabe 
---
 src/openvpn/Makefile.am  |  1 +
 src/openvpn/openvpn.vcxproj  |  2 +
 src/openvpn/openvpn.vcxproj.filters  |  6 +++
 src/openvpn/ssl.c|  2 +-
 src/openvpn/ssl_ncp.c| 20 ++
 src/openvpn/ssl_util.c   | 59 
 src/openvpn/ssl_util.h   | 49 +++
 src/openvpn/ssl_verify.c |  1 +
 tests/unit_tests/openvpn/Makefile.am |  3 +-
 9 files changed, 125 insertions(+), 18 deletions(-)
 create mode 100644 src/openvpn/ssl_util.c
 create mode 100644 src/openvpn/ssl_util.h

diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am
index 37b002c6..ec84929b 100644
--- a/src/openvpn/Makefile.am
+++ b/src/openvpn/Makefile.am
@@ -119,6 +119,7 @@ openvpn_SOURCES = \
ssl_openssl.c ssl_openssl.h \
ssl_mbedtls.c ssl_mbedtls.h \
ssl_ncp.c ssl_ncp.h \
+   ssl_util.c ssl_util.h \
ssl_common.h \
ssl_verify.c ssl_verify.h ssl_verify_backend.h \
ssl_verify_openssl.c ssl_verify_openssl.h \
diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj
index 3863854b..cf31940c 100644
--- a/src/openvpn/openvpn.vcxproj
+++ b/src/openvpn/openvpn.vcxproj
@@ -212,6 +212,7 @@
 
 
 
+
 
 
 
@@ -300,6 +301,7 @@
 
 
 
+
 
 
 
diff --git a/src/openvpn/openvpn.vcxproj.filters 
b/src/openvpn/openvpn.vcxproj.filters
index cf5748c7..e8aed2c5 100644
--- a/src/openvpn/openvpn.vcxproj.filters
+++ b/src/openvpn/openvpn.vcxproj.filters
@@ -243,6 +243,9 @@
 
   Source Files
 
+
+  Source Files
+
   
   
 
@@ -509,6 +512,9 @@
 
   Header Files
 
+
+  Header Files
+
   
   
 
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 14c8116f..f59b409f 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -4201,4 +4201,4 @@ void
 ssl_clean_user_pass(void)
 {
 purge_user_pass(_user_pass, false);
-}
+}
\ No newline at end of file
diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c
index 45bddbe0..f02a3103 100644
--- a/src/openvpn/ssl_ncp.c
+++ b/src/openvpn/ssl_ncp.c
@@ -48,6 +48,7 @@
 #include "common.h"
 
 #include "ssl_ncp.h"
+#include "ssl_util.h"
 #include "openvpn.h"
 
 /**
@@ -195,23 +196,10 @@ const char *
 tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc)
 {
 /* Check if the peer sends the IV_CIPHERS list */
-const char *ncp_ciphers_start;
-if (peer_info && (ncp_ciphers_start = strstr(peer_info, "IV_CIPHERS=")))
+const char *iv_ciphers = extract_var_peer_info(peer_info,"IV_CIPHERS=", 
gc);
+if (iv_ciphers)
 {
-ncp_ciphers_start += strlen("IV_CIPHERS=");
-const char *ncp_ciphers_end = strstr(ncp_ciphers_start, "\n");
-if (!ncp_ciphers_end)
-{
-/* IV_CIPHERS is at end of the peer_info list and no '\n'
- * follows */
-ncp_ciphers_end = ncp_ciphers_start + strlen(ncp_ciphers_start);
-}
-
-char *ncp_ciphers_peer = string_alloc(ncp_ciphers_start, gc);
-/* NULL terminate the copy at the right position */
-ncp_ciphers_peer[ncp_ciphers_end - ncp_ciphers_start] = '\0';
-return ncp_ciphers_peer;
-
+return iv_ciphers;
 }
 else if (tls_peer_info_ncp_ver(peer_info)>=2)
 {
diff --git a/src/openvpn/ssl_util.c b/src/openvpn/ssl_util.c
new file mode 100644
index ..d6ead462
--- /dev/null
+++ b/src/openvpn/ssl_util.c
@@ -0,0 +1,59 @@
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ *  Copyright (C) 2002-2020 OpenVPN Inc 
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#elif 

[Openvpn-devel] [PATCH v2 03/11] Implement server side of AUTH_PENDING with extending timeout

2021-01-25 Thread Arne Schwabe
Patch V2: eliminate parse_kid function, fix style

Signed-off-by: Arne Schwabe 
---
 src/openvpn/manage.c | 23 +
 src/openvpn/manage.h |  3 ++-
 src/openvpn/multi.c  | 27 +++-
 src/openvpn/push.c   | 55 +---
 src/openvpn/push.h   | 10 
 src/openvpn/ssl.c|  1 +
 src/openvpn/ssl_common.h |  1 +
 7 files changed, 81 insertions(+), 39 deletions(-)

diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index ed9dde1e..98a9a4cc 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -972,15 +972,15 @@ parse_cid(const char *str, unsigned long *cid)
 }
 
 static bool
-parse_kid(const char *str, unsigned int *kid)
+parse_uint(const char *str, const char* what, unsigned int *uint)
 {
-if (sscanf(str, "%u", kid) == 1)
+if (sscanf(str, "%u", uint) == 1)
 {
 return true;
 }
 else
 {
-msg(M_CLIENT, "ERROR: cannot parse KID");
+msg(M_CLIENT, "ERROR: cannot parse %s", what);
 return false;
 }
 }
@@ -995,15 +995,18 @@ parse_kid(const char *str, unsigned int *kid)
  *  the information of the additional steps
  */
 static void
-man_client_pending_auth(struct management *man, const char *cid_str, const 
char *extra)
+man_client_pending_auth(struct management *man, const char *cid_str,
+const char *extra, const char *timeout_str)
 {
 unsigned long cid = 0;
-if (parse_cid(cid_str, ))
+unsigned int timeout = 0;
+if (parse_cid(cid_str, )
+&& parse_uint(timeout_str, "TIMEOUT", ))
 {
 if (man->persist.callback.client_pending_auth)
 {
 bool ret = (*man->persist.callback.client_pending_auth)
-   (man->persist.callback.arg, cid, extra);
+   (man->persist.callback.arg, cid, extra, timeout);
 
 if (ret)
 {
@@ -1029,7 +1032,7 @@ man_client_auth(struct management *man, const char 
*cid_str, const char *kid_str
 mc->in_extra_cid = 0;
 mc->in_extra_kid = 0;
 if (parse_cid(cid_str, >in_extra_cid)
-&& parse_kid(kid_str, >in_extra_kid))
+&& parse_uint(kid_str, "KID", >in_extra_kid))
 {
 mc->in_extra_cmd = IEC_CLIENT_AUTH;
 in_extra_reset(mc, IER_NEW);
@@ -1045,7 +1048,7 @@ man_client_deny(struct management *man, const char 
*cid_str, const char *kid_str
 {
 unsigned long cid = 0;
 unsigned int kid = 0;
-if (parse_cid(cid_str, ) && parse_kid(kid_str, ))
+if (parse_cid(cid_str, ) && parse_uint(kid_str, "KID", ))
 {
 if (man->persist.callback.client_auth)
 {
@@ -1560,9 +1563,9 @@ man_dispatch_command(struct management *man, struct 
status_output *so, const cha
 }
 else if (streq(p[0], "client-pending-auth"))
 {
-if (man_need(man, p, 2, 0))
+if (man_need(man, p, 3, 0))
 {
-man_client_pending_auth(man, p[1], p[2]);
+man_client_pending_auth(man, p[1], p[2], p[3]);
 }
 }
 #ifdef MANAGEMENT_PF
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index a3364644..aaa3b848 100644
--- a/src/openvpn/manage.h
+++ b/src/openvpn/manage.h
@@ -173,7 +173,8 @@ struct management_callback
  struct buffer_list *cc_config); /* ownership 
transferred */
 bool (*client_pending_auth) (void *arg,
  const unsigned long cid,
- const char *url);
+ const char *extra,
+ unsigned int timeout);
 char *(*get_peer_info) (void *arg, const unsigned long cid);
 #ifdef MANAGEMENT_PF
 bool (*client_pf)(void *arg,
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index dd713049..ac5d3f5b 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -1768,28 +1768,6 @@ multi_client_connect_setenv(struct multi_context *m,
 gc_free();
 }
 
-/**
- * Extracts the IV_PROTO variable and returns its value or 0
- * if it cannot be extracted.
- *
- */
-static unsigned int
-extract_iv_proto(const char *peer_info)
-{
-
-const char *optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL;
-if (optstr)
-{
-int proto = 0;
-int r = sscanf(optstr, "IV_PROTO=%d", );
-if (r == 1 && proto > 0)
-{
-return proto;
-}
-}
-return 0;
-}
-
 /**
  * Calculates the options that depend on the client capabilities
  * based on local options and available peer info
@@ -3918,14 +3896,15 @@ management_kill_by_cid(void *arg, const unsigned long 
cid, const char *kill_msg)
 static bool
 management_client_pending_auth(void *arg,
const unsigned long cid,
-   const char *extra)
+   const char *extra,
+   unsigned int timeout)
 {
 struct multi_context *m = (struct 

[Openvpn-devel] [PATCH v2 11/11] Add example script demonstrating TOTP via auth-pending

2021-01-25 Thread Arne Schwabe
Signed-off-by: Arne Schwabe 
---
 Changes.rst |   9 +++
 doc/man-sections/script-options.rst |   3 +
 sample/sample-scripts/totpauth.py   | 107 
 3 files changed, 119 insertions(+)
 create mode 100755 sample/sample-scripts/totpauth.py

diff --git a/Changes.rst b/Changes.rst
index 188bd8ab..d64c6d83 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -19,6 +19,15 @@ Pending auth support for plugins and scripts
 be used to parse a client response to a ``CR_TEXT`` two factor challenge.
 
 See ``sample/sample-scripts/totpauth.py`` for an example.
+<<< HEAD
+===
+
+Deprecated features
+---
+``inetd`` has been removed
+This was a very limited and not-well-tested way to run OpenVPN, on TCP
+and TAP mode only.
+>>> 239e8cfd (Add example script demonstrating TOTP via auth-pending)
 
 
 Overview of changes in 2.5
diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 1d7118ae..05815020 100644
--- a/doc/man-sections/script-options.rst
+++ b/doc/man-sections/script-options.rst
@@ -147,6 +147,9 @@ SCRIPT HOOKS
   :code:`auth_control_file or further defer it. See ``--auth-user-pass-verify``
   for details.
 
+  For a sample script that implement TOTP (RFC 6238) based two-factor
+  authentication, see :code:`sample-scripts/totp.py`.
+
 --client-connect cmd
   Run command ``cmd`` on client connection.
 
diff --git a/sample/sample-scripts/totpauth.py 
b/sample/sample-scripts/totpauth.py
new file mode 100755
index ..95ac3529
--- /dev/null
+++ b/sample/sample-scripts/totpauth.py
@@ -0,0 +1,107 @@
+#! /usr/bin/python3
+# Copyright (c) 2020 OpenVPN Inc 
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in 
all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import sys
+import os
+from base64 import standard_b64decode
+
+import pyotp
+
+import pprint
+
+# Example script demonstrating how to use the auth-pending API in
+# OpenVPN. This script is provided under MIT license to allow easy
+# modification for other purposes.
+#
+# To use this script add the following lines in the openvpn config
+
+# client-crresponse /path/to/totpauth.py 
+# auth-user-pass-verify /path/to/totpauth.py via-file
+# auth-user-pass-optional
+# auth-gen-token
+
+# Note that this script does NOT verify username/password
+# It is only meant for querying additional 2FA when certificates are
+# used to authenticate
+
+secrets = {"styx": "OS6JDNRK2BNUPQVX",
+   "apate": "IXWEMP7SK2QWSHTG"}
+
+
+def main():
+# Get common name and script type from environment
+script_type = os.environ['script_type']
+cn = os.environ['common_name']
+
+if script_type == 'user-pass-verify':
+# signal text based challenge response
+
+if cn in secrets:
+extra = "CR_TEXT:E,R:Please enter your TOTP code!"
+write_auth_pending(300, 'crtext', extra)
+
+# Signal authentication being deferred
+sys.exit(2)
+else:
+# For unkown CN we report failure. Change to 0
+# to allow CNs without secret to auth without 2FA
+sys.exit(1)
+
+elif script_type == 'client-crresponse':
+response = None
+
+# Read the crresponse from the argument file
+# and convert it into text. A failure because of bad user
+# input (e.g. invalid base64) will make the script throw
+# an error and make OpenVPN return AUTH_FAILED
+with open(sys.argv[1], 'r') as crinput:
+response = crinput.read()
+response = standard_b64decode(response)
+response = response.decode().strip()
+
+if cn not in secrets:
+write_auth_control(1)
+return
+
+totp = pyotp.TOTP(secrets[cn])
+
+# Check if the code is valid (and also allow code +/-1)
+if totp.verify(response, valid_window=1):
+write_auth_control(1)
+else:
+write_auth_control(0)
+else:
+

[Openvpn-devel] [PATCH v2 02/11] Implement client side handling of AUTH_PENDING message

2021-01-25 Thread Arne Schwabe
This allows a client to extend the timeout of pull-request response
while waiting for the user to complete a pending authentication. A
timeout of 60s for a normal authentication might still works for a
simple 2FA (but still challenging). With a sophisticated (or overly
complicated) web based authentication 60s are quite short.

To avoid not detecting network problem in this phase, we use the
constant sending of PUSH_REQUEST/AUTH_PENDING as keepalive signal
and still timeout the session after the handshake window time.

patch v2: typo fixes, invert if for sscanf

Signed-off-by: Arne Schwabe 
---
 doc/man-sections/server-options.rst |  4 ++
 doc/management-notes.txt| 39 +
 src/openvpn/forward.c   | 11 -
 src/openvpn/integer.h   | 25 +++
 src/openvpn/push.c  | 68 -
 src/openvpn/push.h  |  9 
 src/openvpn/ssl.c   |  3 ++
 src/openvpn/ssl.h   |  3 ++
 src/openvpn/ssl_common.h|  1 +
 9 files changed, 152 insertions(+), 11 deletions(-)

diff --git a/doc/man-sections/server-options.rst 
b/doc/man-sections/server-options.rst
index 5a689452..271c54d0 100644
--- a/doc/man-sections/server-options.rst
+++ b/doc/man-sections/server-options.rst
@@ -473,6 +473,10 @@ fast hardware. SSL/TLS authentication must be used in this 
mode.
 - bit 1: The peer supports peer-id floating mechanism
 - bit 2: The client expects a push-reply and the server may
   send this reply without waiting for a push-request first.
+- bit 3: The client is capable of doing key derivation using
+  RFC5705 key material exporter.
+- bit 4: The client is capable of accepting additional arguments
+  to the `AUTH_PENDING` message.
 
   :code:`IV_NCP=2`
 Negotiable ciphers, client supports ``--cipher`` pushed by
diff --git a/doc/management-notes.txt b/doc/management-notes.txt
index 50f0f567..3aff6eb6 100644
--- a/doc/management-notes.txt
+++ b/doc/management-notes.txt
@@ -610,14 +610,30 @@ to signal a pending authenticating to the client. A 
pending auth means
 that the connecting requires extra authentication like a one time
 password or doing a single sign one via web.
 
-client-pending-auth {CID} {EXTRA}
-
-The server will send AUTH_PENDING and INFO_PRE,{EXTRA} to the client.
-The client is expected to inform the user that authentication is pending and
-display the extra information. For the format of EXTRA see below
-For the OpenVPN server this is stateless operation and needs to be
-followed by a client-deny/client-auth[-nt] command (that is the result of the
-out of band authentication).
+client-pending-auth {CID} {EXTRA} {TIMEOUT}
+
+The server will send AUTH_PENDING and INFO_PRE,{EXTRA} to the client. If the
+client supports accepting keywords to AUTH_PENDING (announced via IV_PROTO),
+TIMEOUT parameter will be also be announced to the client to allow it to modify
+its own timeout. The client is expected to inform the user that authentication
+is pending and display the extra information and also show the user the
+remaining time to complete the auth if applicable.
+
+Receiving an AUTH_PENDING message will make the client change its timeout to
+the timeout proposed by the server, even if the timeout is shorter.
+If the client does not receive a packet from the server for hand-window the
+connection times out regardless of the timeout. This ensures that the 
connection
+still times out relatively quickly in case of network problems. The client will
+continously send PULL_REQUEST messages to the server until the timeout is 
reached.
+This message also triggers an ACK message from the server that resets the
+hand-window based timeout.
+
+Both client and server limit the maximum timeout to the smaller value of half 
the
+--tls-reneg minimum time and --hand-window time (defaults to 60s).
+
+For the format of EXTRA see below. For the OpenVPN server this is a stateless
+operation and needs to be followed by a client-deny/client-auth[-nt] command
+(that is the result of the out of band authentication).
 
 Before issuing a client-pending-auth to a client instead of a
 client-auth/client-deny, the server should check the IV_SSO
@@ -630,7 +646,7 @@ set
 setenv IV_SSO openurl,crtext
 
 The variable name IV_SSO is historic as AUTH_PENDING was first used
-to signal single sign on support. To keep compatiblity with existing
+to signal single sign on support. To keep compatibility with existing
 implementations the name IV_SSO is kept in lieu of a better name.
 
 openurl
@@ -646,6 +662,11 @@ The space in a control message is limited, so this url 
should be kept
 short to avoid issues. If a loger url is required a URL that redirects
 to the longer URL should be sent instead.
 
+A complete documentation how URLs should be handled on the client is available
+in the openvpn3 repository:
+
+https://github.com/OpenVPN/openvpn3/blob/master/doc/webauth.md

[Openvpn-devel] [PATCH v2 01/11] Change pull request timeout use a timeout rather than a number

2021-01-25 Thread Arne Schwabe
This commit changes the count n_sent_push_requests to time_t based
push_request_timeout. This is more in line to our other timeouts which
are also time based instead of number retries based.

This does not change the behaviour but it prepares allowing to extend
the pull request timeout during a pending authentication. As a user
visible change we print the the time we waited for a timeout instead

Also update the man page to actually document that hand-window controls
this timeout.

Patch V2: grammar fix in manual page

Signed-off-by: Arne Schwabe 
---
 doc/man-sections/tls-options.rst | 3 +++
 src/openvpn/forward.c| 1 +
 src/openvpn/openvpn.h| 2 +-
 src/openvpn/push.c   | 9 ++---
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/doc/man-sections/tls-options.rst b/doc/man-sections/tls-options.rst
index 28cf6f1e..e13fb3c8 100644
--- a/doc/man-sections/tls-options.rst
+++ b/doc/man-sections/tls-options.rst
@@ -200,6 +200,9 @@ certificates and keys: https://github.com/OpenVPN/easy-rsa
   will still use our expiring key for up to ``--tran-window`` seconds to
   maintain continuity of transmission of tunnel data.
 
+  The ``--hand-window`` parameter also controls the amount of time that
+  the OpenVPN client repeats the pull request until it times out.
+
 --key file
   Local peer's private key in .pem format. Use the private key which was
   generated when you built your peer's certificate (see ``--cert file``
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 67615a6b..76f5a032 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -299,6 +299,7 @@ check_connection_established(struct context *c)
 }
 #endif
 /* fire up push request right away (already 1s delayed) */
+c->c2.push_request_timeout = now + c->options.handshake_window;
 event_timeout_init(>c2.push_request_interval, 0, now);
 reset_coarse_timers(c);
 }
diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h
index 4ca89ba9..e9bc7dad 100644
--- a/src/openvpn/openvpn.h
+++ b/src/openvpn/openvpn.h
@@ -462,7 +462,7 @@ struct context_2
 enum client_connect_status context_auth;
 
 struct event_timeout push_request_interval;
-int n_sent_push_requests;
+time_t push_request_timeout;
 bool did_pre_pull_restore;
 
 /* hash of pulled options, so we can compare when options change */
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index 26a6201f..fb6b9d17 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -369,14 +369,17 @@ cleanup:
 bool
 send_push_request(struct context *c)
 {
-const int max_push_requests = c->options.handshake_window / 
PUSH_REQUEST_INTERVAL;
-if (++c->c2.n_sent_push_requests <= max_push_requests)
+struct tls_session *session = >c2.tls_multi->session[TM_ACTIVE];
+struct key_state *ks = >key[KS_PRIMARY];
+
+if (c->c2.push_request_timeout > now)
 {
 return send_control_channel_string(c, "PUSH_REQUEST", D_PUSH);
 }
 else
 {
-msg(D_STREAM_ERRORS, "No reply from server after sending %d push 
requests", max_push_requests);
+msg(D_STREAM_ERRORS, "No reply from server to push requests in %ds",
+(int)(now - ks->established));
 c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed 
connection reset */
 c->sig->signal_text = "no-push-reply";
 return false;
-- 
2.30.0



___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH v2 08/11] Allow pending auth to be send from a auth plugin

2021-01-25 Thread Arne Schwabe
Patch v2: removed change that slipped into this patch and belongs
  into the next

Signed-off-by: Arne Schwabe 
---
 doc/man-sections/generic-options.rst |   3 +-
 include/openvpn-plugin.h.in  |   8 ++
 src/openvpn/ssl.c|   2 +-
 src/openvpn/ssl_common.h |   1 +
 src/openvpn/ssl_verify.c | 161 +--
 src/openvpn/ssl_verify.h |   2 +-
 6 files changed, 162 insertions(+), 15 deletions(-)

diff --git a/doc/man-sections/generic-options.rst 
b/doc/man-sections/generic-options.rst
index d5f08839..32eeda68 100644
--- a/doc/man-sections/generic-options.rst
+++ b/doc/man-sections/generic-options.rst
@@ -409,7 +409,8 @@ which mode OpenVPN is configured as.
 
   * :code:`OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY` plug-in hooks returns
 success/failure via :code:`auth_control_file` when using deferred auth
-method
+method and pending authentification via :code:`pending_auth_file`.
+
 
   * :code:`OPENVPN_PLUGIN_ENABLE_PF` plugin hook to pass filtering rules
 via ``pf_file``
diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in
index 64b20886..bb561643 100644
--- a/include/openvpn-plugin.h.in
+++ b/include/openvpn-plugin.h.in
@@ -567,6 +567,14 @@ OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t 
OPENVPN_PLUGIN_FUNC(openvpn_plugin_op
  * auth_control_file/client_connect_deferred_file
  * in the environmental variable list (envp).
  *
+ * Additionally the auth_pending_file can be written, which causes the openvpn
+ * server to send a pending auth request to the client. See doc/management.txt
+ * for more details on this authentication mechanism. The format of the
+ * auth_pending_file is
+ * line 1: timeout in seconds
+ * line 2: Pending auth method the client needs to support (e.g. openurl)
+ * line 3: EXTRA (e.g. OPEN_URL:http://www.example.com)
+ *
  * In addition the OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER and
  * OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2 are called when OpenVPN tries to
  * get the deferred result. For a V2 call implementing this function is
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index f59b409f..b8e77f0e 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -993,7 +993,7 @@ key_state_free(struct key_state *ks, bool clear)
 packet_id_free(>crypto_options.packet_id);
 
 #ifdef PLUGIN_DEF_AUTH
-key_state_rm_auth_control_file(ks);
+key_state_rm_auth_control_files(ks);
 #endif
 
 if (clear)
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index bf7f9ba3..b493cbb7 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -215,6 +215,7 @@ struct key_state
 unsigned int auth_control_status;
 time_t acf_last_mod;
 char *auth_control_file;
+char *auth_pending_file;
 };
 
 /** Control channel wrapping (--tls-auth/--tls-crypt) context */
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index e0ef399f..b9647c1a 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -865,13 +865,129 @@ man_def_auth_test(const struct key_state *ks)
 }
 #endif /* ifdef ENABLE_MANAGEMENT */
 
+/**
+ *  Removes auth_pending file from the file system
+ *  and key_state structure
+ */
+static void
+key_state_rm_auth_pending_file(struct key_state *ks)
+{
+if (ks && ks->auth_pending_file)
+{
+platform_unlink(ks->auth_pending_file);
+free(ks->auth_pending_file);
+ks->auth_pending_file = NULL;
+}
+}
 
-/*
- * auth_control_file functions
+/**
+ * Check peer_info if the client supports the requested pending auth method
+ */
+static bool
+check_auth_pending_method(const char *peer_info, const char *method)
+{
+struct gc_arena gc = gc_new();
+
+char *iv_sso = extract_var_peer_info(peer_info, "IV_SSO=", );
+if (!iv_sso)
+{
+gc_free();
+return false;
+}
+
+const char *client_method = strtok(iv_sso, ",");
+bool supported = false;
+
+while (client_method)
+{
+if (0 == strcmp(client_method, method))
+{
+supported = true;
+break;
+}
+client_method = strtok(NULL, ":");
+}
+
+gc_free();
+return supported;
+}
+
+/**
+ *  Checks if the deferred state should also send auth pending
+ *  request to the client. Also removes the auth_pending control file
+ *
+ *  @returns true   if file was either processed sucessfully or did not
+ *  exist at all
+ *  @returns false  The file had an invlaid format or another error occured
  */
+static bool
+key_state_check_auth_pending_file(struct key_state *ks,
+  struct tls_multi *multi)
+{
+bool ret = true;
+if (ks && ks->auth_pending_file)
+{
+struct buffer_list *lines = buffer_list_file(ks->auth_pending_file,
+ 1024);
+if (lines && lines->head)
+{
+/* Must have at least three lines. further lines are 

[Openvpn-devel] [PATCH v2 09/11] Implement deferred auth for scripts

2021-01-25 Thread Arne Schwabe
This patch also refactors the if condition that checks the result of
the authentication since that has become quite unreadable. It renames
s1/s2 and extracts some parts of the condition into individual variables
to make the condition better understandle

Patch V2: add refactoring of the if condition

Signed-off-by: Arne Schwabe 
---
 Changes.rst | 12 
 doc/man-sections/script-options.rst | 14 -
 src/openvpn/ssl.c   |  2 -
 src/openvpn/ssl_verify.c| 86 +
 4 files changed, 89 insertions(+), 25 deletions(-)

diff --git a/Changes.rst b/Changes.rst
index 2a2829e7..188bd8ab 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -9,6 +9,18 @@ Keying Material Exporters (RFC 5705) based key generation
 the RFC5705 based key material generation to the current custom
 OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+.
 
+Deferred auth support for scripts
+The ``--auth-user-pass-verify`` script supports now deferred 
authentication.
+
+Pending auth support for plugins and scripts
+Both auth plugin and script can now signal pending authentication to
+the client when using deferred authentication. The new 
``client-crresponse``
+script option and ``OPENVPN_PLUGIN_CLIENT_CRRESPONSE`` plugin function can
+be used to parse a client response to a ``CR_TEXT`` two factor challenge.
+
+See ``sample/sample-scripts/totpauth.py`` for an example.
+
+
 Overview of changes in 2.5
 ==
 
diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 03b3dd77..50edd986 100644
--- a/doc/man-sections/script-options.rst
+++ b/doc/man-sections/script-options.rst
@@ -90,7 +90,19 @@ SCRIPT HOOKS
 
   The script should examine the username and password, returning a success
   exit code (:code:`0`) if the client's authentication request is to be
-  accepted, or a failure code (:code:`1`) to reject the client.
+  accepted, a failure code (:code:`1`) to reject the client, or a that
+  the authentication is deferred (:code:`2`). If the authentication is
+  deferred, the script must fork/start a background or another non-blocking
+  operation to continue the authentication in the background. When finshing
+  the authentication, a :code:`1` or :code:`0` must be written to the
+  file specified by the :code:`auth_control_file`.
+
+  When deferred authentication is in use, the script can also request
+  pending authentication by writing to the file specified by the
+  :code:`auth_pending_file`. The first line must be the timeout in
+  seconds and the second line the EXTRA as documented in the
+  ``client-pending-auth`` section of `doc/management.txt`.
+
 
   This directive is designed to enable a plugin-style interface for
   extending OpenVPN's authentication capabilities.
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index b8e77f0e..699b7347 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -992,9 +992,7 @@ key_state_free(struct key_state *ks, bool clear)
 
 packet_id_free(>crypto_options.packet_id);
 
-#ifdef PLUGIN_DEF_AUTH
 key_state_rm_auth_control_files(ks);
-#endif
 
 if (clear)
 {
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index b9647c1a..fc9f1d2e 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -1188,14 +1188,14 @@ tls_authenticate_key(struct tls_multi *multi, const 
unsigned int mda_key_id, con
 /*
  * Verify the user name and password using a script
  */
-static bool
+static int
 verify_user_pass_script(struct tls_session *session, struct tls_multi *multi,
 const struct user_pass *up)
 {
 struct gc_arena gc = gc_new();
 struct argv argv = argv_new();
 const char *tmp_file = "";
-bool ret = false;
+int retval = OPENVPN_PLUGIN_FUNC_ERROR;
 
 /* Set environmental variables prior to calling script */
 setenv_str(session->opt->es, "script_type", "user-pass-verify");
@@ -1223,25 +1223,61 @@ verify_user_pass_script(struct tls_session *session, 
struct tls_multi *multi,
 /* pass temp file name to script */
 argv_printf_cat(, "%s", tmp_file);
 }
-else
-{
-msg(D_TLS_ERRORS, "TLS Auth Error: could not create write "
-"username/password to temp file");
-}
 }
 else
 {
+setenv_str(session->opt->es, "username", up->username);
 setenv_str(session->opt->es, "password", up->password);
 }
 
+/* generate filename for deferred auth control file */
+if (!key_state_gen_auth_control_files(>key[KS_PRIMARY],
+ session->opt))
+{
+msg(D_TLS_ERRORS, "TLS Auth Error (%s): "
+  "could not create deferred auth control file", 
__func__);
+return OPENVPN_PLUGIN_FUNC_ERROR;
+}
+
 /* call command */
-ret = openvpn_run_script(, session->opt->es, 0,
-

[Openvpn-devel] [PATCH v2 06/11] Add S_EXITCODE flag for openvpn_run_script to report exit code

2021-01-25 Thread Arne Schwabe
This allows to use script that have more than just fail/sucess but
also deferred as status

Patch v2: minor style fixes, improve doxygen comments

Signed-off-by: Arne Schwabe 
---
 src/openvpn/platform.c| 34 ++
 src/openvpn/platform.h|  5 -
 src/openvpn/run_command.c | 25 -
 src/openvpn/run_command.h | 15 +++
 4 files changed, 65 insertions(+), 14 deletions(-)

diff --git a/src/openvpn/platform.c b/src/openvpn/platform.c
index 53d07f9c..ef688c23 100644
--- a/src/openvpn/platform.c
+++ b/src/openvpn/platform.c
@@ -240,6 +240,40 @@ platform_system_ok(int stat)
 #endif
 }
 
+#ifdef _WIN32
+int
+platform_ret_code(int stat)
+{
+if (stat >= 0 && stat < 255)
+{
+return stat;
+}
+else
+{
+return -1;
+}
+}
+#else
+int
+platform_ret_code(int stat)
+{
+if (!WIFEXITED(stat) || stat == -1)
+{
+return -1;
+}
+
+int status = WEXITSTATUS(stat);
+if (status >= 0 && status < 255)
+{
+return status;
+}
+else
+{
+return -1;
+}
+}
+#endif
+
 int
 platform_access(const char *path, int mode)
 {
diff --git a/src/openvpn/platform.h b/src/openvpn/platform.h
index 091fc9c4..01f3200c 100644
--- a/src/openvpn/platform.h
+++ b/src/openvpn/platform.h
@@ -119,9 +119,12 @@ void platform_mlockall(bool print_msg);  /* Disable paging 
*/
 
 int platform_chdir(const char *dir);
 
-/* interpret the status code returned by execve() */
+/** interpret the status code returned by execve() */
 bool platform_system_ok(int stat);
 
+/** Return an exit code if valid and between 0 and 255, -1 otherwise */
+int platform_ret_code(int stat);
+
 int platform_access(const char *path, int mode);
 
 void platform_sleep_milliseconds(unsigned int n);
diff --git a/src/openvpn/run_command.c b/src/openvpn/run_command.c
index 4c4adf97..8f99ec88 100644
--- a/src/openvpn/run_command.c
+++ b/src/openvpn/run_command.c
@@ -191,27 +191,34 @@ openvpn_execve(const struct argv *a, const struct env_set 
*es, const unsigned in
 /*
  * Wrapper around openvpn_execve
  */
-bool
+int
 openvpn_execve_check(const struct argv *a, const struct env_set *es, const 
unsigned int flags, const char *error_message)
 {
 struct gc_arena gc = gc_new();
 const int stat = openvpn_execve(a, es, flags);
 int ret = false;
 
-if (platform_system_ok(stat))
+if (flags & S_EXITCODE)
+{
+ret = platform_ret_code(stat);
+if (ret != -1) {
+goto done;
+}
+}
+else if (platform_system_ok(stat))
 {
 ret = true;
+goto done;
 }
-else
+if (error_message)
 {
-if (error_message)
-{
-msg(((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s",
-error_message,
-system_error_message(stat, ));
-}
+msg(((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s",
+error_message,
+system_error_message(stat, ));
 }
+done:
 gc_free();
+
 return ret;
 }
 
diff --git a/src/openvpn/run_command.h b/src/openvpn/run_command.h
index 7ccb13c6..da33d92b 100644
--- a/src/openvpn/run_command.h
+++ b/src/openvpn/run_command.h
@@ -42,18 +42,25 @@ int script_security(void);
 void script_security_set(int level);
 
 /* openvpn_execve flags */
-#define S_SCRIPT (1<<0)
-#define S_FATAL  (1<<1)
+#define S_SCRIPT(1<<0)
+#define S_FATAL (1<<1)
+/** Instead of returning 1/0 for success/fail,
+ * return exit code when between 0 and 255 and -1 otherwise */
+#define S_EXITCODE  (1<<2)
 
 /* wrapper around the execve() call */
 int openvpn_popen(const struct argv *a,  const struct env_set *es);
 
 bool openvpn_execve_allowed(const unsigned int flags);
 
-bool openvpn_execve_check(const struct argv *a, const struct env_set *es,
+int openvpn_execve_check(const struct argv *a, const struct env_set *es,
   const unsigned int flags, const char *error_message);
 
-static inline bool
+/**
+ * Will run a script and return the exit code of the script if between
+ * 0 and 255, -1 otherwise
+ */
+static inline int
 openvpn_run_script(const struct argv *a, const struct env_set *es,
const unsigned int flags, const char *hook)
 {
-- 
2.30.0



___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH v2] Allow running a default configuration with TLS libraries without BF-CBC

2021-01-25 Thread Arne Schwabe
Modern TLS libraries might drop Blowfish by default or distributions
might disable Blowfish in OpenSSL/mbed TLS. We still signal OCC
options with BF-CBC compatible strings. To avoid requiring BF-CBC
for this, special this one usage of BF-CBC enough to avoid a hard
requirement on Blowfish in the default configuration.

Signed-off-by: Arne Schwabe 

Patch v2: add more clarifying comment, do not warn about OCC only insecure
  ciphers, code improvements

Signed-off-by: Arne Schwabe 
---
 src/openvpn/init.c| 32 ++
 src/openvpn/options.c | 46 +--
 2 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index c3493c42..df0c7ebc 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2770,14 +2770,30 @@ do_init_crypto_tls_c1(struct context *c)
 #endif /* if P2MP */
 }
 
-/* Do not warn if we only have BF-CBC in options->ciphername
- * because it is still the default cipher */
-bool warn = !streq(options->ciphername, "BF-CBC")
- || options->enable_ncp_fallback;
-/* Get cipher & hash algorithms */
-init_key_type(>c1.ks.key_type, options->ciphername, 
options->authname,
-  options->keysize, true, warn);
-
+   /*
+* BF-CBC is allowed to be used only when explicitly configured
+* as NCP-fallback or when NCP has been disabled.
+* In all other cases don't attempt to initialize BF-CBC as it
+* may not even be supported by the underlying SSL library.
+*
+* Therefore, the key structure has to be initialized when:
+* - any non-BF-CBC cipher was selected; or
+* - BF-CBC is selected and NCP is disabled (explicit request to
+*   use the BF-CBC cipher); or
+* - BF-CBC is selected, NCP is enabled and fallback is enabled
+*   (BF-CBC will be the fallback).
+*
+* Note that BF-CBC will still be part of the OCC string to retain
+* backwards compatibility with older clients.
+*/
+if (!streq(options->ciphername, "BF-CBC") || !options->ncp_enabled
+|| options->enable_ncp_fallback)
+{
+/* Do not warn if the if the cipher is used only in OCC */
+bool warn = !options->ncp_enabled || options->enable_ncp_fallback;
+init_key_type(>c1.ks.key_type, options->ciphername, 
options->authname,
+  options->keysize, true, warn);
+}
 /* Initialize PRNG with config-specified digest */
 prng_init(options->prng_hash, options->prng_nonce_secret_len);
 
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index b81137cf..d52057cc 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -3664,9 +3664,29 @@ calc_options_string_link_mtu(const struct options *o, 
const struct frame *frame)
 {
 struct frame fake_frame = *frame;
 struct key_type fake_kt;
-init_key_type(_kt, o->ciphername, o->authname, o->keysize, true,
-  false);
+
 frame_remove_from_extra_frame(_frame, crypto_max_overhead());
+
+
+/* o->ciphername might be BF-CBC even though the underlying SSL library
+ * does not support it. For this reason we workaround this corner case
+ * by pretending to have no encryption enabled and by manually adding
+ * the required packet overhead to the MTU computation.
+ */
+const char* ciphername = o->ciphername;
+
+if (strcmp(o->ciphername, "BF-CBC") == 0)
+{
+/* none has no overhead, so use this to later add only --auth
+ * overhead */
+
+/* overhead of BF-CBC: 64 bit block size, 64 bit IV size */
+frame_add_to_extra_frame(_frame, 64/8 + 64/8);
+}
+
+init_key_type(_kt, ciphername, o->authname, o->keysize, true,
+  false);
+
 crypto_adjust_frame_parameters(_frame, _kt, o->replay,
cipher_kt_mode_ofb_cfb(fake_kt.cipher));
 frame_finalize(_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
@@ -3836,18 +3856,32 @@ options_string(const struct options *o,
+ (TLS_SERVER == true)
<= 1);
 
-init_key_type(, o->ciphername, o->authname, o->keysize, true,
-  false);
+/* Skip resolving BF-CBC to allow SSL libraries without BF-CBC
+ * to work here in the default configuration */
+const char *ciphername = o->ciphername;
+int keysize;
+
+if (strcmp(o->ciphername, "BF-CBC") == 0) {
+init_key_type(, "none", o->authname, o->keysize, true,
+  false);
+ciphername = cipher_kt_name(kt.cipher);
+keysize = 128;
+}
+else
+{
+init_key_type(, o->ciphername, o->authname, o->keysize, true,
+ 

Re: [Openvpn-devel] [PATCH 09/11] Implement deferred auth for scripts

2021-01-25 Thread Arne Schwabe

>> +    int script_ret = openvpn_run_script(, session->opt->es,
>> S_EXITCODE,
>> +    "--auth-user-pass-verify");
> 
> Perhaps move the retval declaration down here, as we're touching it
> anyhow?  This switch() is the first place we use it, unless I'm
> overlooking something.

You are overlooking the 'goto done' code path for error handling.


> 
>> @@ -1499,7 +1534,11 @@ verify_user_pass(struct user_pass *up, struct
>> tls_multi *multi,
>>   #ifdef PLUGIN_DEF_AUTH
>>    || s1 == OPENVPN_PLUGIN_FUNC_DEFERRED
>>   #endif
>> - ) && s2
>> + ) &&
>> +    ((s2 == OPENVPN_PLUGIN_FUNC_SUCCESS)
>> +#ifdef ENABLE_DEF_AUTH
>> + || s2 ==  OPENVPN_PLUGIN_FUNC_DEFERRED)
>> +#endif
>>   #ifdef MANAGEMENT_DEF_AUTH
>>   && man_def_auth != KMDA_ERROR
>>   #endif
> 
> Yikes!  This if() statement is unreadable.  Since you are doing changes
> here, could we improve this whole logic.  Perhaps using a helper macro
> like this (incorrect code-style, for e-mail readability)
>

This is already the improved version after the connect patches cleaned
it up a bit :P

I really don't like hiding condition behind macros just make them
shorter, I will propose a variant that extracts parts of the condition
into individual booleans.

Arne


___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


Re: [Openvpn-devel] [PATCH 02/11] Implement client side handling of AUTH_PENDING message

2021-01-25 Thread Arne Schwabe
Am 15.01.21 um 14:13 schrieb Lev Stipakov:
> Hi,
> 
> Please not that I got errors applying this patch, so I reviewed
> corresponding commit
> from github 
> (https://github.com/schwabe/openvpn/commit/3901e46127a2db3e6dfb20c44e8d8e30adea58c7).
> 
>> +Receiving a AUTH_PENDING message will make the client change its timeout the
>> +timeout proposed by the server, even if the timeout is shorter.
> 
> Typo.
> 
> 
>>  /*
>>   * min/max functions
>>   */
>> +static inline unsigned int
>> +max_uint(unsigned int x, unsigned int y)
> 
> It is 2021 and we have to write our own min/max :(

Yes. We had a discussion on #openvpn-devel and there seem to be no
(non-float) min/max version in the standard library. The linux kernel
also has a macro for this. This would be min_t(unsigned int, x, y) iirc
in the kernel, so similar to what we do here

Arne


___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel