-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwhonix
executable file
·252 lines (213 loc) · 7.01 KB
/
whonix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/bin/bash
# do not run this as root
if [ "$(id -u)" = "0" ]; then
echo "Error: Do not run this as root!"
exit 1
fi
# check if argument is not missing
if [ -z "$1" ]; then
echo "Error: Missing tag argument. Please provide a tag argument."
exit 2
fi
# Check if the 'debian' user exists
if id "debian" &>/dev/null; then
# Check if 'debian' user is in the 'sudo' group
if groups "debian" | grep -qw "sudo"; then
# Check if the sudoers file already exists
if [ ! -f /etc/sudoers.d/debian_nopass ]; then
echo "Creating no-password sudo entry for debian user..."
# Use echo piped to sudo tee to safely create a sudoers file without using a text editor
echo 'debian' | sudo -S sh -c "echo '%sudo ALL=(ALL) NOPASSWD: ALL' | tee /etc/sudoers.d/debian_nopass > /dev/null"
# Set correct permissions for the sudoers file
echo 'debian' | sudo -S chmod 0440 /etc/sudoers.d/debian_nopass
echo "No-password sudo entry created successfully."
fi
fi
fi
# set options
set -e
set -o nounset
set -o errtrace
set -o pipefail
# variables and configuration
NAME="whonix"
DM="derivative-maker"
DB="derivative-binary"
BL="build-log"
VERSION="$1"
VERSION_MASTER="master"
VERSION_NUMBER="${VERSION%%-*}"
REPOSITORY_URL="https://github.com/Whonix/derivative-maker.git"
FLAVOR_GATEWAY="whonix-gateway-xfce"
FLAVOR_WORKSTATION="whonix-workstation-xfce"
TARGET="utm"
ARCH="arm64"
TB="open"
REPO="true"
SIZE_GATEWAY="15G"
SIZE_WORKSTATION="25G"
WB="whonix-binary-$VERSION"
APT="/usr/bin/apt"
GIT="/usr/bin/git"
GPG="/usr/bin/gpg"
# catching errors as they occur
function catch() {
echo "Error Report"
if [ "$1" != "0" ]; then
echo "Error $1 occurred on line $2, command: '$3'"
exit 11 # Exit on any error caught by this function
fi
}
# SIGINT or SIGTERM
function handle_signal() {
echo "Error: received SIGINT or SIGTERM exiting"
exit 3
}
# start text
function beginning() {
echo "Starting $NAME build for version $VERSION"
}
# finishing text
function bye() {
echo "Exiting without errors."
echo "Build function finished, please check log"
echo "Its recommended that you verify the signing key on the repository and build, more info here:"
echo "https://www.whonix.org/wiki/Signing_Key"
}
# safe exit of the script
function safe_exit() {
trap bye EXIT
exit 0
}
function check_apt_sources() {
echo "Checking APT sources availability..."
if ! sudo "$APT" update &> /dev/null; then
echo "Error: APT sources are not reachable. Please check your sources.list and internet connection."
exit 4
fi
}
function check_connectivity() {
local HOST="github.com"
echo "Checking connectivity to $HOST..."
if ! ping -c 1 -W 2 "$HOST" &> /dev/null; then
echo "Error: Unable to reach $HOST. Please check your internet connection."
exit 5
fi
}
function repository_not_found() {
echo "Error: ${HOME}/${DM} not found"
exit 6
}
# Set up trap
trap 'catch $? $LINENO "$BASH_COMMAND"' EXIT
trap handle_signal SIGINT SIGTERM
function update() {
# updates/upgrades and autoremove packages
check_apt_sources
sudo "$APT" update -y
sudo "$APT" upgrade -y
sudo "$APT" autoremove -y
}
function install() {
# install dependencies
local PACKAGES=("git" "time" "curl" "apt-cacher-ng" "lsb-release" "dpkg-dev" "fakeroot" "fasttrack-archive-keyring" "safe-rm" "extrepo-offline-data")
# Loop through each package
for PACKAGE in "${PACKAGES[@]}"; do
if ! dpkg-query -W -f='${Status}' "$PACKAGE" 2>/dev/null | grep -q "install ok installed"; then
echo "$PACKAGE is not installed. Installing..."
sudo DEBIAN_FRONTEND=noninteractive "$APT" install -y "$PACKAGE"
else
echo "$PACKAGE is already installed."
fi
done
# GPG Key Import Check
local KEY_FINGERPRINT="916B8D99C38EAF5E8ADC7A2A8D66066A2EEACCDA"
if ! gpg --list-keys "$KEY_FINGERPRINT" > /dev/null 2>&1; then
echo "GPG key not found. Importing..."
"$GPG" --import /usr/share/extrepo/offline-data/debian/bullseye/whonix.asc
else
echo "GPG key already imported."
fi
}
function repo_down() {
if [ ! -d "${HOME}/${DM}" ]; then
# download git repository
check_connectivity
echo "Git clone $NAME repository"
"$GIT" clone --depth=1 --branch "$VERSION_MASTER" --jobs=4 --recurse-submodules --shallow-submodules "$REPOSITORY_URL"
cd "${HOME}/${DM}" || repository_not_found
fi
}
function fetch_tag() {
cd "${HOME}/${DM}" || repository_not_found
# Verify if the current directory is a git repository
if ! "$GIT" rev-parse --git-dir > /dev/null 2>&1; then
echo "Error: Not a git repository. Please run this script within a git repository."
exit 7
fi
if [ ! "$($GIT status --porcelain)" = "" ]; then
echo "Error: Command git status --porcelain failed at the beginning!"
exit 8
fi
# Before fetching and checking out:
"$GIT" reset --hard
"$GIT" clean -fdx
# Fetch only the specific tag
"$GIT" fetch --depth=1 origin tag "$VERSION"
# Checkout the fetched tag
"$GIT" checkout "$VERSION"
"$GIT" verify-tag "$VERSION"
"$GIT" verify-commit "${VERSION}^{commit}"
"$GIT" verify-commit HEAD
# Reset and clean each submodule
"$GIT" submodule foreach --recursive 'git reset --hard && git clean -fdx'
# Submodule operations
"$GIT" submodule sync --recursive
"$GIT" submodule update --init --recursive --jobs=200
# Double-check everything is clean
"$GIT" submodule foreach --recursive 'git reset --hard && git clean -fdx'
if [ ! "$($GIT status --porcelain)" = "" ]; then
echo "Error: Command git status --porcelain failed at the end!"
exit 9
fi
# verifies correct version is downloaded
GIT_VERSION="$($GIT describe --tags --abbrev=0)"
if [ "$GIT_VERSION" == "$VERSION" ]; then
"$GIT" describe
echo "Git version matches the desired version ($VERSION)."
else
"$GIT" describe
echo "Error: Git version does not match the desired version ($VERSION)."
exit 10
fi
}
function build() {
cd "${HOME}/${DM}" || repository_not_found
echo "Building gateway"
"${HOME}/${DM}/${DM}" --flavor "$FLAVOR_GATEWAY" --target "$TARGET" --arch "$ARCH" --tb "$TB" --repo "$REPO" --vmsize "$SIZE_GATEWAY"
echo "Building workstation"
"${HOME}/${DM}/${DM}" --flavor "$FLAVOR_WORKSTATION" --target "$TARGET" --arch "$ARCH" --tb "$TB" --repo "$REPO" --vmsize "$SIZE_WORKSTATION"
}
function pack() {
mkdir -p "${HOME}/${WB}"
cp -vr "${HOME}/${DB}/${VERSION_NUMBER}"/*.utm.tar.gz "${HOME}/${WB}"
echo "Build of $NAME version $VERSION is finished"
}
function main() {
beginning
update
install
repo_down
fetch_tag
build
pack
}
# Script execution starts here
echo "Starting $NAME build function"
cd "$HOME" || { echo "Error: Failed to change directory to $HOME"; exit 12; }
main 2>&1 | tee -a "${HOME}/${BL}"
# Copy the build log to the binary easy access folder and complete the script
mv "${HOME}/${BL}" "${HOME}/${WB}/" || { echo "Error: Failed to move build log"; exit 13; }
cd "$HOME" || { echo "Error: Failed to change directory to $HOME at script end"; exit 14; }
# Exit the script safely
safe_exit