aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/config/proposal.c5
-rw-r--r--src/libcharon/daemon.c6
-rw-r--r--src/libcharon/encoding/generator.c2
-rw-r--r--src/libcharon/encoding/parser.c2
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c3
-rwxr-xr-xsrc/libcharon/encoding/payloads/notify_payload.c18
-rwxr-xr-xsrc/libcharon/encoding/payloads/notify_payload.h5
-rw-r--r--src/libcharon/encoding/payloads/payload.c19
-rw-r--r--src/libcharon/encoding/payloads/payload.h5
-rw-r--r--src/libcharon/network/receiver.c48
-rw-r--r--src/libcharon/network/sender.c10
-rw-r--r--src/libcharon/network/sender.h7
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_dae.c2
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c21
-rw-r--r--src/libcharon/plugins/nm/nm_service.h2
-rw-r--r--src/libcharon/plugins/radattr/radattr_listener.h2
-rw-r--r--src/libcharon/plugins/smp/smp.c14
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c185
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h10
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c82
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.h24
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c50
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c24
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c65
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.h2
-rw-r--r--src/libcharon/sa/authenticator.c7
-rw-r--r--src/libcharon/sa/authenticator.h5
-rw-r--r--src/libcharon/sa/ike_sa.c2
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c17
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c11
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c24
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c9
-rw-r--r--src/libcharon/sa/keymat.h7
34 files changed, 575 insertions, 122 deletions
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 2251b82dd..d3c60a469 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -598,6 +598,9 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
case AUTH_CAMELLIA_XCBC_96:
prf = PRF_CAMELLIA128_XCBC;
break;
+ case AUTH_AES_CMAC_96:
+ prf = PRF_AES128_CMAC;
+ break;
default:
prf = PRF_UNDEFINED;
}
@@ -794,6 +797,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
case AUTH_HMAC_SHA2_512_256:
case AUTH_HMAC_MD5_96:
case AUTH_AES_XCBC_96:
+ case AUTH_AES_CMAC_96:
add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
break;
default:
@@ -813,6 +817,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
case PRF_HMAC_SHA2_512:
case PRF_HMAC_MD5:
case PRF_AES128_XCBC:
+ case PRF_AES128_CMAC:
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
break;
default:
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 575627206..ee2db3318 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -109,8 +109,11 @@ static void destroy(private_daemon_t *this)
{
this->public.traps->flush(this->public.traps);
}
+ if (this->public.sender)
+ {
+ this->public.sender->flush(this->public.sender);
+ }
DESTROY_IF(this->public.receiver);
- DESTROY_IF(this->public.sender);
#ifdef ME
DESTROY_IF(this->public.connect_manager);
DESTROY_IF(this->public.mediation_manager);
@@ -130,6 +133,7 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.eap);
DESTROY_IF(this->public.xauth);
DESTROY_IF(this->public.backends);
+ DESTROY_IF(this->public.sender);
DESTROY_IF(this->public.socket);
/* rehook library logging, shutdown logging */
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
index bf4480193..4d65bce84 100644
--- a/src/libcharon/encoding/generator.c
+++ b/src/libcharon/encoding/generator.c
@@ -566,7 +566,7 @@ METHOD(generator_t, generate_payload, void,
payload_type_names, payload_type);
DBG3(DBG_ENC, "generated data for this payload %b",
this->buffer + offset_start,
- this->out_position - this->buffer - offset_start);
+ (u_int)(this->out_position - this->buffer - offset_start));
}
}
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index a599de60f..e4b140c3e 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -376,7 +376,7 @@ METHOD(parser_t, parse_payload, status_t,
payload_type_names, payload_type, this->input_roof - this->byte_pos);
DBG3(DBG_ENC, "parsing payload from %b",
- this->byte_pos, this->input_roof - this->byte_pos);
+ this->byte_pos, (u_int)(this->input_roof - this->byte_pos));
/* base pointer for output, avoids casting in every rule */
output = pld;
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index 26d1f0a43..df5e73b5b 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -114,8 +114,7 @@ METHOD(payload_t, verify, status_t,
if (this->type == CERTIFICATE_REQUEST &&
this->encoding == ENC_X509_SIGNATURE)
{
- if (this->data.len < HASH_SIZE_SHA1 ||
- this->data.len % HASH_SIZE_SHA1)
+ if (this->data.len % HASH_SIZE_SHA1)
{
DBG1(DBG_ENC, "invalid X509 hash length (%d) in certreq",
this->data.len);
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index 411534491..d168e1c12 100755
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_
"ME_CONNECT_FAILED");
ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_NOTIFY_STATUS");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
"INITIAL_CONTACT",
"SET_WINDOW_SIZE",
"ADDITIONAL_TS_POSSIBLE",
@@ -105,8 +105,11 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTI
"IKEV2_MESSAGE_ID_SYNC_SUPPORTED",
"IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
"IKEV2_MESSAGE_ID_SYNC",
- "IPSEC_REPLAY_COUNTER_SYNC");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
+ "IPSEC_REPLAY_COUNTER_SYNC",
+ "SECURE PASSWORD_METHOD",
+ "PSK_PERSIST",
+ "PSK_CONFIRM");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
@@ -167,7 +170,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S
"ME_CONN_FAIL");
ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_STATUS");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
"INIT_CONTACT",
"SET_WINSIZE",
"ADD_TS_POSS",
@@ -207,8 +210,11 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, M
"MSG_ID_SYN_SUP",
"RPL_CTR_SYN_SUP",
"MSG_ID_SYN",
- "RPL_CTR_SYN");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
+ "RPL_CTR_SYN",
+ "SEC_PASSWD",
+ "PSK_PST",
+ "PSK_CFM");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index 07fbcb49b..beec1e233 100755
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -138,6 +138,11 @@ enum notify_type_t {
IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED = 16421,
IKEV2_MESSAGE_ID_SYNC = 16422,
IPSEC_REPLAY_COUNTER_SYNC = 16423,
+ /* Secure password methods, RFC 6467 */
+ SECURE_PASSWORD_METHOD = 16424,
+ /* PACE - draft-kuegler-ipsecme-pace-ikev2 */
+ PSK_PERSIST = 16425,
+ PSK_CONFIRM = 16426,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index 257d53858..dc158476b 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -58,7 +58,7 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYL
ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT_D_V1",
"NAT_OA_V1");
-ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
+ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SECURITY_ASSOCIATION",
"KEY_EXCHANGE",
"ID_INITIATOR",
@@ -74,9 +74,10 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
"TRAFFIC_SELECTOR_RESPONDER",
"ENCRYPTED",
"CONFIGURATION",
- "EXTENSIBLE_AUTHENTICATION");
+ "EXTENSIBLE_AUTHENTICATION",
+ "GENERIC_SECURE_PASSWORD_METHOD");
#ifdef ME
-ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
"ID_PEER");
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HEADER",
@@ -91,7 +92,7 @@ ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"CONFIGURATION_ATTRIBUTE_V1",
"ENCRYPTED_V1");
#else
-ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"PROPOSAL_SUBSTRUCTURE_V1",
@@ -127,7 +128,7 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, N
ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT-D",
"NAT-OA");
-ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SA",
"KE",
"IDi",
@@ -143,9 +144,11 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
"TSr",
"E",
"CP",
- "EAP");
+ "EAP",
+ "GSPM");
#ifdef ME
-ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER,
+ GENERIC_SECURE_PASSWORD_METHOD,
"IDp");
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HDR",
@@ -160,7 +163,7 @@ ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"CATTR",
"E");
#else
-ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HDR",
"PROP",
"PROP",
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index ed839fc07..d5e862601 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -207,6 +207,11 @@ enum payload_type_t {
*/
EXTENSIBLE_AUTHENTICATION = 48,
+ /**
+ * Generic Secure Password Method (GSPM).
+ */
+ GENERIC_SECURE_PASSWORD_METHOD = 49,
+
#ifdef ME
/**
* Identification payload for peers has a value from
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 599249fcb..fcc730439 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -30,6 +30,8 @@
/** lifetime of a cookie, in seconds */
#define COOKIE_LIFETIME 10
+/** time we wait before disabling cookies */
+#define COOKIE_CALMDOWN_DELAY 10
/** how many times to reuse the secret */
#define COOKIE_REUSE 10000
/** default value for private_receiver_t.cookie_threshold */
@@ -98,6 +100,11 @@ struct private_receiver_t {
u_int32_t cookie_threshold;
/**
+ * timestamp of last cookie requested
+ */
+ time_t last_cookie;
+
+ /**
* how many half open IKE_SAs per peer before blocking
*/
u_int32_t block_threshold;
@@ -262,24 +269,55 @@ static bool check_cookie(private_receiver_t *this, message_t *message)
}
/**
+ * Check if we currently require cookies
+ */
+static bool cookie_required(private_receiver_t *this,
+ u_int half_open, u_int32_t now)
+{
+ if (this->cookie_threshold && half_open >= this->cookie_threshold)
+ {
+ this->last_cookie = now;
+ return TRUE;
+ }
+ if (now < this->last_cookie + COOKIE_CALMDOWN_DELAY)
+ {
+ /* We don't disable cookies unless we haven't seen IKE_SA_INITs
+ * for COOKIE_CALMDOWN_DELAY seconds. This avoids jittering between
+ * cookie on / cookie off states, which is problematic. Consider the
+ * following: A legitimiate initiator sends a IKE_SA_INIT while we
+ * are under a DoS attack. If we toggle our cookie behavior,
+ * multiple retransmits of this IKE_SA_INIT might get answered with
+ * and without cookies. The initiator goes on and retries with
+ * a cookie, but it can't know if the completing IKE_SA_INIT response
+ * is to its IKE_SA_INIT request with or without cookies. This is
+ * problematic, as the cookie is part of AUTH payload data.
+ */
+ this->last_cookie = now;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Check if we should drop IKE_SA_INIT because of cookie/overload checking
*/
static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
{
u_int half_open;
+ u_int32_t now;
+ now = time_monotonic(NULL);
half_open = charon->ike_sa_manager->get_half_open_count(
charon->ike_sa_manager, NULL);
/* check for cookies in IKEv2 */
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
- this->cookie_threshold && half_open >= this->cookie_threshold &&
- !check_cookie(this, message))
+ cookie_required(this, half_open, now) && !check_cookie(this, message))
{
- u_int32_t now = time_monotonic(NULL);
- chunk_t cookie = cookie_build(this, message, now - this->secret_offset,
- chunk_from_thing(this->secret));
+ chunk_t cookie;
+ cookie = cookie_build(this, message, now - this->secret_offset,
+ chunk_from_thing(this->secret));
DBG2(DBG_NET, "received packet from: %#H to %#H",
message->get_source(message),
message->get_destination(message));
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index 4df930b15..6d5ad8f2a 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -149,7 +149,7 @@ static job_requeue_t send_packets(private_sender_t * this)
return JOB_REQUEUE_DIRECT;
}
-METHOD(sender_t, destroy, void,
+METHOD(sender_t, flush, void,
private_sender_t *this)
{
/* send all packets in the queue */
@@ -159,8 +159,13 @@ METHOD(sender_t, destroy, void,
this->sent->wait(this->sent, this->mutex);
}
this->mutex->unlock(this->mutex);
+}
+
+METHOD(sender_t, destroy, void,
+ private_sender_t *this)
+{
this->job->cancel(this->job);
- this->list->destroy(this->list);
+ this->list->destroy_offset(this->list, offsetof(packet_t, destroy));
this->got->destroy(this->got);
this->sent->destroy(this->sent);
this->mutex->destroy(this->mutex);
@@ -177,6 +182,7 @@ sender_t * sender_create()
INIT(this,
.public = {
.send = _send_,
+ .flush = _flush,
.destroy = _destroy,
},
.list = linked_list_create(),
diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h
index f77fadab2..6ee070435 100644
--- a/src/libcharon/network/sender.h
+++ b/src/libcharon/network/sender.h
@@ -44,6 +44,13 @@ struct sender_t {
void (*send) (sender_t *this, packet_t *packet);
/**
+ * Enforce a flush of the send queue.
+ *
+ * This function blocks until all queued packets have been sent.
+ */
+ void (*flush)(sender_t *this);
+
+ /**
* Destroys a sender object.
*/
void (*destroy) (sender_t *this);
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
index 5823142cc..e84fe5b9c 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_dae.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
@@ -435,7 +435,7 @@ static job_requeue_t receive(private_eap_radius_dae_t *this)
}
else
{
- DBG1(DBG_NET, "receving RADIUS DAE request failed: %s", strerror(errno));
+ DBG1(DBG_NET, "receiving RADIUS DAE request failed: %s", strerror(errno));
}
return JOB_REQUEUE_DIRECT;
}
diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
index 629792489..c3f0f24b3 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
+++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c
@@ -207,7 +207,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -223,7 +224,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -239,7 +241,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
- DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -255,14 +258,15 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS)
{
- DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
if (!decode_imsi_ef(pbRecvBuffer, dwRecvLength-APDU_STATUS_LEN, imsi))
{
DBG1(DBG_IKE, "Couldn't decode IMSI EF: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
@@ -288,7 +292,7 @@ METHOD(simaka_card_t, get_triplet, bool,
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA)
{
DBG1(DBG_IKE, "Run GSM Algorithm failed: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
@@ -305,7 +309,8 @@ METHOD(simaka_card_t, get_triplet, bool,
if (dwRecvLength < APDU_STATUS_LEN ||
pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS)
{
- DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, dwRecvLength);
+ DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer,
+ (u_int)dwRecvLength);
continue;
}
@@ -320,7 +325,7 @@ METHOD(simaka_card_t, get_triplet, bool,
else
{
DBG1(DBG_IKE, "Get Response incorrect length: %b",
- pbRecvBuffer, dwRecvLength);
+ pbRecvBuffer, (u_int)dwRecvLength);
continue;
}
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h
index b00000b6f..828d1a452 100644
--- a/src/libcharon/plugins/nm/nm_service.h
+++ b/src/libcharon/plugins/nm/nm_service.h
@@ -21,7 +21,7 @@
#ifndef NM_SERVICE_H_
#define NM_SERVICE_H_
-#include <glib/gtypes.h>
+#include <glib.h>
#include <glib-object.h>
#include <nm-vpn-plugin.h>
diff --git a/src/libcharon/plugins/radattr/radattr_listener.h b/src/libcharon/plugins/radattr/radattr_listener.h
index 9a14827fc..e61c441bf 100644
--- a/src/libcharon/plugins/radattr/radattr_listener.h
+++ b/src/libcharon/plugins/radattr/radattr_listener.h
@@ -15,7 +15,7 @@
/**
* @defgroup radattr_listener radattr_listener
- * @{ @ingroup
+ * @{ @ingroup radattr
*/
#ifndef RADATTR_LISTENER_H_
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index c2fe11f74..1b2adc952 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -456,17 +456,21 @@ static void request_control_initiate(xmlTextReaderPtr reader,
/* <log> */
xmlTextWriterStartElement(writer, "log");
- peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
+ peer = charon->backends->get_peer_cfg_by_name(charon->backends,
+ (char*)str);
if (peer)
{
enumerator = peer->create_child_cfg_enumerator(peer);
if (ike)
{
- if (!enumerator->enumerate(enumerator, &child))
+ if (enumerator->enumerate(enumerator, &child))
+ {
+ child->get_ref(child);
+ }
+ else
{
child = NULL;
}
- child->get_ref(child);
}
else
{
@@ -622,7 +626,7 @@ static job_requeue_t process(int *fdp)
int fd = *fdp;
bool oldstate;
char buffer[4096];
- size_t len;
+ ssize_t len;
xmlTextReaderPtr reader;
char *id = NULL, *type = NULL;
@@ -637,7 +641,7 @@ static job_requeue_t process(int *fdp)
DBG2(DBG_CFG, "SMP XML connection closed");
return JOB_REQUEUE_NONE;
}
- DBG3(DBG_CFG, "got XML request: %b", buffer, len);
+ DBG3(DBG_CFG, "got XML request: %b", buffer, (u_int)len);
reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
if (reader == NULL)
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index 74dba82cc..eee3814a8 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -235,7 +235,7 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
DBG1(DBG_NET, "receive buffer too small, packet discarded");
return NULL;
}
- DBG3(DBG_NET, "received packet %b", buffer, len);
+ DBG3(DBG_NET, "received packet %b", buffer, (u_int)len);
if (len < MARKER_LEN)
{
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 8ca1464fb..89e1e0a91 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -263,7 +264,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
{
identification_t *identity;
certificate_t *certificate;
- char *auth, *id, *cert, *ca;
+ char *auth, *id, *pubkey, *cert, *ca;
stroke_end_t *end, *other_end;
auth_cfg_t *cfg;
@@ -358,6 +359,18 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+ /* add raw RSA public key */
+ pubkey = end->rsakey;
+ if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
+ {
+ certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey,
+ identity);
+ if (certificate)
+ {
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ }
+ }
+
/* CA constraint */
if (ca)
{
@@ -931,6 +944,175 @@ METHOD(stroke_config_t, del, void,
}
}
+METHOD(stroke_config_t, set_user_credentials, void,
+ private_stroke_config_t *this, stroke_msg_t *msg, FILE *prompt)
+{
+ enumerator_t *enumerator, *children, *remote_auth;
+ peer_cfg_t *peer, *found = NULL;
+ auth_cfg_t *auth_cfg, *remote_cfg;
+ auth_class_t auth_class;
+ child_cfg_t *child;
+ identification_t *id, *identity, *gw = NULL;
+ shared_key_type_t type = SHARED_ANY;
+ chunk_t password = chunk_empty;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
+ { /* find the peer (or child) config with the given name */
+ if (streq(peer->get_name(peer), msg->user_creds.name))
+ {
+ found = peer;
+ }
+ else
+ {
+ children = peer->create_child_cfg_enumerator(peer);
+ while (children->enumerate(children, &child))
+ {
+ if (streq(child->get_name(child), msg->user_creds.name))
+ {
+ found = peer;
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, " no config named '%s'", msg->user_creds.name);
+ fprintf(prompt, "no config named '%s'\n", msg->user_creds.name);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+
+ id = identification_create_from_string(msg->user_creds.username);
+ if (strlen(msg->user_creds.username) == 0 ||
+ !id || id->get_type(id) == ID_ANY)
+ {
+ DBG1(DBG_CFG, " invalid username '%s'", msg->user_creds.username);
+ fprintf(prompt, "invalid username '%s'\n", msg->user_creds.username);
+ this->mutex->unlock(this->mutex);
+ DESTROY_IF(id);
+ return;
+ }
+
+ /* replace/set the username in the first EAP auth_cfg, also look for a
+ * suitable remote ID.
+ * note that adding the identity here is not fully thread-safe as the
+ * peer_cfg and in turn the auth_cfg could be in use. for the default use
+ * case (setting user credentials before upping the connection) this will
+ * not be a problem, though. */
+ enumerator = found->create_auth_cfg_enumerator(found, TRUE);
+ remote_auth = found->create_auth_cfg_enumerator(found, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&auth_cfg))
+ {
+ if (remote_auth->enumerate(remote_auth, (void**)&remote_cfg))
+ { /* fall back on rightid, in case aaa_identity is not specified */
+ identity = remote_cfg->get(remote_cfg, AUTH_RULE_IDENTITY);
+ if (identity && identity->get_type(identity) != ID_ANY)
+ {
+ gw = identity;
+ }
+ }
+
+ auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS);
+ if (auth_class == AUTH_CLASS_EAP)
+ {
+ auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ /* if aaa_identity is specified use that as remote ID */
+ identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
+ if (identity && identity->get_type(identity) != ID_ANY)
+ {
+ gw = identity;
+ }
+ DBG1(DBG_CFG, " configured EAP-Identity %Y", id);
+ type = SHARED_EAP;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ remote_auth->destroy(remote_auth);
+ /* clone the gw ID before unlocking the mutex */
+ if (gw)
+ {
+ gw = gw->clone(gw);
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (type == SHARED_ANY)
+ {
+ DBG1(DBG_CFG, " config '%s' unsuitable for user credentials",
+ msg->user_creds.name);
+ fprintf(prompt, "config '%s' unsuitable for user credentials\n",
+ msg->user_creds.name);
+ id->destroy(id);
+ DESTROY_IF(gw);
+ return;
+ }
+
+ if (msg->user_creds.password)
+ {
+ char *pass;
+
+ pass = msg->user_creds.password;
+ password = chunk_clone(chunk_create(pass, strlen(pass)));
+ memwipe(pass, strlen(pass));
+ }
+ else
+ { /* prompt the user for the password */
+ char buf[256];
+
+ fprintf(prompt, "Password:\n");
+ if (fgets(buf, sizeof(buf), prompt))
+ {
+ password = chunk_clone(chunk_create(buf, strlen(buf)));
+ if (password.len > 0)
+ { /* trim trailing \n */
+ password.len--;
+ }
+ memwipe(buf, sizeof(buf));
+ }
+ }
+
+ if (password.len)
+ {
+ shared_key_t *shared;
+ linked_list_t *owners;
+
+ shared = shared_key_create(type, password);
+
+ owners = linked_list_create();
+ owners->insert_last(owners, id->clone(id));
+ if (gw && gw->get_type(gw) != ID_ANY)
+ {
+ owners->insert_last(owners, gw->clone(gw));
+ DBG1(DBG_CFG, " added %N secret for %Y %Y", shared_key_type_names,
+ type, id, gw);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " added %N secret for %Y", shared_key_type_names,
+ type, id);
+ }
+ this->cred->add_shared(this->cred, shared, owners);
+ DBG4(DBG_CFG, " secret: %#B", &password);
+ }
+ else
+ { /* in case a user answers the password prompt by just pressing enter */
+ chunk_clear(&password);
+ }
+ id->destroy(id);
+ DESTROY_IF(gw);
+}
+
METHOD(stroke_config_t, destroy, void,
private_stroke_config_t *this)
{
@@ -955,6 +1137,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
},
.add = _add,
.del = _del,
+ .set_user_credentials = _set_user_credentials,
.destroy = _destroy,
},
.list = linked_list_create(),
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
index 05e4665ca..450d517f3 100644
--- a/src/libcharon/plugins/stroke/stroke_config.h
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -53,6 +54,15 @@ struct stroke_config_t {
void (*del)(stroke_config_t *this, stroke_msg_t *msg);
/**
+ * Set the username and password for a connection in this backend.
+ *
+ * @param msg received stroke message
+ * @param prompt I/O channel to prompt for the password
+ */
+ void (*set_user_credentials)(stroke_config_t *this, stroke_msg_t *msg,
+ FILE *prompt);
+
+ /**
* Destroy a stroke_config instance.
*/
void (*destroy)(stroke_config_t *this);
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index cdf69135a..535ece233 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -158,6 +158,78 @@ METHOD(stroke_cred_t, load_peer, certificate_t*,
return NULL;
}
+METHOD(stroke_cred_t, load_pubkey, certificate_t*,
+ private_stroke_cred_t *this, key_type_t type, char *filename,
+ identification_t *identity)
+{
+ certificate_t *cert;
+ char path[PATH_MAX];
+
+ if (streq(filename, "%dns"))
+ {
+
+ }
+ else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2))
+ {
+ chunk_t printable_key, rfc3110_key;
+ public_key_t *key;
+
+ printable_key = chunk_create(filename + 2, strlen(filename) - 2);
+ rfc3110_key = strncaseeq(filename, "0x", 2) ?
+ chunk_from_hex(printable_key, NULL) :
+ chunk_from_base64(printable_key, NULL);
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_DNSKEY, rfc3110_key,
+ BUILD_END);
+ free(rfc3110_key.ptr);
+ if (key)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, key,
+ BUILD_SUBJECT, identity,
+ BUILD_END);
+ key->destroy(key);
+ if (cert)
+ {
+ cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+ DBG1(DBG_CFG, " loaded %N public key for \"%Y\"",
+ key_type_names, type, identity);
+ return cert;
+ }
+ }
+ DBG1(DBG_CFG, " loading %N public key for \"%Y\" failed",
+ key_type_names, type, identity);
+ }
+ else
+ {
+ if (*filename == '/')
+ {
+ snprintf(path, sizeof(path), "%s", filename);
+ }
+ else
+ {
+ snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
+ }
+
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+ BUILD_FROM_FILE, path,
+ BUILD_SUBJECT, identity,
+ BUILD_END);
+ if (cert)
+ {
+ cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+ DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'",
+ key_type_names, type, identity, filename);
+ return cert;
+ }
+ DBG1(DBG_CFG, " loading %N public key for \"%Y\" from '%s' failed",
+ key_type_names, type, identity, filename);
+ }
+ return NULL;
+}
+
/**
* load trusted certificates from a directory
*/
@@ -1065,6 +1137,12 @@ METHOD(stroke_cred_t, reread, void,
}
}
+METHOD(stroke_cred_t, add_shared, void,
+ private_stroke_cred_t *this, shared_key_t *shared, linked_list_t *owners)
+{
+ this->creds->add_shared_list(this->creds, shared, owners);
+}
+
METHOD(stroke_cred_t, destroy, void,
private_stroke_cred_t *this)
{
@@ -1092,6 +1170,8 @@ stroke_cred_t *stroke_cred_create()
.reread = _reread,
.load_ca = _load_ca,
.load_peer = _load_peer,
+ .load_pubkey = _load_pubkey,
+ .add_shared = _add_shared,
.cachecrl = _cachecrl,
.destroy = _destroy,
},
diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h
index ccee7d87c..83e648819 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.h
+++ b/src/libcharon/plugins/stroke/stroke_cred.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -26,6 +27,7 @@
#include <stroke_msg.h>
#include <credentials/credential_set.h>
#include <credentials/certificates/certificate.h>
+#include <utils/linked_list.h>
typedef struct stroke_cred_t stroke_cred_t;
@@ -56,7 +58,7 @@ struct stroke_cred_t {
certificate_t* (*load_ca)(stroke_cred_t *this, char *filename);
/**
- * Load a peer certificate and serve it rhrough the credential_set.
+ * Load a peer certificate and serve it through the credential_set.
*
* @param filename file to load peer cert from
* @return reference to loaded certificate, or NULL
@@ -64,6 +66,26 @@ struct stroke_cred_t {
certificate_t* (*load_peer)(stroke_cred_t *this, char *filename);
/**
+ * Load a raw public key and serve it through the credential_set.
+ *
+ * @param type type of the raw public key (RSA or ECDSA)
+ * @param filename file to load raw public key from
+ * @param identity identity of the raw public key owner
+ * @return reference to loaded raw public key, or NULL
+ */
+ certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type,
+ char *filename, identification_t *identity);
+
+ /**
+ * Add a shared secret to serve through the credential_set.
+ *
+ * @param shared shared key to add, gets owned
+ * @param owners list of owners (identification_t*), gets owned
+ */
+ void (*add_shared)(stroke_cred_t *this, shared_key_t *shared,
+ linked_list_t *owners);
+
+ /**
* Enable/Disable CRL caching to disk.
*
* @param enabled TRUE to enable, FALSE to disable
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 6b256f29b..c3dea8419 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -708,12 +708,14 @@ static void list_public_key(public_key_t *public, FILE *out)
static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
{
bool first = TRUE;
-
- enumerator_t *enumerator = list->create_enumerator(list);
+ time_t now = time(NULL), notBefore, notAfter;
+ enumerator_t *enumerator;
certificate_t *cert;
+ enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, (void**)&cert))
{
+ identification_t *subject = cert->get_subject(cert);
public_key_t *public = cert->get_public_key(cert);
if (public)
@@ -726,6 +728,41 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
}
fprintf(out, "\n");
+ /* list subject if available */
+ if (subject->get_type(subject) != ID_KEY_ID)
+ {
+ fprintf(out, " subject: %#Y\n", subject);
+ }
+
+ /* list validity if available*/
+ cert->get_validity(cert, &now, &notBefore, &notAfter);
+ if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
+ {
+ fprintf(out, " validity: not before %T, ", &notBefore, utc);
+ if (now < notBefore)
+ {
+ fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
+ }
+ else
+ {
+ fprintf(out, "ok\n");
+ }
+ fprintf(out, " not after %T, ", &notAfter, utc);
+ if (now > notAfter)
+ {
+ fprintf(out, "expired (%V ago)\n", &now, &notAfter);
+ }
+ else
+ {
+ fprintf(out, "ok");
+ if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
+ {
+ fprintf(out, " (expires in %V)", &now, &notAfter);
+ }
+ fprintf(out, " \n");
+ }
+ }
+
list_public_key(public, out);
public->destroy(public);
}
@@ -842,7 +879,7 @@ static void stroke_list_certs(linked_list_t *list, char *label,
fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert));
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
- serial = x509->get_serial(x509);
+ serial = chunk_skip_zero(x509->get_serial(x509));
fprintf(out, " serial: %#B\n", &serial);
/* list validity */
@@ -955,7 +992,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
{
fprintf(out, " hissuer: \"%Y\"\n", id);
}
- chunk = ac->get_holderSerial(ac);
+ chunk = chunk_skip_zero(ac->get_holderSerial(ac));
if (chunk.ptr)
{
fprintf(out, " hserial: %#B\n", &chunk);
@@ -967,7 +1004,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
groups->destroy(groups);
}
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
- chunk = ac->get_serial(ac);
+ chunk = chunk_skip_zero(ac->get_serial(ac));
fprintf(out, " serial: %#B\n", &chunk);
/* list validity */
@@ -1024,13 +1061,14 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
/* list optional crlNumber */
- chunk = crl->get_serial(crl);
+ chunk = chunk_skip_zero(crl->get_serial(crl));
if (chunk.ptr)
{
fprintf(out, " serial: %#B\n", &chunk);
}
if (crl->is_delta_crl(crl, &chunk))
{
+ chunk = chunk_skip_zero(chunk);
fprintf(out, " delta for: %#B\n", &chunk);
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 4956b011f..7ef15db3c 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Tobias Brunner
+ * Copyright (C) 2011-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -185,6 +185,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
pop_string(msg, &end->id2);
+ pop_string(msg, &end->rsakey);
pop_string(msg, &end->cert);
pop_string(msg, &end->cert2);
pop_string(msg, &end->ca);
@@ -200,6 +201,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
+ DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey);
DBG2(DBG_CFG, " %scert=%s", label, end->cert);
DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
@@ -427,7 +429,7 @@ static void stroke_export(private_stroke_socket_t *this,
{
pop_string(msg, &msg->export.selector);
- if (msg->purge.flags & EXPORT_X509)
+ if (msg->export.flags & EXPORT_X509)
{
enumerator_t *enumerator;
identification_t *id;
@@ -475,6 +477,21 @@ static void stroke_memusage(private_stroke_socket_t *this,
}
/**
+ * Set username and password for a connection
+ */
+static void stroke_user_creds(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->user_creds.name);
+ pop_string(msg, &msg->user_creds.username);
+ pop_string(msg, &msg->user_creds.password);
+
+ DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
+
+ this->config->set_user_credentials(this->config, msg, out);
+}
+
+/**
* set the verbosity debug output
*/
static void stroke_loglevel(private_stroke_socket_t *this,
@@ -647,6 +664,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_MEMUSAGE:
stroke_memusage(this, msg, out);
break;
+ case STR_USER_CREDS:
+ stroke_user_creds(this, msg, out);
+ break;
default:
DBG1(DBG_CFG, "received unknown stroke");
break;
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
index 8607e5d9b..913cdab12 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
@@ -70,15 +70,14 @@ struct private_tnc_ifmap_soap_t {
/**
* Send request and receive result via SOAP
*/
-static bool send_receive(private_tnc_ifmap_soap_t *this,
- char *request_qname, axiom_node_t *request,
- char *receipt_qname, axiom_node_t **result)
+static axiom_element_t* send_receive(private_tnc_ifmap_soap_t *this,
+ char *request_qname, axiom_node_t *request,
+ char *receipt_qname, axiom_node_t **result)
{
axiom_node_t *parent, *node;
- axiom_element_t *el;
+ axiom_element_t *parent_el, *el;
axutil_qname_t *qname;
- bool success = FALSE;
/* send request and receive result */
DBG2(DBG_TNC, "sending ifmap %s", request_qname);
@@ -87,45 +86,44 @@ static bool send_receive(private_tnc_ifmap_soap_t *this,
if (!parent)
{
DBG1(DBG_TNC, "no ifmap %s received from MAP server", receipt_qname);
- return FALSE;
+ return NULL;
}
+ DBG2(DBG_TNC, "received ifmap %s", receipt_qname);
+
+ /* extract the parent element */
+ parent_el = (axiom_element_t*)axiom_node_get_data_element(parent, this->env);
- /* pre-process result */
- node = axiom_node_get_first_child(parent, this->env);
- if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
+ /* look for a child node with the given receipt qname */
+ qname = axutil_qname_create_from_string(this->env, strdup(receipt_qname));
+ el = axiom_element_get_first_child_with_qname(parent_el, this->env, qname,
+ parent, &node);
+ axutil_qname_free(qname, this->env);
+
+ if (el)
{
- el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-
- qname = axiom_element_get_qname(el, this->env, node);
- success = streq(receipt_qname, axutil_qname_to_string(qname, this->env));
- if (success)
- {
- DBG2(DBG_TNC, "received ifmap %s", receipt_qname);
- if (result)
- {
- *result = parent;
- }
- else
- {
- /* no further processing requested */
- axiom_node_free_tree(parent, this->env);
- }
- return TRUE;
+ if (result)
+ {
+ *result = parent;
}
- /* TODO proper error handling */
- DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
+ else
+ {
+ /* no further processing requested */
+ axiom_node_free_tree(parent, this->env);
+ }
+ return el;
}
+ DBG1(DBG_TNC, "child node with qname '%s' not found", receipt_qname);
/* free parent in the error case */
axiom_node_free_tree(parent, this->env);
- return FALSE;
+ return NULL;
}
METHOD(tnc_ifmap_soap_t, newSession, bool,
private_tnc_ifmap_soap_t *this)
{
- axiom_node_t *request, *result, *node;
+ axiom_node_t *request, *result;
axiom_element_t *el;
axiom_namespace_t *ns;
axis2_char_t *value;
@@ -136,15 +134,12 @@ METHOD(tnc_ifmap_soap_t, newSession, bool,
el = axiom_element_create(this->env, NULL, "newSession", ns, &request);
/* send newSession request and receive newSessionResult */
- if (!send_receive(this, "newSession", request, "newSessionResult", &result))
+ el = send_receive(this, "newSession", request, "newSessionResult", &result);
+ if (!el)
{
return FALSE;
}
- /* process newSessionResult */
- node = axiom_node_get_first_child(result, this->env);
- el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-
/* get session-id */
value = axiom_element_get_attribute_value_by_name(el, this->env,
"session-id");
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
index e769353b7..06291220f 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h
@@ -14,7 +14,7 @@
*/
/**
- * @defgroup tnc_pdp tnc_pdp
+ * @defgroup tnc_pdp_t tnc_pdp
* @{ @ingroup tnc_pdp
*/
diff --git a/src/libcharon/sa/authenticator.c b/src/libcharon/sa/authenticator.c
index 91bb7715f..a32b6ab12 100644
--- a/src/libcharon/sa/authenticator.c
+++ b/src/libcharon/sa/authenticator.c
@@ -31,11 +31,12 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS,
"RSA signature",
"pre-shared key",
"DSS signature");
-ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
+ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS,
"ECDSA-256 signature",
"ECDSA-384 signature",
- "ECDSA-521 signature");
-ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_ECDSA_521,
+ "ECDSA-521 signature",
+ "secure password method");
+ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_GSPM,
"XAuthInitPSK",
"XAuthRespPSK",
"XAuthInitRSA",
diff --git a/src/libcharon/sa/authenticator.h b/src/libcharon/sa/authenticator.h
index 3af939160..86b42da7a 100644
--- a/src/libcharon/sa/authenticator.h
+++ b/src/libcharon/sa/authenticator.h
@@ -75,6 +75,11 @@ enum auth_method_t {
AUTH_ECDSA_521 = 11,
/**
+ * Generic Secure Password Authentication Method as specified in RFC 6467
+ */
+ AUTH_GSPM = 12,
+
+ /**
* IKEv1 initiator XAUTH with PSK, outside of IANA range
*/
AUTH_XAUTH_INIT_PSK = 256,
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 5d0a5aea8..e94ebb15e 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1679,7 +1679,7 @@ static bool is_any_path_valid(private_ike_sa_t *this)
{
bool valid = FALSE;
enumerator_t *enumerator;
- host_t *src, *addr;
+ host_t *src = NULL, *addr;
DBG1(DBG_IKE, "old path is not available anymore, try to find another");
enumerator = this->peer_addresses->create_enumerator(this->peer_addresses);
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index b81c5c853..2e661dc66 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -219,23 +219,12 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
*/
static void replace_eap_identity(private_eap_authenticator_t *this)
{
- enumerator_t *enumerator;
- auth_rule_t rule;
+ identification_t *eap_identity;
auth_cfg_t *cfg;
- void *ptr;
+ eap_identity = this->eap_identity->clone(this->eap_identity);
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- enumerator = cfg->create_enumerator(cfg);
- while (enumerator->enumerate(enumerator, &rule, &ptr))
- {
- if (rule == AUTH_RULE_EAP_IDENTITY)
- {
- cfg->replace(cfg, enumerator, AUTH_RULE_EAP_IDENTITY,
- this->eap_identity->clone(this->eap_identity));
- break;
- }
- }
- enumerator->destroy(enumerator);
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity);
}
/**
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index ba7fdd2da..cc6d37849 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -610,7 +610,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
task_t *task;
message_t *message;
host_t *me, *other;
- bool delete = FALSE;
+ bool delete = FALSE, hook = FALSE;
status_t status;
me = request->get_destination(request);
@@ -645,9 +645,11 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
enumerator);
}
break;
- case DESTROY_ME:
case FAILED:
default:
+ hook = TRUE;
+ /* FALL */
+ case DESTROY_ME:
/* destroy IKE_SA, but SEND response first */
delete = TRUE;
break;
@@ -682,7 +684,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
this->responding.packet->clone(this->responding.packet));
if (delete)
{
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ if (hook)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
return DESTROY_ME;
}
return SUCCESS;
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 183ca3440..6af0b3778 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -419,10 +420,14 @@ METHOD(task_t, build_i, status_t,
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!idi)
- {
- DBG1(DBG_CFG, "configuration misses IDi");
- return FAILED;
+ if (!idi || idi->get_type(idi) == ID_ANY)
+ { /* ID_ANY is invalid as IDi, use local IP address instead */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDi configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ idi = identification_create_from_sockaddr(me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, idi);
}
this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
@@ -689,9 +694,14 @@ METHOD(task_t, build_r, status_t,
if (id->get_type(id) == ID_ANY)
{ /* no IDr received, apply configured ID */
if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
- {
- DBG1(DBG_CFG, "IDr not configured and negotiation failed");
- goto peer_auth_failed;
+ { /* no ID configured, use local IP address */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDr configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ id_cfg = identification_create_from_sockaddr(
+ me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id_cfg);
}
this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
id = id_cfg;
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index de68e8662..3fbbcfd2a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -519,9 +519,12 @@ METHOD(task_t, migrate, void,
this->ike_sa = ike_sa;
this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
- DESTROY_IF(this->dh);
- this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
- this->dh_group);
+ if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group)
+ { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */
+ this->dh->destroy(this->dh);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ this->dh_group);
+ }
}
METHOD(task_t, destroy, void,
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
index 9de2574e1..8bfe79660 100644
--- a/src/libcharon/sa/keymat.h
+++ b/src/libcharon/sa/keymat.h
@@ -48,7 +48,12 @@ struct keymat_t {
*
* The diffie hellman is either for IKE negotiation/rekeying or
* CHILD_SA rekeying (using PFS). The resulting DH object must be passed
- * to derive_keys or to derive_child_keys and destroyed after use
+ * to derive_keys or to derive_child_keys and destroyed after use.
+ *
+ * Only DH objects allocated through this method are passed to other
+ * keymat_t methods, allowing private DH implementations. In some cases
+ * (such as retrying with a COOKIE), a DH object allocated from a different
+ * keymat_t instance may be passed to other methods.
*
* @param group diffie hellman group
* @return DH object, NULL if group not supported