11
11
# #
12
12
set -u
13
13
14
- # Functions useful for dealing with the manifest (which is JSON).
15
-
16
- # Get the version of a tag from the manifest JSON file.
17
- # Arguments:
18
- # $1 - The tag to get.
19
- # STDIN - The manifest file.
20
- # Returns:
21
- # 0 if the tag was found, 1 if it wasn't.
22
- # Prints out the version number.
23
- get_tag_from_manifest_json () {
24
- # Find the tag in the file. Then get the last digits.
25
- # The first grep returns `"tag_name": "1.2.3` (without the last quote).
26
- cat \
27
- | tr -d ' \n' \
28
- | grep -o " \" $1 \" :[[:space:]]*\" [a-zA-Z0-9.]*" \
29
- | grep -o " [0-9.]*$"
30
- }
31
-
32
14
# A newline separated list of boolean flags. See the read_flags function to see how it's parsed.
33
15
DFX_BOOL_FLAGS=" "
34
16
@@ -111,7 +93,6 @@ err() {
111
93
say " $1 " >&2
112
94
exit 1
113
95
}
114
- # # 110_assert.sh
115
96
116
97
need_cmd () {
117
98
if ! check_cmd " $1 " ; then
@@ -144,61 +125,81 @@ ignore() {
144
125
define_flag_BOOL " insecure" " Allows downloading from insecure URLs, either using HTTP or TLS 1.2 or less."
145
126
146
127
check_help_for () {
128
+ local _arch
147
129
local _cmd
148
130
local _arg
149
- local _ok
131
+ _arch=" $1 "
132
+ shift
150
133
_cmd=" $1 "
151
- _ok=" y"
152
134
shift
153
135
154
- # If we're running on OS-X, older than 10.13, then we always
155
- # fail to find these options to force fallback
156
- if check_cmd sw_vers; then
157
- case " $( sw_vers -productVersion) " in
158
- 10.15* ) ;; # Catalina
159
- 11.* ) ;; # Big Sur
160
- 12.* ) ;; # Monterey
161
- 13.* ) ;; # Ventura
162
- * )
163
- warn " Detected OS X platform older than 10.15 (Catalina)"
164
- _ok=" n"
165
- ;;
166
- esac
136
+ local _category
137
+ if " $_cmd " --help | grep -q ' For all options use the manual or "--help all".' ; then
138
+ _category=" all"
139
+ else
140
+ _category=" "
167
141
fi
168
142
143
+ case " $_arch " in
144
+
145
+ * darwin* )
146
+ if check_cmd sw_vers; then
147
+ case $( sw_vers -productVersion) in
148
+ 10.* )
149
+ # If we're running on macOS, older than 10.13, then we always
150
+ # fail to find these options to force fallback
151
+ if [ " $( sw_vers -productVersion | cut -d. -f2) " -lt 13 ]; then
152
+ # Older than 10.13
153
+ echo " Warning: Detected macOS platform older than 10.13"
154
+ return 1
155
+ fi
156
+ ;;
157
+
158
+ # We assume these will be OK for now
159
+ 11.* ) ;; # Big Sur
160
+ 12.* ) ;; # Monterey
161
+ 13.* ) ;; # Ventura
162
+ 14.* ) ;; # Sonoma
163
+
164
+ * )
165
+ # Unknown product version, warn and continue
166
+ echo " Warning: Detected unknown macOS major version: $( sw_vers -productVersion) "
167
+ echo " Warning TLS capabilities detection may fail"
168
+ ;;
169
+ esac
170
+ fi
171
+ ;;
172
+
173
+ esac
174
+
169
175
for _arg in " $@ " ; do
170
- if ! " $_cmd " --help all | grep -q -- " $_arg " ; then
171
- _ok= " n "
176
+ if ! " $_cmd " --help " $_category " | grep -q -- " $_arg " ; then
177
+ return 1
172
178
fi
173
179
done
174
180
175
- test " $_ok " = " y "
181
+ true # not strictly needed
176
182
}
177
183
178
- # Check for an error message in the output of a command.
179
- # Arguments:
180
- # $1 - The error message to look for.
181
- # $2... - The command and arguments to run.
182
- # Returns:
183
- # Whether false if the error message was not found, or true if it wasn't (so the feature is
184
- # supported.
185
- # TODO: move this logic to execute once during install.sh run.
186
- check_support_for () {
187
- local err=" $1 "
188
- shift
189
- local cmd=" $* "
190
-
191
- # Run the command, grep for the error message, if it is found returns false, if it
192
- # is not found, returns true.
193
- ! ($cmd 2>&1 | grep " $err " > /dev/null)
184
+ is_zsh () {
185
+ [ -n " ${ZSH_VERSION-} " ]
194
186
}
195
187
196
- # This wraps curl or wget. Try curl first, if not installed, use wget instead.
188
+ # This wraps curl or wget. Try curl first, if not installed,
189
+ # use wget instead.
197
190
# Arguments:
198
191
# $1 - URL to download.
199
192
# $2 - Path to output the download. Use - to output to stdout.
193
+ # $3 - The architecture, used to determine TLS capabilities.
200
194
downloader () {
195
+ # zsh does not split words by default, Required for curl retry arguments below.
196
+ is_zsh && setopt local_options shwordsplit
197
+
201
198
local _dld
199
+ local _ciphersuites
200
+ local _err
201
+ local _status
202
+ local _retry
202
203
if check_cmd curl; then
203
204
_dld=curl
204
205
elif check_cmd wget; then
@@ -210,28 +211,171 @@ downloader() {
210
211
if [ " $1 " = --check ]; then
211
212
need_cmd " $_dld "
212
213
elif [ " $_dld " = curl ]; then
213
- if check_help_for curl --proto --tlsv1.2; then
214
- curl --proto ' =https' --tlsv1.2 --show-error --fail --connect-timeout 10 --retry 5 --location " $1 " --output " $2 " --progress-bar
215
- elif ! [ " $flag_INSECURE " ]; then
216
- warn " Not forcing TLS v1.2, this is potentially less secure"
217
- curl --show-error --fail --connect-timeout 10 --retry 5 --location " $1 " --output " $2 " --progress-bar
214
+ check_curl_for_retry_support
215
+ _retry=" $RETVAL "
216
+ get_ciphersuites_for_curl
217
+ _ciphersuites=" $RETVAL "
218
+ if [ -n " $_ciphersuites " ]; then
219
+ # shellcheck disable=SC2086 # $retry is intentionally split
220
+ _err=$( curl $_retry --proto ' =https' --tlsv1.2 --ciphers " $_ciphersuites " --silent --show-error --fail --location " $1 " --output " $2 " 2>&1 )
221
+ _status=$?
218
222
else
219
- err " TLS 1.2 is not supported on this platform. To force using it, use the --insecure flag."
223
+ echo " Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
224
+ if ! check_help_for " $3 " curl --proto --tlsv1.2; then
225
+ echo " Warning: Not enforcing TLS v1.2, this is potentially less secure"
226
+ # shellcheck disable=SC2086 # $retry is intentionally split
227
+ _err=$( curl $_retry --silent --show-error --fail --location " $1 " --output " $2 " 2>&1 )
228
+ _status=$?
229
+ else
230
+ # shellcheck disable=SC2086 # $retry is intentionally split
231
+ _err=$( curl $_retry --proto ' =https' --tlsv1.2 --silent --show-error --fail --location " $1 " --output " $2 " 2>&1 )
232
+ _status=$?
233
+ fi
220
234
fi
235
+ if [ -n " $_err " ]; then
236
+ echo " $_err " >&2
237
+ if echo " $_err " | grep -q 404$; then
238
+ err " installer for platform '$3 ' not found, this may be unsupported"
239
+ fi
240
+ fi
241
+ return $_status
221
242
elif [ " $_dld " = wget ]; then
222
- if check_help_for wget --https-only --secure-protocol; then
223
- wget --https-only --secure-protocol=TLSv1_2 --timeout 10 --tries 5 --waitretry 5 " $1 " -O " $2 "
224
- elif ! [ " $flag_INSECURE " ]; then
225
- warn " Not forcing TLS v1.2, this is potentially less secure"
226
- wget --timeout 10 --tries 5 --waitretry 5 " $1 " -O " $2 "
243
+ if [ " $( wget -V 2>&1 | head -2 | tail -1 | cut -f1 -d" " ) " = " BusyBox" ]; then
244
+ echo " Warning: using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure"
245
+ _err=$( wget " $1 " -O " $2 " 2>&1 )
246
+ _status=$?
227
247
else
228
- err " TLS 1.2 is not supported on this platform. To force using it, use the --insecure flag."
248
+ get_ciphersuites_for_wget
249
+ _ciphersuites=" $RETVAL "
250
+ if [ -n " $_ciphersuites " ]; then
251
+ _err=$( wget --https-only --secure-protocol=TLSv1_2 --ciphers " $_ciphersuites " " $1 " -O " $2 " 2>&1 )
252
+ _status=$?
253
+ else
254
+ echo " Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
255
+ if ! check_help_for " $3 " wget --https-only --secure-protocol; then
256
+ echo " Warning: Not enforcing TLS v1.2, this is potentially less secure"
257
+ _err=$( wget " $1 " -O " $2 " 2>&1 )
258
+ _status=$?
259
+ else
260
+ _err=$( wget --https-only --secure-protocol=TLSv1_2 " $1 " -O " $2 " 2>&1 )
261
+ _status=$?
262
+ fi
263
+ fi
229
264
fi
265
+ if [ -n " $_err " ]; then
266
+ echo " $_err " >&2
267
+ if echo " $_err " | grep -q ' 404 Not Found$' ; then
268
+ err " installer for platform '$3 ' not found, this may be unsupported"
269
+ fi
270
+ fi
271
+ return $_status
230
272
else
231
273
err " Unknown downloader" # should not reach here
232
274
fi
233
275
}
234
276
277
+ # Check if curl supports the --retry flag, then pass it to the curl invocation.
278
+ check_curl_for_retry_support () {
279
+ local _retry_supported=" "
280
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
281
+ if check_help_for " notspecified" " curl" " --retry" ; then
282
+ _retry_supported=" --retry 3"
283
+ if check_help_for " notspecified" " curl" " --continue-at" ; then
284
+ # "-C -" tells curl to automatically find where to resume the download when retrying.
285
+ _retry_supported=" --retry 3 -C -"
286
+ fi
287
+ fi
288
+
289
+ RETVAL=" $_retry_supported "
290
+ }
291
+
292
+ # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
293
+ # if support by local tools is detected. Detection currently supports these curl backends:
294
+ # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
295
+ get_ciphersuites_for_curl () {
296
+ if [ -n " ${RUSTUP_TLS_CIPHERSUITES-} " ]; then
297
+ # user specified custom cipher suites, assume they know what they're doing
298
+ RETVAL=" $RUSTUP_TLS_CIPHERSUITES "
299
+ return
300
+ fi
301
+
302
+ local _openssl_syntax=" no"
303
+ local _gnutls_syntax=" no"
304
+ local _backend_supported=" yes"
305
+ if curl -V | grep -q ' OpenSSL/' ; then
306
+ _openssl_syntax=" yes"
307
+ elif curl -V | grep -iq ' LibreSSL/' ; then
308
+ _openssl_syntax=" yes"
309
+ elif curl -V | grep -iq ' BoringSSL/' ; then
310
+ _openssl_syntax=" yes"
311
+ elif curl -V | grep -iq ' GnuTLS/' ; then
312
+ _gnutls_syntax=" yes"
313
+ else
314
+ _backend_supported=" no"
315
+ fi
316
+
317
+ local _args_supported=" no"
318
+ if [ " $_backend_supported " = " yes" ]; then
319
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
320
+ if check_help_for " notspecified" " curl" " --tlsv1.2" " --ciphers" " --proto" ; then
321
+ _args_supported=" yes"
322
+ fi
323
+ fi
324
+
325
+ local _cs=" "
326
+ if [ " $_args_supported " = " yes" ]; then
327
+ if [ " $_openssl_syntax " = " yes" ]; then
328
+ _cs=$( get_strong_ciphersuites_for " openssl" )
329
+ elif [ " $_gnutls_syntax " = " yes" ]; then
330
+ _cs=$( get_strong_ciphersuites_for " gnutls" )
331
+ fi
332
+ fi
333
+
334
+ RETVAL=" $_cs "
335
+ }
336
+
337
+ # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
338
+ # if support by local tools is detected. Detection currently supports these wget backends:
339
+ # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
340
+ get_ciphersuites_for_wget () {
341
+ if [ -n " ${RUSTUP_TLS_CIPHERSUITES-} " ]; then
342
+ # user specified custom cipher suites, assume they know what they're doing
343
+ RETVAL=" $RUSTUP_TLS_CIPHERSUITES "
344
+ return
345
+ fi
346
+
347
+ local _cs=" "
348
+ if wget -V | grep -q ' \-DHAVE_LIBSSL' ; then
349
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
350
+ if check_help_for " notspecified" " wget" " TLSv1_2" " --ciphers" " --https-only" " --secure-protocol" ; then
351
+ _cs=$( get_strong_ciphersuites_for " openssl" )
352
+ fi
353
+ elif wget -V | grep -q ' \-DHAVE_LIBGNUTLS' ; then
354
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
355
+ if check_help_for " notspecified" " wget" " TLSv1_2" " --ciphers" " --https-only" " --secure-protocol" ; then
356
+ _cs=$( get_strong_ciphersuites_for " gnutls" )
357
+ fi
358
+ fi
359
+
360
+ RETVAL=" $_cs "
361
+ }
362
+
363
+ # Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
364
+ # excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
365
+ # DH params often found on servers (see RFC 7919). Sequence matches or is
366
+ # similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
367
+ # $1 must be openssl or gnutls.
368
+ get_strong_ciphersuites_for () {
369
+ if [ " $1 " = " openssl" ]; then
370
+ # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
371
+ echo " TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
372
+ elif [ " $1 " = " gnutls" ]; then
373
+ # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
374
+ # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
375
+ echo " SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
376
+ fi
377
+ }
378
+
235
379
DFXVM_GITHUB_LATEST_RELEASE_ROOT=" ${DFXVM_GITHUB_LATEST_RELEASE_ROOT:- https:// github.com/ dfinity/ dfxvm/ releases/ latest/ download} "
236
380
DFX_VERSION=" ${DFX_VERSION-} "
237
381
@@ -252,14 +396,13 @@ download_and_install() {
252
396
local _sha256_url=" ${_tarball_url} .sha256"
253
397
254
398
log " Downloading latest release..."
255
- ensure downloader " $_tarball_url " " ${_tarball_filename} "
256
- ensure downloader " $_sha256_url " " ${_sha256_filename} "
399
+ ensure downloader " $_tarball_url " " ${_tarball_filename} " " $_arch "
400
+ ensure downloader " $_sha256_url " " ${_sha256_filename} " " $_arch "
257
401
258
402
log " Checking integrity of tarball..."
259
403
ensure " $SHASUM " -c " ${_sha256_filename} "
260
404
261
- ensure tar -xzf " ${_tarball_filename} "
262
- ensure cd " ${_archive} " > /dev/null
405
+ ensure tar -xzf " ${_tarball_filename} " --strip-components=1 " ${_archive} /dfxvm"
263
406
ensure chmod u+x dfxvm
264
407
ensure mv dfxvm dfxvm-init
265
408
@@ -320,7 +463,9 @@ main() {
320
463
)
321
464
local _subshell_exit_code=$?
322
465
323
- ignore rm -rf " ${_dir} "
466
+ ignore rm " ${_dir} " /dfxvm*
467
+ ignore rmdir " ${_dir} "
468
+
324
469
exit $_subshell_exit_code
325
470
}
326
471
0 commit comments