Files
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

77 lines
1.7 KiB
Go

package source
import (
"fmt"
"path/filepath"
"strings"
"github.com/pranshuparmar/witr/pkg/model"
)
func detectSSH(ancestry []model.Process) *model.Source {
if len(ancestry) < 2 {
return nil
}
// Look for sshd in the ancestry chain (excluding the target itself)
hasSSHD := false
for i := 0; i < len(ancestry)-1; i++ {
base := filepath.Base(ancestry[i].Command)
if base == "sshd" || base == "sshd.exe" || strings.HasPrefix(base, "sshd:") {
hasSSHD = true
break
}
}
if !hasSSHD {
return nil
}
// Extract SSH connection details from environment variables.
// Check all processes in the chain (target first, then ancestors) because
// su/sudo create clean login shells that don't inherit SSH_* vars.
target := ancestry[len(ancestry)-1]
var remoteIP, tty string
for i := len(ancestry) - 1; i >= 0 && remoteIP == ""; i-- {
for _, entry := range ancestry[i].Env {
key, val, ok := strings.Cut(entry, "=")
if !ok {
continue
}
switch key {
case "SSH_CLIENT":
if fields := strings.Fields(val); len(fields) >= 1 {
remoteIP = fields[0]
}
case "SSH_CONNECTION":
if remoteIP == "" {
if fields := strings.Fields(val); len(fields) >= 1 {
remoteIP = fields[0]
}
}
case "SSH_TTY":
if tty == "" {
tty = val
}
}
}
}
desc := "SSH session"
if remoteIP != "" {
if tty != "" {
desc = fmt.Sprintf("SSH session from %s (%s@%s)", remoteIP, target.User, strings.TrimPrefix(tty, "/dev/"))
} else if target.User != "" {
desc = fmt.Sprintf("SSH session from %s (%s)", remoteIP, target.User)
} else {
desc = fmt.Sprintf("SSH session from %s", remoteIP)
}
}
return &model.Source{
Type: model.SourceSSH,
Name: "sshd",
Description: desc,
}
}