forked from moul/sshportal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
1 changed file
with
68 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import ( | |
"log" | ||
"os" | ||
"path/filepath" | ||
"sync" | ||
"time" | ||
|
||
"github.com/gliderlabs/ssh" | ||
|
@@ -15,6 +16,13 @@ import ( | |
gossh "golang.org/x/crypto/ssh" | ||
) | ||
|
||
const ( | ||
authAgentReqOpenSSH = "[email protected]" | ||
authAgentChannelOpenSSH = "[email protected]" | ||
authAgentReqRFC = "auth-agent-req" | ||
authAgentChannelRFC = "auth-agent" | ||
) | ||
|
||
type sessionConfig struct { | ||
Addr string | ||
LogsLocation string | ||
|
@@ -61,11 +69,12 @@ func multiChannelHandler(conn *gossh.ServerConn, newChan gossh.NewChannel, ctx s | |
if err != nil { | ||
return err | ||
} | ||
|
||
user := conn.User() | ||
actx := ctx.Value(authContextKey).(*authContext) | ||
username := actx.user.Name | ||
// pipe everything | ||
return pipe(lreqs, rreqs, lch, rch, configs[len(configs)-1], user, username, sessionID, newChan) | ||
return pipe(conn, lastClient, lreqs, rreqs, lch, rch, configs[len(configs)-1], user, username, sessionID, newChan, actx.aesKey) | ||
case "direct-tcpip": | ||
lch, lreqs, err := newChan.Accept() | ||
// TODO: defer clean closer | ||
|
@@ -110,7 +119,7 @@ func multiChannelHandler(conn *gossh.ServerConn, newChan gossh.NewChannel, ctx s | |
actx := ctx.Value(authContextKey).(*authContext) | ||
username := actx.user.Name | ||
// pipe everything | ||
return pipe(lreqs, rreqs, lch, rch, configs[len(configs)-1], user, username, sessionID, newChan) | ||
return pipe(conn, lastClient, lreqs, rreqs, lch, rch, configs[len(configs)-1], user, username, sessionID, newChan, actx.aesKey) | ||
default: | ||
if err := newChan.Reject(gossh.UnknownChannelType, "unsupported channel type"); err != nil { | ||
log.Printf("failed to reject chan: %v", err) | ||
|
@@ -119,7 +128,7 @@ func multiChannelHandler(conn *gossh.ServerConn, newChan gossh.NewChannel, ctx s | |
} | ||
} | ||
|
||
func pipe(lreqs, rreqs <-chan *gossh.Request, lch, rch gossh.Channel, sessConfig sessionConfig, user string, username string, sessionID uint, newChan gossh.NewChannel) error { | ||
func pipe(serverConn *gossh.ServerConn, client *gossh.Client, lreqs, rreqs <-chan *gossh.Request, lch, rch gossh.Channel, sessConfig sessionConfig, user string, username string, sessionID uint, newChan gossh.NewChannel, aesKey string) error { | ||
defer func() { | ||
_ = lch.Close() | ||
_ = rch.Close() | ||
|
@@ -195,6 +204,16 @@ func pipe(lreqs, rreqs <-chan *gossh.Request, lch, rch gossh.Channel, sessConfig | |
log.Printf("failed to write log: %v", err) | ||
} | ||
} | ||
if req.Type == authAgentReqOpenSSH { | ||
if err := ForwardToRemote(authAgentChannelOpenSSH, serverConn, client); err != nil { | ||
log.Println("Failed to forward openssh agent", err) | ||
} | ||
} | ||
if req.Type == authAgentReqRFC { | ||
if err := ForwardToRemote(authAgentChannelRFC, serverConn, client); err != nil { | ||
log.Println("Failed to forward RFC agent", err) | ||
} | ||
} | ||
|
||
if err != nil { | ||
errch <- err | ||
|
@@ -253,6 +272,52 @@ func pipe(lreqs, rreqs <-chan *gossh.Request, lch, rch gossh.Channel, sessConfig | |
} | ||
} | ||
|
||
func ForwardToRemote(chanName string, conn *gossh.ServerConn, client *gossh.Client) error { | ||
channels := client.HandleChannelOpen(chanName) | ||
if channels == nil { | ||
return errors.New("agent: already have handler for " + chanName) | ||
} | ||
|
||
go func() { | ||
for ch := range channels { | ||
lch, reqs, err := ch.Accept() | ||
if err != nil { | ||
log.Println("On auth-agent channel accept", err) | ||
continue | ||
} | ||
defer lch.Close() | ||
go gossh.DiscardRequests(reqs) | ||
|
||
rch, rreqs, err := conn.OpenChannel(chanName, nil) | ||
if err != nil { | ||
log.Println("On auth-agent channel open", err) | ||
continue | ||
} | ||
defer rch.Close() | ||
go gossh.DiscardRequests(rreqs) | ||
|
||
forwardChannel(rch, lch) | ||
} | ||
}() | ||
return nil | ||
} | ||
|
||
func forwardChannel(rch, lch gossh.Channel) { | ||
var wg sync.WaitGroup | ||
wg.Add(2) | ||
go func() { | ||
io.Copy(lch, rch) | ||
lch.CloseWrite() | ||
wg.Done() | ||
}() | ||
go func() { | ||
io.Copy(rch, lch) | ||
rch.CloseWrite() | ||
wg.Done() | ||
}() | ||
wg.Wait() | ||
} | ||
|
||
func newDiscardWriteCloser() io.WriteCloser { return &discardWriteCloser{ioutil.Discard} } | ||
|
||
type discardWriteCloser struct { | ||
|