From 08ee5250bd9c43fda5f24d10b791ca2c4c17fcee Mon Sep 17 00:00:00 2001
From: Rene Mayrhofer <rene@mayrhofer.eu.org>
Date: Sun, 3 Jun 2007 17:36:35 +0000
Subject: [svn-upgrade] Integrating new upstream version, strongswan (4.1.3)

---
 src/charon/sa/authenticators/eap/eap_method.c    |  35 +-------
 src/charon/sa/authenticators/eap/eap_sim.c       | 104 ++++++++++++++++++++++-
 src/charon/sa/authenticators/eap_authenticator.c |  58 ++++++++-----
 src/charon/sa/authenticators/psk_authenticator.c |  10 +--
 src/charon/sa/authenticators/rsa_authenticator.c |  37 ++++----
 5 files changed, 162 insertions(+), 82 deletions(-)

(limited to 'src/charon/sa/authenticators')

diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c
index a4d8abb58..e4a58f0a3 100644
--- a/src/charon/sa/authenticators/eap/eap_method.c
+++ b/src/charon/sa/authenticators/eap/eap_method.c
@@ -85,7 +85,7 @@ void eap_method_unload()
 		
 		while (modules->remove_last(modules, (void**)&entry) == SUCCESS)
 		{
-			DBG2(DBG_CFG, "unloaded module for %s", eap_type_names, entry->type);
+			DBG2(DBG_CFG, "unloaded module for %N", eap_type_names, entry->type);
 			dlclose(entry->handle);
 			free(entry);
 		}
@@ -100,27 +100,10 @@ void eap_method_unload()
 void eap_method_load(char *directory)
 {
 	struct dirent* entry;
-	struct stat stb;
 	DIR* dir;
 	
 	eap_method_unload();	
 	modules = linked_list_create();
-	
-	if (stat(directory, &stb) == -1 || !(stb.st_mode & S_IFDIR))
-	{
-		DBG1(DBG_CFG, "error opening EAP modules directory %s", directory);
-		return;
-	}
-	if (stb.st_uid != 0)
-	{
-		DBG1(DBG_CFG, "EAP modules directory %s not owned by root, skipped", directory);
-		return;
-	}
-	if (stb.st_mode & S_IWOTH || stb.st_mode & S_IWGRP)
-	{
-		DBG1(DBG_CFG, "EAP modules directory %s writable by others, skipped", directory);
-		return;
-	}
 
 	dir = opendir(directory);
 	if (dir == NULL)
@@ -141,12 +124,6 @@ void eap_method_load(char *directory)
 		
 		snprintf(file, sizeof(file), "%s/%s", directory, entry->d_name);
 		
-		if (stat(file, &stb) == -1 || !(stb.st_mode & S_IFREG))
-		{
-			DBG2(DBG_CFG, "  skipping %s, doesn't look like a file",
-				 entry->d_name);
-			continue;
-		}
 		ending = entry->d_name + strlen(entry->d_name) - 3;
 		if (ending <= entry->d_name || !streq(ending, ".so"))
 		{
@@ -155,16 +132,6 @@ void eap_method_load(char *directory)
 				 entry->d_name);
 			continue;
 		}
-		if (stb.st_uid != 0)
-		{
-			DBG1(DBG_CFG, "  skipping %s, file is not owned by root", entry->d_name);
-			return;
-		}
-		if (stb.st_mode & S_IWOTH || stb.st_mode & S_IWGRP)
-		{
-			DBG1(DBG_CFG, "  skipping %s, file is writeable by others", entry->d_name);
-			continue;
-		}
 		
 		/* try to load the library */
 		module.handle = dlopen(file, RTLD_LAZY);
diff --git a/src/charon/sa/authenticators/eap/eap_sim.c b/src/charon/sa/authenticators/eap/eap_sim.c
index 3dc59fb6b..38d7f2534 100644
--- a/src/charon/sa/authenticators/eap/eap_sim.c
+++ b/src/charon/sa/authenticators/eap/eap_sim.c
@@ -398,6 +398,30 @@ static status_t process_start(private_eap_sim_t *this, eap_payload_t *in,
 				/* only include AT_IDENTITY if requested */
 				include_id = AT_IDENTITY;
 				break;
+			case AT_NOTIFICATION:
+			{
+				u_int16_t code = 0;
+				if (data.len == 2)
+				{
+					code = ntohs(*(u_int16_t*)data.ptr);
+				}
+				if (code <= 32767) /* no success bit */
+				{
+					DBG1(DBG_IKE, "received %N error %d",
+				 		 sim_attribute_names, attribute, code);
+					*out = build_payload(this,
+									in->get_identifier(in), SIM_CLIENT_ERROR,
+						 			AT_CLIENT_ERROR_CODE, client_error_general,
+									AT_END);
+					return NEED_MORE;
+				}
+				else
+				{
+					DBG1(DBG_IKE, "received %N code %d",
+				 		 sim_attribute_names, attribute, code);
+				}
+				break;
+			}
 			default:
 				DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N",
 					 sim_attribute_names, attribute);
