mirror of
https://git.sr.ht/~nabijaczleweli/tzpfms
synced 2025-04-11 09:30:02 +03:00
Proof passphrase.h. Fix helper for empty output, fortify against ENOMEM and mmap(2) error
This commit is contained in:
parent
8df40d5506
commit
ea0a5bd52e
@ -11,7 +11,7 @@
|
||||
[ -s /run/tzpfms-err ] && plymouth display-message --text="$(cat /run/tzpfms-err)"
|
||||
elif [ -e /run/systemd/system ] && command -v systemd-ask-password > /dev/null; then # --no-tty matches zfs and actually works
|
||||
# shellcheck disable=SC2016
|
||||
TZPFMS_PASSPHRASE_HELPER='exec systemd-ask-password --no-tty --id="tzpfms:$2" "$1: "' "$@" 2>/run/tzpfms-err; ret="$?"
|
||||
TZPFMS_PASSPHRASE_HELPER='exec systemd-ask-password --no-tty --id="tzpfms:$2" "$1:"' "$@" 2>/run/tzpfms-err; ret="$?"
|
||||
else
|
||||
# Mimic /scripts/zfs#decrypt_fs(): setting "printk" temporarily to "7" will allow prompt even if kernel option "quiet"
|
||||
read -r printk _ < /proc/sys/kernel/printk
|
||||
|
@ -3,24 +3,33 @@
|
||||
.Sh ENVIRONMENT VARIABLES
|
||||
.Bl -tag -compact -width "TZPFMS"
|
||||
.It Ev TZPFMS_PASSPHRASE_HELPER
|
||||
If set and nonempty, will be run as
|
||||
.Dl Pa /bin/ Ns Nm sh Fl c Li \&"$TZPFMS_PASSPHRASE_HELPER" \&"$TZPFMS_PASSPHRASE_HELPER" Qo Ar prepared prompt Qc Qo Ar target Qc Qo Oo Li new Oc Qc Qo Oo Li again Oc Qc
|
||||
to provide a passphrase, instead of reading from the standard input.
|
||||
If set and nonempty, will be run via
|
||||
.Pa /bin/ Ns Nm sh Fl c
|
||||
.\"Li \&"$TZPFMS_PASSPHRASE_HELPER" \&"$TZPFMS_PASSPHRASE_HELPER" Qo Ar prepared prompt Qc Qo Ar target Qc Qo Oo Li new Oc Qc Qo Oo Li again Oc Qc
|
||||
to provide a passphrase, instead of reading from the standard input stream.
|
||||
.Pp
|
||||
The standard output stream of the helper is tied to an anonymous file and used in its entirety as the passphrase, except for a trailing new-line, if any.
|
||||
The second argument contains either the dataset name or the element of the TPM hierarchy.
|
||||
The third argument is
|
||||
.Li new
|
||||
if this is for a new passphrase, and the fourth is
|
||||
.Li again
|
||||
if it's the second prompt for that passphrase.
|
||||
The first argument already contains all of this information, as a pre-formatted noun phrase.
|
||||
The arguments are:
|
||||
.Bl -enum -compact -offset "@@" -width "@"
|
||||
.It
|
||||
Pre-formatted noun phrase with all the information below
|
||||
.It
|
||||
Either the dataset name or the element of the TPM hierarchy.
|
||||
.It
|
||||
.Qq new
|
||||
if this is for a new passphrase
|
||||
.It
|
||||
.Qq again
|
||||
if it's the second prompt for that passphrase
|
||||
.El
|
||||
.Pp
|
||||
If the helper doesn't exist
|
||||
.Pq the shell exits with Sy 127 ,
|
||||
a diagnostic is issued and the normal prompt is used as fall-back.
|
||||
If it fails for any other reason, the prompting is aborted.
|
||||
.Pp
|
||||
An example value would be:
|
||||
.No ' Ns Nm systemd-ask-password Fl -id Ns Li = Ns Qo Li tzpfms:\& Ns Ar $2 Qc Qo Ar $1 Ns Li ": " Qc Ns ' .
|
||||
An example value facilitating
|
||||
.Xr systemd 1
|
||||
integration would be:
|
||||
.No ' Ns Ic exec Nm systemd-ask-password Fl -id Ns Li = Ns Qo Li tzpfms:\& Ns Ar $2 Qc Qo Ar $1 Ns Li ": " Qc Ns ' .
|
||||
.El
|
||||
|
26
src/fd.cpp
26
src/fd.cpp
@ -107,19 +107,25 @@ static int get_key_material_helper(const char * helper, const char * whom, bool
|
||||
case 0:
|
||||
struct stat sb;
|
||||
fstat(outfd, &sb);
|
||||
if(auto out = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, outfd, 0); out != MAP_FAILED) {
|
||||
if(!sb.st_size) // unmmappable
|
||||
return buf = nullptr, len_out = 0, 0;
|
||||
else if(auto out = static_cast<uint8_t *>(mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, outfd, 0)); out != MAP_FAILED) {
|
||||
quickscope_wrapper out_deleter{[=] { munmap(out, sb.st_size); }};
|
||||
buf = static_cast<uint8_t *>(malloc(sb.st_size)); // TODO:if failed
|
||||
len_out = sb.st_size;
|
||||
memcpy(buf, out, sb.st_size);
|
||||
// Trim ending newline, if any
|
||||
if(buf[len_out - 1] == '\n')
|
||||
buf[--len_out] = '\0';
|
||||
if(out[len_out - 1] == '\n') // Trim ending newline, if any
|
||||
--len_out;
|
||||
if(!len_out)
|
||||
buf = nullptr;
|
||||
else {
|
||||
if(!(buf = static_cast<uint8_t *>(malloc(len_out))))
|
||||
len_out = 0, (void)TRY("allocate passphrase", -1);
|
||||
memcpy(buf, out, len_out);
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
; // error
|
||||
TRY("read back passphrase", -1);
|
||||
|
||||
case 127: // enoent, error already written by shell or child
|
||||
case 127: // ENOENT, error already written by shell or child
|
||||
return -1;
|
||||
|
||||
default:
|
||||
@ -215,8 +221,8 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
|
||||
static int get_key_material_dispatch(const char * whom, bool again, bool newkey, uint8_t *& buf, size_t & len_out) {
|
||||
static const char * helper{};
|
||||
if(!helper)
|
||||
helper = getenv("TZPFMS_PASSPHRASE_HELPER");
|
||||
if(helper && *helper) {
|
||||
helper = getenv("TZPFMS_PASSPHRASE_HELPER") ?: "";
|
||||
if(*helper) {
|
||||
if(auto err = get_key_material_helper(helper, whom, again, newkey, buf, len_out); err != -1)
|
||||
return err;
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user