Attention is currently required from: MaxF.

Hello flichtenheld, plaisthos,

I'd like you to reexamine a change. Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1304?usp=email

to look at the new patch set (#5).


Change subject: Add option to check tls-crypt-v2 key timestamps
......................................................................

Add option to check tls-crypt-v2 key timestamps

This commit adds the option --tls-crypt-v2-max-age n. When a client key
is older than n days or has no timestamp, the server rejects it.

Based on work by Rein van Baaren for Sentyron.

Co-authored-by: Rein van Baaren <[email protected]>
Change-Id: I0579d18c784e2ac16973d5553992c28f281a0900
Signed-off-by: Max Fillinger <[email protected]>
---
M doc/man-sections/tls-options.rst
M doc/tls-crypt-v2.txt
M src/openvpn/init.c
M src/openvpn/options.c
M src/openvpn/options.h
M src/openvpn/ssl_common.h
M src/openvpn/tls_crypt.c
7 files changed, 56 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/04/1304/5

diff --git a/doc/man-sections/tls-options.rst b/doc/man-sections/tls-options.rst
index db107e6..63cb32f 100644
--- a/doc/man-sections/tls-options.rst
+++ b/doc/man-sections/tls-options.rst
@@ -568,6 +568,10 @@
   The command can reject the connection by exiting with a non-zero exit
   code.

+--tls-crypt-v2-max-age n
+  Reject tls-crypt-v2 client keys that are older than n days or have
+  no timestamp.
+
 --tls-exit
   Exit on TLS negotiation failure. This option can be useful when you only
   want to make one attempt at connecting, e.g. in a test or monitoring script.
diff --git a/doc/tls-crypt-v2.txt b/doc/tls-crypt-v2.txt
index 7dcd041..c2e9deb 100644
--- a/doc/tls-crypt-v2.txt
+++ b/doc/tls-crypt-v2.txt
@@ -139,7 +139,10 @@
    The message is dropped and no error response is sent when either 3.1, 3.2 or
    3.3 fails (DoS protection).

-4. Server optionally checks metadata using a --tls-crypt-v2-verify script
+4. The server optionally checks if the client key contains a timestamp that is
+   below a maximum age configured with the --tls-crypt-v2-max-age option.
+
+5. Server optionally checks metadata using a --tls-crypt-v2-verify script

    This allows early abort of connection, *before* we expose any of the
    notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 8d95d5c..fc079e1 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3418,6 +3418,7 @@
         {
             to.tls_wrap.tls_crypt_v2_server_key = 
c->c1.ks.tls_crypt_v2_server_key;
             to.tls_crypt_v2_verify_script = 
c->options.tls_crypt_v2_verify_script;
+            to.tls_crypt_v2_max_age = c->options.tls_crypt_v2_max_age;
             if (options->ce.tls_crypt_v2_force_cookie)
             {
                 to.tls_wrap.opt.flags |= CO_FORCE_TLSCRYPTV2_COOKIE;
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index ecf9374..e1a9a61 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -650,6 +650,8 @@
     "                  fresh tls-crypt-v2 server key, and store to keyfile\n"
     "--tls-crypt-v2-verify cmd : Run command cmd to verify the metadata of 
the\n"
     "                  client-supplied tls-crypt-v2 client key\n"
+    "--tls-crypt-v2-max-age n : Only accept tls-crypt-v2 client keys that have 
a\n"
+    "                  timestamp which is at most n days old.\n"
     "--askpass [file]: Get PEM password from controlling tty before we 
daemonize.\n"
     "--auth-nocache  : Don't cache --askpass or --auth-user-pass passwords.\n"
     "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n"
@@ -9084,6 +9086,14 @@
         VERIFY_PERMISSION(OPT_P_GENERAL);
         options->tls_crypt_v2_verify_script = p[1];
     }
+    else if (streq(p[0], "tls-crypt-v2-max-age") && p[1])
+    {
+        VERIFY_PERMISSION(OPT_P_GENERAL);
+        if (!atoi_constrained(p[1], &options->tls_crypt_v2_max_age, 
"tls-crypt-v2-max-age", 1, INT_MAX, msglevel))
+        {
+            goto err;
+        }
+    }
     else if (streq(p[0], "x509-track") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_GENERAL);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 9d2ff9f..42db9ca 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -678,6 +678,8 @@

     const char *tls_crypt_v2_verify_script;

+    int tls_crypt_v2_max_age;
+
     /* Allow only one session */
     bool single_session;

diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index de89d30..0402a6a 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -383,6 +383,7 @@

     bool tls_crypt_v2;
     const char *tls_crypt_v2_verify_script;
+    int tls_crypt_v2_max_age;

     /** TLS handshake wrapping state */
     struct tls_wrap_ctx tls_wrap;
diff --git a/src/openvpn/tls_crypt.c b/src/openvpn/tls_crypt.c
index a808de3..cbd955e 100644
--- a/src/openvpn/tls_crypt.c
+++ b/src/openvpn/tls_crypt.c
@@ -29,6 +29,7 @@
 #include "argv.h"
 #include "base64.h"
 #include "crypto.h"
+#include "integer.h"
 #include "platform.h"
 #include "run_command.h"
 #include "session_id.h"
@@ -528,6 +529,33 @@
 }

 static bool
+tls_crypt_v2_check_client_key_age(const struct tls_wrap_ctx *ctx, int max_days)
+{
+    if (ctx->tls_crypt_v2_metadata.len < 1 + sizeof(int64_t))
+    {
+        msg(M_WARN, "ERROR: Client key metadata is too small to contain a 
timestamp.");
+    }
+
+    const uint8_t *metadata = ctx->tls_crypt_v2_metadata.data;
+    if (*metadata != TLS_CRYPT_METADATA_TYPE_TIMESTAMP)
+    {
+        msg(M_WARN, "ERROR: Client key does not have a timestamp.");
+        return false;
+    }
+
+    int64_t timestamp;
+    memcpy(&timestamp, metadata + 1, sizeof(int64_t));
+    timestamp = (int64_t)ntohll((uint64_t)timestamp);
+    int64_t max_age_in_seconds = max_days * 24 * 60 * 60;
+    if (now - timestamp > max_age_in_seconds)
+    {
+        msg(M_WARN, "ERROR: Client key is too old.");
+        return false;
+    }
+    return true;
+}
+
+static bool
 tls_crypt_v2_verify_metadata(const struct tls_wrap_ctx *ctx, const struct 
tls_options *opt)
 {
     bool ret = false;
@@ -642,6 +670,12 @@
         return false;
     }

+    if (opt && opt->tls_crypt_v2_max_age > 0 && 
!tls_crypt_v2_check_client_key_age(ctx, opt->tls_crypt_v2_max_age))
+    {
+        secure_memzero(&ctx->original_wrap_keydata, 
sizeof(ctx->original_wrap_keydata));
+        return false;
+    }
+
     if (opt && opt->tls_crypt_v2_verify_script && 
!tls_crypt_v2_verify_metadata(ctx, opt))
     {
         secure_memzero(&ctx->original_wrap_keydata, 
sizeof(ctx->original_wrap_keydata));

--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1304?usp=email
To unsubscribe, or for help writing mail filters, visit 
http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I0579d18c784e2ac16973d5553992c28f281a0900
Gerrit-Change-Number: 1304
Gerrit-PatchSet: 5
Gerrit-Owner: MaxF <[email protected]>
Gerrit-Reviewer: flichtenheld <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: MaxF <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to