run is the entrypoint for a newly accepted SSH session. It handles ss once it's been accepted and determined that it should run.
()
| 966 | // It handles ss once it's been accepted and determined |
| 967 | // that it should run. |
| 968 | func (ss *sshSession) run() { |
| 969 | metricActiveSessions.Add(1) |
| 970 | defer metricActiveSessions.Add(-1) |
| 971 | defer ss.cancelCtx(errSessionDone) |
| 972 | |
| 973 | if attached := ss.conn.srv.attachSessionToConnIfNotShutdown(ss); !attached { |
| 974 | fmt.Fprintf(ss, "Tailscale SSH is shutting down\r\n") |
| 975 | ss.Exit(1) |
| 976 | return |
| 977 | } |
| 978 | defer ss.conn.detachSession(ss) |
| 979 | |
| 980 | lu := ss.conn.localUser |
| 981 | logf := ss.logf |
| 982 | |
| 983 | if ss.conn.finalAction.SessionDuration != 0 { |
| 984 | t := time.AfterFunc(ss.conn.finalAction.SessionDuration, func() { |
| 985 | ss.cancelCtx(userVisibleError{ |
| 986 | fmt.Sprintf("Session timeout of %v elapsed.", ss.conn.finalAction.SessionDuration), |
| 987 | context.DeadlineExceeded, |
| 988 | }) |
| 989 | }) |
| 990 | defer t.Stop() |
| 991 | } |
| 992 | |
| 993 | if euid := os.Geteuid(); euid != 0 && runtime.GOOS != "plan9" { |
| 994 | if lu.Uid != fmt.Sprint(euid) { |
| 995 | ss.logf("can't switch to user %q from process euid %v", lu.Username, euid) |
| 996 | fmt.Fprintf(ss, "can't switch user\r\n") |
| 997 | ss.Exit(1) |
| 998 | return |
| 999 | } |
| 1000 | } |
| 1001 | |
| 1002 | // Take control of the PTY so that we can configure it below. |
| 1003 | // See https://github.com/tailscale/tailscale/issues/4146 |
| 1004 | ss.DisablePTYEmulation() |
| 1005 | |
| 1006 | var rec *recording // or nil if disabled |
| 1007 | if ss.Subsystem() != "sftp" { |
| 1008 | if err := ss.handleSSHAgentForwarding(ss, lu); err != nil { |
| 1009 | ss.logf("agent forwarding failed: %v", err) |
| 1010 | } else if ss.agentListener != nil { |
| 1011 | // TODO(maisem/bradfitz): add a way to close all session resources |
| 1012 | defer ss.agentListener.Close() |
| 1013 | } |
| 1014 | |
| 1015 | if ss.shouldRecord() { |
| 1016 | var err error |
| 1017 | rec, err = ss.startNewRecording() |
| 1018 | if err != nil { |
| 1019 | if uve, ok := errors.AsType[userVisibleError](err); ok { |
| 1020 | fmt.Fprintf(ss, "%s\r\n", uve.SSHTerminationMessage()) |
| 1021 | } else { |
| 1022 | fmt.Fprintf(ss, "can't start new recording\r\n") |
| 1023 | } |
| 1024 | ss.logf("startNewRecording: %v", err) |
| 1025 | ss.Exit(1) |
nothing calls this directly
no test coverage detected