xref: /openbsd/usr.sbin/sysupgrade/sysupgrade.sh (revision 09467b48)
1#!/bin/ksh
2#
3# $OpenBSD: sysupgrade.sh,v 1.39 2020/07/04 18:30:46 ajacoutot 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
30ug_err()
31{
32	echo "${1}" 1>&2 && return ${2:-1}
33}
34
35usage()
36{
37	ug_err "usage: ${0##*/} [-fkn] [-r | -s] [installurl]"
38}
39
40unpriv()
41{
42	local _file _rc=0 _user=_syspatch
43
44	if [[ $1 == -f ]]; then
45		_file=$2
46		shift 2
47	fi
48 	if [[ -n ${_file} ]]; then
49		>${_file}
50		chown "${_user}" "${_file}"
51	fi
52	(($# >= 1))
53
54	eval su -s /bin/sh ${_user} -c "'$@'" || _rc=$?
55
56	[[ -n ${_file} ]] && chown root "${_file}"
57
58	return ${_rc}
59}
60
61# Remove all occurrences of first argument from list formed by the remaining
62# arguments.
63rmel() {
64	local _a=$1 _b _c
65
66	shift
67	for _b; do
68		[[ $_a != "$_b" ]] && _c="${_c:+$_c }$_b"
69	done
70	echo -n "$_c"
71}
72
73RELEASE=false
74SNAP=false
75FORCE=false
76KEEP=false
77REBOOT=true
78
79while getopts fknrs arg; do
80	case ${arg} in
81	f)	FORCE=true;;
82	k)	KEEP=true;;
83	n)	REBOOT=false;;
84	r)	RELEASE=true;;
85	s)	SNAP=true;;
86	*)	usage;;
87	esac
88done
89
90(($(id -u) != 0)) && ug_err "${0##*/}: need root privileges"
91
92if $RELEASE && $SNAP; then
93	usage
94fi
95
96set -A _KERNV -- $(sysctl -n kern.version |
97	sed 's/^OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\).*/\1 \2/;q')
98
99shift $(( OPTIND -1 ))
100
101case $# in
1020)	MIRROR=$(sed 's/#.*//;/^$/d' /etc/installurl) 2>/dev/null ||
103		MIRROR=https://cdn.openbsd.org/pub/OpenBSD
104	;;
1051)	MIRROR=$1
106	;;
107*)	usage
108esac
109
110if ! $RELEASE && [[ ${#_KERNV[*]} == 2 ]]; then
111	SNAP=true
112fi
113
114if $RELEASE && [[ ${_KERNV[1]} == '-beta' ]]; then
115	NEXT_VERSION=${_KERNV[0]}
116else
117	NEXT_VERSION=$(echo ${_KERNV[0]} + 0.1 | bc)
118fi
119
120if $SNAP; then
121	URL=${MIRROR}/snapshots/${ARCH}/
122else
123	URL=${MIRROR}/${NEXT_VERSION}/${ARCH}/
124fi
125
126install -d -o 0 -g 0 -m 0755 ${SETSDIR}
127cd ${SETSDIR}
128
129echo "Fetching from ${URL}"
130unpriv -f SHA256.sig ftp -N sysupgrade -Vmo SHA256.sig ${URL}SHA256.sig
131
132_KEY=openbsd-${_KERNV[0]%.*}${_KERNV[0]#*.}-base.pub
133_NEXTKEY=openbsd-${NEXT_VERSION%.*}${NEXT_VERSION#*.}-base.pub
134
135read _LINE <SHA256.sig
136case ${_LINE} in
137*\ ${_KEY})	SIGNIFY_KEY=/etc/signify/${_KEY} ;;
138*\ ${_NEXTKEY})	SIGNIFY_KEY=/etc/signify/${_NEXTKEY} ;;
139*)		ug_err "invalid signing key" ;;
140esac
141
142[[ -f ${SIGNIFY_KEY} ]] || ug_err "cannot find ${SIGNIFY_KEY}"
143
144unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256
145rm SHA256.sig
146
147if cmp -s /var/db/installed.SHA256 SHA256 && ! $FORCE; then
148	echo "Already on latest snapshot."
149	exit 0
150fi
151
152# INSTALL.*, bsd*, *.tgz
153SETS=$(sed -n -e 's/^SHA256 (\(.*\)) .*/\1/' \
154    -e '/^INSTALL\./p;/^bsd/p;/\.tgz$/p' SHA256)
155
156OLD_FILES=$(ls)
157OLD_FILES=$(rmel SHA256 $OLD_FILES)
158DL=$SETS
159
160[[ -n ${OLD_FILES} ]] && echo Verifying old sets.
161for f in ${OLD_FILES}; do
162	if cksum -C SHA256 $f >/dev/null 2>&1; then
163		DL=$(rmel $f ${DL})
164		OLD_FILES=$(rmel $f ${OLD_FILES})
165	fi
166done
167
168[[ -n ${OLD_FILES} ]] && rm ${OLD_FILES}
169for f in ${DL}; do
170	unpriv -f $f ftp -N sysupgrade -Vmo ${f} ${URL}${f}
171done
172
173if [[ -n ${DL} ]]; then
174	echo Verifying sets.
175	unpriv cksum -qC SHA256 ${DL}
176fi
177
178cat <<__EOT >/auto_upgrade.conf
179Location of sets = disk
180Pathname to the sets = /home/_sysupgrade/
181Set name(s) = done
182Directory does not contain SHA256.sig. Continue without verification = yes
183__EOT
184
185if ! ${KEEP}; then
186	CLEAN=$(echo SHA256 ${SETS} | sed -e 's/ /,/g')
187	cat <<__EOT > /etc/rc.firsttime
188rm -f /home/_sysupgrade/{${CLEAN}}
189__EOT
190fi
191
192echo Fetching updated firmware.
193fw_update || echo "Warning: firmware not updated."
194
195install -F -m 700 bsd.rd /bsd.upgrade
196logger -t sysupgrade -p kern.info "installed new /bsd.upgrade. Old kernel version: $(sysctl -n kern.version)"
197sync
198
199if ${REBOOT}; then
200	echo Upgrading.
201	exec reboot
202else
203	echo "Will upgrade on next reboot"
204fi
205