@@ -456,6 +480,30 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in,
 				memset(data.ptr, 0, data.len);
 				break;
 			}
+			case AT_NOTIFICATION:
+			{
+				u_int16_t code = 0;
+				if (data.len == 2)
+				{
+					code = ntohs(*(u_int16_t*)data.ptr);
+				}
+				if (code <= 32767) /* no success bit */
+				{
+					DBG1(DBG_IKE, "received %N error %d",
+				 		 sim_attribute_names, attribute, code);
+					*out = build_payload(this,
+									in->get_identifier(in), SIM_CLIENT_ERROR,
+						 			AT_CLIENT_ERROR_CODE, client_error_general,
+									AT_END);
+					return NEED_MORE;
+				}
+				else
+				{
+					DBG1(DBG_IKE, "received %N code %d",
+				 		 sim_attribute_names, attribute, code);
+				}
+				break;
+			}
 			default:
 				DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N",
 					 sim_attribute_names, attribute);
@@ -472,7 +520,7 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in,
 		*out = build_payload(this, identifier, SIM_CLIENT_ERROR,
 							 AT_CLIENT_ERROR_CODE, client_error_insufficient,
 							 AT_END);
-		return FAILED;
+		return NEED_MORE;
 	}
 	if (mac.len != MAC_LEN)
 	{
@@ -556,6 +604,58 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in,
 	return NEED_MORE;
 }
 
+/**
+ * process an EAP-SIM/Request/Notification message
+ */
+static status_t process_notification(private_eap_sim_t *this, eap_payload_t *in,
+									 eap_payload_t **out)
+{
+	chunk_t message, data;
+	sim_attribute_t attribute;
+	
+	message = in->get_data(in);
+	read_header(&message);
+
+	while ((attribute = read_attribute(&message, &data)) != AT_END)
+	{
+		switch (attribute)
+		{
+			case AT_NOTIFICATION:
+			{
+				u_int16_t code = 0;
+				if (data.len == 2)
+				{
+					code = ntohs(*(u_int16_t*)data.ptr);
+				}
+				if (code <= 32767) /* no success bit */
+				{
+					DBG1(DBG_IKE, "received %N error %d",
+				 		 sim_attribute_names, attribute, code);
+					*out = build_payload(this,
+									in->get_identifier(in), SIM_CLIENT_ERROR,
+						 			AT_CLIENT_ERROR_CODE, client_error_general,
+									AT_END);
+					return NEED_MORE;
+				}
+				else
+				{
+					DBG1(DBG_IKE, "received %N code %d",
+				 		 sim_attribute_names, attribute, code);
+				}
+				break;
+			}
+			default:
+				DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N",
+					 sim_attribute_names, attribute);
+				break;
+		}
+	}
+	/* reply with empty notification */
+	*out = build_payload(this, in->get_identifier(in), SIM_NOTIFICATION, AT_END);
+	return NEED_MORE;
+}
+
+
 /**
  * Implementation of eap_method_t.process for the peer
  */
