mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	[Vendor] Update go-ldap to v3.2.4 (#13163)
* [Vendor] update go-ldap to v3.0.3 * update go-ldap to v3.2.4 Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
		
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							@@ -39,6 +39,7 @@ require (
 | 
			
		||||
	github.com/go-enry/go-enry/v2 v2.5.2
 | 
			
		||||
	github.com/go-git/go-billy/v5 v5.0.0
 | 
			
		||||
	github.com/go-git/go-git/v5 v5.1.0
 | 
			
		||||
	github.com/go-ldap/ldap/v3 v3.2.4
 | 
			
		||||
	github.com/go-redis/redis/v7 v7.4.0
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.5.0
 | 
			
		||||
	github.com/go-swagger/go-swagger v0.25.0
 | 
			
		||||
@@ -112,10 +113,8 @@ require (
 | 
			
		||||
	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
 | 
			
		||||
	golang.org/x/tools v0.0.0-20200921210052-fa0125251cc4
 | 
			
		||||
	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 | 
			
		||||
	gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
 | 
			
		||||
	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 | 
			
		||||
	gopkg.in/ini.v1 v1.61.0
 | 
			
		||||
	gopkg.in/ldap.v3 v3.0.2
 | 
			
		||||
	gopkg.in/yaml.v2 v2.3.0
 | 
			
		||||
	mvdan.cc/xurls/v2 v2.1.0
 | 
			
		||||
	strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								go.sum
									
									
									
									
									
								
							@@ -50,6 +50,8 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGq
 | 
			
		||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
 | 
			
		||||
github.com/6543/go-version v1.2.3 h1:uF30BawMhoQLzqBeCwhFcWM6HVxlzMHe/zXbzJeKP+o=
 | 
			
		||||
github.com/6543/go-version v1.2.3/go.mod h1:fcfWh4zkneEgGXe8JJptiGwp8l6JgJJgS7oTw6P83So=
 | 
			
		||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
 | 
			
		||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
 | 
			
		||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
			
		||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
			
		||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 | 
			
		||||
@@ -242,6 +244,8 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqo
 | 
			
		||||
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
 | 
			
		||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
 | 
			
		||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
 | 
			
		||||
github.com/go-enry/go-enry/v2 v2.5.2 h1:3f3PFAO6JitWkPi1GQ5/m6Xu4gNL1U5soJ8QaYqJ0YQ=
 | 
			
		||||
github.com/go-enry/go-enry/v2 v2.5.2/go.mod h1:GVzIiAytiS5uT/QiuakK7TF1u4xDab87Y8V5EJRpsIQ=
 | 
			
		||||
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
 | 
			
		||||
@@ -256,6 +260,8 @@ github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEss
 | 
			
		||||
github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
 | 
			
		||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 | 
			
		||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 | 
			
		||||
github.com/go-ldap/ldap/v3 v3.2.4 h1:PFavAq2xTgzo/loE8qNXcQaofAaqIpI4WgaLdv+1l3E=
 | 
			
		||||
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
 | 
			
		||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 | 
			
		||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 | 
			
		||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
 | 
			
		||||
@@ -934,6 +940,7 @@ golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8U
 | 
			
		||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
 | 
			
		||||
@@ -1148,8 +1155,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 | 
			
		||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
			
		||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
 | 
			
		||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
 | 
			
		||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 h1:nn6Zav2sOQHCFJHEspya8KqxhFwKci30UxHy3HXPTyQ=
 | 
			
		||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
@@ -1170,8 +1175,6 @@ gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/ini.v1 v1.60.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10=
 | 
			
		||||
gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w=
 | 
			
		||||
gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
 | 
			
		||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 | 
			
		||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/ldap.v3"
 | 
			
		||||
	"github.com/go-ldap/ldap/v3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SecurityProtocol protocol type
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/Azure/go-ntlmssp/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/Azure/go-ntlmssp/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
sudo: false
 | 
			
		||||
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
  - go get -u golang.org/x/lint/golint
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
  - 1.10.x
 | 
			
		||||
  - master
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - test -z "$(gofmt -s -l . | tee /dev/stderr)"
 | 
			
		||||
  - test -z "$(golint ./... |  tee /dev/stderr)"
 | 
			
		||||
  - go vet ./...
 | 
			
		||||
  - go build -v ./...
 | 
			
		||||
  - go test -v ./...
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/Azure/go-ntlmssp/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/Azure/go-ntlmssp/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2016 Microsoft
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/Azure/go-ntlmssp/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/Azure/go-ntlmssp/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
# go-ntlmssp
 | 
			
		||||
Golang package that provides NTLM/Negotiate authentication over HTTP
 | 
			
		||||
 | 
			
		||||
[](https://godoc.org/github.com/Azure/go-ntlmssp) [](https://travis-ci.org/Azure/go-ntlmssp)
 | 
			
		||||
 | 
			
		||||
Protocol details from https://msdn.microsoft.com/en-us/library/cc236621.aspx
 | 
			
		||||
Implementation hints from http://davenport.sourceforge.net/ntlm.html
 | 
			
		||||
 | 
			
		||||
This package only implements authentication, no key exchange or encryption. It
 | 
			
		||||
only supports Unicode (UTF16LE) encoding of protocol strings, no OEM encoding.
 | 
			
		||||
This package implements NTLMv2.
 | 
			
		||||
 | 
			
		||||
# Usage
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
url, user, password := "http://www.example.com/secrets", "robpike", "pw123"
 | 
			
		||||
client := &http.Client{
 | 
			
		||||
  Transport: ntlmssp.Negotiator{
 | 
			
		||||
    RoundTripper:&http.Transport{},
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
req, _ := http.NewRequest("GET", url, nil)
 | 
			
		||||
req.SetBasicAuth(user, password)
 | 
			
		||||
res, _ := client.Do(req)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
-----
 | 
			
		||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
 | 
			
		||||
							
								
								
									
										183
									
								
								vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type authenicateMessage struct {
 | 
			
		||||
	LmChallengeResponse []byte
 | 
			
		||||
	NtChallengeResponse []byte
 | 
			
		||||
 | 
			
		||||
	TargetName string
 | 
			
		||||
	UserName   string
 | 
			
		||||
 | 
			
		||||
	// only set if negotiateFlag_NTLMSSP_NEGOTIATE_KEY_EXCH
 | 
			
		||||
	EncryptedRandomSessionKey []byte
 | 
			
		||||
 | 
			
		||||
	NegotiateFlags negotiateFlags
 | 
			
		||||
 | 
			
		||||
	MIC []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type authenticateMessageFields struct {
 | 
			
		||||
	messageHeader
 | 
			
		||||
	LmChallengeResponse varField
 | 
			
		||||
	NtChallengeResponse varField
 | 
			
		||||
	TargetName          varField
 | 
			
		||||
	UserName            varField
 | 
			
		||||
	Workstation         varField
 | 
			
		||||
	_                   [8]byte
 | 
			
		||||
	NegotiateFlags      negotiateFlags
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m authenicateMessage) MarshalBinary() ([]byte, error) {
 | 
			
		||||
	if !m.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEUNICODE) {
 | 
			
		||||
		return nil, errors.New("Only unicode is supported")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	target, user := toUnicode(m.TargetName), toUnicode(m.UserName)
 | 
			
		||||
	workstation := toUnicode("go-ntlmssp")
 | 
			
		||||
 | 
			
		||||
	ptr := binary.Size(&authenticateMessageFields{})
 | 
			
		||||
	f := authenticateMessageFields{
 | 
			
		||||
		messageHeader:       newMessageHeader(3),
 | 
			
		||||
		NegotiateFlags:      m.NegotiateFlags,
 | 
			
		||||
		LmChallengeResponse: newVarField(&ptr, len(m.LmChallengeResponse)),
 | 
			
		||||
		NtChallengeResponse: newVarField(&ptr, len(m.NtChallengeResponse)),
 | 
			
		||||
		TargetName:          newVarField(&ptr, len(target)),
 | 
			
		||||
		UserName:            newVarField(&ptr, len(user)),
 | 
			
		||||
		Workstation:         newVarField(&ptr, len(workstation)),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f.NegotiateFlags.Unset(negotiateFlagNTLMSSPNEGOTIATEVERSION)
 | 
			
		||||
 | 
			
		||||
	b := bytes.Buffer{}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &f); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &m.LmChallengeResponse); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &m.NtChallengeResponse); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &target); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &workstation); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b.Bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//ProcessChallenge crafts an AUTHENTICATE message in response to the CHALLENGE message
 | 
			
		||||
//that was received from the server
 | 
			
		||||
func ProcessChallenge(challengeMessageData []byte, user, password string) ([]byte, error) {
 | 
			
		||||
	if user == "" && password == "" {
 | 
			
		||||
		return nil, errors.New("Anonymous authentication not supported")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cm challengeMessage
 | 
			
		||||
	if err := cm.UnmarshalBinary(challengeMessageData); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATELMKEY) {
 | 
			
		||||
		return nil, errors.New("Only NTLM v2 is supported, but server requested v1 (NTLMSSP_NEGOTIATE_LM_KEY)")
 | 
			
		||||
	}
 | 
			
		||||
	if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEKEYEXCH) {
 | 
			
		||||
		return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	am := authenicateMessage{
 | 
			
		||||
		UserName:       user,
 | 
			
		||||
		TargetName:     cm.TargetName,
 | 
			
		||||
		NegotiateFlags: cm.NegotiateFlags,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	timestamp := cm.TargetInfo[avIDMsvAvTimestamp]
 | 
			
		||||
	if timestamp == nil { // no time sent, take current time
 | 
			
		||||
		ft := uint64(time.Now().UnixNano()) / 100
 | 
			
		||||
		ft += 116444736000000000 // add time between unix & windows offset
 | 
			
		||||
		timestamp = make([]byte, 8)
 | 
			
		||||
		binary.LittleEndian.PutUint64(timestamp, ft)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clientChallenge := make([]byte, 8)
 | 
			
		||||
	rand.Reader.Read(clientChallenge)
 | 
			
		||||
 | 
			
		||||
	ntlmV2Hash := getNtlmV2Hash(password, user, cm.TargetName)
 | 
			
		||||
 | 
			
		||||
	am.NtChallengeResponse = computeNtlmV2Response(ntlmV2Hash,
 | 
			
		||||
		cm.ServerChallenge[:], clientChallenge, timestamp, cm.TargetInfoRaw)
 | 
			
		||||
 | 
			
		||||
	if cm.TargetInfoRaw == nil {
 | 
			
		||||
		am.LmChallengeResponse = computeLmV2Response(ntlmV2Hash,
 | 
			
		||||
			cm.ServerChallenge[:], clientChallenge)
 | 
			
		||||
	}
 | 
			
		||||
	return am.MarshalBinary()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ProcessChallengeWithHash(challengeMessageData []byte, user, hash string) ([]byte, error) {
 | 
			
		||||
	if user == "" && hash == "" {
 | 
			
		||||
		return nil, errors.New("Anonymous authentication not supported")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cm challengeMessage
 | 
			
		||||
	if err := cm.UnmarshalBinary(challengeMessageData); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATELMKEY) {
 | 
			
		||||
		return nil, errors.New("Only NTLM v2 is supported, but server requested v1 (NTLMSSP_NEGOTIATE_LM_KEY)")
 | 
			
		||||
	}
 | 
			
		||||
	if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEKEYEXCH) {
 | 
			
		||||
		return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	am := authenicateMessage{
 | 
			
		||||
		UserName:       user,
 | 
			
		||||
		TargetName:     cm.TargetName,
 | 
			
		||||
		NegotiateFlags: cm.NegotiateFlags,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	timestamp := cm.TargetInfo[avIDMsvAvTimestamp]
 | 
			
		||||
	if timestamp == nil { // no time sent, take current time
 | 
			
		||||
		ft := uint64(time.Now().UnixNano()) / 100
 | 
			
		||||
		ft += 116444736000000000 // add time between unix & windows offset
 | 
			
		||||
		timestamp = make([]byte, 8)
 | 
			
		||||
		binary.LittleEndian.PutUint64(timestamp, ft)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clientChallenge := make([]byte, 8)
 | 
			
		||||
	rand.Reader.Read(clientChallenge)
 | 
			
		||||
 | 
			
		||||
	hashParts := strings.Split(hash, ":")
 | 
			
		||||
	if len(hashParts) > 1 {
 | 
			
		||||
		hash = hashParts[1]
 | 
			
		||||
	}
 | 
			
		||||
	hashBytes, err := hex.DecodeString(hash)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ntlmV2Hash := hmacMd5(hashBytes, toUnicode(strings.ToUpper(user)+cm.TargetName))
 | 
			
		||||
 | 
			
		||||
	am.NtChallengeResponse = computeNtlmV2Response(ntlmV2Hash,
 | 
			
		||||
		cm.ServerChallenge[:], clientChallenge, timestamp, cm.TargetInfoRaw)
 | 
			
		||||
 | 
			
		||||
	if cm.TargetInfoRaw == nil {
 | 
			
		||||
		am.LmChallengeResponse = computeLmV2Response(ntlmV2Hash,
 | 
			
		||||
			cm.ServerChallenge[:], clientChallenge)
 | 
			
		||||
	}
 | 
			
		||||
	return am.MarshalBinary()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/Azure/go-ntlmssp/authheader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/Azure/go-ntlmssp/authheader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type authheader string
 | 
			
		||||
 | 
			
		||||
func (h authheader) IsBasic() bool {
 | 
			
		||||
	return strings.HasPrefix(string(h), "Basic ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h authheader) IsNegotiate() bool {
 | 
			
		||||
	return strings.HasPrefix(string(h), "Negotiate")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h authheader) IsNTLM() bool {
 | 
			
		||||
	return strings.HasPrefix(string(h), "NTLM")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h authheader) GetData() ([]byte, error) {
 | 
			
		||||
	p := strings.Split(string(h), " ")
 | 
			
		||||
	if len(p) < 2 {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return base64.StdEncoding.DecodeString(string(p[1]))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h authheader) GetBasicCreds() (username, password string, err error) {
 | 
			
		||||
	d, err := h.GetData()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", "", err
 | 
			
		||||
	}
 | 
			
		||||
	parts := strings.SplitN(string(d), ":", 2)
 | 
			
		||||
	return parts[0], parts[1], nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/Azure/go-ntlmssp/avids.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/Azure/go-ntlmssp/avids.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
type avID uint16
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	avIDMsvAvEOL avID = iota
 | 
			
		||||
	avIDMsvAvNbComputerName
 | 
			
		||||
	avIDMsvAvNbDomainName
 | 
			
		||||
	avIDMsvAvDNSComputerName
 | 
			
		||||
	avIDMsvAvDNSDomainName
 | 
			
		||||
	avIDMsvAvDNSTreeName
 | 
			
		||||
	avIDMsvAvFlags
 | 
			
		||||
	avIDMsvAvTimestamp
 | 
			
		||||
	avIDMsvAvSingleHost
 | 
			
		||||
	avIDMsvAvTargetName
 | 
			
		||||
	avIDMsvChannelBindings
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										82
									
								
								vendor/github.com/Azure/go-ntlmssp/challenge_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/github.com/Azure/go-ntlmssp/challenge_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type challengeMessageFields struct {
 | 
			
		||||
	messageHeader
 | 
			
		||||
	TargetName      varField
 | 
			
		||||
	NegotiateFlags  negotiateFlags
 | 
			
		||||
	ServerChallenge [8]byte
 | 
			
		||||
	_               [8]byte
 | 
			
		||||
	TargetInfo      varField
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m challengeMessageFields) IsValid() bool {
 | 
			
		||||
	return m.messageHeader.IsValid() && m.MessageType == 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type challengeMessage struct {
 | 
			
		||||
	challengeMessageFields
 | 
			
		||||
	TargetName    string
 | 
			
		||||
	TargetInfo    map[avID][]byte
 | 
			
		||||
	TargetInfoRaw []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *challengeMessage) UnmarshalBinary(data []byte) error {
 | 
			
		||||
	r := bytes.NewReader(data)
 | 
			
		||||
	err := binary.Read(r, binary.LittleEndian, &m.challengeMessageFields)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !m.challengeMessageFields.IsValid() {
 | 
			
		||||
		return fmt.Errorf("Message is not a valid challenge message: %+v", m.challengeMessageFields.messageHeader)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if m.challengeMessageFields.TargetName.Len > 0 {
 | 
			
		||||
		m.TargetName, err = m.challengeMessageFields.TargetName.ReadStringFrom(data, m.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEUNICODE))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if m.challengeMessageFields.TargetInfo.Len > 0 {
 | 
			
		||||
		d, err := m.challengeMessageFields.TargetInfo.ReadFrom(data)
 | 
			
		||||
		m.TargetInfoRaw = d
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		m.TargetInfo = make(map[avID][]byte)
 | 
			
		||||
		r := bytes.NewReader(d)
 | 
			
		||||
		for {
 | 
			
		||||
			var id avID
 | 
			
		||||
			var l uint16
 | 
			
		||||
			err = binary.Read(r, binary.LittleEndian, &id)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if id == avIDMsvAvEOL {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = binary.Read(r, binary.LittleEndian, &l)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			value := make([]byte, l)
 | 
			
		||||
			n, err := r.Read(value)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if n != int(l) {
 | 
			
		||||
				return fmt.Errorf("Expected to read %d bytes, got only %d", l, n)
 | 
			
		||||
			}
 | 
			
		||||
			m.TargetInfo[id] = value
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/Azure/go-ntlmssp/messageheader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/Azure/go-ntlmssp/messageheader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var signature = [8]byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0}
 | 
			
		||||
 | 
			
		||||
type messageHeader struct {
 | 
			
		||||
	Signature   [8]byte
 | 
			
		||||
	MessageType uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h messageHeader) IsValid() bool {
 | 
			
		||||
	return bytes.Equal(h.Signature[:], signature[:]) &&
 | 
			
		||||
		h.MessageType > 0 && h.MessageType < 4
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMessageHeader(messageType uint32) messageHeader {
 | 
			
		||||
	return messageHeader{signature, messageType}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiate_flags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiate_flags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
type negotiateFlags uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	/*A*/ negotiateFlagNTLMSSPNEGOTIATEUNICODE negotiateFlags = 1 << 0
 | 
			
		||||
	/*B*/ negotiateFlagNTLMNEGOTIATEOEM = 1 << 1
 | 
			
		||||
	/*C*/ negotiateFlagNTLMSSPREQUESTTARGET = 1 << 2
 | 
			
		||||
 | 
			
		||||
	/*D*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATESIGN = 1 << 4
 | 
			
		||||
	/*E*/ negotiateFlagNTLMSSPNEGOTIATESEAL = 1 << 5
 | 
			
		||||
	/*F*/ negotiateFlagNTLMSSPNEGOTIATEDATAGRAM = 1 << 6
 | 
			
		||||
	/*G*/ negotiateFlagNTLMSSPNEGOTIATELMKEY = 1 << 7
 | 
			
		||||
 | 
			
		||||
	/*H*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATENTLM = 1 << 9
 | 
			
		||||
 | 
			
		||||
	/*J*/
 | 
			
		||||
	negotiateFlagANONYMOUS = 1 << 11
 | 
			
		||||
	/*K*/ negotiateFlagNTLMSSPNEGOTIATEOEMDOMAINSUPPLIED = 1 << 12
 | 
			
		||||
	/*L*/ negotiateFlagNTLMSSPNEGOTIATEOEMWORKSTATIONSUPPLIED = 1 << 13
 | 
			
		||||
 | 
			
		||||
	/*M*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATEALWAYSSIGN = 1 << 15
 | 
			
		||||
	/*N*/ negotiateFlagNTLMSSPTARGETTYPEDOMAIN = 1 << 16
 | 
			
		||||
	/*O*/ negotiateFlagNTLMSSPTARGETTYPESERVER = 1 << 17
 | 
			
		||||
 | 
			
		||||
	/*P*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATEEXTENDEDSESSIONSECURITY = 1 << 19
 | 
			
		||||
	/*Q*/ negotiateFlagNTLMSSPNEGOTIATEIDENTIFY = 1 << 20
 | 
			
		||||
 | 
			
		||||
	/*R*/
 | 
			
		||||
	negotiateFlagNTLMSSPREQUESTNONNTSESSIONKEY = 1 << 22
 | 
			
		||||
	/*S*/ negotiateFlagNTLMSSPNEGOTIATETARGETINFO = 1 << 23
 | 
			
		||||
 | 
			
		||||
	/*T*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATEVERSION = 1 << 25
 | 
			
		||||
 | 
			
		||||
	/*U*/
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATE128 = 1 << 29
 | 
			
		||||
	/*V*/ negotiateFlagNTLMSSPNEGOTIATEKEYEXCH = 1 << 30
 | 
			
		||||
	/*W*/ negotiateFlagNTLMSSPNEGOTIATE56 = 1 << 31
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (field negotiateFlags) Has(flags negotiateFlags) bool {
 | 
			
		||||
	return field&flags == flags
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (field *negotiateFlags) Unset(flags negotiateFlags) {
 | 
			
		||||
	*field = *field ^ (*field & flags)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiate_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiate_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const expMsgBodyLen = 40
 | 
			
		||||
 | 
			
		||||
type negotiateMessageFields struct {
 | 
			
		||||
	messageHeader
 | 
			
		||||
	NegotiateFlags negotiateFlags
 | 
			
		||||
 | 
			
		||||
	Domain      varField
 | 
			
		||||
	Workstation varField
 | 
			
		||||
 | 
			
		||||
	Version
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var defaultFlags = negotiateFlagNTLMSSPNEGOTIATETARGETINFO |
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATE56 |
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATE128 |
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATEUNICODE |
 | 
			
		||||
	negotiateFlagNTLMSSPNEGOTIATEEXTENDEDSESSIONSECURITY
 | 
			
		||||
 | 
			
		||||
//NewNegotiateMessage creates a new NEGOTIATE message with the
 | 
			
		||||
//flags that this package supports.
 | 
			
		||||
func NewNegotiateMessage(domainName, workstationName string) ([]byte, error) {
 | 
			
		||||
	payloadOffset := expMsgBodyLen
 | 
			
		||||
	flags := defaultFlags
 | 
			
		||||
 | 
			
		||||
	if domainName != "" {
 | 
			
		||||
		flags |= negotiateFlagNTLMSSPNEGOTIATEOEMDOMAINSUPPLIED
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if workstationName != "" {
 | 
			
		||||
		flags |= negotiateFlagNTLMSSPNEGOTIATEOEMWORKSTATIONSUPPLIED
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msg := negotiateMessageFields{
 | 
			
		||||
		messageHeader:  newMessageHeader(1),
 | 
			
		||||
		NegotiateFlags: flags,
 | 
			
		||||
		Domain:         newVarField(&payloadOffset, len(domainName)),
 | 
			
		||||
		Workstation:    newVarField(&payloadOffset, len(workstationName)),
 | 
			
		||||
		Version:        DefaultVersion(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b := bytes.Buffer{}
 | 
			
		||||
	if err := binary.Write(&b, binary.LittleEndian, &msg); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if b.Len() != expMsgBodyLen {
 | 
			
		||||
		return nil, errors.New("incorrect body length")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	payload := strings.ToUpper(domainName + workstationName)
 | 
			
		||||
	if _, err := b.WriteString(payload); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b.Bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										144
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/Azure/go-ntlmssp/negotiator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetDomain : parse domain name from based on slashes in the input
 | 
			
		||||
func GetDomain(user string) (string, string) {
 | 
			
		||||
	domain := ""
 | 
			
		||||
 | 
			
		||||
	if strings.Contains(user, "\\") {
 | 
			
		||||
		ucomponents := strings.SplitN(user, "\\", 2)
 | 
			
		||||
		domain = ucomponents[0]
 | 
			
		||||
		user = ucomponents[1]
 | 
			
		||||
	}
 | 
			
		||||
	return user, domain
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Negotiator is a http.Roundtripper decorator that automatically
 | 
			
		||||
//converts basic authentication to NTLM/Negotiate authentication when appropriate.
 | 
			
		||||
type Negotiator struct{ http.RoundTripper }
 | 
			
		||||
 | 
			
		||||
//RoundTrip sends the request to the server, handling any authentication
 | 
			
		||||
//re-sends as needed.
 | 
			
		||||
func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) {
 | 
			
		||||
	// Use default round tripper if not provided
 | 
			
		||||
	rt := l.RoundTripper
 | 
			
		||||
	if rt == nil {
 | 
			
		||||
		rt = http.DefaultTransport
 | 
			
		||||
	}
 | 
			
		||||
	// If it is not basic auth, just round trip the request as usual
 | 
			
		||||
	reqauth := authheader(req.Header.Get("Authorization"))
 | 
			
		||||
	if !reqauth.IsBasic() {
 | 
			
		||||
		return rt.RoundTrip(req)
 | 
			
		||||
	}
 | 
			
		||||
	// Save request body
 | 
			
		||||
	body := bytes.Buffer{}
 | 
			
		||||
	if req.Body != nil {
 | 
			
		||||
		_, err = body.ReadFrom(req.Body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		req.Body.Close()
 | 
			
		||||
		req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
 | 
			
		||||
	}
 | 
			
		||||
	// first try anonymous, in case the server still finds us
 | 
			
		||||
	// authenticated from previous traffic
 | 
			
		||||
	req.Header.Del("Authorization")
 | 
			
		||||
	res, err = rt.RoundTrip(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode != http.StatusUnauthorized {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resauth := authheader(res.Header.Get("Www-Authenticate"))
 | 
			
		||||
	if !resauth.IsNegotiate() && !resauth.IsNTLM() {
 | 
			
		||||
		// Unauthorized, Negotiate not requested, let's try with basic auth
 | 
			
		||||
		req.Header.Set("Authorization", string(reqauth))
 | 
			
		||||
		io.Copy(ioutil.Discard, res.Body)
 | 
			
		||||
		res.Body.Close()
 | 
			
		||||
		req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
 | 
			
		||||
 | 
			
		||||
		res, err = rt.RoundTrip(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if res.StatusCode != http.StatusUnauthorized {
 | 
			
		||||
			return res, err
 | 
			
		||||
		}
 | 
			
		||||
		resauth = authheader(res.Header.Get("Www-Authenticate"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resauth.IsNegotiate() || resauth.IsNTLM() {
 | 
			
		||||
		// 401 with request:Basic and response:Negotiate
 | 
			
		||||
		io.Copy(ioutil.Discard, res.Body)
 | 
			
		||||
		res.Body.Close()
 | 
			
		||||
 | 
			
		||||
		// recycle credentials
 | 
			
		||||
		u, p, err := reqauth.GetBasicCreds()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// get domain from username
 | 
			
		||||
		domain := ""
 | 
			
		||||
		u, domain = GetDomain(u)
 | 
			
		||||
 | 
			
		||||
		// send negotiate
 | 
			
		||||
		negotiateMessage, err := NewNegotiateMessage(domain, "")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if resauth.IsNTLM() {
 | 
			
		||||
			req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(negotiateMessage))
 | 
			
		||||
		} else {
 | 
			
		||||
			req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
 | 
			
		||||
 | 
			
		||||
		res, err = rt.RoundTrip(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// receive challenge?
 | 
			
		||||
		resauth = authheader(res.Header.Get("Www-Authenticate"))
 | 
			
		||||
		challengeMessage, err := resauth.GetData()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if !(resauth.IsNegotiate() || resauth.IsNTLM()) || len(challengeMessage) == 0 {
 | 
			
		||||
			// Negotiation failed, let client deal with response
 | 
			
		||||
			return res, nil
 | 
			
		||||
		}
 | 
			
		||||
		io.Copy(ioutil.Discard, res.Body)
 | 
			
		||||
		res.Body.Close()
 | 
			
		||||
 | 
			
		||||
		// send authenticate
 | 
			
		||||
		authenticateMessage, err := ProcessChallenge(challengeMessage, u, p)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if resauth.IsNTLM() {
 | 
			
		||||
			req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(authenticateMessage))
 | 
			
		||||
		} else {
 | 
			
		||||
			req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(authenticateMessage))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
 | 
			
		||||
 | 
			
		||||
		return rt.RoundTrip(req)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/github.com/Azure/go-ntlmssp/nlmp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/Azure/go-ntlmssp/nlmp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
// Package ntlmssp provides NTLM/Negotiate authentication over HTTP
 | 
			
		||||
//
 | 
			
		||||
// Protocol details from https://msdn.microsoft.com/en-us/library/cc236621.aspx,
 | 
			
		||||
// implementation hints from http://davenport.sourceforge.net/ntlm.html .
 | 
			
		||||
// This package only implements authentication, no key exchange or encryption. It
 | 
			
		||||
// only supports Unicode (UTF16LE) encoding of protocol strings, no OEM encoding.
 | 
			
		||||
// This package implements NTLMv2.
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"golang.org/x/crypto/md4"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getNtlmV2Hash(password, username, target string) []byte {
 | 
			
		||||
	return hmacMd5(getNtlmHash(password), toUnicode(strings.ToUpper(username)+target))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getNtlmHash(password string) []byte {
 | 
			
		||||
	hash := md4.New()
 | 
			
		||||
	hash.Write(toUnicode(password))
 | 
			
		||||
	return hash.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func computeNtlmV2Response(ntlmV2Hash, serverChallenge, clientChallenge,
 | 
			
		||||
	timestamp, targetInfo []byte) []byte {
 | 
			
		||||
 | 
			
		||||
	temp := []byte{1, 1, 0, 0, 0, 0, 0, 0}
 | 
			
		||||
	temp = append(temp, timestamp...)
 | 
			
		||||
	temp = append(temp, clientChallenge...)
 | 
			
		||||
	temp = append(temp, 0, 0, 0, 0)
 | 
			
		||||
	temp = append(temp, targetInfo...)
 | 
			
		||||
	temp = append(temp, 0, 0, 0, 0)
 | 
			
		||||
 | 
			
		||||
	NTProofStr := hmacMd5(ntlmV2Hash, serverChallenge, temp)
 | 
			
		||||
	return append(NTProofStr, temp...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func computeLmV2Response(ntlmV2Hash, serverChallenge, clientChallenge []byte) []byte {
 | 
			
		||||
	return append(hmacMd5(ntlmV2Hash, serverChallenge, clientChallenge), clientChallenge...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hmacMd5(key []byte, data ...[]byte) []byte {
 | 
			
		||||
	mac := hmac.New(md5.New, key)
 | 
			
		||||
	for _, d := range data {
 | 
			
		||||
		mac.Write(d)
 | 
			
		||||
	}
 | 
			
		||||
	return mac.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/Azure/go-ntlmssp/unicode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/Azure/go-ntlmssp/unicode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// helper func's for dealing with Windows Unicode (UTF16LE)
 | 
			
		||||
 | 
			
		||||
func fromUnicode(d []byte) (string, error) {
 | 
			
		||||
	if len(d)%2 > 0 {
 | 
			
		||||
		return "", errors.New("Unicode (UTF 16 LE) specified, but uneven data length")
 | 
			
		||||
	}
 | 
			
		||||
	s := make([]uint16, len(d)/2)
 | 
			
		||||
	err := binary.Read(bytes.NewReader(d), binary.LittleEndian, &s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return string(utf16.Decode(s)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toUnicode(s string) []byte {
 | 
			
		||||
	uints := utf16.Encode([]rune(s))
 | 
			
		||||
	b := bytes.Buffer{}
 | 
			
		||||
	binary.Write(&b, binary.LittleEndian, &uints)
 | 
			
		||||
	return b.Bytes()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								vendor/github.com/Azure/go-ntlmssp/varfield.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/Azure/go-ntlmssp/varfield.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type varField struct {
 | 
			
		||||
	Len          uint16
 | 
			
		||||
	MaxLen       uint16
 | 
			
		||||
	BufferOffset uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f varField) ReadFrom(buffer []byte) ([]byte, error) {
 | 
			
		||||
	if len(buffer) < int(f.BufferOffset+uint32(f.Len)) {
 | 
			
		||||
		return nil, errors.New("Error reading data, varField extends beyond buffer")
 | 
			
		||||
	}
 | 
			
		||||
	return buffer[f.BufferOffset : f.BufferOffset+uint32(f.Len)], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f varField) ReadStringFrom(buffer []byte, unicode bool) (string, error) {
 | 
			
		||||
	d, err := f.ReadFrom(buffer)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if unicode { // UTF-16LE encoding scheme
 | 
			
		||||
		return fromUnicode(d)
 | 
			
		||||
	}
 | 
			
		||||
	// OEM encoding, close enough to ASCII, since no code page is specified
 | 
			
		||||
	return string(d), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newVarField(ptr *int, fieldsize int) varField {
 | 
			
		||||
	f := varField{
 | 
			
		||||
		Len:          uint16(fieldsize),
 | 
			
		||||
		MaxLen:       uint16(fieldsize),
 | 
			
		||||
		BufferOffset: uint32(*ptr),
 | 
			
		||||
	}
 | 
			
		||||
	*ptr += fieldsize
 | 
			
		||||
	return f
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/Azure/go-ntlmssp/version.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/Azure/go-ntlmssp/version.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
package ntlmssp
 | 
			
		||||
 | 
			
		||||
// Version is a struct representing https://msdn.microsoft.com/en-us/library/cc236654.aspx
 | 
			
		||||
type Version struct {
 | 
			
		||||
	ProductMajorVersion uint8
 | 
			
		||||
	ProductMinorVersion uint8
 | 
			
		||||
	ProductBuild        uint16
 | 
			
		||||
	_                   [3]byte
 | 
			
		||||
	NTLMRevisionCurrent uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultVersion returns a Version with "sensible" defaults (Windows 7)
 | 
			
		||||
func DefaultVersion() Version {
 | 
			
		||||
	return Version{
 | 
			
		||||
		ProductMajorVersion: 6,
 | 
			
		||||
		ProductMinorVersion: 1,
 | 
			
		||||
		ProductBuild:        7601,
 | 
			
		||||
		NTLMRevisionCurrent: 15,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
  - 1.2.x
 | 
			
		||||
  - 1.6.x
 | 
			
		||||
  - 1.9.x
 | 
			
		||||
  - 1.10.x
 | 
			
		||||
  - 1.11.x
 | 
			
		||||
  - 1.12.x
 | 
			
		||||
  - 1.14.x
 | 
			
		||||
  - tip
 | 
			
		||||
 | 
			
		||||
os:
 | 
			
		||||
  - linux
 | 
			
		||||
 | 
			
		||||
arch:
 | 
			
		||||
  - amd64
 | 
			
		||||
 | 
			
		||||
dist: xenial
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  - GOARCH=amd64
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  include:
 | 
			
		||||
    - os: windows
 | 
			
		||||
      go: 1.14.x
 | 
			
		||||
    - os: osx
 | 
			
		||||
      go: 1.14.x
 | 
			
		||||
    - os: linux
 | 
			
		||||
      go: 1.14.x
 | 
			
		||||
      arch: arm64
 | 
			
		||||
    - os: linux
 | 
			
		||||
      go: 1.14.x
 | 
			
		||||
      env:
 | 
			
		||||
        - GOARCH=386
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - go test -v -cover ./... || go test -v ./...
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com)
 | 
			
		||||
Portions copyright (c) 2015-2016 go-asn1-ber Authors
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
							
								
								
									
										224
									
								
								vendor/gopkg.in/asn1-ber.v1/ber.go → vendor/github.com/go-asn1-ber/asn1-ber/ber.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										224
									
								
								vendor/gopkg.in/asn1-ber.v1/ber.go → vendor/github.com/go-asn1-ber/asn1-ber/ber.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,10 +5,17 @@ import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MaxPacketLengthBytes specifies the maximum allowed packet size when calling ReadPacket or DecodePacket. Set to 0 for
 | 
			
		||||
// no limit.
 | 
			
		||||
var MaxPacketLengthBytes int64 = math.MaxInt32
 | 
			
		||||
 | 
			
		||||
type Packet struct {
 | 
			
		||||
	Identifier
 | 
			
		||||
	Value       interface{}
 | 
			
		||||
@@ -138,42 +145,46 @@ var TypeMap = map[Type]string{
 | 
			
		||||
	TypeConstructed: "Constructed",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Debug bool = false
 | 
			
		||||
var Debug = false
 | 
			
		||||
 | 
			
		||||
func PrintBytes(out io.Writer, buf []byte, indent string) {
 | 
			
		||||
	data_lines := make([]string, (len(buf)/30)+1)
 | 
			
		||||
	num_lines := make([]string, (len(buf)/30)+1)
 | 
			
		||||
	dataLines := make([]string, (len(buf)/30)+1)
 | 
			
		||||
	numLines := make([]string, (len(buf)/30)+1)
 | 
			
		||||
 | 
			
		||||
	for i, b := range buf {
 | 
			
		||||
		data_lines[i/30] += fmt.Sprintf("%02x ", b)
 | 
			
		||||
		num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
 | 
			
		||||
		dataLines[i/30] += fmt.Sprintf("%02x ", b)
 | 
			
		||||
		numLines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < len(data_lines); i++ {
 | 
			
		||||
		out.Write([]byte(indent + data_lines[i] + "\n"))
 | 
			
		||||
		out.Write([]byte(indent + num_lines[i] + "\n\n"))
 | 
			
		||||
	for i := 0; i < len(dataLines); i++ {
 | 
			
		||||
		_, _ = out.Write([]byte(indent + dataLines[i] + "\n"))
 | 
			
		||||
		_, _ = out.Write([]byte(indent + numLines[i] + "\n\n"))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WritePacket(out io.Writer, p *Packet) {
 | 
			
		||||
	printPacket(out, p, 0, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PrintPacket(p *Packet) {
 | 
			
		||||
	printPacket(os.Stdout, p, 0, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
 | 
			
		||||
	indent_str := ""
 | 
			
		||||
	indentStr := ""
 | 
			
		||||
 | 
			
		||||
	for len(indent_str) != indent {
 | 
			
		||||
		indent_str += " "
 | 
			
		||||
	for len(indentStr) != indent {
 | 
			
		||||
		indentStr += " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	class_str := ClassMap[p.ClassType]
 | 
			
		||||
	classStr := ClassMap[p.ClassType]
 | 
			
		||||
 | 
			
		||||
	tagtype_str := TypeMap[p.TagType]
 | 
			
		||||
	tagTypeStr := TypeMap[p.TagType]
 | 
			
		||||
 | 
			
		||||
	tag_str := fmt.Sprintf("0x%02X", p.Tag)
 | 
			
		||||
	tagStr := fmt.Sprintf("0x%02X", p.Tag)
 | 
			
		||||
 | 
			
		||||
	if p.ClassType == ClassUniversal {
 | 
			
		||||
		tag_str = tagMap[p.Tag]
 | 
			
		||||
		tagStr = tagMap[p.Tag]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := fmt.Sprint(p.Value)
 | 
			
		||||
@@ -183,10 +194,10 @@ func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
 | 
			
		||||
		description = p.Description + ": "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
 | 
			
		||||
	_, _ = fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indentStr, description, classStr, tagTypeStr, tagStr, p.Data.Len(), value)
 | 
			
		||||
 | 
			
		||||
	if printBytes {
 | 
			
		||||
		PrintBytes(out, p.Bytes(), indent_str)
 | 
			
		||||
		PrintBytes(out, p.Bytes(), indentStr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, child := range p.Children {
 | 
			
		||||
@@ -194,7 +205,7 @@ func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPacket reads a single Packet from the reader
 | 
			
		||||
// ReadPacket reads a single Packet from the reader.
 | 
			
		||||
func ReadPacket(reader io.Reader) (*Packet, error) {
 | 
			
		||||
	p, _, err := readPacket(reader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -207,7 +218,7 @@ func DecodeString(data []byte) string {
 | 
			
		||||
	return string(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseInt64(bytes []byte) (ret int64, err error) {
 | 
			
		||||
func ParseInt64(bytes []byte) (ret int64, err error) {
 | 
			
		||||
	if len(bytes) > 8 {
 | 
			
		||||
		// We'll overflow an int64 in this case.
 | 
			
		||||
		err = fmt.Errorf("integer too large")
 | 
			
		||||
@@ -230,7 +241,7 @@ func encodeInteger(i int64) []byte {
 | 
			
		||||
 | 
			
		||||
	var j int
 | 
			
		||||
	for ; n > 0; n-- {
 | 
			
		||||
		out[j] = (byte(i >> uint((n-1)*8)))
 | 
			
		||||
		out[j] = byte(i >> uint((n-1)*8))
 | 
			
		||||
		j++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -262,7 +273,7 @@ func DecodePacket(data []byte) *Packet {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodePacketErr decodes the given bytes into a single Packet
 | 
			
		||||
// If a decode error is encountered, nil is returned
 | 
			
		||||
// If a decode error is encountered, nil is returned.
 | 
			
		||||
func DecodePacketErr(data []byte) (*Packet, error) {
 | 
			
		||||
	p, _, err := readPacket(bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -271,7 +282,7 @@ func DecodePacketErr(data []byte) (*Packet, error) {
 | 
			
		||||
	return p, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readPacket reads a single Packet from the reader, returning the number of bytes read
 | 
			
		||||
// readPacket reads a single Packet from the reader, returning the number of bytes read.
 | 
			
		||||
func readPacket(reader io.Reader) (*Packet, int, error) {
 | 
			
		||||
	identifier, length, read, err := readHeader(reader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -330,7 +341,10 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Read definite-length content
 | 
			
		||||
	content := make([]byte, length, length)
 | 
			
		||||
	if MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes {
 | 
			
		||||
		return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes)
 | 
			
		||||
	}
 | 
			
		||||
	content := make([]byte, length)
 | 
			
		||||
	if length > 0 {
 | 
			
		||||
		_, err := io.ReadFull(reader, content)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -349,11 +363,11 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
 | 
			
		||||
		switch p.Tag {
 | 
			
		||||
		case TagEOC:
 | 
			
		||||
		case TagBoolean:
 | 
			
		||||
			val, _ := parseInt64(content)
 | 
			
		||||
			val, _ := ParseInt64(content)
 | 
			
		||||
 | 
			
		||||
			p.Value = val != 0
 | 
			
		||||
		case TagInteger:
 | 
			
		||||
			p.Value, _ = parseInt64(content)
 | 
			
		||||
			p.Value, _ = ParseInt64(content)
 | 
			
		||||
		case TagBitString:
 | 
			
		||||
		case TagOctetString:
 | 
			
		||||
			// the actual string encoding is not known here
 | 
			
		||||
@@ -365,22 +379,42 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
 | 
			
		||||
		case TagObjectDescriptor:
 | 
			
		||||
		case TagExternal:
 | 
			
		||||
		case TagRealFloat:
 | 
			
		||||
			p.Value, err = ParseReal(content)
 | 
			
		||||
		case TagEnumerated:
 | 
			
		||||
			p.Value, _ = parseInt64(content)
 | 
			
		||||
			p.Value, _ = ParseInt64(content)
 | 
			
		||||
		case TagEmbeddedPDV:
 | 
			
		||||
		case TagUTF8String:
 | 
			
		||||
			p.Value = DecodeString(content)
 | 
			
		||||
			val := DecodeString(content)
 | 
			
		||||
			if !utf8.Valid([]byte(val)) {
 | 
			
		||||
				err = errors.New("invalid UTF-8 string")
 | 
			
		||||
			} else {
 | 
			
		||||
				p.Value = val
 | 
			
		||||
			}
 | 
			
		||||
		case TagRelativeOID:
 | 
			
		||||
		case TagSequence:
 | 
			
		||||
		case TagSet:
 | 
			
		||||
		case TagNumericString:
 | 
			
		||||
		case TagPrintableString:
 | 
			
		||||
			p.Value = DecodeString(content)
 | 
			
		||||
			val := DecodeString(content)
 | 
			
		||||
			if err = isPrintableString(val); err == nil {
 | 
			
		||||
				p.Value = val
 | 
			
		||||
			}
 | 
			
		||||
		case TagT61String:
 | 
			
		||||
		case TagVideotexString:
 | 
			
		||||
		case TagIA5String:
 | 
			
		||||
			val := DecodeString(content)
 | 
			
		||||
			for i, c := range val {
 | 
			
		||||
				if c >= 0x7F {
 | 
			
		||||
					err = fmt.Errorf("invalid character for IA5String at pos %d: %c", i, c)
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				p.Value = val
 | 
			
		||||
			}
 | 
			
		||||
		case TagUTCTime:
 | 
			
		||||
		case TagGeneralizedTime:
 | 
			
		||||
			p.Value, err = ParseGeneralizedTime(content)
 | 
			
		||||
		case TagGraphicString:
 | 
			
		||||
		case TagVisibleString:
 | 
			
		||||
		case TagGeneralString:
 | 
			
		||||
@@ -392,7 +426,24 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
 | 
			
		||||
		p.Data.Write(content)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p, read, nil
 | 
			
		||||
	return p, read, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isPrintableString(val string) error {
 | 
			
		||||
	for i, c := range val {
 | 
			
		||||
		switch {
 | 
			
		||||
		case c >= 'a' && c <= 'z':
 | 
			
		||||
		case c >= 'A' && c <= 'Z':
 | 
			
		||||
		case c >= '0' && c <= '9':
 | 
			
		||||
		default:
 | 
			
		||||
			switch c {
 | 
			
		||||
			case '\'', '(', ')', '+', ',', '-', '.', '=', '/', ':', '?', ' ':
 | 
			
		||||
			default:
 | 
			
		||||
				return fmt.Errorf("invalid character in position %d", i)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Packet) Bytes() []byte {
 | 
			
		||||
@@ -410,61 +461,99 @@ func (p *Packet) AppendChild(child *Packet) {
 | 
			
		||||
	p.Children = append(p.Children, child)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Encode(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
 | 
			
		||||
func Encode(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
 | 
			
		||||
	p := new(Packet)
 | 
			
		||||
 | 
			
		||||
	p.ClassType = ClassType
 | 
			
		||||
	p.TagType = TagType
 | 
			
		||||
	p.Tag = Tag
 | 
			
		||||
	p.ClassType = classType
 | 
			
		||||
	p.TagType = tagType
 | 
			
		||||
	p.Tag = tag
 | 
			
		||||
	p.Data = new(bytes.Buffer)
 | 
			
		||||
 | 
			
		||||
	p.Children = make([]*Packet, 0, 2)
 | 
			
		||||
 | 
			
		||||
	p.Value = Value
 | 
			
		||||
	p.Description = Description
 | 
			
		||||
	p.Value = value
 | 
			
		||||
	p.Description = description
 | 
			
		||||
 | 
			
		||||
	if Value != nil {
 | 
			
		||||
		v := reflect.ValueOf(Value)
 | 
			
		||||
	if value != nil {
 | 
			
		||||
		v := reflect.ValueOf(value)
 | 
			
		||||
 | 
			
		||||
		if ClassType == ClassUniversal {
 | 
			
		||||
			switch Tag {
 | 
			
		||||
		if classType == ClassUniversal {
 | 
			
		||||
			switch tag {
 | 
			
		||||
			case TagOctetString:
 | 
			
		||||
				sv, ok := v.Interface().(string)
 | 
			
		||||
 | 
			
		||||
				if ok {
 | 
			
		||||
					p.Data.Write([]byte(sv))
 | 
			
		||||
				}
 | 
			
		||||
			case TagEnumerated:
 | 
			
		||||
				bv, ok := v.Interface().([]byte)
 | 
			
		||||
				if ok {
 | 
			
		||||
					p.Data.Write(bv)
 | 
			
		||||
				}
 | 
			
		||||
			case TagEmbeddedPDV:
 | 
			
		||||
				bv, ok := v.Interface().([]byte)
 | 
			
		||||
				if ok {
 | 
			
		||||
					p.Data.Write(bv)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else if classType == ClassContext {
 | 
			
		||||
			switch tag {
 | 
			
		||||
			case TagEnumerated:
 | 
			
		||||
				bv, ok := v.Interface().([]byte)
 | 
			
		||||
				if ok {
 | 
			
		||||
					p.Data.Write(bv)
 | 
			
		||||
				}
 | 
			
		||||
			case TagEmbeddedPDV:
 | 
			
		||||
				bv, ok := v.Interface().([]byte)
 | 
			
		||||
				if ok {
 | 
			
		||||
					p.Data.Write(bv)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSequence(Description string) *Packet {
 | 
			
		||||
	return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, Description)
 | 
			
		||||
func NewSequence(description string) *Packet {
 | 
			
		||||
	return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, description)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewBoolean(ClassType Class, TagType Type, Tag Tag, Value bool, Description string) *Packet {
 | 
			
		||||
func NewBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
 | 
			
		||||
	intValue := int64(0)
 | 
			
		||||
 | 
			
		||||
	if Value {
 | 
			
		||||
	if value {
 | 
			
		||||
		intValue = 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
 | 
			
		||||
	p.Value = Value
 | 
			
		||||
	p.Value = value
 | 
			
		||||
	p.Data.Write(encodeInteger(intValue))
 | 
			
		||||
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewInteger(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
 | 
			
		||||
	p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
			
		||||
// NewLDAPBoolean returns a RFC 4511-compliant Boolean packet.
 | 
			
		||||
func NewLDAPBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
 | 
			
		||||
	intValue := int64(0)
 | 
			
		||||
 | 
			
		||||
	p.Value = Value
 | 
			
		||||
	switch v := Value.(type) {
 | 
			
		||||
	if value {
 | 
			
		||||
		intValue = 255
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
 | 
			
		||||
	p.Value = value
 | 
			
		||||
	p.Data.Write(encodeInteger(intValue))
 | 
			
		||||
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewInteger(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
 | 
			
		||||
	p.Value = value
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case int:
 | 
			
		||||
		p.Data.Write(encodeInteger(int64(v)))
 | 
			
		||||
	case uint:
 | 
			
		||||
@@ -494,11 +583,38 @@ func NewInteger(ClassType Class, TagType Type, Tag Tag, Value interface{}, Descr
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewString(ClassType Class, TagType Type, Tag Tag, Value, Description string) *Packet {
 | 
			
		||||
	p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
			
		||||
func NewString(classType Class, tagType Type, tag Tag, value, description string) *Packet {
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
 | 
			
		||||
	p.Value = Value
 | 
			
		||||
	p.Data.Write([]byte(Value))
 | 
			
		||||
	p.Value = value
 | 
			
		||||
	p.Data.Write([]byte(value))
 | 
			
		||||
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewGeneralizedTime(classType Class, tagType Type, tag Tag, value time.Time, description string) *Packet {
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
	var s string
 | 
			
		||||
	if value.Nanosecond() != 0 {
 | 
			
		||||
		s = value.Format(`20060102150405.000000000Z`)
 | 
			
		||||
	} else {
 | 
			
		||||
		s = value.Format(`20060102150405Z`)
 | 
			
		||||
	}
 | 
			
		||||
	p.Value = s
 | 
			
		||||
	p.Data.Write([]byte(s))
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewReal(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
 | 
			
		||||
	p := Encode(classType, tagType, tag, nil, description)
 | 
			
		||||
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case float64:
 | 
			
		||||
		p.Data.Write(encodeFloat(v))
 | 
			
		||||
	case float32:
 | 
			
		||||
		p.Data.Write(encodeFloat(float64(v)))
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Sprintf("Invalid type %T, expected float{64|32}", v))
 | 
			
		||||
	}
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
@@ -6,7 +6,7 @@ func encodeUnsignedInteger(i uint64) []byte {
 | 
			
		||||
 | 
			
		||||
	var j int
 | 
			
		||||
	for ; n > 0; n-- {
 | 
			
		||||
		out[j] = (byte(i >> uint((n-1)*8)))
 | 
			
		||||
		out[j] = byte(i >> uint((n-1)*8))
 | 
			
		||||
		j++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/generalizedTime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/generalizedTime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
package ber
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrInvalidTimeFormat is returned when the generalizedTime string was not correct.
 | 
			
		||||
var ErrInvalidTimeFormat = errors.New("invalid time format")
 | 
			
		||||
 | 
			
		||||
var zeroTime = time.Time{}
 | 
			
		||||
 | 
			
		||||
// ParseGeneralizedTime parses a string value and if it conforms to
 | 
			
		||||
// GeneralizedTime[^0] format, will return a time.Time for that value.
 | 
			
		||||
//
 | 
			
		||||
// [^0]: https://www.itu.int/rec/T-REC-X.690-201508-I/en Section 11.7
 | 
			
		||||
func ParseGeneralizedTime(v []byte) (time.Time, error) {
 | 
			
		||||
	var format string
 | 
			
		||||
	var fract time.Duration
 | 
			
		||||
 | 
			
		||||
	str := []byte(DecodeString(v))
 | 
			
		||||
	tzIndex := bytes.IndexAny(str, "Z+-")
 | 
			
		||||
	if tzIndex < 0 {
 | 
			
		||||
		return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dot := bytes.IndexAny(str, ".,")
 | 
			
		||||
	switch dot {
 | 
			
		||||
	case -1:
 | 
			
		||||
		switch tzIndex {
 | 
			
		||||
		case 10:
 | 
			
		||||
			format = `2006010215Z`
 | 
			
		||||
		case 12:
 | 
			
		||||
			format = `200601021504Z`
 | 
			
		||||
		case 14:
 | 
			
		||||
			format = `20060102150405Z`
 | 
			
		||||
		default:
 | 
			
		||||
			return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case 10, 12:
 | 
			
		||||
		if tzIndex < dot {
 | 
			
		||||
			return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
		}
 | 
			
		||||
		// a "," is also allowed, but would not be parsed by time.Parse():
 | 
			
		||||
		str[dot] = '.'
 | 
			
		||||
 | 
			
		||||
		// If <minute> is omitted, then <fraction> represents a fraction of an
 | 
			
		||||
		// hour; otherwise, if <second> and <leap-second> are omitted, then
 | 
			
		||||
		// <fraction> represents a fraction of a minute; otherwise, <fraction>
 | 
			
		||||
		// represents a fraction of a second.
 | 
			
		||||
 | 
			
		||||
		// parse as float from dot to timezone
 | 
			
		||||
		f, err := strconv.ParseFloat(string(str[dot:tzIndex]), 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return zeroTime, fmt.Errorf("failed to parse float: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		// ...and strip that part
 | 
			
		||||
		str = append(str[:dot], str[tzIndex:]...)
 | 
			
		||||
		tzIndex = dot
 | 
			
		||||
 | 
			
		||||
		if dot == 10 {
 | 
			
		||||
			fract = time.Duration(int64(f * float64(time.Hour)))
 | 
			
		||||
			format = `2006010215Z`
 | 
			
		||||
		} else {
 | 
			
		||||
			fract = time.Duration(int64(f * float64(time.Minute)))
 | 
			
		||||
			format = `200601021504Z`
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case 14:
 | 
			
		||||
		if tzIndex < dot {
 | 
			
		||||
			return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
		}
 | 
			
		||||
		str[dot] = '.'
 | 
			
		||||
		// no need for fractional seconds, time.Parse() handles that
 | 
			
		||||
		format = `20060102150405Z`
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l := len(str)
 | 
			
		||||
	switch l - tzIndex {
 | 
			
		||||
	case 1:
 | 
			
		||||
		if str[l-1] != 'Z' {
 | 
			
		||||
			return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
		}
 | 
			
		||||
	case 3:
 | 
			
		||||
		format += `0700`
 | 
			
		||||
		str = append(str, []byte("00")...)
 | 
			
		||||
	case 5:
 | 
			
		||||
		format += `0700`
 | 
			
		||||
	default:
 | 
			
		||||
		return zeroTime, ErrInvalidTimeFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t, err := time.Parse(format, string(str))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return zeroTime, fmt.Errorf("%s: %s", ErrInvalidTimeFormat, err)
 | 
			
		||||
	}
 | 
			
		||||
	return t.Add(fract), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
module github.com/go-asn1-ber/asn1-ber
 | 
			
		||||
 | 
			
		||||
go 1.13
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/gopkg.in/asn1-ber.v1/header.go → vendor/github.com/go-asn1-ber/asn1-ber/header.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/gopkg.in/asn1-ber.v1/header.go → vendor/github.com/go-asn1-ber/asn1-ber/header.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,28 +2,37 @@ package ber
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func readHeader(reader io.Reader) (identifier Identifier, length int, read int, err error) {
 | 
			
		||||
	if i, c, err := readIdentifier(reader); err != nil {
 | 
			
		||||
		return Identifier{}, 0, read, err
 | 
			
		||||
	} else {
 | 
			
		||||
		identifier = i
 | 
			
		||||
		read += c
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		c, l int
 | 
			
		||||
		i    Identifier
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if l, c, err := readLength(reader); err != nil {
 | 
			
		||||
	if i, c, err = readIdentifier(reader); err != nil {
 | 
			
		||||
		return Identifier{}, 0, read, err
 | 
			
		||||
	} else {
 | 
			
		||||
		length = l
 | 
			
		||||
		read += c
 | 
			
		||||
	}
 | 
			
		||||
	identifier = i
 | 
			
		||||
	read += c
 | 
			
		||||
 | 
			
		||||
	if l, c, err = readLength(reader); err != nil {
 | 
			
		||||
		return Identifier{}, 0, read, err
 | 
			
		||||
	}
 | 
			
		||||
	length = l
 | 
			
		||||
	read += c
 | 
			
		||||
 | 
			
		||||
	// Validate length type with identifier (x.600, 8.1.3.2.a)
 | 
			
		||||
	if length == LengthIndefinite && identifier.TagType == TypePrimitive {
 | 
			
		||||
		return Identifier{}, 0, read, errors.New("indefinite length used with primitive type")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if length < LengthIndefinite {
 | 
			
		||||
		err = fmt.Errorf("length cannot be less than %d", LengthIndefinite)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return identifier, length, read, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -4,7 +4,6 @@ import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func readIdentifier(reader io.Reader) (Identifier, int, error) {
 | 
			
		||||
@@ -80,24 +79,34 @@ func encodeIdentifier(identifier Identifier) []byte {
 | 
			
		||||
 | 
			
		||||
		tag := identifier.Tag
 | 
			
		||||
 | 
			
		||||
		highBit := uint(63)
 | 
			
		||||
		for {
 | 
			
		||||
			if tag&(1<<highBit) != 0 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			highBit--
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		tagBytes := int(math.Ceil(float64(highBit) / 7.0))
 | 
			
		||||
		for i := tagBytes - 1; i >= 0; i-- {
 | 
			
		||||
			offset := uint(i) * 7
 | 
			
		||||
			mask := Tag(0x7f) << offset
 | 
			
		||||
			tagByte := (tag & mask) >> offset
 | 
			
		||||
			if i != 0 {
 | 
			
		||||
				tagByte |= 0x80
 | 
			
		||||
			}
 | 
			
		||||
			b = append(b, byte(tagByte))
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, encodeHighTag(tag)...)
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeHighTag(tag Tag) []byte {
 | 
			
		||||
	// set cap=4 to hopefully avoid additional allocations
 | 
			
		||||
	b := make([]byte, 0, 4)
 | 
			
		||||
	for tag != 0 {
 | 
			
		||||
		// t := last 7 bits of tag (HighTagValueBitmask = 0x7F)
 | 
			
		||||
		t := tag & HighTagValueBitmask
 | 
			
		||||
 | 
			
		||||
		// right shift tag 7 to remove what was just pulled off
 | 
			
		||||
		tag >>= 7
 | 
			
		||||
 | 
			
		||||
		// if b already has entries this entry needs a continuation bit (0x80)
 | 
			
		||||
		if len(b) != 0 {
 | 
			
		||||
			t |= HighTagContinueBitmask
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		b = append(b, byte(t))
 | 
			
		||||
	}
 | 
			
		||||
	// reverse
 | 
			
		||||
	// since bits were pulled off 'tag' small to high the byte slice is in reverse order.
 | 
			
		||||
	// example: tag = 0xFF results in {0x7F, 0x01 + 0x80 (continuation bit)}
 | 
			
		||||
	// this needs to be reversed into 0x81 0x7F
 | 
			
		||||
	for i, j := 0, len(b)-1; i < len(b)/2; i++ {
 | 
			
		||||
		b[i], b[j-i] = b[j-i], b[i]
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/gopkg.in/asn1-ber.v1/length.go → vendor/github.com/go-asn1-ber/asn1-ber/length.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/gopkg.in/asn1-ber.v1/length.go → vendor/github.com/go-asn1-ber/asn1-ber/length.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -38,6 +38,9 @@ func readLength(reader io.Reader) (length int, read int, err error) {
 | 
			
		||||
		if lengthBytes > 8 {
 | 
			
		||||
			return 0, read, errors.New("long-form length overflow")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Accumulate into a 64-bit variable
 | 
			
		||||
		var length64 int64
 | 
			
		||||
		for i := 0; i < lengthBytes; i++ {
 | 
			
		||||
			b, err = readByte(reader)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
@@ -49,8 +52,15 @@ func readLength(reader io.Reader) (length int, read int, err error) {
 | 
			
		||||
			read++
 | 
			
		||||
 | 
			
		||||
			// x.600, 8.1.3.5
 | 
			
		||||
			length <<= 8
 | 
			
		||||
			length |= int(b)
 | 
			
		||||
			length64 <<= 8
 | 
			
		||||
			length64 |= int64(b)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Cast to a platform-specific integer
 | 
			
		||||
		length = int(length64)
 | 
			
		||||
		// Ensure we didn't overflow
 | 
			
		||||
		if int64(length) != length64 {
 | 
			
		||||
			return 0, read, errors.New("long-form length overflow")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
@@ -61,11 +71,11 @@ func readLength(reader io.Reader) (length int, read int, err error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeLength(length int) []byte {
 | 
			
		||||
	length_bytes := encodeUnsignedInteger(uint64(length))
 | 
			
		||||
	if length > 127 || len(length_bytes) > 1 {
 | 
			
		||||
		longFormBytes := []byte{(LengthLongFormBitmask | byte(len(length_bytes)))}
 | 
			
		||||
		longFormBytes = append(longFormBytes, length_bytes...)
 | 
			
		||||
		length_bytes = longFormBytes
 | 
			
		||||
	lengthBytes := encodeUnsignedInteger(uint64(length))
 | 
			
		||||
	if length > 127 || len(lengthBytes) > 1 {
 | 
			
		||||
		longFormBytes := []byte{LengthLongFormBitmask | byte(len(lengthBytes))}
 | 
			
		||||
		longFormBytes = append(longFormBytes, lengthBytes...)
 | 
			
		||||
		lengthBytes = longFormBytes
 | 
			
		||||
	}
 | 
			
		||||
	return length_bytes
 | 
			
		||||
	return lengthBytes
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										157
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/real.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								vendor/github.com/go-asn1-ber/asn1-ber/real.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
package ber
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func encodeFloat(v float64) []byte {
 | 
			
		||||
	switch {
 | 
			
		||||
	case math.IsInf(v, 1):
 | 
			
		||||
		return []byte{0x40}
 | 
			
		||||
	case math.IsInf(v, -1):
 | 
			
		||||
		return []byte{0x41}
 | 
			
		||||
	case math.IsNaN(v):
 | 
			
		||||
		return []byte{0x42}
 | 
			
		||||
	case v == 0.0:
 | 
			
		||||
		if math.Signbit(v) {
 | 
			
		||||
			return []byte{0x43}
 | 
			
		||||
		}
 | 
			
		||||
		return []byte{}
 | 
			
		||||
	default:
 | 
			
		||||
		// we take the easy part ;-)
 | 
			
		||||
		value := []byte(strconv.FormatFloat(v, 'G', -1, 64))
 | 
			
		||||
		var ret []byte
 | 
			
		||||
		if bytes.Contains(value, []byte{'E'}) {
 | 
			
		||||
			ret = []byte{0x03}
 | 
			
		||||
		} else {
 | 
			
		||||
			ret = []byte{0x02}
 | 
			
		||||
		}
 | 
			
		||||
		ret = append(ret, value...)
 | 
			
		||||
		return ret
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseReal(v []byte) (val float64, err error) {
 | 
			
		||||
	if len(v) == 0 {
 | 
			
		||||
		return 0.0, nil
 | 
			
		||||
	}
 | 
			
		||||
	switch {
 | 
			
		||||
	case v[0]&0x80 == 0x80:
 | 
			
		||||
		val, err = parseBinaryFloat(v)
 | 
			
		||||
	case v[0]&0xC0 == 0x40:
 | 
			
		||||
		val, err = parseSpecialFloat(v)
 | 
			
		||||
	case v[0]&0xC0 == 0x0:
 | 
			
		||||
		val, err = parseDecimalFloat(v)
 | 
			
		||||
	default:
 | 
			
		||||
		return 0.0, fmt.Errorf("invalid info block")
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0.0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if val == 0.0 && !math.Signbit(val) {
 | 
			
		||||
		return 0.0, errors.New("REAL value +0 must be encoded with zero-length value block")
 | 
			
		||||
	}
 | 
			
		||||
	return val, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseBinaryFloat(v []byte) (float64, error) {
 | 
			
		||||
	var info byte
 | 
			
		||||
	var buf []byte
 | 
			
		||||
 | 
			
		||||
	info, v = v[0], v[1:]
 | 
			
		||||
 | 
			
		||||
	var base int
 | 
			
		||||
	switch info & 0x30 {
 | 
			
		||||
	case 0x00:
 | 
			
		||||
		base = 2
 | 
			
		||||
	case 0x10:
 | 
			
		||||
		base = 8
 | 
			
		||||
	case 0x20:
 | 
			
		||||
		base = 16
 | 
			
		||||
	case 0x30:
 | 
			
		||||
		return 0.0, errors.New("bits 6 and 5 of information octet for REAL are equal to 11")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scale := uint((info & 0x0c) >> 2)
 | 
			
		||||
 | 
			
		||||
	var expLen int
 | 
			
		||||
	switch info & 0x03 {
 | 
			
		||||
	case 0x00:
 | 
			
		||||
		expLen = 1
 | 
			
		||||
	case 0x01:
 | 
			
		||||
		expLen = 2
 | 
			
		||||
	case 0x02:
 | 
			
		||||
		expLen = 3
 | 
			
		||||
	case 0x03:
 | 
			
		||||
		expLen = int(v[0])
 | 
			
		||||
		if expLen > 8 {
 | 
			
		||||
			return 0.0, errors.New("too big value of exponent")
 | 
			
		||||
		}
 | 
			
		||||
		v = v[1:]
 | 
			
		||||
	}
 | 
			
		||||
	buf, v = v[:expLen], v[expLen:]
 | 
			
		||||
	exponent, err := ParseInt64(buf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0.0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(v) > 8 {
 | 
			
		||||
		return 0.0, errors.New("too big value of mantissa")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mant, err := ParseInt64(v)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0.0, err
 | 
			
		||||
	}
 | 
			
		||||
	mantissa := mant << scale
 | 
			
		||||
 | 
			
		||||
	if info&0x40 == 0x40 {
 | 
			
		||||
		mantissa = -mantissa
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return float64(mantissa) * math.Pow(float64(base), float64(exponent)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseDecimalFloat(v []byte) (val float64, err error) {
 | 
			
		||||
	switch v[0] & 0x3F {
 | 
			
		||||
	case 0x01: // NR form 1
 | 
			
		||||
		var iVal int64
 | 
			
		||||
		iVal, err = strconv.ParseInt(strings.TrimLeft(string(v[1:]), " "), 10, 64)
 | 
			
		||||
		val = float64(iVal)
 | 
			
		||||
	case 0x02, 0x03: // NR form 2, 3
 | 
			
		||||
		val, err = strconv.ParseFloat(strings.Replace(strings.TrimLeft(string(v[1:]), " "), ",", ".", -1), 64)
 | 
			
		||||
	default:
 | 
			
		||||
		err = errors.New("incorrect NR form")
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0.0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if val == 0.0 && math.Signbit(val) {
 | 
			
		||||
		return 0.0, errors.New("REAL value -0 must be encoded as a special value")
 | 
			
		||||
	}
 | 
			
		||||
	return val, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseSpecialFloat(v []byte) (float64, error) {
 | 
			
		||||
	if len(v) != 1 {
 | 
			
		||||
		return 0.0, errors.New(`encoding of "special value" must not contain exponent and mantissa`)
 | 
			
		||||
	}
 | 
			
		||||
	switch v[0] {
 | 
			
		||||
	case 0x40:
 | 
			
		||||
		return math.Inf(1), nil
 | 
			
		||||
	case 0x41:
 | 
			
		||||
		return math.Inf(-1), nil
 | 
			
		||||
	case 0x42:
 | 
			
		||||
		return math.NaN(), nil
 | 
			
		||||
	case 0x43:
 | 
			
		||||
		return math.Copysign(0, -1), nil
 | 
			
		||||
	}
 | 
			
		||||
	return 0.0, errors.New(`encoding of "special value" not from ASN.1 standard`)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/gopkg.in/asn1-ber.v1/util.go → vendor/github.com/go-asn1-ber/asn1-ber/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/gopkg.in/asn1-ber.v1/util.go → vendor/github.com/go-asn1-ber/asn1-ber/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,7 +3,7 @@ package ber
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
func readByte(reader io.Reader) (byte, error) {
 | 
			
		||||
	bytes := make([]byte, 1, 1)
 | 
			
		||||
	bytes := make([]byte, 1)
 | 
			
		||||
	_, err := io.ReadFull(reader, bytes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/gopkg.in/ldap.v3/LICENSE → vendor/github.com/go-ldap/ldap/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/gopkg.in/ldap.v3/LICENSE → vendor/github.com/go-ldap/ldap/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
									
										62
									
								
								vendor/gopkg.in/ldap.v3/add.go → vendor/github.com/go-ldap/ldap/v3/add.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/gopkg.in/ldap.v3/add.go → vendor/github.com/go-ldap/ldap/v3/add.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,19 +1,9 @@
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
//
 | 
			
		||||
// AddRequest ::= [APPLICATION 8] SEQUENCE {
 | 
			
		||||
//      entry           LDAPDN,
 | 
			
		||||
//      attributes      AttributeList }
 | 
			
		||||
//
 | 
			
		||||
// AttributeList ::= SEQUENCE OF attribute Attribute
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Attribute represents an LDAP attribute
 | 
			
		||||
@@ -45,20 +35,26 @@ type AddRequest struct {
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a AddRequest) encode() *ber.Packet {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.DN, "DN"))
 | 
			
		||||
func (req *AddRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.DN, "DN"))
 | 
			
		||||
	attributes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
 | 
			
		||||
	for _, attribute := range a.Attributes {
 | 
			
		||||
	for _, attribute := range req.Attributes {
 | 
			
		||||
		attributes.AppendChild(attribute.encode())
 | 
			
		||||
	}
 | 
			
		||||
	request.AppendChild(attributes)
 | 
			
		||||
	return request
 | 
			
		||||
	pkt.AppendChild(attributes)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attribute adds an attribute with the given type and values
 | 
			
		||||
func (a *AddRequest) Attribute(attrType string, attrVals []string) {
 | 
			
		||||
	a.Attributes = append(a.Attributes, Attribute{Type: attrType, Vals: attrVals})
 | 
			
		||||
func (req *AddRequest) Attribute(attrType string, attrVals []string) {
 | 
			
		||||
	req.Attributes = append(req.Attributes, Attribute{Type: attrType, Vals: attrVals})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAddRequest returns an AddRequest for the given DN, with no attributes
 | 
			
		||||
@@ -72,39 +68,17 @@ func NewAddRequest(dn string, controls []Control) *AddRequest {
 | 
			
		||||
 | 
			
		||||
// Add performs the given AddRequest
 | 
			
		||||
func (l *Conn) Add(addRequest *AddRequest) error {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	packet.AppendChild(addRequest.encode())
 | 
			
		||||
	if len(addRequest.Controls) > 0 {
 | 
			
		||||
		packet.AppendChild(encodeControls(addRequest.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	msgCtx, err := l.doRequest(addRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationAddResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -113,7 +87,5 @@ func (l *Conn) Add(addRequest *AddRequest) error {
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										540
									
								
								vendor/github.com/go-ldap/ldap/v3/bind.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								vendor/github.com/go-ldap/ldap/v3/bind.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,540 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	enchex "encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/Azure/go-ntlmssp"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SimpleBindRequest represents a username/password bind operation
 | 
			
		||||
type SimpleBindRequest struct {
 | 
			
		||||
	// Username is the name of the Directory object that the client wishes to bind as
 | 
			
		||||
	Username string
 | 
			
		||||
	// Password is the credentials to bind with
 | 
			
		||||
	Password string
 | 
			
		||||
	// Controls are optional controls to send with the bind request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
	// AllowEmptyPassword sets whether the client allows binding with an empty password
 | 
			
		||||
	// (normally used for unauthenticated bind).
 | 
			
		||||
	AllowEmptyPassword bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SimpleBindResult contains the response from the server
 | 
			
		||||
type SimpleBindResult struct {
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSimpleBindRequest returns a bind request
 | 
			
		||||
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
 | 
			
		||||
	return &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           password,
 | 
			
		||||
		Controls:           controls,
 | 
			
		||||
		AllowEmptyPassword: false,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *SimpleBindRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.Username, "User Name"))
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.Password, "Password"))
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SimpleBind performs the simple bind operation defined in the given request
 | 
			
		||||
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
 | 
			
		||||
	if simpleBindRequest.Password == "" && !simpleBindRequest.AllowEmptyPassword {
 | 
			
		||||
		return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.doRequest(simpleBindRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := &SimpleBindResult{
 | 
			
		||||
		Controls: make([]Control, 0),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(packet.Children) == 3 {
 | 
			
		||||
		for _, child := range packet.Children[2].Children {
 | 
			
		||||
			decodedChild, decodeErr := DecodeControl(child)
 | 
			
		||||
			if decodeErr != nil {
 | 
			
		||||
				return nil, fmt.Errorf("failed to decode child control: %s", decodeErr)
 | 
			
		||||
			}
 | 
			
		||||
			result.Controls = append(result.Controls, decodedChild)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = GetLDAPError(packet)
 | 
			
		||||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bind performs a bind with the given username and password.
 | 
			
		||||
//
 | 
			
		||||
// It does not allow unauthenticated bind (i.e. empty password). Use the UnauthenticatedBind method
 | 
			
		||||
// for that.
 | 
			
		||||
func (l *Conn) Bind(username, password string) error {
 | 
			
		||||
	req := &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           password,
 | 
			
		||||
		AllowEmptyPassword: false,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.SimpleBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnauthenticatedBind performs an unauthenticated bind.
 | 
			
		||||
//
 | 
			
		||||
// A username may be provided for trace (e.g. logging) purpose only, but it is normally not
 | 
			
		||||
// authenticated or otherwise validated by the LDAP server.
 | 
			
		||||
//
 | 
			
		||||
// See https://tools.ietf.org/html/rfc4513#section-5.1.2 .
 | 
			
		||||
// See https://tools.ietf.org/html/rfc4513#section-6.3.1 .
 | 
			
		||||
func (l *Conn) UnauthenticatedBind(username string) error {
 | 
			
		||||
	req := &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           "",
 | 
			
		||||
		AllowEmptyPassword: true,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.SimpleBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DigestMD5BindRequest represents a digest-md5 bind operation
 | 
			
		||||
type DigestMD5BindRequest struct {
 | 
			
		||||
	Host string
 | 
			
		||||
	// Username is the name of the Directory object that the client wishes to bind as
 | 
			
		||||
	Username string
 | 
			
		||||
	// Password is the credentials to bind with
 | 
			
		||||
	Password string
 | 
			
		||||
	// Controls are optional controls to send with the bind request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *DigestMD5BindRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
 | 
			
		||||
 | 
			
		||||
	auth := ber.Encode(ber.ClassContext, ber.TypeConstructed, 3, "", "authentication")
 | 
			
		||||
	auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "DIGEST-MD5", "SASL Mech"))
 | 
			
		||||
	request.AppendChild(auth)
 | 
			
		||||
	envelope.AppendChild(request)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DigestMD5BindResult contains the response from the server
 | 
			
		||||
type DigestMD5BindResult struct {
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MD5Bind performs a digest-md5 bind with the given host, username and password.
 | 
			
		||||
func (l *Conn) MD5Bind(host, username, password string) error {
 | 
			
		||||
	req := &DigestMD5BindRequest{
 | 
			
		||||
		Host:     host,
 | 
			
		||||
		Username: username,
 | 
			
		||||
		Password: password,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.DigestMD5Bind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DigestMD5Bind performs the digest-md5 bind operation defined in the given request
 | 
			
		||||
func (l *Conn) DigestMD5Bind(digestMD5BindRequest *DigestMD5BindRequest) (*DigestMD5BindResult, error) {
 | 
			
		||||
	if digestMD5BindRequest.Password == "" {
 | 
			
		||||
		return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.doRequest(digestMD5BindRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err = addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := &DigestMD5BindResult{
 | 
			
		||||
		Controls: make([]Control, 0),
 | 
			
		||||
	}
 | 
			
		||||
	var params map[string]string
 | 
			
		||||
	if len(packet.Children) == 2 {
 | 
			
		||||
		if len(packet.Children[1].Children) == 4 {
 | 
			
		||||
			child := packet.Children[1].Children[0]
 | 
			
		||||
			if child.Tag != ber.TagEnumerated {
 | 
			
		||||
				return result, GetLDAPError(packet)
 | 
			
		||||
			}
 | 
			
		||||
			if child.Value.(int64) != 14 {
 | 
			
		||||
				return result, GetLDAPError(packet)
 | 
			
		||||
			}
 | 
			
		||||
			child = packet.Children[1].Children[3]
 | 
			
		||||
			if child.Tag != ber.TagObjectDescriptor {
 | 
			
		||||
				return result, GetLDAPError(packet)
 | 
			
		||||
			}
 | 
			
		||||
			if child.Data == nil {
 | 
			
		||||
				return result, GetLDAPError(packet)
 | 
			
		||||
			}
 | 
			
		||||
			data, _ := ioutil.ReadAll(child.Data)
 | 
			
		||||
			params, err = parseParams(string(data))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return result, fmt.Errorf("parsing digest-challenge: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if params != nil {
 | 
			
		||||
		resp := computeResponse(
 | 
			
		||||
			params,
 | 
			
		||||
			"ldap/"+strings.ToLower(digestMD5BindRequest.Host),
 | 
			
		||||
			digestMD5BindRequest.Username,
 | 
			
		||||
			digestMD5BindRequest.Password,
 | 
			
		||||
		)
 | 
			
		||||
		packet = ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
		packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
 | 
			
		||||
		request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
		request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
		request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
 | 
			
		||||
 | 
			
		||||
		auth := ber.Encode(ber.ClassContext, ber.TypeConstructed, 3, "", "authentication")
 | 
			
		||||
		auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "DIGEST-MD5", "SASL Mech"))
 | 
			
		||||
		auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, resp, "Credentials"))
 | 
			
		||||
		request.AppendChild(auth)
 | 
			
		||||
		packet.AppendChild(request)
 | 
			
		||||
		msgCtx, err = l.sendMessage(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("send message: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		defer l.finishMessage(msgCtx)
 | 
			
		||||
		packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
		}
 | 
			
		||||
		packet, err = packetResponse.ReadPacket()
 | 
			
		||||
		l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("read packet: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = GetLDAPError(packet)
 | 
			
		||||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseParams(str string) (map[string]string, error) {
 | 
			
		||||
	m := make(map[string]string)
 | 
			
		||||
	var key, value string
 | 
			
		||||
	var state int
 | 
			
		||||
	for i := 0; i <= len(str); i++ {
 | 
			
		||||
		switch state {
 | 
			
		||||
		case 0: //reading key
 | 
			
		||||
			if i == len(str) {
 | 
			
		||||
				return nil, fmt.Errorf("syntax error on %d", i)
 | 
			
		||||
			}
 | 
			
		||||
			if str[i] != '=' {
 | 
			
		||||
				key += string(str[i])
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			state = 1
 | 
			
		||||
		case 1: //reading value
 | 
			
		||||
			if i == len(str) {
 | 
			
		||||
				m[key] = value
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			switch str[i] {
 | 
			
		||||
			case ',':
 | 
			
		||||
				m[key] = value
 | 
			
		||||
				state = 0
 | 
			
		||||
				key = ""
 | 
			
		||||
				value = ""
 | 
			
		||||
			case '"':
 | 
			
		||||
				if value != "" {
 | 
			
		||||
					return nil, fmt.Errorf("syntax error on %d", i)
 | 
			
		||||
				}
 | 
			
		||||
				state = 2
 | 
			
		||||
			default:
 | 
			
		||||
				value += string(str[i])
 | 
			
		||||
			}
 | 
			
		||||
		case 2: //inside quotes
 | 
			
		||||
			if i == len(str) {
 | 
			
		||||
				return nil, fmt.Errorf("syntax error on %d", i)
 | 
			
		||||
			}
 | 
			
		||||
			if str[i] != '"' {
 | 
			
		||||
				value += string(str[i])
 | 
			
		||||
			} else {
 | 
			
		||||
				state = 1
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func computeResponse(params map[string]string, uri, username, password string) string {
 | 
			
		||||
	nc := "00000001"
 | 
			
		||||
	qop := "auth"
 | 
			
		||||
	cnonce := enchex.EncodeToString(randomBytes(16))
 | 
			
		||||
	x := username + ":" + params["realm"] + ":" + password
 | 
			
		||||
	y := md5Hash([]byte(x))
 | 
			
		||||
 | 
			
		||||
	a1 := bytes.NewBuffer(y)
 | 
			
		||||
	a1.WriteString(":" + params["nonce"] + ":" + cnonce)
 | 
			
		||||
	if len(params["authzid"]) > 0 {
 | 
			
		||||
		a1.WriteString(":" + params["authzid"])
 | 
			
		||||
	}
 | 
			
		||||
	a2 := bytes.NewBuffer([]byte("AUTHENTICATE"))
 | 
			
		||||
	a2.WriteString(":" + uri)
 | 
			
		||||
	ha1 := enchex.EncodeToString(md5Hash(a1.Bytes()))
 | 
			
		||||
	ha2 := enchex.EncodeToString(md5Hash(a2.Bytes()))
 | 
			
		||||
 | 
			
		||||
	kd := ha1
 | 
			
		||||
	kd += ":" + params["nonce"]
 | 
			
		||||
	kd += ":" + nc
 | 
			
		||||
	kd += ":" + cnonce
 | 
			
		||||
	kd += ":" + qop
 | 
			
		||||
	kd += ":" + ha2
 | 
			
		||||
	resp := enchex.EncodeToString(md5Hash([]byte(kd)))
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		`username="%s",realm="%s",nonce="%s",cnonce="%s",nc=00000001,qop=%s,digest-uri="%s",response=%s`,
 | 
			
		||||
		username,
 | 
			
		||||
		params["realm"],
 | 
			
		||||
		params["nonce"],
 | 
			
		||||
		cnonce,
 | 
			
		||||
		qop,
 | 
			
		||||
		uri,
 | 
			
		||||
		resp,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func md5Hash(b []byte) []byte {
 | 
			
		||||
	hasher := md5.New()
 | 
			
		||||
	hasher.Write(b)
 | 
			
		||||
	return hasher.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func randomBytes(len int) []byte {
 | 
			
		||||
	b := make([]byte, len)
 | 
			
		||||
	for i := 0; i < len; i++ {
 | 
			
		||||
		b[i] = byte(rand.Intn(256))
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var externalBindRequest = requestFunc(func(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
 | 
			
		||||
 | 
			
		||||
	saslAuth := ber.Encode(ber.ClassContext, ber.TypeConstructed, 3, "", "authentication")
 | 
			
		||||
	saslAuth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "EXTERNAL", "SASL Mech"))
 | 
			
		||||
	saslAuth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "SASL Cred"))
 | 
			
		||||
 | 
			
		||||
	pkt.AppendChild(saslAuth)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// ExternalBind performs SASL/EXTERNAL authentication.
 | 
			
		||||
//
 | 
			
		||||
// Use ldap.DialURL("ldapi://") to connect to the Unix socket before ExternalBind.
 | 
			
		||||
//
 | 
			
		||||
// See https://tools.ietf.org/html/rfc4422#appendix-A
 | 
			
		||||
func (l *Conn) ExternalBind() error {
 | 
			
		||||
	msgCtx, err := l.doRequest(externalBindRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return GetLDAPError(packet)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NTLMBind performs an NTLMSSP bind leveraging https://github.com/Azure/go-ntlmssp
 | 
			
		||||
 | 
			
		||||
// NTLMBindRequest represents an NTLMSSP bind operation
 | 
			
		||||
type NTLMBindRequest struct {
 | 
			
		||||
	// Domain is the AD Domain to authenticate too. If not specified, it will be grabbed from the NTLMSSP Challenge
 | 
			
		||||
	Domain string
 | 
			
		||||
	// Username is the name of the Directory object that the client wishes to bind as
 | 
			
		||||
	Username string
 | 
			
		||||
	// Password is the credentials to bind with
 | 
			
		||||
	Password string
 | 
			
		||||
	// Hash is the hex NTLM hash to bind with. Password or hash must be provided
 | 
			
		||||
	Hash string
 | 
			
		||||
	// Controls are optional controls to send with the bind request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *NTLMBindRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
 | 
			
		||||
 | 
			
		||||
	// generate an NTLMSSP Negotiation message for the  specified domain (it can be blank)
 | 
			
		||||
	negMessage, err := ntlmssp.NewNegotiateMessage(req.Domain, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("err creating negmessage: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// append the generated NTLMSSP message as a TagEnumerated BER value
 | 
			
		||||
	auth := ber.Encode(ber.ClassContext, ber.TypePrimitive, ber.TagEnumerated, negMessage, "authentication")
 | 
			
		||||
	request.AppendChild(auth)
 | 
			
		||||
	envelope.AppendChild(request)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NTLMBindResult contains the response from the server
 | 
			
		||||
type NTLMBindResult struct {
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NTLMBind performs an NTLMSSP Bind with the given domain, username and password
 | 
			
		||||
func (l *Conn) NTLMBind(domain, username, password string) error {
 | 
			
		||||
	req := &NTLMBindRequest{
 | 
			
		||||
		Domain:   domain,
 | 
			
		||||
		Username: username,
 | 
			
		||||
		Password: password,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.NTLMChallengeBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NTLMBindWithHash performs an NTLM Bind with an NTLM hash instead of plaintext password (pass-the-hash)
 | 
			
		||||
func (l *Conn) NTLMBindWithHash(domain, username, hash string) error {
 | 
			
		||||
	req := &NTLMBindRequest{
 | 
			
		||||
		Domain:   domain,
 | 
			
		||||
		Username: username,
 | 
			
		||||
		Hash:     hash,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.NTLMChallengeBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NTLMChallengeBind performs the NTLMSSP bind operation defined in the given request
 | 
			
		||||
func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindResult, error) {
 | 
			
		||||
	if ntlmBindRequest.Password == "" && ntlmBindRequest.Hash == "" {
 | 
			
		||||
		return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.doRequest(ntlmBindRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err = addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
	result := &NTLMBindResult{
 | 
			
		||||
		Controls: make([]Control, 0),
 | 
			
		||||
	}
 | 
			
		||||
	var ntlmsspChallenge []byte
 | 
			
		||||
 | 
			
		||||
	// now find the NTLM Response Message
 | 
			
		||||
	if len(packet.Children) == 2 {
 | 
			
		||||
		if len(packet.Children[1].Children) == 3 {
 | 
			
		||||
			child := packet.Children[1].Children[1]
 | 
			
		||||
			ntlmsspChallenge = child.ByteValue
 | 
			
		||||
			// Check to make sure we got the right message. It will always start with NTLMSSP
 | 
			
		||||
			if !bytes.Equal(ntlmsspChallenge[:7], []byte("NTLMSSP")) {
 | 
			
		||||
				return result, GetLDAPError(packet)
 | 
			
		||||
			}
 | 
			
		||||
			l.Debug.Printf("%d: found ntlmssp challenge", msgCtx.id)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if ntlmsspChallenge != nil {
 | 
			
		||||
		var err error
 | 
			
		||||
		var responseMessage []byte
 | 
			
		||||
		// generate a response message to the challenge with the given Username/Password if password is provided
 | 
			
		||||
		if ntlmBindRequest.Password != "" {
 | 
			
		||||
			responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password)
 | 
			
		||||
		} else if ntlmBindRequest.Hash != "" {
 | 
			
		||||
			responseMessage, err = ntlmssp.ProcessChallengeWithHash(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = fmt.Errorf("need a password or hash to generate reply")
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, fmt.Errorf("parsing ntlm-challenge: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		packet = ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
		packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
 | 
			
		||||
		request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
		request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
		request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
 | 
			
		||||
 | 
			
		||||
		// append the challenge response message as a TagEmbeddedPDV BER value
 | 
			
		||||
		auth := ber.Encode(ber.ClassContext, ber.TypePrimitive, ber.TagEmbeddedPDV, responseMessage, "authentication")
 | 
			
		||||
 | 
			
		||||
		request.AppendChild(auth)
 | 
			
		||||
		packet.AppendChild(request)
 | 
			
		||||
		msgCtx, err = l.sendMessage(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("send message: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		defer l.finishMessage(msgCtx)
 | 
			
		||||
		packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
		}
 | 
			
		||||
		packet, err = packetResponse.ReadPacket()
 | 
			
		||||
		l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("read packet: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = GetLDAPError(packet)
 | 
			
		||||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/go-ldap/ldap/v3/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/go-ldap/ldap/v3/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client knows how to interact with an LDAP server
 | 
			
		||||
type Client interface {
 | 
			
		||||
	Start()
 | 
			
		||||
	StartTLS(*tls.Config) error
 | 
			
		||||
	Close()
 | 
			
		||||
	SetTimeout(time.Duration)
 | 
			
		||||
 | 
			
		||||
	Bind(username, password string) error
 | 
			
		||||
	UnauthenticatedBind(username string) error
 | 
			
		||||
	SimpleBind(*SimpleBindRequest) (*SimpleBindResult, error)
 | 
			
		||||
	ExternalBind() error
 | 
			
		||||
 | 
			
		||||
	Add(*AddRequest) error
 | 
			
		||||
	Del(*DelRequest) error
 | 
			
		||||
	Modify(*ModifyRequest) error
 | 
			
		||||
	ModifyDN(*ModifyDNRequest) error
 | 
			
		||||
 | 
			
		||||
	Compare(dn, attribute, value string) (bool, error)
 | 
			
		||||
	PasswordModify(*PasswordModifyRequest) (*PasswordModifyResult, error)
 | 
			
		||||
 | 
			
		||||
	Search(*SearchRequest) (*SearchResult, error)
 | 
			
		||||
	SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/github.com/go-ldap/ldap/v3/compare.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/go-ldap/ldap/v3/compare.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CompareRequest represents an LDAP CompareRequest operation.
 | 
			
		||||
type CompareRequest struct {
 | 
			
		||||
	DN        string
 | 
			
		||||
	Attribute string
 | 
			
		||||
	Value     string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *CompareRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.DN, "DN"))
 | 
			
		||||
 | 
			
		||||
	ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
 | 
			
		||||
	ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.Attribute, "AttributeDesc"))
 | 
			
		||||
	ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.Value, "AssertionValue"))
 | 
			
		||||
 | 
			
		||||
	pkt.AppendChild(ava)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
 | 
			
		||||
// false with any error that occurs if any.
 | 
			
		||||
func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
 | 
			
		||||
	msgCtx, err := l.doRequest(&CompareRequest{
 | 
			
		||||
		DN:        dn,
 | 
			
		||||
		Attribute: attribute,
 | 
			
		||||
		Value:     value})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationCompareResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
 | 
			
		||||
		switch {
 | 
			
		||||
		case IsErrorWithCode(err, LDAPResultCompareTrue):
 | 
			
		||||
			return true, nil
 | 
			
		||||
		case IsErrorWithCode(err, LDAPResultCompareFalse):
 | 
			
		||||
			return false, nil
 | 
			
		||||
		default:
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								vendor/gopkg.in/ldap.v3/conn.go → vendor/github.com/go-ldap/ldap/v3/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										122
									
								
								vendor/gopkg.in/ldap.v3/conn.go → vendor/github.com/go-ldap/ldap/v3/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -11,7 +11,7 @@ import (
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -112,8 +112,63 @@ var _ Client = &Conn{}
 | 
			
		||||
// multiple places will probably result in undesired behaviour.
 | 
			
		||||
var DefaultTimeout = 60 * time.Second
 | 
			
		||||
 | 
			
		||||
// DialOpt configures DialContext.
 | 
			
		||||
type DialOpt func(*DialContext)
 | 
			
		||||
 | 
			
		||||
// DialWithDialer updates net.Dialer in DialContext.
 | 
			
		||||
func DialWithDialer(d *net.Dialer) DialOpt {
 | 
			
		||||
	return func(dc *DialContext) {
 | 
			
		||||
		dc.d = d
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialWithTLSConfig updates tls.Config in DialContext.
 | 
			
		||||
func DialWithTLSConfig(tc *tls.Config) DialOpt {
 | 
			
		||||
	return func(dc *DialContext) {
 | 
			
		||||
		dc.tc = tc
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialContext contains necessary parameters to dial the given ldap URL.
 | 
			
		||||
type DialContext struct {
 | 
			
		||||
	d  *net.Dialer
 | 
			
		||||
	tc *tls.Config
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
 | 
			
		||||
	if u.Scheme == "ldapi" {
 | 
			
		||||
		if u.Path == "" || u.Path == "/" {
 | 
			
		||||
			u.Path = "/var/run/slapd/ldapi"
 | 
			
		||||
		}
 | 
			
		||||
		return dc.d.Dial("unix", u.Path)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	host, port, err := net.SplitHostPort(u.Host)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// we assume that error is due to missing port
 | 
			
		||||
		host = u.Host
 | 
			
		||||
		port = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch u.Scheme {
 | 
			
		||||
	case "ldap":
 | 
			
		||||
		if port == "" {
 | 
			
		||||
			port = DefaultLdapPort
 | 
			
		||||
		}
 | 
			
		||||
		return dc.d.Dial("tcp", net.JoinHostPort(host, port))
 | 
			
		||||
	case "ldaps":
 | 
			
		||||
		if port == "" {
 | 
			
		||||
			port = DefaultLdapsPort
 | 
			
		||||
		}
 | 
			
		||||
		return tls.DialWithDialer(dc.d, "tcp", net.JoinHostPort(host, port), dc.tc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, fmt.Errorf("Unknown scheme '%s'", u.Scheme)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dial connects to the given address on the given network using net.Dial
 | 
			
		||||
// and then returns a new Conn for the connection.
 | 
			
		||||
// @deprecated Use DialURL instead.
 | 
			
		||||
func Dial(network, addr string) (*Conn, error) {
 | 
			
		||||
	c, err := net.DialTimeout(network, addr, DefaultTimeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -126,6 +181,7 @@ func Dial(network, addr string) (*Conn, error) {
 | 
			
		||||
 | 
			
		||||
// DialTLS connects to the given address on the given network using tls.Dial
 | 
			
		||||
// and then returns a new Conn for the connection.
 | 
			
		||||
// @deprecated Use DialURL instead.
 | 
			
		||||
func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
 | 
			
		||||
	c, err := tls.DialWithDialer(&net.Dialer{Timeout: DefaultTimeout}, network, addr, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -136,40 +192,31 @@ func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
 | 
			
		||||
	return conn, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialURL connects to the given ldap URL vie TCP using tls.Dial or net.Dial if ldaps://
 | 
			
		||||
// or ldap:// specified as protocol. On success a new Conn for the connection
 | 
			
		||||
// is returned.
 | 
			
		||||
func DialURL(addr string) (*Conn, error) {
 | 
			
		||||
 | 
			
		||||
	lurl, err := url.Parse(addr)
 | 
			
		||||
// DialURL connects to the given ldap URL.
 | 
			
		||||
// The following schemas are supported: ldap://, ldaps://, ldapi://.
 | 
			
		||||
// On success a new Conn for the connection is returned.
 | 
			
		||||
func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
 | 
			
		||||
	u, err := url.Parse(addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	host, port, err := net.SplitHostPort(lurl.Host)
 | 
			
		||||
	var dc DialContext
 | 
			
		||||
	for _, opt := range opts {
 | 
			
		||||
		opt(&dc)
 | 
			
		||||
	}
 | 
			
		||||
	if dc.d == nil {
 | 
			
		||||
		dc.d = &net.Dialer{Timeout: DefaultTimeout}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c, err := dc.dial(u)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// we asume that error is due to missing port
 | 
			
		||||
		host = lurl.Host
 | 
			
		||||
		port = ""
 | 
			
		||||
		return nil, NewError(ErrorNetwork, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch lurl.Scheme {
 | 
			
		||||
	case "ldap":
 | 
			
		||||
		if port == "" {
 | 
			
		||||
			port = DefaultLdapPort
 | 
			
		||||
		}
 | 
			
		||||
		return Dial("tcp", net.JoinHostPort(host, port))
 | 
			
		||||
	case "ldaps":
 | 
			
		||||
		if port == "" {
 | 
			
		||||
			port = DefaultLdapsPort
 | 
			
		||||
		}
 | 
			
		||||
		tlsConf := &tls.Config{
 | 
			
		||||
			ServerName: host,
 | 
			
		||||
		}
 | 
			
		||||
		return DialTLS("tcp", net.JoinHostPort(host, port), tlsConf)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, NewError(ErrorNetwork, fmt.Errorf("Unknown scheme '%s'", lurl.Scheme))
 | 
			
		||||
	conn := NewConn(c, u.Scheme == "ldaps")
 | 
			
		||||
	conn.Start()
 | 
			
		||||
	return conn, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewConn returns a new Conn using conn for network I/O.
 | 
			
		||||
@@ -187,9 +234,9 @@ func NewConn(conn net.Conn, isTLS bool) *Conn {
 | 
			
		||||
 | 
			
		||||
// Start initializes goroutines to read responses and process messages
 | 
			
		||||
func (l *Conn) Start() {
 | 
			
		||||
	l.wgClose.Add(1)
 | 
			
		||||
	go l.reader()
 | 
			
		||||
	go l.processMessages()
 | 
			
		||||
	l.wgClose.Add(1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsClosing returns whether or not we're currently closing.
 | 
			
		||||
@@ -274,7 +321,7 @@ func (l *Conn) StartTLS(config *tls.Config) error {
 | 
			
		||||
			l.Close()
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
		l.Debug.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := GetLDAPError(packet); err == nil {
 | 
			
		||||
@@ -343,7 +390,12 @@ func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags)
 | 
			
		||||
			responses: responses,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	l.sendProcessMessage(message)
 | 
			
		||||
	if !l.sendProcessMessage(message) {
 | 
			
		||||
		if l.IsClosing() {
 | 
			
		||||
			return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
 | 
			
		||||
		}
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message for unknown reason"))
 | 
			
		||||
	}
 | 
			
		||||
	return message.Context, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -447,7 +499,7 @@ func (l *Conn) processMessages() {
 | 
			
		||||
					msgCtx.sendResponse(&PacketResponse{message.Packet, nil})
 | 
			
		||||
				} else {
 | 
			
		||||
					log.Printf("Received unexpected message %d, %v", message.MessageID, l.IsClosing())
 | 
			
		||||
					ber.PrintPacket(message.Packet)
 | 
			
		||||
					l.Debug.PrintPacket(message.Packet)
 | 
			
		||||
				}
 | 
			
		||||
			case MessageTimeout:
 | 
			
		||||
				// Handle the timeout by closing the channel
 | 
			
		||||
@@ -490,11 +542,13 @@ func (l *Conn) reader() {
 | 
			
		||||
			// A read error is expected here if we are closing the connection...
 | 
			
		||||
			if !l.IsClosing() {
 | 
			
		||||
				l.closeErr.Store(fmt.Errorf("unable to read LDAP response packet: %s", err))
 | 
			
		||||
				l.Debug.Printf("reader error: %s", err.Error())
 | 
			
		||||
				l.Debug.Printf("reader error: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		addLDAPDescriptions(packet)
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			l.Debug.Printf("descriptions error: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(packet.Children) == 0 {
 | 
			
		||||
			l.Debug.Printf("Received bad ldap packet")
 | 
			
		||||
			continue
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/gopkg.in/ldap.v3/control.go → vendor/github.com/go-ldap/ldap/v3/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/gopkg.in/ldap.v3/control.go → vendor/github.com/go-ldap/ldap/v3/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -63,7 +63,9 @@ func (c *ControlString) Encode() *ber.Packet {
 | 
			
		||||
	if c.Criticality {
 | 
			
		||||
		packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
 | 
			
		||||
	}
 | 
			
		||||
	packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(c.ControlValue), "Control Value"))
 | 
			
		||||
	if c.ControlValue != "" {
 | 
			
		||||
		packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(c.ControlValue), "Control Value"))
 | 
			
		||||
	}
 | 
			
		||||
	return packet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -402,33 +404,26 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
 | 
			
		||||
			if child.Tag == 0 {
 | 
			
		||||
				//Warning
 | 
			
		||||
				warningPacket := child.Children[0]
 | 
			
		||||
				packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
 | 
			
		||||
				val, err := ber.ParseInt64(warningPacket.Data.Bytes())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, fmt.Errorf("failed to decode data bytes: %s", err)
 | 
			
		||||
				}
 | 
			
		||||
				val, ok := packet.Value.(int64)
 | 
			
		||||
				if ok {
 | 
			
		||||
					if warningPacket.Tag == 0 {
 | 
			
		||||
						//timeBeforeExpiration
 | 
			
		||||
						c.Expire = val
 | 
			
		||||
						warningPacket.Value = c.Expire
 | 
			
		||||
					} else if warningPacket.Tag == 1 {
 | 
			
		||||
						//graceAuthNsRemaining
 | 
			
		||||
						c.Grace = val
 | 
			
		||||
						warningPacket.Value = c.Grace
 | 
			
		||||
					}
 | 
			
		||||
				if warningPacket.Tag == 0 {
 | 
			
		||||
					//timeBeforeExpiration
 | 
			
		||||
					c.Expire = val
 | 
			
		||||
					warningPacket.Value = c.Expire
 | 
			
		||||
				} else if warningPacket.Tag == 1 {
 | 
			
		||||
					//graceAuthNsRemaining
 | 
			
		||||
					c.Grace = val
 | 
			
		||||
					warningPacket.Value = c.Grace
 | 
			
		||||
				}
 | 
			
		||||
			} else if child.Tag == 1 {
 | 
			
		||||
				// Error
 | 
			
		||||
				packet, err := ber.DecodePacketErr(child.Data.Bytes())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, fmt.Errorf("failed to decode data bytes: %s", err)
 | 
			
		||||
				}
 | 
			
		||||
				val, ok := packet.Value.(int8)
 | 
			
		||||
				if !ok {
 | 
			
		||||
					// what to do?
 | 
			
		||||
					val = -1
 | 
			
		||||
				bs := child.Data.Bytes()
 | 
			
		||||
				if len(bs) != 1 || bs[0] > 8 {
 | 
			
		||||
					return nil, fmt.Errorf("failed to decode data bytes: %s", "invalid PasswordPolicyResponse enum value")
 | 
			
		||||
				}
 | 
			
		||||
				val := int8(bs[0])
 | 
			
		||||
				c.Error = val
 | 
			
		||||
				child.Value = c.Error
 | 
			
		||||
				c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error]
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/gopkg.in/ldap.v3/debug.go → vendor/github.com/go-ldap/ldap/v3/debug.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/gopkg.in/ldap.v3/debug.go → vendor/github.com/go-ldap/ldap/v3/debug.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,20 +3,26 @@ package ldap
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// debugging type
 | 
			
		||||
//     - has a Printf method to write the debug output
 | 
			
		||||
type debugging bool
 | 
			
		||||
 | 
			
		||||
// write debug output
 | 
			
		||||
// Enable controls debugging mode.
 | 
			
		||||
func (debug *debugging) Enable(b bool) {
 | 
			
		||||
	*debug = debugging(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf writes debug output.
 | 
			
		||||
func (debug debugging) Printf(format string, args ...interface{}) {
 | 
			
		||||
	if debug {
 | 
			
		||||
		log.Printf(format, args...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrintPacket dumps a packet.
 | 
			
		||||
func (debug debugging) PrintPacket(packet *ber.Packet) {
 | 
			
		||||
	if debug {
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
							
								
								
									
										59
									
								
								vendor/github.com/go-ldap/ldap/v3/del.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/go-ldap/ldap/v3/del.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DelRequest implements an LDAP deletion request
 | 
			
		||||
type DelRequest struct {
 | 
			
		||||
	// DN is the name of the directory entry to delete
 | 
			
		||||
	DN string
 | 
			
		||||
	// Controls hold optional controls to send with the request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *DelRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypePrimitive, ApplicationDelRequest, req.DN, "Del Request")
 | 
			
		||||
	pkt.Data.Write([]byte(req.DN))
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDelRequest creates a delete request for the given DN and controls
 | 
			
		||||
func NewDelRequest(DN string, Controls []Control) *DelRequest {
 | 
			
		||||
	return &DelRequest{
 | 
			
		||||
		DN:       DN,
 | 
			
		||||
		Controls: Controls,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Del executes the given delete request
 | 
			
		||||
func (l *Conn) Del(delRequest *DelRequest) error {
 | 
			
		||||
	msgCtx, err := l.doRequest(delRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationDelResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/gopkg.in/ldap.v3/dn.go → vendor/github.com/go-ldap/ldap/v3/dn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/gopkg.in/ldap.v3/dn.go → vendor/github.com/go-ldap/ldap/v3/dn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,44 +1,3 @@
 | 
			
		||||
// File contains DN parsing functionality
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4514
 | 
			
		||||
//
 | 
			
		||||
//   distinguishedName = [ relativeDistinguishedName
 | 
			
		||||
//         *( COMMA relativeDistinguishedName ) ]
 | 
			
		||||
//     relativeDistinguishedName = attributeTypeAndValue
 | 
			
		||||
//         *( PLUS attributeTypeAndValue )
 | 
			
		||||
//     attributeTypeAndValue = attributeType EQUALS attributeValue
 | 
			
		||||
//     attributeType = descr / numericoid
 | 
			
		||||
//     attributeValue = string / hexstring
 | 
			
		||||
//
 | 
			
		||||
//     ; The following characters are to be escaped when they appear
 | 
			
		||||
//     ; in the value to be encoded: ESC, one of <escaped>, leading
 | 
			
		||||
//     ; SHARP or SPACE, trailing SPACE, and NULL.
 | 
			
		||||
//     string =   [ ( leadchar / pair ) [ *( stringchar / pair )
 | 
			
		||||
//        ( trailchar / pair ) ] ]
 | 
			
		||||
//
 | 
			
		||||
//     leadchar = LUTF1 / UTFMB
 | 
			
		||||
//     LUTF1 = %x01-1F / %x21 / %x24-2A / %x2D-3A /
 | 
			
		||||
//        %x3D / %x3F-5B / %x5D-7F
 | 
			
		||||
//
 | 
			
		||||
//     trailchar  = TUTF1 / UTFMB
 | 
			
		||||
//     TUTF1 = %x01-1F / %x21 / %x23-2A / %x2D-3A /
 | 
			
		||||
//        %x3D / %x3F-5B / %x5D-7F
 | 
			
		||||
//
 | 
			
		||||
//     stringchar = SUTF1 / UTFMB
 | 
			
		||||
//     SUTF1 = %x01-21 / %x23-2A / %x2D-3A /
 | 
			
		||||
//        %x3D / %x3F-5B / %x5D-7F
 | 
			
		||||
//
 | 
			
		||||
//     pair = ESC ( ESC / special / hexpair )
 | 
			
		||||
//     special = escaped / SPACE / SHARP / EQUALS
 | 
			
		||||
//     escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
 | 
			
		||||
//     hexstring = SHARP 1*hexpair
 | 
			
		||||
//     hexpair = HEX HEX
 | 
			
		||||
//
 | 
			
		||||
//  where the productions <descr>, <numericoid>, <COMMA>, <DQUOTE>,
 | 
			
		||||
//  <EQUALS>, <ESC>, <HEX>, <LANGLE>, <NULL>, <PLUS>, <RANGLE>, <SEMI>,
 | 
			
		||||
//  <SPACE>, <SHARP>, and <UTFMB> are defined in [RFC4512].
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@@ -48,7 +7,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AttributeTypeAndValue represents an attributeTypeAndValue from https://tools.ietf.org/html/rfc4514
 | 
			
		||||
@@ -69,7 +28,8 @@ type DN struct {
 | 
			
		||||
	RDNs []*RelativeDN
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDN returns a distinguishedName or an error
 | 
			
		||||
// ParseDN returns a distinguishedName or an error.
 | 
			
		||||
// The function respects https://tools.ietf.org/html/rfc4514
 | 
			
		||||
func ParseDN(str string) (*DN, error) {
 | 
			
		||||
	dn := new(DN)
 | 
			
		||||
	dn.RDNs = make([]*RelativeDN, 0)
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/gopkg.in/ldap.v3/doc.go → vendor/github.com/go-ldap/ldap/v3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/gopkg.in/ldap.v3/doc.go → vendor/github.com/go-ldap/ldap/v3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
									
										37
									
								
								vendor/gopkg.in/ldap.v3/error.go → vendor/github.com/go-ldap/ldap/v3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/gopkg.in/ldap.v3/error.go → vendor/github.com/go-ldap/ldap/v3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,7 +3,7 @@ package ldap
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LDAP Result Codes
 | 
			
		||||
@@ -184,6 +184,8 @@ type Error struct {
 | 
			
		||||
	ResultCode uint16
 | 
			
		||||
	// MatchedDN is the matchedDN returned if any
 | 
			
		||||
	MatchedDN string
 | 
			
		||||
	// Packet is the returned packet if any
 | 
			
		||||
	Packet *ber.Packet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *Error) Error() string {
 | 
			
		||||
@@ -196,22 +198,28 @@ func (e *Error) Error() string {
 | 
			
		||||
func GetLDAPError(packet *ber.Packet) error {
 | 
			
		||||
	if packet == nil {
 | 
			
		||||
		return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")}
 | 
			
		||||
	} else if len(packet.Children) >= 2 {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(packet.Children) >= 2 {
 | 
			
		||||
		response := packet.Children[1]
 | 
			
		||||
		if response == nil {
 | 
			
		||||
			return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
 | 
			
		||||
			return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet}
 | 
			
		||||
		}
 | 
			
		||||
		if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
 | 
			
		||||
			resultCode := uint16(response.Children[0].Value.(int64))
 | 
			
		||||
			if resultCode == 0 { // No error
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
 | 
			
		||||
				Err: fmt.Errorf("%s", response.Children[2].Value.(string))}
 | 
			
		||||
			return &Error{
 | 
			
		||||
				ResultCode: resultCode,
 | 
			
		||||
				MatchedDN:  response.Children[1].Value.(string),
 | 
			
		||||
				Err:        fmt.Errorf("%s", response.Children[2].Value.(string)),
 | 
			
		||||
				Packet:     packet,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
 | 
			
		||||
	return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format"), Packet: packet}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewError creates an LDAP error with the given code and underlying error
 | 
			
		||||
@@ -219,8 +227,8 @@ func NewError(resultCode uint16, err error) error {
 | 
			
		||||
	return &Error{ResultCode: resultCode, Err: err}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
 | 
			
		||||
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
 | 
			
		||||
// IsErrorAnyOf returns true if the given error is an LDAP error with any one of the given result codes
 | 
			
		||||
func IsErrorAnyOf(err error, codes ...uint16) bool {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
@@ -230,5 +238,16 @@ func IsErrorWithCode(err error, desiredResultCode uint16) bool {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return serverError.ResultCode == desiredResultCode
 | 
			
		||||
	for _, code := range codes {
 | 
			
		||||
		if serverError.ResultCode == code {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
 | 
			
		||||
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
 | 
			
		||||
	return IsErrorAnyOf(err, desiredResultCode)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										176
									
								
								vendor/gopkg.in/ldap.v3/filter.go → vendor/github.com/go-ldap/ldap/v3/filter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										176
									
								
								vendor/gopkg.in/ldap.v3/filter.go → vendor/github.com/go-ldap/ldap/v3/filter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,10 +5,12 @@ import (
 | 
			
		||||
	hexpac "encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Filter choices
 | 
			
		||||
@@ -69,6 +71,8 @@ var MatchingRuleAssertionMap = map[uint64]string{
 | 
			
		||||
	MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _SymbolAny = []byte{'*'}
 | 
			
		||||
 | 
			
		||||
// CompileFilter converts a string representation of a filter into a BER-encoded packet
 | 
			
		||||
func CompileFilter(filter string) (*ber.Packet, error) {
 | 
			
		||||
	if len(filter) == 0 || filter[0] != '(' {
 | 
			
		||||
@@ -88,74 +92,75 @@ func CompileFilter(filter string) (*ber.Packet, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecompileFilter converts a packet representation of a filter into a string representation
 | 
			
		||||
func DecompileFilter(packet *ber.Packet) (ret string, err error) {
 | 
			
		||||
func DecompileFilter(packet *ber.Packet) (_ string, err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if r := recover(); r != nil {
 | 
			
		||||
			err = NewError(ErrorFilterDecompile, errors.New("ldap: error decompiling filter"))
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	ret = "("
 | 
			
		||||
	err = nil
 | 
			
		||||
 | 
			
		||||
	buf := bytes.NewBuffer(nil)
 | 
			
		||||
	buf.WriteByte('(')
 | 
			
		||||
	childStr := ""
 | 
			
		||||
 | 
			
		||||
	switch packet.Tag {
 | 
			
		||||
	case FilterAnd:
 | 
			
		||||
		ret += "&"
 | 
			
		||||
		buf.WriteByte('&')
 | 
			
		||||
		for _, child := range packet.Children {
 | 
			
		||||
			childStr, err = DecompileFilter(child)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			ret += childStr
 | 
			
		||||
			buf.WriteString(childStr)
 | 
			
		||||
		}
 | 
			
		||||
	case FilterOr:
 | 
			
		||||
		ret += "|"
 | 
			
		||||
		buf.WriteByte('|')
 | 
			
		||||
		for _, child := range packet.Children {
 | 
			
		||||
			childStr, err = DecompileFilter(child)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			ret += childStr
 | 
			
		||||
			buf.WriteString(childStr)
 | 
			
		||||
		}
 | 
			
		||||
	case FilterNot:
 | 
			
		||||
		ret += "!"
 | 
			
		||||
		buf.WriteByte('!')
 | 
			
		||||
		childStr, err = DecompileFilter(packet.Children[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ret += childStr
 | 
			
		||||
		buf.WriteString(childStr)
 | 
			
		||||
 | 
			
		||||
	case FilterSubstrings:
 | 
			
		||||
		ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
			
		||||
		ret += "="
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
 | 
			
		||||
		buf.WriteByte('=')
 | 
			
		||||
		for i, child := range packet.Children[1].Children {
 | 
			
		||||
			if i == 0 && child.Tag != FilterSubstringsInitial {
 | 
			
		||||
				ret += "*"
 | 
			
		||||
				buf.Write(_SymbolAny)
 | 
			
		||||
			}
 | 
			
		||||
			ret += EscapeFilter(ber.DecodeString(child.Data.Bytes()))
 | 
			
		||||
			buf.WriteString(EscapeFilter(ber.DecodeString(child.Data.Bytes())))
 | 
			
		||||
			if child.Tag != FilterSubstringsFinal {
 | 
			
		||||
				ret += "*"
 | 
			
		||||
				buf.Write(_SymbolAny)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case FilterEqualityMatch:
 | 
			
		||||
		ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
			
		||||
		ret += "="
 | 
			
		||||
		ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
 | 
			
		||||
		buf.WriteByte('=')
 | 
			
		||||
		buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
 | 
			
		||||
	case FilterGreaterOrEqual:
 | 
			
		||||
		ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
			
		||||
		ret += ">="
 | 
			
		||||
		ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
 | 
			
		||||
		buf.WriteString(">=")
 | 
			
		||||
		buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
 | 
			
		||||
	case FilterLessOrEqual:
 | 
			
		||||
		ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
			
		||||
		ret += "<="
 | 
			
		||||
		ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
 | 
			
		||||
		buf.WriteString("<=")
 | 
			
		||||
		buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
 | 
			
		||||
	case FilterPresent:
 | 
			
		||||
		ret += ber.DecodeString(packet.Data.Bytes())
 | 
			
		||||
		ret += "=*"
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Data.Bytes()))
 | 
			
		||||
		buf.WriteString("=*")
 | 
			
		||||
	case FilterApproxMatch:
 | 
			
		||||
		ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
			
		||||
		ret += "~="
 | 
			
		||||
		ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
 | 
			
		||||
		buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
 | 
			
		||||
		buf.WriteString("~=")
 | 
			
		||||
		buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
 | 
			
		||||
	case FilterExtensibleMatch:
 | 
			
		||||
		attr := ""
 | 
			
		||||
		dnAttributes := false
 | 
			
		||||
@@ -176,21 +181,22 @@ func DecompileFilter(packet *ber.Packet) (ret string, err error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(attr) > 0 {
 | 
			
		||||
			ret += attr
 | 
			
		||||
			buf.WriteString(attr)
 | 
			
		||||
		}
 | 
			
		||||
		if dnAttributes {
 | 
			
		||||
			ret += ":dn"
 | 
			
		||||
			buf.WriteString(":dn")
 | 
			
		||||
		}
 | 
			
		||||
		if len(matchingRule) > 0 {
 | 
			
		||||
			ret += ":"
 | 
			
		||||
			ret += matchingRule
 | 
			
		||||
			buf.WriteString(":")
 | 
			
		||||
			buf.WriteString(matchingRule)
 | 
			
		||||
		}
 | 
			
		||||
		ret += ":="
 | 
			
		||||
		ret += EscapeFilter(value)
 | 
			
		||||
		buf.WriteString(":=")
 | 
			
		||||
		buf.WriteString(EscapeFilter(value))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret += ")"
 | 
			
		||||
	return
 | 
			
		||||
	buf.WriteByte(')')
 | 
			
		||||
 | 
			
		||||
	return buf.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func compileFilterSet(filter string, pos int, parent *ber.Packet) (int, error) {
 | 
			
		||||
@@ -253,11 +259,10 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		state := stateReadingAttr
 | 
			
		||||
 | 
			
		||||
		attribute := ""
 | 
			
		||||
		attribute := bytes.NewBuffer(nil)
 | 
			
		||||
		extensibleDNAttributes := false
 | 
			
		||||
		extensibleMatchingRule := ""
 | 
			
		||||
		condition := ""
 | 
			
		||||
		extensibleMatchingRule := bytes.NewBuffer(nil)
 | 
			
		||||
		condition := bytes.NewBuffer(nil)
 | 
			
		||||
 | 
			
		||||
		for newPos < len(filter) {
 | 
			
		||||
			remainingFilter := filter[newPos:]
 | 
			
		||||
@@ -324,7 +329,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
 | 
			
		||||
				// Still reading the attribute name
 | 
			
		||||
				default:
 | 
			
		||||
					attribute += fmt.Sprintf("%c", currentRune)
 | 
			
		||||
					attribute.WriteRune(currentRune)
 | 
			
		||||
					newPos += currentWidth
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@@ -338,13 +343,13 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
 | 
			
		||||
				// Still reading the matching rule oid
 | 
			
		||||
				default:
 | 
			
		||||
					extensibleMatchingRule += fmt.Sprintf("%c", currentRune)
 | 
			
		||||
					extensibleMatchingRule.WriteRune(currentRune)
 | 
			
		||||
					newPos += currentWidth
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case stateReadingCondition:
 | 
			
		||||
				// append to the condition
 | 
			
		||||
				condition += fmt.Sprintf("%c", currentRune)
 | 
			
		||||
				condition.WriteRune(currentRune)
 | 
			
		||||
				newPos += currentWidth
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -368,17 +373,17 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
			// }
 | 
			
		||||
 | 
			
		||||
			// Include the matching rule oid, if specified
 | 
			
		||||
			if len(extensibleMatchingRule) > 0 {
 | 
			
		||||
				packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule, MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule]))
 | 
			
		||||
			if extensibleMatchingRule.Len() > 0 {
 | 
			
		||||
				packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule.String(), MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule]))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Include the attribute, if specified
 | 
			
		||||
			if len(attribute) > 0 {
 | 
			
		||||
				packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionType, attribute, MatchingRuleAssertionMap[MatchingRuleAssertionType]))
 | 
			
		||||
			if attribute.Len() > 0 {
 | 
			
		||||
				packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionType, attribute.String(), MatchingRuleAssertionMap[MatchingRuleAssertionType]))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Add the value (only required child)
 | 
			
		||||
			encodedString, encodeErr := escapedStringToEncodedBytes(condition)
 | 
			
		||||
			encodedString, encodeErr := decodeEscapedSymbols(condition.Bytes())
 | 
			
		||||
			if encodeErr != nil {
 | 
			
		||||
				return packet, newPos, encodeErr
 | 
			
		||||
			}
 | 
			
		||||
@@ -389,16 +394,16 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
				packet.AppendChild(ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionDNAttributes, extensibleDNAttributes, MatchingRuleAssertionMap[MatchingRuleAssertionDNAttributes]))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case packet.Tag == FilterEqualityMatch && condition == "*":
 | 
			
		||||
			packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute, FilterMap[FilterPresent])
 | 
			
		||||
		case packet.Tag == FilterEqualityMatch && strings.Contains(condition, "*"):
 | 
			
		||||
			packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
 | 
			
		||||
		case packet.Tag == FilterEqualityMatch && bytes.Equal(condition.Bytes(), _SymbolAny):
 | 
			
		||||
			packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute.String(), FilterMap[FilterPresent])
 | 
			
		||||
		case packet.Tag == FilterEqualityMatch && bytes.Index(condition.Bytes(), _SymbolAny) > -1:
 | 
			
		||||
			packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute.String(), "Attribute"))
 | 
			
		||||
			packet.Tag = FilterSubstrings
 | 
			
		||||
			packet.Description = FilterMap[uint64(packet.Tag)]
 | 
			
		||||
			seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Substrings")
 | 
			
		||||
			parts := strings.Split(condition, "*")
 | 
			
		||||
			parts := bytes.Split(condition.Bytes(), _SymbolAny)
 | 
			
		||||
			for i, part := range parts {
 | 
			
		||||
				if part == "" {
 | 
			
		||||
				if len(part) == 0 {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				var tag ber.Tag
 | 
			
		||||
@@ -410,7 +415,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
				default:
 | 
			
		||||
					tag = FilterSubstringsAny
 | 
			
		||||
				}
 | 
			
		||||
				encodedString, encodeErr := escapedStringToEncodedBytes(part)
 | 
			
		||||
				encodedString, encodeErr := decodeEscapedSymbols(part)
 | 
			
		||||
				if encodeErr != nil {
 | 
			
		||||
					return packet, newPos, encodeErr
 | 
			
		||||
				}
 | 
			
		||||
@@ -418,11 +423,11 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
			}
 | 
			
		||||
			packet.AppendChild(seq)
 | 
			
		||||
		default:
 | 
			
		||||
			encodedString, encodeErr := escapedStringToEncodedBytes(condition)
 | 
			
		||||
			encodedString, encodeErr := decodeEscapedSymbols(condition.Bytes())
 | 
			
		||||
			if encodeErr != nil {
 | 
			
		||||
				return packet, newPos, encodeErr
 | 
			
		||||
			}
 | 
			
		||||
			packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
 | 
			
		||||
			packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute.String(), "Attribute"))
 | 
			
		||||
			packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -432,34 +437,51 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
 | 
			
		||||
func escapedStringToEncodedBytes(escapedString string) (string, error) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	i := 0
 | 
			
		||||
	for i < len(escapedString) {
 | 
			
		||||
		currentRune, currentWidth := utf8.DecodeRuneInString(escapedString[i:])
 | 
			
		||||
		if currentRune == utf8.RuneError {
 | 
			
		||||
			return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", i))
 | 
			
		||||
func decodeEscapedSymbols(src []byte) (string, error) {
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		buffer  bytes.Buffer
 | 
			
		||||
		offset  int
 | 
			
		||||
		reader  = bytes.NewReader(src)
 | 
			
		||||
		byteHex []byte
 | 
			
		||||
		byteVal []byte
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		runeVal, runeSize, err := reader.ReadRune()
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			return buffer.String(), nil
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: failed to read filter: %v", err))
 | 
			
		||||
		} else if runeVal == unicode.ReplacementChar {
 | 
			
		||||
			return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", offset))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Check for escaped hex characters and convert them to their literal value for transport.
 | 
			
		||||
		if currentRune == '\\' {
 | 
			
		||||
		if runeVal == '\\' {
 | 
			
		||||
			// http://tools.ietf.org/search/rfc4515
 | 
			
		||||
			// \ (%x5C) is not a valid character unless it is followed by two HEX characters due to not
 | 
			
		||||
			// being a member of UTF1SUBSET.
 | 
			
		||||
			if i+2 > len(escapedString) {
 | 
			
		||||
				return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
 | 
			
		||||
			if byteHex == nil {
 | 
			
		||||
				byteHex = make([]byte, 2)
 | 
			
		||||
				byteVal = make([]byte, 1)
 | 
			
		||||
			}
 | 
			
		||||
			escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3])
 | 
			
		||||
			if decodeErr != nil {
 | 
			
		||||
				return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
 | 
			
		||||
 | 
			
		||||
			if _, err := io.ReadFull(reader, byteHex); err != nil {
 | 
			
		||||
				if err == io.ErrUnexpectedEOF {
 | 
			
		||||
					return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
 | 
			
		||||
				}
 | 
			
		||||
				return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: invalid characters for escape in filter: %v", err))
 | 
			
		||||
			}
 | 
			
		||||
			buffer.WriteByte(escByte[0])
 | 
			
		||||
			i += 2 // +1 from end of loop, so 3 total for \xx.
 | 
			
		||||
 | 
			
		||||
			if _, err := hexpac.Decode(byteVal, byteHex); err != nil {
 | 
			
		||||
				return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: invalid characters for escape in filter: %v", err))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer.Write(byteVal)
 | 
			
		||||
		} else {
 | 
			
		||||
			buffer.WriteRune(currentRune)
 | 
			
		||||
			buffer.WriteRune(runeVal)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i += currentWidth
 | 
			
		||||
		offset += runeSize
 | 
			
		||||
	}
 | 
			
		||||
	return buffer.String(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/github.com/go-ldap/ldap/v3/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/go-ldap/ldap/v3/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
module github.com/go-ldap/ldap/v3
 | 
			
		||||
 | 
			
		||||
go 1.13
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c
 | 
			
		||||
	github.com/go-asn1-ber/asn1-ber v1.5.1
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 // indirect
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/go-ldap/ldap/v3/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/go-ldap/ldap/v3/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
 | 
			
		||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
							
								
								
									
										53
									
								
								vendor/gopkg.in/ldap.v3/ldap.go → vendor/github.com/go-ldap/ldap/v3/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								vendor/gopkg.in/ldap.v3/ldap.go → vendor/github.com/go-ldap/ldap/v3/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,12 +1,11 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LDAP Application Codes
 | 
			
		||||
@@ -87,7 +86,7 @@ var BeheraPasswordPolicyErrorMap = map[int8]string{
 | 
			
		||||
func addLDAPDescriptions(packet *ber.Packet) (err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if r := recover(); r != nil {
 | 
			
		||||
			err = NewError(ErrorDebugging, errors.New("ldap: cannot process packet to add descriptions"))
 | 
			
		||||
			err = NewError(ErrorDebugging, fmt.Errorf("ldap: cannot process packet to add descriptions: %s", r))
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	packet.Description = "LDAP Response"
 | 
			
		||||
@@ -224,32 +223,26 @@ func addControlDescriptions(packet *ber.Packet) error {
 | 
			
		||||
				if child.Tag == 0 {
 | 
			
		||||
					//Warning
 | 
			
		||||
					warningPacket := child.Children[0]
 | 
			
		||||
					packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
 | 
			
		||||
					val, err := ber.ParseInt64(warningPacket.Data.Bytes())
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return fmt.Errorf("failed to decode data bytes: %s", err)
 | 
			
		||||
					}
 | 
			
		||||
					val, ok := packet.Value.(int64)
 | 
			
		||||
					if ok {
 | 
			
		||||
						if warningPacket.Tag == 0 {
 | 
			
		||||
							//timeBeforeExpiration
 | 
			
		||||
							value.Description += " (TimeBeforeExpiration)"
 | 
			
		||||
							warningPacket.Value = val
 | 
			
		||||
						} else if warningPacket.Tag == 1 {
 | 
			
		||||
							//graceAuthNsRemaining
 | 
			
		||||
							value.Description += " (GraceAuthNsRemaining)"
 | 
			
		||||
							warningPacket.Value = val
 | 
			
		||||
						}
 | 
			
		||||
					if warningPacket.Tag == 0 {
 | 
			
		||||
						//timeBeforeExpiration
 | 
			
		||||
						value.Description += " (TimeBeforeExpiration)"
 | 
			
		||||
						warningPacket.Value = val
 | 
			
		||||
					} else if warningPacket.Tag == 1 {
 | 
			
		||||
						//graceAuthNsRemaining
 | 
			
		||||
						value.Description += " (GraceAuthNsRemaining)"
 | 
			
		||||
						warningPacket.Value = val
 | 
			
		||||
					}
 | 
			
		||||
				} else if child.Tag == 1 {
 | 
			
		||||
					// Error
 | 
			
		||||
					packet, err := ber.DecodePacketErr(child.Data.Bytes())
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return fmt.Errorf("failed to decode data bytes: %s", err)
 | 
			
		||||
					}
 | 
			
		||||
					val, ok := packet.Value.(int8)
 | 
			
		||||
					if !ok {
 | 
			
		||||
						val = -1
 | 
			
		||||
					bs := child.Data.Bytes()
 | 
			
		||||
					if len(bs) != 1 || bs[0] > 8 {
 | 
			
		||||
						return fmt.Errorf("failed to decode data bytes: %s", "invalid PasswordPolicyResponse enum value")
 | 
			
		||||
					}
 | 
			
		||||
					val := int8(bs[0])
 | 
			
		||||
					child.Description = "Error"
 | 
			
		||||
					child.Value = val
 | 
			
		||||
				}
 | 
			
		||||
@@ -270,10 +263,18 @@ func addRequestDescriptions(packet *ber.Packet) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error {
 | 
			
		||||
	err := GetLDAPError(packet)
 | 
			
		||||
	packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[err.(*Error).ResultCode] + ")"
 | 
			
		||||
	packet.Children[1].Children[1].Description = "Matched DN (" + err.(*Error).MatchedDN + ")"
 | 
			
		||||
	packet.Children[1].Children[2].Description = "Error Message"
 | 
			
		||||
	resultCode := uint16(LDAPResultSuccess)
 | 
			
		||||
	matchedDN := ""
 | 
			
		||||
	description := "Success"
 | 
			
		||||
	if err := GetLDAPError(packet); err != nil {
 | 
			
		||||
		resultCode = err.(*Error).ResultCode
 | 
			
		||||
		matchedDN = err.(*Error).MatchedDN
 | 
			
		||||
		description = "Error Message"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
 | 
			
		||||
	packet.Children[1].Children[1].Description = "Matched DN (" + matchedDN + ")"
 | 
			
		||||
	packet.Children[1].Children[2].Description = description
 | 
			
		||||
	if len(packet.Children[1].Children) > 3 {
 | 
			
		||||
		packet.Children[1].Children[3].Description = "Referral"
 | 
			
		||||
	}
 | 
			
		||||
							
								
								
									
										80
									
								
								vendor/github.com/go-ldap/ldap/v3/moddn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								vendor/github.com/go-ldap/ldap/v3/moddn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ModifyDNRequest holds the request to modify a DN
 | 
			
		||||
type ModifyDNRequest struct {
 | 
			
		||||
	DN           string
 | 
			
		||||
	NewRDN       string
 | 
			
		||||
	DeleteOldRDN bool
 | 
			
		||||
	NewSuperior  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewModifyDNRequest creates a new request which can be passed to ModifyDN().
 | 
			
		||||
//
 | 
			
		||||
// To move an object in the tree, set the "newSup" to the new parent entry DN. Use an
 | 
			
		||||
// empty string for just changing the object's RDN.
 | 
			
		||||
//
 | 
			
		||||
// For moving the object without renaming, the "rdn" must be the first
 | 
			
		||||
// RDN of the given DN.
 | 
			
		||||
//
 | 
			
		||||
// A call like
 | 
			
		||||
//   mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
 | 
			
		||||
// will setup the request to just rename uid=someone,dc=example,dc=org to
 | 
			
		||||
// uid=newname,dc=example,dc=org.
 | 
			
		||||
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
 | 
			
		||||
	return &ModifyDNRequest{
 | 
			
		||||
		DN:           dn,
 | 
			
		||||
		NewRDN:       rdn,
 | 
			
		||||
		DeleteOldRDN: delOld,
 | 
			
		||||
		NewSuperior:  newSup,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *ModifyDNRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.DN, "DN"))
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.NewRDN, "New RDN"))
 | 
			
		||||
	if req.DeleteOldRDN {
 | 
			
		||||
		buf := []byte{0xff}
 | 
			
		||||
		pkt.AppendChild(ber.NewString(ber.ClassUniversal,ber.TypePrimitive,ber.TagBoolean, string(buf),"Delete old RDN"))
 | 
			
		||||
	}else{
 | 
			
		||||
		pkt.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, req.DeleteOldRDN, "Delete old RDN"))
 | 
			
		||||
	}  
 | 
			
		||||
	if req.NewSuperior != "" {
 | 
			
		||||
		pkt.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.NewSuperior, "New Superior"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument
 | 
			
		||||
// to NewModifyDNRequest() is not "").
 | 
			
		||||
func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
 | 
			
		||||
	msgCtx, err := l.doRequest(m)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationModifyDNResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								vendor/github.com/go-ldap/ldap/v3/modify.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								vendor/github.com/go-ldap/ldap/v3/modify.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Change operation choices
 | 
			
		||||
const (
 | 
			
		||||
	AddAttribute       = 0
 | 
			
		||||
	DeleteAttribute    = 1
 | 
			
		||||
	ReplaceAttribute   = 2
 | 
			
		||||
	IncrementAttribute = 3 // (https://tools.ietf.org/html/rfc4525)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PartialAttribute for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type PartialAttribute struct {
 | 
			
		||||
	// Type is the type of the partial attribute
 | 
			
		||||
	Type string
 | 
			
		||||
	// Vals are the values of the partial attribute
 | 
			
		||||
	Vals []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PartialAttribute) encode() *ber.Packet {
 | 
			
		||||
	seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
 | 
			
		||||
	seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.Type, "Type"))
 | 
			
		||||
	set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
 | 
			
		||||
	for _, value := range p.Vals {
 | 
			
		||||
		set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
 | 
			
		||||
	}
 | 
			
		||||
	seq.AppendChild(set)
 | 
			
		||||
	return seq
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Change for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type Change struct {
 | 
			
		||||
	// Operation is the type of change to be made
 | 
			
		||||
	Operation uint
 | 
			
		||||
	// Modification is the attribute to be modified
 | 
			
		||||
	Modification PartialAttribute
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Change) encode() *ber.Packet {
 | 
			
		||||
	change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
 | 
			
		||||
	change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(c.Operation), "Operation"))
 | 
			
		||||
	change.AppendChild(c.Modification.encode())
 | 
			
		||||
	return change
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type ModifyRequest struct {
 | 
			
		||||
	// DN is the distinguishedName of the directory entry to modify
 | 
			
		||||
	DN string
 | 
			
		||||
	// Changes contain the attributes to modify
 | 
			
		||||
	Changes []Change
 | 
			
		||||
	// Controls hold optional controls to send with the request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add appends the given attribute to the list of changes to be made
 | 
			
		||||
func (req *ModifyRequest) Add(attrType string, attrVals []string) {
 | 
			
		||||
	req.appendChange(AddAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete appends the given attribute to the list of changes to be made
 | 
			
		||||
func (req *ModifyRequest) Delete(attrType string, attrVals []string) {
 | 
			
		||||
	req.appendChange(DeleteAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Replace appends the given attribute to the list of changes to be made
 | 
			
		||||
func (req *ModifyRequest) Replace(attrType string, attrVals []string) {
 | 
			
		||||
	req.appendChange(ReplaceAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Increment appends the given attribute to the list of changes to be made
 | 
			
		||||
func (req *ModifyRequest) Increment(attrType string, attrVal string) {
 | 
			
		||||
	req.appendChange(IncrementAttribute, attrType, []string{attrVal})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *ModifyRequest) appendChange(operation uint, attrType string, attrVals []string) {
 | 
			
		||||
	req.Changes = append(req.Changes, Change{operation, PartialAttribute{Type: attrType, Vals: attrVals}})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *ModifyRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.DN, "DN"))
 | 
			
		||||
	changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
 | 
			
		||||
	for _, change := range req.Changes {
 | 
			
		||||
		changes.AppendChild(change.encode())
 | 
			
		||||
	}
 | 
			
		||||
	pkt.AppendChild(changes)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewModifyRequest creates a modify request for the given DN
 | 
			
		||||
func NewModifyRequest(dn string, controls []Control) *ModifyRequest {
 | 
			
		||||
	return &ModifyRequest{
 | 
			
		||||
		DN:       dn,
 | 
			
		||||
		Controls: controls,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Modify performs the ModifyRequest
 | 
			
		||||
func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
 | 
			
		||||
	msgCtx, err := l.doRequest(modifyRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationModifyResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,9 @@
 | 
			
		||||
// This file contains the password modify extended operation as specified in rfc 3062
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc3062
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -36,30 +30,33 @@ type PasswordModifyResult struct {
 | 
			
		||||
	Referral string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, passwordModifyOID, "Extended Request Name: Password Modify OID"))
 | 
			
		||||
func (req *PasswordModifyRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, passwordModifyOID, "Extended Request Name: Password Modify OID"))
 | 
			
		||||
 | 
			
		||||
	extendedRequestValue := ber.Encode(ber.ClassContext, ber.TypePrimitive, 1, nil, "Extended Request Value: Password Modify Request")
 | 
			
		||||
	passwordModifyRequestValue := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Password Modify Request")
 | 
			
		||||
	if r.UserIdentity != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, r.UserIdentity, "User Identity"))
 | 
			
		||||
	if req.UserIdentity != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.UserIdentity, "User Identity"))
 | 
			
		||||
	}
 | 
			
		||||
	if r.OldPassword != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, r.OldPassword, "Old Password"))
 | 
			
		||||
	if req.OldPassword != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, req.OldPassword, "Old Password"))
 | 
			
		||||
	}
 | 
			
		||||
	if r.NewPassword != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, r.NewPassword, "New Password"))
 | 
			
		||||
	if req.NewPassword != "" {
 | 
			
		||||
		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, req.NewPassword, "New Password"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	extendedRequestValue.AppendChild(passwordModifyRequestValue)
 | 
			
		||||
	request.AppendChild(extendedRequestValue)
 | 
			
		||||
 | 
			
		||||
	return request, nil
 | 
			
		||||
	pkt.AppendChild(extendedRequestValue)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPasswordModifyRequest creates a new PasswordModifyRequest
 | 
			
		||||
//
 | 
			
		||||
// According to the RFC 3602:
 | 
			
		||||
// According to the RFC 3602 (https://tools.ietf.org/html/rfc3062):
 | 
			
		||||
// userIdentity is a string representing the user associated with the request.
 | 
			
		||||
// This string may or may not be an LDAPDN (RFC 2253).
 | 
			
		||||
// If userIdentity is empty then the operation will act on the user associated
 | 
			
		||||
@@ -84,46 +81,18 @@ func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPasswo
 | 
			
		||||
 | 
			
		||||
// PasswordModify performs the modification request
 | 
			
		||||
func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
 | 
			
		||||
	encodedPasswordModifyRequest, err := passwordModifyRequest.encode()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	packet.AppendChild(encodedPasswordModifyRequest)
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	msgCtx, err := l.doRequest(passwordModifyRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	result := &PasswordModifyResult{}
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	packet, err := l.readPacket(msgCtx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet == nil {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
	result := &PasswordModifyResult{}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationExtendedResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
							
								
								
									
										66
									
								
								vendor/github.com/go-ldap/ldap/v3/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/go-ldap/ldap/v3/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errRespChanClosed = errors.New("ldap: response channel closed")
 | 
			
		||||
	errCouldNotRetMsg = errors.New("ldap: could not retrieve message")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type request interface {
 | 
			
		||||
	appendTo(*ber.Packet) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type requestFunc func(*ber.Packet) error
 | 
			
		||||
 | 
			
		||||
func (f requestFunc) appendTo(p *ber.Packet) error {
 | 
			
		||||
	return f(p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Conn) doRequest(req request) (*messageContext, error) {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	if err := req.appendTo(packet); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		l.Debug.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return msgCtx, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Conn) readPacket(msgCtx *messageContext) (*ber.Packet, error) {
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errRespChanClosed)
 | 
			
		||||
	}
 | 
			
		||||
	packet, err := packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet == nil {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errCouldNotRetMsg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err = addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		l.Debug.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
	return packet, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										176
									
								
								vendor/gopkg.in/ldap.v3/search.go → vendor/github.com/go-ldap/ldap/v3/search.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										176
									
								
								vendor/gopkg.in/ldap.v3/search.go → vendor/github.com/go-ldap/ldap/v3/search.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,58 +1,3 @@
 | 
			
		||||
// File contains Search functionality
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
//
 | 
			
		||||
//         SearchRequest ::= [APPLICATION 3] SEQUENCE {
 | 
			
		||||
//              baseObject      LDAPDN,
 | 
			
		||||
//              scope           ENUMERATED {
 | 
			
		||||
//                   baseObject              (0),
 | 
			
		||||
//                   singleLevel             (1),
 | 
			
		||||
//                   wholeSubtree            (2),
 | 
			
		||||
//                   ...  },
 | 
			
		||||
//              derefAliases    ENUMERATED {
 | 
			
		||||
//                   neverDerefAliases       (0),
 | 
			
		||||
//                   derefInSearching        (1),
 | 
			
		||||
//                   derefFindingBaseObj     (2),
 | 
			
		||||
//                   derefAlways             (3) },
 | 
			
		||||
//              sizeLimit       INTEGER (0 ..  maxInt),
 | 
			
		||||
//              timeLimit       INTEGER (0 ..  maxInt),
 | 
			
		||||
//              typesOnly       BOOLEAN,
 | 
			
		||||
//              filter          Filter,
 | 
			
		||||
//              attributes      AttributeSelection }
 | 
			
		||||
//
 | 
			
		||||
//         AttributeSelection ::= SEQUENCE OF selector LDAPString
 | 
			
		||||
//                         -- The LDAPString is constrained to
 | 
			
		||||
//                         -- <attributeSelector> in Section 4.5.1.8
 | 
			
		||||
//
 | 
			
		||||
//         Filter ::= CHOICE {
 | 
			
		||||
//              and             [0] SET SIZE (1..MAX) OF filter Filter,
 | 
			
		||||
//              or              [1] SET SIZE (1..MAX) OF filter Filter,
 | 
			
		||||
//              not             [2] Filter,
 | 
			
		||||
//              equalityMatch   [3] AttributeValueAssertion,
 | 
			
		||||
//              substrings      [4] SubstringFilter,
 | 
			
		||||
//              greaterOrEqual  [5] AttributeValueAssertion,
 | 
			
		||||
//              lessOrEqual     [6] AttributeValueAssertion,
 | 
			
		||||
//              present         [7] AttributeDescription,
 | 
			
		||||
//              approxMatch     [8] AttributeValueAssertion,
 | 
			
		||||
//              extensibleMatch [9] MatchingRuleAssertion,
 | 
			
		||||
//              ...  }
 | 
			
		||||
//
 | 
			
		||||
//         SubstringFilter ::= SEQUENCE {
 | 
			
		||||
//              type           AttributeDescription,
 | 
			
		||||
//              substrings     SEQUENCE SIZE (1..MAX) OF substring CHOICE {
 | 
			
		||||
//                   initial [0] AssertionValue,  -- can occur at most once
 | 
			
		||||
//                   any     [1] AssertionValue,
 | 
			
		||||
//                   final   [2] AssertionValue } -- can occur at most once
 | 
			
		||||
//              }
 | 
			
		||||
//
 | 
			
		||||
//         MatchingRuleAssertion ::= SEQUENCE {
 | 
			
		||||
//              matchingRule    [1] MatchingRuleId OPTIONAL,
 | 
			
		||||
//              type            [2] AttributeDescription OPTIONAL,
 | 
			
		||||
//              matchValue      [3] AssertionValue,
 | 
			
		||||
//              dnAttributes    [4] BOOLEAN DEFAULT FALSE }
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@@ -61,7 +6,7 @@ import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
	ber "github.com/go-asn1-ber/asn1-ber"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// scope choices
 | 
			
		||||
@@ -132,6 +77,17 @@ func (e *Entry) GetAttributeValues(attribute string) []string {
 | 
			
		||||
	return []string{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEqualFoldAttributeValues returns the values for the named attribute, or an
 | 
			
		||||
// empty list. Attribute matching is done with strings.EqualFold.
 | 
			
		||||
func (e *Entry) GetEqualFoldAttributeValues(attribute string) []string {
 | 
			
		||||
	for _, attr := range e.Attributes {
 | 
			
		||||
		if strings.EqualFold(attribute, attr.Name) {
 | 
			
		||||
			return attr.Values
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []string{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRawAttributeValues returns the byte values for the named attribute, or an empty list
 | 
			
		||||
func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
 | 
			
		||||
	for _, attr := range e.Attributes {
 | 
			
		||||
@@ -142,6 +98,16 @@ func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
 | 
			
		||||
	return [][]byte{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEqualFoldRawAttributeValues returns the byte values for the named attribute, or an empty list
 | 
			
		||||
func (e *Entry) GetEqualFoldRawAttributeValues(attribute string) [][]byte {
 | 
			
		||||
	for _, attr := range e.Attributes {
 | 
			
		||||
		if strings.EqualFold(attr.Name, attribute) {
 | 
			
		||||
			return attr.ByteValues
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return [][]byte{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAttributeValue returns the first value for the named attribute, or ""
 | 
			
		||||
func (e *Entry) GetAttributeValue(attribute string) string {
 | 
			
		||||
	values := e.GetAttributeValues(attribute)
 | 
			
		||||
@@ -151,6 +117,16 @@ func (e *Entry) GetAttributeValue(attribute string) string {
 | 
			
		||||
	return values[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEqualFoldAttributeValue returns the first value for the named attribute, or "".
 | 
			
		||||
// Attribute comparison is done with strings.EqualFold.
 | 
			
		||||
func (e *Entry) GetEqualFoldAttributeValue(attribute string) string {
 | 
			
		||||
	values := e.GetEqualFoldAttributeValues(attribute)
 | 
			
		||||
	if len(values) == 0 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return values[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRawAttributeValue returns the first value for the named attribute, or an empty slice
 | 
			
		||||
func (e *Entry) GetRawAttributeValue(attribute string) []byte {
 | 
			
		||||
	values := e.GetRawAttributeValues(attribute)
 | 
			
		||||
@@ -160,6 +136,15 @@ func (e *Entry) GetRawAttributeValue(attribute string) []byte {
 | 
			
		||||
	return values[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEqualFoldRawAttributeValue returns the first value for the named attribute, or an empty slice
 | 
			
		||||
func (e *Entry) GetEqualFoldRawAttributeValue(attribute string) []byte {
 | 
			
		||||
	values := e.GetEqualFoldRawAttributeValues(attribute)
 | 
			
		||||
	if len(values) == 0 {
 | 
			
		||||
		return []byte{}
 | 
			
		||||
	}
 | 
			
		||||
	return values[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Print outputs a human-readable description
 | 
			
		||||
func (e *Entry) Print() {
 | 
			
		||||
	fmt.Printf("DN: %s\n", e.DN)
 | 
			
		||||
@@ -246,27 +231,33 @@ type SearchRequest struct {
 | 
			
		||||
	Controls     []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SearchRequest) encode() (*ber.Packet, error) {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, s.BaseDN, "Base DN"))
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.Scope), "Scope"))
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.DerefAliases), "Deref Aliases"))
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.SizeLimit), "Size Limit"))
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.TimeLimit), "Time Limit"))
 | 
			
		||||
	request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, s.TypesOnly, "Types Only"))
 | 
			
		||||
func (req *SearchRequest) appendTo(envelope *ber.Packet) error {
 | 
			
		||||
	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
 | 
			
		||||
	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.BaseDN, "Base DN"))
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(req.Scope), "Scope"))
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(req.DerefAliases), "Deref Aliases"))
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(req.SizeLimit), "Size Limit"))
 | 
			
		||||
	pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(req.TimeLimit), "Time Limit"))
 | 
			
		||||
	pkt.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, req.TypesOnly, "Types Only"))
 | 
			
		||||
	// compile and encode filter
 | 
			
		||||
	filterPacket, err := CompileFilter(s.Filter)
 | 
			
		||||
	filterPacket, err := CompileFilter(req.Filter)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	request.AppendChild(filterPacket)
 | 
			
		||||
	pkt.AppendChild(filterPacket)
 | 
			
		||||
	// encode attributes
 | 
			
		||||
	attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
 | 
			
		||||
	for _, attribute := range s.Attributes {
 | 
			
		||||
	for _, attribute := range req.Attributes {
 | 
			
		||||
		attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
 | 
			
		||||
	}
 | 
			
		||||
	request.AppendChild(attributesPacket)
 | 
			
		||||
	return request, nil
 | 
			
		||||
	pkt.AppendChild(attributesPacket)
 | 
			
		||||
 | 
			
		||||
	envelope.AppendChild(pkt)
 | 
			
		||||
	if len(req.Controls) > 0 {
 | 
			
		||||
		envelope.AppendChild(encodeControls(req.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSearchRequest creates a new search request
 | 
			
		||||
@@ -366,22 +357,7 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
 | 
			
		||||
 | 
			
		||||
// Search performs the given search request
 | 
			
		||||
func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	// encode search request
 | 
			
		||||
	encodedSearchRequest, err := searchRequest.encode()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	packet.AppendChild(encodedSearchRequest)
 | 
			
		||||
	// encode search controls
 | 
			
		||||
	if len(searchRequest.Controls) > 0 {
 | 
			
		||||
		packet.AppendChild(encodeControls(searchRequest.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	msgCtx, err := l.doRequest(searchRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -392,24 +368,10 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
 | 
			
		||||
		Referrals: make([]string, 0),
 | 
			
		||||
		Controls:  make([]Control, 0)}
 | 
			
		||||
 | 
			
		||||
	foundSearchResultDone := false
 | 
			
		||||
	for !foundSearchResultDone {
 | 
			
		||||
		l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
		packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
		}
 | 
			
		||||
		packet, err = packetResponse.ReadPacket()
 | 
			
		||||
		l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	for {
 | 
			
		||||
		packet, err := l.readPacket(msgCtx)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if l.Debug {
 | 
			
		||||
			if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			ber.PrintPacket(packet)
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch packet.Children[1].Tag {
 | 
			
		||||
@@ -429,22 +391,20 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
 | 
			
		||||
		case 5:
 | 
			
		||||
			err := GetLDAPError(packet)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
				return result, err
 | 
			
		||||
			}
 | 
			
		||||
			if len(packet.Children) == 3 {
 | 
			
		||||
				for _, child := range packet.Children[2].Children {
 | 
			
		||||
					decodedChild, err := DecodeControl(child)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return nil, fmt.Errorf("failed to decode child control: %s", err)
 | 
			
		||||
						return result, fmt.Errorf("failed to decode child control: %s", err)
 | 
			
		||||
					}
 | 
			
		||||
					result.Controls = append(result.Controls, decodedChild)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			foundSearchResultDone = true
 | 
			
		||||
			return result, nil
 | 
			
		||||
		case 19:
 | 
			
		||||
			result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/gopkg.in/asn1-ber.v1/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/gopkg.in/asn1-ber.v1/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
			
		||||
language: go
 | 
			
		||||
go:
 | 
			
		||||
    - 1.2
 | 
			
		||||
    - 1.3
 | 
			
		||||
    - 1.4
 | 
			
		||||
    - 1.5
 | 
			
		||||
    - tip
 | 
			
		||||
go_import_path: gopkg.in/asn-ber.v1
 | 
			
		||||
install:
 | 
			
		||||
    - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
 | 
			
		||||
    - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
 | 
			
		||||
    - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
 | 
			
		||||
    - go build -v ./...
 | 
			
		||||
script:
 | 
			
		||||
    - go test -v -cover ./...
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/gopkg.in/asn1-ber.v1/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/gopkg.in/asn1-ber.v1/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
			
		||||
Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are
 | 
			
		||||
met:
 | 
			
		||||
 | 
			
		||||
   * Redistributions of source code must retain the above copyright
 | 
			
		||||
notice, this list of conditions and the following disclaimer.
 | 
			
		||||
   * Redistributions in binary form must reproduce the above
 | 
			
		||||
copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
in the documentation and/or other materials provided with the
 | 
			
		||||
distribution.
 | 
			
		||||
   * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
contributors may be used to endorse or promote products derived from
 | 
			
		||||
this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/gopkg.in/ldap.v3/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/gopkg.in/ldap.v3/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
									
										32
									
								
								vendor/gopkg.in/ldap.v3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/gopkg.in/ldap.v3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,32 +0,0 @@
 | 
			
		||||
sudo: false
 | 
			
		||||
language: go
 | 
			
		||||
go:
 | 
			
		||||
    - "1.4.x"
 | 
			
		||||
    - "1.5.x"
 | 
			
		||||
    - "1.6.x"
 | 
			
		||||
    - "1.7.x"
 | 
			
		||||
    - "1.8.x"
 | 
			
		||||
    - "1.9.x"
 | 
			
		||||
    - "1.10.x"
 | 
			
		||||
    - "1.11.x"
 | 
			
		||||
    - "1.12.x"
 | 
			
		||||
    - tip
 | 
			
		||||
 | 
			
		||||
git:
 | 
			
		||||
  depth: 1
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
    fast_finish: true
 | 
			
		||||
    allow_failures:
 | 
			
		||||
        - go: tip
 | 
			
		||||
go_import_path: gopkg.in/ldap.v3
 | 
			
		||||
install:
 | 
			
		||||
    - go get gopkg.in/asn1-ber.v1
 | 
			
		||||
    - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
 | 
			
		||||
    - go get github.com/golang/lint/golint || go get golang.org/x/lint/golint || true
 | 
			
		||||
    - go build -v ./...
 | 
			
		||||
script:
 | 
			
		||||
    - make test
 | 
			
		||||
    - make fmt
 | 
			
		||||
    - make vet
 | 
			
		||||
    - make lint
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/gopkg.in/ldap.v3/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/gopkg.in/ldap.v3/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,12 +0,0 @@
 | 
			
		||||
# Contribution Guidelines
 | 
			
		||||
 | 
			
		||||
We welcome contribution and improvements.
 | 
			
		||||
 | 
			
		||||
## Guiding Principles
 | 
			
		||||
 | 
			
		||||
To begin with here is a draft from an email exchange:
 | 
			
		||||
 | 
			
		||||
 * take compatibility seriously (our semvers, compatibility with older go versions, etc)
 | 
			
		||||
 * don't tag untested code for release
 | 
			
		||||
 * beware of baking in implicit behavior based on other libraries/tools choices
 | 
			
		||||
 * be as high-fidelity as possible in plumbing through LDAP data (don't mask errors or reduce power of someone using the library)
 | 
			
		||||
							
								
								
									
										82
									
								
								vendor/gopkg.in/ldap.v3/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								vendor/gopkg.in/ldap.v3/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,82 +0,0 @@
 | 
			
		||||
.PHONY: default install build test quicktest fmt vet lint 
 | 
			
		||||
 | 
			
		||||
# List of all release tags "supported" by our current Go version
 | 
			
		||||
# E.g. ":go1.1:go1.2:go1.3:go1.4:go1.5:go1.6:go1.7:go1.8:go1.9:go1.10:go1.11:go1.12:"
 | 
			
		||||
GO_RELEASE_TAGS := $(shell go list -f ':{{join (context.ReleaseTags) ":"}}:' runtime)
 | 
			
		||||
 | 
			
		||||
# Only use the `-race` flag on newer versions of Go (version 1.3 and newer)
 | 
			
		||||
ifeq (,$(findstring :go1.3:,$(GO_RELEASE_TAGS)))
 | 
			
		||||
	RACE_FLAG :=
 | 
			
		||||
else
 | 
			
		||||
	RACE_FLAG := -race -cpu 1,2,4
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# Run `go vet` on Go 1.12 and newer. For Go 1.5-1.11, use `go tool vet`
 | 
			
		||||
ifneq (,$(findstring :go1.12:,$(GO_RELEASE_TAGS)))
 | 
			
		||||
	GO_VET := go vet \
 | 
			
		||||
		-atomic \
 | 
			
		||||
		-bool \
 | 
			
		||||
		-copylocks \
 | 
			
		||||
		-nilfunc \
 | 
			
		||||
		-printf \
 | 
			
		||||
		-rangeloops \
 | 
			
		||||
		-unreachable \
 | 
			
		||||
		-unsafeptr \
 | 
			
		||||
		-unusedresult \
 | 
			
		||||
		.
 | 
			
		||||
else ifneq (,$(findstring :go1.5:,$(GO_RELEASE_TAGS)))
 | 
			
		||||
	GO_VET := go tool vet \
 | 
			
		||||
		-atomic \
 | 
			
		||||
		-bool \
 | 
			
		||||
		-copylocks \
 | 
			
		||||
		-nilfunc \
 | 
			
		||||
		-printf \
 | 
			
		||||
		-shadow \
 | 
			
		||||
		-rangeloops \
 | 
			
		||||
		-unreachable \
 | 
			
		||||
		-unsafeptr \
 | 
			
		||||
		-unusedresult \
 | 
			
		||||
		.
 | 
			
		||||
else
 | 
			
		||||
	GO_VET := @echo "go vet skipped -- not supported on this version of Go"
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
default: fmt vet lint build quicktest
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
	go get -t -v ./...
 | 
			
		||||
 | 
			
		||||
build:
 | 
			
		||||
	go build -v ./...
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
	go test -v $(RACE_FLAG) -cover ./...
 | 
			
		||||
 | 
			
		||||
quicktest:
 | 
			
		||||
	go test ./...
 | 
			
		||||
 | 
			
		||||
# Capture output and force failure when there is non-empty output
 | 
			
		||||
fmt:
 | 
			
		||||
	@echo gofmt -l .
 | 
			
		||||
	@OUTPUT=`gofmt -l . 2>&1`; \
 | 
			
		||||
	if [ "$$OUTPUT" ]; then \
 | 
			
		||||
		echo "gofmt must be run on the following files:"; \
 | 
			
		||||
		echo "$$OUTPUT"; \
 | 
			
		||||
		exit 1; \
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
vet:
 | 
			
		||||
	$(GO_VET)
 | 
			
		||||
 | 
			
		||||
# https://github.com/golang/lint
 | 
			
		||||
# go get github.com/golang/lint/golint
 | 
			
		||||
# Capture output and force failure when there is non-empty output
 | 
			
		||||
# Only run on go1.5+
 | 
			
		||||
lint:
 | 
			
		||||
	@echo golint ./...
 | 
			
		||||
	@OUTPUT=`command -v golint >/dev/null 2>&1 && golint ./... 2>&1`; \
 | 
			
		||||
	if [ "$$OUTPUT" ]; then \
 | 
			
		||||
		echo "golint errors:"; \
 | 
			
		||||
		echo "$$OUTPUT"; \
 | 
			
		||||
		exit 1; \
 | 
			
		||||
	fi
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/gopkg.in/ldap.v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								vendor/gopkg.in/ldap.v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,54 +0,0 @@
 | 
			
		||||
[](https://godoc.org/gopkg.in/ldap.v3)
 | 
			
		||||
[](https://travis-ci.org/go-ldap/ldap)
 | 
			
		||||
 | 
			
		||||
# Basic LDAP v3 functionality for the GO programming language.
 | 
			
		||||
 | 
			
		||||
## Install
 | 
			
		||||
 | 
			
		||||
For the latest version use:
 | 
			
		||||
 | 
			
		||||
    go get gopkg.in/ldap.v3
 | 
			
		||||
 | 
			
		||||
Import the latest version with:
 | 
			
		||||
 | 
			
		||||
    import "gopkg.in/ldap.v3"
 | 
			
		||||
 | 
			
		||||
## Required Libraries:
 | 
			
		||||
 | 
			
		||||
 - gopkg.in/asn1-ber.v1
 | 
			
		||||
 | 
			
		||||
## Features:
 | 
			
		||||
 | 
			
		||||
 - Connecting to LDAP server (non-TLS, TLS, STARTTLS)
 | 
			
		||||
 - Binding to LDAP server
 | 
			
		||||
 - Searching for entries
 | 
			
		||||
 - Filter Compile / Decompile
 | 
			
		||||
 - Paging Search Results
 | 
			
		||||
 - Modify Requests / Responses
 | 
			
		||||
 - Add Requests / Responses
 | 
			
		||||
 - Delete Requests / Responses
 | 
			
		||||
 - Modify DN Requests / Responses
 | 
			
		||||
 | 
			
		||||
## Examples:
 | 
			
		||||
 | 
			
		||||
 - search
 | 
			
		||||
 - modify
 | 
			
		||||
 | 
			
		||||
## Contributing:
 | 
			
		||||
 | 
			
		||||
Bug reports and pull requests are welcome!
 | 
			
		||||
 | 
			
		||||
Before submitting a pull request, please make sure tests and verification scripts pass:
 | 
			
		||||
```
 | 
			
		||||
make all
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To set up a pre-push hook to run the tests and verify scripts before pushing:
 | 
			
		||||
```
 | 
			
		||||
ln -s ../../.githooks/pre-push .git/hooks/pre-push
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
 | 
			
		||||
The design is licensed under the Creative Commons 3.0 Attributions license.
 | 
			
		||||
Read this article for more details: http://blog.golang.org/gopher
 | 
			
		||||
							
								
								
									
										135
									
								
								vendor/gopkg.in/ldap.v3/bind.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										135
									
								
								vendor/gopkg.in/ldap.v3/bind.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,135 +0,0 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SimpleBindRequest represents a username/password bind operation
 | 
			
		||||
type SimpleBindRequest struct {
 | 
			
		||||
	// Username is the name of the Directory object that the client wishes to bind as
 | 
			
		||||
	Username string
 | 
			
		||||
	// Password is the credentials to bind with
 | 
			
		||||
	Password string
 | 
			
		||||
	// Controls are optional controls to send with the bind request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
	// AllowEmptyPassword sets whether the client allows binding with an empty password
 | 
			
		||||
	// (normally used for unauthenticated bind).
 | 
			
		||||
	AllowEmptyPassword bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SimpleBindResult contains the response from the server
 | 
			
		||||
type SimpleBindResult struct {
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSimpleBindRequest returns a bind request
 | 
			
		||||
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
 | 
			
		||||
	return &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           password,
 | 
			
		||||
		Controls:           controls,
 | 
			
		||||
		AllowEmptyPassword: false,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
			
		||||
	request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
 | 
			
		||||
 | 
			
		||||
	return request
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SimpleBind performs the simple bind operation defined in the given request
 | 
			
		||||
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
 | 
			
		||||
	if simpleBindRequest.Password == "" && !simpleBindRequest.AllowEmptyPassword {
 | 
			
		||||
		return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	encodedBindRequest := simpleBindRequest.encode()
 | 
			
		||||
	packet.AppendChild(encodedBindRequest)
 | 
			
		||||
	if len(simpleBindRequest.Controls) > 0 {
 | 
			
		||||
		packet.AppendChild(encodeControls(simpleBindRequest.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err = addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := &SimpleBindResult{
 | 
			
		||||
		Controls: make([]Control, 0),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(packet.Children) == 3 {
 | 
			
		||||
		for _, child := range packet.Children[2].Children {
 | 
			
		||||
			decodedChild, decodeErr := DecodeControl(child)
 | 
			
		||||
			if decodeErr != nil {
 | 
			
		||||
				return nil, fmt.Errorf("failed to decode child control: %s", decodeErr)
 | 
			
		||||
			}
 | 
			
		||||
			result.Controls = append(result.Controls, decodedChild)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = GetLDAPError(packet)
 | 
			
		||||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bind performs a bind with the given username and password.
 | 
			
		||||
//
 | 
			
		||||
// It does not allow unauthenticated bind (i.e. empty password). Use the UnauthenticatedBind method
 | 
			
		||||
// for that.
 | 
			
		||||
func (l *Conn) Bind(username, password string) error {
 | 
			
		||||
	req := &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           password,
 | 
			
		||||
		AllowEmptyPassword: false,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.SimpleBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnauthenticatedBind performs an unauthenticated bind.
 | 
			
		||||
//
 | 
			
		||||
// A username may be provided for trace (e.g. logging) purpose only, but it is normally not
 | 
			
		||||
// authenticated or otherwise validated by the LDAP server.
 | 
			
		||||
//
 | 
			
		||||
// See https://tools.ietf.org/html/rfc4513#section-5.1.2 .
 | 
			
		||||
// See https://tools.ietf.org/html/rfc4513#section-6.3.1 .
 | 
			
		||||
func (l *Conn) UnauthenticatedBind(username string) error {
 | 
			
		||||
	req := &SimpleBindRequest{
 | 
			
		||||
		Username:           username,
 | 
			
		||||
		Password:           "",
 | 
			
		||||
		AllowEmptyPassword: true,
 | 
			
		||||
	}
 | 
			
		||||
	_, err := l.SimpleBind(req)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								vendor/gopkg.in/ldap.v3/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/gopkg.in/ldap.v3/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,28 +0,0 @@
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client knows how to interact with an LDAP server
 | 
			
		||||
type Client interface {
 | 
			
		||||
	Start()
 | 
			
		||||
	StartTLS(config *tls.Config) error
 | 
			
		||||
	Close()
 | 
			
		||||
	SetTimeout(time.Duration)
 | 
			
		||||
 | 
			
		||||
	Bind(username, password string) error
 | 
			
		||||
	SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error)
 | 
			
		||||
 | 
			
		||||
	Add(addRequest *AddRequest) error
 | 
			
		||||
	Del(delRequest *DelRequest) error
 | 
			
		||||
	Modify(modifyRequest *ModifyRequest) error
 | 
			
		||||
	ModifyDN(modifyDNRequest *ModifyDNRequest) error
 | 
			
		||||
 | 
			
		||||
	Compare(dn, attribute, value string) (bool, error)
 | 
			
		||||
	PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
 | 
			
		||||
 | 
			
		||||
	Search(searchRequest *SearchRequest) (*SearchResult, error)
 | 
			
		||||
	SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								vendor/gopkg.in/ldap.v3/compare.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/gopkg.in/ldap.v3/compare.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,83 +0,0 @@
 | 
			
		||||
// File contains Compare functionality
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
//
 | 
			
		||||
// CompareRequest ::= [APPLICATION 14] SEQUENCE {
 | 
			
		||||
//              entry           LDAPDN,
 | 
			
		||||
//              ava             AttributeValueAssertion }
 | 
			
		||||
//
 | 
			
		||||
// AttributeValueAssertion ::= SEQUENCE {
 | 
			
		||||
//              attributeDesc   AttributeDescription,
 | 
			
		||||
//              assertionValue  AssertionValue }
 | 
			
		||||
//
 | 
			
		||||
// AttributeDescription ::= LDAPString
 | 
			
		||||
//                         -- Constrained to <attributedescription>
 | 
			
		||||
//                         -- [RFC4512]
 | 
			
		||||
//
 | 
			
		||||
// AttributeValue ::= OCTET STRING
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
 | 
			
		||||
// false with any error that occurs if any.
 | 
			
		||||
func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, dn, "DN"))
 | 
			
		||||
 | 
			
		||||
	ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
 | 
			
		||||
	ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "AttributeDesc"))
 | 
			
		||||
	ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "AssertionValue"))
 | 
			
		||||
	request.AppendChild(ava)
 | 
			
		||||
	packet.AppendChild(request)
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return false, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationCompareResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
 | 
			
		||||
		switch {
 | 
			
		||||
		case IsErrorWithCode(err, LDAPResultCompareTrue):
 | 
			
		||||
			return true, nil
 | 
			
		||||
		case IsErrorWithCode(err, LDAPResultCompareFalse):
 | 
			
		||||
			return false, nil
 | 
			
		||||
		default:
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										84
									
								
								vendor/gopkg.in/ldap.v3/del.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										84
									
								
								vendor/gopkg.in/ldap.v3/del.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,84 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
//
 | 
			
		||||
// DelRequest ::= [APPLICATION 10] LDAPDN
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DelRequest implements an LDAP deletion request
 | 
			
		||||
type DelRequest struct {
 | 
			
		||||
	// DN is the name of the directory entry to delete
 | 
			
		||||
	DN string
 | 
			
		||||
	// Controls hold optional controls to send with the request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d DelRequest) encode() *ber.Packet {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypePrimitive, ApplicationDelRequest, d.DN, "Del Request")
 | 
			
		||||
	request.Data.Write([]byte(d.DN))
 | 
			
		||||
	return request
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDelRequest creates a delete request for the given DN and controls
 | 
			
		||||
func NewDelRequest(DN string,
 | 
			
		||||
	Controls []Control) *DelRequest {
 | 
			
		||||
	return &DelRequest{
 | 
			
		||||
		DN:       DN,
 | 
			
		||||
		Controls: Controls,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Del executes the given delete request
 | 
			
		||||
func (l *Conn) Del(delRequest *DelRequest) error {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	packet.AppendChild(delRequest.encode())
 | 
			
		||||
	if len(delRequest.Controls) > 0 {
 | 
			
		||||
		packet.AppendChild(encodeControls(delRequest.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationDelResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										104
									
								
								vendor/gopkg.in/ldap.v3/moddn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										104
									
								
								vendor/gopkg.in/ldap.v3/moddn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,104 +0,0 @@
 | 
			
		||||
// Package ldap - moddn.go contains ModifyDN functionality
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
 | 
			
		||||
//      entry           LDAPDN,
 | 
			
		||||
//      newrdn          RelativeLDAPDN,
 | 
			
		||||
//      deleteoldrdn    BOOLEAN,
 | 
			
		||||
//      newSuperior     [0] LDAPDN OPTIONAL }
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ModifyDNRequest holds the request to modify a DN
 | 
			
		||||
type ModifyDNRequest struct {
 | 
			
		||||
	DN           string
 | 
			
		||||
	NewRDN       string
 | 
			
		||||
	DeleteOldRDN bool
 | 
			
		||||
	NewSuperior  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewModifyDNRequest creates a new request which can be passed to ModifyDN().
 | 
			
		||||
//
 | 
			
		||||
// To move an object in the tree, set the "newSup" to the new parent entry DN. Use an
 | 
			
		||||
// empty string for just changing the object's RDN.
 | 
			
		||||
//
 | 
			
		||||
// For moving the object without renaming, the "rdn" must be the first
 | 
			
		||||
// RDN of the given DN.
 | 
			
		||||
//
 | 
			
		||||
// A call like
 | 
			
		||||
//   mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
 | 
			
		||||
// will setup the request to just rename uid=someone,dc=example,dc=org to
 | 
			
		||||
// uid=newname,dc=example,dc=org.
 | 
			
		||||
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
 | 
			
		||||
	return &ModifyDNRequest{
 | 
			
		||||
		DN:           dn,
 | 
			
		||||
		NewRDN:       rdn,
 | 
			
		||||
		DeleteOldRDN: delOld,
 | 
			
		||||
		NewSuperior:  newSup,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m ModifyDNRequest) encode() *ber.Packet {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN Request")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.NewRDN, "New RDN"))
 | 
			
		||||
	request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, m.DeleteOldRDN, "Delete old RDN"))
 | 
			
		||||
	if m.NewSuperior != "" {
 | 
			
		||||
		request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, m.NewSuperior, "New Superior"))
 | 
			
		||||
	}
 | 
			
		||||
	return request
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument
 | 
			
		||||
// to NewModifyDNRequest() is not "").
 | 
			
		||||
func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	packet.AppendChild(m.encode())
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationModifyDNResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										173
									
								
								vendor/gopkg.in/ldap.v3/modify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										173
									
								
								vendor/gopkg.in/ldap.v3/modify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,173 +0,0 @@
 | 
			
		||||
// File contains Modify functionality
 | 
			
		||||
//
 | 
			
		||||
// https://tools.ietf.org/html/rfc4511
 | 
			
		||||
//
 | 
			
		||||
// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
 | 
			
		||||
//      object          LDAPDN,
 | 
			
		||||
//      changes         SEQUENCE OF change SEQUENCE {
 | 
			
		||||
//           operation       ENUMERATED {
 | 
			
		||||
//                add     (0),
 | 
			
		||||
//                delete  (1),
 | 
			
		||||
//                replace (2),
 | 
			
		||||
//                ...  },
 | 
			
		||||
//           modification    PartialAttribute } }
 | 
			
		||||
//
 | 
			
		||||
// PartialAttribute ::= SEQUENCE {
 | 
			
		||||
//      type       AttributeDescription,
 | 
			
		||||
//      vals       SET OF value AttributeValue }
 | 
			
		||||
//
 | 
			
		||||
// AttributeDescription ::= LDAPString
 | 
			
		||||
//                         -- Constrained to <attributedescription>
 | 
			
		||||
//                         -- [RFC4512]
 | 
			
		||||
//
 | 
			
		||||
// AttributeValue ::= OCTET STRING
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
package ldap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/asn1-ber.v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Change operation choices
 | 
			
		||||
const (
 | 
			
		||||
	AddAttribute     = 0
 | 
			
		||||
	DeleteAttribute  = 1
 | 
			
		||||
	ReplaceAttribute = 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PartialAttribute for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type PartialAttribute struct {
 | 
			
		||||
	// Type is the type of the partial attribute
 | 
			
		||||
	Type string
 | 
			
		||||
	// Vals are the values of the partial attribute
 | 
			
		||||
	Vals []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PartialAttribute) encode() *ber.Packet {
 | 
			
		||||
	seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
 | 
			
		||||
	seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.Type, "Type"))
 | 
			
		||||
	set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
 | 
			
		||||
	for _, value := range p.Vals {
 | 
			
		||||
		set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
 | 
			
		||||
	}
 | 
			
		||||
	seq.AppendChild(set)
 | 
			
		||||
	return seq
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Change for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type Change struct {
 | 
			
		||||
	// Operation is the type of change to be made
 | 
			
		||||
	Operation uint
 | 
			
		||||
	// Modification is the attribute to be modified
 | 
			
		||||
	Modification PartialAttribute
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Change) encode() *ber.Packet {
 | 
			
		||||
	change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
 | 
			
		||||
	change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(c.Operation), "Operation"))
 | 
			
		||||
	change.AppendChild(c.Modification.encode())
 | 
			
		||||
	return change
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
 | 
			
		||||
type ModifyRequest struct {
 | 
			
		||||
	// DN is the distinguishedName of the directory entry to modify
 | 
			
		||||
	DN string
 | 
			
		||||
	// Changes contain the attributes to modify
 | 
			
		||||
	Changes []Change
 | 
			
		||||
	// Controls hold optional controls to send with the request
 | 
			
		||||
	Controls []Control
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add appends the given attribute to the list of changes to be made
 | 
			
		||||
func (m *ModifyRequest) Add(attrType string, attrVals []string) {
 | 
			
		||||
	m.appendChange(AddAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete appends the given attribute to the list of changes to be made
 | 
			
		||||
func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
 | 
			
		||||
	m.appendChange(DeleteAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Replace appends the given attribute to the list of changes to be made
 | 
			
		||||
func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
 | 
			
		||||
	m.appendChange(ReplaceAttribute, attrType, attrVals)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *ModifyRequest) appendChange(operation uint, attrType string, attrVals []string) {
 | 
			
		||||
	m.Changes = append(m.Changes, Change{operation, PartialAttribute{Type: attrType, Vals: attrVals}})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m ModifyRequest) encode() *ber.Packet {
 | 
			
		||||
	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
 | 
			
		||||
	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
 | 
			
		||||
	changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
 | 
			
		||||
	for _, change := range m.Changes {
 | 
			
		||||
		changes.AppendChild(change.encode())
 | 
			
		||||
	}
 | 
			
		||||
	request.AppendChild(changes)
 | 
			
		||||
	return request
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewModifyRequest creates a modify request for the given DN
 | 
			
		||||
func NewModifyRequest(
 | 
			
		||||
	dn string,
 | 
			
		||||
	controls []Control,
 | 
			
		||||
) *ModifyRequest {
 | 
			
		||||
	return &ModifyRequest{
 | 
			
		||||
		DN:       dn,
 | 
			
		||||
		Controls: controls,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Modify performs the ModifyRequest
 | 
			
		||||
func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
 | 
			
		||||
	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
			
		||||
	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
 | 
			
		||||
	packet.AppendChild(modifyRequest.encode())
 | 
			
		||||
	if len(modifyRequest.Controls) > 0 {
 | 
			
		||||
		packet.AppendChild(encodeControls(modifyRequest.Controls))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.PrintPacket(packet)
 | 
			
		||||
 | 
			
		||||
	msgCtx, err := l.sendMessage(packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.finishMessage(msgCtx)
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: waiting for response", msgCtx.id)
 | 
			
		||||
	packetResponse, ok := <-msgCtx.responses
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
 | 
			
		||||
	}
 | 
			
		||||
	packet, err = packetResponse.ReadPacket()
 | 
			
		||||
	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.Debug {
 | 
			
		||||
		if err := addLDAPDescriptions(packet); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ber.PrintPacket(packet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if packet.Children[1].Tag == ApplicationModifyResponse {
 | 
			
		||||
		err := GetLDAPError(packet)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.Debug.Printf("%d: returning", msgCtx.id)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -49,6 +49,8 @@ gitea.com/macaron/session/postgres
 | 
			
		||||
# gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7
 | 
			
		||||
## explicit
 | 
			
		||||
gitea.com/macaron/toolbox
 | 
			
		||||
# github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c
 | 
			
		||||
github.com/Azure/go-ntlmssp
 | 
			
		||||
# github.com/BurntSushi/toml v0.3.1
 | 
			
		||||
github.com/BurntSushi/toml
 | 
			
		||||
# github.com/PuerkitoBio/goquery v1.5.1
 | 
			
		||||
@@ -250,6 +252,8 @@ github.com/gliderlabs/ssh
 | 
			
		||||
# github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/glycerine/go-unsnap-stream
 | 
			
		||||
# github.com/go-asn1-ber/asn1-ber v1.5.1
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber
 | 
			
		||||
# github.com/go-enry/go-enry/v2 v2.5.2
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/go-enry/go-enry/v2
 | 
			
		||||
@@ -318,6 +322,9 @@ github.com/go-git/go-git/v5/utils/merkletrie/filesystem
 | 
			
		||||
github.com/go-git/go-git/v5/utils/merkletrie/index
 | 
			
		||||
github.com/go-git/go-git/v5/utils/merkletrie/internal/frame
 | 
			
		||||
github.com/go-git/go-git/v5/utils/merkletrie/noder
 | 
			
		||||
# github.com/go-ldap/ldap/v3 v3.2.4
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/go-ldap/ldap/v3
 | 
			
		||||
# github.com/go-openapi/analysis v0.19.10
 | 
			
		||||
github.com/go-openapi/analysis
 | 
			
		||||
github.com/go-openapi/analysis/internal
 | 
			
		||||
@@ -935,18 +942,12 @@ google.golang.org/protobuf/runtime/protoimpl
 | 
			
		||||
# gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/alexcesaro/quotedprintable.v3
 | 
			
		||||
# gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/asn1-ber.v1
 | 
			
		||||
# gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/gomail.v2
 | 
			
		||||
# gopkg.in/ini.v1 v1.61.0
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/ini.v1
 | 
			
		||||
# gopkg.in/ldap.v3 v3.0.2
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/ldap.v3
 | 
			
		||||
# gopkg.in/warnings.v0 v0.1.2
 | 
			
		||||
gopkg.in/warnings.v0
 | 
			
		||||
# gopkg.in/yaml.v2 v2.3.0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user