Browse Source

Merge pull request #669 from Neilpang/dev

Dev
neil 8 years ago
parent
commit
98c8c7ce0d
4 changed files with 202 additions and 40 deletions
  1. 1 0
      README.md
  2. 40 40
      acme.sh
  3. 13 0
      dnsapi/README.md
  4. 148 0
      dnsapi/dns_do.sh

+ 1 - 0
README.md

@@ -293,6 +293,7 @@ You don't have to do anything manually!
 1. Linode.com API
 1. Linode.com API
 1. FreeDNS (https://freedns.afraid.org/)
 1. FreeDNS (https://freedns.afraid.org/)
 1. cyon.ch
 1. cyon.ch
+1. Domain-Offensive/Resellerinterface/Domainrobot API
 
 
 **More APIs coming soon...**
 **More APIs coming soon...**
 
 

+ 40 - 40
acme.sh

@@ -137,11 +137,11 @@ _printargs() {
 
 
 _dlg_versions() {
 _dlg_versions() {
   echo "Diagnosis versions: "
   echo "Diagnosis versions: "
-  echo "openssl:$OPENSSL_BIN"
-  if _exists "$OPENSSL_BIN"; then
-    $OPENSSL_BIN version 2>&1
+  echo "openssl:$ACME_OPENSSL_BIN"
+  if _exists "$ACME_OPENSSL_BIN"; then
+    $ACME_OPENSSL_BIN version 2>&1
   else
   else
-    echo "$OPENSSL_BIN doesn't exists."
+    echo "$ACME_OPENSSL_BIN doesn't exists."
   fi
   fi
 
 
   echo "apache:"
   echo "apache:"
@@ -780,19 +780,19 @@ _base64() {
   [ "" ] #urgly
   [ "" ] #urgly
   if [ "$1" ]; then
   if [ "$1" ]; then
     _debug3 "base64 multiline:'$1'"
     _debug3 "base64 multiline:'$1'"
-    $OPENSSL_BIN base64 -e
+    $ACME_OPENSSL_BIN base64 -e
   else
   else
     _debug3 "base64 single line."
     _debug3 "base64 single line."
-    $OPENSSL_BIN base64 -e | tr -d '\r\n'
+    $ACME_OPENSSL_BIN base64 -e | tr -d '\r\n'
   fi
   fi
 }
 }
 
 
 #Usage: multiline
 #Usage: multiline
 _dbase64() {
 _dbase64() {
   if [ "$1" ]; then
   if [ "$1" ]; then
-    $OPENSSL_BIN base64 -d -A
+    $ACME_OPENSSL_BIN base64 -d -A
   else
   else
-    $OPENSSL_BIN base64 -d
+    $ACME_OPENSSL_BIN base64 -d
   fi
   fi
 }
 }
 
 
@@ -809,9 +809,9 @@ _digest() {
 
 
   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
     if [ "$outputhex" ]; then
     if [ "$outputhex" ]; then
-      $OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
+      $ACME_OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
     else
     else
-      $OPENSSL_BIN dgst -"$alg" -binary | _base64
+      $ACME_OPENSSL_BIN dgst -"$alg" -binary | _base64
     fi
     fi
   else
   else
     _err "$alg is not supported yet"
     _err "$alg is not supported yet"
@@ -834,9 +834,9 @@ _hmac() {
 
 
   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
     if [ "$outputhex" ]; then
     if [ "$outputhex" ]; then
-      ($OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
+      ($ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
     else
     else
-      $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
+      $ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
     fi
     fi
   else
   else
     _err "$alg is not supported yet"
     _err "$alg is not supported yet"
@@ -855,7 +855,7 @@ _sign() {
     return 1
     return 1
   fi
   fi
 
 
-  _sign_openssl="$OPENSSL_BIN   dgst -sign $keyfile "
+  _sign_openssl="$ACME_OPENSSL_BIN   dgst -sign $keyfile "
   if [ "$alg" = "sha256" ]; then
   if [ "$alg" = "sha256" ]; then
     _sign_openssl="$_sign_openssl -$alg"
     _sign_openssl="$_sign_openssl -$alg"
   else
   else
@@ -866,7 +866,7 @@ _sign() {
   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
     $_sign_openssl | _base64
     $_sign_openssl | _base64
   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
-    if ! _signedECText="$($_sign_openssl | $OPENSSL_BIN asn1parse -inform DER)"; then
+    if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then
       _err "Sign failed: $_sign_openssl"
       _err "Sign failed: $_sign_openssl"
       _err "Key file: $keyfile"
       _err "Key file: $keyfile"
       _err "Key content:$(wc -l <"$keyfile") lises"
       _err "Key content:$(wc -l <"$keyfile") lises"
@@ -929,10 +929,10 @@ _createkey() {
 
 
   if _isEccKey "$length"; then
   if _isEccKey "$length"; then
     _debug "Using ec name: $eccname"
     _debug "Using ec name: $eccname"
-    $OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
+    $ACME_OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
   else
   else
     _debug "Using RSA: $length"
     _debug "Using RSA: $length"
-    $OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f"
+    $ACME_OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f"
   fi
   fi
 
 
   if [ "$?" != "0" ]; then
   if [ "$?" != "0" ]; then
@@ -1019,9 +1019,9 @@ _createcsr() {
   _csr_cn="$(_idn "$domain")"
   _csr_cn="$(_idn "$domain")"
   _debug2 _csr_cn "$_csr_cn"
   _debug2 _csr_cn "$_csr_cn"
   if _contains "$(uname -a)" "MINGW"; then
   if _contains "$(uname -a)" "MINGW"; then
-    $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
+    $ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
   else
   else
-    $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
+    $ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
   fi
   fi
 }
 }
 
 
@@ -1033,7 +1033,7 @@ _signcsr() {
   cert="$4"
   cert="$4"
   _debug "_signcsr"
   _debug "_signcsr"
 
 
-  _msg="$($OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
+  _msg="$($ACME_OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
   _ret="$?"
   _ret="$?"
   _debug "$_msg"
   _debug "$_msg"
   return $_ret
   return $_ret
@@ -1046,7 +1046,7 @@ _readSubjectFromCSR() {
     _usage "_readSubjectFromCSR mycsr.csr"
     _usage "_readSubjectFromCSR mycsr.csr"
     return 1
     return 1
   fi
   fi
-  $OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
+  $ACME_OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
 }
 }
 
 
 #_csrfile
 #_csrfile
@@ -1061,7 +1061,7 @@ _readSubjectAltNamesFromCSR() {
   _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
   _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
   _debug _csrsubj "$_csrsubj"
   _debug _csrsubj "$_csrsubj"
 
 
-  _dnsAltnames="$($OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
+  _dnsAltnames="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
   _debug _dnsAltnames "$_dnsAltnames"
   _debug _dnsAltnames "$_dnsAltnames"
 
 
   if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
   if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
@@ -1082,7 +1082,7 @@ _readKeyLengthFromCSR() {
     return 1
     return 1
   fi
   fi
 
 
-  _outcsr="$($OPENSSL_BIN req -noout -text -in "$_csrfile")"
+  _outcsr="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile")"
   if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
   if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
     _debug "ECC CSR"
     _debug "ECC CSR"
     echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
     echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
@@ -1136,9 +1136,9 @@ toPkcs() {
   _initpath "$domain" "$_isEcc"
   _initpath "$domain" "$_isEcc"
 
 
   if [ "$pfxPassword" ]; then
   if [ "$pfxPassword" ]; then
-    $OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
+    $ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
   else
   else
-    $OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
+    $ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
   fi
   fi
 
 
   if [ "$?" = "0" ]; then
   if [ "$?" = "0" ]; then
@@ -1300,7 +1300,7 @@ _calcjwk() {
 
 
   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
     _debug "RSA key"
     _debug "RSA key"
-    pub_exp=$($OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
+    pub_exp=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
     if [ "${#pub_exp}" = "5" ]; then
     if [ "${#pub_exp}" = "5" ]; then
       pub_exp=0$pub_exp
       pub_exp=0$pub_exp
     fi
     fi
@@ -1309,7 +1309,7 @@ _calcjwk() {
     e=$(echo "$pub_exp" | _h2b | _base64)
     e=$(echo "$pub_exp" | _h2b | _base64)
     _debug3 e "$e"
     _debug3 e "$e"
 
 
-    modulus=$($OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
+    modulus=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
     _debug3 modulus "$modulus"
     _debug3 modulus "$modulus"
     n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
     n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
     _debug3 n "$n"
     _debug3 n "$n"
@@ -1322,12 +1322,12 @@ _calcjwk() {
     JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}'
     JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}'
   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
     _debug "EC key"
     _debug "EC key"
-    crv="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
+    crv="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
     _debug3 crv "$crv"
     _debug3 crv "$crv"
 
 
     if [ -z "$crv" ]; then
     if [ -z "$crv" ]; then
       _debug "Let's try ASN1 OID"
       _debug "Let's try ASN1 OID"
-      crv_oid="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
+      crv_oid="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
       _debug3 crv_oid "$crv_oid"
       _debug3 crv_oid "$crv_oid"
       case "${crv_oid}" in
       case "${crv_oid}" in
         "prime256v1")
         "prime256v1")
@@ -1347,15 +1347,15 @@ _calcjwk() {
       _debug3 crv "$crv"
       _debug3 crv "$crv"
     fi
     fi
 
 
-    pubi="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
+    pubi="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
     pubi=$(_math "$pubi" + 1)
     pubi=$(_math "$pubi" + 1)
     _debug3 pubi "$pubi"
     _debug3 pubi "$pubi"
 
 
-    pubj="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
+    pubj="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
     pubj=$(_math "$pubj" - 1)
     pubj=$(_math "$pubj" - 1)
     _debug3 pubj "$pubj"
     _debug3 pubj "$pubj"
 
 
-    pubtext="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
+    pubtext="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
     _debug3 pubtext "$pubtext"
     _debug3 pubtext "$pubtext"
 
 
     xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
     xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
@@ -1964,7 +1964,7 @@ _starttlsserver() {
     return 1
     return 1
   fi
   fi
 
 
-  __S_OPENSSL="$OPENSSL_BIN s_server -cert $TLS_CERT  -key $TLS_KEY "
+  __S_OPENSSL="$ACME_OPENSSL_BIN s_server -cert $TLS_CERT  -key $TLS_KEY "
   if [ "$opaddr" ]; then
   if [ "$opaddr" ]; then
     __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
     __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
   else
   else
@@ -2143,8 +2143,8 @@ _initpath() {
     CERT_HOME="$_DEFAULT_CERT_HOME"
     CERT_HOME="$_DEFAULT_CERT_HOME"
   fi
   fi
 
 
-  if [ -z "$OPENSSL_BIN" ]; then
-    OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
+  if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ] ; then
+    ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
   fi
   fi
 
 
   if [ -z "$1" ]; then
   if [ -z "$1" ]; then
@@ -4368,8 +4368,8 @@ _precheck() {
     fi
     fi
   fi
   fi
 
 
-  if ! _exists "$OPENSSL_BIN"; then
-    _err "Please install openssl first. OPENSSL_BIN=$OPENSSL_BIN"
+  if ! _exists "$ACME_OPENSSL_BIN"; then
+    _err "Please install openssl first. ACME_OPENSSL_BIN=$ACME_OPENSSL_BIN"
     _err "We need openssl to generate keys."
     _err "We need openssl to generate keys."
     return 1
     return 1
   fi
   fi
@@ -4791,9 +4791,9 @@ _processAccountConf() {
   fi
   fi
 
 
   if [ "$_openssl_bin" ]; then
   if [ "$_openssl_bin" ]; then
-    _saveaccountconf "OPENSSL_BIN" "$_openssl_bin"
-  elif [ "$OPENSSL_BIN" ] && [ "$OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
-    _saveaccountconf "OPENSSL_BIN" "$OPENSSL_BIN"
+    _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin"
+  elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
+    _saveaccountconf "ACME_OPENSSL_BIN" "$ACME_OPENSSL_BIN"
   fi
   fi
 
 
   if [ "$_auto_upgrade" ]; then
   if [ "$_auto_upgrade" ]; then
@@ -5219,7 +5219,7 @@ _process() {
         ;;
         ;;
       --openssl-bin)
       --openssl-bin)
         _openssl_bin="$2"
         _openssl_bin="$2"
-        OPENSSL_BIN="$_openssl_bin"
+        ACME_OPENSSL_BIN="$_openssl_bin"
         ;;
         ;;
       *)
       *)
         _err "Unknown parameter : $1"
         _err "Unknown parameter : $1"

+ 13 - 0
dnsapi/README.md

@@ -323,6 +323,19 @@ acme.sh --issue --dns dns_cyon -d example.com -d www.example.com
 
 
 The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
 The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
 
 
+## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API
+
+You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`:
+```
+export DO_PID="KD-1234567"
+export DO_PW="cdfkjl3n2"
+```
+
+Ok, let's issue a cert now:
+```
+acme.sh --issue --dns dns_do -d example.com -d www.example.com
+```
+
 # Use custom API
 # Use custom API
 
 
 If your API is not supported yet, you can write your own DNS API.
 If your API is not supported yet, you can write your own DNS API.

+ 148 - 0
dnsapi/dns_do.sh

@@ -0,0 +1,148 @@
+#!/usr/bin/env sh
+
+# DNS API for Domain-Offensive / Resellerinterface / Domainrobot
+
+# Report bugs at https://github.com/seidler2547/acme.sh/issues
+
+# set these environment variables to match your customer ID and password:
+# DO_PID="KD-1234567"
+# DO_PW="cdfkjl3n2"
+
+DO_URL="https://soap.resellerinterface.de/"
+
+########  Public functions #####################
+
+#Usage: dns_myapi_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_do_add() {
+  fulldomain=$1
+  txtvalue=$2
+  if _dns_do_authenticate; then
+    _info "Adding TXT record to ${_domain} as ${fulldomain}"
+    _dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300
+    if _contains "${response}" '>success<'; then
+      return 0
+    fi
+    _err "Could not create resource record, check logs"
+  fi
+  return 1
+}
+
+#fulldomain
+dns_do_rm() {
+  fulldomain=$1
+  if _dns_do_authenticate; then
+    if _dns_do_list_rrs; then
+      _dns_do_had_error=0
+      for _rrid in ${_rr_list}; do
+        _info "Deleting resource record $_rrid for $_domain"
+        _dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}"
+        if ! _contains "${response}" '>success<'; then
+          _dns_do_had_error=1
+          _err "Could not delete resource record for ${_domain}, id ${_rrid}"
+        fi
+      done
+      return $_dns_do_had_error
+    fi
+  fi
+  return 1
+}
+
+####################  Private functions below ##################################
+_dns_do_authenticate() {
+  _info "Authenticating as ${DO_PID}"
+  _dns_do_soap authPartner partner "${DO_PID}" password "${DO_PW}"
+  if _contains "${response}" '>success<'; then
+    _get_root "$fulldomain"
+    _debug "_domain $_domain"
+    return 0
+  else
+    _err "Authentication failed, are DO_PID and DO_PW set correctly?"
+  fi
+  return 1
+}
+
+_dns_do_list_rrs() {
+  _dns_do_soap getRRList origin "${_domain}"
+  if ! _contains "${response}" 'SOAP-ENC:Array'; then
+    _err "getRRList origin ${_domain} failed"
+    return 1
+  fi
+  _rr_list="$(echo "${response}" \
+    | tr -d "\n\r\t" \
+    | sed -e 's/<item xsi:type="ns2:Map">/\n/g' \
+    | grep ">$(_regexcape "$fulldomain")</value>" \
+    | sed -e 's/<\/item>/\n/g' \
+    | grep '>id</key><value' \
+    | _egrep_o '>[0-9]{1,16}<' \
+    | tr -d '><')"
+  [ "${_rr_list}" ]
+}
+
+_dns_do_soap() {
+  func="$1"
+  shift
+  # put the parameters to xml
+  body="<tns:${func} xmlns:tns=\"${DO_URL}\">"
+  while [ "$1" ]; do
+    _k="$1"
+    shift
+    _v="$1"
+    shift
+    body="$body<$_k>$_v</$_k>"
+  done
+  body="$body</tns:${func}>"
+  _debug2 "SOAP request ${body}"
+
+  # build SOAP XML
+  _xml='<?xml version="1.0" encoding="UTF-8"?>
+<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
+  <env:Body>'"$body"'</env:Body>
+</env:Envelope>'
+
+  # set SOAP headers
+  export _H1="SOAPAction: ${DO_URL}#${func}"
+
+  if ! response="$(_post "${_xml}" "${DO_URL}")"; then
+    _err "Error <$1>"
+    return 1
+  fi
+  _debug2 "SOAP response $response"
+
+  # retrieve cookie header
+  _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)"
+  export _H2
+
+  return 0
+}
+
+_get_root() {
+  domain=$1
+  i=1
+
+  _dns_do_soap getDomainList
+  _all_domains="$(echo "${response}" \
+    | tr -d "\n\r\t " \
+    | _egrep_o 'domain</key><value[^>]+>[^<]+' \
+    | sed -e 's/^domain<\/key><value[^>]*>//g')"
+
+  while true; do
+    h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+    if [ -z "$h" ]; then
+      return 1
+    fi
+
+    if _contains "${_all_domains}" "^$(_regexcape "$h")\$"; then
+      _domain="$h"
+      return 0
+    fi
+
+    i=$(_math $i + 1)
+  done
+  _debug "$domain not found"
+
+  return 1
+}
+
+_regexcape() {
+  echo "$1" | sed -e 's/\([]\.$*^[]\)/\\\1/g'
+}