Peer-id patch v2
PATCH 1/1 Peer-id patch v2
Added new packet format P_DATA_V2, which includes peer-id. If server supports, client sends all data packets in the new format. When data packet arrives, server identifies peer by peer-id. If peer's ip/port has changed, server assumes that client has floated, verifies HMAC and updates ip/port in internal structs.
--- src/openvpn/crypto.c | 66 ++++++++++++++++++++-------- src/openvpn/crypto.h | 3 ++ src/openvpn/init.c | 10 ++++- src/openvpn/mudp.c | 111 +++++++++++++++++++++++++++++++++++++++++------ src/openvpn/multi.c | 6 +++ src/openvpn/multi.h | 2 + src/openvpn/options.c | 9 +++- src/openvpn/options.h | 8 +++- src/openvpn/push.c | 16 ++++++- src/openvpn/ssl.c | 66 +++++++++++++++++++++++++--- src/openvpn/ssl.h | 9 +++- src/openvpn/ssl_common.h | 4 ++ 12 files changed, 269 insertions(+), 41 deletions(-)
src/openvpn/crypto.c +48 -18
@@ -223,6 +223,30 @@ err:return ; } +int verify_hmac (struct buffer *buf,struct key_ctx *ctx,int offset) +{ +uint8_t local_hmac[MAX_HMAC_KEY_LENGTH ];/* HMAC of ciphertext computed locally */ +int hmac_len =0 ; + +hmac_ctx_reset (ctx->hmac); +/* Assume the length of the input HMAC */ + hmac_len =hmac_ctx_size (ctx->hmac); + +/* Authentication fails if insufficient data in packet for HMAC */ +if (buf->len - offset < hmac_len) +return 0 ; + +hmac_ctx_update (ctx->hmac,BPTR (buf) + hmac_len + offset, +BLEN (buf) - hmac_len - offset); +hmac_ctx_final (ctx->hmac, local_hmac); + +/* Compare locally computed HMAC with packet HMAC */ +if (memcmp_constant_time (local_hmac,BPTR (buf) + offset, hmac_len) ==0 ) +return hmac_len; + +return 0 ; +} +/* * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet. *
@@ -249,25 +273,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,/* Verify the HMAC */ if (ctx->hmac) { -int hmac_len; -uint8_t local_hmac[MAX_HMAC_KEY_LENGTH ];/* HMAC of ciphertext computed locally */ - -hmac_ctx_reset (ctx->hmac); - -/* Assume the length of the input HMAC */ - hmac_len =hmac_ctx_size (ctx->hmac); - -/* Authentication fails if insufficient data in packet for HMAC */ -if (buf->len < hmac_len) -CRYPT_ERROR ("missing authentication info" ); - -hmac_ctx_update (ctx->hmac,BPTR (buf) + hmac_len,BLEN (buf) - hmac_len); -hmac_ctx_final (ctx->hmac, local_hmac); - -/* Compare locally computed HMAC with packet HMAC */ -if (memcmp_constant_time (local_hmac,BPTR (buf), hmac_len)) +int hmac_len =verify_hmac (buf, ctx,0 ); +if (hmac_len ==0 )CRYPT_ERROR ("packet HMAC authentication failed" ); -ASSERT (buf_advance (buf, hmac_len)); }
@@ -392,6 +400,28 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, }/* +* This verifies if a packet and its HMAC fit to a crypto context. +* +* On success true is returned. +*/ +bool +crypto_test_hmac (struct buffer *buf,const struct crypto_options *opt) +{ +if (buf->len >0 && opt->key_ctx_bi) + { +struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; + +/* Verify the HMAC */ +if (ctx->hmac) + { +/* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */ +return verify_hmac (buf, ctx,sizeof (uint32_t )) !=0 ; + } + } +return false; +} + +/* * How many bytes will we add to frame buffer for a given * set of crypto options? */
src/openvpn/crypto.h +3 -0
@@ -275,6 +275,9 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,const struct crypto_options *opt, const struct frame* frame); + +bool crypto_test_hmac (struct buffer *buf,const struct crypto_options *opt); +/** @} name Functions for performing security operations on data channel packets */ void crypto_adjust_frame_parameters(struct frame *frame,
src/openvpn/init.c +9 -1
@@ -1718,7 +1718,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 );
@@ -1795,6 +1796,13 @@ 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" ); + +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; + } }/*
src/openvpn/mudp.c +98 -13
140 lines not on this page · raw message
src/openvpn/multi.c +6 -0
@@ -373,6 +373,8 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa*/ m->max_clients = t->options.max_clients; + m->instances =calloc (m->max_clients,sizeof (struct multi_instance *)); +/* * Initialize multi-socket TCP I/O wait object */
@@ -553,6 +555,8 @@ multi_close_instance (struct multi_context *m, }#endif + m->instances[mi->context.c2.tls_multi->peer_id] =NULL ; +schedule_remove_entry (m->schedule, (struct schedule_entry *) mi);ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle, false);
@@ -629,6 +633,8 @@ multi_uninit (struct multi_context *m)#endif m->hash =NULL ; +free (m->instances); +schedule_free (m->schedule);mbuf_free (m->mbuf);ifconfig_pool_free (m->ifconfig_pool);
src/openvpn/multi.h +2 -0
@@ -125,6 +125,8 @@ struct multi_context {# define MC_WORK_THREAD (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)int thread_mode; +struct multi_instance ** instances; +struct hash *hash;/**< VPN tunnel instances indexed by real * address of the remote peer. */ struct hash *vhash;/**< VPN tunnel instances indexed by
src/openvpn/options.c +8 -1
@@ -3906,7 +3906,8 @@ apply_push_options (struct options *options,struct buffer *buf, unsigned int permission_mask, unsigned int *option_types_found, - struct env_set *es) + struct env_set *es, + struct tls_multi *tls_multi) { char line[OPTION_PARM_SIZE];int line_num =0 ;
@@ -6985,6 +6986,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;
src/openvpn/options.h +7 -1
@@ -598,6 +598,9 @@ struct optionsbool show_net_up;int route_method;#endif + +bool use_peer_id; +uint32_t peer_id; };#define streq (x, y) (!strcmp((x), (y)))
@@ -633,6 +636,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))
@@ -719,11 +723,13 @@ void options_postprocess (struct options *options);void pre_pull_save (struct options *o);void pre_pull_restore (struct options *o,struct gc_arena *gc); +struct tls_multi ;bool apply_push_options (struct options *options,struct buffer *buf,unsigned int permission_mask,unsigned int *option_types_found, -struct env_set *es); +struct env_set *es, +struct tls_multi * tls_multi);void options_detach (struct options *o);
src/openvpn/push.c +15 -1
@@ -305,6 +305,19 @@ send_push_reply (struct context *c)if (multi_push)buf_printf (&buf,",push-continuation 1" ); +/* Send peer-id if client supports it */ +if (c->c2.tls_multi->peer_info) + { +const char * proto_str =strstr (c->c2.tls_multi->peer_info,"IV_PROTO=" ); +if (proto_str) + { +int proto =0 ; +int r =sscanf (proto_str,"IV_PROTO=%d" , &proto); +if ((r ==1 ) && (proto >=2 )) +buf_printf (&buf,",peer-id %d" , c->c2.tls_multi->peer_id); + } + } +if (BLEN (&buf) >sizeof (cmd)-1 ) {const bool status =send_control_channel_string (c,BSTR (&buf),D_PUSH );
@@ -464,7 +477,8 @@ process_incoming_push_msg (struct context *c, &buf, permission_mask, option_types_found, - c->c2.es)) + c->c2.es, + c->c2.tls_multi))switch (c->options.push_continuation) {case 0 :
src/openvpn/ssl.c +61 -5
121 lines not on this page · raw message
src/openvpn/ssl.h +8 -1
@@ -60,6 +60,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 */
@@ -67,7 +68,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
@@ -430,6 +431,12 @@ bool tls_send_payload (struct tls_multi *multi,bool tls_rec_payload (struct tls_multi *multi,struct buffer *buf); +/* +* Update remote address of a tls_multi structure +*/ +void tls_update_remote_addr (struct tls_multi *multi, +const struct link_socket_actual *from); +#ifdef MANAGEMENT_DEF_AUTH static inline char *tls_get_peer_info (const struct tls_multi *multi)
src/openvpn/ssl_common.h +4 -0
@@ -495,6 +495,10 @@ struct tls_multichar *peer_info;#endif +/* For P_DATA_V2 */ +uint32_t peer_id; +bool use_peer_id; +/* * Our session objects. */
Signature · 1 line
1.9.1