#
# Customization script for the Magisk Module with openssh
#
# History
#   21.02.2025 /bs
#     initial release
#
#
# Notes:
#
# This Magisk Module contains files for arm64 CPUs
#
# Documentation for creating Magisk Modules: https://topjohnwu.github.io/Magisk/guides.html
#
# Environment variables that can be used:
#
#    MAGISK_VER (string): the version string of current installed Magisk (e.g. v20.0)
#    MAGISK_VER_CODE (int): the version code of current installed Magisk (e.g. 20000)
#    BOOTMODE (bool): true if the module is being installed in the Magisk app
#    MODPATH (path): the path where your module files should be installed
#    TMPDIR (path): a place where you can temporarily store files
#    ZIPFILE (path): your module’s installation zip
#    ARCH (string): the CPU architecture of the device. Value is either arm, arm64, x86, or x64
#    IS64BIT (bool): true if $ARCH is either arm64 or x64
#    API (int): the API level (Android version) of the device (e.g. 21 for Android 5.0)
#

# -----------------------------------------------------------------------------

# define constants
#
__TRUE=0
__FALSE=1

if [ 0 = 1 -o -r /data/local/tmp/debug ] ; then
  ui_print "Writing all messages to the log file /data/local/tmp/openssh_customize.log"	
  exec 1>/data/local/tmp/openssh_customize.log 2>&1
  set -x
fi

# -----------------------------------------------------------------------------
# init global variables
#

MODULE_VERSION="$( grep "^version=" $MODPATH/module.prop  | cut -f2 -d "=" )"

CMD_PARAMETER=""

# format of the entries in this variable
# directory : owner : group : permissions
#
SSH_DATA_DIRS="
/data/local/tmp/var/:shell:shell:755
/data/local/tmp/var/run:shell:shell:755
/data/local/tmp/var/log:shell:shell:755
/data/local/tmp/var/empty:root:shell:700
/data/local/tmp/var/mail:shell:shell:755
/data/local/tmp/home:shell:shell:755
/data/local/tmp/home/.ssh:shell:shell:700
"

# -----------------------------------------------------------------------------

function LogMsg {
  ui_print "$*"
}

function LogInfo {
  LogMsg "INFO: $*"
}

function LogWarning {
  LogMsg "WARNING: $*"
}

function LogError {
  LogMsg "ERROR: $*"
}


# -----------------------------------------------------------------------------

LogMsg "The current environment for this installation is"

LogMsg "The version of the installed Magisk is \"${MAGISK_VER}\" (${MAGISK_VER_CODE})"

LogInfo "BOOTMODE is \"${BOOTMODE}\" "
LogInfo "MODPATH is \"${MODPATH}\" "
LogInfo "TMPDIR is \"${TMPDIR}\" "
LogInfo "ZIPFILE is \"${ZIPFILE}\" "
LogInfo "ARCH is \"${ARCH}\" "
LogInfo "IS64BIT is \"${IS64BIT}\" "
LogInfo "API is \"${API}\" "

# -----------------------------------------------------------------------------

# example output for the variables:


#  The version of the installed Magisk is "25.0" (25000)
#  INFO: BOOTMODE is "true" 
#  INFO: MODPATH is "/data/adb/modules_update/PlayStore_for_MicroG" 
#  INFO: TMPDIR is "/dev/tmp" 
#  INFO: ZIPFILE is "/data/user/0/com.topjohnwu.magisk/cache/flash/install.zip" 
#  INFO: ARCH is "arm64" 
#  INFO: IS64BIT is "true" 
#  INFO: API is "32"


# -----------------------------------------------------------------------------

LogMsg "Installing the Magisk Module with openssh for Android \"${MODULE_VERSION}\" ..."

LogMsg "Checking the OS configuration ..."

ERRORS_FOUND=${__FALSE}

MACHINE_TYPE="$( uname -m )"

# check the current CPU
#
LogMsg "Checking the type of the CPU used in this device ...."

LogMsg "The CPU in this device is a ${ARCH} CPU"
LogMsg "The machine type reported by \"uname -m\" is \"${MACHINE_TYPE}\" "


if [ "${ARCH}"x != "arm64"x ] ; then
  abort "This Magisk module is for arm64 CPUs only"
fi


# ---------------------------------------------------------------------

# config files for ssh and sshd
# 
SSH_CONFIG_FILE="/system/etc/ssh/ssh_config"
SSHD_CONFIG_FILE="/system/etc/ssh/sshd_config"

AUTHORIZED_KEYS_FILE="/data/local/tmp/home/.ssh/authorized_keys"

LogMsg "Installing the binaries for ${ARCH} ..."

cd  ${MODPATH}

