aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS20
-rwxr-xr-xconfigure.in4
-rw-r--r--man/ipsec.conf.5.in5
-rw-r--r--man/strongswan.conf.5.in23
-rw-r--r--src/charon/charon.c8
-rw-r--r--src/libcharon/config/proposal.c5
-rw-r--r--src/libcharon/daemon.c6
-rw-r--r--src/libcharon/encoding/generator.c2
-rw-r--r--src/libcharon/encoding/parser.c2
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c3
-rwxr-xr-xsrc/libcharon/encoding/payloads/notify_payload.c18
-rwxr-xr-xsrc/libcharon/encoding/payloads/notify_payload.h5
-rw-r--r--src/libcharon/encoding/payloads/payload.c19
-rw-r--r--src/libcharon/encoding/payloads/payload.h5
-rw-r--r--src/libcharon/network/receiver.c48
-rw-r--r--src/libcharon/network/sender.c10
-rw-r--r--src/libcharon/network/sender.h7
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_dae.c2
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c21
-rw-r--r--src/libcharon/plugins/nm/nm_service.h2
-rw-r--r--src/libcharon/plugins/radattr/radattr_listener.h2
-rw-r--r--src/libcharon/plugins/smp/smp.c14
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c185
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h10
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c82
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.h24
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c50
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c24
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c65
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.h2
-rw-r--r--src/libcharon/sa/authenticator.c7
-rw-r--r--src/libcharon/sa/authenticator.h5
-rw-r--r--src/libcharon/sa/ike_sa.c2
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c17
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c11
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c24
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c9
-rw-r--r--src/libcharon/sa/keymat.h7
-rw-r--r--src/libhydra/plugins/resolve/resolve_handler.c209
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner.c8
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation.c2
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c5
-rw-r--r--src/libradius/radius_message.c8
-rw-r--r--src/libradius/radius_message.h5
-rw-r--r--src/libstrongswan/Makefile.am7
-rw-r--r--src/libstrongswan/asn1/oid.txt1
-rw-r--r--src/libstrongswan/chunk.c3
-rw-r--r--src/libstrongswan/chunk.h14
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c330
-rw-r--r--src/libstrongswan/credentials/auth_cfg.h21
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.txt1
-rw-r--r--src/libstrongswan/crypto/signers/signer.h4
-rw-r--r--src/libstrongswan/plugins/cmac/Makefile.am16
-rw-r--r--src/libstrongswan/plugins/cmac/cmac.c321
-rw-r--r--src/libstrongswan/plugins/cmac/cmac.h78
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_plugin.c81
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_plugin.h42
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_prf.c121
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_prf.h50
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_signer.c159
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_signer.h47
-rw-r--r--src/libstrongswan/plugins/fips_prf/fips_prf.c6
-rw-r--r--src/libstrongswan/plugins/hmac/hmac.c4
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c33
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_cert.c49
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.am1
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors.h11
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors/aes_cmac.c141
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc.c4
-rw-r--r--src/libstrongswan/utils.c4
-rw-r--r--src/libstrongswan/utils.h2
-rw-r--r--src/libstrongswan/utils/identification.c2
-rw-r--r--src/libstrongswan/utils/identification.h4
-rw-r--r--src/pki/commands/print.c7
-rw-r--r--src/pki/commands/signcrl.c28
-rw-r--r--src/pluto/ac.c4
-rw-r--r--src/pluto/crl.c2
-rw-r--r--src/pluto/keys.c4
-rw-r--r--src/pluto/ocsp.c10
-rw-r--r--src/pluto/plugins/xauth/xauth_default_verifier.c7
-rw-r--r--src/pluto/timer.c13
-rw-r--r--src/pluto/x509.c2
-rw-r--r--src/starter/starterstroke.c1
-rw-r--r--src/stroke/stroke.c32
-rw-r--r--src/stroke/stroke_keywords.h1
-rw-r--r--src/stroke/stroke_keywords.txt1
-rw-r--r--src/stroke/stroke_msg.h10
-rwxr-xr-xtesting/scripts/build-umlrootfs5
-rwxr-xr-xtesting/testing.conf7
-rw-r--r--testing/tests/ikev2/net2net-pubkey/description.txt7
-rw-r--r--testing/tests/ikev2/net2net-pubkey/evaltest.dat7
-rwxr-xr-xtesting/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf25
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/moonPub.derbin0 -> 291 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/sunPub.derbin0 -> 292 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/private/moonKey.derbin0 -> 1187 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.secrets3
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/strongswan.conf5
-rwxr-xr-xtesting/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf23
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/moonPub.derbin0 -> 291 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/sunPub.derbin0 -> 292 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/private/sunKey.derbin0 -> 1189 bytes
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.secrets3
-rw-r--r--testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/strongswan.conf5
-rw-r--r--testing/tests/ikev2/net2net-pubkey/posttest.dat8
-rw-r--r--testing/tests/ikev2/net2net-pubkey/pretest.dat8
-rw-r--r--testing/tests/ikev2/net2net-pubkey/test.conf21
-rw-r--r--testing/tests/ikev2/net2net-rsa/description.txt7
-rw-r--r--testing/tests/ikev2/net2net-rsa/evaltest.dat7
-rwxr-xr-xtesting/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf25
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.d/private/moonKey.derbin0 -> 1187 bytes
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.secrets3
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/moon/etc/strongswan.conf5
-rwxr-xr-xtesting/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf23
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.d/private/sunKey.derbin0 -> 1189 bytes
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.secrets3
-rw-r--r--testing/tests/ikev2/net2net-rsa/hosts/sun/etc/strongswan.conf5
-rw-r--r--testing/tests/ikev2/net2net-rsa/posttest.dat6
-rw-r--r--testing/tests/ikev2/net2net-rsa/pretest.dat8
-rw-r--r--testing/tests/ikev2/net2net-rsa/test.conf21
-rw-r--r--testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf2
-rw-r--r--testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf2
-rw-r--r--testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf2
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/description.txt9
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/evaltest.dat13
-rwxr-xr-xtesting/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.conf21
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.secrets1
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/strongswan.conf5
-rwxr-xr-xtesting/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.conf25
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.secrets5
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/strongswan.conf5
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/posttest.dat4
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/pretest.dat8
-rw-r--r--testing/tests/ikev2/rw-eap-md5-id-prompt/test.conf21
-rw-r--r--testing/tests/openssl-ikev2/rw-cert/hosts/carol/etc/strongswan.conf2
-rw-r--r--testing/tests/openssl-ikev2/rw-cert/hosts/dave/etc/strongswan.conf2
-rw-r--r--testing/tests/openssl-ikev2/rw-cert/hosts/moon/etc/strongswan.conf2
137 files changed, 2658 insertions, 384 deletions
diff --git a/NEWS b/NEWS
index 960aa8036..79e6c896d 100644
--- a/NEWS
+++ b/NEWS
@@ -4,12 +4,28 @@ strongswan-4.6.3
- The tnc-pdp plugin implements a RADIUS server interface allowing
a strongSwan TNC server to act as a Policy Decision Point.
-- Added infrastructure to listen to RADIUS Dynamic Authorization
- Extension requests.
+- The eap-radius authentication backend enforces Session-Timeout attributes
+ using RFC4478 repeated authentication and acts upon RADIUS Dynamic
+ Authorization extensions, RFC 5176. Currently supported are disconnect
+ requests and CoA messages containing a Session-Timeout.
+
+- The eap-radius plugin can forward arbitrary RADIUS attributes from and to
+ clients using custom IKEv2 notify payloads. The new radattr plugin reads
+ attributes to include from files and prints received attributes to the
+ console.
- Added support for untruncated MD5 and SHA1 HMACs in ESP as used in
RFC 4595.
+- The cmac plugin implements the AES-CMAC-96 and AES-CMAC-PRF-128 algorithms
+ as defined in RFC 4494 and RFC 4615, respectively.
+
+- The resolve plugin automatically installs nameservers via resolvconf(8),
+ if it is installed, instead of modifying /etc/resolv.conf directly.
+
+- The IKEv2 charon daemon supports now raw RSA public keys in RFC 3110
+ DNSKEY and PKCS#1 file format.
+
strongswan-4.6.2
----------------
diff --git a/configure.in b/configure.in
index b99487aea..6c6a57f64 100755
--- a/configure.in
+++ b/configure.in
@@ -97,6 +97,7 @@ ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.])
ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.])
ARG_DISBL_SET([pem], [disable PEM decoding plugin.])
ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.])
+ARG_DISBL_SET([cmac], [disable CMAC crypto implementation plugin.])
ARG_DISBL_SET([xcbc], [disable xcbc crypto implementation plugin.])
ARG_ENABL_SET([af-alg], [enable AF_ALG crypto interface to Linux Crypto API.])
ARG_ENABL_SET([test-vectors], [enable plugin providing crypto test vectors.])
@@ -837,6 +838,7 @@ ADD_PLUGIN([fips-prf], [s libcharon])
ADD_PLUGIN([gmp], [s libcharon pluto openac scepclient pki scripts manager medsrv attest])
ADD_PLUGIN([agent], [s libcharon])
ADD_PLUGIN([xcbc], [s libcharon])
+ADD_PLUGIN([cmac], [s libcharon])
ADD_PLUGIN([hmac], [s libcharon pluto scripts])
ADD_PLUGIN([ctr], [s libcharon scripts])
ADD_PLUGIN([ccm], [s libcharon scripts])
@@ -949,6 +951,7 @@ AM_CONDITIONAL(USE_PGP, test x$pgp = xtrue)
AM_CONDITIONAL(USE_DNSKEY, test x$dnskey = xtrue)
AM_CONDITIONAL(USE_PEM, test x$pem = xtrue)
AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue)
+AM_CONDITIONAL(USE_CMAC, test x$cmac = xtrue)
AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue)
AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue)
AM_CONDITIONAL(USE_SQLITE, test x$sqlite = xtrue)
@@ -1110,6 +1113,7 @@ AC_OUTPUT(
src/include/Makefile
src/libstrongswan/Makefile
src/libstrongswan/plugins/aes/Makefile
+ src/libstrongswan/plugins/cmac/Makefile
src/libstrongswan/plugins/des/Makefile
src/libstrongswan/plugins/blowfish/Makefile
src/libstrongswan/plugins/md4/Makefile
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index 642499fc1..92cf0ca8b 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -512,8 +512,11 @@ an optional EAP method can be appended. Currently defined methods are
.BR eap-sim ,
.BR eap-gtc ,
.BR eap-md5 ,
+.BR eap-mschapv2 ,
+.BR eap-peap ,
+.BR eap-sim ,
.BR eap-tls ,
-.B eap-mschapv2
+.BR eap-ttls ,
and
.BR eap-radius .
Alternatively, IANA assigned EAP method numbers are accepted. Vendor specific
diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in
index 12528565c..b754e320c 100644
--- a/man/strongswan.conf.5.in
+++ b/man/strongswan.conf.5.in
@@ -1,4 +1,4 @@
-.TH STRONGSWAN.CONF 5 "2011-07-26" "@IPSEC_VERSION@" "strongSwan"
+.TH STRONGSWAN.CONF 5 "2012-05-01" "@IPSEC_VERSION@" "strongSwan"
.SH NAME
strongswan.conf \- strongSwan configuration file
.SH DESCRIPTION
@@ -467,9 +467,22 @@ Set MTU of ipsecN device
.BR charon.plugins.load-tester
Section to configure the load-tester plugin, see LOAD TESTS
.TP
+.BR charon.plugins.radattr.dir
+Directory where RADIUS attributes are stored in client-ID specific files.
+.TP
+.BR charon.plugins.radattr.message_id " [-1]"
+Attributes are added to all IKE_AUTH messages by default (-1), or only to the
+IKE_AUTH message with the given IKEv2 message ID.
+.TP
.BR charon.plugins.resolve.file " [/etc/resolv.conf]"
File where to add DNS server entries
.TP
+.BR charon.plugins.resolve.resolvconf.iface_prefix " [lo.inet.ipsec.]"
+Prefix used for interface names sent to resolvconf(8). The nameserver address
+is appended to this prefix to make it unique. The result has to be a valid
+interface name according to the rules defined by resolvconf. Also, it should
+have a high priority according to the order defined in interface-order(5).
+.TP
.BR charon.plugins.sql.database
Database URI for charons SQL plugin
.TP
@@ -847,6 +860,14 @@ identifier for each IKE_SA.
Prefix each log entry with a timestamp. The option accepts a format string as
passed to
.BR strftime (3).
+.TP
+.BR charon.syslog.identifier
+Global identifier used for an
+.BR openlog (3)
+call, prepended to each log message by syslog. If not configured,
+.BR openlog (3)
+is not called, so the value will depend on system defaults (often the program
+name).
.SS Subsystems
.TP
diff --git a/src/charon/charon.c b/src/charon/charon.c
index 7a269d7f0..6dbb0b592 100644
--- a/src/charon/charon.c
+++ b/src/charon/charon.c
@@ -291,7 +291,7 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
sys_logger_t *sys_logger;
file_logger_t *file_logger;
enumerator_t *enumerator;
- char *facility, *filename;
+ char *identifier, *facility, *filename;
int loggers_defined = 0;
debug_t group;
level_t def;
@@ -299,6 +299,12 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
FILE *file;
/* setup sysloggers */
+ identifier = lib->settings->get_str(lib->settings,
+ "charon.syslog.identifier", NULL);
+ if (identifier)
+ { /* set identifier, which is prepended to each log line */
+ openlog(identifier, 0, 0);
+ }
enumerator = lib->settings->create_section_enumerator(lib->settings,
"charon.syslog");
while (enumerator->enumerate(enumerator, &facility))
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 2251b82dd..d3c60a469 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -598,6 +598,9 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
case AUTH_CAMELLIA_XCBC_96:
prf = PRF_CAMELLIA128_XCBC;
break;
+ case AUTH_AES_CMAC_96:
+ prf = PRF_AES128_CMAC;
+ break;
default:
prf = PRF_UNDEFINED;
}
@@ -794,6 +797,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
case AUTH_HMAC_SHA2_512_256:
case AUTH_HMAC_MD5_96:
case AUTH_AES_XCBC_96:
+ case AUTH_AES_CMAC_96:
add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
break;
default:
@@ -813,6 +817,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
case PRF_HMAC_SHA2_512:
case PRF_HMAC_MD5:
case PRF_AES128_XCBC:
+ case PRF_AES128_CMAC:
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
break;
default:
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 575627206..ee2db3318 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -109,8 +109,11 @@ static void destroy(private_daemon_t *this)
{
this->public.traps->flush(this->public.traps);
}
+ if (this->public.sender)
+ {
+ this->public.sender->flush(this->public.sender);
+ }
DESTROY_IF(this->public.receiver);
- DESTROY_IF(this->public.sender);
#ifdef ME
DESTROY_IF(this->public.connect_manager);
DESTROY_IF(this->public.mediation_manager);
@@ -130,6 +133,7 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.eap);
DESTROY_IF(this->public.xauth);
DESTROY_IF(this->public.backends);
+ DESTROY_IF(this->public.sender);
DESTROY_IF(this->public.socket);
/* rehook library logging, shutdown logging */
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
index bf4480193..4d65bce84 100644
--- a/src/libcharon/encoding/generator.c
+++ b/src/libcharon/encoding/generator.c
@@ -566,7 +566,7 @@ METHOD(generator_t, generate_payload, void,
payload_type_names, payload_type);
DBG3(DBG_ENC, "generated data for this payload %b",
this->buffer + offset_start,
- this->out_position - this->buffer - offset_start);
+ (u_int)(this->out_position - this->buffer - offset_start));
}
}
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index a599de60f..e4b140c3e 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -376,7 +376,7 @@ METHOD(parser_t, parse_payload, status_t,
payload_type_names, payload_type, this->input_roof - this->byte_pos);
DBG3(DBG_ENC, "parsing payload from %b",
- this->byte_pos, this->input_roof - this->byte_pos);
+ this->byte_pos, (u_int)(this->input_roof - this->byte_pos));
/* base pointer for output, avoids casting in every rule */
output = pld;
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index 26d1f0a43..df5e73b5b 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -114,8 +114,7 @@ METHOD(payload_t, verify, status_t,
if (this->type == CERTIFICATE_REQUEST &&
this->encoding == ENC_X509_SIGNATURE)
{
- if (this->data.len < HASH_SIZE_SHA1 ||
- this->data.len % HASH_SIZE_SHA1)
+ if (this->data.len % HASH_SIZE_SHA1)
{
DBG1(DBG_ENC, "invalid X509 hash length (%d) in certreq",
this->data.len);
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index 411534491..d168e1c12 100755
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_
"ME_CONNECT_FAILED");
ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_NOTIFY_STATUS");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
"INITIAL_CONTACT",
"SET_WINDOW_SIZE",
"ADDITIONAL_TS_POSSIBLE",
@@ -105,8 +105,11 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTI
"IKEV2_MESSAGE_ID_SYNC_SUPPORTED",
"IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
"IKEV2_MESSAGE_ID_SYNC",
- "IPSEC_REPLAY_COUNTER_SYNC");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
+ "IPSEC_REPLAY_COUNTER_SYNC",
+ "SECURE PASSWORD_METHOD",
+ "PSK_PERSIST",
+ "PSK_CONFIRM");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
@@ -167,7 +170,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S
"ME_CONN_FAIL");
ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_STATUS");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
"INIT_CONTACT",
"SET_WINSIZE",
"ADD_TS_POSS",
@@ -207,8 +210,11 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, M
"MSG_ID_SYN_SUP",
"RPL_CTR_SYN_SUP",
"MSG_ID_SYN",
- "RPL_CTR_SYN");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
+ "RPL_CTR_SYN",
+ "SEC_PASSWD",
+ "PSK_PST",
+ "PSK_CFM");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index 07fbcb49b..beec1e233 100755
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -138,6 +138,11 @@ enum notify_type_t {
IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED = 16421,
IKEV2_MESSAGE_ID_SYNC = 16422,
IPSEC_REPLAY_COUNTER_SYNC = 16423,
+ /* Secure password methods, RFC 6467 */
+ SECURE_PASSWORD_METHOD = 16424,
+ /* PACE - draft-kuegler-ipsecme-pace-ikev2 */
+ PSK_PERSIST = 16425,
+ PSK_CONFIRM = 16426,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index 257d53858..dc158476b 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -58,7 +58,7 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYL
ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT_D_V1",
"NAT_OA_V1");
-ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
+ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SECURITY_ASSOCIATION",
"KEY_EXCHANGE",
"ID_INITIATOR",
@@ -74,9 +74,10 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
"TRAFFIC_SELECTOR_RESPONDER",
"ENCRYPTED",
"CONFIGURATION",
- "EXTENSIBLE_AUTHENTICATION");
+ "EXTENSIBLE_AUTHENTICATION",
+ "GENERIC_SECURE_PASSWORD_METHOD");
#ifdef ME
-ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
"ID_PEER");
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HEADER",
@@ -91,7 +92,7 @@ ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"CONFIGURATION_ATTRIBUTE_V1",
"ENCRYPTED_V1");
#else
-ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"PROPOSAL_SUBSTRUCTURE_V1",
@@ -127,7 +128,7 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, N
ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT-D",
"NAT-OA");
-ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SA",
"KE",
"IDi",
@@ -143,9 +144,11 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
"TSr",
"E",
"CP",
- "EAP");
+ "EAP",
+ "GSPM");
#ifdef ME
-ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER,
+ GENERIC_SECURE_PASSWORD_METHOD,
"IDp");
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HDR",
@@ -160,7 +163,7 @@ ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"CATTR",
"E");
#else
-ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HDR",
"PROP",
"PROP",
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index ed839fc07..d5e862601 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -207,6 +207,11 @@ enum payload_type_t {
*/
EXTENSIBLE_AUTHENTICATION = 48,
+ /**
+ * Generic Secure Password Method (GSPM).
+ */
+ GENERIC_SECURE_PASSWORD_METHOD = 49,
+
#ifdef ME
/**
* Identification payload for peers has a value from
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 599249fcb..fcc730439 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -30,6 +30,8 @@
/** lifetime of a cookie, in seconds */
#define COOKIE_LIFETIME 10
+/** time we wait before disabling cookies */
+#define COOKIE_CALMDOWN_DELAY 10
/** how many times to reuse the secret */
#define COOKIE_REUSE 10000
/** default value for private_receiver_t.cookie_threshold */
@@ -98,6 +100,11 @@ struct private_receiver_t {
u_int32_t cookie_threshold;
/**
+ * timestamp of last cookie requested
+ */
+ time_t last_cookie;
+
+ /**
* how many half open IKE_SAs per peer before blocking
*/
u_int32_t block_threshold;
@@ -262,24 +269,55 @@ static bool check_cookie(private_receiver_t *this, message_t *message)
}
/**
+ * Check if we currently require cookies
+ */
+static bool cookie_required(private_receiver_t *this,
+ u_int half_open, u_int32_t now)
+{
+ if (this->cookie_threshold && half_open >= this->cookie_threshold)
+ {
+ this->last_cookie = now;
+ return TRUE;
+ }
+ if (now < this->last_cookie + COOKIE_CALMDOWN_DELAY)
+ {
+ /* We don't disable cookies unless we haven't seen IKE_SA_INITs
+ * for COOKIE_CALMDOWN_DELAY seconds. This avoids jittering between
+ * cookie on / cookie off states, which is problematic. Consider the
+ * following: A legitimiate initiator sends a IKE_SA_INIT while we
+ * are under a DoS attack. If we toggle our cookie behavior,
+ * multiple retransmits of this IKE_SA_INIT might get answered with
+ * and without cookies. The initiator goes on and retries with
+ * a cookie, but it can't know if the completing IKE_SA_INIT response
+ * is to its IKE_SA_INIT request with or without cookies. This is
+ * problematic, as the cookie is part of AUTH payload data.
+ */
+ this->last_cookie = now;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Check if we should drop IKE_SA_INIT because of cookie/overload checking
*/
static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
{
u_int half_open;
+ u_int32_t now;
+ now = time_monotonic(NULL);
half_open = charon->ike_sa_manager->get_half_open_count(
charon->ike_sa_manager, NULL);
/* check for cookies in IKEv2 */
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
- this->cookie_threshold && half_open >= this->cookie_threshold &&
- !check_cookie(this, message))
+ cookie_required(this, half_open, now) && !check_cookie(this, message))
{
- u_int32_t now = time_monotonic(NULL);
- chunk_t cookie = cookie_build(this, message, now - this->secret_offset,
- chunk_from_thing(this->secret));
+ chunk_t cookie;
+ cookie = cookie_build(this, message, now - this->secret_offset,
+ chunk_from_thing(this->secret));
DBG2(DBG_NET, "received packet from: %#H to %#H",
message->get_source(message),
message->get_destination(message));
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index 4df930b15..6d5ad8f2a 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -149,7 +149,7 @@ static job_requeue_t send_packets(private_sender_t * this)
return JOB_REQUEUE_DIRECT;
}
-METHOD(sender_t, destroy, void,
+METHOD(sender_t, flush, void,
private_sender_t *this)
{
/* send all packets in the queue */
@@ -159,8 +159,13 @@ METHOD(sender_t, destroy, void,
this->sent->wait(this->sent, this->mutex);
}
this->mutex->unlock(this->mutex);
+}
+
+METHOD(sender_t, destroy, void,
+ private_sender_t *this)
+{
this->job->cancel(this->job);
- this->list->destroy(this->list);
+ this->list->destroy_offset(this->list, offsetof(packet_t, destroy));
this->got->destroy(this->got);
this->sent->destroy(this->sent);
this->mutex->destroy(this->mutex);
@@ -177,6 +182,7 @@ sender_t * sender_create()
INIT(this,
.public = {
.send = _send_,
+ .flush = _flush,
.destroy = _destroy,
},
.list = linked_list_create(),
diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h
index f77fadab2..6ee070435 100644
--- a/src/libcharon/network/sender.h
+++ b/src/libcharon/network/sender.h
@@ -44,6 +44,13 @@ struct sender_t {
void (*send) (sender_t *this, packet_t *packet);
/**
+ * Enforce a flush of the send queue.
+ *
+ * This function blocks until all queued packets have been sent.
+ */
+ void (*flush)(sender_t *this);
+
+ /**
* Destroys a sender object.
*/
void (*destroy) (sender_t *this);
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
index 5823142cc..e84fe5b9c 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_dae.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
@@ -435,7 +435,7 @@ static job_requeue_t receive(private_eap_radius_dae_t *this)
}
else
{
- DBG1(DBG_NET, "receving RADIUS DAE request failed: %s", strerror(errno));
+ DBG1(DBG_NET, "receiving RADIUS DAE request failed: %s", strerror(errno));
}
return JOB_REQUEUE_DIRECT;
}
diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
index 629792489..c3f0f24b3 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
+++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
@@ -207,7 +207,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -223,7 +224,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -239,7 +241,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -255,14 +258,15 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS)
{
- DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
if (!decode_imsi_ef(pbRecvBuffer, dwRecvLength-APDU_STATUS_LEN, imsi))
{
DBG1(DBG_IKE, "Couldn't decode IMSI EF: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
@@ -288,7 +292,7 @@ METHOD(simaka_card_t, get_triplet, bool,
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
DBG1(DBG_IKE, "Run GSM Algorithm failed: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
@@ -305,7 +309,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS)
{
- DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -320,7 +325,7 @@ METHOD(simaka_card_t, get_triplet, bool,
else
{
DBG1(DBG_IKE, "Get Response incorrect length: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h
index b00000b6f..828d1a452 100644
--- a/src/libcharon/plugins/nm/nm_service.h
+++ b/src/libcharon/plugins/nm/nm_service.h
@@ -21,7 +21,7 @@
#ifndef NM_SERVICE_H_
#define NM_SERVICE_H_
-#include <glib/gtypes.h>
+#include <glib.h>
#include <glib-object.h>
#include <nm-vpn-plugin.h>
diff --git a/src/libcharon/plugins/radattr/radattr_listener.h b/src/libcharon/plugins/radattr/radattr_listener.h
index 9a14827fc..e61c441bf 100644
--- a/src/libcharon/plugins/radattr/radattr_listener.h
+++ b/src/libcharon/plugins/radattr/radattr_listener.h
@@ -15,7 +15,7 @@
/**
* @defgroup radattr_listener radattr_listener
- * @{ @ingroup
+ * @{ @ingroup radattr
*/
#ifndef RADATTR_LISTENER_H_
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index c2fe11f74..1b2adc952 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -456,17 +456,21 @@ static void request_control_initiate(xmlTextReaderPtr reader,
/* <log> */
xmlTextWriterStartElement(writer, "log");
- peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
+ peer = charon->backends->get_peer_cfg_by_name(charon->backends,
+ (char*)str);
if (peer)
{
enumerator = peer->create_child_cfg_enumerator(peer);
if (ike)
{
- if (!enumerator->enumerate(enumerator, &child))
+ if (enumerator->enumerate(enumerator, &child))
+ {
+ child->get_ref(child);
+ }
+ else
{
child = NULL;
}
- child->get_ref(child);
}
else
{
@@ -622,7 +626,7 @@ static job_requeue_t process(int *fdp)
int fd = *fdp;
bool oldstate;
char buffer[4096];
- size_t len;
+ ssize_t len;
xmlTextReaderPtr reader;
char *id = NULL, *type = NULL;
@@ -637,7 +641,7 @@ static job_requeue_t process(int *fdp)
DBG2(DBG_CFG, "SMP XML connection closed");
return JOB_REQUEUE_NONE;
}
- DBG3(DBG_CFG, "got XML request: %b", buffer, len);
+ DBG3(DBG_CFG, "got XML request: %b", buffer, (u_int)len);
reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
if (reader == NULL)
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index 74dba82cc..eee3814a8 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -235,7 +235,7 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
DBG1(DBG_NET, "receive buffer too small, packet discarded");
return NULL;
}
- DBG3(DBG_NET, "received packet %b", buffer, len);
+ DBG3(DBG_NET, "received packet %b", buffer, (u_int)len);
if (len < MARKER_LEN)
{
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 8ca1464fb..89e1e0a91 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -263,7 +264,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
{
identification_t *identity;
certificate_t *certificate;
- char *auth, *id, *cert, *ca;
+ char *auth, *id, *pubkey, *cert, *ca;
stroke_end_t *end, *other_end;
auth_cfg_t *cfg;
@@ -358,6 +359,18 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+ /* add raw RSA public key */
+ pubkey = end->rsakey;
+ if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
+ {
+ certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey,
+ identity);
+ if (certificate)
+ {
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ }
+ }
+
/* CA constraint */
if (ca)
{
@@ -931,6 +944,175 @@ METHOD(stroke_config_t, del, void,
}
}
+METHOD(stroke_config_t, set_user_credentials, void,
+ private_stroke_config_t *this, stroke_msg_t *msg, FILE *prompt)
+{
+ enumerator_t *enumerator, *children, *remote_auth;
+ peer_cfg_t *peer, *found = NULL;
+ auth_cfg_t *auth_cfg, *remote_cfg;
+ auth_class_t auth_class;
+ child_cfg_t *child;
+ identification_t *id, *identity, *gw = NULL;
+ shared_key_type_t type = SHARED_ANY;
+ chunk_t password = chunk_empty;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
+ { /* find the peer (or child) config with the given name */
+ if (streq(peer->get_name(peer), msg->user_creds.name))
+ {
+ found = peer;
+ }
+ else
+ {
+ children = peer->create_child_cfg_enumerator(peer);
+ while (children->enumerate(children, &child))
+ {
+ if (streq(child->get_name(child), msg->user_creds.name))
+ {
+ found = peer;
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, " no config named '%s'", msg->user_creds.name);
+ fprintf(prompt, "no config named '%s'\n", msg->user_creds.name);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+
+ id = identification_create_from_string(msg->user_creds.username);
+ if (strlen(msg->user_creds.username) == 0 ||
+ !id || id->get_type(id) == ID_ANY)
+ {
+ DBG1(DBG_CFG, " invalid username '%s'", msg->user_creds.username);
+ fprintf(prompt, "invalid username '%s'\n", msg->user_creds.username);
+ this->mutex->unlock(this->mutex);
+ DESTROY_IF(id);
+ return;
+ }
+
+ /* replace/set the username in the first EAP auth_cfg, also look for a
+ * suitable remote ID.
+ * note that adding the identity here is not fully thread-safe as the
+ * peer_cfg and in turn the auth_cfg could be in use. for the default use
+ * case (setting user credentials before upping the connection) this will
+ * not be a problem, though. */
+ enumerator = found->create_auth_cfg_enumerator(found, TRUE);
+ remote_auth = found->create_auth_cfg_enumerator(found, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&auth_cfg))
+ {
+ if (remote_auth->enumerate(remote_auth, (void**)&remote_cfg))
+ { /* fall back on rightid, in case aaa_identity is not specified */
+ identity = remote_cfg->get(remote_cfg, AUTH_RULE_IDENTITY);
+ if (identity && identity->get_type(identity) != ID_ANY)
+ {
+ gw = identity;
+ }
+ }
+
+ auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS);
+ if (auth_class == AUTH_CLASS_EAP)
+ {
+ auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ /* if aaa_identity is specified use that as remote ID */
+ identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
+ if (identity && identity->get_type(identity) != ID_ANY)
+ {
+ gw = identity;
+ }
+ DBG1(DBG_CFG, " configured EAP-Identity %Y", id);
+ type = SHARED_EAP;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ remote_auth->destroy(remote_auth);
+ /* clone the gw ID before unlocking the mutex */
+ if (gw)
+ {
+ gw = gw->clone(gw);
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (type == SHARED_ANY)
+ {
+ DBG1(DBG_CFG, " config '%s' unsuitable for user credentials",
+ msg->user_creds.name);
+ fprintf(prompt, "config '%s' unsuitable for user credentials\n",
+ msg->user_creds.name);
+ id->destroy(id);
+ DESTROY_IF(gw);
+ return;
+ }
+
+ if (msg->user_creds.password)
+ {
+ char *pass;
+
+ pass = msg->user_creds.password;
+ password = chunk_clone(chunk_create(pass, strlen(pass)));
+ memwipe(pass, strlen(pass));
+ }
+ else
+ { /* prompt the user for the password */
+ char buf[256];
+
+ fprintf(prompt, "Password:\n");
+ if (fgets(buf, sizeof(buf), prompt))
+ {
+ password = chunk_clone(chunk_create(buf, strlen(buf)));
+ if (password.len > 0)
+ { /* trim trailing \n */
+ password.len--;
+ }
+ memwipe(buf, sizeof(buf));
+ }
+ }
+
+ if (password.len)
+ {
+ shared_key_t *shared;
+ linked_list_t *owners;
+
+ shared = shared_key_create(type, password);
+
+ owners = linked_list_create();
+ owners->insert_last(owners, id->clone(id));
+ if (gw && gw->get_type(gw) != ID_ANY)
+ {
+ owners->insert_last(owners, gw->clone(gw));
+ DBG1(DBG_CFG, " added %N secret for %Y %Y", shared_key_type_names,
+ type, id, gw);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " added %N secret for %Y", shared_key_type_names,
+ type, id);
+ }
+ this->cred->add_shared(this->cred, shared, owners);
+ DBG4(DBG_CFG, " secret: %#B", &password);
+ }
+ else
+ { /* in case a user answers the password prompt by just pressing enter */
+ chunk_clear(&password);
+ }
+ id->destroy(id);
+ DESTROY_IF(gw);
+}
+
METHOD(stroke_config_t, destroy, void,
private_stroke_config_t *this)
{
@@ -955,6 +1137,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
},
.add = _add,
.del = _del,
+ .set_user_credentials = _set_user_credentials,
.destroy = _destroy,
},
.list = linked_list_create(),
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
index 05e4665ca..450d517f3 100644
--- a/src/libcharon/plugins/stroke/stroke_config.h
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -53,6 +54,15 @@ struct stroke_config_t {
void (*del)(stroke_config_t *this, stroke_msg_t *msg);
/**
+ * Set the username and password for a connection in this backend.
+ *
+ * @param msg received stroke message
+ * @param prompt I/O channel to prompt for the password
+ */
+ void (*set_user_credentials)(stroke_config_t *this, stroke_msg_t *msg,
+ FILE *prompt);
+
+ /**
* Destroy a stroke_config instance.
*/
void (*destroy)(stroke_config_t *this);
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index cdf69135a..535ece233 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -158,6 +158,78 @@ METHOD(stroke_cred_t, load_peer, certificate_t*,
return NULL;
}
+METHOD(stroke_cred_t, load_pubkey, certificate_t*,
+ private_stroke_cred_t *this, key_type_t type, char *filename,
+ identification_t *identity)
+{
+ certificate_t *cert;
+ char path[PATH_MAX];
+
+ if (streq(filename, "%dns"))
+ {
+
+ }
+ else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2))
+ {
+ chunk_t printable_key, rfc3110_key;
+ public_key_t *key;
+
+ printable_key = chunk_create(filename + 2, strlen(filename) - 2);
+ rfc3110_key = strncaseeq(filename, "0x", 2) ?
+ chunk_from_hex(printable_key, NULL) :
+ chunk_from_base64(printable_key, NULL);
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_DNSKEY, rfc3110_key,
+ BUILD_END);
+ free(rfc3110_key.ptr);
+ if (key)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, key,
+ BUILD_SUBJECT, identity,
+ BUILD_END);
+ key->destroy(key);
+ if (cert)
+ {
+ cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+ DBG1(DBG_CFG, " loaded %N public key for \"%Y\"",
+ key_type_names, type, identity);
+ return cert;
+ }
+ }
+ DBG1(DBG_CFG, " loading %N public key for \"%Y\" failed",
+ key_type_names, type, identity);
+ }
+ else
+ {
+ if (*filename == '/')
+ {
+ snprintf(path, sizeof(path), "%s", filename);
+ }
+ else
+ {
+ snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
+ }
+
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+ BUILD_FROM_FILE, path,
+ BUILD_SUBJECT, identity,
+ BUILD_END);
+ if (cert)
+ {
+ cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+ DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'",
+ key_type_names, type, identity, filename);
+ return cert;
+ }
+ DBG1(DBG_CFG, " loading %N public key for \"%Y\" from '%s' failed",
+ key_type_names, type, identity, filename);
+ }
+ return NULL;
+}
+
/**
* load trusted certificates from a directory
*/
@@ -1065,6 +1137,12 @@ METHOD(stroke_cred_t, reread, void,
}
}
+METHOD(stroke_cred_t, add_shared, void,
+ private_stroke_cred_t *this, shared_key_t *shared, linked_list_t *owners)
+{
+ this->creds->add_shared_list(this->creds, shared, owners);
+}
+
METHOD(stroke_cred_t, destroy, void,
private_stroke_cred_t *this)
{
@@ -1092,6 +1170,8 @@ stroke_cred_t *stroke_cred_create()
.reread = _reread,
.load_ca = _load_ca,
.load_peer = _load_peer,
+ .load_pubkey = _load_pubkey,
+ .add_shared = _add_shared,
.cachecrl = _cachecrl,
.destroy = _destroy,
},
diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h
index ccee7d87c..83e648819 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.h
+++ b/src/libcharon/plugins/stroke/stroke_cred.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -26,6 +27,7 @@
#include <stroke_msg.h>
#include <credentials/credential_set.h>
#include <credentials/certificates/certificate.h>
+#include <utils/linked_list.h>
typedef struct stroke_cred_t stroke_cred_t;
@@ -56,7 +58,7 @@ struct stroke_cred_t {
certificate_t* (*load_ca)(stroke_cred_t *this, char *filename);
/**
- * Load a peer certificate and serve it rhrough the credential_set.
+ * Load a peer certificate and serve it through the credential_set.
*
* @param filename file to load peer cert from
* @return reference to loaded certificate, or NULL
@@ -64,6 +66,26 @@ struct stroke_cred_t {
certificate_t* (*load_peer)(stroke_cred_t *this, char *filename);
/**
+ * Load a raw public key and serve it through the credential_set.
+ *
+ * @param type type of the raw public key (RSA or ECDSA)
+ * @param filename file to load raw public key from
+ * @param identity identity of the raw public key owner
+ * @return reference to loaded raw public key, or NULL
+ */
+ certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type,
+ char *filename, identification_t *identity);
+
+ /**
+ * Add a shared secret to serve through the credential_set.
+ *
+ * @param shared shared key to add, gets owned
+ * @param owners list of owners (identification_t*), gets owned
+ */
+ void (*add_shared)(stroke_cred_t *this, shared_key_t *shared,
+ linked_list_t *owners);
+
+ /**
* Enable/Disable CRL caching to disk.
*
* @param enabled TRUE to enable, FALSE to disable
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 6b256f29b..c3dea8419 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -708,12 +708,14 @@ static void list_public_key(public_key_t *public, FILE *out)
static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
{
bool first = TRUE;
-
- enumerator_t *enumerator = list->create_enumerator(list);
+ time_t now = time(NULL), notBefore, notAfter;
+ enumerator_t *enumerator;
certificate_t *cert;
+ enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, (void**)&cert))
{
+ identification_t *subject = cert->get_subject(cert);
public_key_t *public = cert->get_public_key(cert);
if (public)
@@ -726,6 +728,41 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
}
fprintf(out, "\n");
+ /* list subject if available */
+ if (subject->get_type(subject) != ID_KEY_ID)
+ {
+ fprintf(out, " subject: %#Y\n", subject);
+ }
+
+ /* list validity if available*/
+ cert->get_validity(cert, &now, &notBefore, &notAfter);
+ if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
+ {
+ fprintf(out, " validity: not before %T, ", &notBefore, utc);
+ if (now < notBefore)
+ {
+ fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
+ }
+ else
+ {
+ fprintf(out, "ok\n");
+ }
+ fprintf(out, " not after %T, ", &notAfter, utc);
+ if (now > notAfter)
+ {
+ fprintf(out, "expired (%V ago)\n", &now, &notAfter);
+ }
+ else
+ {
+ fprintf(out, "ok");
+ if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
+ {
+ fprintf(out, " (expires in %V)", &now, &notAfter);
+ }
+ fprintf(out, " \n");
+ }
+ }
+
list_public_key(public, out);
public->destroy(public);
}
@@ -842,7 +879,7 @@ static void stroke_list_certs(linked_list_t *list, char *label,
fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert));
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
- serial = x509->get_serial(x509);
+ serial = chunk_skip_zero(x509->get_serial(x509));
fprintf(out, " serial: %#B\n", &serial);
/* list validity */
@@ -955,7 +992,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
{
fprintf(out, " hissuer: \"%Y\"\n", id);
}
- chunk = ac->get_holderSerial(ac);
+ chunk = chunk_skip_zero(ac->get_holderSerial(ac));
if (chunk.ptr)
{
fprintf(out, " hserial: %#B\n", &chunk);
@@ -967,7 +1004,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
groups->destroy(groups);
}
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
- chunk = ac->get_serial(ac);
+ chunk = chunk_skip_zero(ac->get_serial(ac));
fprintf(out, " serial: %#B\n", &chunk);
/* list validity */
@@ -1024,13 +1061,14 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
/* list optional crlNumber */
- chunk = crl->get_serial(crl);
+ chunk = chunk_skip_zero(crl->get_serial(crl));
if (chunk.ptr)
{
fprintf(out, " serial: %#B\n", &chunk);
}
if (crl->is_delta_crl(crl, &chunk))
{
+ chunk = chunk_skip_zero(chunk);
fprintf(out, " delta for: %#B\n", &chunk);
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 4956b011f..7ef15db3c 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Tobias Brunner
+ * Copyright (C) 2011-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -185,6 +185,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
pop_string(msg, &end->id2);
+ pop_string(msg, &end->rsakey);
pop_string(msg, &end->cert);
pop_string(msg, &end->cert2);
pop_string(msg, &end->ca);
@@ -200,6 +201,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
+ DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey);
DBG2(DBG_CFG, " %scert=%s", label, end->cert);
DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
@@ -427,7 +429,7 @@ static void stroke_export(private_stroke_socket_t *this,
{
pop_string(msg, &msg->export.selector);
- if (msg->purge.flags & EXPORT_X509)
+ if (msg->export.flags & EXPORT_X509)
{
enumerator_t *enumerator;
identification_t *id;
@@ -475,6 +477,21 @@ static void stroke_memusage(private_stroke_socket_t *this,
}
/**
+ * Set username and password for a connection
+ */
+static void stroke_user_creds(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->user_creds.name);
+ pop_string(msg, &msg->user_creds.username);
+ pop_string(msg, &msg->user_creds.password);
+
+ DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
+
+ this->config->set_user_credentials(this->config, msg, out);
+}
+
+/**
* set the verbosity debug output
*/
static void stroke_loglevel(private_stroke_socket_t *this,
@@ -647,6 +664,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_MEMUSAGE:
stroke_memusage(this, msg, out);
break;
+ case STR_USER_CREDS:
+ stroke_user_creds(this, msg, out);
+ break;
default:
DBG1(DBG_CFG, "received unknown stroke");
break;
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
index 8607e5d9b..913cdab12 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
@@ -70,15 +70,14 @@ struct private_tnc_ifmap_soap_t {
/**
* Send request and receive result via SOAP
*/
-static bool send_receive(private_tnc_ifmap_soap_t *this,
- char *request_qname, axiom_node_t *request,
- char *receipt_qname, axiom_node_t **result)
+static axiom_element_t* send_receive(private_tnc_ifmap_soap_t *this,
+ char *request_qname, axiom_node_t *request,
+ char *receipt_qname, axiom_node_t **result)
{
axiom_node_t *parent, *node;
- axiom_element_t *el;
+ axiom_element_t *parent_el, *el;
axutil_qname_t *qname;
- bool success = FALSE;
/* send request and receive result */
DBG2(DBG_TNC, "sending ifmap %s", request_qname);
@@ -87,45 +86,44 @@ static bool send_receive(private_tnc_ifmap_soap_t *this,
if (!parent)
{
DBG1(DBG_TNC, "no ifmap %s received from MAP server", receipt_qname);
- return FALSE;
+ return NULL;
}
+ DBG2(DBG_TNC, "received ifmap %s", receipt_qname);
+
+ /* extract the parent element */
+ parent_el = (axiom_element_t*)axiom_node_get_data_element(parent, this->env);
- /* pre-process result */
- node = axiom_node_get_first_child(parent, this->env);
- if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
+ /* look for a child node with the given receipt qname */
+ qname = axutil_qname_create_from_string(this->env, strdup(receipt_qname));
+ el = axiom_element_get_first_child_with_qname(parent_el, this->env, qname,
+ parent, &node);
+ axutil_qname_free(qname, this->env);
+
+ if (el)
{
- el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-
- qname = axiom_element_get_qname(el, this->env, node);
- success = streq(receipt_qname, axutil_qname_to_string(qname, this->env));
- if (success)
- {
- DBG2(DBG_TNC, "received ifmap %s", receipt_qname);
- if (result)
- {
- *result = parent;
- }
- else
- {
- /* no further processing requested */
- axiom_node_free_tree(parent, this->env);
- }
- return TRUE;
+ if (result)
+ {
+ *result = parent;
}
- /* TODO proper error handling */
- DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
+ else
+ {
+ /* no further processing requested */
+ axiom_node_free_tree(parent, this->env);
+ }
+ return el;
}
+ DBG1(DBG_TNC, "child node with qname '%s' not found", receipt_qname);
/* free parent in the error case */
axiom_node_free_tree(parent, this->env);
- return FALSE;
+ return NULL;
}
METHOD(tnc_ifmap_soap_t, newSession, bool,
private_tnc_ifmap_soap_t *this)
{
- axiom_node_t *request, *result, *node;
+ axiom_node_t *request, *result;
axiom_element_t *el;
axiom_namespace_t *ns;
axis2_char_t *value;
@@ -136,15 +134,12 @@ METHOD(tnc_ifmap_soap_t, newSession, bool,
el = axiom_element_create(this->env, NULL, "newSession", ns, &request);
/* send newSession request and receive newSessionResult */
- if (!send_receive(this, "newSession", request, "newSessionResult", &result))
+ el = send_receive(this, "newSession", request, "newSessionResult", &result);
+ if (!el)
{
return FALSE;
}
- /* process newSessionResult */
- node = axiom_node_get_first_child(result, this->env);
- el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-
/* get session-id */
value = axiom_element_get_attribute_value_by_name(el, this->env,
"session-id");
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
index e769353b7..06291220f 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
@@ -14,7 +14,7 @@
*/
/**
- * @defgroup tnc_pdp tnc_pdp
+ * @defgroup tnc_pdp_t tnc_pdp
* @{ @ingroup tnc_pdp
*/
diff --git a/src/libcharon/sa/authenticator.c b/src/libcharon/sa/authenticator.c
index 91bb7715f..a32b6ab12 100644
--- a/src/libcharon/sa/authenticator.c
+++ b/src/libcharon/sa/authenticator.c
@@ -31,11 +31,12 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS,
"RSA signature",
"pre-shared key",
"DSS signature");
-ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
+ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS,
"ECDSA-256 signature",
"ECDSA-384 signature",
- "ECDSA-521 signature");
-ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_ECDSA_521,
+ "ECDSA-521 signature",
+ "secure password method");
+ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_GSPM,
"XAuthInitPSK",
"XAuthRespPSK",
"XAuthInitRSA",
diff --git a/src/libcharon/sa/authenticator.h b/src/libcharon/sa/authenticator.h
index 3af939160..86b42da7a 100644
--- a/src/libcharon/sa/authenticator.h
+++ b/src/libcharon/sa/authenticator.h
@@ -75,6 +75,11 @@ enum auth_method_t {
AUTH_ECDSA_521 = 11,
/**
+ * Generic Secure Password Authentication Method as specified in RFC 6467
+ */
+ AUTH_GSPM = 12,
+
+ /**
* IKEv1 initiator XAUTH with PSK, outside of IANA range
*/
AUTH_XAUTH_INIT_PSK = 256,
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 5d0a5aea8..e94ebb15e 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1679,7 +1679,7 @@ static bool is_any_path_valid(private_ike_sa_t *this)
{
bool valid = FALSE;
enumerator_t *enumerator;
- host_t *src, *addr;
+ host_t *src = NULL, *addr;
DBG1(DBG_IKE, "old path is not available anymore, try to find another");
enumerator = this->peer_addresses->create_enumerator(this->peer_addresses);
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index b81c5c853..2e661dc66 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -219,23 +219,12 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
*/
static void replace_eap_identity(private_eap_authenticator_t *this)
{
- enumerator_t *enumerator;
- auth_rule_t rule;
+ identification_t *eap_identity;
auth_cfg_t *cfg;
- void *ptr;
+ eap_identity = this->eap_identity->clone(this->eap_identity);
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- enumerator = cfg->create_enumerator(cfg);
- while (enumerator->enumerate(enumerator, &rule, &ptr))
- {
- if (rule == AUTH_RULE_EAP_IDENTITY)
- {
- cfg->replace(cfg, enumerator, AUTH_RULE_EAP_IDENTITY,
- this->eap_identity->clone(this->eap_identity));
- break;
- }
- }
- enumerator->destroy(enumerator);
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity);
}
/**
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index ba7fdd2da..cc6d37849 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -610,7 +610,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
task_t *task;
message_t *message;
host_t *me, *other;
- bool delete = FALSE;
+ bool delete = FALSE, hook = FALSE;
status_t status;
me = request->get_destination(request);
@@ -645,9 +645,11 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
enumerator);
}
break;
- case DESTROY_ME:
case FAILED:
default:
+ hook = TRUE;
+ /* FALL */
+ case DESTROY_ME:
/* destroy IKE_SA, but SEND response first */
delete = TRUE;
break;
@@ -682,7 +684,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
this->responding.packet->clone(this->responding.packet));
if (delete)
{
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ if (hook)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
return DESTROY_ME;
}
return SUCCESS;
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 183ca3440..6af0b3778 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -419,10 +420,14 @@ METHOD(task_t, build_i, status_t,
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!idi)
- {
- DBG1(DBG_CFG, "configuration misses IDi");
- return FAILED;
+ if (!idi || idi->get_type(idi) == ID_ANY)
+ { /* ID_ANY is invalid as IDi, use local IP address instead */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDi configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ idi = identification_create_from_sockaddr(me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, idi);
}
this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
@@ -689,9 +694,14 @@ METHOD(task_t, build_r, status_t,
if (id->get_type(id) == ID_ANY)
{ /* no IDr received, apply configured ID */
if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
- {
- DBG1(DBG_CFG, "IDr not configured and negotiation failed");
- goto peer_auth_failed;
+ { /* no ID configured, use local IP address */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDr configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ id_cfg = identification_create_from_sockaddr(
+ me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id_cfg);
}
this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
id = id_cfg;
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index de68e8662..3fbbcfd2a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -519,9 +519,12 @@ METHOD(task_t, migrate, void,
this->ike_sa = ike_sa;
this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
- DESTROY_IF(this->dh);
- this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
- this->dh_group);
+ if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group)
+ { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */
+ this->dh->destroy(this->dh);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ this->dh_group);
+ }
}
METHOD(task_t, destroy, void,
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
index 9de2574e1..8bfe79660 100644
--- a/src/libcharon/sa/keymat.h
+++ b/src/libcharon/sa/keymat.h
@@ -48,7 +48,12 @@ struct keymat_t {
*
* The diffie hellman is either for IKE negotiation/rekeying or
* CHILD_SA rekeying (using PFS). The resulting DH object must be passed
- * to derive_keys or to derive_child_keys and destroyed after use
+ * to derive_keys or to derive_child_keys and destroyed after use.
+ *
+ * Only DH objects allocated through this method are passed to other
+ * keymat_t methods, allowing private DH implementations. In some cases
+ * (such as retrying with a COOKIE), a DH object allocated from a different
+ * keymat_t instance may be passed to other methods.
*
* @param group diffie hellman group
* @return DH object, NULL if group not supported
diff --git a/src/libhydra/plugins/resolve/resolve_handler.c b/src/libhydra/plugins/resolve/resolve_handler.c
index 62376dcc6..011ebbaaf 100644
--- a/src/libhydra/plugins/resolve/resolve_handler.c
+++ b/src/libhydra/plugins/resolve/resolve_handler.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -15,12 +16,20 @@
#include "resolve_handler.h"
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <hydra.h>
#include <debug.h>
#include <threading/mutex.h>
+/* path to resolvconf executable */
+#define RESOLVCONF_EXEC "/sbin/resolvconf"
+
+/* default prefix used for resolvconf interfaces (should have high prio) */
+#define RESOLVCONF_PREFIX "lo.inet.ipsec."
+
typedef struct private_resolve_handler_t private_resolve_handler_t;
/**
@@ -39,47 +48,40 @@ struct private_resolve_handler_t {
char *file;
/**
+ * use resolvconf instead of writing directly to resolv.conf
+ */
+ bool use_resolvconf;
+
+ /**
+ * prefix to be used for interface names sent to resolvconf
+ */
+ char *iface_prefix;
+
+ /**
* Mutex to access file exclusively
*/
mutex_t *mutex;
};
-METHOD(attribute_handler_t, handle, bool,
- private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
+/**
+ * Writes the given nameserver to resolv.conf
+ */
+static bool write_nameserver(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr)
{
FILE *in, *out;
char buf[1024];
- host_t *addr;
size_t len;
bool handled = FALSE;
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- addr = host_create_from_chunk(AF_INET, data, 0);
- break;
- case INTERNAL_IP6_DNS:
- addr = host_create_from_chunk(AF_INET6, data, 0);
- break;
- default:
- return FALSE;
- }
-
- if (!addr || addr->is_anyaddr(addr))
- {
- DESTROY_IF(addr);
- return FALSE;
- }
- this->mutex->lock(this->mutex);
-
in = fopen(this->file, "r");
/* allows us to stream from in to out */
unlink(this->file);
out = fopen(this->file, "w");
if (out)
{
- fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server);
+ fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr,
+ server);
DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
handled = TRUE;
@@ -97,38 +99,17 @@ METHOD(attribute_handler_t, handle, bool,
{
fclose(in);
}
- this->mutex->unlock(this->mutex);
- addr->destroy(addr);
-
- if (!handled)
- {
- DBG1(DBG_IKE, "adding DNS server failed", this->file);
- }
return handled;
}
-METHOD(attribute_handler_t, release,void,
- private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
+/**
+ * Removes the given nameserver from resolv.conf
+ */
+static void remove_nameserver(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr)
{
FILE *in, *out;
char line[1024], matcher[512];
- host_t *addr;
- int family;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- family = AF_INET;
- break;
- case INTERNAL_IP6_DNS:
- family = AF_INET6;
- break;
- default:
- return;
- }
-
- this->mutex->lock(this->mutex);
in = fopen(this->file, "r");
if (in)
@@ -138,7 +119,6 @@ METHOD(attribute_handler_t, release,void,
out = fopen(this->file, "w");
if (out)
{
- addr = host_create_from_chunk(family, data, 0);
snprintf(matcher, sizeof(matcher),
"nameserver %H # by strongSwan, from %Y\n",
addr, server);
@@ -156,13 +136,129 @@ METHOD(attribute_handler_t, release,void,
fputs(line, out);
}
}
- addr->destroy(addr);
fclose(out);
}
fclose(in);
}
+}
+
+/**
+ * Add or remove the given nameserver by invoking resolvconf.
+ */
+static bool invoke_resolvconf(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr,
+ bool install)
+{
+ char cmd[128];
+
+ /* we use the nameserver's IP address as part of the interface name to
+ * make them unique */
+ if (snprintf(cmd, sizeof(cmd), "%s %s %s%H", RESOLVCONF_EXEC,
+ install ? "-a" : "-d", this->iface_prefix, addr) >= sizeof(cmd))
+ {
+ return FALSE;
+ }
+
+ if (install)
+ {
+ FILE *out;
+
+ out = popen(cmd, "w");
+ if (!out)
+ {
+ return FALSE;
+ }
+ DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
+ fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr,
+ server);
+ if (ferror(out) || pclose(out))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ ignore_result(system(cmd));
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ host_t *addr;
+ bool handled;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ addr = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ addr = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!addr || addr->is_anyaddr(addr))
+ {
+ DESTROY_IF(addr);
+ return FALSE;
+ }
+
+ this->mutex->lock(this->mutex);
+ if (this->use_resolvconf)
+ {
+ handled = invoke_resolvconf(this, server, addr, TRUE);
+ }
+ else
+ {
+ handled = write_nameserver(this, server, addr);
+ }
+ this->mutex->unlock(this->mutex);
+ addr->destroy(addr);
+
+ if (!handled)
+ {
+ DBG1(DBG_IKE, "adding DNS server failed");
+ }
+ return handled;
+}
+METHOD(attribute_handler_t, release, void,
+ private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ host_t *addr;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+ addr = host_create_from_chunk(family, data, 0);
+
+ this->mutex->lock(this->mutex);
+ if (this->use_resolvconf)
+ {
+ invoke_resolvconf(this, server, addr, FALSE);
+ }
+ else
+ {
+ remove_nameserver(this, server, addr);
+ }
this->mutex->unlock(this->mutex);
+
+ addr->destroy(addr);
}
/**
@@ -226,6 +322,7 @@ METHOD(resolve_handler_t, destroy, void,
resolve_handler_t *resolve_handler_create()
{
private_resolve_handler_t *this;
+ struct stat st;
INIT(this,
.public = {
@@ -241,6 +338,14 @@ resolve_handler_t *resolve_handler_create()
RESOLV_CONF, hydra->daemon),
);
+ if (stat(RESOLVCONF_EXEC, &st) == 0)
+ {
+ this->use_resolvconf = TRUE;
+ this->iface_prefix = lib->settings->get_str(lib->settings,
+ "%s.plugins.resolve.resolvconf.iface_prefix",
+ RESOLVCONF_PREFIX, hydra->daemon);
+ }
+
return &this->public;
}
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner.c b/src/libimcv/plugins/imv_scanner/imv_scanner.c
index 845511555..dba3fd632 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner.c
@@ -67,7 +67,7 @@ static linked_list_t* get_port_list(char *label)
{
char key[40], *value;
linked_list_t *list;
- chunk_t port_list, port_item, port_stop;
+ chunk_t port_list, port_item, port_start;
port_range_t *port_range;
list = linked_list_create();
@@ -92,11 +92,11 @@ static linked_list_t* get_port_list(char *label)
port_list = chunk_empty;
}
port_range = malloc_thing(port_range_t);
- port_range->start = atoi(port_item.ptr);;
+ port_range->start = atoi(port_item.ptr);
- if (extract_token(&port_stop, '-', &port_item))
+ if (extract_token(&port_start, '-', &port_item) && port_item.len)
{
- port_range->stop = atoi(port_stop.ptr);
+ port_range->stop = atoi(port_item.ptr);
}
else
{
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation.c b/src/libpts/plugins/imv_attestation/imv_attestation.c
index 6bd5984e0..51069b02d 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation.c
@@ -322,7 +322,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
{
attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
state->set_recommendation(state,
- TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
TNC_IMV_EVALUATION_RESULT_ERROR);
return imv_attestation->provide_recommendation(imv_attestation,
connection_id);
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index 287aae727..a85de8cd8 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -144,6 +144,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
+ if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
+ {
+ return FAILED;
+ }
+
hash_algo = pts->get_meas_algorithm(pts);
hash_size = pts_meas_algo_hash_size(hash_algo);
pcr_len = pts->get_pcr_len(pts);
diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
index ce8903cdb..17fa7357b 100644
--- a/src/libradius/radius_message.c
+++ b/src/libradius/radius_message.c
@@ -66,6 +66,14 @@ struct private_radius_message_t {
rmsg_t *msg;
};
+/**
+ * Described in header.
+ */
+void libradius_init(void)
+{
+ /* empty */
+}
+
ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONSE,
"Access-Request",
"Access-Accept",
diff --git a/src/libradius/radius_message.h b/src/libradius/radius_message.h
index 90698ae7b..6d0df53c3 100644
--- a/src/libradius/radius_message.h
+++ b/src/libradius/radius_message.h
@@ -279,6 +279,11 @@ struct radius_message_t {
};
/**
+ * Dummy libradius initialization function needed for integrity test
+ */
+void libradius_init(void);
+
+/**
* Create an empty RADIUS message.
*
* @param code request type
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index d3c360b47..7bb0812bd 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -215,6 +215,13 @@ if MONOLITHIC
endif
endif
+if USE_CMAC
+ SUBDIRS += plugins/cmac
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/cmac/libstrongswan-cmac.la
+endif
+endif
+
if USE_XCBC
SUBDIRS += plugins/xcbc
if MONOLITHIC
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index 5daa6dad6..51a29eb33 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -33,6 +33,7 @@
0x2A "G" OID_GIVEN_NAME
0x2B "I" OID_INITIALS
0x2D "ID" OID_UNIQUE_IDENTIFIER
+ 0x2E "dnQualifier" OID_DN_QUALIFIER
0x48 "role" OID_ROLE
0x1D "id-ce"
0x09 "subjectDirectoryAttrs"
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index bb879002e..9397c4e44 100644
--- a/src/libstrongswan/chunk.c
+++ b/src/libstrongswan/chunk.c
@@ -668,7 +668,8 @@ int chunk_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (!spec->hash)
{
- const void *new_args[] = {&chunk->ptr, &chunk->len};
+ u_int chunk_len = chunk->len;
+ const void *new_args[] = {&chunk->ptr, &chunk_len};
return mem_printf_hook(dst, len, spec, new_args);
}
diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h
index ff569ac13..c7bc7a5e8 100644
--- a/src/libstrongswan/chunk.h
+++ b/src/libstrongswan/chunk.h
@@ -235,6 +235,20 @@ static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
}
/**
+ * Skip a leading zero-valued byte
+ */
+static inline chunk_t chunk_skip_zero(chunk_t chunk)
+{
+ if (chunk.len > 1 && *chunk.ptr == 0x00)
+ {
+ chunk.ptr++;
+ chunk.len--;
+ }
+ return chunk;
+}
+
+
+/**
* Compare two chunks, returns zero if a equals b
* or negative/positive if a is small/greater than b
*/
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index 0646b0e2c..fd2cee607 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2007-2009 Martin Willi
- * Copyright (C) 2008 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -56,6 +56,42 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT,
"HELPER_REVOCATION_CERT",
);
+/**
+ * Check if the given rule is a rule for which there may be multiple values.
+ */
+static inline bool is_multi_value_rule(auth_rule_t type)
+{
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_RSA_STRENGTH:
+ case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ case AUTH_RULE_MAX:
+ return FALSE;
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_CERT_POLICY:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_REVOCATION_CERT:
+ return TRUE;
+ }
+ return FALSE;
+}
+
typedef struct private_auth_cfg_t private_auth_cfg_t;
/**
@@ -93,6 +129,8 @@ typedef struct {
enumerator_t *inner;
/** current entry */
entry_t *current;
+ /** types we have already enumerated */
+ bool enumerated[AUTH_RULE_MAX];
} entry_enumerator_t;
/**
@@ -102,11 +140,22 @@ static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
{
entry_t *entry;
- if (this->inner->enumerate(this->inner, &entry))
+ while (this->inner->enumerate(this->inner, &entry))
{
+ if (!is_multi_value_rule(entry->type) && this->enumerated[entry->type])
+ {
+ continue;
+ }
+ this->enumerated[entry->type] = TRUE;
this->current = entry;
- *type = entry->type;
- *value = entry->value;
+ if (type)
+ {
+ *type = entry->type;
+ }
+ if (value)
+ {
+ *value = entry->value;
+ }
return TRUE;
}
return FALSE;
@@ -126,15 +175,123 @@ METHOD(auth_cfg_t, create_enumerator, enumerator_t*,
{
entry_enumerator_t *enumerator;
- enumerator = malloc_thing(entry_enumerator_t);
- enumerator->inner = this->entries->create_enumerator(this->entries);
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)entry_enumerator_destroy;
- enumerator->current = NULL;
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)enumerate,
+ .destroy = (void*)entry_enumerator_destroy,
+ },
+ .inner = this->entries->create_enumerator(this->entries),
+ );
return &enumerator->public;
}
/**
+ * Create an entry from the given arguments.
+ */
+static entry_t *entry_create(auth_rule_t type, va_list args)
+{
+ entry_t *this = malloc_thing(entry_t);
+
+ this->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_RSA_STRENGTH:
+ case AUTH_RULE_ECDSA_STRENGTH:
+ /* integer type */
+ this->value = (void*)(uintptr_t)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_RULE_XAUTH_IDENTITY:
+ case AUTH_RULE_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_RULE_CERT_POLICY:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ case AUTH_HELPER_REVOCATION_CERT:
+ /* pointer type */
+ this->value = va_arg(args, void*);
+ break;
+ case AUTH_RULE_MAX:
+ this->value = NULL;
+ break;
+ }
+ return this;
+}
+
+/**
+ * Compare two entries for equality.
+ */
+static bool entry_equals(entry_t *e1, entry_t *e2)
+{
+ if (e1->type != e2->type)
+ {
+ return FALSE;
+ }
+ switch (e1->type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_RSA_STRENGTH:
+ case AUTH_RULE_ECDSA_STRENGTH:
+ {
+ return e1->value == e2->value;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_REVOCATION_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)e1->value;
+ c2 = (certificate_t*)e2->value;
+
+ return c1->equals(c1, c2);
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_IDENTITY:
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)e1->value;
+ id2 = (identification_t*)e2->value;
+
+ return id1->equals(id1, id2);
+ }
+ case AUTH_RULE_CERT_POLICY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ return streq(e1->value, e2->value);
+ }
+ case AUTH_RULE_MAX:
+ break;
+ }
+ return FALSE;
+}
+
+/**
* Destroy the value associated with an entry
*/
static void destroy_entry_value(entry_t *entry)
@@ -177,6 +334,7 @@ static void destroy_entry_value(entry_t *entry)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_MAX:
break;
}
}
@@ -189,12 +347,13 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
{
if (enumerator->current)
{
+ entry_t *entry;
va_list args;
va_start(args, type);
-
- destroy_entry_value(enumerator->current);
- enumerator->current->type = type;
+ entry = enumerator->current;
+ destroy_entry_value(entry);
+ entry->type = type;
switch (type)
{
case AUTH_RULE_AUTH_CLASS:
@@ -205,7 +364,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
/* integer type */
- enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
+ entry->value = (void*)(uintptr_t)va_arg(args, u_int);
break;
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
@@ -223,7 +382,10 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
case AUTH_HELPER_SUBJECT_HASH_URL:
case AUTH_HELPER_REVOCATION_CERT:
/* pointer type */
- enumerator->current->value = va_arg(args, void*);
+ entry->value = va_arg(args, void*);
+ break;
+ case AUTH_RULE_MAX:
+ entry->value = NULL;
break;
}
va_end(args);
@@ -292,9 +454,10 @@ METHOD(auth_cfg_t, get, void*,
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
case AUTH_HELPER_REVOCATION_CERT:
- default:
- return NULL;
+ case AUTH_RULE_MAX:
+ break;
}
+ return NULL;
}
/**
@@ -302,44 +465,22 @@ METHOD(auth_cfg_t, get, void*,
*/
static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
{
- entry_t *entry = malloc_thing(entry_t);
+ entry_t *entry;
va_list args;
va_start(args, type);
- entry->type = type;
- switch (type)
- {
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- case AUTH_RULE_RSA_STRENGTH:
- case AUTH_RULE_ECDSA_STRENGTH:
- /* integer type */
- entry->value = (void*)(uintptr_t)va_arg(args, u_int);
- break;
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AAA_IDENTITY:
- case AUTH_RULE_XAUTH_BACKEND:
- case AUTH_RULE_XAUTH_IDENTITY:
- case AUTH_RULE_GROUP:
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_RULE_CERT_POLICY:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- case AUTH_HELPER_REVOCATION_CERT:
- /* pointer type */
- entry->value = va_arg(args, void*);
- break;
- }
+ entry = entry_create(type, args);
va_end(args);
- this->entries->insert_last(this->entries, entry);
+
+ if (is_multi_value_rule(type))
+ { /* insert rules that may occur multiple times at the end */
+ this->entries->insert_last(this->entries, entry);
+ }
+ else
+ { /* insert rules we expect only once at the front (get() will return
+ * the latest value) */
+ this->entries->insert_first(this->entries, entry);
+ }
}
METHOD(auth_cfg_t, complies, bool,
@@ -599,6 +740,7 @@ METHOD(auth_cfg_t, complies, bool,
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
case AUTH_HELPER_REVOCATION_CERT:
+ case AUTH_RULE_MAX:
/* skip helpers */
continue;
}
@@ -635,6 +777,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
auth_rule_t type;
void *value;
+ /* this enumerator skips duplicates for rules we expect only once */
enumerator = create_enumerator(other);
while (enumerator->enumerate(enumerator, &type, &value))
{
@@ -682,6 +825,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
add(this, type, strdup((char*)value));
break;
}
+ case AUTH_RULE_MAX:
+ break;
}
}
enumerator->destroy(enumerator);
@@ -707,87 +852,23 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
entry_t *i1, *i2;
bool equal = TRUE, found;
- if (this->entries->get_count(this->entries) !=
- other->entries->get_count(other->entries))
- {
- return FALSE;
- }
+ /* the rule count does not have to be equal for the two, as we only compare
+ * the first value found for some rules */
e1 = this->entries->create_enumerator(this->entries);
while (e1->enumerate(e1, &i1))
{
found = FALSE;
+
e2 = other->entries->create_enumerator(other->entries);
while (e2->enumerate(e2, &i2))
{
- if (i1->type == i2->type)
+ if (entry_equals(i1, i2))
{
- switch (i1->type)
- {
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- case AUTH_RULE_RSA_STRENGTH:
- case AUTH_RULE_ECDSA_STRENGTH:
- {
- if (i1->value == i2->value)
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_REVOCATION_CERT:
- {
- certificate_t *c1, *c2;
-
- c1 = (certificate_t*)i1->value;
- c2 = (certificate_t*)i2->value;
-
- if (c1->equals(c1, c2))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AAA_IDENTITY:
- case AUTH_RULE_GROUP:
- case AUTH_RULE_XAUTH_IDENTITY:
- {
- identification_t *id1, *id2;
-
- id1 = (identification_t*)i1->value;
- id2 = (identification_t*)i2->value;
-
- if (id1->equals(id1, id2))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_RULE_XAUTH_BACKEND:
- case AUTH_RULE_CERT_POLICY:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- {
- if (streq(i1->value, i2->value))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- }
+ found = TRUE;
+ break;
+ }
+ else if (i1->type == i2->type && !is_multi_value_rule(i1->type))
+ { /* we continue our search, only for multi valued rules */
break;
}
}
@@ -836,6 +917,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
entry_t *entry;
clone = auth_cfg_create();
+ /* this enumerator skips duplicates for rules we expect only once */
enumerator = this->entries->create_enumerator(this->entries);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -879,6 +961,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_ECDSA_STRENGTH:
clone->add(clone, entry->type, (uintptr_t)entry->value);
break;
+ case AUTH_RULE_MAX:
+ break;
}
}
enumerator->destroy(enumerator);
diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h
index 31c7e7d90..409ec4901 100644
--- a/src/libstrongswan/credentials/auth_cfg.h
+++ b/src/libstrongswan/credentials/auth_cfg.h
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2007-2009 Martin Willi
- * Copyright (C) 2008 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -112,6 +112,9 @@ enum auth_rule_t {
AUTH_HELPER_SUBJECT_HASH_URL,
/** revocation certificate (CRL, OCSP), certificate_t* */
AUTH_HELPER_REVOCATION_CERT,
+
+ /** helper to determine the number of elements in this enum */
+ AUTH_RULE_MAX,
};
/**
@@ -155,7 +158,14 @@ extern enum_name_t *auth_rule_names;
struct auth_cfg_t {
/**
- * Add an rule to the set.
+ * Add a rule to the set.
+ *
+ * Rules we expect only once (e.g. identities) implicitly replace previous
+ * rules of the same type (but pointers to previous values will remain
+ * valid until the auth_cfg_t object is destroyed).
+ * Rules that may occur multiple times (e.g. CA certificates) are inserted
+ * so that they can be enumerated in the order in which they were added.
+ * For these get() will return the value added first.
*
* @param rule rule type
* @param ... associated value to rule
@@ -165,6 +175,8 @@ struct auth_cfg_t {
/**
* Get a rule value.
*
+ * For rules we expect only once the latest value is returned.
+ *
* @param rule rule type
* @return bool if item has been found
*/
@@ -173,6 +185,9 @@ struct auth_cfg_t {
/**
* Create an enumerator over added rules.
*
+ * Refer to add() regarding the order in which rules are enumerated.
+ * For rules we expect only once the latest value is enumerated only.
+ *
* @return enumerator over (auth_rule_t, union{void*,uintpr_t})
*/
enumerator_t* (*create_enumerator)(auth_cfg_t *this);
@@ -214,6 +229,8 @@ struct auth_cfg_t {
/**
* Check two configs for equality.
*
+ * For rules we expect only once the latest value is compared only.
+ *
* @param other other config to compare against this
* @return TRUE if auth infos identical
*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.txt b/src/libstrongswan/crypto/proposal/proposal_keywords.txt
index b16e2eccb..1d04f2dc4 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.txt
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.txt
@@ -131,6 +131,7 @@ md5, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0
md5_128, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0
aesxcbc, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0
camelliaxcbc, INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0
+aescmac, INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0
modpnull, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0
modp768, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0
modp1024, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0
diff --git a/src/libstrongswan/crypto/signers/signer.h b/src/libstrongswan/crypto/signers/signer.h
index e2c224d8b..c6870e475 100644
--- a/src/libstrongswan/crypto/signers/signer.h
+++ b/src/libstrongswan/crypto/signers/signer.h
@@ -66,9 +66,9 @@ enum integrity_algorithm_t {
AUTH_HMAC_SHA1_128 = 1025,
/** SHA256 96 bit truncation variant, supported by Linux kernels */
AUTH_HMAC_SHA2_256_96 = 1026,
- /** SHA256 full length tuncation variant, as used in TLS */
+ /** SHA256 full length truncation variant, as used in TLS */
AUTH_HMAC_SHA2_256_256 = 1027,
- /** SHA384 full length tuncation variant, as used in TLS */
+ /** SHA384 full length truncation variant, as used in TLS */
AUTH_HMAC_SHA2_384_384 = 1028,
/** draft-kanno-ipsecme-camellia-xcbc, not yet assigned by IANA */
AUTH_CAMELLIA_XCBC_96 = 1029,
diff --git a/src/libstrongswan/plugins/cmac/Makefile.am b/src/libstrongswan/plugins/cmac/Makefile.am
new file mode 100644
index 000000000..ce0104f11
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-cmac.la
+else
+plugin_LTLIBRARIES = libstrongswan-cmac.la
+endif
+
+libstrongswan_cmac_la_SOURCES = \
+ cmac_plugin.h cmac_plugin.c cmac.h cmac.c \
+ cmac_prf.h cmac_prf.c cmac_signer.h cmac_signer.c
+
+libstrongswan_cmac_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/cmac/cmac.c b/src/libstrongswan/plugins/cmac/cmac.c
new file mode 100644
index 000000000..5ec7073c7
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 <string.h>
+
+#include "cmac.h"
+
+#include <debug.h>
+
+typedef struct private_cmac_t private_cmac_t;
+
+/**
+ * Private data of a cmac_t object.
+ *
+ * The variable names are the same as in the RFC.
+ */
+struct private_cmac_t {
+
+ /**
+ * Public interface.
+ */
+ cmac_t public;
+
+ /**
+ * Block size, in bytes
+ */
+ u_int8_t b;
+
+ /**
+ * Crypter with key K
+ */
+ crypter_t *k;
+
+ /**
+ * K1
+ */
+ u_int8_t *k1;
+
+ /**
+ * K2
+ */
+ u_int8_t *k2;
+
+ /**
+ * T
+ */
+ u_int8_t *t;
+
+ /**
+ * remaining, unprocessed bytes in append mode
+ */
+ u_int8_t *remaining;
+
+ /**
+ * number of bytes in remaining
+ */
+ int remaining_bytes;
+};
+
+/**
+ * process supplied data, but do not run final operation
+ */
+static void update(private_cmac_t *this, chunk_t data)
+{
+ chunk_t iv;
+
+ if (this->remaining_bytes + data.len <= this->b)
+ { /* no complete block (or last block), just copy into remaining */
+ memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
+ this->remaining_bytes += data.len;
+ return;
+ }
+
+ iv = chunk_alloca(this->b);
+ memset(iv.ptr, 0, iv.len);
+
+ /* T := 0x00000000000000000000000000000000 (initially)
+ * for each block M_i (except the last)
+ * X := T XOR M_i;
+ * T := AES-128(K, X);
+ */
+
+ /* append data to remaining bytes, process block M_1 */
+ memcpy(this->remaining + this->remaining_bytes, data.ptr,
+ this->b - this->remaining_bytes);
+ data = chunk_skip(data, this->b - this->remaining_bytes);
+ memxor(this->t, this->remaining, this->b);
+ this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+
+ /* process blocks M_2 ... M_n-1 */
+ while (data.len > this->b)
+ {
+ memcpy(this->remaining, data.ptr, this->b);
+ data = chunk_skip(data, this->b);
+ memxor(this->t, this->remaining, this->b);
+ this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+ }
+
+ /* store remaining bytes of block M_n */
+ memcpy(this->remaining, data.ptr, data.len);
+ this->remaining_bytes = data.len;
+}
+
+/**
+ * process last block M_last
+ */
+static void final(private_cmac_t *this, u_int8_t *out)
+{
+ chunk_t iv;
+
+ iv = chunk_alloca(this->b);
+ memset(iv.ptr, 0, iv.len);
+
+ /* if last block is complete
+ * M_last := M_n XOR K1;
+ * else
+ * M_last := padding(M_n) XOR K2;
+ */
+ if (this->remaining_bytes == this->b)
+ {
+ memxor(this->remaining, this->k1, this->b);
+ }
+ else
+ {
+ /* padding(x) = x || 10^i where i is 128-8*r-1
+ * That is, padding(x) is the concatenation of x and a single '1',
+ * followed by the minimum number of '0's, so that the total length is
+ * equal to 128 bits.
+ */
+ if (this->remaining_bytes < this->b)
+ {
+ this->remaining[this->remaining_bytes] = 0x80;
+ while (++this->remaining_bytes < this->b)
+ {
+ this->remaining[this->remaining_bytes] = 0x00;
+ }
+ }
+ memxor(this->remaining, this->k2, this->b);
+ }
+ /* T := M_last XOR T;
+ * T := AES-128(K,T);
+ */
+ memxor(this->t, this->remaining, this->b);
+ this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+
+ memcpy(out, this->t, this->b);
+
+ /* reset state */
+ memset(this->t, 0, this->b);
+ this->remaining_bytes = 0;
+}
+
+METHOD(cmac_t, get_mac, void,
+ private_cmac_t *this, chunk_t data, u_int8_t *out)
+{
+ /* update T, do not process last block */
+ update(this, data);
+
+ if (out)
+ { /* if not in append mode, process last block and output result */
+ final(this, out);
+ }
+}
+
+METHOD(cmac_t, get_block_size, size_t,
+ private_cmac_t *this)
+{
+ return this->b;
+}
+
+/**
+ * Left-shift the given chunk by one bit.
+ */
+static void bit_shift(chunk_t chunk)
+{
+ size_t i;
+
+ for (i = 0; i < chunk.len; i++)
+ {
+ chunk.ptr[i] <<= 1;
+ if (i < chunk.len - 1 && chunk.ptr[i + 1] & 0x80)
+ {
+ chunk.ptr[i] |= 0x01;
+ }
+ }
+}
+
+/**
+ * Apply the following key derivation (in-place):
+ * if MSB(C) == 0
+ * C := C << 1
+ * else
+ * C := (C << 1) XOR 0x00000000000000000000000000000087
+ */
+static void derive_key(chunk_t chunk)
+{
+ if (chunk.ptr[0] & 0x80)
+ {
+ chunk_t rb;
+
+ rb = chunk_alloca(chunk.len);
+ memset(rb.ptr, 0, rb.len);
+ rb.ptr[rb.len - 1] = 0x87;
+ bit_shift(chunk);
+ memxor(chunk.ptr, rb.ptr, chunk.len);
+ }
+ else
+ {
+ bit_shift(chunk);
+ }
+}
+
+METHOD(cmac_t, set_key, void,
+ private_cmac_t *this, chunk_t key)
+{
+ chunk_t resized, iv, l;
+
+ /* we support variable keys as defined in RFC 4615 */
+ if (key.len == this->b)
+ {
+ resized = key;
+ }
+ else
+ { /* use cmac recursively to resize longer or shorter keys */
+ resized = chunk_alloca(this->b);
+ memset(resized.ptr, 0, resized.len);
+ set_key(this, resized);
+ get_mac(this, key, resized.ptr);
+ }
+
+ /*
+ * Rb = 0x00000000000000000000000000000087
+ * L = 0x00000000000000000000000000000000 encrypted with K
+ * if MSB(L) == 0
+ * K1 = L << 1
+ * else
+ * K1 = (L << 1) XOR Rb
+ * if MSB(K1) == 0
+ * K2 = K1 << 1
+ * else
+ * K2 = (K1 << 1) XOR Rb
+ */
+ iv = chunk_alloca(this->b);
+ memset(iv.ptr, 0, iv.len);
+ l = chunk_alloca(this->b);
+ memset(l.ptr, 0, l.len);
+ this->k->set_key(this->k, resized);
+ this->k->encrypt(this->k, l, iv, NULL);
+ derive_key(l);
+ memcpy(this->k1, l.ptr, l.len);
+ derive_key(l);
+ memcpy(this->k2, l.ptr, l.len);
+ memwipe(l.ptr, l.len);
+}
+
+METHOD(cmac_t, destroy, void,
+ private_cmac_t *this)
+{
+ this->k->destroy(this->k);
+ memwipe(this->k1, this->b);
+ free(this->k1);
+ memwipe(this->k2, this->b);
+ free(this->k2);
+ free(this->t);
+ free(this->remaining);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
+{
+ private_cmac_t *this;
+ crypter_t *crypter;
+ u_int8_t b;
+
+ crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
+ if (!crypter)
+ {
+ return NULL;
+ }
+ b = crypter->get_block_size(crypter);
+ /* input and output of crypter must be equal for cmac */
+ if (b != key_size)
+ {
+ crypter->destroy(crypter);
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_mac = _get_mac,
+ .get_block_size = _get_block_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .b = b,
+ .k = crypter,
+ .k1 = malloc(b),
+ .k2 = malloc(b),
+ .t = malloc(b),
+ .remaining = malloc(b),
+ );
+ memset(this->t, 0, b);
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/cmac/cmac.h b/src/libstrongswan/plugins/cmac/cmac.h
new file mode 100644
index 000000000..061609127
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 cmac cmac
+ * @{ @ingroup cmac_p
+ */
+
+#ifndef CMAC_H_
+#define CMAC_H_
+
+#include <crypto/crypters/crypter.h>
+
+typedef struct cmac_t cmac_t;
+
+/**
+ * Cipher-based Message Authentication Code (CMAC).
+ *
+ * This class implements the message authentication algorithm
+ * described in RFC 4493.
+ */
+struct cmac_t {
+
+ /**
+ * Generate message authentication code.
+ *
+ * If buffer is NULL, no result is given back. A next call will
+ * append the data to already supplied data. If buffer is not NULL,
+ * the mac of all apended data is calculated, returned and the internal
+ * state is reset.
+ *
+ * @param data chunk of data to authenticate
+ * @param buffer pointer where the generated bytes will be written
+ */
+ void (*get_mac) (cmac_t *this, chunk_t data, u_int8_t *buffer);
+
+ /**
+ * Get the block size of this cmac_t object.
+ *
+ * @return block size in bytes
+ */
+ size_t (*get_block_size) (cmac_t *this);
+
+ /**
+ * Set the key for this cmac_t object.
+ *
+ * @param key key to set
+ */
+ void (*set_key) (cmac_t *this, chunk_t key);
+
+ /**
+ * Destroys a cmac_t object.
+ */
+ void (*destroy) (cmac_t *this);
+};
+
+/**
+ * Creates a new cmac_t object.
+ *
+ * @param algo underlying crypto algorithm
+ * @param key_size key size to use, if required for algorithm
+ * @return cmac_t object, NULL if not supported
+ */
+cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size);
+
+#endif /** CMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/cmac/cmac_plugin.c b/src/libstrongswan/plugins/cmac/cmac_plugin.c
new file mode 100644
index 000000000..5b42c5002
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_plugin.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 "cmac_plugin.h"
+
+#include <library.h>
+#include "cmac_prf.h"
+#include "cmac_signer.h"
+
+typedef struct private_cmac_plugin_t private_cmac_plugin_t;
+
+/**
+ * private data of cmac_plugin
+ */
+struct private_cmac_plugin_t {
+
+ /**
+ * public functions
+ */
+ cmac_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_cmac_plugin_t *this)
+{
+ return "cmac";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_cmac_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_REGISTER(PRF, cmac_prf_create),
+ PLUGIN_PROVIDE(PRF, PRF_AES128_CMAC),
+ PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16),
+ PLUGIN_REGISTER(SIGNER, cmac_signer_create),
+ PLUGIN_PROVIDE(SIGNER, AUTH_AES_CMAC_96),
+ PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_cmac_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *cmac_plugin_create()
+{
+ private_cmac_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libstrongswan/plugins/cmac/cmac_plugin.h b/src/libstrongswan/plugins/cmac/cmac_plugin.h
new file mode 100644
index 000000000..a31e1077d
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 cmac_p cmac
+ * @ingroup plugins
+ *
+ * @defgroup cmac_plugin cmac_plugin
+ * @{ @ingroup cmac_p
+ */
+
+#ifndef CMAC_PLUGIN_H_
+#define CMAC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct cmac_plugin_t cmac_plugin_t;
+
+/**
+ * Plugin implementing CMAC algorithm to provide crypter based PRF and signer.
+ */
+struct cmac_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** CMAC_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/cmac/cmac_prf.c b/src/libstrongswan/plugins/cmac/cmac_prf.c
new file mode 100644
index 000000000..17affe439
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_prf.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 "cmac_prf.h"
+
+#include "cmac.h"
+
+typedef struct private_cmac_prf_t private_cmac_prf_t;
+
+/**
+ * Private data of a cmac_prf_t object.
+ */
+struct private_cmac_prf_t {
+
+ /**
+ * Public cmac_prf_t interface.
+ */
+ cmac_prf_t public;
+
+ /**
+ * cmac to use for generation.
+ */
+ cmac_t *cmac;
+};
+
+METHOD(prf_t, get_bytes, void,
+ private_cmac_prf_t *this, chunk_t seed, u_int8_t *buffer)
+{
+ this->cmac->get_mac(this->cmac, seed, buffer);
+}
+
+METHOD(prf_t, allocate_bytes, void,
+ private_cmac_prf_t *this, chunk_t seed, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ *chunk = chunk_alloc(this->cmac->get_block_size(this->cmac));
+ get_bytes(this, seed, chunk->ptr);
+ }
+ else
+ {
+ get_bytes(this, seed, NULL);
+ }
+}
+
+METHOD(prf_t, get_block_size, size_t,
+ private_cmac_prf_t *this)
+{
+ return this->cmac->get_block_size(this->cmac);
+}
+
+METHOD(prf_t, get_key_size, size_t,
+ private_cmac_prf_t *this)
+{
+ /* in cmac, block and key size are always equal */
+ return this->cmac->get_block_size(this->cmac);
+}
+
+METHOD(prf_t, set_key, void,
+ private_cmac_prf_t *this, chunk_t key)
+{
+ this->cmac->set_key(this->cmac, key);
+}
+
+METHOD(prf_t, destroy, void,
+ private_cmac_prf_t *this)
+{
+ this->cmac->destroy(this->cmac);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+cmac_prf_t *cmac_prf_create(pseudo_random_function_t algo)
+{
+ private_cmac_prf_t *this;
+ cmac_t *cmac;
+
+ switch (algo)
+ {
+ case PRF_AES128_CMAC:
+ cmac = cmac_create(ENCR_AES_CBC, 16);
+ break;
+ default:
+ return NULL;
+ }
+ if (!cmac)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .prf = {
+ .get_bytes = _get_bytes,
+ .allocate_bytes = _allocate_bytes,
+ .get_block_size = _get_block_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ },
+ .cmac = cmac,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/cmac/cmac_prf.h b/src/libstrongswan/plugins/cmac/cmac_prf.h
new file mode 100644
index 000000000..a53cc5947
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_prf.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 cmac_prf cmac_prf
+ * @{ @ingroup cmac_p
+ */
+
+#ifndef PRF_CMAC_H_
+#define PRF_CMAC_H_
+
+typedef struct cmac_prf_t cmac_prf_t;
+
+#include <crypto/prfs/prf.h>
+
+/**
+ * Implementation of prf_t on CBC block cipher using CMAC, RFC 4493 / RFC 4615.
+ *
+ * This simply wraps a cmac_t in a prf_t. More a question of
+ * interface matching.
+ */
+struct cmac_prf_t {
+
+ /**
+ * Implements prf_t interface.
+ */
+ prf_t prf;
+};
+
+/**
+ * Creates a new cmac_prf_t object.
+ *
+ * @param algo algorithm to implement
+ * @return cmac_prf_t object, NULL if hash not supported
+ */
+cmac_prf_t *cmac_prf_create(pseudo_random_function_t algo);
+
+#endif /** PRF_CMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/cmac/cmac_signer.c b/src/libstrongswan/plugins/cmac/cmac_signer.c
new file mode 100644
index 000000000..82e8885d6
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_signer.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 <string.h>
+
+#include "cmac_signer.h"
+#include "cmac.h"
+
+typedef struct private_cmac_signer_t private_cmac_signer_t;
+
+/**
+ * Private data structure with signing context.
+ */
+struct private_cmac_signer_t {
+
+ /**
+ * Public interface.
+ */
+ cmac_signer_t public;
+
+ /**
+ * Assigned cmac function.
+ */
+ cmac_t *cmac;
+
+ /**
+ * Block size (truncation of CMAC MAC)
+ */
+ size_t block_size;
+};
+
+METHOD(signer_t, get_signature, void,
+ private_cmac_signer_t *this, chunk_t data, u_int8_t *buffer)
+{
+ if (buffer == NULL)
+ { /* append mode */
+ this->cmac->get_mac(this->cmac, data, NULL);
+ }
+ else
+ {
+ u_int8_t mac[this->cmac->get_block_size(this->cmac)];
+
+ this->cmac->get_mac(this->cmac, data, mac);
+ memcpy(buffer, mac, this->block_size);
+ }
+}
+
+METHOD(signer_t, allocate_signature, void,
+ private_cmac_signer_t *this, chunk_t data, chunk_t *chunk)
+{
+ if (chunk == NULL)
+ { /* append mode */
+ this->cmac->get_mac(this->cmac, data, NULL);
+ }
+ else
+ {
+ u_int8_t mac[this->cmac->get_block_size(this->cmac)];
+
+ this->cmac->get_mac(this->cmac, data, mac);
+
+ chunk->ptr = malloc(this->block_size);
+ chunk->len = this->block_size;
+
+ memcpy(chunk->ptr, mac, this->block_size);
+ }
+}
+
+METHOD(signer_t, verify_signature, bool,
+ private_cmac_signer_t *this, chunk_t data, chunk_t signature)
+{
+ u_int8_t mac[this->cmac->get_block_size(this->cmac)];
+
+ if (signature.len != this->block_size)
+ {
+ return FALSE;
+ }
+
+ this->cmac->get_mac(this->cmac, data, mac);
+ return memeq(signature.ptr, mac, this->block_size);
+}
+
+METHOD(signer_t, get_key_size, size_t,
+ private_cmac_signer_t *this)
+{
+ return this->cmac->get_block_size(this->cmac);
+}
+
+METHOD(signer_t, get_block_size, size_t,
+ private_cmac_signer_t *this)
+{
+ return this->block_size;
+}
+
+METHOD(signer_t, set_key, void,
+ private_cmac_signer_t *this, chunk_t key)
+{
+ this->cmac->set_key(this->cmac, key);
+}
+
+METHOD(signer_t, destroy, void,
+ private_cmac_signer_t *this)
+{
+ this->cmac->destroy(this->cmac);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+cmac_signer_t *cmac_signer_create(integrity_algorithm_t algo)
+{
+ private_cmac_signer_t *this;
+ size_t truncation;
+ cmac_t *cmac;
+
+ switch (algo)
+ {
+ case AUTH_AES_CMAC_96:
+ cmac = cmac_create(ENCR_AES_CBC, 16);
+ truncation = 12;
+ break;
+ default:
+ return NULL;
+ }
+ if (cmac == NULL)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .signer = {
+ .get_signature = _get_signature,
+ .allocate_signature = _allocate_signature,
+ .verify_signature = _verify_signature,
+ .get_key_size = _get_key_size,
+ .get_block_size = _get_block_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ },
+ .cmac = cmac,
+ .block_size = min(truncation, cmac->get_block_size(cmac)),
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/cmac/cmac_signer.h b/src/libstrongswan/plugins/cmac/cmac_signer.h
new file mode 100644
index 000000000..2e3724471
--- /dev/null
+++ b/src/libstrongswan/plugins/cmac/cmac_signer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 cmac_signer cmac_signer
+ * @{ @ingroup cmac_p
+ */
+
+#ifndef CMAC_SIGNER_H_
+#define CMAC_SIGNER_H_
+
+typedef struct cmac_signer_t cmac_signer_t;
+
+#include <crypto/signers/signer.h>
+
+/**
+ * Implementation of signer_t on CBC symmetric cipher using CMAC, RFC 4494.
+ */
+struct cmac_signer_t {
+
+ /**
+ * Implements signer_t interface.
+ */
+ signer_t signer;
+};
+
+/**
+ * Creates a new cmac_signer_t.
+ *
+ * @param algo algorithm to implement
+ * @return cmac_signer_t, NULL if not supported
+ */
+cmac_signer_t *cmac_signer_create(integrity_algorithm_t algo);
+
+#endif /** CMAC_SIGNER_H_ @}*/
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c
index ee71f6efd..c0666367a 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf.c
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c
@@ -127,14 +127,14 @@ METHOD(prf_t, get_bytes, void,
{
/* a. XVAL = (XKEY + XSEED j) mod 2^b */
add_mod(this->b, xkey, xseed, xval);
- DBG3(DBG_LIB, "XVAL %b", xval, this->b);
+ DBG3(DBG_LIB, "XVAL %b", xval, (u_int)this->b);
/* b. wi = G(t, XVAL ) */
this->g(this, chunk_create(xval, this->b), &w[i * this->b]);
- DBG3(DBG_LIB, "w[%d] %b", i, &w[i * this->b], this->b);
+ DBG3(DBG_LIB, "w[%d] %b", i, &w[i * this->b], (u_int)this->b);
/* c. XKEY = (1 + XKEY + wi) mod 2b */
add_mod(this->b, xkey, &w[i * this->b], sum);
add_mod(this->b, sum, one, xkey);
- DBG3(DBG_LIB, "XKEY %b", xkey, this->b);
+ DBG3(DBG_LIB, "XKEY %b", xkey, (u_int)this->b);
}
/* 3.3 done already, mod q not used */
diff --git a/src/libstrongswan/plugins/hmac/hmac.c b/src/libstrongswan/plugins/hmac/hmac.c
index 397a1ea11..91294305e 100644
--- a/src/libstrongswan/plugins/hmac/hmac.c
+++ b/src/libstrongswan/plugins/hmac/hmac.c
@@ -4,13 +4,13 @@
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General hmac License as published by the
+ * 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 hmac License
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index f05d348ee..c5d96be47 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -355,7 +355,7 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
* load the credential from a blob
*/
static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
- x509_flag_t flags)
+ identification_t *subject, x509_flag_t flags)
{
void *cred = NULL;
bool pgp = FALSE;
@@ -381,10 +381,19 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
{
subtype = pgp ? CERT_GPG : CERT_X509;
}
- cred = lib->creds->create(lib->creds, type, subtype,
+ if (type == CRED_CERTIFICATE && subtype == CERT_TRUSTED_PUBKEY && subject)
+ {
+ cred = lib->creds->create(lib->creds, type, subtype,
+ BUILD_BLOB_ASN1_DER, blob, BUILD_SUBJECT, subject,
+ BUILD_END);
+ }
+ else
+ {
+ cred = lib->creds->create(lib->creds, type, subtype,
pgp ? BUILD_BLOB_PGP : BUILD_BLOB_ASN1_DER, blob,
flags ? BUILD_X509_FLAG : BUILD_END,
flags, BUILD_END);
+ }
chunk_clear(&blob);
return cred;
}
@@ -393,7 +402,7 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
* load the credential from a file
*/
static void *load_from_file(char *file, credential_type_t type, int subtype,
- x509_flag_t flags)
+ identification_t *subject, x509_flag_t flags)
{
void *cred = NULL;
struct stat sb;
@@ -423,7 +432,8 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
return NULL;
}
- cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype, flags);
+ cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype,
+ subject, flags);
munmap(addr, sb.st_size);
close(fd);
@@ -434,7 +444,7 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
* load the credential from a file descriptor
*/
static void *load_from_fd(int fd, credential_type_t type, int subtype,
- x509_flag_t flags)
+ identification_t *subject, x509_flag_t flags)
{
char buf[8096];
char *pos = buf;
@@ -460,7 +470,8 @@ static void *load_from_fd(int fd, credential_type_t type, int subtype,
return NULL;
}
}
- return load_from_blob(chunk_create(buf, total), type, subtype, flags);
+ return load_from_blob(chunk_create(buf, total), type, subtype,
+ subject, flags);
}
/**
@@ -471,6 +482,7 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
char *file = NULL;
int fd = -1;
chunk_t pem = chunk_empty;
+ identification_t *subject = NULL;
int flags = 0;
while (TRUE)
@@ -486,6 +498,9 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
case BUILD_BLOB_PEM:
pem = va_arg(args, chunk_t);
continue;
+ case BUILD_SUBJECT:
+ subject = va_arg(args, identification_t*);
+ continue;
case BUILD_X509_FLAG:
flags = va_arg(args, int);
continue;
@@ -499,15 +514,15 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
if (pem.len)
{
- return load_from_blob(pem, type, subtype, flags);
+ return load_from_blob(pem, type, subtype, subject, flags);
}
if (file)
{
- return load_from_file(file, type, subtype, flags);
+ return load_from_file(file, type, subtype, subject, flags);
}
if (fd != -1)
{
- return load_from_fd(fd, type, subtype, flags);
+ return load_from_fd(fd, type, subtype, subject, flags);
}
return NULL;
}
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.c b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
index 54c51a834..67240fe0c 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_cert.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
@@ -15,6 +15,8 @@
#include "pubkey_cert.h"
+#include <time.h>
+
#include <debug.h>
typedef struct private_pubkey_cert_t private_pubkey_cert_t;
@@ -45,6 +47,16 @@ struct private_pubkey_cert_t {
identification_t *subject;
/**
+ * key inception time
+ */
+ time_t notBefore;
+
+ /**
+ * key expiration time
+ */
+ time_t notAfter;
+
+ /**
* reference count
*/
refcount_t ref;
@@ -85,7 +97,8 @@ METHOD(certificate_t, has_subject, id_match_t,
}
}
}
- return ID_MATCH_NONE;
+
+ return this->subject->matches(this->subject, subject);
}
METHOD(certificate_t, has_issuer, id_match_t,
@@ -129,15 +142,18 @@ METHOD(certificate_t, get_validity, bool,
private_pubkey_cert_t *this, time_t *when, time_t *not_before,
time_t *not_after)
{
+ time_t t = when ? *when : time(NULL);
+
if (not_before)
{
- *not_before = 0;
+ *not_before = this->notBefore;
}
if (not_after)
{
- *not_after = ~0;
+ *not_after = this->notAfter;
}
- return TRUE;
+ return ((this->notBefore == UNDEFINED_TIME || t >= this->notBefore) &&
+ (this->notAfter == UNDEFINED_TIME || t <= this->notAfter));
}
METHOD(certificate_t, get_encoding, bool,
@@ -168,7 +184,9 @@ METHOD(certificate_t, destroy, void,
/*
* see header file
*/
-static pubkey_cert_t *pubkey_cert_create(public_key_t *key)
+static pubkey_cert_t *pubkey_cert_create(public_key_t *key,
+ time_t notBefore, time_t notAfter,
+ identification_t *subject)
{
private_pubkey_cert_t *this;
chunk_t fingerprint;
@@ -192,10 +210,16 @@ static pubkey_cert_t *pubkey_cert_create(public_key_t *key)
},
.ref = 1,
.key = key,
+ .notBefore = notBefore,
+ .notAfter = notAfter,
.issuer = identification_create_from_encoding(ID_ANY, chunk_empty),
);
- if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &fingerprint))
+ if (subject)
+ {
+ this->subject = subject->clone(subject);
+ }
+ else if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &fingerprint))
{
this->subject = identification_create_from_encoding(ID_KEY_ID, fingerprint);
}
@@ -214,6 +238,8 @@ pubkey_cert_t *pubkey_cert_wrap(certificate_type_t type, va_list args)
{
public_key_t *key = NULL;
chunk_t blob = chunk_empty;
+ identification_t *subject = NULL;
+ time_t notBefore = UNDEFINED_TIME, notAfter = UNDEFINED_TIME;
while (TRUE)
{
@@ -225,6 +251,15 @@ pubkey_cert_t *pubkey_cert_wrap(certificate_type_t type, va_list args)
case BUILD_PUBLIC_KEY:
key = va_arg(args, public_key_t*);
continue;
+ case BUILD_NOT_BEFORE_TIME:
+ notBefore = va_arg(args, time_t);
+ continue;
+ case BUILD_NOT_AFTER_TIME:
+ notAfter = va_arg(args, time_t);
+ continue;
+ case BUILD_SUBJECT:
+ subject = va_arg(args, identification_t*);
+ continue;
case BUILD_END:
break;
default:
@@ -243,7 +278,7 @@ pubkey_cert_t *pubkey_cert_wrap(certificate_type_t type, va_list args)
}
if (key)
{
- return pubkey_cert_create(key);
+ return pubkey_cert_create(key, notBefore, notAfter, subject);
}
return NULL;
}
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am
index 049301977..5280300a8 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.am
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.am
@@ -15,6 +15,7 @@ libstrongswan_test_vectors_la_SOURCES = \
test_vectors/aes_cbc.c \
test_vectors/aes_ctr.c \
test_vectors/aes_xcbc.c \
+ test_vectors/aes_cmac.c \
test_vectors/aes_ccm.c \
test_vectors/aes_gcm.c \
test_vectors/blowfish.c \
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h
index ab4689c1c..40fb51da6 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors.h
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h
@@ -91,6 +91,10 @@ TEST_VECTOR_SIGNER(aes_xcbc_s2)
TEST_VECTOR_SIGNER(aes_xcbc_s3)
TEST_VECTOR_SIGNER(aes_xcbc_s4)
TEST_VECTOR_SIGNER(aes_xcbc_s5)
+TEST_VECTOR_SIGNER(aes_cmac_s1)
+TEST_VECTOR_SIGNER(aes_cmac_s2)
+TEST_VECTOR_SIGNER(aes_cmac_s3)
+TEST_VECTOR_SIGNER(aes_cmac_s4)
TEST_VECTOR_SIGNER(camellia_xcbc_s1)
TEST_VECTOR_SIGNER(md5_hmac_s1)
TEST_VECTOR_SIGNER(md5_hmac_s2)
@@ -156,6 +160,13 @@ TEST_VECTOR_PRF(aes_xcbc_p4)
TEST_VECTOR_PRF(aes_xcbc_p5)
TEST_VECTOR_PRF(aes_xcbc_p6)
TEST_VECTOR_PRF(aes_xcbc_p7)
+TEST_VECTOR_PRF(aes_cmac_p1)
+TEST_VECTOR_PRF(aes_cmac_p2)
+TEST_VECTOR_PRF(aes_cmac_p3)
+TEST_VECTOR_PRF(aes_cmac_p4)
+TEST_VECTOR_PRF(aes_cmac_p5)
+TEST_VECTOR_PRF(aes_cmac_p6)
+TEST_VECTOR_PRF(aes_cmac_p7)
TEST_VECTOR_PRF(camellia_xcbc_p1)
TEST_VECTOR_PRF(camellia_xcbc_p2)
TEST_VECTOR_PRF(camellia_xcbc_p3)
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/aes_cmac.c b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_cmac.c
new file mode 100644
index 000000000..cc4121424
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_cmac.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 Licenseor (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 usefulbut
+ * 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 <crypto/crypto_tester.h>
+
+/**
+ * RFC 4493 Example #1: AES-CMAC with 0-byte input
+ */
+prf_test_vector_t aes_cmac_p1 = {
+ .alg = PRF_AES128_CMAC, .key_size = 16, .len = 0,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .seed = "",
+ .out = "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46"
+};
+
+/**
+ * RFC 4493 Example #2: AES-CMAC with 16-byte input
+ */
+prf_test_vector_t aes_cmac_p2 = {
+ .alg = PRF_AES128_CMAC, .key_size = 16, .len = 16,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .seed = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
+ .out = "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c"
+};
+
+/**
+ * RFC 4493 Example #3: AES-CMAC with 40-byte input
+ */
+prf_test_vector_t aes_cmac_p3 = {
+ .alg = PRF_AES128_CMAC, .key_size = 16, .len = 40,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .seed = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
+ .out = "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27"
+};
+
+/**
+ * RFC 4493 Example #4: AES-CMAC with 64-byte input
+ */
+prf_test_vector_t aes_cmac_p4 = {
+ .alg = PRF_AES128_CMAC, .key_size = 16, .len = 64,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .seed = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .out = "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe"
+};
+
+/**
+ * RFC 4615 Test Case #1: AES-CMAC with 20-byte input, 18-byte key
+ */
+prf_test_vector_t aes_cmac_p5 = {
+ .alg = PRF_AES128_CMAC, .key_size = 18, .len = 20,
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\xed\xcb",
+ .seed = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13",
+ .out = "\x84\xa3\x48\xa4\xa4\x5d\x23\x5b\xab\xff\xfc\x0d\x2b\x4d\xa0\x9a"
+};
+
+/**
+ * RFC 4615 Test Case #2: AES-CMAC with 20-byte input, 16-byte key
+ */
+prf_test_vector_t aes_cmac_p6 = {
+ .alg = PRF_AES128_CMAC, .key_size = 16, .len = 20,
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .seed = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13",
+ .out = "\x98\x0a\xe8\x7b\x5f\x4c\x9c\x52\x14\xf5\xb6\xa8\x45\x5e\x4c\x2d"
+};
+
+/**
+ * RFC 4615 Test Case #3: AES-CMAC with 20-byte input, 10-byte key
+ */
+prf_test_vector_t aes_cmac_p7 = {
+ .alg = PRF_AES128_CMAC, .key_size = 10, .len = 20,
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09",
+ .seed = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13",
+ .out = "\x29\x0d\x9e\x11\x2e\xdb\x09\xee\x14\x1f\xcf\x64\xc0\xb7\x2f\x3d"
+};
+
+/**
+ * RFC 4494 Test Case #1: AES-CMAC-96 with 0-byte input
+ */
+signer_test_vector_t aes_cmac_s1 = {
+ .alg = AUTH_AES_CMAC_96, .len = 0,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .data = "",
+ .mac = "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12"
+};
+
+
+/**
+ * RFC 4494 Test Case #2: AES-CMAC-96 with 16-byte input
+ */
+signer_test_vector_t aes_cmac_s2 = {
+ .alg = AUTH_AES_CMAC_96, .len = 16,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .data = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
+ .mac = "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d"
+};
+
+/**
+ * RFC 4494 Test Case #3: AES-CMAC-96 with 40-byte input
+ */
+signer_test_vector_t aes_cmac_s3 = {
+ .alg = AUTH_AES_CMAC_96, .len = 40,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .data = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
+ .mac = "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61"
+};
+
+/**
+ * RFC 4494 Test Case #4: AES-CMAC-96 with 64-byte input
+ */
+signer_test_vector_t aes_cmac_s4 = {
+ .alg = AUTH_AES_CMAC_96, .len = 64,
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .data = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .mac = "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17"
+};
diff --git a/src/libstrongswan/plugins/xcbc/xcbc.c b/src/libstrongswan/plugins/xcbc/xcbc.c
index 8ddde962c..53629abe5 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc.c
+++ b/src/libstrongswan/plugins/xcbc/xcbc.c
@@ -3,13 +3,13 @@
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General xcbc License as published by the
+ * 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 xcbc License
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c
index 5a104de7f..f76245a19 100644
--- a/src/libstrongswan/utils.c
+++ b/src/libstrongswan/utils.c
@@ -444,7 +444,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
printf_hook_spec_t *spec, const void *const *args)
{
char *bytes = *((void**)(args[0]));
- int len = *((size_t*)(args[1]));
+ u_int len = *((int*)(args[1]));
char buffer[BYTES_PER_LINE * 3];
char ascii_buffer[BYTES_PER_LINE + 1];
@@ -455,7 +455,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
int i = 0;
int written = 0;
- written += print_in_hook(dst, dstlen, "=> %d bytes @ %p", len, bytes);
+ written += print_in_hook(dst, dstlen, "=> %u bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{
diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h
index 367b3e37c..c5718d9f8 100644
--- a/src/libstrongswan/utils.h
+++ b/src/libstrongswan/utils.h
@@ -651,7 +651,7 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
* printf hook for memory areas.
*
* Arguments are:
- * u_char *ptr, int len
+ * u_char *ptr, u_int len
*/
int mem_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
const void *const *args);
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 252cfa28e..9f0007f78 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -81,6 +81,7 @@ static const x501rdn_t x501rdns[] = {
{"N", OID_NAME, ASN1_PRINTABLESTRING},
{"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING},
{"I", OID_INITIALS, ASN1_PRINTABLESTRING},
+ {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING},
{"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING},
{"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
{"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
@@ -219,6 +220,7 @@ METHOD(enumerator_t, rdn_part_enumerate, bool,
{OID_NAME, ID_PART_RDN_N},
{OID_GIVEN_NAME, ID_PART_RDN_G},
{OID_INITIALS, ID_PART_RDN_I},
+ {OID_DN_QUALIFIER, ID_PART_RDN_DNQ},
{OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
{OID_EMAIL_ADDRESS, ID_PART_RDN_E},
{OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index af0804f32..3978b23f3 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -171,6 +171,8 @@ enum id_part_t {
ID_PART_RDN_G,
/** Initials RDN of a DN */
ID_PART_RDN_I,
+ /** DN Qualifier RDN of a DN */
+ ID_PART_RDN_DNQ,
/** UniqueIdentifier RDN of a DN */
ID_PART_RDN_ID,
/** Locality RDN of a DN */
@@ -298,7 +300,7 @@ struct identification_t {
*
* A distinguished name may contain one or more of the following RDNs:
* ND, UID, DC, CN, S, SN, serialNumber, C, L, ST, O, OU, T, D,
- * N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
+ * N, G, I, dnQualifier, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
* unstructuredName, TCGID.
*
* This constructor never returns NULL. If it does not find a suitable
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index 2bc80f96b..90cf254c8 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -79,7 +79,7 @@ static void print_x509(x509_t *x509)
x509_cert_policy_t *policy;
x509_policy_mapping_t *mapping;
- chunk = x509->get_serial(x509);
+ chunk = chunk_skip_zero(x509->get_serial(x509));
printf("serial: %#B\n", &chunk);
first = TRUE;
@@ -333,10 +333,12 @@ static void print_crl(crl_t *crl)
struct tm tm;
x509_cdp_t *cdp;
- chunk = crl->get_serial(crl);
+ chunk = chunk_skip_zero(crl->get_serial(crl));
printf("serial: %#B\n", &chunk);
+
if (crl->is_delta_crl(crl, &chunk))
{
+ chunk = chunk_skip_zero(chunk);
printf("delta CRL: for serial %#B\n", &chunk);
}
chunk = crl->get_authKeyIdentifier(crl);
@@ -375,6 +377,7 @@ static void print_crl(crl_t *crl)
enumerator = crl->create_enumerator(crl);
while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
{
+ chunk = chunk_skip_zero(chunk);
localtime_r(&ts, &tm);
strftime(buf, sizeof(buf), "%F %T", &tm);
printf(" %#B %N %s\n", &chunk, crl_reason_names, reason, buf);
diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c
index 827fd7318..153734f53 100644
--- a/src/pki/commands/signcrl.c
+++ b/src/pki/commands/signcrl.c
@@ -120,7 +120,7 @@ static int sign_crl()
hash_algorithm_t digest = HASH_SHA1;
char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL;
char *basecrl = NULL;
- char serial[512], crl_serial[8], *keyid = NULL;
+ char serial[512], *keyid = NULL;
int serial_len = 0;
crl_reason_t reason = CRL_REASON_UNSPECIFIED;
time_t thisUpdate, nextUpdate, date = time(NULL);
@@ -128,13 +128,12 @@ static int sign_crl()
linked_list_t *list, *cdps;
enumerator_t *enumerator, *lastenum = NULL;
x509_cdp_t *cdp;
- chunk_t encoding = chunk_empty, baseCrlNumber = chunk_empty;
+ chunk_t crl_serial = chunk_empty, baseCrlNumber = chunk_empty;
+ chunk_t encoding = chunk_empty;
list = linked_list_create();
cdps = linked_list_create();
- memset(crl_serial, 0, sizeof(crl_serial));
-
while (TRUE)
{
switch (command_getopt(&arg))
@@ -334,9 +333,8 @@ static int sign_crl()
error = "loading base CRL failed";
goto error;
}
- memcpy(crl_serial, lastcrl->get_serial(lastcrl).ptr,
- min(lastcrl->get_serial(lastcrl).len, sizeof(crl_serial)));
baseCrlNumber = chunk_clone(lastcrl->get_serial(lastcrl));
+ crl_serial = baseCrlNumber;
DESTROY_IF((certificate_t*)lastcrl);
lastcrl = NULL;
}
@@ -350,22 +348,31 @@ static int sign_crl()
error = "loading lastUpdate CRL failed";
goto error;
}
- memcpy(crl_serial, lastcrl->get_serial(lastcrl).ptr,
- min(lastcrl->get_serial(lastcrl).len, sizeof(crl_serial)));
+ crl_serial = lastcrl->get_serial(lastcrl);
lastenum = lastcrl->create_enumerator(lastcrl);
}
else
{
+ crl_serial = chunk_from_chars(0x00);
lastenum = enumerator_create_empty();
}
- chunk_increment(chunk_create(crl_serial, sizeof(crl_serial)));
+ /* remove superfluous leading zeros */
+ while (crl_serial.len > 1 && crl_serial.ptr[0] == 0x00 &&
+ (crl_serial.ptr[1] & 0x80) == 0x00)
+ {
+ crl_serial = chunk_skip_zero(crl_serial);
+ }
+ crl_serial = chunk_clone(crl_serial);
+
+ /* increment the serial number by one */
+ chunk_increment(crl_serial);
enumerator = enumerator_create_filter(list->create_enumerator(list),
(void*)filter, NULL, NULL);
crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca,
- BUILD_SERIAL, chunk_create(crl_serial, sizeof(crl_serial)),
+ BUILD_SERIAL, crl_serial,
BUILD_NOT_BEFORE_TIME, thisUpdate, BUILD_NOT_AFTER_TIME, nextUpdate,
BUILD_REVOKED_ENUMERATOR, enumerator,
BUILD_REVOKED_ENUMERATOR, lastenum, BUILD_DIGEST_ALG, digest,
@@ -374,6 +381,7 @@ static int sign_crl()
enumerator->destroy(enumerator);
lastenum->destroy(lastenum);
DESTROY_IF((certificate_t*)lastcrl);
+ free(crl_serial.ptr);
if (!crl)
{
diff --git a/src/pluto/ac.c b/src/pluto/ac.c
index 3339d91fb..cd8007aea 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -261,7 +261,7 @@ void ac_list_certs(bool utc)
whack_log(RC_COMMENT, " hissuer: \"%Y\"", holderIssuer);
}
- holderSerial = ac->get_holderSerial(ac);
+ holderSerial = chunk_skip_zero(ac->get_holderSerial(ac));
if (holderSerial.ptr)
{
whack_log(RC_COMMENT, " hserial: %#B", &holderSerial);
@@ -277,7 +277,7 @@ void ac_list_certs(bool utc)
issuer = cert->get_issuer(cert);
whack_log(RC_COMMENT, " issuer: \"%Y\"", issuer);
- serial = ac->get_serial(ac);
+ serial = chunk_skip_zero(ac->get_serial(ac));
whack_log(RC_COMMENT, " serial: %#B", &serial);
cert->get_validity(cert, &now, &notBefore, &notAfter);
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index 38db0f2fd..c49b09e19 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -507,7 +507,7 @@ void list_crls(bool utc, bool strict)
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " issuer: \"%Y\"",
cert_crl->get_issuer(cert_crl));
- serial = crl->get_serial(crl);
+ serial = chunk_skip_zero(crl->get_serial(crl));
if (serial.ptr)
{
whack_log(RC_COMMENT, " serial: %#B", &serial);
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index fb61bef5c..5fcbdfa40 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -1435,6 +1435,7 @@ void remove_x509_public_key(const cert_t *cert)
void list_public_keys(bool utc)
{
pubkey_list_t *p = pubkeys;
+ chunk_t serial;
if (p != NULL)
{
@@ -1465,7 +1466,8 @@ void list_public_keys(bool utc)
}
if (key->serial.len)
{
- whack_log(RC_COMMENT," serial: %#B", &key->serial);
+ serial = chunk_skip_zero(key->serial);
+ whack_log(RC_COMMENT," serial: %#B", &serial);
}
p = p->next;
}
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c
index d89bfdf01..c299e3d39 100644
--- a/src/pluto/ocsp.c
+++ b/src/pluto/ocsp.c
@@ -607,23 +607,23 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests,
}
while (certinfo)
{
+ chunk_t serial = chunk_skip_zero(certinfo->serialNumber);
+
if (requests)
{
whack_log(RC_COMMENT, " serial: %#B, %d trials",
- &certinfo->serialNumber, certinfo->trials);
+ &serial, certinfo->trials);
}
else if (certinfo->once)
{
whack_log(RC_COMMENT, " serial: %#B, %s, once%s",
- &certinfo->serialNumber,
- cert_status_names[certinfo->status],
+ &serial, cert_status_names[certinfo->status],
(certinfo->nextUpdate < time(NULL))? " (expired)": "");
}
else
{
whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s",
- &certinfo->serialNumber,
- cert_status_names[certinfo->status],
+ &serial, cert_status_names[certinfo->status],
&certinfo->nextUpdate, utc,
check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict));
}
diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.c b/src/pluto/plugins/xauth/xauth_default_verifier.c
index 776f77134..ca2e36aa0 100644
--- a/src/pluto/plugins/xauth/xauth_default_verifier.c
+++ b/src/pluto/plugins/xauth/xauth_default_verifier.c
@@ -43,6 +43,13 @@ METHOD(xauth_verifier_t, verify_secret, bool,
if (get_xauth_secret(user, server, &xauth_secret))
{
success = chunk_equals(secret, xauth_secret);
+
+ if (!success && secret.len && secret.ptr[secret.len - 1] == 0)
+ { /* fix for null-terminated passwords (e.g. from Android 4) */
+ secret.len--;
+ success = chunk_equals(secret, xauth_secret);
+ }
+
chunk_clear(&xauth_secret);
}
return success;
diff --git a/src/pluto/timer.c b/src/pluto/timer.c
index c1ad55f5e..1d34d2c54 100644
--- a/src/pluto/timer.c
+++ b/src/pluto/timer.c
@@ -46,18 +46,7 @@
*/
time_t now(void)
{
- static time_t delta = 0
- , last_time = 0;
- time_t n = time(NULL);
-
- passert(n != (time_t)-1);
- if (last_time > n)
- {
- plog("time moved backwards %ld seconds", (long)(last_time - n));
- delta += last_time - n;
- }
- last_time = n;
- return n + delta;
+ return time_monotonic(NULL);
}
/* This file has the event handling routines. Events are
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index 7e2aca862..f017e5775 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -410,7 +410,7 @@ void list_x509cert_chain(const char *caption, cert_t* cert,
certificate->get_subject(certificate));
whack_log(RC_COMMENT, " issuer: \"%Y\"",
certificate->get_issuer(certificate));
- serial = x509->get_serial(x509);
+ serial = chunk_skip_zero(x509->get_serial(x509));
whack_log(RC_COMMENT, " serial: %#B", &serial);
/* list validity */
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index c527ae0b4..2b6f55bc8 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -162,6 +162,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
msg_end->auth2 = push_string(msg, conn_end->auth2);
msg_end->id = push_string(msg, conn_end->id);
msg_end->id2 = push_string(msg, conn_end->id2);
+ msg_end->rsakey = push_string(msg, conn_end->rsakey);
msg_end->cert = push_string(msg, conn_end->cert);
msg_end->cert2 = push_string(msg, conn_end->cert2);
msg_end->cert_policy = push_string(msg, conn_end->cert_policy);
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 6aadd3ec9..5dc7f0436 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -1,5 +1,5 @@
/* Stroke for charon is the counterpart to whack from pluto
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2012 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -89,9 +89,11 @@ static int send_stroke_msg (stroke_msg_t *msg)
{
buffer[byte_count] = '\0';
- /* we prompt if we receive the "Passphrase:"/"PIN:" magic keyword */
+ /* we prompt if we receive a magic keyword */
if ((byte_count >= 12 &&
strcmp(buffer + byte_count - 12, "Passphrase:\n") == 0) ||
+ (byte_count >= 10 &&
+ strcmp(buffer + byte_count - 10, "Password:\n") == 0) ||
(byte_count >= 5 &&
strcmp(buffer + byte_count - 5, "PIN:\n") == 0))
{
@@ -349,6 +351,19 @@ static int memusage()
return send_stroke_msg(&msg);
}
+static int user_credentials(char *name, char *user, char *pass)
+{
+ stroke_msg_t msg;
+
+ msg.type = STR_USER_CREDS;
+ msg.length = offsetof(stroke_msg_t, buffer);
+ msg.user_creds.name = push_string(&msg, name);
+ msg.user_creds.username = push_string(&msg, user);
+ msg.user_creds.password = push_string(&msg, pass);
+ return send_stroke_msg(&msg);
+}
+
+
static int set_loglevel(char *type, u_int level)
{
stroke_msg_t msg;
@@ -424,6 +439,11 @@ static void exit_usage(char *error)
printf(" stroke memusage\n");
printf(" Show leases of a pool:\n");
printf(" stroke leases [POOL [ADDRESS]]\n");
+ printf(" Set username and password for a connection:\n");
+ printf(" stroke user-creds NAME USERNAME [PASSWORD]\n");
+ printf(" where: NAME is a connection name added with \"stroke add\"\n");
+ printf(" USERNAME is the username\n");
+ printf(" PASSWORD is the optional password, you'll be asked to enter it if not given\n");
exit_error(error);
}
@@ -564,6 +584,14 @@ int main(int argc, char *argv[])
case STROKE_MEMUSAGE:
res = memusage();
break;
+ case STROKE_USER_CREDS:
+ if (argc < 4)
+ {
+ exit_usage("\"user-creds\" needs a connection name, "
+ "username and optionally a password");
+ }
+ res = user_credentials(argv[2], argv[3], argc > 4 ? argv[4] : NULL);
+ break;
default:
exit_usage(NULL);
}
diff --git a/src/stroke/stroke_keywords.h b/src/stroke/stroke_keywords.h
index 3bd68bdc3..554d071f3 100644
--- a/src/stroke/stroke_keywords.h
+++ b/src/stroke/stroke_keywords.h
@@ -57,6 +57,7 @@ typedef enum {
STROKE_EXPORT_X509,
STROKE_LEASES,
STROKE_MEMUSAGE,
+ STROKE_USER_CREDS,
} stroke_keyword_t;
#define STROKE_LIST_FIRST STROKE_LIST_PUBKEYS
diff --git a/src/stroke/stroke_keywords.txt b/src/stroke/stroke_keywords.txt
index 4a4cc57a9..1d7ab8a45 100644
--- a/src/stroke/stroke_keywords.txt
+++ b/src/stroke/stroke_keywords.txt
@@ -64,3 +64,4 @@ purgeike, STROKE_PURGE_IKE
exportx509, STROKE_EXPORT_X509
leases, STROKE_LEASES
memusage, STROKE_MEMUSAGE
+user-creds, STROKE_USER_CREDS
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index be12cabbe..22d4f11a3 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -146,6 +146,7 @@ struct stroke_end_t {
char *id;
char *id2;
char *eap_id;
+ char *rsakey;
char *cert;
char *cert2;
char *ca;
@@ -218,6 +219,8 @@ struct stroke_msg_t {
STR_EXPORT,
/* print memory usage details */
STR_MEMUSAGE,
+ /* set username and password for a connection */
+ STR_USER_CREDS,
/* more to come */
} type;
@@ -338,6 +341,13 @@ struct stroke_msg_t {
char *pool;
char *address;
} leases;
+
+ /* data for STR_USER_CREDS */
+ struct {
+ char *name;
+ char *username;
+ char *password;
+ } user_creds;
};
char buffer[STROKE_BUF_LEN];
};
diff --git a/testing/scripts/build-umlrootfs b/testing/scripts/build-umlrootfs
index 37d1de66b..4c066001c 100755
--- a/testing/scripts/build-umlrootfs
+++ b/testing/scripts/build-umlrootfs
@@ -342,6 +342,11 @@ then
echo -n " --enable-gcm" >> $INSTALLSHELL
fi
+if [ "$USE_CMAC" = "yes" ]
+then
+ echo -n " --enable-cmac" >> $INSTALLSHELL
+fi
+
if [ "$USE_HA" = "yes" ]
then
echo -n " --enable-ha" >> $INSTALLSHELL
diff --git a/testing/testing.conf b/testing/testing.conf
index 88aa8e15a..80cee18ac 100755
--- a/testing/testing.conf
+++ b/testing/testing.conf
@@ -19,19 +19,19 @@ UMLTESTDIR=~/strongswan-testing
# Bzipped kernel sources
# (file extension .tar.bz2 required)
-KERNEL=$UMLTESTDIR/linux-3.1.5.tar.bz2
+KERNEL=$UMLTESTDIR/linux-3.3.2.tar.bz2
# Extract kernel version
KERNELVERSION=`basename $KERNEL .tar.bz2 | sed -e 's/linux-//'`
# Kernel configuration file
-KERNELCONFIG=$UMLTESTDIR/.config-3.1
+KERNELCONFIG=$UMLTESTDIR/.config-3.3
# Bzipped uml patch for kernel
UMLPATCH=$UMLTESTDIR/ha-3.0.patch.bz2
# Bzipped source of strongSwan
-STRONGSWAN=$UMLTESTDIR/strongswan-4.6.2.tar.bz2
+STRONGSWAN=$UMLTESTDIR/strongswan-4.6.3.tar.bz2
# strongSwan compile options (use "yes" or "no")
USE_LIBCURL="yes"
@@ -76,6 +76,7 @@ USE_ADDRBLOCK="yes"
USE_CTR="yes"
USE_CCM="yes"
USE_GCM="yes"
+USE_CMAC="yes"
USE_HA="yes"
USE_AF_ALG="yes"
USE_WHITELIST="yes"
diff --git a/testing/tests/ikev2/net2net-pubkey/description.txt b/testing/tests/ikev2/net2net-pubkey/description.txt
new file mode 100644
index 000000000..1cb90f13f
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/description.txt
@@ -0,0 +1,7 @@
+A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
+The authentication is based on <b>raw RSA keys</b> loaded in PKCS#1 format.
+<p/>
+Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b>
+automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
+pings client <b>bob</b> located behind gateway <b>sun</b>.
diff --git a/testing/tests/ikev2/net2net-pubkey/evaltest.dat b/testing/tests/ikev2/net2net-pubkey/evaltest.dat
new file mode 100644
index 000000000..0ccfb7efd
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/evaltest.dat
@@ -0,0 +1,7 @@
+moon::ipsec status::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
+sun::ipsec status::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
+moon::ipsec status::INSTALLED, TUNNEL::YES
+sun::ipsec status::INSTALLED, TUNNEL::YES
+alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_seq=1::YES
+sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
+sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf
new file mode 100755
index 000000000..945cf3a40
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,25 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn net-net
+ left=PH_IP_MOON
+ leftsubnet=10.1.0.0/16
+ leftid=@moon.strongswan.org
+ leftrsasigkey=moonPub.der
+ leftauth=pubkey
+ leftfirewall=yes
+ right=PH_IP_SUN
+ rightsubnet=10.2.0.0/16
+ rightid=@sun.strongswan.org
+ rightrsasigkey=sunPub.der
+ rightauth=pubkey
+ auto=add
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/moonPub.der b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/moonPub.der
new file mode 100644
index 000000000..55bd362a5
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/moonPub.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/sunPub.der b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/sunPub.der
new file mode 100644
index 000000000..8d0c644f1
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/sunPub.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/private/moonKey.der b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/private/moonKey.der
new file mode 100644
index 000000000..49e0111f2
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/private/moonKey.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.secrets b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 000000000..b9ec17dbc
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA moonKey.der
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/strongswan.conf
new file mode 100644
index 000000000..0581bae5c
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = sha1 sha2 md5 aes des hmac gmp pem pkcs1 pubkey random curl kernel-netlink socket-default stroke updown
+}
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf
new file mode 100755
index 000000000..5c07de8a2
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn net-net
+ left=PH_IP_SUN
+ leftsubnet=10.2.0.0/16
+ leftid=@sun.strongswan.org
+ leftrsasigkey=sunPub.der
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightsubnet=10.1.0.0/16
+ rightid=@moon.strongswan.org
+ rightrsasigkey=moonPub.der
+ auto=add
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/moonPub.der b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/moonPub.der
new file mode 100644
index 000000000..55bd362a5
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/moonPub.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/sunPub.der b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/sunPub.der
new file mode 100644
index 000000000..8d0c644f1
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/sunPub.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/private/sunKey.der b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/private/sunKey.der
new file mode 100644
index 000000000..7c284f939
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/private/sunKey.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.secrets b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.secrets
new file mode 100644
index 000000000..6aa9ed562
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA sunKey.der
diff --git a/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/strongswan.conf
new file mode 100644
index 000000000..0581bae5c
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = sha1 sha2 md5 aes des hmac gmp pem pkcs1 pubkey random curl kernel-netlink socket-default stroke updown
+}
diff --git a/testing/tests/ikev2/net2net-pubkey/posttest.dat b/testing/tests/ikev2/net2net-pubkey/posttest.dat
new file mode 100644
index 000000000..65b18b7ca
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/posttest.dat
@@ -0,0 +1,8 @@
+moon::ipsec stop
+sun::ipsec stop
+moon::/etc/init.d/iptables stop 2> /dev/null
+sun::/etc/init.d/iptables stop 2> /dev/null
+moon::rm /etc/ipsec.d/private/moonKey.der
+sun::rm /etc/ipsec.d/private/sunKey.der
+moon::rm /etc/ipsec.d/certs/*.der
+sun::rm /etc/ipsec.d/certs/*.der
diff --git a/testing/tests/ikev2/net2net-pubkey/pretest.dat b/testing/tests/ikev2/net2net-pubkey/pretest.dat
new file mode 100644
index 000000000..9e40684ab
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/pretest.dat
@@ -0,0 +1,8 @@
+moon::/etc/init.d/iptables start 2> /dev/null
+sun::/etc/init.d/iptables start 2> /dev/null
+moon::rm /etc/ipsec.d/cacerts/*
+sun::rm /etc/ipsec.d/cacerts/*
+moon::ipsec start
+sun::ipsec start
+moon::sleep 2
+moon::ipsec up net-net
diff --git a/testing/tests/ikev2/net2net-pubkey/test.conf b/testing/tests/ikev2/net2net-pubkey/test.conf
new file mode 100644
index 000000000..f74d0f7d6
--- /dev/null
+++ b/testing/tests/ikev2/net2net-pubkey/test.conf
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# UML instances used for this test
+
+# All UML instances that are required for this test
+#
+UMLHOSTS="alice moon winnetou sun bob"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-w-s-b.png"
+
+# UML instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="sun"
+
+# UML instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon sun"
diff --git a/testing/tests/ikev2/net2net-rsa/description.txt b/testing/tests/ikev2/net2net-rsa/description.txt
new file mode 100644
index 000000000..a9310d475
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/description.txt
@@ -0,0 +1,7 @@
+A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
+The authentication is based on <b>raw RSA keys</b> in Base64-encoded RFC 3110 DNSKEY format.
+<p/>
+Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b>
+automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
+pings client <b>bob</b> located behind gateway <b>sun</b>.
diff --git a/testing/tests/ikev2/net2net-rsa/evaltest.dat b/testing/tests/ikev2/net2net-rsa/evaltest.dat
new file mode 100644
index 000000000..0ccfb7efd
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/evaltest.dat
@@ -0,0 +1,7 @@
+moon::ipsec status::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
+sun::ipsec status::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
+moon::ipsec status::INSTALLED, TUNNEL::YES
+sun::ipsec status::INSTALLED, TUNNEL::YES
+alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_seq=1::YES
+sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
+sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf
new file mode 100755
index 000000000..61b9b710a
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,25 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn net-net
+ left=PH_IP_MOON
+ leftsubnet=10.1.0.0/16
+ leftid=@moon.strongswan.org
+ leftrsasigkey=0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj
+ leftauth=pubkey
+ leftfirewall=yes
+ right=PH_IP_SUN
+ rightsubnet=10.2.0.0/16
+ rightid=@sun.strongswan.org
+ rightrsasigkey=0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT
+ rightauth=pubkey
+ auto=add
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.d/private/moonKey.der b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.d/private/moonKey.der
new file mode 100644
index 000000000..49e0111f2
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.d/private/moonKey.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.secrets b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 000000000..b9ec17dbc
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA moonKey.der
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/strongswan.conf
new file mode 100644
index 000000000..3bc16ccda
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey random curl kernel-netlink socket-default stroke updown
+}
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf
new file mode 100755
index 000000000..24e20dc25
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn net-net
+ left=PH_IP_SUN
+ leftsubnet=10.2.0.0/16
+ leftid=@sun.strongswan.org
+ leftrsasigkey=0sAQOiSuR9e/WMZFOxK3IdaFBOT2DGoObFDJURejqLcjMpmY2yVbA9Lpc+AEGKxqjb37WG6sVo3fBCDBOAhgmMw9s0b6DTSeXaIQloqW1M8IC+xe1fT+F0BsW1ttaEN0WTF5H+J+a4/arYg4HyiA+sjoqHagnCVPM15Rm5mkmg913XmSCgtkenD4WUq+NfPLuOcggqTjHAAoGD0doswRa3sebyqHQNAb32PXW9ecKi9ExcPrdr5hR5uNXRMYGumBtoxcE6xEvCM/sPRK1hbyynixc5nfMQ5Ymb4mdCUotUGaCyKDa4pF58sYgP6xpd/HXMXGdRP+KxqA4sfes46gp8UuJT
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightsubnet=10.1.0.0/16
+ rightid=@moon.strongswan.org
+ rightrsasigkey=0sAQN+mkeECF5Bm7XnDkkkfmgny/TZndTkN1XzFZWB7nJroM3cTk3zMtdSPX8hY9GQxVGWSsmUBq7mGA5Qx39JpRNpyzxW7wRcMbwqDquG1PRfblLzV1ixdXOGSLUNaXonqDI/h5fCkqTuZtLbE4q3Pf4PmQAwzWVWaTZQ1gXXqUqKlN6218Hm2vbvNRE/CBHuFMmaCz11jckvaPvcqBLZzRTx9b/Mi+qD6xT7k9RpYHmtaGCJ95ed1bY6SZkapgHWu88/3M6bxCzD0KOA3oFbwlkHkFyaGWFB2+fc7L6BfYq0wr/d84tQdOxEn3BwLTrVKo7+6AxDrMi0I+blD2nd9cxj
+ auto=add
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.d/private/sunKey.der b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.d/private/sunKey.der
new file mode 100644
index 000000000..7c284f939
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.d/private/sunKey.der
Binary files differ
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.secrets b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.secrets
new file mode 100644
index 000000000..6aa9ed562
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA sunKey.der
diff --git a/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/strongswan.conf
new file mode 100644
index 000000000..3bc16ccda
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey random curl kernel-netlink socket-default stroke updown
+}
diff --git a/testing/tests/ikev2/net2net-rsa/posttest.dat b/testing/tests/ikev2/net2net-rsa/posttest.dat
new file mode 100644
index 000000000..a199946aa
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/posttest.dat
@@ -0,0 +1,6 @@
+moon::ipsec stop
+sun::ipsec stop
+moon::/etc/init.d/iptables stop 2> /dev/null
+sun::/etc/init.d/iptables stop 2> /dev/null
+moon::rm /etc/ipsec.d/private/moonKey.der
+sun::rm /etc/ipsec.d/private/sunKey.der
diff --git a/testing/tests/ikev2/net2net-rsa/pretest.dat b/testing/tests/ikev2/net2net-rsa/pretest.dat
new file mode 100644
index 000000000..9e40684ab
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/pretest.dat
@@ -0,0 +1,8 @@
+moon::/etc/init.d/iptables start 2> /dev/null
+sun::/etc/init.d/iptables start 2> /dev/null
+moon::rm /etc/ipsec.d/cacerts/*
+sun::rm /etc/ipsec.d/cacerts/*
+moon::ipsec start
+sun::ipsec start
+moon::sleep 2
+moon::ipsec up net-net
diff --git a/testing/tests/ikev2/net2net-rsa/test.conf b/testing/tests/ikev2/net2net-rsa/test.conf
new file mode 100644
index 000000000..f74d0f7d6
--- /dev/null
+++ b/testing/tests/ikev2/net2net-rsa/test.conf
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# UML instances used for this test
+
+# All UML instances that are required for this test
+#
+UMLHOSTS="alice moon winnetou sun bob"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-w-s-b.png"
+
+# UML instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="sun"
+
+# UML instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon sun"
diff --git a/testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf
index bbb5a76fd..e070f9a27 100644
--- a/testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {
diff --git a/testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf b/testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf
index bbb5a76fd..e070f9a27 100644
--- a/testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {
diff --git a/testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf
index bbb5a76fd..e070f9a27 100644
--- a/testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/description.txt b/testing/tests/ikev2/rw-eap-md5-id-prompt/description.txt
new file mode 100644
index 000000000..b1590090e
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/description.txt
@@ -0,0 +1,9 @@
+The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>.
+<b>carol</b> uses the <i>Extensible Authentication Protocol</i>
+in association with an <i>MD5</i> challenge and response protocol
+(<b>EAP-MD5</b>) to authenticate against the gateway. The EAP identity and password
+of the user is kept in <b>ipsec.secrets</b> on the gateway <b>moon</b> and
+is entered interactively on the client <b>carol</b> using the command
+<b>ipsec stroke user-creds home carol "Ar3etTnp"</b>.
+Gateway <b>moon</b> additionally uses an <b>RSA signature</b> to authenticate itself
+against <b>carol</b>.
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/evaltest.dat b/testing/tests/ikev2/rw-eap-md5-id-prompt/evaltest.dat
new file mode 100644
index 000000000..3f828141c
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/evaltest.dat
@@ -0,0 +1,13 @@
+carol::cat /var/log/daemon.log::configured EAP-Identity carol::YES
+carol::cat /var/log/daemon.log::added EAP secret for carol moon.strongswan.org::YES
+carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature successful::YES
+carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
+moon::cat /var/log/daemon.log::authentication of '192.168.0.100' with EAP successful::YES
+moon::cat /var/log/daemon.log::received EAP identity.*carol::YES
+moon::ipsec statusall::rw-eap.*ESTABLISHED::YES
+carol::ipsec statusall::home.*ESTABLISHED::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_seq=1::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+
+
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.conf
new file mode 100755
index 000000000..7859ee9cc
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,21 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn home
+ left=PH_IP_CAROL
+ leftauth=eap
+ leftfirewall=yes
+ right=PH_IP_MOON
+ rightid=@moon.strongswan.org
+ rightsubnet=10.1.0.0/16
+ rightauth=pubkey
+ auto=add
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.secrets b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.secrets
new file mode 100644
index 000000000..ddd495699
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/ipsec.secrets
@@ -0,0 +1 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/strongswan.conf
new file mode 100644
index 000000000..fe067d344
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc stroke kernel-netlink socket-default fips-prf eap-md5 eap-identity updown
+}
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.conf
new file mode 100755
index 000000000..c132b9ab8
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,25 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+ strictcrlpolicy=no
+ plutostart=no
+
+conn %default
+ ikelifetime=60m
+ keylife=20m
+ rekeymargin=3m
+ keyingtries=1
+ keyexchange=ikev2
+
+conn rw-eap
+ left=PH_IP_MOON
+ leftsubnet=10.1.0.0/16
+ leftid=@moon.strongswan.org
+ leftcert=moonCert.pem
+ leftauth=pubkey
+ leftfirewall=yes
+ rightauth=eap-md5
+ rightsendcert=never
+ right=%any
+ eap_identity=%any
+ auto=add
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.secrets b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 000000000..e11a2204c
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,5 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA moonKey.pem
+
+carol : EAP "Ar3etTnp"
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/strongswan.conf
new file mode 100644
index 000000000..fe067d344
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+ load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc stroke kernel-netlink socket-default fips-prf eap-md5 eap-identity updown
+}
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/posttest.dat b/testing/tests/ikev2/rw-eap-md5-id-prompt/posttest.dat
new file mode 100644
index 000000000..94a400606
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/posttest.dat
@@ -0,0 +1,4 @@
+moon::ipsec stop
+carol::ipsec stop
+moon::/etc/init.d/iptables stop 2> /dev/null
+carol::/etc/init.d/iptables stop 2> /dev/null
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/pretest.dat b/testing/tests/ikev2/rw-eap-md5-id-prompt/pretest.dat
new file mode 100644
index 000000000..9c301f484
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/pretest.dat
@@ -0,0 +1,8 @@
+moon::/etc/init.d/iptables start 2> /dev/null
+carol::/etc/init.d/iptables start 2> /dev/null
+moon::ipsec start
+carol::ipsec start
+carol::sleep 1
+carol::ipsec stroke user-creds home carol "Ar3etTnp"
+carol::ipsec up home
+carol::sleep 1
diff --git a/testing/tests/ikev2/rw-eap-md5-id-prompt/test.conf b/testing/tests/ikev2/rw-eap-md5-id-prompt/test.conf
new file mode 100644
index 000000000..2bd21499b
--- /dev/null
+++ b/testing/tests/ikev2/rw-eap-md5-id-prompt/test.conf
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# UML instances used for this test
+
+# All UML instances that are required for this test
+#
+UMLHOSTS="alice carol moon"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c.png"
+
+# UML instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# UML instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol"
diff --git a/testing/tests/openssl-ikev2/rw-cert/hosts/carol/etc/strongswan.conf b/testing/tests/openssl-ikev2/rw-cert/hosts/carol/etc/strongswan.conf
index c78da2c08..2b862e1b3 100644
--- a/testing/tests/openssl-ikev2/rw-cert/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/openssl-ikev2/rw-cert/hosts/carol/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors pem pkcs1 openssl revocation random hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors pem pkcs1 openssl revocation random hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {
diff --git a/testing/tests/openssl-ikev2/rw-cert/hosts/dave/etc/strongswan.conf b/testing/tests/openssl-ikev2/rw-cert/hosts/dave/etc/strongswan.conf
index e483eba9d..4e74127fe 100644
--- a/testing/tests/openssl-ikev2/rw-cert/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/openssl-ikev2/rw-cert/hosts/dave/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random x509 revocation hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {
diff --git a/testing/tests/openssl-ikev2/rw-cert/hosts/moon/etc/strongswan.conf b/testing/tests/openssl-ikev2/rw-cert/hosts/moon/etc/strongswan.conf
index 848adaf6a..48b7d16f2 100644
--- a/testing/tests/openssl-ikev2/rw-cert/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/openssl-ikev2/rw-cert/hosts/moon/etc/strongswan.conf
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
- load = curl test-vectors pem pkcs1 openssl revocation random hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+ load = curl test-vectors pem pkcs1 openssl revocation random hmac xcbc cmac ctr ccm gcm stroke kernel-netlink socket-default updown
}
libstrongswan {