@@ -574,6 +674,8 @@ static status_t process(private_eap_sim_t *this,
 			return process_start(this, in, out);
 		case SIM_CHALLENGE:
 			return process_challenge(this, in, out);
+		case SIM_NOTIFICATION:
+			return process_notification(this, in, out);
 		default:
 			DBG1(DBG_IKE, "unable to process EAP_SIM subtype %N",
 				 sim_subtype_names, type);
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c
index 6c8ca8d8f..6e2f73a43 100644
--- a/src/charon/sa/authenticators/eap_authenticator.c
+++ b/src/charon/sa/authenticators/eap_authenticator.c
@@ -25,7 +25,7 @@
 #include "eap_authenticator.h"
 
 #include <daemon.h>
-#include <config/policies/policy.h>
+#include <config/peer_cfg.h>
 #include <sa/authenticators/eap/eap_method.h>
 
 typedef struct private_eap_authenticator_t private_eap_authenticator_t;
@@ -61,21 +61,31 @@ struct private_eap_authenticator_t {
 	chunk_t msk;
 };
 
+/**
+ * reuse shared key signature function from PSK authenticator
+ */
 extern chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
-								 		  chunk_t secret, identification_t *id,
-										  prf_t *prf_skp, prf_t *prf);
-
+										  chunk_t secret, identification_t *id,
+										  chunk_t skp, prf_t *prf);
 /**
  * Implementation of authenticator_t.verify.
  */
 static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
 					   chunk_t my_nonce, auth_payload_t *auth_payload)
 {
-	chunk_t auth_data, recv_auth_data;
+	chunk_t auth_data, recv_auth_data, secret;
 	identification_t *other_id = this->ike_sa->get_other_id(this->ike_sa);
 	
-	auth_data = build_shared_key_signature(ike_sa_init, my_nonce, this->msk,
-						other_id, this->ike_sa->get_auth_verify(this->ike_sa),
+	if (this->msk.len)
+	{	/* use MSK if EAP method established one... */
+		secret = this->msk;
+	}
+	else
+	{	/* ... or use SKp if not */
+		secret = this->ike_sa->get_skp_verify(this->ike_sa);
+	}
+	auth_data = build_shared_key_signature(ike_sa_init, my_nonce, secret,
+						other_id, this->ike_sa->get_skp_verify(this->ike_sa),
 						this->ike_sa->get_prf(this->ike_sa));
 	
 	recv_auth_data = auth_payload->get_data(auth_payload);
@@ -98,14 +108,22 @@ static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
 static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
 					  chunk_t other_nonce, auth_payload_t **auth_payload)
 {
-	chunk_t auth_data;
+	chunk_t auth_data, secret;
 	identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa);
 	
 	DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
 		 my_id, auth_method_names, AUTH_EAP);
