]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Obseleted BUILD_PASSPHRASE(_CALLBACK) for private key loading, use credential sets
authorMartin Willi <martin@revosec.ch>
Mon, 19 Jul 2010 12:12:05 +0000 (14:12 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Aug 2010 07:26:21 +0000 (09:26 +0200)
src/libcharon/plugins/nm/nm_creds.c
src/libcharon/plugins/nm/nm_creds.h
src/libcharon/plugins/nm/nm_service.c
src/libcharon/plugins/stroke/stroke_cred.c
src/libstrongswan/credentials/builder.h
src/libstrongswan/plugins/pem/pem_builder.c
src/openac/openac.c
src/pluto/certs.c
src/pluto/certs.h
src/pluto/defs.h
src/pluto/keys.c

index 193838e6b1d79a0f4f51a2941b8aa35420d5e0c0..4ee94362fed35c262246b51e79c108a0ec2ac7f5 100644 (file)
@@ -50,6 +50,11 @@ struct private_nm_creds_t {
         */
        char *pass;
 
+       /**
+        * Private key decryption password
+        */
+       char *keypass;
+
        /**
         * users certificate
         */
@@ -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;
 }
 
@@ -369,6 +391,17 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
        this->lock->unlock(this->lock);
 }
 
+/**
+ * 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
  */
@@ -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;
index b55cff31e3e7cd68e81f5883f1d894faacd70fb4..44936dd6a2fafd67f32b213605947d03f3861cab 100644 (file)
@@ -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.
         */
index 07318bbbfd784a49d7e0ba8e08b357061d701882..910b01cc882d8e894d3ecf715e3d6cea62f11846 100644 (file)
@@ -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);
index cfa33a746074b06eac4f16c0d75caaae0d8f4bf7..69e2054f887356114641176017ee7475be20a656 100644 (file)
@@ -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;
 }
 
index 996ce83621f52230cb951c795d9a690e1b9fc616..dc87da2a4d66369d84c4b70acf3f4acd3a149c8a 100644 (file)
@@ -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* */
index a15c3f2588079cc460441b5ec32f02e96ea39b42..34527d9921704c990ecec14a54de5c5e46aabe90 100644 (file)
@@ -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;
 }
index 3f28b0ac4189db121b1592d55ba7485ddfabe3ec..5de8f5b7c2468a57c63cdf28ac5275f731082f27 100755 (executable)
@@ -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;
index 24e8ffb27615d8f96f49c9cf9fdb0078aa004771..414f2430a82fc4450102d3ec5a013cb78a0290b7 100644 (file)
@@ -97,90 +97,6 @@ cert_t* cert_add(cert_t *cert)
        return 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
  */
index 21e856a3c316bb5a80aba0269debbda89a0f79ee..b31c4c3edb9c32d80f7a72c8245f7d783d6d3c1e 100644 (file)
@@ -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);
index 8491f4ae8260f69339f6d376898ba82133963c4e..1eeae28b0942e161fdc21c07411ce8254fe555f9 100644 (file)
@@ -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);
index 6db757ba757ad460ca39ca0a700bd3ac6485f0b8..dc78b0e7fa23a31bd3b9bf6498c5f2cd7d857925 100644 (file)
@@ -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 */