sshmngr: Fix session detection for OpenSSH backend

The `sshmngr` service failed to list active sessions with the `sshd`
(OpenSSH) backend because the session detection logic could not handle
the process structure of modern OpenSSH, which uses an intermediate
process for new connections.

This commit resolves the issue by:
- Improving process lookup to check for grandparent PIDs, correctly
  identifying the session process.
- Querying the correct intermediate process for network connection details.
  parse netstat output.

The new logic is encapsulated in a `get_network_info` function within the
`openssh` backend script to maintain compatibility with the `dropbear`
backend, which uses a simpler implementation of the same function.
This commit is contained in:
Xiaofeng Meng 2025-06-24 09:26:15 +02:00 committed by Vivek Dutta
parent c64701e6b2
commit ed5169b94c
3 changed files with 70 additions and 16 deletions

View file

@ -82,22 +82,15 @@ case "$1" in
# if pid equals server pid then skip
[ "$session_pid" -eq "$server_pid" ] && continue
# get this session's ppid
session_ppid="$(grep PPid /proc/$session_pid/status | awk '{print $2}')"
# if session's parent is this server
if [ "$session_ppid" -eq "$server_pid" ]; then
session="$(netstat -ntp | grep $session_pid/ | awk '{print $5,$7}' | cut -d'/' -f 1)"
# return session IP, Port, PID
ip=$(echo "$session" | cut -d ':' -f 1)
port=$(echo "$session" | cut -d ':' -f 2 | cut -d ' ' -f 1)
pid=$(echo "$session" | cut -d ':' -f 2 | cut -d ' ' -f 2)
network_info="$(get_network_info "$session_pid" "$server_pid")"
if [ $? -eq 0 ]; then
ip=$(echo "$network_info" | cut -d' ' -f1)
port=$(echo "$network_info" | cut -d' ' -f2)
json_add_object
json_add_string "ip" "$ip"
json_add_string "port" "$port"
json_add_string "pid" "$pid"
json_add_string "pid" "$session_pid"
json_close_object
fi
done
@ -142,10 +135,14 @@ case "$1" in
[ "$session_pid" -eq "$server_pid" ] && continue
# get this session's ppid
session_ppid="$(grep PPid /proc/$session_pid/status | awk '{print $2}')"
session_ppid="$(grep PPid /proc/$session_pid/status 2>/dev/null | awk '{print $2}')"
[ -z "$session_ppid" ] && continue
# if session's parent is this server
if [ "$session_ppid" -eq "$server_pid" ]; then
# get the parent of the parent (the grandparent)
grandparent_pid="$(grep PPid /proc/$session_ppid/status 2>/dev/null | awk '{print $2}')"
# if session's parent or grandparent is this server
if [ "$session_ppid" -eq "$server_pid" ] || { [ -n "$grandparent_pid" ] && [ "$grandparent_pid" -eq "$server_pid" ]; }; then
kill -15 "$session_pid"
fi
done

View file

@ -17,5 +17,26 @@ get_session_pids()
{
local PidFile="$1"
echo "$(ps -w | grep $PidFile | grep -v grep | awk '{print $1}')"
echo "$(ps -w | grep "$PidFile" | grep -v grep | awk '{print $1}')"
}
get_network_info()
{
local session_pid="$1"
local server_pid="$2"
# get this session's ppid
session_ppid="$(grep PPid /proc/$session_pid/status | awk '{print $2}')"
# if session's parent is this server
if [ "$session_ppid" -eq "$server_pid" ]; then
session="$(netstat -ntp | grep "$session_pid/" | awk '{print $5,$7}' | cut -d'/' -f 1)"
if [ -n "$session" ]; then
ip=$(echo "$session" | cut -d ':' -f 1)
port=$(echo "$session" | cut -d ':' -f 2 | cut -d ' ' -f 1)
echo "$ip $port"
return 0
fi
fi
return 1
}

View file

@ -17,3 +17,39 @@ get_session_pids()
{
echo "$(ps -w | grep sshd | grep pts | awk '{print $1}')"
}
get_network_info()
{
local session_pid="$1"
local server_pid="$2"
local session_info=""
local ip=""
local port=""
# get this session's ppid
session_ppid="$(grep PPid /proc/$session_pid/status 2>/dev/null | awk '{print $2}')"
[ -z "$session_ppid" ] && return 1
# get the parent of the parent (the grandparent)
grandparent_pid="$(grep PPid /proc/$session_ppid/status 2>/dev/null | awk '{print $2}')"
# if session's parent, or grandparent, is this server
if [ "$session_ppid" -eq "$server_pid" ] || { [ -n "$grandparent_pid" ] && [ "$grandparent_pid" -eq "$server_pid" ]; }; then
# The connection is usually handled by the parent process for openssh
session_info="$(netstat -ntp 2>/dev/null | awk -v pid="$session_ppid" '$7 ~ "^"pid"/" {print $5}')"
# If not found on parent, check the child process itself (less common for openssh)
if [ -z "$session_info" ]; then
session_info="$(netstat -ntp 2>/dev/null | awk -v pid="$session_pid" '$7 ~ "^"pid"/" {print $5}')"
fi
if [ -n "$session_info" ]; then
ip=$(echo "$session_info" | cut -d ':' -f 1)
port=$(echo "$session_info" | cut -d ':' -f 2)
echo "$ip $port"
return 0
fi
fi
return 1
}