mutex.h is not needed any more
[strongswan.git] / src / libcharon / plugins / tnc_imv / tnc_imv_recommendations.c
index 5a2d0de..58ad37c 100644 (file)
@@ -13,9 +13,9 @@
  */
 
 #include <debug.h>
-#include <utils/linked_list.h>
-#include <threading/mutex.h>
+#include <daemon.h>
 #include <tnc/tncifimv_names.h>
+#include <tnc/imv/imv.h>
 #include <tnc/imv/imv_recommendations.h>
 
 typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
@@ -89,12 +89,140 @@ METHOD(recommendations_t, have_recommendation, bool,
        private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
                                                                                         TNC_IMV_Evaluation_Result *eval)
 {
-       /* TODO */
-       *rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
-       *eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+       enumerator_t *enumerator;
+       recommendation_entry_t *entry;
+       recommendation_policy_t policy;
+       TNC_IMV_Action_Recommendation final_rec;
+       TNC_IMV_Evaluation_Result final_eval;
+       bool first = TRUE, incomplete = FALSE;
+
+       *rec = final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+       *eval = final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+
+       if (this->recs->get_count(this->recs) == 0)
+       {
+               DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
+               return TRUE;
+       }
+       policy = charon->imvs->get_recommendation_policy(charon->imvs);
+
+       enumerator = this->recs->create_enumerator(this->recs);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION ||
+                       entry->eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+               {
+                       incomplete = TRUE;
+                       break;
+               }
+               if (first)
+               {
+                       final_rec = entry->rec;
+                       final_eval = entry->eval;
+                       first = FALSE;
+               }
+               switch (policy)
+               {
+                       case RECOMMENDATION_POLICY_DEFAULT:
+                               /* Consolidate action recommendations */
+                               if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+                               }
+                               else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
+                                                final_rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+                               }
+                               else
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+                               }
+
+                               /* Consolidate evaluation results */
+                               if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+                               }
+                               else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_ERROR)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
+                               }
+                               else if (entry->eval ==  TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_ERROR &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
+                               }
+                               else if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+                               }
+                               break;
+                       case RECOMMENDATION_POLICY_ALL:
+                               /* Consolidate action recommendations */
+                               if (entry->rec != final_rec)
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+                               }
+
+                               /* Consolidate evaluation results */
+                               if (entry->eval != final_eval)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+                               }
+                               break;
+                       case RECOMMENDATION_POLICY_ANY:
+                               /* Consolidate action recommendations */
+                               if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+                               }
+                               else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
+                                                final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+                               }
+                               else
+                               {
+                                       final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+                               }
+
+                               /* Consolidate evaluation results */
+                               if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+                               }
+                               else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
+                               }
+                               else if (entry->eval ==  TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
+                                                final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
+                               }
+                               else if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
+                               {
+                                       final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+                               }
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       if (incomplete)
+       {
+               return FALSE;
+       }
+       *rec = final_rec;
+       *eval = final_eval;
        return TRUE;
 }
 
+
 METHOD(recommendations_t, destroy, void,
        private_tnc_imv_recommendations_t *this)
 {
@@ -110,7 +238,7 @@ recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
        private_tnc_imv_recommendations_t *this;
        recommendation_entry_t *entry;
        enumerator_t *enumerator;
-       TNC_IMVID id;
+       imv_t *imv;
 
        INIT(this,
                .public = {
@@ -122,10 +250,10 @@ recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
        );
 
        enumerator = imv_list->create_enumerator(imv_list);
-       while (enumerator->enumerate(enumerator, &id))
+       while (enumerator->enumerate(enumerator, &imv))
        {
                entry = malloc_thing(recommendation_entry_t);
-               entry->id = id;
+               entry->id = imv->get_id(imv);
                entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
                entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
                this->recs->insert_last(this->recs, entry);