Commit | Line | Data |
---|---|---|
6c01d562 MW |
1 | #!/bin/sh |
2 | # shellcheck shell=dash | |
3 | ||
4 | # This is just a little script that can be downloaded from the internet to | |
5 | # install rustup. It just does platform detection, downloads the installer | |
6 | # and runs it. | |
7 | ||
8 | # It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local` | |
9 | # extension. Note: Most shells limit `local` to 1 var per line, contra bash. | |
10 | ||
11 | if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then | |
12 | # The version of ksh93 that ships with many illumos systems does not | |
13 | # support the "local" extension. Print a message rather than fail in | |
14 | # subtle ways later on: | |
15 | echo 'rustup does not work with this ksh93 version; please try bash!' >&2 | |
16 | exit 1 | |
17 | fi | |
18 | ||
19 | ||
20 | set -u | |
21 | ||
22 | # If RUSTUP_UPDATE_ROOT is unset or empty, default it. | |
23 | RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}" | |
24 | ||
25 | #XXX: If you change anything here, please make the same changes in setup_mode.rs | |
26 | usage() { | |
27 | cat 1>&2 <<EOF | |
28 | rustup-init 1.25.2 (8c4dad73d 2023-02-01) | |
29 | The installer for rustup | |
30 | ||
31 | USAGE: | |
32 | rustup-init [FLAGS] [OPTIONS] | |
33 | ||
34 | FLAGS: | |
35 | -v, --verbose Enable verbose output | |
36 | -q, --quiet Disable progress output | |
37 | -y Disable confirmation prompt. | |
38 | --no-modify-path Don't configure the PATH environment variable | |
39 | -h, --help Prints help information | |
40 | -V, --version Prints version information | |
41 | ||
42 | OPTIONS: | |
43 | --default-host <default-host> Choose a default host triple | |
44 | --default-toolchain <default-toolchain> Choose a default toolchain to install | |
45 | --default-toolchain none Do not install any toolchains | |
46 | --profile [minimal|default|complete] Choose a profile | |
47 | -c, --component <components>... Component name to also install | |
48 | -t, --target <targets>... Target name to also install | |
49 | EOF | |
50 | } | |
51 | ||
52 | main() { | |
53 | downloader --check | |
54 | need_cmd uname | |
55 | need_cmd mktemp | |
56 | need_cmd chmod | |
57 | need_cmd mkdir | |
58 | need_cmd rm | |
59 | need_cmd rmdir | |
60 | ||
61 | get_architecture || return 1 | |
62 | local _arch="$RETVAL" | |
63 | assert_nz "$_arch" "arch" | |
64 | ||
65 | local _ext="" | |
66 | case "$_arch" in | |
67 | *windows*) | |
68 | _ext=".exe" | |
69 | ;; | |
70 | esac | |
71 | ||
72 | local _url="${RUSTUP_UPDATE_ROOT}/dist/${_arch}/rustup-init${_ext}" | |
73 | ||
74 | local _dir | |
75 | _dir="$(ensure mktemp -d)" | |
76 | local _file="${_dir}/rustup-init${_ext}" | |
77 | ||
78 | local _ansi_escapes_are_valid=false | |
79 | if [ -t 2 ]; then | |
80 | if [ "${TERM+set}" = 'set' ]; then | |
81 | case "$TERM" in | |
82 | xterm*|rxvt*|urxvt*|linux*|vt*) | |
83 | _ansi_escapes_are_valid=true | |
84 | ;; | |
85 | esac | |
86 | fi | |
87 | fi | |
88 | ||
89 | # check if we have to use /dev/tty to prompt the user | |
90 | local need_tty=yes | |
91 | for arg in "$@"; do | |
92 | case "$arg" in | |
93 | --help) | |
94 | usage | |
95 | exit 0 | |
96 | ;; | |
97 | *) | |
98 | OPTIND=1 | |
99 | if [ "${arg%%--*}" = "" ]; then | |
100 | # Long option (other than --help); | |
101 | # don't attempt to interpret it. | |
102 | continue | |
103 | fi | |
104 | while getopts :hy sub_arg "$arg"; do | |
105 | case "$sub_arg" in | |
106 | h) | |
107 | usage | |
108 | exit 0 | |
109 | ;; | |
110 | y) | |
111 | # user wants to skip the prompt -- | |
112 | # we don't need /dev/tty | |
113 | need_tty=no | |
114 | ;; | |
115 | *) | |
116 | ;; | |
117 | esac | |
118 | done | |
119 | ;; | |
120 | esac | |
121 | done | |
122 | ||
123 | if $_ansi_escapes_are_valid; then | |
124 | printf "\33[1minfo:\33[0m downloading installer\n" 1>&2 | |
125 | else | |
126 | printf '%s\n' 'info: downloading installer' 1>&2 | |
127 | fi | |
128 | ||
129 | ensure mkdir -p "$_dir" | |
130 | ensure downloader "$_url" "$_file" "$_arch" | |
131 | ensure chmod u+x "$_file" | |
132 | if [ ! -x "$_file" ]; then | |
133 | printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2 | |
134 | printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 1>&2 | |
135 | exit 1 | |
136 | fi | |
137 | ||
138 | if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then | |
139 | # The installer is going to want to ask for confirmation by | |
140 | # reading stdin. This script was piped into `sh` though and | |
141 | # doesn't have stdin to pass to its children. Instead we're going | |
142 | # to explicitly connect /dev/tty to the installer's stdin. | |
143 | if [ ! -t 1 ]; then | |
144 | err "Unable to run interactively. Run with -y to accept defaults, --help for additional options" | |
145 | fi | |
146 | ||
147 | ignore "$_file" "$@" < /dev/tty | |
148 | else | |
149 | ignore "$_file" "$@" | |
150 | fi | |
151 | ||
152 | local _retval=$? | |
153 | ||
154 | ignore rm "$_file" | |
155 | ignore rmdir "$_dir" | |
156 | ||
157 | return "$_retval" | |
158 | } | |
159 | ||
160 | check_proc() { | |
161 | # Check for /proc by looking for the /proc/self/exe link | |
162 | # This is only run on Linux | |
163 | if ! test -L /proc/self/exe ; then | |
164 | err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc." | |
165 | fi | |
166 | } | |
167 | ||
168 | get_bitness() { | |
169 | need_cmd head | |
170 | # Architecture detection without dependencies beyond coreutils. | |
171 | # ELF files start out "\x7fELF", and the following byte is | |
172 | # 0x01 for 32-bit and | |
173 | # 0x02 for 64-bit. | |
174 | # The printf builtin on some shells like dash only supports octal | |
175 | # escape sequences, so we use those. | |
176 | local _current_exe_head | |
177 | _current_exe_head=$(head -c 5 /proc/self/exe ) | |
178 | if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then | |
179 | echo 32 | |
180 | elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then | |
181 | echo 64 | |
182 | else | |
183 | err "unknown platform bitness" | |
184 | fi | |
185 | } | |
186 | ||
187 | is_host_amd64_elf() { | |
188 | need_cmd head | |
189 | need_cmd tail | |
190 | # ELF e_machine detection without dependencies beyond coreutils. | |
191 | # Two-byte field at offset 0x12 indicates the CPU, | |
192 | # but we're interested in it being 0x3E to indicate amd64, or not that. | |
193 | local _current_exe_machine | |
194 | _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1) | |
195 | [ "$_current_exe_machine" = "$(printf '\076')" ] | |
196 | } | |
197 | ||
198 | get_endianness() { | |
199 | local cputype=$1 | |
200 | local suffix_eb=$2 | |
201 | local suffix_el=$3 | |
202 | ||
203 | # detect endianness without od/hexdump, like get_bitness() does. | |
204 | need_cmd head | |
205 | need_cmd tail | |
206 | ||
207 | local _current_exe_endianness | |
208 | _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)" | |
209 | if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then | |
210 | echo "${cputype}${suffix_el}" | |
211 | elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then | |
212 | echo "${cputype}${suffix_eb}" | |
213 | else | |
214 | err "unknown platform endianness" | |
215 | fi | |
216 | } | |
217 | ||
218 | get_architecture() { | |
219 | local _ostype _cputype _bitness _arch _clibtype | |
220 | _ostype="$(uname -s)" | |
221 | _cputype="$(uname -m)" | |
222 | _clibtype="gnu" | |
223 | ||
224 | if [ "$_ostype" = Linux ]; then | |
225 | if [ "$(uname -o)" = Android ]; then | |
226 | _ostype=Android | |
227 | fi | |
228 | if ldd --version 2>&1 | grep -q 'musl'; then | |
229 | _clibtype="musl" | |
230 | fi | |
231 | fi | |
232 | ||
233 | if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then | |
234 | # Darwin `uname -m` lies | |
235 | if sysctl hw.optional.x86_64 | grep -q ': 1'; then | |
236 | _cputype=x86_64 | |
237 | fi | |
238 | fi | |
239 | ||
240 | if [ "$_ostype" = SunOS ]; then | |
241 | # Both Solaris and illumos presently announce as "SunOS" in "uname -s" | |
242 | # so use "uname -o" to disambiguate. We use the full path to the | |
243 | # system uname in case the user has coreutils uname first in PATH, | |
244 | # which has historically sometimes printed the wrong value here. | |
245 | if [ "$(/usr/bin/uname -o)" = illumos ]; then | |
246 | _ostype=illumos | |
247 | fi | |
248 | ||
249 | # illumos systems have multi-arch userlands, and "uname -m" reports the | |
250 | # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86 | |
251 | # systems. Check for the native (widest) instruction set on the | |
252 | # running kernel: | |
253 | if [ "$_cputype" = i86pc ]; then | |
254 | _cputype="$(isainfo -n)" | |
255 | fi | |
256 | fi | |
257 | ||
258 | case "$_ostype" in | |
259 | ||
260 | Android) | |
261 | _ostype=linux-android | |
262 | ;; | |
263 | ||
264 | Linux) | |
265 | check_proc | |
266 | _ostype=unknown-linux-$_clibtype | |
267 | _bitness=$(get_bitness) | |
268 | ;; | |
269 | ||
270 | FreeBSD) | |
271 | _ostype=unknown-freebsd | |
272 | ;; | |
273 | ||
274 | NetBSD) | |
275 | _ostype=unknown-netbsd | |
276 | ;; | |
277 | ||
278 | DragonFly) | |
279 | _ostype=unknown-dragonfly | |
280 | ;; | |
281 | ||
282 | Darwin) | |
283 | _ostype=apple-darwin | |
284 | ;; | |
285 | ||
286 | illumos) | |
287 | _ostype=unknown-illumos | |
288 | ;; | |
289 | ||
290 | MINGW* | MSYS* | CYGWIN* | Windows_NT) | |
291 | _ostype=pc-windows-gnu | |
292 | ;; | |
293 | ||
294 | *) | |
295 | err "unrecognized OS type: $_ostype" | |
296 | ;; | |
297 | ||
298 | esac | |
299 | ||
300 | case "$_cputype" in | |
301 | ||
302 | i386 | i486 | i686 | i786 | x86) | |
303 | _cputype=i686 | |
304 | ;; | |
305 | ||
306 | xscale | arm) | |
307 | _cputype=arm | |
308 | if [ "$_ostype" = "linux-android" ]; then | |
309 | _ostype=linux-androideabi | |
310 | fi | |
311 | ;; | |
312 | ||
313 | armv6l) | |
314 | _cputype=arm | |
315 | if [ "$_ostype" = "linux-android" ]; then | |
316 | _ostype=linux-androideabi | |
317 | else | |
318 | _ostype="${_ostype}eabihf" | |
319 | fi | |
320 | ;; | |
321 | ||
322 | armv7l | armv8l) | |
323 | _cputype=armv7 | |
324 | if [ "$_ostype" = "linux-android" ]; then | |
325 | _ostype=linux-androideabi | |
326 | else | |
327 | _ostype="${_ostype}eabihf" | |
328 | fi | |
329 | ;; | |
330 | ||
331 | aarch64 | arm64) | |
332 | _cputype=aarch64 | |
333 | ;; | |
334 | ||
335 | x86_64 | x86-64 | x64 | amd64) | |
336 | _cputype=x86_64 | |
337 | ;; | |
338 | ||
339 | mips) | |
340 | _cputype=$(get_endianness mips '' el) | |
341 | ;; | |
342 | ||
343 | mips64) | |
344 | if [ "$_bitness" -eq 64 ]; then | |
345 | # only n64 ABI is supported for now | |
346 | _ostype="${_ostype}abi64" | |
347 | _cputype=$(get_endianness mips64 '' el) | |
348 | fi | |
349 | ;; | |
350 | ||
351 | ppc) | |
352 | _cputype=powerpc | |
353 | ;; | |
354 | ||
355 | ppc64) | |
356 | _cputype=powerpc64 | |
357 | ;; | |
358 | ||
359 | ppc64le) | |
360 | _cputype=powerpc64le | |
361 | ;; | |
362 | ||
363 | s390x) | |
364 | _cputype=s390x | |
365 | ;; | |
366 | riscv64) | |
367 | _cputype=riscv64gc | |
368 | ;; | |
369 | *) | |
370 | err "unknown CPU type: $_cputype" | |
371 | ||
372 | esac | |
373 | ||
374 | # Detect 64-bit linux with 32-bit userland | |
375 | if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then | |
376 | case $_cputype in | |
377 | x86_64) | |
378 | if [ -n "${RUSTUP_CPUTYPE:-}" ]; then | |
379 | _cputype="$RUSTUP_CPUTYPE" | |
380 | else { | |
381 | # 32-bit executable for amd64 = x32 | |
382 | if is_host_amd64_elf; then { | |
383 | echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2 | |
384 | echo "and there isn't a native toolchain -- you will have to install" 1>&2 | |
385 | echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2 | |
386 | echo "by re-running this script with the RUSTUP_CPUTYPE environment variable" 1>&2 | |
387 | echo "set to i686 or x86_64, respectively." 1>&2 | |
388 | echo 1>&2 | |
389 | echo "You will be able to add an x32 target after installation by running" 1>&2 | |
390 | echo " rustup target add x86_64-unknown-linux-gnux32" 1>&2 | |
391 | exit 1 | |
392 | }; else | |
393 | _cputype=i686 | |
394 | fi | |
395 | }; fi | |
396 | ;; | |
397 | mips64) | |
398 | _cputype=$(get_endianness mips '' el) | |
399 | ;; | |
400 | powerpc64) | |
401 | _cputype=powerpc | |
402 | ;; | |
403 | aarch64) | |
404 | _cputype=armv7 | |
405 | if [ "$_ostype" = "linux-android" ]; then | |
406 | _ostype=linux-androideabi | |
407 | else | |
408 | _ostype="${_ostype}eabihf" | |
409 | fi | |
410 | ;; | |
411 | riscv64gc) | |
412 | err "riscv64 with 32-bit userland unsupported" | |
413 | ;; | |
414 | esac | |
415 | fi | |
416 | ||
417 | # Detect armv7 but without the CPU features Rust needs in that build, | |
418 | # and fall back to arm. | |
419 | # See https://github.com/rust-lang/rustup.rs/issues/587. | |
420 | if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then | |
421 | if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then | |
422 | # At least one processor does not have NEON. | |
423 | _cputype=arm | |
424 | fi | |
425 | fi | |
426 | ||
427 | _arch="${_cputype}-${_ostype}" | |
428 | ||
429 | RETVAL="$_arch" | |
430 | } | |
431 | ||
432 | say() { | |
433 | printf 'rustup: %s\n' "$1" | |
434 | } | |
435 | ||
436 | err() { | |
437 | say "$1" >&2 | |
438 | exit 1 | |
439 | } | |
440 | ||
441 | need_cmd() { | |
442 | if ! check_cmd "$1"; then | |
443 | err "need '$1' (command not found)" | |
444 | fi | |
445 | } | |
446 | ||
447 | check_cmd() { | |
448 | command -v "$1" > /dev/null 2>&1 | |
449 | } | |
450 | ||
451 | assert_nz() { | |
452 | if [ -z "$1" ]; then err "assert_nz $2"; fi | |
453 | } | |
454 | ||
455 | # Run a command that should never fail. If the command fails execution | |
456 | # will immediately terminate with an error showing the failing | |
457 | # command. | |
458 | ensure() { | |
459 | if ! "$@"; then err "command failed: $*"; fi | |
460 | } | |
461 | ||
462 | # This is just for indicating that commands' results are being | |
463 | # intentionally ignored. Usually, because it's being executed | |
464 | # as part of error handling. | |
465 | ignore() { | |
466 | "$@" | |
467 | } | |
468 | ||
469 | # This wraps curl or wget. Try curl first, if not installed, | |
470 | # use wget instead. | |
471 | downloader() { | |
472 | local _dld | |
473 | local _ciphersuites | |
474 | local _err | |
475 | local _status | |
476 | local _retry | |
477 | if check_cmd curl; then | |
478 | _dld=curl | |
479 | elif check_cmd wget; then | |
480 | _dld=wget | |
481 | else | |
482 | _dld='curl or wget' # to be used in error message of need_cmd | |
483 | fi | |
484 | ||
485 | if [ "$1" = --check ]; then | |
486 | need_cmd "$_dld" | |
487 | elif [ "$_dld" = curl ]; then | |
488 | check_curl_for_retry_support | |
489 | _retry="$RETVAL" | |
490 | get_ciphersuites_for_curl | |
491 | _ciphersuites="$RETVAL" | |
492 | if [ -n "$_ciphersuites" ]; then | |
493 | _err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1) | |
494 | _status=$? | |
495 | else | |
496 | echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure" | |
497 | if ! check_help_for "$3" curl --proto --tlsv1.2; then | |
498 | echo "Warning: Not enforcing TLS v1.2, this is potentially less secure" | |
499 | _err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1) | |
500 | _status=$? | |
501 | else | |
502 | _err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1) | |
503 | _status=$? | |
504 | fi | |
505 | fi | |
506 | if [ -n "$_err" ]; then | |
507 | echo "$_err" >&2 | |
508 | if echo "$_err" | grep -q 404$; then | |
509 | err "installer for platform '$3' not found, this may be unsupported" | |
510 | fi | |
511 | fi | |
512 | return $_status | |
513 | elif [ "$_dld" = wget ]; then | |
514 | if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then | |
515 | echo "Warning: using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure" | |
516 | _err=$(wget "$1" -O "$2" 2>&1) | |
517 | _status=$? | |
518 | else | |
519 | get_ciphersuites_for_wget | |
520 | _ciphersuites="$RETVAL" | |
521 | if [ -n "$_ciphersuites" ]; then | |
522 | _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1) | |
523 | _status=$? | |
524 | else | |
525 | echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure" | |
526 | if ! check_help_for "$3" wget --https-only --secure-protocol; then | |
527 | echo "Warning: Not enforcing TLS v1.2, this is potentially less secure" | |
528 | _err=$(wget "$1" -O "$2" 2>&1) | |
529 | _status=$? | |
530 | else | |
531 | _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1) | |
532 | _status=$? | |
533 | fi | |
534 | fi | |
535 | fi | |
536 | if [ -n "$_err" ]; then | |
537 | echo "$_err" >&2 | |
538 | if echo "$_err" | grep -q ' 404 Not Found$'; then | |
539 | err "installer for platform '$3' not found, this may be unsupported" | |
540 | fi | |
541 | fi | |
542 | return $_status | |
543 | else | |
544 | err "Unknown downloader" # should not reach here | |
545 | fi | |
546 | } | |
547 | ||
548 | check_help_for() { | |
549 | local _arch | |
550 | local _cmd | |
551 | local _arg | |
552 | _arch="$1" | |
553 | shift | |
554 | _cmd="$1" | |
555 | shift | |
556 | ||
557 | local _category | |
558 | if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then | |
559 | _category="all" | |
560 | else | |
561 | _category="" | |
562 | fi | |
563 | ||
564 | case "$_arch" in | |
565 | ||
566 | *darwin*) | |
567 | if check_cmd sw_vers; then | |
568 | case $(sw_vers -productVersion) in | |
569 | 10.*) | |
570 | # If we're running on macOS, older than 10.13, then we always | |
571 | # fail to find these options to force fallback | |
572 | if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then | |
573 | # Older than 10.13 | |
574 | echo "Warning: Detected macOS platform older than 10.13" | |
575 | return 1 | |
576 | fi | |
577 | ;; | |
578 | 11.*) | |
579 | # We assume Big Sur will be OK for now | |
580 | ;; | |
581 | *) | |
582 | # Unknown product version, warn and continue | |
583 | echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)" | |
584 | echo "Warning TLS capabilities detection may fail" | |
585 | ;; | |
586 | esac | |
587 | fi | |
588 | ;; | |
589 | ||
590 | esac | |
591 | ||
592 | for _arg in "$@"; do | |
593 | if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then | |
594 | return 1 | |
595 | fi | |
596 | done | |
597 | ||
598 | true # not strictly needed | |
599 | } | |
600 | ||
601 | # Check if curl supports the --retry flag, then pass it to the curl invocation. | |
602 | check_curl_for_retry_support() { | |
603 | local _retry_supported="" | |
604 | # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. | |
605 | if check_help_for "notspecified" "curl" "--retry"; then | |
606 | _retry_supported="--retry 3" | |
607 | fi | |
608 | ||
609 | RETVAL="$_retry_supported" | |
610 | ||
611 | } | |
612 | ||
613 | # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites | |
614 | # if support by local tools is detected. Detection currently supports these curl backends: | |
615 | # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty. | |
616 | get_ciphersuites_for_curl() { | |
617 | if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then | |
618 | # user specified custom cipher suites, assume they know what they're doing | |
619 | RETVAL="$RUSTUP_TLS_CIPHERSUITES" | |
620 | return | |
621 | fi | |
622 | ||
623 | local _openssl_syntax="no" | |
624 | local _gnutls_syntax="no" | |
625 | local _backend_supported="yes" | |
626 | if curl -V | grep -q ' OpenSSL/'; then | |
627 | _openssl_syntax="yes" | |
628 | elif curl -V | grep -iq ' LibreSSL/'; then | |
629 | _openssl_syntax="yes" | |
630 | elif curl -V | grep -iq ' BoringSSL/'; then | |
631 | _openssl_syntax="yes" | |
632 | elif curl -V | grep -iq ' GnuTLS/'; then | |
633 | _gnutls_syntax="yes" | |
634 | else | |
635 | _backend_supported="no" | |
636 | fi | |
637 | ||
638 | local _args_supported="no" | |
639 | if [ "$_backend_supported" = "yes" ]; then | |
640 | # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. | |
641 | if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then | |
642 | _args_supported="yes" | |
643 | fi | |
644 | fi | |
645 | ||
646 | local _cs="" | |
647 | if [ "$_args_supported" = "yes" ]; then | |
648 | if [ "$_openssl_syntax" = "yes" ]; then | |
649 | _cs=$(get_strong_ciphersuites_for "openssl") | |
650 | elif [ "$_gnutls_syntax" = "yes" ]; then | |
651 | _cs=$(get_strong_ciphersuites_for "gnutls") | |
652 | fi | |
653 | fi | |
654 | ||
655 | RETVAL="$_cs" | |
656 | } | |
657 | ||
658 | # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites | |
659 | # if support by local tools is detected. Detection currently supports these wget backends: | |
660 | # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty. | |
661 | get_ciphersuites_for_wget() { | |
662 | if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then | |
663 | # user specified custom cipher suites, assume they know what they're doing | |
664 | RETVAL="$RUSTUP_TLS_CIPHERSUITES" | |
665 | return | |
666 | fi | |
667 | ||
668 | local _cs="" | |
669 | if wget -V | grep -q '\-DHAVE_LIBSSL'; then | |
670 | # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. | |
671 | if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then | |
672 | _cs=$(get_strong_ciphersuites_for "openssl") | |
673 | fi | |
674 | elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then | |
675 | # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. | |
676 | if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then | |
677 | _cs=$(get_strong_ciphersuites_for "gnutls") | |
678 | fi | |
679 | fi | |
680 | ||
681 | RETVAL="$_cs" | |
682 | } | |
683 | ||
684 | # Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2 | |
685 | # excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad | |
686 | # DH params often found on servers (see RFC 7919). Sequence matches or is | |
687 | # similar to Firefox 68 ESR with weak cipher suites disabled via about:config. | |
688 | # $1 must be openssl or gnutls. | |
689 | get_strong_ciphersuites_for() { | |
690 | if [ "$1" = "openssl" ]; then | |
691 | # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet. | |
692 | 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" | |
693 | elif [ "$1" = "gnutls" ]; then | |
694 | # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't. | |
695 | # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order. | |
696 | 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" | |
697 | fi | |
698 | } | |
699 | ||
700 | main "$@" || exit 1 |