Skip to content

Commit

Permalink
add driver name and version to TDS packets (microsoft#77)
Browse files Browse the repository at this point in the history
feat: add driver name and version to TDS packets
  • Loading branch information
shueybubbles authored Jan 6, 2023
1 parent 86ecefd commit 12048ef
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 78 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog

## 0.20.0

### Features

* Add driver version and name to TDS login packets

### Bug fixes

* Added checks while reading prelogin for invalid data ([#64](https://github.com/microsoft/go-mssqldb/issues/64))([86ecefd8b](https://github.com/microsoft/go-mssqldb/commit/86ecefd8b57683aeb5ad9328066ee73fbccd62f5))
25 changes: 14 additions & 11 deletions tds.go
Original file line number Diff line number Diff line change
Expand Up @@ -936,9 +936,10 @@ func preparePreloginFields(p msdsn.Config, fe *featureExtFedAuth) map[uint8][]by
case msdsn.EncryptionOff:
encrypt = encryptOff
}

v := getDriverVersion(driverVersion)
fields := map[uint8][]byte{
preloginVERSION: {0, 0, 0, 0, 0, 0},
// 4 bytes for version and 2 bytes for minor version
preloginVERSION: {byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24), 0, 0},
preloginENCRYPTION: {encrypt},
preloginINSTOPT: instance_buf,
preloginTHREADID: {0, 0, 0, 0},
Expand Down Expand Up @@ -992,15 +993,17 @@ func prepareLogin(ctx context.Context, c *Connector, p msdsn.Config, logger Cont
serverName = p.Host
}
l = &login{
TDSVersion: verTDS74,
PacketSize: packetSize,
Database: p.Database,
OptionFlags2: fODBC, // to get unlimited TEXTSIZE
OptionFlags1: fUseDB | fSetLang,
HostName: p.Workstation,
ServerName: serverName,
AppName: p.AppName,
TypeFlags: typeFlags,
TDSVersion: verTDS74,
PacketSize: packetSize,
Database: p.Database,
OptionFlags2: fODBC, // to get unlimited TEXTSIZE
OptionFlags1: fUseDB | fSetLang,
HostName: p.Workstation,
ServerName: serverName,
AppName: p.AppName,
TypeFlags: typeFlags,
CtlIntName: "go-mssqldb",
ClientProgVer: getDriverVersion(driverVersion),
}
switch {
case fe.FedAuthLibrary == FedAuthLibrarySecurityToken:
Expand Down
139 changes: 72 additions & 67 deletions tds_login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func testLoginSequenceServer(result chan error, conn net.Conn, expectedPackets,

for b := 0; b < len(expectedBytes) && err == nil; {
n, err := conn.Read(packet)

p := hex.EncodeToString(packet[:n])
// Ignore EOF: ErrPipeClosed is the real signal
if err == io.EOF {
err = nil
Expand All @@ -82,8 +82,8 @@ func testLoginSequenceServer(result chan error, conn net.Conn, expectedPackets,
if bi < n {
suffix = fmt.Sprintf("%s Next byte:%02X", suffix, packet[bi+1])
}
err = fmt.Errorf("Client sent unexpected byte %02X != %02X at offset %d of packet %d. %s",
packet[bi], expectedBytes[bi+b], bi+b, i, suffix)
err = fmt.Errorf("Client sent unexpected byte %02X != %02X at offset %d of packet %d. %s\nActual:%s\nExpected:%s",
packet[bi], expectedBytes[bi+b], bi+b, i, suffix, p, expectedHex)

result <- err
return
Expand Down Expand Up @@ -126,24 +126,25 @@ func TestLoginWithSQLServerAuth(t *testing.T) {
tl := testLogger{t: t}
defer tl.StopLogging()
SetLogger(&tl)

v := versionToHexString(getDriverVersion(driverVersion))
mock := NewMockTransportDialer(
[]string{
" 12 01 00 2f 00 00 01 00 00 00 1a 00 06 01 00 20\n" +
"00 01 02 00 21 00 01 03 00 22 00 04 04 00 26 00\n" +
"01 ff 00 00 00 00 00 00 00 00 00 00 00 00 00\n",
" 10 01 00 b2 00 00 01 00 aa 00 00 00 04 00 00 74\n" +
"00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n" +
"A0 02 00 00 00 00 00 00 00 00 00 00 5e 00 09 00\n" +
"70 00 04 00 78 00 06 00 84 00 0a 00 98 00 09 00\n" +
"00 00 00 00 aa 00 00 00 aa 00 00 00 aa 00 00 00\n" +
"00 00 00 00 00 00 aa 00 00 00 aa 00 00 00 aa 00\n" +
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n" +
"68 00 6f 00 73 00 74 00 74 00 65 00 73 00 74 00\n" +
"92 a5 f3 a5 93 a5 82 a5 f3 a5 e2 a5 67 00 6f 00\n" +
"2d 00 6d 00 73 00 73 00 71 00 6c 00 64 00 62 00\n" +
"6c 00 6f 00 63 00 61 00 6c 00 68 00 6f 00 73 00\n" +
"74 00\n",
fmt.Sprintf("12 01 00 2f 00 00 01 00 00 00 1a 00 06 01 00 20\n"+
"00 01 02 00 21 00 01 03 00 22 00 04 04 00 26 00\n"+
"01 ff %s 00 00 00 00 00 00 00 00 00\n", v),
fmt.Sprintf("10 01 00 c6 00 00 01 00 be 00 00 00 04 00 00 74\n"+
"00 10 00 00 %s 00 00 00 00 00 00 00 00\n"+
"A0 02 00 00 00 00 00 00 00 00 00 00 5e 00 09 00\n"+
"70 00 04 00 78 00 06 00 84 00 0a 00 98 00 09 00\n"+
"00 00 00 00 aa 00 0a 00 be 00 00 00 be 00 00 00\n"+
"00 00 00 00 00 00 be 00 00 00 be 00 00 00 be 00\n"+
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n"+
"68 00 6f 00 73 00 74 00 74 00 65 00 73 00 74 00\n"+
"92 a5 f3 a5 93 a5 82 a5 f3 a5 e2 a5 67 00 6f 00\n"+
"2d 00 6d 00 73 00 73 00 71 00 6c 00 64 00 62 00\n"+
"6c 00 6f 00 63 00 61 00 6c 00 68 00 6f 00 73 00\n"+
"74 00 67 00 6f 00 2d 00 6d 00 73 00 73 00 71 00\n"+
"6c 00 64 00 62 00\n", v),
},
[]string{
" 04 01 00 20 00 00 01 00 00 00 10 00 06 01 00 16\n" +
Expand Down Expand Up @@ -186,25 +187,26 @@ func TestLoginWithSecurityTokenAuth(t *testing.T) {
tl := testLogger{t: t}
defer tl.StopLogging()
SetLogger(&tl)

v := versionToHexString(getDriverVersion(driverVersion))
mock := NewMockTransportDialer(
[]string{
" 12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n" +
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n" +
"01 06 00 2c 00 01 ff 00 00 00 00 00 00 00 00 00\n" +
"00 00 00 00 01\n",
" 10 01 00 BB 00 00 01 00 B3 00 00 00 04 00 00 74\n" +
"00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n" +
"A0 02 00 10 00 00 00 00 00 00 00 00 5E 00 09 00\n" +
"70 00 00 00 70 00 00 00 70 00 0A 00 84 00 09 00\n" +
"96 00 04 00 96 00 00 00 96 00 00 00 96 00 00 00\n" +
"00 00 00 00 00 00 96 00 00 00 96 00 00 00 96 00\n" +
"00 00 00 00 00 00 6C 00 6F 00 63 00 61 00 6C 00\n" +
"68 00 6F 00 73 00 74 00 67 00 6F 00 2D 00 6D 00\n" +
"73 00 73 00 71 00 6C 00 64 00 62 00 6C 00 6F 00\n" +
"63 00 61 00 6C 00 68 00 6F 00 73 00 74 00 9A 00\n" +
"00 00 02 13 00 00 00 03 0E 00 00 00 3C 00 74 00\n" +
"6F 00 6B 00 65 00 6E 00 3E 00 FF\n",
fmt.Sprintf("12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n"+
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n"+
"01 06 00 2c 00 01 ff %s 00 00 00 00 00\n"+
"00 00 00 00 01\n", v),
fmt.Sprintf("10 01 00 CF 00 00 01 00 C7 00 00 00 04 00 00 74\n"+
"00 10 00 00 %s 00 00 00 00 00 00 00 00\n"+
"A0 02 00 10 00 00 00 00 00 00 00 00 5E 00 09 00\n"+
"70 00 00 00 70 00 00 00 70 00 0A 00 84 00 09 00\n"+
"AA 00 04 00 96 00 0A 00 AA 00 00 00 AA 00 00 00\n"+
"00 00 00 00 00 00 AA 00 00 00 AA 00 00 00 AA 00\n"+
"00 00 00 00 00 00 6C 00 6F 00 63 00 61 00 6C 00\n"+
"68 00 6F 00 73 00 74 00 67 00 6F 00 2D 00 6D 00\n"+
"73 00 73 00 71 00 6C 00 64 00 62 00 6C 00 6F 00\n"+
"63 00 61 00 6C 00 68 00 6F 00 73 00 74 00 67 00\n"+
"6F 00 2D 00 6D 00 73 00 73 00 71 00 6C 00 64 00\n"+
"62 00 AE 00 00 00 02 13 00 00 00 03 0E 00 00 00\n"+
"3C 00 74 00 6F 00 6B 00 65 00 6E 00 3E 00 FF\n", v),
},
[]string{
" 04 01 00 20 00 00 01 00 00 00 10 00 06 01 00 16\n" +
Expand Down Expand Up @@ -249,24 +251,25 @@ func TestLoginWithADALUsernamePasswordAuth(t *testing.T) {
tl := testLogger{t: t}
defer tl.StopLogging()
SetLogger(&tl)

v := versionToHexString(getDriverVersion(driverVersion))
mock := NewMockTransportDialer(
[]string{
" 12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n" +
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n" +
"01 06 00 2C 00 01 ff 00 00 00 00 00 00 00 00 00\n" +
"00 00 00 00 01\n",
" 10 01 00 aa 00 00 01 00 a2 00 00 00 04 00 00 74\n" +
"00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n" +
"A0 02 00 10 00 00 00 00 00 00 00 00 5e 00 09 00\n" +
"70 00 00 00 70 00 00 00 70 00 0a 00 84 00 09 00\n" +
"96 00 04 00 96 00 00 00 96 00 00 00 96 00 00 00\n" +
"00 00 00 00 00 00 96 00 00 00 96 00 00 00 96 00\n" +
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n" +
"68 00 6f 00 73 00 74 00 67 00 6f 00 2d 00 6d 00\n" +
"73 00 73 00 71 00 6c 00 64 00 62 00 6c 00 6f 00\n" +
"63 00 61 00 6c 00 68 00 6f 00 73 00 74 00 9a 00\n" +
"00 00 02 02 00 00 00 05 01 ff\n",
fmt.Sprintf("12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n"+
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n"+
"01 06 00 2C 00 01 ff %s 00 00 00 00 00\n"+
"00 00 00 00 01\n", v),
fmt.Sprintf("10 01 00 BE 00 00 01 00 b6 00 00 00 04 00 00 74\n"+
"00 10 00 00 %s 00 00 00 00 00 00 00 00\n"+
"A0 02 00 10 00 00 00 00 00 00 00 00 5e 00 09 00\n"+
"70 00 00 00 70 00 00 00 70 00 0a 00 84 00 09 00\n"+
"AA 00 04 00 96 00 0A 00 AA 00 00 00 AA 00 00 00\n"+
"00 00 00 00 00 00 AA 00 00 00 AA 00 00 00 AA 00\n"+
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n"+
"68 00 6f 00 73 00 74 00 67 00 6f 00 2d 00 6d 00\n"+
"73 00 73 00 71 00 6c 00 64 00 62 00 6c 00 6f 00\n"+
"63 00 61 00 6c 00 68 00 6f 00 73 00 74 00 67 00\n"+
"6f 00 2d 00 6d 00 73 00 73 00 71 00 6c 00 64 00\n"+
"62 00 AE 00 00 00 02 02 00 00 00 05 01 ff\n", v),
" 08 01 00 1e 00 00 01 00 12 00 00 00 0e 00 00 00\n" +
"3c 00 74 00 6f 00 6b 00 65 00 6e 00 3e 00\n",
},
Expand Down Expand Up @@ -324,23 +327,25 @@ func TestLoginWithADALManagedIdentityAuth(t *testing.T) {
defer tl.StopLogging()
SetLogger(&tl)

v := versionToHexString(getDriverVersion(driverVersion))
mock := NewMockTransportDialer(
[]string{
" 12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n" +
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n" +
"01 06 00 2C 00 01 ff 00 00 00 00 00 00 00 00 00\n" +
"00 00 00 00 01\n",
" 10 01 00 aa 00 00 01 00 a2 00 00 00 04 00 00 74\n" +
"00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n" +
"A0 02 00 10 00 00 00 00 00 00 00 00 5e 00 09 00\n" +
"70 00 00 00 70 00 00 00 70 00 0a 00 84 00 09 00\n" +
"96 00 04 00 96 00 00 00 96 00 00 00 96 00 00 00\n" +
"00 00 00 00 00 00 96 00 00 00 96 00 00 00 96 00\n" +
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n" +
"68 00 6f 00 73 00 74 00 67 00 6f 00 2d 00 6d 00\n" +
"73 00 73 00 71 00 6c 00 64 00 62 00 6c 00 6f 00\n" +
"63 00 61 00 6c 00 68 00 6f 00 73 00 74 00 9a 00\n" +
"00 00 02 02 00 00 00 05 03 ff\n",
fmt.Sprintf("12 01 00 35 00 00 01 00 00 00 1F 00 06 01 00 25\n"+
"00 01 02 00 26 00 01 03 00 27 00 04 04 00 2B 00\n"+
"01 06 00 2C 00 01 ff %s 00 00 00 00 00\n"+
"00 00 00 00 01\n", v),
fmt.Sprintf("10 01 00 be 00 00 01 00 b6 00 00 00 04 00 00 74\n"+
"00 10 00 00 %s 00 00 00 00 00 00 00 00\n"+
"A0 02 00 10 00 00 00 00 00 00 00 00 5e 00 09 00\n"+
"70 00 00 00 70 00 00 00 70 00 0a 00 84 00 09 00\n"+
"AA 00 04 00 96 00 0A 00 AA 00 00 00 AA 00 00 00\n"+
"00 00 00 00 00 00 AA 00 00 00 AA 00 00 00 AA 00\n"+
"00 00 00 00 00 00 6c 00 6f 00 63 00 61 00 6c 00\n"+
"68 00 6f 00 73 00 74 00 67 00 6f 00 2d 00 6d 00\n"+
"73 00 73 00 71 00 6c 00 64 00 62 00 6c 00 6f 00\n"+
"63 00 61 00 6c 00 68 00 6f 00 73 00 74 00 67 00\n"+
"6f 00 2d 00 6d 00 73 00 73 00 71 00 6c 00 64 00\n"+
"62 00 AE 00 00 00 02 02 00 00 00 05 03 ff\n", v),
" 08 01 00 1e 00 00 01 00 12 00 00 00 0e 00 00 00\n" +
"3c 00 74 00 6f 00 6b 00 65 00 6e 00 3e 00\n",
},
Expand Down
15 changes: 15 additions & 0 deletions tds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"context"
"database/sql"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
Expand Down Expand Up @@ -952,3 +953,17 @@ func runBatch(t testing.TB, p msdsn.Config) {
}
}
}

func TestGetDriverVersion(t *testing.T) {
v := getDriverVersion("v1.20.3")
t.Logf("driverVersion %08x (%s)", v, versionToHexString(v))
if v != (1<<24)|(20<<16)|(3) {
t.Fatalf("Incorrect getDriverVersion. In: v1.20.3 Out: 0x%x", v)
}
}

func versionToHexString(v uint32) string {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, v)
return hex.EncodeToString(b)
}
15 changes: 15 additions & 0 deletions version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package mssql

import "fmt"

// Update this variable with the release tag before pushing the tag
// This value is written to the prelogin and login7 packets during a new connection
const driverVersion = "v0.20.0"

func getDriverVersion(ver string) uint32 {
var majorVersion uint32
var minorVersion uint32
var rev uint32
_, _ = fmt.Sscanf(ver, "v%d.%d.%d", &majorVersion, &minorVersion, &rev)
return (majorVersion << 24) | (minorVersion << 16) | rev
}

0 comments on commit 12048ef

Please sign in to comment.