Translate to Polish

This commit is contained in:
наб 2023-11-25 17:30:20 +01:00
parent e78ba80bc9
commit 47cd20aa32
No known key found for this signature in database
GPG Key ID: BCFD0B018D2658F1
20 changed files with 492 additions and 96 deletions

2
.gitignore vendored
View File

@ -21,3 +21,5 @@
!initrd/** !initrd/**
!init.d !init.d
!init.d/** !init.d/**
!po
!po/**

10
LICENSES/0BSD Normal file
View File

@ -0,0 +1,10 @@
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -12,8 +12,10 @@ SED ?= sed
MANDOC ?= mandoc MANDOC ?= mandoc
PKGCONF ?= pkgconf PKGCONF ?= pkgconf
SHELLCHECK ?= shellcheck SHELLCHECK ?= shellcheck
OUTDIR ?= out/
BLDDIR ?= out/build/ NOLOCREGEN ?=
OUTDIR := out/
BLDDIR := out/build/
SYSTEMD_SYSTEM_UNITDIR := $(shell $(PKGCONF) --variable=systemd_system_unit_dir systemd 2>/dev/null || echo /usr/lib/systemd/system) SYSTEMD_SYSTEM_UNITDIR := $(shell $(PKGCONF) --variable=systemd_system_unit_dir systemd 2>/dev/null || echo /usr/lib/systemd/system)
@ -31,6 +33,9 @@ COMMON_SOURCES := $(filter-out $(BINARY_SOURCES),$(sort $(wildcard src/*.cpp src
MANPAGE_HEADERS := $(sort $(wildcard man/*.h)) MANPAGE_HEADERS := $(sort $(wildcard man/*.h))
MANPAGE_SOURCES := $(sort $(wildcard man/*.[0-8].pp)) MANPAGE_SOURCES := $(sort $(wildcard man/*.[0-8].pp))
INITRD_HEADERS := $(sort $(wildcard initrd/*.h)) INITRD_HEADERS := $(sort $(wildcard initrd/*.h))
ifneq (,$(shell command -v msgfmt))
LOCALES := $(wildcard po/*.po)
endif
ifdef TZPFMS_PASSPHRASE_HELPER ifdef TZPFMS_PASSPHRASE_HELPER
@ -52,10 +57,10 @@ endif
.PHONY : all clean build shellcheck i-t dracut init.d-systemd manpages htmlpages .PHONY : all locales clean build shellcheck i-t dracut init.d-systemd manpages htmlpages
all : build manpages htmlpages shellcheck i-t init.d-systemd dracut all : build locales manpages htmlpages shellcheck i-t init.d-systemd dracut
shellcheck : i-t dracut shellcheck : i-t dracut
find $(OUTDIR)initramfs-tools/ $(OUTDIR)dracut/ init.d/ -name '*.sh' -exec echo $(SHELLCHECK) --exclude SC1091,SC2093 {} + | sh -x find $(OUTDIR)initramfs-tools/ $(OUTDIR)dracut/ init.d/ -name '*.sh' -exec echo $(SHELLCHECK) --exclude SC1091,SC2093 {} + | sh -x
@ -66,11 +71,23 @@ clean :
build : $(subst src/bin/,$(OUTDIR),$(subst .cpp,,$(BINARY_SOURCES))) build : $(subst src/bin/,$(OUTDIR),$(subst .cpp,,$(BINARY_SOURCES)))
manpages : $(patsubst man/%.pp,$(OUTDIR)man/%,$(MANPAGE_SOURCES)) manpages : $(patsubst man/%.pp,$(OUTDIR)man/%,$(MANPAGE_SOURCES))
htmlpages : $(patsubst man/%.pp,$(OUTDIR)man/%.html,$(MANPAGE_SOURCES)) $(OUTDIR)man/style.css htmlpages : $(patsubst man/%.pp,$(OUTDIR)man/%.html,$(MANPAGE_SOURCES)) $(OUTDIR)man/style.css
locales : $(patsubst po/%.po,$(OUTDIR)loc/%/LC_MESSAGES/tzpfms.mo,$(LOCALES))
i-t : $(OUTDIR)initramfs-tools/usr/share/initramfs-tools/hooks/tzpfms $(OUTDIR)initramfs-tools/usr/share/tzpfms/initramfs-tools-zfs-patch.sh i-t : $(OUTDIR)initramfs-tools/usr/share/initramfs-tools/hooks/tzpfms $(OUTDIR)initramfs-tools/usr/share/tzpfms/initramfs-tools-zfs-patch.sh
dracut : $(patsubst initrd/dracut/%,$(OUTDIR)dracut/usr/lib/dracut/modules.d/91tzpfms/%,$(sort $(wildcard initrd/dracut/*.sh))) dracut : $(patsubst initrd/dracut/%,$(OUTDIR)dracut/usr/lib/dracut/modules.d/91tzpfms/%,$(sort $(wildcard initrd/dracut/*.sh)))
init.d-systemd : $(OUTDIR)systemd/$(SYSTEMD_SYSTEM_UNITDIR)/zfs-load-key@.service.d/tzpfms.conf $(OUTDIR)systemd/usr/libexec/tzpfms-zfs-load-key@ init.d-systemd : $(OUTDIR)systemd/$(SYSTEMD_SYSTEM_UNITDIR)/zfs-load-key@.service.d/tzpfms.conf $(OUTDIR)systemd/usr/libexec/tzpfms-zfs-load-key@
$(BLDDIR)tzpfms.pot: src/*.[ch]pp src/bin/*.[ch]pp
@mkdir -p $(@D)
$(NOLOCREGEN)xgettext --check=ellipsis-unicode -kfgettext -kfngettext:1,2 --from-code=UTF-8 -c -io- $^ | sed -n '/^#[:.]/,$$p' > $@
$(NOLOCREGEN)$(foreach l,$(LOCALES),msgmerge --backup=off --no-wrap -Uiq $(l) $@ &&) :
@>> $@
$(OUTDIR)loc/%/LC_MESSAGES/tzpfms.mo : po/%.po $(BLDDIR)tzpfms.pot
@mkdir -p $(@D)
msgfmt --statistics --check-format --check-domain -o $@ $<
$(OUTDIR)initramfs-tools/usr/share/initramfs-tools/hooks/tzpfms: initrd/initramfs-tools/hook $(INITRD_HEADERS) $(OUTDIR)initramfs-tools/usr/share/initramfs-tools/hooks/tzpfms: initrd/initramfs-tools/hook $(INITRD_HEADERS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
$(AWK) -f pp.awk $< > $@ $(AWK) -f pp.awk $< > $@

282
po/pl.po Normal file
View File

@ -0,0 +1,282 @@
# SPDX-License-Identifier: 0BSD
msgid ""
msgstr "Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: src/fd.cpp:79
#, c-format
msgid "Passphrase for %s"
msgstr "Hasło do %s"
#: src/fd.cpp:81
#, c-format
msgid "Passphrase for %s (again)"
msgstr "Powtórz hasło do %s"
#: src/fd.cpp:83
#, c-format
msgid "New passphrase for %s"
msgstr "Nowe hasło do %s"
#. newkey && again
#: src/fd.cpp:85
#, c-format
msgid "New passphrase for %s (again)"
msgstr "Powtórz howe hasło do %s"
#. exit status
#: src/fd.cpp:132
#, c-format
msgid "Helper '%s' failed with %d.\n"
msgstr "'%s' zawiódł: %d.\n"
#: src/fd.cpp:135
#, c-format
msgid "Helper '%s' died to signal %d: %s.\n"
msgstr "'%s' zabity przez sygnał %d: %s.\n"
#: src/fd.cpp:171
#, c-format
msgid "Enter passphrase for %s: "
msgstr "Hasło do %s"
#: src/fd.cpp:173
#, c-format
msgid "Enter passphrase for new %s: "
msgstr "Hasło do nowego %s"
#: src/fd.cpp:175
#, c-format
msgid "Re-enter passphrase for %s: "
msgstr "Ponownie, hasło do %s"
#. again && newkey
#: src/fd.cpp:177
#, c-format
msgid "Re-enter passphrase for new %s: "
msgstr "Ponownie, hasło do nowego %s"
#: src/fd.cpp:254 src/fd.cpp:270
#, c-format
msgid "Passphrase too long (max %zu)\n"
msgstr "Hasło za długie (maks. %zu)\n"
#: src/fd.cpp:268
#, c-format
msgid "Passphrase too short (min %u)\n"
msgstr "Hasło za krótkie (maks. %u)\n"
#: src/fd.cpp:278
#, c-format
msgid "Provided passphrases do not match.\n"
msgstr "Hasła się różnią\n"
#: src/main.hpp:46 src/main.hpp:59 src/main.hpp:64
#, c-format
msgid "usage: %s [-hV] %s%s%s\n"
msgstr "składnia: %s [-hV] %s%s%s\n"
#. as-in argument in a usage string
#: src/main.hpp:72
msgid "dataset"
msgstr "dataset"
#: src/main.hpp:76
#, c-format
msgid "No dataset to act on?\n"
"usage: %s [-hV] %s%sdataset\n"
msgstr "Nie podano datasetu?\n"
"składnia: %s [-hV] %s%sdataset\n"
#: src/main.hpp:81
#, c-format
msgid "usage: %s [-hV] %s%sdataset\n"
msgstr "składnia: %s [-hV] %s%sdataset\n"
#: src/main.hpp:91
#, c-format
msgid "Dataset %s not encrypted?\n"
msgstr "Dataset %s nie jest zaszyfrowany?\n"
#: src/main.hpp:93
#, c-format
msgid "Using dataset %s's encryption root %s instead.\n"
msgstr "Używam zamiast %s jego korzenia szyfrowania %s.\n"
#. user-supplied parameter, errno
#: src/tpm1x.cpp:101
#, c-format
msgid "PCR %s: %s\n"
msgstr "PCR %s: %s\n"
#. user-supplied parameter
#: src/tpm1x.cpp:104
#, c-format
msgid "PCR %s: too large (max 229).\n"
msgstr "PCR %s: za duży (maks. 229)\n"
#. == TPM2_NUM_PCR_BANKS
#: src/tpm2.cpp:116
#, c-format
msgid "Too many PCR banks specified! Can only have up to %zu\n"
msgstr "Zbyt wiele grup PCRów! Mogę przyjąć maks. %zu\n"
#. comma-separated list follows
#: src/tpm2.cpp:133
#, c-format
msgid "Unknown hash algorithm %s.\n"
"Can be any of case-insensitive "
msgstr "Nie znany algorytm haszowania %s.\n"
"Można użyć dowolnego z (rozmiar liter nie ma znaczenia): "
#. user-passed parameter
#: src/tpm2.cpp:164
#, c-format
msgid "PCR bank \"%s\": no algorithm; need alg:PCR[,PCR]…\n"
msgstr "PCR bank \"%s\": nie podano algorytmu; potrzebuję alg:PCR[,PCR]…\n"
#. %s=dataset name, then TPM2. noun for "Enter passphrase for" prompt
#. %s=dataset, then TPM1.X. noun for "Enter passphrase for" prompt
#: src/tpm2.cpp:374 src/bin/zfs-tpm1x-change-key.cpp:108
#, c-format
msgid "%s %s wrapping key (or empty for none)"
msgstr "klucza zawijania %2$s dla %1$s (puste żeby nie używać żadnego)"
#. %s=dataset name, then TPM2. noun for "Enter passphrase for" prompt
#. %s=dataset name, then TPM1.x. noun for "Enter passphrase for" prompt
#: src/tpm2.cpp:425 src/bin/zfs-tpm1x-load-key.cpp:63
#, c-format
msgid "%s %s wrapping key"
msgstr "klucza zawijania %2$s dla %1$s"
#: src/tpm2.cpp:439
#, c-format
msgid "Couldn't unseal wrapping key with PCR policy: %s\n"
msgstr "Nie udało się rozpieczętować klucza zawijania z polityką PCR: %s\n"
#: src/zfs.cpp:101
#, c-format
msgid "You might need to run \"zfs inherit %s %s\" and \"zfs inherit %s %s\" to fully clear metadata!\n"
msgstr "Możliwe, że potrzebujesz uruchomić \"zfs inherit %s %s\" i \"zfs inherit %s %s\" żeby całkowicie pozbyć się metadanych!\n"
#: src/zfs.cpp:116
#, c-format
msgid "Dataset %s not encrypted with tzpfms!\n"
msgstr "Dataset %s nie jest szyfrowany tzpfms!\n"
#: src/zfs.cpp:118
#, c-format
msgid "Dataset %s encrypted with tzpfms back-end %s, but we are %s.\n"
msgstr "Dataset %s szyfrowany tzpfms %s, ale ten program rozumie %s.\n"
#: src/zfs.cpp:122
#, c-format
msgid "Dataset %s missing key data.\n"
msgstr "Dataset %s nie ma klucza.\n"
#. / Mimic libzfs error output
#: src/zfs.hpp:26
#, c-format
msgid "Key change error: Key must be loaded.\n"
msgstr "Błąd zmiany klucza: Klucz musi być załadowany.\n"
#. dataset name: (null), 0A123...
#. dataset name: TPM1.X, (null)
#: src/zfs.hpp:70
#, c-format
msgid "Inconsistent tzpfms metadata for %s: back-end is %s, but handle is %s?\n"
msgstr "Niespójne metadane tzpfms dla %s: tzpfms %s ale obiekt z kluczem %s?\n"
#: src/zfs.hpp:75
#, c-format
msgid "Dataset %s was encrypted with tzpfms back-end %s before, but we are %s. You will have to free handle %s for back-end %s manually!\n"
msgstr "Dataset %s był zaszyfrowany tzpfms %s, ale ten program rozumie %s. Konieczne będzie ręczne usunięcie obiektu z kluczem %s %s!\n"
#: src/zfs_meat.cpp:33
#, c-format
msgid "Key for %s changed\n"
msgstr "Klucz do %s zmieniony\n"
#: src/zfs_meat.cpp:46
#, c-format
msgid "Key for %s OK\n"
msgstr "Klucz do %s OK\n"
#: src/zfs_meat.cpp:48
#, c-format
msgid "Key for %s loaded\n"
msgstr "Klucz do %s załadowany\n"
#: src/bin/zfs-tpm1x-change-key.cpp:30
msgid "[-b backup-file] [-P PCR[,PCR]…]"
msgstr "[-b plik-z-backupem] [-P PCR[,PCR]…]"
#. 0A1234... follows
#: src/bin/zfs-tpm1x-load-key.cpp:71
#, c-format
msgid "Wrong sealed data length (%u != %zu): "
msgstr "Zła długość zaplombowanych danych (%u != %zu): "
#: src/bin/zfs-tpm2-change-key.cpp:25
msgid "[-b backup-file] [-P algorithm:PCR[,PCR]…[+algorithm:PCR[,PCR]…]… [-A]]"
msgstr "[-b plik-z-backupem] [-P algorytm:PCR[,PCR]…[+algorytm:PCR[,PCR]…]… [-A]]"
#: src/bin/zfs-tpm2-change-key.cpp:72
#, c-format
msgid "Couldn't parse previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c %s\" or equivalent!\n"
msgstr "Nie udało się rozczytać poprzedniego obiektu z kluczem dla %s. Możliwe, że potrzeba będzie uruchomić \"tpm2_evictcontrol -c %s\", albo jego ekwiwalent!\n"
#: src/bin/zfs-tpm2-change-key.cpp:78
#, c-format
msgid "Couldn't free previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c 0x%X\" or equivalent!\n"
msgstr "Nie udało się uwolnić poprzedniego obiektu z kluczem dla %s. Możliwe, że potrzeba będzie uruchomić \"tpm2_evictcontrol -c 0x%X\", albo jego ekwiwalent!\n"
#: src/bin/zfs-tpm2-change-key.cpp:94
#, c-format
msgid "Couldn't free persistent handle. You might need to run \"tpm2_evictcontrol -c 0x%X\" or equivalent!\n"
msgstr "Nie udało się uwolnić obiektu z kluczem. Możliwe, że potrzeba będzie uruchomić \"tpm2_evictcontrol -c 0x%X\", albo jego ekwiwalent!\n"
#. for KEYSTATUS column
#: src/bin/zfs-tpm-list.cpp:44
msgid "unavailable"
msgstr "niedostępny"
#: src/bin/zfs-tpm-list.cpp:44
msgid "available"
msgstr "dostępny"
#. for COHERENT column
#: src/bin/zfs-tpm-list.cpp:46
msgid "no"
msgstr "nie"
#: src/bin/zfs-tpm-list.cpp:46
msgid "yes"
msgstr "tak"
#: src/bin/zfs-tpm-list.cpp:88
msgid "[-H] [-r|-d max] [-a|-b back-end] [-u|-l]"
msgstr "[-H] [-r|-d maks.] [-a|-b rodzaj-tzpfms] [-u|-l]"
#: src/bin/zfs-tpm-list.cpp:88
msgid "[filesystem|volume]…"
msgstr "[system-plików|wolumin]…"
#: src/bin/zfs-tpm-list.cpp:152 src/bin/zfs-tpm-list.cpp:173
msgid "NAME"
msgstr "NAZWA"
#: src/bin/zfs-tpm-list.cpp:153 src/bin/zfs-tpm-list.cpp:173
msgid "BACK-END"
msgstr "RODZAJ"
#: src/bin/zfs-tpm-list.cpp:154 src/bin/zfs-tpm-list.cpp:173
msgid "KEYSTATUS"
msgstr "KLUCZ"
#: src/bin/zfs-tpm-list.cpp:173
msgid "COHERENT"
msgstr "SPÓJNY"

View File

@ -6,6 +6,7 @@
#include "../zfs.hpp" #include "../zfs.hpp"
#include <algorithm> #include <algorithm>
#include <wchar.h>
#define TZPFMS_BACKEND_MAX_LEN 16 #define TZPFMS_BACKEND_MAX_LEN 16
@ -19,8 +20,11 @@ enum class key_loadedness : char {
/// zfs(8) uses struct zprop_get_cbdata_t, which is powerful, but inscrutable; we have a fixed format, which makes this easier /// zfs(8) uses struct zprop_get_cbdata_t, which is powerful, but inscrutable; we have a fixed format, which makes this easier
struct output_line { struct output_line {
static const char * const key_available_display[2]; static const char * key_available_display[2];
static const char * const coherent_display[2]; static const char * coherent_display[2];
static uint8_t key_available_display_width[2];
static void init_display();
char name[ZFS_MAX_DATASET_NAME_LEN + 1]; char name[ZFS_MAX_DATASET_NAME_LEN + 1];
@ -36,8 +40,42 @@ struct output_line {
const char * backend_display() const { return (this->backend[0] != '\0') ? this->backend : "-"; } const char * backend_display() const { return (this->backend[0] != '\0') ? this->backend : "-"; }
}; };
const char * const output_line::key_available_display[2]{"unavailable", key_available_display[0] + 2}; // for KEYSTATUS column
const char * const output_line::coherent_display[2]{"no", "yes"}; const char * output_line::key_available_display[2]{gettext_noop("unavailable"), gettext_noop("available")};
// for COHERENT column
const char * output_line::coherent_display[2]{gettext_noop("no"), gettext_noop("yes")};
uint8_t output_line::key_available_display_width[2];
// infallible strings only
static int strwidth(const char * str) {
int ret{};
wchar_t c;
mbstate_t state{};
auto len = strlen(str);
for(;;)
switch(auto rd = mbrtowc(&c, str, len, &state)) {
case 0: // NUL
case(size_t)-1: // EILSEQ
case(size_t)-2: // ENODATA
return ret;
default:
ret += wcwidth(c) ?: 0;
str += rd;
len -= rd;
break;
}
}
void output_line::init_display() {
key_available_display[false] = gettext(key_available_display[false]);
key_available_display[true] = gettext(key_available_display[true]);
key_available_display_width[false] = strwidth(key_available_display[false]);
key_available_display_width[true] = strwidth(key_available_display[true]);
coherent_display[false] = gettext(coherent_display[false]);
coherent_display[true] = gettext(coherent_display[true]);
}
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
@ -47,7 +85,7 @@ int main(int argc, char ** argv) {
const char * backend_restrixion = nullptr; const char * backend_restrixion = nullptr;
auto key_loadedness_restrixion = key_loadedness::none; auto key_loadedness_restrixion = key_loadedness::none;
return do_bare_main( return do_bare_main(
argc, argv, "Hrd:ab:ul", "[-H] [-r|-d max] [-a|-b back-end] [-u|-l]", "[filesystem|volume]…", argc, argv, "Hrd:ab:ul", gettext_noop("[-H] [-r|-d max] [-a|-b back-end] [-u|-l]"), gettext_noop("[filesystem|volume]…"),
[&](auto arg) { [&](auto arg) {
switch(arg) { switch(arg) {
case 'H': case 'H':
@ -104,35 +142,35 @@ int main(int argc, char ** argv) {
return 0; return 0;
})); }));
output_line::init_display();
size_t max_name_len = 0; size_t max_name_len = 0;
size_t max_backend_len = 0; size_t max_backend_len = 0;
size_t max_key_available_len = 0; size_t max_key_available_len = 0;
size_t max_coherent_len = 0;
auto separator = "\t"; auto separator = "\t";
if(human) { if(human) {
max_name_len = strlen("NAME"); max_name_len = strwidth(gettext("NAME"));
max_backend_len = strlen("BACK-END"); max_backend_len = strwidth(gettext("BACK-END"));
max_key_available_len = strlen("KEYSTATUS"); max_key_available_len = strwidth(gettext("KEYSTATUS"));
max_coherent_len = strlen("COHERENT");
separator = " "; separator = " ";
for(auto cur = lines; cur != lines + lines_len; ++cur) for(auto cur = lines; cur != lines + lines_len; ++cur)
if(cur->included(print_nontzpfms, backend_restrixion, key_loadedness_restrixion)) { if(cur->included(print_nontzpfms, backend_restrixion, key_loadedness_restrixion)) {
max_name_len = std::max(max_name_len, strlen(cur->name)); max_name_len = std::max(max_name_len, strlen(cur->name));
max_backend_len = std::max(max_backend_len, strlen(cur->backend_display())); max_backend_len = std::max(max_backend_len, strlen(cur->backend_display()));
max_key_available_len = std::max(max_key_available_len, strlen(output_line::key_available_display[cur->key_available])); max_key_available_len = std::max(max_key_available_len, static_cast<size_t>(output_line::key_available_display_width[cur->key_available]));
} }
} }
auto println = [&](auto name, auto backend, auto key_available, auto coherent) { auto println = [&](auto name, auto backend, auto key_available, auto coherent) {
printf("%-*s%s%-*s%s%-*s%s%-*s\n", // printf("%-*s%s%-*s%s%-*s%s%s\n", //
static_cast<int>(max_name_len), name, separator, // static_cast<int>(max_name_len), name, separator, //
static_cast<int>(max_backend_len), backend, separator, // static_cast<int>(max_backend_len), backend, separator, //
static_cast<int>(max_key_available_len), key_available, separator, // static_cast<int>(max_key_available_len), key_available, separator, //
static_cast<int>(max_coherent_len), coherent); coherent);
}; };
if(human) if(human)
println("NAME", "BACK-END", "KEYSTATUS", "COHERENT"); println(gettext("NAME"), gettext("BACK-END"), gettext("KEYSTATUS"), gettext("COHERENT"));
for(auto cur = lines; cur != lines + lines_len; ++cur) for(auto cur = lines; cur != lines + lines_len; ++cur)
if(cur->included(print_nontzpfms, backend_restrixion, key_loadedness_restrixion)) if(cur->included(print_nontzpfms, backend_restrixion, key_loadedness_restrixion))
println(cur->name, cur->backend_display(), output_line::key_available_display[cur->key_available], output_line::coherent_display[cur->coherent]); println(cur->name, cur->backend_display(), output_line::key_available_display[cur->key_available], output_line::coherent_display[cur->coherent]);

View File

@ -27,7 +27,7 @@ int main(int argc, char ** argv) {
uint32_t * pcrs{}; uint32_t * pcrs{};
size_t pcrs_len{}; size_t pcrs_len{};
return do_main( return do_main(
argc, argv, "b:P:", "[-b backup-file] [-P PCR[,PCR]…]", argc, argv, "b:P:", gettext_noop("[-b backup-file] [-P PCR[,PCR]…]"),
[&](auto o) { [&](auto o) {
switch(o) { switch(o) {
case 'b': case 'b':
@ -103,8 +103,9 @@ int main(int argc, char ** argv) {
}}; }};
{ {
char what_for[ZFS_MAX_DATASET_NAME_LEN + 40 + 1]; char what_for[ZFS_MAX_DATASET_NAME_LEN + 512 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM1.X wrapping key (or empty for none)", zfs_get_name(dataset)); // %s=dataset, then TPM1.X. noun for "Enter passphrase for" prompt
snprintf(what_for, sizeof(what_for), gettext("%s %s wrapping key (or empty for none)"), zfs_get_name(dataset), THIS_BACKEND);
uint8_t * parent_key_passphrase{}; uint8_t * parent_key_passphrase{};
size_t parent_key_passphrase_len{}; size_t parent_key_passphrase_len{};

View File

@ -5,7 +5,6 @@
// #include <sys/zio_crypt.h> // #include <sys/zio_crypt.h>
#define WRAPPING_KEY_LEN 32 #define WRAPPING_KEY_LEN 32
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -59,15 +58,17 @@ int main(int argc, char ** argv) {
TRY_TPM1X("load sealed object from blob", Tspi_SetAttribData(sealed_object, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, TRY_TPM1X("load sealed object from blob", Tspi_SetAttribData(sealed_object, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB,
handle.sealed_object_blob_len, handle.sealed_object_blob)); handle.sealed_object_blob_len, handle.sealed_object_blob));
char what_for[ZFS_MAX_DATASET_NAME_LEN + 20 + 1]; char what_for[ZFS_MAX_DATASET_NAME_LEN + 512 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM1.X wrapping key", zfs_get_name(dataset)); // %s=dataset name, then TPM1.x. noun for "Enter passphrase for" prompt
snprintf(what_for, sizeof(what_for), gettext("%s %s wrapping key"), zfs_get_name(dataset), THIS_BACKEND);
uint8_t * loaded_wrap_key{}; uint8_t * loaded_wrap_key{};
uint32_t loaded_wrap_key_len{}; uint32_t loaded_wrap_key_len{};
TRY_MAIN(try_policy_or_passphrase("unseal wrapping key", what_for, parent_key_policy, TRY_MAIN(try_policy_or_passphrase("unseal wrapping key", what_for, parent_key_policy,
[&] { return Tspi_Data_Unseal(sealed_object, parent_key, &loaded_wrap_key_len, &loaded_wrap_key); })); [&] { return Tspi_Data_Unseal(sealed_object, parent_key, &loaded_wrap_key_len, &loaded_wrap_key); }));
if(loaded_wrap_key_len != sizeof(wrap_key)) { if(loaded_wrap_key_len != sizeof(wrap_key)) {
fprintf(stderr, "Wrong sealed data length (%" PRIu32 " != %zu): ", loaded_wrap_key_len, sizeof(wrap_key)); // 0A1234... follows
fprintf(stderr, gettext("Wrong sealed data length (%u != %zu): "), loaded_wrap_key_len, sizeof(wrap_key));
for(auto i = 0u; i < loaded_wrap_key_len; ++i) for(auto i = 0u; i < loaded_wrap_key_len; ++i)
fprintf(stderr, "%02hhX", loaded_wrap_key[i]); fprintf(stderr, "%02hhX", loaded_wrap_key[i]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");

View File

@ -5,7 +5,6 @@
// #include <sys/zio_crypt.h> // #include <sys/zio_crypt.h>
#define WRAPPING_KEY_LEN 32 #define WRAPPING_KEY_LEN 32
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include "../fd.hpp" #include "../fd.hpp"
@ -23,7 +22,7 @@ int main(int argc, char ** argv) {
TPML_PCR_SELECTION pcrs{}; TPML_PCR_SELECTION pcrs{};
bool allow_PCR_or_pass{}; bool allow_PCR_or_pass{};
return do_main( return do_main(
argc, argv, "b:P:A", "[-b backup-file] [-P algorithm:PCR[,PCR]…[+algorithm:PCR[,PCR]…]… [-A]]", argc, argv, "b:P:A", gettext_noop("[-b backup-file] [-P algorithm:PCR[,PCR]…[+algorithm:PCR[,PCR]…]… [-A]]"),
[&](auto o) { [&](auto o) {
switch(o) { switch(o) {
case 'b': case 'b':
@ -69,14 +68,15 @@ int main(int argc, char ** argv) {
TRY_MAIN(verify_backend(dataset, THIS_BACKEND, [&](auto previous_handle_s) { TRY_MAIN(verify_backend(dataset, THIS_BACKEND, [&](auto previous_handle_s) {
TPMI_DH_PERSISTENT previous_handle{}; TPMI_DH_PERSISTENT previous_handle{};
if(tpm2_parse_prop(zfs_get_name(dataset), previous_handle_s, previous_handle, nullptr)) if(tpm2_parse_prop(zfs_get_name(dataset), previous_handle_s, previous_handle, nullptr))
fprintf(stderr, "Couldn't parse previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c %s\" or equivalent!\n", fprintf(stderr,
gettext("Couldn't parse previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c %s\" or equivalent!\n"),
zfs_get_name(dataset), previous_handle_s); zfs_get_name(dataset), previous_handle_s);
else { else {
if(tpm2_free_persistent(tpm2_ctx, tpm2_session, previous_handle)) if(tpm2_free_persistent(tpm2_ctx, tpm2_session, previous_handle))
fprintf(stderr, fprintf(
"Couldn't free previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c 0x%" PRIX32 stderr,
"\" or equivalent!\n", gettext("Couldn't free previous persistent handle for dataset %s. You might need to run \"tpm2_evictcontrol -c 0x%X\" or equivalent!\n"),
zfs_get_name(dataset), previous_handle); zfs_get_name(dataset), previous_handle);
} }
})); }));
@ -91,7 +91,7 @@ int main(int argc, char ** argv) {
bool ok = false; // Try to free the persistent handle if we're unsuccessful in actually using it later on bool ok = false; // Try to free the persistent handle if we're unsuccessful in actually using it later on
quickscope_wrapper persistent_clearer{[&] { quickscope_wrapper persistent_clearer{[&] {
if(!ok && tpm2_free_persistent(tpm2_ctx, tpm2_session, persistent_handle)) if(!ok && tpm2_free_persistent(tpm2_ctx, tpm2_session, persistent_handle))
fprintf(stderr, "Couldn't free persistent handle. You might need to run \"tpm2_evictcontrol -c 0x%" PRIX32 "\" or equivalent!\n", fprintf(stderr, gettext("Couldn't free persistent handle. You might need to run \"tpm2_evictcontrol -c 0x%X\" or equivalent!\n"),
persistent_handle); persistent_handle);
if(!ok) if(!ok)
clear_key_props(dataset); clear_key_props(dataset);

View File

@ -30,4 +30,4 @@ struct quickscope_wrapper {
}; };
template <class F> template <class F>
quickscope_wrapper(F)->quickscope_wrapper<F>; quickscope_wrapper(F) -> quickscope_wrapper<F>;

View File

@ -74,8 +74,17 @@ static int get_key_material_helper(const char * helper, const char * whom, bool
if(auto pid = TRY_HELPER("create child", fork()); pid == 0) { // child if(auto pid = TRY_HELPER("create child", fork()); pid == 0) { // child
dup2(pipes[1], 1); dup2(pipes[1], 1);
const char * fmt;
if(!newkey && !again)
fmt = gettext("Passphrase for %s");
else if(!newkey && again)
fmt = gettext("Passphrase for %s (again)");
else if(newkey && !again)
fmt = gettext("New passphrase for %s");
else // newkey && again
fmt = gettext("New passphrase for %s (again)");
char * msg; char * msg;
if(asprintf(&msg, "%sassphrase for %s%s", newkey ? "New p" : "P", whom, again ? " (again)" : "") == -1) if(asprintf(&msg, fmt, whom) == -1)
msg = const_cast<char *>(whom); msg = const_cast<char *>(whom);
execl("/bin/sh", "sh", "-c", helper, helper, msg, whom, newkey ? "new" : "", again ? "again" : "", nullptr); execl("/bin/sh", "sh", "-c", helper, helper, msg, whom, newkey ? "new" : "", again ? "again" : "", nullptr);
@ -119,13 +128,11 @@ static int get_key_material_helper(const char * helper, const char * whom, bool
case 127: // ENOENT, error already written by shell or child case 127: // ENOENT, error already written by shell or child
return -1; return -1;
default: default:
fprintf(stderr, "Helper '%s' failed with %d.\n", helper, WEXITSTATUS(err)); // exit status
return __LINE__; return fprintf(stderr, gettext("Helper '%s' failed with %d.\n"), helper, WEXITSTATUS(err)), __LINE__;
} }
else { else
fprintf(stderr, "Helper '%s' died to signal %d: %s.\n", helper, WTERMSIG(err), strsignal(WTERMSIG(err))); return fprintf(stderr, gettext("Helper '%s' died to signal %d: %s.\n"), helper, WTERMSIG(err), strsignal(WTERMSIG(err))), __LINE__;
return __LINE__;
}
} }
@ -147,8 +154,8 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
caught_interrupt = 0; caught_interrupt = 0;
act.sa_handler = [](auto sig) { act.sa_handler = [](auto sig) {
caught_interrupt = sig; caught_interrupt = sig;
fputs("^C\n", stderr); fputs("^C\n", stderr);
}; };
sigaction(SIGINT, &act, &osigint); sigaction(SIGINT, &act, &osigint);
@ -156,7 +163,16 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
sigaction(SIGTSTP, &act, &osigtstp); sigaction(SIGTSTP, &act, &osigtstp);
// Prompt for the key // Prompt for the key
printf("%s %spassphrase for %s: ", again ? "Re-enter" : "Enter", newkey ? "new " : "", whom); const char * fmt;
if(!again && !newkey)
fmt = gettext("Enter passphrase for %s: ");
else if(!again && newkey)
fmt = gettext("Enter passphrase for new %s: ");
else if(again && !newkey)
fmt = gettext("Re-enter passphrase for %s: ");
else // again && newkey
fmt = gettext("Re-enter passphrase for new %s: ");
printf(fmt, whom);
fflush(stdout); fflush(stdout);
// Disable the terminal echo for key input // Disable the terminal echo for key input
@ -232,7 +248,7 @@ int read_known_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, s
if(len_out <= max_len) if(len_out <= max_len)
return 0; return 0;
fprintf(stderr, "Passphrase too long (max %zu)\n", max_len); fprintf(stderr, gettext("Passphrase too long (max %zu)\n"), max_len);
free(buf); free(buf);
buf = nullptr; buf = nullptr;
len_out = 0; len_out = 0;
@ -246,9 +262,9 @@ int read_new_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, siz
quickscope_wrapper first_passphrase_deleter{[&] { free(first_passphrase); }}; quickscope_wrapper first_passphrase_deleter{[&] { free(first_passphrase); }};
if(first_passphrase_len != 0 && first_passphrase_len < MIN_PASSPHRASE_LEN) if(first_passphrase_len != 0 && first_passphrase_len < MIN_PASSPHRASE_LEN)
return fprintf(stderr, "Passphrase too short (min %u)\n", MIN_PASSPHRASE_LEN), __LINE__; return fprintf(stderr, gettext("Passphrase too short (min %u)\n"), MIN_PASSPHRASE_LEN), __LINE__;
if(first_passphrase_len > max_len) if(first_passphrase_len > max_len)
return fprintf(stderr, "Passphrase too long (max %zu)\n", max_len), __LINE__; return fprintf(stderr, gettext("Passphrase too long (max %zu)\n"), max_len), __LINE__;
uint8_t * second_passphrase{}; uint8_t * second_passphrase{};
size_t second_passphrase_len{}; size_t second_passphrase_len{};
@ -256,7 +272,7 @@ int read_new_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, siz
quickscope_wrapper second_passphrase_deleter{[&] { free(second_passphrase); }}; quickscope_wrapper second_passphrase_deleter{[&] { free(second_passphrase); }};
if(second_passphrase_len != first_passphrase_len || memcmp(first_passphrase, second_passphrase, first_passphrase_len)) if(second_passphrase_len != first_passphrase_len || memcmp(first_passphrase, second_passphrase, first_passphrase_len))
return fprintf(stderr, "Provided keys do not match.\n"), __LINE__; return fprintf(stderr, gettext("Provided passphrases do not match.\n")), __LINE__;
if(second_passphrase_len) if(second_passphrase_len)
buf = std::exchange(second_passphrase, nullptr); buf = std::exchange(second_passphrase, nullptr);

View File

@ -5,16 +5,16 @@
#include "common.hpp" #include "common.hpp"
#include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
template <class F> template <class F>
int with_stdin_at(int fd, F && what) { int with_stdin_at(int fd, F && what) {
auto stdin_saved = TRY("dup() stdin", dup(0)); auto stdin_saved = dup(0);
quickscope_wrapper stdin_saved_deleter{[=] { close(stdin_saved); }}; quickscope_wrapper stdin_saved_deleter{[=] { close(stdin_saved); }};
TRY("dup2() onto stdin", dup2(fd, 0)); dup2(fd, 0);
clearerr(stdin); clearerr(stdin);
if(int ret = what()) { if(int ret = what()) {
@ -22,7 +22,7 @@ int with_stdin_at(int fd, F && what) {
return ret; return ret;
} }
TRY("dup2() stdin back onto stdin", dup2(stdin_saved, 0)); dup2(stdin_saved, 0);
return 0; return 0;
} }

View File

@ -5,10 +5,13 @@
#include "common.hpp" #include "common.hpp"
#include <libintl.h>
#include <libzfs.h> #include <libzfs.h>
#include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <type_traits> #include <type_traits>
#include <unistd.h> #include <unistd.h>
#define gettext_noop(s) s
#define TRY_PTR(what, ...) TRY_GENERIC(what, !, , errno, __LINE__, strerror, __VA_ARGS__) #define TRY_PTR(what, ...) TRY_GENERIC(what, !, , errno, __LINE__, strerror, __VA_ARGS__)
@ -23,6 +26,11 @@ template <class G, class M, class V = int (*)()>
static int do_bare_main( static int do_bare_main(
int argc, char ** argv, const char * getoptions, const char * usage, const char * dataset_usage, G && getoptfn, M && main, int argc, char ** argv, const char * getoptions, const char * usage, const char * dataset_usage, G && getoptfn, M && main,
V && validate = []() { return 0; }) { V && validate = []() { return 0; }) {
setlocale(LC_ALL, "");
// bindtextdomain("tzpfms", "/usr/share/locale");
bindtextdomain("tzpfms", "out/loc");
textdomain("tzpfms");
const auto libz = TRY_PTR("initialise libzfs", libzfs_init()); const auto libz = TRY_PTR("initialise libzfs", libzfs_init());
quickscope_wrapper libz_deleter{[=] { libzfs_fini(libz); }}; quickscope_wrapper libz_deleter{[=] { libzfs_fini(libz); }};
@ -35,7 +43,8 @@ static int do_bare_main(
switch(opt) { switch(opt) {
case '?': case '?':
case 'h': case 'h':
fprintf(opt == 'h' ? stdout : stderr, "Usage: %s [-hV] %s%s%s\n", argv[0], usage, strlen(usage) ? " " : "", dataset_usage); fprintf(opt == 'h' ? stdout : stderr, gettext("usage: %s [-hV] %s%s%s\n"), argv[0], *usage ? gettext(usage) : "", *usage ? " " : "",
gettext(dataset_usage));
return opt == 'h' ? 0 : __LINE__; return opt == 'h' ? 0 : __LINE__;
case 'V': case 'V':
puts("tzpfms version " TZPFMS_VERSION); puts("tzpfms version " TZPFMS_VERSION);
@ -47,29 +56,29 @@ static int do_bare_main(
TRY_MAIN(getoptfn(opt)); TRY_MAIN(getoptfn(opt));
else { else {
if(auto err = getoptfn(opt)) if(auto err = getoptfn(opt))
return fprintf(stderr, "Usage: %s [-hV] %s%s%s\n", argv[0], usage, strlen(usage) ? " " : "", dataset_usage), err; return fprintf(stderr, gettext("usage: %s [-hV] %s%s%s\n"), argv[0], *usage ? gettext(usage) : "", *usage ? " " : "", gettext(dataset_usage)), err;
} }
} }
if(auto err = validate()) if(auto err = validate())
return fprintf(stderr, "Usage: %s [-hV] %s%s%s\n", argv[0], usage, strlen(usage) ? " " : "", dataset_usage), err; return fprintf(stderr, gettext("usage: %s [-hV] %s%s%s\n"), argv[0], *usage ? gettext(usage) : "", *usage ? " " : "", gettext(dataset_usage)), err;
return main(libz); return main(libz);
} }
template <class G, class M, class V = int (*)()> template <class G, class M, class V = int (*)()>
static int do_main( static int do_main(int argc, char ** argv, const char * getoptions, const char * usage, G && getoptfn, M && main, V && validate = []() { return 0; }) {
int argc, char ** argv, const char * getoptions, const char * usage, G && getoptfn, M && main, V && validate = []() { return 0; }) {
return do_bare_main( return do_bare_main(
argc, argv, getoptions, usage, "dataset", getoptfn, // as-in argument in a usage string
argc, argv, getoptions, usage, gettext_noop("dataset"), getoptfn,
[&](auto libz) { [&](auto libz) {
if(!*(argv + optind)) if(!*(argv + optind))
return fprintf(stderr, return fprintf(stderr,
"No dataset to act on?\n" gettext("No dataset to act on?\n"
"Usage: %s [-hV] %s%sdataset\n", "usage: %s [-hV] %s%sdataset\n"),
argv[0], usage, strlen(usage) ? " " : ""), argv[0], usage, strlen(usage) ? " " : ""),
__LINE__; __LINE__;
if(*(argv + optind + 1)) if(*(argv + optind + 1))
return fprintf(stderr, "Usage: %s [-hV] %s%sdataset\n", argv[0], usage, strlen(usage) ? " " : ""), __LINE__; return fprintf(stderr, gettext("usage: %s [-hV] %s%sdataset\n"), argv[0], usage, strlen(usage) ? " " : ""), __LINE__;
auto dataset = TRY_PTR(nullptr, zfs_open(libz, argv[optind], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); auto dataset = TRY_PTR(nullptr, zfs_open(libz, argv[optind], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME));
quickscope_wrapper dataset_deleter{[&] { zfs_close(dataset); }}; quickscope_wrapper dataset_deleter{[&] { zfs_close(dataset); }};
@ -79,9 +88,9 @@ static int do_main(
TRY("get encryption root", zfs_crypto_get_encryption_root(dataset, &dataset_is_root, encryption_root)); TRY("get encryption root", zfs_crypto_get_encryption_root(dataset, &dataset_is_root, encryption_root));
if(!dataset_is_root && !strlen(encryption_root)) if(!dataset_is_root && !strlen(encryption_root))
return fprintf(stderr, "Dataset %s not encrypted?\n", zfs_get_name(dataset)), __LINE__; return fprintf(stderr, gettext("Dataset %s not encrypted?\n"), zfs_get_name(dataset)), __LINE__;
else if(!dataset_is_root) { else if(!dataset_is_root) {
fprintf(stderr, "Using dataset %s's encryption root %s instead.\n", zfs_get_name(dataset), encryption_root); fprintf(stderr, gettext("Using dataset %s's encryption root %s instead.\n"), zfs_get_name(dataset), encryption_root);
zfs_close(dataset); zfs_close(dataset);
dataset = TRY_PTR(nullptr, zfs_open(libz, encryption_root, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); dataset = TRY_PTR(nullptr, zfs_open(libz, encryption_root, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME));
} }

View File

@ -13,7 +13,7 @@ int do_clear_main(int argc, char ** argv, const char * this_backend, H && handle
return do_main( return do_main(
argc, argv, "", "", [&](auto) {}, argc, argv, "", "", [&](auto) {},
[&](auto dataset) { [&](auto dataset) {
REQUIRE_KEY_LOADED(dataset); REQUIRE_KEY_LOADED(dataset);
char * handle_s{}; char * handle_s{};
TRY_MAIN(parse_key_props(dataset, this_backend, handle_s)); TRY_MAIN(parse_key_props(dataset, this_backend, handle_s));

View File

@ -1,13 +1,13 @@
/* SPDX-License-Identifier: MIT */ // SPDX-License-Identifier: 0BSD
#pragma once #pragma once
#include <charconv> #include <charconv>
#include <errno.h>
#include <limits> #include <limits>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include <string.h> #include <string.h>

