[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,
+ ¶ms);
+
+ 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