aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2009-08-14 15:01:35 +0200
committerMartin Willi <martin@strongswan.org>2009-08-26 11:23:50 +0200
commit750bbcf9a80c2613245b47a366ed66e0abace561 (patch)
tree83e122bd1b717bc0f2d8570bcd4d09d8f4d3288c /src
parent7c2d883af79ded800a19179bdb061210ac30e4fc (diff)
downloadstrongswan-750bbcf9a80c2613245b47a366ed66e0abace561.tar.bz2
strongswan-750bbcf9a80c2613245b47a366ed66e0abace561.tar.xz
added support for %prompt-ing private key passhprases in strokes "ipsec secrets"
Diffstat (limited to 'src')
-rw-r--r--src/charon/plugins/stroke/stroke_cred.c86
-rw-r--r--src/charon/plugins/stroke/stroke_cred.h11
-rw-r--r--src/charon/plugins/stroke/stroke_socket.c4
-rw-r--r--src/stroke/stroke.c12
4 files changed, 96 insertions, 17 deletions
diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index 43046b1cc..80ca177d3 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -729,9 +729,54 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line)
}
/**
+ * Data to pass to passphrase_cb
+ */
+typedef struct {
+ /** socket we use for prompting */
+ FILE *prompt;
+ /** private key file */
+ char *file;
+ /** buffer for passphrase */
+ char buf[256];
+} passphrase_cb_data_t;
+
+/**
+ * Passphrase callback to read from whack fd
+ */
+chunk_t passphrase_cb(passphrase_cb_data_t *data, int try)
+{
+ chunk_t secret = chunk_empty;;
+
+ if (try > 5)
+ {
+ fprintf(data->prompt, "invalid passphrase, too many trials\n");
+ return chunk_empty;
+ }
+ if (try == 1)
+ {
+ fprintf(data->prompt, "Private key '%s' is encrypted\n", data->file);
+ }
+ else
+ {
+ fprintf(data->prompt, "invalid passphrase\n");
+ }
+ fprintf(data->prompt, "Passphrase:\n");
+ if (fgets(data->buf, sizeof(data->buf), data->prompt))
+ {
+ secret = chunk_create(data->buf, strlen(data->buf));
+ if (secret.len)
+ { /* trim appended \n */
+ secret.len--;
+ }
+ }
+ return secret;
+}
+
+/**
* reload ipsec.secrets
*/
-static void load_secrets(private_stroke_cred_t *this, char *file, int level)
+static void load_secrets(private_stroke_cred_t *this, char *file, int level,
+ FILE *prompt)
{
size_t bytes;
int line_nr = 0;
@@ -838,7 +883,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level)
{
for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
{
- load_secrets(this, *expanded, level + 1);
+ load_secrets(this, *expanded, level + 1, prompt);
}
}
globfree(&buf);
@@ -873,7 +918,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level)
char path[PATH_MAX];
chunk_t filename;
chunk_t secret = chunk_empty;
- private_key_t *key;
+ private_key_t *key = NULL;
key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
err_t ugh = extract_value(&filename, &line);
@@ -910,15 +955,36 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level)
goto error;
}
}
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
- BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE, secret,BUILD_END);
+ if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7))
+ {
+ if (prompt)
+ {
+ passphrase_cb_data_t data;
+
+ data.prompt = prompt;
+ data.file = path;
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ key_type, BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE_CALLBACK,
+ passphrase_cb, &data, BUILD_END);
+ }
+ }
+ else
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
+ BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE, secret, BUILD_END);
+ }
if (key)
{
DBG1(DBG_CFG, " loaded %N private key file '%s'",
key_type_names, key->get_type(key), path);
this->private->insert_last(this->private, key);
}
+ else
+ {
+ DBG1(DBG_CFG, " skipped private key file '%s'", path);
+ }
chunk_clear(&secret);
}
else if (match("PIN", &token))
@@ -1083,12 +1149,12 @@ static void load_certs(private_stroke_cred_t *this)
/**
* Implementation of stroke_cred_t.reread.
*/
-static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
+static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt)
{
if (msg->reread.flags & REREAD_SECRETS)
{
DBG1(DBG_CFG, "rereading secrets");
- load_secrets(this, SECRETS_FILE, 0);
+ load_secrets(this, SECRETS_FILE, 0, prompt);
}
if (msg->reread.flags & REREAD_CACERTS)
{
@@ -1147,7 +1213,7 @@ stroke_cred_t *stroke_cred_create()
this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
this->public.set.create_cdp_enumerator = (void*)return_null;
this->public.set.cache_cert = (void*)cache_cert;
- this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread;
+ this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg, FILE*))reread;
this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
@@ -1159,7 +1225,7 @@ stroke_cred_t *stroke_cred_create()
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
load_certs(this);
- load_secrets(this, SECRETS_FILE, 0);
+ load_secrets(this, SECRETS_FILE, 0, NULL);
this->cachecrl = FALSE;
diff --git a/src/charon/plugins/stroke/stroke_cred.h b/src/charon/plugins/stroke/stroke_cred.h
index 8bc042f13..3924ccbc1 100644
--- a/src/charon/plugins/stroke/stroke_cred.h
+++ b/src/charon/plugins/stroke/stroke_cred.h
@@ -21,6 +21,8 @@
#ifndef STROKE_CRED_H_
#define STROKE_CRED_H_
+#include <stdio.h>
+
#include <stroke_msg.h>
#include <credentials/credential_set.h>
#include <credentials/certificates/certificate.h>
@@ -41,8 +43,9 @@ struct stroke_cred_t {
* Reread secrets from config files.
*
* @param msg stroke message
+ * @param prompt I/O channel to prompt for private key passhprase
*/
- void (*reread)(stroke_cred_t *this, stroke_msg_t *msg);
+ void (*reread)(stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt);
/**
* Load a CA certificate, and serve it through the credential_set.
@@ -68,9 +71,9 @@ struct stroke_cred_t {
void (*cachecrl)(stroke_cred_t *this, bool enabled);
/**
- * Destroy a stroke_cred instance.
- */
- void (*destroy)(stroke_cred_t *this);
+ * Destroy a stroke_cred instance.
+ */
+ void (*destroy)(stroke_cred_t *this);
};
/**
diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c
index 9b6a8a3a7..f420266cd 100644
--- a/src/charon/plugins/stroke/stroke_socket.c
+++ b/src/charon/plugins/stroke/stroke_socket.c
@@ -333,7 +333,7 @@ static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *
static void stroke_reread(private_stroke_socket_t *this,
stroke_msg_t *msg, FILE *out)
{
- this->cred->reread(this->cred, msg);
+ this->cred->reread(this->cred, msg, out);
}
/**
@@ -467,7 +467,7 @@ static job_requeue_t process(stroke_job_context_t *ctx)
return JOB_REQUEUE_NONE;
}
- out = fdopen(strokefd, "w");
+ out = fdopen(strokefd, "w+");
if (out == NULL)
{
DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index c27a8ca3e..186e480d1 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -55,7 +55,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
{
struct sockaddr_un ctl_addr;
int sock;
- char buffer[64];
+ char buffer[512];
int byte_count;
ctl_addr.sun_family = AF_UNIX;
@@ -89,6 +89,16 @@ static int send_stroke_msg (stroke_msg_t *msg)
{
buffer[byte_count] = '\0';
printf("%s", buffer);
+
+ /* we prompt if we receive the "Passphrase:" magic keyword */
+ if (byte_count >= 12 &&
+ strcmp(buffer + byte_count - 12, "Passphrase:\n") == 0)
+ {
+ if (fgets(buffer, sizeof(buffer), stdin))
+ {
+ if (write(sock, buffer, strlen(buffer)));
+ }
+ }
}
if (byte_count < 0)
{