make getpeername() return the original socket address which before it was intercepted
[hband-tools.git] / root-tools / sshwho
blob3801852e0e14656dfea1541534650f9a6ee93cc4
1 #!/bin/bash
3 set -e
4 OPTERR=1
5 declare -a argv
6 declare -A flag
7 sshd_exe_path=/usr/sbin/sshd
10 ps()
12 command ps "$@" || true
15 psgetenv()
17 grep -aPo "\x00$2=[^\x00]+" "/proc/$1/environ" | cut -f2- -d=
20 find_slave_sshd_pids()
22 local pids=()
23 local current_master_sshd_pid=`cat /var/run/sshd.pid`
25 for pid in `find /proc -mindepth 1 -maxdepth 1 -regex '/proc/[0-9]+' -printf "%f "`
27 if [ $pid = $current_master_sshd_pid ]
28 then
29 continue
31 if [ "$(readlink /proc/$pid/exe)" = "$sshd_exe_path" ]
32 then
33 if [ "$(stat -c %u /proc/$pid)" = 0 ]
34 then
35 if grep -q -m1 -E "^PPid:\s*(1|$current_master_sshd_pid)" /proc/$pid/status
36 then
37 pids+=($pid)
41 done
42 if [ ${#pids[@]} -gt 0 ]
43 then
44 echo "${pids[@]}"
45 return 0
47 return 1
50 while getopts hntd opt
52 Usage="Usage: $0 [-n] [-t] [-d]
53 -n Do not resolve IP addresses
54 -t Display time as unix timestamp
55 -d Replace inherited details with '%' sign"
56 if [ ."$1" = .--help ]
57 then
58 echo "$Usage" >&2
59 exit 0
61 case "$opt" in
62 h) echo "$Usage" >&2
63 exit 0;;
64 n|t|d) flag[$opt]=1;;
65 '?') exit 1;;
66 esac
67 done
72 echo "USER;TTY;FROM;LOGIN@;PID;WHAT"
74 for slave_sshd_pid in `find_slave_sshd_pids`
76 user_sshd_pid=`ps o pid= --ppid $slave_sshd_pid`
77 user_sshd_pid=${user_sshd_pid//[!0-9]/}
78 if [ -z "$user_sshd_pid" ]
79 then
80 continue
83 username=`stat -c %U "/proc/$user_sshd_pid"`
84 start_time=`stat -c %Y "/proc/$user_sshd_pid"`
85 if [ "${flag[t]}" != 1 ]
86 then
87 start_time=`date -d@$start_time`
90 shells=0
91 for shell_pid in `ps o pid= --ppid "$user_sshd_pid"`
93 shell_pid=${shell_pid//[!0-9]/}
94 test -n "$shell_pid" || continue
95 shells=$[shells+1]
97 #tty=`readlink "/proc/$shell_pid/fd/0"`
98 tty=`psgetenv "$shell_pid" SSH_TTY`
99 tty=${tty#/dev/}
100 tty=${tty:--}
102 if [ "${flag[d]}" = 1 -a $shells -gt 1 ]
103 then
104 from=%
105 else
106 env_ssh_client=`psgetenv "$shell_pid" SSH_CLIENT`
107 hostip=`cut -f1 -d' ' <<<"$env_ssh_client"`
108 port=`cut -f2 -d' ' <<<"$env_ssh_client"`
109 if [ "${flag[n]}" != 1 ]
110 then
111 if type resolveip >/dev/null 2>&1
112 then
113 set +e
114 host=`resolveip -s "$hostip"`
115 if [ -z "$host" ]
116 then
117 host=$hostip
119 set -e
120 else
121 host=`dig +short -x "$hostip"`
123 else
124 host=$hostip
126 from=$host:$port
129 exe=`readlink "/proc/$shell_pid/exe"`
130 comm=`cat "/proc/$shell_pid/comm"`
131 argv=(`tr "\0" "\n" <"/proc/$shell_pid/cmdline"`)
132 exe_if_spoofed=''
133 if [ "${argv[0]}" != "$exe" ]
134 then
135 exe_if_spoofed=" ($exe)"
138 echo "$username;$tty;$from;$start_time;$shell_pid;${argv[@]}$exe_if_spoofed"
140 if [ "${flag[d]}" = 1 -a $shells = 1 ]
141 then
142 username=%
143 start_time=%
145 done
147 if [ $shells = 0 ]
148 then
149 set -- `lastcsv -f /var/run/sshd/wtmp | awk -F';' '$9=="'$slave_sshd_pid'"{print $3, $2; exit}'`
150 host=$1
151 port=$2
152 port=${port//[!0-9]/}
153 from=$host:$port
154 echo "$username;-;$from;$start_time;$user_sshd_pid;-"
156 done
157 } | column -t -s';' -n