mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-12-22 10:08:58 +00:00
Pitchforked sphinx integration for remote password storage
This commit is contained in:
parent
a0c74985ca
commit
b054a83ee5
24
.travis.yml
24
.travis.yml
@ -1,26 +1,12 @@
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: c
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- zsh
|
||||
- gnupg
|
||||
- cryptsetup
|
||||
- pinentry-curses
|
||||
- gawk
|
||||
- libgcrypt20-dev
|
||||
- steghide
|
||||
- qrencode
|
||||
- e2fsprogs
|
||||
- python2.7
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_script:
|
||||
- make --directory=extras/kdf-keys
|
||||
- sudo make --directory=extras/kdf-keys install
|
||||
- sudo ./extras/install_cloakify.sh
|
||||
- docker build -t dyne/tomb .
|
||||
- docker run -it --privileged dyne/tomb /bin/bash -c "oracle & make test"
|
||||
|
||||
script:
|
||||
- make --directory=extras/kdf-keys test
|
||||
- make test
|
||||
- docker run -it --privileged dyne/tomb /bin/bash -c "make --directory=extras/kdf-keys test"
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM dyne/devuan:beowulf
|
||||
|
||||
RUN apt-get update -y -q && apt-get install -y -q zsh cryptsetup gawk libgcrypt20-dev steghide qrencode python python2.7 python3-pip python3-dev libsodium-dev libssl-dev make gcc g++ sudo gettext file bsdmainutils
|
||||
RUN pip3 install setuptools wheel
|
||||
|
||||
COPY . /Tomb/
|
||||
|
||||
WORKDIR /Tomb/extras
|
||||
RUN ./install_sphinx.sh
|
||||
RUN cp test/sphinx.cfg /etc/sphinx/config
|
||||
|
||||
WORKDIR /Tomb
|
||||
RUN make --directory=extras/kdf-keys
|
||||
RUN make --directory=extras/kdf-keys install
|
@ -4,8 +4,8 @@ wget https://github.com/TryCatchHCF/Cloakify/archive/v1.0.3.tar.gz -O /tmp/cloak
|
||||
mkdir -p extras/cloakify
|
||||
tar -xvf /tmp/cloakify.tar.gz --strip-components=1 -C $PWD/extras/cloakify
|
||||
echo "#!/bin/sh
|
||||
python2 $PWD/extras/cloakify/cloakify.py" > /usr/bin/cloakify
|
||||
python2 $PWD/extras/cloakify/cloakify.py $@" > /usr/bin/cloakify
|
||||
echo "#!/bin/sh
|
||||
python2 $PWD/extras/cloakify/decloakify.py" > /usr/bin/decloakify
|
||||
python2 $PWD/extras/cloakify/decloakify.py $@" > /usr/bin/decloakify
|
||||
chmod +x /usr/bin/cloakify
|
||||
chmod +x /usr/bin/decloakify
|
12
extras/install_sphinx.sh
Executable file
12
extras/install_sphinx.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
git clone https://github.com/stef/libsphinx
|
||||
cd libsphinx
|
||||
git submodule update --init --recursive --remote
|
||||
cd src
|
||||
sed -i 's|/usr/local|/usr|' makefile
|
||||
make
|
||||
sudo make install
|
||||
ldconfig
|
||||
pip3 install pwdsphinx
|
||||
sudo mkdir -p /etc/sphinx
|
@ -15,4 +15,16 @@ test_expect_success 'Testing tomb creation: dig, forge and lock' '
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test"
|
||||
test_expect_success 'Testing tomb creation: dig, forge and lock (sphinx password handling)' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
print $(echo $DUMMYPASS | sphinx get $DUMMYUSER $DUMMYHOST) \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| hexdump -C &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -44,4 +44,13 @@ if test_have_prereq LSOF; then
|
||||
'
|
||||
fi
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing open with good password (sphinx)' '
|
||||
tt_open --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
|
||||
test_done
|
||||
|
@ -16,4 +16,11 @@ if test_have_prereq RESIZER; then
|
||||
'
|
||||
fi
|
||||
|
||||
if test_have_prereq RESIZER SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing resize to 30 MB tomb (sphinx)' '
|
||||
tt resize -s 30 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -17,4 +17,16 @@ test_expect_success 'Testing tomb with GnuPG keys: passwd' '
|
||||
tt passwd -k $tomb_key -g -r $KEY2
|
||||
'
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing changing tomb password with sphinx' '
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
export test_description="Testing tomb bind hooks"
|
||||
|
||||
TEMPHOME=$HOME
|
||||
|
||||
source ./setup
|
||||
|
||||
test_export "test" # Using already generated tomb
|
||||
@ -14,9 +16,9 @@ test_expect_success 'Testing bind hooks' '
|
||||
rm -f "$MEDIA/$testname/bind-hooks" &&
|
||||
echo "$bindtest $bindtest" > "$MEDIA/$testname/bind-hooks" &&
|
||||
tt_close &&
|
||||
touch "/home/$USER/$bindtest" &&
|
||||
touch "$TEMPHOME/$bindtest" &&
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
RND2=$(cat "/home/$USER/$bindtest") &&
|
||||
RND2=$(cat "$TEMPHOME/$bindtest") &&
|
||||
[[ "$RND" = "$RND2" ]] &&
|
||||
tt list $testname &&
|
||||
tt_close
|
||||
|
@ -26,4 +26,23 @@ test_expect_success 'Testing tomb with GnuPG keys: setkey' '
|
||||
tt_close
|
||||
'
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing set key (sphinx)' '
|
||||
tt forge -k $tomb_key_new --tomb-pwd $DUMMYPASS \
|
||||
--ignore-swap --unsafe --use-urandom --force \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt setkey -k $tomb_key_new $tomb_key $tomb \
|
||||
--unsafe --tomb-pwd $DUMMYPASS --tomb-old-pwd $DUMMYPASS \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt open -k $tomb_key_new $tomb \
|
||||
--unsafe --tomb-pwd $DUMMYPASS \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key_new \
|
||||
| hexdump -C &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -55,6 +55,8 @@ command -v lsof > /dev/null && test_set_prereq LSOF
|
||||
command -v python2 > /dev/null && test_set_prereq PYTHON2
|
||||
command -v cloakify > /dev/null && test_set_prereq CLOAKIFY
|
||||
command -v decloakify > /dev/null && test_set_prereq DECLOAKIFY
|
||||
command -v sphinx > /dev/null && test_set_prereq SPHINX
|
||||
command -v oracle > /dev/null && test_set_prereq ORACLE
|
||||
|
||||
|
||||
# GnuPG config
|
||||
@ -73,6 +75,10 @@ chmod 700 "$GNUPGHOME"
|
||||
export DUMMYPASS=test
|
||||
export DUMMYPASSNEW=changetest
|
||||
|
||||
# Dummy host and username for sphinx
|
||||
export DUMMYHOST=example.com
|
||||
export DUMMYUSER=user
|
||||
|
||||
|
||||
# Test helpers
|
||||
|
||||
|
16
extras/test/sphinx.cfg
Normal file
16
extras/test/sphinx.cfg
Normal file
@ -0,0 +1,16 @@
|
||||
[client]
|
||||
verbose = False
|
||||
address = 127.0.0.1
|
||||
port = 2355
|
||||
datadir = /tmp/.sphinx/
|
||||
|
||||
[server]
|
||||
verbose = False
|
||||
address = 127.0.0.1
|
||||
port = 2355
|
||||
datadir = /tmp/.sphinx/
|
||||
keydir = /tmp/.sphinx/
|
||||
|
||||
[websphinx]
|
||||
pinentry=/usr/bin/pinentry
|
||||
log=
|
121
tomb
121
tomb
@ -76,6 +76,7 @@ typeset -i KDF=1
|
||||
typeset -i STEGHIDE=1
|
||||
typeset -i CLOAKIFY=1
|
||||
typeset -i DECLOAKIFY=1
|
||||
typeset -i SPHINX=1
|
||||
typeset -i RESIZER=1
|
||||
typeset -i SWISH=1
|
||||
typeset -i QRENCODE=1
|
||||
@ -501,6 +502,12 @@ ask_password() {
|
||||
[[ "$i" =~ "^D .*" ]] && password="${i##D }";
|
||||
done
|
||||
|
||||
# if sphinx mode is chosen, use the provided input
|
||||
# as master password to retrieve the actual password
|
||||
{ option_is_set --sphx-user } || { option_is_set --sphx-host } && {
|
||||
password=$(sphinx_get_password "$password")
|
||||
}
|
||||
|
||||
[[ "$password" = "" ]] && {
|
||||
_warning "Empty password"
|
||||
print "empty"
|
||||
@ -511,6 +518,64 @@ ask_password() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Retrieve PASSWORD from sphinx
|
||||
# $1 MASTER password for the password store
|
||||
# requires --sphx-host and --sphx-user flags to be set
|
||||
sphinx_get_password() {
|
||||
local errorfile
|
||||
local password
|
||||
{ option_is_set --sphx-user && option_is_set --sphx-host } && {
|
||||
# value error in sphinx doesn't set exit code
|
||||
# using tempfile as a workaround to notice the error
|
||||
errorfile=$(mktemp /tmp/tomb_error.XXXXXXXXX)
|
||||
password=$(echo "$1" | sphinx get $(option_value --sphx-user) $(option_value --sphx-host) 2>$errorfile)
|
||||
if ! grep -q "ValueError: fail" $errorfile ; then
|
||||
echo "$password"
|
||||
rm $errorfile
|
||||
return 0
|
||||
else
|
||||
_warning "sphinx returns error: ::1 error::" $(cat $errorfile)
|
||||
rm $errorfile
|
||||
_failure "Failed to retrieve actual password with sphinx."
|
||||
fi
|
||||
} || {
|
||||
_failure "Both host and user have to be set to use sphinx"
|
||||
}
|
||||
}
|
||||
|
||||
# Create PASSWORD in sphinx
|
||||
# $1 MASTER password for the password store
|
||||
# requires --sphx-host and --sphx-user flags to be set
|
||||
sphinx_set_password() {
|
||||
local errorfile
|
||||
local password
|
||||
{ option_is_set --sphx-user && option_is_set --sphx-host } && {
|
||||
# value error in sphinx doesn't set exit code
|
||||
# using tempfile as a workaround to notice the error
|
||||
errorfile=$(mktemp /tmp/tomb_error.XXXXXXXXX)
|
||||
# check first if this host/user combination exists in store
|
||||
# if yes, there is no need to make a call to create
|
||||
password=$(echo "$1" | sphinx get $(option_value --sphx-user) $(option_value --sphx-host) 2>$errorfile)
|
||||
if ! grep -q "ValueError: fail" $errorfile ; then
|
||||
echo "$password"
|
||||
rm $errorfile
|
||||
return 0
|
||||
fi
|
||||
# no such host/user combination in store, create one
|
||||
password=$(echo "$1" | sphinx create $(option_value --sphx-user) $(option_value --sphx-host) ulsd 0 2>$errorfile)
|
||||
if ! grep -q "ValueError: fail" $errorfile ; then
|
||||
echo "$password"
|
||||
rm $errorfile
|
||||
return 0
|
||||
else
|
||||
_warning "sphinx returns error: ::1 error::" $(cat $errorfile)
|
||||
rm $errorfile
|
||||
_failure "Failed to create password with sphinx"
|
||||
fi
|
||||
} || {
|
||||
_failure "Both host and user have to be set to use sphinx"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Check if a filename is a valid tomb
|
||||
@ -682,6 +747,11 @@ usage() {
|
||||
_print " -r provide GnuPG recipients (separated by comma)"
|
||||
_print " -R provide GnuPG hidden recipients (separated by comma)"
|
||||
|
||||
[[ $SPHINX == 1 ]] && {
|
||||
_print " --sphx-user user associated with the key (for use with pitchforkedsphinx)"
|
||||
_print " --sphx-host host associated with the key (for use with pitchforkedsphinx)"
|
||||
}
|
||||
|
||||
[[ $KDF == 1 ]] && {
|
||||
_print " --kdf forge keys armored against dictionary attacks"
|
||||
}
|
||||
@ -863,6 +933,8 @@ _ensure_dependencies() {
|
||||
command -v cloakify 1>/dev/null 2>/dev/null || CLOAKIFY=0
|
||||
# Check for decloakify
|
||||
command -v decloakify 1>/dev/null 2>/dev/null || DECLOAKIFY=0
|
||||
# Check for pitchforkedsphinx client
|
||||
command -v sphinx 1>/dev/null 2>/dev/null || SPHINX=0
|
||||
# Check for resize
|
||||
command -v resize2fs 1>/dev/null 2>/dev/null || RESIZER=0
|
||||
# Check for KDF auxiliary tools
|
||||
@ -1196,6 +1268,12 @@ ask_key_password() {
|
||||
tombpass="$1"
|
||||
_verbose "ask_key_password with tombpass: ::1 tomb pass::" $tombpass
|
||||
|
||||
# if sphinx mode is chosen, use the provided input
|
||||
# as master password to retrieve the actual password
|
||||
{ option_is_set --sphx-user } || { option_is_set --sphx-host } && {
|
||||
tombpass=$(sphinx_get_password "$tombpass")
|
||||
}
|
||||
|
||||
get_lukskey "$tombpass"
|
||||
|
||||
[[ $? = 0 ]] && {
|
||||
@ -1212,7 +1290,7 @@ ask_key_password() {
|
||||
# call cryptsetup with arguments using the currently known secret
|
||||
# echo flags eliminate newline and disable escape (BSD_ECHO)
|
||||
_cryptsetup() {
|
||||
print -R -n - "$TOMBSECRET" | _sudo cryptsetup --key-file - ${@}
|
||||
print -R -n - "$TOMBSECRET" | _sudo cryptsetup --type luks1 --key-file - ${@}
|
||||
return $?
|
||||
}
|
||||
|
||||
@ -1283,10 +1361,22 @@ gen_key() {
|
||||
local gpgpass opt
|
||||
local recipients_opt
|
||||
typeset -a gpgopt
|
||||
local sphx_host_tmp
|
||||
local sphx_user_tmp
|
||||
# here user is prompted for key password
|
||||
tombpass=""
|
||||
tombpasstmp=""
|
||||
|
||||
# remove sphinx opts not to mess with initial password prompt
|
||||
{ option_is_set --sphx-user } && {
|
||||
sphx_user_tmp="$(option_value --sphx-user)"
|
||||
unset "OPTS[--sphx-user]"
|
||||
}
|
||||
{ option_is_set --sphx-host } && {
|
||||
sphx_host_tmp="$(option_value --sphx-host)"
|
||||
unset "OPTS[--sphx-host]"
|
||||
}
|
||||
|
||||
{ option_is_set -g } && {
|
||||
gpgopt=(--encrypt)
|
||||
|
||||
@ -1347,6 +1437,19 @@ gen_key() {
|
||||
_verbose "gen_key takes tombpass from CLI argument: ::1 tomb pass::" $tombpass
|
||||
fi
|
||||
|
||||
# if sphinx mode is chosen, use the provided input
|
||||
# as master password to generate the actual password
|
||||
if [[ $sphx_host_tmp ]] || [[ $sphx_user_tmp ]]; then
|
||||
OPTS[--sphx-user]=$sphx_user_tmp
|
||||
OPTS[--sphx-host]=$sphx_host_tmp
|
||||
unset sphx_user_tmp
|
||||
unset sphx_host_tmp
|
||||
tombpass=$(sphinx_set_password "$tombpass")
|
||||
if [[ $? != 0 ]]; then
|
||||
_failure "User aborted."
|
||||
fi
|
||||
fi
|
||||
|
||||
header=""
|
||||
[[ $KDF == 1 ]] && {
|
||||
{ option_is_set --kdf } && {
|
||||
@ -2993,19 +3096,19 @@ main() {
|
||||
main_opts=(q -quiet=q D -debug=D h -help=h v -version=v f -force=f -tmp: U: G: T: -no-color -unsafe g -gpgkey=g)
|
||||
subcommands_opts[__default]=""
|
||||
# -o in open and mount is used to pass alternate mount options
|
||||
subcommands_opts[open]="n -nohook=n k: -kdf: o: -ignore-swap -tomb-pwd: r: R: p -preserve-ownership=p"
|
||||
subcommands_opts[open]="n -nohook=n k: -kdf: o: -ignore-swap -tomb-pwd: r: R: -sphx-host: -sphx-user: p -preserve-ownership=p"
|
||||
subcommands_opts[mount]=${subcommands_opts[open]}
|
||||
|
||||
subcommands_opts[create]="" # deprecated, will issue warning
|
||||
|
||||
# -o in forge and lock is used to pass an alternate cipher.
|
||||
subcommands_opts[forge]="-ignore-swap k: -kdf: o: -tomb-pwd: -use-urandom r: R: "
|
||||
subcommands_opts[forge]="-ignore-swap k: -kdf: o: -tomb-pwd: -use-urandom r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[dig]="-ignore-swap s: -size=s "
|
||||
subcommands_opts[lock]="-ignore-swap k: -kdf: o: -tomb-pwd: r: R: "
|
||||
subcommands_opts[setkey]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[lock]="-ignore-swap k: -kdf: o: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[setkey]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[engrave]="k: "
|
||||
|
||||
subcommands_opts[passwd]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[passwd]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[close]=""
|
||||
subcommands_opts[help]=""
|
||||
subcommands_opts[slam]=""
|
||||
@ -3016,8 +3119,8 @@ main() {
|
||||
subcommands_opts[search]=""
|
||||
|
||||
subcommands_opts[help]=""
|
||||
subcommands_opts[bury]="k: -tomb-pwd: r: R: "
|
||||
subcommands_opts[exhume]="k: -tomb-pwd: r: R: "
|
||||
subcommands_opts[bury]="k: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[exhume]="k: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[cloak]="k: "
|
||||
subcommands_opts[uncloak]="k: "
|
||||
# subcommands_opts[decompose]=""
|
||||
@ -3025,7 +3128,7 @@ main() {
|
||||
# subcommands_opts[install]=""
|
||||
subcommands_opts[askpass]=""
|
||||
subcommands_opts[source]=""
|
||||
subcommands_opts[resize]="-ignore-swap s: -size=s k: -tomb-pwd: r: R: "
|
||||
subcommands_opts[resize]="-ignore-swap s: -size=s k: -tomb-pwd: r: R: -sphx-host: -sphx-user: "
|
||||
subcommands_opts[check]="-ignore-swap "
|
||||
# subcommands_opts[translate]=""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user