1
0

initial commit

This commit is contained in:
2025-06-05 11:01:19 +03:00
commit 48f13f97a3
297 changed files with 7136 additions and 0 deletions

12
scripts/angie Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
set -ef
## hardcoded configuration directory
d=/run/ngx/conf
## reparse PATH: remove /usr/local/sbin
PATH=$(printf 'x:%s:x' "${PATH}" | sed -zE 's#:/usr/local/sbin/?:#:#g;s/^x://;s/:x$//')
export PATH
exec env -C $d /usr/sbin/angie -p $d -c $d/angie.conf -e stderr --log-level=info -g 'error_log stderr info;' "$@"
exit 126

View File

@@ -0,0 +1,26 @@
#!/bin/sh
set -f
conf_dir='/etc/angie.dist'
## Angie: unset core variables
unset ANGIE ANGIE_BPF_MAPS
t=$(mktemp) || exit $?
/usr/sbin/angie -m 2>&1 | tee "$t" >/dev/null
sed -En '/^ngx_(http|mail|stream)/d;/^ngx_(.+)_module$/{s//\1/;s/_filter$//;s/_/-/g;p}' < "$t" \
| sort -uV > "${conf_dir}/builtin.core"
for m in http mail stream ; do
sed -En '/^ngx_'"${m}"'_(.+)_module$/{s//\1/;s/_filter$//;s/_/-/g;p}' < "$t" \
| sort -uV > "${conf_dir}/builtin.$m"
done
rm -f "$t" ; unset t
## merely debug output
for m in core http mail stream ; do
echo "${conf_dir}/builtin.$m"
done | xargs -r ls -ld >&2

15
scripts/angie-reload.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
set -ef
pid_file="${1:-/run/ngx/angie.pid}"
[ -f "${pid_file}" ] || {
echo "Angie is not running? (${pid_file} not found)"
exit 0
}
[ -s "${pid_file}" ] || {
echo "Angie is not running? (${pid_file} is empty)"
exit 1
}
pid=$(cat "${pid_file}") || exit 1
exec env kill -SIGHUP "${pid}"

56
scripts/apt-clean.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
set -f
## apt
find /var/cache/apt/ ! -type d ! -name 'lock' -delete
find /var/lib/apt/ ! -type d -wholename '/var/lib/apt/listchanges*' -delete
find /var/lib/apt/lists/ ! -type d ! -name 'lock' -delete
find /var/log/ ! -type d -wholename '/var/log/apt/*' -delete
find /var/log/ ! -type d -wholename '/var/log/aptitude*' -delete
## dpkg
: "${DPKG_ADMINDIR:=/var/lib/dpkg}"
truncate -s 0 "${DPKG_ADMINDIR}/available"
find "${DPKG_ADMINDIR}/" ! -type d -wholename "${DPKG_ADMINDIR}/*-old" -delete
find /var/log/ ! -type d -wholename '/var/log/alternatives.log' -delete
find /var/log/ ! -type d -wholename '/var/log/dpkg.log' -delete
## DONT DO THIS AT HOME!
find "${DPKG_ADMINDIR}/" ! -type d -wholename "${DPKG_ADMINDIR}/info/*.symbols" -delete
## debconf
find /var/cache/debconf/ ! -type d -wholename '/var/cache/debconf/*-old' -delete
__t=$(mktemp) ; : "${__t:?}"
debconf_trim_i18n() {
mawk 'BEGIN { m = 0; }
$0 == "" { print; }
/^[^[:space:]]/ {
if ($1 ~ "\.[Uu][Tt][Ff]-?8:") {
m = 1;
next;
}
m = 0;
print $0;
}
/^[[:space:]]/ {
if (m == 1) next;
print $0;
}' < "$1" > "${__t}"
cat < "${__t}" > "$1"
}
debconf_trim_i18n /var/cache/debconf/templates.dat
while read -r tmpl ; do
[ -n "${tmpl}" ] || continue
[ -s "${tmpl}" ] || continue
debconf_trim_i18n "${tmpl}"
done <<EOF
$(find "${DPKG_ADMINDIR}/info/" -type f -name '*.templates' | sort -V)
EOF
rm -f "${__t}" ; unset __t
## misc
rm -f /var/cache/ldconfig/aux-cache
exit 0

