From ada93e39c662314977f448b27ffd44ee1f5fe2b9 Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Thu, 29 Feb 2024 16:06:24 -0800 Subject: [PATCH 1/3] Fix:Enable connection to WID --- namedpipe/namedpipe_windows.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/namedpipe/namedpipe_windows.go b/namedpipe/namedpipe_windows.go index 24ea737e..9e2df884 100644 --- a/namedpipe/namedpipe_windows.go +++ b/namedpipe/namedpipe_windows.go @@ -28,26 +28,34 @@ func (n namedPipeDialer) ParseServer(server string, p *msdsn.Config) error { if strings.HasPrefix(server, `\\`) { // assume a server name starting with \\ is the full named pipe path p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: server} - } else if p.Host == "" { // if the string specifies np:host\instance, tcpParser won't have filled in p.Host + return nil + } + pipeHost := "." + if p.Host == "" { // if the string specifies np:host\instance, tcpParser won't have filled in p.Host parts := strings.SplitN(server, `\`, 2) - p.Host = parts[0] - if p.Host == "." || strings.ToUpper(p.Host) == "(LOCAL)" { + host := parts[0] + if host == "." || strings.ToUpper(host) == "(LOCAL)" { + // localhost replaces . to query the browser service but some SQL instances + // like Windows Internal Database require the . in the pipe name to connect p.Host = "localhost" + } else { + p.Host = host + pipeHost = host } if len(parts) > 1 { p.Instance = parts[1] } } else { - host := strings.ToLower(p.Host) + pipeHost = strings.ToLower(p.Host) for _, domain := range azureDomains { - if strings.HasSuffix(host, domain) { + if strings.HasSuffix(pipeHost, domain) { return fmt.Errorf("Named pipes disallowed for Azure SQL Database connections") } } } pipe, ok := p.Parameters["pipe"] if ok { - p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: fmt.Sprintf(`\\%s\pipe\%s`, p.Host, pipe)} + p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: fmt.Sprintf(`\\%s\pipe\%s`, pipeHost, pipe)} } return nil } From e8681094eb8febe2bf1f7a7bcdf53189a03379a9 Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Fri, 1 Mar 2024 07:13:47 -0800 Subject: [PATCH 2/3] add tests --- namedpipe/namepipe_windows_test.go | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 namedpipe/namepipe_windows_test.go diff --git a/namedpipe/namepipe_windows_test.go b/namedpipe/namepipe_windows_test.go new file mode 100644 index 00000000..f51bb0a3 --- /dev/null +++ b/namedpipe/namepipe_windows_test.go @@ -0,0 +1,54 @@ +package namedpipe + +import ( + "testing" + + "github.com/microsoft/go-mssqldb/msdsn" + "github.com/stretchr/testify/assert" +) + +func TestParseServer(t *testing.T) { + c := &msdsn.Config{ + Port: 1000, + } + n := &namedPipeDialer{} + err := n.ParseServer("server", c) + assert.Errorf(t, err, "ParseServer with a Port") + + c = &msdsn.Config{ + Parameters: make(map[string]string), + ProtocolParameters: make(map[string]interface{}), + } + err = n.ParseServer(`\\.\pipe\MSSQL$Instance\sql\query`, c) + assert.NoError(t, err, "ParseServer with a full pipe name") + assert.Equal(t, "", c.Host, "Config Host with a full pipe name") + + c = &msdsn.Config{ + Parameters: make(map[string]string), + ProtocolParameters: make(map[string]interface{}), + } + err = n.ParseServer(`.\instance`, c) + assert.NoError(t, err, "ParseServer .") + assert.Equal(t, "localhost", c.Host, `Config Host with server == .\instance`) + assert.Equal(t, "instance", c.Instance, `Config Instance with server == .\instance`) + _, ok := c.ProtocolParameters[n.Protocol()] + assert.Equal(t, ok, false, "Should have no namedPipeData when pipe name omitted") + + c = &msdsn.Config{ + Host: "server", + Parameters: make(map[string]string), + ProtocolParameters: make(map[string]interface{}), + } + c.Parameters["pipe"] = `myinstance\sql\query` + err = n.ParseServer(`anything`, c) + assert.NoError(t, err, "ParseServer anything") + data, ok := c.ProtocolParameters[n.Protocol()] + assert.True(t, ok, "Should have added ProtocolParameters when pipe name is provided") + switch d := data.(type) { + case namedPipeData: + assert.Equal(t, `\\server\pipe\myinstance\sql\query`, d.PipeName, "Pipe name in ProtocolParameters") + default: + assert.Fail(t, "Incorrect protocol parameters type:", d) + } + +} From d4192bcc31dbb82b88fa04b5bc7e55b35e317dfb Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Fri, 1 Mar 2024 07:17:43 -0800 Subject: [PATCH 3/3] update test --- namedpipe/namepipe_windows_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/namedpipe/namepipe_windows_test.go b/namedpipe/namepipe_windows_test.go index f51bb0a3..e6b0c5e3 100644 --- a/namedpipe/namepipe_windows_test.go +++ b/namedpipe/namepipe_windows_test.go @@ -22,6 +22,14 @@ func TestParseServer(t *testing.T) { err = n.ParseServer(`\\.\pipe\MSSQL$Instance\sql\query`, c) assert.NoError(t, err, "ParseServer with a full pipe name") assert.Equal(t, "", c.Host, "Config Host with a full pipe name") + data, ok := c.ProtocolParameters[n.Protocol()] + assert.True(t, ok, "Should have added ProtocolParameters when server is pipe name") + switch d := data.(type) { + case namedPipeData: + assert.Equal(t, `\\.\pipe\MSSQL$Instance\sql\query`, d.PipeName, "Pipe name in ProtocolParameters when server is pipe name") + default: + assert.Fail(t, "Incorrect protocol parameters type:", d) + } c = &msdsn.Config{ Parameters: make(map[string]string), @@ -31,7 +39,7 @@ func TestParseServer(t *testing.T) { assert.NoError(t, err, "ParseServer .") assert.Equal(t, "localhost", c.Host, `Config Host with server == .\instance`) assert.Equal(t, "instance", c.Instance, `Config Instance with server == .\instance`) - _, ok := c.ProtocolParameters[n.Protocol()] + _, ok = c.ProtocolParameters[n.Protocol()] assert.Equal(t, ok, false, "Should have no namedPipeData when pipe name omitted") c = &msdsn.Config{ @@ -42,7 +50,7 @@ func TestParseServer(t *testing.T) { c.Parameters["pipe"] = `myinstance\sql\query` err = n.ParseServer(`anything`, c) assert.NoError(t, err, "ParseServer anything") - data, ok := c.ProtocolParameters[n.Protocol()] + data, ok = c.ProtocolParameters[n.Protocol()] assert.True(t, ok, "Should have added ProtocolParameters when pipe name is provided") switch d := data.(type) { case namedPipeData: