From ecef526a51c5a276681472fd6df239570c9ce518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Tue, 7 Nov 2017 16:54:26 +0100 Subject: [PATCH] Stop using crypt_get_error Instead of crypt_get_error, which has been removed in cryptsetup 2.0, set up a log callback, which is available in both older and newer versions. Fixes #13. --- lib/volume_luks.c | 90 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/lib/volume_luks.c b/lib/volume_luks.c index 14794d7..f4bf2c8 100644 --- a/lib/volume_luks.c +++ b/lib/volume_luks.c @@ -61,17 +61,13 @@ my_strerror (int err_no) } /* Set ERROR based on libcryptsetup error state after returning RES. - Use CODE. */ + Use CODE and LAST_LOG_ENTRY. */ static void -error_from_cryptsetup (GError **error, LIBVKError code, int res) +error_from_cryptsetup (GError **error, LIBVKError code, int res, + char *last_log_entry) { - /* It's not possible to get the error message length from libcryptsetup, just - guess. */ - char crypt_msg[4096]; - - crypt_get_error (crypt_msg, sizeof (crypt_msg)); - if (crypt_msg[0] != '\0') - g_set_error (error, LIBVK_ERROR, code, "%s", crypt_msg); + if (last_log_entry != NULL && last_log_entry[0] != '\0') + g_set_error (error, LIBVK_ERROR, code, "%s", last_log_entry); else { char *s; @@ -82,17 +78,33 @@ error_from_cryptsetup (GError **error, LIBVKError code, int res) } } +static void +record_cryptsetup_log_entry (int level, const char *msg, void *usrptr) +{ + char **last_log_entry = usrptr; + + if (level == CRYPT_LOG_ERROR) + { + g_free (*last_log_entry); + *last_log_entry = g_strdup (msg); + } +} + /* Open volume PATH and load its header. + Set up *LAST_LOG_ENTRY to be updated to the last logged message for the + device. The caller must g_free(*LAST_LOG_ENTRY) after closing the device. Return the volume, or NULL on error. */ static struct crypt_device * -open_crypt_device (const char *path, GError **error) +open_crypt_device (const char *path, char **last_log_entry, GError **error) { struct crypt_device *cd; int r; + *last_log_entry = NULL; r = crypt_init (&cd, path); if (r < 0) goto err; + crypt_set_log_callback(cd, record_cryptsetup_log_entry, last_log_entry); r = crypt_load (cd, CRYPT_LUKS1, NULL); if (r < 0) goto err_cd; @@ -101,9 +113,12 @@ open_crypt_device (const char *path, GError **error) err_cd: crypt_free (cd); err: - error_from_cryptsetup (error, LIBVK_ERROR_VOLUME_UNKNOWN_FORMAT, r); + error_from_cryptsetup (error, LIBVK_ERROR_VOLUME_UNKNOWN_FORMAT, r, + *last_log_entry); g_prefix_error (error, _("Error getting information about volume `%s': "), path); + g_free (*last_log_entry); + *last_log_entry = NULL; return NULL; } @@ -173,10 +188,11 @@ luks_volume_open (struct libvk_volume *vol, const char *path, GError **error) { struct luks_volume *luks; struct crypt_device *cd; + char *last_log_entry; const char *uuid; (void)vol; - cd = open_crypt_device (path, error); + cd = open_crypt_device (path, &last_log_entry, error); if (cd == NULL) return NULL; /* A bit of paranoia */ @@ -187,6 +203,7 @@ luks_volume_open (struct libvk_volume *vol, const char *path, GError **error) _("UUID mismatch between libblkid and libcryptsetup: `%s' " "vs. `%s'"), vol->uuid, uuid); crypt_free (cd); + g_free (last_log_entry); return NULL; } @@ -195,6 +212,7 @@ luks_volume_open (struct libvk_volume *vol, const char *path, GError **error) luks->cipher_mode = g_strdup (crypt_get_cipher_mode (cd)); luks->key_bytes = crypt_get_volume_key_size (cd); crypt_free (cd); + g_free (last_log_entry); luks->key = NULL; luks->passphrase = NULL; @@ -256,7 +274,7 @@ luks_get_secret (struct libvk_volume *vol, enum libvk_secret secret_type, const struct libvk_ui *ui, GError **error) { struct crypt_device *cd; - char *passphrase; + char *last_log_entry, *passphrase; void *key; size_t key_length; int slot; @@ -276,7 +294,7 @@ luks_get_secret (struct libvk_volume *vol, enum libvk_secret secret_type, _("Encryption information type unsupported in LUKS")); goto err; } - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) goto err; key_length = crypt_get_volume_key_size (cd); @@ -303,7 +321,7 @@ luks_get_secret (struct libvk_volume *vol, enum libvk_secret secret_type, g_free_passphrase (passphrase); if (r != -EPERM) { - error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r); + error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r, last_log_entry); g_prefix_error (error, _("Error getting LUKS data encryption key: ")); goto err_prompt; } @@ -322,12 +340,14 @@ luks_get_secret (struct libvk_volume *vol, enum libvk_secret secret_type, vol->v.luks->passphrase_slot = slot; g_free (prompt); crypt_free (cd); + g_free (last_log_entry); return 0; err_prompt: g_free (prompt); g_free_key (key, key_length); crypt_free (cd); + g_free (last_log_entry); err: return -1; } @@ -383,11 +403,12 @@ luks_load_packet (struct libvk_volume *vol, const struct libvk_volume *packet, if (packet->v.luks->key != NULL) { struct crypt_device *cd; + char *last_log_entry; int r; g_return_val_if_fail (vol->v.luks->key_bytes == packet->v.luks->key_bytes, -1); - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) return -1; r = crypt_volume_key_verify (cd, packet->v.luks->key, @@ -395,21 +416,25 @@ luks_load_packet (struct libvk_volume *vol, const struct libvk_volume *packet, crypt_free (cd); if (r < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_PACKET_VOLUME_MISMATCH, r); + error_from_cryptsetup (error, LIBVK_ERROR_PACKET_VOLUME_MISMATCH, r, + last_log_entry); g_prefix_error (error, _("LUKS data encryption key in packet is " "invalid: ")); + g_free (last_log_entry); return -1; } + g_free (last_log_entry); luks_replace_key (vol, packet->v.luks->key); } if (packet->v.luks->passphrase != NULL) { struct crypt_device *cd; + char *last_log_entry; void *key; size_t key_size; int r; - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) return -1; key_size = crypt_get_volume_key_size (cd); @@ -420,10 +445,13 @@ luks_load_packet (struct libvk_volume *vol, const struct libvk_volume *packet, crypt_free (cd); if (r < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_PACKET_VOLUME_MISMATCH, r); + error_from_cryptsetup (error, LIBVK_ERROR_PACKET_VOLUME_MISMATCH, r, + last_log_entry); g_prefix_error (error, _("LUKS passphrase in packet is invalid: ")); + g_free (last_log_entry); return -1; } + g_free (last_log_entry); luks_replace_passphrase (vol, packet->v.luks->passphrase); vol->v.luks->passphrase_slot = r; if (packet->v.luks->key == NULL) @@ -446,7 +474,7 @@ luks_apply_secret (struct libvk_volume *vol, const struct libvk_volume *packet, GError **error) { struct crypt_device *cd; - char *prompt, *prompt2, *error_prompt, *passphrase; + char *last_log_entry, *prompt, *prompt2, *error_prompt, *passphrase; unsigned failed; int res; @@ -498,7 +526,7 @@ luks_apply_secret (struct libvk_volume *vol, const struct libvk_volume *packet, goto err_prompts; got_passphrase: - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) goto err_passphrase; res = crypt_keyslot_add_by_volume_key (cd, CRYPT_ANY_SLOT, @@ -508,10 +536,12 @@ luks_apply_secret (struct libvk_volume *vol, const struct libvk_volume *packet, crypt_free (cd); if (res < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_FAILED, res); + error_from_cryptsetup (error, LIBVK_ERROR_FAILED, res, last_log_entry); g_prefix_error (error, _("Error adding a LUKS passphrase")); + g_free (last_log_entry); goto err_passphrase; } + g_free (last_log_entry); g_return_val_if_fail (vol->v.luks->key_bytes == packet->v.luks->key_bytes, -1); @@ -542,6 +572,7 @@ luks_add_secret (struct libvk_volume *vol, enum libvk_secret secret_type, const void *secret, size_t size, GError **error) { struct crypt_device *cd; + char *last_log_entry; int res; if (secret_type != LIBVK_SECRET_PASSPHRASE) @@ -562,7 +593,7 @@ luks_add_secret (struct libvk_volume *vol, enum libvk_secret secret_type, _("The passphrase must be a string")); return -1; } - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) return -1; res = crypt_keyslot_add_by_volume_key (cd, CRYPT_ANY_SLOT, vol->v.luks->key, @@ -570,10 +601,12 @@ luks_add_secret (struct libvk_volume *vol, enum libvk_secret secret_type, crypt_free (cd); if (res < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_FAILED, res); + error_from_cryptsetup (error, LIBVK_ERROR_FAILED, res, last_log_entry); g_prefix_error (error, _("Error adding a LUKS passphrase")); + g_free (last_log_entry); return -1; } + g_free (last_log_entry); luks_replace_passphrase (vol, secret); vol->v.luks->passphrase_slot = res; @@ -823,12 +856,13 @@ luks_open_with_packet (struct libvk_volume *vol, GError **error) { struct crypt_device *cd; + char *last_log_entry; void *to_free; const void *key; int r; size_t key_size; - cd = open_crypt_device (vol->path, error); + cd = open_crypt_device (vol->path, &last_log_entry, error); if (cd == NULL) goto err; if (packet->v.luks->key != NULL) @@ -846,7 +880,7 @@ luks_open_with_packet (struct libvk_volume *vol, strlen (packet->v.luks->passphrase)); if (r < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r); + error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r, last_log_entry); g_prefix_error (error, _("Error getting LUKS data encryption key: ")); goto err_to_free; } @@ -862,7 +896,7 @@ luks_open_with_packet (struct libvk_volume *vol, r = crypt_activate_by_volume_key (cd, name, key, key_size, 0); if (r < 0) { - error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r); + error_from_cryptsetup (error, LIBVK_ERROR_FAILED, r, last_log_entry); g_prefix_error (error, _("Error opening LUKS volume: ")); goto err_to_free; } @@ -870,6 +904,7 @@ luks_open_with_packet (struct libvk_volume *vol, if (to_free != NULL) g_free_key (to_free, key_size); crypt_free (cd); + g_free (last_log_entry); return 0; err_to_free: @@ -877,6 +912,7 @@ luks_open_with_packet (struct libvk_volume *vol, g_free_key (to_free, key_size); err_cd: crypt_free (cd); + g_free (last_log_entry); err: return -1; } -- 2.13.6