Checked that only diffs are warning messages (as agreed)
and different indentation in #define VERIFY_PERMISSION
(probably caused by uncrustify).

Acked-by: Lev Stipakov <lstipa...@gmail.com>

pe 26. kesäk. 2020 klo 14.06 Arne Schwabe (a...@rfc2549.org) kirjoitti:
>
> This commit introduces the allow-compression option that allow
> changing the new default to the previous default or to a stricter
> version.
>
> Warning for comp-lzo/compress are not generated in the post option check
> (options_postprocess_mutate) since these warnings should also be shown
> on pushed options. Moving the showing the warning showing for
> allow-compression to options_postprocess_mutate will complicate the
> option handling without giving any other benefit.
>
> Patch V2: fix spelling and grammer (thanks tincantech), also fix
>    uncompressiable to incompressible in three other instances in the
>    source code
>
> Patch V3: fix overlong lines. Do not allow compression to be pushed
>
> Patch V4: rename COMP_F_NO_ASYM to COMP_F_ALLOW_COMPRESS, fix style.
>           The logic of warnings etc in options.c has not been changed
>           since adding all the code to mutate_options would a lot more
>           and more complicated code and after discussion we decided that
>           it is okay as is.
>
> Patch V5: Reword warnings, rebase on master
>
> Signed-off-by: Arne Schwabe <a...@rfc2549.org>
> ---
>  doc/openvpn.8          |  44 +++++++++++++---
>  src/openvpn/comp-lz4.c |   3 +-
>  src/openvpn/comp.c     |   2 +-
>  src/openvpn/comp.h     |  16 ++++--
>  src/openvpn/lzo.c      |   2 +-
>  src/openvpn/mtu.h      |   2 +-
>  src/openvpn/options.c  | 115 +++++++++++++++++++++++++++++++++++------
>  7 files changed, 153 insertions(+), 31 deletions(-)
>
> diff --git a/doc/openvpn.8 b/doc/openvpn.8
> index dcc72abe..03ae5ac5 100644
> --- a/doc/openvpn.8
> +++ b/doc/openvpn.8
> @@ -2545,26 +2545,54 @@ Enable a compression algorithm.
>
>  The
>  .B algorithm
> -parameter may be "lzo", "lz4", or empty.  LZO and LZ4
> -are different compression algorithms, with LZ4 generally
> +parameter may be "lzo", "lz4", "lz4\-v2", "stub", "stub\-v2" or empty.
> +LZO and LZ4 are different compression algorithms, with LZ4 generally
>  offering the best performance with least CPU usage.
>  For backwards compatibility with OpenVPN versions before v2.4, use "lzo"
>  (which is identical to the older option "\-\-comp\-lzo yes").
>
> +The "lz4\-v2" and "stub\-v2" variants implement a better framing that does 
> not add
> +overhead when packets cannot be compressed. All other variants always add 
> one extra
> +framing byte compared to no compression framing.
> +
>  If the
>  .B algorithm
> -parameter is empty, compression will be turned off, but the packet
> -framing for compression will still be enabled, allowing a different
> -setting to be pushed later.
> +parameter is "stub", "stub\-v2", or empty, compression will be turned off, 
> but
> +the packet framing for compression will still be enabled, allowing a 
> different
> +setting to be pushed later. Additionally, "stub" and "stub\-v2" will disable
> +announcing lzo and lz4 compression support via "IV_" variables to the server.
> +
>
>  .B Security Considerations
>
>  Compression and encryption is a tricky combination.  If an attacker knows or 
> is
>  able to control (parts of) the plaintext of packets that contain secrets, the
>  attacker might be able to extract the secret if compression is enabled.  See
> -e.g. the CRIME and BREACH attacks on TLS which also leverage compression to
> -break encryption.  If you are not entirely sure that the above does not apply
> -to your traffic, you are advised to *not* enable compression.
> +e.g. the CRIME and BREACH attacks on TLS and VORACLE on VPNs which also 
> leverage
> +compression to break encryption.  If you are not entirely sure that the 
> above does
> +not apply to your traffic, you are advised to *not* enable compression.
> +
> +.\"*********************************************************
> +.TP
> +.B \-\-allow\-compression [mode]
> +As described in
> +\.B \-\-compress
> +option, compression is potentially dangerous option. This option allows
> +controlling the behaviour of OpenVPN when compression is used and allowed.
> +.B mode
> +may be "yes", "no", or "asym" (default).
> +
> +With allow\-compression set to "no", OpenVPN will refuse any non stub
> +compression. With "yes" OpenVPN will send and receive compressed packets.
> +With "asym", the default, OpenVPN will only decompress (downlink) packets but
> +not compress (uplink) packets. This also allows migrating to disable 
> compression
> +when changing both server and client configurations to remove compression at 
> the
> +same time is not a feasible option.
> +
> +The default of asym has been chosen to maximise compatibility with existing
> +configuration while at the same time phasing out compression in existing
> +deployment by disabling compression on the uplink, effectively completely 
> disabling
> +compression if both client and server are upgraded.
>
>  .\"*********************************************************
>  .TP
> diff --git a/src/openvpn/comp-lz4.c b/src/openvpn/comp-lz4.c
> index f52fdbfb..30e6da95 100644
> --- a/src/openvpn/comp-lz4.c
> +++ b/src/openvpn/comp-lz4.c
> @@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf,
>  {
>      /*
>       * In order to attempt compression, length must be at least 
> COMPRESS_THRESHOLD.
> +     * and asymmetric compression must be disabled
>       */
> -    if (buf->len >= COMPRESS_THRESHOLD)
> +    if (buf->len >= COMPRESS_THRESHOLD && (compctx->flags & 
> COMP_F_ALLOW_COMPRESS))
>      {
>          const size_t ps = PAYLOAD_SIZE(frame);
>          int zlen_max = ps + COMP_EXTRA_BUFFER(ps);
> diff --git a/src/openvpn/comp.c b/src/openvpn/comp.c
> index a9459133..9b131137 100644
> --- a/src/openvpn/comp.c
> +++ b/src/openvpn/comp.c
> @@ -127,7 +127,7 @@ void
>  comp_add_to_extra_buffer(struct frame *frame)
>  {
>      /* Leave room for compression buffer to expand in worst case scenario
> -     * where data is totally uncompressible */
> +     * where data is totally incompressible */
>      frame_add_to_extra_buffer(frame, 
> COMP_EXTRA_BUFFER(EXPANDED_SIZE(frame)));
>  }
>
> diff --git a/src/openvpn/comp.h b/src/openvpn/comp.h
> index 0dadd1e6..5c0322ca 100644
> --- a/src/openvpn/comp.h
> +++ b/src/openvpn/comp.h
> @@ -52,10 +52,12 @@
>   */
>
>  /* Compression flags */
> -#define COMP_F_ADAPTIVE   (1<<0) /* COMP_ALG_LZO only */
> -#define COMP_F_ASYM       (1<<1) /* only downlink is compressed, not uplink 
> */
> -#define COMP_F_SWAP       (1<<2) /* initial command byte is swapped with 
> last byte in buffer to preserve payload alignment */
> +#define COMP_F_ADAPTIVE             (1<<0) /* COMP_ALG_LZO only */
> +#define COMP_F_ALLOW_COMPRESS       (1<<1) /* not only downlink is 
> compressed but also uplink */
> +#define COMP_F_SWAP                 (1<<2) /* initial command byte is 
> swapped with last byte in buffer to preserve payload alignment */
>  #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only 
> support compression stubs */
> +#define COMP_F_ALLOW_STUB_ONLY      (1<<4) /* Only accept stub compression, 
> even with COMP_F_ADVERTISE_STUBS_ONLY
> +                                            * we still accept other 
> compressions to be pushed */
>
>
>  /*
> @@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)
>      return info->alg != COMP_ALG_UNDEF;
>  }
>
> +static inline bool
> +comp_non_stub_enabled(const struct compress_options *info)
> +{
> +    return info->alg != COMP_ALGV2_UNCOMPRESSED
> +           && info->alg != COMP_ALG_STUB
> +           && info->alg != COMP_ALG_UNDEF;
> +}
> +
>  static inline bool
>  comp_unswapped_prefix(const struct compress_options *info)
>  {
> diff --git a/src/openvpn/lzo.c b/src/openvpn/lzo.c
> index e3be6adf..d053fedf 100644
> --- a/src/openvpn/lzo.c
> +++ b/src/openvpn/lzo.c
> @@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)
>  static inline bool
>  lzo_compression_enabled(struct compress_context *compctx)
>  {
> -    if (compctx->flags & COMP_F_ASYM)
> +    if (!(compctx->flags & COMP_F_ALLOW_COMPRESS))
>      {
>          return false;
>      }
> diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h
> index cfa8d2f7..549c319b 100644
> --- a/src/openvpn/mtu.h
> +++ b/src/openvpn/mtu.h
> @@ -45,7 +45,7 @@
>   *      ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450
>   *
>   *    Compression overflow bytes is the worst-case size expansion that would 
> be
> - *    expected if we tried to compress mtu + extra_frame bytes of 
> uncompressible data.
> + *    expected if we tried to compress mtu + extra_frame bytes of 
> incompressible data.
>   */
>
>  /*
> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index 3484f7d4..9580d1d2 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -357,9 +357,10 @@ static const char usage_message[] =
>  #endif
>  #if defined(USE_COMP)
>      "--compress alg  : Use compression algorithm alg\n"
> +    "--allow-compression: Specify whether compression should be allowed\n"
>  #if defined(ENABLE_LZO)
>      "--comp-lzo      : Use LZO compression -- may add up to 1 byte per\n"
> -    "                  packet for uncompressible data.\n"
> +    "                  packet for incompressible data.\n"
>      "--comp-noadapt  : Don't use adaptive compression when --comp-lzo\n"
>      "                  is specified.\n"
>  #endif
> @@ -4978,11 +4979,11 @@ options_string_import(struct options *options,
>  #if P2MP
>
>  #define VERIFY_PERMISSION(mask) {                                            
> \
> -    if (!verify_permission(p[0], file, line, (mask), permission_mask,        
> \
> -                           option_types_found, msglevel, options, 
> is_inline))\
> -    {                                                                        
> \
> -        goto err;                                                            
> \
> -    }                                                                        
> \
> +        if (!verify_permission(p[0], file, line, (mask), permission_mask,    
>     \
> +                               option_types_found, msglevel, options, 
> is_inline)) \
> +        {                                                                    
>     \
> +            goto err;                                                        
>     \
> +        }                                                                    
>     \
>  }
>
>  static bool
> @@ -5115,6 +5116,25 @@ set_user_script(struct options *options,
>  #endif
>  }
>
> +static void
> +show_compression_warning(struct compress_options *info)
> +{
> +    if (comp_non_stub_enabled(info))
> +    {
> +        /*
> +         * Check if already displayed the strong warning and enabled full
> +         * compression
> +         */
> +        if (!(info->flags & COMP_F_ALLOW_COMPRESS))
> +        {
> +            msg(M_WARN, "WARNING: Compression for receiving enabled. "
> +                "Compression has been used in the past to break encryption. "
> +                "Sent packets are not compressed unless \"allow-compression 
> yes\" "
> +                "is also set.");
> +        }
> +    }
> +}
> +
>  static void
>  add_option(struct options *options,
>             char *p[],
> @@ -7606,29 +7626,80 @@ add_option(struct options *options,
>      }
>  #endif
>  #if defined(USE_COMP)
> +    else if (streq(p[0], "allow-compression") && p[1] && !p[2])
> +    {
> +        VERIFY_PERMISSION(OPT_P_GENERAL);
> +
> +        if (streq(p[1], "no"))
> +        {
> +            options->comp.flags =
> +                COMP_F_ALLOW_STUB_ONLY|COMP_F_ADVERTISE_STUBS_ONLY;
> +            if (comp_non_stub_enabled(&options->comp))
> +            {
> +                msg(msglevel, "'--allow-compression no' conflicts with "
> +                    " enabling compression");
> +            }
> +        }
> +        else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
> +        {
> +            /* Also printed on a push to hint at configuration problems */
> +            msg(msglevel, "Cannot set allow-compression to '%s' "
> +                "after set to 'no'", p[1]);
> +            goto err;
> +        }
> +        else if (streq(p[1], "asym"))
> +        {
> +            options->comp.flags &= ~COMP_F_ALLOW_COMPRESS;
> +        }
> +        else if (streq(p[1], "yes"))
> +        {
> +            msg(M_WARN, "WARNING: Compression for sending and receiving 
> enabled. Compression has "
> +                "been used in the past to break encryption. Allowing 
> compression allows "
> +                "attacks that break encryption. Using \"--allow-compression 
> yes\" is "
> +                "strongly discouraged for common usage. See --compress in 
> the manual "
> +                "page for more information ");
> +
> +            options->comp.flags |= COMP_F_ALLOW_COMPRESS;
> +        }
> +        else
> +        {
> +            msg(msglevel, "bad allow-compression option: %s -- "
> +                "must be 'yes', 'no', or 'asym'", p[1]);
> +            goto err;
> +        }
> +    }
>      else if (streq(p[0], "comp-lzo") && !p[2])
>      {
>          VERIFY_PERMISSION(OPT_P_COMP);
>
> +        /* All lzo variants do not use swap */
> +        options->comp.flags &= ~COMP_F_SWAP;
>  #if defined(ENABLE_LZO)
>          if (p[1] && streq(p[1], "no"))
>  #endif
>          {
>              options->comp.alg = COMP_ALG_STUB;
> -            options->comp.flags = 0;
> +            options->comp.flags &= ~COMP_F_ADAPTIVE;
>          }
>  #if defined(ENABLE_LZO)
> +        else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
> +        {
> +            /* Also printed on a push to hint at configuration problems */
> +            msg(msglevel, "Cannot set comp-lzo to '%s', "
> +                "allow-compression is set to 'no'", p[1]);
> +            goto err;
> +        }
>          else if (p[1])
>          {
>              if (streq(p[1], "yes"))
>              {
>                  options->comp.alg = COMP_ALG_LZO;
> -                options->comp.flags = 0;
> +                options->comp.flags &= ~COMP_F_ADAPTIVE;
>              }
>              else if (streq(p[1], "adaptive"))
>              {
>                  options->comp.alg = COMP_ALG_LZO;
> -                options->comp.flags = COMP_F_ADAPTIVE;
> +                options->comp.flags |= COMP_F_ADAPTIVE;
>              }
>              else
>              {
> @@ -7639,12 +7710,17 @@ add_option(struct options *options,
>          else
>          {
>              options->comp.alg = COMP_ALG_LZO;
> -            options->comp.flags = COMP_F_ADAPTIVE;
> +            options->comp.flags |= COMP_F_ADAPTIVE;
>          }
> +        show_compression_warning(&options->comp);
>  #endif /* if defined(ENABLE_LZO) */
>      }
>      else if (streq(p[0], "comp-noadapt") && !p[1])
>      {
> +        /*
> +         * We do not need to check here if we allow compression since
> +         * it only modifies a flag if compression is enabled
> +         */
>          VERIFY_PERMISSION(OPT_P_COMP);
>          options->comp.flags &= ~COMP_F_ADAPTIVE;
>      }
> @@ -7656,30 +7732,36 @@ add_option(struct options *options,
>              if (streq(p[1], "stub"))
>              {
>                  options->comp.alg = COMP_ALG_STUB;
> -                options->comp.flags = 
> (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
> +                options->comp.flags |= 
> (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
>              }
>              else if (streq(p[1], "stub-v2"))
>              {
>                  options->comp.alg = COMP_ALGV2_UNCOMPRESSED;
> -                options->comp.flags = COMP_F_ADVERTISE_STUBS_ONLY;
> +                options->comp.flags |= COMP_F_ADVERTISE_STUBS_ONLY;
> +            }
> +            else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
> +            {
> +                /* Also printed on a push to hint at configuration problems 
> */
> +                msg(msglevel, "Cannot set compress to '%s', "
> +                    "allow-compression is set to 'no'", p[1]);
> +                goto err;
>              }
>  #if defined(ENABLE_LZO)
>              else if (streq(p[1], "lzo"))
>              {
>                  options->comp.alg = COMP_ALG_LZO;
> -                options->comp.flags = 0;
> +                options->comp.flags &= ~(COMP_F_ADAPTIVE | COMP_F_SWAP);
>              }
>  #endif
>  #if defined(ENABLE_LZ4)
>              else if (streq(p[1], "lz4"))
>              {
>                  options->comp.alg = COMP_ALG_LZ4;
> -                options->comp.flags = COMP_F_SWAP;
> +                options->comp.flags |= COMP_F_SWAP;
>              }
>              else if (streq(p[1], "lz4-v2"))
>              {
>                  options->comp.alg = COMP_ALGV2_LZ4;
> -                options->comp.flags = 0;
>              }
>  #endif
>              else
> @@ -7691,8 +7773,9 @@ add_option(struct options *options,
>          else
>          {
>              options->comp.alg = COMP_ALG_STUB;
> -            options->comp.flags = COMP_F_SWAP;
> +            options->comp.flags |= COMP_F_SWAP;
>          }
> +        show_compression_warning(&options->comp);
>      }
>  #endif /* USE_COMP */
>      else if (streq(p[0], "show-ciphers") && !p[1])
> --
> 2.26.2
>
>
>
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel



-- 
-Lev


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

Reply via email to