-	
-	auth_data = build_shared_key_signature(ike_sa_init, other_nonce, this->msk,
-							my_id, this->ike_sa->get_auth_build(this->ike_sa),
+
+	if (this->msk.len)
+	{	/* use MSK if EAP method established one... */
+		secret = this->msk;
+	}
+	else
+	{	/* ... or use SKp if not */
+		secret = this->ike_sa->get_skp_build(this->ike_sa);
+	}
+	auth_data = build_shared_key_signature(ike_sa_init, other_nonce, secret,
+							my_id, this->ike_sa->get_skp_build(this->ike_sa),
 							this->ike_sa->get_prf(this->ike_sa));
 	
 	*auth_payload = auth_payload_create();
@@ -233,13 +251,14 @@ static status_t process_server(private_eap_authenticator_t *this,
 				DBG1(DBG_IKE, "EAP method %N succeded, MSK established",
 					 eap_type_names, this->method->get_type(this->method));
 				this->msk = chunk_clone(this->msk);
-				*out = eap_payload_create_code(EAP_SUCCESS);
-				return SUCCESS;
 			}
-			DBG1(DBG_IKE, "EAP method %N succeded, but no MSK established",
-				 eap_type_names, this->method->get_type(this->method));
-			*out = eap_payload_create_code(EAP_FAILURE);
-			return FAILED;
+			else
+			{
+				DBG1(DBG_IKE, "EAP method %N succeded, no MSK established",
+					 eap_type_names, this->method->get_type(this->method));
+			}
+			*out = eap_payload_create_code(EAP_SUCCESS);
+			return SUCCESS;
 		case FAILED:
 		default:
 			DBG1(DBG_IKE, "EAP method %N failed for peer %D",
@@ -290,11 +309,8 @@ static status_t process(private_eap_authenticator_t *this, eap_payload_t *in,
 					if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
 					{
 						this->msk = chunk_clone(this->msk);
-						return SUCCESS;
 					}
-					DBG1(DBG_IKE, "EAP method %N has no MSK established",
-						 eap_type_names, this->method->get_type(this->method));
-					return FAILED;
+					return SUCCESS;
 				}
 				case EAP_FAILURE:
 				default:
diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c
index 43aec0971..37465d029 100644
--- a/src/charon/sa/authenticators/psk_authenticator.c
+++ b/src/charon/sa/authenticators/psk_authenticator.c
@@ -25,7 +25,6 @@
 
 #include "psk_authenticator.h"
 
-#include <config/policies/policy.h>
 #include <daemon.h>
 
 /**
@@ -78,11 +77,12 @@ chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce,
  */
 chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
 								   chunk_t secret, identification_t *id,
-								   prf_t *prf_skp, prf_t *prf)
+								   chunk_t skp, prf_t *prf)
 {
 	chunk_t key_pad, key, auth_data, octets;
 	
-	octets = build_tbs_octets(ike_sa_init, nonce, id, prf_skp);
+	prf->set_key(prf, skp);
+	octets = build_tbs_octets(ike_sa_init, nonce, id, prf);
 	/* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
 	key_pad.ptr = IKEV2_KEY_PAD;
 	key_pad.len = IKEV2_KEY_PAD_LENGTH;
@@ -122,7 +122,7 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
 	}
 	
 	auth_data = build_shared_key_signature(ike_sa_init, my_nonce, shared_key,
-						other_id, this->ike_sa->get_auth_verify(this->ike_sa),
+						other_id, this->ike_sa->get_skp_verify(this->ike_sa),
 						this->ike_sa->get_prf(this->ike_sa));
 	chunk_free(&shared_key);
 	
@@ -165,7 +165,7 @@ static status_t build(private_psk_authenticator_t *this, chunk_t ike_sa_init,
 	}
 			
 	auth_data = build_shared_key_signature(ike_sa_init, other_nonce, shared_key,
-							my_id, this->ike_sa->get_auth_build(this->ike_sa),
+							my_id, this->ike_sa->get_skp_build(this->ike_sa),
 							this->ike_sa->get_prf(this->ike_sa));
 	DBG2(DBG_IKE, "successfully created shared key MAC");
 	chunk_free(&shared_key);
diff --git a/src/charon/sa/authenticators/rsa_authenticator.c b/src/charon/sa/authenticators/rsa_authenticator.c
index dfa01e332..e5c5cd60e 100644
--- a/src/charon/sa/authenticators/rsa_authenticator.c
+++ b/src/charon/sa/authenticators/rsa_authenticator.c
@@ -25,7 +25,6 @@
 
 #include "rsa_authenticator.h"
 
-#include <config/policies/policy.h>
 #include <daemon.h>
 
 
@@ -61,8 +60,9 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
 {
 	status_t status;
 	chunk_t auth_data, octets;
-	rsa_public_key_t *public_key;
 	identification_t *other_id;
+	ca_info_t *issuer;
+	prf_t *prf;
 	
 	other_id = this->ike_sa->get_other_id(this->ike_sa);
 	
@@ -71,27 +71,20 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
 		return INVALID_ARG;
 	}
 	auth_data = auth_payload->get_data(auth_payload);
-	public_key = charon->credentials->get_trusted_public_key(charon->credentials,
-															 other_id);
-	if (public_key == NULL)
-	{
-		DBG1(DBG_IKE, "no RSA public key found for '%D'", other_id);
-		return NOT_FOUND;
-	}
-	octets = build_tbs_octets(ike_sa_init, my_nonce, other_id,
-							  this->ike_sa->get_auth_verify(this->ike_sa));
-	status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data);
+	prf = this->ike_sa->get_prf(this->ike_sa);
+	prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa));
+	octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf);
+	status = charon->credentials->verify_signature(charon->credentials,
+								  octets, auth_data, other_id, &issuer);
 	chunk_free(&octets);
 	
-	if (status != SUCCESS)
+	if (status == SUCCESS)
 	{
-		DBG1(DBG_IKE, "RSA signature verification failed");
-		return status;
+		this->ike_sa->set_other_ca(this->ike_sa, issuer);
+		DBG1(DBG_IKE, "authentication of '%D' with %N successful",
+					   other_id, auth_method_names, AUTH_RSA);
 	}
-	
-	DBG1(DBG_IKE, "authentication of '%D' with %N successful",
-		 other_id, auth_method_names, AUTH_RSA);
-	return SUCCESS;
+	return status;
 }
 
 /**
@@ -107,6 +100,7 @@ static status_t build(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
 	rsa_public_key_t *my_pubkey;
 	rsa_private_key_t *my_key;
 	identification_t *my_id;
+	prf_t *prf;
 
 	my_id = this->ike_sa->get_my_id(this->ike_sa);
 	DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
@@ -131,8 +125,9 @@ static status_t build(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
 	}
 	DBG2(DBG_IKE, "matching RSA private key found");
 
-	octets = build_tbs_octets(ike_sa_init, other_nonce, my_id,
-							  this->ike_sa->get_auth_build(this->ike_sa));
+	prf = this->ike_sa->get_prf(this->ike_sa);
+	prf->set_key(prf, this->ike_sa->get_skp_build(this->ike_sa));
+	octets = build_tbs_octets(ike_sa_init, other_nonce, my_id, prf);
 	status = my_key->build_emsa_pkcs1_signature(my_key, HASH_SHA1, octets, &auth_data);
 	chunk_free(&octets);
 
-- 
cgit v1.2.3