[systemd-commits] 5 commits - .gitignore Makefile.am src/99-systemd.rules src/ask-password-api.c src/ask-password-api.h src/cryptsetup.c src/cryptsetup-generator.c src/load-fragment.c src/test-strv.c TODO

Lennart Poettering lennart at kemper.freedesktop.org
Sun Nov 14 10:59:44 PST 2010


 .gitignore                 |    1 
 Makefile.am                |   12 ++
 TODO                       |   16 +--
 src/99-systemd.rules       |    2 
 src/ask-password-api.c     |   10 +
 src/ask-password-api.h     |    2 
 src/cryptsetup-generator.c |    3 
 src/cryptsetup.c           |  226 ++++++++++++++++++++++++++++++++++-----------
 src/load-fragment.c        |   10 -
 src/test-strv.c            |   41 ++++++++
 10 files changed, 251 insertions(+), 72 deletions(-)

New commits:
commit f90cf44c02ac09469279126e2863a1e71358ee11
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 14 19:58:33 2010 +0100

    load-fragment: properly do comparison of words

diff --git a/.gitignore b/.gitignore
index 21dd394..d5c667a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+test-strv
 systemd-ac-power
 systemd-timestamp
 systemd-cryptsetup
diff --git a/Makefile.am b/Makefile.am
index 8c92256..e008cc7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -137,7 +137,8 @@ noinst_PROGRAMS = \
 	test-hostname \
 	test-daemon \
 	test-cgroup \
-	test-env-replace
+	test-env-replace \
+	test-strv
 
 if HAVE_PAM
 pamlib_LTLIBRARIES = \
@@ -619,6 +620,15 @@ test_env_replace_CFLAGS = \
 test_env_replace_LDADD = \
 	libsystemd-basic.la
 
+test_strv_SOURCES = \
+	src/test-strv.c
+
+test_strv_CFLAGS = \
+	$(AM_CFLAGS)
+
+test_strv_LDADD = \
+	libsystemd-basic.la
+
 systemd_logger_SOURCES = \
 	src/logger.c \
 	src/sd-daemon.c \
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 424e6c3..9b39d91 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -433,7 +433,7 @@ static int config_parse_exec(
 
                 k = 0;
                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
-                        if (strncmp(w, ";", l) == 0)
+                        if (strncmp(w, ";", MAX(l, 1U)) == 0)
                                 break;
 
                         k++;
@@ -444,7 +444,7 @@ static int config_parse_exec(
 
                 k = 0;
                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
-                        if (strncmp(w, ";", l) == 0)
+                        if (strncmp(w, ";", MAX(l, 1U)) == 0)
                                 break;
 
                         if (honour_argv0 && w == rvalue) {
@@ -1077,11 +1077,11 @@ static int config_parse_mount_flags(
         assert(data);
 
         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
-                if (strncmp(w, "shared", l) == 0)
+                if (strncmp(w, "shared", MAX(l, 6U)) == 0)
                         flags |= MS_SHARED;
-                else if (strncmp(w, "slave", l) == 0)
+                else if (strncmp(w, "slave", MAX(l, 5U)) == 0)
                         flags |= MS_SLAVE;
-                else if (strncmp(w, "private", l) == 0)
+                else if (strncmp(w, "private", MAX(l, 7U)) == 0)
                         flags |= MS_PRIVATE;
                 else {
                         log_error("[%s:%u] Failed to parse mount flags, ignoring: %s", filename, line, rvalue);
diff --git a/src/test-strv.c b/src/test-strv.c
new file mode 100644
index 0000000..5734368
--- /dev/null
+++ b/src/test-strv.c
@@ -0,0 +1,41 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  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 General Public License as published by
+  the Free Software Foundation; either version 2 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <string.h>
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+        char *w, *state;
+        size_t l;
+        const char test[] = "test a b c 'd' e '' '' hhh '' ''";
+
+        printf("<%s>\n", test);
+
+        FOREACH_WORD_QUOTED(w, l, test, state) {
+                char *t;
+
+                assert_se(t = strndup(w, l));
+                printf("<%s>\n", t);
+                free(t);
+        }
+
+        return 0;
+}

commit 5475ff4b7ad8b95d9863c98f0930a6c9b5c80eed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 14 19:24:41 2010 +0100

    udev: ignore temporary udev devices

diff --git a/TODO b/TODO
index 09a392f..cb12969 100644
--- a/TODO
+++ b/TODO
@@ -56,8 +56,6 @@
 * start getty 2-6 only when actual vt switch happens
   (same model as socket on-demand activation)
 
-* ask-password: find way to disable wall agent where tty agent is running
-
 * readahead: btrfs/LVM SSD detection
 
 * man pages for: locale.conf, vconsole.conf modules-load.d
@@ -68,20 +66,12 @@
 
 * parse early boot time env var from dracut RD_TIMEOUT, drop RD_xxx
 
-* cryptsetup
-
 * add seperate man page for [Install] settings
 
 * only add quotacheck deps to .mount units which mention grpquota/usrquota in the mount flags
 
-* we now order plymouth after udev-trigger. Can we optimize this?
-
-* drop tmp.mount
-
 * systemctl condrestart should return 0 if service isn't running
 
-* fsck-root.service/start gets queued twice
-
 * tmpfiles: allow specification of .conf files on cmdline
 
 * allow runtime changing of log level and target
@@ -90,10 +80,16 @@
 
 * tmpfiles: skip sticky files and after wallclock time change
 
+Pre v12:
+
+* fsck-root.service/start gets queued twice
+
 * pull in 'following' units in transactions
 
 * fix hotplug transactions
 
+* make it possible to wait for device unplug, i.e. issue "stop" on devices
+
 External:
 
 * patch kernel for xattr support in /dev, /proc/, /sys and /sys/fs/cgroup.
diff --git a/src/99-systemd.rules b/src/99-systemd.rules
index 470b1a0..815c8fd 100644
--- a/src/99-systemd.rules
+++ b/src/99-systemd.rules
@@ -7,6 +7,8 @@
 
 ACTION!="add|change", GOTO="systemd_end"
 
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="systemd_end"
+
 KERNEL=="tty[0-9]|tty1[0-2]", TAG+="systemd"
 KERNEL=="ttyS*", TAG+="systemd"
 

commit 1fc7633598538fc5005e679da9ae5ce042376029
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 14 02:08:31 2010 +0100

    cryptsetup: handle password=none properly

diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 91a4436..c007b87 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -37,6 +37,18 @@ static bool opt_readonly = false;
 static bool opt_verify = false;
 static usec_t opt_timeout = 0;
 
+/* Options Debian's crypttab knows we don't:
+
+    offset=
+    skip=
+    precheck=
+    check=
+    checkargs=
+    noearly=
+    loud=
+    keyscript=
+*/
+
 static int parse_one_option(const char *option) {
         assert(option);
 
@@ -155,7 +167,10 @@ int main(int argc, char *argv[]) {
                         goto finish;
                 }
 
-                if (argc >= 5 && argv[4][0] && !streq(argv[4], "-")) {
+                if (argc >= 5 &&
+                    argv[4][0] &&
+                    !streq(argv[4], "-") &&
+                    !streq(argv[4], "none")) {
 
                         if (!path_is_absolute(argv[4]))
                                 log_error("Password file path %s is not absolute. Ignoring.", argv[4]);

commit e2d480b9d192cef125a531aa5eec574827c69b44
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 14 02:01:29 2010 +0100

    cryptsetup: properly parse cipher= switch

diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 997a61a..91a4436 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -30,7 +30,6 @@
 
 static const char *opt_type = NULL; /* LUKS1 or PLAIN */
 static char *opt_cipher = NULL;
-static char *opt_cipher_mode = NULL;
 static unsigned opt_key_size = 0;
 static char *opt_hash = NULL;
 static unsigned opt_tries = 0;
@@ -70,15 +69,6 @@ static int parse_one_option(const char *option) {
                 free(opt_hash);
                 opt_hash = t;
 
-        } else if (startswith(option, "mode=")) {
-                char *t;
-
-                if (!(t = strdup(option+5)))
-                        return -ENOMEM;
-
-                free(opt_cipher_mode);
-                opt_cipher_mode = t;
-
         } else if (startswith(option, "tries=")) {
 
                 if (safe_atou(option+6, &opt_tries) < 0) {
@@ -140,9 +130,8 @@ static void log_glue(int level, const char *msg, void *usrptr) {
 int main(int argc, char *argv[]) {
         int r = EXIT_FAILURE;
         struct crypt_device *cd = NULL;
-        char *password = NULL;
+        char *password = NULL, *truncated_cipher = NULL;
         const char *cipher = NULL, *cipher_mode = NULL, *hash = NULL;
-        crypt_status_info status;
 
         if (argc < 3) {
                 log_error("This program requires at least two arguments.");
@@ -159,6 +148,7 @@ int main(int argc, char *argv[]) {
                 unsigned try;
                 const char *key_file = NULL;
                 usec_t until;
+                crypt_status_info status;
 
                 if (argc < 4) {
                         log_error("attach requires at least two arguments.");
@@ -197,10 +187,25 @@ int main(int argc, char *argv[]) {
 
                 opt_tries = opt_tries > 0 ? opt_tries : 3;
                 opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);
-                cipher = opt_cipher ? opt_cipher : "aes";
-                cipher_mode = opt_cipher_mode ? opt_cipher_mode : "cbc-essiv:sha256";
                 hash = opt_hash ? opt_hash : "ripemd160";
 
+                if (opt_cipher) {
+                        size_t l;
+
+                        l = strcspn(opt_cipher, "-");
+
+                        if (!(truncated_cipher = strndup(opt_cipher, l))) {
+                                log_error("Out of memory");
+                                goto finish;
+                        }
+
+                        cipher = truncated_cipher;
+                        cipher_mode = opt_cipher[l] ? opt_cipher+l+1 : "plain";
+                } else {
+                        cipher = "aes";
+                        cipher_mode = "cbc-essiv:sha256";
+                }
+
                 for (try = 0; try < opt_tries; try++) {
                         bool pass_volume_key = false;
 
@@ -335,9 +340,10 @@ finish:
                 crypt_free(cd);
 
         free(opt_cipher);
-        free(opt_cipher_mode);
         free(opt_hash);
 
+        free(truncated_cipher);
+
         free(password);
 
         return r;

commit 260ab287953153a8b4ae13133adfdfc2b3514a46
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 14 01:53:46 2010 +0100

    cryptsetup: support non-LUKS crypto partitions

diff --git a/src/ask-password-api.c b/src/ask-password-api.c
index e4ee8ad..9f7023e 100644
--- a/src/ask-password-api.c
+++ b/src/ask-password-api.c
@@ -480,3 +480,13 @@ finish:
 
         return r;
 }
+
+int ask_password_auto(const char *message, const char *icon, usec_t until, char **_passphrase) {
+        assert(message);
+        assert(_passphrase);
+
+        if (isatty(STDIN_FILENO))
+                return ask_password_tty(message, until, NULL, _passphrase);
+        else
+                return ask_password_agent(message, icon, until, _passphrase);
+}
diff --git a/src/ask-password-api.h b/src/ask-password-api.h
index 8ef1aa6..ec858ba 100644
--- a/src/ask-password-api.h
+++ b/src/ask-password-api.h
@@ -28,4 +28,6 @@ int ask_password_tty(const char *message, usec_t until, const char *flag_file, c
 
 int ask_password_agent(const char *message, const char *icon, usec_t until, char **_passphrase);
 
+int ask_password_auto(const char *message, const char *icon, usec_t until, char **_passphrase);
+
 #endif
diff --git a/src/cryptsetup-generator.c b/src/cryptsetup-generator.c
index d1d7bb6..3c3b99d 100644
--- a/src/cryptsetup-generator.c
+++ b/src/cryptsetup-generator.c
@@ -115,9 +115,8 @@ static int create_disk(
                 "\n[Service]\n"
                 "Type=oneshot\n"
                 "RemainAfterExit=yes\n"
-                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " %s '%s' '%s' '%s' '%s'\n"
+                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
                 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
-                options && has_option(options, "swap") ? "format-and-attach" : "attach",
                 name, u, strempty(password), strempty(options),
                 name);
 
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index d9b9ebe..997a61a 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -28,21 +28,21 @@
 #include "util.h"
 #include "ask-password-api.h"
 
-static unsigned opt_tries = 0;
+static const char *opt_type = NULL; /* LUKS1 or PLAIN */
 static char *opt_cipher = NULL;
-static unsigned opt_size = 0;
+static char *opt_cipher_mode = NULL;
+static unsigned opt_key_size = 0;
 static char *opt_hash = NULL;
+static unsigned opt_tries = 0;
 static bool opt_readonly = false;
 static bool opt_verify = false;
-static usec_t arg_timeout = 0;
+static usec_t opt_timeout = 0;
 
 static int parse_one_option(const char *option) {
         assert(option);
 
         /* Handled outside of this tool */
-        if (streq(option, "swap") ||
-            streq(option, "tmp") ||
-            streq(option, "noauto"))
+        if (streq(option, "noauto"))
                 return 0;
 
         if (startswith(option, "cipher=")) {
@@ -56,7 +56,7 @@ static int parse_one_option(const char *option) {
 
         } else if (startswith(option, "size=")) {
 
-                if (safe_atou(option+5, &opt_size) < 0) {
+                if (safe_atou(option+5, &opt_key_size) < 0) {
                         log_error("size= parse failure, ignoring.");
                         return 0;
                 }
@@ -70,6 +70,15 @@ static int parse_one_option(const char *option) {
                 free(opt_hash);
                 opt_hash = t;
 
+        } else if (startswith(option, "mode=")) {
+                char *t;
+
+                if (!(t = strdup(option+5)))
+                        return -ENOMEM;
+
+                free(opt_cipher_mode);
+                opt_cipher_mode = t;
+
         } else if (startswith(option, "tries=")) {
 
                 if (safe_atou(option+6, &opt_tries) < 0) {
@@ -81,9 +90,15 @@ static int parse_one_option(const char *option) {
                 opt_readonly = true;
         else if (streq(option, "verify"))
                 opt_verify = true;
+        else if (streq(option, "luks"))
+                opt_type = CRYPT_LUKS1;
+        else if (streq(option, "plain") ||
+                 streq(option, "swap") ||
+                 streq(option, "tmp"))
+                opt_type = CRYPT_PLAIN;
         else if (startswith(option, "timeout=")) {
 
-                if (parse_usec(option+8, &arg_timeout) < 0) {
+                if (parse_usec(option+8, &opt_timeout) < 0) {
                         log_error("timeout= parse failure, ignoring.");
                         return 0;
                 }
@@ -119,35 +134,15 @@ static int parse_options(const char *options) {
 }
 
 static void log_glue(int level, const char *msg, void *usrptr) {
-
-        log_full(level == CRYPT_LOG_ERROR   ? LOG_ERR :
-                 level == CRYPT_LOG_VERBOSE ? LOG_INFO :
-                 level == CRYPT_LOG_DEBUG   ? LOG_DEBUG :
-                                              LOG_NOTICE,
-                 "%s", msg);
-}
-
-static int password_glue(const char *msg, char *buf, size_t length, void *usrptr) {
-        usec_t until;
-        char *password = NULL;
-        int k;
-
-        until = now(CLOCK_MONOTONIC) + (arg_timeout > 0 ? arg_timeout : 60 * USEC_PER_SEC);
-
-        if ((k = ask_password_agent(msg, "drive-harddisk", until, &password)) < 0)
-                return k;
-
-        strncpy(buf, password, length-1);
-        buf[length-1] = 0;
-
-        free(password);
-
-        return strlen(buf);
+        log_debug("%s", msg);
 }
 
 int main(int argc, char *argv[]) {
         int r = EXIT_FAILURE;
         struct crypt_device *cd = NULL;
+        char *password = NULL;
+        const char *cipher = NULL, *cipher_mode = NULL, *hash = NULL;
+        crypt_status_info status;
 
         if (argc < 3) {
                 log_error("This program requires at least two arguments.");
@@ -158,11 +153,12 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
-        if (streq(argv[1], "attach") ||
-            streq(argv[1], "format-and-attach")) {
+        if (streq(argv[1], "attach")) {
                 uint32_t flags = 0;
                 int k;
+                unsigned try;
                 const char *key_file = NULL;
+                usec_t until;
 
                 if (argc < 4) {
                         log_error("attach requires at least two arguments.");
@@ -186,34 +182,129 @@ int main(int argc, char *argv[]) {
                 }
 
                 crypt_set_log_callback(cd, log_glue, NULL);
-                crypt_set_password_callback(cd, password_glue, NULL);
-
-                if (streq(argv[1], "format-and-attach")) {
 
-                        /* Format with random key and attach */
-
-                        log_error("Formatting not yet supported.");
-                        goto finish;
-
-                } else if ((k = crypt_load(cd, CRYPT_LUKS1, NULL))) {
-                        log_error("crypt_load() failed: %s", strerror(-k));
+                status = crypt_status(cd, argv[2]);
+                if (status == CRYPT_ACTIVE || status == CRYPT_BUSY) {
+                        log_info("Volume %s already active.", argv[2]);
+                        r = EXIT_SUCCESS;
                         goto finish;
                 }
 
                 if (opt_readonly)
                         flags |= CRYPT_ACTIVATE_READONLY;
 
-                if (key_file) {
-                        crypt_set_password_retry(cd, 1);
-                        k = crypt_activate_by_keyfile(cd, argv[2], CRYPT_ANY_SLOT, key_file, 0, flags);
-                } else  {
-                        crypt_set_password_retry(cd, opt_tries > 0 ? opt_tries : 3);
-                        k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, NULL, 0, flags);
+                until = now(CLOCK_MONOTONIC) + (opt_timeout > 0 ? opt_timeout : 60 * USEC_PER_SEC);
+
+                opt_tries = opt_tries > 0 ? opt_tries : 3;
+                opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);
+                cipher = opt_cipher ? opt_cipher : "aes";
+                cipher_mode = opt_cipher_mode ? opt_cipher_mode : "cbc-essiv:sha256";
+                hash = opt_hash ? opt_hash : "ripemd160";
+
+                for (try = 0; try < opt_tries; try++) {
+                        bool pass_volume_key = false;
+
+                        free(password);
+                        password = NULL;
+
+                        if (!key_file) {
+
+                                if ((k = ask_password_auto("Please enter passphrase for disk:", "drive-harddisk", until, &password)) < 0) {
+                                        log_error("Failed to query password: %s", strerror(-k));
+                                        goto finish;
+                                }
+
+                                if (opt_verify) {
+                                        char *password2 = NULL;
+
+                                        if ((k = ask_password_auto("Please enter passphrase for disk (verification):", "drive-harddisk", until, &password2)) < 0) {
+                                                log_error("Failed to query verification password: %s", strerror(-k));
+                                                goto finish;
+                                        }
+
+                                        if (!streq(password, password2)) {
+                                                log_warning("Passwords did not match, retrying.");
+                                                free(password2);
+                                                continue;
+                                        }
+
+                                        free(password2);
+                                }
+
+                                if (strlen(password)+1 < opt_key_size) {
+                                        char *c;
+
+                                        /* Pad password if necessary */
+
+                                        if (!(c = new(char, opt_key_size))) {
+                                                log_error("Out of memory.");
+                                                goto finish;
+                                        }
+
+                                        strncpy(c, password, opt_key_size);
+                                        free(password);
+                                        password = c;
+                                }
+                        }
+
+                        if (!opt_type || streq(opt_type, CRYPT_LUKS1))
+                                k = crypt_load(cd, CRYPT_LUKS1, NULL);
+
+                        if ((!opt_type && k < 0) || streq_ptr(opt_type, CRYPT_PLAIN)) {
+                                struct crypt_params_plain params;
+
+                                zero(params);
+                                params.hash = hash;
+
+                                /* In contrast to what the name
+                                 * crypt_setup() might suggest this
+                                 * doesn't actually format anything,
+                                 * it just configures encryption
+                                 * parameters when used for plain
+                                 * mode. */
+                                k = crypt_format(cd, CRYPT_PLAIN,
+                                                 cipher,
+                                                 cipher_mode,
+                                                 NULL,
+                                                 NULL,
+                                                 opt_key_size / 8,
+                                                 &params);
+
+                                pass_volume_key = streq(hash, "plain");
+                        }
+
+                        if (k < 0) {
+                                log_error("Loading of cryptographic parameters failed: %s", strerror(-k));
+                                goto finish;
+                        }
+
+                        log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
+                                 crypt_get_cipher(cd),
+                                 crypt_get_cipher_mode(cd),
+                                 crypt_get_volume_key_size(cd)*8,
+                                 argv[3]);
+
+                        if (key_file)
+                                k = crypt_activate_by_keyfile(cd, argv[2], CRYPT_ANY_SLOT, key_file, opt_key_size, flags);
+                        else if (pass_volume_key)
+                                k = crypt_activate_by_volume_key(cd, argv[2], password, opt_key_size, flags);
+                        else
+                                k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, password, strlen(password), flags);
+
+                        if (k >= 0)
+                                break;
+
+                        if (k != -EPERM) {
+                                log_error("Failed to activate: %s", strerror(-k));
+                                goto finish;
+                        }
+
+                        log_warning("Invalid passphrase.");
                 }
 
-                if (k < 0) {
-                        log_error("Failed to activate: %s", strerror(-k));
-                        goto finish;
+                if (try >= opt_tries) {
+                        log_error("Too many attempts.");
+                        r = EXIT_FAILURE;
                 }
 
         } else if (streq(argv[1], "detach")) {
@@ -243,5 +334,11 @@ finish:
         if (cd)
                 crypt_free(cd);
 
+        free(opt_cipher);
+        free(opt_cipher_mode);
+        free(opt_hash);
+
+        free(password);
+
         return r;
 }



More information about the systemd-commits mailing list