@@ -10,6 +10,8 @@ NC='\033[0m'
1010
1111AMNEZIAWG_DIR=" /etc/amnezia/amneziawg"
1212WEB_PANEL_CONFIG_DIR=" ${AMNEZIAWG_DIR} /clients"
13+ WEB_PANEL_ENV_FILE=" /etc/amneziawg-web/env.conf"
14+ WEB_PANEL_SYSTEMD_UNIT=" /etc/systemd/system/amneziawg-web.service"
1315
1416# Ensure sbin directories are in PATH for depmod, modprobe, sysctl, etc.
1517# Some minimal or non-login root shells may not include these by default.
@@ -1634,26 +1636,93 @@ function detectPublicIPv4() {
16341636 return 0
16351637}
16361638
1639+ # Resolve the web panel's active config directory without sourcing its env file.
1640+ # A custom web installer --env-file is recorded in the installed service unit,
1641+ # while AWG_CONFIG_DIR itself is recorded in that root-controlled env file.
1642+ function resolveWebPanelConfigDir() {
1643+ local env_file="${WEB_PANEL_ENV_FILE} "
1644+ local configured_env configured_dir env_file_required=0 env_file_optional=0
1645+
1646+ if [[ -L "${WEB_PANEL_SYSTEMD_UNIT} " ]]; then
1647+ echo "ERROR: refusing unsafe web panel service unit '${WEB_PANEL_SYSTEMD_UNIT} '" >& 2
1648+ return 1
1649+ fi
1650+ if [[ -e "${WEB_PANEL_SYSTEMD_UNIT} " ]]; then
1651+ if [[ ! -f "${WEB_PANEL_SYSTEMD_UNIT} " ]]; then
1652+ echo "ERROR: refusing unsafe web panel service unit '${WEB_PANEL_SYSTEMD_UNIT} '" >& 2
1653+ return 1
1654+ fi
1655+ configured_env="$(sed -n 's/^[[:space:]]*EnvironmentFile=//p' "${WEB_PANEL_SYSTEMD_UNIT} " 2 >/ dev/ null | tail - n 1 )"
1656+ if [[ "${configured_env} " == -* ]]; then
1657+ env_file_optional=1
1658+ configured_env="${configured_env# -} "
1659+ fi
1660+ configured_env="${configured_env# \" } "
1661+ configured_env="${configured_env% \" } "
1662+ configured_env="${configured_env# \' } "
1663+ configured_env="${configured_env% \' } "
1664+ if [[ -n "${configured_env} " ]]; then
1665+ if [[ "${configured_env} " != /* || "${configured_env} " =~ [[: space: ][: cntrl: ]] ]]; then
1666+ echo "ERROR: refusing unsafe web panel environment path '${configured_env} '" >& 2
1667+ return 1
1668+ fi
1669+ env_file="${configured_env} "
1670+ env_file_required=1
1671+ fi
1672+ fi
1673+
1674+ if [[ -L "${env_file} " ]]; then
1675+ echo "ERROR: refusing unsafe web panel environment file '${env_file} '" >& 2
1676+ return 1
1677+ fi
1678+ if [[ -e "${env_file} " ]]; then
1679+ if [[ ! -f "${env_file} " ]]; then
1680+ echo "ERROR: refusing unsafe web panel environment file '${env_file} '" >& 2
1681+ return 1
1682+ fi
1683+ configured_dir="$(sed -n 's/^AWG_CONFIG_DIR=//p' "${env_file} " 2 >/ dev/ null | tail - n 1 )"
1684+ configured_dir="${configured_dir# \" } "
1685+ configured_dir="${configured_dir% \" } "
1686+ configured_dir="${configured_dir# \' } "
1687+ configured_dir="${configured_dir% \' } "
1688+ if [[ -n "${configured_dir} " ]]; then
1689+ if [[ "${configured_dir} " != /* || "${configured_dir} " =~ [[: space: ][: cntrl: ]] ]]; then
1690+ echo "ERROR: refusing unsafe AWG_CONFIG_DIR '${configured_dir} '" >& 2
1691+ return 1
1692+ fi
1693+ printf '%s\n' "${configured_dir%/ } "
1694+ return 0
1695+ fi
1696+ elif [[ "${env_file_required} " - eq 1 && "${env_file_optional} " - eq 0 ]]; then
1697+ echo "ERROR: web panel environment file '${env_file} ' does not exist" >& 2
1698+ return 1
1699+ fi
1700+
1701+ printf '%s\n' "${WEB_PANEL_CONFIG_DIR%/ } "
1702+ }
1703+
16371704# Copy a client config file to the web panel config directory so the panel
16381705# can discover and display it. This is a best-effort operation: if the web
16391706# panel is not installed (directory absent), the copy is silently skipped.
16401707function copyToWebPanelDir() {
16411708 local src_file="$1 "
1642- if [[ -d "${WEB_PANEL_CONFIG_DIR} " && ! - L "${WEB_PANEL_CONFIG_DIR} " && - f "${src_file} " && ! - L "${src_file} " ]]; then
1709+ local panel_config_dir
1710+ panel_config_dir="$(resolveWebPanelConfigDir)" || return 0
1711+ if [[ -d "${panel_config_dir} " && ! - L "${panel_config_dir} " && - f "${src_file} " && ! - L "${src_file} " ]]; then
16431712 local dest
1644- dest="${WEB_PANEL_CONFIG_DIR } / $(basename "${src_file} ")"
1713+ dest="${panel_config_dir } / $(basename "${src_file} ")"
16451714 # Avoid following or overwriting a pre-existing symlink at the destination.
16461715 if [[ -L "${dest} " ]]; then
16471716 # Best-effort: warn and skip rather than risk clobbering the symlink target.
16481717 echo "Warning: refusing to copy '${src_file} ' to '${dest} ' because destination is a symlink" >& 2
16491718 return 0
16501719 fi
1651- cp -f "${src_file} " "${WEB_PANEL_CONFIG_DIR} / " 2 >/ dev/ null || true
1720+ cp -f "${src_file} " "${dest} " 2 >/ dev/ null || true
16521721 # Only adjust ownership and permissions on a regular non-symlink file we just copied.
16531722 if [[ -f "${dest} " && ! - L "${dest} " ]]; then
16541723 # Determine the directory's group; use it if available, otherwise fall back to root.
16551724 local dir_group dest_group
1656- dir_group="$(stat -c '%G' "${WEB_PANEL_CONFIG_DIR } " 2 >/ dev/ null || true)"
1725+ dir_group="$(stat -c '%G' "${panel_config_dir } " 2 >/ dev/ null || true)"
16571726 if [[ -n "${dir_group} " ]]; then
16581727 dest_group="${dir_group} "
16591728 else
@@ -1669,8 +1738,10 @@ function copyToWebPanelDir() {
16691738# Remove a client config file from the web panel config directory.
16701739function removeFromWebPanelDir() {
16711740 local filename="$1 "
1672- if [[ -d "${WEB_PANEL_CONFIG_DIR} " && ! - L "${WEB_PANEL_CONFIG_DIR} " ]]; then
1673- rm -f -- "${WEB_PANEL_CONFIG_DIR} / ${filename} " 2 >/ dev/ null || true
1741+ local panel_config_dir
1742+ panel_config_dir="$(resolveWebPanelConfigDir)" || return 0
1743+ if [[ -d "${panel_config_dir} " && ! - L "${panel_config_dir} " ]]; then
1744+ rm -f -- "${panel_config_dir} / ${filename} " 2 >/ dev/ null || true
16741745 fi
16751746}
16761747
@@ -5711,8 +5782,9 @@ CLIENT_LIFECYCLE_LOCK_FD=""
57115782# lock pathname. The caller runs in a subshell so the descriptor, and therefore
57125783# the lock, is released on every success, return, or exit path.
57135784function acquireClientLifecycleLock() {
5714- local lock_dir= " ${WEB_PANEL_CONFIG_DIR} "
5785+ local lock_dir
57155786 local old_umask dir_identity descriptor_identity descriptor_path
5787+ lock_dir=" $( resolveWebPanelConfigDir) " || return 1
57165788
57175789 if ! command -v flock > /dev/null 2>&1 ; then
57185790 echo " ERROR: flock is required for serialized client lifecycle operations" >&2
0 commit comments