File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtnccs / plugins / tnc_imv / tnc_imv_recommendations.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2010-2012 Andreas Steffen
    3:  * HSR Hochschule fuer Technik Rapperswil
    4:  *
    5:  * This program is free software; you can redistribute it and/or modify it
    6:  * under the terms of the GNU General Public License as published by the
    7:  * Free Software Foundation; either version 2 of the License, or (at your
    8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
    9:  *
   10:  * This program is distributed in the hope that it will be useful, but
   11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13:  * for more details.
   14:  */
   15: 
   16: #include <tncifimv.h>
   17: #include <tncif_names.h>
   18: #include <tncif_policy.h>
   19: 
   20: #include <tnc/tnc.h>
   21: #include <tnc/imv/imv.h>
   22: #include <tnc/imv/imv_manager.h>
   23: #include <tnc/imv/imv_recommendations.h>
   24: 
   25: #include <utils/debug.h>
   26: #include <collections/linked_list.h>
   27: 
   28: typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
   29: typedef struct recommendation_entry_t recommendation_entry_t;
   30: 
   31: /**
   32:  * Recommendation entry
   33:  */
   34: struct recommendation_entry_t {
   35: 
   36: 	/**
   37: 	 * IMV ID
   38: 	 */
   39: 	TNC_IMVID id;
   40: 
   41: 	/**
   42: 	 * Received a recommendation message from this IMV?
   43: 	 */
   44: 	bool have_recommendation;
   45: 
   46: 	/**
   47: 	 * Action Recommendation provided by IMV instance
   48: 	 */
   49: 	TNC_IMV_Action_Recommendation rec;
   50: 
   51: 	/**
   52: 	 * Evaluation Result provided by IMV instance
   53: 	 */
   54: 	TNC_IMV_Evaluation_Result eval;
   55: 
   56: 	/**
   57: 	 * Reason string provided by IMV instance
   58: 	 */
   59: 	chunk_t reason;
   60: 
   61: 	/**
   62: 	 * Reason language provided by IMV instance
   63: 	 */
   64: 	chunk_t reason_language;
   65: };
   66: 
   67: /**
   68:  * Private data of a recommendations_t object.
   69:  */
   70: struct private_tnc_imv_recommendations_t {
   71: 
   72: 	/**
   73: 	 * Public members of recommendations_t.
   74: 	 */
   75: 	recommendations_t public;
   76: 
   77: 	/**
   78: 	 * list of recommendations and evaluations provided by IMVs
   79: 	 */
   80: 	linked_list_t *recs;
   81: 
   82: 	/**
   83: 	 * Preferred language for remediation messages
   84: 	 */
   85: 	chunk_t preferred_language;
   86: };
   87: 
   88: METHOD(recommendations_t, provide_recommendation, TNC_Result,
   89: 	private_tnc_imv_recommendations_t* this, TNC_IMVID id,
   90: 											 TNC_IMV_Action_Recommendation rec,
   91: 											 TNC_IMV_Evaluation_Result eval)
   92: {
   93: 	enumerator_t *enumerator;
   94: 	recommendation_entry_t *entry;
   95: 	bool found = FALSE;
   96: 
   97: 	DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'", id,
   98: 		 TNC_IMV_Action_Recommendation_names, rec,
   99: 		 TNC_IMV_Evaluation_Result_names, eval);
  100: 
  101: 	enumerator = this->recs->create_enumerator(this->recs);
  102: 	while (enumerator->enumerate(enumerator, &entry))
  103: 	{
  104: 		if (entry->id == id)
  105: 		{
  106: 			found = TRUE;
  107: 			entry->have_recommendation = TRUE;
  108: 			entry->rec = rec;
  109: 			entry->eval = eval;
  110: 			break;
  111: 		}
  112: 	}
  113: 	enumerator->destroy(enumerator);
  114: 	return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL;
  115: }
  116: 
  117: METHOD(recommendations_t, have_recommendation, bool,
  118: 	private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
  119: 											 TNC_IMV_Evaluation_Result *eval)
  120: {
  121: 	enumerator_t *enumerator;
  122: 	recommendation_entry_t *entry;
  123: 	recommendation_policy_t policy;
  124: 	TNC_IMV_Action_Recommendation final_rec;
  125: 	TNC_IMV_Evaluation_Result final_eval;
  126: 	bool first = TRUE, incomplete = FALSE;
  127: 
  128: 	final_rec  = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
  129: 	final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
  130: 	if (rec && eval)
  131: 	{
  132: 		*rec  = final_rec;
  133: 		*eval = final_eval;
  134: 	}
  135: 
  136: 	if (this->recs->get_count(this->recs) == 0)
  137: 	{
  138: 		DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
  139: 		return TRUE;
  140: 	}
  141: 	policy = tnc->imvs->get_recommendation_policy(tnc->imvs);
  142: 
  143: 	enumerator = this->recs->create_enumerator(this->recs);
  144: 	while (enumerator->enumerate(enumerator, &entry))
  145: 	{
  146: 		if (!entry->have_recommendation)
  147: 		{
  148: 			incomplete = TRUE;
  149: 			break;
  150: 		}
  151: 		if (first)
  152: 		{
  153: 			final_rec = entry->rec;
  154: 			final_eval = entry->eval;
  155: 			first = FALSE;
  156: 			continue;
  157: 		}
  158: 		switch (policy)
  159: 		{
  160: 			case RECOMMENDATION_POLICY_DEFAULT:
  161: 				final_rec = tncif_policy_update_recommendation(final_rec,
  162: 															   entry->rec);
  163: 				final_eval = tncif_policy_update_evaluation(final_eval,
  164: 															entry->eval);
  165: 				break;
  166: 
  167: 			case RECOMMENDATION_POLICY_ALL:
  168: 				if (entry->rec != final_rec)
  169: 				{
  170: 					final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
  171: 				}
  172: 				if (entry->eval != final_eval)
  173: 				{
  174: 					final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
  175: 				}
  176: 				break;
  177: 
  178: 			case RECOMMENDATION_POLICY_ANY:
  179: 				switch (entry->rec)
  180: 				{
  181: 					case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
  182: 						final_rec = entry->rec;
  183: 						break;
  184: 					case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
  185: 						if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
  186: 						{
  187: 							final_rec = entry->rec;
  188: 						};
  189: 						break;
  190: 					case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
  191: 						if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
  192: 						{
  193: 							final_rec = entry->rec;
  194: 						};
  195: 						break;
  196: 					case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
  197: 						break;
  198: 				}
  199: 				switch (entry->eval)
  200: 				{
  201: 					case TNC_IMV_EVALUATION_RESULT_COMPLIANT:
  202: 						final_eval = entry->eval;
  203: 						break;
  204: 					case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR:
  205: 						if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
  206: 						{
  207: 							final_eval = entry->eval;
  208: 						}
  209: 						break;
  210: 					case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR:
  211: 						if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
  212: 							final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
  213: 						{
  214: 							final_eval = entry->eval;
  215: 						}
  216: 						break;
  217: 					case TNC_IMV_EVALUATION_RESULT_ERROR:
  218: 						if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
  219: 						{
  220: 							final_eval = entry->eval;
  221: 						}
  222: 						break;
  223: 					case TNC_IMV_EVALUATION_RESULT_DONT_KNOW:
  224: 						break;
  225: 				}
  226: 		}
  227: 	}
  228: 	enumerator->destroy(enumerator);
  229: 
  230: 	if (incomplete)
  231: 	{
  232: 		return FALSE;
  233: 	}
  234: 	if (rec && eval)
  235: 	{
  236: 		*rec  = final_rec;
  237: 		*eval = final_eval;
  238: 	}
  239: 	return TRUE;
  240: }
  241: 
  242: METHOD(recommendations_t, clear_recommendation, void,
  243: 	private_tnc_imv_recommendations_t *this)
  244: {
  245: 	enumerator_t *enumerator;
  246: 	recommendation_entry_t *entry;
  247: 
  248: 	enumerator = this->recs->create_enumerator(this->recs);
  249: 	while (enumerator->enumerate(enumerator, &entry))
  250: 	{
  251: 		entry->have_recommendation = FALSE;
  252: 		entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
  253: 		entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
  254: 		chunk_clear(&entry->reason);
  255: 		chunk_clear(&entry->reason_language);
  256: 	}
  257: 	enumerator->destroy(enumerator);
  258: }
  259: 
  260: METHOD(recommendations_t, get_preferred_language, chunk_t,
  261: 	private_tnc_imv_recommendations_t *this)
  262: {
  263: 	return this->preferred_language;
  264: }
  265: 
  266: METHOD(recommendations_t, set_preferred_language, void,
  267: 	private_tnc_imv_recommendations_t *this, chunk_t pref_lang)
  268: {
  269: 	free(this->preferred_language.ptr);
  270: 	this->preferred_language = chunk_clone(pref_lang);
  271: }
  272: 
  273: METHOD(recommendations_t, set_reason_string, TNC_Result,
  274: 	private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason)
  275: {
  276: 	enumerator_t *enumerator;
  277: 	recommendation_entry_t *entry;
  278: 	bool found = FALSE;
  279: 
  280: 	DBG2(DBG_TNC, "IMV %u is setting reason string to '%.*s'",
  281: 		 id, (int)reason.len, reason.ptr);
  282: 
  283: 	enumerator = this->recs->create_enumerator(this->recs);
  284: 	while (enumerator->enumerate(enumerator, &entry))
  285: 	{
  286: 		if (entry->id == id)
  287: 		{
  288: 			found = TRUE;
  289: 			free(entry->reason.ptr);
  290: 			entry->reason = chunk_clone(reason);
  291: 			break;
  292: 		}
  293: 	}
  294: 	enumerator->destroy(enumerator);
  295: 	return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
  296: }
  297: 
  298: METHOD(recommendations_t, set_reason_language, TNC_Result,
  299: 	private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason_lang)
  300: {
  301: 	enumerator_t *enumerator;
  302: 	recommendation_entry_t *entry;
  303: 	bool found = FALSE;
  304: 
  305: 	DBG2(DBG_TNC, "IMV %u is setting reason language to '%.*s'",
  306: 		 id, (int)reason_lang.len, reason_lang.ptr);
  307: 
  308: 	enumerator = this->recs->create_enumerator(this->recs);
  309: 	while (enumerator->enumerate(enumerator, &entry))
  310: 	{
  311: 		if (entry->id == id)
  312: 		{
  313: 			found = TRUE;
  314: 			free(entry->reason_language.ptr);
  315: 			entry->reason_language = chunk_clone(reason_lang);
  316: 			break;
  317: 		}
  318: 	}
  319: 	enumerator->destroy(enumerator);
  320: 	return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
  321: }
  322: 
  323: CALLBACK(reason_filter, bool,
  324: 	void *null, enumerator_t *orig, va_list args)
  325: {
  326: 	recommendation_entry_t *entry;
  327: 	TNC_IMVID *id;
  328: 	chunk_t *reason, *reason_language;
  329: 
  330: 	VA_ARGS_VGET(args, id, reason, reason_language);
  331: 
  332: 	while (orig->enumerate(orig, &entry))
  333: 	{
  334: 		if (entry->reason.len)
  335: 		{
  336: 			*id = entry->id;
  337: 			*reason = entry->reason;
  338: 			*reason_language = entry->reason_language;
  339: 			return TRUE;
  340: 		}
  341: 	}
  342: 	return FALSE;
  343: }
  344: 
  345: METHOD(recommendations_t, create_reason_enumerator, enumerator_t*,
  346: 	private_tnc_imv_recommendations_t *this)
  347: {
  348: 	return enumerator_create_filter(this->recs->create_enumerator(this->recs),
  349: 									reason_filter, NULL, NULL);
  350: }
  351: 
  352: METHOD(recommendations_t, destroy, void,
  353: 	private_tnc_imv_recommendations_t *this)
  354: {
  355: 	recommendation_entry_t *entry;
  356: 
  357: 	while (this->recs->remove_last(this->recs, (void**)&entry) == SUCCESS)
  358: 	{
  359: 		free(entry->reason.ptr);
  360: 		free(entry->reason_language.ptr);
  361: 		free(entry);
  362: 	}
  363: 	this->recs->destroy(this->recs);
  364: 	free(this->preferred_language.ptr);
  365: 	free(this);
  366: }
  367: 
  368: /**
  369:  * Described in header.
  370:  */
  371: recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
  372: {
  373: 	private_tnc_imv_recommendations_t *this;
  374: 	recommendation_entry_t *entry;
  375: 	enumerator_t *enumerator;
  376: 	imv_t *imv;
  377: 
  378: 	INIT(this,
  379: 		.public = {
  380: 			.provide_recommendation = _provide_recommendation,
  381: 			.have_recommendation = _have_recommendation,
  382: 			.clear_recommendation = _clear_recommendation,
  383: 			.get_preferred_language = _get_preferred_language,
  384: 			.set_preferred_language = _set_preferred_language,
  385: 			.set_reason_string = _set_reason_string,
  386: 			.set_reason_language = _set_reason_language,
  387: 			.create_reason_enumerator = _create_reason_enumerator,
  388: 			.destroy = _destroy,
  389: 		},
  390: 		.recs = linked_list_create(),
  391: 	);
  392: 
  393: 	enumerator = imv_list->create_enumerator(imv_list);
  394: 	while (enumerator->enumerate(enumerator, &imv))
  395: 	{
  396: 		entry = malloc_thing(recommendation_entry_t);
  397: 		entry->id = imv->get_id(imv);
  398: 		entry->have_recommendation = FALSE;
  399: 		entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
  400: 		entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
  401: 		entry->reason = chunk_empty;
  402: 		entry->reason_language = chunk_empty;
  403: 		this->recs->insert_last(this->recs, entry);
  404: 	}
  405: 	enumerator->destroy(enumerator);
  406: 
  407: 	return &this->public;
  408: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>