/ rustup.sh
rustup.sh
1 #!/bin/sh 2 # shellcheck shell=dash 3 # shellcheck disable=SC2039 # local is non-POSIX 4 5 # This is just a little script that can be downloaded from the internet to 6 # install rustup. It just does platform detection, downloads the installer 7 # and runs it. 8 9 # It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local` 10 # extension. Note: Most shells limit `local` to 1 var per line, contra bash. 11 12 # Some versions of ksh have no `local` keyword. Alias it to `typeset`, but 13 # beware this makes variables global with f()-style function syntax in ksh93. 14 # mksh has this alias by default. 15 has_local() { 16 # shellcheck disable=SC2034 # deliberately unused 17 local _has_local 18 } 19 20 has_local 2>/dev/null || alias local=typeset 21 22 is_zsh() { 23 [ -n "${ZSH_VERSION-}" ] 24 } 25 26 set -u 27 28 # If RUSTUP_UPDATE_ROOT is unset or empty, default it. 29 RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}" 30 # Set quiet as a global for ease of use 31 RUSTUP_QUIET=no 32 33 # NOTICE: If you change anything here, please make the same changes in setup_mode.rs 34 usage() { 35 cat <<EOF 36 rustup-init 1.28.2 (d1f31992a 2025-04-28) 37 38 The installer for rustup 39 40 Usage: rustup-init[EXE] [OPTIONS] 41 42 Options: 43 -v, --verbose 44 Set log level to 'DEBUG' if 'RUSTUP_LOG' is unset 45 -q, --quiet 46 Disable progress output, set log level to 'WARN' if 'RUSTUP_LOG' is unset 47 -y 48 Disable confirmation prompt 49 --default-host <DEFAULT_HOST> 50 Choose a default host triple 51 --default-toolchain <DEFAULT_TOOLCHAIN> 52 Choose a default toolchain to install. Use 'none' to not install any toolchains at all 53 --profile <PROFILE> 54 [default: default] [possible values: minimal, default, complete] 55 -c, --component <COMPONENT> 56 Comma-separated list of component names to also install 57 -t, --target <TARGET> 58 Comma-separated list of target names to also install 59 --no-update-default-toolchain 60 Don't update any existing default toolchain after install 61 --no-modify-path 62 Don't configure the PATH environment variable 63 -h, --help 64 Print help 65 -V, --version 66 Print version 67 EOF 68 } 69 70 main() { 71 downloader --check 72 need_cmd uname 73 need_cmd mktemp 74 need_cmd chmod 75 need_cmd mkdir 76 need_cmd rm 77 need_cmd rmdir 78 79 get_architecture || return 1 80 local _arch="$RETVAL" 81 assert_nz "$_arch" "arch" 82 83 local _ext="" 84 case "$_arch" in 85 *windows*) 86 _ext=".exe" 87 ;; 88 esac 89 90 local _url 91 if [ "${RUSTUP_VERSION+set}" = 'set' ]; then 92 say "\`RUSTUP_VERSION\` has been set to \`${RUSTUP_VERSION}\`" 93 _url="${RUSTUP_UPDATE_ROOT}/archive/${RUSTUP_VERSION}" 94 else 95 _url="${RUSTUP_UPDATE_ROOT}/dist" 96 fi 97 _url="${_url}/${_arch}/rustup-init${_ext}" 98 99 100 local _dir 101 if ! _dir="$(ensure mktemp -d)"; then 102 # Because the previous command ran in a subshell, we must manually 103 # propagate exit status. 104 exit 1 105 fi 106 local _file="${_dir}/rustup-init${_ext}" 107 108 local _ansi_escapes_are_valid=false 109 if [ -t 2 ]; then 110 if [ "${TERM+set}" = 'set' ]; then 111 case "$TERM" in 112 xterm*|rxvt*|urxvt*|linux*|vt*) 113 _ansi_escapes_are_valid=true 114 ;; 115 esac 116 fi 117 fi 118 119 # check if we have to use /dev/tty to prompt the user 120 local need_tty=yes 121 for arg in "$@"; do 122 case "$arg" in 123 --help) 124 usage 125 exit 0 126 ;; 127 --quiet) 128 RUSTUP_QUIET=yes 129 ;; 130 *) 131 OPTIND=1 132 if [ "${arg%%--*}" = "" ]; then 133 # Long option (other than --help); 134 # don't attempt to interpret it. 135 continue 136 fi 137 while getopts :hqy sub_arg "$arg"; do 138 case "$sub_arg" in 139 h) 140 usage 141 exit 0 142 ;; 143 q) 144 RUSTUP_QUIET=yes 145 ;; 146 y) 147 # user wants to skip the prompt -- 148 # we don't need /dev/tty 149 need_tty=no 150 ;; 151 *) 152 ;; 153 esac 154 done 155 ;; 156 esac 157 done 158 159 say 'downloading installer' 160 161 ensure mkdir -p "$_dir" 162 ensure downloader "$_url" "$_file" "$_arch" 163 ensure chmod u+x "$_file" 164 if [ ! -x "$_file" ]; then 165 err "Cannot execute $_file (likely because of mounting /tmp as noexec)." 166 err "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 167 exit 1 168 fi 169 170 if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then 171 # The installer is going to want to ask for confirmation by 172 # reading stdin. This script was piped into `sh` though and 173 # doesn't have stdin to pass to its children. Instead we're going 174 # to explicitly connect /dev/tty to the installer's stdin. 175 if [ ! -t 1 ]; then 176 err "Unable to run interactively. Run with -y to accept defaults, --help for additional options" 177 exit 1; 178 fi 179 180 ignore "$_file" "$@" < /dev/tty 181 else 182 ignore "$_file" "$@" 183 fi 184 185 local _retval=$? 186 187 ignore rm "$_file" 188 ignore rmdir "$_dir" 189 190 return "$_retval" 191 } 192 193 get_current_exe() { 194 # Returns the executable used for system architecture detection 195 # This is only run on Linux 196 local _current_exe 197 if test -L /proc/self/exe ; then 198 _current_exe=/proc/self/exe 199 else 200 warn "Unable to find /proc/self/exe. System architecture detection might be inaccurate." 201 if test -n "$SHELL" ; then 202 _current_exe=$SHELL 203 else 204 need_cmd /bin/sh 205 _current_exe=/bin/sh 206 fi 207 warn "Falling back to $_current_exe." 208 fi 209 echo "$_current_exe" 210 } 211 212 get_bitness() { 213 need_cmd head 214 # Architecture detection without dependencies beyond coreutils. 215 # ELF files start out "\x7fELF", and the following byte is 216 # 0x01 for 32-bit and 217 # 0x02 for 64-bit. 218 # The printf builtin on some shells like dash only supports octal 219 # escape sequences, so we use those. 220 local _current_exe=$1 221 local _current_exe_head 222 _current_exe_head=$(head -c 5 "$_current_exe") 223 if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then 224 echo 32 225 elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then 226 echo 64 227 else 228 err "unknown platform bitness" 229 exit 1; 230 fi 231 } 232 233 is_host_amd64_elf() { 234 local _current_exe=$1 235 236 need_cmd head 237 need_cmd tail 238 # ELF e_machine detection without dependencies beyond coreutils. 239 # Two-byte field at offset 0x12 indicates the CPU, 240 # but we're interested in it being 0x3E to indicate amd64, or not that. 241 local _current_exe_machine 242 _current_exe_machine=$(head -c 19 "$_current_exe" | tail -c 1) 243 [ "$_current_exe_machine" = "$(printf '\076')" ] 244 } 245 246 get_endianness() { 247 local _current_exe=$1 248 local cputype=$2 249 local suffix_eb=$3 250 local suffix_el=$4 251 252 # detect endianness without od/hexdump, like get_bitness() does. 253 need_cmd head 254 need_cmd tail 255 256 local _current_exe_endianness 257 _current_exe_endianness="$(head -c 6 "$_current_exe" | tail -c 1)" 258 if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then 259 echo "${cputype}${suffix_el}" 260 elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then 261 echo "${cputype}${suffix_eb}" 262 else 263 err "unknown platform endianness" 264 exit 1 265 fi 266 } 267 268 # Detect the Linux/LoongArch UAPI flavor, with all errors being non-fatal. 269 # Returns 0 or 234 in case of successful detection, 1 otherwise (/tmp being 270 # noexec, or other causes). 271 check_loongarch_uapi() { 272 need_cmd base64 273 274 local _tmp 275 if ! _tmp="$(ensure mktemp)"; then 276 return 1 277 fi 278 279 # Minimal Linux/LoongArch UAPI detection, exiting with 0 in case of 280 # upstream ("new world") UAPI, and 234 (-EINVAL truncated) in case of 281 # old-world (as deployed on several early commercial Linux distributions 282 # for LoongArch). 283 # 284 # See https://gist.github.com/xen0n/5ee04aaa6cecc5c7794b9a0c3b65fc7f for 285 # source to this helper binary. 286 ignore base64 -d > "$_tmp" <<EOF 287 f0VMRgIBAQAAAAAAAAAAAAIAAgEBAAAAeAAgAAAAAABAAAAAAAAAAAAAAAAAAAAAQQAAAEAAOAAB 288 AAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAJAAAAAAAAAAkAAAAAAAAAAAA 289 AQAAAAAABCiAAwUAFQAGABUAByCAAwsYggMAACsAC3iBAwAAKwAxen0n 290 EOF 291 292 ignore chmod u+x "$_tmp" 293 if [ ! -x "$_tmp" ]; then 294 ignore rm "$_tmp" 295 return 1 296 fi 297 298 "$_tmp" 299 local _retval=$? 300 301 ignore rm "$_tmp" 302 return "$_retval" 303 } 304 305 ensure_loongarch_uapi() { 306 check_loongarch_uapi 307 case $? in 308 0) 309 return 0 310 ;; 311 234) 312 err 'Your Linux kernel does not provide the ABI required by this Rust distribution.' 313 err 'Please check with your OS provider for how to obtain a compatible Rust package for your system.' 314 exit 1 315 ;; 316 *) 317 warn "Cannot determine current system's ABI flavor, continuing anyway." 318 warn 'Note that the official Rust distribution only works with the upstream kernel ABI.' 319 warn 'Installation will fail if your running kernel happens to be incompatible.' 320 ;; 321 esac 322 } 323 324 get_architecture() { 325 local _ostype _cputype _bitness _arch _clibtype 326 _ostype="$(uname -s)" 327 _cputype="$(uname -m)" 328 _clibtype="gnu" 329 330 if [ "$_ostype" = Linux ]; then 331 if [ "$(uname -o)" = Android ]; then 332 _ostype=Android 333 fi 334 if ldd --version 2>&1 | grep -q 'musl'; then 335 _clibtype="musl" 336 fi 337 fi 338 339 if [ "$_ostype" = Darwin ]; then 340 # Darwin `uname -m` can lie due to Rosetta shenanigans. If you manage to 341 # invoke a native shell binary and then a native uname binary, you can 342 # get the real answer, but that's hard to ensure, so instead we use 343 # `sysctl` (which doesn't lie) to check for the actual architecture. 344 if [ "$_cputype" = i386 ]; then 345 # Handling i386 compatibility mode in older macOS versions (<10.15) 346 # running on x86_64-based Macs. 347 # Starting from 10.15, macOS explicitly bans all i386 binaries from running. 348 # See: <https://support.apple.com/en-us/HT208436> 349 350 # Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code. 351 if sysctl hw.optional.x86_64 2> /dev/null || true | grep -q ': 1'; then 352 _cputype=x86_64 353 fi 354 elif [ "$_cputype" = x86_64 ]; then 355 # Handling x86-64 compatibility mode (a.k.a. Rosetta 2) 356 # in newer macOS versions (>=11) running on arm64-based Macs. 357 # Rosetta 2 is built exclusively for x86-64 and cannot run i386 binaries. 358 359 # Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code. 360 if sysctl hw.optional.arm64 2> /dev/null || true | grep -q ': 1'; then 361 _cputype=arm64 362 fi 363 fi 364 fi 365 366 if [ "$_ostype" = SunOS ]; then 367 # Both Solaris and illumos presently announce as "SunOS" in "uname -s" 368 # so use "uname -o" to disambiguate. We use the full path to the 369 # system uname in case the user has coreutils uname first in PATH, 370 # which has historically sometimes printed the wrong value here. 371 if [ "$(/usr/bin/uname -o)" = illumos ]; then 372 _ostype=illumos 373 fi 374 375 # illumos systems have multi-arch userlands, and "uname -m" reports the 376 # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86 377 # systems. Check for the native (widest) instruction set on the 378 # running kernel: 379 if [ "$_cputype" = i86pc ]; then 380 _cputype="$(isainfo -n)" 381 fi 382 fi 383 384 local _current_exe 385 case "$_ostype" in 386 387 Android) 388 _ostype=linux-android 389 ;; 390 391 Linux) 392 _current_exe=$(get_current_exe) 393 _ostype=unknown-linux-$_clibtype 394 _bitness=$(get_bitness "$_current_exe") 395 ;; 396 397 FreeBSD) 398 _ostype=unknown-freebsd 399 ;; 400 401 NetBSD) 402 _ostype=unknown-netbsd 403 ;; 404 405 DragonFly) 406 _ostype=unknown-dragonfly 407 ;; 408 409 Darwin) 410 _ostype=apple-darwin 411 ;; 412 413 illumos) 414 _ostype=unknown-illumos 415 ;; 416 417 MINGW* | MSYS* | CYGWIN* | Windows_NT) 418 _ostype=pc-windows-gnu 419 ;; 420 421 *) 422 err "unrecognized OS type: $_ostype" 423 exit 1 424 ;; 425 426 esac 427 428 case "$_cputype" in 429 430 i386 | i486 | i686 | i786 | x86) 431 _cputype=i686 432 ;; 433 434 xscale | arm) 435 _cputype=arm 436 if [ "$_ostype" = "linux-android" ]; then 437 _ostype=linux-androideabi 438 fi 439 ;; 440 441 armv6l) 442 _cputype=arm 443 if [ "$_ostype" = "linux-android" ]; then 444 _ostype=linux-androideabi 445 else 446 _ostype="${_ostype}eabihf" 447 fi 448 ;; 449 450 armv7l | armv8l) 451 _cputype=armv7 452 if [ "$_ostype" = "linux-android" ]; then 453 _ostype=linux-androideabi 454 else 455 _ostype="${_ostype}eabihf" 456 fi 457 ;; 458 459 aarch64 | arm64) 460 _cputype=aarch64 461 ;; 462 463 x86_64 | x86-64 | x64 | amd64) 464 _cputype=x86_64 465 ;; 466 467 mips) 468 _cputype=$(get_endianness "$_current_exe" mips '' el) 469 ;; 470 471 mips64) 472 if [ "$_bitness" -eq 64 ]; then 473 # only n64 ABI is supported for now 474 _ostype="${_ostype}abi64" 475 _cputype=$(get_endianness "$_current_exe" mips64 '' el) 476 fi 477 ;; 478 479 ppc) 480 _cputype=powerpc 481 ;; 482 483 ppc64) 484 _cputype=powerpc64 485 ;; 486 487 ppc64le) 488 _cputype=powerpc64le 489 ;; 490 491 s390x) 492 _cputype=s390x 493 ;; 494 riscv64) 495 _cputype=riscv64gc 496 ;; 497 loongarch64) 498 _cputype=loongarch64 499 ensure_loongarch_uapi 500 ;; 501 *) 502 err "unknown CPU type: $_cputype" 503 exit 1 504 505 esac 506 507 # Detect 64-bit linux with 32-bit userland 508 if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then 509 case $_cputype in 510 x86_64) 511 if [ -n "${RUSTUP_CPUTYPE:-}" ]; then 512 _cputype="$RUSTUP_CPUTYPE" 513 else { 514 # 32-bit executable for amd64 = x32 515 if is_host_amd64_elf "$_current_exe"; then { 516 err "This host is running an x32 userland, for which no native toolchain is provided." 517 err "You will have to install multiarch compatibility with i686 or amd64." 518 err "To do so, set the RUSTUP_CPUTYPE environment variable set to i686 or amd64 and re-run this script." 519 err "You will be able to add an x32 target after installation by running \`rustup target add x86_64-unknown-linux-gnux32\`." 520 exit 1 521 }; else 522 _cputype=i686 523 fi 524 }; fi 525 ;; 526 mips64) 527 _cputype=$(get_endianness "$_current_exe" mips '' el) 528 ;; 529 powerpc64) 530 _cputype=powerpc 531 ;; 532 aarch64) 533 _cputype=armv7 534 if [ "$_ostype" = "linux-android" ]; then 535 _ostype=linux-androideabi 536 else 537 _ostype="${_ostype}eabihf" 538 fi 539 ;; 540 riscv64gc) 541 err "riscv64 with 32-bit userland unsupported" 542 exit 1 543 ;; 544 esac 545 fi 546 547 # Detect armv7 but without the CPU features Rust needs in that build, 548 # and fall back to arm. 549 # See https://github.com/rust-lang/rustup.rs/issues/587. 550 if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then 551 if ! (ensure grep '^Features' /proc/cpuinfo | grep -E -q 'neon|simd') ; then 552 # Either `/proc/cpuinfo` is malformed or unavailable, or 553 # at least one processor does not have NEON (which is asimd on armv8+). 554 _cputype=arm 555 fi 556 fi 557 558 _arch="${_cputype}-${_ostype}" 559 560 RETVAL="$_arch" 561 } 562 563 __print() { 564 if $_ansi_escapes_are_valid; then 565 printf '\33[1m%s:\33[0m %s\n' "$1" "$2" >&2 566 else 567 printf '%s: %s\n' "$1" "$2" >&2 568 fi 569 } 570 571 warn() { 572 __print 'warn' "$1" >&2 573 } 574 575 say() { 576 if [ "$RUSTUP_QUIET" = "no" ]; then 577 __print 'info' "$1" >&2 578 fi 579 } 580 581 # NOTE: you are required to exit yourself 582 # we don't do it here because of multiline errors 583 err() { 584 __print 'error' "$1" >&2 585 } 586 587 need_cmd() { 588 if ! check_cmd "$1"; then 589 err "need '$1' (command not found)" 590 exit 1 591 fi 592 } 593 594 check_cmd() { 595 command -v "$1" > /dev/null 2>&1 596 } 597 598 assert_nz() { 599 if [ -z "$1" ]; then 600 err "assert_nz $2" 601 exit 1 602 fi 603 } 604 605 # Run a command that should never fail. If the command fails execution 606 # will immediately terminate with an error showing the failing 607 # command. 608 ensure() { 609 if ! "$@"; then 610 err "command failed: $*" 611 exit 1 612 fi 613 } 614 615 # This is just for indicating that commands' results are being 616 # intentionally ignored. Usually, because it's being executed 617 # as part of error handling. 618 ignore() { 619 "$@" 620 } 621 622 # This wraps curl or wget. Try curl first, if not installed, 623 # use wget instead. 624 downloader() { 625 # zsh does not split words by default, Required for curl retry arguments below. 626 is_zsh && setopt local_options shwordsplit 627 628 local _dld 629 local _ciphersuites 630 local _err 631 local _status 632 local _retry 633 if check_cmd curl; then 634 _dld=curl 635 elif check_cmd wget; then 636 _dld=wget 637 else 638 _dld='curl or wget' # to be used in error message of need_cmd 639 fi 640 641 if [ "$1" = --check ]; then 642 need_cmd "$_dld" 643 elif [ "$_dld" = curl ]; then 644 check_curl_for_retry_support 645 _retry="$RETVAL" 646 get_ciphersuites_for_curl 647 _ciphersuites="$RETVAL" 648 if [ -n "$_ciphersuites" ]; then 649 # shellcheck disable=SC2086 650 _err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1) 651 _status=$? 652 else 653 warn "Not enforcing strong cipher suites for TLS, this is potentially less secure" 654 if ! check_help_for "$3" curl --proto --tlsv1.2; then 655 warn "Not enforcing TLS v1.2, this is potentially less secure" 656 # shellcheck disable=SC2086 657 _err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1) 658 _status=$? 659 else 660 # shellcheck disable=SC2086 661 _err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1) 662 _status=$? 663 fi 664 fi 665 if [ -n "$_err" ]; then 666 warn "$_err" 667 if echo "$_err" | grep -q 404$; then 668 err "installer for platform '$3' not found, this may be unsupported" 669 exit 1 670 fi 671 fi 672 return $_status 673 elif [ "$_dld" = wget ]; then 674 if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then 675 warn "using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure" 676 _err=$(wget "$1" -O "$2" 2>&1) 677 _status=$? 678 else 679 get_ciphersuites_for_wget 680 _ciphersuites="$RETVAL" 681 if [ -n "$_ciphersuites" ]; then 682 _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1) 683 _status=$? 684 else 685 warn "Not enforcing strong cipher suites for TLS, this is potentially less secure" 686 if ! check_help_for "$3" wget --https-only --secure-protocol; then 687 warn "Not enforcing TLS v1.2, this is potentially less secure" 688 _err=$(wget "$1" -O "$2" 2>&1) 689 _status=$? 690 else 691 _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1) 692 _status=$? 693 fi 694 fi 695 fi 696 if [ -n "$_err" ]; then 697 warn "$_err" 698 if echo "$_err" | grep -q ' 404 Not Found$'; then 699 err "installer for platform '$3' not found, this may be unsupported" 700 exit 1 701 fi 702 fi 703 return $_status 704 else 705 err "Unknown downloader" # should not reach here 706 exit 1 707 fi 708 } 709 710 check_help_for() { 711 local _arch 712 local _cmd 713 local _arg 714 _arch="$1" 715 shift 716 _cmd="$1" 717 shift 718 719 local _category 720 if "$_cmd" --help | grep -q '"--help all"'; then 721 _category="all" 722 else 723 _category="" 724 fi 725 726 case "$_arch" in 727 728 *darwin*) 729 if check_cmd sw_vers; then 730 local _os_version 731 local _os_major 732 _os_version=$(sw_vers -productVersion) 733 _os_major=$(echo "$_os_version" | cut -d. -f1) 734 case $_os_major in 735 10) 736 # If we're running on macOS, older than 10.13, then we always 737 # fail to find these options to force fallback 738 if [ "$(echo "$_os_version" | cut -d. -f2)" -lt 13 ]; then 739 # Older than 10.13 740 warn "Detected macOS platform older than 10.13" 741 return 1 742 fi 743 ;; 744 *) 745 if ! { [ "$_os_major" -eq "$_os_major" ] 2>/dev/null && [ "$_os_major" -ge 11 ]; }; then 746 # Unknown product version, warn and continue 747 warn "Detected unknown macOS major version: $_os_version" 748 warn "TLS capabilities detection may fail" 749 fi 750 ;; # We assume that macOS v11+ will always be okay. 751 esac 752 fi 753 ;; 754 755 esac 756 757 for _arg in "$@"; do 758 if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then 759 return 1 760 fi 761 done 762 763 true # not strictly needed 764 } 765 766 # Check if curl supports the --retry flag, then pass it to the curl invocation. 767 check_curl_for_retry_support() { 768 local _retry_supported="" 769 # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. 770 if check_help_for "notspecified" "curl" "--retry"; then 771 _retry_supported="--retry 3" 772 if check_help_for "notspecified" "curl" "--continue-at"; then 773 # "-C -" tells curl to automatically find where to resume the download when retrying. 774 _retry_supported="--retry 3 -C -" 775 fi 776 fi 777 778 RETVAL="$_retry_supported" 779 } 780 781 # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites 782 # if support by local tools is detected. Detection currently supports these curl backends: 783 # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty. 784 get_ciphersuites_for_curl() { 785 if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then 786 # user specified custom cipher suites, assume they know what they're doing 787 RETVAL="$RUSTUP_TLS_CIPHERSUITES" 788 return 789 fi 790 791 local _openssl_syntax="no" 792 local _gnutls_syntax="no" 793 local _backend_supported="yes" 794 if curl -V | grep -q ' OpenSSL/'; then 795 _openssl_syntax="yes" 796 elif curl -V | grep -iq ' LibreSSL/'; then 797 _openssl_syntax="yes" 798 elif curl -V | grep -iq ' BoringSSL/'; then 799 _openssl_syntax="yes" 800 elif curl -V | grep -iq ' GnuTLS/'; then 801 _gnutls_syntax="yes" 802 else 803 _backend_supported="no" 804 fi 805 806 local _args_supported="no" 807 if [ "$_backend_supported" = "yes" ]; then 808 # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. 809 if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then 810 _args_supported="yes" 811 fi 812 fi 813 814 local _cs="" 815 if [ "$_args_supported" = "yes" ]; then 816 if [ "$_openssl_syntax" = "yes" ]; then 817 _cs=$(get_strong_ciphersuites_for "openssl") 818 elif [ "$_gnutls_syntax" = "yes" ]; then 819 _cs=$(get_strong_ciphersuites_for "gnutls") 820 fi 821 fi 822 823 RETVAL="$_cs" 824 } 825 826 # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites 827 # if support by local tools is detected. Detection currently supports these wget backends: 828 # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty. 829 get_ciphersuites_for_wget() { 830 if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then 831 # user specified custom cipher suites, assume they know what they're doing 832 RETVAL="$RUSTUP_TLS_CIPHERSUITES" 833 return 834 fi 835 836 local _cs="" 837 if wget -V | grep -q '\-DHAVE_LIBSSL'; then 838 # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. 839 if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then 840 _cs=$(get_strong_ciphersuites_for "openssl") 841 fi 842 elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then 843 # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc. 844 if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then 845 _cs=$(get_strong_ciphersuites_for "gnutls") 846 fi 847 fi 848 849 RETVAL="$_cs" 850 } 851 852 # Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2 853 # excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad 854 # DH params often found on servers (see RFC 7919). Sequence matches or is 855 # similar to Firefox 68 ESR with weak cipher suites disabled via about:config. 856 # $1 must be openssl or gnutls. 857 get_strong_ciphersuites_for() { 858 if [ "$1" = "openssl" ]; then 859 # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet. 860 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" 861 elif [ "$1" = "gnutls" ]; then 862 # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't. 863 # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order. 864 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" 865 fi 866 } 867 868 set +u 869 case "$RUSTUP_INIT_SH_PRINT" in 870 arch | architecture) 871 get_architecture || exit 1 872 echo "$RETVAL" 873 ;; 874 *) 875 main "$@" || exit 1 876 ;; 877 esac