LogMsg "Creating the data directories ..."
for CUR_ENTRY in ${SSH_DATA_DIRS} ; do

  [[ ${CUR_ENTRY} == \#* ]] && continue

  CUR_DIR="${CUR_ENTRY%%:*}"
  CUR_ENTRY="${CUR_ENTRY#*:}"

  CUR_OWNER="${CUR_ENTRY%%:*}"
  CUR_ENTRY="${CUR_ENTRY#*:}"

  CUR_GROUP="${CUR_ENTRY%%:*}"
  CUR_PERMISSIONS="${CUR_ENTRY#*:}"

  if [ ! -d "${CUR_DIR}" ] ; then
    LogMsg "Creating the directory \"${CUR_DIR}\" ..."
    mkdir -p "${CUR_DIR}" &&  \
      chown ${CUR_OWNER}:${CUR_GROUP} "${CUR_DIR}" && \
      chmod ${CUR_PERMISSIONS} "${CUR_DIR}"
   else
     LogMsg "The directory \"${CUR_DIR}\" already exists"
  fi
  echo "  $( ls -ld "${CUR_DIR}" )"
done

if [ ! -r ${AUTHORIZED_KEYS_FILE} ] ; then
  echo "# Add the ssh public keys for ssh access using public keys in this file" >"${AUTHORIZED_KEYS_FILE}" && \
    chmod 644 "${AUTHORIZED_KEYS_FILE}" && \
    chown shell:shell "${AUTHORIZED_KEYS_FILE}"
fi


LogMsg "Creating the ssh and sshd config files ..."

if [ -r "${SSH_CONFIG_FILE}" ] ; then
  LogMsg "Using the existing file \"${SSH_CONFIG_FILE}\" ..."

  if [ -r "${MODPATH}/${SSH_CONFIG_FILE}" ] ; then
     cp "${MODPATH}/${SSH_CONFIG_FILE}" "${MODPATH}/${SSH_CONFIG_FILE}.new"
     LogMsg "The new ssh config file from this module is \"${MODPATH}/${SSH_CONFIG_FILE}.new\" "
  fi
  cp "${SSH_CONFIG_FILE}" "{MODPATH}/${SSH_CONFIG_FILE}"

else
  LogMsg "No existing file \"${SSH_CONFIG_FILE}\" found -- using the new one from this Module"
fi

if [ -r "${SSHD_CONFIG_FILE}" ] ; then
  LogMsg "Using the existing file \"${SSHD_CONFIG_FILE}\" ..."

  if [ -r "${MODPATH}/${SSHD_CONFIG_FILE}" ] ; then	 
    cp -a "${MODPATH}/${SSHD_CONFIG_FILE}" "${MODPATH}/${SSHD_CONFIG_FILE}.new"
    LogMsg "The new sshd config file from this module is \"${MODPATH}/${SSHD_CONFIG_FILE}.new\" "
  fi
  cp -a "${SSHD_CONFIG_FILE}" "${MODPATH}/${SSHD_CONFIG_FILE}"

else
  LogMsg "No existing file \"${SSHD_CONFIG_FILE}\" found -- using the new one from this Module"
fi


LogMsg "Correcting the permissions for the new files ..."

# first usr/* then bin, lib  etc !
# 
for i in ${MODPATH}/system/usr/* usr etc ; do

  [[ $i != /\* ]] && CUR_ENTRY="${MODPATH}/system/$i" || CUR_ENTRY="$i"

  [ ! -d "${CUR_ENTRY}" ] && continue

  LogMsg "Processing the files in the directory ${CUR_ENTRY} ..."
  set_perm_recursive "${CUR_ENTRY}" 0 0 0755 0644 u:object_r:system_file:s0
  chcon -R -h u:object_r:system_file:s0 "${CUR_ENTRY}"
done

for i in bin lib lib64 usr/bin usr/sbin usr/libexec ; do
  [ ! -d "${MODPATH}/system/$i" ] && continue
  LogMsg "Processing the files in the directory ${MODPATH}/system/$i ..."

  set_perm_recursive "${MODPATH}/system/$i" 0 0 0755 0755 u:object_r:system_file:s0

  chcon -R -h  u:object_r:system_file:s0 "${MODPATH}/system/$i"
done


LogMsg "Creating the ssh host keys ..."

for CUR_KEY_FILE in $( grep "^HostKey" ${MODPATH}/system/etc/ssh/sshd_config | awk '{ print $2}' ) ; do
  LogMsg ""
  if [ -r "${CUR_KEY_FILE}" ] ; then
    LogMsg "Using the existing ssh host key file \"${CUR_KEY_FILE}\" "
    cp -a "${CUR_KEY_FILE}" "${MODPATH}/${CUR_KEY_FILE}"
  else
    CUR_KEY_TYPE="$( echo "${CUR_KEY_FILE}" | cut -f3 -d "_" )"
    LogMsg "Creating the ssh host key file \"${CUR_KEY_FILE}\" (${CUR_KEY_TYPE}) ..."

    case ${CUR_KEY_TYPE} in
      *ecdsa*  )
        KEY_LENGTH=521
        ;;
      * )
        KEY_LENGTH=2048
        ;;
    esac
    CUR_OUTPUT=$( exec 2>&1 ;   set -x  ; ${MODPATH}/system/bin/ssh-keygen -t "${CUR_KEY_TYPE}" -b ${KEY_LENGTH} -f "${MODPATH}/${CUR_KEY_FILE}" -N ""   &&  \
	    chown shell:shell "${MODPATH}/${CUR_KEY_FILE}" && chmod 600 "${MODPATH}/${CUR_KEY_FILE}" && chmod 644 "${MODPATH}/${CUR_KEY_FILE}.pub" )
    if [ $? -eq 0 ] ; then
      echo "${MODPATH}/${CUR_KEY_FILE} successfully created"
    else
      echo "${CUR_OUTPUT}"
      echo "ERROR: Error creating the file \"${MODPATH}/${CUR_KEY_FILE}\" "
    fi
  fi
done

