File strongswan_ipsec-secrets-include.diff of Package strongswan

From: Martin Willi <martin@strongswan.org>
Date: Thu, 6 Aug 2009 11:29:55 +0200
Subject: [PATCH] added support for ipsec.secrets "include" directive

[adopted patch for 4.2.8]

Signed-off-by: Marius Tomaschewski <mt@suse.de>

diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index c699a08..2a646e0 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -19,6 +19,8 @@
 #include <pthread.h>
 #include <sys/stat.h>
 #include <limits.h>
+#include <glob.h>
+#include <libgen.h>
 
 #include "stroke_cred.h"
 #include "stroke_shared_key.h"
@@ -43,6 +45,8 @@
 #define CRL_DIR IPSEC_D_DIR "/crls"
 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
 
+#define MAX_SECRETS_RECURSION 10
+
 typedef struct private_stroke_cred_t private_stroke_cred_t;
 
 /**
@@ -671,7 +675,7 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line)
 /**
  * reload ipsec.secrets
  */
-static void load_secrets(private_stroke_cred_t *this)
+static void load_secrets(private_stroke_cred_t *this, char *file, int level)
 {
 	size_t bytes;
 	int line_nr = 0;
@@ -680,9 +684,9 @@ static void load_secrets(private_stroke_cred_t *this)
 	private_key_t *private;
 	shared_key_t *shared;
 
-	DBG1(DBG_CFG, "loading secrets from '%s'", SECRETS_FILE);
+	DBG1(DBG_CFG, "loading secrets from '%s'", file);
 
-	fd = fopen(SECRETS_FILE, "r");
+	fd = fopen(file, "r");
 	if (fd == NULL)
 	{
 		DBG1(DBG_CFG, "opening secrets file '%s' failed");
@@ -699,15 +703,19 @@ static void load_secrets(private_stroke_cred_t *this)
 	src = chunk;
 
 	pthread_rwlock_wrlock(&this->lock);
-	while (this->shared->remove_last(this->shared,
-		 								   (void**)&shared) == SUCCESS)
-	{
-		shared->destroy(shared);
-	}
-	while (this->private->remove_last(this->private,
-		 								    (void**)&private) == SUCCESS)
+	if (level == 0)
 	{
-		private->destroy(private);
+		/* flush secrets on non-recursive invocation */
+		while (this->shared->remove_last(this->shared,
+										 (void**)&shared) == SUCCESS)
+		{
+			shared->destroy(shared);
+		}
+		while (this->private->remove_last(this->private,
+										  (void**)&private) == SUCCESS)
+		{
+			private->destroy(private);
+		}
 	}
 	
 	while (fetchline(&src, &line))
@@ -721,6 +729,66 @@ static void load_secrets(private_stroke_cred_t *this)
 		{
 			continue;
 		}
+		if (line.len > strlen("include ") &&
+			strneq(line.ptr, "include ", strlen("include ")))
+		{
+			glob_t buf;
+			char **expanded, *dir, pattern[PATH_MAX];
+			u_char *pos;
+			
+			if (level > MAX_SECRETS_RECURSION)
+			{
+				DBG1(DBG_CFG, "maximum level of %d includes reached, ignored",
+					 MAX_SECRETS_RECURSION);
+				continue;
+			}
+			/* terminate filename by space */
+			line = chunk_skip(line, strlen("include "));
+			pos = memchr(line.ptr, ' ', line.len);
+			if (pos)
+			{
+				line.len = pos - line.ptr;
+			}
+			if (line.len && line.ptr[0] == '/')
+			{
+				if (line.len + 1 > sizeof(pattern))
+				{
+					DBG1(DBG_CFG, "include pattern too long, ignored");
+					continue;
+				}
+				snprintf(pattern, sizeof(pattern), "%.*s", line.len, line.ptr);
+			}
+			else
+			{	/* use directory of current file if relative */
+				dir = strdup(file);
+				dir = dirname(dir);
+				
+				if (line.len + 1 + strlen(dir) + 1 > sizeof(pattern))
+				{
+					DBG1(DBG_CFG, "include pattern too long, ignored");
+					free(dir);
+					continue;
+				}
+				snprintf(pattern, sizeof(pattern), "%s/%.*s",
+						 dir, line.len, line.ptr);
+				free(dir);
+			}
+			if (glob(pattern, GLOB_ERR, NULL, &buf) != 0)
+			{
+				DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern);
+				globfree(&buf);
+			}
+			else
+			{
+				for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
+				{
+					load_secrets(this, *expanded, level + 1);
+				}
+			}
+			globfree(&buf);
+			continue;
+		}
+
 		if (!extract_last_token(&ids, ':', &line))
 		{
 			DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr);
@@ -906,7 +974,7 @@ static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
 	if (msg->reread.flags & REREAD_SECRETS)
 	{
 		DBG1(DBG_CFG, "rereading secrets");
-		load_secrets(this);
+		load_secrets(this, SECRETS_FILE, 0);
 	}
 	if (msg->reread.flags & REREAD_CACERTS)
 	{
@@ -977,7 +1045,7 @@ stroke_cred_t *stroke_cred_create()
 	pthread_rwlock_init(&this->lock, NULL);
 
 	load_certs(this);
-	load_secrets(this);
+	load_secrets(this, SECRETS_FILE, 0);
 	
 	this->cachecrl = FALSE;
 	
-- 
1.6.0.2


From: Marius Tomaschewski <mt@suse.de>
Date: Wed, 2 Sep 2009 13:49:39 +0200
Subject: [PATCH] Fixed load_secrets to acquire/release lock in level 0 only

The write_lock call fails with EDEADLK and unlocks in the
next recursion level.

[adopted patch for 4.2.8]

Signed-off-by: Marius Tomaschewski <mt@suse.de>

diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index 2a646e0..522e78c 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -702,9 +702,10 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level)
 	fclose(fd);
 	src = chunk;
 
-	pthread_rwlock_wrlock(&this->lock);
 	if (level == 0)
 	{
+		pthread_rwlock_wrlock(&this->lock);
+
 		/* flush secrets on non-recursive invocation */
 		while (this->shared->remove_last(this->shared,
 										 (void**)&shared) == SUCCESS)
@@ -936,7 +937,10 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level)
 		}
 	}
 error:
-	pthread_rwlock_unlock(&this->lock);
+	if (level == 0)
+	{
+		pthread_rwlock_unlock(&this->lock);
+	}
 	chunk_clear(&chunk);
 }
 
-- 
1.6.0.2

From: Marius Tomaschewski <mt@suse.de>
Date: Fri, 4 Sep 2009 11:28:52 +0200
Subject: [PATCH] fixed open failure debug message in load_secrets


diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index e34613e..57a02c7 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -780,7 +780,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
 	fd = fopen(file, "r");
 	if (fd == NULL)
 	{
-		DBG1(DBG_CFG, "opening secrets file '%s' failed");
+		DBG1(DBG_CFG, "opening secrets file '%s' failed", file);
 		return;
 	}
 
-- 
1.6.0.2

openSUSE Build Service is sponsored by