]>
Commit | Line | Data |
---|---|---|
731ed695 | 1 | #!/usr/bin/env sh |
657334fb | 2 | |
3 | # | |
4 | #INWX_User="username" | |
5 | # | |
6 | #INWX_Password="password" | |
63f32835 JOK |
7 | # |
8 | # Dependencies: | |
9 | # ------------- | |
10 | # - oathtool (When using 2 Factor Authentication) | |
657334fb | 11 | |
12 | INWX_Api="https://api.domrobot.com/xmlrpc/" | |
13 | ||
14 | ######## Public functions ##################### | |
15 | ||
16 | #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
17 | dns_inwx_add() { | |
18 | fulldomain=$1 | |
19 | txtvalue=$2 | |
20 | ||
21 | INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" | |
22 | INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" | |
63f32835 | 23 | INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}" |
657334fb | 24 | if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then |
25 | INWX_User="" | |
26 | INWX_Password="" | |
27 | _err "You don't specify inwx user and password yet." | |
28 | _err "Please create you key and try again." | |
29 | return 1 | |
30 | fi | |
31 | ||
32 | #save the api key and email to the account conf file. | |
33 | _saveaccountconf_mutable INWX_User "$INWX_User" | |
34 | _saveaccountconf_mutable INWX_Password "$INWX_Password" | |
63f32835 | 35 | _saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret" |
657334fb | 36 | |
5d00edc8 NS |
37 | if ! _inwx_login; then |
38 | return 1 | |
39 | fi | |
40 | ||
657334fb | 41 | _debug "First detect the root zone" |
42 | if ! _get_root "$fulldomain"; then | |
43 | _err "invalid domain" | |
44 | return 1 | |
45 | fi | |
46 | _debug _sub_domain "$_sub_domain" | |
47 | _debug _domain "$_domain" | |
657334fb | 48 | |
584fb290 | 49 | _info "Adding record" |
50 | _inwx_add_record "$_domain" "$_sub_domain" "$txtvalue" | |
657334fb | 51 | |
52 | } | |
53 | ||
54 | #fulldomain txtvalue | |
55 | dns_inwx_rm() { | |
56 | ||
57 | fulldomain=$1 | |
58 | txtvalue=$2 | |
59 | ||
60 | INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" | |
61 | INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" | |
ea652c02 | 62 | INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}" |
657334fb | 63 | if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then |
64 | INWX_User="" | |
65 | INWX_Password="" | |
66 | _err "You don't specify inwx user and password yet." | |
67 | _err "Please create you key and try again." | |
68 | return 1 | |
69 | fi | |
70 | ||
5d00edc8 NS |
71 | if ! _inwx_login; then |
72 | return 1 | |
73 | fi | |
74 | ||
657334fb | 75 | _debug "First detect the root zone" |
76 | if ! _get_root "$fulldomain"; then | |
77 | _err "invalid domain" | |
78 | return 1 | |
79 | fi | |
80 | _debug _sub_domain "$_sub_domain" | |
81 | _debug _domain "$_domain" | |
82 | ||
83 | _debug "Getting txt records" | |
84 | ||
9a1f7698 | 85 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 86 | <methodCall> |
87 | <methodName>nameserver.info</methodName> | |
88 | <params> | |
89 | <param> | |
90 | <value> | |
91 | <struct> | |
92 | <member> | |
93 | <name>domain</name> | |
94 | <value> | |
95 | <string>%s</string> | |
96 | </value> | |
97 | </member> | |
98 | <member> | |
99 | <name>type</name> | |
100 | <value> | |
101 | <string>TXT</string> | |
102 | </value> | |
103 | </member> | |
104 | <member> | |
105 | <name>name</name> | |
106 | <value> | |
107 | <string>%s</string> | |
108 | </value> | |
109 | </member> | |
110 | </struct> | |
111 | </value> | |
112 | </param> | |
113 | </params> | |
9a1f7698 | 114 | </methodCall>' "$_domain" "$_sub_domain") |
657334fb | 115 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" |
116 | ||
584fb290 | 117 | if ! _contains "$response" "Command completed successfully"; then |
657334fb | 118 | _err "Error could not get txt records" |
119 | return 1 | |
120 | fi | |
121 | ||
9a1f7698 | 122 | if ! printf "%s" "$response" | grep "count" >/dev/null; then |
657334fb | 123 | _info "Do not need to delete record" |
124 | else | |
59115949 | 125 | _record_id=$(printf '%s' "$response" | _egrep_o '.*(<member><name>record){1}(.*)([0-9]+){1}' | _egrep_o '<name>id<\/name><value><int>[0-9]+' | _egrep_o '[0-9]+') |
657334fb | 126 | _info "Deleting record" |
a8202d4b | 127 | _inwx_delete_record "$_record_id" |
657334fb | 128 | fi |
129 | ||
657334fb | 130 | } |
131 | ||
132 | #################### Private functions below ################################## | |
133 | ||
5d00edc8 NS |
134 | _inwx_check_cookie() { |
135 | INWX_Cookie="${INWX_Cookie:-$(_readaccountconf_mutable INWX_Cookie)}" | |
136 | if [ -z "$INWX_Cookie" ]; then | |
137 | _debug "No cached cookie found" | |
138 | return 1 | |
139 | fi | |
140 | _H1="$INWX_Cookie" | |
141 | export _H1 | |
142 | ||
143 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> | |
144 | <methodCall> | |
145 | <methodName>account.info</methodName> | |
146 | </methodCall>') | |
147 | ||
148 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" | |
149 | ||
150 | if _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then | |
151 | _debug "Cached cookie still valid" | |
152 | return 0 | |
153 | fi | |
154 | ||
155 | _debug "Cached cookie no longer valid" | |
156 | _H1="" | |
157 | export _H1 | |
158 | INWX_Cookie="" | |
159 | _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" | |
160 | return 1 | |
161 | } | |
162 | ||
657334fb | 163 | _inwx_login() { |
164 | ||
5d00edc8 NS |
165 | if _inwx_check_cookie; then |
166 | _debug "Already logged in" | |
167 | return 0 | |
168 | fi | |
169 | ||
9a1f7698 | 170 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 171 | <methodCall> |
172 | <methodName>account.login</methodName> | |
173 | <params> | |
174 | <param> | |
175 | <value> | |
176 | <struct> | |
177 | <member> | |
178 | <name>user</name> | |
179 | <value> | |
180 | <string>%s</string> | |
181 | </value> | |
182 | </member> | |
183 | <member> | |
184 | <name>pass</name> | |
185 | <value> | |
186 | <string>%s</string> | |
187 | </value> | |
188 | </member> | |
189 | </struct> | |
190 | </value> | |
191 | </param> | |
192 | </params> | |
3bad8159 | 193 | </methodCall>' "$INWX_User" "$INWX_Password") |
657334fb | 194 | |
195 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" | |
5d00edc8 NS |
196 | |
197 | INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") | |
198 | _H1=$INWX_Cookie | |
63f32835 | 199 | export _H1 |
5d00edc8 NS |
200 | export INWX_Cookie |
201 | _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" | |
a8202d4b | 202 | |
3bad8159 NS |
203 | if ! _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then |
204 | _err "INWX API: Authentication error (username/password correct?)" | |
205 | return 1 | |
206 | fi | |
207 | ||
63f32835 | 208 | #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71 |
3bad8159 | 209 | if _contains "$response" "<member><name>tfa</name><value><string>GOOGLE-AUTH</string></value></member>"; then |
63f32835 | 210 | if [ -z "$INWX_Shared_Secret" ]; then |
3bad8159 | 211 | _err "INWX API: Mobile TAN detected." |
63f32835 JOK |
212 | _err "Please define a shared secret." |
213 | return 1 | |
214 | fi | |
215 | ||
216 | if ! _exists oathtool; then | |
217 | _err "Please install oathtool to use 2 Factor Authentication." | |
218 | _err "" | |
219 | return 1 | |
220 | fi | |
221 | ||
222 | tan="$(oathtool --base32 --totp "${INWX_Shared_Secret}" 2>/dev/null)" | |
223 | ||
224 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> | |
225 | <methodCall> | |
226 | <methodName>account.unlock</methodName> | |
227 | <params> | |
228 | <param> | |
229 | <value> | |
230 | <struct> | |
231 | <member> | |
232 | <name>tan</name> | |
233 | <value> | |
234 | <string>%s</string> | |
235 | </value> | |
236 | </member> | |
237 | </struct> | |
238 | </value> | |
239 | </param> | |
240 | </params> | |
241 | </methodCall>' "$tan") | |
242 | ||
243 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" | |
3bad8159 NS |
244 | |
245 | if ! _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then | |
246 | _err "INWX API: Mobile TAN not correct." | |
247 | return 1 | |
248 | fi | |
63f32835 | 249 | fi |
657334fb | 250 | |
251 | } | |
252 | ||
253 | _get_root() { | |
a8202d4b | 254 | domain=$1 |
657334fb | 255 | _debug "get root" |
256 | ||
257 | domain=$1 | |
258 | i=2 | |
259 | p=1 | |
260 | ||
9a1f7698 | 261 | xml_content='<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 262 | <methodCall> |
263 | <methodName>nameserver.list</methodName> | |
94bf54e7 Q |
264 | <params> |
265 | <param> | |
266 | <value> | |
267 | <struct> | |
268 | <member> | |
269 | <name>pagelimit</name> | |
270 | <value> | |
271 | <int>9999</int> | |
272 | </value> | |
273 | </member> | |
274 | </struct> | |
275 | </value> | |
276 | </param> | |
277 | </params> | |
657334fb | 278 | </methodCall>' |
a8202d4b | 279 | |
657334fb | 280 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" |
281 | while true; do | |
282 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
283 | _debug h "$h" | |
284 | if [ -z "$h" ]; then | |
285 | #not valid | |
286 | return 1 | |
287 | fi | |
288 | ||
289 | if _contains "$response" "$h"; then | |
290 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
291 | _domain="$h" | |
292 | return 0 | |
293 | fi | |
294 | p=$i | |
295 | i=$(_math "$i" + 1) | |
296 | done | |
297 | return 1 | |
298 | ||
299 | } | |
300 | ||
301 | _inwx_delete_record() { | |
302 | record_id=$1 | |
9a1f7698 | 303 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 304 | <methodCall> |
305 | <methodName>nameserver.deleteRecord</methodName> | |
306 | <params> | |
307 | <param> | |
308 | <value> | |
309 | <struct> | |
310 | <member> | |
311 | <name>id</name> | |
312 | <value> | |
313 | <int>%s</int> | |
314 | </value> | |
315 | </member> | |
316 | </struct> | |
317 | </value> | |
318 | </param> | |
319 | </params> | |
9a1f7698 | 320 | </methodCall>' "$record_id") |
ecba959d | 321 | |
657334fb | 322 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" |
a8202d4b | 323 | |
657334fb | 324 | if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then |
325 | _err "Error" | |
326 | return 1 | |
327 | fi | |
328 | return 0 | |
ecba959d | 329 | |
657334fb | 330 | } |
331 | ||
332 | _inwx_update_record() { | |
333 | record_id=$1 | |
334 | txtval=$2 | |
9a1f7698 | 335 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 336 | <methodCall> |
337 | <methodName>nameserver.updateRecord</methodName> | |
338 | <params> | |
339 | <param> | |
340 | <value> | |
341 | <struct> | |
342 | <member> | |
343 | <name>content</name> | |
344 | <value> | |
345 | <string>%s</string> | |
346 | </value> | |
347 | </member> | |
348 | <member> | |
349 | <name>id</name> | |
350 | <value> | |
351 | <int>%s</int> | |
352 | </value> | |
353 | </member> | |
354 | </struct> | |
355 | </value> | |
356 | </param> | |
357 | </params> | |
9a1f7698 | 358 | </methodCall>' "$txtval" "$record_id") |
a8202d4b | 359 | |
657334fb | 360 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" |
ecba959d | 361 | |
657334fb | 362 | if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then |
363 | _err "Error" | |
364 | return 1 | |
365 | fi | |
366 | return 0 | |
ecba959d | 367 | |
657334fb | 368 | } |
369 | ||
370 | _inwx_add_record() { | |
371 | ||
372 | domain=$1 | |
373 | sub_domain=$2 | |
374 | txtval=$3 | |
375 | ||
9a1f7698 | 376 | xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> |
657334fb | 377 | <methodCall> |
378 | <methodName>nameserver.createRecord</methodName> | |
379 | <params> | |
380 | <param> | |
381 | <value> | |
382 | <struct> | |
383 | <member> | |
384 | <name>domain</name> | |
385 | <value> | |
386 | <string>%s</string> | |
387 | </value> | |
388 | </member> | |
389 | <member> | |
390 | <name>type</name> | |
391 | <value> | |
392 | <string>TXT</string> | |
393 | </value> | |
394 | </member> | |
395 | <member> | |
396 | <name>content</name> | |
397 | <value> | |
398 | <string>%s</string> | |
399 | </value> | |
400 | </member> | |
401 | <member> | |
402 | <name>name</name> | |
403 | <value> | |
404 | <string>%s</string> | |
405 | </value> | |
406 | </member> | |
407 | </struct> | |
408 | </value> | |
409 | </param> | |
410 | </params> | |
9a1f7698 | 411 | </methodCall>' "$domain" "$txtval" "$sub_domain") |
a8202d4b | 412 | |
657334fb | 413 | response="$(_post "$xml_content" "$INWX_Api" "" "POST")" |
a8202d4b | 414 | |
657334fb | 415 | if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then |
416 | _err "Error" | |
417 | return 1 | |
418 | fi | |
419 | return 0 | |
420 | } |