summaryrefslogtreecommitdiffstats
path: root/modules.d/45url-lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xmodules.d/45url-lib/module-setup.sh88
-rwxr-xr-xmodules.d/45url-lib/url-lib.sh174
2 files changed, 262 insertions, 0 deletions
diff --git a/modules.d/45url-lib/module-setup.sh b/modules.d/45url-lib/module-setup.sh
new file mode 100755
index 0000000..65da87e
--- /dev/null
+++ b/modules.d/45url-lib/module-setup.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+# module-setup for url-lib
+
+# called by dracut
+check() {
+ require_binaries curl || return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo network
+ return 0
+}
+
+# called by dracut
+install() {
+ local _dir _crt _crts _found _lib _nssckbi _p11roots _p11root
+ inst_simple "$moddir/url-lib.sh" "/lib/url-lib.sh"
+ inst_multiple -o ctorrent
+ inst_multiple curl sed
+ if curl --version | grep -qi '\bNSS\b'; then
+ # also install libs for curl https
+ inst_libdir_file "libnsspem.so*"
+ inst_libdir_file "libnsssysinit.so*"
+ inst_libdir_file "libsoftokn3.so*"
+ inst_libdir_file "libsqlite3.so*"
+ fi
+
+ for _dir in $libdirs; do
+ [[ -d $dracutsysrootdir$_dir ]] || continue
+ for _lib in "$dracutsysrootdir$_dir"/libcurl.so.* "$dracutsysrootdir$_dir"/libcrypto.so.*; do
+ [[ -e $_lib ]] || continue
+ if ! [[ $_nssckbi ]]; then
+ read -r -d '' _nssckbi < <(grep -F --binary-files=text -z libnssckbi "$_lib")
+ fi
+ read -r -d '' _crt < <(grep -E --binary-files=text -z "\.(pem|crt)" "$_lib" | sed 's/\x0//g')
+ [[ $_crt ]] || continue
+ [[ $_crt == /*/* ]] || continue
+ if [[ -e $_crt ]]; then
+ _crts="$_crts $_crt"
+ _found=1
+ fi
+ done
+ done
+ if [[ $_found ]] && [[ -n $_crts ]]; then
+ for _crt in $_crts; do
+ if ! inst "${_crt#"$dracutsysrootdir"}"; then
+ dwarn "Couldn't install '$_crt' SSL CA cert bundle; HTTPS might not work."
+ continue
+ fi
+ done
+ fi
+ # If we found no cert bundle files referenced in libcurl but we
+ # *did* find a mention of libnssckbi (checked above), install it.
+ # If its truly NSS libnssckbi, it includes its own trust bundle,
+ # but if it's really p11-kit-trust.so, we need to find the dirs
+ # where it will look for a trust bundle and install them too.
+ if ! [[ $_found ]] && [[ $_nssckbi ]]; then
+ _found=1
+ inst_libdir_file "libnssckbi.so*" || _found=
+ for _dir in $libdirs; do
+ [[ -e $dracutsysrootdir$_dir/libnssckbi.so ]] || continue
+ # this looks for directory-ish strings in the file
+ grep -z -o --binary-files=text '/[[:alpha:]][[:print:]]*' "${dracutsysrootdir}${_dir}"/libnssckbi.so \
+ | while read -r -d '' _p11roots || [[ $_p11roots ]]; do
+ IFS=":" read -r -a _p11roots <<< "$_p11roots"
+ # the string can be a :-separated list of dirs
+ for _p11root in "${_p11roots[@]}"; do
+ # check if it's actually a directory (there are
+ # several false positives in the results)
+ [[ -d "$dracutsysrootdir$_p11root" ]] || continue
+ # check if it has some specific subdirs that all
+ # p11-kit trust dirs have
+ [[ -d "$dracutsysrootdir${_p11root}/anchors" ]] || continue
+ [[ -d "$dracutsysrootdir${_p11root}/blacklist" ]] || continue
+ # so now we know it's really a p11-kit trust dir;
+ # install everything in it
+ mkdir -p -- "${initdir}/${_p11root}"
+ if ! $DRACUT_CP -L -t "${initdir}/${_p11root}" "${dracutsysrootdir}${_p11root}"/*; then
+ dwarn "Couldn't install from p11-kit trust dir '${_p11root#"$dracutsysrootdir"}'; HTTPS might not work."
+ fi
+ done
+ done
+ done
+ fi
+ [[ $_found ]] || dwarn "Couldn't find SSL CA cert bundle or libnssckbi.so; HTTPS won't work."
+}
diff --git a/modules.d/45url-lib/url-lib.sh b/modules.d/45url-lib/url-lib.sh
new file mode 100755
index 0000000..7c3ef1e
--- /dev/null
+++ b/modules.d/45url-lib/url-lib.sh
@@ -0,0 +1,174 @@
+#!/bin/sh
+# url-lib.sh - functions for handling URLs (file fetching etc.)
+#
+# Authors:
+# Will Woods <wwoods@redhat.com>
+
+type mkuniqdir > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# fetch_url URL [OUTFILE]
+# fetch the given URL to a locally-visible location.
+# if OUTFILE is given, the URL will be fetched to that filename,
+# overwriting it if present.
+# If the URL is something mountable (e.g. nfs://) and no OUTFILE is given,
+# the server will be left mounted until pre-pivot.
+# the return values are as follows:
+# 0: success
+# 253: unknown error (file missing)
+# 254: unhandled URL scheme / protocol
+# 255: bad arguments / unparsable URLs
+# other: fetch command failure (whatever curl/mount/etc return)
+fetch_url() {
+ local url="$1" outloc="$2"
+ local handler
+ handler="$(get_url_handler "$url")"
+ [ -n "$handler" ] || return 254
+ [ -n "$url" ] || return 255
+ "$handler" "$url" "$outloc"
+}
+
+# get_url_handler URL
+# returns the first HANDLERNAME corresponding to the URL's scheme
+get_url_handler() {
+ local scheme="${1%%:*}" item=""
+ for item in $url_handler_map; do
+ [ "$scheme" = "${item%%:*}" ] && echo "${item#*:}" && return 0
+ done
+ return 1
+}
+
+# add_url_handler HANDLERNAME SCHEME [SCHEME...]
+# associate the named handler with the named scheme(s).
+add_url_handler() {
+ local handler="$1"
+ shift
+ local schemes="$*" scheme=""
+ set --
+ for scheme in $schemes; do
+ [ "$(get_url_handler "$scheme")" = "$handler" ] && continue
+ set -- "$@" "$scheme:$handler"
+ done
+ set -- "$@" "$url_handler_map" # add new items to *front* of list
+ url_handler_map="$*"
+}
+
+### HTTP, HTTPS, FTP #################################################
+
+export CURL_HOME="/run/initramfs/url-lib"
+mkdir -p $CURL_HOME
+curl_args="--globoff --location --retry 3 --retry-connrefused --fail --show-error"
+getargbool 0 rd.noverifyssl && curl_args="$curl_args --insecure"
+
+proxy=$(getarg proxy=)
+[ -n "$proxy" ] && curl_args="$curl_args --proxy $proxy"
+
+curl_fetch_url() {
+ local url="$1" outloc="$2"
+ echo "$url" > /proc/self/fd/0
+ if [ -n "$outloc" ]; then
+ # shellcheck disable=SC2086
+ curl $curl_args --output "$outloc" -- "$url" || return $?
+ else
+ local outdir
+ outdir="$(mkuniqdir /tmp curl_fetch_url)"
+ (
+ cd "$outdir" || exit
+ # shellcheck disable=SC2086
+ curl $curl_args --remote-name "$url" || return $?
+ )
+ outloc="$outdir/$(ls -A "$outdir")"
+ fi
+ if ! [ -f "$outloc" ]; then
+ warn "Downloading '$url' failed!"
+ return 253
+ fi
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+add_url_handler curl_fetch_url http https ftp tftp
+
+set_http_header() {
+ echo "header = \"$1: $2\"" >> $CURL_HOME/.curlrc
+}
+
+### TORRENT ##########################################################
+
+ctorrent_args="-E 0 -e 0"
+
+ctorrent_fetch_url() {
+ local url="$1" outloc="$2"
+ url=${url#*//}
+ torrent_outloc="$outloc.torrent"
+ echo "$url" > /proc/self/fd/0
+ if [ -n "$outloc" ]; then
+ # shellcheck disable=SC2086
+ curl $curl_args --output "$torrent_outloc" -- "$url" || return $?
+ else
+ local outdir
+ outdir="$(mkuniqdir /tmp torrent_fetch_url)"
+ (
+ cd "$outdir" || exit
+ # shellcheck disable=SC2086
+ curl $curl_args --remote-name "$url" || return $?
+ )
+ torrent_outloc="$outdir/$(ls -A "$outdir")"
+ outloc=${torrent_outloc%.*}
+ fi
+ if ! [ -f "$torrent_outloc" ]; then
+ warn "Downloading '$url' failed!"
+ return 253
+ fi
+ # shellcheck disable=SC2086
+ ctorrent $ctorrent_args -s "$outloc" "$torrent_outloc" >&2
+ if ! [ -f "$outloc" ]; then
+ warn "Torrent download of '$url' failed!"
+ return 253
+ fi
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+
+command -v ctorrent > /dev/null \
+ && add_url_handler ctorrent_fetch_url torrent
+
+### NFS ##############################################################
+
+[ -e /lib/nfs-lib.sh ] && . /lib/nfs-lib.sh
+
+nfs_already_mounted() {
+ local server="$1" path="$2" s="" p=""
+ while read -r src mnt rest || [ -n "$src" ]; do
+ splitsep ":" "$src" s p
+ p=${p%/}
+ if [ "$server" = "$s" ]; then
+ if [ "$path" = "$p" ]; then
+ echo "$mnt"
+ elif str_starts "$path" "$p"; then
+ echo "$mnt"/"${path#"$p"/}"
+ fi
+ fi
+ done < /proc/mounts
+}
+
+nfs_fetch_url() {
+ local url="$1" outloc="$2" nfs="" server="" path="" options=""
+ nfs_to_var "$url" || return 255
+ local filepath="${path%/*}" filename="${path##*/}" mntdir=""
+
+ # skip mount if server:/filepath is already mounted
+ mntdir=$(nfs_already_mounted "$server" "$filepath")
+ if [ -z "$mntdir" ]; then
+ local mntdir
+ mntdir="$(mkuniqdir /run nfs_mnt)"
+ mount_nfs "$nfs:$server:$filepath${options:+:$options}" "$mntdir"
+ # lazy unmount during pre-pivot hook
+ inst_hook --hook pre-pivot --name 99url-lib-umount-nfs-"$(basename "$mntdir")" umount -l -- "$mntdir"
+ fi
+
+ if [ -z "$outloc" ]; then
+ outloc="$mntdir/$filename"
+ else
+ cp -f -- "$mntdir/$filename" "$outloc" || return $?
+ fi
+ [ -f "$outloc" ] || return 253
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+command -v nfs_to_var > /dev/null && add_url_handler nfs_fetch_url nfs nfs4