#!/usr/bin/env sh #This file name is "dns_freedns.sh" #So, here must be a method dns_freedns_add() #Which will be called by acme.sh to add the txt record to your api system. #returns 0 means success, otherwise error. # #Author: David Kerr #Report Bugs here: https://github.com/dkerr64/acme.sh # ######## Public functions ##################### # Export FreeDNS userid and password in following variables... # FREEDNS_User=username # FREEDNS_Password=password # login cookie is saved in acme account config file so userid / pw # need to be set only when changed. #Usage: dns_freedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_freedns_add() { fulldomain="$1" txtvalue="$2" _info "Add TXT record using FreeDNS" _debug "fulldomain: $fulldomain" _debug "txtvalue: $txtvalue" if [ -z "$FREEDNS_User" ] || [ -z "$FREEDNS_Password" ]; then FREEDNS_User="" FREEDNS_Password="" if [ -z "$FREEDNS_COOKIE" ]; then _err "You did not specify the FreeDNS username and password yet." _err "Please export as FREEDNS_User / FREEDNS_Password and try again." return 1 fi using_cached_cookies="true" else FREEDNS_COOKIE="$(_freedns_login "$FREEDNS_User" "$FREEDNS_Password")" if [ -z "$FREEDNS_COOKIE" ]; then return 1 fi using_cached_cookies="false" fi _debug "FreeDNS login cookies: $FREEDNS_COOKIE (cached = $using_cached_cookies)" _saveaccountconf FREEDNS_COOKIE "$FREEDNS_COOKIE" # split our full domain name into two parts... # top_domain is everything after the first dot # sub_domain is the element before the first dot top_domain="$(echo "$fulldomain" | cut -d. -f 2-)" sub_domain="$(echo "$fulldomain" | cut -d. -f 1)" DNSdomainid= while [ -z "$DNSdomainid" ]; do _debug "top_domain: $top_domain" _debug "sub_domain: $sub_domain" found_domainid="$(_freedns_find_domain "$FREEDNS_COOKIE" "$top_domain")" if [ "$?" != "0" ]; then # Check if there is a dot in the top_domain # If not, we can't split any more and should assume the domain doesn't exist if ! echo "$top_domain" | grep -qF '.'; then _info "Domain $top_domain not found at FreeDNS. All domain parts exhausted" _err "Domain $fulldomain not found at FreeDNS" return 1 fi # Move the subdomain part from top_domain to the bottom of top_domain # e.g a | b.c.d becomes a.b | c.d where the pipe represents the split _info "Domain $top_domain not found at FreeDNS. Splitting again" sub_domain="$sub_domain.$(echo "$top_domain" | cut -d. -f 1)" top_domain="$(echo "$top_domain" | cut -d. -f 2-)" # Try again with the newly split domain continue else # Domain found, carry on! DNSdomainid="$found_domainid" _info "Domain $top_domain found at FreeDNS!" _debug2 "DNSdomainid for $top_domain: $DNSdomainid" break fi done # 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 #Remove the txt record after validation. dns_freedns_rm() { fulldomain="$1" txtvalue="$2" _info "Delete TXT record using FreeDNS" _debug "fulldomain: $fulldomain" _debug "txtvalue: $txtvalue" # Need to read cookie from conf file again in case new value set # during login to FreeDNS when TXT record was created. # acme.sh does not have a _readaccountconf() function FREEDNS_COOKIE="$(_read_conf "$ACCOUNT_CONF_PATH" "FREEDNS_COOKIE")" _debug "FreeDNS login cookies: $FREEDNS_COOKIE" # 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 # returns the correct subdomain page. So, we will try twice to # load the page and obtain our TXT record. attempts=2 while [ "$attempts" -gt "0" ]; do attempts="$(_math "$attempts" - 1)" htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")" if [ "$?" != "0" ]; then return 1 fi subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '