diff --git a/.github/README.md b/.github/README.md index d279584..033c195 100644 --- a/.github/README.md +++ b/.github/README.md @@ -3,7 +3,7 @@ Easy-TLS is an Easy-RSA extension utility to help manage: + Easy-RSA based x509 security credentials + OpenVPN specific TLS keys -+ Verified `Inline` files for use with OpenVPN ++ Verified **`Inline`** files for use with OpenVPN + Concise OpenVPN TLS-Crypt-V2 Client Key Metadata definition + X509 Certificate **and matched** Easy-TLS Inline-file Expiry management tools + Complete **Inter-active Menus** @@ -38,7 +38,7 @@ For full support, you will also need these scripts for use by your OpenVPN Serve This script is used by Openvpn-Server to manage connection tracking. ## Environment -`easytls` is intended to work **everywhere** that `openvpn` and `easyrsa` work. +**`easytls`** is intended to work **everywhere** that **`openvpn`** and **`easyrsa`** work. ## Requirements + Easy-RSA Version 3.0.6+ diff --git a/easytls b/easytls index 65dfc80..63dccf3 100755 --- a/easytls +++ b/easytls @@ -326,7 +326,7 @@ cmd_help() cf|cfg|config) opt_config ;; ver|version) text=" - Show version information." ;; + Show version information." ;; "") usage ;; *) text=" @@ -4820,9 +4820,13 @@ build_tls_crypt_v2_client () md_temp_addr="${1}" if hw_addr_hex_check "${md_temp_addr}" >/dev/null 2>&1; then EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${temp_hw_addr}" - elif validate_ip4_address "${md_temp_addr}" >/dev/null 2>&1; then + elif validate_ip4_data "${md_temp_addr}" >/dev/null 2>&1; then + md_temp_addr="${valid_octets}/${mask_len}" + unset valid_octets mask_len EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${md_temp_addr}" - elif validate_ip6_address "${md_temp_addr}" >/dev/null 2>&1; then + elif validate_ip6_data "${md_temp_addr}" >/dev/null 2>&1; then + md_temp_addr="${valid_hextets}/${mask_len}" + unset valid_octets mask_len EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${md_temp_addr}" else die "Invalid Address: ${md_temp_addr}" @@ -4954,9 +4958,13 @@ build_tls_cv2_group_client () md_temp_addr="${1}" if hw_addr_hex_check "${md_temp_addr}" >/dev/null 2>&1; then EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${temp_hw_addr}" - elif validate_ip4_address "${md_temp_addr}" >/dev/null 2>&1; then + elif validate_ip4_data "${md_temp_addr}" >/dev/null 2>&1; then + md_temp_addr="${valid_octets}/${mask_len}" + unset valid_octets mask_len EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${md_temp_addr}" - elif validate_ip6_address "${md_temp_addr}" >/dev/null 2>&1; then + elif validate_ip6_data "${md_temp_addr}" >/dev/null 2>&1; then + md_temp_addr="${valid_hextets}/${mask_len}" + unset valid_octets mask_len EASYTLS_TLSCV2_HWLIST="${EASYTLS_TLSCV2_HWLIST} ${md_temp_addr}" else die "Invalid Address: ${md_temp_addr}" @@ -5013,7 +5021,7 @@ hw_addr_hex_check () } # Verify hex only - [ ${temp_hw_addr} = ${temp_hw_addr%[!0123456789abcdefABCDEF]*} ] || { + [ ${temp_hw_addr} = ${temp_hw_addr%[!0123456789ABCDEF]*} ] || { easytls_verbose "temp_hw_addr - !Hex: ${temp_hw_addr}" return 1 } @@ -5022,120 +5030,191 @@ hw_addr_hex_check () # Front end validate IP address validate_ip_address () { + # This is probably broken [ "${1}" = "${1%%.*}" ] || ipv4=1 [ "${1}" = "${1%%:*}" ] || ipv6=1 [ -n "${ipv4}${ipv6}" ] || return 1 [ $ipv4 ] && [ $ipv6 ] && easytls_verbose "Unsupported <:Port>" && return 1 - [ $ipv4 ] && validate_ip4_address "$@" && valid4=1 - [ $ipv6 ] && validate_ip6_address "$@" && valid6=1 + [ $ipv4 ] && validate_ip4_data "$@" && valid4=1 + [ $ipv6 ] && validate_ip6_data "$@" && valid6=1 [ $valid4 ] && [ $valid6 ] && return 1 [ $valid4 ] || [ $valid6 ] || return 1 [ $ipv6 ] || print "Valid IPv4: $*" [ $ipv4 ] || print "Valid IPv6: $*" } # => validate_ip_address () -# Validate IPv4 address -validate_ip4_address () +# Validate IPv4 data +validate_ip4_data () { + [ -z "${2}" ] || return 10 temp_ip_addr="${1}" # Syntax case "${temp_ip_addr}" in - *":"* ) easytls_verbose "IPv4 error: colon"; return 1 ;; - *[!0123456789./]*) easytls_verbose "IPv4 error: illegal"; return 1 ;; + *".."* | *"[!0123456789./]"* ) + return 11 esac - # Octets - Should really redo this - o1=${temp_ip_addr%%.*}; temp_ip_addr=${temp_ip_addr#*.}; - o2=${temp_ip_addr%%.*}; temp_ip_addr=${temp_ip_addr#*.}; - o3=${temp_ip_addr%%.*}; temp_ip_addr=${temp_ip_addr#*.}; - o4=${temp_ip_addr%%/*}; temp_ip_addr=${temp_ip_addr#*/}; - fx=${temp_ip_addr}; - [ "${fx}" = "${o4}" ] && fx=32 - [ "${fx}" = 32 ] && [ "${o4}" = 0 ] && \ - easytls_verbose "IPv4 error: net/mask" && return 1 - - for i in "${o1}" "${o2}" "${o3}" "${o4}" + # Netmask + mask_len=${temp_ip_addr##*/} + if [ "${mask_len}" = "${temp_ip_addr}" ] + then + mask_len=32 + else + temp_ip_addr="${temp_ip_addr%/*}" + fi + + [ -z "${mask_len}" ] && return 12 + if [ "${mask_len}" -lt 0 ] || [ "${mask_len}" -gt 32 ] + then + return 13 + fi + + # Address + unset valid_octets octet_delim + i=0 + while [ -n "${temp_ip_addr}" ] do - [ -z "${i}" ] && easytls_verbose "IPv4 error: zero-val" && return 1 - [ "${i}" = "${i%[!0123456789]*}" ] || { - easytls_verbose "IPv4 error: number" - return 1 - } - if [ "${i}" -lt 0 ] || [ "${i}" -gt 255 ] + i=$(( i + 1 )) + octet=${temp_ip_addr%%.*} + + if [ "${octet}" != "${octet#0}" ] then - easytls_verbose "IPv4 error: value" - return 1 + [ "${octet}" = "0" ] || { + return 14 + } fi - done - # Bitmask - [ -z "${fx}" ] && easytls_verbose "IPv4 error: bitmask" && return 1 - [ "${fx}" = "${fx%[!0123456789]*}" ] || return 1 - if [ "${fx}" -lt 0 ] || [ "${fx}" -gt 32 ] - then - easytls_verbose "IPv4 error: mask-val" - return 1 - fi -} # => validate_ip4_address () + if [ "${octet}" -lt 0 ] || [ "${octet}" -gt 255 ] + then + return 15 + fi + + valid_octets="${valid_octets}${octet_delim}${octet}" + octet_delim='.' + [ "${temp_ip_addr}" != "${temp_ip_addr#*.}" ] || break + temp_ip_addr=${temp_ip_addr#*.} + done + [ ${i} -eq 4 ] || return 16 + unset temp_ip_addr octet_delim octet i + return 0 +} # => validate_ip4_data () -# Validate IPv6 address -validate_ip6_address () +# Validate IPv6 data +validate_ip6_data () { + [ -z "${2}" ] || return 10 temp_ip_addr="${1}" # Syntax case "${temp_ip_addr}" in - *"::"*"::"* | *":::"* | *[!:]":" | *"."* ) - easytls_verbose "IPv6 error: format" - return 1 - ;; - *[!0123456789abcdefABCDEF:/]*) - easytls_verbose "IPv6 error: illegal" - return 1 - ;; + :[!:]* ) return 1 ;; + *[!:]: ) return 11 ;; + *[!:]:/* ) return 11 ;; + *::*::* ) return 11 ;; + */*:* ) return 11 ;; + *"[!0123456789abcdef:/]"* ) return 11 ;; + *) + : # OK esac - # Set bitmask - default /128 - bitmask="${temp_ip_addr#*/}" - [ "${bitmask}" = "${temp_ip_addr}" ] && bitmask="128" - temp_ip_addr="${temp_ip_addr%/*}" + # Netmask + mask_len=${temp_ip_addr##*/} + if [ "${mask_len}" = "${temp_ip_addr}" ] + then + mask_len=128 + else + temp_ip_addr="${temp_ip_addr%/*}" + fi + + [ -z "${mask_len}" ] && return 12 + if [ "${mask_len}" -lt 0 ] || [ "${mask_len}" -gt 128 ] + then + return 13 + fi - # Collapse first :: - delim_pair_1="${temp_ip_addr%%:*}" - delim_pair_2="${delim_pair_1%%:*}" - if [ "${delim_pair_1}" = "${delim_pair_2}" ] + # Trailing : + if [ "${temp_ip_addr}" != "${temp_ip_addr%:}" ] then - temp_ip_addr="${temp_ip_addr#::}" + trailing_colon=1 fi - # Hextets + + # Address + unset valid_hextets hextet_delim + i=0 while [ -n "${temp_ip_addr}" ] do - oct_str=${temp_ip_addr%%:*} - hex="0x${oct_str:-0}" - [ $(( hex )) -lt 65536 ] || { - easytls_verbose "IPv6 error: oct-val" - return 1 - } - if [ "${#oct_str}" != 4 ] + i=$(( i + 1 )) + unset hextet + + # Leading : to current string + if [ -z "${temp_ip_addr%%:*}" ] then - [ "${oct_str}" = "${oct_str#0}" ] || { - easytls_verbose "IPv6 error: format" - return 1 - } + if [ ${i} -eq 1 ] + then + # Leading single : + # Does not count as double_colon + # Leading single : + [ ! $lead_colon ] || return 19 + lead_colon=1 + hextet=: + #unset hextet_delim + else + # right-hand colon in '::' + # The left-hand colon was stripped with the last hextet + [ ! $double_colon ] || return 17 + double_colon=1 + hextet=: + unset hextet_delim + fi fi + + # Left to right + temptet=${temp_ip_addr%%:*} + hextet=${hextet:-${temptet}} + unset temptet + + if [ "${hextet}" = ":" ] + then + # OK + : + else + # Normal hextet + # Leading zero + if [ "${hextet}" != "${hextet#0}" ] + then + [ "${hextet}" = "0" ] || { + return 14 + } + fi + + # Range: 0 < hextet < 65535 + if [ 0 -gt $(( 0x${hextet} )) ] || [ $(( 0x${hextet} )) -gt 65535 ] + then + return 15 + fi + fi + + [ $lead_colon ] && [ ${i} -eq 1 ] && unset hextet + valid_hextets="${valid_hextets}${hextet_delim}${hextet}" + hextet_delim=':' + [ "${temp_ip_addr}" != "${temp_ip_addr#*:}" ] || break + # Drop the left most 'ffff:' not '::' temp_ip_addr=${temp_ip_addr#*:} - [ "${temp_ip_addr}" = "${oct_str}" ] && break done + [ ! $trailing_colon ] || valid_hextets="${valid_hextets}${hextet_delim}" - # Bitmask - if [ "${bitmask}" -lt 0 ] || [ "${bitmask}" -gt 128 ] + # shudder + if [ $double_colon ] then - easytls_verbose "IPv6 error: mask-val" - return 1 + { [ ${i} -gt 1 ] && [ ${i} -lt 9 ]; } || return 16 + else + [ ${i} -eq 8 ] || return 16 fi -} # => validate_ip6_address () + unset temp_ip_addr hextet_delim hextet i double_colon lead_colon + return 0 +} # => validate_ip6_data () # Base64 encode metadata fields b64_enc_metadata () @@ -8641,11 +8720,19 @@ main () exit ;; v4ip) - validate_ip4_address "$@" || print "Invalid address: $*" && exit 1 + validate_ip4_data "$@" || { + print "*** Invalid IP4: ${*} ***" + exit 1 + } + print "VALID: ${valid_octets} ${mask_len}" exit ;; v6ip) - validate_ip6_address "$@" || print "Invalid address: $*" && exit 1 + validate_ip6_data "$@" || { + print "*** Invalid IP6: ${*} ***" + exit 1 + } + print "VALID: ${valid_hextets}/${mask_len}" exit ;; *) diff --git a/easytls-unit-tests.sh b/easytls-unit-tests.sh index 5f1c6e9..ca8bd00 100755 --- a/easytls-unit-tests.sh +++ b/easytls-unit-tests.sh @@ -184,8 +184,8 @@ export EASYRSA="$WORK_DIR" export EASYRSA_PKI="$PKI_DIR" hwaddr1="00:15:5d:c9:6e:01" hwaddr2="00:80:ea:06:fe:fc" -ip4addr="10.1.101.226" -ip6addr="12fc:1918::10:1:101:226" +ip4addr="10.1.101.0/24" +ip6addr="12fc:1918::10:1:101:0/64" echo "============================================================" echo "No-CA mode:"