* Fix password callback call.
authorMilan Broz <gmazyland@gmail.com>
Sat, 13 Nov 2010 16:41:20 +0000 (16:41 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sat, 13 Nov 2010 16:41:20 +0000 (16:41 +0000)
* Fix default plain password entry from terminal in activate_by_passphrase.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@362 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
lib/libcryptsetup.h
lib/setup.c
tests/api-test.c

index 6095f74..9ff38de 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-11-13  Milan Broz  <mbroz@redhat.com>
+       * Fix password callback call.
+       * Fix default plain password entry from terminal in activate_by_passphrase.
+
 2010-11-01  Milan Broz  <mbroz@redhat.com>
        * No longer support luksDelKey, reload and --non-exclusive.
        * Remove some obsolete info from man page.
index e138acc..78e0c89 100644 (file)
@@ -88,7 +88,7 @@ void crypt_set_confirm_callback(struct crypt_device *cd,
  * - Note that if this function is defined, verify option is ignored
  *   (caller whch provided callback is responsible fo password verification)
  * - Only zero terminated passwords can be enteted this way, for complex
- *   API functions directly.
+ *   use API functions directly.
  * - Maximal length of password is limited to @length-1 (minimal 511 chars)
  */
 void crypt_set_password_callback(struct crypt_device *cd,
index b10c920..ef9b08f 100644 (file)
@@ -95,7 +95,12 @@ static char *process_key(struct crypt_device *cd, const char *hash_name,
                         const char *key_file, size_t key_size,
                         const char *pass, size_t passLen)
 {
-       char *key = crypt_safe_alloc(key_size);
+       char *key;
+
+       if (!key_size)
+               return NULL;
+
+       key = crypt_safe_alloc(key_size);
        memset(key, 0, key_size);
 
        /* key is coming from binary file */
@@ -369,12 +374,14 @@ static int create_device_helper(struct crypt_device *cd,
                return -ENOMEM;
 
        processed_key = process_key(cd, hash, key_file, key_size, key, keyLen);
-       if (!processed_key)
-               return -ENOENT;
+       if (!processed_key) {
+               r = -ENOENT;
+               goto out;
+       }
 
        r = dm_create_device(name, cd->device, dm_cipher ?: cipher, cd->type, uuid, size, skip, offset,
                             key_size, processed_key, read_only, reload);
-
+out:
        free(dm_cipher);
        crypt_safe_free(processed_key);
        return r;
@@ -433,13 +440,24 @@ int crypt_confirm(struct crypt_device *cd, const char *msg)
 static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
                              unsigned int *key_len, int force_verify)
 {
+       char *prompt = NULL;
        int r;
 
+       *key = NULL;
+       if(!msg && asprintf(&prompt, _("Enter passphrase for %s: "),
+                           cd->device) < 0)
+               return;
+
+       if (!msg)
+               msg = prompt;
+
        if (cd->password) {
                *key = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
-               if (*key)
+               if (!*key) {
+                       free(prompt);
                        return;
-               r = cd->password(msg, *key, (size_t)key_len, cd->password_usrptr);
+               }
+               r = cd->password(msg, *key, MAX_TTY_PASSWORD_LEN, cd->password_usrptr);
                if (r < 0) {
                        crypt_safe_free(*key);
                        *key = NULL;
@@ -448,25 +466,24 @@ static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
        } else
                crypt_get_key(msg, key, key_len, 0, NULL, cd->timeout,
                              (force_verify || cd->password_verify), cd);
+
+       free(prompt);
 }
 
 static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot,
                                             struct volume_key **vk)
 {
-       char *prompt = NULL, *passphrase_read = NULL;
+       char *passphrase_read = NULL;
        unsigned int passphrase_size_read;
        int r = -EINVAL, tries = cd->tries;
 
-       if(asprintf(&prompt, _("Enter passphrase for %s: "), cd->device) < 0)
-               return -ENOMEM;
-
        *vk = NULL;
        do {
                if (*vk)
                        crypt_free_volume_key(*vk);
                *vk = NULL;
 
-               key_from_terminal(cd, prompt, &passphrase_read,
+               key_from_terminal(cd, NULL, &passphrase_read,
                                  &passphrase_size_read, 0);
                if(!passphrase_read) {
                        r = -EINVAL;
@@ -483,10 +500,8 @@ static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslo
                crypt_free_volume_key(*vk);
                *vk = NULL;
        }
-       free(prompt);
 
        return r;
-
 }
 
 static void key_from_file(struct crypt_device *cd, char *msg,
@@ -1747,20 +1762,13 @@ int crypt_activate_by_passphrase(struct crypt_device *cd,
 {
        crypt_status_info ci;
        struct volume_key *vk = NULL;
-       char *prompt = NULL;
+       char *read_passphrase = NULL;
        int r;
 
        log_dbg("%s volume %s [keyslot %d] using %spassphrase.",
                name ? "Activating" : "Checking", name ?: "",
                keyslot, passphrase ? "" : "[none] ");
 
-       /* plain, use hashed passphrase */
-       if (isPLAIN(cd->type))
-               return create_device_helper(cd, name, cd->plain_hdr.hash,
-                       cd->plain_cipher, cd->plain_cipher_mode, NULL, passphrase, passphrase_size,
-                       cd->volume_key->keylength, 0, cd->plain_hdr.skip,
-                       cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
-
        if (name) {
                ci = crypt_status(NULL, name);
                if (ci == CRYPT_INVALID)
@@ -1771,24 +1779,43 @@ int crypt_activate_by_passphrase(struct crypt_device *cd,
                }
        }
 
-       if(asprintf(&prompt, _("Enter passphrase for %s: "), cd->device) < 0)
-               return -ENOMEM;
+       /* plain, use hashed passphrase */
+       if (isPLAIN(cd->type)) {
+               if (!passphrase) {
+                       key_from_terminal(cd, NULL, &read_passphrase,
+                                         &passphrase_size, 0);
+                       if (!read_passphrase) {
+                               r = -EINVAL;
+                               goto out;
+                       }
+                       passphrase = read_passphrase;
+               }
+               r = create_device_helper(cd, name, cd->plain_hdr.hash,
+                                        cd->plain_cipher, cd->plain_cipher_mode,
+                                        NULL, passphrase, passphrase_size,
+                                        cd->volume_key->keylength, 0,
+                                        cd->plain_hdr.skip, cd->plain_hdr.offset,
+                                        cd->plain_uuid,
+                                        flags & CRYPT_ACTIVATE_READONLY, 0, 0);
+               keyslot = 0;
+       } else if (isLUKS(cd->type)) {
+               /* provided passphrase, do not retry */
+               if (passphrase) {
+                       r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
+                                                  passphrase_size, &cd->hdr, &vk, cd);
+               } else
+                       r = volume_key_by_terminal_passphrase(cd, keyslot, &vk);
 
-       /* provided passphrase, do not retry */
-       if (passphrase) {
-               r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
-                                          passphrase_size, &cd->hdr, &vk, cd);
+               if (r >= 0) {
+                       keyslot = r;
+                       if (name)
+                               r = open_from_hdr_and_vk(cd, vk, name, flags);
+               }
        } else
-               r = volume_key_by_terminal_passphrase(cd, keyslot, &vk);
-
-       if (r >= 0) {
-               keyslot = r;
-               if (name)
-                       r = open_from_hdr_and_vk(cd, vk, name, flags);
-       }
-
+               r = -EINVAL;
+out:
+       crypt_safe_free(read_passphrase);
        crypt_free_volume_key(vk);
-       free(prompt);
 
        return r < 0  ? r : keyslot;
 }
@@ -1860,6 +1887,9 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
 
        log_dbg("Activating volume %s by volume key.", name);
 
+       if (!volume_key_size)
+               return -EINVAL;
+
        /* use key directly, no hash */
        if (isPLAIN(cd->type))
                return create_device_helper(cd, name, NULL,
index d217342..25170aa 100644 (file)
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <linux/fs.h>
 #include <errno.h>
+#include <assert.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 
@@ -52,6 +53,8 @@
 #define KEYFILE2 "key2.file"
 #define KEY2 "0123456789abcdef"
 
+#define PASSPHRASE "blabla"
+
 #define DEVICE_TEST_UUID "12345678-1234-1234-1234-123456789abc"
 
 static int _debug   = 0;
@@ -539,7 +542,7 @@ static void AddDevicePlain(void)
        int fd;
        char key[128], key2[128], path[128];
 
-       char *passphrase = "blabla";
+       char *passphrase = PASSPHRASE;
        char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
        size_t key_size = strlen(mk_hex) / 2;
        char *cipher = "aes";
@@ -598,6 +601,64 @@ static void AddDevicePlain(void)
        crypt_free(cd);
 }
 
+#define CALLBACK_ERROR "calback_error xyz"
+static int pass_callback_err(const char *msg, char *buf, size_t length, void *usrptr)
+{
+       struct crypt_device *cd = usrptr;
+
+       assert(cd);
+       assert(length);
+       assert(msg);
+
+       crypt_log(cd, CRYPT_LOG_ERROR, CALLBACK_ERROR);
+       return -EINVAL;
+}
+
+static int pass_callback_ok(const char *msg, char *buf, size_t length, void *usrptr)
+{
+       assert(length);
+       assert(msg);
+       strcpy(buf, PASSPHRASE);
+       return strlen(buf);
+}
+
+static void CallbacksTest(void)
+{
+       struct crypt_device *cd;
+       struct crypt_params_plain params = {
+               .hash = "sha1",
+               .skip = 0,
+               .offset = 0,
+       };
+
+       size_t key_size = 256 / 8;
+       char *cipher = "aes";
+       char *cipher_mode = "cbc-essiv:sha256";
+       char *passphrase = PASSPHRASE;
+
+       OK_(crypt_init(&cd, DEVICE_1));
+       crypt_set_log_callback(cd, &new_log, NULL);
+       //crypt_set_log_callback(cd, NULL, NULL);
+
+       OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+       EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+
+       reset_log();
+       crypt_set_password_callback(cd, pass_callback_err, cd);
+       FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, NULL, 0, 0), "callback fails");
+       EQ_(strncmp(global_log, CALLBACK_ERROR, strlen(CALLBACK_ERROR)), 0);
+
+       crypt_set_password_callback(cd, pass_callback_ok, NULL);
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, NULL, 0, 0));
+       EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+
+       crypt_free(cd);
+}
+
 static void UseLuksDevice(void)
 {
        struct crypt_device *cd;
@@ -817,6 +878,7 @@ int main (int argc, char *argv[])
        crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
 
        RUN_(NonFIPSAlg, "Crypto is properly initialised in format"); //must be the first!
+
        RUN_(LuksUUID, "luksUUID API call");
        RUN_(IsLuks, "isLuks API call");
        RUN_(LuksOpen, "luksOpen API call");
@@ -831,6 +893,8 @@ int main (int argc, char *argv[])
        RUN_(UseLuksDevice, "Use pre-formated LUKS device");
        RUN_(SuspendDevice, "Suspend/Resume test");
 
+       RUN_(CallbacksTest, "API callbacks test");
+
        _cleanup();
        return 0;
 }