#!/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 "; }; # ============================================================================ # 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 "$@"