DARWIN: ensure OpenAFS.pkg is signed
[openafs.git] / src / packaging / MacOS / pkgbuild.sh.in
1 #!/bin/bash
2 # Portions Copyright (c) 2003, 2006 Apple Computer, Inc.  All rights reserved.
3 echo '**BUILDPKG**' "$@"
4
5 usage() {
6     exec >&2
7
8     echo 'Usage: pkgbuild.sh [-x] [--app-key <appkey>] [--inst-key <instkey>]'
9     echo '                   [--apple-id <appleid> <password>]'
10     echo '                   [--pass N] [--csdb <CellServDB>] <binary-dir>'
11     echo
12     echo '--app-key and --inst-key are for signing. -x prints all comamnds as '
13     echo 'they are run. --apple-id is for notarizing.'
14     echo
15     echo 'Note: the password associated with <appleid> can be a reference to a'
16     echo 'keychain item. Including your password as cleartext is not'
17     echo 'recommended. e.g.'
18     echo
19     echo '--apple-id foo@bar.com "@keychain:PASSWORD"'
20     echo
21     echo 'In this case, keychain must hold a keychain item named PASSWORD with'
22     echo 'an account matching foo@bar.com.'
23     echo
24     echo 'By default, all passes are run. Available passes:'
25     echo '    --pass 1: prepare pkgroot'
26     echo '    --pass 2: create packages/installer from pkgroot'
27     echo 'If you want to alter the pkgroot, run pass 1, then alter what you'
28     echo 'want, and then run pass 2 to create the resulting packages.'
29     echo 'The --pass argument may be given multiple times.'
30     exit 1
31 }
32
33 if [ x"$#" = x0 ]; then
34     usage
35 fi
36
37 anypass=0
38 PASS1=
39 PASS2=
40
41 APP_KEY=
42 INST_KEY=
43 APPLE_ID=
44 APPLE_PW=
45 DEST_DIR=
46 CSDB=
47
48 CODESIGN_OPTS=
49
50 while [ x"$#" != x0 ] ; do
51     key="$1"
52     shift
53
54     case "$key" in
55     --app-key)
56         APP_KEY="$1"
57         shift
58         ;;
59     --inst-key)
60         INST_KEY="$1"
61         shift
62         ;;
63     --apple-id)
64         APPLE_ID="$1"
65         shift
66         APPLE_PW="$1"
67         shift
68         ;;
69     --csdb)
70         CSDB="$1"
71         shift
72         ;;
73     --pass)
74         anypass=1
75         pass_arg="$1"
76         shift
77         case "$pass_arg" in
78         1)
79             PASS1=1
80             ;;
81         2)
82             PASS2=1
83             ;;
84         *)
85             echo "Unknown pass $pass_arg" >&2
86             exit 1
87             ;;
88         esac
89         ;;
90     -x)
91         DO_X=1
92         ;;
93     *)
94         if [ x"$DEST_DIR" = x ] ; then
95             DEST_DIR="$key"
96         else
97             echo "Error: Unknown arg $key" >&2
98             usage
99         fi
100         ;;
101     esac
102 done
103
104 if [ x"$anypass" = x0 ] ; then
105     PASS1=1
106     PASS2=1
107 fi
108
109 if [ x"$DEST_DIR" = x ] ; then
110     echo "Error: binary 'dest' dir not given"
111     usage
112 fi
113
114 set -e
115
116 if [ x"$DO_X" = x1 ] ; then
117     set -x
118 fi
119
120 BINDEST=`cd "$DEST_DIR" && pwd`
121 CURDIR=`pwd`
122 RESSRC=`dirname "$0"`
123 RESSRC=`cd "$RESSRC" && pwd`
124 majorvers=`uname -r | cut -d. -f1`
125
126 if [ x"$majorvers" = x10 ]; then
127     RELNAME="Snowleopard"
128     THISREL=6
129
130 elif [ x"$majorvers" = x11 ]; then
131     RELNAME="Lion"
132     THISREL=7
133
134 elif [ x"$majorvers" = x12 ]; then
135     RELNAME="MountainLion"
136     THISREL=8
137
138 elif [ x"$majorvers" = x13 ]; then
139     RELNAME="Mavericks"
140     THISREL=9
141
142 elif [ x"$majorvers" = x14 ]; then
143     RELNAME="Yosemite"
144     THISREL=10
145
146 elif [ x"$majorvers" = x15 ]; then
147     RELNAME="ElCapitan"
148     THISREL=11
149
150 elif [ x"$majorvers" = x16 ]; then
151     RELNAME="Sierra"
152     THISREL=12
153
154 elif [ x"$majorvers" = x17 ]; then
155     RELNAME="HighSierra"
156     THISREL=13
157
158 elif [ x"$majorvers" = x18 ]; then
159     RELNAME="Mojave"
160     THISREL=14
161
162 elif [ x"$majorvers" = x19 ]; then
163     RELNAME="Catalina"
164     THISREL=15
165
166 elif [ x"$majorvers" = x ] ; then
167     echo "Error running uname" >&2
168     exit 1
169
170 else
171     echo "Unknown major version $majorvers" >&2
172     exit 1
173 fi
174
175 if [ $THISREL -ge 14 ]; then
176     # Enable the Hardened Runtime capability, required as of 10.14.5.
177     CODESIGN_OPTS="--options runtime"
178 fi
179
180 SEP=:
181
182 PKGROOT="$CURDIR"/pkgroot
183 PKGRES="$CURDIR"/pkgres
184 DPKGROOT="$CURDIR"/dpkgroot
185 PLUGINS="$CURDIR"/plugins
186 if test -e /usr/bin/pkgbuild; then
187     :
188 else
189     echo pkgbuild not found >&2
190     exit 1
191 fi
192 if test -e /usr/bin/productbuild; then
193     :
194 else
195     echo productbuild not found >&2
196     exit 1
197 fi
198
199 if [ x"$PASS1" = x1 ]; then
200     if [ -x /usr/bin/curl ] && [ x"$CSDB" = x ]; then
201         echo "No CellServDB provided; downloading one from central.org"
202         /usr/bin/curl -f -O https://www.central.org/dl/cellservdb/CellServDB
203         if [ -f "$CURDIR"/CellServDB ] ; then
204             CSDB="$CURDIR"/CellServDB
205         fi
206     fi
207
208     if [ x"$CSDB" = x ]; then
209         echo "A CellServDB file must be provided with --csdb" >&2
210         die=1
211     else
212         # Turn CSDB into an absolute path
213         case "$CSDB" in
214         /*)
215             ;;
216         *)
217             CSDB="$CURDIR/$CSDB"
218             ;;
219         esac
220
221         if grep -q 'GCO Public CellServDB' "$CSDB" ; then
222             touch "$CSDB"
223         else
224             echo "A proper CellServDB file must be provided" >&2
225             die=1
226         fi
227     fi
228
229     for f in ReadMe.rtf."$majorvers" \
230              License.rtf \
231              CellServDB.list \
232              OpenAFS.info \
233              OpenAFS.post_install \
234              OpenAFS.pre_upgrade \
235              csrvdbmerge.pl \
236              2.0.txt
237     do
238         if [ ! -f "$RESSRC/$f" ]; then
239             echo "file missing: $RESSRC/$f" >&2
240             die=1
241         fi
242     done
243     if [ x"$die" = x1 ]; then
244         echo "Correct above errors; then retry" >&2
245         exit 1
246     fi
247
248     for f in "$BINDEST"/bin/translate_et \
249              "$BINDEST/root.client/usr/vice/etc/afs.kext/Contents/MacOS/afs"
250     do
251         if [ ! -f "$f" ] ; then
252             echo "dest file missing: $f" >&2
253             die=1
254         fi
255     done
256     if [ x"$die" = x1 ]; then
257         echo $BINDEST " is not a valid binary dir. it should be the result of" >&2
258         echo "make dest" >&2
259         exit 1
260     fi
261
262     rm -rf "$PKGROOT" "$PLUGINS"
263     mkdir "$PKGROOT"
264     mkdir "$PLUGINS"
265
266     mkdir -p "$PKGROOT"/Library
267     mkdir -p "$PKGROOT"/Library/PreferencePanes
268     mkdir -p "$PKGROOT"/Library/Security/SecurityAgentPlugins
269
270     chown -R root${SEP}admin "$PKGROOT"
271     chmod -R 755 "$PKGROOT"
272
273     (cd "$BINDEST"/tools && pax -rw OpenAFS.prefPane "$PKGROOT"/Library/PreferencePanes/)
274     (cd "$BINDEST"/tools && pax -rw aklog.bundle \
275     "$PKGROOT"/Library/Security/SecurityAgentPlugins/)
276
277     mkdir -p "$PKGROOT"/Library/OpenAFS/Tools
278     (cd "$BINDEST" && pax -rw * "$PKGROOT"/Library/OpenAFS/Tools)
279
280     cd "$RESSRC"
281     mv "$PKGROOT"/Library/OpenAFS/Tools/installer/* "$PLUGINS"/
282
283     mkdir -p "$PKGROOT"/Library/LaunchDaemons
284     chmod -R o-w "$PKGROOT"/Library
285     chmod -R g-w "$PKGROOT"/Library
286
287     cp openafs.launchd.plist "$PKGROOT"/Library/LaunchDaemons/org.openafs.filesystems.afs.plist
288     chmod 644 "$PKGROOT"/Library/LaunchDaemons/org.openafs.filesystems.afs.plist
289
290     chown root${SEP}admin "$PKGROOT"/Library
291     chown -R root${SEP}wheel "$PKGROOT"/Library/LaunchDaemons
292     chown -R root${SEP}wheel "$PKGROOT"/Library/OpenAFS/Tools
293     chmod -R og-w "$PKGROOT"/Library/OpenAFS/Tools
294
295     mkdir -p "$PKGROOT"/private/var/db/openafs/cache
296     mkdir -p "$PKGROOT"/private/var/db/openafs/etc/config
297
298     cp openafs.launchdaemon "$PKGROOT"/private/var/db/openafs/etc/launchafs.sh
299     chmod 755 "$PKGROOT"/private/var/db/openafs/etc/launchafs.sh
300
301     cp "$CSDB" "$PKGROOT"/private/var/db/openafs/etc/CellServDB.master
302     echo grand.central.org > "$PKGROOT"/private/var/db/openafs/etc/ThisCell.sample
303     echo /afs:/var/db/openafs/cache:100000 > \
304          "$PKGROOT"/private/var/db/openafs/etc/cacheinfo.sample
305
306     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/etc/afssettings \
307            "$PKGROOT"/private/var/db/openafs/etc/config
308     cp settings.plist "$PKGROOT"/private/var/db/openafs/etc/config/settings.plist.orig
309     cp afs.conf "$PKGROOT"/private/var/db/openafs/etc/config/afs.conf.sample
310     cp krb5-weak.conf "$PKGROOT"/private/var/db/openafs/etc/krb5-weak.conf
311
312     cp decode-panic "$PKGROOT"/Library/OpenAFS/Tools/tools
313     chmod a+x "$PKGROOT"/Library/OpenAFS/Tools/tools/decode-panic
314
315     rm -rf "$DPKGROOT"
316     mkdir "$DPKGROOT"
317     mkdir -p "$DPKGROOT"/Library/OpenAFS/Debug
318
319     mv "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext.dSYM \
320        "$DPKGROOT"/Library/OpenAFS/Debug/
321     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
322            "$DPKGROOT"/Library/OpenAFS/Debug/
323     chown -R root${SEP}wheel "$DPKGROOT"/Library/OpenAFS/Debug
324     chmod -R og-w "$DPKGROOT"/Library/OpenAFS/Debug
325
326     strip -X -S \
327         "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext/Contents/MacOS/afs
328
329     mkdir -p "$PKGROOT"/private/var/db/openafs
330
331     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
332            "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/C \
333            "$PKGROOT"/private/var/db/openafs/etc
334
335     chown -R root${SEP}wheel "$PKGROOT"/private
336     chmod -R og-w "$PKGROOT"/private
337
338     chown -R root${SEP}wheel "$PKGROOT"/private
339     chmod -R og-w "$PKGROOT"/private
340     chmod  og-rx "$PKGROOT"/private/var/db/openafs/cache
341
342     if [ x"$APP_KEY" != x ] ; then
343         # To be notarized by Apple, all files must be signed.
344         find "$PKGROOT" -type f -exec codesign --verbose --force \
345             --timestamp --sign "$APP_KEY" $CODESIGN_OPTS {} \;
346
347         # Sign each 'thing' that we have (commands, kexts, etc)
348         for obj in "$DPKGROOT"/Library/OpenAFS/Debug/afs.kext \
349                    "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
350                    "$PKGROOT"/private/var/db/openafs/etc/afs.kext \
351                    "$PKGROOT"/Library/PreferencePanes/OpenAFS.prefPane/Contents/Resources/AFSBackgrounder.app \
352                    "$PKGROOT"/Library/PreferencePanes/OpenAFS.prefPane \
353                    "$PKGROOT"/Library/Security/SecurityAgentPlugins/aklog.bundle \
354                    "$PKGROOT"/Library/OpenAFS/Tools/tools/growlagent-openafs.app \
355                    "$PKGROOT"/Library/OpenAFS/Tools/tools/aklog.bundle \
356                    "$PKGROOT"/Library/OpenAFS/Tools/tools/OpenAFS.prefPane/Contents/Resources/AFSBackgrounder.app \
357                    "$PKGROOT"/Library/OpenAFS/Tools/tools/OpenAFS.prefPane \
358                    "$PLUGINS"/afscell.bundle
359         do
360             codesign --verbose --force --timestamp --sign "$APP_KEY" $CODESIGN_OPTS "$obj"
361         done
362
363
364         # Check if our signatures for our kexts are valid. 'kextutil' will exit
365         # with an error and print out a message if something is wrong with the
366         # signature. Note that a code signing cert must have the
367         # 1.2.840.113635.100.6.1.18 extension present to be used for kexts
368         # (most code signing certs cannot be used for kexts).
369         for kext in "$DPKGROOT"/Library/OpenAFS/Debug/afs.kext \
370                     "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
371                     "$PKGROOT"/private/var/db/openafs/etc/afs.kext
372         do
373             kextutil -no-load -print-diagnostics "$kext"
374         done
375     fi
376
377     if [ $majorvers -ge 15 ]; then
378         # El Capitan and further prevent us from touching /usr/bin directly
379         PREFIX=/opt
380         USRBIN=/opt/openafs/bin
381         USRBIN2TOOLS=../../../Library/OpenAFS/Tools
382
383         USRSBIN=/opt/openafs/sbin
384         USRSBIN2TOOLS=../../../Library/OpenAFS/Tools
385
386         MANDIR=/opt/openafs/share/man
387         MANDIR2TOOLS=../../../../Library/OpenAFS/Tools
388
389         # Add our bin, sbin, and man directories to the default search path
390         mkdir -p "$PKGROOT"/etc/paths.d "$PKGROOT"/etc/manpaths.d
391         echo "$USRBIN" > "$PKGROOT"/etc/paths.d/40-openafs
392         echo "$USRSBIN" >> "$PKGROOT"/etc/paths.d/40-openafs
393         echo "$MANDIR" > "$PKGROOT"/etc/manpaths.d/40-openafs
394     else
395         PREFIX=/usr
396         USRBIN=/usr/bin
397         USRBIN2TOOLS=../../Library/OpenAFS/Tools
398
399         USRSBIN=/usr/sbin
400         USRSBIN2TOOLS="$USRBIN2TOOLS"
401
402         MANDIR=/usr/share/man
403         MANDIR2TOOLS=../../../Library/OpenAFS/Tools
404     fi
405
406     mkdir -p "$PKGROOT$USRBIN" \
407              "$PKGROOT$USRSBIN" \
408              "$PKGROOT$MANDIR"/man1 \
409              "$PKGROOT$MANDIR"/man5 \
410              "$PKGROOT$MANDIR"/man8
411
412     BINLIST="fs klog klog.krb pagsh pagsh.krb pts sys tokens tokens.krb unlog unlog.krb aklog"
413     ETCLIST="vos"
414
415     if [ x"$DO_X" = x1 ] ; then
416         # Don't print out every single 'ln -s'... that's kinda useless
417         : 'Symlinking commands and manpages into place...'
418         set +x
419     fi
420
421     for f in $BINLIST; do
422         ln -s "$USRBIN2TOOLS"/bin/"$f" "$PKGROOT$USRBIN/$f"
423     done
424     for f in $ETCLIST; do
425         ln -s "$USRSBIN2TOOLS"/etc/"$f" "$PKGROOT$USRSBIN/$f"
426     done
427
428     for section in man1 man5 man8 ; do
429         for f in $(ls $PKGROOT/Library/OpenAFS/Tools/man/$section); do
430
431             if [ -L "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f" ] ; then
432                 # If this manpage is a symlink, just change where it's pointing,
433                 # and rename the link; don't actually 'gzip' it.
434                 link=$(readlink "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f")
435                 rm -f "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f"
436                 ln -s "$link".gz "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f".gz
437
438             else
439                 gzip -9 "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f"
440             fi
441             ln -s ../"$MANDIR2TOOLS"/man/"$section/$f".gz \
442                   "$PKGROOT$MANDIR/$section/$f".gz
443         done
444     done
445
446     if [ x"$DO_X" = x1 ] ; then
447         set -x
448     fi
449
450     ln -s "$USRBIN2TOOLS"/bin/kpasswd "$PKGROOT$USRBIN"/kpasswd.afs
451
452     ln -s "$USRSBIN2TOOLS"/root.client/usr/vice/etc/afsd "$PKGROOT$USRSBIN"/afsd
453
454     chown -R root${SEP}wheel "$PKGROOT$PREFIX"
455     chmod -R og-w "$PKGROOT$PREFIX"
456 fi
457
458 if [ x"$PASS2" = x1 ]; then
459     rm -rf "$PKGRES"
460     mkdir "$PKGRES"
461     cd "$RESSRC"
462
463     rm -rf "$CURDIR"/OpenAFS-debug-extension.pkg
464     /usr/bin/pkgbuild --root "$DPKGROOT" --id org.openafs.OpenAFS-debug.pkg \
465                       --version '@PACKAGE_VERSION@' \
466              "$CURDIR"/OpenAFS-debug-extension.pkg
467
468     cd "$RESSRC"
469     cp OpenAFS.post_install "$PKGRES"/postinstall
470     cp OpenAFS.pre_upgrade "$PKGRES"/preupgrade
471     cp OpenAFS.post_install "$PKGRES"/postupgrade
472     cp csrvdbmerge.pl "$PKGRES"
473
474     chmod a+x "$PKGRES"/csrvdbmerge.pl \
475               "$PKGRES"/postinstall \
476               "$PKGRES"/postupgrade \
477               "$PKGRES"/preupgrade
478
479     cp CellServDB.list "$PKGRES"
480     chown -R root${SEP}wheel "$PKGRES"
481
482     rm -rf "$CURDIR"/OpenAFS-dist.pkg
483     /usr/bin/pkgbuild --root "$PKGROOT" --id org.openafs.OpenAFS.pkg \
484                       --version '@PACKAGE_VERSION@' \
485                       --scripts "$PKGRES" "$CURDIR"/OpenAFS-dist.pkg
486
487     rm -rf "$PKGRES"
488     mkdir "$PKGRES"
489     cp background.jpg "$PKGRES"/background.jpg
490     cp License.rtf "$PKGRES"
491     cp ReadMe.rtf."$majorvers" "$PKGRES"/ReadMe.rtf
492     chown -R root${SEP}wheel "$PKGRES"
493
494     if [ $majorvers -ge 15 ] ; then
495         # For El Capitan and further, we have some extra information to tell
496         # the user at the end of the installation process.
497         cp conclusion.txt "$PKGRES"/conclusion.txt
498         PRES_EXTRA="<conclusion file=\"conclusion.txt\"/>"
499     fi
500
501     # generate Distribution.xml from Distribution.xml.in -- nonstandard substs
502     sed -e "s/%%OSX_MAJOR_CUR%%/$THISREL/g" \
503         -e "s/%%OSX_MAJOR_NEXT%%/$(( $THISREL + 1 ))/g" \
504         -e "s,%%PRES_EXTRA%%,$PRES_EXTRA,g" \
505         -e "s/%%OPENAFS_VERSION%%/@PACKAGE_VERSION@/g" \
506         < Distribution.xml.in > Distribution.xml
507
508     rm -rf "$CURDIR/prod"
509     mkdir "$CURDIR/prod"
510     mv "$CURDIR"/OpenAFS-dist.pkg "$CURDIR"/OpenAFS-debug-extension.pkg "$CURDIR"/prod
511     /usr/bin/productbuild --distribution Distribution.xml --resources "$PKGRES" \
512                           --plugins "$PLUGINS" --package-path "$CURDIR"/prod "$CURDIR"/OpenAFS.pkg
513
514     if [ x"$INST_KEY" != x ] ; then
515         mv "$CURDIR"/OpenAFS.pkg "$CURDIR"/OpenAFS-unsigned.pkg
516         productsign --timestamp --sign "$INST_KEY" "$CURDIR"/OpenAFS-unsigned.pkg \
517                     "$CURDIR"/OpenAFS.pkg
518         rm -f "$CURDIR"/OpenAFS-unsigned.pkg
519     fi
520
521     rm -rf "$CURDIR/dmg"
522     rm -f "$CURDIR/TMP.dmg"
523     rm -rf "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
524
525     mkdir "$CURDIR"/dmg
526     mv "$CURDIR"/OpenAFS.pkg "$CURDIR"/dmg
527     cp "$RESSRC"/Uninstall.14.15 "$CURDIR"/dmg/Uninstall.command
528     cp "$RESSRC"/DS_Store "$CURDIR"/dmg/.DS_Store
529     mkdir "$CURDIR"/dmg/.background
530     cp "$RESSRC"/afslogo.jpg "$CURDIR"/dmg/.background
531
532     if [ x"$APP_KEY" != x ] ; then
533         codesign --verbose --force --timestamp --sign "$APP_KEY" "$CURDIR"/dmg/Uninstall.command
534         codesign --verbose --force --timestamp --sign "$APP_KEY" "$CURDIR"/dmg/OpenAFS.pkg
535     fi
536
537     hdiutil create -srcfolder "$CURDIR"/dmg -volname OpenAFS \
538             -o "$CURDIR"/TMP.dmg
539     hdiutil convert -format UDZO "$CURDIR"/TMP.dmg \
540             -o "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg
541
542     echo
543     echo "Created $CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg
544
545     if [ x"$APPLE_ID" != x ] ; then
546         echo "Notarizing package..."
547         ./notarize.pl "$APPLE_ID" "$APPLE_PW" "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
548     fi
549 fi