mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-25 05:47:00 +00:00
8139438fc0
Override the default shutdown action (stop) and close all processes of dropbear Since commit 498fe85, the stop action only closes the process that's listening for new connections, maintaining the ones with existing clients. This poses a problem when restarting or shutting-down a device, because the connections with existing SSH clients, like OpenSSH, are not properly closed, causing them to hang. This situation can be avoided by closing all dropbear processes when shutting-down the system, which closes properly the connections with current clients. Signed-off-by: Christian Schoenebeck <christian.schoenebeck@gmail.com> [Luis: Rework commit message] Signed-off-by: Luis Araneda <luaraneda@gmail.com> (cherry picked from commit 1e177844bc814d3846312c91cd0f7a54df4f32b9)
209 lines
4.8 KiB
Bash
Executable File
209 lines
4.8 KiB
Bash
Executable File
#!/bin/sh /etc/rc.common
|
|
# Copyright (C) 2006-2010 OpenWrt.org
|
|
# Copyright (C) 2006 Carlos Sobrinho
|
|
|
|
START=50
|
|
STOP=50
|
|
|
|
USE_PROCD=1
|
|
PROG=/usr/sbin/dropbear
|
|
NAME=dropbear
|
|
PIDCOUNT=0
|
|
EXTRA_COMMANDS="killclients"
|
|
EXTRA_HELP=" killclients Kill ${NAME} processes except servers and yourself"
|
|
|
|
append_ports()
|
|
{
|
|
local ipaddrs="$1"
|
|
local port="$2"
|
|
|
|
[ -z "$ipaddrs" ] && {
|
|
procd_append_param command -p "$port"
|
|
return
|
|
}
|
|
|
|
for addr in $ipaddrs; do
|
|
procd_append_param command -p "$addr:$port"
|
|
done
|
|
}
|
|
|
|
validate_section_dropbear()
|
|
{
|
|
uci_validate_section dropbear dropbear "${1}" \
|
|
'PasswordAuth:bool:1' \
|
|
'enable:bool:1' \
|
|
'Interface:string' \
|
|
'GatewayPorts:bool:0' \
|
|
'RootPasswordAuth:bool:1' \
|
|
'RootLogin:bool:1' \
|
|
'rsakeyfile:file' \
|
|
'BannerFile:file' \
|
|
'Port:list(port):22' \
|
|
'SSHKeepAlive:uinteger:300' \
|
|
'IdleTimeout:uinteger:0' \
|
|
'MaxAuthTries:uinteger:3' \
|
|
'RecvWindowSize:uinteger:0' \
|
|
'mdns:bool:1'
|
|
}
|
|
|
|
dropbear_instance()
|
|
{
|
|
local PasswordAuth enable Interface GatewayPorts \
|
|
RootPasswordAuth RootLogin rsakeyfile \
|
|
BannerFile Port SSHKeepAlive IdleTimeout \
|
|
MaxAuthTries RecvWindowSize mdns ipaddrs
|
|
|
|
validate_section_dropbear "${1}" || {
|
|
echo "validation failed"
|
|
return 1
|
|
}
|
|
|
|
[ -n "${Interface}" ] && {
|
|
network_get_ipaddrs_all ipaddrs "${Interface}" || {
|
|
echo "interface ${Interface} has no physdev or physdev has no suitable ip"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
[ "${enable}" = "0" ] && return 1
|
|
PIDCOUNT="$(( ${PIDCOUNT} + 1))"
|
|
local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
|
|
|
|
procd_open_instance
|
|
procd_set_param command "$PROG" -F -P "$pid_file"
|
|
[ "${PasswordAuth}" -eq 0 ] && procd_append_param command -s
|
|
[ "${GatewayPorts}" -eq 1 ] && procd_append_param command -a
|
|
[ "${RootPasswordAuth}" -eq 0 ] && procd_append_param command -g
|
|
[ "${RootLogin}" -eq 0 ] && procd_append_param command -w
|
|
[ -n "${rsakeyfile}" ] && procd_append_param command -r "${rsakeyfile}"
|
|
[ -n "${BannerFile}" ] && procd_append_param command -b "${BannerFile}"
|
|
append_ports "${ipaddrs}" "${Port}"
|
|
[ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}"
|
|
[ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}"
|
|
[ "${MaxAuthTries}" -ne 0 ] && procd_append_param command -T "${MaxAuthTries}"
|
|
[ "${RecvWindowSize}" -gt 0 -a "${RecvWindowSize}" -le 1048576 ] && \
|
|
procd_append_param command -W "${RecvWindowSize}"
|
|
[ "${mdns}" -ne 0 ] && procd_add_mdns "ssh" "tcp" "$Port" "daemon=dropbear"
|
|
procd_set_param respawn
|
|
procd_close_instance
|
|
}
|
|
|
|
keygen()
|
|
{
|
|
for keytype in rsa; do
|
|
# check for keys
|
|
key=dropbear/dropbear_${keytype}_host_key
|
|
[ -f /tmp/$key -o -s /etc/$key ] || {
|
|
# generate missing keys
|
|
mkdir -p /tmp/dropbear
|
|
[ -x /usr/bin/dropbearkey ] && {
|
|
/usr/bin/dropbearkey -t $keytype -f /tmp/$key 2>&- >&- && exec /etc/rc.common "$initscript" start
|
|
} &
|
|
exit 0
|
|
}
|
|
done
|
|
|
|
lock /tmp/.switch2jffs
|
|
mkdir -p /etc/dropbear
|
|
mv /tmp/dropbear/dropbear_* /etc/dropbear/
|
|
lock -u /tmp/.switch2jffs
|
|
chown root /etc/dropbear
|
|
chmod 0700 /etc/dropbear
|
|
}
|
|
|
|
load_interfaces()
|
|
{
|
|
config_get interface "$1" Interface
|
|
config_get enable "$1" enable 1
|
|
|
|
[ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}"
|
|
}
|
|
|
|
start_service()
|
|
{
|
|
[ -s /etc/dropbear/dropbear_rsa_host_key ] || keygen
|
|
|
|
. /lib/functions.sh
|
|
. /lib/functions/network.sh
|
|
|
|
config_load "${NAME}"
|
|
config_foreach dropbear_instance dropbear
|
|
}
|
|
|
|
service_triggers()
|
|
{
|
|
local interfaces
|
|
|
|
procd_add_config_trigger "config.change" "dropbear" /etc/init.d/dropbear reload
|
|
|
|
config_load "${NAME}"
|
|
config_foreach load_interfaces dropbear
|
|
|
|
[ -n "${interfaces}" ] && {
|
|
for n in $interfaces ; do
|
|
procd_add_interface_trigger "interface.*" $n /etc/init.d/dropbear reload
|
|
done
|
|
}
|
|
|
|
procd_add_validation validate_section_dropbear
|
|
}
|
|
|
|
shutdown() {
|
|
# close all open connections
|
|
killall dropbear
|
|
}
|
|
|
|
killclients()
|
|
{
|
|
local ignore=''
|
|
local server
|
|
local pid
|
|
|
|
# if this script is run from inside a client session, then ignore that session
|
|
pid="$$"
|
|
while [ "${pid}" -ne 0 ]
|
|
do
|
|
# get parent process id
|
|
pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
|
|
[ "${pid}" -eq 0 ] && break
|
|
|
|
# check if client connection
|
|
grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" && {
|
|
append ignore "${pid}"
|
|
break
|
|
}
|
|
done
|
|
|
|
# get all server pids that should be ignored
|
|
for server in `cat /var/run/${NAME}.*.pid`
|
|
do
|
|
append ignore "${server}"
|
|
done
|
|
|
|
# get all running pids and kill client connections
|
|
local skip
|
|
for pid in `pidof "${NAME}"`
|
|
do
|
|
# check if correct program, otherwise process next pid
|
|
grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
|
|
continue
|
|
}
|
|
|
|
# check if pid should be ignored (servers, ourself)
|
|
skip=0
|
|
for server in ${ignore}
|
|
do
|
|
if [ "${pid}" = "${server}" ]
|
|
then
|
|
skip=1
|
|
break
|
|
fi
|
|
done
|
|
[ "${skip}" -ne 0 ] && continue
|
|
|
|
# kill process
|
|
echo "${initscript}: Killing ${pid}..."
|
|
kill -KILL ${pid}
|
|
done
|
|
}
|