diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml
index b16ee09cee..fbe62262af 100644
--- a/man/systemd-creds.xml
+++ b/man/systemd-creds.xml
@@ -228,7 +228,8 @@
When specified with encrypt controls whether to show the encrypted
credential as SetCredentialEncrypted= setting that may be pasted directly into a
- unit file.
+ unit file. Has effect only when used together with and -
+ as the output file.
diff --git a/src/creds/creds.c b/src/creds/creds.c
index ef32efe1e2..670e719d21 100644
--- a/src/creds/creds.c
+++ b/src/creds/creds.c
@@ -506,20 +506,21 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
if (base64_size < 0)
return base64_size;
- if (arg_pretty) {
+ /* Pretty print makes sense only if we're printing stuff to stdout
+ * and if a cred name is provided via --name= (since we can't use
+ * the output file name as the cred name here) */
+ if (arg_pretty && !output_path && name) {
_cleanup_free_ char *escaped = NULL, *indented = NULL, *j = NULL;
- if (name) {
- escaped = cescape(name);
- if (!escaped)
- return log_oom();
- }
+ escaped = cescape(name);
+ if (!escaped)
+ return log_oom();
indented = strreplace(base64_buf, "\n", " \\\n ");
if (!indented)
return log_oom();
- j = strjoin("SetCredentialEncrypted=", name, ": \\\n ", indented, "\n");
+ j = strjoin("SetCredentialEncrypted=", escaped, ": \\\n ", indented, "\n");
if (!j)
return log_oom();
diff --git a/src/test/test-secure-bits.c b/src/test/test-secure-bits.c
index d44bef6a09..27e6a20e09 100644
--- a/src/test/test-secure-bits.c
+++ b/src/test/test-secure-bits.c
@@ -28,6 +28,7 @@ TEST(secure_bits_basic) {
r = secure_bits_from_string(*bit);
assert_se(r > 0);
+ assert_se(secure_bits_is_valid(r));
assert_se(secure_bits_to_string_alloc(r, &s) >= 0);
printf("%s = 0x%x = %s\n", *bit, (unsigned)r, s);
assert_se(streq(*bit, s));
@@ -38,6 +39,7 @@ TEST(secure_bits_basic) {
assert_se(joined);
r = secure_bits_from_string(joined);
assert_se(r > 0);
+ assert_se(secure_bits_is_valid(r));
assert_se(secure_bits_to_string_alloc(r, &str) >= 0);
printf("%s = 0x%x = %s\n", joined, (unsigned)r, str);
assert_se(streq(joined, str));
@@ -54,6 +56,16 @@ TEST(secure_bits_basic) {
/* Empty secure bits */
assert_se(secure_bits_to_string_alloc(0, &str) >= 0);
assert_se(isempty(str));
+
+ str = mfree(str);
+
+ /* Bits to string with check */
+ assert_se(secure_bits_to_string_alloc_with_check(INT_MAX, &str) == -EINVAL);
+ assert_se(str == NULL);
+ assert_se(secure_bits_to_string_alloc_with_check(
+ (1 << SECURE_KEEP_CAPS) | (1 << SECURE_KEEP_CAPS_LOCKED),
+ &str) >= 0);
+ assert_se(streq(str, "keep-caps keep-caps-locked"));
}
TEST(secure_bits_mix) {
@@ -75,6 +87,7 @@ TEST(secure_bits_mix) {
r = secure_bits_from_string(s->input);
assert_se(r > 0);
+ assert_se(secure_bits_is_valid(r));
assert_se(secure_bits_to_string_alloc(r, &str) >= 0);
printf("%s = 0x%x = %s\n", s->input, (unsigned)r, str);
assert_se(streq(s->expected, str));
diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh
index cc732989a2..d243d93d81 100755
--- a/test/units/testsuite-54.sh
+++ b/test/units/testsuite-54.sh
@@ -5,6 +5,152 @@ set -eux
systemd-analyze log-level debug
+run_with_cred_compare() {
+ local cred="${1:?}"
+ local exp="${2?}"
+ shift 2
+
+ diff <(systemd-run -p SetCredential="$cred" --wait --pipe -- systemd-creds "$@") <(echo -ne "$exp")
+}
+
+# Sanity checks
+#
+# Create a dummy "full" disk (similar to /dev/full) to check out-of-space
+# scenarios
+mkdir /tmp/full
+mount -t tmpfs -o size=1,nr_inodes=1 tmpfs /tmp/full
+
+# verb: setup
+# Run this first, otherwise any encrypted credentials wouldn't be decryptable
+# as we regnerate the host key
+rm -fv /var/lib/systemd/credential.secret
+systemd-creds setup
+test -e /var/lib/systemd/credential.secret
+rm -fv /var/lib/systemd/credential.secret
+
+# Prepare a couple of dummy credentials for the cat/list verbs
+CRED_DIR="$(mktemp -d)"
+ENC_CRED_DIR="$(mktemp -d)"
+echo foo >"$CRED_DIR/secure-or-weak"
+echo foo >"$CRED_DIR/insecure"
+echo foo | systemd-creds --name="encrypted" encrypt - - | base64 -d >"$ENC_CRED_DIR/encrypted"
+echo foo | systemd-creds encrypt - - | base64 -d >"$ENC_CRED_DIR/encrypted-unnamed"
+chmod -R 0400 "$CRED_DIR" "$ENC_CRED_DIR"
+chmod -R 0444 "$CRED_DIR/insecure"
+mkdir /tmp/empty/
+
+systemd-creds --system
+systemd-creds --no-pager --help
+systemd-creds --version
+systemd-creds has-tpm2 || :
+systemd-creds has-tpm2 -q || :
+
+# verb: list
+systemd-creds list --system
+ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --no-legend
+ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=pretty | jq
+ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=short | jq
+ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=off
+ENCRYPTED_CREDENTIALS_DIRECTORY="/tmp/empty/" CREDENTIALS_DIRECTORY="/tmp/empty/" systemd-creds list
+
+# verb: cat
+for cred in secure-or-weak insecure encrypted encrypted-unnamed; do
+ ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds cat "$cred"
+done
+run_with_cred_compare "mycred:" "" cat mycred
+run_with_cred_compare "mycred:\n" "\n" cat mycred
+run_with_cred_compare "mycred:foo" "foo" cat mycred
+run_with_cred_compare "mycred:foo" "foofoofoo" cat mycred mycred mycred
+# Note: --newline= does nothing when stdout is not a tty, which is the case here
+run_with_cred_compare "mycred:foo" "foo" --newline=yes cat mycred
+run_with_cred_compare "mycred:foo" "foo" --newline=no cat mycred
+run_with_cred_compare "mycred:foo" "foo" --newline=auto cat mycred
+run_with_cred_compare "mycred:foo" "foo" --transcode=no cat mycred
+run_with_cred_compare "mycred:foo" "foo" --transcode=0 cat mycred
+run_with_cred_compare "mycred:foo" "foo" --transcode=false cat mycred
+run_with_cred_compare "mycred:foo" "Zm9v" --transcode=base64 cat mycred
+run_with_cred_compare "mycred:Zm9v" "foo" --transcode=unbase64 cat mycred
+run_with_cred_compare "mycred:Zm9v" "foofoofoo" --transcode=unbase64 cat mycred mycred mycred
+run_with_cred_compare "mycred:Zm9vCg==" "foo\n" --transcode=unbase64 cat mycred
+run_with_cred_compare "mycred:hello world" "68656c6c6f20776f726c64" --transcode=hex cat mycred
+run_with_cred_compare "mycred:68656c6c6f20776f726c64" "hello world" --transcode=unhex cat mycred
+run_with_cred_compare "mycred:68656c6c6f20776f726c64" "hello worldhello world" --transcode=unhex cat mycred mycred
+run_with_cred_compare "mycred:68656c6c6f0a776f726c64" "hello\nworld" --transcode=unhex cat mycred
+run_with_cred_compare 'mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' '{"foo":"bar","baz":[3,4]}\n' --json=short cat mycred
+systemd-run -p SetCredential='mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' --wait --pipe -- systemd-creds --json=pretty cat mycred | jq
+
+# verb: encrypt/decrypt
+echo "According to all known laws of aviation..." >/tmp/cred.orig
+systemd-creds --with-key=host encrypt /tmp/cred.orig /tmp/cred.enc
+systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec
+diff /tmp/cred.orig /tmp/cred.dec
+rm -f /tmp/cred.{enc,dec}
+# --pretty
+cred_name="fo'''o''bar"
+cred_option="$(systemd-creds --pretty --name="$cred_name" encrypt /tmp/cred.orig -)"
+mkdir -p /run/systemd/system
+cat >/run/systemd/system/test-54-pretty-cred.service <