summaryrefslogtreecommitdiffstats
path: root/src/openvpn/ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ssl.c')
-rw-r--r--src/openvpn/ssl.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index c81659f..2adfa26 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -624,6 +624,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;
}
@@ -1826,6 +1831,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
buf_printf (&out, "IV_PLAT=win\n");
#endif
+ /* support for P_DATA_V2 */
+ buf_printf(&out, "IV_PROTO=2\n");
+
/* push compression status */
#ifdef USE_COMP
comp_generate_peer_info_string(&session->opt->comp_options, &out);
@@ -2765,7 +2773,8 @@ bool
tls_pre_decrypt (struct tls_multi *multi,
const struct link_socket_actual *from,
struct buffer *buf,
- struct crypto_options *opt)
+ struct crypto_options *opt,
+ bool floated)
{
struct gc_arena gc = gc_new ();
bool ret = false;
@@ -2783,8 +2792,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];
@@ -2808,7 +2818,7 @@ tls_pre_decrypt (struct tls_multi *multi,
#ifdef ENABLE_DEF_AUTH
&& !ks->auth_deferred
#endif
- && link_socket_actual_match (from, &ks->remote_addr))
+ && (floated || link_socket_actual_match (from, &ks->remote_addr)))
{
/* return appropriate data channel decrypt key in opt */
opt->key_ctx_bi = &ks->key;
@@ -2816,7 +2826,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,
@@ -3381,14 +3403,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;
}
@@ -3461,6 +3493,34 @@ tls_rec_payload (struct tls_multi *multi,
return ret;
}
+void
+tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual *addr)
+{
+ struct gc_arena gc = gc_new ();
+ int i, j;
+
+ for (i = 0; i < TM_SIZE; ++i)
+ {
+ struct tls_session *session = &multi->session[i];
+
+ for (j = 0; j < KS_SIZE; ++j)
+ {
+ struct key_state *ks = &session->key[j];
+
+ if (!link_socket_actual_defined(&ks->remote_addr) ||
+ link_socket_actual_match (addr, &ks->remote_addr))
+ continue;
+
+ dmsg (D_TLS_KEYSELECT, "TLS: tls_update_remote_addr from IP=%s to IP=%s",
+ print_link_socket_actual (&ks->remote_addr, &gc),
+ print_link_socket_actual (addr, &gc));
+
+ ks->remote_addr = *addr;
+ }
+ }
+ gc_free (&gc);
+}
+
/*
* Dump a human-readable rendition of an openvpn packet
* into a garbage collectable string which is returned.
@@ -3495,7 +3555,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;
/*