| |
| # Copyright 2015-2024 Rivoreo |
| |
| # Permission is hereby granted, free of charge, to any person obtaining a copy |
| # of this software and associated documentation files (the "Software"), to |
| # deal in the Software without restriction, including without limitation the |
| # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| # sell copies of the Software, and to permit persons to whom the Software is |
| # furnished to do so, subject to the following conditions: |
| |
| # The above copyright notice and this permission notice shall be included in |
| # all copies or substantial portions of the Software. |
| |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR |
| # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| # SOFTWARE. |
| |
| |
| _load_encryped_history_internal() { |
| [ -n "$HISTORY_KEY" ] || return |
| local tmp_history_file r=1 |
| tmp_history_file="`mktemp \"$HOME/.bash_history.$$.XXXXXX\"`" || return |
| if _decrypt_history "$HISTORY_KEY" < "$ENCRYPTED_HISTORY_FILE" > "$tmp_history_file"; then |
| history -r "$tmp_history_file" && r=0 |
| fi |
| rm -f "$tmp_history_file" |
| return $r |
| } |
| |
| load_encryped_history() { |
| [ "${-#*i}" = "$-" ] && return 1 |
| [ -f "$ENCRYPTED_HISTORY_FILE" ] || return |
| begin_print_status "Loading history" |
| if _load_encryped_history_internal; then |
| end_print_status_ok |
| else |
| end_print_status_fail |
| fi |
| } |
| |
| _append_encrypted_history_internal() { |
| [ -n "$HISTORY_KEY" ] || return |
| local value nonce pad |
| if get_encrypted_byte_count "$ENCRYPTED_HISTORY_FILE"; then |
| nonce=$((value/8)) |
| pad=$((value%8)) |
| else |
| nonce=0 |
| pad=0 |
| chmod 600 "$ENCRYPTED_HISTORY_FILE" >> "$ENCRYPTED_HISTORY_FILE" || return |
| fi |
| if [ "$1" = -e ]; then |
| history -a /dev/stdout | _encrypt_history "$HISTORY_KEY" $nonce $pad >> "$ENCRYPTED_HISTORY_FILE" |
| return |
| fi |
| local history_pipe="$HOME/.bash_history.$$" pid r=0 |
| rm -f "$history_pipe" |
| mkfifo -m 600 "$history_pipe" || return |
| _encrypt_history "$HISTORY_KEY" $nonce $pad < "$history_pipe" >> "$ENCRYPTED_HISTORY_FILE" & pid=$! |
| history -a "$history_pipe" || r=1 |
| wait $pid || r=1 |
| rm -f "$history_pipe" |
| return $r |
| } |
| |
| append_encrypted_history() { |
| [ "${-#*i}" = "$-" ] && return 1 |
| begin_print_status "Storing history" |
| if _append_encrypted_history_internal "$@"; then |
| end_print_status_ok |
| else |
| end_print_status_fail |
| fi |
| } |
| |
| ask_history_passphrase() { |
| local passphrase |
| read -rs -p "History key or passphrase? " passphrase && [ -n "$passphrase" ] || return |
| echo 1>&2 |
| if printf %s\\n "$passphrase" | grep -Eq '^[0-9a-f]{32}$'; then |
| HISTORY_KEY="$passphrase" |
| elif HISTORY_KEY="`printf %s \"$passphrase\" | md5sum 2> /dev/null`"; then |
| HISTORY_KEY="${HISTORY_KEY%% *}" |
| elif HISTORY_KEY="`md5 -q -s \"$passphrase\" 2> /dev/null`"; then |
| true |
| elif HISTORY_KEY="`printf %s \"$passphrase\" | toolbox md5 -q -- - 2> /dev/null`"; then |
| true |
| else |
| echo "Couldn't find a working md5sum(1) or md5(1) tool" 1>&2 |
| false |
| fi |
| } |
| |
| if [ "${-#*i}" != "$-" ]; then |
| for f in "$HOME"/.bash_history.*.??????; do |
| if [ -h "$f" ]; then |
| rm -f "$f" |
| continue |
| fi |
| [ -e "$f" ] || continue |
| if [ ! -f "$f" ]; then |
| printf "Warning: Found non-regular file '%s'\\n" "${f##*/}" 1>&2 |
| continue |
| fi |
| pid="${f##*/.bash_history.}" |
| pid="${pid%.??????}" |
| if printf %s\\n "$pid" | grep -Eq '^[0-9]+$'; then |
| [ -d "/proc/$pid" ] || ps -p "$pid" > /dev/null && continue |
| fi |
| rm -f "$f" > "$f" |
| done |
| unset HISTFILE |
| if [ -n "${HISTORY_KEY+set}" ]; then |
| if printf %s\\n "$HISTORY_KEY" | grep -Eq '^[0-9a-fA-F]{32}$'; then |
| # Unexport this variable for security |
| declare +x HISTORY_KEY |
| else |
| echo "Warning: Predefined HISTORY_KEY is invalid" 1>&2 |
| unset HISTORY_KEY |
| fi |
| fi |
| if [ -n "$HISTORY_KEY" ] || ask_history_passphrase; then |
| [ -z "$ENCRYPTED_HISTORY_FILE" ] && ENCRYPTED_HISTORY_FILE="$HOME/.bash_history.e" |
| load_encryped_history |
| trap "append_encrypted_history -e" EXIT |
| else |
| echo "Warning: Persistent history disabled" 1>&2 |
| HISTORY_KEY= |
| fi |
| fi |