Hi,

On 07-07-18 11:04, Antonio Quartulli wrote:
> Different VPN servers may use different tls-auth/crypt keys.
> For this reason it is convenient to make tls-auth/crypt
> per-connection-block options so that the user is allowed to
> specify one key per remote.
> 
> If no tls-auth/crypt option is specified in a given connection
> block, the global settings, if any, are used.
> 
> Trac: #720
> Cc: Steffan Karger <stef...@karger.me>
> Signed-off-by: Antonio Quartulli <a...@unstable.cc>
> ---
> v2:
> - convert tls-auth keyfile to inline key if persist-key was specified
> v3:
> - squash 2/3 and 3/3 in one patch to prevent temporary features
>   breakages
> - restyle code introduced in options_postprocess_mutate_ce()
> v4:
> - rebase on top of latest 1/2
> 
>  doc/openvpn.8         |   3 +
>  src/openvpn/init.c    |  18 ++---
>  src/openvpn/options.c | 173 +++++++++++++++++++++++++++++-------------
>  src/openvpn/options.h |   9 +++
>  4 files changed, 142 insertions(+), 61 deletions(-)
> 
> diff --git a/doc/openvpn.8 b/doc/openvpn.8
> index 46ea58b6..f01b48b6 100644
> --- a/doc/openvpn.8
> +++ b/doc/openvpn.8
> @@ -361,6 +361,7 @@ block:
>  .B fragment,
>  .B http\-proxy,
>  .B http\-proxy\-option,
> +.B key\-direction,
>  .B link\-mtu,
>  .B local,
>  .B lport,
> @@ -372,6 +373,8 @@ block:
>  .B remote,
>  .B rport,
>  .B socks\-proxy,
> +.B tls\-auth,
> +.B tls\-crypt,
>  .B tun\-mtu and
>  .B tun\-mtu\-extra.
>  
> diff --git a/src/openvpn/init.c b/src/openvpn/init.c
> index 1b46b364..14732e34 100644
> --- a/src/openvpn/init.c
> +++ b/src/openvpn/init.c
> @@ -2507,7 +2507,7 @@ do_init_tls_wrap_key(struct context *c)
>      const struct options *options = &c->options;
>  
>      /* TLS handshake authentication (--tls-auth) */
> -    if (options->tls_auth_file)
> +    if (options->ce.tls_auth_file)
>      {
>          /* Initialize key_type for tls-auth with auth only */
>          CLEAR(c->c1.ks.tls_auth_key_type);
> @@ -2525,18 +2525,18 @@ do_init_tls_wrap_key(struct context *c)
>  
>          crypto_read_openvpn_key(&c->c1.ks.tls_auth_key_type,
>                                  &c->c1.ks.tls_wrap_key,
> -                                options->tls_auth_file,
> -                                options->tls_auth_file_inline,
> -                                options->key_direction,
> +                                options->ce.tls_auth_file,
> +                                options->ce.tls_auth_file_inline,
> +                                options->ce.key_direction,
>                                  "Control Channel Authentication", 
> "tls-auth");
>      }
>  
>      /* TLS handshake encryption+authentication (--tls-crypt) */
> -    if (options->tls_crypt_file)
> +    if (options->ce.tls_crypt_file)
>      {
>          tls_crypt_init_key(&c->c1.ks.tls_wrap_key,
> -                           options->tls_crypt_file,
> -                           options->tls_crypt_inline, options->tls_server);
> +                           options->ce.tls_crypt_file,
> +                           options->ce.tls_crypt_inline, 
> options->tls_server);
>      }
>  }
>  
> @@ -2806,7 +2806,7 @@ do_init_crypto_tls(struct context *c, const unsigned 
> int flags)
>  #endif
>  
>      /* TLS handshake authentication (--tls-auth) */
> -    if (options->tls_auth_file)
> +    if (options->ce.tls_auth_file)
>      {
>          to.tls_wrap.mode = TLS_WRAP_AUTH;
>          to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key;
> @@ -2817,7 +2817,7 @@ do_init_crypto_tls(struct context *c, const unsigned 
> int flags)
>      }
>  
>      /* TLS handshake encryption (--tls-crypt) */
> -    if (options->tls_crypt_file)
> +    if (options->ce.tls_crypt_file)
>      {
>          to.tls_wrap.mode = TLS_WRAP_CRYPT;
>          to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key;
> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index b2ca2738..6f1a5382 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -1506,6 +1506,11 @@ show_connection_entry(const struct connection_entry *o)
>  #ifdef ENABLE_OCC
>      SHOW_INT(explicit_exit_notification);
>  #endif
> +
> +    SHOW_STR(tls_auth_file);
> +    SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, 
> true),
> +              "%s");
> +    SHOW_STR(tls_crypt_file);
>  }
>  
>  
> @@ -1786,9 +1791,6 @@ show_settings(const struct options *o)
>      SHOW_BOOL(push_peer_info);
>      SHOW_BOOL(tls_exit);
>  
> -    SHOW_STR(tls_auth_file);
> -    SHOW_STR(tls_crypt_file);
> -
>  #ifdef ENABLE_PKCS11
>      {
>          int i;
> @@ -2723,7 +2725,7 @@ options_postprocess_verify_ce(const struct options 
> *options, const struct connec
>                  notnull(options->priv_key_file, "private key file (--key) or 
> PKCS#12 file (--pkcs12)");
>              }
>          }
> -        if (options->tls_auth_file && options->tls_crypt_file)
> +        if (ce->tls_auth_file && ce->tls_crypt_file)
>          {
>              msg(M_USAGE, "--tls-auth and --tls-crypt are mutually 
> exclusive");
>          }
> @@ -2869,6 +2871,49 @@ options_postprocess_mutate_ce(struct options *o, 
> struct connection_entry *ce)
>          }
>      }
>  
> +    /*
> +     * Set per-connection block tls-auth/crypt fields if undefined.
> +     *
> +     * At the end only one of the two will be really set because the parser
> +     * logic prevents configurations where both are set.
> +     */
> +    if (!ce->tls_auth_file && !ce->tls_crypt_file)
> +    {
> +        ce->tls_auth_file = o->tls_auth_file;
> +        ce->tls_auth_file_inline = o->tls_auth_file_inline;
> +        ce->key_direction = o->key_direction;
> +
> +        ce->tls_crypt_file = o->tls_crypt_file;
> +        ce->tls_crypt_inline = o->tls_crypt_inline;
> +    }
> +
> +    /* pre-cache tls-auth/crypt key file if persist-key was specified and 
> keys
> +     * were not already embedded in the config file
> +     */
> +    if (o->persist_key)
> +    {
> +        if (ce->tls_auth_file && !ce->tls_auth_file_inline)
> +        {
> +            struct buffer in = buffer_read_from_file(o->tls_auth_file, 
> &o->gc);
> +            if (!buf_valid(&in))
> +                msg(M_FATAL, "Cannot pre-load tls-auth keyfile (%s)",
> +                    o->tls_auth_file);
> +
> +            ce->tls_auth_file = INLINE_FILE_TAG;
> +            ce->tls_auth_file_inline = (char *)in.data;
> +        }
> +
> +        if (ce->tls_crypt_file && !ce->tls_crypt_inline)
> +        {
> +            struct buffer in = buffer_read_from_file(o->tls_crypt_file, 
> &o->gc);
> +            if (!buf_valid(&in))
> +                msg(M_FATAL, "Cannot pre-load tls-crypt keyfile (%s)",
> +                    o->tls_auth_file);
> +
> +            ce->tls_crypt_file = INLINE_FILE_TAG;
> +            ce->tls_crypt_inline = (char *)in.data;
> +        }
> +    }
>  }
>  
>  #ifdef _WIN32
> @@ -3019,32 +3064,6 @@ options_postprocess_mutate(struct options *o)
>          options_postprocess_mutate_ce(o, o->connection_list->array[i]);
>      }
>  
> -    /* pre-cache tls-auth/crypt key file if persist-key was specified */
> -    if (o->persist_key)
> -    {
> -        if (o->tls_auth_file && !o->tls_auth_file_inline)
> -        {
> -            struct buffer in = buffer_read_from_file(o->tls_auth_file, 
> &o->gc);
> -            if (!buf_valid(&in))
> -                msg(M_FATAL, "Cannot pre-load tls-auth keyfile (%s)",
> -                    o->tls_auth_file);
> -
> -            o->tls_auth_file = INLINE_FILE_TAG;
> -            o->tls_auth_file_inline = (char *)in.data;
> -        }
> -
> -        if (o->tls_crypt_file && !o->tls_crypt_inline)
> -        {
> -            struct buffer in = buffer_read_from_file(o->tls_crypt_file, 
> &o->gc);
> -            if (!buf_valid(&in))
> -                msg(M_FATAL, "Cannot pre-load tls-crypt keyfile (%s)",
> -                    o->tls_auth_file);
> -
> -            o->tls_crypt_file = INLINE_FILE_TAG;
> -            o->tls_crypt_inline = (char *)in.data;
> -        }
> -    }
> -
>      if (o->tls_server)
>      {
>          /* Check that DH file is specified, or explicitly disabled */
> @@ -3311,12 +3330,22 @@ options_postprocess_filechecks(struct options 
> *options)
>                                           options->crl_file, R_OK, 
> "--crl-verify");
>      }
>  
> -    errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
> -                              options->tls_auth_file, R_OK, "--tls-auth");
> -    errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
> -                              options->tls_crypt_file, R_OK, "--tls-crypt");
> +    ASSERT(options->connection_list);
> +    for (int i = 0; i < options->connection_list->len; ++i)
> +    {
> +        struct connection_entry *ce = options->connection_list->array[i];
> +
> +        errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
> +                                  ce->tls_auth_file, R_OK, "--tls-auth");
> +
> +        errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
> +                                  ce->tls_crypt_file, R_OK, "--tls-crypt");
> +
> +    }
> +
>      errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
>                                options->shared_secret_file, R_OK, "--secret");
> +
>      errs |= check_file_access(CHKACC_DIRPATH|CHKACC_FILEXSTWR,
>                                options->packet_id_file, R_OK|W_OK, 
> "--replay-persist");
>  
> @@ -3673,7 +3702,7 @@ options_string(const struct options *o,
>      {
>          if (TLS_CLIENT || TLS_SERVER)
>          {
> -            if (o->tls_auth_file)
> +            if (o->ce.tls_auth_file)
>              {
>                  buf_printf(&out, ",tls-auth");
>              }
> @@ -7446,10 +7475,19 @@ add_option(struct options *options,
>      {
>          int key_direction;
>  
> +        VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION);
> +
>          key_direction = ascii2keydirection(msglevel, p[1]);
>          if (key_direction >= 0)
>          {
> -            options->key_direction = key_direction;
> +            if (permission_mask & OPT_P_GENERAL)
> +            {
> +                options->key_direction = key_direction;
> +            }
> +            else if (permission_mask & OPT_P_CONNECTION)
> +            {
> +                options->ce.key_direction = key_direction;
> +            }
>          }
>          else
>          {
> @@ -8018,35 +8056,66 @@ add_option(struct options *options,
>      }
>      else if (streq(p[0], "tls-auth") && p[1] && !p[3])
>      {
> -        VERIFY_PERMISSION(OPT_P_GENERAL);
> -        if (streq(p[1], INLINE_FILE_TAG) && p[2])
> +        int key_direction = -1;
> +
> +        VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION);
> +
> +        if (permission_mask & OPT_P_GENERAL)
>          {
> -            options->tls_auth_file_inline = p[2];
> +            if (streq(p[1], INLINE_FILE_TAG) && p[2])
> +            {
> +                options->tls_auth_file_inline = p[2];
> +            }
> +            else if (p[2])
> +            {
> +                key_direction = ascii2keydirection(msglevel, p[2]);
> +                if (key_direction < 0)
> +                {
> +                    goto err;
> +                }
> +                options->key_direction = key_direction;
> +            }
> +            options->tls_auth_file = p[1];
>          }
> -        else if (p[2])
> +        else if (permission_mask & OPT_P_CONNECTION)
>          {
> -            int key_direction;
> -
> -            key_direction = ascii2keydirection(msglevel, p[2]);
> -            if (key_direction >= 0)
> +            options->ce.key_direction = KEY_DIRECTION_BIDIRECTIONAL;
> +            if (streq(p[1], INLINE_FILE_TAG) && p[2])
>              {
> -                options->key_direction = key_direction;
> +                options->ce.tls_auth_file_inline = p[2];
>              }
> -            else
> +            else if (p[2])
>              {
> -                goto err;
> +                key_direction = ascii2keydirection(msglevel, p[2]);
> +                if (key_direction < 0)
> +                {
> +                    goto err;
> +                }
> +                options->ce.key_direction = key_direction;
>              }
> +            options->ce.tls_auth_file = p[1];
>          }
> -        options->tls_auth_file = p[1];
>      }
>      else if (streq(p[0], "tls-crypt") && p[1] && !p[3])
>      {
> -        VERIFY_PERMISSION(OPT_P_GENERAL);
> -        if (streq(p[1], INLINE_FILE_TAG) && p[2])
> +        VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION);
> +        if (permission_mask & OPT_P_GENERAL)
>          {
> -            options->tls_crypt_inline = p[2];
> +            if (streq(p[1], INLINE_FILE_TAG) && p[2])
> +            {
> +                options->tls_crypt_inline = p[2];
> +            }
> +            options->tls_crypt_file = p[1];
> +        }
> +        else if (permission_mask & OPT_P_CONNECTION)
> +        {
> +            if (streq(p[1], INLINE_FILE_TAG) && p[2])
> +            {
> +                options->ce.tls_crypt_inline = p[2];
> +            }
> +            options->ce.tls_crypt_file = p[1];
> +
>          }
> -        options->tls_crypt_file = p[1];
>      }
>      else if (streq(p[0], "key-method") && p[1] && !p[2])
>      {
> diff --git a/src/openvpn/options.h b/src/openvpn/options.h
> index 3a6c33f8..acbd1087 100644
> --- a/src/openvpn/options.h
> +++ b/src/openvpn/options.h
> @@ -130,6 +130,15 @@ struct connection_entry
>  #define CE_MAN_QUERY_REMOTE_MASK   (0x07)
>  #define CE_MAN_QUERY_REMOTE_SHIFT  (2)
>      unsigned int flags;
> +
> +    /* Shared secret used for TLS control channel authentication */
> +    const char *tls_auth_file;
> +    const char *tls_auth_file_inline;
> +    int key_direction;
> +
> +    /* Shared secret used for TLS control channel authenticated encryption */
> +    const char *tls_crypt_file;
> +    const char *tls_crypt_inline;
>  };
>  
>  struct remote_entry
> 

Patch looks good, and I can no longer get this to fail on me, so:

Acked-by: Steffan Karger <stef...@karger.me>
Tested-by; Steffan Karger <stef...@karger.me>

-Steffan

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to