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

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