8
scripts/apt-env.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -a
DEBCONF_NONINTERACTIVE_SEEN=true
DEBIAN_FRONTEND=noninteractive
DEBIAN_PRIORITY=critical
TERM=linux
set +a
exec "$@"

267
scripts/apt-install-angie-mod.sh Executable file
View File

@@ -0,0 +1,267 @@
#!/bin/sh
set -ef
[ $# -gt 0 ] || exit 1
set -a
ANGIE_MODULES_DIR="${ANGIE_MODULES_DIR:-/usr/lib/angie/modules}"
set +a
unset NGX_DEBUG
NGX_DEBUG=$(/usr/sbin/angie --build-env 2>&1 | mawk '$1=="DEBUG:" {print $2;exit;}')
NGX_DEBUG="${NGX_DEBUG:-0}"
case "${NGX_DEBUG}" in
0 | 1 ) ;;
* ) NGX_DEBUG=1 ;;
esac
unset NGX_PRO
NGX_PRO=$(/usr/sbin/angie -v 2>&1 | mawk 'NR==1 {print $4;exit;}' | tr '[:upper:]' '[:lower:]')
NGX_PRO="${NGX_PRO:-0}"
case "${NGX_PRO}" in
'(pro)' ) NGX_PRO=1 ;;
* ) NGX_PRO=0 ;;
esac
## "fqpn" stands for "Full Qualified Package Name"
## Angie OSS: angie-module-<name>
## Angie PRO: angie-pro-module-<name>
if [ ${NGX_PRO} = 1 ] ; then
fqpn() { echo "angie-pro-module-$1" ; }
else
fqpn() { echo "angie-module-$1" ; }
fi
is_pkg_installed() {
case "$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null)" in
"install ok installed" )
## package is installed normally
return 0
;;
"hold ok installed" )
## package is installed and marked as "hold"
return 0
;;
esac
return 1
}
is_mod_installed() {
is_pkg_installed "$(fqpn "$1")" || return 1
}
## produce package list
mods=
for i ; do
[ -n "$i" ] || continue
printf '%s' "$i" | grep -zEq '^[a-z0-9.+-]+$' || {
env printf 'package name %q is not legal, quitting!\n' "$i" >&2
exit 1
}
if is_mod_installed "$i" ; then
echo "package '$i' is already installed, skipping" >&2
continue
fi
mods="${mods}${mods:+ }$i"
done
[ -n "${mods}" ] || exit 0
list_have_item() {
[ -n "$1" ] || return 1
[ -n "$2" ] || return 1
case " $1 " in
*" $2 "* ) return 0 ;;
esac
return 1
}
normalize_list() {
[ -n "$1" ] || return 0
printf '%s' "$1" \
| sed -zE 's/[[:space:]]+/ /g;s/^ //;s/ $//'
}
sort_dedup_list() {
[ -n "$1" ] || return 0
printf '%s' "$1" \
| tr -s '[:space:]' '\n' | sort -uV \
| sed -zE 's/[[:space:]]+/ /g;s/^ //;s/ $//'
}
mods=$(sort_dedup_list "${mods}")
## angie-module-lua: depends on angie-module-ndk
## angie-module-set-misc: depends on angie-module-ndk
unset want_ndk ; want_ndk=0
if list_have_item "${mods}" lua ; then
want_ndk=1
elif list_have_item "${mods}" set-misc ; then
want_ndk=1
fi
if [ ${want_ndk} = 1 ] ; then
while : ; do
if list_have_item "${mods}" ndk ; then break ; fi
if is_mod_installed ndk ; then break ; fi
mods="${mods} ndk"
break ; done
fi
## angie-module-wamr: depends on angie-module-wasm
## angie-module-wasmtime: depends on angie-module-wasm
unset want_wasm ; want_wasm=0
if list_have_item "${mods}" wamr ; then
want_wasm=1
elif list_have_item "${mods}" wasmtime ; then
want_wasm=1
fi
if [ ${want_wasm} = 1 ] ; then
while : ; do
if list_have_item "${mods}" wasm ; then break ; fi
if is_mod_installed wasm ; then break ; fi
mods="${mods} wasm"
break ; done
fi
## kind of quirk
dirs='cache lib log'
for n in ${dirs} ; do
d="/run/ngx/$n"
[ -d "$d" ] || install -d "$d"
done
pkgs=
for m in ${mods} ; do
pkgs="${pkgs}${pkgs:+ }$(fqpn "$m")"
done
apt-install.sh ${pkgs}
ANGIE_DIST_MODCONF_DIR=/etc/angie.dist/mod
ANGIE_MODCONF_DIR=/etc/angie/mod
[ -d "${ANGIE_MODCONF_DIR}" ] || install -d "${ANGIE_MODCONF_DIR}"
have_preseed() {
if [ -e "${ANGIE_DIST_MODCONF_DIR}/.$1.preseed" ] ; then
return 0
fi
if [ -e "${ANGIE_MODCONF_DIR}/.$1.preseed" ] ; then
return 0
fi
return 1
}
list_ngx_modules() {
set +e
dpkg-query -L "$1" \
| grep -F -e "${ANGIE_MODULES_DIR}/" \
| grep -E -e '/[^/]+_module(-debug)?\.so$' \
| sed -E '\,^(.+)-debug\.so$,{p;s//\1.so/;p;d}' \
| sort -uV \
| xargs -r ls -U1d 2>/dev/null
set -e
}
is_same_file() {
find -L "$1" -samefile "$2" -printf . -quit 2>/dev/null | grep -Fq . || return 1
}
gen_mod_config() {
if [ -s "$2" ] ; then
printf '%s: configuration already exists: %s\n' "$1" "$2" >&2
return
fi
[ -n "$3" ] || return
local __m
for __m in $3 ; do
echo "load_module ${__m};"
done > "$2"
}
for m in ${mods} ; do
[ -n "$m" ] || continue
p=$(fqpn "$m")
## adjust modules:
## - remove debug module if not in debug image
## - move debug module to usual location otherwise
while read -r fmod_debug ; do
# [ -n "${fmod_debug}" ] || continue
case "${fmod_debug}" in
*-debug.so ) ;;
* ) continue ;;
esac
fmod="${fmod_debug%-debug.so}.so"
if [ "${NGX_DEBUG}" = 0 ] ; then
if [ -f "${fmod}" ] ; then
fmod_real=$(readlink -f "${fmod}")
else
env printf 'missing (non-debug) file: %q\n' "${fmod}" >&2
env printf 'falling back to (debug) file: %q\n' "${fmod_debug}" >&2
fmod_real=$(readlink -f "${fmod_debug}")
fi
else
fmod_real=$(readlink -f "${fmod_debug}")
fi
[ -n "${fmod_real}" ] || exit 1
fmod_tmp=$(mktemp -u "${fmod}.XXXXXXXXXX")
ln "${fmod_real}" "${fmod_tmp}"
rm -f "${fmod}" "${fmod_debug}"
mv -f "${fmod_tmp}" "${fmod}"
apt-mark hold "$p" || :
done <<-EOF
$(list_ngx_modules "$p")
EOF
if have_preseed "$m" ; then
printf '%s: skipping generation of module load config (preseed is in effect)\n' "$p" >&2
continue
fi
## produce attachable module configs
http_modules= ; mail_modules= ; stream_modules=
while read -r fmod ; do
[ -n "${fmod}" ] || continue
fmod_short="modules/${fmod#"${ANGIE_MODULES_DIR}/"}"
fname=${fmod##*/}
case "${fname}" in
ngx_http_* )
http_modules="${http_modules}${http_modules:+ }${fmod_short}"
;;
ngx_mail_* )
mail_modules="${mail_modules}${mail_modules:+ }${fmod_short}"
;;
ngx_stream_* )
stream_modules="${stream_modules}${stream_modules:+ }${fmod_short}"
;;
## damn NDK
ndk_http_* )
http_modules="${http_modules}${http_modules:+ }${fmod_short}"
;;
* )
env printf '%s: unable to determine module type for file (skipping): %q\n' "$p" "${fmod}" >&2
continue
;;
esac
done <<-EOF
$(list_ngx_modules "$p")
EOF
[ -z "${http_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/http-$m.conf" "${http_modules}"
[ -z "${mail_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/mail-$m.conf" "${mail_modules}"
[ -z "${stream_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/stream-$m.conf" "${stream_modules}"
done
echo "extra files/directories (if any):" >&2
find /run/ngx/cache/ /run/ngx/lib/ /run/ngx/log/ -mindepth 1 -exec ls -ld {} + >&2

45
scripts/apt-install.sh Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/sh
set -ef
find_fresh_ts() {
{
find "$@" -exec stat -c '%Y' '{}' '+' 2>/dev/null || :
# duck and cover!
echo 1
} | sort -rn | head -n 1
}
_apt_update() {
# update package lists; may fail sometimes,
# e.g. soon-to-release channels like Debian "bullseye" @ 22.04.2021
# (wannabe) smart package list update
ts_sources=$(find_fresh_ts /etc/apt/ -follow -regextype egrep -regex '.+\.(list|sources)$' -type f)
ts_lists=$(find_fresh_ts /var/lib/apt/lists/ -maxdepth 1 -regextype egrep -regex '.+_Packages(\.(bz2|gz|lz[4o]|xz|zstd?))?$' -type f)
if [ ${ts_sources} -gt ${ts_lists} ] ; then
apt-env.sh apt-get update
fi
}
_dpkg_avail_hack() {
: "${DPKG_ADMINDIR:=/var/lib/dpkg}"
VERSION_CODENAME=$(. /etc/os-release ; printf '%s' "${VERSION_CODENAME}") || :
f="${DPKG_ADMINDIR}/available"
# if ${VERSION_CODENAME} is empty then we're on Debian sid or so :)
case "${VERSION_CODENAME}" in
stretch | buster | bionic | focal )
# ref: https://unix.stackexchange.com/a/271387/49297
if [ -s "$f" ] ; then
return
fi
/usr/lib/dpkg/methods/apt/update "${DPKG_ADMINDIR}" apt apt
;;
* )
touch "$f"
;;
esac
}
_apt_update
_dpkg_avail_hack
exec apt-env.sh apt-get install -y --no-install-recommends --no-install-suggests "$@"

5
scripts/apt-remove.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -ef
apt-env.sh apt-get purge -y --allow-remove-essential "$@"
exec apt-env.sh apt-get autopurge -y

7
scripts/divert-rm.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -ef
: "${1:?}"
d=$(printf '%s' "/run/ngx/dpkg-divert/$1" | tr -s '/')
mkdir -p "${d%/*}"
dpkg-divert --divert "$d" --rename "$1" 2>/dev/null
rm -f "$d"

24
scripts/dpkg-search.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -ef
: "${1:?}"
if dpkg-query --search "$1" ; then
exit 0
fi
case "$1" in
*\** | *\?* )
env printf '%s does not support globs: %q\n' "${0##*/}" "$1" >&2
exit 1
;;
esac
while read -r f ; do
[ -n "$f" ] || continue
dpkg-query --search "$f" || continue
exit 0
done <<EOF
$(set +e ; find / -xdev -follow -samefile "$1" 2>/dev/null | grep -Fxv -e "$1")
EOF
exit 1

