Newer
Older
# _____ _ _
# | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# | __| _| -_| -_| . | . | | . | . | | -_|
# |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___|
#
# IRC server application
#
# License
# =======
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
IN_DEFAULT_INSTALL=0
# An optional password to log into IRC. This applies to all users
IRC_PASSWORD=
IRC_DESCRIPTION=$'The classic low bandwidth chat system'
IRC_MOBILE_APP_URL='https://f-droid.org/packages/org.yaaic'
function upgrade_distro_irc {
target_distro="$1"
if [[ "$target_distro" == 'buster' ]]; then
echo -n ''
fi
}
function change_default_domain_name_irc {
new_default_domain_name="$1"
read_config_param DEFAULT_DOMAIN_NAME
sed -i "s/$DEFAULT_DOMAIN_NAME/$new_default_domain_name/g" /etc/ngircd/ngircd.conf
if [ -f "/etc/ssl/certs/${new_default_domain_name}.pem" ]; then
sed -i "s|CertFile = .*|CertFile = /etc/ssl/certs/${new_default_domain_name}.pem|g" /etc/ngircd/ngircd.conf
else
sed -i "s|CertFile = .*|CertFile = /etc/ssl/certs/${new_default_domain_name}.crt|g" /etc/ngircd/ngircd.conf
fi
sed -i "s|DHFile = .*|DHFile = /etc/ssl/certs/${new_default_domain_name}.dhparam|g" /etc/ngircd/ngircd.conf
sed -i "s|KeyFile = .*|KeyFile = /etc/ssl/private/${new_default_domain_name}.key|g" /etc/ngircd/ngircd.conf
systemctl restart ngircd
}
function logging_on_irc {
echo -n ''
}
function logging_off_irc {
echo -n ''
}
grep "Password =" /etc/ngircd/ngircd.conf | head -n 1 | awk -F '=' '{print $2}'
if [ ! -f /home/znc/.znc/znc.pem ]; then
# no certificate exists
else
# an existing certificate is being used
}
function stop_irc_bouncer {
pkill znc
}
function create_irssi_config {
new_username="$1"
read_config_param IRC_BOUNCER_PORT
read_config_param IRC_ONION_PORT
new_name="$2"
if [ ${#new_name} -eq 0 ]; then
new_name="$new_username"
fi
{ echo 'servers = (';
echo ' {';
echo ' address = "chat.freenode.net";';
echo ' chatnet = "Freenode";';
echo ' port = "6667";';
echo ' autoconnect = "no";';
echo ' },';
echo ' {';
echo ' address = "irc.oftc.net";';
echo ' chatnet = "OFTC";';
echo ' port = "6667";';
echo ' autoconnect = "no";';
echo ' },';
echo ' {';
echo " address = \"127.0.0.1\";";
echo ' ssl_verify = "no";'; } > "/home/${new_username}/.irssi/config"
echo ' use_ssl = "yes";' >> "/home/${new_username}/.irssi/config"
echo " port = \"${IRC_BOUNCER_PORT}\";" >> "/home/${new_username}/.irssi/config"
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
echo ' use_ssl = "no";' >> "/home/${new_username}/.irssi/config"
IRC_ONION_HOSTNAME=$(grep "irc onion domain" "${COMPLETION_FILE}" | head -n 1 | awk -F ':' '{print $2}')
echo " port = \"${IRC_ONION_PORT}\";" >> "/home/${new_username}/.irssi/config"
fi
echo ' chatnet = "Freedombone";' >> "/home/${new_username}/.irssi/config"
echo ' autoconnect = "yes";' >> "/home/${new_username}/.irssi/config"
if [ "${IRC_PASSWORD}" ]; then
echo " password = \"${IRC_PASSWORD}\";" >> "/home/${new_username}/.irssi/config"
fi
{ echo ' }';
echo ');';
echo '';
echo 'chatnets = {';
echo ' Freedombone = {';
echo ' type = "IRC";';
echo ' max_kicks = "1";';
echo ' max_msgs = "4";';
echo ' max_whois = "1";';
echo ' };';
echo ' Freenode = {';
echo ' type = "IRC";';
echo ' max_kicks = "1";';
echo ' max_msgs = "4";';
echo ' max_whois = "1";';
echo ' };';
echo ' OFTC = {';
echo ' type = "IRC";';
echo ' max_kicks = "1";';
echo ' max_msgs = "1";';
echo ' max_whois = "1";';
echo ' };';
echo '};';
echo '';
echo 'channels = (';
echo ' { name = "#freedombone"; chatnet = "Freedombone"; autojoin = "Yes"; },';
echo ');';
echo '';
echo 'settings = {';
echo " core = { real_name = \"$new_name\"; user_name = \"$new_username\"; nick = \"$new_username\"; };";
echo ' "fe-text" = { actlist_sort = "refnum"; };';
echo '};';
echo 'ignores = ( { level = "CTCPS"; } );'; } >> "/home/${new_username}/.irssi/config"
chown -R "${new_username}":"${new_username}" "/home/${new_username}/.irssi"
function remove_user_irc_bouncer {
remove_username="$1"
sed -i "/<User ${remove_username}>/,/</User>/d" /home/znc/.znc/configs/znc.conf
function remove_user_irc {
remove_username="$1"
remove_user_irc_bouncer "${remove_username}"
if [ -d "/home/${remove_username}/.irssi" ]; then
rm -rf "/home/${remove_username}/.irssi"
if [ -d "/home/${remove_username}/irclogs" ]; then
rm -rf "/home/${remove_username}/irclogs"
function irc_set_global_password_base {
NEW_IRC_PASSWORD="$1"
EXISTING_IRC_PASSWORD=$(irc_get_global_password)
sed -i "0,/RE/s/Password =.*/Password =$NEW_IRC_PASSWORD/" /etc/ngircd/ngircd.conf
# replace the password for all users
for d in /home/*/ ; do
IRC_USERNAME=$(echo "$d" | awk -F '/' '{print $3}')
if [[ $(is_valid_user "$IRC_USERNAME") == "1" ]]; then
if [ -f "/home/${IRC_USERNAME}/.irssi/config" ]; then
sed -i "s|$EXISTING_IRC_PASSWORD|$NEW_IRC_PASSWORD|g" "/home/${IRC_USERNAME}/.irssi/config"
chown -R "${IRC_USERNAME}":"${IRC_USERNAME}" "/home/${IRC_USERNAME}/.irssi"
fi
fi
done
read_config_param DEFAULT_DOMAIN_NAME
read_config_param IRC_PORT
read_config_param MY_USERNAME
stop_irc_bouncer
sleep 2
# change the hashes. There are multiple users, but since we're using a global
# password this doesn't matter
ZNC_SALT="$(dd if=/dev/urandom bs=16c count=1 | md5sum | awk -F ' ' '{print $1}' | cut -c1-20)"
new_user_hash=$(echo -n "${NEW_IRC_PASSWORD}${ZNC_SALT}" | sha256sum | awk -F ' ' '{print $1}')
sed -i "s|Hash = .*|Hash = ${new_user_hash}|g" /home/znc/.znc/configs/znc.conf
sed -i "s|Salt = .*|Salt = ${ZNC_SALT}|g" /home/znc/.znc/configs/znc.conf
# change the server password
sed -i "s|Server = 127.0.0.1.*|Server = 127.0.0.1 ${IRC_PORT} ${NEW_IRC_PASSWORD}|g" /home/znc/.znc/configs/znc.conf
# Update the password
"${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a irc -p "$NEW_IRC_PASSWORD"
if [ -f "$INSTALL_DIR/matrix_irc_bridge/config.yaml" ]; then
sed -i "s|password: .*|password: \"$NEW_IRC_PASSWORD\"|g" "$INSTALL_DIR/matrix_irc_bridge/config.yaml"
systemctl restart matrix_irc_bridge
fi
write_config_param "IRC_PASSWORD" "$NEW_IRC_PASSWORD"
# restart the daemon for the new password to take effect
systemctl restart ngircd
start_irc_bouncer
}
function change_password_irc {
new_global_password="$2"
irc_set_global_password_base "$new_global_password"
}
new_user_password=$(irc_get_global_password)
IRC_PASSWORD="$new_user_password"
if [[ $(is_valid_user "$new_username") == "0" ]]; then
return
fi
read_config_param IRC_PORT
read_config_param DEFAULT_DOMAIN_NAME
"${PROJECT_NAME}-pass" -u "$new_username" -a irc -p "$new_user_password"
ZNC_SALT="$(dd if=/dev/urandom bs=16c count=1 | md5sum | awk -F ' ' '{print $1}' | cut -c1-20)"
new_user_hash=$(echo -n "${new_user_password}${ZNC_SALT}" | sha256sum | awk -F ' ' '{print $1}')
if grep -q "<User ${new_username}>" /home/znc/.znc/configs/znc.conf; then
# user already exists
sed -i "s|Hash = .*|Hash = ${new_user_hash}|g" /home/znc/.znc/configs/znc.conf
sed -i "s|Salt = .*|Salt = ${ZNC_SALT}|g" /home/znc/.znc/configs/znc.conf
return
fi
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
{ echo "<User ${new_username}>";
echo " Admin = ${is_admin}";
echo " AltNick = ${new_username}_";
echo ' AppendTimestamp = false';
echo ' AutoClearChanBuffer = true';
echo ' AutoClearQueryBuffer = true';
echo " Buffer = ${IRC_BUFFER_LENGTH}";
echo ' DenyLoadMod = false';
echo ' DenySetBindHost = false';
echo " Ident = ${new_username}";
echo ' JoinTries = 10';
echo ' LoadModule = chansaver';
echo ' LoadModule = controlpanel';
echo ' MaxJoins = 10';
echo ' MaxNetworks = 10';
echo ' MaxQueryBuffers = 50';
echo ' MultiClients = true';
echo " Nick = ${new_username}";
echo ' PrependTimestamp = true';
echo ' QuitMsg = Bye';
echo " RealName = ${new_username}";
echo ' StatusPrefix = *';
echo ' TimestampFormat = [%H:%M:%S]';
echo '';
echo " <Network ${PROJECT_NAME}>";
echo ' LoadModule = chansaver';
echo ' LoadModule = simple_away';
echo '';
echo " Server = 127.0.0.1 ${IRC_PORT} ${IRC_PASSWORD}";
echo '';
echo " <Chan #${PROJECT_NAME}>";
echo ' </Chan>';
echo ' </Network>';
echo '';
echo ' <Network oftc>';
echo ' LoadModule = chansaver';
echo ' LoadModule = simple_away';
echo ' FloodBurst = 4';
echo ' FloodRate = 1.00';
echo ' IRCConnectEnabled = true';
echo ' Server = irc.oftc.net 6697';
echo ' </Network>';
echo '';
echo ' <Network freenode>';
echo ' LoadModule = chansaver';
echo ' LoadModule = simple_away';
echo ' FloodBurst = 4';
echo ' FloodRate = 1.00';
echo ' IRCConnectEnabled = true';
echo ' Server = irc.freenode.net 6697';
echo ' </Network>';
echo '';
echo ' <Pass password>';
echo " Hash = ${new_user_hash}";
echo ' Method = sha256';
echo " Salt = ${ZNC_SALT}";
echo ' </Pass>';
echo '</User>'; } >> /home/znc/.znc/configs/znc.conf
mkdir -p "/home/znc/.znc/users/${new_username}/moddata"
mkdir -p "/home/znc/.znc/users/${new_username}/networks"
mkdir "/home/znc/.znc/users/${new_username}/moddata/chanserver"
mkdir "/home/znc/.znc/users/${new_username}/moddata/controlpanel"
mkdir "/home/znc/.znc/users/${new_username}/moddata/perform"
mkdir "/home/znc/.znc/users/${new_username}/moddata/webadmin"
mkdir -p "/home/znc/.znc/users/${new_username}/networks/${PROJECT_NAME}/moddata/chansaver"
mkdir -p "/home/znc/.znc/users/${new_username}/networks/${PROJECT_NAME}/moddata/simple_away"
mkdir -p /home/znc/.znc/moddata/webadmin
chown -R znc:znc /home/znc/.znc
start_irc_bouncer
}
if [ ${#IRC_PASSWORD} -lt 2 ]; then
IRC_PASSWORD=
fi
if [ ! -d "/home/${new_username}/.irssi" ]; then
mkdir "/home/${new_username}/.irssi"
add_user_irc_bouncer "${new_username}" "${IRC_PASSWORD}"
function run_client_irc {
irssi
}
function irc_show_password {
dialog --title $"IRC Password" \
--msgbox "$IRC_PASSWORD" 6 40
}
function irc_set_global_password {
dialog --title $"IRC Password" \
--clear \
--backtitle $"Freedombone Control Panel" \
--passwordbox $"Password for all IRC users, or press Enter for no password" 10 60 "$EXISTING_IRC_PASSWORD" 2> "$data"
sel=$?
case $sel in
0)
dialog --title $"IRC Password" \
--msgbox $"The IRC password was changed" 6 40
;;
esac
}
function configure_interactive_irc {
if [ ! -d /etc/ngircd ]; then
dialog --title $"IRC Menu" \
--msgbox $"No IRC server is installed" 6 70
return
fi
W=(1 $"Set a password for all IRC users"
2 $"Show current IRC login password")
while true
do
# shellcheck disable=SC2068
selection=$(dialog --backtitle $"Freedombone Administrator Control Panel" --title $"IRC" --menu $"Choose an operation, or ESC to exit:" 10 60 2 "${W[@]}" 3>&2 2>&1 1>&3)
if [ ! "$selection" ]; then
break
fi
case $selection in
1) irc_set_global_password;;
2) irc_show_password;;
esac
done
}
function install_interactive_irc {
echo -n ''
$REMOVE_PACKAGES_PURGE ngircd
$REMOVE_PACKAGES_PURGE irssi
if [ -d /etc/ngircd ]; then
rm -rf /etc/ngircd
fi
iptables -D INPUT -p tcp --dport 1024:65535 --sport ${IRC_BOUNCER_PORT} -j ACCEPT
function_check save_firewall_settings
save_firewall_settings
function_check remove_onion_service
remove_onion_service irc ${IRC_ONION_PORT}
remove_completion_param install_irc
remove_completion_param configure_firewall_for_irc
if [ -d /var/run/ircd ]; then
rm -rf /var/run/ircd
fi
function configure_firewall_for_irc {
if [ ! -d /etc/ngircd ]; then
return
fi
if [[ $(is_completed "${FUNCNAME[0]}") == "1" ]]; then
if [[ ${INSTALLED_WITHIN_DOCKER} == "yes" ]]; then
# docker does its own firewalling
return
fi
iptables -I INPUT -p tcp --dport 1024:65535 --sport ${IRC_BOUNCER_PORT} -j ACCEPT
function_check save_firewall_settings
save_firewall_settings
if [ ! -d /etc/ngircd ]; then
echo $"ERROR: ngircd does not appear to have installed. $CHECK_MESSAGE"
exit 53
fi
# obtain a cert for the default domain
if [[ "$(cert_exists "${DEFAULT_DOMAIN_NAME}" pem)" == "0" ]]; then
echo $'Obtaining certificate for the main domain'
if [[ "$(cert_exists "${DEFAULT_DOMAIN_NAME}")" == "0" ]]; then
"${PROJECT_NAME}-addcert" -h ngircd --dhkey "${DH_KEYLENGTH}"
IRC_PASSWORD="$(create_password "${MINIMUM_PASSWORD_LENGTH}")"
{ echo '**************************************************';
echo $'* F R E E D O M B O N E I R C *';
echo '* *';
echo $'* Freedom in the Cloud *';
echo '**************************************************'; } > /etc/ngircd/motd
sed -i 's|MotdFile = /etc/ngircd/ngircd.motd|MotdFile = /etc/ngircd/motd|g' /etc/ngircd/ngircd.conf
sed -i "s/irc@irc.example.com/$MY_EMAIL_ADDRESS/g" /etc/ngircd/ngircd.conf
sed -i "s/irc.example.net/$DEFAULTDOMAIN/g" /etc/ngircd/ngircd.conf
sed -i "s|Yet another IRC Server running on Debian GNU/Linux|IRC Server of $DEFAULTDOMAIN|g" /etc/ngircd/ngircd.conf
sed -i 's/;Password = wealllikedebian/Password =/g' /etc/ngircd/ngircd.conf
sed -i "s/;Ports =.*/Ports = ${IRC_PORT}/g" /etc/ngircd/ngircd.conf
if [[ $ONION_ONLY == 'no' ]]; then
sed -i "s|;CertFile = /etc/ssl/certs/server.crt|CertFile = /etc/ssl/certs/${DEFAULT_DOMAIN_NAME}.pem|g" /etc/ngircd/ngircd.conf
else
sed -i "s|;CertFile = /etc/ssl/certs/server.crt|CertFile = /etc/ssl/certs/${DEFAULT_DOMAIN_NAME}.crt|g" /etc/ngircd/ngircd.conf
fi
sed -i "s|;DHFile = /etc/ngircd/dhparams.pem|DHFile = /etc/ssl/certs/${DEFAULT_DOMAIN_NAME}.dhparam|g" /etc/ngircd/ngircd.conf
sed -i "s|;KeyFile = /etc/ssl/private/server.key|KeyFile = /etc/ssl/private/${DEFAULT_DOMAIN_NAME}.key|g" /etc/ngircd/ngircd.conf
sed -i "s/;Ports =.*/Ports = ${IRC_PORT}/2" /etc/ngircd/ngircd.conf
else
sed -i 's|;SSLConnect.*|SSLConnect = no|g'
# comment out the second Ports entry
sed -i '0,/Ports =/! s/Ports =/;Ports =/' /etc/ngircd/ngircd.conf
fi
sed -i "s/;Name = #ngircd/Name = #${PROJECT_NAME}/g" /etc/ngircd/ngircd.conf
sed -i "s/;Topic = Our ngircd testing channel/Topic = ${PROJECT_NAME} chat channel/g" /etc/ngircd/ngircd.conf
sed -i 's/;MaxUsers = 23/MaxUsers = 23/g' /etc/ngircd/ngircd.conf
sed -i "s|;KeyFile = /etc/ngircd/#chan.key|KeyFile = /etc/ngircd/${PROJECT_NAME}.key|g" /etc/ngircd/ngircd.conf
sed -i "s/;CloakHost = cloaked.host/CloakHost = ${PROJECT_NAME}/g" /etc/ngircd/ngircd.conf
IRC_SALT="$(create_password 30)"
if [ -f "${IMAGE_PASSWORD_FILE}" ]; then
IRC_OPERATOR_PASSWORD="$(printf "%s" "$(cat "$IMAGE_PASSWORD_FILE")")"
IRC_OPERATOR_PASSWORD="$(create_password "${MINIMUM_PASSWORD_LENGTH}")"
fi
sed -i "s|;CloakHostSalt = abcdefghijklmnopqrstuvwxyz|CloakHostSalt = $IRC_SALT|g" /etc/ngircd/ngircd.conf
sed -i 's/;ConnectIPv4 = yes/ConnectIPv4 = yes/g' /etc/ngircd/ngircd.conf
sed -i 's/;MorePrivacy = no/MorePrivacy = yes/g' /etc/ngircd/ngircd.conf
sed -i 's/;RequireAuthPing = no/RequireAuthPing = no/g' /etc/ngircd/ngircd.conf
sed -i "s/;Name = TheOper/Name = $MY_USERNAME/g" /etc/ngircd/ngircd.conf
sed -i "s/;Password = ThePwd/Password = $IRC_OPERATOR_PASSWORD/g" /etc/ngircd/ngircd.conf
sed -i 's|;Listen =.*|Listen = 0.0.0.0,0.0.0.0:9050,127.0.0.1,127.0.0.1:9050|g' /etc/ngircd/ngircd.conf
sed -i "0,/RE/s/Password =.*/Password =$IRC_PASSWORD/" /etc/ngircd/ngircd.conf
fi
# upgrade a cypher
sed -i 's|SECURE128|SECURE256|g' /etc/ngircd/ngircd.conf
mkdir /var/run/ircd
chown -R irc:irc /var/run/ircd
mkdir /var/run/ngircd
touch /var/run/ngircd/ngircd.pid
chown -R irc:irc /var/run/ngircd
# shellcheck disable=SC2034
IRC_ONION_HOSTNAME=$(add_onion_service irc "${IRC_BOUNCER_PORT}" "${IRC_ONION_PORT}")
if [ ! -d /var/run/ircd ]; then
mkdir /var/run/ircd
chown -R irc:irc /var/run/ircd
fi
function_check configure_firewall_for_irc
configure_firewall_for_irc
if [ ! -d "/home/${MY_USERNAME}/.irssi" ]; then
mkdir "/home/${MY_USERNAME}/.irssi"
create_irssi_config "${MY_USERNAME}" "$MY_NAME"
function install_irc_bouncer {
if [[ $(app_is_installed irc_bouncer) == "1" ]]; then
return
fi
if [ ! -d /home/znc ]; then
echo $"/home/znc directory not created"
mkdir -p /home/znc/.znc/configs
mkdir -p /home/znc/.znc/users
{ echo 'AnonIPLimit = 10';
echo 'ConnectDelay = 5';
echo 'HideVersion = false';
echo 'MaxBufferSize = 500';
echo 'ProtectWebSessions = true';
echo 'SSLCertFile = /home/znc/.znc/znc.pem';
echo 'ServerThrottle = 30';
echo 'Version = 1.6.2';
echo '';
echo '<Listener listener0>';
echo ' AllowIRC = true';
echo ' AllowWeb = false';
echo ' IPv4 = true';
echo ' IPv6 = true';
echo ' Port = 6697'; } > /home/znc/.znc/configs/znc.conf
if [[ "${ONION_ONLY}" == 'no' ]]; then
echo ' SSL = true' >> /home/znc/.znc/configs/znc.conf
else
echo ' SSL = false' >> /home/znc/.znc/configs/znc.conf
fi
{ echo ' URIPrefix = /';
echo '</Listener>';
echo ''; } >> /home/znc/.znc/configs/znc.conf
{ echo '<Listener listener1>';
echo ' AllowIRC = true';
echo ' AllowWeb = false';
echo ' IPv4 = true';
echo ' IPv6 = true';
echo " Port = ${IRC_ONION_PORT}";
echo ' SSL = false';
echo ' URIPrefix = /';
echo '</Listener>';
echo ''; } >> /home/znc/.znc/configs/znc.conf
add_user_irc_bouncer "${MY_USERNAME}" "${IRC_PASSWORD}" true
# certificate for use with SSL
start_irc_bouncer
function_check cron_add_mins
cron_add_mins 10 "/usr/bin/znc 2> /dev/null" znc
install_completed irc_bouncer
}
increment_app_install_progress
increment_app_install_progress