Harden IPv6 validation
This commit is contained in:
@@ -247,13 +247,42 @@ validate_ipv4() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_validate_ipv6_part_count() {
|
||||||
|
local part=${1-}
|
||||||
|
local IFS=':'
|
||||||
|
local -a fields=()
|
||||||
|
local field idx count=0
|
||||||
|
|
||||||
|
[[ -n ${part} ]] || {
|
||||||
|
printf '0\n'
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ ${part} != :* ]] || return 1
|
||||||
|
[[ ${part} != *: ]] || return 1
|
||||||
|
[[ ${part} != *::* ]] || return 1
|
||||||
|
|
||||||
|
read -r -a fields <<<"${part}"
|
||||||
|
for idx in "${!fields[@]}"; do
|
||||||
|
field=${fields[idx]}
|
||||||
|
[[ -n ${field} ]] || return 1
|
||||||
|
if [[ ${field} == IPV4TAIL ]]; then
|
||||||
|
(( idx == ${#fields[@]} - 1 )) || return 1
|
||||||
|
((count += 2))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
[[ ${field} =~ ^[0-9A-Fa-f]{1,4}$ ]] || return 1
|
||||||
|
((count++))
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '%s\n' "${count}"
|
||||||
|
}
|
||||||
|
|
||||||
validate_ipv6() {
|
validate_ipv6() {
|
||||||
local ip=${1-}
|
local ip=${1-}
|
||||||
local base scope
|
local base scope tail prefix left right left_count right_count total_count
|
||||||
[[ -n ${ip} ]] || return 1
|
[[ -n ${ip} ]] || return 1
|
||||||
[[ ${ip} != *.* ]] || return 1
|
|
||||||
[[ ${ip} == *:* ]] || return 1
|
[[ ${ip} == *:* ]] || return 1
|
||||||
[[ ${ip} != *:::* ]] || return 1
|
|
||||||
|
|
||||||
scope=''
|
scope=''
|
||||||
base=${ip}
|
base=${ip}
|
||||||
@@ -264,8 +293,29 @@ validate_ipv6() {
|
|||||||
[[ ${scope} =~ ^[A-Za-z0-9_.:-]+$ ]] || return 1
|
[[ ${scope} =~ ^[A-Za-z0-9_.:-]+$ ]] || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ ${base} =~ ^[0-9A-Fa-f:]+$ ]] || return 1
|
if [[ ${base} == *.* ]]; then
|
||||||
[[ ${base} =~ :: ]] || [[ ${base} =~ ^([0-9A-Fa-f]{1,4}:){1,7}[0-9A-Fa-f]{1,4}$ ]] || return 1
|
tail=${base##*:}
|
||||||
|
prefix=${base%:*}
|
||||||
|
[[ ${prefix} != "${base}" ]] || return 1
|
||||||
|
validate_ipv4 "${tail}" || return 1
|
||||||
|
base="${prefix}:IPV4TAIL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ ${base//IPV4TAIL/} =~ ^[0-9A-Fa-f:]+$ ]] || return 1
|
||||||
|
|
||||||
|
if [[ ${base} == *::* ]]; then
|
||||||
|
[[ ${base#*::} != *::* ]] || return 1
|
||||||
|
left=${base%%::*}
|
||||||
|
right=${base#*::}
|
||||||
|
left_count=$(_validate_ipv6_part_count "${left}") || return 1
|
||||||
|
right_count=$(_validate_ipv6_part_count "${right}") || return 1
|
||||||
|
total_count=$((left_count + right_count))
|
||||||
|
(( total_count < 8 )) || return 1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
total_count=$(_validate_ipv6_part_count "${base}") || return 1
|
||||||
|
(( total_count == 8 ))
|
||||||
}
|
}
|
||||||
|
|
||||||
validate_port() {
|
validate_port() {
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ assert_status 1 "$(status_of validate_ipv4 '')" 'validate_ipv4 should reject emp
|
|||||||
assert_status 0 "$(status_of validate_ipv6 '::1')" 'validate_ipv6 should accept loopback'
|
assert_status 0 "$(status_of validate_ipv6 '::1')" 'validate_ipv6 should accept loopback'
|
||||||
assert_status 0 "$(status_of validate_ipv6 '2001:db8::1')" 'validate_ipv6 should accept compressed address'
|
assert_status 0 "$(status_of validate_ipv6 '2001:db8::1')" 'validate_ipv6 should accept compressed address'
|
||||||
assert_status 0 "$(status_of validate_ipv6 'fe80::1%eth0')" 'validate_ipv6 should accept scoped address'
|
assert_status 0 "$(status_of validate_ipv6 'fe80::1%eth0')" 'validate_ipv6 should accept scoped address'
|
||||||
|
assert_status 0 "$(status_of validate_ipv6 '::ffff:192.0.2.128')" 'validate_ipv6 should accept embedded ipv4 tail'
|
||||||
assert_status 1 "$(status_of validate_ipv6 ':::1')" 'validate_ipv6 should reject malformed address'
|
assert_status 1 "$(status_of validate_ipv6 ':::1')" 'validate_ipv6 should reject malformed address'
|
||||||
|
assert_status 1 "$(status_of validate_ipv6 '2001::1::1')" 'validate_ipv6 should reject multiple compression markers'
|
||||||
|
assert_status 1 "$(status_of validate_ipv6 '12345::1')" 'validate_ipv6 should reject oversized hextet'
|
||||||
|
assert_status 1 "$(status_of validate_ipv6 '2001:db8::1::')" 'validate_ipv6 should reject trailing double compression'
|
||||||
assert_status 1 "$(status_of validate_ipv6 '1.2.3.4')" 'validate_ipv6 should reject ipv4 literal'
|
assert_status 1 "$(status_of validate_ipv6 '1.2.3.4')" 'validate_ipv6 should reject ipv4 literal'
|
||||||
assert_status 1 "$(status_of validate_ipv6 '')" 'validate_ipv6 should reject empty string'
|
assert_status 1 "$(status_of validate_ipv6 '')" 'validate_ipv6 should reject empty string'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user