🍕 Sync 2026-09-14 23:30:37

This commit is contained in:
github-actions[bot] committed 2026-09-14 23:30:37 +08:00
1 parent 0603b094cf
commit 81fe4cd866
214 files changed
+10806 -2630

No files matched your search

+4 -3
View File
@@ -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.
+11 -4
View File
@@ -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=""
+3
View File
@@ -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'
+16 -13
View File
@@ -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"
}
+220
View File
@@ -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
}