mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 05:45:13 +08:00
🍕 Sync 2026-09-14 23:30:37
This commit is contained in:
1 parent
0603b094cf
commit
81fe4cd866
214 files changed
+10806
-2630
No files matched your search
+4
-3
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
PKG_NAME:=openlist2
|
||||
PKG_VERSION:=4.2.6
|
||||
PKG_WEB_VERSION:=4.2.6
|
||||
PKG_RELEASE:=16
|
||||
PKG_RELEASE:=17
|
||||
|
||||
PKG_SOURCE:=openlist-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/OpenListTeam/OpenList/tar.gz/v$(PKG_VERSION)?
|
||||
@@ -51,8 +51,8 @@ define Package/openlist2
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=A file list program that supports multiple storage
|
||||
URL:=https://doc.oplist.org/
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +jshn +jsonfilter
|
||||
PROVIDES:=openlist2-helper
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +coreutils-stat +coreutils-timeout +jshn +jsonfilter +openssl-util
|
||||
PROVIDES:=openlist2-helper openlist2-tls
|
||||
endef
|
||||
|
||||
define Package/openlist2/conffiles
|
||||
@@ -90,6 +90,7 @@ define Package/openlist2/install
|
||||
$(INSTALL_CONF) $(CURDIR)/files/openlist2.config $(1)/etc/config/openlist2
|
||||
$(INSTALL_BIN) $(CURDIR)/files/openlist2.init $(1)/etc/init.d/openlist2
|
||||
$(INSTALL_DATA) $(CURDIR)/files/openlist2.common $(1)/usr/share/openlist2/functions.sh
|
||||
$(INSTALL_DATA) $(CURDIR)/files/openlist2.tls $(1)/usr/share/openlist2/tls.sh
|
||||
$(INSTALL_BIN) $(CURDIR)/files/openlist2.helper $(1)/usr/libexec/openlist2-helper
|
||||
$(INSTALL_BIN) $(CURDIR)/files/openlist2.defaults $(1)/etc/uci-defaults/99-openlist2
|
||||
$(INSTALL_CONF) $(CURDIR)/files/data.db $(1)/etc/openlist2/data.db
|
||||
|
||||
Binary file not shown.
@@ -147,7 +147,7 @@ openlist2_validate_dirs() {
|
||||
}
|
||||
|
||||
openlist2_prepare_dirs() {
|
||||
local entry identity previous registered marker="$data_dir/.temp-dir"
|
||||
local entry identity previous registered nonempty=0 marker="$data_dir/.temp-dir"
|
||||
umask 077
|
||||
mkdir -p "$data_dir" "$temp_dir" "$bleve_dir" ||
|
||||
{ openlist2_error "Unable to create data, cache or index directory."; return 1; }
|
||||
@@ -157,10 +157,17 @@ openlist2_prepare_dirs() {
|
||||
{ openlist2_error "config.json must be a regular file."; return 1; }
|
||||
[ ! -e "$marker" ] || [ -f "$marker" ] ||
|
||||
{ openlist2_error "Cache ownership marker must be a regular file."; return 1; }
|
||||
entry="$(find "$temp_dir" -mindepth 1 -maxdepth 1 -print -quit)" || return 1
|
||||
identity="$(stat -c '%d:%i' "$temp_dir")" || return 1
|
||||
# OpenWrt's BusyBox find may omit -quit. Include hidden entries and
|
||||
# dangling symlinks without depending on optional find applets.
|
||||
for entry in "$temp_dir"/* "$temp_dir"/.[!.]* "$temp_dir"/..?*; do
|
||||
[ -e "$entry" ] || [ -L "$entry" ] || continue
|
||||
nonempty=1
|
||||
break
|
||||
done
|
||||
identity="$(stat -c '%d:%i' "$temp_dir")" ||
|
||||
{ openlist2_error "Unable to identify the cache directory; ensure coreutils-stat is installed."; return 1; }
|
||||
registered="$(cat "$marker" 2>/dev/null)"
|
||||
if [ -n "$entry" ] && [ "$registered" != "$(printf '%s\n%s' "$temp_dir" "$identity")" ]; then
|
||||
if [ "$nonempty" = "1" ] && [ "$registered" != "$(printf '%s\n%s' "$temp_dir" "$identity")" ]; then
|
||||
# An existing config identifies the old cache on the first upgrade.
|
||||
# Once registered, an inode/device change must never inherit ownership.
|
||||
previous=""
|
||||
|
||||
@@ -35,6 +35,9 @@ config openlist2
|
||||
option listen_addr '0.0.0.0'
|
||||
option listen_http_port '5244'
|
||||
option listen_https_port '-1'
|
||||
# Leave both paths empty to manage self-signed certificates in data_dir/tls.
|
||||
option ssl_cert ''
|
||||
option ssl_key ''
|
||||
option listen_unix_file ''
|
||||
option listen_unix_file_perm ''
|
||||
option listen_enable_h2c '0'
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. /usr/share/openlist2/functions.sh
|
||||
. /usr/share/openlist2/tls.sh
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
@@ -211,16 +212,6 @@ validate_config() {
|
||||
openlist2_error "Force HTTPS and HTTP/3 require an enabled HTTPS port."
|
||||
return 1
|
||||
fi
|
||||
if [ "$https_port" != "-1" ] || { [ "$s3" = "1" ] && [ "$s3_ssl" = "1" ]; }; then
|
||||
local file
|
||||
for file in "$ssl_cert" "$ssl_key"; do
|
||||
case "$file" in /*) ;; *)
|
||||
openlist2_error "HTTPS/S3 TLS requires absolute certificate and key paths."; return 1 ;;
|
||||
esac
|
||||
[ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ] ||
|
||||
{ openlist2_error "TLS certificate/key is missing, empty or unreadable: $file"; return 1; }
|
||||
done
|
||||
fi
|
||||
if [ -n "$listen_unix_file" ]; then
|
||||
case "$listen_unix_file" in /*) ;; *)
|
||||
openlist2_error "Unix socket path must be absolute."; return 1 ;;
|
||||
@@ -257,7 +248,7 @@ validate_config() {
|
||||
openlist2_error "Log size must be at least 1 MB."
|
||||
return 1
|
||||
fi
|
||||
openlist2_validate_dirs
|
||||
openlist2_validate_dirs && openlist2_configure_tls
|
||||
}
|
||||
|
||||
write_config() (
|
||||
@@ -343,7 +334,7 @@ set_firewall() {
|
||||
return 0
|
||||
}
|
||||
|
||||
start_service() {
|
||||
start_openlist2() {
|
||||
openlist2_migrate_config || return 1
|
||||
config_load openlist2 || return 1
|
||||
section_id=""
|
||||
@@ -355,7 +346,7 @@ start_service() {
|
||||
external_access="deny" set_firewall
|
||||
return $?
|
||||
fi
|
||||
validate_config && openlist2_prepare_dirs || return 1
|
||||
validate_config && openlist2_prepare_dirs && openlist2_prepare_tls || return 1
|
||||
if [ -e /proc/uptime ]; then
|
||||
boot_uptime="$(awk -F. '{print $1}' /proc/uptime)"
|
||||
[ "$boot_uptime" -lt "120" ] || delayed_start=0
|
||||
@@ -552,6 +543,18 @@ start_service() {
|
||||
procd_close_instance openlist2
|
||||
}
|
||||
|
||||
start_service() {
|
||||
# rc.common closes the procd request even if start_service fails.
|
||||
# Preserve our result for its service_started hook instead of losing it.
|
||||
openlist2_start_status=0
|
||||
start_openlist2 "$@" || openlist2_start_status=$?
|
||||
return "$openlist2_start_status"
|
||||
}
|
||||
|
||||
service_started() {
|
||||
return "${openlist2_start_status:-1}"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "openlist2"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
#!/bin/sh
|
||||
# Sourced by the init script after functions.sh. Only runtime paths are changed;
|
||||
# empty UCI certificate paths continue to select automatic certificates.
|
||||
# The && chains deliberately fail if any preparation command fails.
|
||||
# shellcheck disable=SC2034,SC2154,SC2015
|
||||
|
||||
OPENLIST2_TLS_TIMEOUT=60
|
||||
OPENLIST2_TLS_RENEW_BEFORE=2592000
|
||||
|
||||
openlist2_tls_run() {
|
||||
timeout -k 1 "$OPENLIST2_TLS_TIMEOUT" "$@" </dev/null
|
||||
}
|
||||
|
||||
openlist2_tls_managed_paths_safe() {
|
||||
local path
|
||||
[ ! -L "$tls_dir" ] && { [ ! -e "$tls_dir" ] || [ -d "$tls_dir" ]; } &&
|
||||
! openlist2_mountpoint "$tls_dir" ||
|
||||
{ openlist2_error "Automatic TLS requires a dedicated directory without symlinks or mount roots: $tls_dir"; return 1; }
|
||||
for path in "$ssl_cert" "$ssl_key"; do
|
||||
[ ! -L "$path" ] && { [ ! -e "$path" ] || [ -f "$path" ]; } ||
|
||||
{ openlist2_error "Refusing an unsafe automatic TLS certificate/key path: $path"; return 1; }
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
openlist2_configure_tls() {
|
||||
local path directory protected
|
||||
tls_mode=off
|
||||
tls_dir=""
|
||||
if [ "$https_port" = "-1" ] && { [ "$s3" != "1" ] || [ "$s3_ssl" != "1" ]; }; then
|
||||
return 0
|
||||
fi
|
||||
if [ -z "$ssl_cert" ] && [ -z "$ssl_key" ]; then
|
||||
tls_mode=auto
|
||||
tls_dir="$data_dir/tls"
|
||||
ssl_cert="$tls_dir/openlist2.crt"
|
||||
ssl_key="$tls_dir/openlist2.key"
|
||||
openlist2_tls_managed_paths_safe || return 1
|
||||
for directory in "$temp_dir" "$bleve_dir" "$dist_dir"; do
|
||||
[ -n "$directory" ] || continue
|
||||
if openlist2_contains_path "$directory" "$tls_dir" ||
|
||||
openlist2_contains_path "$tls_dir" "$directory"; then
|
||||
openlist2_error "Automatic TLS directory must be separate from cache, index and public frontend directories."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
elif [ -n "$ssl_cert" ] && [ -n "$ssl_key" ]; then
|
||||
tls_mode=custom
|
||||
else
|
||||
openlist2_error "Leave both certificate paths empty for automatic TLS, or provide both custom certificate and key paths."
|
||||
return 1
|
||||
fi
|
||||
for path in "$ssl_cert" "$ssl_key"; do
|
||||
case "$path" in /*) ;; *)
|
||||
openlist2_error "TLS certificate and key paths must be absolute."; return 1 ;;
|
||||
esac
|
||||
protected="$(readlink -f "$path" 2>/dev/null)" || protected="$path"
|
||||
for directory in "$temp_dir" "$bleve_dir" "$dist_dir"; do
|
||||
[ -n "$directory" ] || continue
|
||||
if openlist2_contains_path "$directory" "$protected"; then
|
||||
openlist2_error "TLS files must not be inside cache, index or public frontend directories."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
openlist2_tls_hostname() {
|
||||
local hostname
|
||||
hostname="$(uci -q get 'system.@system[0].hostname')"
|
||||
case "$hostname" in ''|*[!A-Za-z0-9.-]*) hostname=openlist ;; esac
|
||||
if [ "${#hostname}" -gt 253 ] || ! printf '%s\n' "$hostname" |
|
||||
grep -Eq '^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$'; then
|
||||
hostname=openlist
|
||||
fi
|
||||
# Hostnames above are ASCII; minimal BusyBox tr may omit character classes.
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
printf '%s\n' "$hostname" | LC_ALL=C tr 'A-Z' 'a-z'
|
||||
}
|
||||
|
||||
openlist2_tls_lan_ip() (
|
||||
local address ip
|
||||
set -f
|
||||
# OpenWrt accepts a list of LAN addresses, optionally with CIDR suffixes.
|
||||
# shellcheck disable=SC2046
|
||||
for address in $(uci -q get network.lan.ipaddr); do
|
||||
ip="$(printf '%s\n' "${address%%/*}" | LC_ALL=C awk -F. '
|
||||
NF != 4 { exit 1 }
|
||||
{
|
||||
for (i = 1; i <= 4; i++)
|
||||
if ($i !~ /^[0-9]+$/ || length($i) > 3 || $i + 0 > 255) exit 1
|
||||
printf "%d.%d.%d.%d\n", $1, $2, $3, $4
|
||||
}
|
||||
')" || continue
|
||||
printf '%s\n' "$ip"
|
||||
exit 0
|
||||
done
|
||||
exit 0
|
||||
)
|
||||
|
||||
openlist2_tls_pair_valid() (
|
||||
local cert="$1" key="$2" min_lifetime="${3:-0}" hostname="${4:-}" ip="${5:-}"
|
||||
local work_dir cert_pub key_pub actual_san expected_san
|
||||
umask 077
|
||||
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/openlist2-tls-check.XXXXXX")" || exit 1
|
||||
trap 'rm -rf "$work_dir"' 0
|
||||
trap 'exit 1' HUP INT TERM
|
||||
# Arguments are expanded by the child shell, inside the timeout.
|
||||
# shellcheck disable=SC2016
|
||||
openlist2_tls_run /bin/sh -c '
|
||||
[ -f "$1" ] && [ -r "$1" ] && [ -s "$1" ] &&
|
||||
[ -f "$2" ] && [ -r "$2" ] && [ -s "$2" ]
|
||||
' openlist2-tls-check "$cert" "$key" 2>/dev/null &&
|
||||
openlist2_tls_run openssl x509 -in "$cert" -noout -pubkey -checkend "$min_lifetime" >"$work_dir/cert" 2>/dev/null &&
|
||||
openlist2_tls_run openssl pkey -in "$key" -pubout >"$work_dir/key.pub" 2>/dev/null &&
|
||||
openlist2_tls_run openssl verify -purpose sslserver -partial_chain -trusted "$cert" "$cert" >/dev/null 2>&1 || exit 1
|
||||
# Trusting the configured leaf here checks its dates and server purpose;
|
||||
# it does not install trust into the router or any browser.
|
||||
cert_pub="$(sed -n '/^-----BEGIN PUBLIC KEY-----$/,/^-----END PUBLIC KEY-----$/p' "$work_dir/cert")"
|
||||
key_pub="$(cat "$work_dir/key.pub")"
|
||||
[ -n "$cert_pub" ] && [ "$cert_pub" = "$key_pub" ] || exit 1
|
||||
if [ -n "$hostname" ]; then
|
||||
openlist2_tls_run openssl x509 -in "$cert" -noout -ext subjectAltName >"$work_dir/san" 2>/dev/null || exit 1
|
||||
actual_san="$(sed '1d' "$work_dir/san" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;/^$/d' | LC_ALL=C sort)"
|
||||
expected_san="$(
|
||||
{ printf 'DNS:%s\n' "$hostname"; [ -z "$ip" ] || printf 'IP Address:%s\n' "$ip"; } | LC_ALL=C sort
|
||||
)"
|
||||
[ "$actual_san" = "$expected_san" ] || exit 1
|
||||
fi
|
||||
exit 0
|
||||
)
|
||||
|
||||
openlist2_generate_tls() (
|
||||
local hostname ip cn san work_dir="" old_cert=0 old_key=0 replacing=0 committed=0
|
||||
local restore_ok keep_backup=0 status
|
||||
umask 077
|
||||
openlist2_tls_managed_paths_safe || exit 1
|
||||
mkdir -p "$tls_dir" && chmod 700 "$tls_dir" ||
|
||||
{ openlist2_error "Unable to prepare automatic TLS directory: $tls_dir"; exit 1; }
|
||||
hostname="$(openlist2_tls_hostname)"
|
||||
ip="$(openlist2_tls_lan_ip)"
|
||||
if openlist2_tls_pair_valid "$ssl_cert" "$ssl_key" "$OPENLIST2_TLS_RENEW_BEFORE" "$hostname" "$ip"; then
|
||||
chmod 600 "$ssl_key" && chmod 644 "$ssl_cert"
|
||||
exit $?
|
||||
fi
|
||||
work_dir="$(mktemp -d "$tls_dir/.generate.XXXXXX")" ||
|
||||
{ openlist2_error "Unable to stage automatic TLS certificate files."; exit 1; }
|
||||
# Invoked through the EXIT trap, including interrupted replacements.
|
||||
# shellcheck disable=SC2329
|
||||
openlist2_tls_cleanup() {
|
||||
status=$?
|
||||
trap - 0 HUP INT TERM
|
||||
if [ "$replacing" = "1" ] && [ "$committed" != "1" ]; then
|
||||
restore_ok=1
|
||||
if [ "$old_key" = "1" ]; then
|
||||
mv -f "$work_dir/previous.key" "$ssl_key" || restore_ok=0
|
||||
else
|
||||
rm -f "$ssl_key" || restore_ok=0
|
||||
fi
|
||||
if [ "$old_cert" = "1" ]; then
|
||||
mv -f "$work_dir/previous.crt" "$ssl_cert" || restore_ok=0
|
||||
else
|
||||
rm -f "$ssl_cert" || restore_ok=0
|
||||
fi
|
||||
if [ "$restore_ok" != "1" ]; then
|
||||
keep_backup=1
|
||||
status=1
|
||||
openlist2_error "Unable to restore the previous TLS files; recovery files retained at $work_dir"
|
||||
fi
|
||||
fi
|
||||
[ "$keep_backup" = "1" ] || rm -rf "$work_dir"
|
||||
exit "$status"
|
||||
}
|
||||
trap openlist2_tls_cleanup 0
|
||||
trap 'exit 1' HUP INT TERM
|
||||
cn="${ip:-$hostname}"
|
||||
[ "${#cn}" -le 64 ] || cn=OpenList
|
||||
san="DNS:$hostname"
|
||||
[ -z "$ip" ] || san="$san,IP:$ip"
|
||||
openlist2_tls_run openssl req -x509 -nodes -newkey ec \
|
||||
-pkeyopt ec_paramgen_curve:prime256v1 -pkeyopt ec_param_enc:named_curve \
|
||||
-sha256 -days 3650 -keyout "$work_dir/new.key" -out "$work_dir/new.crt" \
|
||||
-subj "/CN=$cn" -addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=digitalSignature" -addext "extendedKeyUsage=serverAuth" \
|
||||
-addext "subjectAltName=$san" >/dev/null 2>&1 ||
|
||||
{ openlist2_error "Unable to generate an automatic TLS certificate."; exit 1; }
|
||||
openlist2_tls_pair_valid "$work_dir/new.crt" "$work_dir/new.key" "$OPENLIST2_TLS_RENEW_BEFORE" "$hostname" "$ip" &&
|
||||
chmod 600 "$work_dir/new.key" && chmod 644 "$work_dir/new.crt" ||
|
||||
{ openlist2_error "Unable to validate the generated TLS certificate and key."; exit 1; }
|
||||
openlist2_tls_managed_paths_safe || exit 1
|
||||
if [ -f "$ssl_cert" ]; then
|
||||
cp -p "$ssl_cert" "$work_dir/previous.crt" ||
|
||||
{ openlist2_error "Unable to back up the previous TLS certificate."; exit 1; }
|
||||
old_cert=1
|
||||
fi
|
||||
if [ -f "$ssl_key" ]; then
|
||||
cp -p "$ssl_key" "$work_dir/previous.key" ||
|
||||
{ openlist2_error "Unable to back up the previous TLS key."; exit 1; }
|
||||
old_key=1
|
||||
fi
|
||||
replacing=1
|
||||
mv -f "$work_dir/new.key" "$ssl_key" && mv -f "$work_dir/new.crt" "$ssl_cert" ||
|
||||
{ openlist2_error "Unable to install the generated TLS certificate pair; restoring previous files."; exit 1; }
|
||||
committed=1
|
||||
logger -t openlist2 "Generated automatic TLS certificate in $tls_dir"
|
||||
exit 0
|
||||
)
|
||||
|
||||
openlist2_prepare_tls() {
|
||||
[ "$tls_mode" != "off" ] || return 0
|
||||
command -v openssl >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1 ||
|
||||
{ openlist2_error "TLS requires openssl-util and coreutils-timeout."; return 1; }
|
||||
if [ "$tls_mode" = "auto" ]; then
|
||||
openlist2_generate_tls
|
||||
else
|
||||
openlist2_tls_pair_valid "$ssl_cert" "$ssl_key" ||
|
||||
{ openlist2_error "Custom TLS certificate/key is missing, unreadable, invalid, expired or mismatched; custom files were not changed."; return 1; }
|
||||
fi
|
||||
}
|
||||
Reference in new issue
Block a user