[systemd-devel] [PATCH] cryptsetup-generator: support rd.luks.key=keyfile:keyfile_device

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Fri Feb 20 04:37:28 PST 2015


On Fri, Feb 20, 2015 at 11:15:36AM +0100, Przemyslaw Rudy wrote:
> Could you use the rd.luks.key.tout= instead of hardcoded
> JobTimeoutSec=30, as the dracut does?
Maybe we could rename it to rd.luks.key.device-timeout= ? tout is not
really descriptive. (Old name should be kept for comptibility, the new
one should be documented.)

Zbyszek

> On 02/20/2015 10:56 AM, Jan Synacek wrote:
> > To be more consistent with how dracut parses rd.luks.key, it is now
> > allowed to specified it in the format "keyfile[:keyfile_device]".
> > 
> > Should keyfile_device be provided, it needs to be in "UUID=uuid-here"
> > format. Also, keyfile path is then treated relatively to the root of the
> > keyfile device.
> > 
> > If no keyfile_device appears on the command line, keyfile is then
> > treated as an absolute path.
> > 
> > Examples:
> > 
> > rd.luks.key=/etc/key/secret-partition.key
> > 
> > The keyfile is treated as an absolute path.
> > 
> > rd.luks.key=/root.key:UUID=dead-beef
> > 
> > First, the device UUID=dead-beef is temporarily mounted in /mnt and the
> > absolute path to the keyfile is constructed as /mnt/root.key.
> > ---
> >  src/cryptsetup/cryptsetup-generator.c | 163 +++++++++++++++++++++++++++++++---
> >  1 file changed, 150 insertions(+), 13 deletions(-)
> > 
> > diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
> > index 05061c0..3590787 100644
> > --- a/src/cryptsetup/cryptsetup-generator.c
> > +++ b/src/cryptsetup/cryptsetup-generator.c
> > @@ -43,6 +43,12 @@ typedef struct crypto_device {
> >          bool create;
> >  } crypto_device;
> >  
> > +typedef struct key_device {
> > +        const crypto_device *device;
> > +        char *keyfile;
> > +        char *name;
> > +} key_device;
> > +
> >  static const char *arg_dest = "/tmp";
> >  static bool arg_enabled = true;
> >  static bool arg_read_crypttab = true;
> > @@ -50,6 +56,39 @@ static bool arg_whitelist = false;
> >  static Hashmap *arg_disks = NULL;
> >  static char *arg_default_options = NULL;
> >  static char *arg_default_keyfile = NULL;
> > +static key_device *arg_key_device = NULL;
> > +
> > +static char *crypt_service_name_build(const char *name)
> > +{
> > +        _cleanup_free_ char *e = NULL;
> > +
> > +        e = unit_name_escape(name);
> > +        if (!e)
> > +                return e;
> > +
> > +        return unit_name_build("systemd-cryptsetup", e, ".service");
> > +}
> > +
> > +static key_device *get_key_device(void)
> > +{
> > +        key_device *d;
> > +
> > +        if (arg_key_device)
> > +                return arg_key_device;
> > +
> > +        d = new0(struct key_device, 1);
> > +        if (!d)
> > +                return NULL;
> > +
> > +        arg_key_device = d;
> > +        return arg_key_device;
> > +}
> > +
> > +static void free_key_device(key_device *kd)
> > +{
> > +        free(kd->keyfile);
> > +        free(kd->name);
> > +}
> >  
> >  static int create_disk(
> >                  const char *name,
> > @@ -77,11 +116,7 @@ static int create_disk(
> >                  return -EINVAL;
> >          }
> >  
> > -        e = unit_name_escape(name);
> > -        if (!e)
> > -                return log_oom();
> > -
> > -        n = unit_name_build("systemd-cryptsetup", e, ".service");
> > +        n = crypt_service_name_build(name);
> >          if (!n)
> >                  return log_oom();
> >  
> > @@ -233,6 +268,76 @@ static int create_disk(
> >          return 0;
> >  }
> >  
> > +static int create_temporary_mount(void)
> > +{
> > +        _cleanup_fclose_ FILE *f = NULL;
> > +        _cleanup_free_ char *p = NULL, *n = NULL, *c = NULL, *wants_dir = NULL, *to = NULL, *u = NULL;
> > +        const char *m = "mnt.mount";
> > +        key_device *kd;
> > +
> > +        kd = get_key_device();
> > +        if (!kd)
> > +                return log_oom();
> > +
> > +        /* no uuid where we should search for the key was specified */
> > +        if (!kd->name)
> > +                return 0;
> > +
> > +
> > +        if (!kd->device) {
> > +                log_warning("No rd.luks.uuid specified. Can't generate a temporary mount unit");
> > +                return 0;
> > +        }
> > +
> > +        p = strjoin(arg_dest, "/", m, NULL);
> > +        if (!p)
> > +                return log_oom();
> > +
> > +
> > +        f = fopen(p, "wxe");
> > +        if (!f)
> > +                return log_error_errno(errno, "Failed to open %s: %m", p);
> > +
> > +        fprintf(f, "# Automatically generated by systemd-cryptsetup-generator\n\n"
> > +                "[Unit]\n"
> > +                "Description=Temporary keyfile mount point.\n"
> > +                "JobTimeoutSec=30\n");
> > +
> > +        n = strjoin("luks-", kd->device->uuid, NULL);
> > +        if (!n)
> > +                return log_oom();
> > +
> > +        c = crypt_service_name_build(n);
> > +        if (!c)
> > +                return log_oom();
> > +
> > +        u = fstab_node_to_udev_node(kd->name);
> > +        if (!u)
> > +                return log_oom();
> > +
> > +        fprintf(f, "Before=%s\n\n"
> > +                "[Mount]\n"
> > +                "What=%s\n"
> > +                "Where=/mnt\n",
> > +                c, u);
> > +
> > +        wants_dir = strjoin(arg_dest, "/", c, ".wants", NULL);
> > +        if (!wants_dir)
> > +                return log_oom();
> > +
> > +        to = strjoin(wants_dir, "/", m, NULL);
> > +        if (!to)
> > +                return log_oom();
> > +
> > +        if (mkdir_safe(wants_dir, 0700, 0, 0) < 0)
> > +                log_error("Failed to create %s: %m", wants_dir);
> > +
> > +        if (symlink("../mnt.mount", to) < 0)
> > +                return log_error_errno(errno, "Failed to create symlink %s: %m", to);
> > +
> > +        return 0;
> > +}
> > +
> >  static void free_arg_disks(void) {
> >          crypto_device *d;
> >  
> > @@ -282,6 +387,7 @@ static crypto_device *get_crypto_device(const char *uuid) {
> >  static int parse_proc_cmdline_item(const char *key, const char *value) {
> >          int r;
> >          crypto_device *d;
> > +        key_device *kd;
> >          _cleanup_free_ char *uuid = NULL, *uuid_value = NULL;
> >  
> >          if (STR_IN_SET(key, "luks", "rd.luks") && value) {
> > @@ -308,6 +414,12 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
> >  
> >                  d->create = arg_whitelist = true;
> >  
> > +                kd = get_key_device();
> > +                if (!kd)
> > +                        return log_oom();
> > +
> > +                kd->device = d;
> > +
> >          } else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) {
> >  
> >                  r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
> > @@ -324,16 +436,37 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
> >  
> >          } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) {
> >  
> > -                r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
> > -                if (r == 2) {
> > -                        d = get_crypto_device(uuid);
> > -                        if (!d)
> > +                char **parts = NULL;
> > +                int l;
> > +
> > +                parts = strv_split(value, ":");
> > +                if (!parts)
> > +                        return log_oom();
> > +                l = strv_length(parts);
> > +
> > +                if (l > 1) {
> > +                        kd = get_key_device();
> > +                        if (!kd)
> >                                  return log_oom();
> >  
> > -                        free(d->keyfile);
> > -                        d->keyfile = uuid_value;
> > -                        uuid_value = NULL;
> > -                } else if (free_and_strdup(&arg_default_keyfile, value))
> > +                        kd->keyfile = strdup(parts[0]);
> > +                        if (!kd->keyfile)
> > +                                return log_oom();
> > +
> > +                        if (!startswith(parts[1], "UUID="))
> > +                                log_warning("Keyfile device should start with \"UUID=\"");
> > +                        else {
> > +                                kd->name = strdup(parts[1]);
> > +                                if (!kd->name)
> > +                                        return log_oom();
> > +
> > +                                value = strjoin("/mnt", parts[0], NULL);
> > +                                if (!value)
> > +                                        return log_oom();
> > +                        }
> > +                }
> > +
> > +                if (free_and_strdup(&arg_default_keyfile, value) < 0)
> >                          return log_oom();
> >  
> >          } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) {
> > @@ -504,12 +637,16 @@ int main(int argc, char *argv[]) {
> >          if (add_proc_cmdline_devices() < 0)
> >                  goto cleanup;
> >  
> > +        if (create_temporary_mount() < 0)
> > +                goto cleanup;
> > +
> >          r = EXIT_SUCCESS;
> >  
> >  cleanup:
> >          free_arg_disks();
> >          free(arg_default_options);
> >          free(arg_default_keyfile);
> > +        free_key_device(arg_key_device);
> >  
> >          return r;
> >  }
> > 
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list