23
scripts/envsubst-args.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
set -f
sed -znE '/^([^=]+)=.*$/s,,\1,p' /proc/$$/environ \
| sed -zE \
-e '/^_$/d' \
-e '/^ANGIE(|_BPF_MAPS)$/d' \
-e '/^__IEP_/d;/^IEP_$/d' \
-e '/^NGX_STATIC_/d' \
-e '/^ENVSUBST_/d' \
-e '/^J2CFG_/d' \
| {
if [ -n "${ENVSUBST_EXCLUDE_REGEX:-}" ] ; then
grep -zEv -e "${ENVSUBST_EXCLUDE_REGEX}"
elif [ -n "${ENVSUBST_INCLUDE_REGEX:-}" ] ; then
grep -zE -e "${ENVSUBST_INCLUDE_REGEX}"
else
cat
fi
} \
| sort -zV \
| xargs -0 -r printf '${%s} ' \
| sed -zE 's/ $//'

12
scripts/envsubst.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
set -f
while [ -n "${ENVSUBST_ARGS}" ] ; do
[ -f "${ENVSUBST_ARGS}" ] || break
[ -s "${ENVSUBST_ARGS}" ] || break
exec envsubst "$(cat "${ENVSUBST_ARGS}" </dev/null)" "$@"
exit 126
done
exec envsubst "$(envsubst-args.sh </dev/null)" "$@"

