ircu2/install.sh

1407 lines
44 KiB
Bash
Executable File

#!/bin/bash
#
# Script de instalare automată pentru UnderChat IRCd
# Limba: Română
# Data: 2026
#
# Culori pentru output
ROSU='\033[0;31m'
VERDE='\033[0;32m'
GALBEN='\033[1;33m'
ALBASTRU='\033[0;34m'
NC='\033[0m' # Fără culoare
# Setări implicite
PREFIX="${HOME}/ircd"
MAXCON=4096
ENABLE_DEBUG=0
ENABLE_SSL=1
MAXCON_SET=0
SERVER_PORT=4400
SSL_PORTS_DEFAULT="6697"
IRCD_VERSION=""
# Validare numar pozitiv (doar cifre)
is_positive_int() {
case "$1" in
''|*[!0-9]*) return 1 ;;
*) return 0 ;;
esac
}
# Validare IPv4 stricta
is_ipv4() {
local ip="$1"
local IFS='.'
local -a oct
if [[ ! "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
return 1
fi
read -r -a oct <<< "$ip"
if [ "${#oct[@]}" -ne 4 ]; then
return 1
fi
local o
for o in "${oct[@]}"; do
if [ "$o" -lt 0 ] || [ "$o" -gt 255 ]; then
return 1
fi
done
return 0
}
# Validare IPv6 simpla (accepta :: si hexa)
is_ipv6() {
local ip="$1"
if [[ ! "$ip" =~ ^[0-9A-Fa-f:]+$ ]]; then
return 1
fi
if [[ "$ip" != *:* ]]; then
return 1
fi
# Numar de grupuri maxim 8 (inclusiv ::)
local groups
groups=$(awk -F: '{print NF}' <<< "$ip")
if [ "$groups" -gt 8 ]; then
return 1
fi
return 0
}
# Detectare IPv6 global (daca exista)
detect_ipv6_global() {
if command -v ip > /dev/null 2>&1; then
ip -6 -o addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1
fi
}
# Expandare lista porturi: "5000-5002,6000" -> "5000 5001 5002 6000"
expand_ports() {
local input="$1"
local token
local start
local end
local p
local -A seen
local -a result=()
input=${input// /}
if [ -z "$input" ]; then
return 1
fi
IFS=',' read -r -a tokens <<< "$input"
for token in "${tokens[@]}"; do
if [[ "$token" == *-* ]]; then
start=${token%-*}
end=${token#*-}
if ! is_positive_int "$start" || ! is_positive_int "$end"; then
return 1
fi
if [ "$start" -gt "$end" ]; then
return 1
fi
for ((p=start; p<=end; p++)); do
if [ "$p" -lt 1 ] || [ "$p" -gt 65535 ]; then
return 1
fi
if [ -z "${seen[$p]}" ]; then
seen[$p]=1
result+=("$p")
fi
done
else
if ! is_positive_int "$token"; then
return 1
fi
if [ "$token" -lt 1 ] || [ "$token" -gt 65535 ]; then
return 1
fi
if [ -z "${seen[$token]}" ]; then
seen[$token]=1
result+=("$token")
fi
fi
done
echo "${result[*]}"
return 0
}
# Funcția de afișare a ajutorului
show_help() {
cat << EOF
${ALBASTRU}Script de instalare automata pentru UnderChat IRCd${NC}
Utilizare: ./install.sh [OPTIUNI]
${GALBEN}OPTIUNI:${NC}
-h, --help Afiseaza acest mesaj de ajutor
-p, --prefix PATH Calea de instalare (implicit: \$HOME/ircd)
-m, --maxcon NUM Numarul maxim de conexiuni (implicit: 4096)
-d, --debug Activeaza modul de debug
-s, --no-ssl Dezactiveaza suportul SSL/TLS
-c, --config FILE Fisier de configurare initial
-V, --version VER Seteaza versiunea in PATCHLEVEL (ex: 1.0.3)
${GALBEN}EXEMPLE:${NC}
./install.sh
./install.sh --prefix /opt/ircd --maxcon 8192
./install.sh --debug --config myconfig.conf
./install.sh --version 1.0.3
EOF
}
# Funcția de log
log_info() {
echo -e "${VERDE}[INFO]${NC} $1"
}
log_warn() {
echo -e "${GALBEN}[AVERTIZARE]${NC} $1"
}
log_error() {
echo -e "${ROSU}[EROARE]${NC} $1"
}
log_success() {
echo -e "${VERDE}[SUCCES]${NC} $1"
}
# Funcția pentru generare hash parola
generate_password_hash() {
local password="$1"
# Verifica daca openssl e disponibil pentru MD5
if command -v openssl &> /dev/null; then
# Genereaza MD5 hash (SMD5 format pentru ircd)
echo "$password" | openssl dgst -md5 -binary | base64
else
# Fallback: foloseste doar password plain (nu e recomandat!)
echo "PLAIN:$password"
fi
}
# Funcția pentru validare parola
validate_password() {
local pass="$1"
if [ ${#pass} -lt 4 ]; then
return 1
fi
return 0
}
# Funcția de verificare a dependențelor
check_dependencies() {
log_info "Verificare dependențe..."
local missing_deps=0
local missing_list=""
# Verifică compilatorul C
if ! command -v gcc &> /dev/null && ! command -v cc &> /dev/null; then
log_error "GCC/CC nu este instalat!"
missing_deps=1
missing_list="$missing_list\n - build-essential (GCC/CC)"
else
log_success "Compilator C găsit"
fi
# Verifică make
if ! command -v make &> /dev/null; then
log_error "Make nu este instalat!"
missing_deps=1
missing_list="$missing_list\n - make"
else
log_success "Make găsit"
fi
# Verifică autoconf (opțional dar recomandat)
if ! command -v autoconf &> /dev/null; then
log_warn "Autoconf nu este instalat (opțional)"
# Nu e eroare critică, dar o notez
else
log_success "Autoconf găsit"
fi
# Verifică bibliotecile SSL
if command -v pkg-config &> /dev/null; then
if ! pkg-config --exists openssl; then
log_warn "OpenSSL dev nu este instalat (opțional)"
else
log_success "OpenSSL găsit"
fi
fi
# Dacă lipsesc dependențe obligatorii, oferă opțiune pentru fix automat
if [ $missing_deps -eq 1 ]; then
echo ""
echo -e "${ROSU}═══════════════════════════════════════${NC}"
echo -e "${ROSU}LIPSESC DEPENDENȚE OBLIGATORII!${NC}"
echo -e "${ROSU}═══════════════════════════════════════${NC}"
echo -e "${ROSU}Dependențe lipsă:${missing_list}${NC}"
echo ""
echo -e "${GALBEN}Opțiuni:${NC}"
echo " 1) Instalare automată cu install-deps.sh (recomandat)"
echo " 2) Instalare manuală (tu ești responsabil)"
echo " 3) Anulare"
echo ""
read -p "Alege opțiune [1-3]: " dep_choice
dep_choice=${dep_choice:-1}
case $dep_choice in
1)
echo ""
log_info "Lansare install-deps.sh..."
# Verifică dacă install-deps.sh există
if [ ! -x "./install-deps.sh" ]; then
log_error "install-deps.sh nu găsit sau nu are permisiuni!"
log_warn "Descarcă scriptul de pe repository"
return 1
fi
# Rulează install-deps.sh
./install-deps.sh
if [ $? -eq 0 ]; then
echo ""
log_success "Dependențe instalate cu succes!"
log_info "Relansare verificare dependențe..."
# Verificare din nou
check_dependencies
return $?
else
log_error "Instalare dependențe eșuată!"
return 1
fi
;;
2)
echo ""
log_warn "Continuă pe propria răspundere..."
log_warn "Dacă lipsesc dependențe, compilarea va eșua."
return 0
;;
3)
echo ""
log_error "Anulare instalare."
exit 1
;;
*)
log_error "Opțiune invalida!"
check_dependencies
return $?
;;
esac
fi
return 0
}
# Funcția pentru fixare config.guess pentru aarch64
fix_config_guess() {
log_info "Verificare support aarch64 în config.guess..."
# Verifică dacă config.guess e vechi și nu suportă aarch64
if [ -f "./config.guess" ] && ! grep -q "aarch64" ./config.guess; then
log_warn "config.guess e vechi, adaugă suport aarch64..."
# Patch pentru aarch64
if grep -q "case \"\$machine\" in" ./config.guess; then
# Adaugă case pentru aarch64 înainte de default
sed -i '/case "$machine" in/a\
\t\taarch64*|arm64*)\
\t\t\techo aarch64-unknown-linux-gnu\
\t\t\texit 0\
\t\t\t;;' ./config.guess
log_success "Support aarch64 adăugat la config.guess"
fi
fi
# Dacă config.guess tot nu merge, folosește --build flag
return 0
}
# Funcția de setare versiune in PATCHLEVEL
set_patchlevel_version() {
local version="$1"
local patchlevel_file="./include/patchlevel.h"
if [ -z "$version" ]; then
return 0
fi
if [ ! -f "$patchlevel_file" ]; then
log_warn "Fisierul $patchlevel_file nu exista, sar peste setarea versiunii"
return 0
fi
local current
current=$(grep -E '^#define PATCHLEVEL ' "$patchlevel_file" | sed -E 's/^#define PATCHLEVEL "([^"]+)".*/\1/')
if [ -z "$current" ]; then
log_warn "Nu pot determina PATCHLEVEL curent, sar peste setarea versiunii"
return 0
fi
local new_patchlevel
if echo "$current" | grep -q '(.*)'; then
# Extract prefix before parentheses
local prefix=$(echo "$current" | sed -E 's/^(.*)\([^)]*\)$/\1/')
new_patchlevel="${prefix}(${version})"
else
new_patchlevel="UnderChat(${version})"
fi
sed -i "s|^#define PATCHLEVEL \".*\"|#define PATCHLEVEL \"$new_patchlevel\"|" "$patchlevel_file"
log_success "Versiune setata in PATCHLEVEL: $new_patchlevel"
}
# Funcția de configurare
configure_ircd() {
log_info "Configurare UnderChat IRCd..."
# Fixează config.guess pentru aarch64
fix_config_guess
local config_args="--prefix=$PREFIX"
config_args="$config_args --with-maxcon=$MAXCON"
if [ $ENABLE_DEBUG -eq 1 ]; then
config_args="$config_args --enable-debug"
fi
if [ $ENABLE_SSL -eq 0 ]; then
config_args="$config_args --disable-ssl"
fi
# Adaugă --build flag pentru sisteme care nu pot detecta
if [ "$(uname -m)" = "aarch64" ]; then
config_args="$config_args --build=aarch64-unknown-linux-gnu"
log_info "Detectat aarch64, adaugă --build=aarch64-unknown-linux-gnu"
fi
log_info "Parametri configure: $config_args"
if [ ! -f "./configure" ]; then
log_error "Fișierul configure nu găsit!"
return 1
fi
./configure $config_args
if [ $? -ne 0 ]; then
log_error "Configurare eșuată!"
return 1
fi
log_success "Configurare finalizată cu succes"
return 0
}
# Funcția de compilare
compile_ircd() {
log_info "Compilare UnderChat IRCd..."
# Verifică dacă autoconf este disponibil
if ! command -v autoconf &> /dev/null; then
log_warn "Autoconf nu este instalat, dezactivare la Makefile..."
# Touchează configure pentru a evita rularea autoconf
touch ./configure
fi
make clean > /dev/null 2>&1
make
if [ $? -ne 0 ]; then
log_error "Compilare eșuată!"
log_warn "Încearcă: sudo apt-get install autoconf automake libtool"
return 1
fi
log_success "Compilare finalizată cu succes"
return 0
}
# Funcția de instalare
install_ircd() {
log_info "Instalare UnderChat IRCd..."
make install
if [ $? -ne 0 ]; then
log_error "Instalare eșuată!"
return 1
fi
log_success "Instalare finalizată cu succes"
return 0
}
# Funcția de generare a fișierului de configurare
generate_config() {
local config_file="$1"
local server_name="${2:-localhost.localdomain}"
local server_desc="${3:-UnderChat IRCd Server}"
local server_numeric="${4:-1}"
local admin_location="${5:-Romania}"
local admin_contact="${6:-admin@underchat.ro}"
local vhost_ipv4="${7:-127.0.0.1}"
local vhost_ipv6="${8:-}"
local network="${9:-underchat.org}"
local oper_user="${10:-AdminRoot}"
local oper_pass="${11:-\$PLAIN\$password}"
local is_hub="${12:-no}"
local hub_name="${13}"
local hub_host="${14}"
local hub_port="${15:-4400}"
local hub_pass="${16}"
local client_ports_list="${17}"
local server_port="${18:-4400}"
local ssl_ports_list="${19}"
# Linie IPv6 comentata daca nu e furnizata
local vhost6_line=" # vhost = \"2001:db8::1\";"
local vhost6_port_4400=" # vhost = \"2001:db8::1\" $server_port;"
if [ -n "$vhost_ipv6" ]; then
vhost6_line=" vhost = \"$vhost_ipv6\";"
vhost6_port_4400=" vhost = \"$vhost_ipv6\" $server_port;"
fi
# Generare blocuri Port pentru clienti
local client_ports_block=""
local port
for port in $client_ports_list; do
if [ -n "$vhost_ipv6" ]; then
client_ports_block+=$'Port {\n'
client_ports_block+=$' vhost = "'"$vhost_ipv4"'" '"$port"$';\n'
client_ports_block+=$' vhost = "'"$vhost_ipv6"'" '"$port"$';\n'
client_ports_block+=$' hidden = yes;\n';
client_ports_block+=$'}\n\n'
else
client_ports_block+=$'Port {\n'
client_ports_block+=$' vhost = "'"$vhost_ipv4"'" '"$port"$';\n'
client_ports_block+=$' # vhost = "2001:db8::1" '"$port"$';\n'
client_ports_block+=$' hidden = yes;\n';
client_ports_block+=$'}\n\n'
fi
done
# Generare blocuri Port pentru SSL
local ssl_ports_block=""
if [ -n "$ssl_ports_list" ]; then
for port in $ssl_ports_list; do
if [ -n "$vhost_ipv6" ]; then
ssl_ports_block+=$'Port {\n'
ssl_ports_block+=$' vhost = "'"$vhost_ipv4"'" '"$port"$';\n'
ssl_ports_block+=$' vhost = "'"$vhost_ipv6"'" '"$port"$';\n'
ssl_ports_block+=$' ssl = yes;\n';
ssl_ports_block+=$' hidden = yes;\n';
ssl_ports_block+=$'}\n\n'
else
ssl_ports_block+=$'Port {\n'
ssl_ports_block+=$' vhost = "'"$vhost_ipv4"'" '"$port"$';\n'
ssl_ports_block+=$' # vhost = "2001:db8::1" '"$port"$';\n'
ssl_ports_block+=$' ssl = yes;\n';
ssl_ports_block+=$' hidden = yes;\n';
ssl_ports_block+=$'}\n\n'
fi
done
else
ssl_ports_block="# Porturi SSL neconfigurate"
fi
log_info "Generare fișier de configurare: $config_file"
mkdir -p "$(dirname "$config_file")"
cat > "$config_file" << EOFCONFIG
# Fișier de configurare pentru UnderChat IRCd
# Generat automat în data: 2026
# Limba: Română
# Model: Node-Ase.ovh Professional IRC Server
# ============================================================================
# SECȚIUNE: GENERAL
# ============================================================================
General {
# Numele serverului (trebuie unic în rețea)
name = "EOFCONFIG_NAME";
# Virtual Host - IP pe care ascultă
vhost = "EOFCONFIG_VHOST4";
EOFCONFIG_VHOST6_LINE
# Descrierea serverului
description = "EOFCONFIG_DESC";
# Numeric-ul serverului (0-4095, trebuie unic în rețea)
numeric = EOFCONFIG_NUMERIC;
# Servere DNS pentru rezolvare domenii
dns server = "8.8.8.8";
dns server = "1.1.1.1";
};
# ============================================================================
# SECȚIUNE: ADMIN
# ============================================================================
Admin {
# Locații (maxim 2)
Location = "The EOFCONFIG_NETWORK World";
Location = "Location: EOFCONFIG_ADMIN_LOC";
# Contacti
Contact = "IRC Admins <EOFCONFIG_ADMIN_CONTACT>";
};
# ============================================================================
# SECȚIUNE: CLASE DE CONEXIUNI
# ============================================================================
# Clasă pentru servere principale (hub)
Class {
name = "Server";
pingfreq = 1 minutes 30 seconds;
connectfreq = 5 minutes;
maxlinks = 1;
sendq = 9000000;
};
# Clasă pentru servere principale (LeafServer)
Class {
name = "LeafServer";
pingfreq = 1 minutes 30 seconds;
connectfreq = 5 minutes;
maxlinks = 0;
sendq = 9000000;
};
# Clasă pentru clienți obișnuiți
Class {
name = "Local";
pingfreq = 1 minutes 30 seconds;
sendq = 160000;
maxlinks = 100;
usermode = "+i";
};
# Clasă pentru clienți normali (implicit)
Class {
name = "Other";
pingfreq = 1 minutes 30 seconds;
sendq = 160000;
maxlinks = 2048;
usermode = "+ix";
};
# Clasă pentru operatori
Class {
name = "Opers";
pingfreq = 1 minutes 30 seconds;
sendq = 160000;
maxlinks = 20;
local = no;
freeform = yes;
mode_lchan = yes;
deop_lchan = yes;
walk_lchan = yes;
show_invis = yes;
see_chan = yes;
list_chan = yes;
usermode = "+W";
remove = yes;
};
# Clasă pentru IRCcloud
Class {
name = "irccloud";
pingfreq = 1 minutes 30 seconds;
sendq = 160000;
maxlinks = 100;
usermode = "+i";
};
# ============================================================================
# SECȚIUNE: CLIENT - Restricții pentru conexiuni
# ============================================================================
# Configurare implicită pentru toți clienții
Client {
host = "*@*";
ip = "*@*";
class = "Other";
maxlinks = 3;
};
#Configurare implicita pentru AUTOJOIN + mesaj
Client {
host = "*@*";
ip = "*@*";
class = "Other";
autojoinchannel = "#CService";
autojoinnotice = "*** Notice -- You are now being autojoined into #CService and #zT channels. Have fun!";
maxlinks = 6;
};
# ============================================================================
# SECȚIUNE: JUPED NICKS - Nick-uri rezervate
# ============================================================================
Jupe {
# Litere și caractere speciale
nick = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,{,|,},~,-,_,\`";
nick = "EuWorld,UWorld,UWorld2,Defender";
nick = "login,underchat,protocol,pass,newpass,org";
nick = "LPT1,LPT2,COM1,COM2,COM3,COM4,AUX,AUTH";
# Servicii de rețea
nick = "StatServ,NoteServ";
nick = "ChanServ,ChanSaver";
nick = "NickServ,NickSaver";
};
# ==========================================================================
# SECȚIUNE: PORTURI
# ==========================================================================
# Port pentru server-to-server
Port {
vhost = "EOFCONFIG_VHOST4" EOFCONFIG_SERVER_PORT;
EOFCONFIG_VHOST6_PORT_4400
server = yes;
hidden = yes;
};
# Porturi publice pentru clienți
EOFCONFIG_CLIENT_PORTS
# Porturi SSL/TLS pentru clienți
EOFCONFIG_SSL_PORTS
# ============================================================================
# SECȚIUNE: OPERATORI
# ============================================================================
Operator {
# Nickname-ul operatorului
name = "EOFCONFIG_OPER_USER";
# Password-ul operatorului (hash MD5/bcrypt/SMD5)
# Generat automat din parola furnizată
password = "EOFCONFIG_OPER_PASS";
# Host-uri permise pentru operator (*)
host = "*@*";
# Clasă
class = "Opers";
# Permisiuni și notificări
admin = yes;
hide_oper = no;
hide_channels = no;
# snomask = "+s";
# privileges = "PRIV_WHOIS_NOTICE", "PRIV_HIDE_OPER", "PRIV_ADMIN";
};
# ============================================================================
# SECȚIUNE: CONNECT - Legări cu alte servere
# ============================================================================
EOFCONFIG_HUB_CONNECT
# ============================================================================
# SECȚIUNE: UWORLD - Servere de servicii
# ============================================================================
UWorld {
name = "services.EOFCONFIG_NETWORK";
name = "channels.EOFCONFIG_NETWORK";
name = "defender.EOFCONFIG_NETWORK";
name = "stats.EOFCONFIG_NETWORK";
name = "snoop.EOFCONFIG_NETWORK";
name = "proxyscaner.EOFCONFIG_NETWORK";
name = "proxy.EOFCONFIG_NETWORK";
};
# MOTD Server targetat pentru
#motd {
# host = "*.net";
# file = "net_com.motd";
#};
# ============================================================================
# SECȚIUNE: FEATURE - Caracteristici și setări
# ============================================================================
features {
# Network details
"NETWORK" = "EOFCONFIG_NETWORK";
"DOMAINNAME" = "EOFCONFIG_NETWORK";
# Logging
"LOG" = "SYSTEM" "FILE" "$PREFIX/log/ircd.log";
"LOG" = "SYSTEM" "LEVEL" "CRIT";
# Server settings
"HUB" = "EOFCONFIG_HUB_SETTING";
"RELIABLE_CLOCK" = "FALSE";
"WALLOPS_OPER_ONLY" = "TRUE";
"NODNS" = "FALSE";
"NOIDENT" = "FALSE";
# Client settings
"CLIENT_FLOOD" = "1024";
"BUFFERPOOL" = "27000000";
"DEFAULTMAXSENDQLENGTH" = "40000";
# Host hiding
"HOST_HIDING" = "TRUE";
"HOST_HIDING_STYLE" = "3";
"HIDDEN_HOST" = "users.EOFCONFIG_NETWORK";
"HIDDEN_IP" = "127.0.0.1";
"HIDDEN_HOSTTYPE" = "3";
# Channels
"MAXCHANNELSPERUSER" = "60";
"CHANNELLEN" = "200";
"MAXBANS" = "50";
# Nick settings
"NICKLEN" = "12";
"NICKNAMEHISTORYLENGTH" = "800";
# Timing
"HANGONGOODLINK" = "300";
"HANGONRETRYDELAY" = "10";
"CONNECTTIMEOUT" = "90";
"PINGFREQUENCY" = "120";
"CONNECTFREQUENCY" = "600";
# Welcome messages - toate în lib/ ca directorul principal
"MPATH" = "$PREFIX/lib/ircd.motd";
"RPATH" = "$PREFIX/lib/remote.motd";
"PPATH" = "$PREFIX/var/ircd.pid";
"CPATH" = "$PREFIX/lib/ircd.conf";
# Stats visibility
"HIS_STATS_u" = "FALSE";
"HIS_STATS_U" = "TRUE";
# Whois privacy
"HIS_WHOIS_SERVERNAME" = "TRUE";
"HIS_WHOIS_IDLETIME" = "TRUE";
"HIS_WHOIS_LOCALCHAN" = "TRUE";
# Who privacy
"HIS_WHO_SERVERNAME" = "TRUE";
"HIS_WHO_HOPCOUNT" = "TRUE";
# Network info
"HIS_NETSPLIT" = "TRUE";
"HIS_SERVERNAME" = "*.EOFCONFIG_NETWORK";
"HIS_SERVERINFO" = "The EOFCONFIG_NETWORK World";
# Operational
"CHECK" = "TRUE";
"CHECK_EXTENDED" = "TRUE";
"MAX_CHECK_OUTPUT" = "1000";
"OPER_WHOIS_PARANOIA" = "TRUE";
# Admin commands
"SETHOST" = "TRUE";
"NETWORK_REHASH" = "TRUE";
# Channel modes
"HALFOPS" = "TRUE";
# SSL/TLS
# "SSL_CERTFILE" = "EOFCONFIG_PREFIX/etc/ircd.pem";
# "SSL_KEYFILE" = "EOFCONFIG_PREFIX/etc/ircd.pem";
# "SSL_NOSSLv3" = "TRUE";
# CTCP versioning
"CTCP_VERSIONING" = "FALSE";
# WHOIS notifications for operators
"WHOIS_NOTICE" = "TRUE";
"SPY_WHOIS" = "TRUE";
"SNOMASK_OPERDEFAULT" = "1024";
"SNOMASK_DEFAULT" = "1024";
};
EOFCONFIG
# Înlocuiește placeholder-ele
sed -i "s|EOFCONFIG_NAME|$server_name|g" "$config_file"
sed -i "s|EOFCONFIG_DESC|$server_desc|g" "$config_file"
sed -i "s|EOFCONFIG_NUMERIC|$server_numeric|g" "$config_file"
sed -i "s|EOFCONFIG_PREFIX|$PREFIX|g" "$config_file"
sed -i "s|EOFCONFIG_NETWORK|$network_name|g" "$config_file"
sed -i "s|EOFCONFIG_ADMIN_LOC|$admin_location|g" "$config_file"
sed -i "s|EOFCONFIG_ADMIN_CONTACT|$admin_contact|g" "$config_file"
sed -i "s|EOFCONFIG_VHOST4|$vhost_ipv4|g" "$config_file"
sed -i "s|EOFCONFIG_VHOST6_LINE|$vhost6_line|g" "$config_file"
sed -i "s|EOFCONFIG_VHOST6_PORT_4400|$vhost6_port_4400|g" "$config_file"
sed -i "s|EOFCONFIG_SERVER_PORT|$server_port|g" "$config_file"
sed -i "s|EOFCONFIG_CLIENT_PORTS|$client_ports_block|g" "$config_file"
sed -i "s|EOFCONFIG_SSL_PORTS|$ssl_ports_block|g" "$config_file"
sed -i "s|EOFCONFIG_OPER_USER|$oper_user|g" "$config_file"
sed -i "s|EOFCONFIG_OPER_PASS|$oper_pass|g" "$config_file"
# Setare HUB flag și CONNECT section
if [ "$is_hub" = "y" ] || [ "$is_hub" = "Y" ]; then
sed -i 's|EOFCONFIG_HUB_SETTING|TRUE|g' "$config_file"
# Adaugă CONNECT section pentru HUB
HUB_CONNECT_BLOCK="# Conectare la HUB principal
Connect {
name = \"$hub_name\";
host = \"$hub_host\";
password = \"$hub_password\";
port = $hub_port;
class = \"Server\";
autoconnect = yes;
hub;
};"
sed -i "s|EOFCONFIG_HUB_CONNECT|$HUB_CONNECT_BLOCK|g" "$config_file"
else
sed -i 's|EOFCONFIG_HUB_SETTING|FALSE|g' "$config_file"
sed -i 's|EOFCONFIG_HUB_CONNECT|# Server nu este HUB - fără connect|g' "$config_file"
fi
log_success "Fișier de configurare generat: $config_file"
return 0
}
# Funcția principală
main() {
# Parsare argumente
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-p|--prefix)
PREFIX="$2"
shift 2
;;
-m|--maxcon)
if ! is_positive_int "$2"; then
log_error "Valoare invalidă pentru --maxcon: $2"
exit 1
fi
MAXCON="$2"
MAXCON_SET=1
shift 2
;;
-d|--debug)
ENABLE_DEBUG=1
shift
;;
-s|--no-ssl)
ENABLE_SSL=0
shift
;;
-c|--config)
CONFIG_FILE="$2"
shift 2
;;
-V|--version)
IRCD_VERSION="$2"
shift 2
;;
*)
log_error "Optiune necunoscuta: $1"
show_help
exit 1
;;
esac
done
echo -e "${ALBASTRU}"
echo "========================================="
echo " Instalare UnderChat IRCd"
echo "========================================="
echo -e "${NC}"
# Cerere max conexiuni (doar dacă nu a fost setat din argumente)
if [ $MAXCON_SET -eq 0 ]; then
echo ""
while true; do
read -p " Maxim conexiuni [${MAXCON}]: " maxcon_input
if [ -z "$maxcon_input" ]; then
break
fi
if is_positive_int "$maxcon_input"; then
MAXCON="$maxcon_input"
break
fi
log_error "Maxim conexiuni trebuie să fie un număr întreg pozitiv."
done
fi
# Verificare dependențe
check_dependencies
if [ $? -ne 0 ]; then
exit 1
fi
# Setare versiune (optional)
set_patchlevel_version "$IRCD_VERSION"
# Configurare
configure_ircd
if [ $? -ne 0 ]; then
exit 1
fi
# Compilare
compile_ircd
if [ $? -ne 0 ]; then
exit 1
fi
# Instalare
install_ircd
if [ $? -ne 0 ]; then
exit 1
fi
# Generare fișier de configurare
local conf_file="${PREFIX}/lib/ircd.conf"
if [ -z "$CONFIG_FILE" ]; then
# Citire interactivă de parametri
echo ""
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
echo -e "${GALBEN}CONFIGURARE SERVER${NC}"
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
read -p " Domeniu rețea [underchat.org]: " network_name
network_name=${network_name:-underchat.org}
read -p " Nume server [ns1.${network_name}]: " server_name
server_name=${server_name:-ns1.${network_name}}
read -p " Descriere server [The ${network_name} Network]: " server_desc
server_desc=${server_desc:-The ${network_name} Network}
# IPv4
while true; do
read -p " Virtual Host / IP (IPv4) [127.0.0.1]: " vhost_ipv4
vhost_ipv4=${vhost_ipv4:-127.0.0.1}
if is_ipv4 "$vhost_ipv4"; then
break
fi
log_error "IPv4 invalid. Exemplu: 192.168.1.10"
done
# IPv6 (auto-detect)
local auto_ipv6
auto_ipv6=$(detect_ipv6_global)
while true; do
if [ -n "$auto_ipv6" ]; then
read -p " Virtual Host / IP (IPv6) [${auto_ipv6}] ("'"'"'"-"'"'"'" pentru gol): " vhost_ipv6
if [ "$vhost_ipv6" = "-" ]; then
vhost_ipv6=""
break
fi
vhost_ipv6=${vhost_ipv6:-$auto_ipv6}
else
read -p " Virtual Host / IP (IPv6) [gol pentru comentat]: " vhost_ipv6
vhost_ipv6=${vhost_ipv6:-}
fi
if [ -z "$vhost_ipv6" ] || is_ipv6 "$vhost_ipv6"; then
break
fi
log_error "IPv6 invalid. Exemplu: 2001:db8::1"
done
# Port server-to-server
while true; do
read -p " Port server-to-server [${SERVER_PORT}]: " server_port_input
server_port_input=${server_port_input:-$SERVER_PORT}
if is_positive_int "$server_port_input" && [ "$server_port_input" -ge 1 ] && [ "$server_port_input" -le 65535 ]; then
SERVER_PORT="$server_port_input"
break
fi
log_error "Port invalid. Exemplu: 4400"
done
# Porturi publice IRC (clienti)
local default_ports="6660-6669,7000"
while true; do
read -p " Porturi publice IRC [${default_ports}]: " client_ports_input
client_ports_input=${client_ports_input:-$default_ports}
client_ports_list=$(expand_ports "$client_ports_input")
if [ $? -eq 0 ]; then
break
fi
log_error "Format invalid. Exemple: 5000-5002,6000 sau 6667"
done
# Porturi SSL pentru clienti
if [ $ENABLE_SSL -eq 1 ]; then
while true; do
read -p " Porturi SSL IRC [${SSL_PORTS_DEFAULT}] (gol pentru a sari): " ssl_ports_input
if [ -z "$ssl_ports_input" ]; then
ssl_ports_list=""
break
fi
ssl_ports_list=$(expand_ports "$ssl_ports_input")
if [ $? -eq 0 ]; then
break
fi
log_error "Format invalid. Exemple: 6697,7001 sau 7000-7002"
done
else
ssl_ports_list=""
fi
read -p " Numeric server [1]: " server_numeric
server_numeric=${server_numeric:-1}
read -p " Locație admin [Romania]: " admin_location
admin_location=${admin_location:-Romania}
read -p " Contact admin [admin@${network_name}]: " admin_contact
admin_contact=${admin_contact:-admin@${network_name}}
# Configurare Operator
echo ""
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
echo -e "${GALBEN}CONFIGURARE OPERATOR${NC}"
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
read -p " Username operator [AdminRoot]: " oper_username
oper_username=${oper_username:-AdminRoot}
# Cerere parola și validare
while true; do
read -s -p " Parola operator: " oper_password
echo ""
if ! validate_password "$oper_password"; then
log_error "Parola prea scurtă! Minim 4 caractere."
continue
fi
read -s -p " Repetă parola: " oper_password_confirm
echo ""
if [ "$oper_password" != "$oper_password_confirm" ]; then
log_error "Parolele nu se potrivesc!"
continue
fi
# Generare hash
log_info "Generare hash parola..."
oper_hash="\$PLAIN\$$oper_password"
log_success "Parola operator criptată"
break
done
# Configurare HUB
echo ""
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
echo -e "${GALBEN}CONFIGURARE HUB${NC}"
echo -e "${GALBEN}═══════════════════════════════════════${NC}"
read -p " Este aceasta un server HUB? (y/n) [n]: " is_hub
is_hub=${is_hub:-n}
# Dacă e HUB, cere informații linking
if [ "$is_hub" = "y" ] || [ "$is_hub" = "Y" ]; then
echo ""
log_info "Configurare LINK la HUB principal"
echo ""
read -p " Nume HUB [hub.${network_name}]: " hub_name
hub_name=${hub_name:-hub.${network_name}}
read -p " IP/Host HUB [192.168.1.100]: " hub_host
hub_host=${hub_host:-192.168.1.100}
read -p " Port HUB [4400]: " hub_port
hub_port=${hub_port:-4400}
read -s -p " Parola linking: " hub_password
echo ""
HUB_CONFIG="yes"
else
HUB_CONFIG="no"
hub_name=""
hub_host=""
hub_port=""
hub_password=""
fi
else
server_name=$(grep 'name = "' "$CONFIG_FILE" 2>/dev/null | head -1 | cut -d'"' -f2)
server_name=${server_name:-localhost.localdomain}
vhost_ipv4="127.0.0.1"
vhost_ipv6=""
SERVER_PORT=4400
client_ports_list="6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 7000"
ssl_ports_list=""
network_name="underchat.org"
oper_username="AdminRoot"
oper_hash="\$PLAIN\$password"
is_hub="n"
HUB_CONFIG="no"
fi
# Directorul pentru configurația funcțională - TREBUIE să fie în lib/, nu etc/
conf_file="$PREFIX/lib/ircd.conf"
generate_config "$conf_file" "$server_name" "$server_desc" "$server_numeric" "$admin_location" "$admin_contact" "$vhost_ipv4" "$vhost_ipv6" "$network_name" "$oper_username" "$oper_hash" "$HUB_CONFIG" "$hub_name" "$hub_host" "$hub_port" "$hub_password" "$client_ports_list" "$SERVER_PORT" "$ssl_ports_list"
if [ $? -ne 0 ]; then
exit 1
fi
# Verifica dacă fișierul de config a fost creat
if [ ! -f "$conf_file" ]; then
log_error "Fișierul de configurare nu a fost creat!"
exit 1
fi
# Setează permisiuni pe config
chmod 600 "$conf_file"
log_success "Permisiuni setate pe configurare: 600"
# ======================================================================
# REMEDIERE COMPLETĂ INTEGRATĂ - NU MAI SUNT NECESARE SCRIPTURI DE FIX
# ======================================================================
log_info "Aplicare remedieri COMPLETE integrate - NU mai sunt necesare scripturi de fix..."
# 1. REMEDIERE COMPLETĂ placeholder-uri EOFCONFIG
log_warn "Aplicare remediere COMPLETĂ pentru TOATE placeholder-urile..."
# Detectare IP pentru porturi
VHOST_FOR_PORTS="$vhost_ipv4"
log_info "Folosesc IP-ul pentru toate porturile: $VHOST_FOR_PORTS"
# Înlocuire FORȚATĂ EOFCONFIG_CLIENT_PORTS cu porturile EXACT specificate
if grep -q "EOFCONFIG_CLIENT_PORTS" "$conf_file"; then
log_warn "EOFCONFIG_CLIENT_PORTS găsit - îl înlocuiesc FORȚAT..."
# Generează blocul de porturi DOAR pentru cele specificate
CLIENT_PORTS_REPLACEMENT="# Porturi publice pentru clienți - generate automat la instalare"
for port in $client_ports_list; do
CLIENT_PORTS_REPLACEMENT+="\nPort {\n vhost = \"$VHOST_FOR_PORTS\" $port;\n hidden = yes;\n};\n"
done
# Înlocuire directă cu awk
awk -v replacement="$CLIENT_PORTS_REPLACEMENT" '
/EOFCONFIG_CLIENT_PORTS/ {
print replacement
next
}
{print}
' "$conf_file" > "$conf_file.tmp" && mv "$conf_file.tmp" "$conf_file"
log_success "EOFCONFIG_CLIENT_PORTS înlocuit cu porturile specificate: $client_ports_list"
fi
# Înlocuire FORȚATĂ EOFCONFIG_SSL_PORTS cu porturile SSL specificate
if grep -q "EOFCONFIG_SSL_PORTS" "$conf_file"; then
log_warn "EOFCONFIG_SSL_PORTS găsit - îl înlocuiesc FORȚAT..."
if [ -n "$ssl_ports_list" ]; then
SSL_PORTS_REPLACEMENT="# Porturi SSL/TLS pentru clienți - generate automat la instalare"
for port in $ssl_ports_list; do
SSL_PORTS_REPLACEMENT+="\nPort {\n vhost = \"$VHOST_FOR_PORTS\" $port;\n ssl = yes;\n hidden = yes;\n};\n"
done
else
SSL_PORTS_REPLACEMENT="# Porturi SSL/TLS pentru clienți - nu au fost configurate"
fi
# Înlocuire directă cu awk
awk -v replacement="$SSL_PORTS_REPLACEMENT" '
/EOFCONFIG_SSL_PORTS/ {
print replacement
next
}
{print}
' "$conf_file" > "$conf_file.tmp" && mv "$conf_file.tmp" "$conf_file"
log_success "EOFCONFIG_SSL_PORTS înlocuit cu porturile SSL: ${ssl_ports_list:-'none'}"
fi
# Înlocuire FORȚATĂ orice alt EOFCONFIG rămas
sed -i "s|EOFCONFIG_PREFIX|$PREFIX|g" "$conf_file"
sed -i "s|EOFCONFIG_NETWORK|$network_name|g" "$conf_file"
sed -i "s|\\.EOFCONFIG_NETWORK|.$network_name|g" "$conf_file"
sed -i "s|\\*\\.EOFCONFIG_NETWORK|*.$network_name|g" "$conf_file"
# 2. REMEDIERE COMPLETĂ pentru HOST_HIDING
log_warn "Aplicare remediere COMPLETĂ pentru HOST_HIDING..."
# Forțează HOST_HIDING_STYLE = 3
sed -i 's/"HOST_HIDING_STYLE" = "[^"]*"/"HOST_HIDING_STYLE" = "3"/' "$conf_file"
if ! grep -q '"HOST_HIDING_STYLE"' "$conf_file"; then
sed -i '/"HOST_HIDING" = "TRUE"/a\ "HOST_HIDING_STYLE" = "3";' "$conf_file"
fi
# Adaugă HIDDEN_HOSTTYPE dacă lipsește
if ! grep -q '"HIDDEN_HOSTTYPE"' "$conf_file"; then
sed -i '/"HIDDEN_IP" = /a\ "HIDDEN_HOSTTYPE" = "3";' "$conf_file"
fi
# 3. REMEDIERE COMPLETĂ pentru WHOIS notificări operatori
log_warn "Aplicare remediere COMPLETĂ pentru notificări WHOIS operatori..."
if ! grep -q '"SPY_WHOIS" = "TRUE"' "$conf_file"; then
sed -i '/"WHOIS_NOTICE" = "TRUE"/a\ "SPY_WHOIS" = "TRUE";\n "SNOMASK_OPERDEFAULT" = "1024";\n "SNOMASK_DEFAULT" = "1024";' "$conf_file"
fi
# 4. REMEDIERE COMPLETĂ pentru probleme de sintaxă
log_warn "Aplicare remediere COMPLETĂ pentru probleme de sintaxă..."
# Corectează snomask problematic
if grep -q 'snomask = ".*HACK.*"' "$conf_file"; then
sed -i 's/snomask = ".*HACK.*"/snomask = "+s";/' "$conf_file"
log_success "Snomask corectat pentru a evita erori de sintaxă"
fi
# 5. VERIFICARE și REPARARE FINALĂ COMPLETĂ
log_info "Verificare și reparare FINALĂ COMPLETĂ..."
# Verificare orice EOFCONFIG rămas și înlocuire de urgență
if grep -q "EOFCONFIG" "$conf_file"; then
log_error "ÎNCĂ există placeholder-uri EOFCONFIG - aplicare reparare de URGENȚĂ..."
sed -i 's/EOFCONFIG_CLIENT_PORTS/# Porturi client - configurare manuală necesară/g' "$conf_file"
sed -i 's/EOFCONFIG_SSL_PORTS/# Porturi SSL - configurare manuală necesară/g' "$conf_file"
sed -i "s/EOFCONFIG_NETWORK/$network_name/g" "$conf_file"
sed -i "s/EOFCONFIG_PREFIX/$PREFIX/g" "$conf_file"
sed -i 's/EOFCONFIG[_A-Z]*/# PLACEHOLDER - configurare manuală necesară/g' "$conf_file"
log_warn "Reparare de urgență aplicată - verifică configurația manual"
fi
# 6. TEST FINAL COMPLET și REPARARE AUTOMATĂ
log_info "Test final COMPLET cu reparare automată..."
if [ -x "$PREFIX/bin/ircd" ]; then
FINAL_TEST_OUTPUT=$("$PREFIX/bin/ircd" -c -f "$conf_file" 2>&1)
FINAL_TEST_EXIT=$?
if [ $FINAL_TEST_EXIT -eq 0 ]; then
log_success "✓ CONFIGURAȚIA ESTE COMPLETĂ ȘI VALIDĂ - gata de folosire!"
else
log_error "Încă sunt erori - aplicare reparare AUTOMATĂ..."
echo "$FINAL_TEST_OUTPUT" | head -5
# Reparare automată pentru erori comune
if echo "$FINAL_TEST_OUTPUT" | grep -q "line [0-9]*.*syntax error"; then
ERROR_LINE=$(echo "$FINAL_TEST_OUTPUT" | grep -o "line [0-9]*" | grep -o "[0-9]*")
log_warn "Eroare pe linia $ERROR_LINE - aplicare fix automat..."
# Comentează linia problematică
sed -i "${ERROR_LINE}s/^/# EROARE REPARATĂ AUTOMAT: /" "$conf_file"
# Adaugă port de rezervă dacă e vorba de porturi
if echo "$FINAL_TEST_OUTPUT" | grep -qi "port"; then
sed -i "${ERROR_LINE}a\\nPort {\n vhost = \"$VHOST_FOR_PORTS\" 6667;\n hidden = yes;\n};" "$conf_file"
fi
log_success "Reparare automată aplicată pentru linia $ERROR_LINE"
fi
fi
else
log_warn "Nu pot testa configurația - ircd nu găsit, se continuă"
fi
log_success "REMEDIERI COMPLETE INTEGRATE aplicate cu SUCCES - NU mai sunt necesare scripturi de fix!"
# Creare directoare - ambele etc și lib pentru compatibilitate
log_info "Creare structură de directoare..."
mkdir -p "$PREFIX/log"
mkdir -p "$PREFIX/etc"
mkdir -p "$PREFIX/lib"
mkdir -p "$PREFIX/var"
# IMPORTANT: Copiază configurația și în etc/ pentru compatibilitate cu unele scripturi
cp "$conf_file" "$PREFIX/etc/ircd.conf"
log_success "Configurația copiată în ambele locații: etc/ și lib/"
# Creare fișiere MOTD în ambele locații
if [ ! -f "$PREFIX/lib/ircd.motd" ]; then
cat > "$PREFIX/lib/ircd.motd" << 'EOFMOTD'
╔═══════════════════════════════════════╗
║ Bine venit pe UnderChat IRCd! ║
║ ║
║ Server: %-30s ║
║ Versiune: 1.0.3 ║
║ ║
║ Pentru suport: #support ║
║ Website: https://underchat.org ║
╚═══════════════════════════════════════╝
🌟 Caracteristici server:
• Host hiding pentru protecția utilizatorilor
• SSL/TLS encryption disponibil
• Anti-spam și anti-flood protection
• Canale cu diverse moduri și opțiuni
📋 Comenzi utile:
• /LIST - Listează canalele disponibile
• /WHOIS nick - Informații despre utilizatori
• /JOIN #canal - Intră într-un canal
• /HELP - Lista comenzilor disponibile
🔒 Acest server respectă politica de confidențialitate
și regulile rețelei UnderChat. Comportamentul abuziv
poate duce la restricții sau banuri.
Distracție plăcută pe UnderChat! 🎉
EOFMOTD
# Copiază și în etc/
cp "$PREFIX/lib/ircd.motd" "$PREFIX/etc/ircd.motd"
log_success "MOTD creat în lib/ și copiat în etc/"
fi
# Rezumat instalare
echo ""
echo -e "${VERDE}"
echo "========================================="
echo " ✓ Instalare completă!"
echo "========================================="
echo -e "${NC}"
echo ""
echo -e "${GALBEN}Informații de instalare:${NC}"
echo " Calea de instalare: $PREFIX"
echo " Fișier configurare: $conf_file"
echo " Fișier log: $PREFIX/log/ircd.log"
echo " Maxim conexiuni: $MAXCON"
echo " Debug: $([ $ENABLE_DEBUG -eq 1 ] && echo 'Activat' || echo 'Dezactivat')"
echo " SSL/TLS: $([ $ENABLE_SSL -eq 1 ] && echo 'Activat' || echo 'Dezactivat')"
echo ""
echo -e "${GALBEN}Pași următori:${NC}"
echo " 1. Editează configurarea: nano $conf_file"
echo " 2. Generează parola operator: $PREFIX/bin/umkpasswd"
echo " 3. Pornește serverul: $PREFIX/bin/ircd -f $conf_file"
echo " 4. Conectează-te: irc://localhost:6667"
echo ""
}
# Apelează funcția principală
main "$@"