adapted state_machine for retry batches
[strongswan.git] / src / libcharon / plugins / tnccs_20 / tnccs_20.c
index 0bdd8f1..636f525 100644 (file)
@@ -30,7 +30,7 @@
 #include <daemon.h>
 #include <threading/mutex.h>
 #include <tnc/tncif.h>
-#include <tnc/tncifimv_names.h>
+#include <tnc/tncifimv.h>
 #include <tnc/tnccs/tnccs.h>
 
 typedef struct private_tnccs_20_t private_tnccs_20_t;
@@ -71,7 +71,7 @@ struct private_tnccs_20_t {
        mutex_t *mutex;
 
        /**
-        * Flag set while processingn
+        * Flag set while processing
         */
        bool fatal_error;
 
@@ -92,8 +92,8 @@ METHOD(tnccs_t, send_msg, void,
                                                          TNC_UInt32 msg_len,
                                                          TNC_MessageType msg_type)
 {
-    TNC_MessageSubtype msg_sub_type;
-    TNC_VendorID msg_vendor_id;
+       TNC_MessageSubtype msg_sub_type;
+       TNC_VendorID msg_vendor_id;
        pb_tnc_msg_t *pb_tnc_msg;
        pb_tnc_batch_type_t batch_type;
 
@@ -165,19 +165,33 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
                        assess_msg = (pb_assessment_result_msg_t*)msg;
                        result = assess_msg->get_assessment_result(assess_msg);
                        DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
-                                                  evaluation_result_names, result);
+                                TNC_IMV_Evaluation_Result_names, result);
                        break;
                }
                case PB_MSG_ACCESS_RECOMMENDATION:
                {
                        pb_access_recommendation_msg_t *rec_msg;
                        pb_access_recommendation_code_t rec;
+                       TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
 
                        rec_msg = (pb_access_recommendation_msg_t*)msg;
                        rec = rec_msg->get_access_recommendation(rec_msg);
                        DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
                                                   pb_access_recommendation_code_names, rec);
-                               break;
+                       switch (rec)
+                       {
+                               case PB_REC_ACCESS_ALLOWED:
+                                       state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+                                       break;
+                               case PB_REC_ACCESS_DENIED:
+                                       state = TNC_CONNECTION_STATE_ACCESS_NONE;
+                                       break;
+                               case PB_REC_QUARANTINED:
+                                       state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+                       }
+                       charon->imcs->notify_connection_change(charon->imcs,
+                                                                                                  this->connection_id, state);
+                       break;
                }
                case PB_MSG_REMEDIATION_PARAMETERS:
                {
@@ -271,18 +285,25 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
 }
 
 /**
- *  Build a CRETRY or SRETRY batch 
+ *  Build a CRETRY or SRETRY batch
  */
 static void build_retry_batch(private_tnccs_20_t *this)
 {
+       pb_tnc_batch_type_t batch_retry_type;
+
+       batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
        if (this->batch)
        {
+               if (this->batch->get_type(this->batch) == batch_retry_type)
+               {
+                       /* retry batch has already been created */
+                       return;
+               }
                DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
                        pb_tnc_batch_type_names, this->batch->get_type(this->batch));
                this->batch->destroy(this->batch);
         }
-       this->batch = pb_tnc_batch_create(this->is_server,
-                                               this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY);
+       this->batch = pb_tnc_batch_create(this->is_server, batch_retry_type);
 }
 
 METHOD(tls_t, process, status_t,
@@ -305,12 +326,14 @@ METHOD(tls_t, process, status_t,
                }
                charon->imvs->notify_connection_change(charon->imvs,
                                                        this->connection_id, TNC_CONNECTION_STATE_CREATE);
+               charon->imvs->notify_connection_change(charon->imvs,
+                                                       this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
        }
 
        data = chunk_create(buf, buflen);
        DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u",
                                   data.len, this->connection_id);
-       DBG3(DBG_TNC, "%B", &data);  
+       DBG3(DBG_TNC, "%B", &data);
        batch = pb_tnc_batch_create_from_data(this->is_server, data);
        status = batch->process(batch, this->state_machine);
 
@@ -449,6 +472,7 @@ METHOD(tls_t, build, status_t,
        private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
 {
        status_t status;
+       pb_tnc_state_t state;
 
        /* Initialize the connection */
        if (!this->is_server && !this->connection_id)
@@ -480,8 +504,9 @@ METHOD(tls_t, build, status_t,
                charon->imcs->begin_handshake(charon->imcs, this->connection_id);
        }
 
-       if (this->is_server && this->fatal_error &&
-               this->state_machine->get_state(this->state_machine) == PB_STATE_END)
+       state = this->state_machine->get_state(this->state_machine);
+
+       if (this->is_server && this->fatal_error && state == PB_STATE_END)
        {
                DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
                return FAILED;
@@ -492,7 +517,10 @@ METHOD(tls_t, build, status_t,
 
        if (this->request_handshake_retry)
        {
-               build_retry_batch(this);
+               if (state != PB_STATE_INIT)
+               {
+                       build_retry_batch(this);
+               }
 
                /* Reset the flag for the next handshake retry request */
                this->request_handshake_retry = FALSE;
@@ -500,9 +528,6 @@ METHOD(tls_t, build, status_t,
 
        if (!this->batch)
        {
-               pb_tnc_state_t state;
-
-               state = this->state_machine->get_state(this->state_machine);
                if (this->is_server)
                {
                        if (state == PB_STATE_SERVER_WORKING)
@@ -539,10 +564,17 @@ METHOD(tls_t, build, status_t,
                                                   pb_tnc_batch_type_names, batch_type, data.len,
                                                   this->connection_id);
                        DBG3(DBG_TNC, "%B", &data);
-
                        *msglen = data.len;
-                       *buflen = data.len;
-                       memcpy(buf, data.ptr, data.len);
+
+                       if (data.len > *buflen)
+                       {
+                               DBG1(DBG_TNC, "fragmentation of PB-TNC batch not supported yet");
+                       }
+                       else
+                       {
+                               *buflen = data.len;
+                       }
+                       memcpy(buf, data.ptr, *buflen);
                        status = ALREADY_DONE;
                }
                else
@@ -557,7 +589,7 @@ METHOD(tls_t, build, status_t,
        }
        else
        {
-               DBG1(DBG_TNC, "no TNCCS batch to send");
+               DBG1(DBG_TNC, "no PB-TNC batch to send");
                status = INVALID_STATE;
        }
        this->mutex->unlock(this->mutex);
@@ -585,10 +617,7 @@ METHOD(tls_t, is_complete, bool,
 
        if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
        {
-               DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'",
-                        action_recommendation_names, rec, evaluation_result_names, eval);
-
-               return charon->imvs->enforce_recommendation(charon->imvs, rec);
+               return charon->imvs->enforce_recommendation(charon->imvs, rec, eval);
        }
        else
        {
@@ -605,7 +634,8 @@ METHOD(tls_t, get_eap_msk, chunk_t,
 METHOD(tls_t, destroy, void,
        private_tnccs_20_t *this)
 {
-       charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
+       charon->tnccs->remove_connection(charon->tnccs, this->connection_id,
+                                                                                                       this->is_server);
        this->state_machine->destroy(this->state_machine);
        this->mutex->destroy(this->mutex);
        DESTROY_IF(this->batch);