231 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/bin/bash
 | 
						|
 | 
						|
_SQLITE=$( which sqlite3 2>&1 )
 | 
						|
if [ $? -ne 0 ]; then
 | 
						|
    echo "sqlite3 is missing" >&2
 | 
						|
    return 1
 | 
						|
fi
 | 
						|
 | 
						|
echo "test" | openssl enc -e -aes-256-cbc -pbkdf2 -k test 2>/dev/null > /dev/null
 | 
						|
if [ $? -ne 0 ]; then
 | 
						|
    echo "openssl does not exists nor support pbkdf2" >&2
 | 
						|
    return 1
 | 
						|
fi
 | 
						|
 | 
						|
if [ -z `which xxd` ]; then
 | 
						|
	echo "xxd is required" >&2
 | 
						|
	return 1
 | 
						|
fi
 | 
						|
 | 
						|
_AUTH_DB=$RBASH_HOME/keystore.db
 | 
						|
_AUTH_SECRET=
 | 
						|
_KSTORE_DEF_PROP=${_KSTORE_DEF_PROP:-val}
 | 
						|
 | 
						|
if [ -f "$RBASH_HOME/keystore.secret" ]; then
 | 
						|
	_AUTH_SECRET=$( cat "$RBASH_HOME/keystore.secret" )
 | 
						|
fi
 | 
						|
 | 
						|
function kstore {
 | 
						|
	case $1 in
 | 
						|
		add) shift; kstore-add "$@" ;;
 | 
						|
		del) shift; kstore-del "$@" ;;
 | 
						|
		get) shift; kstore-get "$@" ;;
 | 
						|
		list) shift; kstore-list "$@" ;;
 | 
						|
		query) shift; kstore-query "$@" ;;
 | 
						|
		update) shift; kstore-update "$@" ;;
 | 
						|
		search) shift; kstore-search $@ ;;
 | 
						|
		secret) shift; kstore-secret $@ ;;
 | 
						|
		*)
 | 
						|
			__func_head "add key value [prop, default: $_KSTORE_DEF_PROP]"
 | 
						|
			__func_help "update key value [prop, default: $_KSTORE_DEF_PROP]"
 | 
						|
			__func_help "get key [prop, default: $_KSTORE_DEF_PROP]"
 | 
						|
			__func_help "list"
 | 
						|
			__func_help "del key"
 | 
						|
			__func_help "search key"
 | 
						|
			__func_help "query SQL"
 | 
						|
			return 1
 | 
						|
			;;
 | 
						|
	esac
 | 
						|
	return $?
 | 
						|
}
 | 
						|
 | 
						|
function kstore-secret {
 | 
						|
	case "$1" in
 | 
						|
		clear) shift; kstore-secret-clear "$@" ;;
 | 
						|
		config) shift; kstore-secret-config "$@" ;;
 | 
						|
		*)
 | 
						|
			__func_head "clear"
 | 
						|
			__func_help "config"
 | 
						|
			;;
 | 
						|
	esac
 | 
						|
}
 | 
						|
 | 
						|
function kstore-init {
 | 
						|
	cat <<___SQL___ | $_SQLITE "$_AUTH_DB"
 | 
						|
CREATE TABLE IF NOT EXISTS store ( 
 | 
						|
	key TEXT UNIQUE NOT NULL
 | 
						|
	, prop TEXT NOT NULL
 | 
						|
	, data BLOB
 | 
						|
	, PRIMARY KEY( key ASC, prop ASC )
 | 
						|
);
 | 
						|
___SQL___
 | 
						|
	kstore secret config
 | 
						|
}
 | 
						|
 | 
						|
function kstore-quote {
 | 
						|
	echo -n "$1" | sed -e "s/'/''/g"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-enc {
 | 
						|
	if [ -z "$_AUTH_SECRET" ]; then
 | 
						|
		echo "Secret key is not set yet" >&2
 | 
						|
		return 1
 | 
						|
	fi
 | 
						|
 | 
						|
	openssl enc -e -aes-256-cbc -pbkdf2 -k "$_AUTH_SECRET" | xxd -p | tr -d "\n"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-dec {
 | 
						|
	if [ -z "$_AUTH_SECRET" ]; then
 | 
						|
		echo "Secret key is not set yet" >&2
 | 
						|
		return 1
 | 
						|
	fi
 | 
						|
 | 
						|
	openssl enc -d -aes-256-cbc -pbkdf2 -k "$_AUTH_SECRET"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-secret-macos {
 | 
						|
	local _A
 | 
						|
	case $1 in
 | 
						|
		get)
 | 
						|
			_A=`security find-generic-password -a default -gs rbash-kstore 2>&1 | grep ^password | cut -c 11-`
 | 
						|
			if [ $? -ne 0 ]; then
 | 
						|
				return 1
 | 
						|
			fi
 | 
						|
			_AUTH_SECRET="${_A:1:-1}"
 | 
						|
			;;
 | 
						|
		set)
 | 
						|
			security add-generic-password -a default -s rbash-kstore -w "$_AUTH_SECRET"
 | 
						|
			;;
 | 
						|
		*)
 | 
						|
			echo "Unknown action: $1" >&2
 | 
						|
			return 1
 | 
						|
			;;
 | 
						|
	esac
 | 
						|
}
 | 
						|
 | 
						|
