|
#!/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; |