2
scripts/j2cfg-dump Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"

2
scripts/j2cfg-multi Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"

2
scripts/j2cfg-single Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"

100
scripts/openssl-cert-auto-pem.sh Executable file
View File

@@ -0,0 +1,100 @@
#!/bin/sh
set -f
[ $# -gt 0 ] || exit 0
me=${0##*/}
[ -n "$1" ] || exit 1
[ -f "$1" ] || {
env printf '%s: not a file or does not exist: %q\n' "${me}" "$1" >&2
exit 1
}
[ -s "$1" ] || exit 0
w=$(mktemp -d) || exit 1
w_cleanup() {
[ -z "$w" ] || ls -lA "$w/" >&2
[ -z "$w" ] || rm -rf "$w"
unset w
exit "${1:-0}"
}
bundle_offsets() {
mawk 'BEGIN { OFS = ","; i_begin = 0; }
$0 == "-----BEGIN CERTIFICATE-----" {
i_begin = NR;
}
$0 == "-----END CERTIFICATE-----" {
if (i_begin > 0) {
print i_begin, NR;
i_begin = 0;
}
}' "$1"
}
bundle_fingerprints() {
local x f
while read -r x ; do
[ -n "$x" ] || continue
f=$(sed -ne "${x}p" "$1" | openssl x509 -noout -fingerprint -sha256)
[ -n "$f" ] || f=$(sed -ne "${x}p" "$1" | openssl x509 -noout -fingerprint)
[ -n "$f" ] || continue
printf '%s\n' "$f" | tr '[:upper:]' '[:lower:]'
done < "$2"
}
openssl storeutl -certs "$1" > "$w/cert.pem" || w_cleanup 1
[ -s "$w/cert.pem" ] || w_cleanup 1
tr -s '\r\n' '\n' < "$w/cert.pem" > "$w/cert.txt"
[ -s "$w/cert.txt" ] || w_cleanup 1
rm -f "$w/cert.pem"
bundle_offsets "$w/cert.txt" > "$w/cert.off"
[ -s "$w/cert.off" ] || w_cleanup 1
bundle_fingerprints "$w/cert.txt" "$w/cert.off" > "$w/cert.fp.all"
[ -s "$w/cert.fp.all" ] || w_cleanup 1
sort -uV < "$w/cert.fp.all" > "$w/cert.fp"
while read -r fp ; do
[ -n "${fp}" ] || continue
n=$(grep -m1 -Fxn -e "${fp}" "$w/cert.fp.all" | cut -d : -f 1)
[ -n "$n" ] || continue
off=$(sed -ne "${n}p" "$w/cert.off")
[ -n "${off}" ] || continue
sed -ne "${off}p" "$w/cert.txt"
done < "$w/cert.fp" > "$w/cert.pem"
[ -s "$w/cert.pem" ] || w_cleanup 1
rm -f "$w/cert.txt" "$w/cert.off" "$w/cert.fp.all"
if [ -n "$2" ] ; then
while : ; do
if [ -e "$2" ] ; then
[ -f "$2" ] || break
fi
cat > "$2"
break ; done
else
cat
fi < "$w/cert.pem"
while [ -n "$3" ] ; do
if [ -e "$3" ] ; then
[ -f "$3" ] || break
fi
cat "$w/cert.fp" > "$3"
break ; done
while [ -n "$4" ] ; do
if [ -e "$4" ] ; then
[ -f "$4" ] || break
fi
bundle_offsets "$w/cert.pem" > "$4"
break ; done
rm -rf "$w" ; unset w

View File

@@ -0,0 +1,16 @@
#!/bin/sh
set -ef
for k in 1024 2048 ; do
f="dh${k}.pem"
echo "# openssl genpkey: $f" >&2
timeout --kill-after=32s 30s \
openssl genpkey -quiet -genparam -algorithm DH -out "./$f" -pkeyopt "dh_paramgen_prime_len:${k}"
done
for k in 2048 3072 4096 ; do
f="ffdhe${k}.pem"
echo "# openssl genpkey: $f" >&2
timeout --kill-after=32s 30s \
openssl genpkey -quiet -genparam -algorithm DH -out "./$f" -pkeyopt "group:ffdhe${k}"
done

206
scripts/openssl-ocsp.sh Executable file
View File

@@ -0,0 +1,206 @@
#!/bin/sh
set -ef
ocsp_fetch_timeout=15
ocsp_fetch_retries=3
ocsp_fetch_retry_delay=5
ocsp_valid_threshold=86400
usage() {
cat >&2 <<-EOF
# usage: ${0##*/} <command> [args...]
# ${0##*/} get-uri <in:cert.pem>
# ${0##*/} is-valid <in:issuer.pem> <in:cert.pem> <in:ocsp.der>
# ${0##*/} is-expiring <in:issuer.pem> <in:cert.pem> <in:ocsp.der>
# ${0##*/} fetch <in:issuer.pem> <in:cert.pem> <out:ocsp.der>
EOF
exit "${1:-0}"
}
[ $# != 0 ] || usage
## $1 - X509 in PEM format
ossl_x509_verify_fmt() {
openssl x509 -in "$1" -noout >/dev/null
}
## $1 - cert
ossl_ocsp_uri() {
openssl x509 -in "$1" -noout -ocsp_uri \
| head -n 1
}
## $1 - chain
## $2 - cert
## $3 - ocsp uri
## $4 - ocsp response
ossl_ocsp_fetch() {
openssl ocsp \
-timeout "${ocsp_fetch_timeout}" \
-nonce \
-issuer "$1" -cert "$2" -url "$3" -respout "$4"
}
## $1 - ocsp response
ossl_ocsp_verify_fmt() {
openssl ocsp \
-noverify -respin "$1"
}
## $1 - chain
## $2 - cert
## $3 - ocsp response
ossl_ocsp_read() {
openssl ocsp \
-issuer "$1" -cert "$2" -respin "$3" -resp_text
}
## $1 - chain
## $2 - cert
## $3 - ocsp response
ossl_ocsp_verify() {
ossl_ocsp_read "$@" >/dev/null
}
## stdin - output of ossl_ocsp_read()
ossl_ocsp_next_update() {
sed -En '/^\s*[Nn]ext [Uu]pdate:\s*(\S.+\S)\s*$/{s//\1/;p;q}'
}
unset arg_ok cmd chain cert ocsp_uri ocsp_resp
arg_ok=
while : ; do
[ -n "$1" ] || break
cmd="$1"
case "$1" in
get-uri )
[ -n "$2" ] || break
[ -s "$2" ] || break
ossl_x509_verify_fmt "$2" || break
cert="$2"
;;
is-valid | is-expiring | fetch )
[ -n "$2" ] || break
[ -s "$2" ] || break
ossl_x509_verify_fmt "$2" || break
chain="$2"
[ -n "$3" ] || break
[ -s "$3" ] || break
ossl_x509_verify_fmt "$3" || break
cert="$3"
[ -n "$4" ] || break
ocsp_resp="$4"
## OCSP response validation is handled later and in various ways (!)
## e.g. "is-valid" (cmd_is_valid) validates OCSP response as expected
## but "is-expiring" (cmd_is_expiring) returns success for invalid OCSP response
## which means OCSP response should be updated ASAP
;;
*) break ;;
esac
arg_ok=1
break ; done
[ -n "${arg_ok}" ] || usage 1
unset arg_ok
## OCSP URI is used only in "get-uri" and "fetch" commands
## but implicitly required for all actions
ocsp_uri=$(ossl_ocsp_uri "${cert}") || exit 1
if [ -z "${ocsp_uri}" ] ; then
env printf '%s: unable to extract OCSP URI from %q\n' "${0##*/}" "${cert}" >&2
exit 1
fi
## early command handling
if [ "${cmd}" = 'get-uri' ] ; then
printf '%s\n' "${ocsp_uri}"
exit 0
fi
## $1 - chain
## $2 - cert
## $3 - ocsp response
cmd_is_valid() {
ossl_ocsp_verify_fmt "$3" || return 1
ossl_ocsp_verify "$1" "$2" "$3" || return 1
}
## $1 - chain
## $2 - cert
## $3 - ocsp response
cmd_is_expiring() {
cmd_is_valid "$1" "$2" "$3" || return 0
local need_update next ts_now ts_next ts_diff
need_update=1
while : ; do
next=$(ossl_ocsp_read "$1" "$2" "$3" 2>/dev/null | ossl_ocsp_next_update)
[ -n "${next}" ] || break
ts_now=$(date '+%s')
ts_next=$(date -d "${next}" '+%s')
[ -n "${ts_next}" ] || break
[ ${ts_now} -lt ${ts_next} ] || break
ts_diff=$((ts_next - ts_now))
[ ${ts_diff} -le ${ocsp_valid_threshold} ] || need_update=0
break ; done
if [ "${need_update}" = 0 ] ; then
env printf '%q has valid and fresh OCSP response\n' "$2" >&2
return 1
fi
return 0
}
## $1 - chain
## $2 - cert
## $3 - ocsp uri
## $4 - ocsp response
cmd_fetch() {
local t i r
t=$(mktemp) ; : "${t:?}"
for i in $(seq 1 "${ocsp_fetch_retries}") ; do
i= ## no-op
if ossl_ocsp_fetch "$1" "$2" "$3" "$t" ; then
break
fi
: > "$t"
sleep "${ocsp_fetch_retry_delay}"
done
r=
while : ; do
[ -s "$t" ] || break
cmd_is_valid "$1" "$2" "$t" || break
r=1
break ; done
if [ -z "$r" ] ; then
env printf 'unable to fetch OCSP response for %q via %q\n' "$2" "$3" >&2
rm -rf "$t"
return 1
fi
r=
while : ; do
touch "$4" || break
tee "$4" < "$t" >/dev/null || break
chmod 0644 "$4" || break
r=1
break ; done
if [ -z "$r" ] ; then
env printf 'unable to save OCSP response for %q into %q\n' "$2" "$4" >&2
rm -rf "$t"
return 1
fi
return 0
}
case "${cmd}" in
is-valid ) cmd_is_valid "${chain}" "${cert}" "${ocsp_resp}" ;;
is-expiring ) cmd_is_expiring "${chain}" "${cert}" "${ocsp_resp}" ;;
fetch ) cmd_fetch "${chain}" "${cert}" "${ocsp_uri}" "${ocsp_resp}" ;;
esac

8
scripts/pip-env.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -a
PIP_DISABLE_PIP_VERSION_CHECK=1
PIP_NO_CACHE_DIR=1
PIP_ROOT_USER_ACTION=ignore
PIP_NO_COMPILE=1
set +a
exec "$@"

9
scripts/python-rm-cache.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
set -f
for i ; do
[ -n "$i" ] || continue
[ -d "$i" ] || continue
find "$i/" -name __pycache__ -exec rm -rf {} +
find "$i/" ! -type d -name '*.py[co]' -exec rm -f {} +
done
exit 0

54
scripts/static-compress.sh Executable file
View File

@@ -0,0 +1,54 @@
#!/bin/sh
set -f
if command -v gzip >/dev/null ; then has_gzip=1 ; fi
if command -v brotli >/dev/null ; then has_brotli=1 ; fi
if command -v zstd >/dev/null ; then has_zstd=1 ; fi
do_gzip() { [ -s "$1.gz" ] || gzip -1kf "$1" || return ; comp_fixup "$1" "$1.gz" || rm -f "$1.gz" ; }
do_brotli() { [ -s "$1.br" ] || brotli -1kf "$1" || return ; comp_fixup "$1" "$1.br" || rm -f "$1.br" ; }
do_zstd() { [ -s "$1.zst" ] || zstd -q1kf "$1" || return ; comp_fixup "$1" "$1.zst" || rm -f "$1.zst" ; }
float_div() {
mawk -v "a=$1" -v "b=$2" 'BEGIN{print a/b;exit;}' </dev/null
}
comp_fixup() {
[ -f "$1" ] || return 1
size1=$(env stat -Lc '%s' "$1") || return 1
[ -n "${size1}" ] || return 1
[ "${size1}" != 0 ] || return 1
[ -f "$2" ] || return 1
size2=$(env stat -c '%s' "$2") || return 1
[ -n "${size2}" ] || return 1
[ "${size2}" != 0 ] || return 1
ratio=$(float_div "${size2}" "${size1}") || return 1
case "${ratio}" in
[0-9]*e-[0-9]* )
## doubtful but okay (c) Oleg Tinkov
;;
0.[0-8]* | 0.90* )
## compression ratio below 90% is fine
;;
* ) return 1 ;;
esac
return 0
}
for i ; do
[ -n "$i" ] || continue
case "$i" in
*.br | *.gz | *.zst ) continue ;;
esac
[ -f "$i" ] || continue
[ -s "$i" ] || continue
[ -z "${has_gzip}" ] || do_gzip "$i"
[ -z "${has_brotli}" ] || do_brotli "$i"
[ -z "${has_zstd}" ] || do_zstd "$i"
done