From d1f151c70f037c3096182d344a4ada6af260d882 Mon Sep 17 00:00:00 2001 From: David Ross Smith Date: Fri, 20 Jun 2025 17:07:09 +1000 Subject: [PATCH 1/3] Added spaces to make clearer what is a command substitution --- bt-keys-sync.sh | 140 ++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/bt-keys-sync.sh b/bt-keys-sync.sh index 061edb2..a0cc23c 100644 --- a/bt-keys-sync.sh +++ b/bt-keys-sync.sh @@ -10,17 +10,17 @@ function check_bt_controllers() { check_sudo - bt_controllers_linux="$(sudo ls "/var/lib/bluetooth/" | grep -Eo "^([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}$")" - bt_controllers_windows="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys" | awk -F'\' '{print $8}' | grep -Eo "([[:xdigit:]]){12}")" + bt_controllers_linux="$( sudo ls "/var/lib/bluetooth/" | grep -Eo "^([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}$" )" + bt_controllers_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys" | awk -F'\' '{print $8}' | grep -Eo "([[:xdigit:]]){12}" )" bt_controllers_reg="${bt_controllers_linux//:/$''}\n${bt_controllers_windows}" - bt_controllers="$(echo -e "${bt_controllers_reg,,}" | sort -u)" + bt_controllers="$( echo -e "${bt_controllers_reg,,}" | sort -u )" for bt_controller in ${bt_controllers}; do - bt_controller_macaddr="$(echo "${bt_controller^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//')" - bt_controller_linux="$(echo "${bt_controllers_linux}" | grep "${bt_controller_macaddr}")" - bt_controller_windows="$(echo "${bt_controllers_windows}" | grep "${bt_controller}")" + bt_controller_macaddr="$( echo "${bt_controller^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//' )" + bt_controller_linux="$( echo "${bt_controllers_linux}" | grep "${bt_controller_macaddr}" )" + bt_controller_windows="$( echo "${bt_controllers_windows}" | grep "${bt_controller}" )" echo echo "- bluetooth controller: ${bt_controller_macaddr}" if [[ -z "${bt_controller_linux}" ]]; then @@ -38,31 +38,31 @@ function check_bt_devices() { unset bt_devices_linux if [[ -n "${bt_controller_linux}" ]]; then check_sudo - bt_devices_linux="$(sudo ls "/var/lib/bluetooth/${bt_controller_linux}" | grep -Eo "^([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}$")" + bt_devices_linux="$( sudo ls "/var/lib/bluetooth/${bt_controller_linux}" | grep -Eo "^([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}$" )" fi unset bt_devices_windows if [[ -n "${bt_controller_windows}" ]]; then - bt_devices_windows="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" 2>/dev/null | awk -F'"' '{print $2}' | grep -Eo "^([[:xdigit:]]){12}$")\n" - bt_devices_windows+="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys\\${bt_controller_windows}" | awk -F'\' '{print $9}' | grep -Eo "([[:xdigit:]]){12}")" - bt_devices_windows="$(echo -e "${bt_devices_windows}")" + bt_devices_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" 2>/dev/null | awk -F'"' '{print $2}' | grep -Eo "^([[:xdigit:]]){12}$" )\n" + bt_devices_windows+="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys\\${bt_controller_windows}" | awk -F'\' '{print $9}' | grep -Eo "([[:xdigit:]]){12}" )" + bt_devices_windows="$( echo -e "${bt_devices_windows}" )" fi bt_devices_reg="${bt_devices_linux//:/$''}\n${bt_devices_windows}" - bt_devices="$(echo -e "${bt_devices_reg,,}" | sort -u)" + bt_devices="$( echo -e "${bt_devices_reg,,}" | sort -u )" for bt_device in ${bt_devices}; do - bt_device_macaddr="$(echo "${bt_device^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//')" - bt_device_linux="$(echo "${bt_devices_linux}" | grep "${bt_device_macaddr}")" - bt_device_windows="$(echo "${bt_devices_windows}" | grep "${bt_device}")" + bt_device_macaddr="$( echo "${bt_device^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//' )" + bt_device_linux="$( echo "${bt_devices_linux}" | grep "${bt_device_macaddr}" )" + bt_device_windows="$( echo "${bt_devices_windows}" | grep "${bt_device}" )" if [[ -n "${bt_device_linux}" ]]; then check_sudo - bt_device_info="$(sudo cat "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" 2>/dev/null)" - bt_device_name="$(echo "${bt_device_info}" | grep '^Alias=' | awk -F'=' '{print $2}')" + bt_device_info="$( sudo cat "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" 2>/dev/null )" + bt_device_name="$( echo "${bt_device_info}" | grep '^Alias=' | awk -F'=' '{print $2}' )" if [[ -z "${bt_device_name}" ]]; then - bt_device_name="$(echo "${bt_device_info}" | grep '^Name=' | awk -F'=' '{print $2}')" + bt_device_name="$( echo "${bt_device_info}" | grep '^Name=' | awk -F'=' '{print $2}' )" fi if [[ -z "${bt_device_name}" ]]; then bt_device_name='UNKWNOWN' @@ -72,18 +72,18 @@ function check_bt_devices() { tmp_devs_deployed='true' check_sudo sudo reged -x "${tmp_dir}/${tmp_hive}" "HKEY_LOCAL_MACHINE\SYSTEM" "\\${control_set}\Services\BTHPORT\Parameters\Devices" "${tmp_dir}/${tmp_devs}" 2>&1>/dev/null - bt_devices_info_devs_reg="$(cat -v "${tmp_dir}/${tmp_devs}" | sed 's/\^M//g')" + bt_devices_info_devs_reg="$( cat -v "${tmp_dir}/${tmp_devs}" | sed 's/\^M//g' )" fi - bt_device_info_devs_reg="$(echo "${bt_devices_info_devs_reg}" | awk "/"${bt_device_windows}]"/,/^$/")" - bt_device_name="$(echo "${bt_device_info_devs_reg}" | grep -F '"FriendlyName"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$")" + bt_device_info_devs_reg="$( echo "${bt_devices_info_devs_reg}" | awk "/"${bt_device_windows}]"/,/^$/" )" + bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"FriendlyName"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" if [[ -z "${bt_device_name}" ]]; then - bt_device_name="$(echo "${bt_device_info_devs_reg}" | grep -F '"Name"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$")" + bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"Name"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" fi if [[ -n "${bt_device_name}" ]]; then until [[ "${bt_device_name:(-3)}" != ',00' ]]; do bt_device_name="${bt_device_name::-3}" done - bt_device_name="$(echo -e "\x${bt_device_name//,/$'\x'}")" + bt_device_name="$( echo -e "\x${bt_device_name//,/$'\x'}" )" else bt_device_name='UNKWNOWN' fi @@ -134,9 +134,9 @@ function check_bt_devices() { else check_bt_device_type_windows if [[ "${bt_device_type_windows}" = 'standard' ]]; then - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" | grep "${bt_device_windows}" | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" | grep "${bt_device_windows}" | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" elif [[ "${bt_device_type_windows}" = 'ble' ]]; then - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" fi if [[ "${bt_device_type_windows}" = 'standard' ]]; then # delete after BLE support will be implemented get_bt_keys_windows @@ -187,7 +187,7 @@ function check_bt_device_type_linux() { function check_bt_device_type_windows() { unset bt_device_type_windows - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" if [[ "$(echo "${bt_device_info_keys_reg}" | grep -E "^(\"IRK\"|\"CSRK\"|\"LTK\"|\"KeyLength\"|\"EDIV\"|\"ERand\")" | wc -l)" -ge '5' ]]; then bt_device_type_windows='ble' else @@ -198,7 +198,7 @@ function check_bt_device_type_windows() { function get_bt_keys_linux() { if [[ "${bt_device_type_linux}" = 'standard' ]]; then - key_lk_linux="$(echo "${bt_device_info}" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$")" + key_lk_linux="$( echo "${bt_device_info}" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" if [[ -z "${key_lk_linux}" ]]; then nokey='1' echo -e "\e[1;31m * linux LK key not found. Please try to remove and pair again this device in linux.\e[0m" @@ -206,12 +206,12 @@ function get_bt_keys_linux() { echo " - linux LK key is ${key_lk_linux}" fi elif [[ "${bt_device_type_linux}" = 'ble' ]]; then - key_irk_linux="$(echo "${bt_device_info}" | awk "/"\\[IdentityResolvingKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$")" # to review - key_lsk_linux="$(echo "${bt_device_info}" | awk "/"\\[LocalSignatureKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$")" # to review - key_ltk_linux="$(echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$")" # to review - key_es_linux="$(echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EncSize=' | grep -Eo "([[:digit:]])+$")" # to review - key_ediv_linux="$(echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EDiv=' | grep -Eo "([[:digit:]])+$")" # to review - key_rand_linux="$(echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Rand=' | grep -Eo "([[:digit:]])+$")" # to review + key_irk_linux="$( echo "${bt_device_info}" | awk "/"\\[IdentityResolvingKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review + key_lsk_linux="$( echo "${bt_device_info}" | awk "/"\\[LocalSignatureKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review + key_ltk_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review + key_es_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EncSize=' | grep -Eo "([[:digit:]])+$" )" # to review + key_ediv_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EDiv=' | grep -Eo "([[:digit:]])+$" )" # to review + key_rand_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Rand=' | grep -Eo "([[:digit:]])+$" )" # to review if [[ -z "${key_irk_linux}" ]]; then nokey='1' echo -e "\e[1;31m * linux IRK key not found. Please try to remove and pair again this device in linux.\e[0m" @@ -255,7 +255,7 @@ function get_bt_keys_windows() { if [[ "${bt_device_type_windows}" = 'standard' ]]; then key_lk_windows_reg="${bt_device_info_keys_reg}" - key_lk_windows="$(echo ${key_lk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]')" + key_lk_windows="$( echo ${key_lk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]' )" if [[ -z "${key_lk_windows}" ]]; then nokey='1' echo -e "\e[1;31m * windows LK key not found. Please try to remove and pair again this device in windows.\e[0m" @@ -263,24 +263,24 @@ function get_bt_keys_windows() { echo " - windows LK key is ${key_lk_windows}" fi elif [[ "${bt_device_type_windows}" = 'ble' ]]; then - key_irk_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"IRK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$")" # to review - key_irk_windows="$(echo ${key_irk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]')" # to review + key_irk_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"IRK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" # to review + key_irk_windows="$( echo ${key_irk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]' )" # to review - key_lsk_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"CSRK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$")" # to review - key_lsk_windows="$(echo ${key_lsk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]')" # to review + key_lsk_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"CSRK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" # to review + key_lsk_windows="$( echo ${key_lsk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]' )" # to review - key_ltk_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"LTK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$")" # to review - key_ltk_windows="$(echo ${key_ltk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]')" # to review + key_ltk_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"LTK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" # to review + key_ltk_windows="$( echo ${key_ltk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]' )" # to review - key_es_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"KeyLength"' | awk -F':' '{print $2}')" # to review - key_es_windows="$(echo "obase=10; ibase=16; ${key_es_windows_reg}" | bc)" # to review + key_es_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"KeyLength"' | awk -F':' '{print $2}' )" # to review + key_es_windows="$( echo "obase=10; ibase=16; ${key_es_windows_reg}" | bc )" # to review - key_ediv_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"EDIV"' | awk -F':' '{print $2}')" # to review - key_ediv_windows="$(echo "obase=10; ibase=16; ${key_ediv_windows_reg}" | bc)" # to review + key_ediv_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"EDIV"' | awk -F':' '{print $2}' )" # to review + key_ediv_windows="$( echo "obase=10; ibase=16; ${key_ediv_windows_reg}" | bc )" # to review - key_rand_windows_reg="$(echo "${bt_device_info_keys_reg}" | grep '^"ERand"' | awk -F':' '{print $2}')" # to review - key_rand_windows="$(echo "${key_rand_windows_reg}" | awk -F',' '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }' | tr '[:lower:]' '[:upper:]')" # to review - key_rand_windows="$(echo "obase=10; ibase=16; ${key_rand_windows//' '/$''}" | bc)" # to review + key_rand_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"ERand"' | awk -F':' '{print $2}' )" # to review + key_rand_windows="$( echo "${key_rand_windows_reg}" | awk -F',' '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }' | tr '[:lower:]' '[:upper:]' )" # to review + key_rand_windows="$( echo "obase=10; ibase=16; ${key_rand_windows//' '/$''}" | bc )" # to review if [[ -z "${key_irk_windows}" ]]; then nokey='1' @@ -390,7 +390,7 @@ function bt_keys_sync_common() { fi break fi - retry="$(("${retry}" + 1))" + retry="$( ("${retry}" + 1) )" done } @@ -464,7 +464,7 @@ function bt_keys_sync_from_windows() { fi fi check_sudo - bt_device_info="$(sudo cat "${tmp_dir}/${tmp_info_new}" 2>/dev/null)" + bt_device_info="$( sudo cat "${tmp_dir}/${tmp_info_new}" 2>/dev/null )" get_bt_keys_linux } @@ -472,30 +472,30 @@ function bt_keys_sync_from_linux() { echo -e "\e[1;33m * updating windows registry key...\e[0m" bt_keys_sync_from_os='linux' - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" cp "${tmp_dir}/${tmp_reg}" "${tmp_dir}/${tmp_reg_new}" if [[ "${bt_device_type}" = 'standard' ]]; then - key_lk_linux_reg="$(echo "${key_lk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//')" + key_lk_linux_reg="$( echo "${key_lk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//' )" check_sudo sudo sed -i "s/\"${bt_device_windows}\"=hex:${key_lk_windows_reg}/\"${bt_device_windows}\"=hex:${key_lk_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" elif [[ "${bt_device_type}" = 'ble' ]]; then if [[ "${key_irk_linux}" != "${key_irk_windows}" ]]; then - key_irk_linux_reg="$(echo "${key_irk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//')" # to review + key_irk_linux_reg="$( echo "${key_irk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//' )" # to review check_sudo sudo sed -i "s/\"IRK\"=hex:${key_irk_windows_reg}/\"IRK\"=hex:${key_irk_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi if [[ "${key_lsk_linux}" != "${key_lsk_windows}" ]]; then - key_lsk_linux_reg="$(echo "${key_lsk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//')" # to review + key_lsk_linux_reg="$( echo "${key_lsk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//' )" # to review check_sudo sudo sed -i "s/\"CSRK\"=hex:${key_lsk_windows_reg}/\"CSRK\"=hex:${key_lsk_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi if [[ "${key_ltk_linux}" != "${key_ltk_windows}" ]]; then - key_ltk_linux_reg="$(echo "${key_ltk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//')" # to review + key_ltk_linux_reg="$( echo "${key_ltk_linux,,}" | sed 's/.\{2\}/&,/g' | sed 's/.$//' )" # to review check_sudo sudo sed -i "s/\"LTK\"=hex:${key_ltk_windows_reg}/\"LTK\"=hex:${key_ltk_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi if [[ "${key_es_linux}" != "${key_es_windows}" ]]; then - key_es_linux_reg="$(printf '%x\n' "${key_es_linux}")" # to review + key_es_linux_reg="$( printf '%x\n' "${key_es_linux}" )" # to review until [[ "$(echo "${key_es_linux_reg}" | wc -m)" = '8' ]]; do key_es_linux_reg="0${key_es_linux_reg}" done @@ -503,7 +503,7 @@ function bt_keys_sync_from_linux() { sudo sed -i "s/\"KeyLength\"=dword:${key_es_linux_reg}/\"KeyLength\"=dword:${key_es_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi if [[ "${key_ediv_linux}" != "${key_ediv_windows}" ]]; then - key_ediv_linux_reg="$(printf '%x\n' "${key_ediv_linux}")" # to review + key_ediv_linux_reg="$( printf '%x\n' "${key_ediv_linux}" )" # to review until [[ "$(echo "${key_ediv_linux_reg}" | wc -m)" = '8' ]]; do key_ediv_linux_reg="0${key_ediv_linux_reg}" done @@ -511,17 +511,17 @@ function bt_keys_sync_from_linux() { sudo sed -i "s/\"EDIV\"=dword:${key_ediv_windows_reg}/\"EDIV\"=dword:${key_ediv_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi if [[ "${key_rand_linux}" != "${key_rand_windows}" ]]; then - key_rand_linux_hex="$(printf '%x\n' "${key_rand_linux}" | sed 's/.\{2\}/&,/g')" # to review - key_rand_linux_reverse="$(echo "${key_rand_linux_hex::-1}" | awk -F',' '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }')" # to review + key_rand_linux_hex="$( printf '%x\n' "${key_rand_linux}" | sed 's/.\{2\}/&,/g' )" # to review + key_rand_linux_reverse="$( echo "${key_rand_linux_hex::-1}" | awk -F',' '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }' )" # to review key_rand_linux_reg="${key_rand_linux_reverse//' '/$','}" # to review check_sudo sudo sed -i "s/\"ERand\"=hex(b):${key_rand_windows_reg}/\"ERand\"=hex(b):${key_rand_linux_reg}/g" "${tmp_dir}/${tmp_reg_new}" fi fi if [[ "${bt_device_type_windows}" = 'standard' ]]; then - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg_new}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" | grep "${bt_device_windows}" | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg_new}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" | grep "${bt_device_windows}" | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" elif [[ "${bt_device_type_windows}" = 'ble' ]]; then - bt_device_info_keys_reg="$(cat -v "${tmp_dir}/${tmp_reg_new}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/")" + bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg_new}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" fi get_bt_keys_windows } @@ -609,7 +609,7 @@ function bt_keys_sync() { if [[ -f "${system_hive%/*}/SOFTWARE" ]]; then check_sudo wait $(sudo reged -x "${system_hive%/*}/SOFTWARE" "HKEY_LOCAL_MACHINE\SOFTWARE" "Microsoft\Windows NT\CurrentVersion" "${tmp_dir}/${tmp_ver}") 2>/dev/null - win_version="$(cat -v "${tmp_dir}/${tmp_ver}" | sed 's/\^M//g' | grep "\"ProductName\"" | awk -F'=' '{print $2}')" + win_version="$( cat -v "${tmp_dir}/${tmp_ver}" | sed 's/\^M//g' | grep "\"ProductName\"" | awk -F'=' '{print $2}' )" win_version="${win_version//\"/$''}" if [[ -n "${win_version}" ]]; then echo @@ -637,7 +637,7 @@ function bt_keys_sync() { echo -e "\e[1;33mwindows bluetooth pairing keys haven't been updated.\e[0m" exit 0 elif [[ "${import_registry}" -eq '1' ]]; then - backup_date="$(date +%F_%H-%M-%S)" + backup_date="$( date +%F_%H-%M-%S )" echo echo -e "\e[1;31m- making a windows SYSTEM registry hive file backup at:\e[0m" echo "${system_hive}_${backup_date}.bak" @@ -684,17 +684,17 @@ function bt_keys_sync() { function check_sudo() { if [[ "${sudouser}" != '1' ]]; then - current_sudo="$(date +%s)" + current_sudo="$( date +%s )" if [[ -z "${last_sudo}" ]] || [[ "$(echo "$((${current_sudo}-${last_sudo})) >= ${timestamp_timeout}" | bc -l)" = '1' ]]; then while true; do echo -e "\e[1;33mIn order to proceed you must grant root permissions\e[0m" if sudo -v; then if [[ -z "${timestamp_timeout}" ]]; then - timestamp_timeout_users="$(sudo cat /etc/sudoers | grep 'timestamp_timeout')" + timestamp_timeout_users="$( sudo cat /etc/sudoers | grep 'timestamp_timeout' )" if echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep -q "^Defaults:${myuser} \+"; then - timestamp_timeout="$(echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep "^Defaults:${myuser} \+" | awk -F'=' '{print $2}' | sort -g | head -n 1)"}")" + timestamp_timeout="$( echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep "^Defaults:${myuser} \+" | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" elif echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep -q "^Defaults \+"; then - timestamp_timeout="$(echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep '^Defaults \+' | awk -F'=' '{print $2}' | sort -g | head -n 1)"}")" + timestamp_timeout="$( echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep '^Defaults \+' | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" else timestamp_timeout='900' fi @@ -727,7 +727,7 @@ function check_sudo() { sudouser='1' fi fi - last_sudo="$(date +%s)" + last_sudo="$( date +%s )" break else echo -e "\e[1;31mPermission denied! Press ENTER to exit or wait 5 seconds to retry\e[0m" @@ -744,7 +744,7 @@ function find_system_hive() { for search_path in '/media/' '/mnt/'; do echo -e "\e[1;32m* searching in ${search_path} ...\e[0m" - system_hive_find="$(find "${search_path}" -type f -ipath '*/Windows/System32/config/*' -iname 'SYSTEM' 2>/dev/null)" + system_hive_find="$( find "${search_path}" -type f -ipath '*/Windows/System32/config/*' -iname 'SYSTEM' 2>/dev/null )" if [[ -n "${system_hive_find}" ]]; then if [[ -z "${system_hive_found}" ]]; then system_hive_found="${system_hive_find}" @@ -801,7 +801,7 @@ function find_system_hive() { elif [[ "${selected_path}" -eq '0' ]]; then exit 0 else - system_hive="$(echo "${system_hive_found}" | sed -n "${selected_path}"p)" + system_hive="$( echo "${system_hive_found}" | sed -n "${selected_path}"p )" break fi done @@ -918,9 +918,9 @@ Options: trap cleaning EXIT -bt_keys_sync_name="$(echo "${0}" | rev | awk -F'/' '{print $1}' | rev)" +bt_keys_sync_name="$( echo "${0}" | rev | awk -F'/' '{print $1}' | rev )" if ! command -v "${bt_keys_sync_name}" > /dev/null; then - bt_keys_sync_name="$(readlink -f "${0}")" + bt_keys_sync_name="$( readlink -f "${0}" )" fi export bt_keys_sync_name From 68637faa238d3c1659aab14e802fb38a3d31e5b4 Mon Sep 17 00:00:00 2001 From: David Ross Smith <5095074+DragRedSim@users.noreply.github.com> Date: Sat, 21 Jun 2025 02:26:40 +1000 Subject: [PATCH 2/3] Addition of basic BLE support - Note that currently, this only supports importing keys from Windows to Linux. - The script will attempt to find matching devices (by name) and highlight them. --- README.md | 25 ++- bt-keys-sync.sh | 439 ++++++++++++++++++++++++++++-------------------- 2 files changed, 280 insertions(+), 184 deletions(-) mode change 100644 => 100755 bt-keys-sync.sh diff --git a/README.md b/README.md index 0228f3a..767ba9f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # bt-keys-sync -# Version: 0.3.10 -# Author: KeyofBlueS +# Version: 0.5.0 +# Author: KeyofBlueS, DragRedSim # Repository: https://github.com/KeyofBlueS/bt-keys-sync # License: GNU General Public License v3.0, https://opensource.org/licenses/GPL-3.0 @@ -21,6 +21,12 @@ Importing Bluetooth keys from Windows to Linux is generally safe. However, the r If you choose to import keys from Linux to Windows `(tested only on Windows 10 and 11)`, proceed at your own risk. The script will back up the Windows SYSTEM registry hive file before making changes, allowing you to restore it in case of any issues. ### About Bluetooth Low Energy (BLE) +Basic support for BLE devices has been implemented! Currently, the only implemented transfer is FROM Windows TO Linux. Therefore, you will need to connect these devices to Linux first, reboot into Windows, connect there, and then back to Linux to run the script (matching the recommended workflow above). + +The script will offer a list of Windows devices when it encounters a BLE device on Linux. It will highlight (in green) any devices in Windows which share a name with the Linux device, making it easier to figure out which devices need to be selected. + +Windows BLE devices will appear in the list of devices, but they will not offer any options to synchronise at this point. + BLE devices can be detected, but their keys will not be validated or synchronized. For more information on BLE handling, please refer to [this issue](https://github.com/KeyofBlueS/bt-keys-sync/issues/13). @@ -39,6 +45,12 @@ This script requires the `chntpw` utility, which is used to read and modify Wind `sudo apt install chntpw` +or on Arch-based systems with + +`sudo pacman -S chntpw` + +If you're wanting to use this on a SteamOS setup, you may need to run `sudo steamos-readonly disable` beforehand to allow the installation. You may also need to reinstall `chntpw` after a system update, due to the way the OS is installed and updated. + ### USAGE Before running the script, make sure the Windows partition is mounted with read and write access. @@ -46,7 +58,7 @@ To run the script, simply execute: `$ bt-keys-sync` -The script will automatically search for the Windows `SYSTEM` registry hive file within common mount points such as `/media` and `/mnt`. If it cannot locate the file, you will need to manually provide the full path. This path typically looks like: +The script will automatically search for the Windows `SYSTEM` registry hive file within common mount points such as `/media` and `/mnt`, as well as `/run/media` (for those using Arch and/or SteamOS). If it cannot locate the file, you will need to manually provide the full path. This path typically looks like: `"/Windows/System32/config/SYSTEM"` @@ -58,10 +70,11 @@ By default, the script checks ControlSet001 in the registry. You can specify a d ``` Options: --p, --path Enter the full path of the windows SYSTEM registry hive file. +-p, --path Enter the full path of the Windows SYSTEM registry hive file. -c, --control-set Enter the control set to check. Default is 'ControlSet001'. --l, --linux-keys Import bluetooth pairing keys from linux to windows without asking. --w, --windows-keys Import bluetooth pairing keys from windows to linux without asking. +-l, --linux-keys Import bluetooth pairing keys from Linux to Windows without asking. +-w, --windows-keys Import bluetooth pairing keys from Windows to Linux without asking. -o, --only-list Only list bluetooth devices and pairing keys, don't do anything else. +-d, --dry-run Attempt to run the full syncing sequence, apart from actually writing anything. Useful for debugging. -h, --help Show this help. ``` diff --git a/bt-keys-sync.sh b/bt-keys-sync.sh old mode 100644 new mode 100755 index a0cc23c..d18c28a --- a/bt-keys-sync.sh +++ b/bt-keys-sync.sh @@ -2,8 +2,8 @@ # bt-keys-sync -# Version: 0.3.10 -# Author: KeyofBlueS +# Version: 0.5.0 +# Author: KeyofBlueS, DragRedSim # Repository: https://github.com/KeyofBlueS/bt-keys-sync # License: GNU General Public License v3.0, https://opensource.org/licenses/GPL-3.0 @@ -11,7 +11,7 @@ function check_bt_controllers() { check_sudo bt_controllers_linux="$( sudo ls "/var/lib/bluetooth/" | grep -Eo "^([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}$" )" - bt_controllers_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys" | awk -F'\' '{print $8}' | grep -Eo "([[:xdigit:]]){12}" )" + bt_controllers_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys" | awk -F'\' '{print $8}' | grep -Eo "([[:xdigit:]]){12}" | uniq )" bt_controllers_reg="${bt_controllers_linux//:/$''}\n${bt_controllers_windows}" @@ -22,12 +22,12 @@ function check_bt_controllers() { bt_controller_linux="$( echo "${bt_controllers_linux}" | grep "${bt_controller_macaddr}" )" bt_controller_windows="$( echo "${bt_controllers_windows}" | grep "${bt_controller}" )" echo - echo "- bluetooth controller: ${bt_controller_macaddr}" + echo "- Bluetooth controller: ${bt_controller_macaddr}" if [[ -z "${bt_controller_linux}" ]]; then - echo -e "\e[1;31m* bluetooth controller not found in linux\e[0m" + echo -e "\e[1;31m* Bluetooth controller not found in Linux\e[0m" fi if [[ -z "${bt_controller_windows}" ]]; then - echo -e "\e[1;31m* bluetooth controller not found in windows\e[0m" + echo -e "\e[1;31m* Bluetooth controller not found in Windows\e[0m" fi check_bt_devices done @@ -43,7 +43,9 @@ function check_bt_devices() { unset bt_devices_windows if [[ -n "${bt_controller_windows}" ]]; then - bt_devices_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" 2>/dev/null | awk -F'"' '{print $2}' | grep -Eo "^([[:xdigit:]]){12}$" )\n" + #get devices with single BTkeys stored as values, as opposed to registry keys + bt_devices_windows="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/${bt_controller_windows}]$/,/^$/" 2>/dev/null | awk -F'"' '{print $2}' | grep -Eo "^([[:xdigit:]]){12}$"; echo " " )" + #then add any devices with complex BTkeys bt_devices_windows+="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | grep -F "HKEY_LOCAL_MACHINE\SYSTEM\\${control_set}\Services\BTHPORT\Parameters\Keys\\${bt_controller_windows}" | awk -F'\' '{print $9}' | grep -Eo "([[:xdigit:]]){12}" )" bt_devices_windows="$( echo -e "${bt_devices_windows}" )" fi @@ -54,42 +56,19 @@ function check_bt_devices() { for bt_device in ${bt_devices}; do bt_device_macaddr="$( echo "${bt_device^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//' )" - bt_device_linux="$( echo "${bt_devices_linux}" | grep "${bt_device_macaddr}" )" - bt_device_windows="$( echo "${bt_devices_windows}" | grep "${bt_device}" )" + bt_device_linux="$( echo "${bt_devices_linux}" | grep -o "${bt_device_macaddr}" )" + bt_device_windows="$( echo "${bt_devices_windows}" | grep -o "${bt_device}" )" + + unset bt_device_name + unset linux_bt_device_name if [[ -n "${bt_device_linux}" ]]; then - check_sudo - bt_device_info="$( sudo cat "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" 2>/dev/null )" - bt_device_name="$( echo "${bt_device_info}" | grep '^Alias=' | awk -F'=' '{print $2}' )" - if [[ -z "${bt_device_name}" ]]; then - bt_device_name="$( echo "${bt_device_info}" | grep '^Name=' | awk -F'=' '{print $2}' )" - fi - if [[ -z "${bt_device_name}" ]]; then - bt_device_name='UNKWNOWN' - fi + get_bt_device_name_linux ${bt_device_linux} elif [[ -n "${bt_device_windows}" ]]; then - if [[ "${tmp_devs_deployed}" != 'true' ]]; then - tmp_devs_deployed='true' - check_sudo - sudo reged -x "${tmp_dir}/${tmp_hive}" "HKEY_LOCAL_MACHINE\SYSTEM" "\\${control_set}\Services\BTHPORT\Parameters\Devices" "${tmp_dir}/${tmp_devs}" 2>&1>/dev/null - bt_devices_info_devs_reg="$( cat -v "${tmp_dir}/${tmp_devs}" | sed 's/\^M//g' )" - fi - bt_device_info_devs_reg="$( echo "${bt_devices_info_devs_reg}" | awk "/"${bt_device_windows}]"/,/^$/" )" - bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"FriendlyName"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" - if [[ -z "${bt_device_name}" ]]; then - bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"Name"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" - fi - if [[ -n "${bt_device_name}" ]]; then - until [[ "${bt_device_name:(-3)}" != ',00' ]]; do - bt_device_name="${bt_device_name::-3}" - done - bt_device_name="$( echo -e "\x${bt_device_name//,/$'\x'}" )" - else - bt_device_name='UNKWNOWN' - fi + get_bt_device_name_windows ${bt_device_windows} fi echo - echo " \- bluetooth device: ${bt_device_macaddr} - ${bt_device_name}" + echo " \- Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}" unset bt_device_type_linux unset key_lk_linux @@ -120,42 +99,89 @@ function check_bt_devices() { unset nokey unset bt_device_type if [[ -z "${bt_device_linux}" ]]; then - echo -e "\e[1;31m * bluetooth device not found in linux. Please pair this device in linux.\e[0m" + echo -e "\e[1;31m * Bluetooth device not found in Linux. Please pair this device in Linux.\e[0m" nokey='1' else + echo -e "\e[0;32m * bt device found in Linux\e[0m" check_bt_device_type_linux - if [[ "${bt_device_type_linux}" = 'standard' ]]; then # delete after BLE support will be implemented + #if [[ "${bt_device_type_linux}" = 'standard' ]]; then # delete after BLE support will be implemented get_bt_keys_linux - fi # delete after BLE support will be implemented + #fi # delete after BLE support will be implemented fi if [[ -z "${bt_device_windows}" ]]; then - echo -e "\e[1;31m * bluetooth device not found in windows. Please pair this device in windows.\e[0m" + echo -e "\e[1;31m * Bluetooth device not found in Windows. Please pair this device in Windows.\e[0m" nokey='1' else + echo -e "\e[0;32m * bt device found in Windows\e[0m" check_bt_device_type_windows if [[ "${bt_device_type_windows}" = 'standard' ]]; then bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_controller_windows}]"/,/^$/" | grep "${bt_device_windows}" | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" elif [[ "${bt_device_type_windows}" = 'ble' ]]; then bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" fi - if [[ "${bt_device_type_windows}" = 'standard' ]]; then # delete after BLE support will be implemented + #if [[ "${bt_device_type_windows}" = 'standard' ]]; then # delete after BLE support will be implemented get_bt_keys_windows - fi # delete after BLE support will be implemented + #fi # delete after BLE support will be implemented fi if [[ "${bt_device_type_linux}" = 'standard' ]] && [[ "${bt_device_type_windows}" = 'standard' ]]; then bt_device_type='standard' elif [[ "${bt_device_type_linux}" = 'ble' ]] && [[ "${bt_device_type_windows}" = 'ble' ]]; then bt_device_type='ble' - elif [[ "${bt_device_type_linux}" = 'standard' ]] && [[ "${bt_device_type_windows}" = 'ble' ]] || [[ "${bt_device_type_linux}" = 'ble' ]] && [[ "${bt_device_type_windows}" = 'standard' ]]; then + elif [[ -n "${bt_device_type_linux}" ]] && [[ -n "${bt_device_type_windows}" ]] && [[ "${bt_device_type_linux}" != "${bt_device_type_windows}" ]] ; then echo -e "\e[1;31m * error: mismatch between device type!\e[0m" continue fi + if [[ -n "${bt_device_linux}" ]] && [[ -z "${bt_device_windows}" ]] && [[ "${bt_device_type_linux}" = 'ble' ]]; then + while true; do + echo -e "\e[1;33m This looks like a Linux BLE device that isn't synced yet. Would you like to match it against another device?\e[0m" + echo -e " 0> Skip" + #TODO: automatic match by device name + local i='0' + for win_bt_device in ${bt_devices_windows}; do + while IFS=, read -r win_dev_addr; do + if [[ -n "${win_dev_addr}" ]]; then + i=$((i + 1)) + sp1=' ' + if [[ "${i}" -gt '9' ]]; then + unset sp1 + fi + get_bt_device_name_windows ${win_dev_addr} + if [[ "${windows_bt_device_name}" = "${linux_bt_device_name}" ]]; then + colour_entry="\e[1;32m" + else + unset colour_entry + fi + echo -e "${colour_entry} ${sp1}${i}> $( echo "${win_dev_addr^^}" | sed 's/.\{2\}/&:/g' | sed 's/.$//' ) [ $( echo -e ${windows_bt_device_name} ) ]\e[0m" + fi + done <<< "${win_bt_device}" + done + unset selected_win_bt_device + echo + read -rp " choose> " selected_win_bt_device + if [[ ! "${selected_win_bt_device}" =~ ^[[:digit:]]+$ ]] || [[ "${selected_win_bt_device}" -gt "${i}" ]] || [[ "${selected_win_bt_device}" -lt '0' ]]; then + echo + echo -e "\e[1;31mInvalid choice!\e[0m" + sleep '1' + elif [[ "${selected_win_bt_device}" -eq '0' ]]; then + break + else + bt_device_windows="$( echo "${bt_devices_windows}" | sed -n "${selected_win_bt_device}"p | grep -Eo "([[:xdigit:]]){12}" )" + unset nokey + check_bt_device_type_windows + if [[ "${bt_device_type_windows}" != 'ble' ]]; then + echo -e "\e[1;31m That is not a BLE device in Windows!\e[0m" + else + get_bt_keys_windows + bt_device_type='ble' + break + fi + fi + done ############################################################## # delete after BLE support will be implemented - if [[ "${bt_device_type_linux}" = 'ble' ]] || [[ "${bt_device_type_windows}" = 'ble' ]]; then - echo -e "\e[1;31m * this device appear to be a Bluetooth Low Energy Device (BLE)\e[0m" - echo -e "\e[1;31m * support for Bluetooth Low Energy Devices is currently unimplemented\e[0m" - echo -e "\e[1;31m * please take a look at: \e[1;34mhttps://github.com/KeyofBlueS/bt-keys-sync/issues/13\e[0m" + elif [[ "${bt_device_type_linux}" = 'ble' ]] || [[ "${bt_device_type_windows}" = 'ble' ]]; then + echo -e "\e[1;31m * this device appears to be a Bluetooth Low Energy Device (BLE)\e[0m" + echo -e "\e[1;31m * support for Bluetooth Low Energy Devices is currently in development\e[0m" continue fi ############################################################## @@ -174,21 +200,61 @@ function check_bt_devices() { done } -function check_bt_device_type_linux() { +function deploy_tmp_devs() { + if [[ "${tmp_devs_deployed}" != 'true' ]]; then + tmp_devs_deployed='true' + check_sudo + sudo reged -x "${tmp_dir}/${tmp_hive}" "HKEY_LOCAL_MACHINE\SYSTEM" "\\${control_set}\Services\BTHPORT\Parameters\Devices" "${tmp_dir}/${tmp_devs}" 2>&1>/dev/null + bt_devices_info_devs_reg="$( cat -v "${tmp_dir}/${tmp_devs}" | sed 's/\^M//g' | sed -z 's/\\\n //g' )" + fi +} + +function get_bt_device_name_linux() { + check_sudo + bt_device_info="$( sudo cat "/var/lib/bluetooth/${bt_controller_macaddr}/${1}/info" 2>/dev/null )" + bt_device_name="$( echo "${bt_device_info}" | grep '^Alias=' | awk -F'=' '{print $2}' )" + if [[ -z "${bt_device_name}" ]]; then + bt_device_name="$( echo "${bt_device_info}" | grep '^Name=' | awk -F'=' '{print $2}' )" + linux_bt_device_name="${bt_device_name}" + fi + if [[ -z "${bt_device_name}" ]]; then + bt_device_name='UNKNOWN' + unset linux_bt_device_name + fi +} + +function get_bt_device_name_windows() { + deploy_tmp_devs + bt_device_info_devs_reg="$( echo "${bt_devices_info_devs_reg}" | awk "/"${1}]"/,/^$/" )" + bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"FriendlyName"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" + if [[ -z "${bt_device_name}" ]]; then + bt_device_name="$( echo "${bt_device_info_devs_reg}" | grep -F '"Name"=' | grep -Eo "([[:xdigit:]]{1,2},)+[[:xdigit:]]{2}$" )" + fi + if [[ -n "${bt_device_name}" ]]; then + until [[ "${bt_device_name:(-3)}" != ',00' ]]; do + bt_device_name="${bt_device_name::-3}" + done + bt_device_name="$( echo -e "\x${bt_device_name//,/$'\x'}" )" + windows_bt_device_name="${bt_device_name}" + else + bt_device_name='UNKNOWN' + unset windows_bt_device_name + fi +} +function check_bt_device_type_linux() { unset bt_device_type_linux if echo "${bt_device_info}" | grep -Eq "^\[LinkKey\]$"; then bt_device_type_linux='standard' - elif [[ "$(echo "${bt_device_info}" | grep -E "^(\[IdentityResolvingKey\]|\[LocalSignatureKey\]|\[LongTermKey\]|EncSize|EDiv|Rand)" | wc -l)" -ge '5' ]]; then + elif [[ "$( echo "${bt_device_info}" | grep -E "^(\[IdentityResolvingKey\]|\[LocalSignatureKey\]|\[LongTermKey\]|EncSize|EDiv|Rand)" | wc -l )" -ge '4' ]]; then bt_device_type_linux='ble' fi } function check_bt_device_type_windows() { - unset bt_device_type_windows bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" - if [[ "$(echo "${bt_device_info_keys_reg}" | grep -E "^(\"IRK\"|\"CSRK\"|\"LTK\"|\"KeyLength\"|\"EDIV\"|\"ERand\")" | wc -l)" -ge '5' ]]; then + if [[ "$( echo "${bt_device_info_keys_reg}" | grep -E "^(\"IRK\"|\"CSRK\"|\"LTK\"|\"KeyLength\"|\"EDIV\"|\"ERand\")" | wc -l )" -ge '4' ]]; then bt_device_type_windows='ble' else bt_device_type_windows='standard' @@ -196,71 +262,69 @@ function check_bt_device_type_windows() { } function get_bt_keys_linux() { - if [[ "${bt_device_type_linux}" = 'standard' ]]; then key_lk_linux="$( echo "${bt_device_info}" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" if [[ -z "${key_lk_linux}" ]]; then nokey='1' - echo -e "\e[1;31m * linux LK key not found. Please try to remove and pair again this device in linux.\e[0m" + echo -e "\e[1;31m * Linux LK key not found. Please try to remove and pair again this device in Linux.\e[0m" else - echo " - linux LK key is ${key_lk_linux}" + echo " - Linux LK key is ${key_lk_linux}" fi elif [[ "${bt_device_type_linux}" = 'ble' ]]; then key_irk_linux="$( echo "${bt_device_info}" | awk "/"\\[IdentityResolvingKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review key_lsk_linux="$( echo "${bt_device_info}" | awk "/"\\[LocalSignatureKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review - key_ltk_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" )" # to review - key_es_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EncSize=' | grep -Eo "([[:digit:]])+$" )" # to review - key_ediv_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^EDiv=' | grep -Eo "([[:digit:]])+$" )" # to review - key_rand_linux="$( echo "${bt_device_info}" | awk "/"\\[LongTermKey\\]"/,/^$/" | grep '^Rand=' | grep -Eo "([[:digit:]])+$" )" # to review + key_ltk_linux="$( echo "${bt_device_info}" | awk "/"\\[\(Peripheral\|Slave\)?LongTermKey\\]"/,/^$/" | grep '^Key=' | grep -Eo "([[:xdigit:]]){32}$" | uniq )" # to review + key_es_linux="$( echo "${bt_device_info}" | awk "/"\\[\(Peripheral\|Slave\)?LongTermKey\\]"/,/^$/" | grep '^EncSize=' | grep -Eo "([[:digit:]])+$" | uniq )" # to review + key_ediv_linux="$( echo "${bt_device_info}" | awk "/"\\[\(Peripheral\|Slave\)?LongTermKey\\]"/,/^$/" | grep '^EDiv=' | grep -Eo "([[:digit:]])+$" | uniq )" # to review + key_rand_linux="$( echo "${bt_device_info}" | awk "/"\\[\(Peripheral\|Slave\)?LongTermKey\\]"/,/^$/" | grep '^Rand=' | grep -Eo "([[:digit:]])+$" | uniq )" # to review if [[ -z "${key_irk_linux}" ]]; then - nokey='1' - echo -e "\e[1;31m * linux IRK key not found. Please try to remove and pair again this device in linux.\e[0m" + #nokey='1' + echo -e "\e[1;33m * Linux IRK key not found. This may not be an issue, but if syncing fails, try repairing the device in Linux.\e[0m" else - echo -e "\e[0;32m - linux IRK key is \e[0;32m${key_irk_linux}\e[0m" + echo -e "\e[0;32m - Linux IRK key is \e[0;32m${key_irk_linux}\e[0m" fi if [[ -z "${key_lsk_linux}" ]]; then - nokey='1' - echo -e "\e[1;31m * linux LSK key not found. Please try to remove and pair again this device in linux.\e[0m" + #nokey='1' + echo -e "\e[1;33m * Linux LSK key not found. This may not be an issue, but if syncing fails, try repairing the device in Linux.\e[0m" else - echo -e "\e[0;32m - linux LSK key is \e[0;33m${key_lsk_linux}\e[0m" + echo -e "\e[0;32m - Linux LSK key is \e[0;33m${key_lsk_linux}\e[0m" fi if [[ -z "${key_ltk_linux}" ]]; then nokey='1' - echo -e "\e[1;31m * linux LTK key not found. Please try to remove and pair again this device in linux.\e[0m" + echo -e "\e[1;31m * Linux LTK key not found. Please try to remove and pair again this device in Linux.\e[0m" else - echo -e "\e[0;32m - linux LTK key is \e[1;34m${key_ltk_linux}\e[0m" + echo -e "\e[0;32m - Linux LTK key is \e[1;34m${key_ltk_linux}\e[0m" fi if [[ -z "${key_es_linux}" ]]; then nokey='1' - echo -e "\e[1;31m * linux ES key not found. Please try to remove and pair again this device in linux.\e[0m" + echo -e "\e[1;31m * Linux ES key not found. Please try to remove and pair again this device in Linux.\e[0m" else - echo -e "\e[0;32m - linux ES key is \e[1;35m${key_es_linux}\e[0m" + echo -e "\e[0;32m - Linux ES key is \e[1;35m${key_es_linux}\e[0m" fi if [[ -z "${key_ediv_linux}" ]]; then nokey='1' - echo -e "\e[1;31m * linux EDIV key not found. Please try to remove and pair again this device in linux.\e[0m" + echo -e "\e[1;31m * Linux EDIV key not found. Please try to remove and pair again this device in Linux.\e[0m" else - echo -e "\e[0;32m - linux EDIV key is \e[1;35m${key_ediv_linux}\e[0m" + echo -e "\e[0;32m - Linux EDIV key is \e[1;35m${key_ediv_linux}\e[0m" fi if [[ -z "${key_rand_linux}" ]]; then nokey='1' - echo -e "\e[1;31m * linux RAND key not found. Please try to remove and pair again this device in linux.\e[0m" + echo -e "\e[1;31m * Linux RAND key not found. Please try to remove and pair again this device in Linux.\e[0m" else - echo -e "\e[0;32m - linux RAND key is \e[1;36m${key_rand_linux}\e[0m" + echo -e "\e[0;32m - Linux RAND key is \e[1;36m${key_rand_linux}\e[0m" fi fi } function get_bt_keys_windows() { - if [[ "${bt_device_type_windows}" = 'standard' ]]; then key_lk_windows_reg="${bt_device_info_keys_reg}" key_lk_windows="$( echo ${key_lk_windows_reg//,/$''} | tr '[:lower:]' '[:upper:]' )" if [[ -z "${key_lk_windows}" ]]; then nokey='1' - echo -e "\e[1;31m * windows LK key not found. Please try to remove and pair again this device in windows.\e[0m" + echo -e "\e[1;31m * Windows LK key not found. Please try to remove and pair again this device in Windows.\e[0m" else - echo " - windows LK key is ${key_lk_windows}" + echo " - Windows LK key is ${key_lk_windows}" fi elif [[ "${bt_device_type_windows}" = 'ble' ]]; then key_irk_windows_reg="$( echo "${bt_device_info_keys_reg}" | grep '^"IRK"' | grep -Eo "([[:xdigit:]]{1,2},){15}[[:xdigit:]]{2}$" )" # to review @@ -283,46 +347,45 @@ function get_bt_keys_windows() { key_rand_windows="$( echo "obase=10; ibase=16; ${key_rand_windows//' '/$''}" | bc )" # to review if [[ -z "${key_irk_windows}" ]]; then - nokey='1' - echo -e "\e[1;31m * windows IRK key not found. Please try to remove and pair again this device in windows.\e[0m" + #nokey='1' + echo -e "\e[1;33m * Windows IRK key not found. This may not be an issue, but if syncing fails, try repairing the device in Windows.\e[0m" else - echo -e "\e[0;32m - windows IRK key is \e[0;32m${key_irk_windows}\e[0m" + echo -e "\e[0;32m - Windows IRK key is \e[0;32m${key_irk_windows}\e[0m" fi if [[ -z "${key_lsk_windows}" ]]; then - nokey='1' - echo -e "\e[1;31m * windows LSK key not found. Please try to remove and pair again this device in windows.\e[0m" + #nokey='1' + echo -e "\e[1;33m * Windows LSK key not found. This may not be an issue, but if syncing fails, try repairing the device in Windows.\e[0m" else - echo -e "\e[0;32m - windows LSK key is \e[0;33m${key_lsk_windows}\e[0m" + echo -e "\e[0;32m - Windows LSK key is \e[0;33m${key_lsk_windows}\e[0m" fi if [[ -z "${key_ltk_windows}" ]]; then nokey='1' - echo -e "\e[1;31m * windows LTK key not found. Please try to remove and pair again this device in windows.\e[0m" + echo -e "\e[1;31m * Windows LTK key not found. Please try to remove and pair again this device in Windows.\e[0m" else - echo -e "\e[0;32m - windows LTK key is \e[1;34m${key_ltk_windows}\e[0m" + echo -e "\e[0;32m - Windows LTK key is \e[1;34m${key_ltk_windows}\e[0m" fi if [[ -z "${key_es_windows}" ]]; then nokey='1' - echo -e "\e[1;31m * windows ES key not found. Please try to remove and pair again this device in windows.\e[0m" + echo -e "\e[1;31m * Windows ES key not found. Please try to remove and pair again this device in Windows.\e[0m" else - echo -e "\e[0;32m - windows ES key is \e[1;35m${key_es_windows}\e[0m" + echo -e "\e[0;32m - Windows ES key is \e[1;35m${key_es_windows}\e[0m" fi if [[ -z "${key_ediv_windows}" ]]; then nokey='1' - echo -e "\e[1;31m * windows EDIV key not found. Please try to remove and pair again this device in windows.\e[0m" + echo -e "\e[1;31m * Windows EDIV key not found. Please try to remove and pair again this device in Windows.\e[0m" else - echo -e "\e[0;32m - windows EDIV key is \e[1;35m${key_ediv_windows}\e[0m" + echo -e "\e[0;32m - Windows EDIV key is \e[1;35m${key_ediv_windows}\e[0m" fi if [[ -z "${key_rand_windows}" ]]; then nokey='1' - echo -e "\e[1;31m * windows RAND key not found. Please try to remove and pair again this device in windows.\e[0m" + echo -e "\e[1;31m * Windows RAND key not found. Please try to remove and pair again this device in Windows.\e[0m" else - echo -e "\e[0;32m - windows RAND key is \e[1;36m${key_rand_windows}\e[0m" + echo -e "\e[0;32m - Windows RAND key is \e[1;36m${key_rand_windows}\e[0m" fi fi } function compare_bt_keys() { - unset different if [[ "${bt_device_type}" = 'standard' ]]; then if [[ "${key_lk_linux}" != "${key_lk_windows}" ]]; then @@ -351,12 +414,11 @@ function compare_bt_keys() { } function bt_keys_sync_common() { - unset bt_keys_sync_from_os retry='0' while true; do if [[ "${only_list}" = 'true' ]] || [[ "${skip}" = 'true' ]] || [[ "${retry}" -eq '10' ]]; then - bt_devices_not_synced+="- bluetooth controller: ${bt_controller_macaddr} \ bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" + bt_devices_not_synced+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" if [[ "${only_list}" = 'true' ]] || [[ "${skip}" = 'true' ]]; then echo -e "\e[1;33m * skipping this device\e[0m" unset skip @@ -381,12 +443,32 @@ function bt_keys_sync_common() { noerror='1' if [[ "${bt_keys_sync_from_os}" = 'windows' ]]; then check_sudo - sudo cp "${tmp_dir}/${tmp_info_new}" "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" - bt_devices_sync_from_windows+="- bluetooth controller: ${bt_controller_macaddr} \ bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" + win_mac_addr="$( echo ${bt_device_windows} | sed 's/.\{2\}/&:/g' | sed 's/.$//' | tr '[:lower:]' '[:upper:]' )" + if [[ "${bt_device_linux}" != "${win_mac_addr}" ]]; then + if [[ -n "${dry_run}" ]]; then + echo " *Not writing Linux keys, since dry run is enabled" + break + fi + sudo mkdir -p "/var/lib/bluetooth/${bt_controller_macaddr}/${win_mac_addr}" + sudo mv "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/*" "/var/lib/bluetooth/${bt_controller_macaddr}/${win_mac_addr}/" + sudo cp "${tmp_dir}/${tmp_info_new}" "/var/lib/bluetooth/${bt_controller_macaddr}/${win_mac_addr}/info" + sudo rm "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" + else + if [[ -n "${dry_run}" ]]; then + echo " *Not writing Linux keys, since dry run is enabled" + break + fi + sudo cp "${tmp_dir}/${tmp_info_new}" "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" + fi + bt_devices_sync_from_windows+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" elif [[ "${bt_keys_sync_from_os}" = 'linux' ]]; then - check_sudo - sudo cp "${tmp_dir}/${tmp_reg_new}" "${tmp_dir}/${tmp_reg}" - bt_devices_sync_from_linux+="- bluetooth controller: ${bt_controller_macaddr} \ bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" + if [[ -n "${dry_run}" ]]; then + echo " *Not writing Windows keys, since dry run is enabled" + else + check_sudo + sudo cp "${tmp_dir}/${tmp_reg_new}" "${tmp_dir}/${tmp_reg}" + fi + bt_devices_sync_from_linux+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" fi break fi @@ -395,10 +477,9 @@ function bt_keys_sync_common() { } function bt_keys_sync_ask() { - while true; do - echo -e "\e[1;32m - which pairing key you want to use? (the os in wich you last paired this device has the newer working key)\e[0m" - echo -e "\e[1;31m - 0) skip 1) linux key 2) windows key\e[0m" + echo -e "\e[1;32m - which pairing key do you want to use? (the OS in which you last paired this device has the newer, working key)\e[0m" + echo -e "\e[1;31m - 0) skip 1) Linux key 2) Windows key\e[0m" unset selected_key read -rp " * choose> " selected_key @@ -416,7 +497,7 @@ function bt_keys_sync_ask() { else echo echo -e "\e[1;31m * ${system_hive}: you don't have write permission\e[0m" - echo -e "\e[1;31m * you will only be able to import bluetooth pairing keys from windows to linux, not the opposite\e[0m" + echo -e "\e[1;31m * you will only be able to import Bluetooth pairing keys from Windows to Linux, not the opposite\e[0m" echo -e "\e[1;31m * make sure you have read\write access\e[0m" echo sleep '1' @@ -429,37 +510,35 @@ function bt_keys_sync_ask() { } function bt_keys_sync_from_windows() { - - echo -e "\e[1;33m * updating linux key...\e[0m" + echo -e "\e[1;33m * updating Linux key...\e[0m" bt_keys_sync_from_os='windows' check_sudo sudo cp "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" "${tmp_dir}/${tmp_info_new}" if [[ "${bt_device_type}" = 'standard' ]]; then - check_sudo sudo sed -i "s/${key_lk_linux}/${key_lk_windows}/g" "${tmp_dir}/${tmp_info_new}" elif [[ "${bt_device_type}" = 'ble' ]]; then - if [[ "${key_irk_linux}" != "${key_irk_windows}" ]]; then - check_sudo + if [[ "${key_irk_linux}" != "${key_irk_windows}" ]] && [[ -n "${key_irk_linux}" ]]; then sudo sed -i "s/Key=${key_irk_linux}/Key=${key_irk_windows}/g" "${tmp_dir}/${tmp_info_new}" + elif [[ -n "${key_irk_windows}" ]] && [[ -z "${key_irk_linux}" ]]; then + sudo echo "\n\n[IdentityResolvingKey]\nKey=${key_irk_windows}\n" >> "${tmp_dir}/${tmp_info_new}" fi - if [[ "${key_lsk_linux}" != "${key_lsk_windows}" ]]; then - check_sudo + if [[ "${key_lsk_linux}" != "${key_lsk_windows}" ]] && [[ -n "${key_lsk_linux}" ]]; then sudo sed -i "s/Key=${key_lsk_linux}/Key=${key_lsk_windows}/g" "${tmp_dir}/${tmp_info_new}" + elif [[ -n "${key_lsk_windows}" ]] && [[ -z "${key_lsk_linux}" ]]; then + sudo echo "\n\n[LocalSignatureKey]\nKey=${key_lsk_windows}\n" >> "${tmp_dir}/${tmp_info_new}" fi - if [[ "${key_ltk_linux}" != "${key_ltk_windows}" ]]; then - check_sudo + if [[ "${key_ltk_linux}" != "${key_ltk_windows}" ]] && [[ -n "${key_ltk_linux}" ]]; then sudo sed -i "s/Key=${key_ltk_linux}/Key=${key_ltk_windows}/g" "${tmp_dir}/${tmp_info_new}" + elif [[ -n "${key_ltk_windows}" ]] && [[ -z "${key_ltk_linux}" ]]; then + sudo echo "\n\n[LongTermKey]\nKey=${key_ltk_windows}\nEncSize=${key_es_windows}\nEDiv=${key_ediv_windows}\nRand=${key_rand_windows}\n" >> "${tmp_dir}/${tmp_info_new}" fi - if [[ "${key_es_linux}" != "${key_es_windows}" ]]; then - check_sudo + if [[ "${key_es_linux}" != "${key_es_windows}" ]] && [[ -n "${key_es_linux}" ]]; then sudo sed -i "s/EncSize=${key_es_linux}/EncSize=${key_es_windows}/g" "${tmp_dir}/${tmp_info_new}" fi - if [[ "${key_ediv_linux}" != "${key_ediv_windows}" ]]; then - check_sudo + if [[ "${key_ediv_linux}" != "${key_ediv_windows}" ]] && [[ -n "${key_ediv_linux}" ]]; then sudo sed -i "s/EDiv=${key_ediv_linux}/EDiv=${key_ediv_windows}/g" "${tmp_dir}/${tmp_info_new}" fi - if [[ "${key_rand_linux}" != "${key_rand_windows}" ]]; then - check_sudo + if [[ "${key_rand_linux}" != "${key_rand_windows}" ]] && [[ -n "${key_rand_linux}" ]]; then sudo sed -i "s/Rand=${key_rand_linux}/Rand=${key_rand_windows}/g" "${tmp_dir}/${tmp_info_new}" fi fi @@ -469,8 +548,7 @@ function bt_keys_sync_from_windows() { } function bt_keys_sync_from_linux() { - - echo -e "\e[1;33m * updating windows registry key...\e[0m" + echo -e "\e[1;33m * updating Windows registry key...\e[0m" bt_keys_sync_from_os='linux' bt_device_info_keys_reg="$( cat -v "${tmp_dir}/${tmp_reg}" | sed 's/\^M//g' | awk "/"${bt_device_windows}]"/,/^$/" )" cp "${tmp_dir}/${tmp_reg}" "${tmp_dir}/${tmp_reg_new}" @@ -496,7 +574,7 @@ function bt_keys_sync_from_linux() { fi if [[ "${key_es_linux}" != "${key_es_windows}" ]]; then key_es_linux_reg="$( printf '%x\n' "${key_es_linux}" )" # to review - until [[ "$(echo "${key_es_linux_reg}" | wc -m)" = '8' ]]; do + until [[ ="$( echo "${key_es_linux_reg}" | wc -m )" = '8' ]]; do key_es_linux_reg="0${key_es_linux_reg}" done check_sudo @@ -504,7 +582,7 @@ function bt_keys_sync_from_linux() { fi if [[ "${key_ediv_linux}" != "${key_ediv_windows}" ]]; then key_ediv_linux_reg="$( printf '%x\n' "${key_ediv_linux}" )" # to review - until [[ "$(echo "${key_ediv_linux_reg}" | wc -m)" = '8' ]]; do + until [[ ="$( echo "${key_ediv_linux_reg}" | wc -m )" = '8' ]]; do key_ediv_linux_reg="0${key_ediv_linux_reg}" done check_sudo @@ -527,7 +605,6 @@ function bt_keys_sync_from_linux() { } function bt_keys_sync() { - check_sudo if ! sudo bash -c "command -v reged" >/dev/null; then echo -e "\e[1;31mERROR: This script require \e[1;34mchntpw\e[1;31m. Use e.g. \e[1;34msudo apt install chntpw\e[0m" @@ -536,7 +613,7 @@ function bt_keys_sync() { if ! [[ -f "${tmp_dir}/${tmp_hive}" ]] || ! cmp -s "${system_hive}" "${tmp_dir}/${tmp_hive}"; then if ! cp "${system_hive}" "${tmp_dir}/${tmp_hive}"; then - echo -e "\e[1;31m* error while copying windows SYSTEM registry hive to ${tmp_dir}/${tmp_hive}\e[0m" + echo -e "\e[1;31m* error while copying Windows SYSTEM registry hive to ${tmp_dir}/${tmp_hive}\e[0m" exit 1 fi fi @@ -560,7 +637,7 @@ function bt_keys_sync() { echo echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" - echo -e "\e[1;33mPlease make sure the bluetooth devices are paired in both linux and windows!\e[0m" + echo -e "\e[1;33mPlease make sure the Bluetooth devices are paired in both Linux and Windows!\e[0m" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" fi @@ -568,7 +645,7 @@ function bt_keys_sync() { echo echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" - echo -e "\e[1;33mThe bluetooth pairing keys from the following devices are not synced:\e[0m" + echo -e "\e[1;33mThe Bluetooth pairing keys from the following devices are not synced:\e[0m" echo -e "${bt_devices_not_synced}" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" echo -e "\e[1;33m----------------------------------------------------------------------\e[0m" @@ -577,14 +654,14 @@ function bt_keys_sync() { echo echo -e "\e[1;32m----------------------------------------------------------------------\e[0m" echo -e "\e[1;32m----------------------------------------------------------------------\e[0m" - echo -e "\e[1;32m- The windows bluetooth pairing keys from the following devices have been imported to linux:\e[0m" + echo -e "\e[1;32m- The Windows Bluetooth pairing keys from the following devices have been imported to Linux:\e[0m" echo -e "${bt_devices_sync_from_windows}" - echo -e "\e[1;32m- The os in wich you last paired these devices has the newer working keys\e[0m" - echo -e "\e[1;32m so make sure that windows is the last os in which you paired these bluetooth devices!\e[0m" - echo -e "\e[1;32m- If not, boot into windows and pair them there (if yet paired, remove them first) so windows has the newer working keys\e[0m" - echo -e "\e[1;32m then boot into linux and run ${bt_keys_sync_name} again.\e[0m" + echo -e "\e[1;32m- The OS in which you last paired these devices has the newer working keys\e[0m" + echo -e "\e[1;32m so make sure that Windows is the last OS in which you paired these Bluetooth devices!\e[0m" + echo -e "\e[1;32m- If not, boot into Windows and pair them there (if already paired, remove them first) so Windows has the newer working keys\e[0m" + echo -e "\e[1;32m then boot into Linux and run ${bt_keys_sync_name} again.\e[0m" echo - echo -e "\e[1;32m- restarting bluetooth service...\e[0m" + echo -e "\e[1;32m- restarting Bluetooth service...\e[0m" check_sudo sudo systemctl restart bluetooth echo -e "\e[1;32m----------------------------------------------------------------------\e[0m" @@ -596,15 +673,15 @@ function bt_keys_sync() { echo echo -e "\e[1;31m----------------------------------------------------------------------\e[0m" echo -e "\e[1;31m----------------------------------------------------------------------\e[0m" - echo -e "\e[1;31m- The linux bluetooth pairing keys from the following devices haven't yet been imported to the windows SYSTEM registry hive:\e[0m" + echo -e "\e[1;31m- The Linux Bluetooth pairing keys from the following devices haven't yet been imported to the Windows SYSTEM registry hive:\e[0m" echo -e "${bt_devices_sync_from_linux}" - echo -e "\e[1;31m- This procedure is risky as it could mess with the windows registry.\e[0m" - echo -e "\e[1;31m The os in wich you last paired these devices has the newer working keys\e[0m" - echo -e "\e[1;31m so the recommended procedure is to boot into windows and pair them there (if yet paired, remove them first) so windows has the newer working keys\e[0m" - echo -e "\e[1;31m then boot into linux, run ${bt_keys_sync_name} and always choose \"windows key\" when prompted \"which pairing key you want to use?\" (or use option --windows-keys).\e[0m" + echo -e "\e[1;31m- This procedure is risky as it could mess with the Windows registry.\e[0m" + echo -e "\e[1;31m The OS in wich you last paired these devices has the newer working keys\e[0m" + echo -e "\e[1;31m so the recommended procedure is to boot into Windows and pair them there (if already paired, remove them first) so Windows has the newer working keys\e[0m" + echo -e "\e[1;31m then boot into Linux, run ${bt_keys_sync_name} and always choose \"Windows keys\" when prompted \"which pairing key you want to use?\" (or use option --windows-keys).\e[0m" echo - echo -e "\e[1;31m- If you, at your own risk, decide to import the bluetooth pairing keys from linux to windows (this has been tested on windows 10 only)\e[0m" - echo -e "\e[1;31m a backup of the windows SYSTEM registry hive file will be created, so in case of problems you could try to restore it.\e[0m" + echo -e "\e[1;31m- If you, at your own risk, decide to import the Bluetooth pairing keys from Linux to Windows (this has been tested on Windows 10 only)\e[0m" + echo -e "\e[1;31m a backup of the Windows SYSTEM registry hive file will be created, so in case of problems you could try to restore it.\e[0m" if [[ -f "${system_hive%/*}/SOFTWARE" ]]; then check_sudo @@ -613,19 +690,19 @@ function bt_keys_sync() { win_version="${win_version//\"/$''}" if [[ -n "${win_version}" ]]; then echo - echo -e "\e[1;31m* Your windows version seems to be: ${win_version}\e[0m" + echo -e "\e[1;31m* Your Windows version seems to be: ${win_version}\e[0m" else echo - echo -e "\e[1;31m* Unable to retrieve windows version!\e[0m" + echo -e "\e[1;31m* Unable to retrieve Windows version!\e[0m" fi else echo - echo -e "\e[1;31m* Unable to retrieve windows version!\e[0m" + echo -e "\e[1;31m* Unable to retrieve Windows version!\e[0m" fi while true; do echo - echo -e "\e[1;31m- do you want to import the linux bluetooth pairing keys to the windows SYSTEM registry hive?\e[0m" + echo -e "\e[1;31m- do you want to import the Linux Bluetooth pairing keys to the Windows SYSTEM registry hive?\e[0m" echo -e "\e[1;32m0) No\e[0m" echo -e "\e[1;31m1) Yes\e[0m" read -p " choose> " import_registry @@ -633,23 +710,23 @@ function bt_keys_sync() { echo -e "\e[1;31mInvalid choice!\e[0m" sleep '1' elif [[ "${import_registry}" -eq '0' ]]; then - echo -e "\e[1;33mwindows SYSTEM registry hive left untouched.\e[0m" - echo -e "\e[1;33mwindows bluetooth pairing keys haven't been updated.\e[0m" + echo -e "\e[1;33mWindows SYSTEM registry hive left untouched.\e[0m" + echo -e "\e[1;33mWindows Bluetooth pairing keys haven't been updated.\e[0m" exit 0 elif [[ "${import_registry}" -eq '1' ]]; then backup_date="$( date +%F_%H-%M-%S )" echo - echo -e "\e[1;31m- making a windows SYSTEM registry hive file backup at:\e[0m" + echo -e "\e[1;31m- making a Windows SYSTEM registry hive file backup at:\e[0m" echo "${system_hive}_${backup_date}.bak" if cp "${system_hive}" "${system_hive}_${backup_date}.bak"; then echo - echo -e "\e[1;31m- importing the linux bluetooth pairing keys to the windows SYSTEM registry hive...\e[0m" + echo -e "\e[1;31m- importing the Linux Bluetooth pairing keys to the Windows SYSTEM registry hive...\e[0m" check_sudo sudo reged -ICN "${tmp_dir}/${tmp_hive}" "HKEY_LOCAL_MACHINE\SYSTEM" "${tmp_dir}/${tmp_reg}" if cp "${tmp_dir}/${tmp_hive}" "${system_hive}"; then break else - echo -e "\e[1;31m- error while importing the linux bluetooth pairing keys to the windows SYSTEM registry hive\e[0m" + echo -e "\e[1;31m- error while importing the Linux Bluetooth pairing keys to the Windows SYSTEM registry hive\e[0m" echo -e "\e[1;31m- restoring backup\e[0m" if cp "${system_hive}_${backup_date}.bak" "${system_hive}"; then echo -e "\e[1;31m- backup restored\e[0m" @@ -660,7 +737,7 @@ function bt_keys_sync() { fi fi else - echo -e "\e[1;31m- error while making the backup of the windows SYSTEM registry hive file\e[0m" + echo -e "\e[1;31m- error while making the backup of the Windows SYSTEM registry hive file\e[0m" echo -e "\e[1;31m- aborting\e[0m" exit 1 fi @@ -672,35 +749,34 @@ function bt_keys_sync() { fi fi else - echo -e "\e[1;31m* ${system_hive}: error while exporting windows SYSTEM registry hive to ${tmp_dir}/${tmp_reg}\e[0m" + echo -e "\e[1;31m* ${system_hive}: error while exporting Windows SYSTEM registry hive to ${tmp_dir}/${tmp_reg}\e[0m" error='1' fi else - echo -e "\e[1;31m* ${system_hive}: error while exporting windows SYSTEM registry hive to ${tmp_dir}/${tmp_reg}\e[0m" + echo -e "\e[1;31m* ${system_hive}: error while exporting Windows SYSTEM registry hive to ${tmp_dir}/${tmp_reg}\e[0m" error='1' fi } function check_sudo() { - if [[ "${sudouser}" != '1' ]]; then current_sudo="$( date +%s )" - if [[ -z "${last_sudo}" ]] || [[ "$(echo "$((${current_sudo}-${last_sudo})) >= ${timestamp_timeout}" | bc -l)" = '1' ]]; then + if [[ -z "${last_sudo}" ]] || [[ ="$( echo "$((${current_sudo}-${last_sudo})) >= ${timestamp_timeout}" | bc -l )" = '1' ]]; then while true; do echo -e "\e[1;33mIn order to proceed you must grant root permissions\e[0m" if sudo -v; then if [[ -z "${timestamp_timeout}" ]]; then timestamp_timeout_users="$( sudo cat /etc/sudoers | grep 'timestamp_timeout' )" if echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep -q "^Defaults:${myuser} \+"; then - timestamp_timeout="$( echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep "^Defaults:${myuser} \+" | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" + timestamp_timeout="$( echo - | awk "{print "60" * ="$( echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep "^Defaults:${myuser} \+" | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" elif echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep -q "^Defaults \+"; then - timestamp_timeout="$( echo - | awk "{print "60" * "$(echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep '^Defaults \+' | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" + timestamp_timeout="$( echo - | awk "{print "60" * ="$( echo "${timestamp_timeout_users}" | grep 'timestamp_timeout' | grep '^Defaults \+' | awk -F'=' '{print $2}' | sort -g | head -n 1)"}" )" else timestamp_timeout='900' fi sudo_timeout='1.2' - if [[ "$(echo "${timestamp_timeout} >= 0" | bc -l)" = '1' ]] && [[ "$(echo "${timestamp_timeout} < ${sudo_timeout}" | bc -l)" = '1' ]]; then + if [[ ="$( echo "${timestamp_timeout} >= 0" | bc -l)" = '1' ]] && [[ ="$( echo "${timestamp_timeout} < ${sudo_timeout}" | bc -l )" = '1' ]]; then if [[ "${EUID}" != '0' ]]; then if [[ "${timestamp_timeout}" = '0' ]]; then echo -e "\e[1;31m* Your system is configured to ask for password at every sudo command.\e[0m" @@ -713,7 +789,7 @@ function check_sudo() { fi fi - if [[ "$(echo "${timestamp_timeout} >= ${sudo_timeout}" | bc -l)" = '1' ]]; then + if [[ ="$( echo "${timestamp_timeout} >= ${sudo_timeout}" | bc -l )" = '1' ]]; then if [[ "${EUID}" = '0' ]]; then echo -e "\e[1;31m* no need to run ${bt_keys_sync_name} as root.\e[0m" echo -e "\e[1;31m* ${bt_keys_sync_name} will ask to grant root permission when needed.\e[0m" @@ -741,15 +817,14 @@ function check_sudo() { } function find_system_hive() { - - for search_path in '/media/' '/mnt/'; do + for search_path in '/media/' '/mnt/' '/run/media/'; do echo -e "\e[1;32m* searching in ${search_path} ...\e[0m" system_hive_find="$( find "${search_path}" -type f -ipath '*/Windows/System32/config/*' -iname 'SYSTEM' 2>/dev/null )" if [[ -n "${system_hive_find}" ]]; then if [[ -z "${system_hive_found}" ]]; then system_hive_found="${system_hive_find}" else - system_hive_found+="/n${system_hive_find}" + system_hive_found+="\n${system_hive_find}" fi fi done @@ -758,9 +833,9 @@ function find_system_hive() { #clear echo if [[ -z "${system_hive_found}" ]]; then - echo -e "\e[1;31m- no results while searching for a windows SYSTEM registry hive file\e[0m" + echo -e "\e[1;31m- no results while searching for a Windows SYSTEM registry hive file\e[0m" while true; do - echo -e "\e[1;32m* please enter the full path of the windows SYSTEM registry hive file:\e[0m" + echo -e "\e[1;32m* please enter the full path of the Windows SYSTEM registry hive file:\e[0m" echo ' 0) Exit' read -p " > " system_hive if echo "${system_hive}" | grep -Eixq "(exit|e|quit|q|0)"; then @@ -776,21 +851,24 @@ function find_system_hive() { fi done else - echo -e "\e[1;32m* please select a windows SYSTEM registry hive file:\e[0m" + echo -e "\e[1;32m* please select a Windows SYSTEM registry hive file:\e[0m" fi local i='0' echo ' 0) Exit' - while IFS=, read -r exp_path; do - if [[ -n "${exp_path}" ]]; then - i=$((i + 1)) - sp1=' ' - if [[ "${i}" -gt '9' ]]; then - unset sp1 + system_hive_found="$( echo -e "${system_hive_found}" )" + for hive in ${system_hive_found}; do + while IFS=, read -r exp_path; do + if [[ -n "${exp_path}" ]]; then + i=$((i + 1)) + sp1=' ' + if [[ "${i}" -gt '9' ]]; then + unset sp1 + fi + path=${exp_path} + echo -e "${sp1}${i}) ${path}" fi - path=${exp_path} - echo -e "${sp1}${i}) ${path}" - fi - done <<< "${system_hive_found}" + done <<< "${hive}" + done unset selected_path echo read -rp " choose> " selected_path @@ -808,7 +886,7 @@ function find_system_hive() { } function cleaning() { - + tabs -0 if [[ "${force_exit}" != '1' ]]; then if [[ -f "${tmp_dir}/${tmp_reg}" ]]; then check_sudo @@ -885,7 +963,7 @@ This is true for every system, whether they are linux or windows or both or wath This script is intended to be used in a linux\windows multi boot scenario. It will check for linux and windows paired bluetooth devices and, if it finds that a device pairing key isn't equal between linux\windows, it will ask which pairing key you want to use (the os in wich you last paired this device has the newer working key) so it will update the old key with the new key accordingly. Importing the bluetooth pairing keys from windows to linux is a safe procedure. -This could not be true for the opposite, importing the bluetooth pairing keys from linux to windows is risky as it could mess with the windows registry, so the recommended procedure is to pair your bluetooth devices in linux, then boot into windows and pair them there (if yet paired, remove them first) so windows has the newer working keys, then boot into linux and run ${bt_keys_sync_name} and always choose \"windows key\" when prompted \"which pairing key you want to use?\" (or use option --windows-keys). +This could not be true for the opposite, importing the bluetooth pairing keys from linux to windows is risky as it could mess with the windows registry, so the recommended procedure is to pair your bluetooth devices in linux, then boot into windows and pair them there (if yet paired, remove them first) so windows has the newer working keys, then boot into linux and run ${bt_keys_sync_name} and always choose \"Windows key\" when prompted \"which pairing key you want to use?\" (or use option --windows-keys). If you, at your own risk, decide to import the bluetooth pairing keys from linux to windows (this has been tested on windows 10 only) a backup of the windows SYSTEM registry hive file will be created, so in case of problems you could try to restore it. ### About Bluetooth Low Energy (BLE) @@ -912,11 +990,13 @@ Options: -l, --linux-keys Import bluetooth pairing keys from linux to windows without asking. -w, --windows-keys Import bluetooth pairing keys from windows to linux without asking. -o, --only-list Only list bluetooth devices and pairing keys, don't do anything else. +-d, --dry-run Attempt to run the full syncing sequence, apart from actually writing anything. -h, --help Show this help. " } trap cleaning EXIT +tabs -4 bt_keys_sync_name="$( echo "${0}" | rev | awk -F'/' '{print $1}' | rev )" if ! command -v "${bt_keys_sync_name}" > /dev/null; then @@ -946,12 +1026,13 @@ for opt in "$@"; do '--linux-keys') set -- "$@" '-l' ;; '--windows-keys') set -- "$@" '-w' ;; '--only-list') set -- "$@" '-o' ;; + '--dry-run') set -- "$@" '-d' ;; '--help') set -- "$@" '-h' ;; *) set -- "$@" "$opt" esac done -while getopts "p:c:lwoh" opt; do +while getopts "p:c:lwodh" opt; do case ${opt} in p ) system_hive="${OPTARG}" ;; @@ -963,6 +1044,8 @@ while getopts "p:c:lwoh" opt; do ;; o ) only_list='true' ;; + d ) dry_run='true' + ;; h ) givemehelp; exit 0 ;; *) givemehelp; exit 1 @@ -989,7 +1072,7 @@ if [[ -f "${system_hive}" ]]; then system_hive_permission+="w" else echo -e "\e[1;31m* ${system_hive}: you don't have write permission\e[0m" - echo -e "\e[1;31m* you will only be able to import bluetooth pairing keys from windows to linux, not the opposite\e[0m" + echo -e "\e[1;31m* you will only be able to import Bluetooth pairing keys from Windows to Linux, not the opposite\e[0m" if [[ "${keys_from}" = 'linux' ]]; then echo -e "\e[1;31m* make sure you have read\write access\e[0m" exit 1 @@ -1002,7 +1085,7 @@ else fi if [[ "${error}" = '1' ]]; then - echo -e "\e[1;31m* make sure you enter a valid windows SYSTEM registry hive file path\e[0m" + echo -e "\e[1;31m* make sure you enter a valid Windows SYSTEM registry hive file path\e[0m" if [[ "${control_set}" != 'ControlSet001' ]]; then echo -e "\e[1;31m* make sure you enter a valid control set\e[0m" fi From cd61c9fe573c118a83fd2bac3429af43ecfe0b67 Mon Sep 17 00:00:00 2001 From: David Ross Smith <5095074+DragRedSim@users.noreply.github.com> Date: Sat, 21 Jun 2025 02:54:06 +1000 Subject: [PATCH 3/3] Slight bugfix to reporting synced devices - When syncing a BLE device, the bt_device_name variable gets clobbered while parsing the Windows devices for names. This fix uses the cached Linux device name. --- bt-keys-sync.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bt-keys-sync.sh b/bt-keys-sync.sh index d18c28a..0570b8f 100755 --- a/bt-keys-sync.sh +++ b/bt-keys-sync.sh @@ -460,7 +460,7 @@ function bt_keys_sync_common() { fi sudo cp "${tmp_dir}/${tmp_info_new}" "/var/lib/bluetooth/${bt_controller_macaddr}/${bt_device_macaddr}/info" fi - bt_devices_sync_from_windows+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" + bt_devices_sync_from_windows+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${linux_bt_device_name}\n" elif [[ "${bt_keys_sync_from_os}" = 'linux' ]]; then if [[ -n "${dry_run}" ]]; then echo " *Not writing Windows keys, since dry run is enabled" @@ -468,7 +468,7 @@ function bt_keys_sync_common() { check_sudo sudo cp "${tmp_dir}/${tmp_reg_new}" "${tmp_dir}/${tmp_reg}" fi - bt_devices_sync_from_linux+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${bt_device_name}\n" + bt_devices_sync_from_linux+="- Bluetooth controller: ${bt_controller_macaddr} \ Bluetooth device: ${bt_device_macaddr} - ${windows_bt_device_name}\n" fi break fi