diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 727ba315..be9d3aae 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -1,5 +1,6 @@ name: DNS on: + workflow_dispatch: push: paths: - 'dnsapi/*.sh' @@ -280,7 +281,7 @@ jobs: - uses: vmactions/openbsd-vm@v1 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' - prepare: pkg_add socat curl + prepare: pkg_add socat curl libiconv usesh: true copyback: false run: | diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 4afebaf0..c74e9d3e 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -26,7 +26,7 @@ jobs: Linux: strategy: matrix: - os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:7", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"] + os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"] runs-on: ubuntu-latest env: TEST_LOCAL: 1 diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index 3f8fdb62..b0326332 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -37,7 +37,7 @@ jobs: - name: Install tools run: sudo apt-get install -y socat - name: Run Pebble - run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d + run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker compose up -d - name: Set up Pebble run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4 - name: Clone acmetest diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index ea446d84..435fd6b5 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -15,6 +15,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + DOCKER_IMAGE: neilpang/acme.sh jobs: CheckToken: @@ -44,6 +46,11 @@ jobs: uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v2 + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5.5.1 + with: + images: ${DOCKER_IMAGE} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: login to docker hub @@ -51,8 +58,6 @@ jobs: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin - name: build and push the image run: | - DOCKER_IMAGE=neilpang/acme.sh - if [[ $GITHUB_REF == refs/tags/* ]]; then DOCKER_IMAGE_TAG=${GITHUB_REF#refs/tags/} fi @@ -66,8 +71,14 @@ jobs: fi fi + DOCKER_LABELS=() + while read -r label; do + DOCKER_LABELS+=(--label "${label}") + done <<<"${DOCKER_METADATA_OUTPUT_LABELS}" + docker buildx build \ --tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \ + "${DOCKER_LABELS[@]}" \ --output "type=image,push=true" \ --build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \ --platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386,linux/ppc64le,linux/s390x . diff --git a/.github/workflows/pr_notify.yml b/.github/workflows/pr_notify.yml index 3b0e3e4b..b6b03c67 100644 --- a/.github/workflows/pr_notify.yml +++ b/.github/workflows/pr_notify.yml @@ -1,4 +1,4 @@ -name: Check dns api +name: Check notify api on: pull_request_target: diff --git a/acme.sh b/acme.sh index d154cf77..e39a146b 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=3.0.8 +VER=3.1.0 PROJECT_NAME="acme.sh" @@ -231,11 +231,11 @@ _dlg_versions() { echo "$ACME_OPENSSL_BIN doesn't exist." fi - echo "apache:" + echo "Apache:" if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then $_APACHECTL -V 2>&1 else - echo "apache doesn't exist." + echo "Apache doesn't exist." fi echo "nginx:" @@ -672,8 +672,10 @@ _hex_dump() { #0 1 2 3 4 5 6 7 8 9 - _ . ~ #30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e +#_url_encode [upper-hex] the encoded hex will be upper-case if the argument upper-hex is followed #stdin stdout _url_encode() { + _upper_hex=$1 _hex_str=$(_hex_dump) _debug3 "_url_encode" _debug3 "_hex_str" "$_hex_str" @@ -883,6 +885,9 @@ _url_encode() { ;; #other hex *) + if [ "$_upper_hex" = "upper-hex" ]; then + _hex_code=$(printf "%s" "$_hex_code" | _upper_case) + fi printf '%%%s' "$_hex_code" ;; esac @@ -949,7 +954,7 @@ _getfile() { i="$(grep -n -- "$startline" "$filename" | cut -d : -f 1)" if [ -z "$i" ]; then - _err "Can not find start line: $startline" + _err "Cannot find start line: $startline" return 1 fi i="$(_math "$i" + 1)" @@ -957,7 +962,7 @@ _getfile() { j="$(grep -n -- "$endline" "$filename" | cut -d : -f 1)" if [ -z "$j" ]; then - _err "Can not find end line: $endline" + _err "Cannot find end line: $endline" return 1 fi j="$(_math "$j" - 1)" @@ -1065,7 +1070,7 @@ _sign() { if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then _err "Sign failed: $_sign_openssl" _err "Key file: $keyfile" - _err "Key content:$(wc -l <"$keyfile") lines" + _err "Key content: $(wc -l <"$keyfile") lines" return 1 fi _debug3 "_signedECText" "$_signedECText" @@ -1145,14 +1150,14 @@ _createkey() { length=2048 fi - _debug "Use length $length" + _debug "Using length $length" if ! [ -e "$f" ]; then if ! touch "$f" >/dev/null 2>&1; then _f_path="$(dirname "$f")" _debug _f_path "$_f_path" if ! mkdir -p "$_f_path"; then - _err "Can not create path: $_f_path" + _err "Cannot create path: $_f_path" return 1 fi fi @@ -1163,11 +1168,11 @@ _createkey() { fi if _isEccKey "$length"; then - _debug "Using ec name: $eccname" + _debug "Using EC name: $eccname" if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else - _err "error ecc key name: $eccname" + _err "Error encountered for ECC key named $eccname" return 1 fi else @@ -1179,13 +1184,13 @@ _createkey() { if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else - _err "error rsa key: $length" + _err "Error encountered for RSA key of length $length" return 1 fi fi if [ "$?" != "0" ]; then - _err "Create key error." + _err "Key creation error." return 1 fi } @@ -1243,7 +1248,14 @@ _createcsr() { _debug2 csr "$csr" _debug2 csrconf "$csrconf" - printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\nextendedKeyUsage=serverAuth,clientAuth\n" >"$csrconf" + printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]" >"$csrconf" + + if [ "$Le_ExtKeyUse" ]; then + _savedomainconf Le_ExtKeyUse "$Le_ExtKeyUse" + printf "\nextendedKeyUsage=$Le_ExtKeyUse\n" >>"$csrconf" + else + printf "\nextendedKeyUsage=serverAuth,clientAuth\n" >>"$csrconf" + fi if [ "$acmeValidationv1" ]; then domainlist="$(_idn "$domainlist")" @@ -1452,7 +1464,7 @@ toPkcs() { _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword" if [ "$?" = "0" ]; then - _info "Success, Pfx is exported to: $CERT_PFX_PATH" + _info "Success, PFX has been exported to: $CERT_PFX_PATH" fi } @@ -1496,7 +1508,7 @@ _create_account_key() { length=$1 if [ -z "$length" ] || [ "$length" = "$NO_VALUE" ]; then - _debug "Use default length $DEFAULT_ACCOUNT_KEY_LENGTH" + _debug "Using default length $DEFAULT_ACCOUNT_KEY_LENGTH" length="$DEFAULT_ACCOUNT_KEY_LENGTH" fi @@ -1505,15 +1517,15 @@ _create_account_key() { mkdir -p "$CA_DIR" if [ -s "$ACCOUNT_KEY_PATH" ]; then - _info "Account key exists, skip" + _info "Account key exists, skipping" return 0 else #generate account key if _createkey "$length" "$ACCOUNT_KEY_PATH"; then - _info "Create account key ok." + _info "Account key creation OK." return 0 else - _err "Create account key error." + _err "Account key creation error." return 1 fi fi @@ -1532,7 +1544,7 @@ createDomainKey() { _cdl=$2 if [ -z "$_cdl" ]; then - _debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH" + _debug "Using DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH" _cdl="$DEFAULT_DOMAIN_KEY_LENGTH" fi @@ -1544,16 +1556,16 @@ createDomainKey() { _info "The domain key is here: $(__green $CERT_KEY_PATH)" return 0 else - _err "Can not create domain key" + _err "Cannot create domain key" return 1 fi else if [ "$_ACME_IS_RENEW" ]; then - _info "Domain key exists, skip" + _info "Domain key exists, skipping" return 0 else - _err "Domain key exists, do you want to overwrite the key?" - _err "Add '--force', and try again." + _err "Domain key exists, do you want to overwrite it?" + _err "If so, add '--force' and try again." return 1 fi fi @@ -1562,7 +1574,7 @@ createDomainKey() { # domain domainlist isEcc createCSR() { - _info "Creating csr" + _info "Creating CSR" if [ -z "$1" ]; then _usage "Usage: $PROJECT_ENTRY --create-csr --domain [--domain ...] [--ecc]" return @@ -1575,13 +1587,13 @@ createCSR() { _initpath "$domain" "$_isEcc" if [ -f "$CSR_PATH" ] && [ "$_ACME_IS_RENEW" ] && [ -z "$FORCE" ]; then - _info "CSR exists, skip" + _info "CSR exists, skipping" return fi if [ ! -f "$CERT_KEY_PATH" ]; then - _err "The key file is not found: $CERT_KEY_PATH" - _err "Please create the key file first." + _err "This key file was not found: $CERT_KEY_PATH" + _err "Please create it first." return 1 fi _createcsr "$domain" "$domainlist" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF" @@ -1725,7 +1737,7 @@ _calcjwk() { __ECC_KEY_LEN=512 ;; *) - _err "ECC oid : $crv_oid" + _err "ECC oid: $crv_oid" return 1 ;; esac @@ -1768,7 +1780,7 @@ _calcjwk() { JWK_HEADERPLACE_PART1='{"nonce": "' JWK_HEADERPLACE_PART2='", "alg": "ES'$__ECC_KEY_LEN'"' else - _err "Only RSA or EC key is supported. keyfile=$keyfile" + _err "Only RSA or EC keys are supported. keyfile=$keyfile" _debug2 "$(cat "$keyfile")" return 1 fi @@ -1802,7 +1814,7 @@ _date2time() { if da="$(echo "$1" | tr -d "Z" | tr "T" ' ')" perl -MTime::Piece -e 'print Time::Piece->strptime($ENV{da}, "%Y-%m-%d %H:%M:%S")->epoch, "\n";' 2>/dev/null; then return fi - _err "Can not parse _date2time $1" + _err "Cannot parse _date2time $1" return 1 } @@ -1826,7 +1838,7 @@ _mktemp() { echo "/$LE_TEMP_DIR/wefADf24sf.$(_time).tmp" return 0 fi - _err "Can not create temp file." + _err "Cannot create temp file." } #clear all the https envs to cause _inithttp() to run next time. @@ -2015,7 +2027,7 @@ _post() { _ret="$?" if [ "$_ret" = "8" ]; then _ret=0 - _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." + _debug "wget returned 8 as the server returned a 'Bad Request' response. Let's process the response later." fi if [ "$_ret" != "0" ]; then _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" @@ -2029,7 +2041,7 @@ _post() { _sed_i 's/^ //g' "$HTTP_HEADER" else _ret="$?" - _err "Neither curl nor wget is found, can not do $httpmethod." + _err "Neither curl nor wget have been found, cannot make $httpmethod request." fi _debug "_ret" "$_ret" printf "%s" "$response" @@ -2098,14 +2110,14 @@ _get() { ret=$? if [ "$ret" = "8" ]; then ret=0 - _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." + _debug "wget returned 8 as the server returned a 'Bad Request' response. Let's process the response later." fi if [ "$ret" != "0" ]; then _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret" fi else ret=$? - _err "Neither curl nor wget is found, can not do GET." + _err "Neither curl nor wget have been found, cannot make GET request." fi _debug "ret" "$ret" return $ret @@ -2137,7 +2149,7 @@ _send_signed_request() { if [ -z "$keyfile" ]; then keyfile="$ACCOUNT_KEY_PATH" fi - _debug "=======Begin Send Signed Request=======" + _debug "=======Sending Signed Request=======" _debug url "$url" _debug payload "$payload" @@ -2183,7 +2195,7 @@ _send_signed_request() { fi _debug2 _CACHED_NONCE "$_CACHED_NONCE" if [ "$?" != "0" ]; then - _err "Can not connect to $nonceurl to get nonce." + _err "Cannot connect to $nonceurl to get nonce." return 1 fi else @@ -2226,7 +2238,7 @@ _send_signed_request() { _CACHED_NONCE="" if [ "$?" != "0" ]; then - _err "Can not post to $url" + _err "Cannot make POST request to $url" return 1 fi @@ -2258,21 +2270,21 @@ _send_signed_request() { _sleep_overload_retry_sec=5 fi if [ $_sleep_overload_retry_sec -le 600 ]; then - _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." + _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping for $_sleep_overload_retry_sec seconds." _sleep $_sleep_overload_retry_sec continue else - _info "The retryafter=$_retryafter is too large > 600, not retry anymore." + _info "The retryafter=$_retryafter value is too large (> 600), will not retry anymore." fi fi if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then - _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." + _info "It seems the CA server is busy now, let's wait and retry. Sleeping for $_sleep_retry_sec seconds." _CACHED_NONCE="" _sleep $_sleep_retry_sec continue fi if _contains "$_body" "The Replay Nonce is not recognized"; then - _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _info "The replay nonce is not valid, let's get a new one. Sleeping for $_sleep_retry_sec seconds." _CACHED_NONCE="" _sleep $_sleep_retry_sec continue @@ -2344,7 +2356,7 @@ _save_conf() { if [ "$_s_c_f" ]; then _setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'" else - _err "config file is empty, can not save $_sdkey=$_sdvalue" + _err "Config file is empty, cannot save $_sdkey=$_sdvalue" fi } @@ -2354,9 +2366,9 @@ _clear_conf() { _sdkey="$2" if [ "$_c_c_f" ]; then _conf_data="$(cat "$_c_c_f")" - echo "$_conf_data" | sed "s/^$_sdkey *=.*$//" >"$_c_c_f" + echo "$_conf_data" | sed "/^$_sdkey *=.*$/d" >"$_c_c_f" else - _err "config file is empty, can not clear" + _err "Config file is empty, cannot clear" fi } @@ -2374,7 +2386,7 @@ _read_conf() { fi printf "%s" "$_sdv" else - _debug "config file is empty, can not read $_sdkey" + _debug "Config file is empty, cannot read $_sdkey" fi } @@ -2592,7 +2604,7 @@ _starttlsserver() { #create key TLS_KEY if ! _createkey "2048" "$TLS_KEY"; then - _err "Create tls validation key error." + _err "Error creating TLS validation key." return 1 fi @@ -2602,13 +2614,13 @@ _starttlsserver() { alt="$alt,$san_b" fi if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$acmeValidationv1"; then - _err "Create tls validation csr error." + _err "Error creating TLS validation CSR." return 1 fi #self signed if ! _signcsr "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$TLS_CERT"; then - _err "Create tls validation cert error." + _err "Error creating TLS validation cert." return 1 fi @@ -2662,7 +2674,7 @@ _conapath() { __initHome() { if [ -z "$_SCRIPT_HOME" ]; then if _exists readlink && _exists dirname; then - _debug "Lets find script dir." + _debug "Let's find the script directory." _debug "_SCRIPT_" "$_SCRIPT_" _script="$(_readlink "$_SCRIPT_")" _debug "_script" "$_script" @@ -2671,7 +2683,7 @@ __initHome() { if [ -d "$_script_home" ]; then export _SCRIPT_HOME="$_script_home" else - _err "It seems the script home is not correct:$_script_home" + _err "It seems the script home is not correct: $_script_home" fi fi fi @@ -2686,7 +2698,7 @@ __initHome() { # fi if [ -z "$LE_WORKING_DIR" ]; then - _debug "Using default home:$DEFAULT_INSTALL_HOME" + _debug "Using default home: $DEFAULT_INSTALL_HOME" LE_WORKING_DIR="$DEFAULT_INSTALL_HOME" fi export LE_WORKING_DIR @@ -2694,7 +2706,7 @@ __initHome() { if [ -z "$LE_CONFIG_HOME" ]; then LE_CONFIG_HOME="$LE_WORKING_DIR" fi - _debug "Using config home:$LE_CONFIG_HOME" + _debug "Using config home: $LE_CONFIG_HOME" export LE_CONFIG_HOME _DEFAULT_ACCOUNT_CONF_PATH="$LE_CONFIG_HOME/account.conf" @@ -2731,7 +2743,7 @@ _clearAPI() { #server _initAPI() { _api_server="${1:-$ACME_DIRECTORY}" - _debug "_init api for server: $_api_server" + _debug "_init API for server: $_api_server" MAX_API_RETRY_TIMES=10 _sleep_retry_sec=10 @@ -2741,8 +2753,8 @@ _initAPI() { response=$(_get "$_api_server") if [ "$?" != "0" ]; then _debug2 "response" "$response" - _info "Can not init api for: $_api_server." - _info "Sleep $_sleep_retry_sec and retry." + _info "Cannot init API for: $_api_server." + _info "Sleeping for $_sleep_retry_sec seconds and retrying." _sleep "$_sleep_retry_sec" continue fi @@ -2780,13 +2792,13 @@ _initAPI() { if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then return 0 fi - _info "Sleep $_sleep_retry_sec and retry." + _info "Sleeping for $_sleep_retry_sec seconds and retrying." _sleep "$_sleep_retry_sec" done if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then return 0 fi - _err "Can not init api, for $_api_server" + _err "Cannot init API for $_api_server" return 1 } @@ -2918,7 +2930,7 @@ _initpath() { DOMAIN_PATH="$domainhomeecc" elif [ -z "$__SELECTED_RSA_KEY" ]; then if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then - _info "The domain '$domain' seems to have a ECC cert already, lets use ecc cert." + _info "The domain '$domain' seems to already have an ECC cert, let's use it." DOMAIN_PATH="$domainhomeecc" fi fi @@ -2981,7 +2993,7 @@ _apachePath() { if _exists apache2ctl; then _APACHECTL="apache2ctl" else - _err "'apachectl not found. It seems that apache is not installed, or you are not root user.'" + _err "'apachectl not found. It seems that Apache is not installed or you are not root.'" _err "Please use webroot mode to try again." return 1 fi @@ -3000,7 +3012,7 @@ _apachePath() { _debug httpdconfname "$httpdconfname" if [ -z "$httpdconfname" ]; then - _err "Can not read apache config file." + _err "Cannot read Apache config file." return 1 fi @@ -3017,7 +3029,7 @@ _apachePath() { _debug httpdconf "$httpdconf" _debug httpdconfname "$httpdconfname" if [ ! -f "$httpdconf" ]; then - _err "Apache Config file not found" "$httpdconf" + _err "Apache config file not found" "$httpdconf" return 1 fi return 0 @@ -3040,7 +3052,7 @@ _restoreApache() { cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf" _debug "Restored: $httpdconf." if ! $_APACHECTL -t; then - _err "Sorry, restore apache config error, please contact me." + _err "Sorry, there's been an error restoring the Apache config. Please ask for support on $PROJECT." return 1 fi _debug "Restored successfully." @@ -3055,26 +3067,26 @@ _setApache() { fi #test the conf first - _info "Checking if there is an error in the apache config file before starting." + _info "Checking if there is an error in the Apache config file before starting." if ! $_APACHECTL -t >/dev/null; then - _err "The apache config file has error, please fix it first, then try again." - _err "Don't worry, there is nothing changed to your system." + _err "The Apache config file has errors, please fix them first then try again." + _err "Don't worry, no changes to your system have been made." return 1 else _info "OK" fi #backup the conf - _debug "Backup apache config file" "$httpdconf" + _debug "Backing up Apache config file" "$httpdconf" if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then - _err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed." - _err "This might be a bug of $PROJECT_NAME , please report issue: $PROJECT" + _err "Cannot backup Apache config file, aborting. Don't worry, the Apache config has not been changed." + _err "This might be an $PROJECT_NAME bug, please open an issue on $PROJECT" return 1 fi - _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname" - _info "In case there is an error that can not be restored automatically, you may try restore it yourself." - _info "The backup file will be deleted on success, just forget it." + _info "Config file $httpdconf has been backed up to $APACHE_CONF_BACKUP_DIR/$httpdconfname" + _info "In case an error causes it to not be restored automatically, you can restore it yourself." + _info "You do not need to do anything on success, as the backup file will automatically be deleted." #add alias @@ -3104,11 +3116,11 @@ Allow from all _msg="$($_APACHECTL -t 2>&1)" if [ "$?" != "0" ]; then - _err "Sorry, apache config error" + _err "Sorry, an Apache config error has occurred" if _restoreApache; then - _err "The apache config file is restored." + _err "The Apache config file has been restored." else - _err "Sorry, the apache config file can not be restored, please report bug." + _err "Sorry, the Apache config file cannot be restored, please open an issue on $PROJECT." fi return 1 fi @@ -3119,7 +3131,7 @@ Allow from all fi if ! $_APACHECTL graceful; then - _err "$_APACHECTL graceful error, please contact me." + _err "$_APACHECTL graceful error, please open an issue on $PROJECT." _restoreApache return 1 fi @@ -3143,10 +3155,10 @@ _setNginx() { _start_f="$(echo "$_croot" | cut -d : -f 2)" _debug _start_f "$_start_f" if [ -z "$_start_f" ]; then - _debug "find start conf from nginx command" + _debug "Finding config using the nginx command" if [ -z "$NGINX_CONF" ]; then if ! _exists "nginx"; then - _err "nginx command is not found." + _err "nginx command not found." return 1 fi NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "\-\-conf-path=[^ ]* " | tr -d " ")" @@ -3154,7 +3166,7 @@ _setNginx() { NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)" _debug NGINX_CONF "$NGINX_CONF" if [ -z "$NGINX_CONF" ]; then - _err "Can not find nginx conf." + _err "Cannot find nginx config." NGINX_CONF="" return 1 fi @@ -3163,16 +3175,16 @@ _setNginx() { NGINX_CONF="" return 1 fi - _debug "Found nginx conf file:$NGINX_CONF" + _debug "Found nginx config file: $NGINX_CONF" fi _start_f="$NGINX_CONF" fi - _debug "Start detect nginx conf for $_d from:$_start_f" + _debug "Detecting nginx conf for $_d from: $_start_f" if ! _checkConf "$_d" "$_start_f"; then - _err "Can not find conf file for domain $d" + _err "Cannot find config file for domain $d" return 1 fi - _info "Found conf file: $FOUND_REAL_NGINX_CONF" + _info "Found config file: $FOUND_REAL_NGINX_CONF" _ln=$FOUND_REAL_NGINX_CONF_LN _debug "_ln" "$_ln" @@ -3182,7 +3194,7 @@ _setNginx() { _start_tag="$(sed -n "$_lnn,${_lnn}p" "$FOUND_REAL_NGINX_CONF")" _debug "_start_tag" "$_start_tag" if [ "$_start_tag" = "$NGINX_START" ]; then - _info "The domain $_d is already configured, skip" + _info "The domain $_d is already configured, skipping" FOUND_REAL_NGINX_CONF="" return 0 fi @@ -3191,28 +3203,28 @@ _setNginx() { _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf" _debug _backup_conf "$_backup_conf" BACKUP_NGINX_CONF="$_backup_conf" - _info "Backup $FOUND_REAL_NGINX_CONF to $_backup_conf" + _info "Backing $FOUND_REAL_NGINX_CONF up to $_backup_conf" if ! cp "$FOUND_REAL_NGINX_CONF" "$_backup_conf"; then - _err "backup error." + _err "Backup error." FOUND_REAL_NGINX_CONF="" return 1 fi if ! _exists "nginx"; then - _err "nginx command is not found." + _err "nginx command not found." return 1 fi - _info "Check the nginx conf before setting up." + _info "Checking the nginx config before setting up." if ! nginx -t >/dev/null 2>&1; then - _err "It seems that nginx conf is not correct, cannot continue." + _err "It seems that the nginx config is not correct, cannot continue." return 1 fi - _info "OK, Set up nginx config file" + _info "OK, setting up the nginx config file" if ! sed -n "1,${_ln}p" "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"; then cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" - _err "write nginx conf error, but don't worry, the file is restored to the original version." + _err "Error writing nginx config. Restoring it to its original version." return 1 fi @@ -3226,20 +3238,20 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! sed -n "${_lnn},99999p" "$_backup_conf" >>"$FOUND_REAL_NGINX_CONF"; then cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" - _err "write nginx conf error, but don't worry, the file is restored." + _err "Error writing nginx config. Restoring it to its original version." return 1 fi _debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)" - _info "nginx conf is done, let's check it again." + _info "nginx config has been written, let's check it again." if ! nginx -t >/dev/null 2>&1; then - _err "It seems that nginx conf was broken, let's restore." + _err "There seems to be a problem with the nginx config, let's restore it to its original version." cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi - _info "Reload nginx" + _info "Reloading nginx" if ! nginx -s reload >/dev/null 2>&1; then - _err "It seems that nginx reload error, let's restore." + _err "There seems to be a problem with the nginx config, let's restore it to its original version." cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -3251,7 +3263,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { _checkConf() { _d="$1" _c_file="$2" - _debug "Start _checkConf from:$_c_file" + _debug "Starting _checkConf from: $_c_file" if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then _debug "wildcard" for _w_f in $2; do @@ -3264,14 +3276,14 @@ _checkConf() { elif [ -f "$2" ]; then _debug "single" if _isRealNginxConf "$1" "$2"; then - _debug "$2 is found." + _debug "$2 found." FOUND_REAL_NGINX_CONF="$2" return 0 fi if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then - _debug "Try include files" + _debug "Trying include files" for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do - _debug "check included $included" + _debug "Checking included $included" if ! _startswith "$included" "/" && _exists dirname; then _relpath="$(dirname "$2")" _debug "_relpath" "$_relpath" @@ -3347,7 +3359,7 @@ _isRealNginxConf() { #restore all the nginx conf _restoreNginx() { if [ -z "$NGINX_RESTORE_VLIST" ]; then - _debug "No need to restore nginx, skip." + _debug "No need to restore nginx config, skipping." return fi _debug "_restoreNginx" @@ -3362,9 +3374,9 @@ _restoreNginx() { cat "$_ngbackupconf" >"$_ngconf" done - _info "Reload nginx" + _info "Reloading nginx" if ! nginx -s reload >/dev/null; then - _err "It seems that nginx reload error, please report bug." + _err "An error occurred while reloading nginx, please open an issue on $PROJECT." return 1 fi return 0 @@ -3389,7 +3401,7 @@ _clearupdns() { _debug "dns_entries" "$dns_entries" if [ -z "$dns_entries" ]; then - _debug "skip dns." + _debug "Skipping dns." return fi _info "Removing DNS records." @@ -3412,7 +3424,7 @@ _clearupdns() { fi if [ -z "$d_api" ]; then - _info "Not Found domain api file: $d_api" + _info "Domain API file was not found: $d_api" continue fi @@ -3422,21 +3434,21 @@ _clearupdns() { ( if ! . "$d_api"; then - _err "Load file $d_api error. Please check your api file and try again." + _err "Error loading file $d_api. Please check your API file and try again." return 1 fi rmcommand="${_currentRoot}_rm" if ! _exists "$rmcommand"; then - _err "It seems that your api file doesn't define $rmcommand" + _err "It seems that your API file doesn't define $rmcommand" return 1 fi _info "Removing txt: $txt for domain: $txtdomain" if ! $rmcommand "$txtdomain" "$txt"; then - _err "Error removing txt for domain:$txtdomain" + _err "Error removing txt for domain: $txtdomain" return 1 fi - _info "Removed: Success" + _info "Successfully removed" ) done @@ -3446,7 +3458,7 @@ _clearupdns() { _clearupwebbroot() { __webroot="$1" if [ -z "$__webroot" ]; then - _debug "no webroot specified, skip" + _debug "No webroot specified, skipping" return 0 fi @@ -3458,12 +3470,12 @@ _clearupwebbroot() { elif [ "$2" = '3' ]; then _rmpath="$__webroot/.well-known/acme-challenge/$3" else - _debug "Skip for removelevel:$2" + _debug "Skipping for removelevel: $2" fi if [ "$_rmpath" ]; then if [ "$DEBUG" ]; then - _debug "Debugging, skip removing: $_rmpath" + _debug "Debugging, not removing: $_rmpath" else rm -rf "$_rmpath" fi @@ -3484,13 +3496,13 @@ _on_before_issue() { _debug _chk_alt_domains "$_chk_alt_domains" #run pre hook if [ "$_chk_pre_hook" ]; then - _info "Run pre hook:'$_chk_pre_hook'" + _info "Runing pre hook:'$_chk_pre_hook'" if ! ( export Le_Domain="$_chk_main_domain" export Le_Alt="$_chk_alt_domains" cd "$DOMAIN_PATH" && eval "$_chk_pre_hook" ); then - _err "Error when run pre hook." + _err "Error occurred when running pre hook." return 1 fi fi @@ -3515,7 +3527,7 @@ _on_before_issue() { if [ -z "$d" ]; then break fi - _debug "Check for domain" "$d" + _debug "Checking for domain" "$d" _currentRoot="$(_getfield "$_chk_web_roots" $_index)" _debug "_currentRoot" "$_currentRoot" _index=$(_math $_index + 1) @@ -3562,7 +3574,7 @@ _on_before_issue() { if _hasfield "$_chk_web_roots" "apache"; then if ! _setApache; then - _err "set up apache error. Report error to me." + _err "Error setting up Apache. Please open an issue on $PROJECT." return 1 fi else @@ -3579,17 +3591,17 @@ _on_issue_err() { if [ "$LOG_FILE" ]; then _err "Please check log file for more details: $LOG_FILE" else - _err "Please add '--debug' or '--log' to check more details." + _err "Please add '--debug' or '--log' to see more information." _err "See: $_DEBUG_WIKI" fi #run the post hook if [ "$_chk_post_hook" ]; then - _info "Run post hook:'$_chk_post_hook'" + _info "Running post hook: '$_chk_post_hook'" if ! ( cd "$DOMAIN_PATH" && eval "$_chk_post_hook" ); then - _err "Error when run post hook." + _err "Error encountered while running post hook." return 1 fi fi @@ -3628,7 +3640,7 @@ _on_issue_success() { #run the post hook if [ "$_chk_post_hook" ]; then - _info "Run post hook:'$_chk_post_hook'" + _info "Running post hook:'$_chk_post_hook'" if ! ( export CERT_PATH export CERT_KEY_PATH @@ -3637,14 +3649,14 @@ _on_issue_success() { export Le_Domain="$_main_domain" cd "$DOMAIN_PATH" && eval "$_chk_post_hook" ); then - _err "Error when run post hook." + _err "Error encountered while running post hook." return 1 fi fi #run renew hook if [ "$_ACME_IS_RENEW" ] && [ "$_chk_renew_hook" ]; then - _info "Run renew hook:'$_chk_renew_hook'" + _info "Running renew hook: '$_chk_renew_hook'" if ! ( export CERT_PATH export CERT_KEY_PATH @@ -3653,7 +3665,7 @@ _on_issue_success() { export Le_Domain="$_main_domain" cd "$DOMAIN_PATH" && eval "$_chk_renew_hook" ); then - _err "Error when run renew hook." + _err "Error encountered while running renew hook." return 1 fi fi @@ -3709,7 +3721,7 @@ _regAccount() { if [ ! -f "$ACCOUNT_KEY_PATH" ]; then if ! _create_account_key "$_reg_length"; then - _err "Create account key error." + _err "Error creating account key." return 1 fi fi @@ -3732,7 +3744,7 @@ _regAccount() { if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then - _info "No EAB credentials found for ZeroSSL, let's get one" + _info "No EAB credentials found for ZeroSSL, let's obtain them" if [ -z "$_email" ]; then _info "$(__green "$PROJECT_NAME is using ZeroSSL as default CA now.")" _info "$(__green "Please update your account with an email address first.")" @@ -3743,20 +3755,20 @@ _regAccount() { _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT) if [ "$?" != "0" ]; then _debug2 "$_eabresp" - _err "Can not get EAB credentials from ZeroSSL." + _err "Cannot get EAB credentials from ZeroSSL." return 1 fi _secure_debug2 _eabresp "$_eabresp" _eab_id="$(echo "$_eabresp" | tr ',}' '\n\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" _secure_debug2 _eab_id "$_eab_id" if [ -z "$_eab_id" ]; then - _err "Can not resolve _eab_id" + _err "Cannot resolve _eab_id" return 1 fi _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')" _secure_debug2 _eab_hmac_key "$_eab_hmac_key" if [ -z "$_eab_hmac_key" ]; then - _err "Can not resolve _eab_hmac_key" + _err "Cannot resolve _eab_hmac_key" return 1 fi _savecaconf CA_EAB_KEY_ID "$_eab_id" @@ -3793,7 +3805,7 @@ _regAccount() { _info "Registering account: $ACME_DIRECTORY" if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then - _err "Register account Error: $response" + _err "Error registering account: $response" return 1 fi @@ -3804,10 +3816,10 @@ _regAccount() { elif [ "$code" = '409' ] || [ "$code" = '200' ]; then _info "Already registered" elif [ "$code" = '400' ] && _contains "$response" 'The account is not awaiting external account binding'; then - _info "Already register EAB." + _info "EAB already registered" _eabAlreadyBound=1 else - _err "Register account Error: $response" + _err "Account registration error: $response" return 1 fi @@ -3816,7 +3828,7 @@ _regAccount() { _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" _debug "_accUri" "$_accUri" if [ -z "$_accUri" ]; then - _err "Can not find account id url." + _err "Cannot find account id url." _err "$responseHeaders" return 1 fi @@ -3831,7 +3843,7 @@ _regAccount() { _savecaconf CA_KEY_HASH "$CA_KEY_HASH" if [ "$code" = '403' ]; then - _err "It seems that the account key is already deactivated, please use a new account key." + _err "It seems that the account key has been deactivated, please use a new account key." return 1 fi @@ -3844,7 +3856,7 @@ updateaccount() { _initpath if [ ! -f "$ACCOUNT_KEY_PATH" ]; then - _err "Account key is not found at: $ACCOUNT_KEY_PATH" + _err "Account key not found at: $ACCOUNT_KEY_PATH" return 1 fi @@ -3852,8 +3864,7 @@ updateaccount() { _debug _accUri "$_accUri" if [ -z "$_accUri" ]; then - _err "The account url is empty, please run '--update-account' first to update the account info first," - _err "Then try again." + _err "The account URL is empty, please run '--update-account' first to update the account info, then try again." return 1 fi @@ -3875,8 +3886,11 @@ updateaccount() { if [ "$code" = '200' ]; then echo "$response" >"$ACCOUNT_JSON_PATH" _info "Account update success for $_accUri." + + ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)" + _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT" else - _info "Error. The account was not updated." + _info "An error occurred and the account was not updated." return 1 fi } @@ -3886,7 +3900,7 @@ deactivateaccount() { _initpath if [ ! -f "$ACCOUNT_KEY_PATH" ]; then - _err "Account key is not found at: $ACCOUNT_KEY_PATH" + _err "Account key not found at: $ACCOUNT_KEY_PATH" return 1 fi @@ -3894,8 +3908,7 @@ deactivateaccount() { _debug _accUri "$_accUri" if [ -z "$_accUri" ]; then - _err "The account url is empty, please run '--update-account' first to update the account info first," - _err "Then try again." + _err "The account URL is empty, please run '--update-account' first to update the account info, then try again." return 1 fi @@ -3907,13 +3920,13 @@ deactivateaccount() { _djson="{\"status\":\"deactivated\"}" if _send_signed_request "$_accUri" "$_djson" && _contains "$response" '"deactivated"'; then - _info "Deactivate account success for $_accUri." + _info "Successfully deactivated account $_accUri." _accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,') elif [ "$code" = "403" ]; then _info "The account is already deactivated." _accid=$(_getfield "$_accUri" "999" "/") else - _err "Deactivate: account failed for $_accUri." + _err "Account deactivation failed for $_accUri." return 1 fi @@ -3927,7 +3940,7 @@ deactivateaccount() { mv "$ACCOUNT_JSON_PATH" "$_deactivated_account_path/" mv "$ACCOUNT_KEY_PATH" "$_deactivated_account_path/" else - _err "Can not create dir: $_deactivated_account_path, try to remove the deactivated account key." + _err "Cannot create dir: $_deactivated_account_path, try to remove the deactivated account key." rm -f "$CA_CONF" rm -f "$ACCOUNT_JSON_PATH" rm -f "$ACCOUNT_KEY_PATH" @@ -3970,28 +3983,28 @@ __get_domain_new_authz() { _Max_new_authz_retry_times=5 _authz_i=0 while [ "$_authz_i" -lt "$_Max_new_authz_retry_times" ]; do - _debug "Try new-authz for the $_authz_i time." + _debug "Trying new-authz, attempt number $_authz_i." if ! _send_signed_request "${ACME_NEW_AUTHZ}" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_gdnd")\"}}"; then - _err "Can not get domain new authz." + _err "Cannot get new authz for domain." return 1 fi if _contains "$response" "No registration exists matching provided key"; then - _err "It seems there is an error, but it's recovered now, please try again." - _err "If you see this message for a second time, please report bug: $(__green "$PROJECT")" + _err "There has been an error, but it might now be resolved, please try again." + _err "If you see this message for a second time, please report this as a bug: $(__green "$PROJECT")" _clearcaconf "CA_KEY_HASH" break fi if ! _contains "$response" "An error occurred while processing your request"; then - _info "The new-authz request is ok." + _info "new-authz request successful." break fi _authz_i="$(_math "$_authz_i" + 1)" - _info "The server is busy, Sleep $_authz_i to retry." + _info "The server is busy, sleeping for $_authz_i seconds and retrying." _sleep "$_authz_i" done if [ "$_authz_i" = "$_Max_new_authz_retry_times" ]; then - _err "new-authz retry reach the max $_Max_new_authz_retry_times times." + _err "new-authz has been retried $_Max_new_authz_retry_times times, stopping." fi if [ "$code" ] && [ "$code" != '201' ]; then @@ -4047,7 +4060,7 @@ _ns_lookup_cf() { _ns_purge_cf() { _cf_d="$1" _cf_d_type="$2" - _debug "Cloudflare purge $_cf_d_type record for domain $_cf_d" + _debug "Purging Cloudflare $_cf_d_type record for domain $_cf_d" _cf_purl="https://cloudflare-dns.com/api/v1/purge?domain=$_cf_d&type=$_cf_d_type" response="$(_post "" "$_cf_purl")" _debug2 response "$response" @@ -4112,21 +4125,21 @@ _ns_lookup_dp() { _ns_select_doh() { if [ -z "$DOH_USE" ]; then - _debug "Detect dns server first." + _debug "Detecting DNS server first." if _ns_is_available_cf; then - _debug "Use cloudflare doh server" + _debug "Using Cloudflare doh server" export DOH_USE=$DOH_CLOUDFLARE elif _ns_is_available_google; then - _debug "Use google doh server" + _debug "Using Google DOH server" export DOH_USE=$DOH_GOOGLE elif _ns_is_available_ali; then - _debug "Use aliyun doh server" + _debug "Using Aliyun DOH server" export DOH_USE=$DOH_ALI elif _ns_is_available_dp; then - _debug "Use dns pod doh server" + _debug "Using DNS POD DOH server" export DOH_USE=$DOH_DP else - _err "No doh" + _err "No DOH" fi fi } @@ -4143,7 +4156,7 @@ _ns_lookup() { elif [ "$DOH_USE" = "$DOH_DP" ]; then _ns_lookup_dp "$@" else - _err "Unknown doh provider: DOH_USE=$DOH_USE" + _err "Unknown DOH provider: DOH_USE=$DOH_USE" fi } @@ -4169,7 +4182,7 @@ __purge_txt() { if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then _ns_purge_cf "$_p_txtdomain" "TXT" else - _debug "no purge api for this doh api, just sleep 5 secs" + _debug "No purge API for this DOH API, just sleeping for 5 seconds" _sleep 5 fi @@ -4200,17 +4213,17 @@ _check_dns_entries() { _debug "d_api" "$d_api" _info "Checking $d for $aliasDomain" if _contains "$_success_txt" ",$txt,"; then - _info "Already success, continue next one." + _info "Already succeeded, continuing." continue fi if __check_txt "$txtdomain" "$aliasDomain" "$txt"; then - _info "Domain $d '$aliasDomain' success." + _info "Success for domain $d '$aliasDomain'." _success_txt="$_success_txt,$txt," continue fi _left=1 - _info "Not valid yet, let's wait 10 seconds and check next one." + _info "Not valid yet, let's wait for 10 seconds then check the next one." __purge_txt "$txtdomain" if [ "$txtdomain" != "$aliasDomain" ]; then __purge_txt "$aliasDomain" @@ -4218,10 +4231,10 @@ _check_dns_entries() { _sleep 10 done if [ "$_left" ]; then - _info "Let's wait 10 seconds and check again". + _info "Let's wait for 10 seconds and check again". _sleep 10 else - _info "All success, let's return" + _info "All checks succeeded" return 0 fi done @@ -4337,14 +4350,14 @@ _convertValidaty() { elif _endswith "$_dateTo" "d"; then _v_end=$(_math "$_v_begin + 60 * 60 * 24 * $(echo "$_dateTo" | tr -d '+d')") else - _err "Not recognized format for _dateTo: $_dateTo" + _err "Unrecognized format for _dateTo: $_dateTo" return 1 fi _debug2 "_v_end" "$_v_end" _time2str "$_v_end" else if [ "$(_time)" -gt "$(_date2time "$_dateTo")" ]; then - _err "The validaty to is in the past: _dateTo = $_dateTo" + _err "The validity end date is in the past: _dateTo = $_dateTo" return 1 fi echo "$_dateTo" @@ -4408,7 +4421,7 @@ issue() { _valid_to_saved=$(_readdomainconf Le_Valid_to) if [ "$_valid_to_saved" ] && ! _startswith "$_valid_to_saved" "+"; then _info "The domain is set to be valid to: $_valid_to_saved" - _info "It can not be renewed automatically" + _info "It cannot be renewed automatically" _info "See: $_VALIDITY_WIKI" return $RENEW_SKIP fi @@ -4424,8 +4437,8 @@ issue() { if [ "$_normized_saved_domains" = "$_normized_domains" ]; then _info "Domains not changed." - _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" - _info "Add '$(__red '--force')' to force to renew." + _info "Skipping. Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" + _info "Add '$(__red '--force')' to force renewal." return $RENEW_SKIP else _info "Domains have changed." @@ -4484,7 +4497,7 @@ issue() { return 1 fi else - _debug "_saved_account_key_hash is not changed, skip register account." + _debug "_saved_account_key_hash was not changed, skipping account registration." fi export Le_Next_Domain_Key="$CERT_KEY_PATH.next" @@ -4498,15 +4511,15 @@ issue() { if [ -z "$_key" ]; then _key=2048 fi - _debug "Read key length:$_key" + _debug "Read key length: $_key" if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then if [ "$Le_ForceNewDomainKey" = "1" ] && [ -f "$Le_Next_Domain_Key" ]; then - _info "Using pre generated key: $Le_Next_Domain_Key" + _info "Using pre-generated key: $Le_Next_Domain_Key" cat "$Le_Next_Domain_Key" >"$CERT_KEY_PATH" echo "" >"$Le_Next_Domain_Key" else if ! createDomainKey "$_main_domain" "$_key_length"; then - _err "Create domain key error." + _err "Error creating domain key." _clearup _on_issue_err "$_post_hook" return 1 @@ -4514,18 +4527,18 @@ issue() { fi fi if [ "$Le_ForceNewDomainKey" ]; then - _info "Generate next pre-generate key." + _info "Generating next pre-generate key." if [ ! -e "$Le_Next_Domain_Key" ]; then touch "$Le_Next_Domain_Key" chmod 600 "$Le_Next_Domain_Key" fi if ! _createkey "$_key_length" "$Le_Next_Domain_Key"; then - _err "Can not pre generate domain key" + _err "Cannot pre-generate domain key" return 1 fi fi if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then - _err "Create CSR error." + _err "Error creating CSR." _clearup _on_issue_err "$_post_hook" return 1 @@ -4561,7 +4574,7 @@ issue() { _debug2 "_valid_from" "$_valid_from" _notBefore="$(_convertValidaty "" "$_valid_from")" if [ "$?" != "0" ]; then - _err "Can not parse _valid_from: $_valid_from" + _err "Cannot parse _valid_from: $_valid_from" return 1 fi if [ "$(_time)" -gt "$(_date2time "$_notBefore")" ]; then @@ -4577,7 +4590,7 @@ issue() { _savedomainconf "Le_Valid_To" "$_valid_to" _notAfter="$(_convertValidaty "$_notBefore" "$_valid_to")" if [ "$?" != "0" ]; then - _err "Can not parse _valid_to: $_valid_to" + _err "Cannot parse _valid_to: $_valid_to" return 1 fi else @@ -4594,7 +4607,7 @@ issue() { fi _debug "STEP 1, Ordering a Certificate" if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then - _err "Create new order error." + _err "Error creating new order." _clearup _on_issue_err "$_post_hook" return 1 @@ -4614,7 +4627,7 @@ issue() { Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)" _debug Le_OrderFinalize "$Le_OrderFinalize" if [ -z "$Le_OrderFinalize" ]; then - _err "Create new order error. Le_OrderFinalize not found. $response" + _err "Error creating new order. Le_OrderFinalize not found. $response" _clearup _on_issue_err "$_post_hook" return 1 @@ -4638,7 +4651,7 @@ issue() { for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do _debug2 "_authz_url" "$_authz_url" if ! _send_signed_request "$_authz_url"; then - _err "get to authz error." + _err "Error getting authz." _err "_authorizations_seg" "$_authorizations_seg" _err "_authz_url" "$_authz_url" _err "$response" @@ -4711,7 +4724,7 @@ $_authorizations_map" response="$(echo "$_candidates" | sed "s/$_idn_d,//")" _debug2 "response" "$response" if [ -z "$response" ]; then - _err "get to authz error." + _err "Error getting authz." _err "_authorizations_map" "$_authorizations_map" _clearup _on_issue_err "$_post_hook" @@ -4735,10 +4748,10 @@ $_authorizations_map" _debug entry "$entry" if [ -z "$keyauthorization" -a -z "$entry" ]; then - _err "Error, can not get domain token entry $d for $vtype" + _err "Cannot get domain token entry $d for $vtype" _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" if [ "$_supported_vtypes" ]; then - _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" + _err "Supported validation types are: $_supported_vtypes, but you specified: $vtype" fi _clearup _on_issue_err "$_post_hook" @@ -4750,7 +4763,7 @@ $_authorizations_map" _debug token "$token" if [ -z "$token" ]; then - _err "Error, can not get domain token $entry" + _err "Cannot get domain token $entry" _clearup _on_issue_err "$_post_hook" return 1 @@ -4761,7 +4774,7 @@ $_authorizations_map" _debug uri "$uri" if [ -z "$uri" ]; then - _err "Error, can not get domain uri. $entry" + _err "Cannot get domain URI $entry" _clearup _on_issue_err "$_post_hook" return 1 @@ -4790,7 +4803,7 @@ $_authorizations_map" _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) _debug d "$d" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _debug "$d is already verified, skip $vtype." + _debug "$d has already been verified, skipping $vtype." _alias_index="$(_math "$_alias_index" + 1)" continue fi @@ -4827,37 +4840,37 @@ $_authorizations_map" dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api" _debug2 dns_entry "$dns_entry" if [ "$d_api" ]; then - _debug "Found domain api file: $d_api" + _debug "Found domain API file: $d_api" else if [ "$_currentRoot" != "$W_DNS" ]; then - _err "Can not find dns api hook for: $_currentRoot" - _info "You need to add the txt record manually." + _err "Cannot find DNS API hook for: $_currentRoot" + _info "You need to add the TXT record manually." fi _info "$(__red "Add the following TXT record:")" _info "$(__red "Domain: '$(__green "$txtdomain")'")" _info "$(__red "TXT value: '$(__green "$txt")'")" - _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" - _info "$(__red "so the resulting subdomain will be: $txtdomain")" + _info "$(__red "Please make sure to prepend '_acme-challenge.' to your domain")" + _info "$(__red "so that the resulting subdomain is: $txtdomain")" continue fi ( if ! . "$d_api"; then - _err "Load file $d_api error. Please check your api file and try again." + _err "Error loading file $d_api. Please check your API file and try again." return 1 fi addcommand="${_currentRoot}_add" if ! _exists "$addcommand"; then - _err "It seems that your api file is not correct, it must have a function named: $addcommand" + _err "It seems that your API file is incorrect. Make sure it has a function named: $addcommand" return 1 fi - _info "Adding txt value: $txt for domain: $txtdomain" + _info "Adding TXT value: $txt for domain: $txtdomain" if ! $addcommand "$txtdomain" "$txt"; then - _err "Error add txt for domain:$txtdomain" + _err "Error adding TXT record to domain: $txtdomain" return 1 fi - _info "The txt record is added: Success." + _info "The TXT record has been successfully added." ) if [ "$?" != "0" ]; then @@ -4874,7 +4887,7 @@ $_authorizations_map" if [ "$dnsadded" = '0' ]; then _savedomainconf "Le_Vlist" "$vlist" - _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." + _debug "DNS record not yet added. Will save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and re-run with --renew." _on_issue_err "$_post_hook" _clearup @@ -4887,23 +4900,23 @@ $_authorizations_map" if [ "$dns_entries" ]; then if [ -z "$Le_DNSSleep" ]; then - _info "Let's check each DNS record now. Sleep 20 seconds first." + _info "Let's check each DNS record now. Sleeping for 20 seconds first." _sleep 20 if ! _check_dns_entries; then - _err "check dns error." + _err "Error checking DNS." _on_issue_err "$_post_hook" _clearup return 1 fi else _savedomainconf "Le_DNSSleep" "$Le_DNSSleep" - _info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect" + _info "Sleeping for $(__green $Le_DNSSleep) seconds to wait for the the TXT records to take effect" _sleep "$Le_DNSSleep" fi fi NGINX_RESTORE_VLIST="" - _debug "ok, let's start to verify" + _debug "OK, let's start verification" _ncIndex=1 ventries=$(echo "$vlist" | tr "$dvsep" ' ') @@ -4915,7 +4928,7 @@ $_authorizations_map" _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _info "$d is already verified, skip $vtype." + _info "$d is already verified, skipping $vtype." continue fi @@ -4943,10 +4956,10 @@ $_authorizations_map" sleep 1 _debug serverproc "$serverproc" elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then - _info "Stateless mode for domain:$d" + _info "Stateless mode for domain: $d" _sleep 1 elif _startswith "$_currentRoot" "$NGINX"; then - _info "Nginx mode for domain:$d" + _info "Nginx mode for domain: $d" #set up nginx server FOUND_REAL_NGINX_CONF="" BACKUP_NGINX_CONF="" @@ -4979,26 +4992,26 @@ $_authorizations_map" _debug wellknown_path "$wellknown_path" - _debug "writing token:$token to $wellknown_path/$token" + _debug "Writing token: $token to $wellknown_path/$token" mkdir -p "$wellknown_path" if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then - _err "$d:Can not write token to file : $wellknown_path/$token" + _err "$d: Cannot write token to file: $wellknown_path/$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" return 1 fi if ! chmod a+r "$wellknown_path/$token"; then - _debug "chmod failed, but we just continue." + _debug "chmod failed, will just continue." fi fi elif [ "$vtype" = "$VTYPE_ALPN" ]; then acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")" _debug acmevalidationv1 "$acmevalidationv1" if ! _starttlsserver "$d" "" "$Le_TLSPort" "$keyauthorization" "$_ncaddr" "$acmevalidationv1"; then - _err "Start tls server error." + _err "Error starting TLS server." _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" @@ -5007,7 +5020,7 @@ $_authorizations_map" fi if ! __trigger_validation "$uri" "$keyauthorization" "$vtype"; then - _err "$d:Can not get challenge: $response" + _err "$d: Cannot get challenge: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" @@ -5016,9 +5029,9 @@ $_authorizations_map" if [ "$code" ] && [ "$code" != '202' ]; then if [ "$code" = '200' ]; then - _debug "trigger validation code: $code" + _debug "Trigger validation code: $code" else - _err "$d:Challenge error: $response" + _err "$d: Challenge error: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" @@ -5031,11 +5044,11 @@ $_authorizations_map" MAX_RETRY_TIMES=30 fi - _debug "Lets check the status of the authz" + _debug "Let's check the authz status" while true; do waittimes=$(_math "$waittimes" + 1) if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then - _err "$d:Timeout" + _err "$d: Timeout" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" @@ -5055,13 +5068,13 @@ $_authorizations_map" errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" _debug2 errordetail "$errordetail" if [ "$errordetail" ]; then - _err "Invalid status, $d:Verify error detail:$errordetail" + _err "$d: Invalid status. Verification error details: $errordetail" else - _err "Invalid status, $d:Verify error:$error" + _err "$d: Invalid status, Verification error: $error" fi if [ "$DEBUG" ]; then if [ "$vtype" = "$VTYPE_HTTP" ]; then - _debug "Debug: get token url." + _debug "Debug: GET token URL." _get "http://$d/.well-known/acme-challenge/$token" "" 1 fi fi @@ -5080,46 +5093,59 @@ $_authorizations_map" fi if _contains "$status" "pending"; then - _info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" + _info "Pending. The CA is processing your order, please wait. ($waittimes/$MAX_RETRY_TIMES)" elif _contains "$status" "processing"; then - _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" + _info "Processing. The CA is processing your order, please wait. ($waittimes/$MAX_RETRY_TIMES)" else - _err "Unknown status: $status, $d:Verify error:$response" + _err "$d: Unknown status: $status. Verification error: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" return 1 fi - _debug "sleep 2 secs to verify again" + _debug "Sleep 2 seconds before verifying again" _sleep 2 - _debug "checking" + _debug "Checking" _send_signed_request "$_authz_url" if [ "$?" != "0" ]; then - _err "Invalid code, $d:Verify error:$response" + _err "$d: Invalid code. Verification error: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup _on_issue_err "$_post_hook" "$vlist" return 1 fi + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') + _sleep_overload_retry_sec=$_retryafter + if [ "$_sleep_overload_retry_sec" ]; then + if [ $_sleep_overload_retry_sec -le 600 ]; then + _sleep $_sleep_overload_retry_sec + else + _info "The retryafter=$_retryafter value is too large (> 600), will not retry anymore." + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" + _clearup + _on_issue_err "$_post_hook" "$vlist" + return 1 + fi + fi done done _clearup - _info "Verify finished, start to sign." + _info "Verification finished, beginning signing." der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)" - _info "Lets finalize the order." + _info "Let's finalize the order." _info "Le_OrderFinalize" "$Le_OrderFinalize" if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then - _err "Sign failed." + _err "Signing failed." _on_issue_err "$_post_hook" return 1 fi if [ "$code" != "200" ]; then - _err "Sign failed, finalize code is not 200." + _err "Signing failed. Finalize code was not 200." _err "$response" _on_issue_err "$_post_hook" return 1 @@ -5138,38 +5164,38 @@ $_authorizations_map" Le_LinkCert="$(echo "$response" | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" _debug Le_LinkCert "$Le_LinkCert" if [ -z "$Le_LinkCert" ]; then - _err "Sign error, can not find Le_LinkCert" + _err "A signing error occurred: could not find Le_LinkCert" _err "$response" _on_issue_err "$_post_hook" return 1 fi break elif _contains "$response" "\"processing\""; then - _info "Order status is processing, lets sleep and retry." + _info "Order status is 'processing', let's sleep and retry." _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') _debug "_retryafter" "$_retryafter" if [ "$_retryafter" ]; then - _info "Retry after: $_retryafter" + _info "Sleeping for $_retryafter seconds then retrying" _sleep $_retryafter else _sleep 2 fi else - _err "Sign error, wrong status" + _err "Signing error: wrong status" _err "$response" _on_issue_err "$_post_hook" return 1 fi #the order is processing, so we are going to poll order status if [ -z "$Le_LinkOrder" ]; then - _err "Sign error, can not get order link location header" + _err "Signing error: could not get order link location header" _err "responseHeaders" "$responseHeaders" _on_issue_err "$_post_hook" return 1 fi _info "Polling order status: $Le_LinkOrder" if ! _send_signed_request "$Le_LinkOrder"; then - _err "Sign failed, can not post to Le_LinkOrder cert:$Le_LinkOrder." + _err "Signing failed. Could not make POST request to Le_LinkOrder for cert: $Le_LinkOrder." _err "$response" _on_issue_err "$_post_hook" return 1 @@ -5178,7 +5204,7 @@ $_authorizations_map" done if [ -z "$Le_LinkCert" ]; then - _err "Sign failed, can not get Le_LinkCert, retry time limit." + _err "Signing failed. Could not get Le_LinkCert, and stopped retrying after reaching the retry limit." _err "$response" _on_issue_err "$_post_hook" return 1 @@ -5186,7 +5212,7 @@ $_authorizations_map" _info "Downloading cert." _info "Le_LinkCert" "$Le_LinkCert" if ! _send_signed_request "$Le_LinkCert"; then - _err "Sign failed, can not download cert:$Le_LinkCert." + _err "Signing failed. Could not download cert: $Le_LinkCert." _err "$response" _on_issue_err "$_post_hook" return 1 @@ -5199,15 +5225,15 @@ $_authorizations_map" fi if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then if [ "$DEBUG" ]; then - _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" + _debug "Default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" fi if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)" _debug2 "rels" "$rels" for rel in $rels; do - _info "Try rel: $rel" + _info "Trying rel: $rel" if ! _send_signed_request "$rel"; then - _err "Sign failed, can not download cert:$rel" + _err "Signing failed, could not download cert: $rel" _err "$response" continue fi @@ -5241,7 +5267,7 @@ $_authorizations_map" if [ -z "$Le_LinkCert" ] || ! _checkcert "$CERT_PATH"; then response="$(echo "$response" | _dbase64 "multiline" | tr -d '\0' | _normalizeJson)" - _err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')" + _err "Signing failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')" _on_issue_err "$_post_hook" return 1 fi @@ -5263,9 +5289,9 @@ $_authorizations_map" fi [ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in: $(__green "$CA_CERT_PATH")" - [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green "$CERT_FULLCHAIN_PATH")" + [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full-chain cert is in: $(__green "$CERT_FULLCHAIN_PATH")" if [ "$Le_ForceNewDomainKey" ] && [ -e "$Le_Next_Domain_Key" ]; then - _info "Your pre-generated next key for future cert key change is in: $(__green "$Le_Next_Domain_Key")" + _info "Your pre-generated key for future cert key changes is in: $(__green "$Le_Next_Domain_Key")" fi Le_CertCreateTime=$(_time) @@ -5315,8 +5341,8 @@ $_authorizations_map" Le_NextRenewTime=$(_date2time "$_notAfter") Le_NextRenewTimeStr="$_notAfter" if [ "$_valid_to" ] && ! _startswith "$_valid_to" "+"; then - _info "The domain is set to be valid to: $_valid_to" - _info "It can not be renewed automatically" + _info "The domain is set to be valid until: $_valid_to" + _info "It cannot be renewed automatically" _info "See: $_VALIDITY_WIKI" else _now=$(_time) @@ -5359,7 +5385,7 @@ $_authorizations_map" fi if ! _on_issue_success "$_post_hook" "$_renew_hook"; then - _err "Call hook error." + _err "Error calling hook." return 1 fi } @@ -5395,9 +5421,9 @@ renew() { _initpath "$Le_Domain" "$_isEcc" _set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT} - _info "$(__green "Renew: '$Le_Domain'")" + _info "$(__green "Renewing: '$Le_Domain'")" if [ ! -f "$DOMAIN_CONF" ]; then - _info "'$Le_Domain' is not an issued domain, skip." + _info "'$Le_Domain' is not an issued domain, skipping." return $RENEW_SKIP fi @@ -5426,7 +5452,7 @@ renew() { if [ "$_server" ]; then Le_API="$_server" fi - _info "Renew to Le_API=$Le_API" + _info "Renewing using Le_API=$Le_API" _clearAPI _clearCA @@ -5437,8 +5463,8 @@ renew() { _initpath "$Le_Domain" "$_isEcc" if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then - _info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")" - _info "Add '$(__red '--force')' to force to renew." + _info "Skipping. Next renewal time is: $(__green "$Le_NextRenewTimeStr")" + _info "Add '$(__red '--force')' to force renewal." if [ -z "$_ACME_IN_RENEWALL" ]; then if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then _send_notify "Renew $Le_Domain skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP" @@ -5448,7 +5474,7 @@ renew() { fi if [ "$_ACME_IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then - _info "Skip invalid cert for: $Le_Domain" + _info "Skipping invalid cert for: $Le_Domain" return $RENEW_SKIP fi @@ -5514,7 +5540,7 @@ renewAll() { for di in "${CERT_HOME}"/*.*/; do _debug di "$di" if ! [ -d "$di" ]; then - _debug "Not a directory, skip: $di" + _debug "Not a directory, skipping: $di" continue fi d=$(basename "$di") @@ -5572,12 +5598,12 @@ renewAll() { _error_msg="${_error_msg} $d " if [ "$_stopRenewOnError" ]; then - _err "Error renew $d, stop now." + _err "Error renewing $d, stopping." _ret="$rc" break else _ret="$rc" - _err "Error renew $d." + _err "Error renewing $d." fi fi done @@ -5588,13 +5614,13 @@ renewAll() { _msg_subject="Renew" if [ "$_error_msg" ]; then _msg_subject="${_msg_subject} Error" - _msg_data="Error certs: + _msg_data="Errored certs: ${_error_msg} " fi if [ "$_success_msg" ]; then _msg_subject="${_msg_subject} Success" - _msg_data="${_msg_data}Success certs: + _msg_data="${_msg_data}Successful certs: ${_success_msg} " fi @@ -5635,18 +5661,18 @@ signcsr() { _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then - _err "Can not read subject from csr: $_csrfile" + _err "Cannot read subject from CSR: $_csrfile" return 1 fi _debug _csrsubj "$_csrsubj" if _contains "$_csrsubj" ' ' || ! _contains "$_csrsubj" '.'; then - _info "It seems that the subject: $_csrsubj is not a valid domain name. Drop it." + _info "It seems that the subject $_csrsubj is not a valid domain name. Dropping it." _csrsubj="" fi _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile") if [ "$?" != "0" ]; then - _err "Can not read domain list from csr: $_csrfile" + _err "Cannot read domain list from CSR: $_csrfile" return 1 fi _debug "_csrdomainlist" "$_csrdomainlist" @@ -5659,20 +5685,20 @@ signcsr() { fi if [ -z "$_csrsubj" ]; then - _err "Can not read subject from csr: $_csrfile" + _err "Cannot read subject from CSR: $_csrfile" return 1 fi _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile") if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then - _err "Can not read key length from csr: $_csrfile" + _err "Cannot read key length from CSR: $_csrfile" return 1 fi _initpath "$_csrsubj" "$_csrkeylength" mkdir -p "$DOMAIN_PATH" - _info "Copy csr to: $CSR_PATH" + _info "Copying CSR to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" @@ -5691,18 +5717,18 @@ showcsr() { _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then - _err "Can not read subject from csr: $_csrfile" + _err "Cannot read subject from CSR: $_csrfile" return 1 fi if [ -z "$_csrsubj" ]; then - _info "The Subject is empty" + _info "The subject is empty" fi _info "Subject=$_csrsubj" _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile") if [ "$?" != "0" ]; then - _err "Can not read domain list from csr: $_csrfile" + _err "Cannot read domain list from CSR: $_csrfile" return 1 fi _debug "_csrdomainlist" "$_csrdomainlist" @@ -5711,7 +5737,7 @@ showcsr() { _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile") if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then - _err "Can not read key length from csr: $_csrfile" + _err "Cannot read key length from CSR: $_csrfile" return 1 fi _info "KeyLength=$_csrkeylength" @@ -5767,29 +5793,29 @@ _deploy() { for _d_api in $(echo "$_hooks" | tr ',' " "); do _deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")" if [ -z "$_deployApi" ]; then - _err "The deploy hook $_d_api is not found." + _err "The deploy hook $_d_api was not found." return 1 fi _debug _deployApi "$_deployApi" if ! ( if ! . "$_deployApi"; then - _err "Load file $_deployApi error. Please check your api file and try again." + _err "Error loading file $_deployApi. Please check your API file and try again." return 1 fi d_command="${_d_api}_deploy" if ! _exists "$d_command"; then - _err "It seems that your api file is not correct, it must have a function named: $d_command" + _err "It seems that your API file is not correct. Make sure it has a function named: $d_command" return 1 fi if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then - _err "Error deploy for domain:$_d" + _err "Error deploying for domain: $_d" return 1 fi ); then - _err "Deploy error." + _err "Error encountered while deploying." return 1 else _info "$(__green Success)" @@ -5810,7 +5836,7 @@ deploy() { _initpath "$_d" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then _err "The domain '$_d' is not a cert name. You must use the cert name to specify the cert to install." - _err "Can not find path:'$DOMAIN_PATH'" + _err "Cannot find path: '$DOMAIN_PATH'" return 1 fi @@ -5839,7 +5865,7 @@ installcert() { _initpath "$_main_domain" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then _err "The domain '$_main_domain' is not a cert name. You must use the cert name to specify the cert to install." - _err "Can not find path:'$DOMAIN_PATH'" + _err "Cannot find path: '$DOMAIN_PATH'" return 1 fi @@ -5934,7 +5960,7 @@ _installcert() { fi if [ "$_reload_cmd" ]; then - _info "Run reload cmd: $_reload_cmd" + _info "Running reload cmd: $_reload_cmd" if ( export CERT_PATH export CERT_KEY_PATH @@ -5945,9 +5971,9 @@ _installcert() { export Le_Next_Domain_Key cd "$DOMAIN_PATH" && eval "$_reload_cmd" ); then - _info "$(__green "Reload success")" + _info "$(__green "Reload successful")" else - _err "Reload error for :$Le_Domain" + _err "Reload error for: $Le_Domain" fi fi @@ -5975,25 +6001,25 @@ _install_win_taskscheduler() { return 1 fi if ! _exists schtasks; then - _err "schtasks.exe is not found, are you on Windows?" + _err "schtasks.exe was not found, are you on Windows?" return 1 fi _winbash="$(cygpath -w $(which bash))" _debug _winbash "$_winbash" if [ -z "$_winbash" ]; then - _err "can not find bash path" + _err "Cannot find bash path" return 1 fi _myname="$(whoami)" _debug "_myname" "$_myname" if [ -z "$_myname" ]; then - _err "can not find my user name" + _err "Can not find own username" return 1 fi _debug "_lesh" "$_lesh" - _info "To install scheduler task in your Windows account, you must input your windows password." - _info "$PROJECT_NAME doesn't save your password." + _info "To install the scheduler task to your Windows account, you must input your Windows password." + _info "$PROJECT_NAME will not save your password." _info "Please input your Windows password for: $(__green "$_myname")" _password="$(__read_password)" #SCHTASKS.exe '/create' '/SC' 'DAILY' '/TN' "$_WINDOWS_SCHEDULER_NAME" '/F' '/ST' "00:$_randomminute" '/RU' "$_myname" '/RP' "$_password" '/TR' "$_winbash -l -c '$_lesh --cron --home \"$LE_WORKING_DIR\" $_centry'" >/dev/null @@ -6004,11 +6030,11 @@ _install_win_taskscheduler() { _uninstall_win_taskscheduler() { if ! _exists schtasks; then - _err "schtasks.exe is not found, are you on Windows?" + _err "schtasks.exe was not found, are you on Windows?" return 1 fi if ! echo SCHTASKS /query /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null; then - _debug "scheduler $_WINDOWS_SCHEDULER_NAME is not found." + _debug "scheduler $_WINDOWS_SCHEDULER_NAME was not found." else _info "Removing $_WINDOWS_SCHEDULER_NAME" echo SCHTASKS /delete /f /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null @@ -6027,10 +6053,10 @@ installcronjob() { _script="$(_readlink "$_SCRIPT_")" _debug _script "$_script" if [ -f "$_script" ]; then - _info "Using the current script from: $_script" + _info "Usinging the current script from: $_script" lesh="$_script" else - _err "Can not install cronjob, $PROJECT_ENTRY not found." + _err "Cannot install cronjob, $PROJECT_ENTRY not found." return 1 fi fi @@ -6047,18 +6073,18 @@ installcronjob() { if ! _exists "$_CRONTAB"; then if _exists cygpath && _exists schtasks.exe; then - _info "It seems you are on Windows, let's install Windows scheduler task." + _info "It seems you are on Windows, let's install the Windows scheduler task." if _install_win_taskscheduler "$lesh" "$_c_entry" "$random_minute"; then - _info "Install Windows scheduler task success." + _info "Successfully installed Windows scheduler task." return 0 else - _err "Install Windows scheduler task failed." + _err "Failed to install Windows scheduler task." return 1 fi fi - _err "crontab/fcrontab doesn't exist, so, we can not install cron jobs." - _err "All your certs will not be renewed automatically." - _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday." + _err "crontab/fcrontab doesn't exist, so we cannot install cron jobs." + _err "Your certs will not be renewed automatically." + _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' every day." return 1 fi _info "Installing cron job" @@ -6074,8 +6100,8 @@ installcronjob() { } | $_CRONTAB_STDIN fi if [ "$?" != "0" ]; then - _err "Install cron job failed. You need to manually renew your certs." - _err "Or you can add cronjob by yourself:" + _err "Failed to install cron job. You need to manually renew your certs." + _err "Alternatively, you can add a cron job by yourself:" _err "$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null" return 1 fi @@ -6089,12 +6115,12 @@ uninstallcronjob() { if ! _exists "$_CRONTAB"; then if _exists cygpath && _exists schtasks.exe; then - _info "It seems you are on Windows, let's uninstall Windows scheduler task." + _info "It seems you are on Windows, let's uninstall the Windows scheduler task." if _uninstall_win_taskscheduler; then - _info "Uninstall Windows scheduler task success." + _info "Successfully uninstalled Windows scheduler task." return 0 else - _err "Uninstall Windows scheduler task failed." + _err "Failed to uninstall Windows scheduler task." return 1 fi fi @@ -6134,12 +6160,12 @@ revoke() { fi _initpath "$Le_Domain" "$_isEcc" if [ ! -f "$DOMAIN_CONF" ]; then - _err "$Le_Domain is not a issued domain, skip." + _err "$Le_Domain is not an issued domain, skipping." return 1 fi if [ ! -f "$CERT_PATH" ]; then - _err "Cert for $Le_Domain $CERT_PATH is not found, skip." + _err "Cert for $Le_Domain $CERT_PATH was not found, skipping." return 1 fi @@ -6163,7 +6189,7 @@ revoke() { cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _url_replace)" if [ -z "$cert" ]; then - _err "Cert for $Le_Domain is empty found, skip." + _err "Cert for $Le_Domain is empty, skipping." return 1 fi @@ -6173,31 +6199,31 @@ revoke() { uri="${ACME_REVOKE_CERT}" - _info "Try account key first." + _info "Trying account key first." if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then if [ -z "$response" ]; then - _info "Revoke success." + _info "Successfully revoked." rm -f "$CERT_PATH" cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked" cat "$CSR_PATH" >"$CSR_PATH.revoked" return 0 else - _err "Revoke error." + _err "Error revoking." _debug "$response" fi fi if [ -f "$CERT_KEY_PATH" ]; then - _info "Try domain key." + _info "Trying domain key." if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then if [ -z "$response" ]; then - _info "Revoke success." + _info "Successfully revoked." rm -f "$CERT_PATH" cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked" cat "$CSR_PATH" >"$CSR_PATH.revoked" return 0 else - _err "Revoke error by domain key." + _err "Error revoking using domain key." _err "$response" fi fi @@ -6221,19 +6247,19 @@ remove() { _removed_conf="$DOMAIN_CONF.removed" if [ ! -f "$DOMAIN_CONF" ]; then if [ -f "$_removed_conf" ]; then - _err "$Le_Domain is already removed, You can remove the folder by yourself: $DOMAIN_PATH" + _err "$Le_Domain has already been removed. You can remove the folder by yourself: $DOMAIN_PATH" else - _err "$Le_Domain is not a issued domain, skip." + _err "$Le_Domain is not an issued domain, skipping." fi return 1 fi if mv "$DOMAIN_CONF" "$_removed_conf"; then - _info "$Le_Domain is removed, the key and cert files are in $(__green $DOMAIN_PATH)" + _info "$Le_Domain has been removed. The key and cert files are in $(__green $DOMAIN_PATH)" _info "You can remove them by yourself." return 0 else - _err "Remove $Le_Domain failed." + _err "Failed to remove $Le_Domain." return 1 fi } @@ -6263,7 +6289,7 @@ _deactivate() { _identifiers="{\"type\":\"$(_getIdType "$_d_domain")\",\"value\":\"$_d_domain\"}" if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then - _err "Can not get domain new order." + _err "Cannot get new order for domain." return 1 fi _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" @@ -6278,7 +6304,7 @@ _deactivate() { authzUri="$_authorizations_seg" _debug2 "authzUri" "$authzUri" if ! _send_signed_request "$authzUri"; then - _err "get to authz error." + _err "Error making GET request for authz." _err "_authorizations_seg" "$_authorizations_seg" _err "authzUri" "$authzUri" _clearup @@ -6301,7 +6327,7 @@ _deactivate() { entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" if [ -z "$entry" ]; then - _err "Error, can not get domain token $d" + _err "$d: Cannot get domain token" return 1 fi token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" @@ -6319,13 +6345,13 @@ _deactivate() { _d_i=0 _d_max_retry=$(echo "$entries" | wc -l) while [ "$_d_i" -lt "$_d_max_retry" ]; do - _info "Deactivate: $_d_domain" + _info "Deactivating $_d_domain" _d_i="$(_math $_d_i + 1)" entry="$(echo "$entries" | sed -n "${_d_i}p")" _debug entry "$entry" if [ -z "$entry" ]; then - _info "No more valid entry found." + _info "No more valid entries found." break fi @@ -6337,27 +6363,27 @@ _deactivate() { _debug uri "$uri" if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ]; then - _info "Skip $_vtype" + _info "Skipping $_vtype" continue fi - _info "Deactivate: $_vtype" + _info "Deactivating $_vtype" _djson="{\"status\":\"deactivated\"}" if _send_signed_request "$authzUri" "$_djson" && _contains "$response" '"deactivated"'; then - _info "Deactivate: $_vtype success." + _info "Successfully deactivated $_vtype." else - _err "Can not deactivate $_vtype." + _err "Could not deactivate $_vtype." break fi done _debug "$_d_i" if [ "$_d_i" -eq "$_d_max_retry" ]; then - _info "Deactivated success!" + _info "Successfully deactivated!" else - _err "Deactivate failed." + _err "Deactivation failed." fi } @@ -6438,17 +6464,17 @@ _precheck() { _nocron="$1" if ! _exists "curl" && ! _exists "wget"; then - _err "Please install curl or wget first, we need to access http resources." + _err "Please install curl or wget first to enable access to HTTP resources." return 1 fi if [ -z "$_nocron" ]; then if ! _exists "crontab" && ! _exists "fcrontab"; then if _exists cygpath && _exists schtasks.exe; then - _info "It seems you are on Windows, we will install Windows scheduler task." + _info "It seems you are on Windows, we will install the Windows scheduler task." else - _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." - _err "We need to set cron job to renew the certs automatically." + _err "It is recommended to install crontab first. Try to install 'cron', 'crontab', 'crontabs' or 'vixie-cron'." + _err "We need to set a cron job to renew the certs automatically." _err "Otherwise, your certs will not be able to be renewed automatically." if [ -z "$FORCE" ]; then _err "Please add '--force' and try install again to go without crontab." @@ -6467,8 +6493,8 @@ _precheck() { if ! _exists "socat"; then _err "It is recommended to install socat first." - _err "We use socat for standalone server if you use standalone mode." - _err "If you don't use standalone mode, just ignore this warning." + _err "We use socat for the standalone server, which is used for standalone mode." + _err "If you don't want to use standalone mode, you may ignore this warning." fi return 0 @@ -6516,9 +6542,9 @@ _installalias() { _debug "Found profile: $_profile" _info "Installing alias to '$_profile'" _setopt "$_profile" ". \"$_envfile\"" - _info "OK, Close and reopen your terminal to start using $PROJECT_NAME" + _info "Close and reopen your terminal to start using $PROJECT_NAME" else - _info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME" + _info "No profile has been found, you will need to change your working directory to $LE_WORKING_DIR to use $PROJECT_NAME" fi #for csh @@ -6567,12 +6593,12 @@ install() { return 1 fi if [ "$_nocron" ]; then - _debug "Skip install cron job" + _debug "Skipping cron job installation" fi if [ "$_ACME_IN_CRON" != "1" ]; then if ! _precheck "$_nocron"; then - _err "Pre-check failed, can not install." + _err "Pre-check failed, cannot install." return 1 fi fi @@ -6602,7 +6628,7 @@ install() { if [ ! -d "$LE_WORKING_DIR" ]; then if ! mkdir -p "$LE_WORKING_DIR"; then - _err "Can not create working dir: $LE_WORKING_DIR" + _err "Cannot create working dir: $LE_WORKING_DIR" return 1 fi @@ -6611,7 +6637,7 @@ install() { if [ ! -d "$LE_CONFIG_HOME" ]; then if ! mkdir -p "$LE_CONFIG_HOME"; then - _err "Can not create config dir: $LE_CONFIG_HOME" + _err "Cannot create config dir: $LE_CONFIG_HOME" return 1 fi @@ -6621,7 +6647,7 @@ install() { cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY" if [ "$?" != "0" ]; then - _err "Install failed, can not copy $PROJECT_ENTRY" + _err "Installation failed, cannot copy $PROJECT_ENTRY" return 1 fi @@ -6667,7 +6693,7 @@ install() { fi fi if [ "$_bash_path" ]; then - _info "Good, bash is found, so change the shebang to use bash as preferred." + _info "bash has been found. Changing the shebang to use bash as preferred." _shebang='#!'"$_bash_path" _setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang" for subf in $_SUB_FOLDERS; do @@ -6698,7 +6724,7 @@ uninstall() { _uninstallalias rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY" - _info "The keys and certs are in \"$(__green "$LE_CONFIG_HOME")\", you can remove them by yourself." + _info "The keys and certs are in \"$(__green "$LE_CONFIG_HOME")\". You can remove them by yourself." } @@ -6736,7 +6762,7 @@ cron() { export LE_WORKING_DIR ( if ! upgrade; then - _err "Cron:Upgrade failed!" + _err "Cron: Upgrade failed!" return 1 fi ) @@ -6746,7 +6772,7 @@ cron() { __INTERACTIVE="1" fi - _info "Auto upgraded to: $VER" + _info "Automatically upgraded to: $VER" fi renewAll _ret="$?" @@ -6768,12 +6794,12 @@ _send_notify() { _nerror="$4" if [ "$NOTIFY_LEVEL" = "$NOTIFY_LEVEL_DISABLE" ]; then - _debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, disabled, just return." + _debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, which means it's disabled, so will just return." return 0 fi if [ -z "$_nhooks" ]; then - _debug "The NOTIFY_HOOK is empty, just return." + _debug "The NOTIFY_HOOK is empty, will just return." return 0 fi @@ -6790,29 +6816,29 @@ _send_notify() { _info "Sending via: $_n_hook" _debug "Found $_n_hook_file for $_n_hook" if [ -z "$_n_hook_file" ]; then - _err "Can not find the hook file for $_n_hook" + _err "Cannot find the hook file for $_n_hook" continue fi if ! ( if ! . "$_n_hook_file"; then - _err "Load file $_n_hook_file error. Please check your api file and try again." + _err "Error loading file $_n_hook_file. Please check your API file and try again." return 1 fi d_command="${_n_hook}_send" if ! _exists "$d_command"; then - _err "It seems that your api file is not correct, it must have a function named: $d_command" + _err "It seems that your API file is not correct. Make sure it has a function named: $d_command" return 1 fi if ! $d_command "$_nsubject" "$_ncontent" "$_nerror"; then - _err "Error send message by $d_command" + _err "Error sending message using $d_command" return 1 fi return 0 ); then - _err "Set $_n_hook_file error." + _err "Error setting $_n_hook_file." _send_err=1 else _info "$_n_hook $(__green Success)" @@ -6869,7 +6895,7 @@ setnotify() { if [ "$_nhook" ]; then _info "Set notify hook to: $_nhook" if [ "$_nhook" = "$NO_VALUE" ]; then - _info "Clear notify hook" + _info "Clearing notify hook" _clearaccountconf "NOTIFY_HOOK" else if _set_notify_hook "$_nhook"; then @@ -6877,7 +6903,7 @@ setnotify() { _saveaccountconf "NOTIFY_HOOK" "$NOTIFY_HOOK" return 0 else - _err "Can not set notify hook to: $_nhook" + _err "Cannot set notify hook to: $_nhook" return 1 fi fi @@ -6897,7 +6923,7 @@ Commands: --upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT. --issue Issue a cert. --deploy Deploy the cert to your server. - -i, --install-cert Install the issued cert to apache/nginx or any other server. + -i, --install-cert Install the issued cert to Apache/nginx or any other server. -r, --renew Renew a cert. --renew-all Renew all the certs. --revoke Revoke a cert. @@ -6953,7 +6979,7 @@ Parameters: --stateless Use stateless mode. See: $_STATELESS_WIKI - --apache Use apache mode. + --apache Use Apache mode. --dns [dns_hook] Use dns manual mode or dns api. Defaults to manual mode when argument is omitted. See: $_DNS_API_WIKI @@ -6968,7 +6994,7 @@ Parameters: --eab-hmac-key HMAC key for External Account Binding. - These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert: + These parameters are to install the cert to nginx/Apache or any other server after issue/renew a cert: --cert-file Path to copy the cert file to after issue/renew. --key-file Path to copy the key file to after issue/renew. @@ -7007,6 +7033,7 @@ Parameters: --post-hook Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed. --renew-hook Command to be run after each successfully renewed certificate. --deploy-hook The hook file to deploy cert + --extended-key-usage Manually define the CSR extended key usage value. The default is serverAuth,clientAuth. --ocsp, --ocsp-must-staple Generate OCSP-Must-Staple extension. --always-force-new-domain-key Generate new domain key on renewal. Otherwise, the domain key is not changed by default. --auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. Defaults to 1 if argument is omitted. @@ -7075,8 +7102,8 @@ installOnline() { _getRepoHash() { _hash_path=$1 shift - _hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/$_hash_path" - _get $_hash_url | tr -d "\r\n" | tr '{},' '\n\n\n' | grep '"sha":' | cut -d '"' -f 4 + _hash_url="${PROJECT_API:-https://api.github.com/repos/acmesh-official}/$PROJECT_NAME/git/refs/$_hash_path" + _get "$_hash_url" "" 30 | tr -d "\r\n" | tr '{},' '\n\n\n' | grep '"sha":' | cut -d '"' -f 4 } _getUpgradeHash() { @@ -7092,12 +7119,12 @@ _getUpgradeHash() { upgrade() { if ( _initpath - [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 + [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already up to date!" && exit 0 export LE_WORKING_DIR cd "$LE_WORKING_DIR" installOnline "--nocron" "--noprofile" ); then - _info "Upgrade success!" + _info "Upgrade successful!" exit 0 else _err "Upgrade failed!" @@ -7133,7 +7160,7 @@ _processAccountConf() { } _checkSudo() { - if [ -z "__INTERACTIVE" ]; then + if [ -z "$__INTERACTIVE" ]; then #don't check if it's not in an interactive shell return 0 fi @@ -7213,7 +7240,7 @@ _getCAShortName() { #set default ca to $ACME_DIRECTORY setdefaultca() { if [ -z "$ACME_DIRECTORY" ]; then - _err "Please give a --server parameter." + _err "Please provide a --server parameter." return 1 fi _saveaccountconf "DEFAULT_ACME_SERVER" "$ACME_DIRECTORY" @@ -7225,7 +7252,7 @@ setdefaultchain() { _initpath _preferred_chain="$1" if [ -z "$_preferred_chain" ]; then - _err "Please give a '--preferred-chain value' value." + _err "Please provide a value for '--preferred-chain'." return 1 fi mkdir -p "$CA_DIR" @@ -7423,7 +7450,7 @@ _process() { return 1 fi if _is_idn "$_dvalue" && ! _exists idn; then - _err "It seems that $_dvalue is an IDN( Internationalized Domain Names), please install 'idn' command first." + _err "It seems that $_dvalue is an IDN (Internationalized Domain Names), please install the 'idn' command first." return 1 fi @@ -7698,6 +7725,10 @@ _process() { _deploy_hook="$_deploy_hook$2," shift ;; + --extended-key-usage) + Le_ExtKeyUse="$2" + shift + ;; --ocsp-must-staple | --ocsp) Le_OCSP_Staple="1" ;; @@ -7785,7 +7816,7 @@ _process() { --notify-level) _nlevel="$2" if _startswith "$_nlevel" "-"; then - _err "'$_nlevel' is not a integer for '$1'" + _err "'$_nlevel' is not an integer for '$1'" return 1 fi _notify_level="$_nlevel" @@ -7794,7 +7825,7 @@ _process() { --notify-mode) _nmode="$2" if _startswith "$_nmode" "-"; then - _err "'$_nmode' is not a integer for '$1'" + _err "'$_nmode' is not an integer for '$1'" return 1 fi _notify_mode="$_nmode" @@ -7803,7 +7834,7 @@ _process() { --notify-source) _nsource="$2" if _startswith "$_nsource" "-"; then - _err "'$_nsource' is not valid host name for '$1'" + _err "'$_nsource' is not a valid host name for '$1'" return 1 fi _notify_source="$_nsource" @@ -7812,7 +7843,7 @@ _process() { --revoke-reason) _revoke_reason="$2" if _startswith "$_revoke_reason" "-"; then - _err "'$_revoke_reason' is not a integer for '$1'" + _err "'$_revoke_reason' is not an integer for '$1'" return 1 fi shift @@ -7830,7 +7861,7 @@ _process() { shift ;; *) - _err "Unknown parameter : $1" + _err "Unknown parameter: $1" return 1 ;; esac @@ -7847,7 +7878,7 @@ _process() { if [ "$__INTERACTIVE" ] && ! _checkSudo; then if [ -z "$FORCE" ]; then #Use "echo" here, instead of _info. it's too early - echo "It seems that you are using sudo, please read this link first:" + echo "It seems that you are using sudo, please read this page first:" echo "$_SUDO_WIKI" return 1 fi @@ -7877,7 +7908,7 @@ _process() { fi SYS_LOG="$_syslog" else - _err "The 'logger' command is not found, can not enable syslog." + _err "The 'logger' command was not found, cannot enable syslog." _clearaccountconf "SYS_LOG" SYS_LOG="" fi @@ -8004,7 +8035,7 @@ _process() { _saveaccountconf "SYS_LOG" "$_syslog" fi else - _err "The 'logger' command is not found, can not enable syslog." + _err "The 'logger' command was not found, cannot enable syslog." _clearaccountconf "SYS_LOG" SYS_LOG="" fi diff --git a/deploy/ali_cdn.sh b/deploy/ali_cdn.sh new file mode 100644 index 00000000..70a2e532 --- /dev/null +++ b/deploy/ali_cdn.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034,SC2154 + +# Script to create certificate to Alibaba Cloud CDN +# +# Docs: https://github.com/acmesh-official/acme.sh/wiki/deployhooks#33-deploy-your-certificate-to-cdn-or-dcdn-of-alibaba-cloud-aliyun +# +# This deployment required following variables +# export Ali_Key="ALIACCESSKEY" +# export Ali_Secret="ALISECRETKEY" +# The credentials are shared with all the Alibaba Cloud deploy hooks and dnsapi +# +# To specify the CDN domain that is different from the certificate CN, usually used for multi-domain or wildcard certificates +# export DEPLOY_ALI_CDN_DOMAIN="cdn.example.com" +# If you have multiple CDN domains using the same certificate, just +# export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com" +# +# For DCDN, see ali_dcdn deploy hook + +Ali_CDN_API="https://cdn.aliyuncs.com/" + +ali_cdn_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + # Load dnsapi/dns_ali.sh to reduce the duplicated codes + # https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276 + dnsapi_ali="$(_findHook "$_cdomain" "$_SUB_FOLDER_DNSAPI" dns_ali)" + # shellcheck source=/dev/null + if ! . "$dnsapi_ali"; then + _err "Error loading file $dnsapi_ali. Please check your API file and try again." + return 1 + fi + + _prepare_ali_credentials || return 1 + + _getdeployconf DEPLOY_ALI_CDN_DOMAIN + if [ "$DEPLOY_ALI_CDN_DOMAIN" ]; then + _savedeployconf DEPLOY_ALI_CDN_DOMAIN "$DEPLOY_ALI_CDN_DOMAIN" + else + DEPLOY_ALI_CDN_DOMAIN="$_cdomain" + fi + + # read cert and key files and urlencode both + _cert=$(_url_encode upper-hex <"$_cfullchain") + _key=$(_url_encode upper-hex <"$_ckey") + + _debug2 _cert "$_cert" + _debug2 _key "$_key" + + ## update domain ssl config + for domain in $DEPLOY_ALI_CDN_DOMAIN; do + _set_cdn_domain_ssl_certificate_query "$domain" "$_cert" "$_key" + if _ali_rest "Set CDN domain SSL certificate for $domain" "" POST; then + _info "Domain $domain certificate has been deployed successfully" + fi + done + + return 0 +} + +# domain pub pri +_set_cdn_domain_ssl_certificate_query() { + endpoint=$Ali_CDN_API + query='' + query=$query'AccessKeyId='$Ali_Key + query=$query'&Action=SetCdnDomainSSLCertificate' + query=$query'&CertType=upload' + query=$query'&DomainName='$1 + query=$query'&Format=json' + query=$query'&SSLPri='$3 + query=$query'&SSLProtocol=on' + query=$query'&SSLPub='$2 + query=$query'&SignatureMethod=HMAC-SHA1' + query=$query"&SignatureNonce=$(_ali_nonce)" + query=$query'&SignatureVersion=1.0' + query=$query'&Timestamp='$(_timestamp) + query=$query'&Version=2018-05-10' +} diff --git a/deploy/ali_dcdn.sh b/deploy/ali_dcdn.sh new file mode 100644 index 00000000..14ac500a --- /dev/null +++ b/deploy/ali_dcdn.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034,SC2154 + +# Script to create certificate to Alibaba Cloud DCDN +# +# Docs: https://github.com/acmesh-official/acme.sh/wiki/deployhooks#33-deploy-your-certificate-to-cdn-or-dcdn-of-alibaba-cloud-aliyun +# +# This deployment required following variables +# export Ali_Key="ALIACCESSKEY" +# export Ali_Secret="ALISECRETKEY" +# The credentials are shared with all the Alibaba Cloud deploy hooks and dnsapi +# +# To specify the DCDN domain that is different from the certificate CN, usually used for multi-domain or wildcard certificates +# export DEPLOY_ALI_DCDN_DOMAIN="dcdn.example.com" +# If you have multiple CDN domains using the same certificate, just +# export DEPLOY_ALI_DCDN_DOMAIN="dcdn1.example.com dcdn2.example.com" +# +# For regular CDN, see ali_cdn deploy hook + +Ali_DCDN_API="https://dcdn.aliyuncs.com/" + +ali_dcdn_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + # Load dnsapi/dns_ali.sh to reduce the duplicated codes + # https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276 + dnsapi_ali="$(_findHook "$_cdomain" "$_SUB_FOLDER_DNSAPI" dns_ali)" + # shellcheck source=/dev/null + if ! . "$dnsapi_ali"; then + _err "Error loading file $dnsapi_ali. Please check your API file and try again." + return 1 + fi + + _prepare_ali_credentials || return 1 + + _getdeployconf DEPLOY_ALI_DCDN_DOMAIN + if [ "$DEPLOY_ALI_DCDN_DOMAIN" ]; then + _savedeployconf DEPLOY_ALI_DCDN_DOMAIN "$DEPLOY_ALI_DCDN_DOMAIN" + else + DEPLOY_ALI_DCDN_DOMAIN="$_cdomain" + fi + + # read cert and key files and urlencode both + _cert=$(_url_encode upper-hex <"$_cfullchain") + _key=$(_url_encode upper-hex <"$_ckey") + + _debug2 _cert "$_cert" + _debug2 _key "$_key" + + ## update domain ssl config + for domain in $DEPLOY_ALI_DCDN_DOMAIN; do + _set_dcdn_domain_ssl_certificate_query "$domain" "$_cert" "$_key" + if _ali_rest "Set DCDN domain SSL certificate for $domain" "" POST; then + _info "Domain $domain certificate has been deployed successfully" + fi + done + + return 0 +} + +# domain pub pri +_set_dcdn_domain_ssl_certificate_query() { + endpoint=$Ali_DCDN_API + query='' + query=$query'AccessKeyId='$Ali_Key + query=$query'&Action=SetDcdnDomainSSLCertificate' + query=$query'&CertType=upload' + query=$query'&DomainName='$1 + query=$query'&Format=json' + query=$query'&SSLPri='$3 + query=$query'&SSLProtocol=on' + query=$query'&SSLPub='$2 + query=$query'&SignatureMethod=HMAC-SHA1' + query=$query"&SignatureNonce=$(_ali_nonce)" + query=$query'&SignatureVersion=1.0' + query=$query'&Timestamp='$(_timestamp) + query=$query'&Version=2018-01-15' +} diff --git a/deploy/exim4.sh b/deploy/exim4.sh index 260b8798..cf664d79 100644 --- a/deploy/exim4.sh +++ b/deploy/exim4.sh @@ -109,6 +109,5 @@ exim4_deploy() { fi return 1 fi - return 0 } diff --git a/deploy/routeros.sh b/deploy/routeros.sh index d1779b8d..90f0ad1a 100644 --- a/deploy/routeros.sh +++ b/deploy/routeros.sh @@ -137,7 +137,8 @@ routeros_deploy() { return $_err_code fi - DEPLOY_SCRIPT_CMD="/system script add name=\"LECertDeploy-$_cdomain\" owner=$ROUTER_OS_USERNAME \ + DEPLOY_SCRIPT_CMD=":do {/system script remove \"LECertDeploy-$_cdomain\" } on-error={ }; \ +/system script add name=\"LECertDeploy-$_cdomain\" owner=$ROUTER_OS_USERNAME \ comment=\"generated by routeros deploy script in acme.sh\" \ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\ \n/certificate remove [ find name=$_cdomain.cer_1 ];\ @@ -146,8 +147,8 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\ \n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\ \n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\ \ndelay 1;\ -\n/file remove $_cdomain.cer;\ -\n/file remove $_cdomain.key;\ +\n:do {/file remove $_cdomain.cer; } on-error={ }\ +\n:do {/file remove $_cdomain.key; } on-error={ }\ \ndelay 2;\ \n/ip service set www-ssl certificate=$_cdomain.cer_0;\ \n$ROUTER_OS_ADDITIONAL_SERVICES;\ diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 342fb32e..0d01e199 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -39,7 +39,7 @@ ################################################################################ # Dependencies: # - curl -# - synouser & synogroup (When available and SYNO_USE_TEMP_ADMIN is set) +# - synouser & synogroup & synosetkeyvalue (Required for SYNO_USE_TEMP_ADMIN=1) ################################################################################ # Return value: # 0 means success, otherwise error. @@ -66,14 +66,18 @@ synology_dsm_deploy() { _getdeployconf SYNO_DEVICE_NAME # Prepare to use temp admin if SYNO_USE_TEMP_ADMIN is set - _debug2 SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN" _getdeployconf SYNO_USE_TEMP_ADMIN _check2cleardeployconfexp SYNO_USE_TEMP_ADMIN _debug2 SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN" if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then - if ! _exists synouser || ! _exists synogroup; then - _err "Tools are missing for creating temp admin user, please set SYNO_USERNAME and SYNO_PASSWORD instead." + if ! _exists synouser || ! _exists synogroup || ! _exists synosetkeyvalue; then + _err "Missing required tools to creat temp admin user, please set SYNO_USERNAME and SYNO_PASSWORD instead." + _err "Notice: temp admin user authorization method only supports local deployment on DSM." + return 1 + fi + if synouser --help 2>&1 | grep -q 'Permission denied'; then + _err "For creating temp admin user, the deploy script must be run as root." return 1 fi @@ -109,9 +113,9 @@ synology_dsm_deploy() { # Default values for scheme, hostname and port # Defaulting to localhost and http, because it's localhost… - [ -n "$SYNO_SCHEME" ] || SYNO_SCHEME="http" - [ -n "$SYNO_HOSTNAME" ] || SYNO_HOSTNAME="localhost" - [ -n "$SYNO_PORT" ] || SYNO_PORT="5000" + [ -n "$SYNO_SCHEME" ] || SYNO_SCHEME=http + [ -n "$SYNO_HOSTNAME" ] || SYNO_HOSTNAME=localhost + [ -n "$SYNO_PORT" ] || SYNO_PORT=5000 _savedeployconf SYNO_SCHEME "$SYNO_SCHEME" _savedeployconf SYNO_HOSTNAME "$SYNO_HOSTNAME" _savedeployconf SYNO_PORT "$SYNO_PORT" @@ -169,7 +173,7 @@ synology_dsm_deploy() { _debug3 H1 "${_H1}" fi - response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DEVICE_ID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DEVICE_ID" "$_base_url/webapi/$api_path?enable_syno_token=yes") _debug3 response "$response" # ## END ## - DEPRECATED, for backward compatibility # If SYNO_DEVICE_ID or SYNO_OTP_CODE is set, we treat current account enabled 2FA-OTP. @@ -184,7 +188,7 @@ synology_dsm_deploy() { _debug SYNO_LOCAL_HOSTNAME "${SYNO_LOCAL_HOSTNAME:-}" if [ "$SYNO_LOCAL_HOSTNAME" != "1" ] && [ "$SYNO_LOCAL_HOSTNAME" == "$SYNO_HOSTNAME" ]; then if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then - _err "SYNO_USE_TEMP_ADMIN=1 Only support locally deployment, if you are sure that hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun." + _err "SYNO_USE_TEMP_ADMIN=1 only support local deployment, though if you are sure that the hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun." return 1 fi fi @@ -201,24 +205,27 @@ synology_dsm_deploy() { # shellcheck disable=SC2086 synogroup --member administrators $cur_admins $SYNO_USERNAME >/dev/null else - _err "Tool synogroup may be broken, please set SYNO_USERNAME and SYNO_PASSWORD instead." + _err "The tool synogroup may be broken, please set SYNO_USERNAME and SYNO_PASSWORD instead." return 1 fi else _err "Unsupported synogroup tool detected, please set SYNO_USERNAME and SYNO_PASSWORD instead." return 1 fi - # havig a workaround to temporary disable enforce 2FA-OTP + # havig a workaround to temporary disable enforce 2FA-OTP, will restore + # it soon (after a single request), though if any accident occurs like + # unexpected interruption, this setting can be easily reverted manually. otp_enforce_option=$(synogetkeyvalue /etc/synoinfo.conf otp_enforce_option) if [ -n "$otp_enforce_option" ] && [ "${otp_enforce_option:-"none"}" != "none" ]; then synosetkeyvalue /etc/synoinfo.conf otp_enforce_option none - _info "Temporary disabled enforce 2FA-OTP to complete authentication." + _info "Enforcing 2FA-OTP has been disabled to complete temp admin authentication." + _info "Notice: it will be restored soon, if not, you can restore it manually via Control Panel." _info "previous_otp_enforce_option" "$otp_enforce_option" else otp_enforce_option="" fi fi - response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes") + response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes") if [ -n "$SYNO_USE_TEMP_ADMIN" ] && [ -n "$otp_enforce_option" ]; then synosetkeyvalue /etc/synoinfo.conf otp_enforce_option "$otp_enforce_option" _info "Restored previous enforce 2FA-OTP option." @@ -230,7 +237,7 @@ synology_dsm_deploy() { error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*') _debug2 error_code "$error_code" # Account has 2FA-OTP enabled, since error 403 reported. - # https://global.download.synology.com/download/Document/Software/DeveloperGuide/Firmware/DSM/All/enu/Synology_DiskStation_Administration_CLI_Guide.pdf + # https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf if [ "$error_code" == "403" ]; then if [ -z "$SYNO_DEVICE_NAME" ]; then printf "Enter device name or leave empty for default (CertRenewal): " @@ -274,12 +281,16 @@ synology_dsm_deploy() { _err "Failed to authenticate with provided 2FA-OTP code, please try again in a new terminal window." elif [ "$error_code" == "406" ]; then if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then - _err "SYNO_USE_TEMP_ADMIN=1 is not supported if enforce auth with 2FA-OTP is enabled." + _err "Failed with unexcepted error, please report this by providing full log with '--debug 3'." else _err "Enforce auth with 2FA-OTP enabled, please configure the user to enable 2FA-OTP to continue." fi - elif [ "$error_code" == "400" ] || [ "$error_code" == "401" ] || [ "$error_code" == "408" ] || [ "$error_code" == "409" ] || [ "$error_code" == "410" ]; then - _err "Failed to authenticate with a non-existent or disabled account, or the account password is incorrect or has expired." + elif [ "$error_code" == "400" ]; then + _err "Failed to authenticate, no such account or incorrect password." + elif [ "$error_code" == "401" ]; then + _err "Failed to authenticate with a non-existent account." + elif [ "$error_code" == "408" ] || [ "$error_code" == "409" ] || [ "$error_code" == "410" ]; then + _err "Failed to authenticate, the account password has expired or must be changed." else _err "Failed to authenticate with error: $error_code." fi @@ -293,7 +304,7 @@ synology_dsm_deploy() { _debug SynoToken "$token" if [ -z "$sid" ] || [ -z "$token" ]; then # Still can't get necessary info even got no errors, may Synology have API updated? - _err "Unable to authenticate to $_base_url, you may report the full log to the community." + _err "Unable to authenticate to $_base_url, you may report this by providing full log with '--debug 3'." _temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME" return 1 fi @@ -331,7 +342,7 @@ synology_dsm_deploy() { if [ "$error_code" -eq 105 ]; then _err "Current user is not administrator and does not have sufficient permission for deploying." else - _err "Failed to fetch certificate info with error: $error_code, please try again or contact Synology to learn more." + _err "Failed to fetch certificate info: $error_code, please try again or contact Synology to learn more." fi _temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME" return 1 diff --git a/deploy/unifi.sh b/deploy/unifi.sh index a864135e..4d8c058e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -5,6 +5,15 @@ # - self-hosted Unifi Controller # - Unifi Cloud Key (Gen1/2/2+) # - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# - Unifi Dream Machine +# This has not been tested on other "all-in-one" devices such as +# UDM Pro or Unifi Express. +# +# OS Version v2.0.0+ +# Network Application version 7.0.0+ +# OS version ~3.1 removed java and keytool from the UnifiOS. +# Using PKCS12 format keystore appears to work fine. +# # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. @@ -74,14 +83,16 @@ unifi_deploy() { _reload_cmd="" # Unifi Controller environment (self hosted or any Cloud Key) -- - # auto-detect by file /usr/lib/unifi/data/keystore: + # auto-detect by file /usr/lib/unifi/data/keystore _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" if [ -f "$_unifi_keystore" ]; then - _info "Installing certificate for Unifi Controller (Java keystore)" _debug _unifi_keystore "$_unifi_keystore" if ! _exists keytool; then - _err "keytool not found" - return 1 + _do_keytool=0 + _info "Installing certificate for Unifi Controller (PKCS12 keystore)." + else + _do_keytool=1 + _info "Installing certificate for Unifi Controller (Java keystore)" fi if [ ! -w "$_unifi_keystore" ]; then _err "The file $_unifi_keystore is not writable, please change the permission." @@ -92,6 +103,7 @@ unifi_deploy() { _debug "Generate import pkcs12" _import_pkcs12="$(_mktemp)" + _debug "_toPkcs $_import_pkcs12 $_ckey $_ccert $_cca $_unifi_keypass unifi root" _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root # shellcheck disable=SC2181 if [ "$?" != "0" ]; then @@ -99,22 +111,57 @@ unifi_deploy() { return 1 fi - _debug "Import into keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _debug "Import keystore success!" - rm "$_import_pkcs12" + # Save the existing keystore in case something goes wrong. + mv -f "${_unifi_keystore}" "${_unifi_keystore}"_original + _info "Previous keystore saved to ${_unifi_keystore}_original." + + if [ "$_do_keytool" -eq 1 ]; then + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + else + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + _info "Restoring original keystore." + mv -f "${_unifi_keystore}"_original "${_unifi_keystore}" + rm "$_import_pkcs12" + return 1 + fi else - _err "Error importing into Unifi Java keystore." - _err "Please re-run with --debug and report a bug." - rm "$_import_pkcs12" - return 1 + _debug "Copying new keystore to $_unifi_keystore" + cp -f "$_import_pkcs12" "$_unifi_keystore" + fi + + # Update unifi service for certificate cipher compatibility + if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \ + -in "$_import_pkcs12" \ + -password pass:aircontrolenterprise \ + -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \ + -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then + cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original + _info "Updating system configuration for cipher compatibility." + _info "Saved original system config to /usr/lib/unifi/data/system.properties_original" + sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties + echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties + sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties + echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties + _info "System configuration updated." fi + rm "$_import_pkcs12" + + # Restarting unifi-core will bring up unifi, doing it out of order results in + # a certificate error, and breaks wifiman. + # Restart if we aren't doing unifi-core, otherwise stop for later restart. if systemctl -q is-active unifi; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi" + else + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl stop unifi" + fi fi _services_updated="${_services_updated} unifi" _info "Install Unifi Controller certificate success!" @@ -165,6 +212,11 @@ unifi_deploy() { return 1 fi + # Save the existing certs in case something goes wrong. + cp -f "${_unifi_core_config}"/unifi-core.crt "${_unifi_core_config}"/unifi-core_original.crt + cp -f "${_unifi_core_config}"/unifi-core.key "${_unifi_core_config}"/unifi-core_original.key + _info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt/key." + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" diff --git a/deploy/vault.sh b/deploy/vault.sh index 569faba2..03a0de83 100644 --- a/deploy/vault.sh +++ b/deploy/vault.sh @@ -70,10 +70,10 @@ vault_deploy() { # JSON does not allow multiline strings. # So replacing new-lines with "\n" here - _ckey=$(sed -z 's/\n/\\n/g' <"$2") - _ccert=$(sed -z 's/\n/\\n/g' <"$3") - _cca=$(sed -z 's/\n/\\n/g' <"$4") - _cfullchain=$(sed -z 's/\n/\\n/g' <"$5") + _ckey=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$2") + _ccert=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$3") + _cca=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$4") + _cfullchain=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$5") export _H1="X-Vault-Token: $VAULT_TOKEN" diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh index 8cf24e4f..570495cc 100644 --- a/deploy/vsftpd.sh +++ b/deploy/vsftpd.sh @@ -106,5 +106,5 @@ vsftpd_deploy() { fi return 1 fi - return 0 + } diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index 3f54a714..906ea443 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -211,8 +211,8 @@ _get_root() { return 1 fi - _authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." - if _contains "$_response" "serial" && ! _contains "$_response" "null"; then + _authget "https://1984.hosting/domains/zonestatus/$h/?cached=no" + if _contains "$_response" '"ok": true'; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 @@ -246,7 +246,6 @@ _authget() { } # Truncate huge HTML response -# Echo: Argument list too long _htmlget() { export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" _response=$(_get "$1" | grep "$2") diff --git a/dnsapi/dns_active24.sh b/dnsapi/dns_active24.sh index 1a6f97f0..c56dd363 100755 --- a/dnsapi/dns_active24.sh +++ b/dnsapi/dns_active24.sh @@ -83,10 +83,10 @@ _get_root() { return 1 fi - i=2 + i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug "h" "$h" if [ -z "$h" ]; then #not valid @@ -94,7 +94,7 @@ _get_root() { fi if _contains "$response" "\"$h\"" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh index ccd8226f..850af5b4 100755 --- a/dnsapi/dns_ad.sh +++ b/dnsapi/dns_ad.sh @@ -95,7 +95,7 @@ _get_root() { if _ad_rest GET "domain/"; then response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -106,7 +106,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_ali.sh b/dnsapi/dns_ali.sh index 9bdfc20b..53a82f91 100755 --- a/dnsapi/dns_ali.sh +++ b/dnsapi/dns_ali.sh @@ -9,25 +9,19 @@ Options: Ali_Secret API Secret ' -Ali_API="https://alidns.aliyuncs.com/" +# NOTICE: +# This file is referenced by Alibaba Cloud Services deploy hooks +# https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276 +# Be careful when modifying this file, especially when making breaking changes for common functions + +Ali_DNS_API="https://alidns.aliyuncs.com/" #Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_ali_add() { fulldomain=$1 txtvalue=$2 - Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}" - Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}" - if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then - Ali_Key="" - Ali_Secret="" - _err "You don't specify aliyun api key and secret yet." - return 1 - fi - - #save the api key and secret to the account conf file. - _saveaccountconf_mutable Ali_Key "$Ali_Key" - _saveaccountconf_mutable Ali_Secret "$Ali_Secret" + _prepare_ali_credentials || return 1 _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -52,14 +46,74 @@ dns_ali_rm() { _clean } -#################### Private functions below ################################## +#################### Alibaba Cloud common functions below #################### + +_prepare_ali_credentials() { + Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}" + Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}" + if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then + Ali_Key="" + Ali_Secret="" + _err "You don't specify aliyun api key and secret yet." + return 1 + fi + + #save the api key and secret to the account conf file. + _saveaccountconf_mutable Ali_Key "$Ali_Key" + _saveaccountconf_mutable Ali_Secret "$Ali_Secret" +} + +# act ign mtd +_ali_rest() { + act="$1" + ign="$2" + mtd="${3:-GET}" + + signature=$(printf "%s" "$mtd&%2F&$(printf "%s" "$query" | _url_encode upper-hex)" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64) + signature=$(printf "%s" "$signature" | _url_encode upper-hex) + url="$endpoint?Signature=$signature" + + if [ "$mtd" = "GET" ]; then + url="$url&$query" + response="$(_get "$url")" + else + response="$(_post "$query" "$url" "" "$mtd" "application/x-www-form-urlencoded")" + fi + + _ret="$?" + _debug2 response "$response" + if [ "$_ret" != "0" ]; then + _err "Error <$act>" + return 1 + fi + + if [ -z "$ign" ]; then + message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")" + if [ "$message" ]; then + _err "$message" + return 1 + fi + fi +} + +_ali_nonce() { + #_head_n 1 " - return 1 - fi - - _debug2 response "$response" - if [ -z "$2" ]; then - message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")" - if [ "$message" ]; then - _err "$message" - return 1 - fi - fi -} - -_ali_urlencode() { - _str="$1" - _str_len=${#_str} - _u_i=1 - while [ "$_u_i" -le "$_str_len" ]; do - _str_c="$(printf "%s" "$_str" | cut -c "$_u_i")" - case $_str_c in [a-zA-Z0-9.~_-]) - printf "%s" "$_str_c" - ;; - *) - printf "%%%02X" "'$_str_c" - ;; - esac - _u_i="$(_math "$_u_i" + 1)" - done -} - -_ali_nonce() { - #_head_n 1 1" >/dev/null; then _zone="$(echo "$autodns_response" | _egrep_o '[^<]*' | cut -d '>' -f 2 | cut -d '<' -f 1)" _system_ns="$(echo "$autodns_response" | _egrep_o '[^<]*' | cut -d '>' -f 2 | cut -d '<' -f 1)" - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") return 0 fi diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index c599b4e0..c88c9d9c 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -158,7 +158,7 @@ _get_root() { # iterate over names (a.b.c.d -> b.c.d -> c.d -> d) while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100 | sed 's/\./\\./g') + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100 | sed 's/\./\\./g') _debug "Checking domain: $h" if [ -z "$h" ]; then _error "invalid domain" @@ -174,7 +174,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o ".*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_azion.sh b/dnsapi/dns_azion.sh index 2371833e..1375e32f 100644 --- a/dnsapi/dns_azion.sh +++ b/dnsapi/dns_azion.sh @@ -100,7 +100,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then # not valid @@ -111,7 +111,7 @@ _get_root() { _domain_id=$(echo "$response" | tr '{' "\n" | grep "\"domain\":\"$h\"" | _egrep_o "\"id\":[0-9]*" | _head_n 1 | cut -d : -f 2 | tr -d \") _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index 00ccd798..7d818cc2 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -11,12 +11,14 @@ Options: AZUREDNS_MANAGEDIDENTITY Use Managed Identity. Use Managed Identity assigned to a resource instead of a service principal. "true"/"false" ' +wiki=https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS + ######## Public functions ##################### # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Used to add txt record # -# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate +# Ref: https://learn.microsoft.com/en-us/rest/api/dns/record-sets/create-or-update?view=rest-dns-2018-05-01&tabs=HTTP # dns_azure_add() { @@ -133,7 +135,7 @@ dns_azure_add() { # Usage: fulldomain txtvalue # Used to remove the txt record after validation # -# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/delete +# Ref: https://learn.microsoft.com/en-us/rest/api/dns/record-sets/delete?view=rest-dns-2018-05-01&tabs=HTTP # dns_azure_rm() { fulldomain=$1 @@ -265,10 +267,10 @@ _azure_rest() { if [ "$_code" = "401" ]; then # we have an invalid access token set to expired _saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "0" - _err "access denied make sure your Azure settings are correct. See $WIKI" + _err "Access denied. Invalid access token. Make sure your Azure settings are correct. See: $wiki" return 1 fi - # See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes + # See https://learn.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then _request_retry_times="$(_math "$_request_retry_times" + 1)" _info "REST call error $_code retrying $ep in $_request_retry_times s" @@ -286,7 +288,7 @@ _azure_rest() { return 0 } -## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token +## Ref: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow#request-an-access-token _azure_getaccess_token() { managedIdentity=$1 tenantID=$2 @@ -310,7 +312,7 @@ _azure_getaccess_token() { _debug "getting new bearer token" if [ "$managedIdentity" = true ]; then - # https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http + # https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http export _H1="Metadata: true" response="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)" response="$(echo "$response" | _normalizeJson)" @@ -330,7 +332,7 @@ _azure_getaccess_token() { fi if [ -z "$accesstoken" ]; then - _err "no acccess token received. Check your Azure settings see $WIKI" + _err "No acccess token received. Check your Azure settings. See: $wiki" return 1 fi if [ "$_ret" != "0" ]; then @@ -350,15 +352,18 @@ _get_root() { i=1 p=1 - ## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list - ## returns up to 100 zones in one response therefore handling more results is not not implemented - ## (ZoneListResult with continuation token for the next page of results) - ## Per https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits#dns-limits you are limited to 100 Zone/subscriptions anyways + ## Ref: https://learn.microsoft.com/en-us/rest/api/dns/zones/list?view=rest-dns-2018-05-01&tabs=HTTP + ## returns up to 100 zones in one response. Handling more results is not implemented + ## (ZoneListResult with continuation token for the next page of results) + ## + ## TODO: handle more than 100 results, as per: + ## https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-dns-limits + ## The new limit is 250 Public DNS zones per subscription, while the old limit was only 100 ## _azure_rest GET "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Network/dnszones?\$top=500&api-version=2017-09-01" "" "$accesstoken" # Find matching domain name in Json response while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug2 "Checking domain: $h" if [ -z "$h" ]; then #not valid @@ -373,7 +378,7 @@ _get_root() { #create the record at the domain apex (@) if only the domain name was provided as --domain-alias _sub_domain="@" else - _sub_domain=$(echo "$domain" | cut -d . -f 1-$p) + _sub_domain=$(echo "$domain" | cut -d . -f 1-"$p") fi _domain=$h return 0 diff --git a/dnsapi/dns_bunny.sh b/dnsapi/dns_bunny.sh index 681f748a..780198e1 100644 --- a/dnsapi/dns_bunny.sh +++ b/dnsapi/dns_bunny.sh @@ -196,7 +196,7 @@ _get_base_domain() { _debug2 domain_list "$domain_list" i=1 - while [ $i -gt 0 ]; do + while [ "$i" -gt 0 ]; do ## get next longest domain _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") ## check we got something back from our cut (or are we at the end) @@ -208,7 +208,7 @@ _get_base_domain() { ## check if it exists if [ -n "$found" ]; then ## exists - exit loop returning the parts - sub_point=$(_math $i - 1) + sub_point=$(_math "$i" - 1) _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") _domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" _debug _domain_id "$_domain_id" @@ -218,11 +218,11 @@ _get_base_domain() { return 0 fi ## increment cut point $i - i=$(_math $i + 1) + i=$(_math "$i" + 1) done if [ -z "$found" ]; then - page=$(_math $page + 1) + page=$(_math "$page" + 1) nextpage="https://api.bunny.net/dnszone?page=$page" ## Find the next page if we don't have a match. hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")" diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index da63e771..736742f3 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -186,7 +186,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -206,7 +206,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 145a85be..8bb0e00d 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -164,7 +164,7 @@ _dns_cloudns_get_zone_info() { _dns_cloudns_get_zone_name() { i=2 while true; do - zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) + zoneForCheck=$(printf "%s" "$1" | cut -d . -f "$i"-100) if [ -z "$zoneForCheck" ]; then return 1 diff --git a/dnsapi/dns_cn.sh b/dnsapi/dns_cn.sh index 797f788e..79698e88 100644 --- a/dnsapi/dns_cn.sh +++ b/dnsapi/dns_cn.sh @@ -131,7 +131,7 @@ _cn_get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" _debug _H1 "${_H1}" @@ -149,7 +149,7 @@ _cn_get_root() { fi if _contains "$_cn_zonelist" "\"name\":\"$h\"" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 else diff --git a/dnsapi/dns_conoha.sh b/dnsapi/dns_conoha.sh index 6ceca829..ecd56fc8 100755 --- a/dnsapi/dns_conoha.sh +++ b/dnsapi/dns_conoha.sh @@ -237,7 +237,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100). + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100). _debug h "$h" if [ -z "$h" ]; then #not valid @@ -251,7 +251,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\"" >/dev/null; then _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 0376dda1..6a50e199 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -122,7 +122,7 @@ _get_root() { p=1 _debug "Detecting root zone" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then return 1 fi @@ -134,7 +134,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\""; then _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-"$p") _domain="$h" _debug _domain_id "$_domain_id" diff --git a/dnsapi/dns_curanet.sh b/dnsapi/dns_curanet.sh index a530d304..f57afa1f 100644 --- a/dnsapi/dns_curanet.sh +++ b/dnsapi/dns_curanet.sh @@ -142,7 +142,7 @@ _get_root() { i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid diff --git a/dnsapi/dns_da.sh b/dnsapi/dns_da.sh index b2789a6f..36251b05 100755 --- a/dnsapi/dns_da.sh +++ b/dnsapi/dns_da.sh @@ -61,7 +61,7 @@ _get_root() { # response will contain "list[]=example.com&list[]=example.org" _da_api CMD_API_SHOW_DOMAINS "" "${domain}" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then # not valid @@ -69,7 +69,7 @@ _get_root() { return 1 fi if _contains "$response" "$h" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_desec.sh b/dnsapi/dns_desec.sh index 0d6a6c2f..d6b9c355 100644 --- a/dnsapi/dns_desec.sh +++ b/dnsapi/dns_desec.sh @@ -176,7 +176,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -188,7 +188,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index 9aaa9606..cb887cfa 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -203,7 +203,7 @@ _get_base_domain() { _debug2 domain_list "$domain_list" i=1 - while [ $i -gt 0 ]; do + while [ "$i" -gt 0 ]; do ## get next longest domain _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") ## check we got something back from our cut (or are we at the end) @@ -215,14 +215,14 @@ _get_base_domain() { ## check if it exists if [ -n "$found" ]; then ## exists - exit loop returning the parts - sub_point=$(_math $i - 1) + sub_point=$(_math "$i" - 1) _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") _debug _domain "$_domain" _debug _sub_domain "$_sub_domain" return 0 fi ## increment cut point $i - i=$(_math $i + 1) + i=$(_math "$i" + 1) done if [ -z "$found" ]; then diff --git a/dnsapi/dns_dnsexit.sh b/dnsapi/dns_dnsexit.sh index 9f2871b4..ec3b07a4 100644 --- a/dnsapi/dns_dnsexit.sh +++ b/dnsapi/dns_dnsexit.sh @@ -84,7 +84,7 @@ _get_root() { domain=$1 i=1 while true; do - _domain=$(printf "%s" "$domain" | cut -d . -f $i-100) + _domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$_domain" if [ -z "$_domain" ]; then return 1 diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index e080ecf0..10a3821d 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -92,7 +92,7 @@ _get_root() { i=2 previous=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then # not valid return 1 @@ -105,7 +105,7 @@ _get_root() { if _contains "$response" 'not found'; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$previous") _domain="$h" _debug _domain "$_domain" diff --git a/dnsapi/dns_doapi.sh b/dnsapi/dns_doapi.sh index 9bc6a4a4..0804f2e6 100755 --- a/dnsapi/dns_doapi.sh +++ b/dnsapi/dns_doapi.sh @@ -2,7 +2,6 @@ # shellcheck disable=SC2034 dns_doapi_info='Domain-Offensive do.de Official LetsEncrypt API for do.de / Domain-Offensive. - This is different from the dns_do adapter, because dns_do is only usable for enterprise customers. This API is also available to private customers/individuals. Site: do.de Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_doapi @@ -11,7 +10,7 @@ Options: Issues: github.com/acmesh-official/acme.sh/issues/2057 ' -DO_API="https://www.do.de/api/letsencrypt" +DO_API="https://my.do.de/api/letsencrypt" ######## Public functions ##################### diff --git a/dnsapi/dns_domeneshop.sh b/dnsapi/dns_domeneshop.sh index 16d3dbe5..925ca335 100644 --- a/dnsapi/dns_domeneshop.sh +++ b/dnsapi/dns_domeneshop.sh @@ -93,7 +93,7 @@ _get_domainid() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug "h" "$h" if [ -z "$h" ]; then #not valid @@ -102,7 +102,7 @@ _get_domainid() { if _contains "$response" "\"$h\"" >/dev/null; then # We have found the domain name. - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h _domainid=$(printf "%s" "$response" | _egrep_o "[^{]*\"domain\":\"$_domain\"[^}]*" | _egrep_o "\"id\":[0-9]+" | cut -d : -f 2) return 0 diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 29d32c27..7bc331e2 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -109,7 +109,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -123,7 +123,7 @@ _get_root() { _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _debug _sub_domain "$_sub_domain" _domain="$h" _debug _domain "$_domain" diff --git a/dnsapi/dns_dpi.sh b/dnsapi/dns_dpi.sh index 521f2d69..e8b9b5a5 100755 --- a/dnsapi/dns_dpi.sh +++ b/dnsapi/dns_dpi.sh @@ -109,7 +109,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -123,7 +123,7 @@ _get_root() { _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _debug _sub_domain "$_sub_domain" _domain="$h" _debug _domain "$_domain" diff --git a/dnsapi/dns_durabledns.sh b/dnsapi/dns_durabledns.sh index cd4bd2eb..d71f0ccb 100644 --- a/dnsapi/dns_durabledns.sh +++ b/dnsapi/dns_durabledns.sh @@ -110,7 +110,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -118,7 +118,7 @@ _get_root() { fi if _contains "$response" ">$h."; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_dynu.sh b/dnsapi/dns_dynu.sh index 0dbeda24..1d1fc311 100644 --- a/dnsapi/dns_dynu.sh +++ b/dnsapi/dns_dynu.sh @@ -126,7 +126,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -140,7 +140,7 @@ _get_root() { if _contains "$response" "\"domainName\":\"$h\"" >/dev/null; then dnsId=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 2 | cut -d : -f 2) _domain_name=$h - _node=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _node=$(printf "%s" "$domain" | cut -d . -f 1-"$p") return 0 fi p=$i diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index 8b94dae7..76af17f5 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -16,8 +16,8 @@ dynv6_api="https://dynv6.com/api/v2" # Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide #Usage: dns_dynv6_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_dynv6_add() { - fulldomain=$1 - txtvalue=$2 + fulldomain="$(echo "$1" | _lower_case)" + txtvalue="$2" _info "Using dynv6 api" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -43,15 +43,14 @@ dns_dynv6_add() { _err "Something went wrong! it does not seem like the record was added successfully" return 1 fi - return 1 fi - return 1 + } #Usage: fulldomain txtvalue #Remove the txt record after validation. dns_dynv6_rm() { - fulldomain=$1 - txtvalue=$2 + fulldomain="$(echo "$1" | _lower_case)" + txtvalue="$2" _info "Using dynv6 API" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -206,7 +205,7 @@ _get_zone_id() { return 1 fi - zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep id | tr -d '"')" + zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep '"id":' | tr -d '"')" _zone_id="${zone_id#id:}" _debug "zone id: $_zone_id" } diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index d168054a..1c96ac8f 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -121,7 +121,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -133,7 +133,7 @@ _get_root() { fi if _contains "$response" "\"status\":200"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_euserv.sh b/dnsapi/dns_euserv.sh index 2da00c3d..744f6ca6 100644 --- a/dnsapi/dns_euserv.sh +++ b/dnsapi/dns_euserv.sh @@ -151,7 +151,7 @@ _get_root() { response="$_euserv_domain_orders" while true; do - h=$(echo "$domain" | cut -d . -f $i-100) + h=$(echo "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -159,7 +159,7 @@ _get_root() { fi if _contains "$response" "$h"; then - _sub_domain=$(echo "$domain" | cut -d . -f 1-$p) + _sub_domain=$(echo "$domain" | cut -d . -f 1-"$p") _domain="$h" if ! _euserv_get_domain_id "$_domain"; then _err "invalid domain" diff --git a/dnsapi/dns_exoscale.sh b/dnsapi/dns_exoscale.sh index 4cc5a513..6898ce38 100755 --- a/dnsapi/dns_exoscale.sh +++ b/dnsapi/dns_exoscale.sh @@ -119,7 +119,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -130,7 +130,7 @@ _get_root() { _domain_id=$(echo "$response" | tr '{' "\n" | grep "\"name\":\"$h\"" | _egrep_o "\"id\":[^,]+" | _head_n 1 | cut -d : -f 2 | tr -d \") _domain_token=$(echo "$response" | tr '{' "\n" | grep "\"name\":\"$h\"" | _egrep_o "\"token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_token" ] && [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_fornex.sh b/dnsapi/dns_fornex.sh index 38cdf5e6..cede0cd0 100644 --- a/dnsapi/dns_fornex.sh +++ b/dnsapi/dns_fornex.sh @@ -90,7 +90,7 @@ _get_root() { i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index 141ddccf..0516fee9 100644 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -95,7 +95,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -112,7 +112,7 @@ _get_root() { elif _contains "$response" '"code": 404'; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_gcore.sh b/dnsapi/dns_gcore.sh index ac2e614c..fbdba7ee 100755 --- a/dnsapi/dns_gcore.sh +++ b/dnsapi/dns_gcore.sh @@ -28,7 +28,7 @@ dns_gcore_add() { fi #save the api key to the account conf file. - _saveaccountconf_mutable GCORE_Key "$GCORE_Key" + _saveaccountconf_mutable GCORE_Key "$GCORE_Key" "base64" _debug "First detect the zone name" if ! _get_root "$fulldomain"; then @@ -138,7 +138,7 @@ _get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -152,7 +152,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\""; then _zone_name=$h if [ "$_zone_name" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_gd.sh b/dnsapi/dns_gd.sh index 08afa8f5..ee66ee19 100755 --- a/dnsapi/dns_gd.sh +++ b/dnsapi/dns_gd.sh @@ -148,7 +148,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -161,7 +161,7 @@ _get_root() { if _contains "$response" '"code":"NOT_FOUND"'; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_geoscaling.sh b/dnsapi/dns_geoscaling.sh index 96b3e218..05887c7e 100755 --- a/dnsapi/dns_geoscaling.sh +++ b/dnsapi/dns_geoscaling.sh @@ -202,7 +202,7 @@ find_zone() { # Walk through all possible zone names strip_counter=1 while true; do - attempted_zone=$(echo "${domain}" | cut -d . -f ${strip_counter}-) + attempted_zone=$(echo "${domain}" | cut -d . -f "${strip_counter}"-) # All possible zone names have been tried if [ -z "${attempted_zone}" ]; then diff --git a/dnsapi/dns_googledomains.sh b/dnsapi/dns_googledomains.sh index 7d241ab6..07a37e07 100755 --- a/dnsapi/dns_googledomains.sh +++ b/dnsapi/dns_googledomains.sh @@ -132,7 +132,7 @@ _dns_googledomains_get_zone() { i=2 while true; do - curr=$(printf "%s" "$domain" | cut -d . -f $i-100) + curr=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug curr "$curr" if [ -z "$curr" ]; then diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index cfb6efb8..a768f352 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -143,7 +143,7 @@ _find_zone() { # Walk through all possible zone names _strip_counter=1 while true; do - _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) + _attempted_zone=$(echo "$_domain" | cut -d . -f "${_strip_counter}"-) # All possible zone names have been tried if [ -z "$_attempted_zone" ]; then diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh index a60bd55d..5a9cf2d9 100644 --- a/dnsapi/dns_hetzner.sh +++ b/dnsapi/dns_hetzner.sh @@ -181,7 +181,7 @@ _get_root() { _debug "Trying to get zone id by domain name for '$domain_without_acme'." while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -193,7 +193,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h HETZNER_Zone_ID=$_domain_id _savedomainconf "$domain_param_name" "$HETZNER_Zone_ID" diff --git a/dnsapi/dns_hexonet.sh b/dnsapi/dns_hexonet.sh index 6c86e6a4..017641fd 100755 --- a/dnsapi/dns_hexonet.sh +++ b/dnsapi/dns_hexonet.sh @@ -123,7 +123,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -135,7 +135,7 @@ _get_root() { fi if _contains "$response" "CODE=200"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index f3df41f4..ee2d2b8e 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -210,7 +210,7 @@ _get_recordset_id() { _zoneid=$3 export _H1="X-Auth-Token: ${_token}" - response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}") + response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}&status=ACTIVE") if _contains "${response}" '"id"'; then _id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")" printf "%s" "${_id}" @@ -227,7 +227,7 @@ _add_record() { # Get Existing Records export _H1="X-Auth-Token: ${_token}" - response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") + response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}&status=ACTIVE") _debug2 "${response}" _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') diff --git a/dnsapi/dns_internetbs.sh b/dnsapi/dns_internetbs.sh index 84dfd70f..4238bfe4 100755 --- a/dnsapi/dns_internetbs.sh +++ b/dnsapi/dns_internetbs.sh @@ -133,7 +133,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f ${i}-100) + h=$(printf "%s" "$domain" | cut -d . -f "${i}"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -141,7 +141,7 @@ _get_root() { fi if _contains "$response" "\"$h\""; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-${p}) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"${p}") _domain=${h} return 0 fi diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 8c89a697..808fc3a9 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -163,6 +163,15 @@ _inwx_check_cookie() { return 1 } +_htmlEscape() { + _s="$1" + _s=$(echo "$_s" | sed "s/&/&/g") + _s=$(echo "$_s" | sed "s//\>/g") + _s=$(echo "$_s" | sed 's/"/\"/g') + printf -- %s "$_s" +} + _inwx_login() { if _inwx_check_cookie; then @@ -170,6 +179,8 @@ _inwx_login() { return 0 fi + XML_PASS=$(_htmlEscape "$INWX_Password") + xml_content=$(printf ' account.login @@ -193,7 +204,7 @@ _inwx_login() { - ' "$INWX_User" "$INWX_Password") + ' "$INWX_User" "$XML_PASS") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" @@ -282,7 +293,7 @@ _get_root() { response="$(_post "$xml_content" "$INWX_Api" "" "POST")" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -290,7 +301,7 @@ _get_root() { fi if _contains "$response" "$h"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e4d28e11..9a464253 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -87,7 +87,7 @@ _get_root() { _response="$(echo "$_response" | tr -d "\n")" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then return 1 fi @@ -96,7 +96,7 @@ _get_root() { if [ "$_zone" ]; then _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 diff --git a/dnsapi/dns_ionos_cloud.sh b/dnsapi/dns_ionos_cloud.sh new file mode 100644 index 00000000..fa229e03 --- /dev/null +++ b/dnsapi/dns_ionos_cloud.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env sh + +# Supports IONOS Cloud DNS API v1.15.4 +# +# Usage: +# Export IONOS_TOKEN before calling acme.sh: +# $ export IONOS_TOKEN="..." +# +# $ acme.sh --issue --dns dns_ionos_cloud ... + +IONOS_CLOUD_API="https://dns.de-fra.ionos.com" +IONOS_CLOUD_ROUTE_ZONES="/zones" + +dns_ionos_cloud_add() { + fulldomain=$1 + txtvalue=$2 + + if ! _ionos_init; then + return 1 + fi + + _record_name=$(printf "%s" "$fulldomain" | cut -d . -f 1) + _body="{\"properties\":{\"name\":\"$_record_name\", \"type\":\"TXT\", \"content\":\"$txtvalue\"}}" + + if _ionos_cloud_rest POST "$IONOS_CLOUD_ROUTE_ZONES/$_zone_id/records" "$_body" && [ "$_code" = "202" ]; then + _info "TXT record has been created successfully." + return 0 + fi + + return 1 +} + +dns_ionos_cloud_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _ionos_init; then + return 1 + fi + + if ! _ionos_cloud_get_record "$_zone_id" "$txtvalue" "$fulldomain"; then + _err "Could not find _acme-challenge TXT record." + return 1 + fi + + if _ionos_cloud_rest DELETE "$IONOS_CLOUD_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ "$_code" = "202" ]; then + _info "TXT record has been deleted successfully." + return 0 + fi + + return 1 +} + +_ionos_init() { + IONOS_TOKEN="${IONOS_TOKEN:-$(_readaccountconf_mutable IONOS_TOKEN)}" + + if [ -z "$IONOS_TOKEN" ]; then + _err "You didn't specify an IONOS token yet." + _err "Read https://api.ionos.com/docs/authentication/v1/#tag/tokens/operation/tokensGenerate to learn how to get a token." + _err "You need to set it before calling acme.sh:" + _err "\$ export IONOS_TOKEN=\"...\"" + _err "\$ acme.sh --issue -d ... --dns dns_ionos_cloud" + return 1 + fi + + _saveaccountconf_mutable IONOS_TOKEN "$IONOS_TOKEN" + + if ! _get_cloud_zone "$fulldomain"; then + _err "Cannot find zone $zone in your IONOS account." + return 1 + fi + + return 0 +} + +_get_cloud_zone() { + domain=$1 + zone=$(printf "%s" "$domain" | cut -d . -f 2-) + + if _ionos_cloud_rest GET "$IONOS_CLOUD_ROUTE_ZONES?filter.zoneName=$zone"; then + _response="$(echo "$_response" | tr -d "\n")" + + _zone_list_items=$(echo "$_response" | _egrep_o "\"items\":.*") + + _zone_id=$(printf "%s\n" "$_zone_list_items" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + if [ "$_zone_id" ]; then + return 0 + fi + fi + + return 1 +} + +_ionos_cloud_get_record() { + zone_id=$1 + txtrecord=$2 + # this is to transform the domain to lower case + fulldomain=$(printf "%s" "$3" | _lower_case) + # this is to transform record name to lower case + # IONOS Cloud API transforms all record names to lower case + _record_name=$(printf "%s" "$fulldomain" | cut -d . -f 1 | _lower_case) + + if _ionos_cloud_rest GET "$IONOS_CLOUD_ROUTE_ZONES/$zone_id/records"; then + _response="$(echo "$_response" | tr -d "\n")" + + pattern="\{\"id\":\"[a-fA-F0-9\-]*\",\"type\":\"record\",\"href\":\"/zones/$zone_id/records/[a-fA-F0-9\-]*\",\"metadata\":\{\"createdDate\":\"[A-Z0-9\:\.\-]*\",\"lastModifiedDate\":\"[A-Z0-9\:\.\-]*\",\"fqdn\":\"$fulldomain\",\"state\":\"AVAILABLE\",\"zoneId\":\"$zone_id\"\},\"properties\":\{\"content\":\"$txtrecord\",\"enabled\":true,\"name\":\"$_record_name\",\"priority\":[0-9]*,\"ttl\":[0-9]*,\"type\":\"TXT\"\}\}" + + _record="$(echo "$_response" | _egrep_o "$pattern")" + if [ "$_record" ]; then + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + return 0 + fi + fi + + return 1 +} + +_ionos_cloud_rest() { + method="$1" + route="$2" + data="$3" + + export _H1="Authorization: Bearer $IONOS_TOKEN" + + # clear headers + : >"$HTTP_HEADER" + + if [ "$method" != "GET" ]; then + _response="$(_post "$data" "$IONOS_CLOUD_API$route" "" "$method" "application/json")" + else + _response="$(_get "$IONOS_CLOUD_API$route")" + fi + + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + + if [ "$?" != "0" ]; then + _err "Error $route: $_response" + return 1 + fi + + _debug2 "_response" "$_response" + _debug2 "_code" "$_code" + + return 0 +} diff --git a/dnsapi/dns_ispconfig.sh b/dnsapi/dns_ispconfig.sh index 7fd0d99c..edc789e1 100755 --- a/dnsapi/dns_ispconfig.sh +++ b/dnsapi/dns_ispconfig.sh @@ -14,6 +14,8 @@ Options: # User must provide login data and URL to the ISPConfig installation incl. port. # The remote user in ISPConfig must have access to: # - DNS txt Functions +# - DNS zone functions +# - Client functions ######## Public functions ##################### diff --git a/dnsapi/dns_jd.sh b/dnsapi/dns_jd.sh index a45aa2ca..4b9067f2 100644 --- a/dnsapi/dns_jd.sh +++ b/dnsapi/dns_jd.sh @@ -135,7 +135,7 @@ _get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug2 "Checking domain: $h" if ! jd_rest GET "domain"; then _err "error get domain list" @@ -153,7 +153,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id="$(echo "$hostedzone" | tr ',' '\n' | grep "\"id\":" | cut -d : -f 2)" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh index 49c544b9..1fe33c67 100644 --- a/dnsapi/dns_joker.sh +++ b/dnsapi/dns_joker.sh @@ -80,7 +80,7 @@ _get_root() { fulldomain=$1 i=1 while true; do - h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then return 1 diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index 7b6fb8a6..762ba8b3 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -102,7 +102,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -113,7 +113,7 @@ _get_root() { if _contains "$response" '"OK":false'; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index 7a1c0a1c..f19333c4 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -113,7 +113,7 @@ _get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -126,7 +126,7 @@ _get_root() { if _contains "$response" '"domainid":'; then _domain_id=$(printf "%s" "$response" | grep '"domainid":' | cut -d : -f 2 | cut -d , -f 1 | tr -d '\r' | tr -d '\n') if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_limacity.sh b/dnsapi/dns_limacity.sh index 649550ae..fb12f8c6 100644 --- a/dnsapi/dns_limacity.sh +++ b/dnsapi/dns_limacity.sh @@ -69,7 +69,7 @@ _lima_get_domain_id() { if [ "$(echo "$domains" | _egrep_o "\{.*""domains""")" ]; then response="$(echo "$domains" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -80,7 +80,7 @@ _lima_get_domain_id() { if [ "$hostedzone" ]; then LIMACITY_DOMAINID=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$LIMACITY_DOMAINID" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 5e4c694b..d74d1fc8 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -136,7 +136,7 @@ _get_root() { if _rest GET "domain.list"; then response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -147,7 +147,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"DOMAINID\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index e562f80f..f6a61a99 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -138,7 +138,7 @@ _get_root() { if _rest GET; then response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -149,7 +149,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_loopia.sh b/dnsapi/dns_loopia.sh index 1f943e51..98a4f3ab 100644 --- a/dnsapi/dns_loopia.sh +++ b/dnsapi/dns_loopia.sh @@ -180,14 +180,14 @@ _get_root() { response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")" while true; do - h=$(echo "$domain" | cut -d . -f $i-100) + h=$(echo "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 fi if _contains "$response" "$h"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_lua.sh b/dnsapi/dns_lua.sh index b037e90f..34cce6a1 100755 --- a/dnsapi/dns_lua.sh +++ b/dnsapi/dns_lua.sh @@ -110,7 +110,7 @@ _get_root() { return 1 fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -121,7 +121,7 @@ _get_root() { _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1) _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_maradns.sh b/dnsapi/dns_maradns.sh index 09d7248e..9eefb175 100755 --- a/dnsapi/dns_maradns.sh +++ b/dnsapi/dns_maradns.sh @@ -72,7 +72,7 @@ _reload_maradns() { pidpath="$1" kill -s HUP -- "$(cat "$pidpath")" if [ $? -ne 0 ]; then - _err "Unable to reload MaraDNS, kill returned $?" + _err "Unable to reload MaraDNS, kill returned" return 1 fi } diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 66545c46..43c903cd 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -107,7 +107,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -120,7 +120,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\""; then _domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/') if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index ec9867db..0824a4e7 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -17,7 +17,7 @@ Author: Darven Dissek, William Gertz dns_miab_add() { fulldomain=$1 txtvalue=$2 - _info "Using miab challange add" + _info "Using miab challenge add" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -26,7 +26,7 @@ dns_miab_add() { return 1 fi - #check domain and seperate into doamin and host + #check domain and seperate into domain and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" return 1 @@ -55,7 +55,7 @@ dns_miab_rm() { fulldomain=$1 txtvalue=$2 - _info "Using miab challage delete" + _info "Using miab challenge delete" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -112,7 +112,7 @@ _get_root() { #cycle through the passed domain seperating out a test domain discarding # the subdomain by marching thorugh the dots while true; do - _test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f ${_i}-100) + _test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f "${_i}"-100) _debug _test_domain "$_test_domain" if [ -z "$_test_domain" ]; then @@ -122,7 +122,7 @@ _get_root() { #report found if the test domain is in the json response and # report the subdomain if _contains "$response" "\"$_test_domain\""; then - _sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-${_p}) + _sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-"${_p}") _domain=${_test_domain} return 0 fi diff --git a/dnsapi/dns_misaka.sh b/dnsapi/dns_misaka.sh index c6c0f5f3..50ed4360 100755 --- a/dnsapi/dns_misaka.sh +++ b/dnsapi/dns_misaka.sh @@ -116,7 +116,7 @@ _get_root() { return 1 fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -124,7 +124,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_mydnsjp.sh b/dnsapi/dns_mydnsjp.sh index 4fa646e8..336c4889 100755 --- a/dnsapi/dns_mydnsjp.sh +++ b/dnsapi/dns_mydnsjp.sh @@ -126,7 +126,7 @@ _get_root() { fi while true; do - _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100) if [ -z "$_domain" ]; then # not valid @@ -134,7 +134,7 @@ _get_root() { fi if [ "$_domain" = "$_root_domain" ]; then - _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$p") return 0 fi diff --git a/dnsapi/dns_mythic_beasts.sh b/dnsapi/dns_mythic_beasts.sh index b85401f4..1529e1e7 100755 --- a/dnsapi/dns_mythic_beasts.sh +++ b/dnsapi/dns_mythic_beasts.sh @@ -107,7 +107,7 @@ _get_root() { _debug "Detect the root zone" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then _err "Domain exhausted" return 1 @@ -118,7 +118,7 @@ _get_root() { _mb_rest GET "$h/records" ret="$?" if [ "$ret" -eq 0 ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index abe64d09..5527b357 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -109,7 +109,7 @@ _get_root_by_getList() { while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -123,7 +123,7 @@ _get_root_by_getList() { if ! _contains "$response" "$h"; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi @@ -137,14 +137,14 @@ _get_root_by_getHosts() { i=100 p=99 - while [ $p -ne 0 ]; do + while [ "$p" -ne 0 ]; do - h=$(printf "%s" "$1" | cut -d . -f $i-100) + h=$(printf "%s" "$1" | cut -d . -f "$i"-100) if [ -n "$h" ]; then if _contains "$h" "\\."; then _debug h "$h" if _namecheap_set_tld_sld "$h"; then - _sub_domain=$(printf "%s" "$1" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$1" | cut -d . -f 1-"$p") _domain="$h" return 0 else @@ -378,7 +378,7 @@ _namecheap_set_tld_sld() { while true; do - _tld=$(printf "%s" "$domain" | cut -d . -f $i-100) + _tld=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug tld "$_tld" if [ -z "$_tld" ]; then diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 2d146974..44549c9e 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -159,15 +159,15 @@ _namecom_get_root() { # Need to exclude the last field (tld) numfields=$(echo "$domain" | _egrep_o "\." | wc -l) - while [ $i -le "$numfields" ]; do - host=$(printf "%s" "$domain" | cut -d . -f $i-100) + while [ "$i" -le "$numfields" ]; do + host=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug host "$host" if [ -z "$host" ]; then return 1 fi if _contains "$response" "$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$host" return 0 fi diff --git a/dnsapi/dns_namesilo.sh b/dnsapi/dns_namesilo.sh index 2995e7dc..b31e32a1 100755 --- a/dnsapi/dns_namesilo.sh +++ b/dnsapi/dns_namesilo.sh @@ -109,15 +109,15 @@ _get_root() { # Need to exclude the last field (tld) numfields=$(echo "$domain" | _egrep_o "\." | wc -l) - while [ $i -le "$numfields" ]; do - host=$(printf "%s" "$domain" | cut -d . -f $i-100) + while [ "$i" -le "$numfields" ]; do + host=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug host "$host" if [ -z "$host" ]; then return 1 fi if _contains "$response" ">$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$host" return 0 fi diff --git a/dnsapi/dns_nederhost.sh b/dnsapi/dns_nederhost.sh index d0b97d3c..b16c36ec 100755 --- a/dnsapi/dns_nederhost.sh +++ b/dnsapi/dns_nederhost.sh @@ -88,8 +88,8 @@ _get_root() { i=2 p=1 while true; do - _domain=$(printf "%s" "$domain" | cut -d . -f $i-100) - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _debug _domain "$_domain" if [ -z "$_domain" ]; then #not valid diff --git a/dnsapi/dns_neodigit.sh b/dnsapi/dns_neodigit.sh index 1119f916..a31f8c9b 100644 --- a/dnsapi/dns_neodigit.sh +++ b/dnsapi/dns_neodigit.sh @@ -126,7 +126,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -142,7 +142,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\"" >/dev/null; then _domain_id=$(echo "$response" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d: -f2 | cut -d, -f1) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_netlify.sh b/dnsapi/dns_netlify.sh index bb5f5809..322f10ad 100644 --- a/dnsapi/dns_netlify.sh +++ b/dnsapi/dns_netlify.sh @@ -55,8 +55,6 @@ dns_netlify_add() { return 1 fi - _err "Not fully implemented!" - return 1 } #Usage: dns_myapi_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -95,7 +93,6 @@ dns_netlify_rm() { _err "error removing validation value ($_code)" return 1 fi - return 0 fi return 1 } @@ -111,7 +108,7 @@ _get_root() { _netlify_rest GET "dns_zones" "" "$accesstoken" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug2 "Checking domain: $h" if [ -z "$h" ]; then #not valid @@ -126,7 +123,7 @@ _get_root() { #create the record at the domain apex (@) if only the domain name was provided as --domain-alias _sub_domain="@" else - _sub_domain=$(echo "$domain" | cut -d . -f 1-$p) + _sub_domain=$(echo "$domain" | cut -d . -f 1-"$p") fi _domain=$h return 0 diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 42f35cb0..5f3e7d5d 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -169,7 +169,7 @@ _get_root() { fi if _contains "$_all_domains" "^$h$"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h _service=$(printf "%s" "$response" | grep -m 1 "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/") return 0 diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index 5d241ebf..c410447d 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -126,7 +126,7 @@ _get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -140,7 +140,7 @@ _get_root() { if _contains "$response" "\"$h\""; then _domain_returned=$(echo "$response" | _egrep_o "\{\"name\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") if [ "$_domain_returned" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_nsone.sh b/dnsapi/dns_nsone.sh index 2a073950..e1bfa531 100644 --- a/dnsapi/dns_nsone.sh +++ b/dnsapi/dns_nsone.sh @@ -119,7 +119,7 @@ _get_root() { return 1 fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -127,7 +127,7 @@ _get_root() { fi if _contains "$response" "\"zone\":\"$h\""; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_nsupdate.sh b/dnsapi/dns_nsupdate.sh index 9df6262e..d5dbbcbc 100755 --- a/dnsapi/dns_nsupdate.sh +++ b/dnsapi/dns_nsupdate.sh @@ -20,6 +20,7 @@ dns_nsupdate_add() { NSUPDATE_SERVER_PORT="${NSUPDATE_SERVER_PORT:-$(_readaccountconf_mutable NSUPDATE_SERVER_PORT)}" NSUPDATE_KEY="${NSUPDATE_KEY:-$(_readaccountconf_mutable NSUPDATE_KEY)}" NSUPDATE_ZONE="${NSUPDATE_ZONE:-$(_readaccountconf_mutable NSUPDATE_ZONE)}" + NSUPDATE_OPT="${NSUPDATE_OPT:-$(_readaccountconf_mutable NSUPDATE_OPT)}" _checkKeyFile || return 1 @@ -28,21 +29,25 @@ dns_nsupdate_add() { _saveaccountconf_mutable NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}" _saveaccountconf_mutable NSUPDATE_KEY "${NSUPDATE_KEY}" _saveaccountconf_mutable NSUPDATE_ZONE "${NSUPDATE_ZONE}" + _saveaccountconf_mutable NSUPDATE_OPT "${NSUPDATE_OPT}" [ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost" [ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53 + [ -n "${NSUPDATE_OPT}" ] || NSUPDATE_OPT="" _info "adding ${fulldomain}. 60 in txt \"${txtvalue}\"" [ -n "$DEBUG" ] && [ "$DEBUG" -ge "$DEBUG_LEVEL_1" ] && nsdebug="-d" [ -n "$DEBUG" ] && [ "$DEBUG" -ge "$DEBUG_LEVEL_2" ] && nsdebug="-D" if [ -z "${NSUPDATE_ZONE}" ]; then - nsupdate -k "${NSUPDATE_KEY}" $nsdebug </dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" _real_dns_version=$(echo "$response" | _egrep_o '"uuid_ref":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) return 0 diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index 0e93ecf8..b584fad2 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -68,7 +68,7 @@ dns_openprovider_add() { new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -152,7 +152,7 @@ dns_openprovider_rm() { new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -186,7 +186,7 @@ _get_root() { results_retrieved=0 while true; do - h=$(echo "$domain" | cut -d . -f $i-100) + h=$(echo "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 6d3d3eec..d1e9c0ac 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -144,7 +144,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -153,13 +153,13 @@ _get_root() { id=$(echo "$_domain_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"primary\",\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" - _host=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _host=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="${h}" _domainid="${id}" return 0 fi p=$i - i=$(_math $i + 1) + i=$(_math "$i" + 1) done _debug "$domain not found" diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index 7f62c05e..24ad0904 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -113,7 +113,7 @@ _initAuth() { _saveaccountconf_mutable OVH_END_POINT "$OVH_END_POINT" fi - OVH_API="$(_ovh_get_api $OVH_END_POINT)" + OVH_API="$(_ovh_get_api "$OVH_END_POINT")" _debug OVH_API "$OVH_API" OVH_CK="${OVH_CK:-$(_readaccountconf_mutable OVH_CK)}" @@ -260,7 +260,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -273,7 +273,7 @@ _get_root() { if ! _contains "$response" "This service does not exist" >/dev/null && ! _contains "$response" "This call has not been granted" >/dev/null && ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index cde3b1a6..6cce54da 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -181,7 +181,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." @@ -194,7 +194,7 @@ _get_root() { if [ -z "$h" ]; then return 1 fi - i=$(_math $i + 1) + i=$(_math "$i" + 1) done _debug "$domain not found" diff --git a/dnsapi/dns_pointhq.sh b/dnsapi/dns_pointhq.sh index fe95cd52..0abc087b 100644 --- a/dnsapi/dns_pointhq.sh +++ b/dnsapi/dns_pointhq.sh @@ -118,7 +118,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -130,7 +130,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index bbc7a027..1681ca9a 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -9,7 +9,7 @@ Options: Issues: github.com/acmesh-official/acme.sh/issues/3450 ' -PORKBUN_Api="https://porkbun.com/api/json/v3" +PORKBUN_Api="https://api.porkbun.com/api/json/v3" ######## Public functions ##################### @@ -93,7 +93,7 @@ dns_porkbun_rm() { _err "Delete record error." return 1 fi - echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + echo "$response" | tr -d " " | grep '"status":"SUCCESS"' >/dev/null fi } @@ -107,7 +107,7 @@ _get_root() { domain=$1 i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then return 1 @@ -139,7 +139,7 @@ _porkbun_rest() { api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') - test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + test -z "$data" && data="{" || data="$(echo "$data" | cut -d'}' -f1)," data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" export _H1="Content-Type: application/json" diff --git a/dnsapi/dns_rackcorp.sh b/dnsapi/dns_rackcorp.sh index e1e4f27d..b8fc73ab 100644 --- a/dnsapi/dns_rackcorp.sh +++ b/dnsapi/dns_rackcorp.sh @@ -83,7 +83,7 @@ _get_root() { return 1 fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug searchhost "$h" if [ -z "$h" ]; then _err "Could not find domain for record $domain in RackCorp using the provided credentials" @@ -95,7 +95,7 @@ _get_root() { if _contains "$response" "\"matches\":1"; then if _contains "$response" "\"name\":\"$h\""; then - _lookup=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _lookup=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_rackspace.sh b/dnsapi/dns_rackspace.sh index 03edce0d..05ec14a6 100644 --- a/dnsapi/dns_rackspace.sh +++ b/dnsapi/dns_rackspace.sh @@ -72,7 +72,7 @@ _get_root_zone() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -88,7 +88,7 @@ _get_root_zone() { _domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\"\([^,]*\)\",\"accountId\":\"[0-9]*\",\"name\":\"$h\",.*/\1/p") _debug2 domain_id "$_domain_id" if [ -n "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_rcode0.sh b/dnsapi/dns_rcode0.sh index 131a22b1..4ffdf572 100755 --- a/dnsapi/dns_rcode0.sh +++ b/dnsapi/dns_rcode0.sh @@ -171,7 +171,7 @@ _get_root() { i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug "try to find: $h" if _rcode0_rest "GET" "/api/v1/acme/zones/$h"; then @@ -189,7 +189,7 @@ _get_root() { if [ -z "$h" ]; then return 1 fi - i=$(_math $i + 1) + i=$(_math "$i" + 1) done _debug "no matching domain for $domain found" diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index 64bfcc38..4cbf68d2 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -41,9 +41,7 @@ dns_scaleway_add() { _err error "$response" return 1 fi - _info "Record added." - return 0 } dns_scaleway_rm() { @@ -71,9 +69,7 @@ dns_scaleway_rm() { _err error "$response" return 1 fi - _info "Record deleted." - return 0 } #################### Private functions below ################################## @@ -104,7 +100,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -113,7 +109,7 @@ _get_root() { _scaleway_rest GET "dns-zones/$h/records" if ! _contains "$response" "subdomain not found" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_schlundtech.sh b/dnsapi/dns_schlundtech.sh index 02146494..6d2930a2 100644 --- a/dnsapi/dns_schlundtech.sh +++ b/dnsapi/dns_schlundtech.sh @@ -106,7 +106,7 @@ _get_autodns_zone() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then @@ -124,7 +124,7 @@ _get_autodns_zone() { if _contains "$autodns_response" "1" >/dev/null; then _zone="$(echo "$autodns_response" | _egrep_o '[^<]*' | cut -d '>' -f 2 | cut -d '<' -f 1)" _system_ns="$(echo "$autodns_response" | _egrep_o '[^<]*' | cut -d '>' -f 2 | cut -d '<' -f 1)" - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") return 0 fi diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 37c2a97b..d6994681 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -81,7 +81,6 @@ dns_servercow_add() { return 1 fi - return 1 } # Usage fulldomain txtvalue @@ -137,7 +136,7 @@ _get_root() { p=1 while true; do - _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100) _debug _domain "$_domain" if [ -z "$_domain" ]; then @@ -150,7 +149,7 @@ _get_root() { fi if ! _contains "$response" '"error":"no such domain in user context"' >/dev/null; then - _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$p") if [ -z "$_sub_domain" ]; then # not valid return 1 diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 9fac3ef7..e0ad16e2 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -166,7 +166,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -179,7 +179,7 @@ _get_root() { if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_timeweb.sh b/dnsapi/dns_timeweb.sh new file mode 100644 index 00000000..9860872c --- /dev/null +++ b/dnsapi/dns_timeweb.sh @@ -0,0 +1,406 @@ +#!/usr/bin/env sh + +# acme.sh DNS API for Timeweb Cloud provider (https://timeweb.cloud). +# +# Author: https://github.com/nikolaypronchev. +# +# Prerequisites: +# Timeweb Cloud API JWT token. Obtain one from the Timeweb Cloud control panel +# ("API and Terraform" section: https://timeweb.cloud/my/api-keys). The JWT token +# must be provided to this script in one of two ways: +# 1. As the "TW_Token" variable, for example: "export TW_Token=eyJhbG...zUxMiIs"; +# 2. As a "TW_Token" config entry in acme.sh account config file +# (usually located at ~/.acme.sh/account.conf by default). + +TW_Api="https://api.timeweb.cloud/api/v1" + +################ Public functions ################ + +# Adds an ACME DNS-01 challenge DNS TXT record via the Timeweb Cloud API. +# +# Param1: The ACME DNS-01 challenge FQDN. +# Param2: The value of the ACME DNS-01 challenge TXT record. +# +# Example: dns_timeweb_add "_acme-challenge.sub.domain.com" "D-52Wm...4uYM" +dns_timeweb_add() { + _debug "$(__green "Timeweb DNS API"): \"dns_timeweb_add\" started." + + _timeweb_set_acme_fqdn "$1" || return 1 + _timeweb_set_acme_txt "$2" || return 1 + _timeweb_check_token || return 1 + _timeweb_split_acme_fqdn || return 1 + _timeweb_dns_txt_add || return 1 + + _debug "$(__green "Timeweb DNS API"): \"dns_timeweb_add\" finished." +} + +# Removes a DNS TXT record via the Timeweb Cloud API. +# +# Param1: The ACME DNS-01 challenge FQDN. +# Param2: The value of the ACME DNS-01 challenge TXT record. +# +# Example: dns_timeweb_rm "_acme-challenge.sub.domain.com" "D-52Wm...4uYM" +dns_timeweb_rm() { + _debug "$(__green "Timeweb DNS API"): \"dns_timeweb_rm\" started." + + _timeweb_set_acme_fqdn "$1" || return 1 + _timeweb_set_acme_txt "$2" || return 1 + _timeweb_check_token || return 1 + _timeweb_split_acme_fqdn || return 1 + _timeweb_get_dns_txt || return 1 + _timeweb_dns_txt_remove || return 1 + + _debug "$(__green "Timeweb DNS API"): \"dns_timeweb_rm\" finished." +} + +################ Private functions ################ + +# Checks and sets the ACME DNS-01 challenge FQDN. +# +# Param1: The ACME DNS-01 challenge FQDN. +# +# Example: _timeweb_set_acme_fqdn "_acme-challenge.sub.domain.com" +# +# Sets the "Acme_Fqdn" variable (_acme-challenge.sub.domain.com) +_timeweb_set_acme_fqdn() { + Acme_Fqdn=$1 + _debug "Setting ACME DNS-01 challenge FQDN \"$Acme_Fqdn\"." + [ -z "$Acme_Fqdn" ] && { + _err "ACME DNS-01 challenge FQDN is empty." + return 1 + } + return 0 +} + +# Checks and sets the value of the ACME DNS-01 challenge TXT record. +# +# Param1: Value of the ACME DNS-01 challenge TXT record. +# +# Example: _timeweb_set_acme_txt "D-52Wm...4uYM" +# +# Sets the "Acme_Txt" variable to the provided value (D-52Wm...4uYM) +_timeweb_set_acme_txt() { + Acme_Txt=$1 + _debug "Setting the value of the ACME DNS-01 challenge TXT record to \"$Acme_Txt\"." + [ -z "$Acme_Txt" ] && { + _err "ACME DNS-01 challenge TXT record value is empty." + return 1 + } + return 0 +} + +# Checks if the Timeweb Cloud API JWT token is present (refer to the script description). +# Adds or updates the token in the acme.sh account configuration. +_timeweb_check_token() { + _debug "Checking for the presence of the Timeweb Cloud API JWT token." + + TW_Token="${TW_Token:-$(_readaccountconf_mutable TW_Token)}" + + [ -z "$TW_Token" ] && { + _err "Timeweb Cloud API JWT token was not found." + return 1 + } + + _saveaccountconf_mutable TW_Token "$TW_Token" +} + +# Divides the ACME DNS-01 challenge FQDN into its main domain and subdomain components. +_timeweb_split_acme_fqdn() { + _debug "Trying to divide \"$Acme_Fqdn\" into its main domain and subdomain components." + + TW_Page_Limit=100 + TW_Page_Offset=0 + TW_Domains_Returned="" + + while [ -z "$TW_Domains_Returned" ] || [ "$TW_Domains_Returned" -ge "$TW_Page_Limit" ]; do + + _timeweb_list_domains "$TW_Page_Limit" "$TW_Page_Offset" || return 1 + + # Remove the 'subdomains' subarray to prevent confusion with FQDNs. + + TW_Domains=$( + echo "$TW_Domains" | + sed 's/"subdomains":\[[^]]*]//g' + ) + + [ -z "$TW_Domains" ] && { + _err "Failed to parse the list of domains." + return 1 + } + + while + TW_Domain=$( + echo "$TW_Domains" | + sed -n 's/.*{[^{]*"fqdn":"\([^"]*\)"[^}]*}.*/\1/p' + ) + + [ -n "$TW_Domain" ] && { + _timeweb_is_main_domain "$TW_Domain" && return 0 + + TW_Domains=$( + echo "$TW_Domains" | + sed 's/{\([^{]*"fqdn":"'"$TW_Domain"'"[^}]*\)}//' + ) + continue + } + do :; done + + TW_Page_Offset=$(_math "$TW_Page_Offset" + "$TW_Page_Limit") + done + + _err "Failed to divide \"$Acme_Fqdn\" into its main domain and subdomain components." + return 1 +} + +# Searches for a previously added DNS TXT record. +# +# Sets the "TW_Dns_Txt_Id" variable. +_timeweb_get_dns_txt() { + _debug "Trying to locate a DNS TXT record with the value \"$Acme_Txt\"." + + TW_Page_Limit=100 + TW_Page_Offset=0 + TW_Dns_Records_Returned="" + + while [ -z "$TW_Dns_Records_Returned" ] || [ "$TW_Dns_Records_Returned" -ge "$TW_Page_Limit" ]; do + + _timeweb_list_dns_records "$TW_Page_Limit" "$TW_Page_Offset" || return 1 + + while + Dns_Record=$( + echo "$TW_Dns_Records" | + sed -n 's/.*{\([^{]*{[^{]*'"$Acme_Txt"'[^}]*}[^}]*\)}.*/\1/p' + ) + + [ -n "$Dns_Record" ] && { + _timeweb_is_added_txt "$Dns_Record" && return 0 + + TW_Dns_Records=$( + echo "$TW_Dns_Records" | + sed 's/{\([^{]*{[^{]*'"$Acme_Txt"'[^}]*}[^}]*\)}//' + ) + continue + } + do :; done + + TW_Page_Offset=$(_math "$TW_Page_Offset" + "$TW_Page_Limit") + done + + _err "DNS TXT record was not found." + return 1 +} + +# Lists domains via the Timeweb Cloud API. +# +# Param 1: Limit for listed domains. +# Param 2: Offset for domains list. +# +# Sets the "TW_Domains" variable. +# Sets the "TW_Domains_Returned" variable. +_timeweb_list_domains() { + _debug "Listing domains via Timeweb Cloud API. Limit: $1, offset: $2." + + export _H1="Authorization: Bearer $TW_Token" + + if ! TW_Domains=$(_get "$TW_Api/domains?limit=$1&offset=$2"); then + _err "The request to the Timeweb Cloud API failed." + return 1 + fi + + [ -z "$TW_Domains" ] && { + _err "Empty response from the Timeweb Cloud API." + return 1 + } + + TW_Domains_Returned=$( + echo "$TW_Domains" | + sed 's/.*"meta":{"total":\([0-9]*\)[^0-9].*/\1/' + ) + + [ -z "$TW_Domains_Returned" ] && { + _err "Failed to extract the total count of domains." + return 1 + } + + [ "$TW_Domains_Returned" -eq "0" ] && { + _err "Domains are missing." + return 1 + } + + _debug "Domains returned by Timeweb Cloud API: $TW_Domains_Returned." +} + +# Lists domain DNS records via the Timeweb Cloud API. +# +# Param 1: Limit for listed DNS records. +# Param 2: Offset for DNS records list. +# +# Sets the "TW_Dns_Records" variable. +# Sets the "TW_Dns_Records_Returned" variable. +_timeweb_list_dns_records() { + _debug "Listing domain DNS records via the Timeweb Cloud API. Limit: $1, offset: $2." + + export _H1="Authorization: Bearer $TW_Token" + + if ! TW_Dns_Records=$(_get "$TW_Api/domains/$TW_Main_Domain/dns-records?limit=$1&offset=$2"); then + _err "The request to the Timeweb Cloud API failed." + return 1 + fi + + [ -z "$TW_Dns_Records" ] && { + _err "Empty response from the Timeweb Cloud API." + return 1 + } + + TW_Dns_Records_Returned=$( + echo "$TW_Dns_Records" | + sed 's/.*"meta":{"total":\([0-9]*\)[^0-9].*/\1/' + ) + + [ -z "$TW_Dns_Records_Returned" ] && { + _err "Failed to extract the total count of DNS records." + return 1 + } + + [ "$TW_Dns_Records_Returned" -eq "0" ] && { + _err "DNS records are missing." + return 1 + } + + _debug "DNS records returned by Timeweb Cloud API: $TW_Dns_Records_Returned." +} + +# Verifies whether the domain is the primary domain for the ACME DNS-01 challenge FQDN. +# The requirement is that the provided domain is the top-level domain +# for the ACME DNS-01 challenge FQDN. +# +# Param 1: Domain object returned by Timeweb Cloud API. +# +# Sets the "TW_Main_Domain" variable (e.g. "_acme-challenge.s1.domain.co.uk" → "domain.co.uk"). +# Sets the "TW_Subdomains" variable (e.g. "_acme-challenge.s1.domain.co.uk" → "_acme-challenge.s1"). +_timeweb_is_main_domain() { + _debug "Checking if \"$1\" is the main domain of the ACME DNS-01 challenge FQDN." + + [ -z "$1" ] && { + _debug "Failed to extract FQDN. Skipping domain." + return 1 + } + + ! echo ".$Acme_Fqdn" | grep -qi "\.$1$" && { + _debug "Domain does not match the ACME DNS-01 challenge FQDN. Skipping domain." + return 1 + } + + TW_Main_Domain=$1 + TW_Subdomains=$( + echo "$Acme_Fqdn" | + sed "s/\.*.\{${#1}\}$//" + ) + + _debug "Matched domain. ACME DNS-01 challenge FQDN split as [$TW_Subdomains].[$TW_Main_Domain]." + return 0 +} + +# Verifies whether a DNS record was previously added based on the following criteria: +# - The value matches the ACME DNS-01 challenge TXT record value; +# - The record type is TXT; +# - The subdomain matches the ACME DNS-01 challenge FQDN. +# +# Param 1: DNS record object returned by Timeweb Cloud API. +# +# Sets the "TW_Dns_Txt_Id" variable. +_timeweb_is_added_txt() { + _debug "Checking if \"$1\" is a previously added DNS TXT record." + + echo "$1" | grep -qv '"type":"TXT"' && { + _debug "Not a TXT record. Skipping the record." + return 1 + } + + if [ -n "$TW_Subdomains" ]; then + echo "$1" | grep -qvi "\"subdomain\":\"$TW_Subdomains\"" && { + _debug "Subdomains do not match. Skipping the record." + return 1 + } + else + echo "$1" | grep -q '"subdomain\":"..*"' && { + _debug "Subdomains do not match. Skipping the record." + return 1 + } + fi + + TW_Dns_Txt_Id=$( + echo "$1" | + sed 's/.*"id":\([0-9]*\)[^0-9].*/\1/' + ) + + [ -z "$TW_Dns_Txt_Id" ] && { + _debug "Failed to extract the DNS record ID. Skipping the record." + return 1 + } + + _debug "Matching DNS TXT record ID is \"$TW_Dns_Txt_Id\"." + return 0 +} + +# Adds a DNS TXT record via the Timeweb Cloud API. +_timeweb_dns_txt_add() { + _debug "Adding a new DNS TXT record via the Timeweb Cloud API." + + export _H1="Authorization: Bearer $TW_Token" + export _H2="Content-Type: application/json" + + if ! TW_Response=$( + _post "{ + \"subdomain\":\"$TW_Subdomains\", + \"type\":\"TXT\", + \"value\":\"$Acme_Txt\" + }" \ + "$TW_Api/domains/$TW_Main_Domain/dns-records" + ); then + _err "The request to the Timeweb Cloud API failed." + return 1 + fi + + [ -z "$TW_Response" ] && { + _err "An unexpected empty response was received from the Timeweb Cloud API." + return 1 + } + + TW_Dns_Txt_Id=$( + echo "$TW_Response" | + sed 's/.*"id":\([0-9]*\)[^0-9].*/\1/' + ) + + [ -z "$TW_Dns_Txt_Id" ] && { + _err "Failed to extract the DNS TXT Record ID." + return 1 + } + + _debug "DNS TXT record has been added. ID: \"$TW_Dns_Txt_Id\"." +} + +# Removes a DNS record via the Timeweb Cloud API. +_timeweb_dns_txt_remove() { + _debug "Removing DNS record via the Timeweb Cloud API." + + export _H1="Authorization: Bearer $TW_Token" + + if ! TW_Response=$( + _post \ + "" \ + "$TW_Api/domains/$TW_Main_Domain/dns-records/$TW_Dns_Txt_Id" \ + "" \ + "DELETE" + ); then + _err "The request to the Timeweb Cloud API failed." + return 1 + fi + + [ -n "$TW_Response" ] && { + _err "Received an unexpected response body from the Timeweb Cloud API." + return 1 + } + + _debug "DNS TXT record with ID \"$TW_Dns_Txt_Id\" has been removed." +} diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 6171678e..2abbe34d 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -55,14 +55,14 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 fi - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then diff --git a/dnsapi/dns_udr.sh b/dnsapi/dns_udr.sh index 24a843b9..f9772e10 100644 --- a/dnsapi/dns_udr.sh +++ b/dnsapi/dns_udr.sh @@ -115,7 +115,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then diff --git a/dnsapi/dns_ultra.sh b/dnsapi/dns_ultra.sh index 8b8c9122..e8da431c 100644 --- a/dnsapi/dns_ultra.sh +++ b/dnsapi/dns_ultra.sh @@ -115,7 +115,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" _debug response "$response" if [ -z "$h" ]; then @@ -128,7 +128,7 @@ _get_root() { if _contains "${response}" "${h}." >/dev/null; then _domain_id=$(echo "$response" | _egrep_o "${h}" | head -1) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="${h}" _debug sub_domain "${_sub_domain}" _debug domain "${_domain}" diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index a1263abe..ff70c8b6 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -133,7 +133,7 @@ _get_root() { i=2 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -147,7 +147,7 @@ _get_root() { if _contains "$response" "\"status\": 200"; then _domain_id=$h if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index 23ec29bf..fa38bbb6 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -102,7 +102,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then return 1 fi @@ -112,7 +112,7 @@ _get_root() { fi if _contains "$response" "\"id\":\"$h\""; then - _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_veesp.sh b/dnsapi/dns_veesp.sh index 5ea6e718..1afeeb30 100644 --- a/dnsapi/dns_veesp.sh +++ b/dnsapi/dns_veesp.sh @@ -112,7 +112,7 @@ _get_root() { return 1 fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -125,7 +125,7 @@ _get_root() { _service_id=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$h\",\"service_id\":[^}]*" | cut -d : -f 3 | cut -d '"' -f 2) _debug _service_id "$_service_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi diff --git a/dnsapi/dns_vercel.sh b/dnsapi/dns_vercel.sh index 46a4cb7e..469f7670 100644 --- a/dnsapi/dns_vercel.sh +++ b/dnsapi/dns_vercel.sh @@ -94,7 +94,7 @@ _get_root() { i=1 p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) if [ -z "$h" ]; then #not valid return 1 @@ -105,7 +105,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index 54abb439..c3915c69 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -97,7 +97,7 @@ _get_root() { if _vscale_rest GET "domains/"; then response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -108,7 +108,7 @@ _get_root() { if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index 94d14f02..61ec3f60 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -112,7 +112,7 @@ _get_root() { domain=$1 i=1 while true; do - _domain=$(printf "%s" "$domain" | cut -d . -f $i-100) + _domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$_domain" if [ -z "$_domain" ]; then return 1 diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 3df8d81c..bfc4b23a 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -121,7 +121,7 @@ _get_root() { p=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -135,7 +135,7 @@ _get_root() { if _contains "$response" "\"name\":\"$h\""; then _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh deleted file mode 100755 index d780459f..00000000 --- a/dnsapi/dns_yandex.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env sh -# shellcheck disable=SC2034 -dns_yandex_info='Yandex Domains -Site: tech.Yandex.com/domain/ -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_yandex -Options: - PDD_Token API Token -Issues: github.com/non7top/acme.sh/issues -Author: -' - -######## Public functions ##################### - -#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_yandex_add() { - fulldomain="${1}" - txtvalue="${2}" - _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" - - _PDD_credentials || return 1 - - _PDD_get_domain || return 1 - _debug "Found suitable domain: $domain" - - _PDD_get_record_ids || return 1 - _debug "Record_ids: $record_ids" - - if [ -n "$record_ids" ]; then - _info "All existing $subdomain records from $domain will be removed at the very end." - fi - - data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" - uri="https://pddimp.yandex.ru/api2/admin/dns/add" - result="$(_post "${data}" "${uri}" | _normalizeJson)" - _debug "Result: $result" - - if ! _contains "$result" '"success":"ok"'; then - if _contains "$result" '"success":"error"' && _contains "$result" '"error":"record_exists"'; then - _info "Record already exists." - else - _err "Can't add $subdomain to $domain." - return 1 - fi - fi -} - -#Usage: dns_myapi_rm _acme-challenge.www.domain.com -dns_yandex_rm() { - fulldomain="${1}" - _debug "Calling: dns_yandex_rm() '${fulldomain}'" - - _PDD_credentials || return 1 - - _PDD_get_domain "$fulldomain" || return 1 - _debug "Found suitable domain: $domain" - - _PDD_get_record_ids "${domain}" "${subdomain}" || return 1 - _debug "Record_ids: $record_ids" - - for record_id in $record_ids; do - data="domain=${domain}&record_id=${record_id}" - uri="https://pddimp.yandex.ru/api2/admin/dns/del" - result="$(_post "${data}" "${uri}" | _normalizeJson)" - _debug "Result: $result" - - if ! _contains "$result" '"success":"ok"'; then - _info "Can't remove $subdomain from $domain." - fi - done -} - -#################### Private functions below ################################## - -_PDD_get_domain() { - subdomain_start=1 - while true; do - domain_start=$(_math $subdomain_start + 1) - domain=$(echo "$fulldomain" | cut -d . -f "$domain_start"-) - subdomain=$(echo "$fulldomain" | cut -d . -f -"$subdomain_start") - - _debug "Checking domain $domain" - if [ -z "$domain" ]; then - return 1 - fi - - uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=$domain" - result="$(_get "${uri}" | _normalizeJson)" - _debug "Result: $result" - - if _contains "$result" '"success":"ok"'; then - return 0 - fi - subdomain_start=$(_math $subdomain_start + 1) - done -} - -_PDD_credentials() { - if [ -z "${PDD_Token}" ]; then - PDD_Token="" - _err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx." - _err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token." - return 1 - else - _saveaccountconf PDD_Token "${PDD_Token}" - fi - export _H1="PddToken: $PDD_Token" -} - -_PDD_get_record_ids() { - _debug "Check existing records for $subdomain" - - uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}" - result="$(_get "${uri}" | _normalizeJson)" - _debug "Result: $result" - - if ! _contains "$result" '"success":"ok"'; then - return 1 - fi - - record_ids=$(echo "$result" | _egrep_o "{[^{]*\"subdomain\":\"${subdomain}\"[^}]*}" | sed -n -e 's#.*"record_id": \([0-9]*\).*#\1#p') -} diff --git a/dnsapi/dns_yandex360.sh b/dnsapi/dns_yandex360.sh new file mode 100644 index 00000000..c6b6053d --- /dev/null +++ b/dnsapi/dns_yandex360.sh @@ -0,0 +1,352 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_yandex360_info='Yandex 360 for Business DNS API. +Yandex 360 for Business is a digital environment for effective collaboration. +Site: https://360.yandex.com/ +Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_yandex360 +Options: + YANDEX360_CLIENT_ID OAuth 2.0 ClientID + YANDEX360_CLIENT_SECRET OAuth 2.0 Client secret +OptionsAlt: + YANDEX360_ORG_ID Organization ID. Optional. + YANDEX360_ACCESS_TOKEN OAuth 2.0 Access token. Optional. +Issues: https://github.com/acmesh-official/acme.sh/issues/5213 +Author: +' + +YANDEX360_API_BASE='https://api360.yandex.net/directory/v1' +YANDEX360_OAUTH_BASE='https://oauth.yandex.ru' + +######## Public functions ##################### + +dns_yandex360_add() { + fulldomain="$(_idn "$1")" + txtvalue=$2 + _info 'Using Yandex 360 DNS API' + + if ! _check_variables; then + return 1 + fi + + if ! _get_root "$fulldomain"; then + return 1 + fi + + sub_domain=$(echo "$fulldomain" | sed "s/\.$root_domain$//") + + _debug 'Adding Yandex 360 DNS record for subdomain' "$sub_domain" + dns_api_url="${YANDEX360_API_BASE}/org/${YANDEX360_ORG_ID}/domains/${root_domain}/dns" + data='{"name":"'"$sub_domain"'","type":"TXT","ttl":60,"text":"'"$txtvalue"'"}' + + response="$(_post "$data" "$dns_api_url" '' 'POST' 'application/json')" + + if _contains "$response" 'recordId'; then + return 0 + else + _debug 'Response' "$response" + return 1 + fi +} + +dns_yandex360_rm() { + fulldomain="$(_idn "$1")" + txtvalue=$2 + _info 'Using Yandex 360 DNS API' + + if ! _check_variables; then + return 1 + fi + + if ! _get_root "$fulldomain"; then + return 1 + fi + + _debug 'Retrieving 100 records from Yandex 360 DNS' + dns_api_url="${YANDEX360_API_BASE}/org/${YANDEX360_ORG_ID}/domains/${root_domain}/dns?perPage=100" + response="$(_get "$dns_api_url" '' '')" + + if ! _contains "$response" "$txtvalue"; then + _info 'DNS record not found. Nothing to remove.' + _debug 'Response' "$response" + return 1 + fi + + response="$(echo "$response" | _normalizeJson)" + + record_id=$( + echo "$response" | + _egrep_o '\{[^}]*'"${txtvalue}"'[^}]*\}' | + _egrep_o '"recordId":[0-9]*' | + cut -d':' -f2 + ) + + if [ -z "$record_id" ]; then + _err 'Unable to get record ID to remove' + return 1 + fi + + _debug 'Removing DNS record' "$record_id" + delete_url="${YANDEX360_API_BASE}/org/${YANDEX360_ORG_ID}/domains/${root_domain}/dns/${record_id}" + + response="$(_post '' "$delete_url" '' 'DELETE')" + + if _contains "$response" '{}'; then + return 0 + else + _debug 'Response' "$response" + return 1 + fi +} + +#################### Private functions below ################################## + +_check_variables() { + YANDEX360_CLIENT_ID="${YANDEX360_CLIENT_ID:-$(_readaccountconf_mutable YANDEX360_CLIENT_ID)}" + YANDEX360_CLIENT_SECRET="${YANDEX360_CLIENT_SECRET:-$(_readaccountconf_mutable YANDEX360_CLIENT_SECRET)}" + YANDEX360_ORG_ID="${YANDEX360_ORG_ID:-$(_readaccountconf_mutable YANDEX360_ORG_ID)}" + YANDEX360_ACCESS_TOKEN="${YANDEX360_ACCESS_TOKEN:-$(_readaccountconf_mutable YANDEX360_ACCESS_TOKEN)}" + YANDEX360_REFRESH_TOKEN="${YANDEX360_REFRESH_TOKEN:-$(_readaccountconf_mutable YANDEX360_REFRESH_TOKEN)}" + + if [ -n "$YANDEX360_ACCESS_TOKEN" ]; then + _info '=========================================' + _info ' ATTENTION' + _info '=========================================' + _info 'A manually provided Yandex 360 access token has been detected, which is not recommended.' + _info 'Please note that this token is valid for a limited time after issuance.' + _info 'It is recommended to obtain the token interactively using acme.sh for one-time setup.' + _info 'Subsequent token renewals will be handled automatically.' + _info 'For more details, please visit: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_yandex360' + _info '=========================================' + + _saveaccountconf_mutable YANDEX360_ACCESS_TOKEN "$YANDEX360_ACCESS_TOKEN" + export _H1="Authorization: OAuth $YANDEX360_ACCESS_TOKEN" + + elif [ -z "$YANDEX360_CLIENT_ID" ] || [ -z "$YANDEX360_CLIENT_SECRET" ]; then + _err '=========================================' + _err ' ERROR' + _err '=========================================' + _err 'The required environment variables YANDEX360_CLIENT_ID and YANDEX360_CLIENT_SECRET are not set.' + _err 'Alternatively, you can set YANDEX360_ACCESS_TOKEN environment variable.' + _err 'For more details, please visit: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_yandex360' + _err '=========================================' + return 1 + + else + _saveaccountconf_mutable YANDEX360_CLIENT_ID "$YANDEX360_CLIENT_ID" + _saveaccountconf_mutable YANDEX360_CLIENT_SECRET "$YANDEX360_CLIENT_SECRET" + + if [ -n "$YANDEX360_REFRESH_TOKEN" ]; then + _debug 'Refresh token found. Attempting to refresh access token.' + fi + + _refresh_token || _get_token || return 1 + fi + + if [ -z "$YANDEX360_ORG_ID" ]; then + org_response="$(_get "${YANDEX360_API_BASE}/org" '' '')" + + if _contains "$org_response" '"organizations"'; then + org_response="$(echo "$org_response" | _normalizeJson)" + YANDEX360_ORG_ID=$( + echo "$org_response" | + _egrep_o '"id":[[:space:]]*[0-9]+' | + cut -d':' -f2 + ) + _debug 'Automatically retrieved YANDEX360_ORG_ID' "$YANDEX360_ORG_ID" + else + _err '=========================================' + _err ' ERROR' + _err '=========================================' + _err "Failed to retrieve YANDEX360_ORG_ID automatically." + _err 'For more details, please visit: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_yandex360' + _err '=========================================' + _debug 'Response' "$org_response" + return 1 + fi + fi + + return 0 +} + +_get_token() { + _info "$(__red '=========================================')" + _info "$(__red ' NOTICE')" + _info "$(__red '=========================================')" + _info "$(__red 'Before using the Yandex 360 API, you need to complete an authorization procedure.')" + _info "$(__red 'The initial access token is obtained interactively and is a one-time operation.')" + _info "$(__red 'Subsequent API requests will be handled automatically.')" + _info "$(__red '=========================================')" + + _info 'Initiating device authorization flow' + device_code_url="${YANDEX360_OAUTH_BASE}/device/code" + + hostname=$(uname -n) + data="client_id=$YANDEX360_CLIENT_ID&device_id=acme.sh ${hostname}&device_name=acme.sh ${hostname}" + + response="$(_post "$data" "$device_code_url" '' 'POST')" + + if ! _contains "$response" 'device_code'; then + _err 'Failed to get device code' + _debug 'Response' "$response" + return 1 + fi + + response="$(echo "$response" | _normalizeJson)" + + device_code=$( + echo "$response" | + _egrep_o '"device_code":"[^"]*"' | + cut -d'"' -f4 + ) + _debug 'Device code' "$device_code" + + user_code=$( + echo "$response" | + _egrep_o '"user_code":"[^"]*"' | + cut -d'"' -f4 + ) + _debug 'User code' "$user_code" + + verification_url=$( + echo "$response" | + _egrep_o '"verification_url":"[^"]*"' | + cut -d'"' -f4 + ) + _debug 'Verification URL' "$verification_url" + + interval=$( + echo "$response" | + _egrep_o '"interval":[[:space:]]*[0-9]+' | + cut -d':' -f2 + ) + _debug 'Polling interval' "$interval" + + _info "$(__red 'Please visit '"$verification_url"' and log in as an organization administrator')" + _info "$(__red 'Once logged in, enter the code: '"$user_code"' on the page from the previous step')" + _info "$(__red 'Waiting for authorization...')" + + _debug 'Polling for token' + token_url="${YANDEX360_OAUTH_BASE}/token" + + while true; do + data="grant_type=device_code&code=$device_code&client_id=$YANDEX360_CLIENT_ID&client_secret=$YANDEX360_CLIENT_SECRET" + + response="$(_post "$data" "$token_url" '' 'POST')" + + if _contains "$response" 'access_token'; then + response="$(echo "$response" | _normalizeJson)" + YANDEX360_ACCESS_TOKEN=$( + echo "$response" | + _egrep_o '"access_token":"[^"]*"' | + cut -d'"' -f4 + ) + YANDEX360_REFRESH_TOKEN=$( + echo "$response" | + _egrep_o '"refresh_token":"[^"]*"' | + cut -d'"' -f4 + ) + + _secure_debug 'Obtained access token' "$YANDEX360_ACCESS_TOKEN" + _secure_debug 'Obtained refresh token' "$YANDEX360_REFRESH_TOKEN" + + _saveaccountconf_mutable YANDEX360_REFRESH_TOKEN "$YANDEX360_REFRESH_TOKEN" + + export _H1="Authorization: OAuth $YANDEX360_ACCESS_TOKEN" + + _info 'Access token obtained successfully' + return 0 + elif _contains "$response" 'authorization_pending'; then + _debug 'Response' "$response" + _debug "Authorization pending. Waiting $interval seconds before next attempt." + _sleep "$interval" + else + _debug 'Response' "$response" + _err 'Failed to get access token' + return 1 + fi + done +} + +_refresh_token() { + token_url="${YANDEX360_OAUTH_BASE}/token" + + data="grant_type=refresh_token&refresh_token=$YANDEX360_REFRESH_TOKEN&client_id=$YANDEX360_CLIENT_ID&client_secret=$YANDEX360_CLIENT_SECRET" + + response="$(_post "$data" "$token_url" '' 'POST')" + + if _contains "$response" 'access_token'; then + response="$(echo "$response" | _normalizeJson)" + YANDEX360_ACCESS_TOKEN=$( + echo "$response" | + _egrep_o '"access_token":"[^"]*"' | + cut -d'"' -f4 + ) + YANDEX360_REFRESH_TOKEN=$( + echo "$response" | + _egrep_o '"refresh_token":"[^"]*"' | + cut -d'"' -f4 + ) + + _secure_debug 'Received access token' "$YANDEX360_ACCESS_TOKEN" + _secure_debug 'Received refresh token' "$YANDEX360_REFRESH_TOKEN" + + _saveaccountconf_mutable YANDEX360_REFRESH_TOKEN "$YANDEX360_REFRESH_TOKEN" + + export _H1="Authorization: OAuth $YANDEX360_ACCESS_TOKEN" + + _info 'Access token refreshed successfully' + return 0 + else + _info 'Failed to refresh token. Will attempt to obtain a new one.' + _debug 'Response' "$response" + return 1 + fi +} + +_get_root() { + domain="$1" + + for org_id in $YANDEX360_ORG_ID; do + _debug 'Checking organization ID' "$org_id" + domains_api_url="${YANDEX360_API_BASE}/org/${org_id}/domains" + + domains_response="$(_get "$domains_api_url" '' '')" + + if ! _contains "$domains_response" '"domains"'; then + _debug 'No domains found for organization' "$org_id" + _debug 'Response' "$domains_response" + continue + fi + + domains_response="$(echo "$domains_response" | _normalizeJson)" + domain_names=$( + echo "$domains_response" | + _egrep_o '"name":"[^"]*"' | + cut -d'"' -f4 + ) + + for d in $domain_names; do + d="$(_idn "$d")" + _debug 'Checking domain' "$d" + + if _endswith "$domain" "$d"; then + root_domain="$d" + break + fi + done + + if [ -n "$root_domain" ]; then + _debug "Root domain found: $root_domain in organization $org_id" + + YANDEX360_ORG_ID="$org_id" + _saveaccountconf_mutable YANDEX360_ORG_ID "$YANDEX360_ORG_ID" + + return 0 + fi + done + + if [ -z "$root_domain" ]; then + _err "Could not find a matching root domain for $domain in any organization" + return 1 + fi +} diff --git a/dnsapi/dns_yc.sh b/dnsapi/dns_yc.sh index e81b6fd2..36c49ce4 100644 --- a/dnsapi/dns_yc.sh +++ b/dnsapi/dns_yc.sh @@ -179,7 +179,7 @@ _get_root() { fi while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid @@ -197,7 +197,7 @@ _get_root() { _domain_id=$(echo "$response" | _normalizeJson | _egrep_o "[^{]*\"zone\":\"$h\"[^}]*" | _egrep_o "\"id\"[^,]*" | _egrep_o "[^:]*$" | tr -d '"') _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h return 0 fi diff --git a/dnsapi/dns_zilore.sh b/dnsapi/dns_zilore.sh index 369ce152..a4bacac5 100644 --- a/dnsapi/dns_zilore.sh +++ b/dnsapi/dns_zilore.sh @@ -98,9 +98,9 @@ dns_zilore_rm() { _get_root() { domain=$1 - i=2 + i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then #not valid diff --git a/dnsapi/dns_zone.sh b/dnsapi/dns_zone.sh index e4685707..cf82e5f4 100755 --- a/dnsapi/dns_zone.sh +++ b/dnsapi/dns_zone.sh @@ -137,9 +137,9 @@ _zone_rest() { _get_root() { domain=$1 - i=2 + i=1 while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then return 1 diff --git a/notify/bark.sh b/notify/bark.sh index bbd5bf34..fd9ebd76 100644 --- a/notify/bark.sh +++ b/notify/bark.sh @@ -1,32 +1,40 @@ #!/usr/bin/env sh -#Support iOS Bark Notification +# Support iOS Bark Notification -#BARK_API_URL="https://api.day.app/xxxx" -#BARK_SOUND="yyyy" -#BARK_GROUP="zzzz" +# Every parameter explained: https://github.com/Finb/bark-server/blob/master/docs/API_V2.md#push -# subject content statusCode +# BARK_API_URL="https://api.day.app/xxxx" (required) +# BARK_GROUP="ACME" (optional) +# BARK_SOUND="alarm" (optional) +# BARK_LEVEL="active" (optional) +# BARK_BADGE=0 (optional) +# BARK_AUTOMATICALLYCOPY="1" (optional) +# BARK_COPY="My clipboard Content" (optional) +# BARK_ICON="https://example.com/icon.png" (optional) +# BARK_ISARCHIVE="1" (optional) +# BARK_URL="https://example.com" (optional) + +# subject content statusCode bark_send() { _subject="$1" _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _statusCode="$3" # 0: success, 1: error, 2: skipped _debug "_subject" "$_subject" _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" + _content=$(echo "$_content" | _url_encode) + _subject=$(echo "$_subject" | _url_encode) + BARK_API_URL="${BARK_API_URL:-$(_readaccountconf_mutable BARK_API_URL)}" if [ -z "$BARK_API_URL" ]; then - BARK_API_URL="" _err "You didn't specify a Bark API URL BARK_API_URL yet." _err "You can download Bark from App Store and get yours." return 1 fi _saveaccountconf_mutable BARK_API_URL "$BARK_API_URL" - BARK_SOUND="${BARK_SOUND:-$(_readaccountconf_mutable BARK_SOUND)}" - _saveaccountconf_mutable BARK_SOUND "$BARK_SOUND" - BARK_GROUP="${BARK_GROUP:-$(_readaccountconf_mutable BARK_GROUP)}" if [ -z "$BARK_GROUP" ]; then BARK_GROUP="ACME" @@ -35,10 +43,79 @@ bark_send() { _saveaccountconf_mutable BARK_GROUP "$BARK_GROUP" fi - _content=$(echo "$_content" | _url_encode) - _subject=$(echo "$_subject" | _url_encode) + BARK_SOUND="${BARK_SOUND:-$(_readaccountconf_mutable BARK_SOUND)}" + if [ -n "$BARK_SOUND" ]; then + _saveaccountconf_mutable BARK_SOUND "$BARK_SOUND" + fi + + BARK_LEVEL="${BARK_LEVEL:-$(_readaccountconf_mutable BARK_LEVEL)}" + if [ -n "$BARK_LEVEL" ]; then + _saveaccountconf_mutable BARK_LEVEL "$BARK_LEVEL" + fi + + BARK_BADGE="${BARK_BADGE:-$(_readaccountconf_mutable BARK_BADGE)}" + if [ -n "$BARK_BADGE" ]; then + _saveaccountconf_mutable BARK_BADGE "$BARK_BADGE" + fi + + BARK_AUTOMATICALLYCOPY="${BARK_AUTOMATICALLYCOPY:-$(_readaccountconf_mutable BARK_AUTOMATICALLYCOPY)}" + if [ -n "$BARK_AUTOMATICALLYCOPY" ]; then + _saveaccountconf_mutable BARK_AUTOMATICALLYCOPY "$BARK_AUTOMATICALLYCOPY" + fi + + BARK_COPY="${BARK_COPY:-$(_readaccountconf_mutable BARK_COPY)}" + if [ -n "$BARK_COPY" ]; then + _saveaccountconf_mutable BARK_COPY "$BARK_COPY" + fi + + BARK_ICON="${BARK_ICON:-$(_readaccountconf_mutable BARK_ICON)}" + if [ -n "$BARK_ICON" ]; then + _saveaccountconf_mutable BARK_ICON "$BARK_ICON" + fi + + BARK_ISARCHIVE="${BARK_ISARCHIVE:-$(_readaccountconf_mutable BARK_ISARCHIVE)}" + if [ -n "$BARK_ISARCHIVE" ]; then + _saveaccountconf_mutable BARK_ISARCHIVE "$BARK_ISARCHIVE" + fi + + BARK_URL="${BARK_URL:-$(_readaccountconf_mutable BARK_URL)}" + if [ -n "$BARK_URL" ]; then + _saveaccountconf_mutable BARK_URL "$BARK_URL" + fi + + _params="" + + if [ -n "$BARK_SOUND" ]; then + _params="$_params&sound=$BARK_SOUND" + fi + if [ -n "$BARK_GROUP" ]; then + _params="$_params&group=$BARK_GROUP" + fi + if [ -n "$BARK_LEVEL" ]; then + _params="$_params&level=$BARK_LEVEL" + fi + if [ -n "$BARK_BADGE" ]; then + _params="$_params&badge=$BARK_BADGE" + fi + if [ -n "$BARK_AUTOMATICALLYCOPY" ]; then + _params="$_params&automaticallyCopy=$BARK_AUTOMATICALLYCOPY" + fi + if [ -n "$BARK_COPY" ]; then + _params="$_params©=$BARK_COPY" + fi + if [ -n "$BARK_ICON" ]; then + _params="$_params&icon=$BARK_ICON" + fi + if [ -n "$BARK_ISARCHIVE" ]; then + _params="$_params&isArchive=$BARK_ISARCHIVE" + fi + if [ -n "$BARK_URL" ]; then + _params="$_params&url=$BARK_URL" + fi + + _params=$(echo "$_params" | sed 's/^&//') # remove leading '&' if exists - response="$(_get "$BARK_API_URL/$_subject/$_content?sound=$BARK_SOUND&group=$BARK_GROUP")" + response="$(_get "$BARK_API_URL/$_subject/$_content?$_params")" if [ "$?" = "0" ] && _contains "$response" "success"; then _info "Bark API fired success." diff --git a/notify/teams.sh b/notify/teams.sh old mode 100644 new mode 100755 index 1bc5ed08..5e8fe6c0 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -3,10 +3,6 @@ #Support Microsoft Teams webhooks #TEAMS_WEBHOOK_URL="" -#TEAMS_THEME_COLOR="" -#TEAMS_SUCCESS_COLOR="" -#TEAMS_ERROR_COLOR="" -#TEAMS_SKIP_COLOR="" teams_send() { _subject="$1" @@ -14,9 +10,9 @@ teams_send() { _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped _debug "_statusCode" "$_statusCode" - _color_success="2cbe4e" # green - _color_danger="cb2431" # red - _color_muted="586069" # gray + _color_success="Good" + _color_danger="Attention" + _color_muted="Accent" TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}" if [ -z "$TEAMS_WEBHOOK_URL" ]; then @@ -26,26 +22,6 @@ teams_send() { fi _saveaccountconf_mutable TEAMS_WEBHOOK_URL "$TEAMS_WEBHOOK_URL" - TEAMS_THEME_COLOR="${TEAMS_THEME_COLOR:-$(_readaccountconf_mutable TEAMS_THEME_COLOR)}" - if [ -n "$TEAMS_THEME_COLOR" ]; then - _saveaccountconf_mutable TEAMS_THEME_COLOR "$TEAMS_THEME_COLOR" - fi - - TEAMS_SUCCESS_COLOR="${TEAMS_SUCCESS_COLOR:-$(_readaccountconf_mutable TEAMS_SUCCESS_COLOR)}" - if [ -n "$TEAMS_SUCCESS_COLOR" ]; then - _saveaccountconf_mutable TEAMS_SUCCESS_COLOR "$TEAMS_SUCCESS_COLOR" - fi - - TEAMS_ERROR_COLOR="${TEAMS_ERROR_COLOR:-$(_readaccountconf_mutable TEAMS_ERROR_COLOR)}" - if [ -n "$TEAMS_ERROR_COLOR" ]; then - _saveaccountconf_mutable TEAMS_ERROR_COLOR "$TEAMS_ERROR_COLOR" - fi - - TEAMS_SKIP_COLOR="${TEAMS_SKIP_COLOR:-$(_readaccountconf_mutable TEAMS_SKIP_COLOR)}" - if [ -n "$TEAMS_SKIP_COLOR" ]; then - _saveaccountconf_mutable TEAMS_SKIP_COLOR "$TEAMS_SKIP_COLOR" - fi - export _H1="Content-Type: application/json" _subject=$(echo "$_subject" | _json_encode) @@ -63,16 +39,35 @@ teams_send() { ;; esac - _color=$(echo "$_color" | tr -cd 'a-fA-F0-9') - if [ -z "$_color" ]; then - _color=$(echo "${TEAMS_THEME_COLOR:-$_color_muted}" | tr -cd 'a-fA-F0-9') - fi - - _data="{\"title\": \"$_subject\"," - if [ -n "$_color" ]; then - _data="$_data\"themeColor\": \"$_color\", " - fi - _data="$_data\"text\": \"$_content\"}" + _data="{ + \"type\": \"message\", + \"attachments\": [ + { + \"contentType\": \"application/vnd.microsoft.card.adaptive\", + \"contentUrl\": null, + \"content\": { + \"schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\", + \"type\": \"AdaptiveCard\", + \"version\": \"1.2\", + \"body\": [ + { + \"type\": \"TextBlock\", + \"size\": \"large\", + \"weight\": \"bolder\", + \"wrap\": true, + \"color\": \"$_color\", + \"text\": \"$_subject\" + }, + { + \"type\": \"TextBlock\", + \"text\": \"$_content\", + \"wrap\": true + } + ] + } + } + ] +}" if response=$(_post "$_data" "$TEAMS_WEBHOOK_URL"); then if ! _contains "$response" error; then diff --git a/notify/telegram.sh b/notify/telegram.sh index 454b4146..cca8ee25 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -27,11 +27,12 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" - _content="$(printf "%s" "$_content" | sed -e 's/\([_*`\[]\)/\\\\\1/g')" + _subject="$(printf "%s" "$_subject" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([_*[()~`>#+--=|{}.!]\)/\\\\\1/g')" + _content="$(printf "%s" "$_content" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([_*[()~`>#+--=|{}.!]\)/\\\\\1/g')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " - _data="$_data\"parse_mode\": \"markdown\", " + _data="$_data\"parse_mode\": \"MarkdownV2\", " _data="$_data\"disable_web_page_preview\": \"1\"}" _debug "$_data"