mirror of
https://github.com/dockur/windows.git
synced 2025-10-27 03:15:49 +00:00
feat: Improved installation (#545)
This commit is contained in:
parent
a96941c63e
commit
fd83861e7d
9 changed files with 1437 additions and 271 deletions
185
src/mido.sh
185
src/mido.sh
|
|
@ -6,12 +6,18 @@ handle_curl_error() {
|
|||
local error_code="$1"
|
||||
|
||||
case "$error_code" in
|
||||
1) error "Unsupported protocol!" ;;
|
||||
2) error "Failed to initialize curl!" ;;
|
||||
3) error "The URL format is malformed!" ;;
|
||||
5) error "Failed to resolve address of proxy host!" ;;
|
||||
6) error "Failed to resolve Microsoft servers! Is there an Internet connection?" ;;
|
||||
7) error "Failed to contact Microsoft servers! Is there an Internet connection or is the server down?" ;;
|
||||
8) error "Microsoft servers returned a malformed HTTP response!" ;;
|
||||
16) error "A problem was detected in the HTTP2 framing layer!" ;;
|
||||
22) error "Microsoft servers returned a failing HTTP status code!" ;;
|
||||
23) error "Failed at writing Windows media to disk! Out of disk space or permission error?" ;;
|
||||
26) error "Ran out of memory during download!" ;;
|
||||
26) error "Failed to read Windows media from disk!" ;;
|
||||
27) error "Ran out of memory during download!" ;;
|
||||
28) error "Connection timed out to Microsoft server!" ;;
|
||||
35) error "SSL connection error from Microsoft server!" ;;
|
||||
36) error "Failed to continue earlier download!" ;;
|
||||
|
|
@ -32,22 +38,34 @@ handle_curl_error() {
|
|||
# https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
|
||||
INT) error "Curl was interrupted!" ;;
|
||||
# There could be other signals but these are most common
|
||||
SEGV | ABRT ) error "Curl crashed! Failed exploitation attempt? Please report any core dumps to curl developers." ;;
|
||||
*) error "Curl terminated due to a fatal signal!" ;;
|
||||
SEGV | ABRT ) error "Curl crashed! Please report any core dumps to curl developers." ;;
|
||||
*) error "Curl terminated due to fatal signal $error_code !" ;;
|
||||
esac
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
get_agent() {
|
||||
|
||||
local user_agent
|
||||
|
||||
# Determine approximate latest Firefox release
|
||||
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
|
||||
echo "Mozilla/5.0 (X11; Linux x86_64; rv:${browser_version}.0) Gecko/20100101 Firefox/${browser_version}.0"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
download_windows() {
|
||||
|
||||
local id="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
local sku_id=""
|
||||
local language=""
|
||||
local session_id=""
|
||||
local browser_version=""
|
||||
local user_agent=""
|
||||
local windows_version=""
|
||||
local iso_download_link=""
|
||||
local product_edition_id=""
|
||||
|
|
@ -56,12 +74,13 @@ download_windows() {
|
|||
local language_skuid_table_html=""
|
||||
|
||||
case "${id,,}" in
|
||||
"win11${PLATFORM,,}" ) windows_version="11" ;;
|
||||
"win10${PLATFORM,,}" ) windows_version="10" ;;
|
||||
"win81${PLATFORM,,}" ) windows_version="8" ;;
|
||||
"win11x64" ) windows_version="11" ;;
|
||||
"win10x64" ) windows_version="10" ;;
|
||||
"win81x64" ) windows_version="8" ;;
|
||||
* ) error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
||||
esac
|
||||
|
||||
user_agent=$(get_agent)
|
||||
language=$(getLanguage "$lang" "name")
|
||||
|
||||
local url="https://www.microsoft.com/en-us/software-download/windows$windows_version"
|
||||
|
|
@ -69,12 +88,8 @@ download_windows() {
|
|||
8 | 10) url="${url}ISO";;
|
||||
esac
|
||||
|
||||
# Determine approximate latest Firefox release
|
||||
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
|
||||
local user_agent="Mozilla/5.0 (X11; Linux x86_64; rv:${browser_version}.0) Gecko/20100101 Firefox/${browser_version}.0"
|
||||
|
||||
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
|
||||
session_id="$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)"
|
||||
session_id=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)
|
||||
|
||||
# Get product edition ID for latest release of given Windows version
|
||||
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
|
||||
|
|
@ -82,7 +97,7 @@ download_windows() {
|
|||
# Also, keeping a "$WindowsVersions" array like Fido does would be way too much of a maintenance burden
|
||||
# Remove "Accept" header that curl sends by default
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo " - Parsing download page: ${url}"
|
||||
iso_download_page_html="$(curl --silent --max-time 30 --user-agent "$user_agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url")" || {
|
||||
iso_download_page_html=$(curl --silent --max-time 30 --user-agent "$user_agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
||||
handle_curl_error $?
|
||||
return $?
|
||||
}
|
||||
|
|
@ -90,7 +105,7 @@ download_windows() {
|
|||
[[ "$DEBUG" == [Yy1]* ]] && echo -n "Getting Product edition ID: "
|
||||
# tr: Filter for only numerics to prevent HTTP parameter injection
|
||||
# head -c was recently added to POSIX: https://austingroupbugs.net/view.php?id=407
|
||||
product_edition_id="$(echo "$iso_download_page_html" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)"
|
||||
product_edition_id=$(echo "$iso_download_page_html" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "$product_edition_id"
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Permit Session ID: $session_id"
|
||||
|
|
@ -110,17 +125,17 @@ download_windows() {
|
|||
# SKU ID: This specifies the language of the ISO. We always use "English (United States)", however, the SKU for this changes with each Windows release
|
||||
# We must make this request so our next one will be allowed
|
||||
# --data "" is required otherwise no "Content-Length" header will be sent causing HTTP response "411 Length Required"
|
||||
language_skuid_table_html="$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --header "Accept:" --max-filesize 10K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=getskuinformationbyproductedition&sessionId=$session_id&productEditionId=$product_edition_id&sdVersion=2")" || {
|
||||
language_skuid_table_html=$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --header "Accept:" --max-filesize 10K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=getskuinformationbyproductedition&sessionId=$session_id&productEditionId=$product_edition_id&sdVersion=2") || {
|
||||
handle_curl_error $?
|
||||
return $?
|
||||
}
|
||||
|
||||
# tr: Filter for only alphanumerics or "-" to prevent HTTP parameter injection
|
||||
sku_id="$(echo "$language_skuid_table_html" | grep -m 1 ">${language}<" | sed 's/"//g' | cut -d ',' -f 1 | cut -d ':' -f 2 | tr -cd '[:alnum:]-' | head -c 16)"
|
||||
sku_id=$(echo "$language_skuid_table_html" | grep -m 1 ">${language}<" | sed 's/"//g' | cut -d ',' -f 1 | cut -d ':' -f 2 | tr -cd '[:alnum:]-' | head -c 16)
|
||||
|
||||
if [ -z "$sku_id" ]; then
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download for the $language language available!"
|
||||
error "No download in the $language language available for $desc!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
@ -130,7 +145,7 @@ download_windows() {
|
|||
# Get ISO download link
|
||||
# If any request is going to be blocked by Microsoft it's always this last one (the previous requests always seem to succeed)
|
||||
# --referer: Required by Microsoft servers to allow request
|
||||
iso_download_link_html="$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=6e2a1789-ef16-4f27-a296-74ef7ef5d96b&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=GetProductDownloadLinksBySku&sessionId=$session_id&skuId=$sku_id&language=English&sdVersion=2")"
|
||||
iso_download_link_html=$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=6e2a1789-ef16-4f27-a296-74ef7ef5d96b&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=GetProductDownloadLinksBySku&sessionId=$session_id&skuId=$sku_id&language=English&sdVersion=2")
|
||||
|
||||
if ! [ "$iso_download_link_html" ]; then
|
||||
# This should only happen if there's been some change to how this API works
|
||||
|
|
@ -146,7 +161,7 @@ download_windows() {
|
|||
# Filter for 64-bit ISO download URL
|
||||
# sed: HTML decode "&" character
|
||||
# tr: Filter for only alphanumerics or punctuation
|
||||
iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&/\&/g' | tr -cd '[:alnum:][:punct:]')"
|
||||
iso_download_link=$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&/\&/g' | tr -cd '[:alnum:][:punct:]')
|
||||
|
||||
if ! [ "$iso_download_link" ]; then
|
||||
# This should only happen if there's been some change to the download endpoint web address
|
||||
|
|
@ -162,37 +177,47 @@ download_windows_eval() {
|
|||
|
||||
local id="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
local filter=""
|
||||
local culture=""
|
||||
local language=""
|
||||
local windows_version=""
|
||||
local user_agent=""
|
||||
local enterprise_type=""
|
||||
local windows_version=""
|
||||
|
||||
case "${id,,}" in
|
||||
"win11${PLATFORM,,}-enterprise-eval" )
|
||||
windows_version="windows-11-enterprise"
|
||||
enterprise_type="enterprise" ;;
|
||||
enterprise_type="enterprise"
|
||||
windows_version="windows-11-enterprise" ;;
|
||||
"win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||
enterprise_type="iot"
|
||||
windows_version="windows-11-iot-enterprise-ltsc" ;;
|
||||
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
enterprise_type="iot"
|
||||
windows_version="windows-11-iot-enterprise-ltsc" ;;
|
||||
"win10${PLATFORM,,}-enterprise-eval" )
|
||||
windows_version="windows-10-enterprise"
|
||||
enterprise_type="enterprise" ;;
|
||||
enterprise_type="enterprise"
|
||||
windows_version="windows-10-enterprise" ;;
|
||||
"win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
windows_version="windows-10-enterprise"
|
||||
enterprise_type="ltsc" ;;
|
||||
enterprise_type="ltsc"
|
||||
windows_version="windows-10-enterprise" ;;
|
||||
"win2022-eval" )
|
||||
windows_version="windows-server-2022"
|
||||
enterprise_type="server" ;;
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2022" ;;
|
||||
"win2019-eval" )
|
||||
windows_version="windows-server-2019"
|
||||
enterprise_type="server" ;;
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2019" ;;
|
||||
"win2016-eval" )
|
||||
windows_version="windows-server-2016"
|
||||
enterprise_type="server" ;;
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2016" ;;
|
||||
"win2012r2-eval" )
|
||||
windows_version="windows-server-2012-r2"
|
||||
enterprise_type="server" ;;
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2012-r2" ;;
|
||||
* )
|
||||
error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
||||
esac
|
||||
|
||||
user_agent=$(get_agent)
|
||||
culture=$(getLanguage "$lang" "culture")
|
||||
|
||||
local country="${culture#*-}"
|
||||
|
|
@ -200,7 +225,7 @@ download_windows_eval() {
|
|||
local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version"
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${url}"
|
||||
iso_download_page_html="$(curl --silent --max-time 30 --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url")" || {
|
||||
iso_download_page_html=$(curl --silent --max-time 30 --user-agent "$user_agent" --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
||||
handle_curl_error $?
|
||||
return $?
|
||||
}
|
||||
|
|
@ -212,32 +237,52 @@ download_windows_eval() {
|
|||
fi
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Getting download link.."
|
||||
iso_download_links="$(echo "$iso_download_page_html" | grep -o "https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}")" || {
|
||||
|
||||
if [[ "$enterprise_type" == "iot" ]]; then
|
||||
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
|
||||
else
|
||||
filter="https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
|
||||
fi
|
||||
|
||||
iso_download_links=$(echo "$iso_download_page_html" | grep -io "$filter") || {
|
||||
# This should only happen if there's been some change to the download endpoint web address
|
||||
if [[ "${lang,,}" == "en" ]] || [[ "${lang,,}" == "en-"* ]]; then
|
||||
error "Windows server download page gave us no download link!"
|
||||
else
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download for the $language language available!"
|
||||
error "No download in the $language language available for $desc!"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Limit untrusted size for input validation
|
||||
iso_download_links="$(echo "$iso_download_links" | head -c 1024)"
|
||||
|
||||
case "$enterprise_type" in
|
||||
# Select x64 download link
|
||||
"enterprise") iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1) ;;
|
||||
# Select x64 LTSC download link
|
||||
"ltsc") iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1) ;;
|
||||
*) iso_download_link="$iso_download_links" ;;
|
||||
"enterprise" )
|
||||
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1)
|
||||
;;
|
||||
"iot" )
|
||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||
iso_download_link=$(echo "$iso_download_links" | head -n 1)
|
||||
fi
|
||||
if [[ "${PLATFORM,,}" == "arm64" ]]; then
|
||||
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1)
|
||||
fi
|
||||
;;
|
||||
"ltsc" )
|
||||
iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1)
|
||||
;;
|
||||
"server" )
|
||||
iso_download_link=$(echo "$iso_download_links" | head -n 1)
|
||||
;;
|
||||
* )
|
||||
error "Invalid type specified, value \"$enterprise_type\" is not recognized!" && return 1 ;;
|
||||
esac
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Found download link: $iso_download_link"
|
||||
|
||||
# Follow redirect so proceeding log message is useful
|
||||
# This is a request we make this Fido doesn't
|
||||
# We don't need to set "--max-filesize" here because this is a HEAD request and the output is to /dev/null anyway
|
||||
iso_download_link="$(curl --silent --max-time 30 --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link")" || {
|
||||
iso_download_link=$(curl --silent --max-time 30 --user-agent "$user_agent" --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link") || {
|
||||
# This should only happen if the Microsoft servers are down
|
||||
handle_curl_error $?
|
||||
return $?
|
||||
|
|
@ -252,37 +297,46 @@ getWindows() {
|
|||
local version="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
local language
|
||||
|
||||
local language edition
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
edition=$(printEdition "$version" "$desc")
|
||||
|
||||
local msg="Requesting $desc from Microsoft server..."
|
||||
info "$msg" && html "$msg"
|
||||
|
||||
case "${version,,}" in
|
||||
"win2008r2" | "win81${PLATFORM,,}-enterprise-eval" | "win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
|
||||
error "No download in the $language language available for $edition!"
|
||||
MIDO_URL="" && return 1
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
case "${version,,}" in
|
||||
"win11${PLATFORM,,}-enterprise-iot-eval" ) ;;
|
||||
* )
|
||||
if [[ "${PLATFORM,,}" != "x64" ]]; then
|
||||
error "No download for the ${PLATFORM^^} platform available for $edition!"
|
||||
MIDO_URL="" && return 1
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
case "${version,,}" in
|
||||
"win81${PLATFORM,,}" | "win10${PLATFORM,,}" | "win11${PLATFORM,,}" )
|
||||
download_windows "$version" "$lang" && return 0
|
||||
download_windows "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise-eval" )
|
||||
download_windows_eval "$version" "$lang" && return 0
|
||||
;;
|
||||
"win10${PLATFORM,,}-enterprise-eval" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
download_windows_eval "$version" "$lang" && return 0
|
||||
"win11${PLATFORM,,}-enterprise"* | "win10${PLATFORM,,}-enterprise"* )
|
||||
download_windows_eval "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" )
|
||||
download_windows_eval "$version" "$lang" && return 0
|
||||
download_windows_eval "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win81${PLATFORM,,}-enterprise-eval" )
|
||||
if [[ "${lang,,}" == "en" ]] || [[ "${lang,,}" == "en-"* ]]; then
|
||||
MIDO_URL="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO" && return 0
|
||||
fi
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download for the $language language available!"
|
||||
MIDO_URL="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO" && return 0
|
||||
;;
|
||||
"win2008r2" )
|
||||
if [[ "${lang,,}" == "en" ]] || [[ "${lang,,}" == "en-"* ]]; then
|
||||
MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso" && return 0
|
||||
fi
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download for the $language language available!"
|
||||
MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso" && return 0
|
||||
;;
|
||||
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
|
||||
esac
|
||||
|
|
@ -385,8 +439,9 @@ getESD() {
|
|||
|
||||
size=$(stat -c%s "$dir/$eFile")
|
||||
if ((size<20)); then
|
||||
desc=$(printEdition "$version" "$desc")
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "the $language language is not supported by this download method!" && return 1
|
||||
error "No download in the $language language available for $desc!" && return 1
|
||||
fi
|
||||
|
||||
local tag="FilePath"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue