Browse Source

Adding support for API v2 (multiple TXT records)

David Kerr 7 years ago
parent
commit
e3ddb677e1
1 changed files with 55 additions and 91 deletions
  1. 55 91
      dnsapi/dns_freedns.sh

+ 55 - 91
dnsapi/dns_freedns.sh

@@ -53,8 +53,9 @@ dns_freedns_add() {
   i="$(_math "$i" - 1)"
   sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
 
-  _debug top_domain "$top_domain"
-  _debug sub_domain "$sub_domain"
+  _debug "top_domain: $top_domain"
+  _debug "sub_domain: $sub_domain"
+
   # Sometimes FreeDNS does not return the subdomain page but rather
   # returns a page regarding becoming a premium member.  This usually
   # happens after a period of inactivity.  Immediately trying again
@@ -63,6 +64,7 @@ dns_freedns_add() {
   attempts=2
   while [ "$attempts" -gt "0" ]; do
     attempts="$(_math "$attempts" - 1)"
+
     htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
     if [ "$?" != "0" ]; then
       if [ "$using_cached_cookies" = "true" ]; then
@@ -71,10 +73,9 @@ dns_freedns_add() {
       fi
       return 1
     fi
-    _debug2 htmlpage "$htmlpage"
 
     subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$top_domain")"
-    _debug2 subdomain_csv "$subdomain_csv"
+    _debug3 "subdomain_csv: $subdomain_csv"
 
     # The above beauty ends with striping out rows that do not have an
     # href to edit.php and do not have the top domain we are looking for.
@@ -85,55 +86,25 @@ dns_freedns_add() {
     lines="$(echo "$subdomain_csv" | wc -l)"
     i=0
     found=0
+    DNSdomainid=""
     while [ "$i" -lt "$lines" ]; do
       i="$(_math "$i" + 1)"
       line="$(echo "$subdomain_csv" | sed -n "${i}p")"
-      _debug2 line "$line"
+      _debug2 "line $line"
       if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then
         # this line will contain DNSdomainid for the top_domain
         DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)"
-        _debug2 DNSdomainid "$DNSdomainid"
+        _debug2 "DNSdomainid: $DNSdomainid"
         found=1
-      else
-        # lines contain DNS records for all subdomains
-        DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-        _debug2 DNSname "$DNSname"
-        DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-        _debug2 DNStype "$DNStype"
-        if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
-          DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
-          # Now get current value for the TXT record.  This method may
-          # not produce accurate results as the value field is truncated
-          # on this webpage. To get full value we would need to load
-          # another page. However we don't really need this so long as
-          # there is only one TXT record for the acme challenge subdomain.
-          DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-          _debug2 DNSvalue "$DNSvalue"
-          if [ $found != 0 ]; then
-            break
-            # we are breaking out of the loop at the first match of DNS name
-            # and DNS type (if we are past finding the domainid). This assumes
-            # that there is only ever one TXT record for the LetsEncrypt/acme
-            # challenge subdomain.  This seems to be a reasonable assumption
-            # as the acme client deletes the TXT record on successful validation.
-          fi
-        else
-          DNSname=""
-          DNStype=""
-        fi
+        break;
       fi
     done
 
-    _debug "DNSname: $DNSname DNStype: $DNStype DNSdomainid: $DNSdomainid DNSdataid: $DNSdataid"
-    _debug "DNSvalue: $DNSvalue"
-
     if [ -z "$DNSdomainid" ]; then
       # If domain ID is empty then something went wrong (top level
       # domain not found at FreeDNS).
       if [ "$attempts" = "0" ]; then
         # exhausted maximum retry attempts
-        _debug "$htmlpage"
-        _debug "$subdomain_csv"
         _err "Domain $top_domain not found at FreeDNS"
         return 1
       fi
@@ -145,33 +116,10 @@ dns_freedns_add() {
     _info "Retry loading subdomain page ($attempts attempts remaining)"
   done
 
-  if [ -z "$DNSdataid" ]; then
-    # If data ID is empty then specific subdomain does not exist yet, need
-    # to create it this should always be the case as the acme client
-    # deletes the entry after domain is validated.
-    _freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
-    return $?
-  else
-    if [ "$txtvalue" = "$DNSvalue" ]; then
-      # if value in TXT record matches value requested then DNS record
-      # does not need to be updated. But...
-      # Testing value match fails.  Website is truncating the value field.
-      # So for now we will always go down the else path.  Though in theory
-      # should never come here anyway as the acme client deletes
-      # the TXT record on successful validation, so we should not even
-      # have found a TXT record !!
-      _info "No update necessary for $fulldomain at FreeDNS"
-      return 0
-    else
-      # Delete the old TXT record (with the wrong value)
-      if _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"; then
-        # And add in new TXT record with the value provided
-        _freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
-      fi
-      return $?
-    fi
-  fi
-  return 0
+  # Add in new TXT record with the value provided
+  _debug "Adding TXT record for $fulldomain, $txtvalue"
+  _freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
+  return $?
 }
 
 #Usage: fulldomain txtvalue
@@ -205,7 +153,7 @@ dns_freedns_rm() {
     fi
 
     subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$fulldomain")"
-    _debug2 subdomain_csv "$subdomain_csv"
+    _debug3 "subdomain_csv: $subdomain_csv"
 
     # The above beauty ends with striping out rows that do not have an
     # href to edit.php and do not have the domain name we are looking for.
@@ -216,35 +164,51 @@ dns_freedns_rm() {
     lines="$(echo "$subdomain_csv" | wc -l)"
     i=0
     found=0
+    DNSdataid=""
     while [ "$i" -lt "$lines" ]; do
       i="$(_math "$i" + 1)"
       line="$(echo "$subdomain_csv" | sed -n "${i}p")"
-      _debug2 line "$line"
+      _debug3 "line: $line"
       DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-      _debug2 DNSname "$DNSname"
-      DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-      _debug2 DNStype "$DNStype"
-      if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
-        DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
-        _debug2 DNSdataid "$DNSdataid"
-        DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
-        _debug2 DNSvalue "$DNSvalue"
-        #     if [ "$DNSvalue" = "$txtvalue" ]; then
-        # Testing value match fails.  Website is truncating the value
-        # field. So for now we will assume that there is only one TXT
-        # field for the sub domain and just delete it. Currently this
-        # is a safe assumption.
-        _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
-        return $?
-        #     fi
+      _debug2 "DNSname: $DNSname"
+      if [ "$DNSname" = "$fulldomain" ]; then
+        DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
+        _debug2 "DNStype: $DNStype"
+        if [ "$DNStype" = "TXT" ]; then
+          DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
+          _debug2 "DNSdataid: $DNSdataid"
+          DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
+          if _startswith "$DNSvalue" "&quot;"; then
+            # remove the quotation from the start
+            DNSvalue="$(echo "$DNSvalue" | cut -c 7-)"
+          fi
+          if _endswith "$DNSvalue" "..."; then
+            # value was truncated, remove the dot dot dot from the end
+            DNSvalue="$(echo "$DNSvalue" | sed 's/...$//')"
+          elif _endswith "$DNSvalue" "&quot;"; then
+            # else remove the closing quotation from the end
+            DNSvalue="$(echo "$DNSvalue" | sed 's/......$//')"
+          fi
+          _debug2 "DNSvalue: $DNSvalue"
+
+          if [ -n "$DNSdataid" ] && _startswith "$txtvalue" "$DNSvalue";  then
+            # Found a match. But note... Website is truncating the
+            # value field so we are only testing that part that is not 
+            # truncated.  This should be accurate enough.
+            _debug "Deleting TXT record for $fulldomain, $txtvalue"
+            _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
+            return $?
+          fi
+
+        fi
       fi
     done
   done
 
   # If we get this far we did not find a match (after two attempts)
   # Not necessarily an error, but log anyway.
-  _debug2 "$subdomain_csv"
-  _info "Cannot delete TXT record for $fulldomain/$txtvalue. Does not exist at FreeDNS"
+  _debug3 "$subdomain_csv"
+  _info "Cannot delete TXT record for $fulldomain, $txtvalue. Does not exist at FreeDNS"
   return 0
 }
 
@@ -272,7 +236,7 @@ _freedns_login() {
 
   # if cookies is not empty then logon successful
   if [ -z "$cookies" ]; then
-    _debug "$htmlpage"
+    _debug3 "htmlpage: $htmlpage"
     _err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
     return 1
   fi
@@ -301,7 +265,7 @@ _freedns_retrieve_subdomain_page() {
     return 1
   fi
 
-  _debug2 "$htmlpage"
+  _debug3 "htmlpage: $htmlpage"
 
   printf "%s" "$htmlpage"
   return 0
@@ -323,17 +287,17 @@ _freedns_add_txt_record() {
     _err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
     return 1
   elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
-    _debug "$htmlpage"
+    _debug3 "htmlpage: $htmlpage"
     _err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
     return 1
   elif _contains "$htmlpage" "security code was incorrect"; then
-    _debug "$htmlpage"
+    _debug3 "htmlpage: $htmlpage"
     _err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
     _err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
     return 1
   fi
 
-  _debug2 "$htmlpage"
+  _debug3 "htmlpage: $htmlpage"
   _info "Added acme challenge TXT record for $fulldomain at FreeDNS"
   return 0
 }
@@ -352,7 +316,7 @@ _freedns_delete_txt_record() {
     _err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
     return 1
   elif ! _contains "$htmlheader" "200 OK"; then
-    _debug "$htmlheader"
+    _debug2 "htmlheader: $htmlheader"
     _err "FreeDNS failed to delete TXT record $data_id"
     return 1
   fi