diff options
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c | 236 | ||||
-rw-r--r-- | src/libcharon/plugins/tnccs_11/tnccs_11.c | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/tnccs_20/tnccs_20.c | 4 | ||||
-rw-r--r-- | src/libtnccs/tnc/tnccs/tnccs_manager.h | 8 |
4 files changed, 229 insertions, 23 deletions
diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c index 5a21556c0..64ed160d9 100644 --- a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c @@ -55,6 +55,11 @@ struct tnccs_connection_entry_t { TNC_ConnectionID id; /** + * TNCCS protocol type + */ + tnccs_type_t type; + + /** * TNCCS instance */ tnccs_t *tnccs; @@ -174,13 +179,14 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*, } METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID, - private_tnc_tnccs_manager_t *this, tnccs_t *tnccs, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, tnccs_t *tnccs, tnccs_send_message_t send_message, bool* request_handshake_retry, recommendations_t **recs) { tnccs_connection_entry_t *entry; entry = malloc_thing(tnccs_connection_entry_t); + entry->type = type; entry->tnccs = tnccs; entry->send_message = send_message; entry->request_handshake_retry = request_handshake_retry; @@ -367,6 +373,69 @@ METHOD(tnccs_manager_t, provide_recommendation, TNC_Result, return TNC_RESULT_FATAL; } +/** + * Write the value of a boolean attribute into the buffer + */ +static TNC_Result bool_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + bool value) +{ + *value_len = 1; + + if (buffer && buffer_len > 0) + { + *buffer = value ? 0x01 : 0x00; + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + +/** + * Write the value of an u_int32_t attribute into the buffer + */ +static TNC_Result uint_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + u_int32_t value) +{ + *value_len = sizeof(u_int32_t); + + if (buffer && buffer_len >= *value_len) + { + htoun32(buffer, value); + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + +/** + * Write the value of string attribute into the buffer + */ +static TNC_Result str_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + char *value) +{ + *value_len = 1 + strlen(value); + + if (buffer && buffer_len >= *value_len) + { + snprintf(buffer, buffer_len, "%s", value); + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + METHOD(tnccs_manager_t, get_attribute, TNC_Result, private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, @@ -374,14 +443,80 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, TNC_AttributeID attribute_id, TNC_UInt32 buffer_len, TNC_BufferReference buffer, - TNC_UInt32 *out_value_len) + TNC_UInt32 *value_len) { enumerator_t *enumerator; tnccs_connection_entry_t *entry; - recommendations_t *recs = NULL; + bool attribute_match = FALSE, entry_found = FALSE; + + if (is_imc) + { + switch (attribute_id) + { + /* these attributes are unsupported */ + case TNC_ATTRIBUTEID_SOHR: + case TNC_ATTRIBUTEID_SSOHR: + return TNC_RESULT_INVALID_PARAMETER; + + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PRIMARY_IMC_ID: + attribute_match = TRUE; + break; - if (is_imc || id == TNC_CONNECTIONID_ANY || - attribute_id != TNC_ATTRIBUTEID_PREFERRED_LANGUAGE) + /* these attributes are yet to be matched */ + default: + break; + } + } + else + { + switch (attribute_id) + { + /* these attributes are unsupported or invalid */ + case TNC_ATTRIBUTEID_REASON_STRING: + case TNC_ATTRIBUTEID_REASON_LANGUAGE: + case TNC_ATTRIBUTEID_SOH: + case TNC_ATTRIBUTEID_SSOH: + return TNC_RESULT_INVALID_PARAMETER; + + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PRIMARY_IMV_ID: + attribute_match = TRUE; + break; + + /* these attributes are yet to be matched */ + default: + break; + } + } + + if (!attribute_match) + { + switch (attribute_id) + { + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE: + case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS: + case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE: + case TNC_ATTRIBUTEID_HAS_LONG_TYPES: + case TNC_ATTRIBUTEID_HAS_EXCLUSIVE: + case TNC_ATTRIBUTEID_HAS_SOH: + case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL: + case TNC_ATTRIBUTEID_IFTNCCS_VERSION: + case TNC_ATTRIBUTEID_IFT_PROTOCOL: + case TNC_ATTRIBUTEID_IFT_VERSION: + break; + + /* these attributes are unsupported or unknown */ + case TNC_ATTRIBUTEID_DHPN: + case TNC_ATTRIBUTEID_TLS_UNIQUE: + default: + return TNC_RESULT_INVALID_PARAMETER; + } + } + + /* attributes specific to the TNCC or TNCS are unsupported */ + if (id == TNC_CONNECTIONID_ANY) { return TNC_RESULT_INVALID_PARAMETER; } @@ -392,30 +527,99 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, { if (id == entry->id) { - recs = entry->recs; + entry_found = TRUE; break; } } enumerator->destroy(enumerator); this->connection_lock->unlock(this->connection_lock); - if (recs) + if (!entry_found) { - chunk_t pref_lang; + return TNC_RESULT_INVALID_PARAMETER; + } - pref_lang = recs->get_preferred_language(recs); - if (pref_lang.len == 0) + switch (attribute_id) + { + case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE: { - return TNC_RESULT_INVALID_PARAMETER; + recommendations_t *recs; + chunk_t pref_lang; + + recs = entry->recs; + if (!recs) + { + return TNC_RESULT_INVALID_PARAMETER; + } + pref_lang = recs->get_preferred_language(recs); + if (pref_lang.len == 0) + { + return TNC_RESULT_INVALID_PARAMETER; + } + *value_len = pref_lang.len; + if (buffer && buffer_len >= pref_lang.len) + { + memcpy(buffer, pref_lang.ptr, pref_lang.len); + } + return TNC_RESULT_SUCCESS; } - *out_value_len = pref_lang.len; - if (buffer && buffer_len >= pref_lang.len) + case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS: + return uint_attribute(buffer_len, buffer, value_len, 0xffffffff); + case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE: + return uint_attribute(buffer_len, buffer, value_len, 0x00000000); + case TNC_ATTRIBUTEID_HAS_LONG_TYPES: + case TNC_ATTRIBUTEID_HAS_EXCLUSIVE: + return bool_attribute(buffer_len, buffer, value_len, + entry->type == TNCCS_2_0); + case TNC_ATTRIBUTEID_HAS_SOH: + return bool_attribute(buffer_len, buffer, value_len, + entry->type == TNCCS_SOH); + case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL: { - memcpy(buffer, pref_lang.ptr, pref_lang.len); + char *protocol; + + switch (entry->type) + { + case TNCCS_1_1: + case TNCCS_2_0: + protocol = "IF-TNCCS"; + break; + case TNCCS_SOH: + protocol = "IF-TNCCS-SOH"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, protocol); } - return TNC_RESULT_SUCCESS; + case TNC_ATTRIBUTEID_IFTNCCS_VERSION: + { + char *version; + + switch (entry->type) + { + case TNCCS_1_1: + version = "1.1"; + break; + case TNCCS_2_0: + version = "2.0"; + break; + case TNCCS_SOH: + version = "1.0"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, version); + } + case TNC_ATTRIBUTEID_IFT_PROTOCOL: + return str_attribute(buffer_len, buffer, value_len, + "IF-T for Tunneled EAP"); + case TNC_ATTRIBUTEID_IFT_VERSION: + return str_attribute(buffer_len, buffer, value_len, "1.1"); + default: + return TNC_RESULT_INVALID_PARAMETER; } - return TNC_RESULT_INVALID_PARAMETER; } METHOD(tnccs_manager_t, set_attribute, TNC_Result, diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index 37ead6e4b..3673221e5 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -289,7 +289,7 @@ METHOD(tls_t, process, status_t, if (this->is_server && !this->connection_id) { this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, - (tnccs_t*)this, _send_msg, + TNCCS_1_1, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, &this->recs); if (!this->connection_id) { @@ -415,7 +415,7 @@ METHOD(tls_t, build, status_t, char *pref_lang; this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, - (tnccs_t*)this, _send_msg, + TNCCS_1_1, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, NULL); if (!this->connection_id) { diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index ca72b854f..606fc529b 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -375,7 +375,7 @@ METHOD(tls_t, process, status_t, if (this->is_server && !this->connection_id) { this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, - (tnccs_t*)this, _send_msg, + TNCCS_2_0, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, &this->recs); if (!this->connection_id) { @@ -556,7 +556,7 @@ METHOD(tls_t, build, status_t, char *pref_lang; this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, - (tnccs_t*)this, _send_msg, + TNCCS_2_0, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, NULL); if (!this->connection_id) { diff --git a/src/libtnccs/tnc/tnccs/tnccs_manager.h b/src/libtnccs/tnc/tnccs/tnccs_manager.h index fb5eaf50a..9ca450468 100644 --- a/src/libtnccs/tnc/tnccs/tnccs_manager.h +++ b/src/libtnccs/tnc/tnccs/tnccs_manager.h @@ -66,13 +66,15 @@ struct tnccs_manager_t { * callback function for adding a message to a TNCCS batch and create * an empty set for collecting IMV recommendations * + * @param type TNCCS protocol type * @param tnccs TNCCS connection instance * @param send_message TNCCS callback function * @param request_handshake_retry pointer to boolean variable * @param recs pointer to IMV recommendation set * @return assigned connection ID */ - TNC_ConnectionID (*create_connection)(tnccs_manager_t *this, tnccs_t *tnccs, + TNC_ConnectionID (*create_connection)(tnccs_manager_t *this, + tnccs_type_t type, tnccs_t *tnccs, tnccs_send_message_t send_message, bool *request_handshake_retry, recommendations_t **recs); @@ -148,7 +150,7 @@ struct tnccs_manager_t { * @param attribute_id ID of the requested attribute * @param buffer_len length of the buffer in bytes * @param buffer pointer to the buffer - * @param out_value_len actual length of the returned attribute + * @param value_len actual length of the returned attribute * @return return code */ TNC_Result (*get_attribute)(tnccs_manager_t *this, bool is_imc, @@ -157,7 +159,7 @@ struct tnccs_manager_t { TNC_AttributeID attribute_id, TNC_UInt32 buffer_len, TNC_BufferReference buffer, - TNC_UInt32 *out_value_len); + TNC_UInt32 *value_len); /** * Set the value of an attribute associated with a connection or with the |