#! /bin/sh set -e usage() { echo "$0 " } to_hex() { od -An -t x1 | tr -d ' ' | tr -d '\n' } to_bin() { sed -e 's,\([0-9a-f]\{2\}\),\\\\\\x\1,g' | xargs printf } mktemp_posix() { m4 <&2 exit 1 fi DIR=$1 echo Username: >&2 IFS= read -r USER if printf '%s' "$USER" | grep -qe '[[:space:]]' then echo Username cannot contain whitespaces >&2 exit 1 fi DB="$DIR/db.json" if jq '.users[].name' "$DB" | grep -q $USER then echo User $USER already in $DB >&2 exit 1 fi TTYCFG=$(stty -g) trap "stty $TTYCFG" INT QUIT TERM EXIT stty -echo echo Password: >&2 IFS= read -r PWD stty echo # Force newline echo echo "Quota, in MiB (leave empty for unlimited quota):" >&2 read -r QUOTA QUOTA="$(printf '%d' "$QUOTA")" PWD=$(printf '%s' "$PWD" | to_hex) SALT=$(openssl rand -hex 32) KEY=$(openssl rand -hex 32) PWD=$(printf '%s%s' "$SALT" "$PWD") ROUNDS=1000 for i in $(seq $ROUNDS) do printf "\r%d/$ROUNDS" $i >&2 PWD=$(printf '%s' "$PWD" | to_bin | openssl sha256 -r | cut -d' ' -f1) done echo >&2 TMP=$(mktemp_posix) cleanup() { rm -f $TMP } trap cleanup EXIT jq ".users += [ { \"name\": \"$USER\", \"password\": \""$PWD"\", \"salt\": \"$SALT\", \"key\": \"$KEY\", \"quota\": \"$QUOTA\" }]" "$DB" > $TMP mkdir "$DIR/user/$USER" mv $TMP "$DB"