mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 12:37:20 +01:00
feat: Validate unattended settings before use (#1892)
This commit is contained in:
+167
-22
@@ -1329,7 +1329,7 @@ validVersion() {
|
|||||||
|
|
||||||
local id="$1"
|
local id="$1"
|
||||||
local lang="$2"
|
local lang="$2"
|
||||||
local url
|
local url i=0
|
||||||
|
|
||||||
isESD "$id" "$lang" && return 0
|
isESD "$id" "$lang" && return 0
|
||||||
isMido "$id" "$lang" && return 0
|
isMido "$id" "$lang" && return 0
|
||||||
@@ -1344,6 +1344,143 @@ validVersion() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateResolution() {
|
||||||
|
|
||||||
|
local name="$1"
|
||||||
|
local value="$2"
|
||||||
|
local minimum="$3"
|
||||||
|
local number
|
||||||
|
|
||||||
|
if [[ ! "$value" =~ ^[0-9]+$ ]] || [ "${#value}" -gt 5 ]; then
|
||||||
|
error "The $name variable must be between $minimum and 16384!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
number=$((10#$value))
|
||||||
|
|
||||||
|
if [ "$number" -lt "$minimum" ] || [ "$number" -gt 16384 ]; then
|
||||||
|
error "The $name variable must be between $minimum and 16384!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
validateProductKey() {
|
||||||
|
|
||||||
|
local value="$1"
|
||||||
|
|
||||||
|
[ -z "$value" ] && return 0
|
||||||
|
|
||||||
|
if [[ ! "$value" =~ ^[A-Za-z0-9]{5}(-[A-Za-z0-9]{5}){4}$ ]]; then
|
||||||
|
error "The KEY variable must contain a valid 25-character product key!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
validateLegacyText() {
|
||||||
|
|
||||||
|
local name="$1"
|
||||||
|
local value="$2"
|
||||||
|
local desc="${3:-}"
|
||||||
|
local suffix=""
|
||||||
|
|
||||||
|
[ -n "$desc" ] && suffix=" for $desc"
|
||||||
|
|
||||||
|
if [[ "$value" =~ [[:cntrl:]] ]]; then
|
||||||
|
error "The $name variable cannot contain control characters$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$value" == *'"'* ]]; then
|
||||||
|
error "The $name variable cannot contain double quotes$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
validateLegacyUsername() {
|
||||||
|
|
||||||
|
local value="$1"
|
||||||
|
local desc="${2:-}"
|
||||||
|
local suffix=""
|
||||||
|
|
||||||
|
[ -n "$desc" ] && suffix=" for $desc"
|
||||||
|
|
||||||
|
if [ -z "$value" ]; then
|
||||||
|
error "The USERNAME variable cannot be empty$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${#value}" -gt 20 ]; then
|
||||||
|
error "The USERNAME variable cannot contain more than 20 characters$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$value" =~ [[:cntrl:]] ]]; then
|
||||||
|
error "The USERNAME variable cannot contain control characters$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$value" in
|
||||||
|
*'"'* | *'/'* | *\\* | *'['* | *']'* | *':'* | *';'* | *'|'* | *'='* | *','* | *'+'* | *'*'* | *'?'* | *'<'* | *'>'* )
|
||||||
|
error "The USERNAME variable contains unsupported characters$suffix!"
|
||||||
|
return 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$value" == *"." ]]; then
|
||||||
|
error "The USERNAME variable cannot end with a period$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$value" =~ ^[.[:space:]]+$ ]]; then
|
||||||
|
error "The USERNAME variable cannot consist only of spaces or periods$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
validateLegacyPassword() {
|
||||||
|
|
||||||
|
local value="$1"
|
||||||
|
local desc="${2:-}"
|
||||||
|
local suffix=""
|
||||||
|
|
||||||
|
[ -n "$desc" ] && suffix=" for $desc"
|
||||||
|
|
||||||
|
if [ "${#value}" -gt 127 ]; then
|
||||||
|
error "The PASSWORD variable cannot contain more than 127 characters$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$value" =~ [[:cntrl:]] ]]; then
|
||||||
|
error "The PASSWORD variable cannot contain control characters$suffix!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
escapeSIFValue() {
|
||||||
|
|
||||||
|
local s="$1"
|
||||||
|
|
||||||
|
s=${s//%/%%}
|
||||||
|
s=${s//\"/\"\"}
|
||||||
|
|
||||||
|
printf '%s' "$s"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
escapeRegistryValue() {
|
||||||
|
|
||||||
|
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'
|
||||||
|
}
|
||||||
|
|
||||||
addFolder() {
|
addFolder() {
|
||||||
|
|
||||||
local src="$1"
|
local src="$1"
|
||||||
@@ -1457,7 +1594,6 @@ prepareInstall() {
|
|||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$file" || return 1
|
||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$file" || return 1
|
||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$file" || return 1
|
||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$file" || return 1
|
|
||||||
|
|
||||||
if [ ! -d "$drivers/sata/xp/$arch" ]; then
|
if [ ! -d "$drivers/sata/xp/$arch" ]; then
|
||||||
error "Failed to locate required SATA drivers!" && return 1
|
error "Failed to locate required SATA drivers!" && return 1
|
||||||
@@ -1563,7 +1699,10 @@ prepareInstall() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -n "$KEY" ] && KEY="ProductID=$KEY"
|
validateProductKey "$KEY" || return 1
|
||||||
|
|
||||||
|
local product=""
|
||||||
|
[ -n "$KEY" ] && product="ProductID=$KEY"
|
||||||
|
|
||||||
mkdir -p "$dir/\$OEM\$" || return 1
|
mkdir -p "$dir/\$OEM\$" || return 1
|
||||||
|
|
||||||
@@ -1578,23 +1717,29 @@ prepareInstall() {
|
|||||||
[ -z "$WIDTH" ] && WIDTH="1280"
|
[ -z "$WIDTH" ] && WIDTH="1280"
|
||||||
[ -z "$HEIGHT" ] && HEIGHT="720"
|
[ -z "$HEIGHT" ] && HEIGHT="720"
|
||||||
|
|
||||||
XHEX=$(printf '%08x\n' "$WIDTH") || return 1
|
validateResolution "WIDTH" "$WIDTH" 320 || return 1
|
||||||
YHEX=$(printf '%08x\n' "$HEIGHT") || return 1
|
validateResolution "HEIGHT" "$HEIGHT" 200 || return 1
|
||||||
|
validateLegacyText "APP" "$APP" "$desc" || return 1
|
||||||
|
validateLegacyText "ENGINE" "$ENGINE" "$desc" || return 1
|
||||||
|
|
||||||
local username=""
|
XHEX=$(printf '%08x\n' "$((10#$WIDTH))") || return 1
|
||||||
local password=""
|
YHEX=$(printf '%08x\n' "$((10#$HEIGHT))") || return 1
|
||||||
|
|
||||||
if [ -n "$USERNAME" ]; then
|
local username="${USERNAME:-Docker}"
|
||||||
username=$(echo "$USERNAME" | sed 's/[^[:alnum:]@!._-]//g') || return 1
|
local password="${PASSWORD:-admin}"
|
||||||
fi
|
local organization="$APP for $ENGINE"
|
||||||
[ -z "$username" ] && username="Docker"
|
local sifUsername sifPassword
|
||||||
|
local regUsername regPassword
|
||||||
|
|
||||||
if [ -n "$PASSWORD" ]; then
|
validateLegacyUsername "$username" "$desc" || return 1
|
||||||
password=$(echo "$PASSWORD" | sed 's/"//g') || return 1
|
validateLegacyPassword "$password" "$desc" || return 1
|
||||||
fi
|
|
||||||
[ -z "$password" ] && password="admin"
|
|
||||||
|
|
||||||
find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \; || return 1
|
sifUsername=$(escapeSIFValue "$username") || return 1
|
||||||
|
sifPassword=$(escapeSIFValue "$password") || return 1
|
||||||
|
regUsername=$(escapeRegistryValue "$username") || return 1
|
||||||
|
regPassword=$(escapeRegistryValue "$password") || return 1
|
||||||
|
|
||||||
|
find "$target" -maxdepth 1 -type f -iname winnt.sif -delete || return 1
|
||||||
|
|
||||||
{ echo "[Data]"
|
{ echo "[Data]"
|
||||||
echo " AutoPartition=1"
|
echo " AutoPartition=1"
|
||||||
@@ -1622,16 +1767,16 @@ prepareInstall() {
|
|||||||
echo "[GuiUnattended]"
|
echo "[GuiUnattended]"
|
||||||
echo " OEMSkipRegional=1"
|
echo " OEMSkipRegional=1"
|
||||||
echo " OemSkipWelcome=1"
|
echo " OemSkipWelcome=1"
|
||||||
echo " AdminPassword=$password"
|
echo " AdminPassword=\"$sifPassword\""
|
||||||
echo " TimeZone=0"
|
echo " TimeZone=0"
|
||||||
echo " AutoLogon=Yes"
|
echo " AutoLogon=Yes"
|
||||||
echo " AutoLogonCount=65432"
|
echo " AutoLogonCount=65432"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[UserData]"
|
echo "[UserData]"
|
||||||
echo " FullName=\"$username\""
|
echo " FullName=\"$sifUsername\""
|
||||||
echo " ComputerName=\"*\""
|
echo " ComputerName=\"*\""
|
||||||
echo " OrgName=\"$APP for $ENGINE\""
|
echo " OrgName=\"$organization\""
|
||||||
echo " $KEY"
|
echo " $product"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[Identification]"
|
echo "[Identification]"
|
||||||
echo " JoinWorkgroup = WORKGROUP"
|
echo " JoinWorkgroup = WORKGROUP"
|
||||||
@@ -1696,8 +1841,8 @@ prepareInstall() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]"
|
echo "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]"
|
||||||
echo "\"AutoAdminLogon\"=\"1\""
|
echo "\"AutoAdminLogon\"=\"1\""
|
||||||
echo "\"DefaultUserName\"=\"$username\""
|
echo "\"DefaultUserName\"=\"$regUsername\""
|
||||||
echo "\"DefaultPassword\"=\"$password\""
|
echo "\"DefaultPassword\"=\"$regPassword\""
|
||||||
echo "\"DefaultDomainName\"=\"Dockur\""
|
echo "\"DefaultDomainName\"=\"Dockur\""
|
||||||
echo ""
|
echo ""
|
||||||
echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]"
|
echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]"
|
||||||
|
|||||||
+15
-13
@@ -1013,11 +1013,11 @@ updateDomain() {
|
|||||||
' "$asset" > "$result" ||
|
' "$asset" > "$result" ||
|
||||||
! mv -f "$result" "$asset"; then
|
! mv -f "$result" "$asset"; then
|
||||||
|
|
||||||
rm -rf "$tmp"
|
rm -rf "$tmp" || true
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$tmp"
|
rm -rf "$tmp" || return 1
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1032,10 +1032,9 @@ updateXML() {
|
|||||||
[ -z "$WIDTH" ] && WIDTH="1280"
|
[ -z "$WIDTH" ] && WIDTH="1280"
|
||||||
[ -z "$HEIGHT" ] && HEIGHT="720"
|
[ -z "$HEIGHT" ] && HEIGHT="720"
|
||||||
|
|
||||||
if [[ ! "$WIDTH" =~ ^[0-9]+$ || ! "$HEIGHT" =~ ^[0-9]+$ ]]; then
|
validateResolution "WIDTH" "$WIDTH" 320 || return 1
|
||||||
error "The WIDTH and HEIGHT variables must contain numeric values!"
|
validateResolution "HEIGHT" "$HEIGHT" 200 || return 1
|
||||||
return 1
|
validateProductKey "$KEY" || return 1
|
||||||
fi
|
|
||||||
|
|
||||||
app=$(escapeXMLSed "$APP for $ENGINE") || return 1
|
app=$(escapeXMLSed "$APP for $ENGINE") || return 1
|
||||||
|
|
||||||
@@ -1197,10 +1196,8 @@ updateXML() {
|
|||||||
|
|
||||||
sed -i "s|<Value>password</Value>|<Value>$admin</Value>|g" "$asset" || return 1
|
sed -i "s|<Value>password</Value>|<Value>$admin</Value>|g" "$asset" || return 1
|
||||||
sed -i "s|<PlainText>true</PlainText>|<PlainText>false</PlainText>|g" "$asset" || return 1
|
sed -i "s|<PlainText>true</PlainText>|<PlainText>false</PlainText>|g" "$asset" || return 1
|
||||||
sed -i -z "s|<Password>...........<Value />|<Password>\n <Value>$pw</Value>|g" "$asset" || return 1
|
sed -i -z -E "s|<Password>([[:space:]]*)<Value[[:space:]]*/>|<Password>\1<Value>$pw</Value>|g" "$asset" || return 1
|
||||||
sed -i -z "s|<Password>...............<Value />|<Password>\n <Value>$pw</Value>|g" "$asset" || return 1
|
sed -i -z -E "s|<AdministratorPassword>([[:space:]]*)<Value[[:space:]]*/>|<AdministratorPassword>\1<Value>$admin</Value>|g" "$asset" || return 1
|
||||||
sed -i -z "s|<AdministratorPassword>...........<Value />|<AdministratorPassword>\n <Value>$admin</Value>|g" "$asset" || return 1
|
|
||||||
sed -i -z "s|<AdministratorPassword>...............<Value />|<AdministratorPassword>\n <Value>$admin</Value>|g" "$asset" || return 1
|
|
||||||
|
|
||||||
if [ -n "$domain" ]; then
|
if [ -n "$domain" ]; then
|
||||||
|
|
||||||
@@ -1214,14 +1211,19 @@ updateXML() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$EDITION" ]; then
|
if [ -n "$EDITION" ]; then
|
||||||
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
|
case "${EDITION,,}" in
|
||||||
edition=$(escapeXMLSed "${EDITION^^}") || return 1
|
"core" ) edition="STANDARDCORE" ;;
|
||||||
|
* ) edition="${EDITION^^}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
edition=$(escapeXMLSed "$edition") || return 1
|
||||||
sed -i "s|SERVERSTANDARD</Value>|SERVER$edition</Value>|g" "$asset" || return 1
|
sed -i "s|SERVERSTANDARD</Value>|SERVER$edition</Value>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$KEY" ]; then
|
if [ -n "$KEY" ]; then
|
||||||
key=$(escapeXMLSed "$KEY") || return 1
|
key=$(escapeXMLSed "$KEY") || return 1
|
||||||
sed -i '/<ProductKey>/,/<\/ProductKey>/d' "$asset" || return 1
|
sed -i -E '/^[[:space:]]*<ProductKey>[[:space:]]*$/,/^[[:space:]]*<\/ProductKey>[[:space:]]*$/d' "$asset" || return 1
|
||||||
|
sed -i -E "s|<ProductKey>[^<]*</ProductKey>|<ProductKey>$key</ProductKey>|g" "$asset" || return 1
|
||||||
sed -i "s|</UserData>| <ProductKey>\n <Key>$key</Key>\n <WillShowUI>OnError</WillShowUI>\n </ProductKey>\n </UserData>|g" "$asset" || return 1
|
sed -i "s|</UserData>| <ProductKey>\n <Key>$key</Key>\n <WillShowUI>OnError</WillShowUI>\n </ProductKey>\n </UserData>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user