Skip to content

Commit 41dc50d

Browse files
committed
Improve SSH_AUTH_SOCK support on Windows
1 parent 2d55483 commit 41dc50d

3 files changed

Lines changed: 30 additions & 10 deletions

File tree

pageant_windows.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import (
3636
"golang.org/x/sys/windows"
3737
)
3838

39-
// Maximum size of message can be sent to pageant
39+
// Maximum size of message can be sent to pageant.
4040
const MaxMessageLen = 8192
4141

4242
var (
@@ -76,8 +76,6 @@ func winAPI(dll *windows.LazyDLL, funcName string) func(...uintptr) (uintptr, ui
7676
}
7777

7878
// Query sends message msg to Pageant and returns response or error.
79-
// 'msg' is raw agent request with length prefix
80-
// Response is raw agent response with length prefix
8179
func query(msg []byte) ([]byte, error) {
8280
if len(msg) > MaxMessageLen {
8381
return nil, ErrMessageTooLong

sshagent.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"golang.org/x/crypto/ssh/agent"
2929
)
3030

31-
// New returns a new agent.Agent that uses a unix socket
31+
// New returns a new agent.Agent that uses a unix socket.
3232
func New() (agent.Agent, net.Conn, error) {
3333
if !Available() {
3434
return nil, nil, errors.New("SSH agent requested but SSH_AUTH_SOCK not-specified")
@@ -44,7 +44,7 @@ func New() (agent.Agent, net.Conn, error) {
4444
return agent.NewClient(conn), conn, nil
4545
}
4646

47-
// Available returns true is a auth socket is defined
47+
// Available returns true if an auth socket is defined.
4848
func Available() bool {
4949
return os.Getenv("SSH_AUTH_SOCK") != ""
5050
}

sshagent_windows.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,28 @@ import (
2626
"errors"
2727
"io"
2828
"net"
29+
"os"
30+
"strings"
2931
"sync"
3032

3133
"github.com/Microsoft/go-winio"
3234
"golang.org/x/crypto/ssh/agent"
3335
)
3436

3537
const (
36-
sshAgentPipe = `\\.\pipe\openssh-ssh-agent`
38+
pipe = `\\.\pipe\`
39+
openSSHAgentPipe = pipe + "openssh-ssh-agent"
3740
)
3841

39-
// Available returns true if Pageant is running
42+
// Available returns true if Pageant is running.
4043
func Available() bool {
4144
if pageantWindow() != 0 {
4245
return true
4346
}
44-
conn, err := winio.DialPipe(sshAgentPipe, nil)
47+
if sshAuthSock := os.Getenv("SSH_AUTH_SOCK"); sshAuthSock != "" {
48+
return true
49+
}
50+
conn, err := winio.DialPipe(openSSHAgentPipe, nil)
4551
if err != nil {
4652
return false
4753
}
@@ -50,18 +56,34 @@ func Available() bool {
5056
}
5157

5258
// New returns a new agent.Agent and the (custom) connection it uses
53-
// to communicate with a running pagent.exe instance (see README.md)
59+
// to communicate with a running pagent.exe instance (see README.md).
5460
func New() (agent.Agent, net.Conn, error) {
5561
if pageantWindow() != 0 {
5662
return agent.NewClient(&conn{}), nil, nil
5763
}
64+
65+
sshAgentPipe := openSSHAgentPipe
66+
if sshAuthSock := os.Getenv("SSH_AUTH_SOCK"); sshAuthSock != "" {
67+
conn, err := net.Dial("unix", sshAuthSock)
68+
if err == nil {
69+
return agent.NewClient(conn), conn, nil
70+
}
71+
72+
if !strings.HasPrefix(sshAuthSock, pipe) {
73+
sshAuthSock = pipe + sshAuthSock
74+
}
75+
76+
sshAgentPipe = sshAuthSock
77+
}
78+
5879
conn, err := winio.DialPipe(sshAgentPipe, nil)
5980
if err != nil {
6081
return nil, nil, errors.New(
6182
"SSH agent requested, but could not detect Pageant or Windows native SSH agent",
6283
)
6384
}
64-
return agent.NewClient(conn), nil, nil
85+
86+
return agent.NewClient(conn), conn, nil
6587
}
6688

6789
type conn struct {

0 commit comments

Comments
 (0)