aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r--src/libcharon/plugins/android/android_service.c4
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.c83
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.h6
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_server.c13
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c3
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.am18
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey.c208
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey.h149
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_cred.c263
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_cred.h57
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_plugin.c104
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_plugin.h48
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c4
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c4
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c4
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c3
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c136
-rw-r--r--src/libcharon/plugins/sql/sql_config.c3
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c3
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c15
-rw-r--r--src/libcharon/plugins/tnc_imc/Makefile.am3
-rw-r--r--src/libcharon/plugins/tnc_imv/Makefile.am3
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.c12
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c98
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h10
-rw-r--r--src/libcharon/plugins/tnc_tnccs/Makefile.am1
-rw-r--r--src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c157
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11.c94
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11.h16
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c3
-rw-r--r--src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c1
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c200
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h64
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20.c134
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20.h16
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c3
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c103
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h16
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c3
-rw-r--r--src/libcharon/plugins/uci/uci_config.c4
41 files changed, 1816 insertions, 260 deletions
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index 6af35e5df..9b9bcc3f5 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -266,7 +266,8 @@ static job_requeue_t initiate(private_android_service_t *this)
ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
- hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO);
+ hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO,
+ 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED,
@@ -386,4 +387,3 @@ android_service_t *android_service_create(android_creds_t *creds)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index ffa1bae39..7363ade1d 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -21,6 +21,8 @@
#include <utils/debug.h>
#include <daemon.h>
+#include <tncifimv.h>
+
/**
* Maximum size of an EAP-TNC message
*/
@@ -44,15 +46,50 @@ struct private_eap_tnc_t {
eap_tnc_t public;
/**
+ * Outer EAP authentication type
+ */
+ eap_type_t auth_type;
+
+ /**
* TLS stack, wrapped by EAP helper
*/
tls_eap_t *tls_eap;
+
+ /**
+ * TNCCS instance running over EAP-TNC
+ */
+ tnccs_t *tnccs;
+
};
METHOD(eap_method_t, initiate, status_t,
private_eap_tnc_t *this, eap_payload_t **out)
{
chunk_t data;
+ u_int32_t auth_type;
+
+ /* Determine TNC Client Authentication Type */
+ switch (this->auth_type)
+ {
+ case EAP_TLS:
+ case EAP_TTLS:
+ case EAP_PEAP:
+ auth_type = TNC_AUTH_CERT;
+ break;
+ case EAP_MD5:
+ case EAP_MSCHAPV2:
+ case EAP_GTC:
+ case EAP_OTP:
+ auth_type = TNC_AUTH_PASSWORD;
+ break;
+ case EAP_SIM:
+ case EAP_AKA:
+ auth_type = TNC_AUTH_SIM;
+ break;
+ default:
+ auth_type = TNC_AUTH_UNKNOWN;
+ }
+ this->tnccs->set_auth_type(this->tnccs, auth_type);
if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE)
{
@@ -122,6 +159,18 @@ METHOD(eap_method_t, destroy, void,
free(this);
}
+METHOD(eap_inner_method_t, get_auth_type, eap_type_t,
+ private_eap_tnc_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(eap_inner_method_t, set_auth_type, void,
+ private_eap_tnc_t *this, eap_type_t type)
+{
+ this->auth_type = type;
+}
+
/**
* Generic private constructor
*/
@@ -132,19 +181,22 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
int max_msg_count;
char* protocol;
tnccs_type_t type;
- tnccs_t *tnccs;
INIT(this,
.public = {
- .eap_method = {
- .initiate = _initiate,
- .process = _process,
- .get_type = _get_type,
- .is_mutual = _is_mutual,
- .get_msk = _get_msk,
- .get_identifier = _get_identifier,
- .set_identifier = _set_identifier,
- .destroy = _destroy,
+ .eap_inner_method = {
+ .eap_method = {
+ .initiate = _initiate,
+ .process = _process,
+ .get_type = _get_type,
+ .is_mutual = _is_mutual,
+ .get_msk = _get_msk,
+ .get_identifier = _get_identifier,
+ .set_identifier = _set_identifier,
+ .destroy = _destroy,
+ },
+ .get_auth_type = _get_auth_type,
+ .set_auth_type = _set_auth_type,
},
},
);
@@ -172,10 +224,11 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
free(this);
return NULL;
}
- tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server);
- this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs,
- EAP_TNC_MAX_MESSAGE_LEN,
- max_msg_count, FALSE);
+ this->tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server,
+ server, peer, TNC_IFT_EAP_1_1);
+ this->tls_eap = tls_eap_create(EAP_TNC, &this->tnccs->tls,
+ EAP_TNC_MAX_MESSAGE_LEN,
+ max_msg_count, FALSE);
if (!this->tls_eap)
{
free(this);
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h
index 09abe60fc..8c881f6cf 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.h
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h
@@ -23,7 +23,7 @@
typedef struct eap_tnc_t eap_tnc_t;
-#include <sa/eap/eap_method.h>
+#include <sa/eap/eap_inner_method.h>
/**
* Implementation of the eap_method_t interface using EAP-TNC.
@@ -31,9 +31,9 @@ typedef struct eap_tnc_t eap_tnc_t;
struct eap_tnc_t {
/**
- * Implemented eap_method_t interface.
+ * Implemented eap_inner_method_t interface.
*/
- eap_method_t eap_method;
+ eap_inner_method_t eap_inner_method;
};
/**
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
index 464de17ba..eef8d6682 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
@@ -20,6 +20,7 @@
#include <daemon.h>
#include <sa/eap/eap_method.h>
+#include <sa/eap/eap_inner_method.h>
typedef struct private_eap_ttls_server_t private_eap_ttls_server_t;
@@ -108,8 +109,11 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this)
/**
* If configured, start EAP-TNC protocol
*/
-static status_t start_phase2_tnc(private_eap_ttls_server_t *this)
+static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
+ eap_type_t auth_type)
{
+ eap_inner_method_t *inner_method;
+
if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
"%s.plugins.eap-ttls.phase2_tnc", FALSE, charon->name))
{
@@ -121,6 +125,9 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this)
DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC);
return FAILED;
}
+ inner_method = (eap_inner_method_t *)this->method;
+ inner_method->set_auth_type(inner_method, auth_type);
+
this->start_phase2_tnc = FALSE;
if (this->method->initiate(this->method, &this->out) == NEED_MORE)
{
@@ -237,7 +244,7 @@ METHOD(tls_application_t, process, status_t,
if (lib->settings->get_bool(lib->settings,
"%s.plugins.eap-ttls.request_peer_auth", FALSE, charon->name))
{
- return start_phase2_tnc(this);
+ return start_phase2_tnc(this, EAP_TLS);
}
else
{
@@ -265,7 +272,7 @@ METHOD(tls_application_t, process, status_t,
this->method = NULL;
/* continue phase2 with EAP-TNC? */
- return start_phase2_tnc(this);
+ return start_phase2_tnc(this, type);
case NEED_MORE:
break;
case FAILED:
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index 130c86e48..e6a09a76e 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -205,7 +205,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
/* create config and backend */
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local, FALSE,
charon->socket->get_port(charon->socket, FALSE),
- remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO);
+ remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
@@ -288,4 +288,3 @@ ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am
new file mode 100644
index 000000000..0614017a0
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ipseckey.la
+else
+plugin_LTLIBRARIES = libstrongswan-ipseckey.la
+endif
+
+libstrongswan_ipseckey_la_SOURCES = \
+ ipseckey_plugin.h ipseckey_plugin.c \
+ ipseckey_cred.h ipseckey_cred.c \
+ ipseckey.h ipseckey.c
+
+libstrongswan_ipseckey_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/ipseckey/ipseckey.c b/src/libcharon/plugins/ipseckey/ipseckey.c
new file mode 100644
index 000000000..78ae2cc2a
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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 "ipseckey.h"
+
+#include <library.h>
+#include <utils/debug.h>
+#include <bio/bio_reader.h>
+
+typedef struct private_ipseckey_t private_ipseckey_t;
+
+/**
+* private data of the ipseckey
+*/
+struct private_ipseckey_t {
+
+ /**
+ * public functions
+ */
+ ipseckey_t public;
+
+ /**
+ * Precedence
+ */
+ u_int8_t precedence;
+
+ /**
+ * Gateway type
+ */
+ u_int8_t gateway_type;
+
+ /**
+ * Algorithm
+ */
+ u_int8_t algorithm;
+
+ /**
+ * Gateway
+ */
+ chunk_t gateway;
+
+ /**
+ * Public key
+ */
+ chunk_t public_key;
+};
+
+METHOD(ipseckey_t, get_precedence, u_int8_t,
+ private_ipseckey_t *this)
+{
+ return this->precedence;
+}
+
+METHOD(ipseckey_t, get_gateway_type, ipseckey_gw_type_t,
+ private_ipseckey_t *this)
+{
+ return this->gateway_type;
+}
+
+METHOD(ipseckey_t, get_algorithm, ipseckey_algorithm_t,
+ private_ipseckey_t *this)
+{
+ return this->algorithm;
+}
+
+METHOD(ipseckey_t, get_gateway, chunk_t,
+ private_ipseckey_t *this)
+{
+ return this->gateway;
+}
+
+METHOD(ipseckey_t, get_public_key, chunk_t,
+ private_ipseckey_t *this)
+{
+ return this->public_key;
+}
+
+METHOD(ipseckey_t, destroy, void,
+ private_ipseckey_t *this)
+{
+ chunk_free(&this->gateway);
+ chunk_free(&this->public_key);
+ free(this);
+}
+
+/*
+ * See header
+ */
+ipseckey_t *ipseckey_create_frm_rr(rr_t *rr)
+{
+ private_ipseckey_t *this;
+ bio_reader_t *reader = NULL;
+ u_int8_t label;
+ chunk_t tmp;
+
+ INIT(this,
+ .public = {
+ .get_precedence = _get_precedence,
+ .get_gateway_type = _get_gateway_type,
+ .get_algorithm = _get_algorithm,
+ .get_gateway = _get_gateway,
+ .get_public_key = _get_public_key,
+ .destroy = _destroy,
+ },
+ );
+
+ if (rr->get_type(rr) != RR_TYPE_IPSECKEY)
+ {
+ DBG1(DBG_CFG, "unable to create an ipseckey out of an RR "
+ "whose type is not IPSECKEY");
+ free(this);
+ return NULL;
+ }
+
+ /** Parse the content (RDATA field) of the RR */
+ reader = bio_reader_create(rr->get_rdata(rr));
+ if (!reader->read_uint8(reader, &this->precedence) ||
+ !reader->read_uint8(reader, &this->gateway_type) ||
+ !reader->read_uint8(reader, &this->algorithm))
+ {
+ DBG1(DBG_CFG, "ipseckey RR has a wrong format");
+ reader->destroy(reader);
+ free(this);
+ }
+
+ switch (this->gateway_type)
+ {
+ case IPSECKEY_GW_TP_NOT_PRESENT:
+ break;
+
+ case IPSECKEY_GW_TP_IPV4:
+ if (!reader->read_data(reader, 4, &this->gateway))
+ {
+ DBG1(DBG_CFG, "ipseckey gateway field does not contain an "
+ "IPv4 address as expected");
+ reader->destroy(reader);
+ free(this);
+ return NULL;
+ }
+ this->gateway = chunk_clone(this->gateway);
+ break;
+
+ case IPSECKEY_GW_TP_IPV6:
+ if (!reader->read_data(reader, 16, &this->gateway))
+ {
+ DBG1(DBG_CFG, "ipseckey gateway field does not contain an "
+ "IPv6 address as expected");
+ reader->destroy(reader);
+ free(this);
+ return NULL;
+ }
+ this->gateway = chunk_clone(this->gateway);
+ break;
+
+ case IPSECKEY_GW_TP_WR_ENC_DNAME:
+ /**
+ * Uncompressed domain name as defined in RFC 1035 chapter 3.
+ *
+ * TODO: Currently we ignore wire encoded domain names.
+ *
+ */
+ while (reader->read_uint8(reader, &label) &&
+ label != 0 && label < 192)
+ {
+ if (!reader->read_data(reader, label, &tmp))
+ {
+ DBG1(DBG_CFG, "wrong wire encoded domain name format "
+ "in ipseckey gateway field");
+ reader->destroy(reader);
+ free(this);
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ DBG1(DBG_CFG, "unable to parse ipseckey gateway field");
+ reader->destroy(reader);
+ free(this);
+ return NULL;
+ }
+
+ if (!reader->read_data(reader, reader->remaining(reader),
+ &this->public_key))
+ {
+ DBG1(DBG_CFG, "failed to read ipseckey public key field");
+ reader->destroy(reader);
+ chunk_free(&this->gateway);
+ free(this);
+ return NULL;
+ }
+ this->public_key = chunk_clone(this->public_key);
+ reader->destroy(reader);
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ipseckey/ipseckey.h b/src/libcharon/plugins/ipseckey/ipseckey.h
new file mode 100644
index 000000000..0afc067a5
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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.
+ */
+
+/**
+ * @defgroup ipseckey_cred_i ipseckey
+ * @{ @ingroup ipseckey
+ */
+
+#ifndef IPSECKEY_H_
+#define IPSECKEY_H_
+
+typedef struct ipseckey_t ipseckey_t;
+typedef enum ipseckey_algorithm_t ipseckey_algorithm_t;
+typedef enum ipseckey_gw_type_t ipseckey_gw_type_t;
+
+#include <library.h>
+
+/**
+ * IPSECKEY gateway types as defined in RFC 4025.
+ */
+enum ipseckey_gw_type_t {
+ /** No gateway is present */
+ IPSECKEY_GW_TP_NOT_PRESENT = 0,
+ /** A 4-byte IPv4 address is present */
+ IPSECKEY_GW_TP_IPV4 = 1,
+ /** A 16-byte IPv6 address is present */
+ IPSECKEY_GW_TP_IPV6 = 2,
+ /** A wire-encoded domain name is present */
+ IPSECKEY_GW_TP_WR_ENC_DNAME = 3,
+};
+
+/**
+ * IPSECKEY algorithms as defined in RFC 4025.
+ */
+enum ipseckey_algorithm_t {
+ /** No key present */
+ IPSECKEY_ALGORITHM_NONE = 0,
+ /** DSA key */
+ IPSECKEY_ALGORITHM_DSA = 1,
+ /** RSA key */
+ IPSECKEY_ALGORITHM_RSA = 2,
+};
+
+/**
+ * An IPSECKEY.
+ *
+ * Represents an IPSECKEY as defined in RFC 4025:
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | precedence | gateway type | algorithm | gateway |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------+ +
+ * ~ gateway ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | /
+ * / public key /
+ * / /
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ *
+ *
+ * Note: RFC 4025 defines that the algorithm field has a length of 7 bits.
+ * We use 8 bits instead, because the use of 7 bits is very uncommon
+ * in internet protocols and might be an error in RFC 4025
+ * (also the BIND DNS server uses 8 bits for the algorithm field of the
+ * IPSECKEY resource records).
+ *
+ */
+struct ipseckey_t {
+
+ /**
+ * Get the precedence of the IPSECKEY.
+ *
+ * @return precedence
+ */
+ u_int8_t (*get_precedence)(ipseckey_t *this);
+
+ /**
+ * Get the type of the gateway.
+ *
+ * The "gateway type" determines the format of the gateway field
+ * of the IPSECKEY.
+ *
+ * @return gateway type
+ */
+ ipseckey_gw_type_t (*get_gateway_type)(ipseckey_t *this);
+
+ /**
+ * Get the algorithm.
+ *
+ * The "algorithm" determines the format of the public key field
+ * of the IPSECKEY.
+ *
+ * @return algorithm
+ */
+ ipseckey_algorithm_t (*get_algorithm)(ipseckey_t *this);
+
+ /**
+ * Get the content of the gateway field as chunk.
+ *
+ * The content is in network byte order and its format depends on the
+ * gateway type.
+ *
+ * The data pointed by the chunk is still owned by the IPSECKEY.
+ * Clone it if necessary.
+ *
+ * @return gateway field as chunk
+ */
+ chunk_t (*get_gateway)(ipseckey_t *this);
+
+ /**
+ * Get the content of the public key field as chunk.
+ *
+ * The format of the public key depends on the algorithm type.
+ *
+ * The data pointed by the chunk is still owned by the IPSECKEY.
+ * Clone it if necessary.
+ *
+ * @return public key field as chunk
+ */
+ chunk_t (*get_public_key)(ipseckey_t *this);
+
+ /**
+ * Destroy the IPSECKEY.
+ */
+ void (*destroy) (ipseckey_t *this);
+};
+
+/**
+ * Create an ipseckey instance out of a resource record.
+ *
+ * @param rr resource record which contains an IPSECKEY
+ * @return ipseckey, NULL on failure
+ */
+ipseckey_t *ipseckey_create_frm_rr(rr_t *rr);
+
+#endif /** IPSECKEY_H_ @}*/
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
new file mode 100644
index 000000000..e8722f12c
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+
+#include "ipseckey_cred.h"
+#include "ipseckey.h"
+
+#include <bio/bio_reader.h>
+#include <daemon.h>
+
+typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
+
+/**
+ * Private data of an ipseckey_cred_t object
+ */
+struct private_ipseckey_cred_t {
+
+ /**
+ * Public part
+ */
+ ipseckey_cred_t public;
+
+ /**
+ * DNS resolver
+ */
+ resolver_t *res;
+};
+
+/**
+ * enumerator over certificates
+ */
+typedef struct {
+ /** implements enumerator interface */
+ enumerator_t public;
+ /** inner enumerator (enumerates IPSECKEY resource records) */
+ enumerator_t *inner;
+ /** response of the DNS resolver which contains the IPSECKEYs */
+ resolver_response_t *response;
+ /* IPSECKEYs are not valid before this point in time */
+ time_t notBefore;
+ /* IPSECKEYs are not valid after this point in time */
+ time_t notAfter;
+ /* identity to which the IPSECKEY belongs */
+ identification_t *identity;
+} cert_enumerator_t;
+
+METHOD(enumerator_t, cert_enumerator_enumerate, bool,
+ cert_enumerator_t *this, certificate_t **cert)
+{
+ rr_t *cur_rr = NULL;
+ ipseckey_t *cur_ipseckey = NULL;
+ chunk_t pub_key;
+ public_key_t * key = NULL;
+ bool supported_ipseckey_found = FALSE;
+
+ /* Get the next supported IPSECKEY using the inner enumerator. */
+ while (this->inner->enumerate(this->inner, &cur_rr) &&
+ !supported_ipseckey_found)
+ {
+ supported_ipseckey_found = TRUE;
+
+ cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
+
+ if (!cur_ipseckey)
+ {
+ DBG1(DBG_CFG, "failed to parse ipseckey - skipping this key");
+ supported_ipseckey_found = FALSE;
+ }
+
+ if (cur_ipseckey &&
+ cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA)
+ {
+ DBG1(DBG_CFG, "unsupported ipseckey algorithm -skipping this key");
+ cur_ipseckey->destroy(cur_ipseckey);
+ supported_ipseckey_found = FALSE;
+ }
+ }
+
+ if (supported_ipseckey_found)
+ {
+ /*
+ * Wrap the key of the IPSECKEY in a certificate and return this
+ * certificate.
+ */
+ pub_key = cur_ipseckey->get_public_key(cur_ipseckey);
+
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_DNSKEY, pub_key,
+ BUILD_END);
+
+ if (!key)
+ {
+ DBG1(DBG_CFG, "failed to create public key from ipseckey");
+ cur_ipseckey->destroy(cur_ipseckey);
+ return FALSE;
+ }
+
+ *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, key,
+ BUILD_SUBJECT, this->identity,
+ BUILD_NOT_BEFORE_TIME, this->notBefore,
+ BUILD_NOT_AFTER_TIME, this->notAfter,
+ BUILD_END);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+METHOD(enumerator_t, cert_enumerator_destroy, void,
+ cert_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ this->response->destroy(this->response);
+ free(this);
+}
+
+METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
+ private_ipseckey_cred_t *this, certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ char *fqdn = NULL;
+ resolver_response_t *response = NULL;
+ rr_set_t *rrset = NULL;
+ enumerator_t *rrsig_enum = NULL;
+ rr_t *rrsig = NULL;
+ bio_reader_t *reader = NULL;
+ chunk_t ignore;
+ u_int32_t nBefore, nAfter;
+ cert_enumerator_t *e;
+
+ if (id && id->get_type(id) == ID_FQDN)
+ {
+ /** Query the DNS for the required IPSECKEY RRs */
+
+ if (0 >= asprintf(&fqdn, "%Y", id))
+ {
+ DBG1(DBG_CFG, "empty FQDN string");
+ return enumerator_create_empty();
+ }
+
+ DBG1(DBG_CFG, "performing a DNS query for IPSECKEY RRs of '%s'",
+ fqdn);
+ response = this->res->query(this->res, fqdn, RR_CLASS_IN,
+ RR_TYPE_IPSECKEY);
+ if (!response)
+ {
+ DBG1(DBG_CFG, " query for IPSECKEY RRs failed");
+ free(fqdn);
+ return enumerator_create_empty();
+ }
+
+ if (!response->has_data(response) ||
+ !response->query_name_exist(response))
+ {
+ DBG1(DBG_CFG, " unable to retrieve IPSECKEY RRs from the DNS");
+ response->destroy(response);
+ free(fqdn);
+ return enumerator_create_empty();
+ }
+
+ if (!(response->get_security_state(response) == SECURE))
+ {
+ DBG1(DBG_CFG, " DNSSEC state of IPSECKEY RRs is not secure");
+ response->destroy(response);
+ free(fqdn);
+ return enumerator_create_empty();
+ }
+
+ free(fqdn);
+
+ /** Determine the validity period of the retrieved IPSECKEYs
+ *
+ * We use the "Signature Inception" and "Signature Expiration" field
+ * of the first RRSIG RR to determine the validity period of the
+ * IPSECKEY RRs. TODO: Take multiple RRSIGs into account.
+ */
+ rrset = response->get_rr_set(response);
+ rrsig_enum = rrset->create_rrsig_enumerator(rrset);
+ if (!rrsig_enum || !rrsig_enum->enumerate(rrsig_enum, &rrsig))
+ {
+ DBG1(DBG_CFG, " unable to determine the validity period of "
+ "IPSECKEY RRs because no RRSIGs are present");
+ DESTROY_IF(rrsig_enum);
+ response->destroy(response);
+ return enumerator_create_empty();
+ }
+
+ /**
+ * Parse the RRSIG for its validity period (RFC 4034)
+ */
+ reader = bio_reader_create(rrsig->get_rdata(rrsig));
+ reader->read_data(reader, 8, &ignore);
+ reader->read_uint32(reader, &nAfter);
+ reader->read_uint32(reader, &nBefore);
+ reader->destroy(reader);
+
+ /*Create and return an iterator over the retrieved IPSECKEYs */
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_cert_enumerator_enumerate,
+ .destroy = _cert_enumerator_destroy,
+ },
+ .inner = response->get_rr_set(response)->create_rr_enumerator(
+ response->get_rr_set(response)),
+ .response = response,
+ .notBefore = nBefore,
+ .notAfter = nAfter,
+ .identity = id,
+ );
+
+ return &e->public;
+ }
+
+
+ return enumerator_create_empty();
+}
+
+METHOD(ipseckey_cred_t, destroy, void,
+ private_ipseckey_cred_t *this)
+{
+ this->res->destroy(this->res);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipseckey_cred_t *ipseckey_cred_create(resolver_t *res)
+{
+ private_ipseckey_cred_t *this;
+
+ INIT(this,
+ .public = {
+ .set = {
+ .create_private_enumerator = (void*)return_null,
+ .create_cert_enumerator = _create_cert_enumerator,
+ .create_shared_enumerator = (void*)return_null,
+ .create_cdp_enumerator = (void*)return_null,
+ .cache_cert = (void*)nop,
+ },
+ .destroy = _destroy,
+ },
+ .res = res,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.h b/src/libcharon/plugins/ipseckey/ipseckey_cred.h
new file mode 100644
index 000000000..440020f5d
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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.
+ */
+
+/**
+ * @defgroup ipseckey_cred_i ipseckey_cred
+ * @{ @ingroup ipseckey
+ */
+
+#ifndef IPSECKEY_CRED_H_
+#define IPSECKEY_CRED_H_
+
+#include <credentials/credential_set.h>
+#include <resolver/resolver.h>
+
+typedef struct ipseckey_cred_t ipseckey_cred_t;
+
+/**
+ * IPSECKEY credential set.
+ *
+ * The ipseckey credential set contains IPSECKEYs as certificates of type
+ * pubkey_cert_t.
+ */
+struct ipseckey_cred_t {
+
+ /**
+ * Implements credential_set_t interface
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy the ipseckey_cred.
+ */
+ void (*destroy)(ipseckey_cred_t *this);
+};
+
+/**
+ * Create an ipseckey_cred instance which uses the given resolver
+ * to query the DNS for IPSECKEY resource records.
+ *
+ * @param res resolver to use
+ * @return credential set
+ */
+ipseckey_cred_t *ipseckey_cred_create(resolver_t *res);
+
+#endif /** IPSECKEY_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c
new file mode 100644
index 000000000..6f0f10507
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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 "ipseckey_plugin.h"
+
+#include <daemon.h>
+#include "ipseckey_cred.h"
+
+typedef struct private_ipseckey_plugin_t private_ipseckey_plugin_t;
+
+
+/**
+ * private data of the ipseckey plugin
+ */
+struct private_ipseckey_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ ipseckey_plugin_t public;
+
+ /**
+ * DNS resolver instance
+ */
+ resolver_t *res;
+
+ /**
+ * credential set
+ */
+ ipseckey_cred_t *cred;
+
+ /**
+ * IPSECKEY based authentication enabled
+ */
+ bool enabled;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_ipseckey_plugin_t *this)
+{
+ return "ipseckey";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_ipseckey_plugin_t *this)
+{
+ if (this->enabled)
+ {
+ lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
+ }
+ this->res->destroy(this->res);
+ DESTROY_IF(this->cred);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *ipseckey_plugin_create()
+{
+ private_ipseckey_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .reload = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .res = lib->resolver->create(lib->resolver),
+ .enabled = lib->settings->get_bool(lib->settings,
+ "charon.plugins.ipseckey.enable", FALSE),
+ );
+
+ if (!this->res)
+ {
+ DBG1(DBG_CFG, "ipseckey_plugin: Failed to create"
+ "a DNS resolver instance");
+ destroy(this);
+ return NULL;
+ }
+
+ if (this->enabled)
+ {
+ this->cred = ipseckey_cred_create(this->res);
+ lib->credmgr->add_set(lib->credmgr, &this->cred->set);
+ }
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.h b/src/libcharon/plugins/ipseckey/ipseckey_plugin.h
new file mode 100644
index 000000000..95acc79dd
--- /dev/null
+++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * 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.
+ */
+
+/**
+ * @defgroup ipseckey ipseckey
+ * @ingroup cplugins
+ *
+ * @defgroup ipseckey_plugin ipseckey_plugin
+ * @{ @ingroup ipseckey
+ */
+
+#ifndef IPSECKEY_PLUGIN_H_
+#define IPSECKEY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct ipseckey_plugin_t ipseckey_plugin_t;
+
+/**
+ * IPSECKEY plugin
+ *
+ * The IPSECKEY plugin registers a credential set for IPSECKEYs.
+ *
+ * With this credential set it is possible to authenticate tunnel endpoints
+ * using IPSECKEY resource records which are retrieved from the DNS in a secure
+ * way (DNSSEC).
+ */
+struct ipseckey_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** IPSECKEY_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 1033eb517..52afe1b0a 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -491,7 +491,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
ike_cfg = ike_cfg_create(this->version, TRUE, FALSE,
local, FALSE, this->port + num - 1,
remote, FALSE, IKEV2_NATT_PORT,
- FRAGMENTATION_NO);
+ FRAGMENTATION_NO, 0);
}
else
{
@@ -499,7 +499,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
local, FALSE,
charon->socket->get_port(charon->socket, FALSE),
remote, FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO);
+ FRAGMENTATION_NO, 0);
}
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
peer_cfg = peer_cfg_create("load-test", ike_cfg,
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index 806e4cd65..d7539c2da 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -325,7 +325,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
- hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO);
+ hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO,
+ 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create(this->current, ike_cfg,
@@ -524,4 +525,3 @@ maemo_service_t *maemo_service_create()
return &this->public;
}
-
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 73e128abe..2bff70307 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -105,7 +105,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
"0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
- address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO);
+ address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
med_cfg = peer_cfg_create(
"mediation", ike_cfg,
@@ -381,7 +381,7 @@ medcli_config_t *medcli_config_create(database_t *db)
"0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
"0.0.0.0", FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO),
+ FRAGMENTATION_NO, 0),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index be14380ea..06339220a 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -143,10 +143,9 @@ medsrv_config_t *medsrv_config_create(database_t *db)
"0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
"0.0.0.0", FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO),
+ FRAGMENTATION_NO, 0),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
return &this->public;
}
-
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index 51432c960..c0b744a68 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -55,6 +55,9 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
+#ifndef IPV6_TCLASS
+#define IPV6_TCLASS 67
+#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -113,6 +116,26 @@ struct private_socket_default_socket_t {
int ipv6_natt;
/**
+ * DSCP value set on IPv4 socket
+ */
+ u_int8_t dscp4;
+
+ /**
+ * DSCP value set on IPv4 socket for NAT-T (4500 or natt)
+ */
+ u_int8_t dscp4_natt;
+
+ /**
+ * DSCP value set on IPv6 socket (500 or port)
+ */
+ u_int8_t dscp6;
+
+ /**
+ * DSCP value set on IPv6 socket for NAT-T (4500 or natt)
+ */
+ u_int8_t dscp6_natt;
+
+ /**
* Maximum packet size to receive
*/
int max_packet;
@@ -310,6 +333,7 @@ METHOD(socket_t, sender, status_t,
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
+ u_int8_t *dscp;
src = packet->get_source(packet);
dst = packet->get_destination(packet);
@@ -322,24 +346,34 @@ METHOD(socket_t, sender, status_t,
family = dst->get_family(dst);
if (sport == 0 || sport == this->port)
{
- if (family == AF_INET)
- {
- skt = this->ipv4;
- }
- else
+ switch (family)
{
- skt = this->ipv6;
+ case AF_INET:
+ skt = this->ipv4;
+ dscp = &this->dscp4;
+ break;
+ case AF_INET6:
+ skt = this->ipv6;
+ dscp = &this->dscp6;
+ break;
+ default:
+ return FAILED;
}
}
else if (sport == this->natt)
{
- if (family == AF_INET)
- {
- skt = this->ipv4_natt;
- }
- else
+ switch (family)
{
- skt = this->ipv6_natt;
+ case AF_INET:
+ skt = this->ipv4_natt;
+ dscp = &this->dscp4_natt;
+ break;
+ case AF_INET6:
+ skt = this->ipv6_natt;
+ dscp = &this->dscp6_natt;
+ break;
+ default:
+ return FAILED;
}
}
else
@@ -348,6 +382,43 @@ METHOD(socket_t, sender, status_t,
return FAILED;
}
+ /* setting DSCP values per-packet in a cmsg seems not to be supported
+ * on Linux. We instead setsockopt() before sending it, this should be
+ * safe as only a single thread calls send(). */
+ if (*dscp != packet->get_dscp(packet))
+ {
+ if (family == AF_INET)
+ {
+ u_int8_t ds4;
+
+ ds4 = packet->get_dscp(packet) << 2;
+ if (setsockopt(skt, SOL_IP, IP_TOS, &ds4, sizeof(ds4)) == 0)
+ {
+ *dscp = packet->get_dscp(packet);
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to set IP_TOS on socket: %s",
+ strerror(errno));
+ }
+ }
+ else
+ {
+ u_int ds6;
+
+ ds6 = packet->get_dscp(packet) << 2;
+ if (setsockopt(skt, SOL_IPV6, IPV6_TCLASS, &ds6, sizeof(ds6)) == 0)
+ {
+ *dscp = packet->get_dscp(packet);
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to set IPV6_TCLASS on socket: %s",
+ strerror(errno));
+ }
+ }
+ }
+
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = dst->get_sockaddr(dst);;
msg.msg_namelen = *dst->get_sockaddr_len(dst);
@@ -433,22 +504,24 @@ static int open_socket(private_socket_default_socket_t *this,
int family, u_int16_t *port)
{
int on = TRUE;
- struct sockaddr_storage addr;
+ union {
+ struct sockaddr sockaddr;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
socklen_t addrlen;
u_int sol, pktinfo = 0;
int skt;
memset(&addr, 0, sizeof(addr));
- addr.ss_family = family;
+ addr.sockaddr.sa_family = family;
/* precalculate constants depending on address family */
switch (family)
{
case AF_INET:
- {
- struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
- htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
- htoun16(&sin->sin_port, *port);
- addrlen = sizeof(struct sockaddr_in);
+ addr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin.sin_port = htons(*port);
+ addrlen = sizeof(addr.sin);
sol = SOL_IP;
#ifdef IP_PKTINFO
pktinfo = IP_PKTINFO;
@@ -456,17 +529,13 @@ static int open_socket(private_socket_default_socket_t *this,
pktinfo = IP_RECVDSTADDR;
#endif
break;
- }
case AF_INET6:
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
- memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
- htoun16(&sin6->sin6_port, *port);
- addrlen = sizeof(struct sockaddr_in6);
+ memcpy(&addr.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any));
+ addr.sin6.sin6_port = htons(*port);
+ addrlen = sizeof(addr.sin6);
sol = SOL_IPV6;
pktinfo = IPV6_RECVPKTINFO;
break;
- }
default:
return 0;
}
@@ -485,7 +554,7 @@ static int open_socket(private_socket_default_socket_t *this,
}
/* bind the socket */
- if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
+ if (bind(skt, &addr.sockaddr, addrlen) < 0)
{
DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
close(skt);
@@ -495,7 +564,7 @@ static int open_socket(private_socket_default_socket_t *this,
/* retrieve randomly allocated port if needed */
if (*port == 0)
{
- if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0)
+ if (getsockname(skt, &addr.sockaddr, &addrlen) < 0)
{
DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
close(skt);
@@ -504,17 +573,11 @@ static int open_socket(private_socket_default_socket_t *this,
switch (family)
{
case AF_INET:
- {
- struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
- *port = untoh16(&sin->sin_port);
+ *port = ntohs(addr.sin.sin_port);
break;
- }
case AF_INET6:
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
- *port = untoh16(&sin6->sin6_port);
+ *port = ntohs(addr.sin6.sin6_port);
break;
- }
}
}
@@ -642,4 +705,3 @@ socket_default_socket_t *socket_default_socket_create()
return &this->public;
}
-
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 37bd86671..c3471a078 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -262,7 +262,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
local, FALSE,
charon->socket->get_port(charon->socket, FALSE),
remote, FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO);
+ FRAGMENTATION_NO, 0);
add_ike_proposals(this, ike_cfg, id);
return ike_cfg;
}
@@ -620,4 +620,3 @@ sql_config_t *sql_config_create(database_t *db)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index ed10bdb9f..deff25878 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -234,7 +234,8 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
msg->add_conn.other.address,
msg->add_conn.other.allow_any,
msg->add_conn.other.ikeport,
- msg->add_conn.fragmentation);
+ msg->add_conn.fragmentation,
+ msg->add_conn.ikedscp);
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 2771f0146..e31616cf8 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -516,11 +516,18 @@ static void stroke_loglevel(private_stroke_socket_t *this,
DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
msg->loglevel.level, msg->loglevel.type);
- group = enum_from_name(debug_names, msg->loglevel.type);
- if ((int)group < 0)
+ if (strcaseeq(msg->loglevel.type, "any"))
{
- fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
- return;
+ group = DBG_ANY;
+ }
+ else
+ {
+ group = enum_from_name(debug_names, msg->loglevel.type);
+ if ((int)group < 0)
+ {
+ fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
+ return;
+ }
}
charon->set_level(charon, group, msg->loglevel.level);
}
diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am
index 5e2c30df9..eba280690 100644
--- a/src/libcharon/plugins/tnc_imc/Makefile.am
+++ b/src/libcharon/plugins/tnc_imc/Makefile.am
@@ -4,7 +4,8 @@ INCLUDES = \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libtncif \
- -I$(top_srcdir)/src/libtnccs
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
AM_CFLAGS = -rdynamic
diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am
index eca3b377b..90b3507ce 100644
--- a/src/libcharon/plugins/tnc_imv/Makefile.am
+++ b/src/libcharon/plugins/tnc_imv/Makefile.am
@@ -4,7 +4,8 @@ INCLUDES = \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libtncif \
- -I$(top_srcdir)/src/libtnccs
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
AM_CFLAGS = -rdynamic
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
index 39939d34e..422c28bc9 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
@@ -378,7 +378,10 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
}
this->connections->add(this->connections, nas_id, user_name, peer,
method);
- method->initiate(method, &out);
+ if (method->initiate(method, &out) == NEED_MORE)
+ {
+ send_response(this, request, code, out, group, msk, source);
+ }
}
else
{
@@ -428,16 +431,16 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
in->get_identifier(in));
}
charon->bus->set_sa(charon->bus, NULL);
+ send_response(this, request, code, out, group, msk, source);
+ this->connections->unlock(this->connections);
}
- send_response(this, request, code, out, group, msk, source);
- out->destroy(out);
-
if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT)
{
this->connections->remove(this->connections, nas_id, user_name);
}
+ out->destroy(out);
end:
free(message.ptr);
in->destroy(in);
@@ -648,4 +651,3 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
index 0a960635b..f789c31d2 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
@@ -17,6 +17,15 @@
#include <collections/linked_list.h>
#include <utils/debug.h>
+#include <threading/rwlock.h>
+#include <processing/jobs/callback_job.h>
+
+#include <daemon.h>
+
+/**
+ * Default PDP connection timeout, in s
+ */
+#define DEFAULT_TIMEOUT 30
typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t;
typedef struct entry_t entry_t;
@@ -32,9 +41,19 @@ struct private_tnc_pdp_connections_t {
tnc_pdp_connections_t public;
/**
- * List of TNC PEP RADIUS Connections
+ * TNC PEP RADIUS Connections
*/
linked_list_t *list;
+
+ /**
+ * Lock to access PEP connection list
+ */
+ rwlock_t *lock;
+
+ /**
+ * Connection timeout before we kill non-completed connections, in s
+ */
+ int timeout;
};
/**
@@ -61,6 +80,11 @@ struct entry_t {
* IKE SA used for bus communication
*/
ike_sa_t *ike_sa;
+
+ /**
+ * Timestamp this entry has been created
+ */
+ time_t created;
};
/**
@@ -105,6 +129,35 @@ static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
}
}
+/**
+ * Check if any connection has timed out
+ */
+static job_requeue_t check_timeouts(private_tnc_pdp_connections_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ time_t now;
+
+ now = time_monotonic(NULL);
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->created + this->timeout <= now)
+ {
+ DBG1(DBG_CFG, "RADIUS connection timed out after %d seconds",
+ this->timeout);
+ this->list->remove_at(this->list, enumerator);
+ free_entry(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return JOB_REQUEUE_NONE;
+}
+
METHOD(tnc_pdp_connections_t, add, void,
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
identification_t *peer, eap_method_t *method)
@@ -120,6 +173,7 @@ METHOD(tnc_pdp_connections_t, add, void,
ike_sa_id->destroy(ike_sa_id);
ike_sa->set_other_id(ike_sa, peer);
+ this->lock->read_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -131,20 +185,33 @@ METHOD(tnc_pdp_connections_t, add, void,
DBG1(DBG_CFG, "removed stale RADIUS connection");
entry->method = method;
entry->ike_sa = ike_sa;
+ entry->created = time_monotonic(NULL);
break;
}
}
enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
if (!found)
{
- entry = malloc_thing(entry_t);
- entry->nas_id = chunk_clone(nas_id);
- entry->user_name = chunk_clone(user_name);
- entry->method = method;
- entry->ike_sa = ike_sa;
+ INIT(entry,
+ .nas_id = chunk_clone(nas_id),
+ .user_name = chunk_clone(user_name),
+ .method = method,
+ .ike_sa = ike_sa,
+ .created = time_monotonic(NULL),
+ );
+ this->lock->write_lock(this->lock);
this->list->insert_last(this->list, entry);
+ this->lock->unlock(this->lock);
}
+
+ /* schedule timeout checking */
+ lib->scheduler->schedule_job_ms(lib->scheduler,
+ (job_t*)callback_job_create((callback_job_cb_t)check_timeouts,
+ this, NULL, (callback_job_cancel_t)return_false),
+ this->timeout * 1000);
+
dbg_nas_user(nas_id, user_name, FALSE, "created");
}
@@ -154,6 +221,7 @@ METHOD(tnc_pdp_connections_t, remove_, void,
enumerator_t *enumerator;
entry_t *entry;
+ this->lock->write_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -166,6 +234,7 @@ METHOD(tnc_pdp_connections_t, remove_, void,
}
}
enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
}
METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
@@ -176,6 +245,7 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
entry_t *entry;
eap_method_t *found = NULL;
+ this->lock->read_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -187,14 +257,25 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
}
}
enumerator->destroy(enumerator);
+ if (!found)
+ {
+ this->lock->unlock(this->lock);
+ }
dbg_nas_user(nas_id, user_name, !found, "found");
return found;
}
+METHOD(tnc_pdp_connections_t, unlock, void,
+ private_tnc_pdp_connections_t *this)
+{
+ this->lock->unlock(this->lock);
+}
+
METHOD(tnc_pdp_connections_t, destroy, void,
private_tnc_pdp_connections_t *this)
{
+ this->lock->destroy(this->lock);
this->list->destroy_function(this->list, (void*)free_entry);
free(this);
}
@@ -211,11 +292,14 @@ tnc_pdp_connections_t *tnc_pdp_connections_create(void)
.add = _add,
.remove = _remove_,
.get_state = _get_state,
+ .unlock = _unlock,
.destroy = _destroy,
},
.list = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnc-pdp.timeout", DEFAULT_TIMEOUT, charon->name),
);
return &this->public;
}
-
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
index 16492020e..442f29ce9 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
@@ -53,7 +53,10 @@ struct tnc_pdp_connections_t {
chunk_t user_name);
/**
- * Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection
+ * Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection.
+ *
+ * If this call succeeds, the connection manager is locked. Call unlock
+ * after using the return objects.
*
* @param nas_id NAS identifier of Policy Enforcement Point
* @param user_name User name of TNC Client
@@ -64,6 +67,11 @@ struct tnc_pdp_connections_t {
chunk_t user_name, ike_sa_t **ike_sa);
/**
+ * Unlock connections after successfully calling get_state().
+ */
+ void (*unlock)(tnc_pdp_connections_t *this);
+
+ /**
* Destroys a tnc_pdp_connections_t object.
*/
void (*destroy)(tnc_pdp_connections_t *this);
diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.am b/src/libcharon/plugins/tnc_tnccs/Makefile.am
index c7fc02f7c..9ee9e86ad 100644
--- a/src/libcharon/plugins/tnc_tnccs/Makefile.am
+++ b/src/libcharon/plugins/tnc_tnccs/Makefile.am
@@ -1,6 +1,7 @@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
index 0b623d6ff..6ddda594d 100644
--- a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
+++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +20,13 @@
#include <tnc/imc/imc_manager.h>
#include <tnc/imv/imv_manager.h>
+#include <tncif_identity.h>
+
+#include <tls.h>
+
#include <utils/debug.h>
+#include <pen/pen.h>
+#include <bio/bio_writer.h>
#include <collections/linked_list.h>
#include <threading/rwlock.h>
@@ -158,7 +164,9 @@ METHOD(tnccs_manager_t, remove_method, void,
}
METHOD(tnccs_manager_t, create_instance, tnccs_t*,
- private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
+ private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport)
{
enumerator_t *enumerator;
tnccs_entry_t *entry;
@@ -170,7 +178,7 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*,
{
if (type == entry->type)
{
- protocol = entry->constructor(is_server);
+ protocol = entry->constructor(is_server, server, peer, transport);
if (protocol)
{
break;
@@ -442,6 +450,44 @@ static TNC_Result str_attribute(TNC_UInt32 buffer_len,
}
}
+/**
+ * Write the value of a TNC identity list into the buffer
+ */
+static TNC_Result identity_attribute(TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len,
+ linked_list_t *list)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ u_int32_t count;
+ chunk_t value;
+ tncif_identity_t *tnc_id;
+ TNC_Result result = TNC_RESULT_INVALID_PARAMETER;
+
+ count = list->get_count(list);
+ writer = bio_writer_create(4 + TNCIF_IDENTITY_MIN_SIZE * count);
+ writer->write_uint32(writer, count);
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &tnc_id))
+ {
+ tnc_id->build(tnc_id, writer);
+ }
+ enumerator->destroy(enumerator);
+
+ value = writer->get_buf(writer);
+ *value_len = value.len;
+ if (buffer && buffer_len >= value.len)
+ {
+ memcpy(buffer, value.ptr, value.len);
+ result = TNC_RESULT_SUCCESS;
+ }
+ writer->destroy(writer);
+
+ return result;
+}
+
METHOD(tnccs_manager_t, get_attribute, TNC_Result,
private_tnc_tnccs_manager_t *this, bool is_imc,
TNC_UInt32 imcv_id,
@@ -487,6 +533,7 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
/* these attributes are supported */
case TNC_ATTRIBUTEID_PRIMARY_IMV_ID:
+ case TNC_ATTRIBUTEID_AR_IDENTITIES:
attribute_match = TRUE;
break;
@@ -616,15 +663,111 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
version = "1.0";
break;
default:
- return TNC_RESULT_INVALID_PARAMETER;
+ 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");
+ {
+ char *protocol;
+
+ switch (entry->tnccs->get_transport(entry->tnccs))
+ {
+ case TNC_IFT_EAP_1_0:
+ case TNC_IFT_EAP_1_1:
+ case TNC_IFT_EAP_2_0:
+ protocol = "IF-T for Tunneled EAP";
+ break;
+ case TNC_IFT_TLS_1_0:
+ case TNC_IFT_TLS_2_0:
+ protocol = "IF-T for TLS";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, protocol);
+ }
case TNC_ATTRIBUTEID_IFT_VERSION:
- return str_attribute(buffer_len, buffer, value_len, "1.1");
+ {
+ char *version;
+
+ switch (entry->tnccs->get_transport(entry->tnccs))
+ {
+ case TNC_IFT_EAP_1_0:
+ case TNC_IFT_TLS_1_0:
+ version = "1.0";
+ break;
+ case TNC_IFT_EAP_1_1:
+ version = "1.1";
+ break;
+ case TNC_IFT_EAP_2_0:
+ case TNC_IFT_TLS_2_0:
+ version = "2.0";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, version);
+ }
+ case TNC_ATTRIBUTEID_AR_IDENTITIES:
+ {
+ linked_list_t *list;
+ identification_t *peer;
+ tnccs_t *tnccs;
+ tncif_identity_t *tnc_id;
+ u_int32_t id_type, subject_type;
+ TNC_Result result;
+
+ list = linked_list_create();
+ tnccs = entry->tnccs;
+ peer = tnccs->tls.get_peer_id(&tnccs->tls);
+ if (peer)
+ {
+ switch (peer->get_type(peer))
+ {
+ case ID_IPV4_ADDR:
+ id_type = TNC_ID_IPV4_ADDR;
+ subject_type = TNC_SUBJECT_MACHINE;
+ break;
+ case ID_IPV6_ADDR:
+ id_type = TNC_ID_IPV6_ADDR;
+ subject_type = TNC_SUBJECT_MACHINE;
+ break;
+ case ID_FQDN:
+ id_type = TNC_ID_USER_NAME;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ case ID_RFC822_ADDR:
+ id_type = TNC_ID_RFC822_ADDR;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ case ID_DER_ASN1_DN:
+ id_type = TNC_ID_DER_ASN1_DN;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ case ID_DER_ASN1_GN:
+ id_type = TNC_ID_DER_ASN1_GN;
+ subject_type = TNC_SUBJECT_UNKNOWN;
+ break;
+ default:
+ id_type = TNC_ID_UNKNOWN;
+ subject_type = TNC_SUBJECT_UNKNOWN;
+ }
+ if (id_type != TNC_ID_UNKNOWN)
+ {
+ tnc_id = tncif_identity_create(
+ pen_type_create(PEN_TCG, id_type),
+ peer->get_encoding(peer),
+ pen_type_create(PEN_TCG, subject_type),
+ pen_type_create(PEN_TCG,
+ tnccs->get_auth_type(tnccs)));
+ list->insert_last(list, tnc_id);
+ }
+ }
+ result = identity_attribute(buffer_len, buffer, value_len, list);
+ list->destroy_offset(list, offsetof(tncif_identity_t, destroy));
+ return result;
+ }
default:
return TNC_RESULT_INVALID_PARAMETER;
}
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c
index cfc29d6ab..53817c710 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11.c
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -43,9 +43,9 @@ typedef struct private_tnccs_11_t private_tnccs_11_t;
struct private_tnccs_11_t {
/**
- * Public tls_t interface.
+ * Public tnccs_t interface.
*/
- tls_t public;
+ tnccs_t public;
/**
* TNCC if TRUE, TNCS if FALSE
@@ -53,6 +53,26 @@ struct private_tnccs_11_t {
bool is_server;
/**
+ * Server identity
+ */
+ identification_t *server;
+
+ /**
+ * Client identity
+ */
+ identification_t *peer;
+
+ /**
+ * Underlying TNC IF-T transport protocol
+ */
+ tnc_ift_type_t transport;
+
+ /**
+ * Type of TNC client authentication
+ */
+ u_int32_t auth_type;
+
+ /**
* Connection ID assigned to this TNCCS connection
*/
TNC_ConnectionID connection_id;
@@ -495,6 +515,18 @@ METHOD(tls_t, is_server, bool,
return this->is_server;
}
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_11_t *this)
+{
+ return this->server;
+}
+
+METHOD(tls_t, get_peer_id, identification_t*,
+ private_tnccs_11_t *this)
+{
+ return this->peer;
+}
+
METHOD(tls_t, get_purpose, tls_purpose_t,
private_tnccs_11_t *this)
{
@@ -528,29 +560,69 @@ METHOD(tls_t, destroy, void,
{
tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
this->is_server);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
this->mutex->destroy(this->mutex);
DESTROY_IF(this->batch);
free(this);
}
+METHOD(tnccs_t, get_transport, tnc_ift_type_t,
+ private_tnccs_11_t *this)
+{
+ return this->transport;
+}
+
+METHOD(tnccs_t, set_transport, void,
+ private_tnccs_11_t *this, tnc_ift_type_t transport)
+{
+ this->transport = transport;
+}
+
+METHOD(tnccs_t, get_auth_type, u_int32_t,
+ private_tnccs_11_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(tnccs_t, set_auth_type, void,
+ private_tnccs_11_t *this, u_int32_t auth_type)
+{
+ this->auth_type = auth_type;
+}
+
/**
* See header
*/
-tls_t *tnccs_11_create(bool is_server)
+tnccs_t* tnccs_11_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport)
{
private_tnccs_11_t *this;
INIT(this,
.public = {
- .process = _process,
- .build = _build,
- .is_server = _is_server,
- .get_purpose = _get_purpose,
- .is_complete = _is_complete,
- .get_eap_msk = _get_eap_msk,
- .destroy = _destroy,
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_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,
},
.is_server = is_server,
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.max_msg_len = lib->settings->get_int(lib->settings,
"%s.plugins.tnccs-11.max_message_size", 45000,
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.h b/src/libcharon/plugins/tnccs_11/tnccs_11.h
index 7331fc8cd..531ebb611 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11.h
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,14 +23,20 @@
#include <library.h>
-#include <tls.h>
+#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of the TNC IF-TNCCS 1.1 protocol handler.
*
- * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @return TNC_IF_TNCCS 1.1 protocol stack
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @return TNC_IF_TNCCS 1.1 protocol stack
*/
-tls_t *tnccs_11_create(bool is_server);
+tnccs_t* tnccs_11_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport);
#endif /** TNCCS_11_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c
index cd95afb1e..f534af008 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c
@@ -30,8 +30,6 @@ METHOD(plugin_t, get_features, int,
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnccs_method_register, tnccs_11_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-1.1"),
- PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC),
- PLUGIN_DEPENDS(EAP_PEER, EAP_TNC),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
};
*features = f;
@@ -61,4 +59,3 @@ plugin_t *tnccs_11_plugin_create()
return &this->plugin;
}
-
diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
index 3a2c70f5a..b1f6d1eaa 100644
--- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
+++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -386,6 +386,13 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
}
else
{
+ if (msg_type == PB_MSG_EXPERIMENTAL && noskip_flag)
+ {
+ DBG1(DBG_TNC, "reject PB-Experimental message with NOSKIP flag set");
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
+ goto fatal;
+ }
if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE &&
pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag)
{
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
index 2d2c1316b..aa5e9c723 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
@@ -166,6 +166,7 @@ METHOD(pb_tnc_msg_t, process, status_t,
{
DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
*offset = 4;
+ return FAILED;
}
return SUCCESS;
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
index 63d94b94d..2ef8dd6cd 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
@@ -66,24 +66,24 @@ struct private_pb_remediation_parameters_msg_t {
pb_tnc_msg_type_t type;
/**
- * Remediation Parameters Vendor ID
+ * Remediation Parameters Type
*/
- u_int32_t vendor_id;
+ pen_type_t parameters_type;
/**
- * Remediation Parameters Type
+ * Remediation Parameters
*/
- u_int32_t parameters_type;
+ chunk_t parameters;
/**
- * Remediation Parameters string
+ * Remediation String
*/
- chunk_t remediation_string;
+ chunk_t string;
/**
- * Language code
+ * Remediation Language Code
*/
- chunk_t language_code;
+ chunk_t lang_code;
/**
* Encoded message
@@ -113,10 +113,9 @@ METHOD(pb_tnc_msg_t, build, void,
return;
}
writer = bio_writer_create(64);
- writer->write_uint32(writer, this->vendor_id);
- writer->write_uint32(writer, this->parameters_type);
- writer->write_data32(writer, this->remediation_string);
- writer->write_data8 (writer, this->language_code);
+ writer->write_uint32(writer, this->parameters_type.vendor_id);
+ writer->write_uint32(writer, this->parameters_type.type);
+ writer->write_data32(writer, this->parameters);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
@@ -127,83 +126,103 @@ METHOD(pb_tnc_msg_t, process, status_t,
private_pb_remediation_parameters_msg_t *this, u_int32_t *offset)
{
bio_reader_t *reader;
+ u_int8_t reserved;
+ status_t status = SUCCESS;
+ u_char *pos;
+
+ *offset = 0;
/* process message */
reader = bio_reader_create(this->encoding);
- reader->read_uint32(reader, &this->vendor_id);
- reader->read_uint32(reader, &this->parameters_type);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &this->parameters_type.vendor_id);
+ reader->read_uint32(reader, &this->parameters_type.type);
+ reader->read_data (reader, reader->remaining(reader), &this->parameters);
- if (!reader->read_data32(reader, &this->remediation_string))
+ this->parameters = chunk_clone(this->parameters);
+ reader->destroy(reader);
+
+ if (this->parameters_type.vendor_id == PEN_IETF &&
+ this->parameters_type.type == PB_REMEDIATION_STRING)
{
- DBG1(DBG_TNC, "could not parse remediation string");
- reader->destroy(reader);
+ reader = bio_reader_create(this->parameters);
+ status = FAILED;
*offset = 8;
- return FAILED;
- };
- this->remediation_string = chunk_clone(this->remediation_string);
- if (this->remediation_string.len &&
- this->remediation_string.ptr[this->remediation_string.len-1] == '\0')
- {
- DBG1(DBG_TNC, "remediation string must not be null terminated");
+ if (!reader->read_data32(reader, &this->string))
+ {
+ DBG1(DBG_TNC, "insufficient data for remediation string");
+ goto end;
+ };
+ *offset += 4;
+
+ pos = memchr(this->string.ptr, '\0', this->string.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in remediation string");
+ *offset += (pos - this->string.ptr);
+ goto end;
+ }
+ *offset += this->string.len;
+
+ if (!reader->read_data8(reader, &this->lang_code))
+ {
+ DBG1(DBG_TNC, "insufficient data for remediation string lang code");
+ goto end;
+ };
+ *offset += 1;
+
+ pos = memchr(this->lang_code.ptr, '\0', this->lang_code.len);
+
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in remediation string lang code");
+ *offset += (pos - this->lang_code.ptr);
+ goto end;
+ }
+ status = SUCCESS;
+
+end:
reader->destroy(reader);
- *offset = 11 + this->remediation_string.len;
- return FAILED;
}
-
- if (!reader->read_data8(reader, &this->language_code))
- {
- DBG1(DBG_TNC, "could not parse language code");
- reader->destroy(reader);
- *offset = 12 + this->remediation_string.len;
- return FAILED;
- };
- this->language_code = chunk_clone(this->language_code);
- reader->destroy(reader);
-
- if (this->language_code.len &&
- this->language_code.ptr[this->language_code.len-1] == '\0')
- {
- DBG1(DBG_TNC, "language code must not be null terminated");
- *offset = 12 + this->remediation_string.len + this->language_code.len;
- return FAILED;
- }
-
- return SUCCESS;
+ return status;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_remediation_parameters_msg_t *this)
{
free(this->encoding.ptr);
- free(this->remediation_string.ptr);
- free(this->language_code.ptr);
+ free(this->parameters.ptr);
free(this);
}
-METHOD(pb_remediation_parameters_msg_t, get_vendor_id, u_int32_t,
- private_pb_remediation_parameters_msg_t *this, u_int32_t *type)
+METHOD(pb_remediation_parameters_msg_t, get_parameters_type, pen_type_t,
+ private_pb_remediation_parameters_msg_t *this)
{
- *type = this->parameters_type;
- return this->vendor_id;
+ return this->parameters_type;
}
-METHOD(pb_remediation_parameters_msg_t, get_remediation_string, chunk_t,
+METHOD(pb_remediation_parameters_msg_t, get_parameters, chunk_t,
private_pb_remediation_parameters_msg_t *this)
{
- return this->remediation_string;
+ return this->parameters;
}
-METHOD(pb_remediation_parameters_msg_t, get_language_code, chunk_t,
- private_pb_remediation_parameters_msg_t *this)
+METHOD(pb_remediation_parameters_msg_t, get_string, chunk_t,
+ private_pb_remediation_parameters_msg_t *this, chunk_t *lang_code)
{
- return this->language_code;
+ if (lang_code)
+ {
+ *lang_code = this->lang_code;
+ }
+ return this->string;
}
/**
* See header
*/
-pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
+ chunk_t parameters)
{
private_pb_remediation_parameters_msg_t *this;
@@ -216,24 +235,56 @@ pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
.process = _process,
.destroy = _destroy,
},
- .get_vendor_id = _get_vendor_id,
- .get_remediation_string = _get_remediation_string,
- .get_language_code = _get_language_code,
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_parameters,
+ .get_string = _get_string,
},
- .type = PB_MSG_REASON_STRING,
- .encoding = chunk_clone(data),
+ .type = PB_MSG_REMEDIATION_PARAMETERS,
+ .parameters_type = parameters_type,
+ .parameters = chunk_clone(parameters),
);
return &this->public.pb_interface;
}
/**
+ * Described in header.
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri)
+{
+ pen_type_t type = { PEN_IETF, PB_REMEDIATION_URI };
+
+ return pb_remediation_parameters_msg_create(type, uri);
+}
+
+/**
+ * Described in header.
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
+ chunk_t lang_code)
+{
+ pb_tnc_msg_t *msg;
+ bio_writer_t *writer;
+ pen_type_t type = { PEN_IETF, PB_REMEDIATION_STRING };
+
+ /* limit language code to 255 octets */
+ lang_code.len = min(255, lang_code.len);
+
+ writer = bio_writer_create(4 + string.len + 1 + lang_code.len);
+ writer->write_data32(writer, string);
+ writer->write_data8 (writer, lang_code);
+
+ msg = pb_remediation_parameters_msg_create(type, writer->get_buf(writer));
+ writer->destroy(writer);
+
+ return msg;
+}
+
+/**
* See header
*/
-pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id,
- u_int32_t type,
- chunk_t remediation_string,
- chunk_t language_code)
+pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
{
private_pb_remediation_parameters_msg_t *this;
@@ -246,16 +297,15 @@ pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id,
.process = _process,
.destroy = _destroy,
},
- .get_vendor_id = _get_vendor_id,
- .get_remediation_string = _get_remediation_string,
- .get_language_code = _get_language_code,
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_parameters,
+ .get_string = _get_string,
},
- .type = PB_MSG_REASON_STRING,
- .vendor_id = vendor_id,
- .parameters_type = type,
- .remediation_string = chunk_clone(remediation_string),
- .language_code = chunk_clone(language_code),
+ .type = PB_MSG_REMEDIATION_PARAMETERS,
+ .encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
+
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h
index 258d495ec..f3a1c1009 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2011-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@ typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t;
#include "pb_tnc_msg.h"
+#include <pen/pen.h>
+
/**
* PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793
*/
@@ -50,41 +52,61 @@ struct pb_remediation_parameters_msg_t {
pb_tnc_msg_t pb_interface;
/**
- * Get Remediation Parameters Vendor ID and Type
+ * Get the Remediation Parameters Type (Vendor ID and Type)
*
- * @param type Remediation Parameters Type
- * @return Remediation Parameters Vendor ID
+ * @return Remediation Parameters Type
*/
- u_int32_t (*get_vendor_id)(pb_remediation_parameters_msg_t *this,
- u_int32_t *type);
+ pen_type_t (*get_parameters_type)(pb_remediation_parameters_msg_t *this);
/**
- * Get Remediation String
+ * Get the Remediation Parameters
*
- * @return Remediation String
+ * @return Remediation Parameters
*/
- chunk_t (*get_remediation_string)(pb_remediation_parameters_msg_t *this);
+ chunk_t (*get_parameters)(pb_remediation_parameters_msg_t *this);
/**
- * Get Reason String Language Code
+ * Get the Remediation URI
*
- * @return Language Code
+ * @return Remediation URI
*/
- chunk_t (*get_language_code)(pb_remediation_parameters_msg_t *this);
+ chunk_t (*get_uri)(pb_remediation_parameters_msg_t *this);
+
+ /**
+ * Get the Remediation String
+ *
+ * @param lang_code Optional Language Code
+ * @return Remediation String
+ */
+ chunk_t (*get_string)(pb_remediation_parameters_msg_t *this,
+ chunk_t *lang_code);
+
};
/**
- * Create a PB-Remediation-Parameters message from parameters
+ * Create a general PB-Remediation-Parameters message
+ *
+ * @param parameters_type Remediation Parameters Type
+ * @param parameters Remediation Parameters
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
+ chunk_t parameters);
+
+/**
+ * Create a PB-Remediation-Parameters message of IETF Type Remediation URI
+ *
+ * @param uri Remediation URI
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri);
+
+/**
+ * Create a PB-Remediation-Parameters message of IETF Type Remediation String
*
- * @param vendor_id Remediation Parameters Vendor ID
- * @param type Remediation Parameters Type
- * @param remediation_string Remediation String
- * @param language_code Language Code
+ * @param string Remediation String
+ * @param lang_code Remediation String Language Code
*/
-pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id,
- u_int32_t type,
- chunk_t remediation_string,
- chunk_t language_code);
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
+ chunk_t lang_code);
/**
* Create an unprocessed PB-Remediation-Parameters message from raw data
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c
index 6239b152d..29a161e69 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20.c
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -48,9 +48,9 @@ typedef struct private_tnccs_20_t private_tnccs_20_t;
struct private_tnccs_20_t {
/**
- * Public tls_t interface.
+ * Public tnccs_t interface.
*/
- tls_t public;
+ tnccs_t public;
/**
* TNCC if TRUE, TNCS if FALSE
@@ -58,6 +58,26 @@ struct private_tnccs_20_t {
bool is_server;
/**
+ * Server identity
+ */
+ identification_t *server;
+
+ /**
+ * Client identity
+ */
+ identification_t *peer;
+
+ /**
+ * Underlying TNC IF-T transport protocol
+ */
+ tnc_ift_type_t transport;
+
+ /**
+ * Type of TNC client authentication
+ */
+ u_int32_t auth_type;
+
+ /**
* PB-TNC State Machine
*/
pb_tnc_state_machine_t *state_machine;
@@ -291,7 +311,36 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
}
case PB_MSG_REMEDIATION_PARAMETERS:
{
- /* TODO : Remediation parameters message processing */
+ pb_remediation_parameters_msg_t *rem_msg;
+ pen_type_t parameters_type;
+ chunk_t parameters, string, lang_code;
+
+ rem_msg = (pb_remediation_parameters_msg_t*)msg;
+ parameters_type = rem_msg->get_parameters_type(rem_msg);
+ parameters = rem_msg->get_parameters(rem_msg);
+
+ if (parameters_type.vendor_id == PEN_IETF)
+ {
+ switch (parameters_type.type)
+ {
+ case PB_REMEDIATION_URI:
+ DBG1(DBG_TNC, "remediation uri: %.*s",
+ parameters.len, parameters.ptr);
+ break;
+ case PB_REMEDIATION_STRING:
+ string = rem_msg->get_string(rem_msg, &lang_code);
+ DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s",
+ lang_code.len, lang_code.ptr,
+ string.len, string.ptr);
+ break;
+ default:
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
break;
}
case PB_MSG_ERROR:
@@ -356,9 +405,12 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
lang_msg = (pb_language_preference_msg_t*)msg;
lang = lang_msg->get_language_preference(lang_msg);
- DBG2(DBG_TNC, "setting language preference to '%.*s'",
- (int)lang.len, lang.ptr);
- this->recs->set_preferred_language(this->recs, lang);
+ if (this->recs)
+ {
+ DBG2(DBG_TNC, "setting language preference to '%.*s'",
+ (int)lang.len, lang.ptr);
+ this->recs->set_preferred_language(this->recs, lang);
+ }
break;
}
case PB_MSG_REASON_STRING:
@@ -759,6 +811,18 @@ METHOD(tls_t, is_server, bool,
return this->is_server;
}
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_20_t *this)
+{
+ return this->server;
+}
+
+METHOD(tls_t, get_peer_id, identification_t*,
+ private_tnccs_20_t *this)
+{
+ return this->peer;
+}
+
METHOD(tls_t, get_purpose, tls_purpose_t,
private_tnccs_20_t *this)
{
@@ -792,6 +856,8 @@ METHOD(tls_t, destroy, void,
{
tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
this->is_server);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
this->state_machine->destroy(this->state_machine);
this->mutex->destroy(this->mutex);
this->messages->destroy_offset(this->messages,
@@ -799,24 +865,62 @@ METHOD(tls_t, destroy, void,
free(this);
}
+METHOD(tnccs_t, get_transport, tnc_ift_type_t,
+ private_tnccs_20_t *this)
+{
+ return this->transport;
+}
+
+METHOD(tnccs_t, set_transport, void,
+ private_tnccs_20_t *this, tnc_ift_type_t transport)
+{
+ this->transport = transport;
+}
+
+METHOD(tnccs_t, get_auth_type, u_int32_t,
+ private_tnccs_20_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(tnccs_t, set_auth_type, void,
+ private_tnccs_20_t *this, u_int32_t auth_type)
+{
+ this->auth_type = auth_type;
+}
+
/**
* See header
*/
-tls_t *tnccs_20_create(bool is_server)
+tnccs_t* tnccs_20_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport)
{
private_tnccs_20_t *this;
INIT(this,
.public = {
- .process = _process,
- .build = _build,
- .is_server = _is_server,
- .get_purpose = _get_purpose,
- .is_complete = _is_complete,
- .get_eap_msk = _get_eap_msk,
- .destroy = _destroy,
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_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,
},
.is_server = is_server,
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
.state_machine = pb_tnc_state_machine_create(is_server),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.messages = linked_list_create(),
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.h b/src/libcharon/plugins/tnccs_20/tnccs_20.h
index 400d1dc12..314935069 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20.h
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,14 +23,20 @@
#include <library.h>
-#include <tls.h>
+#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of the TNC IF-TNCCS 2.0 protocol handler.
*
- * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @return TNC_IF_TNCCS 2.0 protocol stack
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @return TNC_IF_TNCCS 2.0 protocol stack
*/
-tls_t *tnccs_20_create(bool is_server);
+tnccs_t* tnccs_20_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport);
#endif /** TNCCS_20_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c
index 4f419ecf0..f74306c8c 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c
@@ -30,8 +30,6 @@ METHOD(plugin_t, get_features, int,
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnccs_method_register, tnccs_20_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-2.0"),
- PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC),
- PLUGIN_DEPENDS(EAP_PEER, EAP_TNC),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
};
*features = f;
@@ -61,4 +59,3 @@ plugin_t *tnccs_20_plugin_create()
return &this->plugin;
}
-
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c
index 03795a947..d4fc6a6f7 100644
--- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,14 +27,35 @@ typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t;
struct private_tnccs_dynamic_t {
/**
- * Public tls_t interface.
+ * Public tnccs_t interface.
*/
- tls_t public;
+ 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;
+
};
/**
@@ -66,6 +87,7 @@ 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)
{
@@ -76,12 +98,15 @@ METHOD(tls_t, process, status_t,
type = determine_tnccs_protocol(*(char*)buf);
DBG1(DBG_TNC, "%N protocol detected dynamically",
tnccs_type_names, type);
- this->tls = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, type, TRUE);
- if (!this->tls)
+ tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE,
+ this->server, this->peer, this->transport);
+ 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);
}
@@ -98,6 +123,18 @@ METHOD(tls_t, is_server, bool,
return TRUE;
}
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_dynamic_t *this)
+{
+ return this->server;
+}
+
+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)
{
@@ -120,26 +157,66 @@ METHOD(tls_t, destroy, void,
private_tnccs_dynamic_t *this)
{
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;
+}
+
/**
* See header
*/
-tls_t *tnccs_dynamic_create(bool is_server)
+tnccs_t* tnccs_dynamic_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport)
{
private_tnccs_dynamic_t *this;
INIT(this,
.public = {
- .process = _process,
- .build = _build,
- .is_server = _is_server,
- .get_purpose = _get_purpose,
- .is_complete = _is_complete,
- .get_eap_msk = _get_eap_msk,
- .destroy = _destroy,
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_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,
},
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
);
return &this->public;
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h
index 42410b17f..e4cff74b8 100644
--- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,14 +23,20 @@
#include <library.h>
-#include <tls.h>
+#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of a dynamic TNC IF-TNCCS protocol handler.
*
- * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @return dynamic TNC IF-TNCCS protocol stack
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @return dynamic TNC IF-TNCCS protocol stack
*/
-tls_t *tnccs_dynamic_create(bool is_server);
+tnccs_t* tnccs_dynamic_create(bool is_server,
+ identification_t *server,
+ identification_t *peer,
+ tnc_ift_type_t transport);
#endif /** TNCCS_DYNAMIC_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
index 6f581c543..aac57813a 100644
--- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
@@ -32,8 +32,6 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CUSTOM, "tnccs-dynamic"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-1.1"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-2.0"),
- PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC),
- PLUGIN_DEPENDS(EAP_PEER, EAP_TNC),
};
*features = f;
return countof(f);
@@ -62,4 +60,3 @@ plugin_t *tnccs_dynamic_plugin_create()
return &this->plugin;
}
-
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index b7df65d1c..b58d120c1 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -156,7 +156,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
local_addr, FALSE,
charon->socket->get_port(charon->socket, FALSE),
remote_addr, FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO);
+ FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create(
name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
@@ -255,7 +255,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool,
local_addr, FALSE,
charon->socket->get_port(charon->socket, FALSE),
remote_addr, FALSE, IKEV2_UDP_PORT,
- FRAGMENTATION_NO);
+ FRAGMENTATION_NO, 0);
this->ike_cfg->add_proposal(this->ike_cfg,
create_proposal(ike_proposal, PROTO_IKE));