ACK. Code is similar to the full-blown patch for master, and float works
nicely.

-Steffan

On 23-11-14 20:17, Gert Doering wrote:
> This is a reduced version of the peer-id patch from Lev Stipakov
> implementing only the client side bits - send IV_PROTO=2, accept
> "peer-id <n>" as pushed option, support P_DATA_V2 packets.
> 
> v2: remove addition of "struct tls_multi;" to options.h, not needed
> 
> Signed-off-by: Gert Doering <g...@greenie.muc.de>
> ---
>  src/openvpn/init.c       | 12 +++++++++++-
>  src/openvpn/options.c    |  6 ++++++
>  src/openvpn/options.h    |  4 ++++
>  src/openvpn/ssl.c        | 40 +++++++++++++++++++++++++++++++++++-----
>  src/openvpn/ssl.h        |  3 ++-
>  src/openvpn/ssl_common.h |  4 ++++
>  6 files changed, 62 insertions(+), 7 deletions(-)
> 
> diff --git a/src/openvpn/init.c b/src/openvpn/init.c
> index 18f506c..4cfa132 100644
> --- a/src/openvpn/init.c
> +++ b/src/openvpn/init.c
> @@ -1711,7 +1711,8 @@ pull_permission_mask (const struct context *c)
>      | OPT_P_MESSAGES
>      | OPT_P_EXPLICIT_NOTIFY
>      | OPT_P_ECHO
> -    | OPT_P_PULL_MODE;
> +    | OPT_P_PULL_MODE
> +    | OPT_P_PEER_ID;
>  
>    if (!c->options.route_nopull)
>      flags |= (OPT_P_ROUTE | OPT_P_IPWIN32);
> @@ -1790,6 +1791,15 @@ do_deferred_options (struct context *c, const unsigned 
> int found)
>      msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options 
> modified");
>    if (found & OPT_P_SETENV)
>      msg (D_PUSH, "OPTIONS IMPORT: environment modified");
> +
> +#ifdef ENABLE_SSL
> +  if (found & OPT_P_PEER_ID)
> +    {
> +      msg (D_PUSH, "OPTIONS IMPORT: peer-id set");
> +      c->c2.tls_multi->use_peer_id = true;
> +      c->c2.tls_multi->peer_id = c->options.peer_id;
> +    }
> +#endif
>  }
>  
>  /*
> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index d91bb63..5bddca4 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -6996,6 +6996,12 @@ add_option (struct options *options,
>        options->persist_mode = 1;
>      }
>  #endif
> +  else if (streq (p[0], "peer-id"))
> +    {
> +      VERIFY_PERMISSION (OPT_P_PEER_ID);
> +      options->use_peer_id = true;
> +      options->peer_id = atoi(p[1]);
> +    }
>    else
>      {
>        int i;
> diff --git a/src/openvpn/options.h b/src/openvpn/options.h
> index 2c18838..af9a47f 100644
> --- a/src/openvpn/options.h
> +++ b/src/openvpn/options.h
> @@ -594,6 +594,9 @@ struct options
>    bool show_net_up;
>    int route_method;
>  #endif
> +
> +  bool use_peer_id;
> +  uint32_t peer_id;
>  };
>  
>  #define streq(x, y) (!strcmp((x), (y)))
> @@ -629,6 +632,7 @@ struct options
>  #define OPT_P_SOCKBUF         (1<<25)
>  #define OPT_P_SOCKFLAGS       (1<<26)
>  #define OPT_P_CONNECTION      (1<<27)
> +#define OPT_P_PEER_ID         (1<<28)
>  
>  #define OPT_P_DEFAULT   (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
>  
> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index 281176e..2373582 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c
> @@ -627,6 +627,8 @@ packet_opcode_name (int op)
>        return "P_ACK_V1";
>      case P_DATA_V1:
>        return "P_DATA_V1";
> +    case P_DATA_V2:
> +      return "P_DATA_V2";
>      default:
>        return "P_???";
>      }
> @@ -1053,6 +1055,9 @@ tls_multi_init (struct tls_options *tls_options)
>    ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK];
>    ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];
>  
> +  /* By default not use P_DATA_V2 */
> +  ret->use_peer_id = false;
> +
>    return ret;
>  }
>  
> @@ -1828,6 +1833,8 @@ push_peer_info(struct buffer *buf, struct tls_session 
> *session)
>  #ifdef ENABLE_LZO_STUB
>        buf_printf (&out, "IV_LZO_STUB=1\n");
>  #endif
> +      /* support for P_DATA_V2 */
> +      buf_printf(&out, "IV_PROTO=2\n");
>  
>        if (session->opt->push_peer_info_detail >= 2)
>          {
> @@ -2777,8 +2784,9 @@ tls_pre_decrypt (struct tls_multi *multi,
>       key_id = c & P_KEY_ID_MASK;
>        }
>  
> -      if (op == P_DATA_V1)
> -     {                       /* data channel packet */
> +      if ((op == P_DATA_V1) || (op == P_DATA_V2))
> +     {
> +       /* data channel packet */
>         for (i = 0; i < KEY_SCAN_SIZE; ++i)
>           {
>             struct key_state *ks = multi->key_scan[i];
> @@ -2810,7 +2818,19 @@ tls_pre_decrypt (struct tls_multi *multi,
>                 opt->pid_persist = NULL;
>                 opt->flags &= multi->opt.crypto_flags_and;
>                 opt->flags |= multi->opt.crypto_flags_or;
> +
>                 ASSERT (buf_advance (buf, 1));
> +               if (op == P_DATA_V2)
> +                 {
> +                   if (buf->len < 4)
> +                     {
> +                       msg (D_TLS_ERRORS, "Protocol error: received 
> P_DATA_V2 from %s but length is < 4",
> +                             print_link_socket_actual (from, &gc));
> +                       goto error;
> +                     }
> +                   ASSERT (buf_advance (buf, 3));
> +                 }
> +
>                 ++ks->n_packets;
>                 ks->n_bytes += buf->len;
>                 dmsg (D_TLS_KEYSELECT,
> @@ -3375,14 +3395,24 @@ tls_post_encrypt (struct tls_multi *multi, struct 
> buffer *buf)
>  {
>    struct key_state *ks;
>    uint8_t *op;
> +  uint32_t peer;
>  
>    ks = multi->save_ks;
>    multi->save_ks = NULL;
>    if (buf->len > 0)
>      {
>        ASSERT (ks);
> -      ASSERT (op = buf_prepend (buf, 1));
> -      *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
> +
> +      if (!multi->opt.server && multi->use_peer_id)
> +     {
> +       peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | 
> (multi->peer_id & 0xFFFFFF));
> +       ASSERT (buf_write_prepend (buf, &peer, 4));
> +     }
> +      else
> +     {
> +       ASSERT (op = buf_prepend (buf, 1));
> +       *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
> +     }
>        ++ks->n_packets;
>        ks->n_bytes += buf->len;
>      }
> @@ -3489,7 +3519,7 @@ protocol_dump (struct buffer *buffer, unsigned int 
> flags, struct gc_arena *gc)
>    key_id = c & P_KEY_ID_MASK;
>    buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id);
>  
> -  if (op == P_DATA_V1)
> +  if ((op == P_DATA_V1) || (op == P_DATA_V2))
>      goto print_data;
>  
>    /*
> diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
> index cd7cae2..6a14768 100644
> --- a/src/openvpn/ssl.h
> +++ b/src/openvpn/ssl.h
> @@ -61,6 +61,7 @@
>  #define P_CONTROL_V1                   4     /* control channel packet 
> (usually TLS ciphertext) */
>  #define P_ACK_V1                       5     /* acknowledgement for packets 
> received */
>  #define P_DATA_V1                      6     /* data channel packet */
> +#define P_DATA_V2                      9     /* data channel packet with 
> peer-id */
>  
>  /* indicates key_method >= 2 */
>  #define P_CONTROL_HARD_RESET_CLIENT_V2 7     /* initial key from client, 
> forget previous state */
> @@ -68,7 +69,7 @@
>  
>  /* define the range of legal opcodes */
>  #define P_FIRST_OPCODE                 1
> -#define P_LAST_OPCODE                  8
> +#define P_LAST_OPCODE                  9
>  
>  /* Should we aggregate TLS
>   * acknowledgements, and tack them onto
> diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
> index ba10459..224df9d 100644
> --- a/src/openvpn/ssl_common.h
> +++ b/src/openvpn/ssl_common.h
> @@ -490,6 +490,10 @@ struct tls_multi
>    time_t tas_last;
>  #endif
>  
> +  /* For P_DATA_V2 */
> +  uint32_t peer_id;
> +  bool use_peer_id;
> +
>    /*
>     * Our session objects.
>     */
> 

Reply via email to