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