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 * Mutex locking the batch in construction
80 * Action Recommendations and Evaluations Results provided by IMVs
82 linked_list_t
*recommendations
;
85 * Mutex locking the recommendations list
87 mutex_t
*recommendation_mutex
;
90 METHOD(tnccs_t
, send_message
, void,
91 private_tnccs_20_t
* this, TNC_BufferReference message
,
92 TNC_UInt32 message_len
,
93 TNC_MessageType message_type
)
95 chunk_t msg
= { message
, message_len
};
97 DBG1(DBG_TNC
, "TNCCS 2.0 send message");
98 this->batch_mutex
->lock(this->batch_mutex
);
99 this->batch
= chunk_cat("mc", this->batch
, msg
);
100 this->batch_mutex
->unlock(this->batch_mutex
);
103 METHOD(tnccs_t
, provide_recommendation
, void,
104 private_tnccs_20_t
* this, TNC_IMVID id
,
105 TNC_IMV_Action_Recommendation rec
,
106 TNC_IMV_Evaluation_Result eval
)
108 enumerator_t
*enumerator
;
109 recommendation_entry_t
*entry
;
112 DBG2(DBG_TNC
, "IMV %u provides recommendation '%N' and evaluation '%N'",
113 id
, action_recommendation_names
, rec
, evaluation_result_names
, eval
);
115 this->recommendation_mutex
->lock(this->recommendation_mutex
);
116 enumerator
= this->recommendations
->create_enumerator(this->recommendations
);
117 while (enumerator
->enumerate(enumerator
, &entry
))
125 enumerator
->destroy(enumerator
);
129 entry
= malloc_thing(recommendation_entry_t
);
131 this->recommendations
->insert_last(this->recommendations
, entry
);
134 /* Assign provided action recommendation and evaluation result */
137 this->recommendation_mutex
->unlock(this->recommendation_mutex
);
140 METHOD(tls_t
, process
, status_t
,
141 private_tnccs_20_t
*this, void *buf
, size_t buflen
)
146 if (this->is_server
&& !this->connection_id
)
148 this->connection_id
= charon
->tnccs
->create_connection(charon
->tnccs
,
150 _send_message
, _provide_recommendation
);
151 charon
->imvs
->notify_connection_change(charon
->imvs
,
152 this->connection_id
, TNC_CONNECTION_STATE_CREATE
);
154 DBG1(DBG_TNC
, "received TNCCS Batch (%u bytes) for Connection ID %u",
155 buflen
, this->connection_id
);
156 DBG3(DBG_TNC
, "%.*s", buflen
, buf
);
157 pos
= strchr(buf
, '|');
161 len
= buflen
- (pos
- (char*)buf
);
168 DBG1(DBG_TNC
, "received message '%.*s'", len
, pos
);
171 charon
->imvs
->receive_message(charon
->imvs
, this->connection_id
,
172 pos
, len
, 0x0080ab31);
173 charon
->imvs
->batch_ending(charon
->imvs
, this->connection_id
);
177 charon
->imcs
->receive_message(charon
->imcs
, this->connection_id
,
178 pos
, len
, 0x0080ab31);
179 charon
->imcs
->batch_ending(charon
->imcs
, this->connection_id
);
184 METHOD(tls_t
, build
, status_t
,
185 private_tnccs_20_t
*this, void *buf
, size_t *buflen
, size_t *msglen
)
187 char *msg
= this->is_server ?
"tncs->tncc 2.0|" : "tncc->tncs 2.0|";
190 this->batch_mutex
->lock(this->batch_mutex
);
191 this->batch
= chunk_cat("cm", chunk_create(msg
, strlen(msg
)), this->batch
);
192 this->batch_mutex
->unlock(this->batch_mutex
);
194 if (!this->is_server
&& !this->connection_id
)
196 this->connection_id
= charon
->tnccs
->create_connection(charon
->tnccs
,
197 (tnccs_t
*)this, _send_message
, NULL
);
198 charon
->imcs
->notify_connection_change(charon
->imcs
,
199 this->connection_id
, TNC_CONNECTION_STATE_CREATE
);
200 charon
->imcs
->notify_connection_change(charon
->imcs
,
201 this->connection_id
, TNC_CONNECTION_STATE_HANDSHAKE
);
202 charon
->imcs
->begin_handshake(charon
->imcs
, this->connection_id
);
205 this->batch_mutex
->lock(this->batch_mutex
);
206 len
= this->batch
.len
;
209 memcpy(buf
, this->batch
.ptr
, len
);
210 chunk_free(&this->batch
);
211 this->batch_mutex
->unlock(this->batch_mutex
);
213 DBG1(DBG_TNC
, "sending TNCCS Batch (%d bytes) for Connection ID %u",
214 len
, this->connection_id
);
215 DBG3(DBG_TNC
, "%.*s", len
, buf
);
220 METHOD(tls_t
, is_server
, bool,
221 private_tnccs_20_t
*this)
223 return this->is_server
;
226 METHOD(tls_t
, get_purpose
, tls_purpose_t
,
227 private_tnccs_20_t
*this)
229 return TLS_PURPOSE_EAP_TNC
;
232 METHOD(tls_t
, is_complete
, bool,
233 private_tnccs_20_t
*this)
238 METHOD(tls_t
, get_eap_msk
, chunk_t
,
239 private_tnccs_20_t
*this)
244 METHOD(tls_t
, destroy
, void,
245 private_tnccs_20_t
*this)
247 charon
->tnccs
->remove_connection(charon
->tnccs
, this->connection_id
);
248 this->recommendations
->destroy_function(this->recommendations
, free
);
249 this->recommendation_mutex
->destroy(this->recommendation_mutex
);
250 this->batch_mutex
->destroy(this->batch_mutex
);
251 free(this->batch
.ptr
);
258 tls_t
*tnccs_20_create(bool is_server
)
260 private_tnccs_20_t
*this;
266 .is_server
= _is_server
,
267 .get_purpose
= _get_purpose
,
268 .is_complete
= _is_complete
,
269 .get_eap_msk
= _get_eap_msk
,
272 .is_server
= is_server
,
273 .recommendations
= linked_list_create(),
274 .recommendation_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
275 .batch_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
278 return &this->public;