diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index ff25449..5e9aa0b 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -193,8 +193,9 @@ if [ -n "$TRACE" ]; then } timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace' timestamp 'Args' "$@" + curl --help | grep -q -- --trace-time && CURL_TFLAGS="--trace-time" # 7.14.0 function curl { - command curl --trace-time --trace-ascii % "$@" 2>>"$TRACE" + command curl ${CURL_TFLAGS} --trace-ascii % "$@" 2>>"$TRACE" } [ -n "$VERB" ] && echo "Appending protocol trace to $TRACE" fi diff --git a/getssl b/getssl index aadb809..da7f386 100755 --- a/getssl +++ b/getssl @@ -192,16 +192,20 @@ VERSION="2.10" # defaults ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY_TYPE="rsa" +export AUTH_DNS_SERVER="" CA="https://acme-staging.api.letsencrypt.org" CA_CERT_LOCATION="" CHALLENGE_CHECK_TYPE="http" CHECK_ALL_AUTH_DNS="false" +CHECK_CERT_TIMEOUT="4" CHECK_REMOTE="true" CHECK_REMOTE_WAIT=0 CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" CSR_SUBJECT="/" DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v01.api.letsencrypt.org" +DNS_CHECK_FUNC="" +DNS_CHECK_OPTIONS="" DNS_EXTRA_WAIT="" DNS_WAIT=10 DOMAIN_KEY_LENGTH=4096 @@ -212,7 +216,7 @@ IGNORE_DIRECTORY_DOMAIN="false" ORIG_UMASK=$(umask) PREVIOUSLY_VALIDATED="true" PRIVATE_KEY_ALG="rsa" -PUBLIC_DNS_SERVER="" +export PUBLIC_DNS_SERVER="" RELOAD_CMD="" RENEW_ALLOW="30" REUSE_PRIVATE_KEY="true" @@ -389,14 +393,14 @@ check_config() { # check the config files for all obvious errors config_errors=true fi # check domain exist - if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" SOA|grep -c "^${d}")" -ge 1 ]]; then debug "found IP for ${d}" else info "${DOMAIN}: DNS lookup failed for ${d}" config_errors=true fi - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "^${d}")" -ge 1 ]]; then debug "found IP for ${d}" else @@ -716,20 +720,19 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns="$all_auth_dns_servers" return fi - - if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" CNAME| grep "^$gad_d") else - res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" CNAME "@$gad_s"| grep "^$gad_d") fi if [[ ! -z "$res" ]]; then # domain is a CNAME so get main domain gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') fi if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC NS "$gad_d"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" NS| grep "^$gad_d") else - res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" NS "@$gad_s"| grep "^$gad_d") fi if [[ -z "$res" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" @@ -744,7 +747,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n return fi - if [[ "$DNS_CHECK_FUNC" == "host" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then if [[ -z "$gad_s" ]]; then res=$($DNS_CHECK_FUNC -t NS "$gad_d"| grep "name server") else @@ -1178,6 +1181,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p response=$($CURL -X POST --data "$body" "$url") fi + touch "$CURL_HEADER" responseHeaders=$(cat "$CURL_HEADER") debug responseHeaders "$responseHeaders" debug response "$response" @@ -1325,6 +1329,21 @@ write_domain_template() { # write out a template file for a domain. # an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true #SERVER_TYPE="https" #CHECK_REMOTE="true" + + # Unusual configurations (especially split views) may require these. + # If these (or any variable) apply to all your domains, put them in + # the per-domain getssl.cfg. + # + # If you must use an external DNS Server (e.g. due to split views) + # Specify it here. Otherwise, the default is to find the zone master. + # The default will usually work. + # PUBLIC_DNS_SERVER="8.8.8.8" + + # If getssl is unable to determine the authoritative nameserver for a domain + # it will as you to enter AUTH_DNS_SERVER. This is the primary server that + # getssl will use to check for the acme tokens. It must be visible externally + # as well as internally. It need not be "authoritiative" in the RFC1035 sense. + # AUTH_DNS_SERVER="8.8.8.8" _EOF_domain_ } @@ -1364,6 +1383,19 @@ write_getssl_template() { # write out the main template file #VALIDATE_VIA_DNS="true" #DNS_ADD_COMMAND= #DNS_DEL_COMMAND= + + # Unusual configurations (especially split views) may require these. + # If you have a mixture, these can go in the per-domain getssl.cfg. + # + # If you must use an external DNS Server (e.g. due to split views) + # Specify it here. Otherwise, the default is to find the zone master. + # The default will usually work. + # PUBLIC_DNS_SERVER="8.8.8.8" + + # If getssl is unable to determine the authoritative nameserver for a domain + # it will as you to enter AUTH_DNS_SERVER. This is a server that + # can answer queries for the zone - a master or a slave, not a recursive server. + # AUTH_DNS_SERVER="10.0.0.14" _EOF_getssl_ } @@ -1446,7 +1478,6 @@ get_os requires which requires openssl requires curl -requires nslookup drill dig host DNS_CHECK_FUNC requires awk requires tr requires date @@ -1497,6 +1528,12 @@ if [[ -s "$WORKING_DIR/getssl.cfg" ]]; then . "$WORKING_DIR/getssl.cfg" fi +if [[ -n "$DNS_CHECK_FUNC" ]]; then + requires "${DNS_CHECK_FUNC}" +else + requires nslookup drill dig host DNS_CHECK_FUNC +fi + # Define defaults for variables not set in the main config. ACCOUNT_KEY="${ACCOUNT_KEY:=$WORKING_DIR/account.key}" DOMAIN_STORAGE="${DOMAIN_STORAGE:=$WORKING_DIR}" @@ -1569,11 +1606,17 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then info "domain config already exists $DOMAIN_DIR/getssl.cfg" else - info "creating domain config file in $DOMAIN_DIR/getssl.cfg" - # if domain has an existing cert, copy from domain and use to create defaults. - EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \ - | openssl x509 2>/dev/null) + info "Contacting ${DOMAIN} to inspect current certificate" + EX_CERT=$( { + if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then + openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 /dev/null & PID=$! + sleep ${CHECK_CERT_TIMEOUT} & PIDW=$! + wait -n # Requires bash 4.3+ + kill -9 "$PID" "$PIDW" 2>/dev/null + else + openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 /dev/null + fi + } | openssl x509 2>/dev/null) EX_SANS="www.${DOMAIN}" if [[ ! -z "${EX_CERT}" ]]; then EX_SANS=$(echo "$EX_CERT" \ @@ -1582,6 +1625,7 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then EX_SANS=${EX_SANS//$'\n'/','} fi write_domain_template "$DOMAIN_DIR/getssl.cfg" + info "created domain config file in $DOMAIN_DIR/getssl.cfg" fi TEMP_DIR="$DOMAIN_DIR/tmp" # end of "-c|--create" option, so exit @@ -1609,6 +1653,11 @@ if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then . "$DOMAIN_DIR/getssl.cfg" fi +# In case special options are needed for DNS_CHECK_FUNC, add them +# to the command. E.G. if a TSIG key or bound local IP is required... + +DNS_CHECK_FUNC="${DNS_CHECK_FUNC} ${DNS_CHECK_OPTIONS}" + # from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA set_server_type @@ -1629,11 +1678,19 @@ URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') # if check_remote is true then connect and obtain the current certificate (if not forcing renewal) if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then - debug "getting certificate for $DOMAIN from remote server" + info "Contacting $DOMAIN on port ${REMOTE_PORT} to inspect current certificate" # shellcheck disable=SC2086 - EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ - | openssl x509 2>/dev/null) + EX_CERT=$( { + if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then + echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null & PID=$! + sleep ${CHECK_CERT_TIMEOUT} & PIDW=$! + wait -n # Requires bash 4.3+ + kill -9 "$PID" "$PIDW" 2>/dev/null + else + echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null + fi + } | openssl x509 2>/dev/null ) + if [[ ! -z "$EX_CERT" ]]; then # if obtained a cert if [[ -s "$CERT_FILE" ]]; then # if local exists CERT_LOCAL=$(openssl x509 -noout -fingerprint < "$CERT_FILE" 2>/dev/null) @@ -1980,10 +2037,10 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${d}" "@${ns}" \ + elif [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then + check_result=$($DNS_CHECK_FUNC "_acme-challenge.${d}" TXT "@${ns}" \ | grep ^_acme|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \ | grep ^_acme|awk -F'"' '{ print $2}') else