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.

311 lines
7.5 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. #!/usr/bin/env sh
  2. # Namecheap API
  3. # https://www.namecheap.com/support/api/intro.aspx
  4. #
  5. # Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable
  6. # Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise.
  7. ######## Public functions #####################
  8. if [ "$STAGE" -eq 1 ]; then
  9. NAMECHEAP_API="https://api.sandbox.namecheap.com/xml.response"
  10. else
  11. NAMECHEAP_API="https://api.namecheap.com/xml.response"
  12. fi
  13. #Usage: dns_namecheap_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  14. dns_namecheap_add() {
  15. fulldomain=$1
  16. txtvalue=$2
  17. if ! _namecheap_check_config; then
  18. _err "$error"
  19. return 1
  20. fi
  21. if ! _namecheap_set_publicip; then
  22. return 1
  23. fi
  24. _debug "First detect the root zone"
  25. if ! _get_root "$fulldomain"; then
  26. _err "invalid domain"
  27. return 1
  28. fi
  29. _debug fulldomain "$fulldomain"
  30. _debug txtvalue "$txtvalue"
  31. _debug domain "$_domain"
  32. _debug sub_domain "$_sub_domain"
  33. _set_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue"
  34. }
  35. #Usage: fulldomain txtvalue
  36. #Remove the txt record after validation.
  37. dns_namecheap_rm() {
  38. fulldomain=$1
  39. txtvalue=$2
  40. if ! _namecheap_set_publicip; then
  41. return 1
  42. fi
  43. if ! _namecheap_check_config; then
  44. _err "$error"
  45. return 1
  46. fi
  47. _debug "First detect the root zone"
  48. if ! _get_root "$fulldomain"; then
  49. _err "invalid domain"
  50. return 1
  51. fi
  52. _debug fulldomain "$fulldomain"
  53. _debug txtvalue "$txtvalue"
  54. _debug domain "$_domain"
  55. _debug sub_domain "$_sub_domain"
  56. _del_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue"
  57. }
  58. #################### Private functions below ##################################
  59. #_acme-challenge.www.domain.com
  60. #returns
  61. # _sub_domain=_acme-challenge.www
  62. # _domain=domain.com
  63. _get_root() {
  64. domain=$1
  65. if ! _namecheap_post "namecheap.domains.getList"; then
  66. _err "$error"
  67. return 1
  68. fi
  69. i=2
  70. p=1
  71. while true; do
  72. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  73. _debug h "$h"
  74. if [ -z "$h" ]; then
  75. #not valid
  76. return 1
  77. fi
  78. if ! _contains "$response" "$h"; then
  79. _debug "$h not found"
  80. else
  81. _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  82. _domain="$h"
  83. return 0
  84. fi
  85. p="$i"
  86. i=$(_math "$i" + 1)
  87. done
  88. return 1
  89. }
  90. _namecheap_set_publicip() {
  91. if [ -z "$NAMECHEAP_SOURCEIP" ]; then
  92. _err "No Source IP specified for Namecheap API."
  93. _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
  94. return 1
  95. else
  96. _saveaccountconf NAMECHEAP_SOURCEIP "$NAMECHEAP_SOURCEIP"
  97. _debug sourceip "$NAMECHEAP_SOURCEIP"
  98. ip=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
  99. addr=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '(http|https)://.*')
  100. _debug2 ip "$ip"
  101. _debug2 addr "$addr"
  102. if [ -n "$ip" ]; then
  103. _publicip="$ip"
  104. elif [ -n "$addr" ]; then
  105. _publicip=$(_get "$addr")
  106. else
  107. _err "No Source IP specified for Namecheap API."
  108. _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
  109. return 1
  110. fi
  111. fi
  112. _debug publicip "$_publicip"
  113. return 0
  114. }
  115. _namecheap_post() {
  116. command=$1
  117. data="ApiUser=${NAMECHEAP_USERNAME}&ApiKey=${NAMECHEAP_API_KEY}&ClientIp=${_publicip}&UserName=${NAMECHEAP_USERNAME}&Command=${command}"
  118. response="$(_post "$data" "$NAMECHEAP_API" "" "POST")"
  119. _debug2 response "$response"
  120. if _contains "$response" "Status=\"ERROR\"" >/dev/null; then
  121. error=$(echo "$response" | _egrep_o ">.*<\\/Error>" | cut -d '<' -f 1 | tr -d '>')
  122. _err "error $error"
  123. return 1
  124. fi
  125. return 0
  126. }
  127. _namecheap_parse_host() {
  128. _host=$1
  129. _debug _host "$_host"
  130. _hostid=$(echo "$_host" | _egrep_o '\sHostId="[^"]*' | cut -d '"' -f 2)
  131. _hostname=$(echo "$_host" | _egrep_o '\sName="[^"]*' | cut -d '"' -f 2)
  132. _hosttype=$(echo "$_host" | _egrep_o '\sType="[^"]*' | cut -d '"' -f 2)
  133. _hostaddress=$(echo "$_host" | _egrep_o '\sAddress="[^"]*' | cut -d '"' -f 2)
  134. _hostmxpref=$(echo "$_host" | _egrep_o '\sMXPref="[^"]*' | cut -d '"' -f 2)
  135. _hostttl=$(echo "$_host" | _egrep_o '\sTTL="[^"]*' | cut -d '"' -f 2)
  136. _debug hostid "$_hostid"
  137. _debug hostname "$_hostname"
  138. _debug hosttype "$_hosttype"
  139. _debug hostaddress "$_hostaddress"
  140. _debug hostmxpref "$_hostmxpref"
  141. _debug hostttl "$_hostttl"
  142. }
  143. _namecheap_check_config() {
  144. if [ -z "$NAMECHEAP_API_KEY" ]; then
  145. _err "No API key specified for Namecheap API."
  146. _err "Create your key and export it as NAMECHEAP_API_KEY"
  147. return 1
  148. fi
  149. if [ -z "$NAMECHEAP_USERNAME" ]; then
  150. _err "No username key specified for Namecheap API."
  151. _err "Create your key and export it as NAMECHEAP_USERNAME"
  152. return 1
  153. fi
  154. _saveaccountconf NAMECHEAP_API_KEY "$NAMECHEAP_API_KEY"
  155. _saveaccountconf NAMECHEAP_USERNAME "$NAMECHEAP_USERNAME"
  156. return 0
  157. }
  158. _set_namecheap_TXT() {
  159. subdomain=$2
  160. txt=$3
  161. tld=$(echo "$1" | cut -d '.' -f 2)
  162. sld=$(echo "$1" | cut -d '.' -f 1)
  163. request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld"
  164. if ! _namecheap_post "$request"; then
  165. _err "$error"
  166. return 1
  167. fi
  168. hosts=$(echo "$response" | _egrep_o '<host[^>]*')
  169. _debug hosts "$hosts"
  170. if [ -z "$hosts" ]; then
  171. _error "Hosts not found"
  172. return 1
  173. fi
  174. _namecheap_reset_hostList
  175. while read -r host; do
  176. if _contains "$host" "<host"; then
  177. _namecheap_parse_host "$host"
  178. _namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
  179. fi
  180. done <<EOT
  181. echo "$hosts"
  182. EOT
  183. _namecheap_add_host "$subdomain" "TXT" "$txt" 10 120
  184. _debug hostrequestfinal "$_hostrequest"
  185. request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}"
  186. if ! _namecheap_post "$request"; then
  187. _err "$error"
  188. return 1
  189. fi
  190. return 0
  191. }
  192. _del_namecheap_TXT() {
  193. subdomain=$2
  194. txt=$3
  195. tld=$(echo "$1" | cut -d '.' -f 2)
  196. sld=$(echo "$1" | cut -d '.' -f 1)
  197. request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld"
  198. if ! _namecheap_post "$request"; then
  199. _err "$error"
  200. return 1
  201. fi
  202. hosts=$(echo "$response" | _egrep_o '<host[^>]*')
  203. _debug hosts "$hosts"
  204. if [ -z "$hosts" ]; then
  205. _error "Hosts not found"
  206. return 1
  207. fi
  208. _namecheap_reset_hostList
  209. found=0
  210. while read -r host; do
  211. if _contains "$host" "<host"; then
  212. _namecheap_parse_host "$host"
  213. if [ "$_hosttype" = "TXT" ] && [ "$_hostname" = "$subdomain" ] && [ "$_hostaddress" = "$txt" ]; then
  214. _debug "TXT entry found"
  215. found=1
  216. else
  217. _namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
  218. fi
  219. fi
  220. done <<EOT
  221. echo "$hosts"
  222. EOT
  223. if [ $found -eq 0 ]; then
  224. _debug "TXT entry not found"
  225. return 0
  226. fi
  227. _debug hostrequestfinal "$_hostrequest"
  228. request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}"
  229. if ! _namecheap_post "$request"; then
  230. _err "$error"
  231. return 1
  232. fi
  233. return 0
  234. }
  235. _namecheap_reset_hostList() {
  236. _hostindex=0
  237. _hostrequest=""
  238. }
  239. #Usage: _namecheap_add_host HostName RecordType Address MxPref TTL
  240. _namecheap_add_host() {
  241. _hostindex=$(_math "$_hostindex" + 1)
  242. _hostrequest=$(printf '%s&HostName%d=%s&RecordType%d=%s&Address%d=%s&MXPref%d=%d&TTL%d=%d' "$_hostrequest" "$_hostindex" "$1" "$_hostindex" "$2" "$_hostindex" "$3" "$_hostindex" "$4" "$_hostindex" "$5")
  243. }