0

I'm looking at the bash script included below. It accepts a couple of command line arguments and creates a .deb package that, when executed, using the sudo dpkg -i created-file.deb command, a new user is created and low and behold, the new user's home directory has a .ssh directory with an authorized_keys file that matches the contents of the file submitted as the 2nd argument. However, how are the .ssh directory and authorized_keys files created? I can see the useradd command but the created .deb file does not seem to have a command that actually moves the files to the new user's home directory.

Here is the command I run on this script:

sudo ./gvm-lsc-deb-creator.sh newuser some_file.pub /home/currentuser /home/currentuser [email protected]

Here is the full script:

# Command line parameters
USERNAME="$1"
PUBKEY_FILE="$2"
TEMP_DIR="$3"
OUTPUT_PATH=$4
MAINTAINER_EMAIL="$5"

if [ -z "${USERNAME}" ]
then
  echo "No username given" >&2
  exit 1
fi

if [ -z "${PUBKEY_FILE}" ]
then
  echo "No pubkey path given" >&2
  exit 1
fi

if [ -z "${TEMP_DIR}" ]
then
  echo "No temp dir path given" >&2
  exit 1
fi

if [ -z "${OUTPUT_PATH}" ]
then
  echo "No output path given" >&2
  exit 1
fi

if [ -z "${MAINTAINER_EMAIL}" ]
then
  MAINTAINER_HOSTNAME="$(hostname)"
  if [ -z "$HOSTNAME" ]
  then
    MAINTAINER_HOSTNAME="localhost"
  fi
  MAINTAINER_EMAIL="admin@${MAINTAINER_HOSTNAME}"
fi

# Constants
# Package data
PACKAGE_NAME="gvm-lsc-target-${USERNAME}"
PACKAGE_VERSION="0.5-1"
PACKAGE_NAME_VERSION="${PACKAGE_NAME}_${PACKAGE_VERSION}"
MAINTAINER="Greenbone Vulnerability Manager  <${MAINTAINER_EMAIL}>"
PACKAGE_DATE=$(date "+%a, %d %b %Y %H:%M:%S %z")

USER_COMMENT="GVM Local Security Checks"
USER_COMMENT_GREP="GVM\\ Local\\ Security\\ Checks"

# Paths
PACKAGE_BASE_DIR="${TEMP_DIR}/${PACKAGE_NAME_VERSION}"

# Data paths
DATA_DIR="${PACKAGE_BASE_DIR}"
HOME_SUBDIR="home/${USERNAME}"
HOME_DATA_DIR="${DATA_DIR}/${HOME_SUBDIR}"
SSH_DATA_DIR="${HOME_DATA_DIR}/.ssh"
DOC_SUBDIR="usr/share/doc/${PACKAGE_NAME}"
DOC_DATA_DIR="${DATA_DIR}/${DOC_SUBDIR}"

# Control file path
CONTROL_DIR="${PACKAGE_BASE_DIR}/DEBIAN"

#
# Test dependencies
#
if [ -z "$(which dpkg)" ]
then
  echo "dpkg not found" >&2
  exit 1
fi

if [ -z "$(which fakeroot)" ]
then
  echo "fakeroot not found" >&2
  exit 1
fi

if [ -z "$(which md5sum)" ]
then
  echo "md5sum not found" >&2
  exit 1
fi

#
# Set up error handling
#
handle_error() {
  echo "DEB package generation failed" >&2
  exit 1
}
trap handle_error ERR

#
# Create data files
#

# Create .ssh directory
mkdir -p "${SSH_DATA_DIR}"

# Copy public key
AUTH_KEYS_FILE="${SSH_DATA_DIR}/authorized_keys"
cp "${PUBKEY_FILE}" "${AUTH_KEYS_FILE}"

# Create doc directory
mkdir -p "${DOC_DATA_DIR}"

# Create Changelog
cd "${DOC_DATA_DIR}"
CHANGELOG_FILE="${DOC_DATA_DIR}/changelog.Debian"
{
  echo "${PACKAGE_NAME} (${PACKAGE_VERSION}) experimental; urgency=low"
  echo ""
  echo "  * Automatically generated local security check credential package"
  echo "  "
  echo ""
  echo " -- ${MAINTAINER}  ${PACKAGE_DATE}"
} > "${CHANGELOG_FILE}"

# Compress Changelog
gzip -f --best "${CHANGELOG_FILE}"
CHANGELOG_FILE="${CHANGELOG_FILE}.gz"

# Create Copyright info
COPYRIGHT_FILE="${DOC_DATA_DIR}/copyright"
{
  echo "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/"
  echo ""
  echo "Files: *"
  echo "Copyright: 2018-2020 Greenbone AG"
  echo "License: GPL-2+ (/usr/share/common-licenses/GPL-2)"
} > "${COPYRIGHT_FILE}"

# Create data archive
cd "${DATA_DIR}"
tar -C "${DATA_DIR}" -z -cf "../data.tar.gz" "${HOME_SUBDIR}" "${DOC_SUBDIR}"


#
# Create control files
#

# Create directory
mkdir -p "${CONTROL_DIR}"
chmod "0755" "${CONTROL_DIR}"

