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