From 92c91e1127b5e6a51642f4e619084deec3100b5c Mon Sep 17 00:00:00 2001 From: Troy Dawson Date: Thu, 15 Oct 2020 13:28:28 -0700 Subject: [PATCH] RHEL 9.0.0 Alpha bootstrap The content of this branch was automatically imported from Fedora ELN with the following as its source: https://src.fedoraproject.org/rpms/volume_key#aa271563e1153ee8924b84ca29995671f0f24a0d --- .gitignore | 10 + sources | 1 + tests/.fmf/version | 1 + tests/Sanity/basic-sanity/main.fmf | 16 + tests/Sanity/basic-sanity/runtest.sh | 354 ++++++++++++ tests/settings/environment.sh | 28 + tests/tests.yml | 14 + tests/utils/common.tcl | 39 ++ tests/utils/cryptsetup.exp | 66 +++ tests/utils/rlwrap.sh | 508 ++++++++++++++++++ tests/utils/utils.sh | 195 +++++++ tests/utils/volume_key.exp | 143 +++++ ...me_key-0.3.12-support_LUKS2_and_more.patch | 24 + volume_key.spec | 361 +++++++++++++ 14 files changed, 1760 insertions(+) create mode 100644 sources create mode 100644 tests/.fmf/version create mode 100644 tests/Sanity/basic-sanity/main.fmf create mode 100755 tests/Sanity/basic-sanity/runtest.sh create mode 100644 tests/settings/environment.sh create mode 100644 tests/tests.yml create mode 100644 tests/utils/common.tcl create mode 100755 tests/utils/cryptsetup.exp create mode 100644 tests/utils/rlwrap.sh create mode 100644 tests/utils/utils.sh create mode 100755 tests/utils/volume_key.exp create mode 100644 volume_key-0.3.12-support_LUKS2_and_more.patch create mode 100644 volume_key.spec diff --git a/.gitignore b/.gitignore index e69de29..92de226 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,10 @@ +/.project +/volume_key-0.3.3.tar.xz +/volume_key-0.3.4.tar.xz +/volume_key-0.3.5.tar.xz +/volume_key-0.3.6.tar.xz +/volume_key-0.3.7.tar.xz +/volume_key-0.3.8.tar.xz +/volume_key-0.3.9.tar.xz +/volume_key-0.3.10.tar.xz +/volume_key-0.3.12.tar.xz diff --git a/sources b/sources new file mode 100644 index 0000000..5250147 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (volume_key-0.3.12.tar.xz) = d056154c9b9d23e4eb661946dd59ed97e116903a3afcff9d9e29258408082f33dcbb69958724143f6bf191a3da488a03b6c02af287790990ed6459e29d66553c diff --git a/tests/.fmf/version b/tests/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/tests/Sanity/basic-sanity/main.fmf b/tests/Sanity/basic-sanity/main.fmf new file mode 100644 index 0000000..ad4c0fa --- /dev/null +++ b/tests/Sanity/basic-sanity/main.fmf @@ -0,0 +1,16 @@ +--- +component: volume_key +summary: basic sanity test for volume_key utility +contact: + - Jan Blazek + - Jiri Kucera +description: basic sanity test for volume_key utility +require: + - volume_key + - cryptsetup + - nss-tools + - expect + - tcllib +test: ./runtest.sh +duration: 10m +tier: 1 diff --git a/tests/Sanity/basic-sanity/runtest.sh b/tests/Sanity/basic-sanity/runtest.sh new file mode 100755 index 0000000..5ea92c8 --- /dev/null +++ b/tests/Sanity/basic-sanity/runtest.sh @@ -0,0 +1,354 @@ +#!/bin/bash +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/Sanity/basic-sanity/runtest.sh +# Author: Jan Blazek +# Jiri Kucera +# Brief: Basic sanity test for volume_key utility +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2017-2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +_TESTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" + +# Include Beaker environment +. /usr/bin/rhts-environment.sh || exit 1 +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +# Include utils +. ${_TESTDIR}/../../utils/utils.sh || { + echo "${_TESTDIR}/../../utils/utils.sh cannot be included." >&2 + exit 1 +} + +# Include test settings: +. ${_TESTDIR}/../../settings/environment.sh || { + errmsg "${_TESTDIR}/../../settings/environment.sh cannot be included." + exit 1 +} + +TEST="${TEST:-/CoreOS/volume_key/tests/Sanity/basic-sanity}" +TESTVERSION="${TESTVERSION:-1.0}" +PACKAGES="${PACKAGES:-volume_key}" +REQUIRES="${REQUIRES:-cryptsetup nss-tools expect tcllib}" + +_GNUPG_DIR="${HOME}/.gnupg" +_IMAGE="${_IMAGE:-image}" +_IMAGE_IMG="${_IMAGE}.img" +_PACKET="${_PACKET:-packet}" +_NEW_PACKET="${_NEW_PACKET:-new-packet}" +_PACKET_ASYM="${_PACKET_ASYM:-packet-asym}" +_NEW_PACKET_ASYM="${_NEW_PACKET_ASYM:-new-packet-asym}" +_ESCROW="${_ESCROW:-escrow}" +_ESCROW_PEM="${_ESCROW}.pem" +_NSSDB="${_NSSDB:-nssdb}" + +_LUKS_PASS="${_LUKS_PASS:-lukspass}" +_PACKET_PASS="${_PACKET_PASS:-packetpass}" +_NEW_PACKET_PASS="${_NEW_PACKET_PASS:-newpacketpass}" +_CERT_PASS="${_CERT_PASS:-certpass}" +_NEW_LUKS_PASS="${_NEW_LUKS_PASS:-newlukspass}" +_NEW_LUKS_PASS_ASYM="${_NEW_LUKS_PASS_ASYM:-newlukspass-asym}" + +_TEMP_DIR="" +_VOLUME="" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~ Setup +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +function Setup() { + LANG=C + LC_ALL=C + export EXPECT_SCRIPTS_PATH="${SCRIPTDIR}" + + rlAssertRpm --all || return $? + + if [[ -d "${_GNUPG_DIR}" ]]; then + rlFileBackup "${_GNUPG_DIR}" || return $? + AtCleanup rlFileRestore + else + AtCleanup Cleanup_RemoveGnuPG + fi + + rlRun CreateTemporaryDirectory || return $? + _TEMP_DIR="${Result}" + AtCleanup Cleanup_RemoveTemporaryDirectory + + PushDir "${_TEMP_DIR}" || return $? + AtCleanup PopDir + + CreateEncryptedVolume \ + --image "${_IMAGE_IMG}" \ + --password "${_LUKS_PASS}" \ + ${USE_LOSETUP:+--with-losetup} \ + || return $? + _VOLUME="${Result}" + AtCleanup Cleanup_DestroyVolume + + CreateCertificate --name "${_ESCROW}" || return $? + + SetupNSSDatabase --dest "${_TEMP_DIR}/${_NSSDB}" \ + --cert-name "${_ESCROW}" --password "${_CERT_PASS}" +} + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~ Cleanup +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +function Cleanup_RemoveGnuPG() { + RunCmd rm -rfv "${_GNUPG_DIR}" +} + +function Cleanup_RemoveTemporaryDirectory() { + RunCmd rm -rfv "${_TEMP_DIR}" +} + +function Cleanup_DestroyVolume() { + if [[ "${USE_LOSETUP:+yes}" == "yes" ]]; then + RunCmd losetup -d "${_VOLUME}" + fi +} + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~ Tests +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +function TestVolumeKeySave() { + RunCmdViaExpect + Command volume_key + Command --save "${_VOLUME}" --output-format=passphrase -o "${_PACKET}" + Input --lukspass "${_LUKS_PASS}" + Input --packetpass "${_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun +} +AddTest TestVolumeKeySave "save" + +function TestVolumeKeyRestore() { + rlAssertExists "${_PACKET}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key --restore "${_VOLUME}" "${_PACKET}" + Input --lukspass "${_NEW_LUKS_PASS}" + Input --packetpass "${_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + RunCmdViaExpect + Command cryptsetup luksOpen "${_VOLUME}" "${_IMAGE}" + Input --password "${_NEW_LUKS_PASS}" + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeyRestore "restore" + +function TestVolumeKeySetupVolume() { + rlAssertExists "${_PACKET}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key --setup-volume "${_VOLUME}" "${_PACKET}" "${_IMAGE}" + Input --packetpass "${_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeySetupVolume "setup-volume" + +function TestVolumeKeyReencrypt() { + rlAssertExists "${_PACKET}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key --reencrypt "${_PACKET}" -o "${_NEW_PACKET}" + Input --packetpass "${_PACKET_PASS}" + Input --newpacketpass "${_NEW_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key --setup-volume "${_VOLUME}" "${_NEW_PACKET}" "${_IMAGE}" + Input --packetpass "${_NEW_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeyReencrypt "reencrypt" + +function TestVolumeKeyDump() { + local __uuid="" + + rlAssertExists "${_PACKET}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + rlRunOptions -s + Command volume_key --dump "${_PACKET}" + Input --packetpass "${_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + __uuid="$(blkid -o value -s UUID "${_VOLUME}")" + + rlAssertGrep '^Packet format:\W+Passphrase-encrypted' "${rlRun_LOG}" -E + rlAssertGrep '^Volume format:\W+crypt_LUKS' "${rlRun_LOG}" -E + rlAssertGrep "^Volume UUID:\W+${__uuid}" "${rlRun_LOG}" -E + rlAssertGrep "^Volume path:\W+${_VOLUME}" "${rlRun_LOG}" -E +} +AddTest TestVolumeKeyDump "dump" + +function TestVolumeKeySecrets() { + rlAssertExists "${_PACKET}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + rlRunOptions -s + Command volume_key --secrets "${_PACKET}" + Input --packetpass "${_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + rlAssertGrep 'Data encryption key:\W+[0-9A-F]+' "${rlRun_LOG}" -E +} +AddTest TestVolumeKeySecrets "secrets" + +function TestVolumeKeySaveAsymmetric() { + RunCmdViaExpect + Command volume_key + Command --save "${_VOLUME}" --output-format=asymmetric + Command -c "${_ESCROW_PEM}" -o "${_PACKET_ASYM}" + Input --lukspass "${_LUKS_PASS}" + FinishRun +} +AddTest TestVolumeKeySaveAsymmetric "save asymmetric" + +function TestVolumeKeyRestoreAsymmetric() { + rlAssertExists "${_PACKET_ASYM}" || return $? + + RunCmdViaExpect + Command volume_key --restore "${_VOLUME}" "${_PACKET_ASYM}" -d "${_NSSDB}" + Input --certpass "${_CERT_PASS}" + Input --lukspass "${_NEW_LUKS_PASS_ASYM}" + FinishRun || return $? + + RunCmdViaExpect + Command cryptsetup luksOpen "${_VOLUME}" "${_IMAGE}" + Input --password "${_NEW_LUKS_PASS_ASYM}" + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeyRestoreAsymmetric "restore asymmetric" + +function TestVolumeKeySetupVolumeAsymmetric() { + rlAssertExists "${_PACKET_ASYM}" || return $? + + RunCmdViaExpect + Command volume_key + Command --setup-volume "${_VOLUME}" "${_PACKET_ASYM}" "${_IMAGE}" + Command -d "${_NSSDB}" + Input --certpass "${_CERT_PASS}" + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeySetupVolumeAsymmetric "setup-volume asymmetric" + +function TestVolumeKeyReencryptAsymmetric() { + rlAssertExists "${_PACKET_ASYM}" || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key --reencrypt + Command -d "${_NSSDB}" "${_PACKET_ASYM}" -o "${_NEW_PACKET_ASYM}" + Input --certpass "${_CERT_PASS}" + Input --newpacketpass "${_NEW_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + ClearGpgAgentsCache + RunCmdViaExpect + Command volume_key + Command --setup-volume "${_VOLUME}" "${_NEW_PACKET_ASYM}" "${_IMAGE}" + Input --packetpass "${_NEW_PACKET_PASS}" + Input ${USING_PINENTRY:+--pinentry} + FinishRun || return $? + + RunCmd ls -la /dev/mapper + rlAssertExists "/dev/mapper/${_IMAGE}" + + RunCmd cryptsetup luksClose "${_IMAGE}" +} +AddTest TestVolumeKeyReencryptAsymmetric "reencrypt asymmetric" + +function TestVolumeKeyDumpAsymmetric() { + local __uuid="" + + rlAssertExists "${_PACKET_ASYM}" || return $? + + RunCmdViaExpect + rlRunOptions -s + Command volume_key --dump "${_PACKET_ASYM}" -d "${_NSSDB}" + Input --certpass "${_CERT_PASS}" + FinishRun || return $? + + __uuid="$(blkid -o value -s UUID "${_VOLUME}")" + + rlAssertGrep '^Packet format:\W+Public key-encrypted' "${rlRun_LOG}" -E + rlAssertGrep '^Volume format:\W+crypt_LUKS' "${rlRun_LOG}" -E + rlAssertGrep "^Volume UUID:\W+${__uuid}" "${rlRun_LOG}" -E + rlAssertGrep "^Volume path:\W+${_VOLUME}" "${rlRun_LOG}" -E +} +AddTest TestVolumeKeyDumpAsymmetric "dump asymmetric" + +function TestVolumeKeySecretsAsymmetric() { + rlAssertExists "${_PACKET_ASYM}" || return $? + + RunCmdViaExpect + rlRunOptions -s + Command volume_key --secrets "${_PACKET_ASYM}" -d "${_NSSDB}" + Input --certpass "${_CERT_PASS}" + FinishRun || return $? + + rlAssertGrep 'Data encryption key:\W+[0-9A-F]+' "${rlRun_LOG}" -E +} +AddTest TestVolumeKeySecretsAsymmetric "secrets asymmetric" + +RunTest diff --git a/tests/settings/environment.sh b/tests/settings/environment.sh new file mode 100644 index 0000000..b11b9da --- /dev/null +++ b/tests/settings/environment.sh @@ -0,0 +1,28 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/settings/environment.sh +# Author: Jiri Kucera +# Brief: Environment variables with distribution specific values +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +export USE_LOSETUP="${USE_LOSETUP:-}" +export USING_PINENTRY="${USING_PINENTRY:-}" +export CLEAR_GPG_AGENTS_CACHE="${CLEAR_GPG_AGENTS_CACHE:-1}" diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..c113f70 --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,14 @@ +--- +- hosts: localhost + roles: + - role: standard-test-beakerlib + tags: + - classic + - container + fmf_filter: "tier: 1" + required_packages: + - volume_key + - cryptsetup + - expect + - tcllib + - nss-tools diff --git a/tests/utils/common.tcl b/tests/utils/common.tcl new file mode 100644 index 0000000..f9362b5 --- /dev/null +++ b/tests/utils/common.tcl @@ -0,0 +1,39 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/utils/common.tcl +# Author: Jiri Kucera +# Brief: Common utilities for expect scripts +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +proc oneof {l1 l2} { + foreach x $l1 { + if {$x in $l2} { + return 1 + } + } + return 0 +} + +proc verify_password {password} { + if {$password == ""} { + return -code error "password required!" + } +} diff --git a/tests/utils/cryptsetup.exp b/tests/utils/cryptsetup.exp new file mode 100755 index 0000000..8da7496 --- /dev/null +++ b/tests/utils/cryptsetup.exp @@ -0,0 +1,66 @@ +#!/usr/bin/expect -f +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/utils/cryptsetup.exp +# Author: Jiri Kucera +# Brief: Expect wrapper around cryptsetup +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +package require cmdline + +source [file join [file dirname [info script]] "common.tcl"] + +set options { + {password.arg "" "Password required by some cryptsetup actions"} +} + +set usage "\[options\] -- cryptsetup_options\noptions:" + +if {[catch { + array set params [::cmdline::getoptions argv $options $usage] +} result]} { + if {$::errorCode eq {CMDLINE USAGE}} { + puts $result + exit 0 + } + puts $::errorCode + puts $::errorInfo + exit 1 +} + +set password $params(password) + +eval spawn cryptsetup $::argv +if {"luksFormat" in $::argv} { + verify_password $password + expect -re "^Are you sure.*:" + send -- "YES\r" + expect -re "Enter( LUKS)? passphrase.*" + send -- "$password\r" + expect -re "Verify passphrase.*" + send -- "$password\r" + expect eof +} elseif {"luksOpen" in $::argv} { + verify_password $password + expect -re "Enter passphrase for.*" + send -- "$password\r" + expect eof +} diff --git a/tests/utils/rlwrap.sh b/tests/utils/rlwrap.sh new file mode 100644 index 0000000..dd9b97b --- /dev/null +++ b/tests/utils/rlwrap.sh @@ -0,0 +1,508 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/utils/rlwrap.sh +# Author: Jiri Kucera +# Brief: Wrapper around beakerlib (rlX) functions +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## +# Result, ResultA, ResultB +# +# If a function has an output, it is stored inside these variables. +Result="" +ResultA="" +ResultB="" + +# Internal variables used by RunCmdViaExpect family of functions. +_rlwrap_expect_script_path="" +declare -ag _rlwrap_rlRun_options=() +declare -ag _rlwrap_expect_options=() +_rlwrap_expect_script="" +_rlwrap_expect_script_scommand="" +declare -ag _rlwrap_expect_script_command_args=() +declare -ag _rlwrap_expect_script_input_args=() +_rlwrap_rlRun_status="0" +_rlwrap_rlRun_comment="" + +# Internal variables used by RunTest family of functions. +declare -ag _CleanupActions=() +declare -ag _Tests=() + +## +# errmsg ERRMSG +# +# ERRMSG +# error message +# +# Print ERRMSG to standard error output. +function errmsg() { + echo "$1" >&2 +} + +## +# required_options OPTION_LIST +# +# OPTION_LIST +# a list of option names (without --) +# +# For every X from OPTION_LIST, test if --$X was specified by checking that +# __${X//-/_} is not empty. +function required_options() { + local __optvar="" + + while [[ $# -gt 0 ]]; do + __optvar="__${1//-/_}" + if [[ -z "${!__optvar}" ]]; then + errmsg "${FUNCTION[1]}: Missing required option: --$1" + return 1 + fi + shift + done +} + +## +# invalid_argument ARG_NAME +# +# ARG_NAME +# argument name +# +# Report to standard error output that ARG_NAME is not a valid argument and +# return 1. +function invalid_argument() { + errmsg "${FUNCTION[1]}: Invalid argument '$1'." + return 1 +} + +## +# Concat ARGS +# +# ARGS +# list of arguments +# +# Make a string by concatenating all arguments from ARGS. Useful for creating +# long comments for rlRun. +function Concat() { + echo "$*" +} + +## +# RunCmd COMMAND [COMMAND_ARGS] +# +# COMMAND +# command that should be run +# COMMAND_ARGS +# command arguments +# +# Shorthand for RunCmdX -- COMMAND COMMAND_ARGS. +function RunCmd() { + RunCmdX -- "$@" +} + +## +# RunCmdX [-t] [-l] [-c] [-s] [STATUS] [COMMENT] [--] COMMAND [COMMAND_ARGS] +# +# -t, -l, -c, -s +# see rlRun +# STATUS +# see rlRun +# COMMENT +# see rlRun +# -- +# options-command delimiter +# COMMAND +# command that should be run +# COMMAND_ARGS +# command arguments +# +# Wrapper around beakerlib's rlRun that allows COMMAND and its arguments to be +# passed separately and not as one long string. +function RunCmdX() { + local __tflag="" + local __lflag="" + local __cflag="" + local __sflag="" + local __command="" + local __status="0" + local __comment="" + + # Handle short options: + while [[ $# -gt 0 ]]; do + case "$1" in + -t) __tflag="$1" ;; + -l) __lflag="$1" ;; + -c) __cflag="$1" ;; + -s) __sflag="$1" ;; + *) break ;; + esac + shift + done + + # First positional argument before -- is expected status code: + if [[ -n "${1:-}" ]] && [[ "$1" != "--" ]]; then + __status="$1" + shift + fi + + # Second positional argument before -- is comment: + if [[ -n "${1:-}" ]] && [[ "$1" != "--" ]]; then + __comment="$1" + shift + fi + + # Consume options-command delimiter: + if [[ "${1:-}" == "--" ]]; then + shift + fi + + # Command name is required: + if [[ -z "${1:-}" ]]; then + errmsg "Expected command." + return 1 + fi + __command="$1"; shift + + # The rest of options are command arguments: + while [[ $# -gt 0 ]]; do + __command="${__command} $1" + shift + done + + # Let the game begin: + rlRun ${__tflag} ${__lflag} ${__cflag} ${__sflag} \ + "${__command}" "${__status}" "${__comment}" +} + +## +# RunCmdViaExpect +# +# Starts a specification of command that should be run via expect. This is +# handy for interactive commands. General usage is +# +# RunCmdViaExpect +# Path ${ScriptsDir} +# rlRunOptions -s +# ExpectOptions -f +# Command cryptsetup luksFormat ${VOLUME} +# Input --password ${PASSWD} +# Status 0 +# Comment "Format ${VOLUME}" +# FinishRun || return $? +# +# In the example above, Path specifies the directory where the expect script +# is located. If it is omitted, EXPECT_SCRIPTS_PATH environment variable is +# read. If EXPECT_SCRIPTS_PATH is not set, `.` is used. +# +# rlRunOptions are options for rlRun, like -s and -t (see beakerlib manual). +# +# ExpectOptions are options for expect tool or Tcl interpreter, not for the +# script. +# +# Command is a command together with its arguments that will be run via expect. +# The first command argument, the command itself, is used as a name of expect +# script so in the example above the name of expect script will be +# cryptsetup.exp. This script must exist in directory specified by Path. The +# rest of Command arguments will be passed to the end of this script's command +# line and it is up to script's implementation what happen to them. +# +# Input gather arguments that specify input data that are feed to command by +# expect tool when they are asked for. +# +# Input, Command, ExpectOptions, and rlRunOptions work in accumulative way. +# That is, you can write `Command cryptsetup luksFormat ${VOLUME}` as a two +# Command calls, e.g. `Command cryptsetup` and `luksFormat ${VOLUME}`. This +# allow to split long commands accross multiple lines without using backslash +# character, which has the benefit of writing comments for particular command +# options. +# +# Status is the expected status/return code (default is 0). +# +# Comment is the comment as described in rlRun documentation. The default +# comment is a string made from arguments of Command separated by spaces. +# +# FinishRun makes a final arguments for rlRun and execute it. In our case, the +# rlRun call will look like this +# +# rlRun -s "${ScriptsDir}/cryptsetup.exp -f -- --password ${PASSWD} -- +# luksFormat ${VOLUME}" 0 "Format ${VOLUME}" +# +# The return code of rlRun is the return code of FinishRun. To parse its +# command line, cryptsetup.exp uses cmdline package from tcllib. +function RunCmdViaExpect() { + _rlwrap_expect_script_path="${EXPECT_SCRIPTS_PATH:-.}" + _rlwrap_rlRun_options=() + _rlwrap_expect_options=() + _rlwrap_expect_script="" + _rlwrap_expect_script_scommand="" + _rlwrap_expect_script_command_args=() + _rlwrap_expect_script_input_args=() + _rlwrap_rlRun_status="0" + _rlwrap_rlRun_comment="" + + alias Path=_rlwrap_Path + alias rlRunOptions=_rlwrap_rlRunOptions + alias ExpectOptions=_rlwrap_ExpectOptions + alias Command=_rlwrap_Command + alias Input=_rlwrap_Input + alias Status=_rlwrap_Status + alias Comment=_rlwrap_Comment +} + +## +# _rlwrap_Path [PATH] +# +# PATH +# PATH to script directory +# +# See Path in RunCmdViaExpect. +function _rlwrap_Path() { + if [[ $# -gt 0 ]]; then + _rlwrap_expect_script_path="${1}" + fi +} + +## +# _rlwrap_rlRunOptions [OPTIONS] +# +# OPTIONS +# options for rlRun +# +# See rlRunOptions in RunCmdViaExpect. +function _rlwrap_rlRunOptions() { + _rlwrap_rlRun_options+=( "$@" ) +} + +## +# _rlwrap_ExpectOptions [OPTIONS] +# +# OPTIONS +# options for expect tool +# +# See ExpectOptions in RunCmdViaExpect. +function _rlwrap_ExpectOptions() { + _rlwrap_expect_options+=( "$@" ) +} + +## +# _rlwrap_Command [COMMAND_OR_OPTION] [COMMAND_OPTIONS] +# +# COMMAND_OR_OPTION +# command name or option (depending on a number of Command invocations) +# COMMAND_OPTIONS +# command options +# +# See Command in RunCmdViaExpect. +function _rlwrap_Command() { + if [[ -z "${_rlwrap_expect_script}" ]]; then + if [[ -n "${1:-}" ]]; then + _rlwrap_expect_script="${1}.exp" + _rlwrap_expect_script_scommand="${1}" + shift + fi + fi + + if [[ $# -gt 0 ]]; then + _rlwrap_expect_script_command_args+=( "$@" ) + _rlwrap_expect_script_scommand="${_rlwrap_expect_script_scommand} $*" + fi +} + +## +# _rlwrap_Input [OPTIONS] +# +# OPTIONS +# options for expect script that are used for passing input values to +# commands that are run from within the script +# +# See Input in RunCmdViaExpect. +function _rlwrap_Input() { + _rlwrap_expect_script_input_args+=( "$@" ) +} + +## +# _rlwrap_Status [STATUS_CODE] +# +# STATUS_CODE +# expected status/return code of expect script +# +# See Status in RunCmdViaExpect. +function _rlwrap_Status() { + if [[ $# -gt 0 ]]; then + _rlwrap_rlRun_status="${1}" + fi +} + +## +# _rlwrap_Comment [COMMENT] +# +# COMMENT +# comment to be passed to rlRun +# +# See Comment in RunCmdViaExpect. +function _rlwrap_Comment() { + if [[ $# -gt 0 ]]; then + _rlwrap_rlRun_comment="${1}" + fi +} + +## +# FinishRun +# +# See RunCmdViaExpect. +function FinishRun() { + local __command="" + + unalias Path + unalias rlRunOptions + unalias ExpectOptions + unalias Command + unalias Input + unalias Status + unalias Comment + + if [[ -z "${_rlwrap_expect_script}" ]]; then + errmsg "RunCmdViaExpect: Missing name of expect script!" + errmsg "| The name of expect script is deduced from the first" + errmsg "| argument given to Command." + return 1 + fi + + if [[ -z "${_rlwrap_rlRun_comment}" ]]; then + _rlwrap_rlRun_comment="${_rlwrap_expect_script_scommand}" + fi + + __command="${_rlwrap_expect_script_path}/${_rlwrap_expect_script}" + __command="${__command} ${_rlwrap_expect_options[*]} --" + __command="${__command} ${_rlwrap_expect_script_input_args[*]} --" + __command="${__command} ${_rlwrap_expect_script_command_args[*]}" + + rlRun "${_rlwrap_rlRun_options[@]}" "${__command}" \ + "${_rlwrap_rlRun_status}" "${_rlwrap_rlRun_comment}" +} + +## +# CreateTemporaryDirectory +# +# Create a temporary directory and store its path to Result. +function CreateTemporaryDirectory() { + Result="$(mktemp -d)" +} + +## +# PushDir DIRECTORY +# +# DIRECTORY +# path to directory +# +# Perform `rlRun pushd DIRECTORY`. +function PushDir() { + RunCmd pushd "\"$1\"" +} + +## +# PopDir +# +# Perform `rlRun popd`. +function PopDir() { + RunCmd popd +} + +## +# AtCleanup COMMAND +# +# COMMAND +# cleanup action as a command +# +# Insert COMMAND to the beginning of the list of cleanup actions. +function AtCleanup() { + _CleanupActions=( "$1" "${_CleanupActions[@]}" ) +} + +## +# AddTest TESTFUNC [DESCRIPTION] +# +# TESTFUNC +# function that performs the test +# DESCRIPTION +# test description +# +# Add test to the list of tests. +function AddTest() { + _Tests+=( "$1=${2:-}" ) +} + +## +# DoSetup +# +# Invoke Setup function and return its status code. Setup must be defined +# before. +function DoSetup() { + local __status=0 + + rlPhaseStartSetup + if [[ "$(LC_ALL=C type -t Setup)" != "function" ]]; then + rlFail "Function 'Setup' is not defined. Please, define it." + else + Setup + fi + __status=$? + rlPhaseEnd + return ${__status} +} + +## +# DoTests +# +# Run all tests from the tests list. +function DoTests() { + for __testspec in "${_Tests[@]}"; do + # __testspec has the format 'testfunc=test description': + rlPhaseStartTest "${__testspec#*=}" + "${__testspec%%=*}" || : + rlPhaseEnd + done +} + +## +# DoCleanup +# +# Run all registered cleanup actions in the reverse order than they were +# registered by AtCleanup. +function DoCleanup() { + rlPhaseStartCleanup + for __action in "${_CleanupActions[@]}"; do + "${__action}" || : + done + rlPhaseEnd +} + +## +# RunTest +# +# Test runner entry point. Perform setup, run all tests, and perform cleanup. +function RunTest() { + rlJournalStart + + DoSetup && DoTests + DoCleanup + + rlJournalPrintText + rlJournalEnd +} diff --git a/tests/utils/utils.sh b/tests/utils/utils.sh new file mode 100644 index 0000000..9eca043 --- /dev/null +++ b/tests/utils/utils.sh @@ -0,0 +1,195 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/utils/utils.sh +# Author: Jiri Kucera +# Brief: Common shell utilities that helps test volume_key +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## +# SCRIPTDIR +# +# Path to the directory with auxiliary scripts. +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" + +# Include beakerlib wrapper: +. "${SCRIPTDIR}/rlwrap.sh" || { + echo "${SCRIPTDIR}/rlwrap.sh cannot be included." >&2 + exit 1 +} + +## +# ClearGpgAgentsCache +# +# If CLEAR_GPG_AGENTS_CACHE is set, clear gpg-agent's password cache. +function ClearGpgAgentsCache() { + local __pid="" + + if [[ "${CLEAR_GPG_AGENTS_CACHE:-}" == "1" ]] \ + && __pid="$(pidof -s gpg-agent)" + then + kill -s SIGHUP ${__pid} || : + fi +} + +## +# CreateEncryptedVolume --image IMAGE --password PASS [--with-losetup] +# +# --image IMAGE +# path to image file from which volume is created; IMAGE is created by +# dd so it should not to point to an existing file +# --password PASS +# password needed to encrypt the volume +# --with-losetup +# create a volume as loop device +# +# Create encrypted volume from IMAGE (use PASS for the encryption). The name of +# created volume is stored to Result. +function CreateEncryptedVolume() { + local __image="" + local __volume="" + local __password="" + local __with_losetup="" + + while [[ $# -gt 0 ]]; do + case "$1" in + --image) shift; __image="$1" ;; + --password) shift; __password="$1" ;; + --with-losetup) __with_losetup="yes" ;; + *) invalid_argument "$1"; return $? ;; + esac + shift + done + + required_options image password || return $? + + RunCmd dd if=/dev/zero of="${__image}" bs=1M count=256 || return $? + + __volume="${__image}" + if [[ "${__with_losetup}" == "yes" ]]; then + RunCmd losetup -v -f "${__image}" || return $? + __volume="$( + set -o pipefail + losetup -a | grep "${__image}" | cut -d: -f1 + )" || return $? + fi + + RunCmdViaExpect + Command cryptsetup luksFormat "${__volume}" + Input --password "${__password}" + FinishRun || return $? + + Result="${__volume}" +} + +## +# CreateCertificate --name NAME [--rsa-bits BITS] +# +# --name NAME +# certificate name +# --rsa-bits BITS +# RSA bits (default: 1024) +# +# Create NAME.key, NAME.cert, and NAME.pem inside current working directory. +function CreateCertificate() { + local __name="" + local __rsa_bits=1024 + local __key="" + local __cert="" + local __pem="" + local __subject="" + + while [[ $# -gt 0 ]]; do + case "$1" in + --name) shift; __name="$1" ;; + --rsa-bits) shift; __rsa_bits="$1" ;; + *) invalid_argument "$1"; return $? ;; + esac + shift + done + + required_options name || return $? + + __key="${__name}.key" + __cert="${__name}.cert" + __pem="${__name}.pem" + + RunCmd openssl genrsa ${__rsa_bits} \> "${__key}" || return $? + + __subject="/C=XX/ST=FooState/L=FooLocality/O=FooOrg/OU=FooOrgUnit" + __subject="${__subject}/CN=John/SN=Doe/emailAddress=jdoe@foo.bar" + + RunCmd openssl req -new -x509 -nodes -sha1 -days 365 \ + -key "${__key}" -subj "'${__subject}'" \> "${__cert}" \ + || return $? + + RunCmd cat "${__cert}" "${__key}" \> "${__pem}" +} + +## +# SetupNSSDatabase --dest DEST --cert-name NAME --password PASS +# +# --dest DEST +# path to directory that become NSS database +# --cert-name NAME +# the name of the certificate +# --password PASS +# a password (common for certificate and for NSS database) +# +# Create and initialize NSS database DEST with certificate NAME and secure it +# with password PASS. +function SetupNSSDatabase() { + local __dest="" + local __cert_name="" + local __password="" + local __pwdfile="" + local __pem="" + local __p12="" + + while [[ $# -gt 0 ]]; do + case "$1" in + --dest) shift; __dest="$1" ;; + --cert-name) shift; __cert_name="$1" ;; + --password) shift; __password="$1" ;; + *) invalid_argument "$1"; return $? ;; + esac + shift + done + + required_options dest cert-name password || return $? + + RunCmd mkdir -p "${__dest}" || return $? + + __pwdfile="$(mktemp "./pwdfileXXXXX")" || return $? + + __pem="${__cert_name}.pem" + __p12="${__cert_name}.p12" + + RunCmd echo "${__password}" \> "${__pwdfile}" || return $? + + RunCmd certutil -N -d "${__dest}" -f "${__pwdfile}" || return $? + + RunCmd openssl pkcs12 -export -in "${__pem}" -out "${__p12}" \ + -name "${__cert-name}" -password "pass:${__password}" \ + || return $? + + RunCmd pk12util -i "${__p12}" -d "${__dest}" \ + -K "${__password}" -W "${__password}" +} diff --git a/tests/utils/volume_key.exp b/tests/utils/volume_key.exp new file mode 100755 index 0000000..82ae878 --- /dev/null +++ b/tests/utils/volume_key.exp @@ -0,0 +1,143 @@ +#!/usr/bin/expect -f +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# File: ./tests/utils/volume_key.exp +# Author: Jiri Kucera +# Brief: Expect wrapper around volume_key +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +package require cmdline + +source [file join [file dirname [info script]] "common.tcl"] + +set options { + {certpass.arg "" "Password for certificate"} + {lukspass.arg "" "Password for LUKS encryption/decryption"} + {packetpass.arg "" "Password for escrow packet encryption/decryption"} + {newpacketpass.arg "" "New password for escrow packet reencryption"} + {pinentry "gpg-agent may ask for password via pinentry"} +} + +set usage "\[options\] -- volume_key_options\noptions:" + +if {[catch { + array set params [::cmdline::getoptions argv $options $usage] +} result]} { + if {$::errorCode eq {CMDLINE USAGE}} { + puts $result + exit 0 + } + puts $::errorCode + puts $::errorInfo + exit 1 +} + +set certpass $params(certpass) +set lukspass $params(lukspass) +set packetpass $params(packetpass) +set newpacketpass $params(newpacketpass) +set pinentry $params(pinentry) + +proc prompt_cert_password {password} { + verify_password $password + expect -re "Enter password for.*" + sleep 1 + send -- "$password\r" +} + +proc prompt_luks_password {password} { + verify_password $password + expect -re "Passphrase for.*" + sleep 1 + send -- "$password\r" +} + +proc prompt_new_luks_password {password} { + verify_password $password + expect -re "New passphrase for.*" + sleep 1 + send -- "$password\r" + expect -re "Repeat new passphrase for.*" + sleep 1 + send -- "$password\r" +} + +proc prompt_packet_password {password pinentry} { + verify_password $password + expect -re "Escrow packet passphrase.*" + sleep 1 + send -- "$password\r" + if {$pinentry} { + expect -re ".*Passphrase.*" + sleep 1 + send -- "$password\r" + } +} + +proc prompt_new_packet_password {password pinentry} { + verify_password $password + expect -re "New packet passphrase.*" + sleep 1 + send -- "$password\r" + expect -re "Repeat new packet passphrase.*" + sleep 1 + send -- "$password\r" + if {$pinentry} { + expect -re ".*Passphrase.*" + sleep 1 + send -- "$password\r" + expect -re ".*Passphrase.*" + sleep 1 + send -- "$password\r" + } +} + +eval spawn volume_key $::argv +if {"--reencrypt" in $::argv} { + if {"-d" in $::argv} { + prompt_cert_password $certpass + } else { + prompt_packet_password $packetpass $pinentry + } + prompt_new_packet_password $newpacketpass $pinentry + expect eof +} elseif {"--restore" in $::argv} { + if {"-d" in $::argv} { + prompt_cert_password $certpass + } else { + prompt_packet_password $packetpass $pinentry + } + prompt_new_luks_password $lukspass + expect eof +} elseif {"--save" in $::argv} { + prompt_luks_password $lukspass + if {"-c" ni $::argv} { + prompt_new_packet_password $packetpass $pinentry + } + expect eof +} elseif {[oneof {"--dump" "--secrets" "--setup-volume"} $::argv]} { + if {"-d" in $::argv} { + prompt_cert_password $certpass + } else { + prompt_packet_password $packetpass $pinentry + } + expect eof +} diff --git a/volume_key-0.3.12-support_LUKS2_and_more.patch b/volume_key-0.3.12-support_LUKS2_and_more.patch new file mode 100644 index 0000000..1e5be56 --- /dev/null +++ b/volume_key-0.3.12-support_LUKS2_and_more.patch @@ -0,0 +1,24 @@ +diff --git a/lib/volume_luks.c b/lib/volume_luks.c +index f4bf2c8..d1c5d47 100644 +--- a/lib/volume_luks.c ++++ b/lib/volume_luks.c +@@ -30,6 +30,10 @@ Author: Miloslav Trmač */ + #include "volume.h" + #include "volume_luks.h" + ++#ifndef CRYPT_LUKS ++#define CRYPT_LUKS NULL ++#endif ++ + /* LUKS - specific code */ + + /* Return an error message for ERR_NO, for g_free (). */ +@@ -105,7 +109,7 @@ open_crypt_device (const char *path, char **last_log_entry, GError **error) + if (r < 0) + goto err; + crypt_set_log_callback(cd, record_cryptsetup_log_entry, last_log_entry); +- r = crypt_load (cd, CRYPT_LUKS1, NULL); ++ r = crypt_load (cd, CRYPT_LUKS, NULL); + if (r < 0) + goto err_cd; + return cd; diff --git a/volume_key.spec b/volume_key.spec new file mode 100644 index 0000000..906288b --- /dev/null +++ b/volume_key.spec @@ -0,0 +1,361 @@ +# Define `python3_sitearch' if there is no one: +%{!?python3_sitearch:%global python3_sitearch %(%{__python3} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} + +# Enable Python 3 in Fedora and RHEL > 7 as default: +%if 0%{?fedora} || 0%{?rhel} > 7 +# Add `--without python3' option (enable python3 by default): +%bcond_without python3 +%else +# Add `--with python3' option (disable python3 by default): +%bcond_with python3 +%endif + +# Drop Python 2 in Fedora >= 30 and RHEL > 7 as default: +%if 0%{?fedora} >= 30 || 0%{?rhel} > 7 +%global drop_python2 1 +%global configure_with_python2 no +%else +# Define `python2_sitearch' if there is no one: +%{!?python2_sitearch:%global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} +%global configure_with_python2 yes +%endif + +%if %{with python3} +%global configure_with_python3 yes +%else +%global configure_with_python3 no +%endif + +# Additional configure options: +%global with_pythons --with-python=%{configure_with_python2} --with-python3=%{?configure_with_python3} + +Summary: An utility for manipulating storage encryption keys and passphrases +Name: volume_key +Version: 0.3.12 +Release: 9%{?dist} +# lib/{SECerrs,SSLerrs}.h are both licensed under MPLv1.1, GPLv2 and LGPLv2 +License: GPLv2 and (MPLv1.1 or GPLv2 or LGPLv2) +URL: https://pagure.io/%{name}/ +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +Source0: https://releases.pagure.org/%{name}/%{name}-%{version}.tar.xz +# Support all LUKS devices +# - backport of 26c09768662d8958debe8c9410dae9fda02292c3 +Patch0: volume_key-0.3.12-support_LUKS2_and_more.patch +BuildRequires: gcc +BuildRequires: cryptsetup-luks-devel, gettext-devel, glib2-devel, /usr/bin/gpg2 +BuildRequires: gpgme-devel, libblkid-devel, nss-devel, python3-devel +%if 0%{?drop_python2} < 1 +BuildRequires: python2-devel +%endif +# Needed by %%check: +BuildRequires: nss-tools + +%global desc_common The main goal of the software is to allow restoring access to an encrypted\ +hard drive if the primary user forgets the passphrase. The encryption key\ +back up can also be useful for extracting data after a hardware or software\ +failure that corrupts the header of the encrypted volume, or to access the\ +company data after an employee leaves abruptly. + +%global desc_app This package provides a command-line tool for manipulating storage volume\ +encryption keys and storing them separately from volumes.\ +\ +%{desc_common} + +%global desc_lib This package provides lib%{name}, a library for manipulating storage volume\ +encryption keys and storing them separately from volumes.\ +\ +%{desc_common} + +%global desc_python(V:) This package provides %%{-V:Python %%{-V*}}%%{!-V:Python} bindings for lib%{name}, a library for\ +manipulating storage volume encryption keys and storing them separately from\ +volumes.\ +\ +%{desc_common}\ +\ +%{name} currently supports only the LUKS volume encryption format. Support\ +for other formats is possible, some formats are planned for future releases. + +%description +%{desc_app} + +%package devel +Summary: A library for manipulating storage encryption keys and passphrases +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description devel +%{desc_lib} + +%package libs +Summary: A library for manipulating storage encryption keys and passphrases +Requires: /usr/bin/gpg2 + +%description libs +%{desc_lib} + +%if 0%{?drop_python2} < 1 +%package -n python2-%{name} +%{?python_provide:%python_provide python2-%{name}} +Summary: Python bindings for lib%{name} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description -n python2-%{name} +%desc_python +%endif + +%if %{with python3} +%package -n python3-%{name} +%{?python_provide:%python_provide python3-%{name}} +Summary: Python 3 bindings for lib%{name} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description -n python3-%{name} +%desc_python -V 3 +%endif + +%prep +%setup -q +%patch0 -p1 + +%build +%configure %{?with_pythons} +make %{?_smp_mflags} + +%install +make install DESTDIR=$RPM_BUILD_ROOT INSTALL='install -p' + +# Remove libtool archive +find %{buildroot} -type f -name "*.la" -delete + +%find_lang %{name} + +%check +make check || { \ +echo "======================== ./test-suite.log ========================"; \ +cat ./test-suite.log; \ +echo "=================================================================="; \ +exit 1; \ +} + +%ldconfig_scriptlets libs + +%files +%doc README contrib +%{_bindir}/%{name} +%{_mandir}/man8/%{name}.8* + +%files devel +%{_includedir}/%{name} +%{_libdir}/lib%{name}.so + +%files libs -f %{name}.lang +%doc AUTHORS COPYING ChangeLog NEWS +%{_libdir}/lib%{name}.so.* + +%if 0%{?drop_python2} < 1 +%files -n python2-%{name} +%{python2_sitearch}/_%{name}.so +%{python2_sitearch}/%{name}.py* +%endif + +%if %{with python3} +%files -n python3-%{name} +%{python3_sitearch}/_%{name}.so +%{python3_sitearch}/%{name}.py* +%{python3_sitearch}/__pycache__/%{name}.* +%endif + +%changelog +* Wed Jul 29 2020 Fedora Release Engineering - 0.3.12-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue May 26 2020 Miro Hrončok - 0.3.12-8 +- Rebuilt for Python 3.9 + +* Fri Jan 31 2020 Fedora Release Engineering - 0.3.12-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Oct 03 2019 Miro Hrončok - 0.3.12-6 +- Rebuilt for Python 3.8.0rc1 (#1748018) + +* Mon Aug 19 2019 Miro Hrončok - 0.3.12-5 +- Rebuilt for Python 3.8 + +* Sat Jul 27 2019 Fedora Release Engineering - 0.3.12-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Feb 03 2019 Fedora Release Engineering - 0.3.12-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 23 2019 Jiri Kucera - 0.3.12-2 +- Add support for LUKS2 and more +- Fix License tag + +* Mon Oct 08 2018 Jiri Kucera - 0.3.12-1 +- Update to volume_key-0.3.12 + Resolves: #1634850 + +* Sat Jul 14 2018 Fedora Release Engineering - 0.3.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed May 16 2018 Jiri Kucera - 0.3.10-1 +- Update to volume_key-0.3.10 + Resolves: #1479349, #1517016 + +* Wed Feb 14 2018 Iryna Shcherbina - 0.3.9-20 +- Update Python 2 dependency declarations to new packaging standards + (See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3) + +* Fri Feb 09 2018 Fedora Release Engineering - 0.3.9-19 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Feb 03 2018 Igor Gnatenko - 0.3.9-18 +- Switch to %%ldconfig_scriptlets + +* Tue Nov 7 2017 Miloslav Trmač - 0.3.9-17 +- Update for libcryptsetup ABI change + +* Sat Aug 19 2017 Zbigniew Jędrzejewski-Szmek - 0.3.9-16 +- Python 2 binary package renamed to python2-volume_key + See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3 + +* Thu Aug 03 2017 Fedora Release Engineering - 0.3.9-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 0.3.9-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon May 29 2017 Miloslav Trmač - 0.3.9-13 +- Point URL: and Source: to the new home at pagure.io + Resolves: 1456378 + +* Sat Feb 11 2017 Fedora Release Engineering - 0.3.9-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Sat Dec 10 2016 Igor Gnatenko - 0.3.9-11 +- Rebuild for gpgme 1.18 + +* Tue Jul 19 2016 Fedora Release Engineering - 0.3.9-10 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Fri Feb 05 2016 Fedora Release Engineering - 0.3.9-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Jun 19 2015 Fedora Release Engineering - 0.3.9-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Jan 13 2015 Miloslav Trmač - 0.3.9-7 +- Don't #include in libvolume_key.h + Patch by Vratislav Podzimek . + +* Mon Aug 18 2014 Fedora Release Engineering - 0.3.9-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sun Jun 08 2014 Fedora Release Engineering - 0.3.9-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sun Aug 04 2013 Fedora Release Engineering - 0.3.9-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Fri Feb 15 2013 Fedora Release Engineering - 0.3.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Thu Nov 22 2012 Miloslav Trmač - 0.3.9-2 +- Fix a crash when trying to use passphrase encryption in FIPS mode + +* Sat Sep 22 2012 Miloslav Trmač - 0.3.9-1 +- Update to volume_key-0.3.9 + +* Mon Aug 6 2012 Miloslav Trmač - 0.3.8-4 +- Use BuildRequires: /usr/bin/gpg instead of gnupg, for compatibility with RHEL + +* Mon Jul 23 2012 Miloslav Trmač - 0.3.8-3 +- Add Requires: /usr/bin/gpg + Resolves: #842074 + +* Sun Jul 22 2012 Fedora Release Engineering - 0.3.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Mar 3 2012 Miloslav Trmač - 0.3.8-1 +- Update to volume_key-0.3.8 + +* Sat Jan 14 2012 Fedora Release Engineering - 0.3.7-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Fri Oct 14 2011 Miloslav Trmač - 0.3.7-2 +- Rebuild with newer libcryptsetup + +* Wed Aug 24 2011 Miloslav Trmač - 0.3.7-1 +- Update to volume_key-0.3.7 + +* Fri Jun 10 2011 Miloslav Trmač - 0.3.6-2 +- Fix a typo + Resolves: #712256 + +* Thu Mar 31 2011 Miloslav Trmač - 0.3.6-1 +- Update to volume_key-0.3.6 + +* Mon Feb 07 2011 Fedora Release Engineering - 0.3.5-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Feb 4 2011 Miloslav Trmač - 0.3.5-2 +- Use %%{?_isa} in Requires: + +* Wed Nov 24 2010 Miloslav Trmač - 0.3.5-1 +- Update to volume_key-0.3.5 + +* Mon Oct 18 2010 Miloslav Trmač - 0.3.4-4 +- Tell the user if asking for the same passphrase again + Resolves: #641111 +- Check certificate file before interacting with the user + Resolves: #643897 + +* Fri Oct 8 2010 Miloslav Trmač - 0.3.4-3 +- Make it possible to interrupt password prompts + Resolves: #641111 + +* Wed Sep 29 2010 Miloslav Trmač - 0.3.4-2 +- Clarify which block device should be passed as an argument + Resolves: #636541 +- Recognize SSL error messages from NSS as well + Resolves: #638732 + +* Fri Aug 27 2010 Miloslav Trmač - 0.3.4-1 +- Update to volume_key-0.3.4 + +* Mon Jul 26 2010 Miloslav Trmač - 0.3.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild + +* Thu Jul 22 2010 Miloslav Trmač - 0.3.3-3 +- Fix build with new gpgme + +* Thu Jul 22 2010 David Malcolm - 0.3.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild + +* Fri Mar 26 2010 Miloslav Trmač - 0.3.3-1 +- Update to volume_key-0.3.3 + +* Thu Mar 4 2010 Miloslav Trmač - 0.3.2-1 +- Update to volume_key-0.3.2 +- Drop no longer necessary references to BuildRoot: + +* Fri Feb 5 2010 Miloslav Trmač - 0.3.1-2 +- Fix a crash when an empty passphrase is provided + Resolves: #558410 + +* Fri Dec 11 2009 Miloslav Trmač - 0.3.1-1 +- Update to volume_key-0.3.1. + +* Wed Sep 30 2009 Miloslav Trmač - 0.3-1 +- Update to volume_key-0.3. +- Drop bundled libcryptsetup. + +* Sat Aug 8 2009 Miloslav Trmač - 0.2-3 +- Handle changed "TYPE=crypto_LUKS" from libblkid +- Preserve file timestamps during installation + +* Sun Jul 26 2009 Fedora Release Engineering - 0.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 30 2009 Miloslav Trmač - 0.2-1 +- Initial build.