From 7fc2736a4f445a82dcf0e84d8426b6e6615cd4eb Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 28 Dec 2017 19:32:58 +1300 Subject: [PATCH 01/10] Inital proof of concept for (libassuane #1) --- npiperelay.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/npiperelay.go b/npiperelay.go index 08cbaab..4bdf6ca 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -1,10 +1,13 @@ package main import ( + "errors" "flag" "io" "log" "os" + "strconv" + "strings" "sync" "syscall" "time" @@ -40,6 +43,49 @@ func dialPipe(p string, poll bool) (*overlappedFile, error) { } } +func dialPort(p int, poll bool) (*overlappedFile, error) { + if p < 0 || p > 65535 { + return nil, errors.New("Invalid port value") + } + + for { + h, err := windows.Socket(windows.AF_INET, windows.SOCK_STREAM, 0) + if err != nil { + return nil, err + } + + // Create a SockaddrInet4 for connecting to + sa := &windows.SockaddrInet4{Addr: [4]byte{0x7F, 0x00, 0x00, 0x01}, Port: p} + if err != nil { + return nil, err + } + + // Bind to a randomly assigned port + err = windows.Bind(h, &windows.SockaddrInet4{}) + if err != nil { + return nil, err + } + + conn := newOverlappedFile(h) + + _, err = conn.asyncIo(func(h windows.Handle, n *uint32, o *windows.Overlapped) error { + return windows.ConnectEx(h, sa, nil, 0, nil, o) + }) + err = os.NewSyscallError("connectEx", err) + + if err == nil { + return conn, nil + } + + if poll && os.IsNotExist(err) { + time.Sleep(200 * time.Millisecond) + continue + } + + return nil, err + } +} + func underlyingError(err error) error { if serr, ok := err.(*os.SyscallError); ok { return serr.Err @@ -64,6 +110,39 @@ func main() { log.Fatalln(err) } + if !strings.HasPrefix("//./", args[0]) { + tmp := make([]byte, 22) // 5 bytes for ascii port number, 1 for newline, 16 for nonce + + var port int + nonce := make([]byte, 16) + + // Check if file is a LibAssuane socket + _, err := conn.Read(tmp) + if err != nil { + log.Fatalln("Could not open socket", err) + } + + for i, c := range tmp { + // Find the new line + if c == 0x0A { + port, _ = strconv.Atoi(string(tmp[:i])) + copy(nonce, tmp[i+1:]) + + log.Printf("Port: %d, Nonce: %X", port, nonce) + break + } + } + + _ = conn.Close() + + conn, err = dialPort(port, *poll) + + _, err = conn.Write(nonce) + if err != nil { + log.Fatal(err) + } + } + if *verbose { log.Println("connected") } From 6048153a0f79711ce7b408a071d6226d5f2e8549 Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 28 Dec 2017 19:48:35 +1300 Subject: [PATCH 02/10] gpg4win relay example --- scripts/gpg-relay | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 scripts/gpg-relay diff --git a/scripts/gpg-relay b/scripts/gpg-relay new file mode 100644 index 0000000..d85ac95 --- /dev/null +++ b/scripts/gpg-relay @@ -0,0 +1,3 @@ +#!/bin/sh + +exec socat UNIX-LISTEN:/home//.gnupg/S.gpg-agent,fork, EXEC:'npiperelay.exe -ep -s "C:/Users//AppData/Roaming/gnupg/S.gpg-agent.extra"',nofork From a3c44478565c357d025eac5fd7192eed0ee51c6b Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 28 Dec 2017 19:58:48 +1300 Subject: [PATCH 03/10] Reduce verbosity unless requested --- npiperelay.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/npiperelay.go b/npiperelay.go index 4bdf6ca..8d1033a 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -128,7 +128,9 @@ func main() { port, _ = strconv.Atoi(string(tmp[:i])) copy(nonce, tmp[i+1:]) - log.Printf("Port: %d, Nonce: %X", port, nonce) + if *verbose { + log.Printf("Port: %d, Nonce: %X", port, nonce) + } break } } From 0015687c47ec6747f2c73a7a19b1dae479e34a21 Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 28 Dec 2017 21:42:20 +1300 Subject: [PATCH 04/10] terminate when pipe or stdin closes in example --- scripts/gpg-relay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gpg-relay b/scripts/gpg-relay index d85ac95..166dd17 100644 --- a/scripts/gpg-relay +++ b/scripts/gpg-relay @@ -1,3 +1,3 @@ #!/bin/sh -exec socat UNIX-LISTEN:/home//.gnupg/S.gpg-agent,fork, EXEC:'npiperelay.exe -ep -s "C:/Users//AppData/Roaming/gnupg/S.gpg-agent.extra"',nofork +exec socat UNIX-LISTEN:/home//.gnupg/S.gpg-agent,fork, EXEC:'npiperelay.exe -ei -ep -s "C:/Users//AppData/Roaming/gnupg/S.gpg-agent"',nofork From 06bad53d17d957fcd42dbc649fc1cec02557b63a Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Fri, 29 Dec 2017 15:01:25 +1300 Subject: [PATCH 05/10] Support polling sockets and general house-keeping --- npiperelay.go | 152 ++++++++++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 66 deletions(-) diff --git a/npiperelay.go b/npiperelay.go index 8d1033a..886cfcd 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -17,6 +17,11 @@ import ( const cERROR_PIPE_NOT_CONNECTED syscall.Errno = 233 +const WSAECONNREFUSED syscall.Errno = 10061 +const WSAENETUNREACH syscall.Errno = 10051 +const WSAETIMEDOUT syscall.Errno = 10060 +const ERROR_CONNECTION_REFUSED syscall.Errno = 1225 + var ( poll = flag.Bool("p", false, "poll until the the named pipe exists") closeWrite = flag.Bool("s", false, "send a 0-byte message to the pipe after EOF on stdin") @@ -30,17 +35,13 @@ func dialPipe(p string, poll bool) (*overlappedFile, error) { if err != nil { return nil, err } - for { - h, err := windows.CreateFile(&p16[0], windows.GENERIC_READ|windows.GENERIC_WRITE, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0) - if err == nil { - return newOverlappedFile(h), nil - } - if poll && os.IsNotExist(err) { - time.Sleep(200 * time.Millisecond) - continue - } - return nil, &os.PathError{Path: p, Op: "open", Err: err} + + h, err := windows.CreateFile(&p16[0], windows.GENERIC_READ|windows.GENERIC_WRITE, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0) + if err == nil { + return newOverlappedFile(h), nil } + + return nil, err } func dialPort(p int, poll bool) (*overlappedFile, error) { @@ -48,42 +49,32 @@ func dialPort(p int, poll bool) (*overlappedFile, error) { return nil, errors.New("Invalid port value") } - for { - h, err := windows.Socket(windows.AF_INET, windows.SOCK_STREAM, 0) - if err != nil { - return nil, err - } - - // Create a SockaddrInet4 for connecting to - sa := &windows.SockaddrInet4{Addr: [4]byte{0x7F, 0x00, 0x00, 0x01}, Port: p} - if err != nil { - return nil, err - } - - // Bind to a randomly assigned port - err = windows.Bind(h, &windows.SockaddrInet4{}) - if err != nil { - return nil, err - } - - conn := newOverlappedFile(h) + h, err := windows.Socket(windows.AF_INET, windows.SOCK_STREAM, 0) + if err != nil { + return nil, err + } - _, err = conn.asyncIo(func(h windows.Handle, n *uint32, o *windows.Overlapped) error { - return windows.ConnectEx(h, sa, nil, 0, nil, o) - }) - err = os.NewSyscallError("connectEx", err) + // Create a SockaddrInet4 for connecting to + sa := &windows.SockaddrInet4{Addr: [4]byte{0x7F, 0x00, 0x00, 0x01}, Port: p} - if err == nil { - return conn, nil - } + // Bind to a randomly assigned local port + err = windows.Bind(h, &windows.SockaddrInet4{}) + if err != nil { + return nil, err + } - if poll && os.IsNotExist(err) { - time.Sleep(200 * time.Millisecond) - continue - } + // Wrap our socket up to be properly handled + conn := newOverlappedFile(h) - return nil, err + // Connect to the LibAssuan socket using overlapped ConnectEx operation + _, err = conn.asyncIo(func(h windows.Handle, n *uint32, o *windows.Overlapped) error { + return windows.ConnectEx(h, sa, nil, 0, nil, o) + }) + if err == nil { + return conn, nil } + + return nil, err } func underlyingError(err error) error { @@ -105,44 +96,73 @@ func main() { log.Println("connecting to", args[0]) } - conn, err := dialPipe(args[0], *poll) - if err != nil { - log.Fatalln(err) - } + var conn *overlappedFile + var err error - if !strings.HasPrefix("//./", args[0]) { - tmp := make([]byte, 22) // 5 bytes for ascii port number, 1 for newline, 16 for nonce + // Loop only if we're polling the named pipe or socket + for { + conn, err = dialPipe(args[0], *poll) - var port int - nonce := make([]byte, 16) + if *poll && os.IsNotExist(err) { + time.Sleep(200 * time.Millisecond) + continue + } - // Check if file is a LibAssuane socket - _, err := conn.Read(tmp) if err != nil { - log.Fatalln("Could not open socket", err) + err = &os.PathError{Path: args[0], Op: "open", Err: err} + log.Fatalln(err) } - for i, c := range tmp { - // Find the new line - if c == 0x0A { - port, _ = strconv.Atoi(string(tmp[:i])) - copy(nonce, tmp[i+1:]) + // Not a named pipe, so attempt to read contents and connect to a TCP port for LibAssaaun + if !strings.HasPrefix("//./", args[0]) { + tmp := make([]byte, 22) // 5 bytes for ascii port number, 1 for newline, 16 for nonce + + var port int + var nonce [16]byte + + _, err := conn.Read(tmp) + if err != nil { + log.Fatalln("Could not open file", err) + } + + for i, c := range tmp { + // Find the new line + if c == 0x0A { + port, err = strconv.Atoi(string(tmp[:i])) + if err != nil { + log.Fatalln(err) + } + + copy(nonce[:], tmp[i+1:]) - if *verbose { - log.Printf("Port: %d, Nonce: %X", port, nonce) + if *verbose { + log.Printf("Port: %d, Nonce: %X", port, nonce) + } + break } - break } - } - _ = conn.Close() + _ = conn.Close() - conn, err = dialPort(port, *poll) + conn, err = dialPort(port, *poll) - _, err = conn.Write(nonce) - if err != nil { - log.Fatal(err) + if *poll && (err == WSAETIMEDOUT || err == WSAECONNREFUSED || err == WSAENETUNREACH || err == ERROR_CONNECTION_REFUSED) { + time.Sleep(200 * time.Millisecond) + continue + } + + err = os.NewSyscallError("ConnectEx", err) + + if err != nil { + log.Fatal(err) + } + + _, err = conn.Write(nonce[:]) + if err != nil { + log.Fatal(err) + } } + break } if *verbose { From f0ef6555b2053a6be34b48cb96e4ee4c974cdc19 Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 4 Jan 2018 05:06:46 +1300 Subject: [PATCH 06/10] Use bufio for reading libassuan files (see #2) --- npiperelay.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/npiperelay.go b/npiperelay.go index 886cfcd..3ceefa7 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -1,13 +1,13 @@ package main import ( + "bufio" "errors" "flag" "io" "log" "os" "strconv" - "strings" "sync" "syscall" "time" @@ -28,6 +28,7 @@ var ( closeOnEOF = flag.Bool("ep", false, "terminate on EOF reading from the pipe, even if there is more data to write") closeOnStdinEOF = flag.Bool("ei", false, "terminate on EOF reading from stdin, even if there is more data to write") verbose = flag.Bool("v", false, "verbose output on stderr") + assuan = flag.Bool("a", false, "treat the target as a libassuan file socket (Used by GnuPG)") ) func dialPipe(p string, poll bool) (*overlappedFile, error) { @@ -113,37 +114,37 @@ func main() { log.Fatalln(err) } - // Not a named pipe, so attempt to read contents and connect to a TCP port for LibAssaaun - if !strings.HasPrefix("//./", args[0]) { - tmp := make([]byte, 22) // 5 bytes for ascii port number, 1 for newline, 16 for nonce - + // LibAssaaun file socket: Attempt to read contents of the target file and connect to a TCP port + if *assuan { var port int var nonce [16]byte - _, err := conn.Read(tmp) + reader := bufio.NewReader(conn) + + // Read the target port number from the first line + tmp, _, err := reader.ReadLine() + port, err = strconv.Atoi(string(tmp)) if err != nil { - log.Fatalln("Could not open file", err) + log.Fatalln(err) } - for i, c := range tmp { - // Find the new line - if c == 0x0A { - port, err = strconv.Atoi(string(tmp[:i])) - if err != nil { - log.Fatalln(err) - } + // Read the rest of the nonce from the file + n, err := reader.Read(nonce[:]) + if err != nil { + log.Fatalln(err) + } - copy(nonce[:], tmp[i+1:]) + if n != 16 { + log.Fatalf("Read incorrect number of bytes for nonce. Expected 16, got %d (0x%X)", n, nonce) + } - if *verbose { - log.Printf("Port: %d, Nonce: %X", port, nonce) - } - break - } + if *verbose { + log.Printf("Port: %d, Nonce: %X", port, nonce) } _ = conn.Close() + // Try to connect to the libassaun TCP socket hosted on localhost conn, err = dialPort(port, *poll) if *poll && (err == WSAETIMEDOUT || err == WSAECONNREFUSED || err == WSAENETUNREACH || err == ERROR_CONNECTION_REFUSED) { From b7795c8bf6897d17962d70f8c2e0424af7a112c2 Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 4 Jan 2018 05:50:58 +1300 Subject: [PATCH 07/10] add flag to gpg-relay example script --- scripts/gpg-relay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gpg-relay b/scripts/gpg-relay index 166dd17..70603af 100644 --- a/scripts/gpg-relay +++ b/scripts/gpg-relay @@ -1,3 +1,3 @@ #!/bin/sh -exec socat UNIX-LISTEN:/home//.gnupg/S.gpg-agent,fork, EXEC:'npiperelay.exe -ei -ep -s "C:/Users//AppData/Roaming/gnupg/S.gpg-agent"',nofork +exec socat UNIX-LISTEN:/home//.gnupg/S.gpg-agent,fork, EXEC:'npiperelay.exe -ei -ep -s -a "C:/Users//AppData/Roaming/gnupg/S.gpg-agent"',nofork From 7fcf2260ec36f34c03165130ea24a9b2c3328ba9 Mon Sep 17 00:00:00 2001 From: Lex Robinson Date: Fri, 19 Apr 2019 14:54:06 +0100 Subject: [PATCH 08/10] Use sys/windows constants for various errors golint was complaining about these existing, and we already use windows.ERROR_BROKEN_PIPE so it made sense to pull the others in too. --- npiperelay.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/npiperelay.go b/npiperelay.go index 3ceefa7..065ab94 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -9,19 +9,11 @@ import ( "os" "strconv" "sync" - "syscall" "time" "golang.org/x/sys/windows" ) -const cERROR_PIPE_NOT_CONNECTED syscall.Errno = 233 - -const WSAECONNREFUSED syscall.Errno = 10061 -const WSAENETUNREACH syscall.Errno = 10051 -const WSAETIMEDOUT syscall.Errno = 10060 -const ERROR_CONNECTION_REFUSED syscall.Errno = 1225 - var ( poll = flag.Bool("p", false, "poll until the the named pipe exists") closeWrite = flag.Bool("s", false, "send a 0-byte message to the pipe after EOF on stdin") @@ -147,7 +139,7 @@ func main() { // Try to connect to the libassaun TCP socket hosted on localhost conn, err = dialPort(port, *poll) - if *poll && (err == WSAETIMEDOUT || err == WSAECONNREFUSED || err == WSAENETUNREACH || err == ERROR_CONNECTION_REFUSED) { + if *poll && (err == windows.WSAETIMEDOUT || err == windows.WSAECONNREFUSED || err == windows.WSAENETUNREACH || err == windows.ERROR_CONNECTION_REFUSED) { time.Sleep(200 * time.Millisecond) continue } @@ -196,7 +188,7 @@ func main() { }() _, err = io.Copy(os.Stdout, conn) - if underlyingError(err) == windows.ERROR_BROKEN_PIPE || underlyingError(err) == cERROR_PIPE_NOT_CONNECTED { + if underlyingError(err) == windows.ERROR_BROKEN_PIPE || underlyingError(err) == windows.ERROR_PIPE_NOT_CONNECTED { // The named pipe is closed and there is no more data to read. Since // named pipes are not bidirectional, there is no way for the other side // of the pipe to get more data, so do not wait for the stdin copy to From 0b25644e0c286f49aab634cf1e0fc6a3da4ad499 Mon Sep 17 00:00:00 2001 From: Lex Robinson Date: Fri, 19 Apr 2019 15:37:17 +0100 Subject: [PATCH 09/10] Address review comments - Move os.NewSyscallError - Remove unused variable - Refactor code into dialAssuan and revert changes to dialPipe --- npiperelay.go | 146 ++++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/npiperelay.go b/npiperelay.go index 065ab94..20a2095 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "flag" + "fmt" "io" "log" "os" @@ -28,13 +29,17 @@ func dialPipe(p string, poll bool) (*overlappedFile, error) { if err != nil { return nil, err } - - h, err := windows.CreateFile(&p16[0], windows.GENERIC_READ|windows.GENERIC_WRITE, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0) - if err == nil { - return newOverlappedFile(h), nil + for { + h, err := windows.CreateFile(&p16[0], windows.GENERIC_READ|windows.GENERIC_WRITE, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0) + if err == nil { + return newOverlappedFile(h), nil + } + if poll && os.IsNotExist(err) { + time.Sleep(200 * time.Millisecond) + continue + } + return nil, &os.PathError{Path: p, Op: "open", Err: err} } - - return nil, err } func dialPort(p int, poll bool) (*overlappedFile, error) { @@ -70,6 +75,66 @@ func dialPort(p int, poll bool) (*overlappedFile, error) { return nil, err } +// LibAssaun file socket: Attempt to read contents of the target file and connect to a TCP port +func dialAssuan(p string, poll bool) (*overlappedFile, error) { + for { + conn, err := dialPipe(p, poll) + + if err != nil { + return nil, err + } + + var port int + var nonce [16]byte + + reader := bufio.NewReader(conn) + + // Read the target port number from the first line + tmp, _, err := reader.ReadLine() + port, err = strconv.Atoi(string(tmp)) + if err != nil { + return nil, err + } + + // Read the rest of the nonce from the file + n, err := reader.Read(nonce[:]) + if err != nil { + return nil, err + } + + if n != 16 { + err = fmt.Errorf("Read incorrect number of bytes for nonce. Expected 16, got %d (0x%X)", n, nonce) + return nil, err + } + + if *verbose { + log.Printf("Port: %d, Nonce: %X", port, nonce) + } + + conn.Close() + + // Try to connect to the libassaun TCP socket hosted on localhost + conn, err = dialPort(port, poll) + + if poll && (err == windows.WSAETIMEDOUT || err == windows.WSAECONNREFUSED || err == windows.WSAENETUNREACH || err == windows.ERROR_CONNECTION_REFUSED) { + time.Sleep(200 * time.Millisecond) + continue + } + + if err != nil { + err = os.NewSyscallError("ConnectEx", err) + return nil, err + } + + _, err = conn.Write(nonce[:]) + if err != nil { + return nil, err + } + + return conn, nil + } +} + func underlyingError(err error) error { if serr, ok := err.(*os.SyscallError); ok { return serr.Err @@ -92,70 +157,13 @@ func main() { var conn *overlappedFile var err error - // Loop only if we're polling the named pipe or socket - for { + if !*assuan { conn, err = dialPipe(args[0], *poll) - - if *poll && os.IsNotExist(err) { - time.Sleep(200 * time.Millisecond) - continue - } - - if err != nil { - err = &os.PathError{Path: args[0], Op: "open", Err: err} - log.Fatalln(err) - } - - // LibAssaaun file socket: Attempt to read contents of the target file and connect to a TCP port - if *assuan { - var port int - var nonce [16]byte - - reader := bufio.NewReader(conn) - - // Read the target port number from the first line - tmp, _, err := reader.ReadLine() - port, err = strconv.Atoi(string(tmp)) - if err != nil { - log.Fatalln(err) - } - - // Read the rest of the nonce from the file - n, err := reader.Read(nonce[:]) - if err != nil { - log.Fatalln(err) - } - - if n != 16 { - log.Fatalf("Read incorrect number of bytes for nonce. Expected 16, got %d (0x%X)", n, nonce) - } - - if *verbose { - log.Printf("Port: %d, Nonce: %X", port, nonce) - } - - _ = conn.Close() - - // Try to connect to the libassaun TCP socket hosted on localhost - conn, err = dialPort(port, *poll) - - if *poll && (err == windows.WSAETIMEDOUT || err == windows.WSAECONNREFUSED || err == windows.WSAENETUNREACH || err == windows.ERROR_CONNECTION_REFUSED) { - time.Sleep(200 * time.Millisecond) - continue - } - - err = os.NewSyscallError("ConnectEx", err) - - if err != nil { - log.Fatal(err) - } - - _, err = conn.Write(nonce[:]) - if err != nil { - log.Fatal(err) - } - } - break + } else { + conn, err = dialAssuan(args[0], *poll) + } + if err != nil { + log.Fatalln(err) } if *verbose { From 2efee540e07a0a860a1f7e66ed07ed20483cd85e Mon Sep 17 00:00:00 2001 From: Lex Robinson Date: Fri, 19 Apr 2019 16:05:52 +0100 Subject: [PATCH 10/10] Refactor code a little - Have a constant for the polling timeout - Use more standard error handling - Don't open the pipe over and over if polling - Don't call strconv.Atoi if we know there's no valid text --- npiperelay.go | 70 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/npiperelay.go b/npiperelay.go index 20a2095..15f72ee 100644 --- a/npiperelay.go +++ b/npiperelay.go @@ -15,6 +15,9 @@ import ( "golang.org/x/sys/windows" ) +// How long to sleep between failures while polling +const pollTimeout = 200 * time.Millisecond + var ( poll = flag.Bool("p", false, "poll until the the named pipe exists") closeWrite = flag.Bool("s", false, "send a 0-byte message to the pipe after EOF on stdin") @@ -35,7 +38,7 @@ func dialPipe(p string, poll bool) (*overlappedFile, error) { return newOverlappedFile(h), nil } if poll && os.IsNotExist(err) { - time.Sleep(200 * time.Millisecond) + time.Sleep(pollTimeout) continue } return nil, &os.PathError{Path: p, Op: "open", Err: err} @@ -68,56 +71,57 @@ func dialPort(p int, poll bool) (*overlappedFile, error) { _, err = conn.asyncIo(func(h windows.Handle, n *uint32, o *windows.Overlapped) error { return windows.ConnectEx(h, sa, nil, 0, nil, o) }) - if err == nil { - return conn, nil + if err != nil { + return nil, err } - return nil, err + return conn, nil } // LibAssaun file socket: Attempt to read contents of the target file and connect to a TCP port func dialAssuan(p string, poll bool) (*overlappedFile, error) { - for { - conn, err := dialPipe(p, poll) - - if err != nil { - return nil, err - } + pipeConn, err := dialPipe(p, poll) + if err != nil { + return nil, err + } - var port int - var nonce [16]byte + var port int + var nonce [16]byte - reader := bufio.NewReader(conn) + reader := bufio.NewReader(pipeConn) - // Read the target port number from the first line - tmp, _, err := reader.ReadLine() + // Read the target port number from the first line + tmp, _, err := reader.ReadLine() + if err == nil { port, err = strconv.Atoi(string(tmp)) - if err != nil { - return nil, err - } + } + if err != nil { + return nil, err + } - // Read the rest of the nonce from the file - n, err := reader.Read(nonce[:]) - if err != nil { - return nil, err - } + // Read the rest of the nonce from the file + n, err := reader.Read(nonce[:]) + if err != nil { + return nil, err + } - if n != 16 { - err = fmt.Errorf("Read incorrect number of bytes for nonce. Expected 16, got %d (0x%X)", n, nonce) - return nil, err - } + if n != 16 { + err = fmt.Errorf("Read incorrect number of bytes for nonce. Expected 16, got %d (0x%X)", n, nonce) + return nil, err + } - if *verbose { - log.Printf("Port: %d, Nonce: %X", port, nonce) - } + if *verbose { + log.Printf("Port: %d, Nonce: %X", port, nonce) + } - conn.Close() + pipeConn.Close() + for { // Try to connect to the libassaun TCP socket hosted on localhost - conn, err = dialPort(port, poll) + conn, err := dialPort(port, poll) if poll && (err == windows.WSAETIMEDOUT || err == windows.WSAECONNREFUSED || err == windows.WSAENETUNREACH || err == windows.ERROR_CONNECTION_REFUSED) { - time.Sleep(200 * time.Millisecond) + time.Sleep(pollTimeout) continue }