You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
8.0 KiB

2 months ago
  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_geoscaling_info='GeoScaling.com
  4. Site: GeoScaling.com
  5. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_geoscaling
  6. Options:
  7. GEOSCALING_Username Username. This is usually NOT an email address
  8. GEOSCALING_Password Password
  9. '
  10. #-- dns_geoscaling_add() - Add TXT record --------------------------------------
  11. # Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..."
  12. dns_geoscaling_add() {
  13. full_domain=$1
  14. txt_value=$2
  15. _info "Using DNS-01 Geoscaling DNS2 hook"
  16. GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
  17. GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
  18. if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
  19. GEOSCALING_Username=
  20. GEOSCALING_Password=
  21. _err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
  22. return 1
  23. fi
  24. _saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
  25. _saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
  26. # Fills in the $zone_id and $zone_name
  27. find_zone "${full_domain}" || return 1
  28. _debug "Zone id '${zone_id}' will be used."
  29. # We're logged in here
  30. # we should add ${full_domain} minus the trailing ${zone_name}
  31. prefix=$(echo "${full_domain}" | sed "s|\\.${zone_name}\$||")
  32. body="id=${zone_id}&name=${prefix}&type=TXT&content=${txt_value}&ttl=300&prio=0"
  33. do_post "$body" "https://www.geoscaling.com/dns2/ajax/add_record.php"
  34. exit_code="$?"
  35. if [ "${exit_code}" -eq 0 ]; then
  36. _info "TXT record added successfully."
  37. else
  38. _err "Couldn't add the TXT record."
  39. fi
  40. do_logout
  41. return "${exit_code}"
  42. }
  43. #-- dns_geoscaling_rm() - Remove TXT record ------------------------------------
  44. # Usage: dns_geoscaling_rm _acme-challenge.subdomain.domain.com "XyZ123..."
  45. dns_geoscaling_rm() {
  46. full_domain=$1
  47. txt_value=$2
  48. _info "Cleaning up after DNS-01 Geoscaling DNS2 hook"
  49. GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
  50. GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
  51. if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
  52. GEOSCALING_Username=
  53. GEOSCALING_Password=
  54. _err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
  55. return 1
  56. fi
  57. _saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
  58. _saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
  59. # fills in the $zone_id
  60. find_zone "${full_domain}" || return 1
  61. _debug "Zone id '${zone_id}' will be used."
  62. # Here we're logged in
  63. # Find the record id to clean
  64. # get the domain
  65. response=$(do_get "https://www.geoscaling.com/dns2/index.php?module=domain&id=${zone_id}")
  66. _debug2 "response" "$response"
  67. table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Basic Records</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
  68. _debug2 table "${table}"
  69. names=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|</td>||; s|.*>||')
  70. ids=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|\.name">.*||; s|id="||')
  71. types=$(echo "${table}" | _egrep_o 'id="[0-9]+\.type">[^<]*</td>' | sed 's|</td>||; s|.*>||')
  72. values=$(echo "${table}" | _egrep_o 'id="[0-9]+\.content">[^<]*</td>' | sed 's|</td>||; s|.*>||')
  73. _debug2 names "${names}"
  74. _debug2 ids "${ids}"
  75. _debug2 types "${types}"
  76. _debug2 values "${values}"
  77. # look for line whose name is ${full_domain}, whose type is TXT, and whose value is ${txt_value}
  78. line_num="$(echo "${values}" | grep -F -n -- "${txt_value}" | _head_n 1 | cut -d ':' -f 1)"
  79. _debug2 line_num "${line_num}"
  80. found_id=
  81. if [ -n "$line_num" ]; then
  82. type=$(echo "${types}" | sed -n "${line_num}p")
  83. name=$(echo "${names}" | sed -n "${line_num}p")
  84. id=$(echo "${ids}" | sed -n "${line_num}p")
  85. _debug2 type "$type"
  86. _debug2 name "$name"
  87. _debug2 id "$id"
  88. _debug2 full_domain "$full_domain"
  89. if [ "${type}" = "TXT" ] && [ "${name}" = "${full_domain}" ]; then
  90. found_id=${id}
  91. fi
  92. fi
  93. if [ "${found_id}" = "" ]; then
  94. _err "Can not find record id."
  95. return 0
  96. fi
  97. # Remove the record
  98. body="id=${zone_id}&record_id=${found_id}"
  99. response=$(do_post "$body" "https://www.geoscaling.com/dns2/ajax/delete_record.php")
  100. exit_code="$?"
  101. if [ "$exit_code" -eq 0 ]; then
  102. _info "Record removed successfully."
  103. else
  104. _err "Could not clean (remove) up the record. Please go to Geoscaling administration interface and clean it by hand."
  105. fi
  106. do_logout
  107. return "${exit_code}"
  108. }
  109. ########################## PRIVATE FUNCTIONS ###########################
  110. do_get() {
  111. _url=$1
  112. export _H1="Cookie: $geoscaling_phpsessid_cookie"
  113. _get "${_url}"
  114. }
  115. do_post() {
  116. _body=$1
  117. _url=$2
  118. export _H1="Cookie: $geoscaling_phpsessid_cookie"
  119. _post "${_body}" "${_url}"
  120. }
  121. do_login() {
  122. _info "Logging in..."
  123. username_encoded="$(printf "%s" "${GEOSCALING_Username}" | _url_encode)"
  124. password_encoded="$(printf "%s" "${GEOSCALING_Password}" | _url_encode)"
  125. body="username=${username_encoded}&password=${password_encoded}"
  126. response=$(_post "$body" "https://www.geoscaling.com/dns2/index.php?module=auth")
  127. _debug2 response "${response}"
  128. #retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | _egrep_o '[0-9]+$')
  129. retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | cut -d ' ' -f 2)
  130. if [ "$retcode" != "302" ]; then
  131. _err "Geoscaling login failed for user ${GEOSCALING_Username}. Check ${HTTP_HEADER} file"
  132. return 1
  133. fi
  134. geoscaling_phpsessid_cookie="$(grep -i '^set-cookie:' "${HTTP_HEADER}" | _egrep_o 'PHPSESSID=[^;]*;' | tr -d ';')"
  135. return 0
  136. }
  137. do_logout() {
  138. _info "Logging out."
  139. response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=auth")"
  140. _debug2 response "$response"
  141. return 0
  142. }
  143. find_zone() {
  144. domain="$1"
  145. # do login
  146. do_login || return 1
  147. # get zones
  148. response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=domains")"
  149. table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Your domains</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
  150. _debug2 table "${table}"
  151. zone_names="$(echo "${table}" | _egrep_o '<b>[^<]*</b>' | sed 's|<b>||;s|</b>||')"
  152. _debug2 _matches "${zone_names}"
  153. # Zone names and zone IDs are in same order
  154. zone_ids=$(echo "${table}" | _egrep_o '<a href=.index\.php\?module=domain&id=[0-9]+. onclick="javascript:show_loader\(\);">' | sed 's|.*id=||;s|. .*||')
  155. _debug2 "These are the zones on this Geoscaling account:"
  156. _debug2 "zone_names" "${zone_names}"
  157. _debug2 "And these are their respective IDs:"
  158. _debug2 "zone_ids" "${zone_ids}"
  159. if [ -z "${zone_names}" ] || [ -z "${zone_ids}" ]; then
  160. _err "Can not get zone names or IDs."
  161. return 1
  162. fi
  163. # Walk through all possible zone names
  164. strip_counter=1
  165. while true; do
  166. attempted_zone=$(echo "${domain}" | cut -d . -f "${strip_counter}"-)
  167. # All possible zone names have been tried
  168. if [ -z "${attempted_zone}" ]; then
  169. _err "No zone for domain '${domain}' found."
  170. return 1
  171. fi
  172. _debug "Looking for zone '${attempted_zone}'"
  173. line_num="$(echo "${zone_names}" | grep -n "^${attempted_zone}\$" | _head_n 1 | cut -d : -f 1)"
  174. _debug2 line_num "${line_num}"
  175. if [ "$line_num" ]; then
  176. zone_id=$(echo "${zone_ids}" | sed -n "${line_num}p")
  177. zone_name=$(echo "${zone_names}" | sed -n "${line_num}p")
  178. if [ -z "${zone_id}" ]; then
  179. _err "Can not find zone id."
  180. return 1
  181. fi
  182. _debug "Found relevant zone '${attempted_zone}' with id '${zone_id}' - will be used for domain '${domain}'."
  183. return 0
  184. fi
  185. _debug "Zone '${attempted_zone}' doesn't exist, let's try a less specific zone."
  186. strip_counter=$(_math "${strip_counter}" + 1)
  187. done
  188. }
  189. # vim: et:ts=2:sw=2: