Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix named pipe path handling to preserve "." #178

Merged
merged 3 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions namedpipe/namedpipe_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
62 changes: 62 additions & 0 deletions namedpipe/namepipe_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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")
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),
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)
}

}
Loading