✨ Sync 2026-08-07 10:27:26

This commit is contained in:
github-actions[bot] committed 2026-08-07 10:27:26 +08:00
1 parent e5abd5d15c
commit 41eaf923aa
10 files changed
+402 -176

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=gecoosac
PKG_VERSION:=2.2.20251015
PKG_RELEASE:=15
PKG_RELEASE:=16
PKG_MAINTAINER:=Roc Lai <laipeng668@qq.com>
PKG_LICENSE:=AGPL-3.0-only
+71 -32
View File
@@ -332,8 +332,6 @@ generate_default_cert() {
return 0
fi
mkdir -p /etc/gecoosac/tls
cert_cn="${cert_ip:-$cert_host}"
cert_san="DNS:$cert_host"
[ -n "$cert_ip" ] && cert_san="${cert_san},IP:${cert_ip}"
@@ -371,6 +369,8 @@ generate_default_cert() {
}
normalize_conf() {
[ "$isonlyoneprot" = "0" ] || isonlyoneprot="1"
[ "$https" = "1" ] || https="0"
if is_safe_upload_dir "$upload_dir"; then
upload_dir="$(normalize_path "$upload_dir")"
else
@@ -383,14 +383,16 @@ normalize_conf() {
logger -t gecoosac "refusing unsupported database directory: $db_dir"
return 1
fi
is_abs_path "$crt_file" || {
logger -t gecoosac "refusing non-absolute certificate path: $crt_file"
return 1
}
is_abs_path "$key_file" || {
logger -t gecoosac "refusing non-absolute key path: $key_file"
return 1
}
if [ "$isonlyoneprot" = "0" ] && [ "$https" = "1" ]; then
is_abs_path "$crt_file" || {
logger -t gecoosac "refusing non-absolute certificate path: $crt_file"
return 1
}
is_abs_path "$key_file" || {
logger -t gecoosac "refusing non-absolute key path: $key_file"
return 1
}
fi
if is_safe_pid_dir "$piddir" "$upload_dir"; then
piddir="$(normalize_path "$piddir")"
else
@@ -401,14 +403,14 @@ normalize_conf() {
logger -t gecoosac "refusing invalid interface port: $port"
return 1
}
is_port "$m_port" || {
logger -t gecoosac "refusing invalid management port: $m_port"
return 1
}
if [ "$isonlyoneprot" = "0" ]; then
is_port "$m_port" || {
logger -t gecoosac "refusing invalid management port: $m_port"
return 1
}
fi
[ "$enabled" = "1" ] || enabled="0"
[ "$isonlyoneprot" = "0" ] || isonlyoneprot="1"
[ "$https" = "1" ] || https="0"
case "$lang" in
zh|en) ;;
*) lang="$DEFAULT_LANG" ;;
@@ -419,22 +421,17 @@ normalize_conf() {
}
ensure_dirs() {
local path
path="$(normalize_path "$upload_dir")" || return 1
if ! ensure_dir_tree "$path" || ! mkdir -p "$db_dir" "$piddir" /etc/gecoosac/tls; then
if ! ensure_managed_dir upload "$upload_dir" || \
! ensure_managed_dir db "$db_dir" || \
! ensure_managed_dir pid "$piddir" || \
! ensure_managed_dir tls /etc/gecoosac/tls; then
logger -t gecoosac "failed to create runtime directories"
return 1
fi
chmod go-w "$path" || return 1
is_secure_upload_dir "$path" || {
logger -t gecoosac "upload directory or its parent is not root-owned and private: $path"
return 1
}
}
ensure_dir_tree() {
local path current part rest
ensure_secure_dir_tree() {
local path current part rest mode
path="$(normalize_path "$1")" || return 1
current="/"
@@ -451,11 +448,53 @@ ensure_dir_tree() {
if [ -e "$current" ]; then
[ -d "$current" ] || return 1
else
mkdir "$current" || return 1
mode=0755
[ -n "$rest" ] || mode=0750
mkdir -m "$mode" "$current" || return 1
fi
case "$current" in
/tmp) is_secure_dir "$current" 1 || return 1 ;;
*) is_secure_dir "$current" || return 1 ;;
esac
done
}
managed_dir_path() {
local role="$1" path="$2" anchor
case "$role:$path" in
db:/var/lib/gecoosac|db:/var/lib/gecoosac/*)
anchor="$(readlink -f /var 2>/dev/null)" || return 1
case "$anchor" in
/var|/tmp) printf '%s%s\n' "$anchor" "${path#/var}" ;;
*) return 1 ;;
esac
;;
pid:/var/run|pid:/var/run/*)
anchor="$(readlink -f /var/run 2>/dev/null)" || return 1
[ "$anchor" = "/tmp/run" ] || return 1
printf '%s%s\n' "$anchor" "${path#/var/run}"
;;
*) printf '%s\n' "$path" ;;
esac
}
ensure_managed_dir() {
local role="$1" path physical
path="$(normalize_path "$2")" || return 1
case "$role" in
upload) is_safe_upload_dir "$path" || return 1 ;;
db) is_safe_db_dir "$path" "$upload_dir" || return 1 ;;
pid) is_safe_pid_dir "$path" "$upload_dir" || return 1 ;;
tls) [ "$path" = "/etc/gecoosac/tls" ] || return 1 ;;
*) return 1 ;;
esac
physical="$(managed_dir_path "$role" "$path")" || return 1
ensure_secure_dir_tree "$physical" || return 1
[ -d "$path" ]
}
prepare_service() {
init_conf
[ "$enabled" = "1" ] || return 0
@@ -528,16 +567,16 @@ wait_service_stopped() {
local i
if ! type service_running >/dev/null 2>&1; then
return 0
return 1
fi
i=0
while [ "$i" -lt 5 ]; do
service_running gecoosac || return 0
while service_running gecoosac; do
[ "$i" -ge 5 ] && return 1
sleep 1
i=$((i + 1))
done
return 1
return 0
}
reload_service() {
+72 -54
View File
@@ -125,15 +125,14 @@ normalize_upload_dir() {
upload_dir="$(uci -q get gecoosac.config.upload_dir)"
[ -n "$upload_dir" ] || return 0
if is_safe_upload_dir "$upload_dir"; then
normalized="$(normalize_path "$upload_dir")"
else
return 0
fi
normalized="$(normalize_path "$upload_dir")" || return 0
case "$normalized" in
/etc/gecoosac/upload) normalized="$DEFAULT_UPLOAD_DIR" ;;
*) is_safe_upload_dir "$normalized" || return 0 ;;
esac
[ "$upload_dir" = "$normalized" ] && return 0
uci -q set "gecoosac.config.upload_dir=${normalized}"
uci -q set "gecoosac.config.upload_dir=${normalized}" || return 1
changed=1
}
@@ -158,73 +157,90 @@ normalize_dir_option() {
changed=1
}
is_managed_cert_path() {
case "$1" in
""|"$2"|"$3") return 0 ;;
esac
return 1
}
is_regular_file_or_absent() {
[ ! -e "$1" ] && [ ! -L "$1" ] && return 0
[ -f "$1" ] && [ ! -L "$1" ]
}
migrate_legacy_cert_paths() {
local crt_file key_file migrate
local crt_file key_file old_crt old_key new_crt new_key path
crt_file="$(uci -q get gecoosac.config.crt_file)"
key_file="$(uci -q get gecoosac.config.key_file)"
migrate=0
is_managed_cert_path "$crt_file" "$OLD_CRT_FILE" "$DEFAULT_CRT_FILE" || return 0
is_managed_cert_path "$key_file" "$OLD_KEY_FILE" "$DEFAULT_KEY_FILE" || return 0
if [ "$crt_file" = "$OLD_CRT_FILE" ] && [ -z "$key_file" ]; then
uci -q set "gecoosac.config.key_file=${OLD_KEY_FILE}" || return 1
key_file="$OLD_KEY_FILE"
changed=1
elif [ -z "$crt_file" ] && [ "$key_file" = "$OLD_KEY_FILE" ]; then
uci -q set "gecoosac.config.crt_file=${OLD_CRT_FILE}" || return 1
crt_file="$OLD_CRT_FILE"
for path in "$OLD_CRT_FILE" "$OLD_KEY_FILE" "$DEFAULT_CRT_FILE" "$DEFAULT_KEY_FILE"; do
is_regular_file_or_absent "$path" || {
logger -t gecoosac "refusing unsafe certificate migration path: $path"
return 1
}
done
old_crt=0
old_key=0
new_crt=0
new_key=0
[ -f "$OLD_CRT_FILE" ] && old_crt=1
[ -f "$OLD_KEY_FILE" ] && old_key=1
[ -f "$DEFAULT_CRT_FILE" ] && new_crt=1
[ -f "$DEFAULT_KEY_FILE" ] && new_key=1
if { [ "$old_crt" = "1" ] && [ "$new_crt" = "1" ]; } || \
{ [ "$old_key" = "1" ] && [ "$new_key" = "1" ]; }; then
logger -t gecoosac "refusing conflicting legacy and current certificate files"
return 1
fi
if [ "$old_crt" = "1" ] && [ "$new_key" = "1" ]; then
logger -t gecoosac "refusing reverse-split certificate migration state"
return 1
fi
if [ $((old_crt + new_crt)) -ne $((old_key + new_key)) ]; then
logger -t gecoosac "refusing incomplete certificate migration state"
return 1
fi
if [ "$old_crt" = "1" ]; then
mv "$OLD_CRT_FILE" "$DEFAULT_CRT_FILE" || return 1
fi
if [ "$old_key" = "1" ]; then
mv "$OLD_KEY_FILE" "$DEFAULT_KEY_FILE" || return 1
fi
if [ -f "$DEFAULT_CRT_FILE" ]; then
chmod 644 "$DEFAULT_CRT_FILE" || return 1
chmod 600 "$DEFAULT_KEY_FILE" || return 1
fi
if [ "$crt_file" != "$DEFAULT_CRT_FILE" ]; then
uci -q set "gecoosac.config.crt_file=${DEFAULT_CRT_FILE}" || return 1
changed=1
fi
if [ "$crt_file" = "$OLD_CRT_FILE" ] && [ "$key_file" = "$OLD_KEY_FILE" ]; then
migrate=1
elif [ -z "$crt_file" ] && [ -z "$key_file" ]; then
[ -f "$OLD_CRT_FILE" ] && [ -f "$OLD_KEY_FILE" ] || return 0
migrate=1
if [ "$key_file" != "$DEFAULT_KEY_FILE" ]; then
uci -q set "gecoosac.config.key_file=${DEFAULT_KEY_FILE}" || return 1
changed=1
fi
[ "$migrate" = "1" ] || return 0
[ -f "$OLD_CRT_FILE" ] && [ ! -L "$OLD_CRT_FILE" ] || return 0
[ -f "$OLD_KEY_FILE" ] && [ ! -L "$OLD_KEY_FILE" ] || return 0
[ ! -e "$DEFAULT_CRT_FILE" ] && [ ! -L "$DEFAULT_CRT_FILE" ] || return 0
[ ! -e "$DEFAULT_KEY_FILE" ] && [ ! -L "$DEFAULT_KEY_FILE" ] || return 0
mkdir -p /etc/gecoosac/tls || {
logger -t gecoosac "unable to prepare TLS directory for legacy certificate migration"
return 1
}
if ! mv "$OLD_CRT_FILE" "$DEFAULT_CRT_FILE"; then
logger -t gecoosac "unable to migrate legacy certificate"
return 1
fi
if ! mv "$OLD_KEY_FILE" "$DEFAULT_KEY_FILE"; then
mv "$DEFAULT_CRT_FILE" "$OLD_CRT_FILE" 2>/dev/null
logger -t gecoosac "unable to migrate legacy private key"
return 1
fi
if ! chmod 644 "$DEFAULT_CRT_FILE" || ! chmod 600 "$DEFAULT_KEY_FILE" || \
! uci -q set "gecoosac.config.crt_file=${DEFAULT_CRT_FILE}" || \
! uci -q set "gecoosac.config.key_file=${DEFAULT_KEY_FILE}"; then
mv "$DEFAULT_KEY_FILE" "$OLD_KEY_FILE" 2>/dev/null
mv "$DEFAULT_CRT_FILE" "$OLD_CRT_FILE" 2>/dev/null
logger -t gecoosac "unable to complete legacy certificate migration"
return 1
fi
changed=1
}
migrate_config() {
local compat
migrate_legacy_cert_paths || return 1
compat="$(uci -q get gecoosac.config.config_compat)"
[ "$compat" = "$CONFIG_COMPAT" ] && return 0
migrate_legacy_cert_paths || return 1
uci -q set "gecoosac.config.config_compat=${CONFIG_COMPAT}" || return 1
changed=1
}
ensure_section
migrate_config || exit 1
normalize_upload_dir
normalize_upload_dir || exit 1
normalize_dir_option db_dir "$DEFAULT_DB_DIR" is_safe_db_dir
normalize_dir_option piddir "$DEFAULT_PID_DIR" is_safe_pid_dir
set_default enabled 0
@@ -243,6 +259,8 @@ set_default debug 0
set_default showtip 0
set_default log 0
[ "$changed" = "1" ] && uci -q commit gecoosac
if [ "$changed" = "1" ]; then
uci -q commit gecoosac || exit 1
fi
exit 0