2 * Copyright (C) 2010 Sansar Choinyanbuu
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
20 #include <threading/mutex.h>
21 #include <tnc/tncif.h>
22 #include <tnc/tncifimv_names.h>
23 #include <tnc/tnccs/tnccs.h>
25 typedef struct recommendation_entry_t recommendation_entry_t
;
26 typedef struct private_tnccs_20_t private_tnccs_20_t
;
29 * Recommendation entry
31 struct recommendation_entry_t
{
39 * Action Recommendation provided by IMV instance
41 TNC_IMV_Action_Recommendation rec
;
44 * Evaluation Result provided by IMV instance
46 TNC_IMV_Evaluation_Result eval
;
50 * Private data of a tnccs_20_t object.
52 struct private_tnccs_20_t
{
55 * Public tls_t interface.
60 * TNCC if TRUE, TNCS if FALSE
65 * Connection ID assigned to this TNCCS connection
67 TNC_ConnectionID connection_id
;
70 * Batch being constructed
75 * Action Recommendations and Evaluations Results provided by IMVs
77 linked_list_t
*recommendations
;
80 * Mutex locking the recommendations list
82 mutex_t
*recommendation_mutex
;
85 METHOD(tnccs_t
, send_message
, void,
86 private_tnccs_20_t
* this, TNC_BufferReference message
,
87 TNC_UInt32 message_len
,
88 TNC_MessageType message_type
)
90 chunk_t msg
= { message
, message_len
},
93 DBG1(DBG_TNC
, "TNCCS 2.0 send message");
94 this->batch
= chunk_cat("mc", batch
, msg
);
97 METHOD(tnccs_t
, provide_recommendation
, void,
98 private_tnccs_20_t
* this, TNC_IMVID id
,
99 TNC_IMV_Action_Recommendation rec
,
100 TNC_IMV_Evaluation_Result eval
)
102 enumerator_t
*enumerator
;
103 recommendation_entry_t
*entry
;
106 DBG2(DBG_TNC
, "IMV %u provides recommendation '%N' and evaluation '%N'",
107 id
, action_recommendation_names
, rec
, evaluation_result_names
, eval
);
109 this->recommendation_mutex
->lock(this->recommendation_mutex
);
110 enumerator
= this->recommendations
->create_enumerator(this->recommendations
);
111 while (enumerator
->enumerate(enumerator
, &entry
))
119 enumerator
->destroy(enumerator
);
123 entry
= malloc_thing(recommendation_entry_t
);
125 this->recommendations
->insert_last(this->recommendations
, entry
);
128 /* Assign provided action recommendation and evaluation result */
131 this->recommendation_mutex
->unlock(this->recommendation_mutex
);
134 METHOD(tls_t
, process
, status_t
,
135 private_tnccs_20_t
*this, void *buf
, size_t buflen
)
140 if (this->is_server
&& !this->connection_id
)
142 this->connection_id
= charon
->tnccs
->create_connection(charon
->tnccs
,
144 _send_message
, _provide_recommendation
);
145 charon
->imvs
->notify_connection_change(charon
->imvs
,
146 this->connection_id
, TNC_CONNECTION_STATE_CREATE
);
148 DBG1(DBG_TNC
, "received TNCCS Batch (%u bytes) for Connection ID %u",
149 buflen
, this->connection_id
);
150 DBG3(DBG_TNC
, "%.*s", buflen
, buf
);
151 pos
= strchr(buf
, '|');
155 len
= buflen
- ((char*)buf
- pos
);
164 charon
->imvs
->receive_message(charon
->imvs
, this->connection_id
,
165 pos
, len
, 0x0080ab31);
166 charon
->imvs
->batch_ending(charon
->imvs
, this->connection_id
);
170 charon
->imcs
->receive_message(charon
->imcs
, this->connection_id
,
171 pos
, len
, 0x0080ab31);
172 charon
->imcs
->batch_ending(charon
->imcs
, this->connection_id
);
177 METHOD(tls_t
, build
, status_t
,
178 private_tnccs_20_t
*this, void *buf
, size_t *buflen
, size_t *msglen
)
180 char *msg
= this->is_server ?
"tncs->tncc 2.0|" : "tncc->tncs 2.0|";
183 this->batch
= chunk_cat("cm", chunk_create(msg
, strlen(msg
)), this->batch
);
185 if (!this->is_server
&& !this->connection_id
)
187 this->connection_id
= charon
->tnccs
->create_connection(charon
->tnccs
,
188 (tnccs_t
*)this, _send_message
, NULL
);
189 charon
->imcs
->notify_connection_change(charon
->imcs
,
190 this->connection_id
, TNC_CONNECTION_STATE_CREATE
);
191 charon
->imcs
->notify_connection_change(charon
->imcs
,
192 this->connection_id
, TNC_CONNECTION_STATE_HANDSHAKE
);
193 charon
->imcs
->begin_handshake(charon
->imcs
, this->connection_id
);
196 len
= this->batch
.len
;
199 memcpy(buf
, this->batch
.ptr
, len
);
201 DBG1(DBG_TNC
, "sending TNCCS Batch (%d bytes) for Connection ID %u",
202 len
, this->connection_id
);
203 DBG3(DBG_TNC
, "%.*s", len
, buf
);
204 chunk_free(&this->batch
);
209 METHOD(tls_t
, is_server
, bool,
210 private_tnccs_20_t
*this)
212 return this->is_server
;
215 METHOD(tls_t
, get_purpose
, tls_purpose_t
,
216 private_tnccs_20_t
*this)
218 return TLS_PURPOSE_EAP_TNC
;
221 METHOD(tls_t
, is_complete
, bool,
222 private_tnccs_20_t
*this)
227 METHOD(tls_t
, get_eap_msk
, chunk_t
,
228 private_tnccs_20_t
*this)
233 METHOD(tls_t
, destroy
, void,
234 private_tnccs_20_t
*this)
236 charon
->tnccs
->remove_connection(charon
->tnccs
, this->connection_id
);
237 this->recommendations
->destroy_function(this->recommendations
, free
);
238 this->recommendation_mutex
->destroy(this->recommendation_mutex
);
239 free(this->batch
.ptr
);
246 tls_t
*tnccs_20_create(bool is_server
)
248 private_tnccs_20_t
*this;
254 .is_server
= _is_server
,
255 .get_purpose
= _get_purpose
,
256 .is_complete
= _is_complete
,
257 .get_eap_msk
= _get_eap_msk
,
260 .is_server
= is_server
,
261 .recommendations
= linked_list_create(),
262 .recommendation_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
265 return &this->public;