aboutsummaryrefslogtreecommitdiffstats
path: root/jsaccess/jstore.sh
diff options
context:
space:
mode:
Diffstat (limited to 'jsaccess/jstore.sh')
-rwxr-xr-xjsaccess/jstore.sh300
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
+