# Create "control" file
CONTROL_FILE="${CONTROL_DIR}/control"
{
  echo "Package: ${PACKAGE_NAME}"
  echo "Version: ${PACKAGE_VERSION}"
  echo "Maintainer: ${MAINTAINER}"
  echo "Priority: optional"
  echo "Architecture: all"
  echo "Description: GVM local security check preparation"
  echo " This package prepares a system for GVM local security checks."
  echo " A user is created with a specific SSH authorized key."
  echo " The corresponding private key is located at the respective"
  echo " GVM installation."
} > "${CONTROL_FILE}"

# Create "preinst" file run before installation
PREINST_FILE="${CONTROL_DIR}/preinst"
touch "${PREINST_FILE}"
chmod "0755" "${PREINST_FILE}"
{
  echo "#!/bin/sh"
  echo "set -e  # abort on errors"
  echo "useradd -c \"${USER_COMMENT}\" -d /home/${USERNAME} -m -s /bin/bash ${USERNAME}"
} > "${PREINST_FILE}"

# Create "postinst" file run after installation
POSTINST_FILE="${CONTROL_DIR}/postinst"
touch "${POSTINST_FILE}"
chmod "0755" "${POSTINST_FILE}"
{
  echo "#!/bin/sh"
  echo "set -e  # abort on errors"
  echo "chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}"
  echo "chmod 500 /home/${USERNAME}/.ssh"
  echo "chmod 400 /home/${USERNAME}/.ssh/authorized_keys"
} > "${POSTINST_FILE}"

# Create "postinst" file run after removal or on error
POSTRM_FILE="${CONTROL_DIR}/postrm"
touch "${POSTRM_FILE}"
chmod "0755" "${POSTRM_FILE}"
{
  echo "#!/bin/sh"
  echo "# Remove user only if it was created by this package."
  echo "# The debian package will run the postun script in case of errors"
  echo "# (e.g. user already existed)."
  echo "# Delete the user only if /etc/passwd lists content that suggests"
  echo "# that the user was created by this package."
  # echo "set -e  # abort on errors"
  echo "grep \"${USERNAME}.*${USER_COMMENT_GREP}\" /etc/passwd && userdel -fr ${USERNAME}"
} > "${POSTRM_FILE}"

# Calculate md5 checksums
MD5SUMS_FILE="${CONTROL_DIR}/md5sums"
cd "${DATA_DIR}"
{
  md5sum "${HOME_SUBDIR}/.ssh/authorized_keys"
  md5sum "${DOC_SUBDIR}/changelog.Debian.gz"
  md5sum "${DOC_SUBDIR}/copyright"
} > "${MD5SUMS_FILE}"

#
# Build package
#

# Combine into .deb file
cd "${TEMP_DIR}"
fakeroot -- dpkg --build "${PACKAGE_NAME_VERSION}" "${OUTPUT_PATH}"

I understand the script will create a directory PACKAGE_BASE_DIR and WILL move the file in the second command argument to THAT directory, which will be tarred and compressed and compiled into the .deb package. However, the .deb package has three executable files 'preinst', postinst, and postrm. The contents of those files are:

preinst:

#!/bin/sh
set -e  # abort on errors
useradd -c "GVM Local Security Checks" -d /home/testing -m -s /bin/bash testing

postinst

#!/bin/sh
set -e  # abort on errors
chown -R testing:testing /home/testing
chmod 500 /home/testing/.ssh
chmod 400 /home/testing/.ssh/authorized_keys

But none of those commands actually move the files contained in the .deb package into the new user's home directory. I have looked at the adduser manpage but I can't see any function that would allow this. This does not just create a skel, it actually moves the files.

I read this answer hoping it would point to some function that would automatically do this, but no.

My question is, how are these files being moved. It seems there is no command to actually move them when the new user is created, yet, they are. Running the script doesn't create a user or the user home directory. It only outputs a .deb package. The .deb package's scripts don't have an obvious way the files are moved.

P.S. THis file stumped ChatGPT and I keep compiling and running it over and over mind blown. The files are moved into the new user's home directory.

2
  • "But none of those commands actually move the files contained in the .deb package into the new user's home directory." ... You do know that one of the steps that dpkg performs in installing a deb file is to extract the files in the data archive to the corresponding locations in the root directory? Commented May 7, 2023 at 3:32
  • No, I didn't know that. So, its dpkg? Thanks. I'll have to read the documentation for dpkg. Commented May 7, 2023 at 4:50

1 Answer 1

0

Thanks to the comment from @muru I was able to quickly understand how .deb packages populate package files into the Linux file structure.

In between the preinst and postinst scripts, the Debian package management system performs several tasks, including unpacking the package files into the file system, setting up the package's configuration files, and registering the package with the system's package management database.

Here is a general overview of the steps that occur when a Debian package is installed:

  • The package is unpacked into a temporary directory. The preinst script is executed, which performs any necessary pre-installation tasks.
  • The package's files are copied to their final locations in the file system.
  • The postinst script is executed, which performs any necessary post-installation tasks.
  • The package is registered with the system's package management database.
  • The system's package management database is updated to reflect the new package installation.
  • The package's configuration files are set up.

Also, after the package has been successfully installed, it can be removed using the system's package management tools, which will execute the prerm and postrm scripts, respectively, before and after the package files are removed from the file system.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.