messages/ietf/pb_reason_string_msg.h messages/ietf/pb_reason_string_msg.c \
messages/ietf/pb_remediation_parameters_msg.h messages/ietf/pb_remediation_parameters_msg.c \
messages/ita/pb_mutual_capability_msg.h messages/ita/pb_mutual_capability_msg.c \
+ messages/ita/pb_noskip_test_msg.h messages/ita/pb_noskip_test_msg.c \
messages/tcg/pb_pdp_referral_msg.h messages/tcg/pb_pdp_referral_msg.c \
state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
METHOD(pb_tnc_batch_t, build, void,
private_pb_tnc_batch_t *this)
{
+ u_int8_t version;
u_int32_t msg_len;
chunk_t msg_value;
enumerator_t *enumerator;
pb_tnc_msg_info_t *msg_infos;
bio_writer_t *writer;
+ /* Set wrong PB-TNC version for testing purposes to force a PB-TNC error */
+ version = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_version",
+ PB_TNC_VERSION, lib->ns);
+
/* build PB-TNC batch header */
writer = bio_writer_create(this->batch_len);
- writer->write_uint8 (writer, PB_TNC_VERSION);
+ writer->write_uint8 (writer, version);
writer->write_uint8 (writer, this->is_server ?
PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
writer->write_uint16(writer, this->type);
fatal:
this->errors->insert_last(this->errors, msg);
- return VERIFY_ERROR;
+ return FAILED;
}
static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
msg_type_names = pb_tnc_msg_type_names;
msg_infos = pb_tnc_msg_infos;
}
- else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF)
+ else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF &&
+ msg_type > PB_TCG_MSG_RESERVED)
{
msg_type_names = pb_tnc_tcg_msg_type_names;
msg_infos = pb_tnc_tcg_msg_infos;
}
- else if (vendor_id == PEN_ITA && msg_type <= PB_ITA_MSG_ROOF)
+ else if (vendor_id == PEN_ITA && msg_type <= PB_ITA_MSG_ROOF &&
+ msg_type > PB_ITA_MSG_NOSKIP_TEST)
{
msg_type_names = pb_tnc_ita_msg_type_names;
msg_infos = pb_tnc_ita_msg_infos;
if (noskip_flag)
{
- DBG1(DBG_TNC, "reject PB-TNC message 0x%06x/0x%08x)",
+ DBG1(DBG_TNC, "reject PB-TNC message (0x%06x/0x%08x)",
vendor_id, msg_type);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
}
else
{
- DBG1(DBG_TNC, "ignore PB-TNC message 0x%06x/0x%08x)",
+ DBG1(DBG_TNC, "ignore PB-TNC message (0x%06x/0x%08x)",
vendor_id, msg_type);
this->offset += msg_len;
return SUCCESS;
--- /dev/null
+/*
+ * Copyright (C) 2015 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 "pb_noskip_test_msg.h"
+
+typedef struct private_pb_noskip_test_msg_t private_pb_noskip_test_msg_t;
+
+/**
+ * Private data of a pb_noskip_test_msg_t object.
+ *
+ */
+struct private_pb_noskip_test_msg_t {
+ /**
+ * Public pb_noskip_test_msg_t interface.
+ */
+ pb_noskip_test_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_noskip_test_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_noskip_test_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_noskip_test_msg_t *this)
+{
+ /* nothing to do since the message is empty */
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_noskip_test_msg_t *this, u_int32_t *offset)
+{
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_noskip_test_msg_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_noskip_test_msg_create(void)
+{
+ private_pb_noskip_test_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_ITA, PB_ITA_MSG_NOSKIP_TEST },
+ );
+
+ return &this->public.pb_interface;
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup pb_noskip_test_msg pb_noskip_test_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_NOSKIP_TEST_MSG_H_
+#define PB_NOSKIP_TEST_MSG_H_
+
+typedef struct pb_noskip_test_msg_t pb_noskip_test_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Noskip-Test message type.
+ */
+struct pb_noskip_test_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+};
+
+/**
+ * Create a PB-Noskip-Test message from parameters
+ */
+pb_tnc_msg_t* pb_noskip_test_msg_create(void);
+
+#endif /** PB_NOSKIP_TEST_MSG_H_ @}*/
"PB-PDP-Referral"
);
-ENUM(pb_tnc_ita_msg_type_names, PB_ITA_MSG_MUTUAL_CAPABILITY,
+ENUM(pb_tnc_ita_msg_type_names, PB_ITA_MSG_NOSKIP_TEST,
PB_ITA_MSG_MUTUAL_CAPABILITY,
+ "PB-Noskip-Test",
"PB-Mutual-Capability"
);
};
pb_tnc_msg_info_t pb_tnc_ita_msg_infos[] = {
- { 0 }, /* dummy entry because pb_tnc_ita_msg_type_t starts with 1 */
+ { 12, TRUE, FALSE, TRUE },
{ 16, FALSE, FALSE, FALSE },
};
* PB-TNC Message Type defined in the TCG namespace
*/
enum pb_tnc_tcg_msg_type_t {
+ PB_TCG_MSG_RESERVED = 0,
PB_TCG_MSG_PDP_REFERRAL = 1,
PB_TCG_MSG_ROOF = 1
};
* PB-TNC Message Type defined in the ITA namespace
*/
enum pb_tnc_ita_msg_type_t {
+ PB_ITA_MSG_NOSKIP_TEST = 0,
PB_ITA_MSG_MUTUAL_CAPABILITY = 1,
PB_ITA_MSG_ROOF = 1
};
#include "messages/ietf/pb_reason_string_msg.h"
#include "messages/ietf/pb_language_preference_msg.h"
#include "messages/ita/pb_mutual_capability_msg.h"
+#include "messages/ita/pb_noskip_test_msg.h"
#include "messages/tcg/pb_pdp_referral_msg.h"
#include "state_machine/pb_tnc_state_machine.h"
this->send_msg = TRUE;
tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
this->send_msg = FALSE;
+
+ /* Send a PB-Noskip-Test message for testing purposes */
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_noskip", FALSE, lib->ns))
+ {
+ msg = pb_noskip_test_msg_create();
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ }
}
METHOD(tnccs_20_handler_t, get_send_flag, bool,
#include "messages/ietf/pb_reason_string_msg.h"
#include "messages/ietf/pb_language_preference_msg.h"
#include "messages/ita/pb_mutual_capability_msg.h"
+#include "messages/ita/pb_noskip_test_msg.h"
#include "messages/tcg/pb_pdp_referral_msg.h"
#include "state_machine/pb_tnc_state_machine.h"
this->messages->insert_last(this->messages, msg);
this->mutex->unlock(this->mutex);
}
+
+ /* Send a PB-Noskip-Test message for testing purposes */
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_noskip", FALSE, lib->ns))
+ {
+ msg = pb_noskip_test_msg_create();
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ }
}
METHOD(tnccs_20_handler_t, get_send_flag, bool,
--- /dev/null
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
+using EAP-TTLS authentication only with the gateway presenting a server certificate and
+the clients doing EAP-MD5 password-based authentication.
+In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
+health of <b>carol</b> and <b>dave</b> via the <b>TNCCS 2.0 </b> client-server interface
+compliant with <b>RFC 5793 PB-TNC</b>.
+<p/>
+Unfortunately <b>carol</b> sends her first PB-TNC batch with a wrong version number and
+<b>dave</b> sends a PB-TNC message not supported by <b>moon</b> with the NOSKIP flag set.
+Therefore both connection setups fail due to fatal PB-TNC errors.
--- /dev/null
+moon:: cat /var/log/daemon.log::unsupported TNCCS batch version 0x03::YES
+carol::cat /var/log/daemon.log::received fatal PB-TNC error.*Version Not Supported.*caused by bad version 0x03::YES
+carol::cat /var/log/daemon.log::EAP_PT_EAP method failed::YES
+moon:: cat /var/log/daemon.log::EAP method EAP_TTLS failed for peer carol@strongswan.org::YES
+carol::cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
+moon:: cat /var/log/daemon.log::reject PB-TNC message (0x00902a/0x00000000)::YES
+dave:: cat /var/log/daemon.log::received fatal PB-TNC error.*Unsupported Mandatory Message::YES
+dave::cat /var/log/daemon.log::EAP_PT_EAP method failed::YES
+moon:: cat /var/log/daemon.log::EAP method EAP_TTLS failed for peer dave@strongswan.org::YES
+dave::cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
--- /dev/null
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ charondebug="tnc 3, imc 3"
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn home
+ left=PH_IP_CAROL
+ leftid=carol@strongswan.org
+ leftauth=eap
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightid=@moon.strongswan.org
+ rightauth=any
+ rightsendcert=never
+ rightsubnet=10.1.0.0/16
+ auto=add
--- /dev/null
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+carol@strongswan.org : EAP "Ar3etTnp"
--- /dev/null
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+
+ multiple_authentication = no
+
+ plugins {
+ tnccs-20 {
+ tests {
+ pb_tnc_version = 3
+ }
+ }
+ }
+}
+
+libimcv {
+ plugins {
+ imc-test {
+ command = allow
+ }
+ }
+}
--- /dev/null
+#IMC configuration file for strongSwan client
+
+IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
--- /dev/null
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ charondebug="tnc 3, imc 3"
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn home
+ left=PH_IP_DAVE
+ leftid=dave@strongswan.org
+ leftauth=eap
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightid=moon.strongswan.org
+ rightauth=any
+ rightsendcert=never
+ rightsubnet=10.1.0.0/16
+ auto=add
--- /dev/null
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+dave@strongswan.org : EAP "W7R0g3do"
--- /dev/null
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+
+ multiple_authentication = no
+
+ plugins {
+ tnc-imc {
+ preferred_language = ru, pl , de
+ }
+ tnccs-20 {
+ tests {
+ pb_tnc_noskip = yes
+ }
+ }
+ }
+}
+
+libimcv {
+ plugins {
+ imc-test {
+ command = isolate
+ }
+ }
+}
--- /dev/null
+#IMC configuration file for strongSwan client
+
+IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
--- /dev/null
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ charondebug="tnc 3, imv 3"
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn rw-allow
+ rightgroups=allow
+ leftsubnet=10.1.0.0/28
+ also=rw-eap
+ auto=add
+
+conn rw-isolate
+ rightgroups=isolate
+ leftsubnet=10.1.0.16/28
+ also=rw-eap
+ auto=add
+
+conn rw-eap
+ left=PH_IP_MOON
+ leftcert=moonCert.pem
+ leftid=@moon.strongswan.org
+ leftauth=eap-ttls
+ leftfirewall=yes
+ rightauth=eap-ttls
+ rightid=*@strongswan.org
+ rightsendcert=never
+ right=%any
--- /dev/null
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA moonKey.pem
+
+carol@strongswan.org : EAP "Ar3etTnp"
+dave@strongswan.org : EAP "W7R0g3do"
--- /dev/null
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+
+ multiple_authentication = no
+
+ plugins {
+ eap-ttls {
+ phase2_method = md5
+ phase2_piggyback = yes
+ phase2_tnc = yes
+ }
+ }
+}
+
+libimcv {
+ plugins {
+ imv-test {
+ rounds = 1
+ }
+ }
+}
--- /dev/null
+#IMV configuration file for strongSwan client
+
+IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so
--- /dev/null
+carol::ipsec stop
+dave::ipsec stop
+moon::ipsec stop
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
--- /dev/null
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cat /etc/tnc_config
+carol::cat /etc/tnc_config
+dave::cat /etc/tnc_config
+moon::ipsec start
+carol::ipsec start
+dave::ipsec start
+carol::sleep 1
+carol::ipsec up home
+dave::ipsec up home
--- /dev/null
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS=""
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# Guest instances on which FreeRadius is started
+#
+RADIUSHOSTS=
+
--- /dev/null
+The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>
+using EAP-TTLS authentication only with the gateway presenting a server certificate and
+the client doing EAP-MD5 password-based authentication.
+In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
+health of <b>carol</b> via the <b>TNCCS 2.0 </b> client-server interface
+compliant with <b>RFC 5793 PB-TNC</b>.
+<p/>
+Unfortunately <b>moon</b> sends his first PB-TNC batch with a wrong version number .
+Therefore the connection setup fails due to a fatal PB-TNC error.
--- /dev/null
+carol:: cat /var/log/daemon.log::unsupported TNCCS batch version 0x03::YES
+moon::cat /var/log/daemon.log::received fatal PB-TNC error.*Version Not Supported.*caused by bad version 0x03::YES
+moon::cat /var/log/daemon.log::EAP_PT_EAP method failed::YES
+moon:: cat /var/log/daemon.log::EAP method EAP_TTLS failed for peer carol@strongswan.org::YES
+carol::cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
--- /dev/null
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ charondebug="tnc 3, imc 3"
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn home
+ left=PH_IP_CAROL
+ leftid=carol@strongswan.org
+ leftauth=eap
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightid=@moon.strongswan.org
+ rightauth=any
+ rightsendcert=never
+ rightsubnet=10.1.0.0/16
+ auto=add
--- /dev/null
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+carol@strongswan.org : EAP "Ar3etTnp"
--- /dev/null
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+
+ multiple_authentication = no
+}
+
+libimcv {
+ plugins {
+ imc-test {
+ command = allow
+ }
+ }
+}
--- /dev/null
+#IMC configuration file for strongSwan client
+
+IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
--- /dev/null
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ charondebug="tnc 3, imv 3"
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn rw-allow
+ rightgroups=allow
+ leftsubnet=10.1.0.0/28
+ also=rw-eap
+ auto=add
+
+conn rw-isolate
+ rightgroups=isolate
+ leftsubnet=10.1.0.16/28
+ also=rw-eap
+ auto=add
+
+conn rw-eap
+ left=PH_IP_MOON
+ leftcert=moonCert.pem
+ leftid=@moon.strongswan.org
+ leftauth=eap-ttls
+ leftfirewall=yes
+ rightauth=eap-ttls
+ rightid=*@strongswan.org
+ rightsendcert=never
+ right=%any
--- /dev/null
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA moonKey.pem
+
+carol@strongswan.org : EAP "Ar3etTnp"
+dave@strongswan.org : EAP "W7R0g3do"
--- /dev/null
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+
+ multiple_authentication = no
+
+ plugins {
+ eap-ttls {
+ phase2_method = md5
+ phase2_piggyback = yes
+ phase2_tnc = yes
+ }
+ tnccs-20 {
+ tests {
+ pb_tnc_version = 3
+ }
+ }
+ }
+}
+
+libimcv {
+ plugins {
+ imv-test {
+ rounds = 1
+ }
+ }
+}
--- /dev/null
+#IMV configuration file for strongSwan client
+
+IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so
--- /dev/null
+carol::ipsec stop
+moon::ipsec stop
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
--- /dev/null
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+moon::cat /etc/tnc_config
+carol::cat /etc/tnc_config
+moon::ipsec start
+carol::ipsec start
+carol::sleep 1
+carol::ipsec up home
--- /dev/null
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="moon carol winnetou"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS=""
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol"
+
+# Guest instances on which FreeRadius is started
+#
+RADIUSHOSTS=
+