View File

@ -97,9 +97,11 @@ int tpm1x_parse_pcrs(char * arg, uint32_t *& pcrs, size_t & pcrs_len) {
for(arg = strtok_r(arg, ", ", &sv); arg; arg = strtok_r(nullptr, ", ", &sv)) { for(arg = strtok_r(arg, ", ", &sv); arg; arg = strtok_r(nullptr, ", ", &sv)) {
uint32_t pcr; uint32_t pcr;
if(!parse_uint(arg, pcr)) if(!parse_uint(arg, pcr))
return fprintf(stderr, "PCR %s: %s\n", arg, strerror(errno)), __LINE__; // user-supplied parameter, errno
return fprintf(stderr, gettext("PCR %s: %s\n"), arg, strerror(errno)), __LINE__;
if(pcr >= 230) if(pcr >= 230)
return fprintf(stderr, "PCR %s: too large (max 229).\n", arg), __LINE__; // user-supplied parameter
return fprintf(stderr, gettext("PCR %s: too large (max 229).\n"), arg), __LINE__;
auto idx = std::upper_bound(pcrs, pcrs + pcrs_len, pcr) - pcrs; auto idx = std::upper_bound(pcrs, pcrs + pcrs_len, pcr) - pcrs;
if(!idx || pcrs[idx - 1] != pcr) { if(!idx || pcrs[idx - 1] != pcr) {

View File

@ -9,7 +9,8 @@
#include <algorithm> #include <algorithm>
#include <inttypes.h> #include <inttypes.h>
#include <iterator> #include <iterator>
#define OPENSSL_SUPPRESS_DEPRECATED // SHA256_*(); supposedly replaced with EVP* but that's horseshit. we'll see how she turns out, given there's no reason given #define OPENSSL_SUPPRESS_DEPRECATED // SHA256_*(); supposedly replaced with EVP* but that's horseshit. we'll see how she turns out, given there's no reason
// given
#include <openssl/sha.h> #include <openssl/sha.h>
#include <optional> #include <optional>
#include <utility> #include <utility>
@ -20,7 +21,7 @@ static int try_or_passphrase(const char * what, const char * what_for, ESYS_CONT
auto err = func(); auto err = func();
for(int i = 0; err == TPM2_RC_9 + valid_error && i < 3; ++i) { for(int i = 0; err == TPM2_RC_9 + valid_error && i < 3; ++i) {
if(i) if(i)
fprintf(stderr, "Couldn't %s: %s\n", what, Tss2_RC_Decode(err)); fprintf(stderr, "Couldn't %s: %s\n", gettext(what), Tss2_RC_Decode(err));
uint8_t * pass{}; uint8_t * pass{};
size_t pass_len{}; size_t pass_len{};
@ -37,7 +38,7 @@ static int try_or_passphrase(const char * what, const char * what_for, ESYS_CONT
// TRY_TPM2() unrolled because no constexpr/string-literal-template arguments until C++20, which is not supported by GCC 8, which we need for Buster // TRY_TPM2() unrolled because no constexpr/string-literal-template arguments until C++20, which is not supported by GCC 8, which we need for Buster
if(err != TPM2_RC_SUCCESS) if(err != TPM2_RC_SUCCESS)
return fprintf(stderr, "Couldn't %s: %s\n", what, Tss2_RC_Decode(err)), __LINE__; return fprintf(stderr, "Couldn't %s: %s\n", gettext(what), Tss2_RC_Decode(err)), __LINE__;
return 0; return 0;
} }
@ -112,7 +113,8 @@ int tpm2_parse_pcrs(char * arg, TPML_PCR_SELECTION & pcrs) {
++per_hash; ++per_hash;
if(bank == pcrs.pcrSelections + (sizeof(pcrs.pcrSelections) / sizeof(*pcrs.pcrSelections))) // == TPM2_NUM_PCR_BANKS if(bank == pcrs.pcrSelections + (sizeof(pcrs.pcrSelections) / sizeof(*pcrs.pcrSelections))) // == TPM2_NUM_PCR_BANKS
return fprintf(stderr, "Too many PCR banks specified! Can only have up to %zu\n", sizeof(pcrs.pcrSelections) / sizeof(*pcrs.pcrSelections)), __LINE__; return fprintf(stderr, gettext("Too many PCR banks specified! Can only have up to %zu\n"), sizeof(pcrs.pcrSelections) / sizeof(*pcrs.pcrSelections)),
__LINE__;
if(auto sep = strchr(per_hash, ':')) { if(auto sep = strchr(per_hash, ':')) {
*sep = '\0'; *sep = '\0';
@ -127,8 +129,9 @@ int tpm2_parse_pcrs(char * arg, TPML_PCR_SELECTION & pcrs) {
if(!parse_uint(per_hash, bank->hash) || !std::binary_search(std::begin(tpm2_hash_algs), std::end(tpm2_hash_algs), tpm2_hash_algs_t{bank->hash, {}}, if(!parse_uint(per_hash, bank->hash) || !std::binary_search(std::begin(tpm2_hash_algs), std::end(tpm2_hash_algs), tpm2_hash_algs_t{bank->hash, {}},
[&](auto && lhs, auto && rhs) { return lhs.alg < rhs.alg; })) { [&](auto && lhs, auto && rhs) { return lhs.alg < rhs.alg; })) {
fprintf(stderr, fprintf(stderr,
"Unknown hash algorithm %s.\n" // comma-separated list follows
"Can be any of case-insensitive ", gettext("Unknown hash algorithm %s.\n"
"Can be any of case-insensitive "),
per_hash); per_hash);
auto first = true; auto first = true;
for(auto && alg : tpm2_hash_algs) for(auto && alg : tpm2_hash_algs)
@ -157,7 +160,8 @@ int tpm2_parse_pcrs(char * arg, TPML_PCR_SELECTION & pcrs) {
} }
} }
} else } else
return fprintf(stderr, "PCR bank \"%s\": no algorithm; need alg:PCR[,PCR]...\n", per_hash), __LINE__; // user-passed parameter
return fprintf(stderr, gettext("PCR bank \"%s\": no algorithm; need alg:PCR[,PCR]…\n"), per_hash), __LINE__;
} }
pcrs.count = bank - pcrs.pcrSelections; pcrs.count = bank - pcrs.pcrSelections;
@ -299,8 +303,8 @@ static int tpm2_police_pcrs(ESYS_CONTEXT * tpm2_ctx, const TPML_PCR_SELECTION &
return with_session(pcr_session); return with_session(pcr_session);
} }
int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, const TPML_PCR_SELECTION & pcrs,
const TPML_PCR_SELECTION & pcrs, bool allow_PCR_or_pass, void * data, size_t data_len) { bool allow_PCR_or_pass, void * data, size_t data_len) {
ESYS_TR primary_handle = ESYS_TR_NONE; ESYS_TR primary_handle = ESYS_TR_NONE;
quickscope_wrapper primary_handle_deleter{[&] { Esys_FlushContext(tpm2_ctx, primary_handle); }}; quickscope_wrapper primary_handle_deleter{[&] { Esys_FlushContext(tpm2_ctx, primary_handle); }};
@ -365,8 +369,9 @@ int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_sessio
memcpy(secret_sens.sensitive.data.buffer, data, secret_sens.sensitive.data.size); memcpy(secret_sens.sensitive.data.buffer, data, secret_sens.sensitive.data.size);
if(!pcrs.count || allow_PCR_or_pass) { if(!pcrs.count || allow_PCR_or_pass) {
char what_for[ZFS_MAX_DATASET_NAME_LEN + 38 + 1]; char what_for[ZFS_MAX_DATASET_NAME_LEN + 512 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM2 wrapping key (or empty for none)", dataset); // %s=dataset name, then TPM2. noun for "Enter passphrase for" prompt
snprintf(what_for, sizeof(what_for), gettext("%s %s wrapping key (or empty for none)"), dataset, "TPM2");
uint8_t * passphrase{}; uint8_t * passphrase{};
size_t passphrase_len{}; size_t passphrase_len{};
@ -415,8 +420,9 @@ int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_sessio
int tpm2_unseal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, const TPML_PCR_SELECTION & pcrs, int tpm2_unseal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, const TPML_PCR_SELECTION & pcrs,
void * data, size_t data_len) { void * data, size_t data_len) {
// Esys_FlushContext(tpm2_ctx, tpm2_session); // Esys_FlushContext(tpm2_ctx, tpm2_session);
char what_for[ZFS_MAX_DATASET_NAME_LEN + 18 + 1]; char what_for[ZFS_MAX_DATASET_NAME_LEN + 512 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM2 wrapping key", dataset); // %s=dataset name, then TPM2. noun for "Enter passphrase for" prompt
snprintf(what_for, sizeof(what_for), gettext("%s %s wrapping key"), dataset, "TPM2");
// Entirely fake and not flushable (tpm:parameter(1):value is out of range or is not correct for the context) // Entirely fake and not flushable (tpm:parameter(1):value is out of range or is not correct for the context)
ESYS_TR pandle; ESYS_TR pandle;
@ -430,7 +436,7 @@ int tpm2_unseal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_sess
// In case there's (PCR policy || passphrase): try PCR once; if it fails, fall back to passphrase // In case there's (PCR policy || passphrase): try PCR once; if it fails, fall back to passphrase
if(pcr_session != ESYS_TR_NONE) { if(pcr_session != ESYS_TR_NONE) {
if(auto err = unseal(pcr_session); err != TPM2_RC_SUCCESS) if(auto err = unseal(pcr_session); err != TPM2_RC_SUCCESS)
fprintf(stderr, "Couldn't %s with PCR policy: %s\n", "unseal wrapping key", Tss2_RC_Decode(err)); fprintf(stderr, gettext("Couldn't unseal wrapping key with PCR policy: %s\n"), Tss2_RC_Decode(err));
else else
return 0; return 0;
} }

View File

@ -98,8 +98,8 @@ int clear_key_props(zfs_handle_t * from) {
bool ok = false; bool ok = false;
quickscope_wrapper props_deleter{[&] { quickscope_wrapper props_deleter{[&] {
if(!ok) if(!ok)
fprintf(stderr, "You might need to run \"zfs inherit %s %s\" and \"zfs inherit %s %s\" to fully clear metadata!\n", PROPNAME_BACKEND, zfs_get_name(from), fprintf(stderr, gettext("You might need to run \"zfs inherit %s %s\" and \"zfs inherit %s %s\" to fully clear metadata!\n"), PROPNAME_BACKEND,
PROPNAME_KEY, zfs_get_name(from)); zfs_get_name(from), PROPNAME_KEY, zfs_get_name(from));
}}; }};
TRY("delete tzpfms.backend", zfs_prop_inherit(from, PROPNAME_BACKEND, B_FALSE)); TRY("delete tzpfms.backend", zfs_prop_inherit(from, PROPNAME_BACKEND, B_FALSE));
@ -113,13 +113,13 @@ int parse_key_props(zfs_handle_t * in, const char * our_backend, char *& handle)
TRY_MAIN(lookup_userprop(in, PROPNAME_BACKEND, backend)); TRY_MAIN(lookup_userprop(in, PROPNAME_BACKEND, backend));
if(!backend) if(!backend)
return fprintf(stderr, "Dataset %s not encrypted with tzpfms!\n", zfs_get_name(in)), __LINE__; return fprintf(stderr, gettext("Dataset %s not encrypted with tzpfms!\n"), zfs_get_name(in)), __LINE__;
if(strcmp(backend, our_backend)) if(strcmp(backend, our_backend))
return fprintf(stderr, "Dataset %s encrypted with tzpfms back-end %s, but we are %s.\n", zfs_get_name(in), backend, our_backend), __LINE__; return fprintf(stderr, gettext("Dataset %s encrypted with tzpfms back-end %s, but we are %s.\n"), zfs_get_name(in), backend, our_backend), __LINE__;
TRY_MAIN(lookup_userprop(in, PROPNAME_KEY, handle)); TRY_MAIN(lookup_userprop(in, PROPNAME_KEY, handle));
if(!handle) if(!handle)
return fprintf(stderr, "Dataset %s missing key data.\n", zfs_get_name(in)), __LINE__; return fprintf(stderr, gettext("Dataset %s missing key data.\n"), zfs_get_name(in)), __LINE__;
return 0; return 0;
} }

View File

@ -20,10 +20,10 @@
/// Mimic libzfs error output /// Mimic libzfs error output
#define REQUIRE_KEY_LOADED(dataset) \ #define REQUIRE_KEY_LOADED(dataset) \
do { \ do { \
if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) \ if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) \
return fprintf(stderr, "Key change error: Key must be loaded.\n"), __LINE__; \ return fprintf(stderr, gettext("Key change error: Key must be loaded.\n")), __LINE__; \
} while(0) } while(0)
@ -65,10 +65,14 @@ int verify_backend(zfs_handle_t * on, const char * this_backend, F && func) {
TRY_MAIN(lookup_userprop(on, PROPNAME_KEY, previous_handle)); TRY_MAIN(lookup_userprop(on, PROPNAME_KEY, previous_handle));
if(!!previous_backend ^ !!previous_handle) if(!!previous_backend ^ !!previous_handle)
fprintf(stderr, "Inconsistent tzpfms metadata for %s: back-end is %s, but handle is %s?\n", zfs_get_name(on), previous_backend, previous_handle); // dataset name: (null), 0A123...
// dataset name: TPM1.X, (null)
fprintf(stderr, gettext("Inconsistent tzpfms metadata for %s: back-end is %s, but handle is %s?\n"), zfs_get_name(on), previous_backend, previous_handle);
else if(previous_backend && previous_handle) { else if(previous_backend && previous_handle) {
if(strcmp(previous_backend, this_backend)) if(strcmp(previous_backend, this_backend))
fprintf(stderr, "Dataset %s was encrypted with tzpfms back-end %s before, but we are %s. You will have to free handle %s for back-end %s manually!\n", // dataset name: TPM1.X, TPM2. 0A1234..., TPM1.X
fprintf(stderr,
gettext("Dataset %s was encrypted with tzpfms back-end %s before, but we are %s. You will have to free handle %s for back-end %s manually!\n"),
zfs_get_name(on), previous_backend, this_backend, previous_handle, previous_backend); zfs_get_name(on), previous_backend, this_backend, previous_handle, previous_backend);
else else
func(previous_handle); func(previous_handle);

View File

@ -30,7 +30,7 @@ int change_key(zfs_handle_t * on, const uint8_t * wrap_key) {
if(zfs_crypto_rewrap(on, TRY_PTR("get rewrap args", rewrap_args()), B_FALSE)) if(zfs_crypto_rewrap(on, TRY_PTR("get rewrap args", rewrap_args()), B_FALSE))
return __LINE__; // Error printed by libzfs return __LINE__; // Error printed by libzfs
else else
printf("Key for %s changed\n", zfs_get_name(on)); printf(gettext("Key for %s changed\n"), zfs_get_name(on));
return 0; return 0;
}); });
@ -41,8 +41,11 @@ int load_key(zfs_handle_t * for_d, const uint8_t * wrap_key, bool noop) {
return with_stdin_at_buffer(wrap_key, WRAPPING_KEY_LEN, [&] { return with_stdin_at_buffer(wrap_key, WRAPPING_KEY_LEN, [&] {
if(zfs_crypto_load_key(for_d, noop ? B_TRUE : B_FALSE, nullptr)) if(zfs_crypto_load_key(for_d, noop ? B_TRUE : B_FALSE, nullptr))
return __LINE__; // Error printed by libzfs return __LINE__; // Error printed by libzfs
else else //
printf("Key for %s %s\n", zfs_get_name(for_d), noop ? "OK" : "loaded"); if(noop)
printf(gettext("Key for %s OK\n"), zfs_get_name(for_d));
else
printf(gettext("Key for %s loaded\n"), zfs_get_name(for_d));
return 0; return 0;
}); });

View File

@ -45,6 +45,11 @@
"name": "Manpages", "name": "Manpages",
"path": "man" "path": "man"
}, },
{
"follow_symlinks": true,
"name": "Localisation",
"path": "po"
},
{ {
"follow_symlinks": true, "follow_symlinks": true,
"name": "Build scripts", "name": "Build scripts",