#! /bin/sh ### ### Fetch an archive, and unpack it into a directory in a safe manner. set -e ## Parse the command line. case $# in 3) ;; *) echo >&2 "usage: $0 DIR LABEL URL"; exit 1 ;; esac dir=$1 label=$2 url=$3 cd "$dir" ## Fetch the archive. rm -rf tmp; mkdir tmp curl -s -o tmp/"$label.tar.gz" "$url" ## Check the archive for unpleasantness. The GNU and FreeBSD versions of ## tar(1) do something vaguely sensible with `..' components in the pathnames ## of archive members. (Specifically, FreeBSD simply ignores the affected ## members; GNU strips leading components in a bizarre way.) But OpenBSD ## gets a special security award for cheerily following the `..' components. ## So we have to do this complicated laundering thing. ## ## The archive ought to unpack everything into a single directory and not ## contain anythig weird. So check. Actually, this won't catch newlines in ## member names, so we'll have to be careful about those. The regular ## expression insists that everything be in a single directory identified by ## the LABEL, and that the rest of the name contains no two adjacent dots. ## We use the LABEL as part of an ERE, so it ought not contain bad things. if tar tzf tmp/"$label.tar.gz" | grep -Ev "^$label/([^.]+|\.[^.])*$" >&2 then echo >&2 "$0: archive has bad member pathnames" exit 1 fi ## Unpack the archive now that we know it's safe. (cd tmp; tar xzf "$label.tar.gz") ## Replace any existing tree with the new one. rm -rf "$label" mv tmp/"$label" . rm -rf tmp