libtls: Don't send TLS close notifies in EAP after application succeeds
authorMartin Willi <martin@revosec.ch>
Thu, 5 Feb 2015 08:13:57 +0000 (09:13 +0100)
committerMartin Willi <martin@revosec.ch>
Thu, 19 Feb 2015 10:29:07 +0000 (11:29 +0100)
With the introduction of PT-TLS, we started sending TLS close notifies after
the application layer completes (7bbf7aa9). While this makes sense for TCP based
transports, it is not required in EAP methods. In EAP, handshake completion
can be directly signaled using the outer EAP-SUCCESS message. This also saves
one round-trip in the EAP exchange.

Windows 7/8 does not seem to like TLS close notifies at all in EAP, and either
stalls (EAP-TTLS) or disconnects (PEAP).

Fixes #556.

src/libtls/tls.c
src/libtls/tls_fragmentation.c
src/libtls/tls_fragmentation.h

index 6a8d503..2016124 100644 (file)
@@ -487,7 +487,7 @@ tls_t *tls_create(bool is_server, identification_t *server,
                                                                                this->alert, peer, server)->handshake;
        }
        this->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
-                                                                                                  this->application);
+                                                                                                  this->application, purpose);
        this->compression = tls_compression_create(this->fragmentation, this->alert);
        this->protection = tls_protection_create(this->compression, this->alert);
        this->crypto->set_protection(this->crypto, this->protection);
index 6e4347e..a97ca1e 100644 (file)
@@ -96,9 +96,32 @@ struct private_tls_fragmentation_t {
         * Upper layer application data protocol
         */
        tls_application_t *application;
+
+       /**
+        * Type of context this TLS instance runs in
+        */
+       tls_purpose_t purpose;
 };
 
 /**
+ * Check if we should send a close notify once the application finishes
+ */
+static bool send_close_notify(private_tls_fragmentation_t *this)
+{
+       switch (this->purpose)
+       {
+               case TLS_PURPOSE_EAP_TLS:
+               case TLS_PURPOSE_EAP_TTLS:
+               case TLS_PURPOSE_EAP_PEAP:
+                       /* not for TLS-in-EAP, as we indicate completion with EAP-SUCCCESS.
+                        * Windows does not like close notifies, and hangs/disconnects. */
+                       return FALSE;
+               default:
+                       return TRUE;
+       }
+}
+
+/**
  * Process a TLS alert
  */
 static status_t process_alert(private_tls_fragmentation_t *this,
@@ -223,6 +246,10 @@ static status_t process_application(private_tls_fragmentation_t *this,
                                continue;
                        case SUCCESS:
                                this->application_finished = TRUE;
+                               if (!send_close_notify(this))
+                               {
+                                       return SUCCESS;
+                               }
                                /* FALL */
                        case FAILED:
                        default:
@@ -368,6 +395,10 @@ static status_t build_application(private_tls_fragmentation_t *this)
                                break;
                        case SUCCESS:
                                this->application_finished = TRUE;
+                               if (!send_close_notify(this))
+                               {
+                                       break;
+                               }
                                /* FALL */
                        case FAILED:
                        default:
@@ -463,7 +494,8 @@ METHOD(tls_fragmentation_t, destroy, void,
  * See header
  */
 tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
-                                                       tls_alert_t *alert, tls_application_t *application)
+                                                       tls_alert_t *alert, tls_application_t *application,
+                                                       tls_purpose_t purpose)
 {
        private_tls_fragmentation_t *this;
 
@@ -478,6 +510,7 @@ tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
                .alert = alert,
                .state = ALERT_NONE,
                .application = application,
+               .purpose = purpose,
        );
 
        return &this->public;
index f650e7b..a49f27b 100644 (file)
@@ -80,9 +80,11 @@ struct tls_fragmentation_t {
  * @param handshake                    upper layer handshake protocol
  * @param alert                                TLS alert handler
  * @param application          upper layer application data or NULL
+ * @param purpose                      type of context this TLS stack is running in
  * @return                                     TLS fragmentation layer
  */
 tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
-                                                       tls_alert_t *alert, tls_application_t *application);
+                                                       tls_alert_t *alert, tls_application_t *application,
+                                                       tls_purpose_t purpose);
 
 #endif /** TLS_FRAGMENTATION_H_ @}*/