diff options
Diffstat (limited to 'jsaccess/jstore.sh')
-rwxr-xr-x | jsaccess/jstore.sh | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/jsaccess/jstore.sh b/jsaccess/jstore.sh new file mode 100755 index 0000000..ea19ea0 --- /dev/null +++ b/jsaccess/jstore.sh @@ -0,0 +1,300 @@ +#!/bin/sh + +# jsaccess - private web file sharing using client side crypto +# jstore.sh: file store manager for encrypting new files and deploy to server + +# Copyright (c) 2013 Laurent Ghigonis <laurent@gouloum.fr> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# 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. + +VERSION=0.2 + +usage_exit() { + echo "jsaccess jstore.sh v$VERSION" + echo "usage: jstore.sh [-v] [action] [action arguments...] [store]" + echo + echo "actions on local store for a given passphrase:" + echo " ls [store] # default action if no arguments" + echo " add <file_to_share> [store] # default action if one argument" + echo " rm <file_in_store> [store]" + echo " rmall [store]" + echo + echo "actions on local store for all passphrases:" + echo " init <store>" + echo " wipe <store>" + echo + echo "actions to deploy local store to remote:" + echo " push [store]" + echo " rset <rsync_uri> [store]" + echo " rget [store]" + echo + echo "actions to get informations:" + echo " help|-h" + echo " version|-V" + echo + echo "By default store is ./store/ or ./jsa/store/" + echo "Use \"unset HISTFILE; export JSA_PASS=mypass\" to avoid typing the passphrase" + echo "Use \"unset JSA_PASS\" to forget the passphrase" + clean_exit 1 +} + +clean_exit() { + ret=9 + [ X"$1" != X"" ] && ret=$1 + rm -f $tmp + umask $sumask + exit $ret +} + +confirm_exit() { + if [ X"$JSA_FORCE" = X"" ]; then + echo -n "Are you sure ? [y/N] " + read r + [ X"$r" != X"y" ] && clean_exit 0 + fi +} + +_store_get() { + store="" + [[ -d ./jsa/store/ ]] && store="`readlink -f ./jsa/store/`" # priority 3 + [[ -d ./store/ ]] && store="`readlink -f ./store/`" # priority 2 + [[ X"$1" != X"" ]] && store=$1 # priority 1 + [[ -z $store ]] && echo "ERROR: store not found !" && \ + echo "Not specified as argument and local stores" \ + "./store/ or ./jsa/store/ not found" && clean_exit 1 + [[ ! -d $store ]] && echo "ERROR: specified store does not exist !" && \ + echo "Cannot access $store" && clean_exit 1 + echo "Using store \"$store\"" +} + +_pass_read() { + if [ X"$JSA_PASS" != X"" ]; then + pass=$JSA_PASS + else + echo "Enter encryption passphrase" + echo -n "> " + read pass + fi + [ -z $pass ] && echo "ERROR: empty passphrase" && clean_exit 1 + enc_dir_hash=`echo -n $pass |openssl rmd160 |cut -d' ' -f2` + enc_path="$store/$enc_dir_hash" +} + +_index_decrypt() { + if [ -f $enc_path/index.txt ]; then + echo -n $pass |openssl enc -d -a -aes-256-cbc -in $enc_path/index.txt -out $tmp -pass stdin ||clean_exit 2 + else + echo > $tmp + fi +} + +_index_encrypt() { + rm -f $enc_path/index.txt + echo -n $pass |openssl enc -e -a -aes-256-cbc -in $tmp -out $enc_path/index.txt -pass stdin ||clean_exit 2 + echo "UPDATED file $enc_path/index.txt" +} + +__file_get_encname() { + clear_name=$1 + enc_name=`echo -n ${enc_dir_hash}${clear_name} |openssl rmd160 |cut -d' ' -f2` +} + +_file_add() { + clear_path=$1 + clear_name=$2 + __file_get_encname $clear_name + if [ ! -d $enc_path ]; then + mkdir -p $enc_path + touch $enc_path/index.html + echo "CREATED directory $enc_path (new passphrase)" + fi + base64 -w0 $clear_path > $tmp ||clean_exit 2 + echo -n $pass |openssl enc -e -a -aes-256-cbc -in $tmp -out $enc_path/$enc_name -pass stdin ||clean_exit 2 + echo "CREATED file $enc_path/$enc_name" +} + +_file_rm() { + clear_name=$1 + __file_get_encname $clear_name + rm $enc_path/$enc_name ||clean_exit 1 + echo "DELETED file $enc_path/$enc_name" +} + +_rset() { + rsync_uri=$1 + if [ -f $store/.rsync_uri ]; then + echo "This will overwrite existing rsync_uri:" + cat $store/.rsync_uri + confirm_exit + fi + echo $rsync_uri > $store/.rsync_uri +} + +_rget() { + [ ! -f $store/.rsync_uri ] && echo "ERROR: no rsync_uri set !" && \ + echo "set it with \"jstore.sh rset <rsync_uri> $store\"" && \ + clean_exit 1 + rsync_uri=`cat $store/.rsync_uri` +} + +action_ls() { + _pass_read + _index_decrypt + [ ! -f $enc_path/index.txt ] && \ + echo "Passphrase not used in store !" && clean_exit 1 + echo "$enc_dir_hash/index.txt:" + cat $tmp +} + +action_add() { + clear_path=$1 + clear_name=`basename $clear_path` + _pass_read + _index_decrypt + if [ `egrep -c "^$clear_name$" $tmp` -ne 0 ]; then + echo "File already encrypted with this passphrase" + clean_exit 1 + fi + _file_add $clear_path $clear_name + _index_decrypt + echo $clear_name >> $tmp + _index_encrypt +} + +action_rm() { + clear_name=$1 + _pass_read + _index_decrypt + if [ `egrep -c "^$clear_name$" $tmp` -eq 0 ]; then + echo "File does not exist for this passphrase" + clean_exit 1 + fi + _file_rm $clear_name + _index_decrypt + sed -i /^$clear_name$/d $tmp + _index_encrypt +} + +action_rmall() { + _pass_read + echo "This will delete all file encrypted with this passphrase" + confirm_exit + rm -rf $enc_path + echo "DELETED directory $enc_path" +} + +action_init() { + store=$1 + mkdir $store ||clean_exit 1 + echo "The monster has emptied me !" > $store/index.html + echo "CREATED store \"$store\"" +} + +action_wipe() { + echo "This will delete all file encrypted with all passphrases" + confirm_exit + rm -rf $store + echo "DELETED store \"$store\"" +} + +action_rset() { + _rset $1 +} + +action_rget() { + _rget + echo "rsync_uri: $rsync_uri" +} + +action_push() { + _rget + cmd="rsync -avzP $store/* $rsync_uri" + echo "Running \"$cmd\"" + $cmd +} + +# Check for dependencies +if [ X"`which base64`" == X"" \ + -o X"`which openssl`" == X"" ]; then + echo "You need to have openssl and base64 available in your path !" + clean_exit 1 +fi + +# Initialize temporary stuff +sumask=$(umask) +umask 077 +tmp=`mktemp ./jsaXXXXXXXX` # Used for storing index / new files +trap clean_exit INT TERM + +# Run action +case $1 in +ls) + [ $# -ne 1 -a $# -ne 2 ] && usage_exit + _store_get $2 + action_ls + ;; +add) + [ $# -ne 2 -a $# -ne 3 ] && usage_exit + _store_get $3 + action_add $2 + ;; +rm) + [ $# -ne 2 -a $# -ne 3 ] && usage_exit + _store_get $3 + action_rm $2 + ;; +rmall) + [ $# -ne 1 -a $# -ne 2 ] && usage_exit + _store_get $2 + action_rmall + ;; +init) + [ $# -ne 2 ] && usage_exit + action_init $2 + ;; +wipe) + [ $# -ne 2 ] && usage_exit + _store_get $2 + action_wipe + ;; +push) + [ $# -ne 1 -a $# -ne 2 ] && usage_exit + _store_get $2 + action_push + ;; +rset) + [ $# -ne 2 -a $# -ne 3 ] && usage_exit + _store_get $3 + action_rset $2 + ;; +rget) + [ $# -ne 1 -a $# -ne 2 ] && usage_exit + _store_get $2 + action_rget + ;; +help|-h|version|-V) + usage_exit + ;; +"") + [ $# -ne 0 ] && usage_exit + _store_get + action_ls + ;; +*) + [ $# -ne 1 ] && usage_exit + _store_get $2 + action_add $1 +esac + +clean_exit 0 + |