2 * Copyright (C) 2010 Sansar Choinyanbuu
3 * Copyright (C) 2010-2015 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "tnccs_20_handler.h"
19 #include "tnccs_20_server.h"
20 #include "tnccs_20_client.h"
21 #include "batch/pb_tnc_batch.h"
22 #include "messages/pb_tnc_msg.h"
23 #include "messages/ietf/pb_pa_msg.h"
25 #include <tncif_names.h>
26 #include <tncif_pa_subtypes.h>
28 #include <utils/debug.h>
30 typedef struct private_tnccs_20_t private_tnccs_20_t
;
33 * Private data of a tnccs_20_t object.
35 struct private_tnccs_20_t
{
38 * Public tnccs_t interface.
43 * TNCC if TRUE, TNCS if FALSE
50 identification_t
*server_id
;
55 identification_t
*peer_id
;
68 * Underlying TNC IF-T transport protocol
70 tnc_ift_type_t transport
;
73 * TNC IF-T transport protocol for EAP methods
78 * Type of TNC client authentication
83 * Mutual TNC measurements
88 * Direction the next batch will go to
95 tnccs_20_handler_t
*tnc_server
;
100 tnccs_20_handler_t
*tnc_client
;
103 * Active TNCSS handler
105 tnccs_20_handler_t
*tnccs_handler
;
108 * Maximum PB-TNC batch size
110 size_t max_batch_len
;
113 * Maximum PA-TNC message size
118 * Callback function to communicate recommendation (TNC Server only)
129 METHOD(tnccs_t
, send_msg
, TNC_Result
,
130 private_tnccs_20_t
* this, TNC_IMCID imc_id
, TNC_IMVID imv_id
,
131 TNC_UInt32 msg_flags
,
132 TNC_BufferReference msg
,
134 TNC_VendorID msg_vid
,
135 TNC_MessageSubtype msg_subtype
)
137 pb_tnc_msg_t
*pb_tnc_msg
;
138 enum_name_t
*pa_subtype_names
;
141 if (!this->tnccs_handler
->get_send_flag(this->tnccs_handler
))
143 DBG1(DBG_TNC
, "%s %u not allowed to call SendMessage()",
144 this->to_server
? "IMC" : "IMV",
145 this->to_server
? imc_id
: imv_id
);
147 return TNC_RESULT_ILLEGAL_OPERATION
;
149 excl
= (msg_flags
& TNC_MESSAGE_FLAGS_EXCLUSIVE
) != 0;
151 pb_tnc_msg
= pb_pa_msg_create(msg_vid
, msg_subtype
, imc_id
, imv_id
,
152 excl
, chunk_create(msg
, msg_len
));
154 pa_subtype_names
= get_pa_subtype_names(msg_vid
);
155 if (pa_subtype_names
)
157 DBG2(DBG_TNC
, "creating PB-PA message type '%N/%N' 0x%06x/0x%08x",
158 pen_names
, msg_vid
, pa_subtype_names
, msg_subtype
,
159 msg_vid
, msg_subtype
);
163 DBG2(DBG_TNC
, "creating PB-PA message type '%N' 0x%06x/0x%08x",
164 pen_names
, msg_vid
, msg_vid
, msg_subtype
);
166 this->tnccs_handler
->add_msg(this->tnccs_handler
, pb_tnc_msg
);
168 return TNC_RESULT_SUCCESS
;
171 METHOD(tls_t
, process
, status_t
,
172 private_tnccs_20_t
*this, void *buf
, size_t buflen
)
175 pb_tnc_batch_t
*batch
;
176 bool from_server
, mutual
;
179 /* On arrival of first PB-TNC batch create TNC server */
180 if (this->is_server
&& !this->tnc_server
)
182 this->tnc_server
= tnccs_20_server_create(&this->public, _send_msg
,
183 this->max_batch_len
, this->max_msg_len
,
184 this->eap_transport
);
185 if (!this->tnc_server
)
189 this->tnccs_handler
= this->tnc_server
;
190 this->tnccs_handler
->begin_handshake(this->tnccs_handler
);
193 data
= chunk_create(buf
, buflen
);
194 DBG1(DBG_TNC
, "received TNCCS batch (%u bytes)", data
.len
);
195 DBG3(DBG_TNC
, "%B", &data
);
197 /* Has a mutual connection been established? */
198 mutual
= this->tnc_client
&& this->tnc_server
;
200 /* Parse the header of the received PB-TNC batch */
201 batch
= pb_tnc_batch_create_from_data(data
);
202 status
= batch
->process_header(batch
, !mutual
, this->is_server
,
204 this->to_server
= mutual
? from_server
: !this->is_server
;
206 /* Set active TNCCS handler */
207 this->tnccs_handler
= this->to_server
? this->tnc_client
: this->tnc_server
;
208 DBG2(DBG_TNC
, "TNC %s is handling the connection",
209 this->to_server
? "client" : "server");
211 if (status
== SUCCESS
)
213 status
= this->tnccs_handler
->process(this->tnccs_handler
, batch
);
215 if (status
== VERIFY_ERROR
)
217 this->tnccs_handler
->handle_errors(this->tnccs_handler
, batch
);
220 batch
->destroy(batch
);
225 METHOD(tls_t
, build
, status_t
,
226 private_tnccs_20_t
*this, void *buf
, size_t *buflen
, size_t *msglen
)
232 /* Before sending the first PB-TNC batch create TNC client */
233 if (!this->tnc_client
)
235 DBG2(DBG_TNC
, "TNC client is handling the connection");
236 this->tnc_client
= tnccs_20_client_create(&this->public, _send_msg
,
239 if (!this->tnc_client
)
243 this->tnccs_handler
= this->tnc_client
;
244 this->tnccs_handler
->begin_handshake(this->tnccs_handler
);
249 /* Before sending the first PB-TNC batch create TNC server */
250 if (!this->tnc_server
)
252 DBG2(DBG_TNC
, "TNC server is handling the connection");
253 this->tnc_server
= tnccs_20_server_create(&this->public, _send_msg
,
254 this->max_batch_len
, this->max_msg_len
,
255 this->eap_transport
);
256 if (!this->tnc_server
)
260 this->tnccs_handler
= this->tnc_server
;
261 this->tnccs_handler
->begin_handshake(this->tnccs_handler
);
264 status
= this->tnccs_handler
->build(this->tnccs_handler
, buf
, buflen
, msglen
);
269 METHOD(tls_t
, is_server
, bool,
270 private_tnccs_20_t
*this)
272 return this->is_server
;
275 METHOD(tls_t
, get_server_id
, identification_t
*,
276 private_tnccs_20_t
*this)
278 return this->server_id
;
281 METHOD(tls_t
, set_peer_id
, void,
282 private_tnccs_20_t
*this, identification_t
*id
)
284 DESTROY_IF(this->peer_id
);
285 this->peer_id
= id
->clone(id
);
288 METHOD(tls_t
, get_peer_id
, identification_t
*,
289 private_tnccs_20_t
*this)
291 return this->peer_id
;
294 METHOD(tls_t
, get_purpose
, tls_purpose_t
,
295 private_tnccs_20_t
*this)
297 return TLS_PURPOSE_EAP_TNC
;
300 METHOD(tls_t
, is_complete
, bool,
301 private_tnccs_20_t
*this)
303 TNC_IMV_Action_Recommendation rec
;
304 TNC_IMV_Evaluation_Result eval
;
306 if (this->tnc_server
)
308 tnccs_20_server_t
*tnc_server
;
310 tnc_server
= (tnccs_20_server_t
*)this->tnc_server
;
311 if (tnc_server
->have_recommendation(tnc_server
, &rec
, &eval
))
313 return this->callback
? this->callback(rec
, eval
) : TRUE
;
319 METHOD(tls_t
, get_eap_msk
, chunk_t
,
320 private_tnccs_20_t
*this)
325 METHOD(tls_t
, destroy
, void,
326 private_tnccs_20_t
*this)
328 if (ref_put(&this->ref
))
330 DESTROY_IF(this->tnc_server
);
331 DESTROY_IF(this->tnc_client
);
332 this->server_id
->destroy(this->server_id
);
333 this->peer_id
->destroy(this->peer_id
);
334 this->server_ip
->destroy(this->server_ip
);
335 this->peer_ip
->destroy(this->peer_ip
);
340 METHOD(tnccs_t
, get_server_ip
, host_t
*,
341 private_tnccs_20_t
*this)
343 return this->server_ip
;
346 METHOD(tnccs_t
, get_peer_ip
, host_t
*,
347 private_tnccs_20_t
*this)
349 return this->peer_ip
;
352 METHOD(tnccs_t
, get_transport
, tnc_ift_type_t
,
353 private_tnccs_20_t
*this)
355 return this->transport
;
358 METHOD(tnccs_t
, set_transport
, void,
359 private_tnccs_20_t
*this, tnc_ift_type_t transport
)
361 this->transport
= transport
;
364 METHOD(tnccs_t
, get_auth_type
, u_int32_t
,
365 private_tnccs_20_t
*this)
367 return this->auth_type
;
370 METHOD(tnccs_t
, set_auth_type
, void,
371 private_tnccs_20_t
*this, u_int32_t auth_type
)
373 this->auth_type
= auth_type
;
376 METHOD(tnccs_t
, get_pdp_server
, chunk_t
,
377 private_tnccs_20_t
*this, u_int16_t
*port
)
379 if (this->tnc_client
)
381 tnccs_20_client_t
*tnc_client
;
383 tnc_client
= (tnccs_20_client_t
*)this->tnc_client
;
385 return tnc_client
->get_pdp_server(tnc_client
, port
);
394 METHOD(tnccs_t
, get_ref
, tnccs_t
*,
395 private_tnccs_20_t
*this)
398 return &this->public;
404 tnccs_t
* tnccs_20_create(bool is_server
, identification_t
*server_id
,
405 identification_t
*peer_id
, host_t
*server_ip
,
406 host_t
*peer_ip
, tnc_ift_type_t transport
,
409 private_tnccs_20_t
*this;
410 size_t max_batch_size
, default_max_batch_size
;
411 size_t max_message_size
, default_max_message_size
;
413 /* Determine the maximum PB-TNC batch size and PA-TNC message size */
416 case TNC_IFT_TLS_2_0
:
417 case TNC_IFT_TLS_1_0
:
418 default_max_batch_size
= 128 * TLS_MAX_FRAGMENT_LEN
- 16;
420 case TNC_IFT_EAP_2_0
:
421 case TNC_IFT_EAP_1_1
:
422 case TNC_IFT_EAP_1_0
:
423 case TNC_IFT_UNKNOWN
:
425 default_max_batch_size
= 4 * TLS_MAX_FRAGMENT_LEN
- 14;
429 max_batch_size
= min(default_max_batch_size
,
430 lib
->settings
->get_int(lib
->settings
,
431 "%s.plugins.tnccs-20.max_batch_size",
432 default_max_batch_size
, lib
->ns
));
434 default_max_message_size
= max_batch_size
- PB_TNC_BATCH_HEADER_SIZE
435 - PB_TNC_MSG_HEADER_SIZE
436 - PB_PA_MSG_HEADER_SIZE
;
438 max_message_size
= min(default_max_message_size
,
439 lib
->settings
->get_int(lib
->settings
,
440 "%s.plugins.tnccs-20.max_message_size",
441 default_max_message_size
, lib
->ns
));
448 .is_server
= _is_server
,
449 .get_server_id
= _get_server_id
,
450 .set_peer_id
= _set_peer_id
,
451 .get_peer_id
= _get_peer_id
,
452 .get_purpose
= _get_purpose
,
453 .is_complete
= _is_complete
,
454 .get_eap_msk
= _get_eap_msk
,
457 .get_server_ip
= _get_server_ip
,
458 .get_peer_ip
= _get_peer_ip
,
459 .get_transport
= _get_transport
,
460 .set_transport
= _set_transport
,
461 .get_auth_type
= _get_auth_type
,
462 .set_auth_type
= _set_auth_type
,
463 .get_pdp_server
= _get_pdp_server
,
466 .is_server
= is_server
,
467 .to_server
= !is_server
,
468 .server_id
= server_id
->clone(server_id
),
469 .peer_id
= peer_id
->clone(peer_id
),
470 .server_ip
= server_ip
->clone(server_ip
),
471 .peer_ip
= peer_ip
->clone(peer_ip
),
472 .transport
= transport
,
473 .eap_transport
= transport
== TNC_IFT_EAP_1_1
||
474 transport
== TNC_IFT_EAP_2_0
,
476 .max_batch_len
= max_batch_size
,
477 .max_msg_len
= max_message_size
,
481 return &this->public;