]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/cryptsetup/cryptsetup-generator.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup-generator.c
index ae53bac60094f78dbef6a3b8c5338d7c74e0bdac..7918c89564fafafb2f40985eb214ce85e52f4235 100644 (file)
@@ -1,5 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -60,11 +59,11 @@ static int create_disk(
                 const char *password,
                 const char *options) {
 
-        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL,
+        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *e = NULL,
                 *filtered = NULL;
         _cleanup_fclose_ FILE *f = NULL;
-        bool noauto, nofail, tmp, swap;
-        char *from;
+        const char *dmname;
+        bool noauto, nofail, tmp, swap, netdev;
         int r;
 
         assert(name);
@@ -74,6 +73,7 @@ static int create_disk(
         nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
         tmp = fstab_test_option(options, "tmp\0");
         swap = fstab_test_option(options, "swap\0");
+        netdev = fstab_test_option(options, "_netdev\0");
 
         if (tmp && swap) {
                 log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
@@ -88,7 +88,7 @@ static int create_disk(
         if (r < 0)
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
-        p = strjoin(arg_dest, "/", n, NULL);
+        p = strjoin(arg_dest, "/", n);
         if (!p)
                 return log_oom();
 
@@ -104,27 +104,27 @@ static int create_disk(
         if (!f)
                 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
 
-        fputs(
+        fprintf(f,
                 "# Automatically generated by systemd-cryptsetup-generator\n\n"
                 "[Unit]\n"
-                "Description=Cryptography Setup for %I\n"
+                "Description=Cryptography Setup for %%I\n"
                 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
                 "SourcePath=/etc/crypttab\n"
                 "DefaultDependencies=no\n"
                 "Conflicts=umount.target\n"
-                "BindsTo=dev-mapper-%i.device\n"
                 "IgnoreOnIsolate=true\n"
-                "After=cryptsetup-pre.target\n",
-                f);
+                "After=%s\n",
+                netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
 
         if (!nofail)
                 fprintf(f,
-                        "Before=cryptsetup.target\n");
+                        "Before=%s\n",
+                        netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
 
         if (password) {
                 if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random"))
-                        fputs("After=systemd-random-seed.service\n", f);
-                else if (!streq(password, "-") && !streq(password, "none")) {
+                        fputs_unlocked("After=systemd-random-seed.service\n", f);
+                else if (!STR_IN_SET(password, "-", "none")) {
                         _cleanup_free_ char *uu;
 
                         uu = fstab_node_to_udev_node(password);
@@ -133,7 +133,7 @@ static int create_disk(
 
                         if (!path_equal(uu, "/dev/null")) {
 
-                                if (is_device_path(uu)) {
+                                if (path_startswith(uu, "/dev/")) {
                                         _cleanup_free_ char *dd = NULL;
 
                                         r = unit_name_from_path(uu, ".device", &dd);
@@ -147,13 +147,17 @@ static int create_disk(
                 }
         }
 
-        if (is_device_path(u))
+        if (path_startswith(u, "/dev/")) {
                 fprintf(f,
                         "BindsTo=%s\n"
                         "After=%s\n"
                         "Before=umount.target\n",
                         d, d);
-        else
+
+                if (swap)
+                        fputs_unlocked("Before=dev-mapper-%i.swap\n",
+                                       f);
+        } else
                 fprintf(f,
                         "RequiresMountsFor=%s\n",
                         u);
@@ -167,6 +171,7 @@ static int create_disk(
                 "Type=oneshot\n"
                 "RemainAfterExit=yes\n"
                 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
+                "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
                 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
                 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
                 name, u, strempty(password), strempty(filtered),
@@ -186,46 +191,24 @@ static int create_disk(
         if (r < 0)
                 return log_error_errno(r, "Failed to write file %s: %m", p);
 
-        from = strjoina("../", n);
-
         if (!noauto) {
+                r = generator_add_symlink(arg_dest, d, "wants", n);
+                if (r < 0)
+                        return r;
 
-                to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
-                if (!to)
-                        return log_oom();
-
-                mkdir_parents_label(to, 0755);
-                if (symlink(from, to) < 0)
-                        return log_error_errno(errno, "Failed to create symlink %s: %m", to);
-
-                free(to);
-                if (!nofail)
-                        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
-                else
-                        to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
-                if (!to)
-                        return log_oom();
-
-                mkdir_parents_label(to, 0755);
-                if (symlink(from, to) < 0)
-                        return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+                r = generator_add_symlink(arg_dest,
+                                          netdev ? "remote-cryptsetup.target" : "cryptsetup.target",
+                                          nofail ? "wants" : "requires", n);
+                if (r < 0)
+                        return r;
         }
 
-        free(to);
-        to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
-        if (!to)
-                return log_oom();
-
-        mkdir_parents_label(to, 0755);
-        if (symlink(from, to) < 0)
-                return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+        dmname = strjoina("dev-mapper-", e, ".device");
+        r = generator_add_symlink(arg_dest, dmname, "requires", n);
+        if (r < 0)
+                return r;
 
         if (!noauto && !nofail) {
-                _cleanup_free_ char *dmname;
-                dmname = strjoin("dev-mapper-", e, ".device", NULL);
-                if (!dmname)
-                        return log_oom();
-
                 r = write_drop_in(arg_dest, dmname, 90, "device-timeout",
                                   "# Automatically generated by systemd-cryptsetup-generator \n\n"
                                   "[Unit]\nJobTimeoutSec=0");
@@ -266,44 +249,44 @@ static crypto_device *get_crypto_device(const char *uuid) {
                 d->keyfile = d->options = d->name = NULL;
 
                 d->uuid = strdup(uuid);
-                if (!d->uuid) {
-                        free(d);
-                        return NULL;
-                }
+                if (!d->uuid)
+                        return mfree(d);
 
                 r = hashmap_put(arg_disks, d->uuid, d);
                 if (r < 0) {
                         free(d->uuid);
-                        free(d);
-                        return NULL;
+                        return mfree(d);
                 }
         }
 
         return d;
 }
 
-static int parse_proc_cmdline_item(const char *key, const char *value) {
-        int r;
-        crypto_device *d;
+static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
         _cleanup_free_ char *uuid = NULL, *uuid_value = NULL;
+        crypto_device *d;
+        int r;
 
-        if (STR_IN_SET(key, "luks", "rd.luks") && value) {
+        if (streq(key, "luks")) {
 
-                r = parse_boolean(value);
+                r = value ? parse_boolean(value) : 1;
                 if (r < 0)
-                        log_warning("Failed to parse luks switch %s. Ignoring.", value);
+                        log_warning("Failed to parse luks= kernel command line switch %s. Ignoring.", value);
                 else
                         arg_enabled = r;
 
-        } else if (STR_IN_SET(key, "luks.crypttab", "rd.luks.crypttab") && value) {
+        } else if (streq(key, "luks.crypttab")) {
 
-                r = parse_boolean(value);
+                r = value ? parse_boolean(value) : 1;
                 if (r < 0)
-                        log_warning("Failed to parse luks crypttab switch %s. Ignoring.", value);
+                        log_warning("Failed to parse luks.crypttab= kernel command line switch %s. Ignoring.", value);
                 else
                         arg_read_crypttab = r;
 
-        } else if (STR_IN_SET(key, "luks.uuid", "rd.luks.uuid") && value) {
+        } else if (streq(key, "luks.uuid")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
 
                 d = get_crypto_device(startswith(value, "luks-") ? value+5 : value);
                 if (!d)
@@ -311,7 +294,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
 
                 d->create = arg_whitelist = true;
 
-        } else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) {
+        } else if (streq(key, "luks.options")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
 
                 r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
                 if (r == 2) {
@@ -319,13 +305,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                         if (!d)
                                 return log_oom();
 
-                        free(d->options);
-                        d->options = uuid_value;
-                        uuid_value = NULL;
+                        free_and_replace(d->options, uuid_value);
                 } else if (free_and_strdup(&arg_default_options, value) < 0)
                         return log_oom();
 
-        } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) {
+        } else if (streq(key, "luks.key")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
 
                 r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
                 if (r == 2) {
@@ -333,13 +320,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                         if (!d)
                                 return log_oom();
 
-                        free(d->keyfile);
-                        d->keyfile = uuid_value;
-                        uuid_value = NULL;
+                        free_and_replace(d->keyfile, uuid_value);
                 } else if (free_and_strdup(&arg_default_keyfile, value) < 0)
                         return log_oom();
 
-        } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) {
+        } else if (streq(key, "luks.name")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
 
                 r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
                 if (r == 2) {
@@ -354,7 +342,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                         uuid_value = NULL;
                 } else
                         log_warning("Failed to parse luks name switch %s. Ignoring.", value);
-
         }
 
         return 0;
@@ -392,7 +379,7 @@ static int add_crypttab_devices(void) {
                 crypttab_line++;
 
                 l = strstrip(line);
-                if (*l == '#' || *l == 0)
+                if (IN_SET(*l, 0, '#'))
                         continue;
 
                 k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyfile, &options);
@@ -463,7 +450,7 @@ static int add_proc_cmdline_devices(void) {
 }
 
 int main(int argc, char *argv[]) {
-        int r = EXIT_FAILURE;
+        int r;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
@@ -480,32 +467,36 @@ int main(int argc, char *argv[]) {
         umask(0022);
 
         arg_disks = hashmap_new(&string_hash_ops);
-        if (!arg_disks)
-                goto cleanup;
+        if (!arg_disks) {
+                r = log_oom();
+                goto finish;
+        }
 
-        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
         if (r < 0) {
-                log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
-                r = EXIT_FAILURE;
+                log_warning_errno(r, "Failed to parse kernel command line: %m");
+                goto finish;
         }
 
         if (!arg_enabled) {
-                r = EXIT_SUCCESS;
-                goto cleanup;
+                r = 0;
+                goto finish;
         }
 
-        if (add_crypttab_devices() < 0)
-                goto cleanup;
+        r = add_crypttab_devices();
+        if (r < 0)
+                goto finish;
 
-        if (add_proc_cmdline_devices() < 0)
-                goto cleanup;
+        r = add_proc_cmdline_devices();
+        if (r < 0)
+                goto finish;
 
-        r = EXIT_SUCCESS;
+        r = 0;
 
-cleanup:
+finish:
         free_arg_disks();
         free(arg_default_options);
         free(arg_default_keyfile);
 
-        return r;
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }