Implemented PB-TNC mutual half-duplex protocol
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 22 Mar 2015 00:07:31 +0000 (01:07 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 23 Mar 2015 21:25:43 +0000 (22:25 +0100)
NEWS
src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
src/libtnccs/plugins/tnccs_20/tnccs_20.c
src/libtnccs/plugins/tnccs_20/tnccs_20_client.c
src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h
src/libtnccs/plugins/tnccs_20/tnccs_20_server.c

diff --git a/NEWS b/NEWS
index e6efa66..81a7fc5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,10 @@ strongswan-5.3.0
   as seen by the TNC server available to all IMVs. This information can be
   forwarded to policy enforcement points (e.g. firewalls or routers).
 
+- The new mutual tnccs-20 plugin parameter activates mutual TNC measurements
+  in PB-TNC half-duplex mode between two endpoints over either a PT-EAP or
+  PT-TLS transport medium.
+
 
 strongswan-5.2.2
 ----------------
index 859dded..ce5b481 100644 (file)
@@ -44,6 +44,7 @@ METHOD(plugin_t, get_features, int,
                PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
                        PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
                                PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+                               PLUGIN_SDEPEND(CUSTOM, "imv-manager"),
                                PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
                                PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
        };
index 33b0128..3d8615c 100644 (file)
@@ -80,7 +80,7 @@ struct private_tnccs_20_t {
        u_int32_t auth_type;
 
        /**
-        * Mutual TNC measurements
+        * Mutual PB-TNC protocol enabled
         */
        bool mutual;
 
@@ -171,12 +171,12 @@ METHOD(tnccs_t, send_msg, TNC_Result,
 METHOD(tls_t, process, status_t,
        private_tnccs_20_t *this, void *buf, size_t buflen)
 {
-       chunk_t data;
        pb_tnc_batch_t *batch;
-       bool from_server, mutual;
+       bool from_server;
        status_t status;
+       chunk_t data;
 
-       /* On arrival of first PB-TNC batch create TNC server */
+       /* On arrival of first batch from TNC client create TNC server */
        if (this->is_server && !this->tnc_server)
        {
                this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
@@ -187,25 +187,40 @@ METHOD(tls_t, process, status_t,
                        return FAILED;
                }
                this->tnccs_handler = this->tnc_server;
-               this->tnccs_handler->begin_handshake(this->tnccs_handler);
+               this->tnccs_handler->begin_handshake(this->tnccs_handler, FALSE);
        }
 
        data = chunk_create(buf, buflen);
        DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len);
        DBG3(DBG_TNC, "%B", &data);
 
-       /* Has a mutual connection been established? */
-       mutual = this->tnc_client && this->tnc_server;
-
        /* Parse the header of the received PB-TNC batch */
        batch = pb_tnc_batch_create_from_data(data);
-       status = batch->process_header(batch, !mutual, this->is_server,
+       status = batch->process_header(batch, !this->mutual, this->is_server,
                                                                   &from_server);
-       this->to_server = mutual ? from_server : !this->is_server;
 
-       /* Set active TNCCS handler */
-       this->tnccs_handler = this->to_server ? this->tnc_client : this->tnc_server;    
-       DBG2(DBG_TNC, "TNC %s is handling the connection",
+       this->to_server = this->mutual ? from_server : !this->is_server;
+
+       /* In the mutual case, first batch from TNC server requires a TNC client */
+       if (this->to_server && !this->tnc_client)
+       {
+               this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
+                                                                       this->max_batch_len, this->max_msg_len);
+               if (!this->tnc_client)
+               {
+                       batch->destroy(batch);
+                       return FAILED;
+               }
+               this->tnccs_handler = this->tnc_client;
+               this->tnccs_handler->begin_handshake(this->tnccs_handler, this->mutual);
+       }
+       else
+       {
+               /* Set active TNCCS handler for processing */
+               this->tnccs_handler = this->to_server ? this->tnc_client :
+                                                                                               this->tnc_server;
+       }
+       DBG2(DBG_TNC, "TNC %s is handling inbound connection",
                                   this->to_server ? "client" : "server");
 
        if (status == SUCCESS)
@@ -219,6 +234,40 @@ METHOD(tls_t, process, status_t,
        }
        batch->destroy(batch);
 
+       /* Has a mutual connection been established? */
+       this->mutual = this->is_server ?
+                                  this->tnc_server->get_mutual(this->tnc_server) :
+                                  this->tnc_client->get_mutual(this->tnc_client);
+
+       if (this->mutual && !this->is_server)
+       {
+               pb_tnc_state_t client_state, server_state;
+
+               client_state = !this->tnc_client ? PB_STATE_INIT :
+                                               this->tnc_client->get_state(this->tnc_client);
+               server_state = !this->tnc_server ? PB_STATE_INIT :
+                                               this->tnc_server->get_state(this->tnc_server);
+
+               /* In half-duplex mutual mode toggle the direction on the client side */
+               if ((!this->to_server && client_state != PB_STATE_DECIDED) ||
+                       ( this->to_server && server_state != PB_STATE_END))
+               {
+                       this->to_server = !this->to_server;
+               }
+               else if (client_state == PB_STATE_DECIDED &&
+                                server_state == PB_STATE_END)
+               {
+                       /* Cause the final CLOSE batch to be sent to the TNC server */
+                       this->to_server = TRUE;
+               }
+
+               /* Suppress a successful CLOSE batch coming from the TNC server */
+               if (status == SUCCESS)
+               {
+                       status = NEED_MORE;
+               }
+       }
+
        return status;
 }
 
@@ -229,10 +278,15 @@ METHOD(tls_t, build, status_t,
 
        if (this->to_server)
        {
+               DBG2(DBG_TNC, "TNC client is handling outbound connection");
+
                /* Before sending the first PB-TNC batch create TNC client */
-               if (!this->tnc_client)
+               if (this->tnc_client)
+               {
+                       this->tnccs_handler = this->tnc_client;
+               }
+               else
                {
-                       DBG2(DBG_TNC, "TNC client is handling the connection");
                        this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
                                                                                                          this->max_batch_len,
                                                                                                          this->max_msg_len);
@@ -241,15 +295,21 @@ METHOD(tls_t, build, status_t,
                                status = FAILED;
                        }
                        this->tnccs_handler = this->tnc_client;
-                       this->tnccs_handler->begin_handshake(this->tnccs_handler);              
+                       this->tnccs_handler->begin_handshake(this->tnccs_handler,
+                                                                                                this->mutual);         
                }
        }
        else
        {
+               DBG2(DBG_TNC, "TNC server is handling outbound connection");
+
                /* Before sending the first PB-TNC batch create TNC server */
-               if (!this->tnc_server)
+               if (this->tnc_server)
+               {
+                       this->tnccs_handler = this->tnc_server;
+               }
+               else
                {
-                       DBG2(DBG_TNC, "TNC server is handling the connection");
                        this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
                                                                                this->max_batch_len, this->max_msg_len,
                                                                                this->eap_transport);
@@ -258,7 +318,8 @@ METHOD(tls_t, build, status_t,
                                status = FAILED;
                        }
                        this->tnccs_handler = this->tnc_server;
-                       this->tnccs_handler->begin_handshake(this->tnccs_handler);              
+                       this->tnccs_handler->begin_handshake(this->tnccs_handler,
+                                                                                                this->mutual);         
                }
        }
        status = this->tnccs_handler->build(this->tnccs_handler, buf, buflen, msglen);
index 4fd27a7..9bfadcb 100644 (file)
@@ -110,6 +110,11 @@ struct private_tnccs_20_client_t {
         */
        bool mutual;
 
+       /**
+        * Mutual Capability message sent
+        */
+       bool sent_mutual_capability;
+
 };
 
 /**
@@ -166,20 +171,29 @@ void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg, bool *fatal_error)
        }
 }
 
-void tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg, bool *mutual)
+bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg)
 {
        pb_mutual_capability_msg_t *mutual_msg;
        uint32_t protocols;
 
+       if (!lib->settings->get_bool(lib->settings,
+                               "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
+       {
+               /* PB-TNC mutual capability disabled, ignore message */
+               return FALSE;
+       }
+
        mutual_msg = (pb_mutual_capability_msg_t*)msg;
        protocols = mutual_msg->get_protocols(mutual_msg);
 
        if (protocols & PB_MUTUAL_HALF_DUPLEX)
        {
-               *mutual = TRUE;
                DBG1(DBG_TNC, "activating mutual PB-TNC %N protocol",
                         pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX);
+               return TRUE;
        }
+
+       return FALSE;
 }
 
 /**
@@ -396,7 +410,7 @@ static void handle_ita_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *ms
        switch (msg_type.type)
        {
                case PB_ITA_MSG_MUTUAL_CAPABILITY:
-                       tnccs_20_handle_ita_mutual_capability_msg(msg, &this->mutual);
+                       this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg);
                        break;
                default:
                        break;
@@ -636,7 +650,7 @@ METHOD(tnccs_20_handler_t, build, status_t,
 }
 
 METHOD(tnccs_20_handler_t, begin_handshake, void,
-       private_tnccs_20_client_t *this)
+       private_tnccs_20_client_t *this, bool mutual)
 {
        pb_tnc_msg_t *msg;
        char *pref_lang;
@@ -645,7 +659,9 @@ METHOD(tnccs_20_handler_t, begin_handshake, void,
                                                                                TNC_CONNECTION_STATE_HANDSHAKE);
 
        /* Announce PB-TNC Mutual Capability if activated */
