Ticket #49: peer-id-v2.patch

File peer-id-v2.patch, 17.8 KB (added by stipa, 9 years ago)
  • src/openvpn/crypto.c

    diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
    index c4c356d..89aa666 100644
    a b err: 
    220220  return;
    221221}
    222222
     223int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset)
     224{
     225  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
     226  int hmac_len = 0;
     227
     228  hmac_ctx_reset(ctx->hmac);
     229  /* Assume the length of the input HMAC */
     230  hmac_len = hmac_ctx_size (ctx->hmac);
     231
     232  /* Authentication fails if insufficient data in packet for HMAC */
     233  if (buf->len - offset < hmac_len)
     234    return 0;
     235
     236  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset,
     237        BLEN (buf) - hmac_len - offset);
     238  hmac_ctx_final (ctx->hmac, local_hmac);
     239
     240  /* Compare locally computed HMAC with packet HMAC */
     241  if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0)
     242    return hmac_len;
     243
     244  return 0;
     245}
     246
    223247/*
    224248 * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.
    225249 *
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    246270      /* Verify the HMAC */
    247271      if (ctx->hmac)
    248272        {
    249           int hmac_len;
    250           uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
    251 
    252           hmac_ctx_reset(ctx->hmac);
    253 
    254           /* Assume the length of the input HMAC */
    255           hmac_len = hmac_ctx_size (ctx->hmac);
    256 
    257           /* Authentication fails if insufficient data in packet for HMAC */
    258           if (buf->len < hmac_len)
    259             CRYPT_ERROR ("missing authentication info");
    260 
    261           hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len);
    262           hmac_ctx_final (ctx->hmac, local_hmac);
    263 
    264           /* Compare locally computed HMAC with packet HMAC */
    265           if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len))
     273          int hmac_len = verify_hmac(buf, ctx, 0);
     274          if (hmac_len == 0)
    266275            CRYPT_ERROR ("packet HMAC authentication failed");
    267 
    268276          ASSERT (buf_advance (buf, hmac_len));
    269277        }
    270278
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    389397}
    390398
    391399/*
     400 * This verifies if a packet and its HMAC fit to a crypto context.
     401 *
     402 * On success true is returned.
     403 */
     404bool
     405crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt)
     406{
     407  if (buf->len > 0 && opt->key_ctx_bi)
     408    {
     409      struct key_ctx *ctx = &opt->key_ctx_bi->decrypt;
     410
     411      /* Verify the HMAC */
     412      if (ctx->hmac)
     413        {
     414          /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */
     415          return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0;
     416        }
     417    }
     418  return false;
     419}
     420
     421/*
    392422 * How many bytes will we add to frame buffer for a given
    393423 * set of crypto options?
    394424 */
  • src/openvpn/crypto.h

    diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
    index 3b4b88e..68cdf16 100644
    a b bool openvpn_decrypt (struct buffer *buf, struct buffer work, 
    279279                      const struct crypto_options *opt,
    280280                      const struct frame* frame);
    281281
     282
     283bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt);
     284
    282285/** @} name Functions for performing security operations on data channel packets */
    283286
    284287void crypto_adjust_frame_parameters(struct frame *frame,
  • src/openvpn/init.c

    diff --git a/src/openvpn/init.c b/src/openvpn/init.c
    index 3b72b96..a92d717 100644
    a b pull_permission_mask (const struct context *c) 
    17481748    | OPT_P_MESSAGES
    17491749    | OPT_P_EXPLICIT_NOTIFY
    17501750    | OPT_P_ECHO
    1751     | OPT_P_PULL_MODE;
     1751    | OPT_P_PULL_MODE
     1752    | OPT_P_PEER_ID;
    17521753
    17531754  if (!c->options.route_nopull)
    17541755    flags |= (OPT_P_ROUTE | OPT_P_IPWIN32);
    do_deferred_options (struct context *c, const unsigned int found) 
    18251826    msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified");
    18261827  if (found & OPT_P_SETENV)
    18271828    msg (D_PUSH, "OPTIONS IMPORT: environment modified");
     1829
     1830  if (found & OPT_P_PEER_ID)
     1831    {
     1832      msg (D_PUSH, "OPTIONS IMPORT: peer-id set");
     1833      c->c2.tls_multi->use_peer_id = true;
     1834      c->c2.tls_multi->peer_id = c->options.peer_id;
     1835    }
    18281836}
    18291837
    18301838/*
  • src/openvpn/mudp.c

    diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c
    index 3468dab..cf3fd0b 100644
    a b  
    3838#include "memdbg.h"
    3939
    4040/*
     41 * Update instance with new peer address
     42 */
     43void
     44update_floated(struct multi_context *m, struct multi_instance *mi,
     45               struct mroute_addr real, uint32_t hv)
     46{
     47  struct mroute_addr real_old;
     48
     49  real_old = mi->real;
     50  generate_prefix (mi);
     51
     52  /* remove before modifying mi->real, since it also modifies key in hash */
     53  hash_remove(m->hash, &real_old);
     54  hash_remove(m->iter, &real_old);
     55
     56  /* update address */
     57  memcpy(&mi->real, &real, sizeof(real));
     58
     59  mi->context.c2.from = m->top.c2.from;
     60  mi->context.c2.to_link_addr = &mi->context.c2.from;
     61
     62  /* switch to new log prefix */
     63  generate_prefix (mi);
     64  /* inherit buffers */
     65  mi->context.c2.buffers = m->top.c2.buffers;
     66
     67  /* inherit parent link_socket and link_socket_info */
     68  mi->context.c2.link_socket = m->top.c2.link_socket;
     69  mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from;
     70
     71  /* fix remote_addr in tls structure */
     72  tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from);
     73  mi->did_open_context = true;
     74
     75  hash_add(m->hash, &mi->real, mi, false);
     76  hash_add(m->iter, &mi->real, mi, false);
     77
     78  mi->did_real_hash = true;
     79#ifdef MANAGEMENT_DEF_AUTH
     80  hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid);
     81  hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false);
     82#endif
     83
     84#ifdef MANAGEMENT_DEF_AUTH
     85  mi->did_cid_hash = true;
     86#endif
     87}
     88
     89/*
    4190 * Get a client instance based on real address.  If
    4291 * the instance doesn't exist, create it while
    4392 * maintaining real address hash table atomicity.
    multi_get_create_instance_udp (struct multi_context *m) 
    56105      struct hash_element *he;
    57106      const uint32_t hv = hash_value (hash, &real);
    58107      struct hash_bucket *bucket = hash_bucket (hash, hv);
    59  
    60       he = hash_lookup_fast (hash, bucket, &real, hv);
     108      uint8_t* ptr = BPTR(&m->top.c2.buf);
     109      uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
     110      uint32_t peer_id;
     111      bool hmac_mismatch = false;
    61112
    62       if (he)
     113      if (op == P_DATA_V2)
    63114        {
    64           mi = (struct multi_instance *) he->value;
     115          peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF;
     116          if ((peer_id < m->max_clients) && (m->instances[peer_id]))
     117            {
     118              mi = m->instances[peer_id];
     119
     120              if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))
     121                {
     122                  msg(D_MULTI_MEDIUM, "float from %s to %s",
     123                        print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc));
     124
     125                  /* peer-id is not trusted, so check hmac */
     126                  hmac_mismatch = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));
     127                  if (hmac_mismatch)
     128                    {
     129                      mi = NULL;
     130                      msg (D_MULTI_MEDIUM, "HMAC mismatch for peer-id %d", peer_id);
     131                    }
     132                  else
     133                    {
     134                      update_floated(m, mi, real, hv);
     135                    }
     136                }
     137            }
    65138        }
    66139      else
    67140        {
     141          he = hash_lookup_fast (hash, bucket, &real, hv);
     142          if (he)
     143            {
     144              mi = (struct multi_instance *) he->value;
     145            }
     146        }
     147      if (!mi && !hmac_mismatch)
     148        {
    68149          if (!m->top.c2.tls_auth_standalone
    69150              || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
    70151            {
    multi_get_create_instance_udp (struct multi_context *m) 
    75156                    {
    76157                      hash_add_fast (hash, bucket, &mi->real, hv, mi);
    77158                      mi->did_real_hash = true;
     159
     160                      int i;
     161                      for (i = 0; i < m->max_clients; ++ i)
     162                        {
     163                          if (!m->instances[i])
     164                            {
     165                              mi->context.c2.tls_multi->peer_id = i;
     166                              m->instances[i] = mi;
     167                              break;
     168                            }
     169                        }
    78170                    }
    79171                }
    80172              else
    multi_get_create_instance_udp (struct multi_context *m) 
    89181#ifdef ENABLE_DEBUG
    90182      if (check_debug_level (D_MULTI_DEBUG))
    91183        {
    92           const char *status;
    93 
    94           if (he && mi)
    95             status = "[succeeded]";
    96           else if (!he && mi)
    97             status = "[created]";
    98           else
    99             status = "[failed]";
    100        
     184          const char *status = mi ? "[ok]" : "[failed]";
     185
    101186          dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
    102187               mroute_addr_print (&real, &gc),
    103188               status);
  • src/openvpn/multi.c

    diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
    index 2839b30..8861909 100644
    a b multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa 
    372372   */
    373373  m->max_clients = t->options.max_clients;
    374374
     375  m->instances = calloc(m->max_clients, sizeof(struct multi_instance*));
     376
    375377  /*
    376378   * Initialize multi-socket TCP I/O wait object
    377379   */
    multi_close_instance (struct multi_context *m, 
    552554        }
    553555#endif
    554556
     557      m->instances[mi->context.c2.tls_multi->peer_id] = NULL;
     558
    555559      schedule_remove_entry (m->schedule, (struct schedule_entry *) mi);
    556560
    557561      ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle, false);
    multi_uninit (struct multi_context *m) 
    628632#endif
    629633          m->hash = NULL;
    630634
     635          free(m->instances);
     636
    631637          schedule_free (m->schedule);
    632638          mbuf_free (m->mbuf);
    633639          ifconfig_pool_free (m->ifconfig_pool);
  • src/openvpn/multi.h

    diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h
    index fc2ffb2..0446fbf 100644
    a b struct multi_context { 
    125125# define MC_WORK_THREAD                (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)
    126126  int thread_mode;
    127127
     128  struct multi_instance** instances;
     129
    128130  struct hash *hash;            /**< VPN tunnel instances indexed by real
    129131                                 *   address of the remote peer. */
    130132  struct hash *vhash;           /**< VPN tunnel instances indexed by
  • src/openvpn/options.c

    diff --git a/src/openvpn/options.c b/src/openvpn/options.c
    index ef6170c..5088994 100644
    a b apply_push_options (struct options *options, 
    39083908                    struct buffer *buf,
    39093909                    unsigned int permission_mask,
    39103910                    unsigned int *option_types_found,
    3911                     struct env_set *es)
     3911                    struct env_set *es,
     3912                    struct tls_multi *tls_multi)
    39123913{
    39133914  char line[OPTION_PARM_SIZE];
    39143915  int line_num = 0;
    add_option (struct options *options, 
    69486949      options->persist_mode = 1;
    69496950    }
    69506951#endif
     6952  else if (streq (p[0], "peer-id"))
     6953    {
     6954      VERIFY_PERMISSION (OPT_P_PEER_ID);
     6955      options->use_peer_id = true;
     6956      options->peer_id = atoi(p[1]);
     6957    }
    69516958  else
    69526959    {
    69536960      int i;
  • src/openvpn/options.h

    diff --git a/src/openvpn/options.h b/src/openvpn/options.h
    index 27bbc14..8897745 100644
    a b struct options 
    597597  bool show_net_up;
    598598  int route_method;
    599599#endif
     600
     601  bool use_peer_id;
     602  uint32_t peer_id;
    600603};
    601604
    602605#define streq(x, y) (!strcmp((x), (y)))
    struct options 
    632635#define OPT_P_SOCKBUF         (1<<25)
    633636#define OPT_P_SOCKFLAGS       (1<<26)
    634637#define OPT_P_CONNECTION      (1<<27)
     638#define OPT_P_PEER_ID         (1<<28)
    635639
    636640#define OPT_P_DEFAULT   (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
    637641
    void options_postprocess (struct options *options); 
    716720void pre_pull_save (struct options *o);
    717721void pre_pull_restore (struct options *o, struct gc_arena *gc);
    718722
     723struct tls_multi;
    719724bool apply_push_options (struct options *options,
    720725                         struct buffer *buf,
    721726                         unsigned int permission_mask,
    722727                         unsigned int *option_types_found,
    723                          struct env_set *es);
     728                         struct env_set *es,
     729                         struct tls_multi* tls_multi);
    724730
    725731void options_detach (struct options *o);
    726732
  • src/openvpn/push.c

    diff --git a/src/openvpn/push.c b/src/openvpn/push.c
    index 606bb05..8a8c96c 100644
    a b send_push_reply (struct context *c) 
    304304  if (multi_push)
    305305    buf_printf (&buf, ",push-continuation 1");
    306306
     307  /* Send peer-id if client supports it */
     308  if (c->c2.tls_multi->peer_info)
     309    {
     310      const char* proto_str = strstr(c->c2.tls_multi->peer_info, "IV_PROTO=");
     311      if (proto_str)
     312        {
     313          int proto = 0;
     314          int r = sscanf(proto_str, "IV_PROTO=%d", &proto);
     315          if ((r == 1) && (proto >= 2))
     316            buf_printf(&buf, ",peer-id %d", c->c2.tls_multi->peer_id);
     317        }
     318  }
     319
    307320  if (BLEN (&buf) > sizeof(cmd)-1)
    308321    {
    309322      const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
    process_incoming_push_msg (struct context *c, 
    463476                                  &buf,
    464477                                  permission_mask,
    465478                                  option_types_found,
    466                                   c->c2.es))
     479                                  c->c2.es,
     480                                  c->c2.tls_multi))
    467481            switch (c->options.push_continuation)
    468482              {
    469483              case 0:
  • src/openvpn/ssl.c

    diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
    index c61701a..7ae59c2 100644
    a b packet_opcode_name (int op) 
    611611      return "P_ACK_V1";
    612612    case P_DATA_V1:
    613613      return "P_DATA_V1";
     614    case P_DATA_V2:
     615      return "P_DATA_V2";
    614616    default:
    615617      return "P_???";
    616618    }
    tls_multi_init (struct tls_options *tls_options) 
    10371039  ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK];
    10381040  ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];
    10391041
     1042  /* By default not use P_DATA_V2 */
     1043  ret->use_peer_id = false;
     1044
    10401045  return ret;
    10411046}
    10421047
    push_peer_info(struct buffer *buf, struct tls_session *session) 
    18101815      buf_printf (&out, "IV_PLAT=win\n");
    18111816#endif
    18121817
     1818      /* support for P_DATA_V2 */
     1819      buf_printf(&out, "IV_PROTO=2\n");
     1820
    18131821      /* push compression status */
    18141822#ifdef USE_COMP
    18151823      comp_generate_peer_info_string(&session->opt->comp_options, &out);
    tls_pre_decrypt (struct tls_multi *multi, 
    27662774        key_id = c & P_KEY_ID_MASK;
    27672775      }
    27682776
    2769       if (op == P_DATA_V1)
    2770         {                       /* data channel packet */
     2777      if ((op == P_DATA_V1) || (op == P_DATA_V2))
     2778        {
     2779          /* data channel packet */
    27712780          for (i = 0; i < KEY_SCAN_SIZE; ++i)
    27722781            {
    27732782              struct key_state *ks = multi->key_scan[i];
    tls_pre_decrypt (struct tls_multi *multi, 
    27992808                  opt->pid_persist = NULL;
    28002809                  opt->flags &= multi->opt.crypto_flags_and;
    28012810                  opt->flags |= multi->opt.crypto_flags_or;
     2811
    28022812                  ASSERT (buf_advance (buf, 1));
     2813                  if (op == P_DATA_V2)
     2814                    {
     2815                      if (buf->len < 4)
     2816                        {
     2817                          msg (D_TLS_ERRORS, "Protocol error: received P_DATA_V2 from %s but length is < 4",
     2818                                print_link_socket_actual (from, &gc));
     2819                          goto error;
     2820                        }
     2821                      ASSERT (buf_advance (buf, 3));
     2822                    }
     2823
    28032824                  ++ks->n_packets;
    28042825                  ks->n_bytes += buf->len;
    28052826                  dmsg (D_TLS_KEYSELECT,
    tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) 
    33643385{
    33653386  struct key_state *ks;
    33663387  uint8_t *op;
     3388  uint32_t peer;
    33673389
    33683390  ks = multi->save_ks;
    33693391  multi->save_ks = NULL;
    33703392  if (buf->len > 0)
    33713393    {
    33723394      ASSERT (ks);
    3373       ASSERT (op = buf_prepend (buf, 1));
    3374       *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
     3395
     3396      if (!multi->opt.server && multi->use_peer_id)
     3397        {
     3398          peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF));
     3399          ASSERT (buf_write_prepend (buf, &peer, 4));
     3400        }
     3401      else
     3402        {
     3403          ASSERT (op = buf_prepend (buf, 1));
     3404          *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
     3405        }
    33753406      ++ks->n_packets;
    33763407      ks->n_bytes += buf->len;
    33773408    }
    tls_rec_payload (struct tls_multi *multi, 
    34443475  return ret;
    34453476}
    34463477
     3478/* Update the remote_addr, needed if a client floats. */
     3479void
     3480tls_update_remote_addr (struct tls_multi *multi,
     3481const struct link_socket_actual *from)
     3482{
     3483  struct gc_arena gc = gc_new ();
     3484  int i;
     3485
     3486  for (i = 0; i < KEY_SCAN_SIZE; ++i)
     3487    {
     3488      struct key_state *ks = multi->key_scan[i];
     3489      if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr))
     3490       {
     3491         if (link_socket_actual_match (from, &ks->remote_addr))
     3492           continue;
     3493         dmsg (D_TLS_KEYSELECT,
     3494                "TLS: tls_update_remote_addr from IP=%s to IP=%s",
     3495               print_link_socket_actual (&ks->remote_addr, &gc),
     3496               print_link_socket_actual (from, &gc));
     3497         memcpy(&ks->remote_addr, from, sizeof(*from));
     3498       }
     3499    }
     3500  gc_free (&gc);
     3501}
     3502
    34473503/*
    34483504 * Dump a human-readable rendition of an openvpn packet
    34493505 * into a garbage collectable string which is returned.
    protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc) 
    34783534  key_id = c & P_KEY_ID_MASK;
    34793535  buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id);
    34803536
    3481   if (op == P_DATA_V1)
     3537  if ((op == P_DATA_V1) || (op == P_DATA_V2))
    34823538    goto print_data;
    34833539
    34843540  /*
  • src/openvpn/ssl.h

    diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
    index cd7cae2..b9b9615 100644
    a b  
    6161#define P_CONTROL_V1                   4     /* control channel packet (usually TLS ciphertext) */
    6262#define P_ACK_V1                       5     /* acknowledgement for packets received */
    6363#define P_DATA_V1                      6     /* data channel packet */
     64#define P_DATA_V2                      9     /* data channel packet with peer-id */
    6465
    6566/* indicates key_method >= 2 */
    6667#define P_CONTROL_HARD_RESET_CLIENT_V2 7     /* initial key from client, forget previous state */
     
    6869
    6970/* define the range of legal opcodes */
    7071#define P_FIRST_OPCODE                 1
    71 #define P_LAST_OPCODE                  8
     72#define P_LAST_OPCODE                  9
    7273
    7374/* Should we aggregate TLS
    7475 * acknowledgements, and tack them onto
    bool tls_send_payload (struct tls_multi *multi, 
    431432bool tls_rec_payload (struct tls_multi *multi,
    432433                      struct buffer *buf);
    433434
     435/*
     436 * Update remote address of a tls_multi structure
     437 */
     438void tls_update_remote_addr (struct tls_multi *multi,
     439                             const struct link_socket_actual *from);
     440
    434441#ifdef MANAGEMENT_DEF_AUTH
    435442static inline char *
    436443tls_get_peer_info(const struct tls_multi *multi)
  • src/openvpn/ssl_common.h

    diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
    index 04ba789..cb0ba62 100644
    a b struct tls_multi 
    495495  char *peer_info;
    496496#endif
    497497
     498  /* For P_DATA_V2 */
     499  uint32_t peer_id;
     500  bool use_peer_id;
     501
    498502  /*
    499503   * Our session objects.
    500504   */