923a60
From 6c45bdd261e027ea78eabb81feaa70f3774bcf2f Mon Sep 17 00:00:00 2001
923a60
From: Harald Hoyer <harald@redhat.com>
923a60
Date: Mon, 1 Jun 2015 17:26:27 +0200
923a60
Subject: [PATCH] cryptsetup: craft a unique ID with the source device
923a60
923a60
If cryptsetup is called with a source device as argv[3], then craft the
923a60
ID for the password agent with a unique device path.
923a60
923a60
If possible "/dev/block/<maj>:<min>" is used, otherwise the original
923a60
argv[3] is used.
923a60
923a60
This enables password agents like petera [1] to provide a password
923a60
according to the source device. The original ID did not carry enough
923a60
information and was more targeted for a human readable string, which
923a60
is specified in the "Message" field anyway.
923a60
923a60
With this patch the ID of the ask.XXX ini file looks like this:
923a60
ID=cryptsetup:/dev/block/<maj>:<min>
923a60
923a60
[1] https://github.com/npmccallum/petera
923a60
923a60
Cherry-picked from: e51b9486d1b59e72c293028fed1384f4e4ef09aa
923a60
Resolves: #1226333
923a60
---
923a60
 src/cryptsetup/cryptsetup.c | 90 ++++++++++++++++++++++++-------------
923a60
 1 file changed, 58 insertions(+), 32 deletions(-)
923a60
923a60
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
923a60
index 3f613d9b65..5dedb073e4 100644
923a60
--- a/src/cryptsetup/cryptsetup.c
923a60
+++ b/src/cryptsetup/cryptsetup.c
923a60
@@ -217,6 +217,23 @@ static void log_glue(int level, const char *msg, void *usrptr) {
923a60
         log_debug("%s", msg);
923a60
 }
923a60
 
923a60
+static int disk_major_minor(const char *path, char **ret) {
923a60
+        struct stat st;
923a60
+
923a60
+        assert(path);
923a60
+
923a60
+        if (stat(path, &st) < 0)
923a60
+                return -errno;
923a60
+
923a60
+        if (!S_ISBLK(st.st_mode))
923a60
+                return -EINVAL;
923a60
+
923a60
+        if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0)
923a60
+                return -errno;
923a60
+
923a60
+        return 0;
923a60
+}
923a60
+
923a60
 static char* disk_description(const char *path) {
923a60
 
923a60
         static const char name_fields[] =
923a60
@@ -278,20 +295,55 @@ static char *disk_mount_point(const char *label) {
923a60
         return NULL;
923a60
 }
923a60
 
923a60
-static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) {
923a60
-        int r;
923a60
+static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) {
923a60
+        int r = 0;
923a60
         char **p;
923a60
         _cleanup_free_ char *text = NULL;
923a60
         _cleanup_free_ char *escaped_name = NULL;
923a60
         char *id;
923a60
+        const char *name = NULL;
923a60
+        _cleanup_free_ char *description = NULL, *name_buffer = NULL,
923a60
+                *mount_point = NULL, *maj_min = NULL;
923a60
 
923a60
-        assert(name);
923a60
+        assert(vol);
923a60
+        assert(src);
923a60
         assert(passwords);
923a60
 
923a60
+        description = disk_description(src);
923a60
+        mount_point = disk_mount_point(vol);
923a60
+
923a60
+        if (description && streq(vol, description)) {
923a60
+                /* If the description string is simply the
923a60
+                 * volume name, then let's not show this
923a60
+                 * twice */
923a60
+                free(description);
923a60
+                description = NULL;
923a60
+        }
923a60
+
923a60
+        if (mount_point && description)
923a60
+                r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point);
923a60
+        else if (mount_point)
923a60
+                r = asprintf(&name_buffer, "%s on %s", vol, mount_point);
923a60
+        else if (description)
923a60
+                r = asprintf(&name_buffer, "%s (%s)", description, vol);
923a60
+
923a60
+        if (r < 0)
923a60
+                return log_oom();
923a60
+
923a60
+        name = name_buffer ? name_buffer : vol;
923a60
+
923a60
         if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0)
923a60
                 return log_oom();
923a60
 
923a60
-        escaped_name = cescape(name);
923a60
+        if (src)
923a60
+                (void) disk_major_minor(src, &maj_min);
923a60
+
923a60
+        if (maj_min) {
923a60
+                escaped_name = maj_min;
923a60
+                maj_min = NULL;
923a60
+        } else
923a60
+                escaped_name = cescape(name);
923a60
+
923a60
         if (!escaped_name)
923a60
                 return log_oom();
923a60
 
923a60
@@ -532,8 +584,7 @@ int main(int argc, char *argv[]) {
923a60
                 unsigned tries;
923a60
                 usec_t until;
923a60
                 crypt_status_info status;
923a60
-                const char *key_file = NULL, *name = NULL;
923a60
-                _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL;
923a60
+                const char *key_file = NULL;
923a60
 
923a60
                 /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
923a60
 
923a60
@@ -561,31 +612,6 @@ int main(int argc, char *argv[]) {
923a60
                 /* A delicious drop of snake oil */
923a60
                 mlockall(MCL_FUTURE);
923a60
 
923a60
-                description = disk_description(argv[3]);
923a60
-                mount_point = disk_mount_point(argv[2]);
923a60
-
923a60
-                if (description && streq(argv[2], description)) {
923a60
-                        /* If the description string is simply the
923a60
-                         * volume name, then let's not show this
923a60
-                         * twice */
923a60
-                        free(description);
923a60
-                        description = NULL;
923a60
-                }
923a60
-
923a60
-                k = 0;
923a60
-                if (mount_point && description)
923a60
-                        k = asprintf(&name_buffer, "%s (%s) on %s", description, argv[2], mount_point);
923a60
-                else if (mount_point)
923a60
-                        k = asprintf(&name_buffer, "%s on %s", argv[2], mount_point);
923a60
-                else if (description)
923a60
-                        k = asprintf(&name_buffer, "%s (%s)", description, argv[2]);
923a60
-
923a60
-                if (k < 0) {
923a60
-                        log_oom();
923a60
-                        goto finish;
923a60
-                }
923a60
-                name = name_buffer ? name_buffer : argv[2];
923a60
-
923a60
                 if (arg_header) {
923a60
                         log_debug("LUKS header: %s", arg_header);
923a60
                         k = crypt_init(&cd, arg_header);
923a60
@@ -632,7 +658,7 @@ int main(int argc, char *argv[]) {
923a60
                         _cleanup_strv_free_ char **passwords = NULL;
923a60
 
923a60
                         if (!key_file) {
923a60
-                                k = get_password(name, until, tries == 0 && !arg_verify, &passwords);
923a60
+                                k = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
923a60
                                 if (k == -EAGAIN)
923a60
                                         continue;
923a60
                                 else if (k < 0)