diff options
author | Martin Willi <martin@strongswan.org> | 2009-08-14 15:01:35 +0200 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2009-08-26 11:23:50 +0200 |
commit | 750bbcf9a80c2613245b47a366ed66e0abace561 (patch) | |
tree | 83e122bd1b717bc0f2d8570bcd4d09d8f4d3288c /src | |
parent | 7c2d883af79ded800a19179bdb061210ac30e4fc (diff) | |
download | strongswan-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.c | 86 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_cred.h | 11 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_socket.c | 4 | ||||
-rw-r--r-- | src/stroke/stroke.c | 12 |
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) { |