#!/bin/bash make_log_file() { log_file="$(readlink -e $0).log.txt"; touch "$log_file"; if [[ -w "$log_file" ]]; then echo "This Bash Shell Script's output will be logged inside: "$log_file""; let made_log_file=0; else echo "This Bash Shell Script's output will NOT be logged inside: "$log_file" because it failed to create or access the stated file."; echo "This Bash Shell Script can still continue its procedures."; let made_log_file=1; fi } opening_statements() { echo "This Bash Shell Script is designed for x86_64 Debian Linux 7.6 and Tested with GnuPG-1-1.4.18 and GnuPG-2-2.0.26."; echo "It can download the Latest GnuPG-1 or GnuPG-2 Stable Source Code archive, extract it, and raise the key size and secure memory limits in the Source Code to enable working with up to 40960-bit keys."; echo "It can build a Portable GnuPG-1 Standalone Static Executable that may be carried to other Debian-based Linux OSs."; echo "It can also build a GnuPG-2 Dynamically-Linked Executable."; echo "Any installations are optional. Clean-up options are provided."; echo "Building dependencies are acquired via the APT repositories. The Source Code is acquired from either the GnuPG Website or the APT repositories."; echo "Use the ldd utility to view a GnuPG executable's dependencies."; echo "GnuPG comes in two flavours, GnuPG-1 (gpg) and GnuPG-2 (gpg2), which provide similar basic functionality and can be installed together."; echo "Only GnuPG-1 is truly standalone. GnuPG-2 is modularized and relies on installed dynamic system components in order to function."; echo "However, GnuPG-2 also supports S/MIME, X.509, CMS, keyring-daemon, SSH-agent, smart-cards, ECC (beta), etc."; echo "Bottom-line: Use GnuPG-1 if you don't need need the extra GnuPG-2 features and if you need portability. The core algorithms are the same."; echo "The GnuPG authors may eventually discontinue the development of GnuPG-1."; echo "Unmodified GnuPG can generate up to 4096-bit keys but use up to 16384-bit keys. Larger keys can be viewed but not operated. Therefore, keep the modified GnuPG-1 Standalone Static Executable available for use."; echo "FOR SECURITY: Manually check the authenticity and integrity of all the downloaded files."; echo "Superuser (sudo) access is required."; } debian76_check() { echo "Checking for OS Name and Version."; os_string=$(uname -a); os_string=${os_string,,}; if [[ $os_string == *debian* ]] && [[ $os_string == *7* ]]; then echo "The OS has been identified as DEBIAN 7.6."; else echo "Unknown OS. Use the recommended OSs. This Bash Shell Script will now exit."; pause; exit; fi } gpg1_or_gpg2_question() { echo "Asking for the flavour of GnuPG to work on."; let repeat_flavour_question=1; while [[ $repeat_flavour_question == 1 ]]; do echo "Which GnuPG flavour?"; echo "[1] GnuPG-1 - Static."; echo "[2] GnuPG-2 - Dynamic."; echo -n "Enter 1 or 2: "; read gpg_flavour; if [[ $gpg_flavour != 1 ]] && [[ $gpg_flavour != 2 ]]; then echo "Invalid choice."; else let repeat_flavour_question=0; fi done echo "Will work on GnuPG-$gpg_flavour."; } ask_to_use_sid() { echo "Asking about whether to add the Sid APT Repository."; echo "CAUTION: The Sid APT Repository significantly changes system package management."; echo "Clean-up options can reverse these changes."; let sid_use_question_answered=0; while [[ $sid_use_question_answered == 0 ]]; do echo -n "Build GnuPG by using the Sid APT Repository (Large Download)? (Recommended Answer: Nn for GnuPG-1. Yy for GnuPG-2.) (Yy or Nn): " read whether_to_use_sid; whether_to_use_sid=${whether_to_use_sid,,}; if [[ $whether_to_use_sid != "n" ]] && [[ $whether_to_use_sid != "y" ]]; then echo "Invalid choice. Enter Yn or Nn."; else let sid_use_question_answered=1; fi done echo "Sid Repository preferences processed."; } web_or_repos_question() { echo "Asking whether to use the GnuPG Website or the APT repositories to acquire the GnuPG Source Code."; let repeat_web_or_repos_question=1; while [[ $repeat_web_or_repos_question == 1 ]]; do echo "Source Code acquisition method?"; echo "[1] GnuPG FTP Server (Web) - Compile Latest Known Version."; echo "[2] APT Repositories - Compile Available Repository Version."; echo -n "Enter 1 or 2: "; read web_or_repos; if [[ $web_or_repos != 1 ]] && [[ $web_or_repos != 2 ]]; then echo "Invalid choice."; else let repeat_web_or_repos_question=0; fi done if [[ $web_or_repos == 1 ]]; then echo "Will use GnuPG FTP Server (Web)."; else echo "Will use Built-in APT Repositories."; fi } set_directories() { echo "Asking for working directory location choice."; echo "Changing into Home (~) directory first."; cd ~; echo "Entered into Home (~) directory: "$(pwd)"."; let repeat_dir_question=1; while [[ $repeat_dir_question == 1 ]]; do echo "Method of setting directory to work inside?"; echo "[1] Preset (Automatically create a directory inside the Home (~) directory)."; echo "[2] Manual (Specify a directory under which to create a working directory)."; echo -n "Enter 1 or 2: "; read dir_choice; if [[ $dir_choice != 1 ]] && [[ $dir_choice != 2 ]]; then echo "Invalid choice. Enter 1 or 2."; elif [[ $dir_choice == 1 ]]; then work_dir="~/work_in_progress/"; directory_input_processor; if [[ $directory_validity == 1 ]]; then working_directories_maker; if [[ $dir_making_success != 0 ]]; then let repeat_dir_question=0; fi fi elif [[ $dir_choice == 2 ]]; then echo "Specify an accessible existing or new directory location for this Script to work inside."; echo -n "Enter directory location: "; read work_dir; directory_input_processor; if [[ $directory_validity == 0 ]]; then let dir_interpretation_question_answered=1; else let dir_interpretation_question_answered=0; fi while [[ $dir_interpretation_question_answered == 0 ]]; do echo "The working directory location will be set as: "$work_dir"."; echo -n "Is this interpretation correct? Continue? (Yy or Nn): "; read if_dir_interpretation_correct; if_dir_interpretation_correct=${if_dir_interpretation_correct,,}; if [[ $if_dir_interpretation_correct != "n" ]] && [[ $if_dir_interpretation_correct != "y" ]]; then echo "Invalid choice. Enter Yn or Nn."; else let dir_interpretation_question_answered=1; fi done if [[ $if_dir_interpretation_correct == "y" ]]; then working_directories_maker; if [[ $dir_making_success != 0 ]]; then let repeat_dir_question=0; fi fi fi done echo "Done processing working directory location choice."; } directory_input_processor() { echo "Processing directory location input."; work_dir=${work_dir// /_spac_}; eval work_dir=""$work_dir""; if [[ $? == 0 ]]; then let eval_pass=1; else let eval_pass=0; fi work_dir=${work_dir//_spac_/ }; work_dir=""$(readlink -m "$work_dir")/gpg_work""; if [[ -z $work_dir ]] || [[ $eval_pass == 0 ]]; then let directory_validity=0; echo "Directory location input seems incorrect."; echo "Manually input a different directory location."; else echo "Directory location input seems correct for now."; let directory_validity=1; fi echo "Directory location input processed."; } working_directories_maker() { echo "Making directories to work inside."; gpg1_source_dir="$work_dir/gpg1_source"; gpg2_source_dir="$work_dir/gpg2_source"; if ( mkdir -vp "$work_dir"; mkdir -vp "$gpg1_source_dir"; mkdir -vp "$gpg2_source_dir"; ); then echo "SUCCESS: The Script will process files inside: "$work_dir"."; let dir_making_success=1; else echo "FAILURE: Directory making process failed. Try again."; let dir_making_success=0; fi echo "Working directory creation process complete."; } change_to_correct_source_dir() { if [[ $gpg_flavour == 1 ]]; then cd "$gpg1_source_dir"; else cd "$gpg2_source_dir"; fi } add_sid_apt_repos() { echo "Installing Sid APT Repository."; sid_repo_list_placement="/etc/apt/sources.list.d/sid_repo.list"; sid_repos_line="deb http://http.us.debian.org/debian/ sid main contrib non-free\ndeb-src http://http.us.debian.org/debian/ sid main contrib non-free"; sudo touch "$sid_repo_list_placement"; echo "$sid_repos_line" | sudo tee -a "$sid_repo_list_placement"; sudo apt-get update; echo "Sid APT Repository installation procedure complete."; } regular_apt_repos_update() { echo "Performing a regular update of the APT Repository information."; sudo apt-get update; echo "APT Repository information update process complete."; } get_apt_gpg1_builddeps() { echo "Installing building dependencies for GnuPG-1 via APT - Automatically."; sudo apt-get build-dep "gnupg"; echo "GnuPG-1 building dependencies Installation procedure complete."; } get_apt_gpg2_builddeps() { echo "Installing building dependencies for GnuPG-2 via APT - Automatically."; sudo apt-get build-dep "gnupg2"; echo "GnuPG-2 building dependencies Installation procedure complete."; } get_apt_gpg1_src() { echo "Getting Source Code for GnuPG-1 via APT."; cd "$work_dir"; apt-get -d source "gnupg"; tar -xf "$(ls source| grep -E 'gnupg.*1..*orig.*tar')" --strip-components=1 -C "$gpg1_source_dir"; echo "Source Code retrieval and extraction for GnuPG-1 complete."; } get_apt_gpg2_src() { echo "Getting Source Code for GnuPG-2 via APT."; cd "$work_dir"; apt-get -d source "gnupg2"; tar -xf "$(ls | grep -E 'gnupg2.*2..*orig.*tar')" --strip-components=1 -C "$gpg2_source_dir"; echo "Source Code retrieval and extraction for GnuPG-2 complete."; } get_web_gpg1_src() { echo "Retrieving GnuPG-1 Source Code from the web."; cd "$work_dir"; wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-1.4.18.tar.bz2; tar -xf $(ls | grep -E 'gnupg.*1..*tar.bz2') --strip-components=1 -C "$gpg1_source_dir"; echo "Web-Based Source Code retrieval and extraction for GnuPG-1 complete."; } get_web_gpg2_src() { echo "Retrieving GnuPG-2 Source Code from the web."; cd "$work_dir"; wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-2.0.26.tar.bz2; tar -xf $(ls | grep -E 'gnupg.*2..*tar.bz2') --strip-components=1 -C "$gpg2_source_dir"; echo "Web-Based Source Code retrieval and extraction for GnuPG-2 complete."; } raise_limits_in_source_code_dir() { echo "Raising the key size and secure memory limits in the GnuPG-$gpg_flavour Source Code to enable working with up to 40960-bit keys."; change_to_correct_source_dir; grep -rl 4096 | xargs sed -i 's/4096/40960/g'; #Replaces the 4096 bit key size limit with 102400 bits. grep -rl 32768 | xargs sed -i 's/32768/10000000/g'; #Replaces the 32768 byte secure memory limit with 10000000 bytes. grep -rl 16384 | xargs sed -i 's/16384/40960/g'; #Replaces the 16384 bit MPI (Message Parsing Interface) Object limit and another secure memory limit with 40960 bits. echo "Source Code Limits on key size and secure memory Raised."; } build_static_gnupg1() { echo "Building a Portable GnuPG-1 Standalone Static Executable."; change_to_correct_source_dir; ./configure --enable-ldap --with-libcurl CFLAGS="-static" LDFLAGS="-static"; make; echo "Building process for a Portable GnuPG-1 Standalone Static Executable complete."; } build_dynamic_gnupg2() { echo "Building a Dynamically-Linked GnuPG-2 Executable."; change_to_correct_source_dir; ./configure; make; echo "Building process for a Dynamically-Linked GnuPG-2 Executable complete."; } ask_and_perform_install() { echo "Asking for installation preference."; let repeat_install_question=1; while [[ $repeat_install_question == 1 ]]; do echo -n "Install this build? (Yy or Nn): "; read install_preference; install_preference=${install_preference,,}; if [[ $install_preference != "n" ]] && [[ $install_preference != "y" ]]; then echo "Invalid choice."; else let repeat_install_question=0; fi done if [[ $install_preference == "y" ]]; then echo "Installing build."; change_to_correct_source_dir; sudo make install; else echo "The built application will not be installed."; fi echo "Preferred installation preference applied."; } ask_and_perform_cleanup() { echo "Checking for clean-up preferences."; echo "The user may need to manually remove some packages to avoid undesired changes in system package management."; echo "Use "apt-get showsrc and markauto package_name" to remove the installed build dependencies."; if [[ $install_preference == "y" ]]; then let repeat_cleanup_question=0; echo "Will not perform clean-up because GnuPG installation was chosen."; else let repeat_cleanup_question=1; fi while [[ $repeat_cleanup_question == 1 ]]; do echo -n "Remove some repository changes and installed packages? (Not needed for Live OSs.) (Yy or Nn): "; read cleanup_preference; cleanup_preference=${cleanup_preference,,}; if [[ $cleanup_preference != "n" ]] && [[ $cleanup_preference != "y" ]]; then echo "Invalid choice."; else let repeat_cleanup_question=0; fi done echo "Processing clean-up options."; if [[ $cleanup_preference == "y" ]] && [[ $whether_to_use_sid == "y" ]]; then remove_sid_apt_repos; clean_debian_deps; elif [[ $cleanup_preference == "y" ]] && [[ $whether_to_use_sid == "n" ]]; then clean_debian_deps; fi echo "Clean-up options processed."; } remove_sid_apt_repos() { echo "Removing Sid APT repository."; sudo rm $sid_repo_list_placement; sudo apt-get update; sudo apt-get clean; echo "Sid APT repository removal procedure complete."; } clean_debian_deps() { echo "Cleaning APT dependencies chain."; sudo apt-get autoremove; sudo apt-get autoclean; sudo apt-get clean; sudo apt-get update; echo "APT dependencies chain cleaning procedure complete."; } core_gpg_tasks() { if [[ $whether_to_use_sid == "y" ]]; then add_sid_apt_repos; regular_apt_repos_update; else regular_apt_repos_update; fi pause; if [[ $gpg_flavour == 1 ]] && [[ $web_or_repos == 1 ]]; then get_apt_gpg1_builddeps; pause; get_web_gpg1_src; pause; raise_limits_in_source_code_dir; pause; build_static_gnupg1; pause; elif [[ $gpg_flavour == 1 ]] && [[ $web_or_repos == 2 ]]; then get_apt_gpg1_builddeps; pause; get_apt_gpg1_src; pause; raise_limits_in_source_code_dir; pause; build_static_gnupg1; pause; elif [[ $gpg_flavour == 2 ]] && [[ $web_or_repos == 1 ]]; then get_apt_gpg2_builddeps; pause; get_web_gpg2_src; pause; raise_limits_in_source_code_dir; pause; build_dynamic_gnupg2; pause; elif [[ $gpg_flavour == 2 ]] && [[ $web_or_repos == 2 ]]; then get_apt_gpg2_builddeps; pause; get_apt_gpg2_src; pause; raise_limits_in_source_code_dir; pause; build_dynamic_gnupg2; pause; fi } closing_statements() { echo "All procedures complete. Completed work is present under "$work_dir"."; echo "Restart the Script to work on the other GnuPG flavour."; echo "Move all completed work out of the directory above before reusing the Script."; echo "This Bash Shell Script will now exit."; } pause() { echo -e "\n"; read -rsn 1 -p "Press any key to continue." < /dev/tty; echo -e "\n"; } main() { opening_statements; pause; debian76_check; pause; gpg1_or_gpg2_question; pause; ask_to_use_sid; pause; web_or_repos_question; pause; set_directories; pause; core_gpg_tasks; pause; ask_and_perform_install; pause; ask_and_perform_cleanup; pause; closing_statements; pause; } clear; make_log_file; pause; if [[ $made_log_file == 0 ]]; then exec > >(tee -a "$log_file"); exec 2>&1; main; else exec 2>&1; main; fi exit;