#!/bin/sh # SPDX-License-Identifier: Apache-2.0 # shellcheck disable=SC2006,SC2181 # remove all existing aliases unalias -a # use a safe umask for created files umask 027 # set locale LANG=C export LANG LC_ALL=C export LC_ALL # standards conformance for GNU utilities _POSIX2_VERSION=199209 export _POSIX2_VERSION # get current working dir # $PWD is not set in solaris 10 UAC_DIR=`pwd` # check if UAC is being executed from untarred directory if [ ! -d "${UAC_DIR}/lib" ] || [ ! -d "${UAC_DIR}/artifacts" ]; then printf %b "uac: required files not found. Make sure you are executing uac \ from untarred directory.\n" >&2 exit 1 fi # set path PATH="/usr/xpg4/bin:/usr/xpg6/bin:/bin:/sbin:/usr/bin:/usr/sbin" PATH="${PATH}:/usr/local/bin:/usr/local/sbin:/usr/ucb:/usr/ccs/bin:/opt/bin" PATH="${PATH}:/opt/sbin:/opt/local/bin:/snap/bin:/netscaler" export PATH # load lib files # shellcheck disable=SC1091 . "${UAC_DIR}/lib/load_lib_files.sh" # global vars UAC_VERSION="2.7.0" MOUNT_POINT="/" OPERATING_SYSTEM="" SYSTEM_ARCH="" START_DATE="" START_DATE_DAYS="" START_DATE_EPOCH="" END_DATE="" END_DATE_DAYS="" END_DATE_EPOCH="" # the following variables are not always set on some systems, so they are set # here to avoid the script exiting with errors after set -u is used below # shellcheck disable=SC2269 HOME="${HOME}" # shellcheck disable=SC2269 HOSTNAME="${HOSTNAME}" # local vars ua_artifacts="" ua_destination_dir="" ua_run_as_non_root=false ua_temp_dir="" ua_case_number="" ua_evidence_number="" ua_evidence_description="" ua_examiner="" ua_notes="" ua_hostname="" ua_sftp_destination="" ua_sftp_port="" ua_sftp_identity_file="" ua_s3_presigned_url="" ua_s3_presigned_url_log_file="" ua_azure_storage_sas_url="" ua_azure_storage_sas_url_log_file="" ua_ibm_cos_url="" ua_ibm_cos_url_log_file="" ua_ibm_cloud_api_key="" ua_delete_local_on_successful_transfer=false ua_debug_mode=false ua_temp_data_dir_symlink_support=false # load config file load_config_file "${UAC_DIR}/config/uac.conf" || exit 1 # get current command # shellcheck disable=SC2124 ua_command_line="$0 $@" # parse command line arguments while [ "${1:-}" != "" ]; do case "${1}" in # optional arguments "-h"|"--help") usage exit 1 ;; "-V"|"--version") printf %b "UAC (Unix-like Artifacts Collector) ${UAC_VERSION}\n" exit 0 ;; "--debug") ua_debug_mode=true ;; # profiling arguments "-p"|"--profile") if [ -n "${2}" ]; then # print available profiles if [ "${2}" = "list" ]; then list_profiles exit 1 fi # get profile file based on the profile name ua_profile_file=`get_profile_file "${2}"` # exit if profile not found if [ -z "${ua_profile_file}" ]; then printf %b "uac: profile not found '${2}'\n" exit 1 fi ua_profile_file="${UAC_DIR}/profiles/${ua_profile_file}" # check if profile file is valid validate_profile_file "${ua_profile_file}" || exit 1 # convert profile file into a comma separated list of artifacts ua_artifacts_from_profile=`profile_file_to_artifact_list "${ua_profile_file}"` ua_artifacts="${ua_artifacts},${ua_artifacts_from_profile}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "-a"|"--artifacts") if [ -n "${2}" ]; then # print available artifacts if [ "${2}" = "list" ]; then list_artifacts exit 1 fi ua_artifacts="${ua_artifacts},${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; # collection arguments "-m"|"--mount-point") if [ -n "${2}" ]; then MOUNT_POINT="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "-s"|"--operating-system") if [ -n "${2}" ]; then OPERATING_SYSTEM="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "-u"|"--run-as-non-root") ua_run_as_non_root=true ;; "--hostname") if [ -n "${2}" ]; then ua_hostname="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--temp-dir") if [ -n "${2}" ]; then ua_temp_dir="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; # filter arguments "--date-range-start") if [ -n "${2}" ]; then START_DATE="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--date-range-end") if [ -n "${2}" ]; then END_DATE="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; # informational arguments "--case-number") if [ -n "${2}" ]; then ua_case_number="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--description") if [ -n "${2}" ]; then ua_evidence_description="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--evidence-number") if [ -n "${2}" ]; then ua_evidence_number="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--examiner") if [ -n "${2}" ]; then ua_examiner="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--notes") if [ -n "${2}" ]; then ua_notes="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; # remote transfer arguments "--sftp") if [ -n "${2}" ]; then ua_sftp_destination="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--sftp-port") if [ -n "${2}" ]; then ua_sftp_port="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--sftp-identity-file") if [ -n "${2}" ]; then ua_sftp_identity_file="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--s3-presigned-url") if [ -n "${2}" ]; then ua_s3_presigned_url="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--s3-presigned-url-log-file") if [ -n "${2}" ]; then ua_s3_presigned_url_log_file="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--azure-storage-sas-url") if [ -n "${2}" ]; then ua_azure_storage_sas_url="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--azure-storage-sas-url-log-file") if [ -n "${2}" ]; then ua_azure_storage_sas_url_log_file="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--ibm-cos-url") if [ -n "${2}" ]; then ua_ibm_cos_url="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--ibm-cos-url-log-file") if [ -n "${2}" ]; then ua_ibm_cos_url_log_file="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--ibm-cloud-api-key") if [ -n "${2}" ]; then ua_ibm_cloud_api_key="${2}" shift else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; "--delete-local-on-successful-transfer") ua_delete_local_on_successful_transfer=true ;; # validation arguments "--validate-artifacts-file") if [ -n "${2}" ]; then validate_artifacts_file "${2}" || exit 1 printf %b "uac: artifacts file '${2}' successfully validated.\n" exit 0 else printf %b "uac: option '${1}' requires an argument.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; # invalid arguments -*) printf %b "uac: invalid option '${1}'\n\ Try 'uac --help' for more information.\n" >&2 exit 1 ;; # positional arguments *) if [ -z "${ua_destination_dir}" ]; then ua_destination_dir="${1}" else printf %b "uac: invalid option '${1}'\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi ;; esac shift done # do not allow using undefined variables # set -u cannot be set at the beginning of the file since it will fail on $@ set -u # exit if list of artifacts or destination dir is empty if [ -z "${ua_artifacts}" ] || [ -z "${ua_destination_dir}" ] ; then usage exit 1 fi # sanitize artifact list ua_artifacts=`sanitize_artifact_list "${ua_artifacts}"` OIFS="${IFS}" IFS="," # check if artifacts exist for ua_artifact_file in ${ua_artifacts}; do ua_artifact_file=`echo "${ua_artifact_file}" | sed -e 's:^!::'` if artifact_file_exist "${ua_artifact_file}"; then true else printf %b "uac: artifact file not found '${UAC_DIR}/artifacts/${ua_artifact_file}'\n" >&2 exit 1 fi done IFS="${OIFS}" # check if destination directory exists if [ ! -d "${ua_destination_dir}" ]; then printf %b "uac: no such file or directory '${ua_destination_dir}'\n" >&2 exit 1 fi # check if temp-dir exists if [ -n "${ua_temp_dir}" ] && [ ! -d "${ua_temp_dir}" ]; then printf %b "uac: no such file or directory '${ua_temp_dir}'\n" >&2 exit 1 fi # get absolute destination directory path ua_destination_dir=`get_absolute_directory_path "${ua_destination_dir}" 2>/dev/null` # get operating system if not set by --operating-system if [ -z "${OPERATING_SYSTEM}" ]; then OPERATING_SYSTEM=`get_operating_system` fi # check if operating system is supported if is_valid_operating_system "${OPERATING_SYSTEM}"; then true else printf %b "uac: invalid operating system '${OPERATING_SYSTEM}'. \ Use '-s' option to set one.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi # check if start and end dates are valid if [ -n "${START_DATE}" ]; then START_DATE_EPOCH=`get_epoch_date "${START_DATE}"` || exit 1 # shellcheck disable=SC2034 START_DATE_DAYS=`get_days_since_date_until_now "${START_DATE}"` fi if [ -n "${END_DATE}" ]; then END_DATE_EPOCH=`get_epoch_date "${END_DATE}"` || exit 1 # shellcheck disable=SC2034 END_DATE_DAYS=`get_days_since_date_until_now "${END_DATE}"` if [ "${START_DATE_EPOCH}" -gt "${END_DATE_EPOCH}" ]; then printf %b "uac: start date cannot be greater than end date.\n" >&2 exit 1 fi fi # check if mount point exists MOUNT_POINT=`sanitize_path "${MOUNT_POINT}"` if [ ! -d "${MOUNT_POINT}" ]; then printf %b "uac: invalid mount point. \ No such file or directory '${MOUNT_POINT}'\n" >&2 exit 1 fi # cannot use not (!) as Solaris 10 does not support it if is_running_with_root_privileges || "${ua_run_as_non_root}"; then true else printf %b "uac: this script requires root privileges to run properly. \ Use '-u' option to disable root user check.\n\ Try 'uac --help' for more information.\n" >&2 exit 1 fi # get hostname if not set by --hostname # useful when running UAC against a mounted image file/disk if [ -z "${ua_hostname}" ]; then ua_hostname=`get_hostname 2>/dev/null` fi # check if destination directory's file system supports symlink creation if [ -n "${ua_temp_dir}" ]; then file_system_symlink_support "${ua_temp_dir}" >/dev/null 2>/dev/null \ && ua_temp_data_dir_symlink_support=true TEMP_DATA_DIR="${ua_temp_dir}/uac-data.tmp" else file_system_symlink_support "${ua_destination_dir}" >/dev/null 2>/dev/null \ && ua_temp_data_dir_symlink_support=true TEMP_DATA_DIR="${ua_destination_dir}/uac-data.tmp" fi # test the connectivity to remote sftp server if [ -n "${ua_sftp_destination}" ]; then if sftp_transfer_test "${ua_sftp_destination}" "${ua_sftp_port}" \ "${ua_sftp_identity_file}" >/dev/null; then true else exit 1 fi fi # test the connectivity to S3 presigned url if [ -n "${ua_s3_presigned_url}" ]; then if eval "curl --version" >/dev/null 2>/dev/null; then if s3_presigned_url_transfer_test "${ua_s3_presigned_url}"; then true else exit 1 fi else printf %b "uac: cannot transfer to S3 presigned URL because 'curl' \ tool was not found.\n" exit 1 fi fi # test the connectivity to Azure Blob Storage SAS url if [ -n "${ua_azure_storage_sas_url}" ]; then if eval "curl --version" >/dev/null 2>/dev/null; then if azure_storage_sas_url_transfer_test "${ua_azure_storage_sas_url}"; then true else exit 1 fi else printf %b "uac: cannot transfer to Azure Blob Storage SAS URL because 'curl' \ tool was not found.\n" exit 1 fi fi # test the connectivity to IBM Cloud Object Storage url if [ -n "${ua_ibm_cos_url}" ]; then if [ -n "${ua_ibm_cloud_api_key}" ]; then if eval "curl --version" >/dev/null 2>/dev/null; then if ibm_cos_transfer_test "${ua_ibm_cos_url}" "${ua_ibm_cloud_api_key}"; then true else exit 1 fi else printf %b "uac: cannot transfer to IBM Cloud Object Storage because 'curl' \ tool was not found.\n" exit 1 fi else printf %b "uac: cannot transfer to IBM Cloud Object Storage. No API \ key / Bearer token provided. Please use --ibm-cloud-api-key option to \ provide one.\n" exit 1 fi fi # remove any existing (old) collected data if [ -d "${TEMP_DATA_DIR}" ]; then rm -rf "${TEMP_DATA_DIR}" >/dev/null if [ "$?" -gt 0 ]; then printf %b "uac: cannot remove old temporary data directory from previous \ collection '${TEMP_DATA_DIR}'.\n" exit 1 fi fi # create temporary directory mkdir "${TEMP_DATA_DIR}" >/dev/null if [ "$?" -gt 0 ]; then printf %b "uac: cannot create temporary data directory '${TEMP_DATA_DIR}'.\n" exit 1 fi # clean up and exit if SIGINT (ctrl-c) is sent trap terminate INT # set log files # shellcheck disable=SC2034 UAC_LOG_FILE="${TEMP_DATA_DIR}/uac.log" UAC_STDERR_LOG_FILE="${TEMP_DATA_DIR}/uac.log.stderr" # get current user ua_current_user=`get_current_user 2>>"${UAC_STDERR_LOG_FILE}"` # get system arch SYSTEM_ARCH=`get_system_arch 2>>"${UAC_STDERR_LOG_FILE}"` # add local 'bin' directory to path PATH="${UAC_DIR}/bin/${OPERATING_SYSTEM}/${SYSTEM_ARCH}:${PATH}" # add 'avml' tool directory to path PATH="${UAC_DIR}/tools/avml/bin/${OPERATING_SYSTEM}/${SYSTEM_ARCH}:${PATH}" # add 'linux_procmemdump.sh' tool directory to path PATH="${UAC_DIR}/tools/linux_procmemdump.sh:${PATH}" export PATH printf %b "--------------------------------------------------------------------------------\n" printf %b " __ __ _______ _______ \n" printf %b " |: | | |: _ |: ____|\n" printf %b " | |_| | | | | |____ \n" printf %b " |_______|__| |__|_______|\n" printf %b "\n" printf %b " Unix-like Artifacts Collector ${UAC_VERSION}\n" printf %b "--------------------------------------------------------------------------------\n" printf %b "Operating System : ${OPERATING_SYSTEM}\n" printf %b "System Architecture : ${SYSTEM_ARCH}\n" printf %b "Hostname : ${ua_hostname}\n" printf %b "Mount Point : ${MOUNT_POINT}\n" printf %b "Running as : ${ua_current_user}\n" printf %b "Temp Directory : ${TEMP_DATA_DIR}\n" printf %b "--------------------------------------------------------------------------------\n" # start uac.log file log_message INFO "UAC (Unix-like Artifacts Collector) ${UAC_VERSION}" log_message INFO "Command line: ${ua_command_line}" log_message INFO "Operating system: ${OPERATING_SYSTEM}" log_message INFO "System architecture: ${SYSTEM_ARCH}" log_message INFO "Hostname: ${ua_hostname}" log_message INFO "Mount point: ${MOUNT_POINT}" log_message INFO "Running as: ${ua_current_user}" log_message INFO "Date range start: ${START_DATE}" log_message INFO "Date range end: ${END_DATE}" log_message INFO "Case number: ${ua_case_number}" log_message INFO "Evidence number: ${ua_evidence_number}" log_message INFO "Description: ${ua_evidence_description}" log_message INFO "Examiner: ${ua_examiner}" log_message INFO "Notes: ${ua_notes}" log_message INFO "Temp directory: ${TEMP_DATA_DIR}" log_message INFO "Current PID: ${$}" # global exclusions from uac.conf log_message INFO "Loading uac.conf settings" log_message INFO "Global exclude path pattern: ${GLOBAL_EXCLUDE_PATH_PATTERN}" log_message INFO "Global exclude name pattern: ${GLOBAL_EXCLUDE_NAME_PATTERN}" log_message INFO "Global exclude file system: ${GLOBAL_EXCLUDE_FILE_SYSTEM}" # get mount points to globally exclude from collection GLOBAL_EXCLUDE_MOUNT_POINT="" if [ -n "${GLOBAL_EXCLUDE_FILE_SYSTEM}" ]; then GLOBAL_EXCLUDE_MOUNT_POINT=`get_mount_point_by_file_system \ "${GLOBAL_EXCLUDE_FILE_SYSTEM}" 2>>"${UAC_STDERR_LOG_FILE}"` fi log_message INFO "Global exclude mount point: ${GLOBAL_EXCLUDE_MOUNT_POINT}" log_message INFO "Hash algorithm: ${HASH_ALGORITHM}" log_message INFO "Enable find mtime: ${ENABLE_FIND_MTIME}" log_message INFO "Enable find atime: ${ENABLE_FIND_ATIME}" log_message INFO "Enable find ctime: ${ENABLE_FIND_CTIME}" # check available system tools log_message INFO "Checking available system tools" check_available_system_tools >/dev/null 2>>"${UAC_STDERR_LOG_FILE}" log_message INFO "'find' opperators support: ${FIND_OPERATORS_SUPPORT}" log_message INFO "'find -path' support: ${FIND_PATH_SUPPORT}" log_message INFO "'find -type' support: ${FIND_TYPE_SUPPORT}" log_message INFO "'find -maxdepth' support: ${FIND_MAXDEPTH_SUPPORT}" log_message INFO "'find -size' support: ${FIND_SIZE_SUPPORT}" log_message INFO "'find -perm' support: ${FIND_PERM_SUPPORT}" log_message INFO "'find -atime' support: ${FIND_ATIME_SUPPORT}" log_message INFO "'find -mtime' support: ${FIND_MTIME_SUPPORT}" log_message INFO "'find -ctime' support: ${FIND_CTIME_SUPPORT}" log_message INFO "MD5 hashing tool: ${MD5_HASHING_TOOL}" log_message INFO "SHA1 hashing tool: ${SHA1_HASHING_TOOL}" log_message INFO "SHA256 hashing tool: ${SHA256_HASHING_TOOL}" log_message INFO "'gzip' tool available: ${GZIP_TOOL_AVAILABLE}" log_message INFO "'perl' tool available: ${PERL_TOOL_AVAILABLE}" log_message INFO "'tar' tool available: ${TAR_TOOL_AVAILABLE}" log_message INFO "'stat' tool available: ${STAT_TOOL_AVAILABLE}" log_message INFO "'stat' btime support: ${STAT_BTIME_SUPPORT}" log_message INFO "'statx' tool available: ${STATX_TOOL_AVAILABLE}" log_message INFO "PATH: ${PATH}" # add UAC_DIR abd TEMP_DATA_DIR to GLOBAL_EXCLUDE_PATH_PATTERN if [ -n "${GLOBAL_EXCLUDE_PATH_PATTERN}" ]; then GLOBAL_EXCLUDE_PATH_PATTERN="${GLOBAL_EXCLUDE_PATH_PATTERN},${UAC_DIR},${TEMP_DATA_DIR}" else GLOBAL_EXCLUDE_PATH_PATTERN="${UAC_DIR},${TEMP_DATA_DIR}" fi # get all user/home list # shellcheck disable=SC2034 USER_HOME_LIST=`get_user_home_list 2>>"${UAC_STDERR_LOG_FILE}"` # get user/home list skipping users with non-interactive shells # shellcheck disable=SC2034 VALID_SHELL_ONLY_USER_HOME_LIST=`get_user_home_list true 2>>"${UAC_STDERR_LOG_FILE}"` # acquisition start date ua_acq_start_date=`date "+%a %b %d %H:%M:%S %Y %z" 2>>"${UAC_STDERR_LOG_FILE}"` # acquisition start epoch date ua_acq_start_date_epoch=`get_epoch_date 2>>"${UAC_STDERR_LOG_FILE}"` log_message INFO "Artifacts collection started" printf %b "Artifacts collection started...\n" # create artifact list create_artifact_list "${ua_artifacts}" \ >"${TEMP_DATA_DIR}/.artifacts.tmp" \ 2>>"${UAC_STDERR_LOG_FILE}" ua_progress_current=0 ua_progress_total=`wc -l "${TEMP_DATA_DIR}/.artifacts.tmp" | awk '{print $1}'` # enable debug mode if it is set to true ${ua_debug_mode} && set -x # shellcheck disable=SC2162 while read ua_artifact_file || [ -n "${ua_artifact_file}" ]; do log_message INFO "Parsing artifacts file '${ua_artifact_file}'" # shellcheck disable=SC2003,SC2086 ua_progress_current=`expr ${ua_progress_current} + 1` ua_progress_timestamp=`date "+%Y-%m-%d %H:%M:%S %z"` printf "[%03d/%03d] %b %b\n" "${ua_progress_current}" \ "${ua_progress_total}" "${ua_progress_timestamp}" "${ua_artifact_file}" ua_artifacts_root_output_directory=`dirname "${ua_artifact_file}"` parse_artifacts_file "${UAC_DIR}/artifacts/${ua_artifact_file}" \ "${ua_artifacts_root_output_directory}" echo "${ua_artifacts_root_output_directory}" >>"${TEMP_DATA_DIR}/.output_file.tmp" done <"${TEMP_DATA_DIR}/.artifacts.tmp" 2>>"${UAC_STDERR_LOG_FILE}" # disable debug mode ${ua_debug_mode} && set +x # acquisition end date ua_acq_end_date=`date "+%a %b %d %H:%M:%S %Y %z" 2>>"${UAC_STDERR_LOG_FILE}"` # acquisition end epoch date ua_acq_end_date_epoch=`get_epoch_date 2>>"${UAC_STDERR_LOG_FILE}"` # get current date and time string (it will be part of the output file name) ua_current_date_time=`date "+%Y%m%d%H%M%S"` # calculate running time # shellcheck disable=SC2003 ua_total_running_time=`expr "${ua_acq_end_date_epoch}" - "${ua_acq_start_date_epoch}"` printf %b "--------------------------------------------------------------------------------\n" log_message INFO "Artifacts collection complete. \ Total execution time: ${ua_total_running_time} seconds" printf %b "Artifacts collection complete. \ Total execution time: ${ua_total_running_time} seconds\n" # output file/directory name ua_output_base_name="uac-${ua_hostname}-${OPERATING_SYSTEM}-${ua_current_date_time}" # output file/directory name ua_output_name="${ua_output_base_name}" # acquisition log file name ua_acquisition_log="${ua_output_base_name}.log" # output file hash ua_output_file_hash="-" # sort and uniq sort_uniq_file "${TEMP_DATA_DIR}/.output_file.tmp" 2>>"${UAC_STDERR_LOG_FILE}" # add uac.log to the list of files to be archived/copied within the output file echo "uac.log" >>"${TEMP_DATA_DIR}/.output_file.tmp" # add uac.log.stderr to the list of files to be archived/copied within the output file echo "uac.log.stderr" >>"${TEMP_DATA_DIR}/.output_file.tmp" if ${TAR_TOOL_AVAILABLE}; then if [ -f "${TEMP_DATA_DIR}/.files.tmp" ]; then # sort and uniq sort_uniq_file "${TEMP_DATA_DIR}/.files.tmp" 2>>"${UAC_STDERR_LOG_FILE}" if ${ua_temp_data_dir_symlink_support}; then # create symbolic link to / ln -s "/" "${TEMP_DATA_DIR}/[root]" 2>>"${UAC_STDERR_LOG_FILE}" else # copy files to uac-data.tmp/[root] printf %b "Copying files to ${TEMP_DATA_DIR}/[root]. Please wait...\n" copy_data "${TEMP_DATA_DIR}/.files.tmp" "${TEMP_DATA_DIR}/[root]" \ 2>>"${UAC_STDERR_LOG_FILE}" fi # add [root] string to the beginning of each entry in .files.tmp # and add them to the list of files to be archived within the output file sed -e 's:^/:\[root\]/:' "${TEMP_DATA_DIR}/.files.tmp" \ >>"${TEMP_DATA_DIR}/.output_file.tmp" fi # archive (and compress) collected artifacts to output file printf %b "Creating output file. Please wait...\n" cd "${TEMP_DATA_DIR}" || exit 1 if ${GZIP_TOOL_AVAILABLE}; then ua_output_name="${ua_output_base_name}.tar.gz" archive_compress_data ".output_file.tmp" \ "${ua_destination_dir}/${ua_output_name}" 2>/dev/null else ua_output_name="${ua_output_base_name}.tar" archive_data ".output_file.tmp" \ "${ua_destination_dir}/${ua_output_name}" 2>/dev/null fi if [ -f "${ua_destination_dir}/${ua_output_name}" ]; then printf %b "Output file created '${ua_destination_dir}/${ua_output_name}'\n" cd "${UAC_DIR}" || exit 1 if ${ua_debug_mode}; then printf %b "Temporary directory not removed '${TEMP_DATA_DIR}'\n" else rm -rf "${TEMP_DATA_DIR}" >/dev/null 2>/dev/null if [ -d "${TEMP_DATA_DIR}" ]; then printf %b "Cannot remove temporary directory '${TEMP_DATA_DIR}'\n" fi fi # hash output file printf %b "Hashing output file. Please wait...\n" cd "${ua_destination_dir}" || exit 1 ua_output_file_hash=`${MD5_HASHING_TOOL} "${ua_output_name}"` cd "${UAC_DIR}" || exit 1 else printf %b "Cannot create output file\n" printf %b "Please check collected artifacts in '${TEMP_DATA_DIR}'\n" cd "${UAC_DIR}" && exit 1 fi else printf %b "'tar' not found. Copying collected artifacts to '${ua_destination_dir}/${ua_output_name}'. Please wait...\n" if [ -f "${TEMP_DATA_DIR}/.files.tmp" ]; then # sort and uniq sort_uniq_file "${TEMP_DATA_DIR}/.files.tmp" 2>>"${UAC_STDERR_LOG_FILE}" copy_data "${TEMP_DATA_DIR}/.files.tmp" "${ua_destination_dir}/${ua_output_name}/[root]" \ 2>>"${UAC_STDERR_LOG_FILE}" fi cd "${TEMP_DATA_DIR}" || exit 1 copy_data "${TEMP_DATA_DIR}/.output_file.tmp" "${ua_destination_dir}/${ua_output_name}" \ 2>>"${UAC_STDERR_LOG_FILE}" ua_file_count=`find "${ua_destination_dir}/${ua_output_name}" -print | wc -l` if [ "${ua_file_count}" -gt 2 ]; then printf %b "Please check collected artifacts in '${ua_destination_dir}/${ua_output_name}'\n" cd "${UAC_DIR}" || exit 1 if ${ua_debug_mode}; then printf %b "Temporary directory not removed '${TEMP_DATA_DIR}'\n" else rm -rf "${TEMP_DATA_DIR}" >/dev/null 2>/dev/null if [ -d "${TEMP_DATA_DIR}" ]; then printf %b "Cannot remove temporary directory '${TEMP_DATA_DIR}'\n" fi fi else printf %b "Cannot copy collected artifacts\n" printf %b "Please check collected artifacts in '${TEMP_DATA_DIR}'\n" exit 1 fi fi # create the acquisition log if create_acquisition_log \ "${ua_case_number}" \ "${ua_evidence_number}" \ "${ua_evidence_description}" \ "${ua_examiner}" \ "${ua_notes}" \ "${ua_hostname}" \ "${ua_acq_start_date}" \ "${ua_acq_end_date}" \ "${ua_output_file_hash}" \ "${ua_destination_dir}" \ "${ua_acquisition_log}" 2>/dev/null; then printf %b "Acquisition log created '${ua_destination_dir}/${ua_acquisition_log}'\n" else printf %b "Cannot create acquisition log\n" fi # transfer output and log file to remote sftp server if [ -n "${ua_sftp_destination}" ]; then if [ -f "${ua_destination_dir}/${ua_output_name}" ] \ || [ -d "${ua_destination_dir}/${ua_output_name}" ]; then printf %b "Transferring output file to remote SFTP server. Please wait...\n" if sftp_transfer "${ua_destination_dir}/${ua_output_name}" \ "${ua_sftp_destination}" "${ua_sftp_port}" "${ua_sftp_identity_file}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_output_name}" 2>/dev/null printf %b "Transferring log file to remote SFTP server. Please wait...\n" if sftp_transfer "${ua_destination_dir}/${ua_acquisition_log}" \ "${ua_sftp_destination}" "${ua_sftp_port}" "${ua_sftp_identity_file}"; then printf %b "File transferred successfully\n" # delete log file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_acquisition_log}" 2>/dev/null else printf %b "Could not transfer log file to remote SFTP server\n" exit 1 fi else printf %b "Could not transfer output file to remote SFTP server\n" exit 1 fi fi fi # transfer output and log file to S3 presigned url if [ -n "${ua_s3_presigned_url}" ]; then if [ -f "${ua_destination_dir}/${ua_output_name}" ]; then printf %b "Transferring output file to S3 presigned URL. Please wait...\n" if s3_presigned_url_transfer "${ua_destination_dir}/${ua_output_name}" \ "${ua_s3_presigned_url}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_output_name}" 2>/dev/null else printf %b "Could not transfer output file to S3 presigned URL\n" exit 1 fi if [ -n "${ua_s3_presigned_url_log_file}" ]; then printf %b "Transferring log file to S3 presigned URL. Please wait...\n" if s3_presigned_url_transfer "${ua_destination_dir}/${ua_acquisition_log}" \ "${ua_s3_presigned_url_log_file}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_acquisition_log}" 2>/dev/null else printf %b "Could not transfer log file to S3 presigned URL\n" exit 1 fi fi fi fi # transfer output and log file to Azure Storage SAS url if [ -n "${ua_azure_storage_sas_url}" ]; then if [ -f "${ua_destination_dir}/${ua_output_name}" ]; then printf %b "Transferring output file to Azure Storage SAS URL. Please wait...\n" if azure_storage_sas_url_transfer "${ua_destination_dir}/${ua_output_name}" \ "${ua_azure_storage_sas_url}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_output_name}" 2>/dev/null else printf %b "Could not transfer output file to Azure Storage SAS URL\n" exit 1 fi if [ -n "${ua_azure_storage_sas_url_log_file}" ]; then printf %b "Transferring log file to Azure Storage SAS URL. Please wait...\n" if azure_storage_sas_url_transfer "${ua_destination_dir}/${ua_acquisition_log}" \ "${ua_azure_storage_sas_url_log_file}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_acquisition_log}" 2>/dev/null else printf %b "Could not transfer log file to Azure Storage SAS URL\n" exit 1 fi fi fi fi # transfer output and log file to IBM Cloud Object Storage if [ -n "${ua_ibm_cos_url}" ]; then if [ -f "${ua_destination_dir}/${ua_output_name}" ]; then printf %b "Transferring output file to IBM Cloud Object Storage. Please wait...\n" if ibm_cos_transfer "${ua_destination_dir}/${ua_output_name}" \ "${ua_ibm_cos_url}" "${ua_ibm_cloud_api_key}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_output_name}" 2>/dev/null else printf %b "Could not transfer output file to IBM Cloud Object Storage\n" exit 1 fi if [ -n "${ua_ibm_cos_url_log_file}" ]; then printf %b "Transferring log file to IBM Cloud Object Storage. Please wait...\n" if ibm_cos_transfer "${ua_destination_dir}/${ua_acquisition_log}" \ "${ua_ibm_cos_url_log_file}" "${ua_ibm_cloud_api_key}"; then printf %b "File transferred successfully\n" # delete output file on success transfer ${ua_delete_local_on_successful_transfer} \ && rm -f "${ua_destination_dir}/${ua_acquisition_log}" 2>/dev/null else printf %b "Could not transfer log file to IBM Cloud Object Storage\n" exit 1 fi fi fi fi exit 0