ddns-scripts: multiple fixes 7115/head
authorDirk Brenken <dev@brenken.org>
Thu, 13 Sep 2018 12:45:44 +0000 (14:45 +0200)
committerDirk Brenken <dev@brenken.org>
Fri, 28 Sep 2018 05:41:52 +0000 (07:41 +0200)
* replace shell based urlencoder with an awk variant
* fix write_log function/syslog output in case of an error
* protect answer string with double quotes in update_route53
* remove bogus set/IFS options in update_route53
* clean-up update_route53 a little bit

This patchset finally fix #6977

Many thanks to @mark0n & @a-bali for testing & debugging

Signed-off-by: Dirk Brenken <dev@brenken.org>
net/ddns-scripts/Makefile
net/ddns-scripts/files/dynamic_dns_functions.sh
net/ddns-scripts/files/update_route53_v1.sh

index d72cab2607dc025241f45c3b9bcaa377ffdce82c..aa57c4fcb9fe74e63cda4782bfb1be54b371010b 100755 (executable)
@@ -12,7 +12,7 @@ PKG_NAME:=ddns-scripts
 PKG_VERSION:=2.7.8
 # Release == build
 # increase on changes of services files or tld_names.dat
-PKG_RELEASE:=4
+PKG_RELEASE:=5
 
 PKG_LICENSE:=GPL-2.0
 PKG_MAINTAINER:=
index 31b6f1974e92c292d7ff05490cdc781875be5c48..6583344808f9556eb9da3e013153dfbc97fc9898 100755 (executable)
@@ -21,7 +21,7 @@
 . /lib/functions/network.sh
 
 # GLOBAL VARIABLES #
-VERSION="2.7.8-4"
+VERSION="2.7.8-5"
 SECTION_ID=""          # hold config's section name
 VERBOSE=0              # default mode is log to console, but easily changed with parameter
 MYPROG=$(basename $0)  # my program call name
@@ -282,11 +282,11 @@ write_log() {
        [ $__LEVEL -eq 7 ] && return    # no syslog for debug messages
        __CMD=$(echo -e "$__CMD" | tr -d '\n' | tr '\t' '     ')        # remove \n \t chars
        [ $__EXIT  -eq 1 ] && {
-               $__CMD          # force syslog before exit
+               eval "$__CMD"   # force syslog before exit
                exit 1
        }
        [ $use_syslog -eq 0 ] && return
-       [ $((use_syslog + __LEVEL)) -le 7 ] && $__CMD
+       [ $((use_syslog + __LEVEL)) -le 7 ] && eval "$__CMD"
 
        return
 }
