Ticket #49: peer-id-v2.patch
File peer-id-v2.patch, 17.8 KB (added by , 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: 220 220 return; 221 221 } 222 222 223 int 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 223 247 /* 224 248 * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet. 225 249 * … … openvpn_decrypt (struct buffer *buf, struct buffer work, 246 270 /* Verify the HMAC */ 247 271 if (ctx->hmac) 248 272 { 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) 266 275 CRYPT_ERROR ("packet HMAC authentication failed"); 267 268 276 ASSERT (buf_advance (buf, hmac_len)); 269 277 } 270 278 … … openvpn_decrypt (struct buffer *buf, struct buffer work, 389 397 } 390 398 391 399 /* 400 * This verifies if a packet and its HMAC fit to a crypto context. 401 * 402 * On success true is returned. 403 */ 404 bool 405 crypto_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 /* 392 422 * How many bytes will we add to frame buffer for a given 393 423 * set of crypto options? 394 424 */ -
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, 279 279 const struct crypto_options *opt, 280 280 const struct frame* frame); 281 281 282 283 bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt); 284 282 285 /** @} name Functions for performing security operations on data channel packets */ 283 286 284 287 void 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) 1748 1748 | OPT_P_MESSAGES 1749 1749 | OPT_P_EXPLICIT_NOTIFY 1750 1750 | OPT_P_ECHO 1751 | OPT_P_PULL_MODE; 1751 | OPT_P_PULL_MODE 1752 | OPT_P_PEER_ID; 1752 1753 1753 1754 if (!c->options.route_nopull) 1754 1755 flags |= (OPT_P_ROUTE | OPT_P_IPWIN32); … … do_deferred_options (struct context *c, const unsigned int found) 1825 1826 msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified"); 1826 1827 if (found & OPT_P_SETENV) 1827 1828 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 } 1828 1836 } 1829 1837 1830 1838 /* -
src/openvpn/mudp.c
diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 3468dab..cf3fd0b 100644
a b 38 38 #include "memdbg.h" 39 39 40 40 /* 41 * Update instance with new peer address 42 */ 43 void 44 update_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 /* 41 90 * Get a client instance based on real address. If 42 91 * the instance doesn't exist, create it while 43 92 * maintaining real address hash table atomicity. … … multi_get_create_instance_udp (struct multi_context *m) 56 105 struct hash_element *he; 57 106 const uint32_t hv = hash_value (hash, &real); 58 107 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; 61 112 62 if ( he)113 if (op == P_DATA_V2) 63 114 { 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 } 65 138 } 66 139 else 67 140 { 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 { 68 149 if (!m->top.c2.tls_auth_standalone 69 150 || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) 70 151 { … … multi_get_create_instance_udp (struct multi_context *m) 75 156 { 76 157 hash_add_fast (hash, bucket, &mi->real, hv, mi); 77 158 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 } 78 170 } 79 171 } 80 172 else … … multi_get_create_instance_udp (struct multi_context *m) 89 181 #ifdef ENABLE_DEBUG 90 182 if (check_debug_level (D_MULTI_DEBUG)) 91 183 { 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 101 186 dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s", 102 187 mroute_addr_print (&real, &gc), 103 188 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 372 372 */ 373 373 m->max_clients = t->options.max_clients; 374 374 375 m->instances = calloc(m->max_clients, sizeof(struct multi_instance*)); 376 375 377 /* 376 378 * Initialize multi-socket TCP I/O wait object 377 379 */ … … multi_close_instance (struct multi_context *m, 552 554 } 553 555 #endif 554 556 557 m->instances[mi->context.c2.tls_multi->peer_id] = NULL; 558 555 559 schedule_remove_entry (m->schedule, (struct schedule_entry *) mi); 556 560 557 561 ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle, false); … … multi_uninit (struct multi_context *m) 628 632 #endif 629 633 m->hash = NULL; 630 634 635 free(m->instances); 636 631 637 schedule_free (m->schedule); 632 638 mbuf_free (m->mbuf); 633 639 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 { 125 125 # define MC_WORK_THREAD (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER) 126 126 int thread_mode; 127 127 128 struct multi_instance** instances; 129 128 130 struct hash *hash; /**< VPN tunnel instances indexed by real 129 131 * address of the remote peer. */ 130 132 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, 3908 3908 struct buffer *buf, 3909 3909 unsigned int permission_mask, 3910 3910 unsigned int *option_types_found, 3911 struct env_set *es) 3911 struct env_set *es, 3912 struct tls_multi *tls_multi) 3912 3913 { 3913 3914 char line[OPTION_PARM_SIZE]; 3914 3915 int line_num = 0; … … add_option (struct options *options, 6948 6949 options->persist_mode = 1; 6949 6950 } 6950 6951 #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 } 6951 6958 else 6952 6959 { 6953 6960 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 597 597 bool show_net_up; 598 598 int route_method; 599 599 #endif 600 601 bool use_peer_id; 602 uint32_t peer_id; 600 603 }; 601 604 602 605 #define streq(x, y) (!strcmp((x), (y))) … … struct options 632 635 #define OPT_P_SOCKBUF (1<<25) 633 636 #define OPT_P_SOCKFLAGS (1<<26) 634 637 #define OPT_P_CONNECTION (1<<27) 638 #define OPT_P_PEER_ID (1<<28) 635 639 636 640 #define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) 637 641 … … void options_postprocess (struct options *options); 716 720 void pre_pull_save (struct options *o); 717 721 void pre_pull_restore (struct options *o, struct gc_arena *gc); 718 722 723 struct tls_multi; 719 724 bool apply_push_options (struct options *options, 720 725 struct buffer *buf, 721 726 unsigned int permission_mask, 722 727 unsigned int *option_types_found, 723 struct env_set *es); 728 struct env_set *es, 729 struct tls_multi* tls_multi); 724 730 725 731 void options_detach (struct options *o); 726 732 -
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) 304 304 if (multi_push) 305 305 buf_printf (&buf, ",push-continuation 1"); 306 306 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 307 320 if (BLEN (&buf) > sizeof(cmd)-1) 308 321 { 309 322 const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH); … … process_incoming_push_msg (struct context *c, 463 476 &buf, 464 477 permission_mask, 465 478 option_types_found, 466 c->c2.es)) 479 c->c2.es, 480 c->c2.tls_multi)) 467 481 switch (c->options.push_continuation) 468 482 { 469 483 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) 611 611 return "P_ACK_V1"; 612 612 case P_DATA_V1: 613 613 return "P_DATA_V1"; 614 case P_DATA_V2: 615 return "P_DATA_V2"; 614 616 default: 615 617 return "P_???"; 616 618 } … … tls_multi_init (struct tls_options *tls_options) 1037 1039 ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK]; 1038 1040 ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK]; 1039 1041 1042 /* By default not use P_DATA_V2 */ 1043 ret->use_peer_id = false; 1044 1040 1045 return ret; 1041 1046 } 1042 1047 … … push_peer_info(struct buffer *buf, struct tls_session *session) 1810 1815 buf_printf (&out, "IV_PLAT=win\n"); 1811 1816 #endif 1812 1817 1818 /* support for P_DATA_V2 */ 1819 buf_printf(&out, "IV_PROTO=2\n"); 1820 1813 1821 /* push compression status */ 1814 1822 #ifdef USE_COMP 1815 1823 comp_generate_peer_info_string(&session->opt->comp_options, &out); … … tls_pre_decrypt (struct tls_multi *multi, 2766 2774 key_id = c & P_KEY_ID_MASK; 2767 2775 } 2768 2776 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 */ 2771 2780 for (i = 0; i < KEY_SCAN_SIZE; ++i) 2772 2781 { 2773 2782 struct key_state *ks = multi->key_scan[i]; … … tls_pre_decrypt (struct tls_multi *multi, 2799 2808 opt->pid_persist = NULL; 2800 2809 opt->flags &= multi->opt.crypto_flags_and; 2801 2810 opt->flags |= multi->opt.crypto_flags_or; 2811 2802 2812 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 2803 2824 ++ks->n_packets; 2804 2825 ks->n_bytes += buf->len; 2805 2826 dmsg (D_TLS_KEYSELECT, … … tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) 3364 3385 { 3365 3386 struct key_state *ks; 3366 3387 uint8_t *op; 3388 uint32_t peer; 3367 3389 3368 3390 ks = multi->save_ks; 3369 3391 multi->save_ks = NULL; 3370 3392 if (buf->len > 0) 3371 3393 { 3372 3394 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 } 3375 3406 ++ks->n_packets; 3376 3407 ks->n_bytes += buf->len; 3377 3408 } … … tls_rec_payload (struct tls_multi *multi, 3444 3475 return ret; 3445 3476 } 3446 3477 3478 /* Update the remote_addr, needed if a client floats. */ 3479 void 3480 tls_update_remote_addr (struct tls_multi *multi, 3481 const 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 3447 3503 /* 3448 3504 * Dump a human-readable rendition of an openvpn packet 3449 3505 * into a garbage collectable string which is returned. … … protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc) 3478 3534 key_id = c & P_KEY_ID_MASK; 3479 3535 buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id); 3480 3536 3481 if ( op == P_DATA_V1)3537 if ((op == P_DATA_V1) || (op == P_DATA_V2)) 3482 3538 goto print_data; 3483 3539 3484 3540 /* -
src/openvpn/ssl.h
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index cd7cae2..b9b9615 100644
a b 61 61 #define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */ 62 62 #define P_ACK_V1 5 /* acknowledgement for packets received */ 63 63 #define P_DATA_V1 6 /* data channel packet */ 64 #define P_DATA_V2 9 /* data channel packet with peer-id */ 64 65 65 66 /* indicates key_method >= 2 */ 66 67 #define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */ … … 68 69 69 70 /* define the range of legal opcodes */ 70 71 #define P_FIRST_OPCODE 1 71 #define P_LAST_OPCODE 872 #define P_LAST_OPCODE 9 72 73 73 74 /* Should we aggregate TLS 74 75 * acknowledgements, and tack them onto … … bool tls_send_payload (struct tls_multi *multi, 431 432 bool tls_rec_payload (struct tls_multi *multi, 432 433 struct buffer *buf); 433 434 435 /* 436 * Update remote address of a tls_multi structure 437 */ 438 void tls_update_remote_addr (struct tls_multi *multi, 439 const struct link_socket_actual *from); 440 434 441 #ifdef MANAGEMENT_DEF_AUTH 435 442 static inline char * 436 443 tls_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 495 495 char *peer_info; 496 496 #endif 497 497 498 /* For P_DATA_V2 */ 499 uint32_t peer_id; 500 bool use_peer_id; 501 498 502 /* 499 503 * Our session objects. 500 504 */