#!/bin/sh if test $(uci get autoupdater.settings.enabled) != 1; then echo "autoupdater is disabled" exit 0 fi BRANCH=$(uci get autoupdater.settings.branch) PROBABILITY=$(uci get autoupdater.${BRANCH}.probability) if test "a$1" != "a-f"; then # get one random byte from /dev/urandom, convert it to decimal and check # against update_probability*255 hexdump -n1 -e '/1 "%d"' /dev/urandom | awk "{exit \$1 > $PROBABILITY * 255}" if test $? -ne 0; then echo "No autoupdate this time. Use -f to override" exit 0 fi fi BASE=$(uci get autoupdater.${BRANCH}.url) PUBKEYS=$(uci get autoupdater.${BRANCH}.pubkey) GOOD_SIGNATURES=$(uci get autoupdater.${BRANCH}.good_signatures) VERSION_FILE=/lib/gluon/release newer_than() { local old="$(printf '%s\n%s\n' "$1" "$2" | sort -n | head -n 1)" test "$1" != "$old" } cleanup() { rm -f $manifest rm -f $fw_image rm -f $manifest_upper rm -f $manifest_lower } trap cleanup INT TERM EXIT PIPE . /lib/gluon/functions/model.sh my_model="$(get_model | tr '[A-Z]' '[a-z]' | sed -r 's/[^a-z0-9]+/-/g;s/-$//')" if [ ! -f "$VERSION_FILE" ]; then echo "Couldn't determine firmware version!" >&2 exit 1 fi my_version="$(cat "$VERSION_FILE")" fetch_manifest() { local MIRROR=$1 wget -O$manifest "$MIRROR"/manifest if test $? -ne 0; then echo "Couldn't fetch manifest from $MIRROR" >&2 return 1 fi } verify_and_analyse_manifest() { awk "BEGIN { sep=0 } /^---\$/ { sep=1; next } { if(sep==0) print > \"$manifest_upper\"; else print > \"$manifest_lower\"}" \ $manifest local signatures="" while read sig; do echo "$sig" | grep -q "^[0-9a-f]\{128\}$" if test $? -ne 0; then continue fi signatures="$signatures -s $sig" done < $manifest_lower local pubkeys="" for key in $PUBKEYS; do pubkeys="$pubkeys -p $key" done ecdsaverify -n $GOOD_SIGNATURES $pubkeys $signatures $manifest_upper if test $? -ne 0; then echo "Not enough valid signatures!" >&2 return 1 fi grep -q "^BRANCH=${BRANCH}$" $manifest_upper if test $? -ne 0; then echo "Wrong branch. We are on ${BRANCH}" >&2 return 1 fi local my_firmware=$(grep "^${my_model} " $manifest_upper) if test $? -ne 0; then echo "No matching firmware found (model ${my_model})" >&2 return 1 fi fw_version=$(echo "${my_firmware}"|cut -d' ' -f2) fw_md5=$(echo "${my_firmware}"|cut -d' ' -f3) fw_file=$(echo "${my_firmware}"|cut -d' ' -f4) return 0 } fetch_firmware() { local MIRROR=$1 wget -O$fw_image "${MIRROR}/${fw_file}" if test $? -ne 0; then echo "Error downloading image from $MIRROR" >&2 return 1 else return 0 fi } autoupdate() { local MIRROR=$1 fw_image=$(mktemp) manifest=$(mktemp) manifest_upper=$(mktemp) manifest_lower=$(mktemp) fetch_manifest $MIRROR || return 1 verify_and_analyse_manifest || return 1 if newer_than "$fw_version" "$my_version"; then echo "New version available" fetch_firmware $MIRROR || return 1 image_md5=$(md5sum "$fw_image"|cut -b-32) if test "$image_md5" != "$fw_md5"; then echo "Invalid image checksum" >&2 return 1 fi echo "Upgrading firmware." sysupgrade "${fw_image}" else echo "No new firmware available" fi return 0 } autoupdate $BASE && exit 0