@@ -301,32 +301,12 @@ write_log() {
 urlencode() {
        # $1    Name of Variable to store encoded string to
        # $2    string to encode
-       local __STR __LEN __CHAR __OUT
-       local __ENC=""
-       local __POS=1
+       local __ENC
 
        [ $# -ne 2 ] && write_log 12 "Error calling 'urlencode()' - wrong number of parameters"
 
-       __STR="$2"              # read string to encode
-       __LEN=${#__STR}         # get string length
-
-       while [ $__POS -le $__LEN ]; do
-               # read one chat of the string
-               __CHAR=$(expr substr "$__STR" $__POS 1)
-
-               case "$__CHAR" in
-                       [-_.~a-zA-Z0-9] )
-                               # standard char
-                               __OUT="${__CHAR}"
-                               ;;
-                       * )
-                               # special char get %hex code
-                              __OUT=$(printf '%%%02x' "'$__CHAR" )
-                               ;;
-               esac
-               __ENC="${__ENC}${__OUT}"        # append to encoded string
-               __POS=$(( $__POS + 1 ))         # increment position
-       done
+       __ENC="$(awk -v str="$2" 'BEGIN{ORS="";for(i=32;i<=127;i++)lookup[sprintf("%c",i)]=i
+               for(k=1;k<=length(str);++k){enc=substr(str,k,1);if(enc!~"[-_.~a-zA-Z0-9]")enc=sprintf("%%%02x", lookup[enc]);print enc}}')"
 
        eval "$1=\"$__ENC\""    # transfer back to variable
        return 0
index 6b9b029e0a775edc11cbf48dad128671ca2588e2..a7d4dfb64ae6aaafefb3bfceeca2113f96ea8e1e 100644 (file)
@@ -1,46 +1,44 @@
 #!/bin/sh
-#.Distributed under the terms of the GNU General Public License (GPL) version 2.0
-#.based on Yuval Adam's route53.sh found at https://github.com/yuvadm/route53-ddns/blob/master/route53.sh
-#.2017 Max Berger <max at berger dot name>
-[ -z "$CURL_SSL" ] && write_log 14 "Amazon AWS Route53 communication require cURL with SSL support. Please install"
-[ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing key as 'username'"
-[ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing secret as 'password'"
-[ -z "$domain" ] && write_log 14 "Service section not configured correctly! Missing zone id as 'domain'"
+# Distributed under the terms of the GNU General Public License (GPL) version 2.0
+# based on Yuval Adam's route53.sh found at https://github.com/yuvadm/route53-ddns/blob/master/route53.sh
+# 2017 Max Berger <max at berger dot name>
 
-set -euo pipefail
-IFS=$'\n\t'
+[ -z "${CURL_SSL}" ] && write_log 14 "Amazon AWS Route53 communication require cURL with SSL support. Please install"
+[ -z "{$username}" ] && write_log 14 "Service section not configured correctly! Missing key as 'username'"
+[ -z "${password}" ] && write_log 14 "Service section not configured correctly! Missing secret as 'password'"
+[ -z "${domain}" ] && write_log 14 "Service section not configured correctly! Missing zone id as 'domain'"
 
 ENDPOINT="route53.amazonaws.com"
 RECORD_TTL=300
-RECORD_NAME="$lookup_host".
-[ $use_ipv6 -eq 0 ] && RECORD_TYPE="A"
-[ $use_ipv6 -eq 1 ] && RECORD_TYPE="AAAA"
-RECORD_VALUE="$LOCAL_IP"
-HOSTED_ZONE_ID="$domain"
+RECORD_NAME="${lookup_host}."
+[ ${use_ipv6} -eq 0 ] && RECORD_TYPE="A"
+[ ${use_ipv6} -eq 1 ] && RECORD_TYPE="AAAA"
+RECORD_VALUE="${LOCAL_IP}"
+HOSTED_ZONE_ID="${domain}"
 API_PATH="/2013-04-01/hostedzone/${HOSTED_ZONE_ID}/rrset/"
 
-AWS_ACCESS_KEY_ID="$username"
-AWS_SECRET_ACCESS_KEY="$password"
+AWS_ACCESS_KEY_ID="${username}"
+AWS_SECRET_ACCESS_KEY="${password}"
 AWS_REGION='us-east-1'
 AWS_SERVICE='route53'
 
 hash() {
-    msg=$1
-    echo -en "$msg" | openssl dgst -sha256 | sed 's/^.* //'
+    msg="$1"
+    echo -en "${msg}" | openssl dgst -sha256 | sed 's/^.* //'
 }
 
 sign_plain() {
     # Sign message using a plaintext key
-    key=$1
-    msg=$2
-    echo -en "$msg" | openssl dgst -hex -sha256 -hmac "$key" | sed 's/^.* //'
+    key="$1"
+    msg="$2"
+    echo -en "${msg}" | openssl dgst -hex -sha256 -hmac "${key}" | sed 's/^.* //'
 }
 
 sign() {
     # Sign message using a hex formatted key
-    key=$1
-    msg=$2
-    echo -en "$msg" | openssl dgst -hex -sha256 -mac HMAC -macopt "hexkey:${key}" | sed 's/^.* //'
+    key="$1"
+    msg="$2"
+    echo -en "${msg}" | openssl dgst -hex -sha256 -mac HMAC -macopt "hexkey:${key}" | sed 's/^.* //'
 }
 
 request_body="<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
@@ -64,34 +62,34 @@ request_body="<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
 </ChangeBatch> \
 </ChangeResourceRecordSetsRequest>"
 
-fulldate=$(date --utc +%Y%m%dT%H%M%SZ)
-shortdate=$(date --utc +%Y%m%d)
+fulldate="$(date --utc +%Y%m%dT%H%M%SZ)"
+shortdate="$(date --utc +%Y%m%d)"
 signed_headers="host;x-amz-date"
-request_hash=$(hash "$request_body")
+request_hash="$(hash "${request_body}")"
 canonical_request="POST\n${API_PATH}\n\nhost:route53.amazonaws.com\nx-amz-date:${fulldate}\n\n${signed_headers}\n${request_hash}"
 
-date_key=$(sign_plain "AWS4${AWS_SECRET_ACCESS_KEY}" "${shortdate}")
-region_key=$(sign "$date_key" $AWS_REGION)
-service_key=$(sign "$region_key" $AWS_SERVICE)
-signing_key=$(sign "$service_key" aws4_request)
+date_key="$(sign_plain "AWS4${AWS_SECRET_ACCESS_KEY}" "${shortdate}")"
+region_key="$(sign "${date_key}" ${AWS_REGION})"
+service_key="$(sign "${region_key}" ${AWS_SERVICE})"
+signing_key="$(sign "${service_key}" aws4_request)"
 
 credential="${shortdate}/${AWS_REGION}/${AWS_SERVICE}/aws4_request"
-sigmsg="AWS4-HMAC-SHA256\n${fulldate}\n${credential}\n$(hash "$canonical_request")"
+sigmsg="AWS4-HMAC-SHA256\n${fulldate}\n${credential}\n$(hash "${canonical_request}")"
 
-signature=$(sign "$signing_key" "$sigmsg")
+signature="$(sign "${signing_key}" "${sigmsg}")"
 
 authorization="AWS4-HMAC-SHA256 Credential=${AWS_ACCESS_KEY_ID}/${credential}, SignedHeaders=${signed_headers}, Signature=${signature}"
 
-ANSWER=$(curl \
+ANSWER="$(curl \
     -X "POST" \
     -H "Host: route53.amazonaws.com" \
     -H "X-Amz-Date: ${fulldate}" \
     -H "Authorization: ${authorization}" \
     -H "Content-Type: text/xml" \
     -d "$request_body" \
-    "https://${ENDPOINT}${API_PATH}")
+    "https://${ENDPOINT}${API_PATH}")"
 write_log 7 "${ANSWER}"
 
-echo ${ANSWER} | grep Error >/dev/null && return 1
-echo ${ANSWER} | grep ChangeInfo >/dev/null && return 0
+echo "${ANSWER}" | grep -F "Error" >/dev/null && return 1
+echo "${ANSWER}" | grep -F "ChangeInfo" >/dev/null && return 0
 return 2