function kstore-secret-windows {
 | 
						|
	# Not impelemented yet
 | 
						|
	if [ "$1" == "get" ]; then
 | 
						|
		return 1
 | 
						|
	fi
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
function kstore-secret-config {
 | 
						|
	local _CONFIRM
 | 
						|
	if [ -z "$_AUTH_SECRET" ]; then
 | 
						|
 | 
						|
		kstore-secret-windows get || kstore-secret-macos get
 | 
						|
		if [ -n "$_AUTH_SECRET" ]; then
 | 
						|
			return 0
 | 
						|
		fi
 | 
						|
 | 
						|
		read -sp "Enter passphrase: " _AUTH_SECRET
 | 
						|
		echo
 | 
						|
		if [ -z "$_AUTH_SECRET" ]; then
 | 
						|
			echo "Passphrase cannot be empty" >&2
 | 
						|
			return 1
 | 
						|
		fi
 | 
						|
 | 
						|
		read -p "Save this password to OS's keystore? (y/n): " _CONFIRM
 | 
						|
		if [ "$_CONFIRM" != "y" ]; then
 | 
						|
			return 0
 | 
						|
		fi
 | 
						|
 | 
						|
		case $OSTYPE in
 | 
						|
			darwin*) kstore-secret-macos "set" ;;
 | 
						|
		esac
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
function kstore-secret-clear {
 | 
						|
	_AUTH_SECRET=
 | 
						|
	case $OSTYPE in
 | 
						|
		darwin*)
 | 
						|
			security delete-generic-password -a default -s rbash-kstore 2>&1 > /dev/null
 | 
						|
		;;
 | 
						|
	esac
 | 
						|
}
 | 
						|
 | 
						|
function kstore-update {
 | 
						|
	kstore-init || return 1
 | 
						|
	local _key _val _prop
 | 
						|
	_key=`kstore-quote "$1"`
 | 
						|
	_val=`echo -n "$2" | kstore-enc`
 | 
						|
	_val=`kstore-quote "$_val"`
 | 
						|
	_prop=`kstore-quote "${3:-$_KSTORE_DEF_PROP}"`
 | 
						|
	_cond="key = '$_key' AND prop = '$_prop'"
 | 
						|
	$_SQLITE "$_AUTH_DB" "UPDATE store SET data = '$_val' WHERE $_cond;"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-add {
 | 
						|
	kstore-init || return 1
 | 
						|
	local _key _val _prop
 | 
						|
	_key=`kstore-quote "$1"`
 | 
						|
	_val=`echo -n "$2" | kstore-enc`
 | 
						|
	_val=`kstore-quote "$_val"`
 | 
						|
	_prop=`kstore-quote "${3:-$_KSTORE_DEF_PROP}"`
 | 
						|
    sqlite3 "$_AUTH_DB" \
 | 
						|
		"INSERT INTO store ( key, prop, data )
 | 
						|
			VALUES( '$_key', '$_prop', X'$_val' );"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-get {
 | 
						|
	kstore-init || return 1
 | 
						|
	local _key _prop _cond
 | 
						|
	_key=`kstore-quote "$1"`
 | 
						|
	_prop=`kstore-quote "${2:-$_KSTORE_DEF_PROP}"`
 | 
						|
	_cond="key = '$_key' AND prop = '$_prop'"
 | 
						|
 | 
						|
	echo -n "`$_SQLITE -list "$_AUTH_DB" "SELECT ( data ) FROM store WHERE $_cond;"`" | kstore-dec
 | 
						|
}
 | 
						|
 | 
						|
function kstore-del {
 | 
						|
	kstore-init || return 1
 | 
						|
 | 
						|
	local _CONFIRM _key _prop _cond
 | 
						|
	_key=`kstore-quote "$1"`
 | 
						|
	_prop=`kstore-quote "${2:-$_KSTORE_DEF_PROP}"`
 | 
						|
	_cond="key = '$_key' AND prop = '$_prop'"
 | 
						|
 | 
						|
    sqlite3 "$_AUTH_DB" "SELECT 1111 FROM store WHERE $_cond;" | grep -q 1111
 | 
						|
	if [ $? -eq 0 ]; then
 | 
						|
		sqlite3 "$_AUTH_DB" "SELECT * FROM store WHERE $_cond;"
 | 
						|
		echo
 | 
						|
		read -p "Delete this entry (yes/no)? " _CONFIRM
 | 
						|
		if [ "$_CONFIRM" == "yes" ]; then
 | 
						|
			sqlite3 "$_AUTH_DB" "DELETE FROM store WHERE $_cond;"
 | 
						|
			if [ $? -eq 0 ]; then
 | 
						|
				echo "deleted"
 | 
						|
			fi
 | 
						|
		else
 | 
						|
			echo "action canceled"
 | 
						|
		fi
 | 
						|
	else
 | 
						|
		echo "$1 not found"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
function kstore-search {
 | 
						|
	echo "Not implemented yet"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-list {
 | 
						|
	$_SQLITE -header -column "$_AUTH_DB" "SELECT key, prop, length( data ) FROM store;"
 | 
						|
}
 | 
						|
 | 
						|
function kstore-query {
 | 
						|
	sqlite3 "$_AUTH_DB" "$@"
 | 
						|
}
 |