You need to sign in or sign up before continuing.
Commit e3ddb677 authored by David Kerr's avatar David Kerr
Browse files

Adding support for API v2 (multiple TXT records)

parent 716f7277
...@@ -53,8 +53,9 @@ dns_freedns_add() { ...@@ -53,8 +53,9 @@ dns_freedns_add() {
i="$(_math "$i" - 1)" i="$(_math "$i" - 1)"
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")" sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
_debug top_domain "$top_domain" _debug "top_domain: $top_domain"
_debug sub_domain "$sub_domain" _debug "sub_domain: $sub_domain"
# Sometimes FreeDNS does not return the subdomain page but rather # Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually # returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again # happens after a period of inactivity. Immediately trying again
...@@ -63,6 +64,7 @@ dns_freedns_add() { ...@@ -63,6 +64,7 @@ dns_freedns_add() {
attempts=2 attempts=2
while [ "$attempts" -gt "0" ]; do while [ "$attempts" -gt "0" ]; do
attempts="$(_math "$attempts" - 1)" attempts="$(_math "$attempts" - 1)"
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")" htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
if [ "$using_cached_cookies" = "true" ]; then if [ "$using_cached_cookies" = "true" ]; then
...@@ -71,10 +73,9 @@ dns_freedns_add() { ...@@ -71,10 +73,9 @@ dns_freedns_add() {
fi fi
return 1 return 1
fi 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")" 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 # 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. # href to edit.php and do not have the top domain we are looking for.
...@@ -85,55 +86,25 @@ dns_freedns_add() { ...@@ -85,55 +86,25 @@ dns_freedns_add() {
lines="$(echo "$subdomain_csv" | wc -l)" lines="$(echo "$subdomain_csv" | wc -l)"
i=0 i=0
found=0 found=0
DNSdomainid=""
while [ "$i" -lt "$lines" ]; do while [ "$i" -lt "$lines" ]; do
i="$(_math "$i" + 1)" i="$(_math "$i" + 1)"
line="$(echo "$subdomain_csv" | sed -n "${i}p")" line="$(echo "$subdomain_csv" | sed -n "${i}p")"
_debug2 line "$line" _debug2 "line $line"
if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then
# this line will contain DNSdomainid for the top_domain # 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)" DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)"
_debug2 DNSdomainid "$DNSdomainid" _debug2 "DNSdomainid: $DNSdomainid"
found=1 found=1
else break;
# 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
fi fi
done done
_debug "DNSname: $DNSname DNStype: $DNStype DNSdomainid: $DNSdomainid DNSdataid: $DNSdataid"
_debug "DNSvalue: $DNSvalue"
if [ -z "$DNSdomainid" ]; then if [ -z "$DNSdomainid" ]; then
# If domain ID is empty then something went wrong (top level # If domain ID is empty then something went wrong (top level
# domain not found at FreeDNS). # domain not found at FreeDNS).
if [ "$attempts" = "0" ]; then if [ "$attempts" = "0" ]; then
# exhausted maximum retry attempts # exhausted maximum retry attempts
_debug "$htmlpage"
_debug "$subdomain_csv"
_err "Domain $top_domain not found at FreeDNS" _err "Domain $top_domain not found at FreeDNS"
return 1 return 1
fi fi
...@@ -145,33 +116,10 @@ dns_freedns_add() { ...@@ -145,33 +116,10 @@ dns_freedns_add() {
_info "Retry loading subdomain page ($attempts attempts remaining)" _info "Retry loading subdomain page ($attempts attempts remaining)"
done done
if [ -z "$DNSdataid" ]; then # Add in new TXT record with the value provided
# If data ID is empty then specific subdomain does not exist yet, need _debug "Adding TXT record for $fulldomain, $txtvalue"
# to create it this should always be the case as the acme client _freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
# deletes the entry after domain is validated. return $?
_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
} }
#Usage: fulldomain txtvalue #Usage: fulldomain txtvalue
...@@ -205,7 +153,7 @@ dns_freedns_rm() { ...@@ -205,7 +153,7 @@ dns_freedns_rm() {
fi 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")" 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 # 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. # href to edit.php and do not have the domain name we are looking for.
...@@ -216,35 +164,51 @@ dns_freedns_rm() { ...@@ -216,35 +164,51 @@ dns_freedns_rm() {
lines="$(echo "$subdomain_csv" | wc -l)" lines="$(echo "$subdomain_csv" | wc -l)"
i=0 i=0
found=0 found=0
DNSdataid=""
while [ "$i" -lt "$lines" ]; do while [ "$i" -lt "$lines" ]; do
i="$(_math "$i" + 1)" i="$(_math "$i" + 1)"
line="$(echo "$subdomain_csv" | sed -n "${i}p")" 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)" DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_debug2 DNSname "$DNSname" _debug2 "DNSname: $DNSname"
DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)" if [ "$DNSname" = "$fulldomain" ]; then
_debug2 DNStype "$DNStype" DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then _debug2 "DNStype: $DNStype"
DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)" if [ "$DNStype" = "TXT" ]; then
_debug2 DNSdataid "$DNSdataid" DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)" _debug2 "DNSdataid: $DNSdataid"
_debug2 DNSvalue "$DNSvalue" DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
# if [ "$DNSvalue" = "$txtvalue" ]; then if _startswith "$DNSvalue" "&quot;"; then
# Testing value match fails. Website is truncating the value # remove the quotation from the start
# field. So for now we will assume that there is only one TXT DNSvalue="$(echo "$DNSvalue" | cut -c 7-)"
# field for the sub domain and just delete it. Currently this fi
# is a safe assumption. if _endswith "$DNSvalue" "..."; then
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid" # value was truncated, remove the dot dot dot from the end
return $? DNSvalue="$(echo "$DNSvalue" | sed 's/...$//')"
# fi 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 fi
done done
done done
# If we get this far we did not find a match (after two attempts) # If we get this far we did not find a match (after two attempts)
# Not necessarily an error, but log anyway. # Not necessarily an error, but log anyway.
_debug2 "$subdomain_csv" _debug3 "$subdomain_csv"
_info "Cannot delete TXT record for $fulldomain/$txtvalue. Does not exist at FreeDNS" _info "Cannot delete TXT record for $fulldomain, $txtvalue. Does not exist at FreeDNS"
return 0 return 0
} }
...@@ -272,7 +236,7 @@ _freedns_login() { ...@@ -272,7 +236,7 @@ _freedns_login() {
# if cookies is not empty then logon successful # if cookies is not empty then logon successful
if [ -z "$cookies" ]; then if [ -z "$cookies" ]; then
_debug "$htmlpage" _debug3 "htmlpage: $htmlpage"
_err "FreeDNS login failed for user $username. Check $HTTP_HEADER file" _err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
return 1 return 1
fi fi
...@@ -301,7 +265,7 @@ _freedns_retrieve_subdomain_page() { ...@@ -301,7 +265,7 @@ _freedns_retrieve_subdomain_page() {
return 1 return 1
fi fi
_debug2 "$htmlpage" _debug3 "htmlpage: $htmlpage"
printf "%s" "$htmlpage" printf "%s" "$htmlpage"
return 0 return 0
...@@ -323,17 +287,17 @@ _freedns_add_txt_record() { ...@@ -323,17 +287,17 @@ _freedns_add_txt_record() {
_err "FreeDNS failed to add TXT record for $subdomain bad RC from _post" _err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
return 1 return 1
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then 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" _err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
return 1 return 1
elif _contains "$htmlpage" "security code was incorrect"; then 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 "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" _err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
return 1 return 1
fi fi
_debug2 "$htmlpage" _debug3 "htmlpage: $htmlpage"
_info "Added acme challenge TXT record for $fulldomain at FreeDNS" _info "Added acme challenge TXT record for $fulldomain at FreeDNS"
return 0 return 0
} }
...@@ -352,7 +316,7 @@ _freedns_delete_txt_record() { ...@@ -352,7 +316,7 @@ _freedns_delete_txt_record() {
_err "FreeDNS failed to delete TXT record for $data_id bad RC from _get" _err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
return 1 return 1
elif ! _contains "$htmlheader" "200 OK"; then elif ! _contains "$htmlheader" "200 OK"; then
_debug "$htmlheader" _debug2 "htmlheader: $htmlheader"
_err "FreeDNS failed to delete TXT record $data_id" _err "FreeDNS failed to delete TXT record $data_id"
return 1 return 1
fi fi
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment