#!/bin/bash
# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-

ROLE=proxy

. /usr/local/bin/usr_local_tput.bash || exit 2


## proxy_ami_cloudflared
proxy_ami_cloudflared() {
    [ $# -gt 0 ] || return 1
    local ip=$1
    for no in "${CLOUDFN[@]}" ; do
	nopat=`sed -e 's@[.0]*/[0-9][0-9]@@' <<< $no`
	[[ $ip =~ ${nopat}.* ]] && {
	    # WARN $url cloudflared $ip $no
	    echo True
	    return 0
	    }
    done
    echo False
    return 0
}

## proxy_ami_cloudflared_py
proxy_ami_cloudflared_py() {
    [ $# -gt 0 ] || return 1
    local ip=$1
    a=`proxy_ami_cloudflared $ip`
    if [ $? -eq 0 -a "$a" = True ] ; then
	echo $a
	return 0
    fi

    # https://netaddr.readthedocs.io/en/latest/tutorial_01.html
    # a=`python3 -c "import netaddr; print(netaddr.IPAddress('$ip') in list(netaddr.IPNetwork('$no')))"`
    # https://stackoverflow.com/questions/819355/how-can-i-check-if-an-ip-is-in-a-network-in-python

    for no in "${CLOUDFN[@]}" ; do
	a=`python3 -c "import ipaddress; print(ipaddress.IPv4Address('$ip') in list(ipaddress.IPv4Network('$no')))"`
	if [ $? -eq 0 -a "$a" = True ] ; then
	    echo $a
	    return 0
	fi
    done
    echo False
    return 0
}

## proxy_ami_nottlsv3
proxy_ami_nottlsv3() {
    [ $# -gt 0 ] || return 1
    local site=$1
    for no in "${NOTLSV3[@]}" ; do
	[[ $site =~ $no ]] && echo True && return 0
    done
    echo False
    return 0
}

declare -a NOTLSV3
NOTLSV3=(
    # connection refused
    www.mirrorservice.org
    # no ipv3
    files.pythonhosted.org
    # forbidden
    download.nvidia.com
    # 500
    www.x.org
)

#     https://web.archive.org/web/20220722104744/https://www.cloudflare.com/ips-v4
declare -a CLOUDFN
CLOUDFN=(
    173.245.48.0/20
    103.21.244.0/22
    103.22.200.0/22
    103.31.4.0/22
    104.16.0.0/13
    104.24.0.0/14
    108.162.192.0/18
    131.0.72.0/22
    141.101.64.0/18
    162.158.0.0/15
    172.64.0.0/13
    188.114.96.0/20
    190.93.240.0/20
    197.234.240.0/22
    198.41.128.0/17
)

#for no in "${CLOUDFN[@]}" ; do
#  # https://netaddr.readthedocs.io/en/latest/tutorial_01.html
#  a=`python3 -c "import netaddr; print('\n'.join(map(str,list(netaddr.IPNetwork('$no')))))"`
#done

# /usr/include/openssl/x509_vfy.h
declare -A OPENSSL_X509_V
OPENSSL_X509_V=(
	[0]=OK
	[1]=ERR_UNSPECIFIED
	[2]=ERR_UNABLE_TO_GET_ISSUER_CERT
	[3]=ERR_UNABLE_TO_GET_CRL
	[4]=ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
	[5]=ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
	[6]=ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
	[7]=ERR_CERT_SIGNATURE_FAILURE
	[8]=ERR_CRL_SIGNATURE_FAILURE
	[9]=ERR_CERT_NOT_YET_VALID
	[10]=ERR_CERT_HAS_EXPIRED
	[11]=ERR_CRL_NOT_YET_VALID
	[12]=ERR_CRL_HAS_EXPIRED
	[13]=ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
	[14]=ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
	[15]=ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
	[16]=ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
	[17]=ERR_OUT_OF_MEM
	[18]=ERR_DEPTH_ZERO_SELF_SIGNED_CERT
	[19]=ERR_SELF_SIGNED_CERT_IN_CHAIN
	[20]=ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
	[21]=ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
	[22]=ERR_CERT_CHAIN_TOO_LONG
	[23]=ERR_CERT_REVOKED
	[24]=ERR_INVALID_CA
	[25]=ERR_PATH_LENGTH_EXCEEDED
	[26]=ERR_INVALID_PURPOSE
	[27]=ERR_CERT_UNTRUSTED
	[28]=ERR_CERT_REJECTED
	# These are 'informational' when looking for issuer cert
	[29]=ERR_SUBJECT_ISSUER_MISMATCH
	[30]=ERR_AKID_SKID_MISMATCH
	[31]=ERR_AKID_ISSUER_SERIAL_MISMATCH
	[32]=ERR_KEYUSAGE_NO_CERTSIGN
	[33]=ERR_UNABLE_TO_GET_CRL_ISSUER
	[34]=ERR_UNHANDLED_CRITICAL_EXTENSION
	[35]=ERR_KEYUSAGE_NO_CRL_SIGN
	[36]=ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
	[37]=ERR_INVALID_NON_CA
	[38]=ERR_PROXY_PATH_LENGTH_EXCEEDED
	[39]=ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
	[40]=ERR_PROXY_CERTIFICATES_NOT_ALLOWED
	[41]=ERR_INVALID_EXTENSION
	[42]=ERR_INVALID_POLICY_EXTENSION
	[43]=ERR_NO_EXPLICIT_POLICY
	[44]=ERR_DIFFERENT_CRL_SCOPE
	[45]=ERR_UNSUPPORTED_EXTENSION_FEATURE
	[46]=ERR_UNNESTED_RESOURCE
	[47]=ERR_PERMITTED_VIOLATION
	[48]=ERR_EXCLUDED_VIOLATION
	[49]=ERR_SUBTREE_MINMAX
	# The application is not happy
	[50]=ERR_APPLICATION_VERIFICATION
	[51]=ERR_UNSUPPORTED_CONSTRAINT_TYPE
	[52]=ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
	[53]=ERR_UNSUPPORTED_NAME_SYNTAX
	[54]=ERR_CRL_PATH_VALIDATION_ERROR
	# Another issuer check debug option
	[55]=ERR_PATH_LOOP
	# Suite B mode algorithm violation
	[56]=ERR_SUITE_B_INVALID_VERSION
	[57]=ERR_SUITE_B_INVALID_ALGORITHM
	[58]=ERR_SUITE_B_INVALID_CURVE
	[59]=ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
	[60]=ERR_SUITE_B_LOS_NOT_ALLOWED
	[61]=ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256
	# Host, email and IP check errors
	[62]=ERR_HOSTNAME_MISMATCH
	[63]=ERR_EMAIL_MISMATCH
	[64]=ERR_IP_ADDRESS_MISMATCH
	# DANE TLSA errors
	[65]=ERR_DANE_NO_MATCH
	# security level errors
	[66]=ERR_EE_KEY_TOO_SMALL
	[67]=ERR_CA_KEY_TOO_SMALL
	[68]=ERR_CA_MD_TOO_WEAK
	# Caller error
	[69]=ERR_INVALID_CALL
	# Issuer lookup error
	[70]=ERR_STORE_LOOKUP
	# Certificate transparency
	[71]=ERR_NO_VALID_SCTS

	[72]=ERR_PROXY_SUBJECT_NAME_VIOLATION
	# OCSP status errors
	[73]=ERR_OCSP_VERIFY_NEEDED  	# Need OCSP verification
	[74]=ERR_OCSP_VERIFY_FAILED  	# Couldn't verify cert through OCSP
	[75]=ERR_OCSP_CERT_UNKNOWN  	# Certificate wasn't recognized by the OCSP responder
	[76]=ERR_SIGNATURE_ALGORITHM_MISMATCH
	[77]=ERR_NO_ISSUER_PUBLIC_KEY
	[78]=ERR_UNSUPPORTED_SIGNATURE_ALGORITHM
	[79]=ERR_EC_KEY_EXPLICIT_PARAMS
	)

# man 3 libcurl-errors
declare -A CURLE
CURLE=(
	[0]=CURLE_OK
	[1]=CURLE_UNSUPPORTED_PROTOCOL
	[2]=CURLE_FAILED_INIT
	[3]=CURLE_URL_MALFORMAT
	[4]=CURLE_NOT_BUILT_IN
	[5]=CURLE_COULDNT_RESOLVE_PROXY
	[6]=CURLE_COULDNT_RESOLVE_HOST
	[7]=CURLE_COULDNT_CONNECT
	[8]=CURLE_WEIRD_SERVER_REPLY
	[9]=CURLE_REMOTE_ACCESS_DENIED
	[10]=CURLE_FTP_ACCEPT_FAILED
	[11]=CURLE_FTP_WEIRD_PASS_REPLY
	[12]=CURLE_FTP_ACCEPT_TIMEOUT
	[13]=CURLE_FTP_WEIRD_PASV_REPLY
	[14]=CURLE_FTP_WEIRD_227_FORMAT
	[15]=CURLE_FTP_CANT_GET_HOST
	[16]=CURLE_HTTP2
	[17]=CURLE_FTP_COULDNT_SET_TYPE
	[18]=CURLE_PARTIAL_FILE
	[19]=CURLE_FTP_COULDNT_RETR_FILE
	[21]=CURLE_QUOTE_ERROR
	[22]=CURLE_HTTP_RETURNED_ERROR
	[23]=CURLE_WRITE_ERROR
	[25]=CURLE_UPLOAD_FAILED
	[26]=CURLE_READ_ERROR
	[27]=CURLE_OUT_OF_MEMORY
	[28]=CURLE_OPERATION_TIMEDOUT
	[30]=CURLE_FTP_PORT_FAILED
	[31]=CURLE_FTP_COULDNT_USE_REST
	[33]=CURLE_RANGE_ERROR
	[34]=CURLE_HTTP_POST_ERROR
	[35]=CURLE_SSL_CONNECT_ERROR
	[36]=CURLE_BAD_DOWNLOAD_RESUME
	[37]=CURLE_FILE_COULDNT_READ_FILE
	[38]=CURLE_LDAP_CANNOT_BIND
	[39]=CURLE_LDAP_SEARCH_FAILED
	[41]=CURLE_FUNCTION_NOT_FOUND
	[42]=CURLE_ABORTED_BY_CALLBACK
	[43]=CURLE_BAD_FUNCTION_ARGUMENT
	[45]=CURLE_INTERFACE_FAILED
	[47]=CURLE_TOO_MANY_REDIRECTS
	[48]=CURLE_UNKNOWN_OPTION
	[49]=CURLE_SETOPT_OPTION_SYNTAX
	[52]=CURLE_GOT_NOTHING
	[53]=CURLE_SSL_ENGINE_NOTFOUND
	[54]=CURLE_SSL_ENGINE_SETFAILED
	[55]=CURLE_SEND_ERROR
	[56]=CURLE_RECV_ERROR
	[58]=CURLE_SSL_CERTPROBLEM
	[59]=CURLE_SSL_CIPHER
	[60]=CURLE_PEER_FAILED_VERIFICATION
	[61]=CURLE_BAD_CONTENT_ENCODING
	[62]=CURLE_LDAP_INVALID_URL
	[63]=CURLE_FILESIZE_EXCEEDED
	[64]=CURLE_USE_SSL_FAILED
	[65]=CURLE_SEND_FAIL_REWIND
	[66]=CURLE_SSL_ENGINE_INITFAILED
	[67]=CURLE_LOGIN_DENIED
	[68]=CURLE_TFTP_NOTFOUND
	[69]=CURLE_TFTP_PERM
	[70]=CURLE_REMOTE_DISK_FULL
	[71]=CURLE_TFTP_ILLEGAL
	[72]=CURLE_TFTP_UNKNOWNID
	[73]=CURLE_REMOTE_FILE_EXISTS
	[74]=CURLE_TFTP_NOSUCHUSER
	[75]=CURLE_CONV_FAILED
	[76]=CURLE_CONV_REQD
	[77]=CURLE_SSL_CACERT_BADFILE
	[78]=CURLE_REMOTE_FILE_NOT_FOUND
	[79]=CURLE_SSH
	[80]=CURLE_SSL_SHUTDOWN_FAILED
	[81]=CURLE_AGAIN
	[82]=CURLE_SSL_CRL_BADFILE
	[83]=CURLE_SSL_ISSUER_ERROR
	[84]=CURLE_FTP_PRET_FAILED
	[85]=CURLE_RTSP_CSEQ_ERROR
	[86]=CURLE_RTSP_SESSION_ERROR
	[87]=CURLE_FTP_BAD_FILE_LIST
	[88]=CURLE_CHUNK_FAILED
	[89]=CURLE_NO_CONNECTION_AVAILABLE
	[90]=CURLE_SSL_PINNEDPUBKEYNOTMATCH
	[91]=CURLE_SSL_INVALIDCERTSTATUS
	[92]=CURLE_HTTP2_STREAM
	[93]=CURLE_RECURSIVE_API_CALL
	[94]=CURLE_AUTH_ERROR
	[95]=CURLE_HTTP3
	[96]=CURLE_QUIC_CONNECT_ERROR
	[98]=CURLE_SSL_CLIENTCERT
	[99]=CURLE_UNRECOVERABLE_POLL
)

#    20 HTTP response status codes
declare -A HTTP_RESPONSE
HTTP_RESPONSE=(
	[100]="Continue"
	[101]="Switching Protocols"
	[103]="Early Hints"
	[200]="OK"
	[201]="Created"
	[202]="Accepted"
	[203]="Non-Authoritative Information"
	[204]="No Content"
	[205]="Reset Content"
	[206]="Partial Content"
	[300]="Multiple Choices"
	[301]="Moved Permanently"
	[302]="Found"
	[303]="See Other"
	[304]="Not Modified"
	[307]="Temporary Redirect"
	[308]="Permanent Redirect"
	[400]="Bad Request"
	[401]="Unauthorized"
	[402]="Payment Required"
	[403]="Forbidden"
	[404]="Not Found"
	[405]="Method Not Allowed"
	[406]="Not Acceptable"
	[407]="Proxy Authentication Required"
	[408]="Request Timeout"
	[409]="Conflict"
	[410]="Gone"
	[411]="Length Required"
	[412]="Precondition Failed"
	[413]="Payload Too Large"
	[414]="URI Too Long"
	[415]="Unsupported Media Type"
	[416]="Range Not Satisfiable"
	[417]="Expectation Failed"
	[418]="Im a teapot"
	[422]="Unprocessable Entity"
	[425]="Too Early"
	[426]="Upgrade Required"
	[428]="Precondition Required"
	[429]="Too Many Requests"
	[431]="Request Header Fields Too Large"
	[451]="Unavailable For Legal Reasons"
	[500]="Internal Server Error"
	[501]="Not Implemented"
	[502]="Bad Gateway"
	[503]="Service Unavailable"
	[504]="Gateway Timeout"
	[505]="HTTP Version Not Supported"
	[506]="Variant Also Negotiates"
	[507]="Insufficient Storage"
	[508]="Loop Detected"
	[510]="Not Extended"
	[511]="Network Authentication Required"
)

# https://techcommunity.microsoft.com/t5/iis-support-blog/ssl-tls-alert-protocol-and-the-alert-codes/ba-p/377132
declare -a SSL_ALERT_CODES
# B.2.  Alert Messages
SSL_ALERT_CODES=(
	[0]="close_notify"
	[10]="unexpected_message"
	[20]="bad_record_mac"
	[21]="decryption_failed_RESERVED"
	[22]="record_overflow"
	[30]="decompression_failure_RESERVED"
	[40]="handshake_failure"
	[41]="no_certificate_RESERVED"
	[42]="bad_certificate"
	[43]="unsupported_certificate"
	[44]="certificate_revoked"
	[45]="certificate_expired"
	[46]="certificate_unknown"
	[47]="illegal_parameter"
	[48]="unknown_ca"
	[49]="access_denied"
	[50]="decode_error"
	[51]="decrypt_error"
	[60]="export_restriction_RESERVED"
	[70]="protocol_version"
	[71]="insufficient_security"
	[80]="internal_error"
	[86]="inappropriate_fallback"
	[90]="user_canceled"
	[100]="no_renegotiation_RESERVED"
	[109]="missing_extension"
	[110]="unsupported_extension"
	[111]="certificate_unobtainable_RESERVED"
	[112]="unrecognized_name"
	[113]="bad_certificate_status_response"
	[114]="bad_certificate_hash_value_RESERVED"
	[115]="unknown_psk_identity"
	[116]="certificate_required"
	[120]="no_application_protocol"
)

# https://curl.se/docs/ssl-ciphers.html

# openssl
# https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html

# https://curl.se/libcurl/c/CURLOPT_SSL_CIPHER_LIST.html
openssl=openssl
# CURLOPT_TLS13_CIPHERS --tls13-ciphers
if [ $openssl = openssl ] ; then
    export CURLOPT_TLS13_CIPHERS="TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256,TLS_AES_128_CCM_8_SHA256,TLS_AES_128_CCM_SHA256"
elif [ $openssl = nss ] ; then
    export CURLOPT_TLS13_CIPHERS="aes_128_gcm_sha_256,aes_256_gcm_sha_384,chacha20_poly1305_sha_256"
fi

