ACK

An elegant fix.

-Steffan

On 07-01-15 20:26, Lev Stipakov wrote:
> Existing check didn't take into account the case when floated client is
> lame duck (CN for lame duck is NULL), which allowed lame duck to float
> to an address taken by another client.
> 
> As a fix we use cert_hash_compare function which, besides fixing
> mentioned case, also allows lame duck to float to an address already
> taken by the same client.
> ---
>  src/openvpn/multi.c      | 13 ++++++++-----
>  src/openvpn/ssl_verify.c |  2 +-
>  src/openvpn/ssl_verify.h |  8 ++++++++
>  3 files changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
> index 6ddfbb5..4412491 100644
> --- a/src/openvpn/multi.c
> +++ b/src/openvpn/multi.c
> @@ -2127,17 +2127,20 @@ void multi_process_float (struct multi_context* m, 
> struct multi_instance* mi)
>    const uint32_t hv = hash_value (hash, &real);
>    struct hash_bucket *bucket = hash_bucket (hash, hv);
>  
> +  /* make sure that we don't float to an address taken by another client */
>    struct hash_element *he = hash_lookup_fast (hash, bucket, &real, hv);
>    if (he)
>      {
>        struct multi_instance *ex_mi = (struct multi_instance *) he->value;
>  
> -      const char *cn = tls_common_name (mi->context.c2.tls_multi, true);
> -      const char *ex_cn = tls_common_name (ex_mi->context.c2.tls_multi, 
> true);
> -      if (cn && ex_cn && strcmp (cn, ex_cn))
> +      struct tls_multi *m1 = mi->context.c2.tls_multi;
> +      struct tls_multi *m2 = ex_mi->context.c2.tls_multi;
> +
> +      /* do not float if target address is taken by client with another cert 
> */
> +      if (!cert_hash_compare(m1->locked_cert_hash_set, 
> m2->locked_cert_hash_set))
>       {
> -       msg (D_MULTI_MEDIUM, "prevent float to %s",
> -             multi_instance_string (ex_mi, false, &gc));
> +       msg (D_MULTI_MEDIUM, "Disallow float to an address taken by another 
> client %s",
> +            multi_instance_string (ex_mi, false, &gc));
>  
>         mi->context.c2.buf.len = 0;
>  
> diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
> index cec5f02..ad50458 100644
> --- a/src/openvpn/ssl_verify.c
> +++ b/src/openvpn/ssl_verify.c
> @@ -238,7 +238,7 @@ cert_hash_free (struct cert_hash_set *chs)
>      }
>  }
>  
> -static bool
> +bool
>  cert_hash_compare (const struct cert_hash_set *chs1, const struct 
> cert_hash_set *chs2)
>  {
>    if (chs1 && chs2)
> diff --git a/src/openvpn/ssl_verify.h b/src/openvpn/ssl_verify.h
> index 5f23431..d5bf22e 100644
> --- a/src/openvpn/ssl_verify.h
> +++ b/src/openvpn/ssl_verify.h
> @@ -137,6 +137,14 @@ const char *tls_common_name (const struct tls_multi* 
> multi, const bool null);
>   */
>  const char *tls_username (const struct tls_multi *multi, const bool null);
>  
> +/**
> + * Compares certificates hashes, returns true if hashes are equal.
> + *
> + * @param chs1 cert 1 hash set
> + * @param chs2 cert 2 hash set
> + */
> +bool cert_hash_compare (const struct cert_hash_set *chs1, const struct 
> cert_hash_set *chs2);
> +
>  #ifdef ENABLE_PF
>  
>  /**
> 

Reply via email to