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.

354 lines
9.2 KiB

2 months ago
2 months ago
  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_euserv_info='EUserv.com
  4. Domains: EUserv.eu
  5. Site: EUserv.com
  6. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_euserv
  7. Options:
  8. EUSERV_Username Username
  9. EUSERV_Password Password
  10. Author: Michael Brueckner
  11. '
  12. EUSERV_Api="https://api.euserv.net"
  13. ######## Public functions #####################
  14. #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  15. dns_euserv_add() {
  16. fulldomain="$(echo "$1" | _lower_case)"
  17. txtvalue=$2
  18. EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
  19. EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
  20. if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
  21. EUSERV_Username=""
  22. EUSERV_Password=""
  23. _err "You don't specify euserv user and password yet."
  24. _err "Please create your key and try again."
  25. return 1
  26. fi
  27. #save the user and email to the account conf file.
  28. _saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
  29. _saveaccountconf_mutable EUSERV_Password "$EUSERV_Password"
  30. _debug "First detect the root zone"
  31. if ! _get_root "$fulldomain"; then
  32. _err "invalid domain"
  33. return 1
  34. fi
  35. _debug "_sub_domain" "$_sub_domain"
  36. _debug "_domain" "$_domain"
  37. _info "Adding record"
  38. if ! _euserv_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
  39. return 1
  40. fi
  41. }
  42. #fulldomain txtvalue
  43. dns_euserv_rm() {
  44. fulldomain="$(echo "$1" | _lower_case)"
  45. txtvalue=$2
  46. EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
  47. EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
  48. if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
  49. EUSERV_Username=""
  50. EUSERV_Password=""
  51. _err "You don't specify euserv user and password yet."
  52. _err "Please create your key and try again."
  53. return 1
  54. fi
  55. #save the user and email to the account conf file.
  56. _saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
  57. _saveaccountconf_mutable EUSERV_Password "$EUSERV_Password"
  58. _debug "First detect the root zone"
  59. if ! _get_root "$fulldomain"; then
  60. _err "invalid domain"
  61. return 1
  62. fi
  63. _debug "_sub_domain" "$_sub_domain"
  64. _debug "_domain" "$_domain"
  65. _debug "Getting txt records"
  66. xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
  67. <methodCall>
  68. <methodName>domain.dns_get_active_records</methodName>
  69. <params>
  70. <param>
  71. <value>
  72. <struct>
  73. <member>
  74. <name>login</name>
  75. <value>
  76. <string>%s</string>
  77. </value>
  78. </member>
  79. <member>
  80. <name>password</name>
  81. <value>
  82. <string>%s</string>
  83. </value>
  84. </member>
  85. <member>
  86. <name>domain_id</name>
  87. <value>
  88. <int>%s</int>
  89. </value>
  90. </member>
  91. </struct>
  92. </value>
  93. </param>
  94. </params>
  95. </methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id")
  96. export _H1="Content-Type: text/xml"
  97. response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
  98. if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
  99. _err "Error could not get txt records"
  100. _debug "xml_content" "$xml_content"
  101. _debug "response" "$response"
  102. return 1
  103. fi
  104. if ! echo "$response" | grep '>dns_record_content<.*>'"$txtvalue"'<' >/dev/null; then
  105. _info "Do not need to delete record"
  106. else
  107. # find XML block where txtvalue is in. The record_id is allways prior this line!
  108. _endLine=$(echo "$response" | grep -n '>dns_record_content<.*>'"$txtvalue"'<' | cut -d ':' -f 1)
  109. # record_id is the last <name> Tag with a number before the row _endLine, identified by </name><value><struct>
  110. _record_id=$(echo "$response" | sed -n '1,'"$_endLine"'p' | grep '</name><value><struct>' | _tail_n 1 | sed 's/.*<name>\([0-9]*\)<\/name>.*/\1/')
  111. _info "Deleting record"
  112. _euserv_delete_record "$_record_id"
  113. fi
  114. }
  115. #################### Private functions below ##################################
  116. _get_root() {
  117. domain=$1
  118. _debug "get root"
  119. # Just to read the domain_orders once
  120. domain=$1
  121. i=2
  122. p=1
  123. if ! _euserv_get_domain_orders; then
  124. return 1
  125. fi
  126. # Get saved response with domain_orders
  127. response="$_euserv_domain_orders"
  128. while true; do
  129. h=$(echo "$domain" | cut -d . -f "$i"-100)
  130. _debug h "$h"
  131. if [ -z "$h" ]; then
  132. #not valid
  133. return 1
  134. fi
  135. if _contains "$response" "$h"; then
  136. _sub_domain=$(echo "$domain" | cut -d . -f 1-"$p")
  137. _domain="$h"
  138. if ! _euserv_get_domain_id "$_domain"; then
  139. _err "invalid domain"
  140. return 1
  141. fi
  142. return 0
  143. fi
  144. p=$i
  145. i=$(_math "$i" + 1)
  146. done
  147. return 1
  148. }
  149. _euserv_get_domain_orders() {
  150. # returns: _euserv_domain_orders
  151. _debug "get domain_orders"
  152. xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
  153. <methodCall>
  154. <methodName>domain.get_domain_orders</methodName>
  155. <params>
  156. <param>
  157. <value>
  158. <struct>
  159. <member>
  160. <name>login</name>
  161. <value><string>%s</string></value>
  162. </member>
  163. <member>
  164. <name>password</name>
  165. <value><string>%s</string></value>
  166. </member>
  167. </struct>
  168. </value>
  169. </param>
  170. </params>
  171. </methodCall>' "$EUSERV_Username" "$EUSERV_Password")
  172. export _H1="Content-Type: text/xml"
  173. response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
  174. if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
  175. _err "Error could not get domain orders"
  176. _debug "xml_content" "$xml_content"
  177. _debug "response" "$response"
  178. return 1
  179. fi
  180. # save response to reduce API calls
  181. _euserv_domain_orders="$response"
  182. return 0
  183. }
  184. _euserv_get_domain_id() {
  185. # returns: _euserv_domain_id
  186. domain=$1
  187. _debug "get domain_id"
  188. # find line where the domain name is within the $response
  189. _startLine=$(echo "$_euserv_domain_orders" | grep -n '>domain_name<.*>'"$domain"'<' | cut -d ':' -f 1)
  190. # next occurency of domain_id after the domain_name is the correct one
  191. _euserv_domain_id=$(echo "$_euserv_domain_orders" | sed -n "$_startLine"',$p' | grep '>domain_id<' | _head_n 1 | sed 's/.*<i4>\([0-9]*\)<\/i4>.*/\1/')
  192. if [ -z "$_euserv_domain_id" ]; then
  193. _err "Could not find domain_id for domain $domain"
  194. _debug "_euserv_domain_orders" "$_euserv_domain_orders"
  195. return 1
  196. fi
  197. return 0
  198. }
  199. _euserv_delete_record() {
  200. record_id=$1
  201. xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
  202. <methodCall>
  203. <methodName>domain.dns_delete_record</methodName>
  204. <params>
  205. <param>
  206. <value>
  207. <struct>
  208. <member>
  209. <name>login</name>
  210. <value>
  211. <string>%s</string>
  212. </value>
  213. </member>
  214. <member>
  215. <name>password</name>
  216. <value>
  217. <string>%s</string>
  218. </value>
  219. </member>
  220. <member>
  221. <name>dns_record_id</name>
  222. <value>
  223. <int>%s</int>
  224. </value>
  225. </member>
  226. </struct>
  227. </value>
  228. </param>
  229. </params>
  230. </methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$record_id")
  231. export _H1="Content-Type: text/xml"
  232. response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
  233. if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
  234. _err "Error deleting record"
  235. _debug "xml_content" "$xml_content"
  236. _debug "response" "$response"
  237. return 1
  238. fi
  239. return 0
  240. }
  241. _euserv_add_record() {
  242. domain=$1
  243. sub_domain=$2
  244. txtval=$3
  245. xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
  246. <methodCall>
  247. <methodName>domain.dns_create_record</methodName>
  248. <params>
  249. <param>
  250. <value>
  251. <struct>
  252. <member>
  253. <name>login</name>
  254. <value>
  255. <string>%s</string>
  256. </value>
  257. </member>
  258. <member>
  259. <name>password</name>
  260. <value>
  261. <string>%s</string></value>
  262. </member>
  263. <member>
  264. <name>domain_id</name>
  265. <value>
  266. <int>%s</int>
  267. </value>
  268. </member>
  269. <member>
  270. <name>dns_record_subdomain</name>
  271. <value>
  272. <string>%s</string>
  273. </value>
  274. </member>
  275. <member>
  276. <name>dns_record_type</name>
  277. <value>
  278. <string>TXT</string>
  279. </value>
  280. </member>
  281. <member>
  282. <name>dns_record_value</name>
  283. <value>
  284. <string>%s</string>
  285. </value>
  286. </member>
  287. <member>
  288. <name>dns_record_ttl</name>
  289. <value>
  290. <int>300</int>
  291. </value>
  292. </member>
  293. </struct>
  294. </value>
  295. </param>
  296. </params>
  297. </methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id" "$sub_domain" "$txtval")
  298. export _H1="Content-Type: text/xml"
  299. response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
  300. if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
  301. _err "Error could not create record"
  302. _debug "xml_content" "$xml_content"
  303. _debug "response" "$response"
  304. return 1
  305. fi
  306. return 0
  307. }