xref: /openbsd-src/usr.sbin/sysupgrade/sysupgrade.sh (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1#!/bin/ksh
2#
3# $OpenBSD: sysupgrade.sh,v 1.44 2020/10/22 07:19:42 tb Exp $
4#
5# Copyright (c) 1997-2015 Todd Miller, Theo de Raadt, Ken Westerback
6# Copyright (c) 2015 Robert Peichaer <rpe@openbsd.org>
7# Copyright (c) 2016, 2017 Antoine Jacoutot <ajacoutot@openbsd.org>
8# Copyright (c) 2019 Christian Weisgerber <naddy@openbsd.org>
9# Copyright (c) 2019 Florian Obser <florian@openbsd.org>
10#
11# Permission to use, copy, modify, and distribute this software for any
12# purpose with or without fee is hereby granted, provided that the above
13# copyright notice and this permission notice appear in all copies.
14#
15# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23set -e
24umask 0022
25export PATH=/usr/bin:/bin:/usr/sbin:/sbin
26
27ARCH=$(uname -m)
28SETSDIR=/home/_sysupgrade
29
30err()
31{
32	echo "${0##*/}: ${1}" 1>&2
33	return ${2:-1}
34}
35
36usage()
37{
38	echo "usage: ${0##*/} [-fkn] [-r | -s] [installurl]" 1>&2
39	return 1
40}
41
42unpriv()
43{
44	local _file _rc=0 _user=_syspatch
45
46	if [[ $1 == -f ]]; then
47		_file=$2
48		shift 2
49	fi
50 	if [[ -n ${_file} ]]; then
51		>${_file}
52		chown "${_user}" "${_file}"
53	fi
54	(($# >= 1))
55
56	eval su -s /bin/sh ${_user} -c "'$@'" || _rc=$?
57
58	[[ -n ${_file} ]] && chown root "${_file}"
59
60	return ${_rc}
61}
62
63# Remove all occurrences of first argument from list formed by the remaining
64# arguments.
65rmel() {
66	local _a=$1 _b _c
67
68	shift
69	for _b; do
70		[[ $_a != "$_b" ]] && _c="${_c:+$_c }$_b"
71	done
72	echo -n "$_c"
73}
74
75RELEASE=false
76SNAP=false
77FORCE=false
78KEEP=false
79REBOOT=true
80
81while getopts fknrs arg; do
82	case ${arg} in
83	f)	FORCE=true;;
84	k)	KEEP=true;;
85	n)	REBOOT=false;;
86	r)	RELEASE=true;;
87	s)	SNAP=true;;
88	*)	usage;;
89	esac
90done
91
92(($(id -u) != 0)) && err "need root privileges"
93
94if $RELEASE && $SNAP; then
95	usage
96fi
97
98set -A _KERNV -- $(sysctl -n kern.version |
99	sed 's/^OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\).*/\1 \2/;q')
100
101shift $(( OPTIND -1 ))
102
103case $# in
1040)	MIRROR=$(sed 's/#.*//;/^$/d' /etc/installurl) 2>/dev/null ||
105		MIRROR=https://cdn.openbsd.org/pub/OpenBSD
106	;;
1071)	MIRROR=$1
108	;;
109*)	usage
110esac
111[[ $MIRROR == @(file|ftp|http|https)://* ]] ||
112	err "invalid installurl: $MIRROR"
113
114if ! $RELEASE && [[ ${#_KERNV[*]} == 2 ]]; then
115	SNAP=true
116fi
117
118if $RELEASE && [[ ${_KERNV[1]} == '-beta' ]]; then
119	NEXT_VERSION=${_KERNV[0]}
120else
121	NEXT_VERSION=$(echo ${_KERNV[0]} + 0.1 | bc)
122fi
123
124if $SNAP; then
125	URL=${MIRROR}/snapshots/${ARCH}/
126	FW_URL=http://firmware.openbsd.org/firmware/snapshots/
127else
128	URL=${MIRROR}/${NEXT_VERSION}/${ARCH}/
129	FW_URL=http://firmware.openbsd.org/firmware/${NEXT_VERSION}/
130fi
131
132install -d -o 0 -g 0 -m 0755 ${SETSDIR}
133cd ${SETSDIR}
134
135echo "Fetching from ${URL}"
136unpriv -f SHA256.sig ftp -N sysupgrade -Vmo SHA256.sig ${URL}SHA256.sig
137
138_KEY=openbsd-${_KERNV[0]%.*}${_KERNV[0]#*.}-base.pub
139_NEXTKEY=openbsd-${NEXT_VERSION%.*}${NEXT_VERSION#*.}-base.pub
140
141read _LINE <SHA256.sig
142case ${_LINE} in
143*\ ${_KEY})	SIGNIFY_KEY=/etc/signify/${_KEY} ;;
144*\ ${_NEXTKEY})	SIGNIFY_KEY=/etc/signify/${_NEXTKEY} ;;
145*)		err "invalid signing key" ;;
146esac
147
148[[ -f ${SIGNIFY_KEY} ]] || err "cannot find ${SIGNIFY_KEY}"
149
150unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256
151rm SHA256.sig
152
153if cmp -s /var/db/installed.SHA256 SHA256 && ! $FORCE; then
154	echo "Already on latest snapshot."
155	exit 0
156fi
157
158# INSTALL.*, bsd*, *.tgz
159SETS=$(sed -n -e 's/^SHA256 (\(.*\)) .*/\1/' \
160    -e '/^INSTALL\./p;/^bsd/p;/\.tgz$/p' SHA256)
161
162OLD_FILES=$(ls)
163OLD_FILES=$(rmel SHA256 $OLD_FILES)
164DL=$SETS
165
166[[ -n ${OLD_FILES} ]] && echo Verifying old sets.
167for f in ${OLD_FILES}; do
168	if cksum -C SHA256 $f >/dev/null 2>&1; then
169		DL=$(rmel $f ${DL})
170		OLD_FILES=$(rmel $f ${OLD_FILES})
171	fi
172done
173
174[[ -n ${OLD_FILES} ]] && rm ${OLD_FILES}
175for f in ${DL}; do
176	unpriv -f $f ftp -N sysupgrade -Vmo ${f} ${URL}${f}
177done
178
179if [[ -n ${DL} ]]; then
180	echo Verifying sets.
181	unpriv cksum -qC SHA256 ${DL}
182fi
183
184cat <<__EOT >/auto_upgrade.conf
185Location of sets = disk
186Pathname to the sets = ${SETSDIR}/
187Set name(s) = done
188Directory does not contain SHA256.sig. Continue without verification = yes
189__EOT
190
191if ! ${KEEP}; then
192	CLEAN=$(echo SHA256 ${SETS} | sed -e 's/ /,/g')
193	cat <<__EOT > /etc/rc.firsttime
194rm -f ${SETSDIR}/{${CLEAN}}
195__EOT
196fi
197
198echo Fetching updated firmware.
199fw_update -p ${FW_URL} || echo "Warning: firmware not updated."
200
201install -F -m 700 bsd.rd /bsd.upgrade
202logger -t sysupgrade -p kern.info "installed new /bsd.upgrade. Old kernel version: $(sysctl -n kern.version)"
203sync
204
205if ${REBOOT}; then
206	echo Upgrading.
207	exec reboot
208else
209	echo "Will upgrade on next reboot"
210fi
211