package ssh

import (
	
	
	
	
	

	gossh 
)

const (
	agentRequestType = "auth-agent-req@openssh.com"
	agentChannelType = "auth-agent@openssh.com"

	agentTempDir    = "auth-agent"
	agentListenFile = "listener.sock"
)

// contextKeyAgentRequest is an internal context key for storing if the
// client requested agent forwarding.
var contextKeyAgentRequest = &contextKey{"auth-agent-req"}

// SetAgentRequested sets up the session context so that AgentRequested
// returns true.
func ( Context) {
	.SetValue(contextKeyAgentRequest, true)
}

// AgentRequested returns true if the client requested agent forwarding.
func ( Session) bool {
	return .Context().Value(contextKeyAgentRequest) == true
}

// NewAgentListener sets up a temporary Unix socket that can be communicated
// to the session environment and used for forwarding connections.
func () (net.Listener, error) {
	,  := os.MkdirTemp("", agentTempDir)
	if  != nil {
		return nil, 
	}
	,  := net.Listen("unix", path.Join(, agentListenFile))
	if  != nil {
		return nil, 
	}
	return , nil
}

// ForwardAgentConnections takes connections from a listener to proxy into the
// session on the OpenSSH channel for agent connections. It blocks and services
// connections until the listener stop accepting.
func ( net.Listener,  Session) {
	 := .Context().Value(ContextKeyConn).(gossh.Conn)
	for {
		,  := .Accept()
		if  != nil {
			return
		}
		go func( net.Conn) {
			defer recoverAndLog("panic forwarding agent connection", nil, nil)
			defer func() { _ = .Close() }()
			, ,  := .OpenChannel(agentChannelType, nil)
			if  != nil {
				return
			}
			defer func() { _ = .Close() }()
			go gossh.DiscardRequests()
			var  sync.WaitGroup
			.Add(2)
			go func() {
				// Done is deferred ahead of the recover so that it runs even
				// if the copy panics. Otherwise the recover would turn a crash
				// into a permanently blocked Wait below, leaking this
				// goroutine along with the socket and the channel.
				defer .Done()
				defer recoverAndLog("panic proxying agent connection", nil, nil)
				_, _ = io.Copy(, )
				_ = .(*net.UnixConn).CloseWrite()
			}()
			go func() {
				defer .Done()
				defer recoverAndLog("panic proxying agent connection", nil, nil)
				_, _ = io.Copy(, )
				_ = .CloseWrite()
			}()
			.Wait()
		}()
	}
}