diff options
137 files changed, 2658 insertions, 384 deletions
@@ -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, ¬Before, ¬After); + if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME) + { + fprintf(out, " validity: not before %T, ", ¬Before, utc); + if (now < notBefore) + { + fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); + } + else + { + fprintf(out, "ok\n"); + } + fprintf(out, " not after %T, ", ¬After, utc); + if (now > notAfter) + { + fprintf(out, "expired (%V ago)\n", &now, ¬After); + } + else + { + fprintf(out, "ok"); + if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) + { + fprintf(out, " (expires in %V)", &now, ¬After); + } + 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, ¬Before, ¬After); 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 Binary files differnew file mode 100644 index 000000000..55bd362a5 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/moonPub.der 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 Binary files differnew file mode 100644 index 000000000..8d0c644f1 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/certs/sunPub.der 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 Binary files differnew file mode 100644 index 000000000..49e0111f2 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/moon/etc/ipsec.d/private/moonKey.der 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 Binary files differnew file mode 100644 index 000000000..55bd362a5 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/moonPub.der 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 Binary files differnew file mode 100644 index 000000000..8d0c644f1 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/certs/sunPub.der 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 Binary files differnew file mode 100644 index 000000000..7c284f939 --- /dev/null +++ b/testing/tests/ikev2/net2net-pubkey/hosts/sun/etc/ipsec.d/private/sunKey.der 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 Binary files differnew file mode 100644 index 000000000..49e0111f2 --- /dev/null +++ b/testing/tests/ikev2/net2net-rsa/hosts/moon/etc/ipsec.d/private/moonKey.der 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 Binary files differnew file mode 100644 index 000000000..7c284f939 --- /dev/null +++ b/testing/tests/ikev2/net2net-rsa/hosts/sun/etc/ipsec.d/private/sunKey.der 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 { |