123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #!/bin/sh
- BRANCH=$(uci get autoupdater.settings.branch)
- PROBABILITY=$(uci get autoupdater.${BRANCH}.probability)
- if test "a$1" != "a-f"; then
- if test $(uci get autoupdater.settings.enabled) != 1; then
- echo "autoupdater is disabled"
- exit 0
- fi
- # 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
- BRANCH_NAME=$(uci get autoupdater.${BRANCH}.name)
- MIRRORS=$(for mirror in $(uci get autoupdater.${BRANCH}.mirror); do \
- hexdump -n1 -e '/1 "%d '"$mirror"'\n"' /dev/urandom; \
- done | sort -n | cut -d' ' -f2)
- PUBKEYS=$(uci get autoupdater.${BRANCH}.pubkey)
- GOOD_SIGNATURES=$(uci get autoupdater.${BRANCH}.good_signatures)
- VERSION_FILE=/lib/gluon/release
- # returns 0 when $1 is a higher version number than $2
- newer_than() {
- # negate the return value as opkg returns 1 when the proposition is true
- ! opkg compare-versions "$1" '>>' "$2"
- }
- fetch_manifest() {
- local MIRROR=$1
- local manifest=$2
- wget -O$manifest "$MIRROR"/manifest
- if test $? -ne 0; then
- echo "Couldn't fetch manifest from $MIRROR" >&2
- return 1
- fi
- return 0
- }
- verify_manifest() {
- local manifest=$1
- local manifest_upper=$2
- local manifest_lower=$(mktemp)
- 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
- rm -f $manifest_lower
- ecdsaverify -n $GOOD_SIGNATURES $pubkeys $signatures $manifest_upper
- if test $? -ne 0; then
- echo "Not enough valid signatures!" >&2
- return 1
- fi
- return 0
- }
- analyse_manifest() {
- local manifest_upper=$1
- grep -q "^BRANCH=${BRANCH_NAME}$" $manifest_upper
- if test $? -ne 0; then
- echo "Wrong branch. We are on ${BRANCH_NAME}" >&2
- return 1
- fi
- local my_firmware
- 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_checksum=$(echo "${my_firmware}"|cut -d' ' -f3)
- fw_file=$(echo "${my_firmware}"|cut -d' ' -f4)
- return 0
- }
- fetch_firmware() {
- local MIRROR=$1
- local fw_image=$2
- wget -O$fw_image "${MIRROR}/${fw_file}"
- if test $? -ne 0; then
- echo "Error downloading image from $MIRROR" >&2
- return 1
- fi
- return 0
- }
- autoupdate() {
- local MIRROR=$1
- local manifest=$(mktemp)
- fetch_manifest $MIRROR $manifest || { rm -f $manifest; return 1; }
- local manifest_upper=$(mktemp)
- verify_manifest $manifest $manifest_upper || { rm -f $manifest $manifest_upper; return 1; }
- rm -f $manifest
- analyse_manifest $manifest_upper || { rm -f $manifest_upper; return 1; }
- rm -f $manifest_upper
- if newer_than "$fw_version" "$my_version"; then
- echo "New version available"
- # drop caches to make room for firmware image
- sync
- sysctl -w vm.drop_caches=3
- local fw_image=$(mktemp)
- fetch_firmware $MIRROR $fw_image || { rm -f $fw_image; return 1; }
- image_sha512=$(sha512sum "$fw_image" | awk '{print $1}')
- image_md5=$(md5sum "$fw_image" | awk '{print $1}')
- if [ "$image_sha512" != "$fw_checksum" -a "$image_md5" != "$fw_checksum" ]; then
- echo "Invalid image checksum" >&2
- rm -f $fw_image
- return 1
- fi
- echo "Upgrading firmware."
- sysupgrade "${fw_image}"
- else
- echo "No new firmware available"
- fi
- return 0
- }
- trap 'echo Signal ignored.' INT TERM 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")"
- for mirror in $MIRRORS; do
- autoupdate $mirror && exit 0
- unset fw_version
- unset fw_checksum
- unset fw_file
- done
|