]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Fixed an issue where application payload transmissions on the
authorJames Yonan <james@openvpn.net>
Tue, 27 Jul 2010 07:10:01 +0000 (07:10 +0000)
committerJames Yonan <james@openvpn.net>
Tue, 27 Jul 2010 07:10:01 +0000 (07:10 +0000)
TLS control channel (such as AUTH_FAILED) that occur during
or immediately after a TLS renegotiation might be dropped.

Version 2.1.1n

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6350 e7ae566f-a301-0410-adde-c780ea21d3b5

buffer.c
buffer.h
ssl.c
ssl.h
syshead.h
version.m4

index c7a42fbace8f37464809cfda912021122c0caba9..5108429ac8b76f975bb41ae830a844e63c12a871 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -896,8 +896,11 @@ buffer_list_new (const int max_size)
 void
 buffer_list_free (struct buffer_list *ol)
 {
-  buffer_list_reset (ol);
-  free (ol);
+  if (ol)
+    {
+      buffer_list_reset (ol);
+      free (ol);
+    }
 }
 
 bool
@@ -924,9 +927,21 @@ buffer_list_reset (struct buffer_list *ol)
 void
 buffer_list_push (struct buffer_list *ol, const unsigned char *str)
 {
-  if (!ol->max_size || ol->size < ol->max_size)
+  if (str)
+    {
+      const size_t len = strlen ((const char *)str);
+      struct buffer_entry *e = buffer_list_push_data (ol, str, len+1);
+      if (e)
+       e->buf.len = len; /* Don't count trailing '\0' as part of length */
+    }
+}
+
+struct buffer_entry *
+buffer_list_push_data (struct buffer_list *ol, const uint8_t *data, size_t size)
+{
+  struct buffer_entry *e = NULL;
+  if (data && (!ol->max_size || ol->size < ol->max_size))
     {
-      struct buffer_entry *e;
       ALLOC_OBJ_CLEAR (e, struct buffer_entry);
 
       ++ol->size;
@@ -940,15 +955,18 @@ buffer_list_push (struct buffer_list *ol, const unsigned char *str)
          ASSERT (!ol->head);
          ol->head = e;
        }
-      e->buf = string_alloc_buf ((const char *) str, NULL);
+      e->buf = alloc_buf (size);
+      memcpy (e->buf.data, data, size);
+      e->buf.len = (int)size;
       ol->tail = e;
     }
+  return e;
 }
 
 struct buffer *
 buffer_list_peek (struct buffer_list *ol)
 {
-  if (ol->head)
+  if (ol && ol->head)
     return &ol->head->buf;
   else
     return NULL;
@@ -993,10 +1011,10 @@ buffer_list_aggregate (struct buffer_list *bl, const size_t max)
     }
 }
 
-static void
+void
 buffer_list_pop (struct buffer_list *ol)
 {
-  if (ol->head)
+  if (ol && ol->head)
     {
       struct buffer_entry *e = ol->head->next;
       free_buf (&ol->head->buf);
index 9351c4e1b15e608efb4cbb99b3cb451660ee94b3..0f22cda4070a6f8a8cae047df7dfd5aba8908667 100644 (file)
--- a/buffer.h
+++ b/buffer.h
@@ -851,8 +851,10 @@ bool buffer_list_defined (const struct buffer_list *ol);
 void buffer_list_reset (struct buffer_list *ol);
 
 void buffer_list_push (struct buffer_list *ol, const unsigned char *str);
+struct buffer_entry *buffer_list_push_data (struct buffer_list *ol, const uint8_t *data, size_t size);
 struct buffer *buffer_list_peek (struct buffer_list *ol);
 void buffer_list_advance (struct buffer_list *ol, int n);
+void buffer_list_pop (struct buffer_list *ol);
 
 void buffer_list_aggregate (struct buffer_list *bl, const size_t max);
 
diff --git a/ssl.c b/ssl.c
index 9801b0eb9907b20687889cdaf87e18d0b38f522e..a14064162621909899837cd9f5b2b9f443f1ceb7 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -2266,6 +2266,7 @@ key_state_free (struct key_state *ks, bool clear)
   free_buf (&ks->plaintext_read_buf);
   free_buf (&ks->plaintext_write_buf);
   free_buf (&ks->ack_write_buf);
+  buffer_list_free(ks->paybuf);
 
   if (ks->send_reliable)
     {
@@ -3064,6 +3065,17 @@ key_source2_read (struct key_source2 *k2,
   return 1;
 }
 
+static void
+flush_payload_buffer (struct tls_multi *multi, struct key_state *ks)
+{
+  struct buffer *b;
+  while ((b = buffer_list_peek (ks->paybuf)))
+    {
+      key_state_write_plaintext_const (multi, ks, b->data, b->len);
+      buffer_list_pop (ks->paybuf);
+    }
+}
+
 /*
  * Macros for key_state_soft_reset & tls_process
  */
@@ -3978,6 +3990,9 @@ tls_process (struct tls_multi *multi,
                  /* Set outgoing address for data channel packets */
                  link_socket_set_outgoing_addr (NULL, to_link_socket_info, &ks->remote_addr, session->common_name, session->opt->es);
 
+                 /* Flush any payload packets that were buffered before our state transitioned to S_ACTIVE */
+                 flush_payload_buffer (multi, ks);
+
 #ifdef MEASURE_TLS_HANDSHAKE_STATS
                  show_tls_performance_stats();
 #endif
@@ -5077,6 +5092,13 @@ tls_send_payload (struct tls_multi *multi,
       if (key_state_write_plaintext_const (multi, ks, data, size) == 1)
        ret = true;
     }
+  else
+    {
+      if (!ks->paybuf)
+       ks->paybuf = buffer_list_new (0);
+      buffer_list_push_data (ks->paybuf, data, (size_t)size);
+      ret = true;
+    }
 
   ERR_clear_error ();
 
diff --git a/ssl.h b/ssl.h
index e895bb20305ce4c69007315b4f1896471113d070..c6a5627f0296b02497278795a268e5b49f88fb01 100644 (file)
--- a/ssl.h
+++ b/ssl.h
@@ -376,6 +376,8 @@ struct key_state
   struct reliable *rec_reliable;  /* order incoming ciphertext packets before we pass to TLS */
   struct reliable_ack *rec_ack;          /* buffers all packet IDs we want to ACK back to sender */
 
+  struct buffer_list *paybuf;
+
   int n_bytes;                  /* how many bytes sent/recvd since last key exchange */
   int n_packets;                /* how many packets sent/recvd since last key exchange */
 
index d2ea8de60012d47bf0537d7f2493ecf242a9cd4f..15445fc4da7e5f2e94e43798644d8a93536265c4 100644 (file)
--- a/syshead.h
+++ b/syshead.h
@@ -531,11 +531,9 @@ socket_defined (const socket_descriptor_t sd)
 #endif
 
 /*
- * Don't compile the struct buffer_list code unless something needs it
+ * Compile the struct buffer_list code
  */
-#if defined(ENABLE_MANAGEMENT) || defined(ENABLE_PF)
 #define ENABLE_BUFFER_LIST
-#endif
 
 /*
  * Do we have pthread capability?
index b6d1f61f1d5280a7029a6b3591332edb6f2d8408..be40252d9dc08bb8a29ba4ddf66887021d71c263 100644 (file)
@@ -1,5 +1,5 @@
 dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1.1m])
+define(PRODUCT_VERSION,[2.1.1n])
 dnl define the TAP version
 define(PRODUCT_TAP_ID,[tap0901])
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])