summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/denisenkom/go-mssqldb
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
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')
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/README.md22
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/accesstokenconnector.go51
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/conn_str.go1
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/mssql.go5
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/ntlm.go173
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/tds.go146
-rw-r--r--vendor/github.com/denisenkom/go-mssqldb/token.go47
7 files changed, 391 insertions, 54 deletions
diff --git a/vendor/github.com/denisenkom/go-mssqldb/README.md b/vendor/github.com/denisenkom/go-mssqldb/README.md
index b655176bb6..94d87fe092 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/README.md
+++ b/vendor/github.com/denisenkom/go-mssqldb/README.md
@@ -18,7 +18,7 @@ Other supported formats are listed below.
### Common parameters:
-* `user id` - enter the SQL Server Authentication user id or the Windows Authentication user id in the DOMAIN\User format. On Windows, if user id is empty or missing Single-Sign-On is used.
+* `user id` - enter the SQL Server Authentication user id or the Windows Authentication user id in the DOMAIN\User format. On Windows, if user id is empty or missing Single-Sign-On is used. The user domain sensitive to the case which is defined in the connection string.
* `password`
* `database`
* `connection timeout` - in seconds (default is 0 for no timeout), set to 0 for no timeout. Recommended to set to 0 and use context to manage query and connection timeouts.
@@ -106,6 +106,26 @@ Other supported formats are listed below.
* `odbc:server=localhost;user id=sa;password={foo{bar}` // Literal `{`, password is "foo{bar"
* `odbc:server=localhost;user id=sa;password={foo}}bar}` // Escaped `} with `}}`, password is "foo}bar"
+### Azure Active Directory authentication - preview
+
+The configuration of functionality might change in the future.
+
+Azure Active Directory (AAD) access tokens are relatively short lived and need to be
+valid when a new connection is made. Authentication is supported using a callback func that
+provides a fresh and valid token using a connector:
+``` golang
+conn, err := mssql.NewAccessTokenConnector(
+ "Server=test.database.windows.net;Database=testdb",
+ tokenProvider)
+if err != nil {
+ // handle errors in DSN
+}
+db := sql.OpenDB(conn)
+```
+Where `tokenProvider` is a function that returns a fresh access token or an error. None of these statements
+actually trigger the retrieval of a token, this happens when the first statment is issued and a connection
+is created.
+
## Executing Stored Procedures
To run a stored procedure, set the query text to the procedure name:
diff --git a/vendor/github.com/denisenkom/go-mssqldb/accesstokenconnector.go b/vendor/github.com/denisenkom/go-mssqldb/accesstokenconnector.go
new file mode 100644
index 0000000000..8dbe5099e4
--- /dev/null
+++ b/vendor/github.com/denisenkom/go-mssqldb/accesstokenconnector.go
@@ -0,0 +1,51 @@
+// +build go1.10
+
+package mssql
+
+import (
+ "context"
+ "database/sql/driver"
+ "errors"
+ "fmt"
+)
+
+var _ driver.Connector = &accessTokenConnector{}
+
+// accessTokenConnector wraps Connector and injects a
+// fresh access token when connecting to the database
+type accessTokenConnector struct {
+ Connector
+
+ accessTokenProvider func() (string, error)
+}
+
+// NewAccessTokenConnector creates a new connector from a DSN and a token provider.
+// The token provider func will be called when a new connection is requested and should return a valid access token.
+// The returned connector may be used with sql.OpenDB.
+func NewAccessTokenConnector(dsn string, tokenProvider func() (string, error)) (driver.Connector, error) {
+ if tokenProvider == nil {
+ return nil, errors.New("mssql: tokenProvider cannot be nil")
+ }
+
+ conn, err := NewConnector(dsn)
+ if err != nil {
+ return nil, err
+ }
+
+ c := &accessTokenConnector{
+ Connector: *conn,
+ accessTokenProvider: tokenProvider,
+ }
+ return c, nil
+}
+
+// Connect returns a new database connection
+func (c *accessTokenConnector) Connect(ctx context.Context) (driver.Conn, error) {
+ var err error
+ c.Connector.params.fedAuthAccessToken, err = c.accessTokenProvider()
+ if err != nil {
+ return nil, fmt.Errorf("mssql: error retrieving access token: %+v", err)
+ }
+
+ return c.Connector.Connect(ctx)
+}
diff --git a/vendor/github.com/denisenkom/go-mssqldb/conn_str.go b/vendor/github.com/denisenkom/go-mssqldb/conn_str.go
index 4ff54b8955..26ac50f38d 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/conn_str.go
+++ b/vendor/github.com/denisenkom/go-mssqldb/conn_str.go
@@ -37,6 +37,7 @@ type connectParams struct {
failOverPartner string
failOverPort uint64
packetSize uint16
+ fedAuthAccessToken string
}
func parseConnectParams(dsn string) (connectParams, error) {
diff --git a/vendor/github.com/denisenkom/go-mssqldb/mssql.go b/vendor/github.com/denisenkom/go-mssqldb/mssql.go
index 5d81516919..a74bc7e3fc 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/mssql.go
+++ b/vendor/github.com/denisenkom/go-mssqldb/mssql.go
@@ -397,7 +397,10 @@ func (s *Stmt) Close() error {
}
func (s *Stmt) SetQueryNotification(id, options string, timeout time.Duration) {
- to := uint32(timeout / time.Second)
+ // 2.2.5.3.1 Query Notifications Header
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/e168d373-a7b7-41aa-b6ca-25985466a7e0
+ // Timeout in milliseconds in TDS protocol.
+ to := uint32(timeout / time.Millisecond)
if to < 1 {
to = 1
}
diff --git a/vendor/github.com/denisenkom/go-mssqldb/ntlm.go b/vendor/github.com/denisenkom/go-mssqldb/ntlm.go
index 7c0cc4f785..ea9148aed0 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/ntlm.go
+++ b/vendor/github.com/denisenkom/go-mssqldb/ntlm.go
@@ -4,11 +4,14 @@ package mssql
import (
"crypto/des"
+ "crypto/hmac"
"crypto/md5"
"crypto/rand"
"encoding/binary"
"errors"
+ "fmt"
"strings"
+ "time"
"unicode/utf16"
"golang.org/x/crypto/md4"
@@ -198,86 +201,204 @@ func ntlmSessionResponse(clientNonce [8]byte, serverChallenge [8]byte, password
return response(hash, passwordHash)
}
-func (auth *ntlmAuth) NextBytes(bytes []byte) ([]byte, error) {
- if string(bytes[0:8]) != "NTLMSSP\x00" {
- return nil, errorNTLM
+func ntlmHashNoPadding(val string) []byte {
+ hash := make([]byte, 16)
+ h := md4.New()
+ h.Write(utf16le(val))
+ h.Sum(hash[:0])
+
+ return hash
+}
+
+func hmacMD5(passwordHash, data []byte) []byte {
+ hmacEntity := hmac.New(md5.New, passwordHash)
+ hmacEntity.Write(data)
+
+ return hmacEntity.Sum(nil)
+}
+
+func getNTLMv2AndLMv2ResponsePayloads(userDomain, username, password string, challenge, nonce [8]byte, targetInfoFields []byte, timestamp time.Time) (ntlmV2Payload, lmV2Payload []byte) {
+ // NTLMv2 response payload: http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response
+
+ ntlmHash := ntlmHashNoPadding(password)
+ usernameAndTargetBytes := utf16le(strings.ToUpper(username) + userDomain)
+ ntlmV2Hash := hmacMD5(ntlmHash, usernameAndTargetBytes)
+ targetInfoLength := len(targetInfoFields)
+ blob := make([]byte, 32+targetInfoLength)
+ binary.BigEndian.PutUint32(blob[:4], 0x01010000)
+ binary.BigEndian.PutUint32(blob[4:8], 0x00000000)
+ binary.BigEndian.PutUint64(blob[8:16], uint64(timestamp.UnixNano()))
+ copy(blob[16:24], nonce[:])
+ binary.BigEndian.PutUint32(blob[24:28], 0x00000000)
+ copy(blob[28:], targetInfoFields)
+ binary.BigEndian.PutUint32(blob[28+targetInfoLength:], 0x00000000)
+ challengeLength := len(challenge)
+ blobLength := len(blob)
+ challengeAndBlob := make([]byte, challengeLength+blobLength)
+ copy(challengeAndBlob[:challengeLength], challenge[:])
+ copy(challengeAndBlob[challengeLength:], blob)
+ hashedChallenge := hmacMD5(ntlmV2Hash, challengeAndBlob)
+ ntlmV2Payload = append(hashedChallenge, blob...)
+
+ // LMv2 response payload: http://davenport.sourceforge.net/ntlm.html#theLmv2Response
+ ntlmV2hash := hmacMD5(ntlmHash, usernameAndTargetBytes)
+ challengeAndNonce := make([]byte, 16)
+ copy(challengeAndNonce[:8], challenge[:])
+ copy(challengeAndNonce[8:], nonce[:])
+ hashedChallenge = hmacMD5(ntlmV2hash, challengeAndNonce)
+ lmV2Payload = append(hashedChallenge, nonce[:]...)
+
+ return
+}
+
+func negotiateExtendedSessionSecurity(flags uint32, message []byte, challenge [8]byte, username, password, userDom string) (lm, nt []byte, err error) {
+ nonce := clientChallenge()
+
+ // Official specification: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b38c36ed-2804-4868-a9ff-8dd3182128e4
+ // Unofficial walk through referenced by https://www.freetds.org/userguide/domains.htm: http://davenport.sourceforge.net/ntlm.html
+ if (flags & _NEGOTIATE_TARGET_INFO) != 0 {
+ targetInfoFields, err := getNTLMv2TargetInfoFields(message)
+ if err != nil {
+ return lm, nt, err
+ }
+
+ nt, lm = getNTLMv2AndLMv2ResponsePayloads(userDom, username, password, challenge, nonce, targetInfoFields, time.Now())
+
+ return lm, nt, nil
}
- if binary.LittleEndian.Uint32(bytes[8:12]) != _CHALLENGE_MESSAGE {
- return nil, errorNTLM
+
+ var lm_bytes [24]byte
+ copy(lm_bytes[:8], nonce[:])
+ lm = lm_bytes[:]
+ nt_bytes := ntlmSessionResponse(nonce, challenge, password)
+ nt = nt_bytes[:]
+
+ return lm, nt, nil
+}
+
+func getNTLMv2TargetInfoFields(type2Message []byte) (info []byte, err error) {
+ type2MessageError := "mssql: while parsing NTLMv2 type 2 message, length %d too small for offset %d"
+ type2MessageLength := len(type2Message)
+ if type2MessageLength < 20 {
+ return nil, fmt.Errorf(type2MessageError, type2MessageLength, 20)
}
- flags := binary.LittleEndian.Uint32(bytes[20:24])
- var challenge [8]byte
- copy(challenge[:], bytes[24:32])
- var lm, nt []byte
- if (flags & _NEGOTIATE_EXTENDED_SESSIONSECURITY) != 0 {
- nonce := clientChallenge()
- var lm_bytes [24]byte
- copy(lm_bytes[:8], nonce[:])
- lm = lm_bytes[:]
- nt_bytes := ntlmSessionResponse(nonce, challenge, auth.Password)
- nt = nt_bytes[:]
- } else {
- lm_bytes := lmResponse(challenge, auth.Password)
- lm = lm_bytes[:]
- nt_bytes := ntResponse(challenge, auth.Password)
- nt = nt_bytes[:]
+ targetNameAllocated := binary.LittleEndian.Uint16(type2Message[14:16])
+ targetNameOffset := binary.LittleEndian.Uint32(type2Message[16:20])
+ endOfOffset := int(targetNameOffset + uint32(targetNameAllocated))
+ if type2MessageLength < endOfOffset {
+ return nil, fmt.Errorf(type2MessageError, type2MessageLength, endOfOffset)
}
+
+ targetInformationAllocated := binary.LittleEndian.Uint16(type2Message[42:44])
+ targetInformationDataOffset := binary.LittleEndian.Uint32(type2Message[44:48])
+ endOfOffset = int(targetInformationDataOffset + uint32(targetInformationAllocated))
+ if type2MessageLength < endOfOffset {
+ return nil, fmt.Errorf(type2MessageError, type2MessageLength, endOfOffset)
+ }
+
+ targetInformationBytes := make([]byte, targetInformationAllocated)
+ copy(targetInformationBytes, type2Message[targetInformationDataOffset:targetInformationDataOffset+uint32(targetInformationAllocated)])
+
+ return targetInformationBytes, nil
+}
+
+func buildNTLMResponsePayload(lm, nt []byte, flags uint32, domain, workstation, username string) ([]byte, error) {
lm_len := len(lm)
nt_len := len(nt)
-
- domain16 := utf16le(auth.Domain)
+ domain16 := utf16le(domain)
domain_len := len(domain16)
- user16 := utf16le(auth.UserName)
+ user16 := utf16le(username)
user_len := len(user16)
- workstation16 := utf16le(auth.Workstation)
+ workstation16 := utf16le(workstation)
workstation_len := len(workstation16)
-
msg := make([]byte, 88+lm_len+nt_len+domain_len+user_len+workstation_len)
copy(msg, []byte("NTLMSSP\x00"))
binary.LittleEndian.PutUint32(msg[8:], _AUTHENTICATE_MESSAGE)
+
// Lm Challenge Response Fields
binary.LittleEndian.PutUint16(msg[12:], uint16(lm_len))
binary.LittleEndian.PutUint16(msg[14:], uint16(lm_len))
binary.LittleEndian.PutUint32(msg[16:], 88)
+
// Nt Challenge Response Fields
binary.LittleEndian.PutUint16(msg[20:], uint16(nt_len))
binary.LittleEndian.PutUint16(msg[22:], uint16(nt_len))
binary.LittleEndian.PutUint32(msg[24:], uint32(88+lm_len))
+
// Domain Name Fields
binary.LittleEndian.PutUint16(msg[28:], uint16(domain_len))
binary.LittleEndian.PutUint16(msg[30:], uint16(domain_len))
binary.LittleEndian.PutUint32(msg[32:], uint32(88+lm_len+nt_len))
+
// User Name Fields
binary.LittleEndian.PutUint16(msg[36:], uint16(user_len))
binary.LittleEndian.PutUint16(msg[38:], uint16(user_len))
binary.LittleEndian.PutUint32(msg[40:], uint32(88+lm_len+nt_len+domain_len))
+
// Workstation Fields
binary.LittleEndian.PutUint16(msg[44:], uint16(workstation_len))
binary.LittleEndian.PutUint16(msg[46:], uint16(workstation_len))
binary.LittleEndian.PutUint32(msg[48:], uint32(88+lm_len+nt_len+domain_len+user_len))
+
// Encrypted Random Session Key Fields
binary.LittleEndian.PutUint16(msg[52:], 0)
binary.LittleEndian.PutUint16(msg[54:], 0)
binary.LittleEndian.PutUint32(msg[56:], uint32(88+lm_len+nt_len+domain_len+user_len+workstation_len))
+
// Negotiate Flags
binary.LittleEndian.PutUint32(msg[60:], flags)
+
// Version
binary.LittleEndian.PutUint32(msg[64:], 0)
binary.LittleEndian.PutUint32(msg[68:], 0)
+
// MIC
binary.LittleEndian.PutUint32(msg[72:], 0)
binary.LittleEndian.PutUint32(msg[76:], 0)
binary.LittleEndian.PutUint32(msg[88:], 0)
binary.LittleEndian.PutUint32(msg[84:], 0)
+
// Payload
copy(msg[88:], lm)
copy(msg[88+lm_len:], nt)
copy(msg[88+lm_len+nt_len:], domain16)
copy(msg[88+lm_len+nt_len+domain_len:], user16)
copy(msg[88+lm_len+nt_len+domain_len+user_len:], workstation16)
+
return msg, nil
}
+func (auth *ntlmAuth) NextBytes(bytes []byte) ([]byte, error) {
+ signature := string(bytes[0:8])
+ if signature != "NTLMSSP\x00" {
+ return nil, errorNTLM
+ }
+
+ messageTypeIndicator := binary.LittleEndian.Uint32(bytes[8:12])
+ if messageTypeIndicator != _CHALLENGE_MESSAGE {
+ return nil, errorNTLM
+ }
+
+ var challenge [8]byte
+ copy(challenge[:], bytes[24:32])
+ flags := binary.LittleEndian.Uint32(bytes[20:24])
+ if (flags & _NEGOTIATE_EXTENDED_SESSIONSECURITY) != 0 {
+ lm, nt, err := negotiateExtendedSessionSecurity(flags, bytes, challenge, auth.UserName, auth.Password, auth.Domain)
+ if err != nil {
+ return nil, err
+ }
+
+ return buildNTLMResponsePayload(lm, nt, flags, auth.Domain, auth.Workstation, auth.UserName)
+ }
+
+ lm_bytes := lmResponse(challenge, auth.Password)
+ lm := lm_bytes[:]
+ nt_bytes := ntResponse(challenge, auth.Password)
+ nt := nt_bytes[:]
+
+ return buildNTLMResponsePayload(lm, nt, flags, auth.Domain, auth.Workstation, auth.UserName)
+}
+
func (auth *ntlmAuth) Free() {
}
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
}
diff --git a/vendor/github.com/denisenkom/go-mssqldb/token.go b/vendor/github.com/denisenkom/go-mssqldb/token.go
index 1acac8a5d2..25385e89dc 100644
--- a/vendor/github.com/denisenkom/go-mssqldb/token.go
+++ b/vendor/github.com/denisenkom/go-mssqldb/token.go
@@ -17,20 +17,21 @@ type token byte
// token ids
const (
- tokenReturnStatus token = 121 // 0x79
- tokenColMetadata token = 129 // 0x81
- tokenOrder token = 169 // 0xA9
- tokenError token = 170 // 0xAA
- tokenInfo token = 171 // 0xAB
- tokenReturnValue token = 0xAC
- tokenLoginAck token = 173 // 0xad
- tokenRow token = 209 // 0xd1
- tokenNbcRow token = 210 // 0xd2
- tokenEnvChange token = 227 // 0xE3
- tokenSSPI token = 237 // 0xED
- tokenDone token = 253 // 0xFD
- tokenDoneProc token = 254
- tokenDoneInProc token = 255
+ tokenReturnStatus token = 121 // 0x79
+ tokenColMetadata token = 129 // 0x81
+ tokenOrder token = 169 // 0xA9
+ tokenError token = 170 // 0xAA
+ tokenInfo token = 171 // 0xAB
+ tokenReturnValue token = 0xAC
+ tokenLoginAck token = 173 // 0xad
+ tokenFeatureExtAck token = 174 // 0xae
+ tokenRow token = 209 // 0xd1
+ tokenNbcRow token = 210 // 0xd2
+ tokenEnvChange token = 227 // 0xE3
+ tokenSSPI token = 237 // 0xED
+ tokenDone token = 253 // 0xFD
+ tokenDoneProc token = 254
+ tokenDoneInProc token = 255
)
// done flags
@@ -447,6 +448,22 @@ func parseLoginAck(r *tdsBuffer) loginAckStruct {
return res
}
+// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/2eb82f8e-11f0-46dc-b42d-27302fa4701a
+func parseFeatureExtAck(r *tdsBuffer) {
+ // at most 1 featureAck per feature in featureExt
+ // go-mssqldb will add at most 1 feature, the spec defines 7 different features
+ for i := 0; i < 8; i++ {
+ featureID := r.byte() // FeatureID
+ if featureID == 0xff {
+ return
+ }
+ size := r.uint32() // FeatureAckDataLen
+ d := make([]byte, size)
+ r.ReadFull(d)
+ }
+ panic("parsed more than 7 featureAck's, protocol implementation error?")
+}
+
// http://msdn.microsoft.com/en-us/library/dd357363.aspx
func parseColMetadata72(r *tdsBuffer) (columns []columnStruct) {
count := r.uint16()
@@ -577,6 +594,8 @@ func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[strin
case tokenLoginAck:
loginAck := parseLoginAck(sess.buf)
ch <- loginAck
+ case tokenFeatureExtAck:
+ parseFeatureExtAck(sess.buf)
case tokenOrder:
order := parseOrder(sess.buf)
ch <- order
table30'>backport/49454/stable30 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
summaryrefslogtreecommitdiffstats
path: root/apps/files/l10n/de_DE.json
blob: a6af138bed1fed01e11392fdf3debb14d7e4ec4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{ "translations": {
    "Storage not available" : "Speicher nicht verfügbar",
    "Storage invalid" : "Speicher ungültig",
    "Unknown error" : "Unbekannter Fehler",
    "Could not move %s - File with this name already exists" : "%s konnte nicht verschoben werden. Eine Datei mit diesem Namen existiert bereits.",
    "Could not move %s" : "Konnte %s nicht verschieben",
    "Permission denied" : "Zugriff verweigert",
    "File name cannot be empty." : "Der Dateiname darf nicht leer sein.",
    "\"%s\" is an invalid file name." : "\"%s\" ist kein gültiger Dateiname.",
    "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." : "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.",
    "The target folder has been moved or deleted." : "Der Ziel-Ordner wurde verschoben oder gelöscht.",
    "The name %s is already used in the folder %s. Please choose a different name." : "Der Name %s wird bereits im Ordner %s benutzt. Bitte wählen Sie einen anderen Namen.",
    "Not a valid source" : "Keine gültige Quelle",
    "Server is not allowed to open URLs, please check the server configuration" : "Dem Server ist das Öffnen von URLs nicht erlaubt, bitte die Serverkonfiguration prüfen",
    "The file exceeds your quota by %s" : "Die Datei überschreitet Ihr Limit um %s",
    "Error while downloading %s to %s" : "Fehler beim Herunterladen von %s nach %s",
    "Error when creating the file" : "Fehler beim Erstellen der Datei",
    "Folder name cannot be empty." : "Der Ordner-Name darf nicht leer sein.",
    "Error when creating the folder" : "Fehler beim Erstellen des Ordners",
    "Unable to set upload directory." : "Das Upload-Verzeichnis konnte nicht gesetzt werden.",
    "Invalid Token" : "Ungültiges Merkmal",
    "No file was uploaded. Unknown error" : "Keine Datei hochgeladen. Unbekannter Fehler",
    "There is no error, the file uploaded with success" : "Es ist kein Fehler aufgetreten. Die Datei wurde erfolgreich hochgeladen.",
    "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Die hochgeladene Datei überschreitet die upload_max_filesize Vorgabe in php.ini",
    "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Die Datei ist größer, als die MAX_FILE_SIZE Vorgabe erlaubt, die im HTML-Formular spezifiziert ist",
    "The uploaded file was only partially uploaded" : "Die Datei konnte nur teilweise übertragen werden",
    "No file was uploaded" : "Keine Datei konnte übertragen werden.",
    "Missing a temporary folder" : "Kein temporärer Ordner vorhanden",
    "Failed to write to disk" : "Fehler beim Schreiben auf die Festplatte",
    "Not enough storage available" : "Nicht genug Speicher vorhanden.",
    "Upload failed. Could not find uploaded file" : "Hochladen fehlgeschlagen. Die hochgeladene Datei konnte nicht gefunden werden.",
    "Upload failed. Could not get file info." : "Hochladen fehlgeschlagen. Die Dateiinformationen konnten nicht abgerufen werden.",
    "Invalid directory." : "Ungültiges Verzeichnis.",
    "Files" : "Dateien",
    "All files" : "Alle Dateien",
    "Favorites" : "Favoriten",
    "Home" : "Zuhause",
    "Unable to upload {filename} as it is a directory or has 0 bytes" : "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist",
    "Total file size {size1} exceeds upload limit {size2}" : "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}",
    "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nicht genügend freier Speicherplatz, Sie möchten {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.",
    "Upload cancelled." : "Upload abgebrochen.",
    "Could not get result from server." : "Ergebnis konnte nicht vom Server abgerufen werden.",
    "File upload is in progress. Leaving the page now will cancel the upload." : "Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.",
    "URL cannot be empty" : "Die URL darf nicht leer sein",
    "{new_name} already exists" : "{new_name} existiert bereits",
    "Could not create file" : "Die Datei konnte nicht erstellt werden",
    "Could not create folder" : "Der Ordner konnte nicht erstellt werden",
    "Error fetching URL" : "Fehler beim Abrufen der URL",
    "Rename" : "Umbenennen",
    "Delete" : "Löschen",
    "Disconnect storage" : "Speicher trennen",
    "Unshare" : "Freigabe aufheben",
    "Select" : "Auswählen",
    "Pending" : "Ausstehend",
    "Unable to determine date" : "Datum konnte nicht ermittelt werden",
    "Error moving file." : "Fehler beim Verschieben der Datei.",
    "Error moving file" : "Fehler beim Verschieben der Datei",
    "Error" : "Fehler",
    "Could not rename file" : "Die Datei konnte nicht umbenannt werden",
    "Error deleting file." : "Fehler beim Löschen der Datei.",
    "Name" : "Name",
    "Size" : "Größe",
    "Modified" : "Geändert",
    "_%n folder_::_%n folders_" : ["%n Ordner","%n Ordner"],
    "_%n file_::_%n files_" : ["%n Datei","%n Dateien"],
    "You don’t have permission to upload or create files here" : "Sie besitzen hier keine Berechtigung Dateien hochzuladen oder zu erstellen",
    "_Uploading %n file_::_Uploading %n files_" : ["%n Datei wird hoch geladen","%n Dateien werden hoch geladen"],
    "\"{name}\" is an invalid file name." : "»{name}« ist kein gültiger Dateiname.",
    "Your storage is full, files can not be updated or synced anymore!" : "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!",
    "Your storage is almost full ({usedSpacePercent}%)" : "Ihr Speicher ist fast voll ({usedSpacePercent}%)",
    "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Verschlüsselungs-App ist aktiviert, aber Ihre Schlüssel sind nicht initialisiert. Bitte melden Sie sich nochmals ab und wieder an.",
    "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Ungültiger privater Schlüssel für die Verschlüsselungs-App. Bitte aktualisieren Sie Ihr privates Schlüsselpasswort, um den Zugriff auf Ihre verschlüsselten Dateien wiederherzustellen.",
    "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." : "Die Verschlüsselung wurde deaktiviert, jedoch sind Ihre Dateien nach wie vor verschlüsselt. Bitte gehen Sie zu Ihren persönlichen Einstellungen, um Ihre Dateien zu entschlüsseln.",
    "_ matches '{filter}'_::_ match '{filter}'_" : ["",""],
    "{dirs} and {files}" : "{dirs} und {files}",
    "Favorited" : "Favorisiert",
    "Favorite" : "Favorit",
    "%s could not be renamed as it has been deleted" : "%s konnte nicht umbenannt werden, da es gelöscht wurde",
    "%s could not be renamed" : "%s konnte nicht umbenannt werden",
    "Upload (max. %s)" : "Hochladen (max. %s)",
    "File handling" : "Dateibehandlung",
    "Maximum upload size" : "Maximale Upload-Größe",
    "max. possible: " : "maximal möglich:",
    "Save" : "Speichern",
    "Settings" : "Einstellungen",
    "WebDAV" : "WebDAV",
    "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Diese Adresse benutzen, um <a href=\"%s\" target=\"_blank\">über WebDAV auf Ihre Dateien zuzugreifen</a>",
    "New" : "Neu",
    "New text file" : "Neue Textdatei",
    "Text file" : "Textdatei",
    "New folder" : "Neuer Ordner",
    "Folder" : "Ordner",
    "From link" : "Von einem Link",
    "Upload" : "Hochladen",
    "Cancel upload" : "Upload abbrechen",
    "No files yet" : "Noch keine Dateien",
    "Upload some content or sync with your devices!" : "Laden Sie Inhalte hoch oder synchronisieren Sie mit Ihren Geräten!",
    "Select all" : "Alle auswählen",
    "Download" : "Herunterladen",
    "Upload too large" : "Der Upload ist zu groß",
    "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server.",
    "Files are being scanned, please wait." : "Dateien werden gescannt, bitte warten.",
    "Currently scanning" : "Durchsuchen läuft",
    "No favorites" : "Keine Favoriten",
    "Files and folders you mark as favorite will show up here" : "Dateien und Ordner, die Sie als Favoriten kennzeichnen, werden hier erscheinen"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}