7cdf3708f0
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 $(())
131 lines
2.8 KiB
Bash
Executable File
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
|