From 2707a90c6ef59da326f58d86af4faaa11b438a8e Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Fri, 20 Sep 2024 13:04:13 +0900 Subject: [PATCH] Make the pipe name configurable Fixes #13 --- config.go | 2 ++ main.go | 2 +- repeater.go | 15 ++++++++++++++- repeater.ps1 | 6 +++++- repeater_test.go | 12 +++++++++--- server.go | 7 ++++--- server_test.go | 4 +++- 7 files changed, 38 insertions(+), 10 deletions(-) diff --git a/config.go b/config.go index 4f7d724..409642b 100644 --- a/config.go +++ b/config.go @@ -19,6 +19,7 @@ import ( type config struct { socketPath string powershellPath string + pipeName string format string foreground bool verbose bool @@ -57,6 +58,7 @@ func newConfig() *config { flag.StringVar(&c.socketPath, "socket", defaultSocketPath(), "a path of UNIX domain socket to listen") flag.StringVar(&c.powershellPath, "powershell-path", powershellPath(), "a path of Windows PowerShell") + flag.StringVar(&c.pipeName, "pipename", "openssh-ssh-agent", "a name of pipe to connect") flag.BoolVar(&c.foreground, "foreground", false, "run in foreground mode") flag.BoolVar(&c.verbose, "verbose", false, "verbose mode") flag.StringVar(&c.logFile, "log", "", "a file path to write the log") diff --git a/main.go b/main.go index b5c55fa..159b657 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,7 @@ func main() { ctx := c.start() - s := newServer(c.socketPath, c.powershellPath) + s := newServer(c.socketPath, c.powershellPath, c.pipeName) s.run(ctx) } diff --git a/repeater.go b/repeater.go index 229bce3..a8ef0b6 100644 --- a/repeater.go +++ b/repeater.go @@ -26,7 +26,7 @@ var waitTimes = []time.Duration{ } // invoke PowerShell.exe and run -func newRepeater(ctx context.Context, powershell string) (*repeater, error) { +func newRepeater(ctx context.Context, powershell string, pipename string) (*repeater, error) { for i, limit := range waitTimes { log.Printf("invoking [W] in PowerShell.exe%s", trial(i)) @@ -69,6 +69,19 @@ func newRepeater(ctx context.Context, powershell string) (*repeater, error) { case ok := <-done: if ok { log.Printf("[W] invoked successfully") + + buf := make([]byte, 4) + buf[0] = byte((len(pipename) >> 24) & 0xff) + buf[1] = byte((len(pipename) >> 16) & 0xff) + buf[2] = byte((len(pipename) >> 8) & 0xff) + buf[3] = byte(len(pipename) & 0xff) + _, err = io.WriteString(in, string(buf)+pipename) + if err != nil { + log.Printf("failed to give [W] the pipe name: %s", err) + terminate(cmd) + continue + } + return &repeater{in, out, cmd}, nil } case <-time.After(limit): diff --git a/repeater.ps1 b/repeater.ps1 index 6ccac03..9a5dd12 100644 --- a/repeater.ps1 +++ b/repeater.ps1 @@ -47,6 +47,10 @@ Function MainLoop { $ssh_client_out.WriteByte(0xff) Log "ready: PSVersion $ver" + $buf = ReadMessage $ssh_client_in + $pipename = [System.Text.Encoding]::UTF8.GetString($buf[4..$buf.Length]) + Log "[W] named pipe: $pipename" + while ($true) { Try { $null = $ssh_client_in.Read((New-Object byte[] 1), 0, 0) @@ -57,7 +61,7 @@ Function MainLoop { Log "[W] return dummy for OpenSSH ext." Continue } - $ssh_agent = New-Object System.IO.Pipes.NamedPipeClientStream ".", "openssh-ssh-agent", InOut + $ssh_agent = New-Object System.IO.Pipes.NamedPipeClientStream ".", $pipename, InOut $ssh_agent.Connect() Log "[W] named pipe: connected" $ssh_agent.Write($buf, 0, $buf.Length) diff --git a/repeater_test.go b/repeater_test.go index 9faf3e8..9f80a59 100644 --- a/repeater_test.go +++ b/repeater_test.go @@ -39,7 +39,7 @@ func setupDummyEnv(t *testing.T) string { func TestRepeaterNoPowerShell(t *testing.T) { setupDummyEnv(t) - _, err := newRepeater(context.Background(), "/dummy/powershell.exe") + _, err := newRepeater(context.Background(), "/dummy/powershell.exe", "dummy-pipe-name") if err == nil || err.Error() != "failed to invoke PowerShell.exe 3 times; give up" { t.Errorf("should fail") } @@ -52,7 +52,7 @@ func TestRepeaterBrokenPowerShell(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = newRepeater(context.Background(), powershellPath()) + _, err = newRepeater(context.Background(), powershellPath(), "dummy-pipe-name") if err == nil || err.Error() != "failed to invoke PowerShell.exe 3 times; give up" { t.Errorf("should fail") } @@ -66,7 +66,7 @@ func TestRepeaterNormal(t *testing.T) { t.Fatal(err) } - rep, err := newRepeater(context.Background(), powershellPath()) + rep, err := newRepeater(context.Background(), powershellPath(), "dummy-pipe-name") if err != nil { t.Errorf("failed: %s", err) } @@ -77,6 +77,12 @@ func TestRepeaterNormal(t *testing.T) { t.Errorf("does not work") } + buf = make([]byte, 19) + _, err = io.ReadFull(rep.out, buf) + if err != nil || string(buf) != "\x00\x00\x00\x0fdummy-pipe-name" { + t.Errorf("does not work: %s", string(buf)) + } + _, err = rep.in.Write([]byte("Hello")) if err != nil { t.Fatal(err) diff --git a/server.go b/server.go index 84a86bd..2e089da 100644 --- a/server.go +++ b/server.go @@ -14,16 +14,17 @@ import ( type server struct { listener net.Listener powershellPath string + pipeName string } -func newServer(socketPath string, powershellPath string) *server { +func newServer(socketPath string, powershellPath string, pipeName string) *server { listener, err := net.Listen("unix", socketPath) if err != nil { log.Fatal(err) } log.Printf("start listening on %s", socketPath) - return &server{listener, powershellPath} + return &server{listener, powershellPath, pipeName} } type request struct { @@ -91,7 +92,7 @@ func (s *server) server(ctx context.Context, cancel func(), requestQueue chan re for { // invoke PowerShell.exe - rep, err := newRepeater(ctx, s.powershellPath) + rep, err := newRepeater(ctx, s.powershellPath, s.pipeName) if err != nil { return } diff --git a/server_test.go b/server_test.go index ee189cb..63d9d35 100644 --- a/server_test.go +++ b/server_test.go @@ -22,6 +22,8 @@ File.write('` + tmpDir + `/pid', $$.to_s) $stdout.sync = true $stdout << "\xff" s = $stdin.read(` + fmt.Sprintf("%d", len(repeaterPs1)) + `) +len = $stdin.read(4) +pipename = $stdin.read(len.unpack1("N")) loop do # echo len = $stdin.read(4) @@ -38,7 +40,7 @@ end } path := filepath.Join(tmpDir, "tmp.sock") - s := newServer(path, powershellPath()) + s := newServer(path, powershellPath(), "dummy-pipe-name") done := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background())