dea6f27b4d
- lib/domain-discovery.sh: Added -- to grep command (1 fix) - lib/reference-db.sh: Added -- to grep command (1 fix) - lib/user-manager.sh: Added -- to grep command (1 fix) - lib/email-functions.sh: Added -- to awk and grep commands (2 fixes) - lib/php-config-manager.sh: Added -- to grep commands (3 fixes) - lib/php-detector.sh: Added -- to grep command (1 fix) Total: 9 ESCAPE fixes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
499 lines
16 KiB
Bash
499 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
#############################################################################
|
|
# Unified Domain/User Discovery Library
|
|
# Abstracts control panel differences for consistent domain/user enumeration
|
|
#############################################################################
|
|
|
|
# Source dependencies
|
|
if [ -z "$TOOLKIT_BASE_DIR" ]; then
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
[ -f "$SCRIPT_DIR/common-functions.sh" ] && source "$SCRIPT_DIR/common-functions.sh" || { echo "ERROR: common-functions.sh not found" >&2; return 1; }
|
|
[ -f "$SCRIPT_DIR/system-detect.sh" ] && source "$SCRIPT_DIR/system-detect.sh" || { echo "ERROR: system-detect.sh not found" >&2; return 1; }
|
|
fi
|
|
|
|
# Source control panel helpers if available
|
|
if [ "$SYS_CONTROL_PANEL" = "plesk" ]; then
|
|
# Try LIB_DIR first, then SCRIPT_DIR
|
|
if [ -n "$LIB_DIR" ] && [ -f "$LIB_DIR/plesk-helpers.sh" ]; then
|
|
source "$LIB_DIR/plesk-helpers.sh"
|
|
elif [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/plesk-helpers.sh" ]; then
|
|
source "$SCRIPT_DIR/plesk-helpers.sh"
|
|
fi
|
|
fi
|
|
|
|
#############################################################################
|
|
# DOMAIN DISCOVERY (Control Panel Agnostic)
|
|
#############################################################################
|
|
|
|
# List all domains on the server
|
|
# Returns: One domain per line
|
|
list_all_domains() {
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
# cPanel: /etc/userdomains maps domains to users
|
|
if [ -f /etc/userdomains ]; then
|
|
awk -F': ' '{print $1}' /etc/userdomains | grep -v "^\*" | sort -u
|
|
else
|
|
# Fallback: scan /var/cpanel/users/
|
|
for user_file in /var/cpanel/users/*; do
|
|
[ -f "$user_file" ] && grep "^DNS=" -- "$user_file" | cut -d'=' -f2
|
|
done | sort -u
|
|
fi
|
|
;;
|
|
|
|
plesk)
|
|
# Use plesk_list_domains if available, otherwise fallback
|
|
if type plesk_list_domains >/dev/null 2>&1; then
|
|
plesk_list_domains
|
|
else
|
|
# Fallback: scan vhosts directory
|
|
ls -1 /var/www/vhosts/ 2>/dev/null | \
|
|
grep -v "^system$\|^chroot$\|^\.skel$\|^default$\|^fs$" | \
|
|
grep -v "^\." || true
|
|
fi
|
|
;;
|
|
|
|
interworx)
|
|
# InterWorx: nodeworx CLI or directory scan
|
|
if command_exists nodeworx; then
|
|
nodeworx -u -n -c Siteworx -a list 2>/dev/null | tail -n +2 | awk '{print $2}'
|
|
else
|
|
# Fallback: scan /chroot/home/*/var/
|
|
find /chroot/home/*/var/* -maxdepth 0 -type d 2>/dev/null | \
|
|
awk -F'/' '{print $(NF)}' | sort -u
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
# Standalone: scan common web directories
|
|
{
|
|
find /var/www/html/*/public_html -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $(NF-1)}'
|
|
find /home/*/public_html -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $(NF-1)}'
|
|
find /var/www/*/public_html -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $(NF-1)}'
|
|
} | sort -u
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get document root for a domain
|
|
# Usage: get_domain_docroot DOMAIN
|
|
# Returns: /path/to/document/root
|
|
get_domain_docroot() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
# cPanel: Get user from domain, then home dir
|
|
local user=$(grep "^${domain}:" /etc/userdomains 2>/dev/null | awk -F': ' '{print $2}')
|
|
if [ -n "$user" ]; then
|
|
# Check if it's the main domain or addon
|
|
local user_data="/var/cpanel/users/$user"
|
|
if [ -f "$user_data" ]; then
|
|
local main_domain=$(grep "^DNS=" "$user_data" | cut -d'=' -f2)
|
|
if [ "$domain" = "$main_domain" ]; then
|
|
echo "/home/$user/public_html"
|
|
else
|
|
# Addon domain or subdomain
|
|
local docroot=$(grep -A1 "^${domain}:" /var/cpanel/userdata/$user/*.yaml 2>/dev/null | \
|
|
grep "documentroot:" | head -1 | awk '{print $2}')
|
|
[ -n "$docroot" ] && echo "$docroot" || echo "/home/$user/public_html/$domain"
|
|
fi
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_docroot "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
# InterWorx: /chroot/home/USER/var/DOMAIN/html
|
|
local user=$(find /chroot/home/*/var/$domain -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $4}' | head -1)
|
|
[ -n "$user" ] && echo "/chroot/home/$user/var/$domain/html"
|
|
;;
|
|
|
|
*)
|
|
# Standalone: common patterns
|
|
for path in \
|
|
"/var/www/html/$domain/public_html" \
|
|
"/var/www/$domain/public_html" \
|
|
"/home/$domain/public_html" \
|
|
"/var/www/html/$domain" \
|
|
"/var/www/$domain" \
|
|
"/home/$domain/html"; do
|
|
[ -d "$path" ] && echo "$path" && return 0
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get log directory for a domain
|
|
# Usage: get_domain_logdir DOMAIN
|
|
# Returns: /path/to/logs
|
|
get_domain_logdir() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
# cPanel: /var/log/apache2/domlogs/ or /usr/local/apache/domlogs/
|
|
if [ -d "/var/log/apache2/domlogs" ]; then
|
|
echo "/var/log/apache2/domlogs"
|
|
elif [ -d "/usr/local/apache/domlogs" ]; then
|
|
echo "/usr/local/apache/domlogs"
|
|
fi
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_logdir "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
# InterWorx: /chroot/home/USER/var/DOMAIN/logs
|
|
local user=$(find /chroot/home/*/var/$domain -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $4}' | head -1)
|
|
[ -n "$user" ] && [ -d "/chroot/home/$user/var/$domain/logs" ] && \
|
|
echo "/chroot/home/$user/var/$domain/logs"
|
|
;;
|
|
|
|
*)
|
|
# Standalone: common log locations
|
|
for logdir in \
|
|
"/var/log/httpd" \
|
|
"/var/log/apache2" \
|
|
"/var/log/nginx"; do
|
|
[ -d "$logdir" ] && echo "$logdir" && return 0
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get access log path for a domain
|
|
# Usage: get_domain_access_log DOMAIN [ssl]
|
|
# Returns: /path/to/access_log
|
|
get_domain_access_log() {
|
|
local domain="$1"
|
|
local ssl="${2:-}"
|
|
local logdir
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
logdir=$(get_domain_logdir "$domain")
|
|
[ -z "$logdir" ] && return 1
|
|
if [ "$ssl" = "ssl" ]; then
|
|
echo "$logdir/${domain}-ssl_log"
|
|
else
|
|
echo "$logdir/${domain}"
|
|
fi
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_access_log "$domain" "$ssl"
|
|
;;
|
|
|
|
interworx)
|
|
logdir=$(get_domain_logdir "$domain")
|
|
[ -z "$logdir" ] && return 1
|
|
echo "$logdir/access_log"
|
|
;;
|
|
|
|
*)
|
|
# Standalone: guess based on web server
|
|
if [ "$SYS_WEB_SERVER" = "nginx" ]; then
|
|
echo "/var/log/nginx/access.log"
|
|
else
|
|
echo "/var/log/httpd/access_log"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get error log path for a domain
|
|
# Usage: get_domain_error_log DOMAIN
|
|
# Returns: /path/to/error_log
|
|
get_domain_error_log() {
|
|
local domain="$1"
|
|
local logdir
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
logdir=$(get_domain_logdir "$domain")
|
|
[ -z "$logdir" ] && return 1
|
|
echo "$logdir/${domain}-error_log"
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_error_log "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
logdir=$(get_domain_logdir "$domain")
|
|
[ -z "$logdir" ] && return 1
|
|
echo "$logdir/error_log"
|
|
;;
|
|
|
|
*)
|
|
# Standalone: guess based on web server
|
|
if [ "$SYS_WEB_SERVER" = "nginx" ]; then
|
|
echo "/var/log/nginx/error.log"
|
|
else
|
|
echo "/var/log/httpd/error_log"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get all log file paths (access and error logs for all domains)
|
|
# Returns: One log file path per line
|
|
get_all_log_files() {
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
find /var/log/apache2/domlogs /usr/local/apache/domlogs -type f 2>/dev/null | \
|
|
grep -E '\.(log|_log)$|^[^.]+$'
|
|
;;
|
|
|
|
plesk)
|
|
# Check both old and new log locations
|
|
{
|
|
find /var/www/vhosts/system/*/logs -type f 2>/dev/null
|
|
find /var/www/vhosts/*/logs -type f 2>/dev/null | grep -v "/system/"
|
|
} | sort -u
|
|
;;
|
|
|
|
interworx)
|
|
find /chroot/home/*/var/*/logs -type f 2>/dev/null
|
|
;;
|
|
|
|
*)
|
|
find /var/log/httpd /var/log/apache2 /var/log/nginx -type f 2>/dev/null | \
|
|
grep -E '\.(log|_log)$|access|error'
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# USER/OWNER DISCOVERY
|
|
#############################################################################
|
|
|
|
# Get owner/user for a domain
|
|
# Usage: get_domain_owner DOMAIN
|
|
# Returns: username
|
|
get_domain_owner() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
grep "^${domain}:" /etc/userdomains 2>/dev/null | awk -F': ' '{print $2}'
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_owner "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
find /chroot/home/*/var/$domain -maxdepth 0 -type d 2>/dev/null | \
|
|
awk -F'/' '{print $4}' | head -1
|
|
;;
|
|
|
|
*)
|
|
# Standalone: check directory ownership
|
|
local docroot=$(get_domain_docroot "$domain")
|
|
[ -n "$docroot" ] && stat -c "%U" "$docroot" 2>/dev/null
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# List all users (control panel accounts)
|
|
# Returns: One username per line
|
|
list_all_users() {
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
ls -1 /var/cpanel/users/ 2>/dev/null
|
|
;;
|
|
|
|
plesk)
|
|
if plesk_cli_available; then
|
|
plesk_exec bin user --list 2>/dev/null
|
|
else
|
|
# Fallback: unique owners from vhosts
|
|
ls -1 /var/www/vhosts/ 2>/dev/null | \
|
|
grep -v "^system$\|^chroot$\|^\.skel$\|^default$\|^fs$" | \
|
|
while read -r domain; do
|
|
[ -d "/var/www/vhosts/$domain" ] && stat -c "%U" "/var/www/vhosts/$domain" 2>/dev/null
|
|
done | sort -u
|
|
fi
|
|
;;
|
|
|
|
interworx)
|
|
ls -1 /chroot/home/ 2>/dev/null
|
|
;;
|
|
|
|
*)
|
|
# Standalone: users with /home directories
|
|
ls -1 /home/ 2>/dev/null | while read -r user; do
|
|
[ -d "/home/$user" ] && echo "$user"
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# PHP-FPM DISCOVERY
|
|
#############################################################################
|
|
|
|
# Get PHP-FPM pool socket for a domain
|
|
# Usage: get_domain_fpm_socket DOMAIN
|
|
# Returns: /path/to/php-fpm.sock
|
|
get_domain_fpm_socket() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
# cPanel: EA-PHP sockets in /opt/cpanel/ea-phpXX/root/usr/var/run/
|
|
local user=$(get_domain_owner "$domain")
|
|
[ -z "$user" ] && return 1
|
|
|
|
# Find socket for this user
|
|
find /opt/cpanel/ea-php*/root/usr/var/run/ -name "*${user}*" -type s 2>/dev/null | head -1
|
|
;;
|
|
|
|
plesk)
|
|
plesk_get_fpm_socket "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
# InterWorx: check /chroot/home/USER/var/DOMAIN/
|
|
local user=$(get_domain_owner "$domain")
|
|
[ -z "$user" ] && return 1
|
|
find /chroot/home/$user/var/$domain/ -name "*.sock" -type s 2>/dev/null | head -1
|
|
;;
|
|
|
|
*)
|
|
# Standalone: common socket locations
|
|
find /var/run/php-fpm /run/php-fpm -name "*.sock" -type s 2>/dev/null | head -1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get all PHP-FPM pool sockets
|
|
# Returns: One socket path per line
|
|
get_all_fpm_sockets() {
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
find /opt/cpanel/ea-php*/root/usr/var/run/ -name "*.sock" -type s 2>/dev/null
|
|
;;
|
|
|
|
plesk)
|
|
plesk_list_fpm_sockets
|
|
;;
|
|
|
|
interworx)
|
|
find /chroot/home/*/var/*/ -name "*.sock" -type s 2>/dev/null
|
|
;;
|
|
|
|
*)
|
|
find /var/run/php-fpm /run/php-fpm -name "*.sock" -type s 2>/dev/null
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# DATABASE DISCOVERY
|
|
#############################################################################
|
|
|
|
# List all databases for a domain
|
|
# Usage: get_domain_databases DOMAIN
|
|
# Returns: One database name per line
|
|
get_domain_databases() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
local user=$(get_domain_owner "$domain")
|
|
[ -z "$user" ] && return 1
|
|
|
|
# cPanel databases are prefixed with username_
|
|
mysql -e "SHOW DATABASES;" 2>/dev/null | grep "^${user}_"
|
|
;;
|
|
|
|
plesk)
|
|
plesk_list_domain_databases "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
local user=$(get_domain_owner "$domain")
|
|
[ -z "$user" ] && return 1
|
|
|
|
# InterWorx uses username prefix
|
|
mysql -e "SHOW DATABASES;" 2>/dev/null | grep "^${user}_"
|
|
;;
|
|
|
|
*)
|
|
# Standalone: just list all non-system databases
|
|
mysql -e "SHOW DATABASES;" 2>/dev/null | \
|
|
grep -v "Database\|information_schema\|performance_schema\|mysql\|sys"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# UTILITY FUNCTIONS
|
|
#############################################################################
|
|
|
|
# Check if a domain exists on the server
|
|
# Usage: domain_exists DOMAIN
|
|
domain_exists() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && return 1
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
grep -q "^${domain}:" /etc/userdomains 2>/dev/null
|
|
;;
|
|
|
|
plesk)
|
|
plesk_domain_exists "$domain"
|
|
;;
|
|
|
|
interworx)
|
|
find /chroot/home/*/var/$domain -maxdepth 0 -type d 2>/dev/null | grep -q .
|
|
;;
|
|
|
|
*)
|
|
local docroot=$(get_domain_docroot "$domain")
|
|
[ -n "$docroot" ] && [ -d "$docroot" ]
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Get all domains with their document roots as TSV
|
|
# Format: DOMAIN\t/path/to/docroot
|
|
list_domains_with_docroots() {
|
|
local domain docroot
|
|
|
|
while IFS= read -r domain; do
|
|
docroot=$(get_domain_docroot "$domain")
|
|
[ -n "$docroot" ] && echo -e "$domain\t$docroot"
|
|
done < <(list_all_domains)
|
|
}
|
|
|
|
# Export all functions
|
|
export -f list_all_domains
|
|
export -f get_domain_docroot
|
|
export -f get_domain_logdir
|
|
export -f get_domain_access_log
|
|
export -f get_domain_error_log
|
|
export -f get_all_log_files
|
|
export -f get_domain_owner
|
|
export -f list_all_users
|
|
export -f get_domain_fpm_socket
|
|
export -f get_all_fpm_sockets
|
|
export -f get_domain_databases
|
|
export -f domain_exists
|
|
export -f list_domains_with_docroots
|