diff --git a/getssl b/getssl index 5248dca..773a6fd 100755 --- a/getssl +++ b/getssl @@ -146,10 +146,11 @@ # 2016-10-31 generate EC account keys and tidy code. # 2016-10-31 fix warning message if cert doesn't exist (1.75) # 2016-10-31 remove only specified DNS token #161 (1.76) +# 2016-11-03 Reduce long lines, and remove echo from update (1.77) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} -VERSION="1.76" +VERSION="1.77" # defaults CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" @@ -267,14 +268,16 @@ check_challenge_completion() { # checks with the ACME server if our challenge is } check_getssl_upgrade() { # check if a more recent version of code is available available - latestcode=$(curl --silent "$CODE_LOCATION") + temp_upgrade="$(mktemp)" +# latestcode=$(curl --silent "$CODE_LOCATION") + curl --silent "$CODE_LOCATION" --output "$temp_upgrade" errcode=$? if [ $errcode -eq 60 ]; then error_exit "your version of curl needs updating, as it does not support SNI (multiple SSL domains on a single IP)" elif [ $errcode -gt 0 ]; then error_exit "curl error : $errcode" fi - latestversion=$(echo "$latestcode" | awk -F '"' '$1 == "VERSION=" {print $2}') + latestversion=$(awk -F '"' '$1 == "VERSION=" {print $2}' "$temp_upgrade") latestvdec=$(echo "$latestversion"| tr -d '.') localvdec=$(echo "$VERSION"| tr -d '.' ) debug "current code is version ${VERSION}" @@ -282,17 +285,14 @@ check_getssl_upgrade() { # check if a more recent version of code is available a # use a default of 0 for cases where the latest code has not been obtained. if [ "${latestvdec:-0}" -gt "$localvdec" ]; then if [ ${_UPGRADE} -eq 1 ]; then - temp_upgrade="$(mktemp)" - echo "$latestcode" > "$temp_upgrade" install "$0" "${0}.v${VERSION}" install -m 700 "$temp_upgrade" "$0" - rm -f "$temp_upgrade" if [ ${_MUTE} -eq 0 ]; then echo "Updated getssl from v${VERSION} to v${latestversion}" echo "these update notification can be turned off using the -Q option" echo "" echo "Updates are;" - echo "$latestcode" | awk "/\(${VERSION}\)$/ {s=1} s; /\(${latestversion}\)$/ {s=0}" | awk '{if(NR>1)print}' + awk "/\(${VERSION}\)$/ {s=1} s; /\(${latestversion}\)$/ {s=0}" "$temp_upgrade" | awk '{if(NR>1)print}' echo "" fi eval "$ORIGCMD" @@ -304,6 +304,7 @@ check_getssl_upgrade() { # check if a more recent version of code is available a info "" fi fi + rm -f "$temp_upgrade" } clean_up() { # Perform pre-exit housekeeping @@ -398,10 +399,13 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) debug "domain csr exists at - $csr_file" # check all domains in config are in csr alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/ //g; y/,/\n/' | sort -u) - domains_in_csr=$(openssl req -text -noout -in "$csr_file" | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' | sort -u) + domains_in_csr=$(openssl req -text -noout -in "$csr_file" \ + | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ + | sort -u) for d in $alldomains; do if [ "$(echo "${domains_in_csr}"| grep "^${d}$")" != "${d}" ]; then - info "existing csr at $csr_file does not contain ${d} - re-create-csr .... $(echo "${domains_in_csr}"| grep "^${d}$")" + info "existing csr at $csr_file does not contain ${d} - re-create-csr"\ + ".... $(echo "${domains_in_csr}"| grep "^${d}$")" _RECREATE_CSR=1 fi done @@ -497,7 +501,9 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n gad_s="$PUBLIC_DNS_SERVER" # start with PUBLIC_DNS_SERVER if [[ "$os" == "cygwin" ]]; then - all_auth_dns_servers=$(nslookup -type=soa "${d}" ${PUBLIC_DNS_SERVER} 2>/dev/null| grep "primary name server" | awk '{print $NF}') + all_auth_dns_servers=$(nslookup -type=soa "${d}" ${PUBLIC_DNS_SERVER} 2>/dev/null \ + | grep "primary name server" \ + | awk '{print $NF}') if [ -z "$all_auth_dns_servers" ]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" fi @@ -568,7 +574,11 @@ get_certificate() { # get certificate for csr, if all domains validated. fi # get a copy of the CA certificate. - IssuerData=$(grep -i '^Link' "$CURL_HEADER" | cut -d " " -f 2| cut -d ';' -f 1 | sed 's///g') + IssuerData=$(grep -i '^Link' "$CURL_HEADER" \ + | cut -d " " -f 2\ + | cut -d ';' -f 1 \ + | sed 's///g') if [ "$IssuerData" ] ; then echo -----BEGIN CERTIFICATE----- > "$gc_cafile" curl --silent "$IssuerData" | openssl base64 -e >> "$gc_cafile" @@ -610,8 +620,16 @@ get_os() { # function to get the current Operating System get_signing_params() { # get signing parameters from key skey=$1 if [ "$(grep -c "RSA PRIVATE KEY" "$skey")" -gt 0 ]; then # RSA key - pub_exp64=$(openssl rsa -in "${skey}" -noout -text | grep publicExponent | grep -oE "0x[a-f0-9]+" | cut -d'x' -f2 | hex2bin | urlbase64) - pub_mod64=$(openssl rsa -in "${skey}" -noout -modulus | cut -d'=' -f2 | hex2bin | urlbase64) + pub_exp64=$(openssl rsa -in "${skey}" -noout -text \ + | grep publicExponent \ + | grep -oE "0x[a-f0-9]+" \ + | cut -d'x' -f2 \ + | hex2bin \ + | urlbase64) + pub_mod64=$(openssl rsa -in "${skey}" -noout -modulus \ + | cut -d'=' -f2 \ + | hex2bin \ + | urlbase64) jwk='{"e":"'"${pub_exp64}"'","kty":"RSA","n":"'"${pub_mod64}"'"}' jwkalg="RS256" @@ -619,7 +637,9 @@ get_signing_params() { # get signing parameters from key elif [ "$(grep -c "EC PRIVATE KEY" "$skey")" -gt 0 ]; then # Elliptic curve key. crv="$(openssl ec -in "$skey" -noout -text 2>/dev/null | awk '$2 ~ "CURVE:" {print $3}')" if [ -z "$crv" ]; then - gsp_keytype="$(openssl ec -in "$skey" -noout -text 2>/dev/null | grep "^ASN1 OID:" | awk '{print $3}')" + gsp_keytype="$(openssl ec -in "$skey" -noout -text 2>/dev/null \ + | grep "^ASN1 OID:" \ + | awk '{print $3}')" case "$gsp_keytype" in prime256v1) crv="P-256" ;; secp384r1) crv="P-384" ;; @@ -633,7 +653,9 @@ get_signing_params() { # get signing parameters from key P-521) jwkalg="ES512" ; signalg="sha512" ;; *) error_exit "invalid curve algorithm type $crv";; esac - pubtext="$(openssl ec -in "$skey" -noout -text 2>/dev/null | awk '/^pub:/{p=1;next}/^ASN1 OID:/{p=0}p' | tr -d ": \n\r")" + pubtext="$(openssl ec -in "$skey" -noout -text 2>/dev/null \ + | awk '/^pub:/{p=1;next}/^ASN1 OID:/{p=0}p' \ + | tr -d ": \n\r")" mid=$(( (${#pubtext} -2) / 2 + 2 )) debug "pubtext = $pubtext" x64=$(echo "$pubtext" | cut -b 3-$mid | hex2bin | urlbase64) @@ -669,7 +691,7 @@ help_message() { # print out the help message -h, --help Display this help message and exit -q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded) -Q, --mute Like -q, but mutes notification about successful upgrade - -r, --revoke cert key [CA_server] Revoke a certificate ( the cert and key are required) + -r, --revoke cert key [CA_server] Revoke a certificate (the cert and key are required) -u, --upgrade Upgrade getssl if a more recent version is available -U, --nocheck Do not check if a more recent version is available -w working_dir Working directory @@ -831,12 +853,15 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p sign_string "$(printf '%s' "${protected64}.${payload64}")" "${ACCOUNT_KEY}" "$signalg" # Send header + extended header + payload + signature to the acme-server - body='{"header": '"${header}"', "protected": "'"${protected64}"'", "payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}' - debug "data for account registration = $body" + body="{\"header\": ${header}," + body+="\"protected\": \"${protected64}\"," + body+="\"payload\": \"${payload64}\"," + body+="\"signature\": \"${signed64}\"}" + debug "header, payload and signature = $body" code="500" loop_limit=5 - while [ $code -eq 500 ]; do + while [[ "$code" -eq 500 ]]; do if [ "$needbase64" ] ; then response=$($CURL -X POST --data "$body" "$url" | urlbase64) else @@ -848,10 +873,11 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p debug response "$response" code=$(awk ' $1 ~ "^HTTP" {print $2}' "$CURL_HEADER" | tail -1) debug code "$code" - response_status=$(json_get "$response" status | head -1| awk -F'"' '{print $2}') + response_status=$(json_get "$response" status \ + | head -1| awk -F'"' '{print $2}') debug "response status = $response_status" - if [ "$code" -eq 500 ]; then + if [[ "$code" -eq 500 ]]; then info "error on acme server - trying again ...." sleep 2 loop_limit=$((loop_limit - 1)) @@ -935,7 +961,8 @@ urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and } usage() { # program usage - echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] domain" + echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet]"\ + "[-Q|--mute] [-u|--upgrade] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] domain" } write_domain_template() { # write out a template file for a domain. @@ -1234,7 +1261,8 @@ if [ ${_CREATE_CONFIG} -eq 1 ]; then 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) + EX_CERT=$(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \ + | openssl x509 2>/dev/null) EX_SANS="www.${DOMAIN}" if [ ! -z "${EX_CERT}" ]; then EX_SANS=$(echo "$EX_CERT" | openssl x509 -noout -text 2>/dev/null| grep "Subject Alternative Name" -A2 \ @@ -1314,7 +1342,8 @@ fi if [[ "${CHECK_REMOTE}" == "true" ]] && [ $_FORCE_RENEW -eq 0 ]; then debug "getting certificate for $DOMAIN from remote server" # 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=$(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ + | 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) @@ -1326,7 +1355,9 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [ $_FORCE_RENEW -eq 0 ]; then debug "certificate on server is same as the local cert" else # check if the certificate is for the right domain - EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' | sort -u | grep "^$DOMAIN\$") + EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text \ + | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ + | sort -u | grep "^$DOMAIN\$") if [ "$EX_CERT_DOMAIN" == "$DOMAIN" ]; then # check renew-date on ex_cert and compare to local ( if local exists) enddate_ex=$(echo "$EX_CERT" | openssl x509 -noout -enddate 2>/dev/null| cut -d= -f 2-) @@ -1559,7 +1590,10 @@ for d in $alldomains; do debug keyauthorization "$keyauthorization" #create signed authorization key from token. - auth_key=$(printf '%s' "$keyauthorization" | openssl sha -sha256 -binary | openssl base64 -e | tr -d '\n\r' | sed -e 's:=*$::g' -e 'y:+/:-_:') + auth_key=$(printf '%s' "$keyauthorization" | openssl sha -sha256 -binary \ + | openssl base64 -e \ + | tr -d '\n\r' \ + | sed -e 's:=*$::g' -e 'y:+/:-_:') debug auth_key "$auth_key" debug "adding dns via command: $DNS_ADD_COMMAND $d $auth_key" @@ -1669,9 +1703,12 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then check_dns="fail" while [ "$check_dns" == "fail" ]; do if [[ "$os" == "cygwin" ]]; then - check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" | grep ^_acme -A2| grep '"'|awk -F'"' '{ print $2}') + check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ + | grep ^_acme -A2\ + | grep '"'|awk -F'"' '{ print $2}') else - check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" | grep ^_acme|awk -F'"' '{ print $2}') + check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ + | grep ^_acme|awk -F'"' '{ print $2}') fi debug "expecting $auth_key" debug "${ns} gave ... $check_result"