]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/cryptsetup/cryptsetup-generator.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup-generator.c
index 9ecb6e3566a25e895b5787e4ce90fb51250e1786..f5a81829b9d75ec05b25fa3a5c919b85c2f4666d 100644 (file)
@@ -1,23 +1,7 @@
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
+#include <stdio_ext.h>
 
 #include "alloc-util.h"
 #include "dropin.h"
@@ -31,6 +15,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "proc-cmdline.h"
+#include "specifier.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unit-name.h"
@@ -58,11 +43,11 @@ static int create_disk(
                 const char *password,
                 const char *options) {
 
-        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *e = NULL,
-                *filtered = NULL;
+        _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
+                *filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         const char *dmname;
-        bool noauto, nofail, tmp, swap;
+        bool noauto, nofail, tmp, swap, netdev;
         int r;
 
         assert(name);
@@ -72,54 +57,66 @@ 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);
                 return -EINVAL;
         }
 
+        name_escaped = specifier_escape(name);
+        if (!name_escaped)
+                return log_oom();
+
         e = unit_name_escape(name);
         if (!e)
                 return log_oom();
 
+        u = fstab_node_to_udev_node(device);
+        if (!u)
+                return log_oom();
+
         r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
         if (r < 0)
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
-        p = strjoin(arg_dest, "/", n);
-        if (!p)
-                return log_oom();
-
-        u = fstab_node_to_udev_node(device);
-        if (!u)
+        u_escaped = specifier_escape(u);
+        if (!u_escaped)
                 return log_oom();
 
         r = unit_name_from_path(u, ".device", &d);
         if (r < 0)
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
-        f = fopen(p, "wxe");
-        if (!f)
-                return log_error_errno(errno, "Failed to create unit file %s: %m", p);
-
-        fputs_unlocked("# Automatically generated by systemd-cryptsetup-generator\n\n"
-                       "[Unit]\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"
-                       "IgnoreOnIsolate=true\n"
-                       "After=cryptsetup-pre.target\n",
-                       f);
+        if (password) {
+                password_escaped = specifier_escape(password);
+                if (!password_escaped)
+                        return log_oom();
+        }
+
+        r = generator_open_unit_file(arg_dest, NULL, n, &f);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "[Unit]\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"
+                "IgnoreOnIsolate=true\n"
+                "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_unlocked("After=systemd-random-seed.service\n", f);
+                        fputs("After=systemd-random-seed.service\n", f);
                 else if (!STR_IN_SET(password, "-", "none")) {
                         _cleanup_free_ char *uu;
 
@@ -129,7 +126,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);
@@ -138,12 +135,12 @@ static int create_disk(
 
                                         fprintf(f, "After=%1$s\nRequires=%1$s\n", dd);
                                 } else
-                                        fprintf(f, "RequiresMountsFor=%s\n", password);
+                                        fprintf(f, "RequiresMountsFor=%s\n", password_escaped);
                         }
                 }
         }
 
-        if (is_device_path(u)) {
+        if (path_startswith(u, "/dev/")) {
                 fprintf(f,
                         "BindsTo=%s\n"
                         "After=%s\n"
@@ -151,47 +148,55 @@ static int create_disk(
                         d, d);
 
                 if (swap)
-                        fputs_unlocked("Before=dev-mapper-%i.swap\n",
-                                       f);
+                        fputs("Before=dev-mapper-%i.swap\n",
+                              f);
         } else
                 fprintf(f,
                         "RequiresMountsFor=%s\n",
-                        u);
+                        u_escaped);
 
         r = generator_write_timeouts(arg_dest, device, name, options, &filtered);
         if (r < 0)
                 return r;
 
+        if (filtered) {
+                filtered_escaped = specifier_escape(filtered);
+                if (!filtered_escaped)
+                        return log_oom();
+        }
+
         fprintf(f,
                 "\n[Service]\n"
                 "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),
-                name);
+                name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped),
+                name_escaped);
 
         if (tmp)
                 fprintf(f,
                         "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
-                        name);
+                        name_escaped);
 
         if (swap)
                 fprintf(f,
                         "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
-                        name);
+                        name_escaped);
 
         r = fflush_and_check(f);
         if (r < 0)
-                return log_error_errno(r, "Failed to write file %s: %m", p);
+                return log_error_errno(r, "Failed to write unit file %s: %m", n);
 
         if (!noauto) {
                 r = generator_add_symlink(arg_dest, d, "wants", n);
                 if (r < 0)
                         return r;
 
-                r = generator_add_symlink(arg_dest, "cryptsetup.target",
+                r = generator_add_symlink(arg_dest,
+                                          netdev ? "remote-cryptsetup.target" : "cryptsetup.target",
                                           nofail ? "wants" : "requires", n);
                 if (r < 0)
                         return r;
@@ -213,18 +218,12 @@ static int create_disk(
         return 0;
 }
 
-static void free_arg_disks(void) {
-        crypto_device *d;
-
-        while ((d = hashmap_steal_first(arg_disks))) {
-                free(d->uuid);
-                free(d->keyfile);
-                free(d->name);
-                free(d->options);
-                free(d);
-        }
-
-        hashmap_free(arg_disks);
+static void crypt_device_free(crypto_device *d) {
+        free(d->uuid);
+        free(d->keyfile);
+        free(d->name);
+        free(d->options);
+        free(d);
 }
 
 static crypto_device *get_crypto_device(const char *uuid) {
@@ -331,9 +330,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
                         d->create = arg_whitelist = true;
 
-                        free(d->name);
-                        d->name = uuid_value;
-                        uuid_value = NULL;
+                        free_and_replace(d->name, uuid_value);
                 } else
                         log_warning("Failed to parse luks name switch %s. Ignoring.", value);
         }
@@ -356,6 +353,8 @@ static int add_crypttab_devices(void) {
                 return 0;
         }
 
+        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
         if (fstat(fileno(f), &st) < 0) {
                 log_error_errno(errno, "Failed to stat /etc/crypttab: %m");
                 return 0;
@@ -373,7 +372,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);
@@ -454,7 +453,8 @@ int main(int argc, char *argv[]) {
         if (argc > 1)
                 arg_dest = argv[1];
 
-        log_set_target(LOG_TARGET_SAFE);
+        log_set_prohibit_ipc(true);
+        log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
         log_open();
 
@@ -488,7 +488,7 @@ int main(int argc, char *argv[]) {
         r = 0;
 
 finish:
-        free_arg_disks();
+        hashmap_free_with_destructor(arg_disks, crypt_device_free);
         free(arg_default_options);
         free(arg_default_keyfile);