Re: [Openvpn-devel] [PATCH v6] Implement deferred auth for scripts

2021-04-15 Thread Antonio Quartulli
Hi,

On 07/04/2021 17:49, Arne Schwabe wrote:
> 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
> Patch v4: fix documentation not mentioning method as 2nd line
> Patch v5: fix deferred auth used by both plugin and script not working
> Patch v6: Add missing async inotify for script deferred auth
> 
> Signed-off-by: Arne Schwabe 

Very nice feature! deferred auth made easy! Thanks Arne :)

> ---
>  Changes.rst |  10 +++
>  doc/man-sections/script-options.rst |  14 +++-
>  src/openvpn/multi.c |   6 ++
>  src/openvpn/ssl.c   |   1 +
>  src/openvpn/ssl_common.h|   1 +
>  src/openvpn/ssl_verify.c| 105 
>  6 files changed, 106 insertions(+), 31 deletions(-)
> 
> diff --git a/Changes.rst b/Changes.rst
> index 457dfc07e..9185b55f7 100644
> --- a/Changes.rst
> +++ b/Changes.rst
> @@ -30,6 +30,16 @@ TLS mode with self-signed certificates
>  become optional. This allows for small OpenVPN setups without setting up
>  a PKI with Easy-RSA or similar software.
>  
> +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.
>  
>  Deprecated features
>  ---
> diff --git a/doc/man-sections/script-options.rst 
> b/doc/man-sections/script-options.rst
> index 03b3dd77b..22990f4f4 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

typ0: "or a that" -> "or 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, the required method on the second line (e.g. crtext) and
> +  third line must be 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/multi.c b/src/openvpn/multi.c
> index 7c9500f3e..e5e466631 100644
> --- a/src/openvpn/multi.c
> +++ b/src/openvpn/multi.c
> @@ -2990,6 +2990,12 @@ multi_process_post(struct multi_context *m, struct 
> multi_instance *mi, const uns
>  add_inotify_file_watch(m, mi, m->top.c2.inotify_fd,
> ks->plugin_auth.auth_control_file);
>  }
> +if (ks && ks->script_auth.auth_control_file && was_unauthenticated
> +&& (ks->authenticated == KS_AUTH_DEFERRED))
> +{
> +add_inotify_file_watch(m, mi, m->top.c2.inotify_fd,
> +   ks->script_auth.auth_control_file);
> +}
>  #endif
>  
>  if (!IS_SIG(>context))
> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index d8662d000..b27a78b3d 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c
> @@ -994,6 +994,7 @@ key_state_free(struct key_state *ks, bool clear)
>  packet_id_free(>crypto_options.packet_id);
>  
>  key_state_rm_auth_control_files(>plugin_auth);
> +key_state_rm_auth_control_files(>script_auth);
>  
>  if (clear)
>  {
> diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
> index b2fa44e56..acb815955 100644
> --- a/src/openvpn/ssl_common.h
> +++ b/src/openvpn/ssl_common.h
> @@ -222,6 +222,7 @@ struct key_state
>  time_t acf_last_mod;
>  
>  struct auth_deferred_status plugin_auth;
> +struct auth_deferred_status script_auth;
>  };
>  
>  /** Control channel wrapping 

[Openvpn-devel] [PATCH v6] Implement deferred auth for scripts

2021-04-07 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
Patch v4: fix documentation not mentioning method as 2nd line
Patch v5: fix deferred auth used by both plugin and script not working
Patch v6: Add missing async inotify for script deferred auth

Signed-off-by: Arne Schwabe 
---
 Changes.rst |  10 +++
 doc/man-sections/script-options.rst |  14 +++-
 src/openvpn/multi.c |   6 ++
 src/openvpn/ssl.c   |   1 +
 src/openvpn/ssl_common.h|   1 +
 src/openvpn/ssl_verify.c| 105 
 6 files changed, 106 insertions(+), 31 deletions(-)

diff --git a/Changes.rst b/Changes.rst
index 457dfc07e..9185b55f7 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -30,6 +30,16 @@ TLS mode with self-signed certificates
 become optional. This allows for small OpenVPN setups without setting up
 a PKI with Easy-RSA or similar software.
 
+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.
 
 Deprecated features
 ---
diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 03b3dd77b..22990f4f4 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, the required method on the second line (e.g. crtext) and
+  third line must be 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/multi.c b/src/openvpn/multi.c
index 7c9500f3e..e5e466631 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -2990,6 +2990,12 @@ multi_process_post(struct multi_context *m, struct 
multi_instance *mi, const uns
 add_inotify_file_watch(m, mi, m->top.c2.inotify_fd,
ks->plugin_auth.auth_control_file);
 }
+if (ks && ks->script_auth.auth_control_file && was_unauthenticated
+&& (ks->authenticated == KS_AUTH_DEFERRED))
+{
+add_inotify_file_watch(m, mi, m->top.c2.inotify_fd,
+   ks->script_auth.auth_control_file);
+}
 #endif
 
 if (!IS_SIG(>context))
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index d8662d000..b27a78b3d 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -994,6 +994,7 @@ key_state_free(struct key_state *ks, bool clear)
 packet_id_free(>crypto_options.packet_id);
 
 key_state_rm_auth_control_files(>plugin_auth);
+key_state_rm_auth_control_files(>script_auth);
 
 if (clear)
 {
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index b2fa44e56..acb815955 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -222,6 +222,7 @@ struct key_state
 time_t acf_last_mod;
 
 struct auth_deferred_status plugin_auth;
+struct auth_deferred_status script_auth;
 };
 
 /** Control channel wrapping (--tls-auth/--tls-crypt) context */
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index 7608155cd..7c02d46ce 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -1102,20 +1102,25 @@ tls_authentication_status(struct tls_multi *multi, 
const int latency)
 }
 else
 {
-unsigned int s1 =