diff --git a/README.md b/README.md index e810ac7f..c4ea5c6e 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,7 @@ You don't have to do anything manually! 1. netcup DNS API (https://www.netcup.de) 1. GratisDNS.dk (https://gratisdns.dk) 1. Namecheap API (https://www.namecheap.com/) +1. MyDNS.JP API (https://www.mydns.jp/) 1. hosting.de (https://www.hosting.de) And: diff --git a/acme.sh b/acme.sh index 6eee183c..392079fb 100755 --- a/acme.sh +++ b/acme.sh @@ -124,23 +124,19 @@ if [ -t 1 ]; then fi __green() { - if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[1;31;32m' + if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then + printf '\033[1;31;32m%b\033[0m' "$1" + return fi printf -- "%b" "$1" - if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[0m' - fi } __red() { - if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[1;31;40m' + if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then + printf '\033[1;31;40m%b\033[0m' "$1" + return fi printf -- "%b" "$1" - if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[0m' - fi } _printargs() { @@ -1810,14 +1806,14 @@ _send_signed_request() { if [ -z "$_CACHED_NONCE" ]; then _headers="" if [ "$ACME_NEW_NONCE" ]; then - _debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE" + _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE" nonceurl="$ACME_NEW_NONCE" if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then _headers="$(cat "$HTTP_HEADER")" fi fi if [ -z "$_headers" ]; then - _debug2 "Get nonce. ACME_DIRECTORY" "$ACME_DIRECTORY" + _debug2 "Get nonce with GET. ACME_DIRECTORY" "$ACME_DIRECTORY" nonceurl="$ACME_DIRECTORY" _headers="$(_get "$nonceurl" "onlyheader")" fi @@ -2925,6 +2921,7 @@ _clearupdns() { _debug txt "$txt" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then _debug "$d is already verified, skip $vtype." + _alias_index="$(_math "$_alias_index" + 1)" continue fi @@ -3775,6 +3772,7 @@ $_authorizations_map" _debug d "$d" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then _debug "$d is already verified, skip $vtype." + _alias_index="$(_math "$_alias_index" + 1)" continue fi @@ -4602,7 +4600,8 @@ deploy() { _initpath "$_d" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then - _err "Domain is not valid:'$_d'" + _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'" return 1 fi @@ -4629,7 +4628,8 @@ installcert() { _initpath "$_main_domain" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then - _err "Domain is not valid:'$_main_domain'" + _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'" return 1 fi @@ -5474,7 +5474,7 @@ Parameters: --log-level 1|2 Specifies the log level, default is 1. --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. - These parameters are to install the cert to nginx/apache or anyother 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 After issue/renew, the cert will be copied to this path. --key-file After issue/renew, the key will be copied to this path. @@ -5485,7 +5485,7 @@ Parameters: --server SERVER ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory) --accountconf Specifies a customized account config file. - --home Specifies the home dir for $PROJECT_NAME . + --home Specifies the home dir for $PROJECT_NAME. --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. diff --git a/dnsapi/README.md b/dnsapi/README.md index e9a32e0d..bb0e89d0 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -6,7 +6,7 @@ https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode ## 1. Use CloudFlare domain API to automatically issue cert -First you need to login to your CloudFlare account to get your API key. +First you need to login to your CloudFlare account to get your [API key](https://dash.cloudflare.com/profile). ``` export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" @@ -454,7 +454,7 @@ The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account. First you need to create/obtain API tokens on your [settings panel](https://vscale.io/panel/settings/tokens/). ``` -VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" +export VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" ``` Ok, let's issue a cert now: @@ -1014,7 +1014,23 @@ Now you can issue a certificate. acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com ``` -## 54. Use hosting.de API +## 54. Use MyDNS.JP API + +First, register to MyDNS.JP and get MasterID and Password. + +``` +export MYDNSJP_MasterID=MasterID +export MYDNSJP_Password=Password +``` + +To issue a certificate: + +``` +acme.sh --issue --dns dns_mydnsjp -d example.com -d www.example.com +``` +The `MYDNSJP_MasterID` and `MYDNSJP_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + +## 55. Use hosting.de API Create an API key in your hosting.de account here: https://secure.hosting.de diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index c6893a0c..ae8aa1ca 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -316,7 +316,7 @@ _get_root() { ## (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 ## - _azure_rest GET "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Network/dnszones?api-version=2017-09-01" "" "$accesstoken" + _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 is Json response while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) diff --git a/dnsapi/dns_cx.sh b/dnsapi/dns_cx.sh index f2d3eadb..d07d8e0c 100755 --- a/dnsapi/dns_cx.sh +++ b/dnsapi/dns_cx.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -# Cloudxns.com Domain api +# CloudXNS Domain api # #CX_Key="1234" # @@ -19,7 +19,7 @@ dns_cx_add() { if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then CX_Key="" CX_Secret="" - _err "You don't specify cloudxns.com api key or secret yet." + _err "You don't specify cloudxns.net api key or secret yet." _err "Please create you key and try again." return 1 fi diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index da4a1b81..df00c746 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -92,7 +92,9 @@ dns_he_rm() { return 1 fi # Remove the record - body="email=${HE_Username}&pass=${HE_Password}" + username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)" + password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)" + body="email=${username_encoded}&pass=${password_encoded}" body="$body&menu=edit_zone" body="$body&hosted_dns_zoneid=$_zone_id" body="$body&hosted_dns_recordid=$_record_id" diff --git a/dnsapi/dns_mydnsjp.sh b/dnsapi/dns_mydnsjp.sh new file mode 100755 index 00000000..aab2aabf --- /dev/null +++ b/dnsapi/dns_mydnsjp.sh @@ -0,0 +1,210 @@ +#!/usr/bin/env sh + +#Here is a api script for MyDNS.JP. +#This file name is "dns_mydnsjp.sh" +#So, here must be a method dns_mydnsjp_add() +#Which will be called by acme.sh to add the txt record to your api system. +#returns 0 means success, otherwise error. +# +#Author: epgdatacapbon +#Report Bugs here: https://github.com/epgdatacapbon/acme.sh +# +######## Public functions ##################### + +# Export MyDNS.JP MasterID and Password in following variables... +# MYDNSJP_MasterID=MasterID +# MYDNSJP_Password=Password + +MYDNSJP_API="https://www.mydns.jp" + +#Usage: dns_mydnsjp_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_mydnsjp_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Using mydnsjp" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + # Load the credentials from the account conf file + MYDNSJP_MasterID="${MYDNSJP_MasterID:-$(_readaccountconf_mutable MYDNSJP_MasterID)}" + MYDNSJP_Password="${MYDNSJP_Password:-$(_readaccountconf_mutable MYDNSJP_Password)}" + if [ -z "$MYDNSJP_MasterID" ] || [ -z "$MYDNSJP_Password" ]; then + MYDNSJP_MasterID="" + MYDNSJP_Password="" + _err "You don't specify mydnsjp api MasterID and Password yet." + _err "Please export as MYDNSJP_MasterID / MYDNSJP_Password and try again." + return 1 + fi + + # Save the credentials to the account conf file + _saveaccountconf_mutable MYDNSJP_MasterID "$MYDNSJP_MasterID" + _saveaccountconf_mutable MYDNSJP_Password "$MYDNSJP_Password" + + _debug "First detect the root zone." + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if _mydnsjp_api "REGIST" "$_domain" "$txtvalue"; then + if printf -- "%s" "$response" | grep "OK." >/dev/null; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_mydnsjp_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Removing TXT record" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + # Load the credentials from the account conf file + MYDNSJP_MasterID="${MYDNSJP_MasterID:-$(_readaccountconf_mutable MYDNSJP_MasterID)}" + MYDNSJP_Password="${MYDNSJP_Password:-$(_readaccountconf_mutable MYDNSJP_Password)}" + if [ -z "$MYDNSJP_MasterID" ] || [ -z "$MYDNSJP_Password" ]; then + MYDNSJP_MasterID="" + MYDNSJP_Password="" + _err "You don't specify mydnsjp api MasterID and Password yet." + _err "Please export as MYDNSJP_MasterID / MYDNSJP_Password and try again." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if _mydnsjp_api "DELETE" "$_domain" "$txtvalue"; then + if printf -- "%s" "$response" | grep "OK." >/dev/null; then + _info "Deleted, OK" + return 0 + else + _err "Delete txt record error." + return 1 + fi + fi + _err "Delete txt record error." + + return 1 +} + +#################### Private functions below ################################## +# _acme-challenge.www.domain.com +# returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + fulldomain=$1 + i=2 + p=1 + + # Get the root domain + _mydnsjp_retrieve_domain + if [ "$?" != "0" ]; then + # not valid + return 1 + fi + + while true; do + _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + + if [ -z "$_domain" ]; then + # not valid + return 1 + fi + + if [ "$_domain" = "$_root_domain" ]; then + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} + +# Retrieve the root domain +# returns 0 success +_mydnsjp_retrieve_domain() { + _debug "Login to MyDNS.JP" + + response="$(_post "masterid=$MYDNSJP_MasterID&masterpwd=$MYDNSJP_Password" "$MYDNSJP_API/?MENU=100")" + cookie="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2)" + + # If cookies is not empty then logon successful + if [ -z "$cookie" ]; then + _err "Fail to get a cookie." + return 1 + fi + + _debug "Retrieve DOMAIN INFO page" + + export _H1="Cookie:${cookie}" + + response="$(_get "$MYDNSJP_API/?MENU=300")" + + if [ "$?" != "0" ]; then + _err "Fail to retrieve DOMAIN INFO." + return 1 + fi + + _root_domain=$(echo "$response" | grep "DNSINFO\[domainname\]" | sed 's/^.*value="\([^"]*\)".*/\1/') + + # Logout + response="$(_get "$MYDNSJP_API/?MENU=090")" + + _debug _root_domain "$_root_domain" + + if [ -z "$_root_domain" ]; then + _err "Fail to get the root domain." + return 1 + fi + + return 0 +} + +_mydnsjp_api() { + cmd=$1 + domain=$2 + txtvalue=$3 + + # Base64 encode the credentials + credentials=$(printf "%s:%s" "$MYDNSJP_MasterID" "$MYDNSJP_Password" | _base64) + + # Construct the HTTP Authorization header + export _H1="Content-Type: application/x-www-form-urlencoded" + export _H2="Authorization: Basic ${credentials}" + + response="$(_post "CERTBOT_DOMAIN=$domain&CERTBOT_VALIDATION=$txtvalue&EDIT_CMD=$cmd" "$MYDNSJP_API/directedit.html")" + + if [ "$?" != "0" ]; then + _err "error $domain" + return 1 + fi + + _debug2 response "$response" + + return 0 +}