summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/denisenkom/go-mssqldb/tds.go
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2020-05-10 19:42:52 +0200
committerGitHub <noreply@github.com>2020-05-10 18:42:52 +0100
commit6e23a1b843a9bde7608e86cdddd3131047b2c70b (patch)
treed52adcd82ddc230ce3df38907144104370c6b079 /vendor/github.com/denisenkom/go-mssqldb/tds.go
parentda5e3fa299f6cac5ee9a4b0c50062dda1e91c8e2 (diff)
downloadgitea-6e23a1b843a9bde7608e86cdddd3131047b2c70b.tar.gz
gitea-6e23a1b843a9bde7608e86cdddd3131047b2c70b.zip
[Vendor] mssqldb: 2019-11-28 -> 2020-04-28 (#11364)
update go-mssqldb 2019-11-28 (1d7a30a10f73) -> 2020-04-28 (06a60b6afbbc)
Diffstat (limited to 'vendor/github.com/denisenkom/go-mssqldb/tds.go')
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/tds.go146
1 files changed, 134 insertions, 12 deletions
diff --git a/vendor/github.com/denisenkom/go-mssqldb/tds.go b/vendor/github.com/denisenkom/go-mssqldb/tds.go
index 9419836448..832c4fd23a 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/tds.go
+++ b/vendor/github.com/denisenkom/go-mssqldb/tds.go
@@ -100,13 +100,15 @@ const (
// prelogin fields
// http://msdn.microsoft.com/en-us/library/dd357559.aspx
const (
- preloginVERSION = 0
- preloginENCRYPTION = 1
- preloginINSTOPT = 2
- preloginTHREADID = 3
- preloginMARS = 4
- preloginTRACEID = 5
- preloginTERMINATOR = 0xff
+ preloginVERSION = 0
+ preloginENCRYPTION = 1
+ preloginINSTOPT = 2
+ preloginTHREADID = 3
+ preloginMARS = 4
+ preloginTRACEID = 5
+ preloginFEDAUTHREQUIRED = 6
+ preloginNONCEOPT = 7
+ preloginTERMINATOR = 0xff
)
const (
@@ -245,6 +247,12 @@ const (
fReadOnlyIntent = 32
)
+// OptionFlags3
+// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/773a62b6-ee89-4c02-9e5e-344882630aac
+const (
+ fExtension = 0x10
+)
+
type login struct {
TDSVersion uint32
PacketSize uint32
@@ -269,6 +277,89 @@ type login struct {
SSPI []byte
AtchDBFile string
ChangePassword string
+ FeatureExt featureExts
+}
+
+type featureExts struct {
+ features map[byte]featureExt
+}
+
+type featureExt interface {
+ featureID() byte
+ toBytes() []byte
+}
+
+func (e *featureExts) Add(f featureExt) error {
+ if f == nil {
+ return nil
+ }
+ id := f.featureID()
+ if _, exists := e.features[id]; exists {
+ f := "Login error: Feature with ID '%v' is already present in FeatureExt block."
+ return fmt.Errorf(f, id)
+ }
+ if e.features == nil {
+ e.features = make(map[byte]featureExt)
+ }
+ e.features[id] = f
+ return nil
+}
+
+func (e featureExts) toBytes() []byte {
+ if len(e.features) == 0 {
+ return nil
+ }
+ var d []byte
+ for featureID, f := range e.features {
+ featureData := f.toBytes()
+
+ hdr := make([]byte, 5)
+ hdr[0] = featureID // FedAuth feature extension BYTE
+ binary.LittleEndian.PutUint32(hdr[1:], uint32(len(featureData))) // FeatureDataLen DWORD
+ d = append(d, hdr...)
+
+ d = append(d, featureData...) // FeatureData *BYTE
+ }
+ if d != nil {
+ d = append(d, 0xff) // Terminator
+ }
+ return d
+}
+
+type featureExtFedAuthSTS struct {
+ FedAuthEcho bool
+ FedAuthToken string
+ Nonce []byte
+}
+
+func (e *featureExtFedAuthSTS) featureID() byte {
+ return 0x02
+}
+
+func (e *featureExtFedAuthSTS) toBytes() []byte {
+ if e == nil {
+ return nil
+ }
+
+ options := byte(0x01) << 1 // 0x01 => STS bFedAuthLibrary 7BIT
+ if e.FedAuthEcho {
+ options |= 1 // fFedAuthEcho
+ }
+
+ d := make([]byte, 5)
+ d[0] = options
+
+ // looks like string in
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/f88b63bb-b479-49e1-a87b-deda521da508
+ tokenBytes := str2ucs2(e.FedAuthToken)
+ binary.LittleEndian.PutUint32(d[1:], uint32(len(tokenBytes))) // Should be a signed int32, but since the length is relatively small, this should work
+ d = append(d, tokenBytes...)
+
+ if len(e.Nonce) == 32 {
+ d = append(d, e.Nonce...)
+ }
+
+ return d
}
type loginHeader struct {
@@ -295,7 +386,7 @@ type loginHeader struct {
ServerNameOffset uint16
ServerNameLength uint16
ExtensionOffset uint16
- ExtensionLenght uint16
+ ExtensionLength uint16
CtlIntNameOffset uint16
CtlIntNameLength uint16
LanguageOffset uint16
@@ -357,6 +448,8 @@ func sendLogin(w *tdsBuffer, login login) error {
database := str2ucs2(login.Database)
atchdbfile := str2ucs2(login.AtchDBFile)
changepassword := str2ucs2(login.ChangePassword)
+ featureExt := login.FeatureExt.toBytes()
+
hdr := loginHeader{
TDSVersion: login.TDSVersion,
PacketSize: login.PacketSize,
@@ -405,7 +498,18 @@ func sendLogin(w *tdsBuffer, login login) error {
offset += uint16(len(atchdbfile))
hdr.ChangePasswordOffset = offset
offset += uint16(len(changepassword))
- hdr.Length = uint32(offset)
+
+ featureExtOffset := uint32(0)
+ featureExtLen := len(featureExt)
+ if featureExtLen > 0 {
+ hdr.OptionFlags3 |= fExtension
+ hdr.ExtensionOffset = offset
+ hdr.ExtensionLength = 4
+ offset += hdr.ExtensionLength // DWORD
+ featureExtOffset = uint32(offset)
+ }
+ hdr.Length = uint32(offset) + uint32(featureExtLen)
+
var err error
err = binary.Write(w, binary.LittleEndian, &hdr)
if err != nil {
@@ -455,6 +559,16 @@ func sendLogin(w *tdsBuffer, login login) error {
if err != nil {
return err
}
+ if featureExtOffset > 0 {
+ err = binary.Write(w, binary.LittleEndian, featureExtOffset)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(featureExt)
+ if err != nil {
+ return err
+ }
+ }
return w.FinishPacket()
}
@@ -844,15 +958,23 @@ initiate_connection:
AppName: p.appname,
TypeFlags: p.typeFlags,
}
- auth, auth_ok := getAuth(p.user, p.password, p.serverSPN, p.workstation)
- if auth_ok {
+ auth, authOk := getAuth(p.user, p.password, p.serverSPN, p.workstation)
+ switch {
+ case p.fedAuthAccessToken != "": // accesstoken ignores user/password
+ featurext := &featureExtFedAuthSTS{
+ FedAuthEcho: len(fields[preloginFEDAUTHREQUIRED]) > 0 && fields[preloginFEDAUTHREQUIRED][0] == 1,
+ FedAuthToken: p.fedAuthAccessToken,
+ Nonce: fields[preloginNONCEOPT],
+ }
+ login.FeatureExt.Add(featurext)
+ case authOk:
login.SSPI, err = auth.InitialBytes()
if err != nil {
return nil, err
}
login.OptionFlags2 |= fIntSecurity
defer auth.Free()
- } else {
+ default:
login.UserName = p.user
login.Password = p.password
}