aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-07-19 14:12:05 +0200
committerMartin Willi <martin@revosec.ch>2010-08-04 09:26:21 +0200
commit15177f5785bcec6700f2a1a698cd8392c9bba5e9 (patch)
tree2c46df5d1c9a49af4c4ed7c4b427dc8c5a9ae90a /src
parent3429be9514c2568ccf2eb3df6ffc7bc7646e7d4f (diff)
downloadstrongswan-15177f5785bcec6700f2a1a698cd8392c9bba5e9.tar.bz2
strongswan-15177f5785bcec6700f2a1a698cd8392c9bba5e9.tar.xz
Obseleted BUILD_PASSPHRASE(_CALLBACK) for private key loading, use credential sets
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/plugins/nm/nm_creds.c64
-rw-r--r--src/libcharon/plugins/nm/nm_creds.h9
-rw-r--r--src/libcharon/plugins/nm/nm_service.c20
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c114
-rw-r--r--src/libstrongswan/credentials/builder.h6
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c89
-rwxr-xr-xsrc/openac/openac.c12
-rw-r--r--src/pluto/certs.c84
-rw-r--r--src/pluto/certs.h2
-rw-r--r--src/pluto/defs.h9
-rw-r--r--src/pluto/keys.c120
11 files changed, 301 insertions, 228 deletions
diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c
index 193838e6b..4ee94362f 100644
--- a/src/libcharon/plugins/nm/nm_creds.c
+++ b/src/libcharon/plugins/nm/nm_creds.c
@@ -51,6 +51,11 @@ struct private_nm_creds_t {
char *pass;
/**
+ * Private key decryption password
+ */
+ char *keypass;
+
+ /**
* users certificate
*/
certificate_t *usercert;
@@ -239,8 +244,14 @@ static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
return FALSE;
}
*key = this->key;
- *me = ID_MATCH_PERFECT;
- *other = ID_MATCH_ANY;
+ if (me)
+ {
+ *me = ID_MATCH_PERFECT;
+ }
+ if (other)
+ {
+ *other = ID_MATCH_ANY;
+ }
this->done = TRUE;
return TRUE;
}
@@ -262,18 +273,31 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
identification_t *other)
{
shared_enumerator_t *enumerator;
+ chunk_t key;
- if (!this->pass || !this->user)
+ switch (type)
{
- return NULL;
- }
- if (type != SHARED_EAP && type != SHARED_IKE)
- {
- return NULL;
- }
- if (me && !me->equals(me, this->user))
- {
- return NULL;
+ case SHARED_EAP:
+ case SHARED_IKE:
+ if (!this->pass || !this->user)
+ {
+ return NULL;
+ }
+ if (me && !me->equals(me, this->user))
+ {
+ return NULL;
+ }
+ key = chunk_create(this->pass, strlen(this->pass));
+ break;
+ case SHARED_PRIVATE_KEY_PASS:
+ if (!this->keypass)
+ {
+ return NULL;
+ }
+ key = chunk_create(this->keypass, strlen(this->keypass));
+ break;
+ default:
+ return NULL;
}
enumerator = malloc_thing(shared_enumerator_t);
@@ -282,9 +306,7 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
enumerator->this = this;
enumerator->done = FALSE;
this->lock->read_lock(this->lock);
- enumerator->key = shared_key_create(type,
- chunk_clone(chunk_create(this->pass,
- strlen(this->pass))));
+ enumerator->key = shared_key_create(type, chunk_clone(key));
return &enumerator->public;
}
@@ -370,6 +392,17 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
}
/**
+ * Implementation of nm_creds_t.set_key_password
+ */
+static void set_key_password(private_nm_creds_t *this, char *password)
+{
+ this->lock->write_lock(this->lock);
+ free(this->keypass);
+ this->keypass = password ? strdup(password) : NULL;
+ this->lock->unlock(this->lock);
+}
+
+/**
* Implementation of nm_creds_t.set_cert_and_key
*/
static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
@@ -430,6 +463,7 @@ nm_creds_t *nm_creds_create()
this->public.add_certificate = (void(*)(nm_creds_t*, certificate_t *cert))add_certificate;
this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir;
this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password;
+ this->public.set_key_password = (void(*)(nm_creds_t*, char *password))set_key_password;
this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key;
this->public.clear = (void(*)(nm_creds_t*))clear;
this->public.destroy = (void(*)(nm_creds_t*))destroy;
diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h
index b55cff31e..44936dd6a 100644
--- a/src/libcharon/plugins/nm/nm_creds.h
+++ b/src/libcharon/plugins/nm/nm_creds.h
@@ -58,6 +58,14 @@ struct nm_creds_t {
*/
void (*set_username_password)(nm_creds_t *this, identification_t *id,
char *password);
+
+ /**
+ * Set the passphrase to use for private key decryption.
+ *
+ * @param password password to use
+ */
+ void (*set_key_password)(nm_creds_t *this, char *password);
+
/**
* Set the certificate and private key to use for client authentication.
*
@@ -66,6 +74,7 @@ struct nm_creds_t {
*/
void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
private_key_t *key);
+
/**
* Clear the stored credentials.
*/
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
index 07318bbbf..910b01cc8 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -380,16 +380,15 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
str = nm_setting_vpn_get_data_item(vpn, "userkey");
if (!agent && str)
{
- chunk_t secret;
+ char *secret;
- secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password");
- if (secret.ptr)
+ secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
+ if (secret)
{
- secret.len = strlen(secret.ptr);
+ priv->creds->set_key_password(priv->creds, secret);
}
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, str,
- BUILD_PASSPHRASE, secret, BUILD_END);
+ KEY_RSA, BUILD_FROM_FILE, str, BUILD_END);
if (!private)
{
g_set_error(err, NM_VPN_PLUGIN_ERROR,
@@ -524,17 +523,10 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
if (path)
{
private_key_t *key;
- chunk_t secret;
- secret.ptr = (char*)nm_setting_vpn_get_secret(settings, "password");
- if (secret.ptr)
- {
- secret.len = strlen(secret.ptr);
- }
/* try to load/decrypt the private key */
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE, secret, BUILD_END);
+ KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
if (key)
{
key->destroy(key);
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index cfa33a746..69e2054f8 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -674,47 +674,57 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line)
}
/**
- * Data to pass to passphrase_cb
+ * Data for passphrase callback
*/
typedef struct {
/** socket we use for prompting */
FILE *prompt;
/** private key file */
- char *file;
- /** buffer for passphrase */
- char buf[256];
+ char *path;
+ /** number of tries */
+ int try;
} passphrase_cb_data_t;
/**
- * Passphrase callback to read from stroke fd
+ * Callback function to receive Passphrases
*/
-chunk_t passphrase_cb(passphrase_cb_data_t *data, int try)
+static shared_key_t* passphrase_cb(passphrase_cb_data_t *data,
+ identification_t *me, identification_t *other,
+ id_match_t *match_me, id_match_t *match_other)
{
- chunk_t secret = chunk_empty;;
+ chunk_t secret;
+ char buf[256];
- 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
+ if (data->try > 1)
{
- fprintf(data->prompt, "invalid passphrase\n");
+ if (data->try > 5)
+ {
+ fprintf(data->prompt, "PIN invalid, giving up.\n");
+ return NULL;
+ }
+ fprintf(data->prompt, "PIN invalid!\n");
}
+ data->try++;
+ fprintf(data->prompt, "Private key '%s' is encrypted.\n", data->path);
fprintf(data->prompt, "Passphrase:\n");
- if (fgets(data->buf, sizeof(data->buf), data->prompt))
+ if (fgets(buf, sizeof(buf), data->prompt))
{
- secret = chunk_create(data->buf, strlen(data->buf));
- if (secret.len)
+ secret = chunk_create(buf, strlen(buf));
+ if (secret.len > 1)
{ /* trim appended \n */
secret.len--;
+ if (match_me)
+ {
+ *match_me = ID_MATCH_PERFECT;
+ }
+ if (match_other)
+ {
+ *match_other = ID_MATCH_NONE;
+ }
+ return shared_key_create(SHARED_PRIVATE_KEY_PASS, chunk_clone(secret));
}
}
- return secret;
+ return NULL;
}
/**
@@ -748,7 +758,7 @@ static shared_key_t* pin_cb(pin_cb_data_t *data,
if (data->try > 1)
{
- fprintf(data->prompt, "PIN invalid, giving up.\n", data->card);
+ fprintf(data->prompt, "PIN invalid, aborting.\n");
return NULL;
}
data->try++;
@@ -859,6 +869,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7))
{
+ free(secret.ptr);
if (!prompt)
{ /* no IO channel to prompt, skip */
free(chunk.ptr);
@@ -933,8 +944,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
{
char path[PATH_MAX];
chunk_t filename;
- chunk_t secret = chunk_empty;
- private_key_t *key = NULL;
+ chunk_t secret;
+ private_key_t *key;
err_t ugh = extract_value(&filename, &line);
@@ -972,23 +983,53 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
}
if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7))
{
- if (prompt)
+ callback_cred_t *cb = NULL;
+ passphrase_cb_data_t pp_data = {
+ .prompt = prompt,
+ .path = path,
+ .try = 1,
+ };
+
+ free(secret.ptr);
+ if (!prompt)
{
- passphrase_cb_data_t data = {
- .prompt = prompt,
- .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);
+ return TRUE;
}
+ /* use callback credential set to prompt for the passphrase */
+ pp_data.prompt = prompt;
+ pp_data.path = path;
+ pp_data.try = 1;
+ cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data);
+ lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+
+ /* unlock, as the builder might ask for a secret */
+ this->lock->unlock(this->lock);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
+ BUILD_FROM_FILE, path, BUILD_END);
+ this->lock->write_lock(this->lock);
+
+ lib->credmgr->remove_local_set(lib->credmgr, &cb->set);
+ cb->destroy(cb);
}
else
{
+ mem_cred_t *mem = NULL;
+ shared_key_t *shared;
+
+ /* provide our pin in a temporary credential set */
+ shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret);
+ mem = mem_cred_create();
+ mem->add_shared(mem, shared, NULL);
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+
+ /* unlock, as the builder might ask for a secret */
+ this->lock->unlock(this->lock);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
- BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE, secret, BUILD_END);
+ BUILD_FROM_FILE, path, BUILD_END);
+ this->lock->write_lock(this->lock);
+
+ lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
+ mem->destroy(mem);
}
if (key)
{
@@ -1000,7 +1041,6 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
{
DBG1(DBG_CFG, " loading private key from '%s' failed", path);
}
- chunk_clear(&secret);
return TRUE;
}
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index 996ce8362..dc87da2a4 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -57,12 +57,6 @@ enum builder_part_t {
BUILD_BLOB_PGP,
/** DNS public key blob (RFC 4034, RSA specifc RFC 3110), chunk_t */
BUILD_BLOB_DNSKEY,
- /** passphrase for e.g. PEM decryption, smartcard unlock, chunk_t */
- BUILD_PASSPHRASE,
- /** passphrase callback, chunk_t(*fn)(void *user, int try), void *user.
- * The callback is invoked until the returned passphrase is accepted, or
- * a zero-length passphrase is returned. Try starts at 1. */
- BUILD_PASSPHRASE_CALLBACK,
/** key size in bits, as used for key generation, u_int */
BUILD_KEY_SIZE,
/** private key to use for signing, private_key_t* */
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index a15c3f258..34527d992 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -167,8 +167,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
/**
* Converts a PEM encoded file into its binary form (RFC 1421, RFC 934)
*/
-static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data,
- bool *pgp)
+static status_t pem_to_bin(chunk_t *blob, bool *pgp)
{
typedef enum {
PEM_PRE = 0,
@@ -187,9 +186,10 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
chunk_t dst = *blob;
chunk_t line = chunk_empty;
chunk_t iv = chunk_empty;
- chunk_t passphrase;
- int try = 0;
u_char iv_buf[HASH_SIZE_MD5];
+ status_t status = NOT_FOUND;
+ enumerator_t *enumerator;
+ shared_key_t *shared;
dst.len = 0;
iv.ptr = iv_buf;
@@ -326,36 +326,35 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
{
return SUCCESS;
}
- if (!cb)
- {
- DBG1(DBG_LIB, " missing passphrase");
- return INVALID_ARG;
- }
- while (TRUE)
+
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_PRIVATE_KEY_PASS, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
{
- passphrase = cb(cb_data, ++try);
- if (!passphrase.len || !passphrase.ptr)
+ chunk_t passphrase, chunk;
+
+ passphrase = shared->get_key(shared);
+ chunk = chunk_clone(*blob);
+ status = pem_decrypt(&chunk, alg, key_size, iv, passphrase);
+ if (status == SUCCESS)
{
- return INVALID_ARG;
+ memcpy(blob->ptr, chunk.ptr, chunk.len);
+ blob->len = chunk.len;
}
- switch (pem_decrypt(blob, alg, key_size, iv, passphrase))
- {
- case INVALID_ARG:
- /* bad passphrase, retry */
- continue;
- case SUCCESS:
- return SUCCESS;
- default:
- return FAILED;
+ free(chunk.ptr);
+ if (status != INVALID_ARG)
+ { /* try again only if passphrase invalid */
+ break;
}
}
+ enumerator->destroy(enumerator);
+ return status;
}
/**
* load the credential from a blob
*/
static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
- chunk_t(*cb)(void*,int), void *cb_data,
x509_flag_t flags)
{
void *cred = NULL;
@@ -364,7 +363,7 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
blob = chunk_clone(blob);
if (!is_asn1(blob))
{
- if (pem_to_bin(&blob, cb, cb_data, &pgp) != SUCCESS)
+ if (pem_to_bin(&blob, &pgp) != SUCCESS)
{
chunk_clear(&blob);
return NULL;
@@ -394,7 +393,6 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
* load the credential from a file
*/
static void *load_from_file(char *file, credential_type_t type, int subtype,
- chunk_t(*cb)(void*,int), void *cb_data,
x509_flag_t flags)
{
void *cred = NULL;
@@ -425,8 +423,7 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
return NULL;
}
- cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype,
- cb, cb_data, flags);
+ cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype, flags);
munmap(addr, sb.st_size);
close(fd);
@@ -437,7 +434,6 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
* load the credential from a file descriptor
*/
static void *load_from_fd(int fd, credential_type_t type, int subtype,
- chunk_t(*cb)(void*,int), void *cb_data,
x509_flag_t flags)
{
char buf[8096];
@@ -464,20 +460,7 @@ static void *load_from_fd(int fd, credential_type_t type, int subtype,
return NULL;
}
}
- return load_from_blob(chunk_create(buf, total), type, subtype,
- cb, cb_data, flags);
-}
-
-/**
- * passphrase callback to use if passphrase given
- */
-static chunk_t given_passphrase_cb(chunk_t *passphrase, int try)
-{
- if (try > 1)
- { /* try only once for given passphrases */
- return chunk_empty;
- }
- return *passphrase;
+ return load_from_blob(chunk_create(buf, total), type, subtype, flags);
}
/**
@@ -487,9 +470,7 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
{
char *file = NULL;
int fd = -1;
- chunk_t pem = chunk_empty, passphrase = chunk_empty;
- chunk_t (*cb)(void *data, int try) = NULL;
- void *cb_data = NULL;
+ chunk_t pem = chunk_empty;
int flags = 0;
while (TRUE)
@@ -505,18 +486,6 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
case BUILD_BLOB_PEM:
pem = va_arg(args, chunk_t);
continue;
- case BUILD_PASSPHRASE:
- passphrase = va_arg(args, chunk_t);
- if (passphrase.len && passphrase.ptr)
- {
- cb = (void*)given_passphrase_cb;
- cb_data = &passphrase;
- }
- continue;
- case BUILD_PASSPHRASE_CALLBACK:
- cb = va_arg(args, chunk_t(*)(void*,int));
- cb_data = va_arg(args, void*);
- continue;
case BUILD_X509_FLAG:
flags = va_arg(args, int);
continue;
@@ -530,15 +499,15 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
if (pem.len)
{
- return load_from_blob(pem, type, subtype, cb, cb_data, flags);
+ return load_from_blob(pem, type, subtype, flags);
}
if (file)
{
- return load_from_file(file, type, subtype, cb, cb_data, flags);
+ return load_from_file(file, type, subtype, flags);
}
if (fd != -1)
{
- return load_from_fd(fd, type, subtype, cb, cb_data, flags);
+ return load_from_fd(fd, type, subtype, flags);
}
return NULL;
}
diff --git a/src/openac/openac.c b/src/openac/openac.c
index 3f28b0ac4..5de8f5b7c 100755
--- a/src/openac/openac.c
+++ b/src/openac/openac.c
@@ -36,6 +36,7 @@
#include <credentials/certificates/x509.h>
#include <credentials/certificates/ac.h>
#include <credentials/keys/private_key.h>
+#include <credentials/sets/mem_cred.h>
#include <utils/optionsfrom.h>
#define OPENAC_PATH IPSEC_CONFDIR "/openac"
@@ -437,10 +438,19 @@ int main(int argc, char **argv)
/* load the signer's RSA private key */
if (keyfile != NULL)
{
+ mem_cred_t *mem;
+ shared_key_t *shared;
+
+ mem = mem_cred_create();
+ lib->credmgr->add_set(lib->credmgr, &mem->set);
+ shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
+ chunk_clone(passphrase));
+ mem->add_shared(mem, shared, NULL);
signerKey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_FROM_FILE, keyfile,
- BUILD_PASSPHRASE, passphrase,
BUILD_END);
+ lib->credmgr->remove_set(lib->credmgr, &mem->set);
+ mem->destroy(mem);
if (signerKey == NULL)
{
goto end;
diff --git a/src/pluto/certs.c b/src/pluto/certs.c
index 24e8ffb27..414f2430a 100644
--- a/src/pluto/certs.c
+++ b/src/pluto/certs.c
@@ -98,90 +98,6 @@ cert_t* cert_add(cert_t *cert)
}
/**
- * Passphrase callback to read from whack fd
- */
-chunk_t whack_pass_cb(prompt_pass_t *pass, int try)
-{
- int n;
-
- if (try > MAX_PROMPT_PASS_TRIALS)
- {
- whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
- return chunk_empty;
- }
- if (try == 1)
- {
- whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
- }
- else
- {
- whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
- }
-
- n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
-
- if (n == -1)
- {
- whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
- return chunk_empty;
- }
-
- pass->secret[n-1] = '\0';
-
- if (strlen(pass->secret) == 0)
- {
- whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
- return chunk_empty;
- }
- return chunk_create(pass->secret, strlen(pass->secret));
-}
-
-/**
- * Loads a PKCS#1 or PGP private key file
- */
-private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
- key_type_t type)
-{
- private_key_t *key = NULL;
- char *path;
-
- path = concatenate_paths(PRIVATE_KEY_PATH, filename);
- if (pass && pass->prompt && pass->fd != NULL_FD)
- { /* use passphrase callback */
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE_CALLBACK, whack_pass_cb, pass,
- BUILD_END);
- if (key)
- {
- whack_log(RC_SUCCESS, "valid passphrase");
- }
- }
- else if (pass)
- { /* use a given passphrase */
- chunk_t password = chunk_create(pass->secret, strlen(pass->secret));
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE, password, BUILD_END);
- }
- else
- { /* no passphrase */
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path, BUILD_END);
-
- }
- if (key)
- {
- plog(" loaded private key from '%s'", filename);
- }
- else
- {
- plog(" syntax error in private key file");
- }
- return key;
-}
-
-/**
* Loads a X.509 or OpenPGP certificate
*/
cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
diff --git a/src/pluto/certs.h b/src/pluto/certs.h
index 21e856a3c..b31c4c3ed 100644
--- a/src/pluto/certs.h
+++ b/src/pluto/certs.h
@@ -65,8 +65,6 @@ extern const cert_t cert_empty;
*/
extern bool no_cr_send;
-extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
- key_type_t type);
extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
extern cert_t* load_host_cert(char *filename);
extern cert_t* load_ca_cert(char *filename);
diff --git a/src/pluto/defs.h b/src/pluto/defs.h
index 8491f4ae8..1eeae28b0 100644
--- a/src/pluto/defs.h
+++ b/src/pluto/defs.h
@@ -66,15 +66,6 @@ extern const char* check_expiry(time_t expiration_date,
#define MAX_PROMPT_PASS_TRIALS 5
#define PROMPT_PASS_LEN 64
-/* struct used to prompt for a secret passphrase
- * from a console with file descriptor fd
- */
-typedef struct {
- char secret[PROMPT_PASS_LEN+1];
- bool prompt;
- int fd;
-} prompt_pass_t;
-
/* filter eliminating the directory entries '.' and '..' */
typedef struct dirent dirent_t;
extern int file_select(const dirent_t *entry);
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 6db757ba7..dc78b0e7f 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -37,6 +37,8 @@
#include <library.h>
#include <asn1/asn1.h>
#include <credentials/certificates/pgp_certificate.h>
+#include <credentials/sets/mem_cred.h>
+#include <credentials/sets/callback_cred.h>
#include "constants.h"
#include "defs.h"
@@ -539,6 +541,123 @@ end:
return ugh;
}
+/* struct used to prompt for a secret passphrase
+ * from a console with file descriptor fd
+ */
+typedef struct {
+ char secret[PROMPT_PASS_LEN+1];
+ bool prompt;
+ int fd;
+ int try;
+} prompt_pass_t;
+
+/**
+ * Passphrase callback to read from whack fd
+ */
+static shared_key_t* whack_pass_cb(prompt_pass_t *pass,
+ identification_t *me, identification_t *other,
+ id_match_t *match_me, id_match_t *match_other)
+{
+ int n;
+
+ if (pass->try > MAX_PROMPT_PASS_TRIALS)
+ {
+ whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
+ return NULL;
+ }
+ if (pass->try == 1)
+ {
+ whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
+ }
+ else
+ {
+ whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
+ }
+ pass->try++;
+
+ n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
+ if (n == -1)
+ {
+ whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
+ return NULL;
+ }
+ pass->secret[n-1] = '\0';
+
+ if (strlen(pass->secret) == 0)
+ {
+ whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
+ return NULL;
+ }
+ if (match_me)
+ {
+ *match_me = ID_MATCH_PERFECT;
+ }
+ if (match_other)
+ {
+ *match_other = ID_MATCH_NONE;
+ }
+ return shared_key_create(SHARED_PRIVATE_KEY_PASS,
+ chunk_clone(chunk_create(pass->secret, strlen(pass->secret))));
+}
+
+/**
+ * Loads a PKCS#1 or PGP private key file
+ */
+static private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+ key_type_t type)
+{
+ private_key_t *key = NULL;
+ char *path;
+
+ path = concatenate_paths(PRIVATE_KEY_PATH, filename);
+ if (pass && pass->prompt && pass->fd != NULL_FD)
+ { /* use passphrase callback */
+ callback_cred_t *cb;
+
+ cb = callback_cred_create_shared((void*)whack_pass_cb, pass);
+ lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path, BUILD_END);
+ lib->credmgr->remove_local_set(lib->credmgr, &cb->set);
+ cb->destroy(cb);
+ if (key)
+ {
+ whack_log(RC_SUCCESS, "valid passphrase");
+ }
+ }
+ else if (pass)
+ { /* use a given passphrase */
+ mem_cred_t *mem;
+ shared_key_t *shared;
+
+ mem = mem_cred_create();
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+ shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
+ chunk_clone(chunk_create(pass->secret, strlen(pass->secret))));
+ mem->add_shared(mem, shared, NULL);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path, BUILD_END);
+ lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
+ mem->destroy(mem);
+ }
+ else
+ { /* no passphrase */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path, BUILD_END);
+
+ }
+ if (key)
+ {
+ plog(" loaded private key from '%s'", filename);
+ }
+ else
+ {
+ plog(" syntax error in private key file");
+ }
+ return key;
+}
+
/**
* process a key file protected with optional passphrase which can either be
* read from ipsec.secrets or prompted for by using whack
@@ -552,6 +671,7 @@ static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
memset(pass.secret,'\0', sizeof(pass.secret));
pass.prompt = FALSE;
pass.fd = whackfd;
+ pass.try = 1;
/* we expect the filename of a PKCS#1 private key file */