diff --git a/README.md b/README.md index c6ea9938..9266a600 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) - [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) - [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) - [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) +- [CentOS Web Panel](http://centos-webpanel.com/) +- [lnmp.org](https://lnmp.org/) - [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) # Tested OS @@ -313,9 +315,9 @@ You don't have to do anything manually! 1. zonomi.com DNS API 1. DreamHost.com API 1. DirectAdmin API +1. KingHost (https://www.kinghost.com.br/) 1. Loopia.se API - And: **lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api @@ -330,6 +332,8 @@ For more details: [How to use DNS API](dnsapi) # 8. Use DNS manual mode: +See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first. + If your dns provider doesn't support any api access, you can add the txt record by your hand. ```bash @@ -399,7 +403,7 @@ Valid values are: It's simple, just give a wildcard domain as the `-d` parameter. ```sh -acme.sh --issue -d example.com -d *.example.com --dns dns_cf +acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf ``` diff --git a/acme.sh b/acme.sh index e7c40c01..da8e60c9 100755 --- a/acme.sh +++ b/acme.sh @@ -110,10 +110,14 @@ _STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode" _DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode" +_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" +_DNS_MANUAL_ERROR="It seems that you are using dns manual mode. Read this link first: $_DNS_MANUAL_WIKI" + __INTERACTIVE="" if [ -t 1 ]; then __INTERACTIVE="1" @@ -1617,6 +1621,7 @@ _post() { _debug $httpmethod _debug "_post_url" "$_post_url" _debug2 "body" "$body" + _debug2 "_postContentType" "$_postContentType" _inithttp @@ -1625,14 +1630,19 @@ _post() { if [ "$HTTPS_INSECURE" ]; then _CURL="$_CURL --insecure " fi - if [ "$_postContentType" ]; then - _CURL="$_CURL -H \"Content-Type: $_postContentType\" " - fi _debug "_CURL" "$_CURL" if [ "$needbase64" ]; then - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" + if [ "$_postContentType" ]; then + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" + else + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" + fi else - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + if [ "$_postContentType" ]; then + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + else + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + fi fi _ret="$?" if [ "$_ret" != "0" ]; then @@ -1785,19 +1795,25 @@ _send_signed_request() { return 1 fi + if [ "$ACME_VERSION" = "2" ]; then + __request_conent_type="$CONTENT_TYPE_JSON" + else + __request_conent_type="" + fi payload64=$(printf "%s" "$payload" | _base64 | _url_replace) _debug3 payload64 "$payload64" MAX_REQUEST_RETRY_TIMES=5 _request_retry_times=0 while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do + _request_retry_times=$(_math "$_request_retry_times" + 1) _debug3 _request_retry_times "$_request_retry_times" if [ -z "$_CACHED_NONCE" ]; then _headers="" if [ "$ACME_NEW_NONCE" ]; then _debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE" nonceurl="$ACME_NEW_NONCE" - if _post "" "$nonceurl" "" "HEAD" "$CONTENT_TYPE_JSON"; then + if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then _headers="$(cat "$HTTP_HEADER")" fi fi @@ -1821,7 +1837,11 @@ _send_signed_request() { fi nonce="$_CACHED_NONCE" _debug2 nonce "$nonce" - + if [ -z "$nonce" ]; then + _info "Could not get nonce, let's try again." + _sleep 2 + continue + fi if [ "$ACME_VERSION" = "2" ]; then if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}' @@ -1852,7 +1872,7 @@ _send_signed_request() { fi _debug3 body "$body" - response="$(_post "$body" "$url" "$needbase64" "POST" "$CONTENT_TYPE_JSON")" + response="$(_post "$body" "$url" "$needbase64" "POST" "$__request_conent_type")" _CACHED_NONCE="" if [ "$?" != "0" ]; then @@ -1879,7 +1899,6 @@ _send_signed_request() { if _contains "$_body" "JWS has invalid anti-replay nonce"; then _info "It seems the CA server is busy now, let's wait and retry." - _request_retry_times=$(_math "$_request_retry_times" + 1) _sleep 5 continue fi @@ -3247,10 +3266,16 @@ _regAccount() { return 1 fi + _debug2 responseHeaders "$responseHeaders" _accUri="$(echo "$responseHeaders" | grep "^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 "$responseHeaders" + return 1 + fi _savecaconf "ACCOUNT_URL" "$_accUri" - export ACCOUNT_URL="$ACCOUNT_URL" + export ACCOUNT_URL="$_accUri" CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" @@ -3460,6 +3485,11 @@ issue() { mkdir -p "$DOMAIN_PATH" fi + if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then + _err "$_DNS_MANUAL_ERROR" + return 1 + fi + _debug "Using ACME_DIRECTORY: $ACME_DIRECTORY" _initAPI @@ -3521,7 +3551,7 @@ issue() { _saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")" _debug2 _saved_account_key_hash "$_saved_account_key_hash" - if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then + if [ -z "$ACCOUNT_URL" ] || [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then if ! _regAccount "$_accountkeylength"; then _on_issue_err "$_post_hook" return 1 @@ -3819,7 +3849,7 @@ $_authorizations_map" if [ "$dnsadded" = '0' ]; then _savedomainconf "Le_Vlist" "$vlist" _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." - _err "Please add the TXT records to the domains, and retry again." + _err "Please add the TXT records to the domains, and re-run with --renew." _clearup _on_issue_err "$_post_hook" return 1 @@ -4083,13 +4113,15 @@ $_authorizations_map" fi if [ "$code" != "200" ]; then _err "Sign failed, code is not 200." + _err "$response" _on_issue_err "$_post_hook" return 1 fi Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" if ! _get "$Le_LinkCert" >"$CERT_PATH"; then - _err "Sign failed, code is not 200." + _err "Sign failed, can not download cert:$Le_LinkCert." + _err "$response" _on_issue_err "$_post_hook" return 1 fi @@ -4105,12 +4137,12 @@ $_authorizations_map" fi else if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then - _err "Sign failed." + _err "Sign failed. $response" _on_issue_err "$_post_hook" return 1 fi _rcert="$response" - Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)" + Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)" echo "$BEGIN_CERT" >"$CERT_PATH" #if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then @@ -5456,8 +5488,8 @@ Parameters: --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. - --accountemail Specifies the account email for registering, Only valid for the '--install' command. - --accountkey Specifies the account key path, Only valid for the '--install' command. + --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. + --accountkey Specifies the account key path, only valid for the '--install' command. --days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. --local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses. @@ -5481,6 +5513,7 @@ Parameters: --listen-v6 Force standalone/tls server to listen at ipv6. --openssl-bin Specifies a custom openssl bin location. --use-wget Force to use wget, if you have both curl and wget installed. + --yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI " } @@ -5969,6 +6002,9 @@ _process() { shift fi ;; + --yes-I-know-dns-manual-mode-enough-go-ahead-please) + export FORCE_DNS_MANUAL=1 + ;; --log | --logfile) _log="1" _logfile="$2" diff --git a/deploy/keychain.sh b/deploy/keychain.sh index a99ed465..d86b4d03 100644 --- a/deploy/keychain.sh +++ b/deploy/keychain.sh @@ -1,11 +1,5 @@ #!/usr/bin/env sh -#Here is a sample custom api script. -#This file name is "myapi.sh" -#So, here must be a method myapi_deploy() -#Which will be called by acme.sh to deploy the cert -#returns 0 means success, otherwise error. - ######## Public functions ##################### #domain keyfile certfile cafile fullchain diff --git a/dnsapi/README.md b/dnsapi/README.md index fe4a701c..58ebecb1 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -325,6 +325,8 @@ The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.s ## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API +ATTENTION: You need to be a registered Reseller to be able to use the ResellerInterface. As a normal user you can not use this method. + You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`: ``` export DO_PID="KD-1234567" @@ -525,8 +527,9 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API -You'll need to fill out the form at https://www.name.com/reseller/apply to apply -for API username and token. +Create your API token here: https://www.name.com/account/settings/api + +Note: `Namecom_Username` should be your Name.com username and not the token name. If you accidentally run the script with the token name as the username see `~/.acme.sh/account.conf` to fix the issue ``` export Namecom_Username="testuser" @@ -784,7 +787,19 @@ acme.sh --issue --dns dns_da -d example.com -d www.example.com The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. -## 42. Use Loopia.se API +## 42. Use KingHost DNS API + +API access must be enabled at https://painel.kinghost.com.br/painel.api.php + +``` +export KINGHOST_Username="yourusername" +export KINGHOST_Password="yourpassword" +acme.sh --issue --dns dns_kinghost -d example.com -d *.example.com +``` + +The `KINGHOST_username` and `KINGHOST_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + +## 43. Use Loopia.se API User must provide login credentials to the Loopia API. The user needs the following permissions: @@ -806,6 +821,7 @@ acme.sh --issue --dns dns_loopia -d example.com -d *.example.com The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +======= # Use custom API diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index 677a9f75..e0d9516f 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -99,6 +99,7 @@ dns_azure_add() { _azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken" if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then _info "validation value added" + return 0 else _err "error adding validation value ($_code)" return 1 @@ -194,6 +195,7 @@ dns_azure_rm() { _azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken" if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then _info "validation value removed" + return 0 else _err "error removing validation value ($_code)" return 1 @@ -226,6 +228,7 @@ _azure_rest() { else response="$(_get "$ep")" fi + _ret="$?" _secure_debug2 "response $response" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" _debug "http response code $_code" @@ -236,7 +239,7 @@ _azure_rest() { 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 - if [ "$?" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then + 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" _sleep "$_request_retry_times" @@ -281,6 +284,7 @@ _azure_getaccess_token() { body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials" _secure_debug2 "data $body" response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")" + _ret="$?" _secure_debug2 "response $response" response="$(echo "$response" | _normalizeJson)" accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") @@ -290,7 +294,7 @@ _azure_getaccess_token() { _err "no acccess token received. Check your Azure settings see $WIKI" return 1 fi - if [ "$?" != "0" ]; then + if [ "$_ret" != "0" ]; then _err "error $response" return 1 fi diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 68264a42..3595b9b0 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -19,8 +19,8 @@ dns_cf_add() { if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then CF_Key="" CF_Email="" - _err "You don't specify cloudflare api key and email yet." - _err "Please create you key and try again." + _err "You didn't specify a cloudflare api key and email yet." + _err "Please create the key and try again." return 1 fi @@ -94,8 +94,8 @@ dns_cf_rm() { if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then CF_Key="" CF_Email="" - _err "You don't specify cloudflare api key and email yet." - _err "Please create you key and try again." + _err "You didn't specify a cloudflare api key and email yet." + _err "Please create the key and try again." return 1 fi diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index 7e1f1fec..5d38ef76 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -20,12 +20,22 @@ dns_dgon_add() { fulldomain="$(echo "$1" | _lower_case)" txtvalue=$2 + + DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}" + # Check if API Key Exist + if [ -z "$DO_API_KEY" ]; then + DO_API_KEY="" + _err "You did not specify DigitalOcean API key." + _err "Please export DO_API_KEY and try again." + return 1 + fi + _info "Using digitalocean dns validation - add record" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" ## save the env vars (key and domain split location) for later automated use - _saveaccountconf DO_API_KEY "$DO_API_KEY" + _saveaccountconf_mutable DO_API_KEY "$DO_API_KEY" ## split the domain for DO API if ! _get_base_domain "$fulldomain"; then @@ -39,7 +49,7 @@ dns_dgon_add() { export _H1="Content-Type: application/json" export _H2="Authorization: Bearer $DO_API_KEY" PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records' - PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}' + PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'","ttl":120}' _debug PURL "$PURL" _debug PBODY "$PBODY" @@ -65,6 +75,16 @@ dns_dgon_add() { dns_dgon_rm() { fulldomain="$(echo "$1" | _lower_case)" txtvalue=$2 + + DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}" + # Check if API Key Exist + if [ -z "$DO_API_KEY" ]; then + DO_API_KEY="" + _err "You did not specify DigitalOcean API key." + _err "Please export DO_API_KEY and try again." + return 1 + fi + _info "Using digitalocean dns validation - remove record" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -92,11 +112,11 @@ dns_dgon_rm() { domain_list="$(_get "$GURL")" ## 2) find record ## check for what we are looing for: "type":"A","name":"$_sub_domain" - record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" + record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" ## 3) check record and get next page if [ -z "$record" ]; then ## find the next page if we dont have a match - nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+")" + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")" if [ -z "$nextpage" ]; then _err "no record and no nextpage in digital ocean DNS removal" return 1 @@ -108,7 +128,7 @@ dns_dgon_rm() { done ## we found the record - rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+")" + rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" _debug rec_id "$rec_id" ## delete the record diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index 0bfe2b99..0dd3918a 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -39,34 +39,17 @@ dns_dnsimple_add() { _get_records "$_account_id" "$_domain" "$_sub_domain" - if [ "$_records_count" = "0" ]; then - _info "Adding record" - if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then - if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then - _info "Added" - return 0 - else - _err "Unexpected response while adding text record." - return 1 - fi - fi - _err "Add txt record error." - else - _info "Updating record" - _extract_record_id "$_records" "$_sub_domain" - - if _dnsimple_rest \ - PATCH \ - "$_account_id/zones/$_domain/records/$_record_id" \ - "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then - - _info "Updated!" + _info "Adding record" + if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then + _info "Added" return 0 + else + _err "Unexpected response while adding text record." + return 1 fi - - _err "Update error" - return 1 fi + _err "Add txt record error." } # fulldomain @@ -84,19 +67,19 @@ dns_dnsimple_rm() { fi _get_records "$_account_id" "$_domain" "$_sub_domain" + _extract_record_id "$_records" "$_sub_domain" - if [ "$_record_id" ]; then - - if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then - _info "removed record" "$_record_id" - return 0 - fi + echo "$_record_id" | while read -r item; do + if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$item"; then + _info "removed record" "$item" + return 0 + else + _err "failed to remove record" "$item" + return 1 + fi + done fi - - _err "failed to remove record" "$_record_id" - return 1 - } #################### Private functions bellow ################################## diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 0d8fae73..7262755e 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -279,7 +279,7 @@ _freedns_add_txt_record() { domain_id="$2" subdomain="$3" value="$(printf '%s' "$4" | _url_encode)" - url="http://freedns.afraid.org/subdomain/save.php?step=2" + url="https://freedns.afraid.org/subdomain/save.php?step=2" htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")" diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index f42d56af..d196fbec 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -143,7 +143,7 @@ _find_zone() { _debug "Looking for zone \"${_attempted_zone}\"" - line_num="$(echo "$_zone_names" | grep -n "$_attempted_zone" | cut -d : -f 1)" + line_num="$(echo "$_zone_names" | grep -n "^$_attempted_zone" | cut -d : -f 1)" if [ "$line_num" ]; then _zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p") diff --git a/dnsapi/dns_kinghost.sh b/dnsapi/dns_kinghost.sh new file mode 100644 index 00000000..898ab286 --- /dev/null +++ b/dnsapi/dns_kinghost.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env sh + +############################################################ +# KingHost API support # +# http://api.kinghost.net/doc/ # +# # +# Author: Felipe Keller Braz # +# Report Bugs here: https://github.com/kinghost/acme.sh # +# # +# Values to export: # +# export KINGHOST_Username="email@provider.com" # +# export KINGHOST_Password="xxxxxxxxxx" # +############################################################ + +KING_Api="https://api.kinghost.net/acme" + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_kinghost_add() { + fulldomain=$1 + txtvalue=$2 + + KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}" + KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}" + if [ -z "$KINGHOST_Username" ] || [ -z "$KINGHOST_Password" ]; then + KINGHOST_Username="" + KINGHOST_Password="" + _err "You don't specify KingHost api password and email yet." + _err "Please create you key and try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable KINGHOST_Username "$KINGHOST_Username" + _saveaccountconf_mutable KINGHOST_Password "$KINGHOST_Password" + + _debug "Getting txt records" + _kinghost_rest GET "dns" "name=$fulldomain&content=$txtvalue" + + #This API call returns "status":"ok" if dns record does not exists + #We are creating a new txt record here, so we expect the "ok" status + if ! echo "$response" | grep '"status":"ok"' >/dev/null; then + _err "Error" + _err "$response" + return 1 + fi + + _kinghost_rest POST "dns" "name=$fulldomain&content=$txtvalue" + if ! echo "$response" | grep '"status":"ok"' >/dev/null; then + _err "Error" + _err "$response" + return 1 + fi + + return 0 +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +dns_kinghost_rm() { + fulldomain=$1 + txtvalue=$2 + + KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}" + KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}" + if [ -z "$KINGHOST_Password" ] || [ -z "$KINGHOST_Username" ]; then + KINGHOST_Password="" + KINGHOST_Username="" + _err "You don't specify KingHost api key and email yet." + _err "Please create you key and try again." + return 1 + fi + + _kinghost_rest DELETE "dns" "name=$fulldomain&content=$txtvalue" + if ! echo "$response" | grep '"status":"ok"' >/dev/null; then + _err "Error" + _err "$response" + return 1 + fi + + return 0 +} + +#################### Private functions below ################################## +_kinghost_rest() { + method=$1 + uri="$2" + data="$3" + _debug "$uri" + + export _H1="X-Auth-Email: $KINGHOST_Username" + export _H2="X-Auth-Key: $KINGHOST_Password" + + if [ "$method" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$KING_Api/$uri.json" "" "$method")" + else + response="$(_get "$KING_Api/$uri.json?$data")" + fi + + if [ "$?" != "0" ]; then + _err "error $uri" + return 1 + fi + _debug2 response "$response" + return 0 +} diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 7d807c81..3d99e103 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -90,7 +90,7 @@ set_record() { full=$2 txtvalue=$3 - if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then + if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then _err "Set txt record error." return 1 fi @@ -107,7 +107,7 @@ rm_record() { root=$1 full=$2 - if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then + if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then _err "Delete txt record error." return 1 fi @@ -122,7 +122,7 @@ rm_record() { notify_slaves() { root=$1 - if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then + if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root/notify"; then _err "Notify slaves error." return 1 fi @@ -144,15 +144,18 @@ _get_root() { while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if [ -z "$h" ]; then - return 1 - fi if _contains "$_zones_response" "\"name\": \"$h.\""; then - _domain="$h" + _domain="$h." + if [ -z "$h" ]; then + _domain="=2E" + fi return 0 fi + if [ -z "$h" ]; then + return 1 + fi i=$(_math $i + 1) done _debug "$domain not found" diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 5fbb09d8..318dee0c 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -50,9 +50,9 @@ _PDD_get_domain() { __last=0 while [ $__last -eq 0 ]; do uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" - res1=$(_get "$uri1" | _normalizeJson) - #_debug "$res1" - __found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') + res1="$(_get "$uri1" | _normalizeJson)" + _debug2 "res1" "$res1" + __found="$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')" _debug "found: $__found results on page" if [ "$__found" -lt 20 ]; then _debug "last page: $__page"