diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-11-01 13:32:07 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-11-01 13:32:07 +0100 |
commit | 5313d2d78ca150515f7f5eb39801c100690b6b29 (patch) | |
tree | c78e420367283bb1b16f14210b12687cdfbd26eb /src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c | |
parent | 6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (diff) | |
download | vyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.tar.gz vyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.zip |
Imported Upstream version 5.1.1
Diffstat (limited to 'src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c')
-rw-r--r-- | src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c new file mode 100644 index 000000000..e08236eb7 --- /dev/null +++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2011-2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "tnccs_dynamic.h" + +#include <tnc/tnc.h> + +#include <utils/debug.h> + +typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t; + +/** + * Private data of a tnccs_dynamic_t object. + */ +struct private_tnccs_dynamic_t { + + /** + * Public tnccs_t interface. + */ + tnccs_t public; + + /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; + + /** + * Detected TNC IF-TNCCS stack + */ + tls_t *tls; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + + /** + * Callback function to communicate recommendation (TNC Server only) + */ + tnccs_cb_t callback; + + /** + * reference count + */ + refcount_t ref; + +}; + +/** + * Determine the version of the IF-TNCCS protocol used by analyzing the first + * byte of the TNCCS batch received from a TNC Client according to the rules + * defined by section 3.5 "Interoperability with older IF-TNCCS versions" of + * the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard. + */ +tnccs_type_t determine_tnccs_protocol(char version) +{ + switch (version) + { + case '\t': + case '\n': + case '\r': + case ' ': + case '<': + return TNCCS_1_1; + case 0x00: + return TNCCS_SOH; + case 0x02: + return TNCCS_2_0; + default: + return TNCCS_UNKNOWN; + } +} + +METHOD(tls_t, process, status_t, + private_tnccs_dynamic_t *this, void *buf, size_t buflen) +{ + tnccs_type_t type; + tnccs_t *tnccs; + + if (!this->tls) + { + if (buflen == 0) + { + return FAILED; + } + type = determine_tnccs_protocol(*(char*)buf); + DBG1(DBG_TNC, "%N protocol detected dynamically", + tnccs_type_names, type); + tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE, + this->server, this->peer, this->transport, + this->callback); + if (!tnccs) + { + DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type); + return FAILED; + } + tnccs->set_auth_type(tnccs, this->auth_type); + this->tls = &tnccs->tls; + } + return this->tls->process(this->tls, buf, buflen); +} + +METHOD(tls_t, build, status_t, + private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen) +{ + return this->tls->build(this->tls, buf, buflen, msglen); +} + +METHOD(tls_t, is_server, bool, + private_tnccs_dynamic_t *this) +{ + return TRUE; +} + +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->server; +} + +METHOD(tls_t, set_peer_id, void, + private_tnccs_dynamic_t *this, identification_t *id) +{ + DESTROY_IF(this->peer); + this->peer = id->clone(id); + if (this->tls) + { + this->tls->set_peer_id(this->tls, id); + } +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->peer; +} + +METHOD(tls_t, get_purpose, tls_purpose_t, + private_tnccs_dynamic_t *this) +{ + return TLS_PURPOSE_EAP_TNC; +} + +METHOD(tls_t, is_complete, bool, + private_tnccs_dynamic_t *this) +{ + return this->tls ? this->tls->is_complete(this->tls) : FALSE; +} + +METHOD(tls_t, get_eap_msk, chunk_t, + private_tnccs_dynamic_t *this) +{ + return chunk_empty; +} + +METHOD(tls_t, destroy, void, + private_tnccs_dynamic_t *this) +{ + if (ref_put(&this->ref)) + { + DESTROY_IF(this->tls); + this->server->destroy(this->server); + this->peer->destroy(this->peer); + free(this); + } +} + +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_dynamic_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_dynamic_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_dynamic_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_dynamic_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + +METHOD(tnccs_t, get_pdp_server, chunk_t, + private_tnccs_dynamic_t *this, u_int16_t *port) +{ + tnccs_t *tnccs = (tnccs_t*)this->tls; + + return tnccs->get_pdp_server(tnccs, port); +} + +METHOD(tnccs_t, get_ref, tnccs_t*, + private_tnccs_dynamic_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +/** + * See header + */ +tnccs_t* tnccs_dynamic_create(bool is_server, + identification_t *server, identification_t *peer, + tnc_ift_type_t transport, tnccs_cb_t cb) +{ + private_tnccs_dynamic_t *this; + + INIT(this, + .public = { + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .set_peer_id = _set_peer_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, + .get_pdp_server = _get_pdp_server, + .get_ref = _get_ref, + }, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, + .callback = cb, + .ref = 1, + ); + + return &this->public; +} |