-       if (lib->settings->get_bool(lib->settings,
+       this->sent_mutual_capability = mutual;
+
+       if (!mutual && lib->settings->get_bool(lib->settings,
                                "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
        {
                pb_tnc_mutual_protocol_type_t protocols;
@@ -657,6 +673,7 @@ METHOD(tnccs_20_handler_t, begin_handshake, void,
                this->mutex->lock(this->mutex);
                this->messages->insert_last(this->messages, msg);
                this->mutex->unlock(this->mutex);
+               this->sent_mutual_capability = TRUE;
        }
 
        /* Create PB-TNC Language Preference message */
@@ -684,6 +701,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool,
        return this->mutual;
 }
 
+METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t,
+       private_tnccs_20_client_t *this)
+{
+       return this->state_machine->get_state(this->state_machine);
+}
+
 METHOD(tnccs_20_handler_t, add_msg, void,
        private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
 {
@@ -761,6 +784,7 @@ tnccs_20_handler_t* tnccs_20_client_create(tnccs_t *tnccs,
                                .begin_handshake = _begin_handshake,
                                .get_send_flag = _get_send_flag,
                                .get_mutual = _get_mutual,
+                               .get_state = _get_state,
                                .add_msg = _add_msg,
                                .handle_errors = _handle_errors,
                                .destroy = _destroy,
index 1e6da87..45df32f 100644 (file)
@@ -54,8 +54,10 @@ struct tnccs_20_handler_t {
 
        /**
         * Put the IMCs or IMVs into the handshake state
+        *
+        * @param mutual                TRUE if PB-TNC mutual mode is already established
         */
-       void (*begin_handshake)(tnccs_20_handler_t *this);
+       void (*begin_handshake)(tnccs_20_handler_t *this, bool mutual);
 
        /**
         * Indicates if IMCs or IMVs are allowed to send PA-TNC messages
@@ -72,6 +74,13 @@ struct tnccs_20_handler_t {
        bool (*get_mutual)(tnccs_20_handler_t *this);
 
        /**
+        * Get state of the PB-TNC protocol
+        *
+        * @return                              PB-TNC state
+        */
+       pb_tnc_state_t (*get_state)(tnccs_20_handler_t *this);
+
+       /**
         * Add a PB-PA message to the handler's message queue
         *
         * @param msg                   PB-PA message to be added
index aacb5aa..c75ecdc 100644 (file)
@@ -110,6 +110,11 @@ struct private_tnccs_20_server_t {
         */
        bool mutual;
 
+       /**
+        * Mutual Capability message sent
+        */
+       bool sent_mutual_capability;
+
 };
 
 /**
@@ -117,8 +122,7 @@ struct private_tnccs_20_server_t {
  */
 extern void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg,
                                                                                   bool *fatal_error);
-extern void tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg,
-                                                                                  bool *mutual);
+extern bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg);
 
 /**
  * If the batch type changes then delete all accumulated PB-TNC messages
@@ -224,18 +228,16 @@ static void handle_ita_message(private_tnccs_20_server_t *this, pb_tnc_msg_t *ms
        switch (msg_type.type)
        {
                case PB_ITA_MSG_MUTUAL_CAPABILITY:
-                       tnccs_20_handle_ita_mutual_capability_msg(msg, &this->mutual);
+                       this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg);
 
-                       /* Respond with PB-TNC Mutual Capability message if activated */
-                       if (this->mutual && lib->settings->get_bool(lib->settings,
-                                                               "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
+                       /* Respond with PB-TNC Mutual Capability message if necessary */
+                       if (this->mutual && !this->sent_mutual_capability)
                        {
-                               pb_tnc_mutual_protocol_type_t protocols = PB_MUTUAL_HALF_DUPLEX;
-
-                               msg = pb_mutual_capability_msg_create(protocols);
+                               msg = pb_mutual_capability_msg_create(PB_MUTUAL_HALF_DUPLEX);
                                this->mutex->lock(this->mutex);
                                this->messages->insert_last(this->messages, msg);
                                this->mutex->unlock(this->mutex);
+                               this->sent_mutual_capability = TRUE;
                        }
                        break;
                default:
@@ -537,7 +539,7 @@ METHOD(tnccs_20_handler_t, build, status_t,
 }
 
 METHOD(tnccs_20_handler_t, begin_handshake, void,
-       private_tnccs_20_server_t *this)
+       private_tnccs_20_server_t *this, bool mutual)
 {
        pb_tnc_msg_t *msg;
        identification_t *pdp_server;
@@ -572,6 +574,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool,
        return this->mutual;
 }
 
+METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t,
+       private_tnccs_20_server_t *this)
+{
+       return this->state_machine->get_state(this->state_machine);
+}
+
 METHOD(tnccs_20_handler_t, add_msg, void,
        private_tnccs_20_server_t *this, pb_tnc_msg_t *msg)
 {
@@ -648,6 +656,7 @@ tnccs_20_handler_t* tnccs_20_server_create(tnccs_t *tnccs,
                                .begin_handshake = _begin_handshake,
                                .get_send_flag = _get_send_flag,
                                .get_mutual = _get_mutual,
+                               .get_state = _get_state,
                                .add_msg = _add_msg,
                                .handle_errors = _handle_errors,
                                .destroy = _destroy,