Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions client/ssh/server/userswitching_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
return true
}

// createPtyLoginCommand creates a Pty command using login for privileged processes
func (s *Server) createPtyLoginCommand(localUser *user.User, ptyReq ssh.Pty, session ssh.Session) (*exec.Cmd, error) {
// createUserSwitchPtyCommand creates a Pty command using login for privileged processes
func (s *Server) createUserSwitchPtyCommand(localUser *user.User, ptyReq ssh.Pty, session ssh.Session) (*exec.Cmd, error) {
loginPath, args, err := s.getLoginCmd(localUser.Username, session.RemoteAddr())
if err != nil {
return nil, fmt.Errorf("get login command: %w", err)
Expand All @@ -75,32 +75,42 @@

// getLoginCmd returns the login command and args for privileged Pty user switching
func (s *Server) getLoginCmd(username string, remoteAddr net.Addr) (string, []string, error) {
loginPath, err := exec.LookPath("login")
if err != nil {
return "", nil, fmt.Errorf("login command not available: %w", err)
}

addrPort, err := netip.ParseAddrPort(remoteAddr.String())
if err != nil {
return "", nil, fmt.Errorf("parse remote address: %w", err)
}

switch runtime.GOOS {
case "linux":

Check warning on line 84 in client/ssh/server/userswitching_unix.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce this case clause number of lines from 10 to at most 6, for example by extracting code into methods.

See more on https://sonarcloud.io/project/issues?id=netbirdio_netbird&issues=AZrKS273-bboaR6PW4bL&open=AZrKS273-bboaR6PW4bL&pullRequest=4873
// Special handling for Arch Linux without /etc/pam.d/remote
if s.fileExists("/etc/arch-release") && !s.fileExists("/etc/pam.d/remote") {
return loginPath, []string{"-f", username, "-p"}, nil
// Try runuser first
runuserPath, err := exec.LookPath("runuser")
if err == nil {
return runuserPath, []string{"-l", username}, nil
}

// Fall back to login
loginPath, err := exec.LookPath("login")
if err == nil {
return loginPath, []string{"-f", username, "-h", addrPort.Addr().String(), "-p"}, nil
}
return loginPath, []string{"-f", username, "-h", addrPort.Addr().String(), "-p"}, nil

return "", nil, fmt.Errorf("neither runuser nor login commands available: %w", err)

case "darwin", "freebsd", "openbsd", "netbsd", "dragonfly":
return loginPath, []string{"-fp", "-h", addrPort.Addr().String(), username}, nil
loginPath, err := exec.LookPath("login")
if err == nil {
return loginPath, []string{"-fp", "-h", addrPort.Addr().String(), username}, nil
}

return "", nil, fmt.Errorf("login command not available: %w", err)

default:
return "", nil, fmt.Errorf("unsupported Unix platform for login command: %s", runtime.GOOS)
}
}

// fileExists checks if a file exists (helper for login command logic)
func (s *Server) fileExists(path string) bool {

Check failure on line 113 in client/ssh/server/userswitching_unix.go

View workflow job for this annotation

GitHub Actions / Darwin

func `(*Server).fileExists` is unused (unused)

Check failure on line 113 in client/ssh/server/userswitching_unix.go

View workflow job for this annotation

GitHub Actions / Linux

func `(*Server).fileExists` is unused (unused)

Check failure on line 113 in client/ssh/server/userswitching_unix.go

View workflow job for this annotation

GitHub Actions / JS / Lint

func `(*Server).fileExists` is unused (unused)
_, err := os.Stat(path)
return err == nil
}
Expand Down Expand Up @@ -196,7 +206,7 @@
return s.createDirectPtyCommand(session, localUser, ptyReq), nil
}

return s.createPtyLoginCommand(localUser, ptyReq, session)
return s.createUserSwitchPtyCommand(localUser, ptyReq, session)
}

// createDirectPtyCommand creates a direct Pty command without privilege dropping
Expand Down
Loading