gluon/package/gluon-autoupdater/files/usr/sbin/autoupdater
Jan-Philipp Litza 7cdf3708f0 gluon-autoupdater: get random number from urandom
The approach with awk's rand() wasn't really random between across
devices: When srand() was called without arguments, time() was used as
seed, which of course is the same on all devices when the script is
called via cron at HH:00:00.

This patch instead uses /dev/urandom as source of random (we don't need
cryptographically strong random numbers, so urandom is just fine) but
still uses awk for the comparison as busybox's ash cannot deal with
floats in $(())
2014-01-19 22:36:49 +01:00

131 lines
2.8 KiB
Bash
Executable File

#!/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")"
fw_image=$(mktemp)
manifest=$(mktemp)
manifest_upper=$(mktemp)
manifest_lower=$(mktemp)
wget -O$manifest "$BASE"/manifest
if test $? -ne 0; then
echo "Couldn't fetch manifest" >&2
exit 1
fi
awk "BEGIN { sep=0 }
/^---\$/ { sep=1; next }
{ if(sep==0) print > \"$manifest_upper\";
else print > \"$manifest_lower\"}" \
$manifest
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
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
exit 1
fi
grep -q "^BRANCH=${BRANCH}$" $manifest_upper
if test $? -ne 0; then
echo "Wrong branch. We'are on ${BRANCH}" >&2
exit 1
fi
my_firmware=$(grep "^${my_model} " $manifest_upper)
if test $? -ne 0; then
echo "No matching firmware found (model ${my_model})" >&2
exit 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)
if newer_than "$fw_version" "$my_version"; then
echo "New version available"
wget -O$fw_image "${BASE}/${fw_file}"
if test $? -ne 0; then
echo "Error downloading image" >&2
exit 1
fi
image_md5=$(md5sum "$fw_image"|cut -b-32)
if test "$image_md5" != "$fw_md5"; then
echo "Invalid image checksum" >&2
exit 1
fi
echo "Upgrading firmware."
sysupgrade "${fw_image}"
else
echo "No new firmware available"
fi
exit 0