diff --git a/.check-gofmt.sh b/.check-gofmt.sh index 708e86d7..1daa7195 100755 --- a/.check-gofmt.sh +++ b/.check-gofmt.sh @@ -3,6 +3,10 @@ # exclude vendor/ SOURCES="./oragono.go ./irc" +if [ "$1" = "--fix" ]; then + exec gofmt -s -w $SOURCES +fi + if [ -n "$(gofmt -s -l $SOURCES)" ]; then echo "Go code is not formatted correctly with \`gofmt -s\`:" gofmt -s -d $SOURCES diff --git a/Makefile b/Makefile index 75ec479e..748f36e0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all install build release capdefs test smoke +.PHONY: all install build release capdefs test smoke gofmt GIT_COMMIT := $(shell git rev-parse HEAD 2> /dev/null) @@ -36,3 +36,6 @@ test: smoke: oragono mkcerts --conf ./default.yaml || true oragono run --conf ./default.yaml --smoke + +gofmt: + ./.check-gofmt.sh --fix diff --git a/conventional.yaml b/conventional.yaml index 2ce840a7..574b6997 100644 --- a/conventional.yaml +++ b/conventional.yaml @@ -456,41 +456,6 @@ accounts: # see /QUOTE HELP umodes for more user modes # default-user-modes: +i - # support for deferring password checking to an external LDAP server - # you should probably ignore this section! consult the grafana docs for details: - # https://grafana.com/docs/grafana/latest/auth/ldap/ - # you will probably want to set require-sasl and disable accounts.registration.enabled - # ldap: - # enabled: true - # # should we automatically create users if their LDAP login succeeds? - # autocreate: true - # # example configuration that works with Forum Systems's testing server: - # # https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/ - # host: "ldap.forumsys.com" - # port: 389 - # timeout: 30s - # # example "single-bind" configuration, where we bind directly to the user's entry: - # bind-dn: "uid=%s,dc=example,dc=com" - # # example "admin bind" configuration, where we bind to an initial admin user, - # # then search for the user's entry with a search filter: - # #search-base-dns: - # # - "dc=example,dc=com" - # #bind-dn: "cn=read-only-admin,dc=example,dc=com" - # #bind-password: "password" - # #search-filter: "(uid=%s)" - # # example of requiring that users be in a particular group - # # (note that this is an OR over the listed groups, not an AND): - # #require-groups: - # # - "ou=mathematicians,dc=example,dc=com" - # #group-search-filter-user-attribute: "dn" - # #group-search-filter: "(uniqueMember=%s)" - # #group-search-base-dns: - # # - "dc=example,dc=com" - # # example of group membership testing via user attributes, as in AD - # # or with OpenLDAP's "memberOf overlay" (overrides group-search-filter): - # attributes: - # member-of: "memberOf" - # pluggable authentication mechanism, via subprocess invocation # see the manual for details on how to write an authentication plugin script auth-script: diff --git a/default.yaml b/default.yaml index fe30f336..d161462c 100644 --- a/default.yaml +++ b/default.yaml @@ -482,41 +482,6 @@ accounts: # see /QUOTE HELP umodes for more user modes default-user-modes: +i - # support for deferring password checking to an external LDAP server - # you should probably ignore this section! consult the grafana docs for details: - # https://grafana.com/docs/grafana/latest/auth/ldap/ - # you will probably want to set require-sasl and disable accounts.registration.enabled - # ldap: - # enabled: true - # # should we automatically create users if their LDAP login succeeds? - # autocreate: true - # # example configuration that works with Forum Systems's testing server: - # # https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/ - # host: "ldap.forumsys.com" - # port: 389 - # timeout: 30s - # # example "single-bind" configuration, where we bind directly to the user's entry: - # bind-dn: "uid=%s,dc=example,dc=com" - # # example "admin bind" configuration, where we bind to an initial admin user, - # # then search for the user's entry with a search filter: - # #search-base-dns: - # # - "dc=example,dc=com" - # #bind-dn: "cn=read-only-admin,dc=example,dc=com" - # #bind-password: "password" - # #search-filter: "(uid=%s)" - # # example of requiring that users be in a particular group - # # (note that this is an OR over the listed groups, not an AND): - # #require-groups: - # # - "ou=mathematicians,dc=example,dc=com" - # #group-search-filter-user-attribute: "dn" - # #group-search-filter: "(uniqueMember=%s)" - # #group-search-base-dns: - # # - "dc=example,dc=com" - # # example of group membership testing via user attributes, as in AD - # # or with OpenLDAP's "memberOf overlay" (overrides group-search-filter): - # attributes: - # member-of: "memberOf" - # pluggable authentication mechanism, via subprocess invocation # see the manual for details on how to write an authentication plugin script auth-script: diff --git a/go.mod b/go.mod index 3d76a304..877b0111 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 - github.com/go-ldap/ldap/v3 v3.1.10 github.com/go-sql-driver/mysql v1.5.0 github.com/go-test/deep v1.0.6 // indirect github.com/gorilla/websocket v1.4.2 diff --git a/go.sum b/go.sum index 3e5dfa3c..c225bb74 100644 --- a/go.sum +++ b/go.sum @@ -9,10 +9,6 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-ldap/ldap/v3 v3.1.10 h1:7WsKqasmPThNvdl0Q5GPpbTDD/ZD98CfuawrMIuh7qQ= -github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8= diff --git a/irc/accounts.go b/irc/accounts.go index 530d2e34..f5ceb757 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -17,7 +17,6 @@ import ( "github.com/oragono/oragono/irc/connection_limits" "github.com/oragono/oragono/irc/email" - "github.com/oragono/oragono/irc/ldap" "github.com/oragono/oragono/irc/modes" "github.com/oragono/oragono/irc/passwd" "github.com/oragono/oragono/irc/utils" @@ -1065,24 +1064,13 @@ func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName s }() config := am.server.Config() - if config.Accounts.LDAP.Enabled { - ldapConf := am.server.Config().Accounts.LDAP - err = ldap.CheckLDAPPassphrase(ldapConf, accountName, passphrase, am.server.logger) - if err != nil { - account, err = am.loadWithAutocreation(accountName, ldapConf.Autocreate) - return - } - } - if config.Accounts.AuthScript.Enabled { var output AuthScriptOutput output, err = CheckAuthScript(config.Accounts.AuthScript, AuthScriptInput{AccountName: accountName, Passphrase: passphrase, IP: client.IP().String()}) if err != nil { am.server.logger.Error("internal", "failed shell auth invocation", err.Error()) - return err - } - if output.Success { + } else if output.Success { if output.AccountName != "" { accountName = output.AccountName } @@ -1419,9 +1407,7 @@ func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid s AuthScriptInput{Certfp: certfp, IP: client.IP().String()}) if err != nil { am.server.logger.Error("internal", "failed shell auth invocation", err.Error()) - return err - } - if output.Success && output.AccountName != "" { + } else if output.Success && output.AccountName != "" { clientAccount, err = am.loadWithAutocreation(output.AccountName, config.Accounts.AuthScript.Autocreate) return } diff --git a/irc/config.go b/irc/config.go index fe5c643f..3e8723f4 100644 --- a/irc/config.go +++ b/irc/config.go @@ -29,7 +29,6 @@ import ( "github.com/oragono/oragono/irc/isupport" "github.com/oragono/oragono/irc/jwt" "github.com/oragono/oragono/irc/languages" - "github.com/oragono/oragono/irc/ldap" "github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/modes" "github.com/oragono/oragono/irc/mysql" @@ -258,7 +257,6 @@ type AccountConfig struct { } `yaml:"require-sasl"` DefaultUserModes *string `yaml:"default-user-modes"` defaultUserModes modes.Modes - LDAP ldap.ServerConfig LoginThrottling ThrottleConfig `yaml:"login-throttling"` SkipServerPassword bool `yaml:"skip-server-password"` LoginViaPassCommand bool `yaml:"login-via-pass-command"` diff --git a/irc/ldap/LICENSE b/irc/ldap/LICENSE deleted file mode 100644 index 373dde57..00000000 --- a/irc/ldap/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2015 Grafana Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/irc/ldap/config.go b/irc/ldap/config.go deleted file mode 100644 index 623fdf09..00000000 --- a/irc/ldap/config.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014-2018 Grafana Labs -// Released under the Apache 2.0 license - -// Modification notice: -// 1. All field names were changed from toml and snake case to yaml and kebab case, -// matching the Oragono project conventions -// 2. Four fields were added: -// 2.1 `Enabled` -// 2.2 `Autocreate` -// 2.3 `Timeout` -// 2.4 `RequireGroups` - -// XXX: none of AttributeMap does anything in oragono, except MemberOf, -// which can be used to retrieve group memberships - -package ldap - -import ( - "time" -) - -type ServerConfig struct { - Enabled bool - Autocreate bool - - Host string - Port int - Timeout time.Duration - UseSSL bool `yaml:"use-ssl"` - StartTLS bool `yaml:"start-tls"` - SkipVerifySSL bool `yaml:"ssl-skip-verify"` - RootCACert string `yaml:"root-ca-cert"` - ClientCert string `yaml:"client-cert"` - ClientKey string `yaml:"client-key"` - - BindDN string `yaml:"bind-dn"` - BindPassword string `yaml:"bind-password"` - SearchFilter string `yaml:"search-filter"` - SearchBaseDNs []string `yaml:"search-base-dns"` - - // user validation: require them to be in any one of these groups - RequireGroups []string `yaml:"require-groups"` - - // two ways of testing group membership: - // either by searching for groups that match the user's DN - // and testing their names: - GroupSearchFilter string `yaml:"group-search-filter"` - GroupSearchFilterUserAttribute string `yaml:"group-search-filter-user-attribute"` - GroupSearchBaseDNs []string `yaml:"group-search-base-dns"` - - // or by an attribute on the user's DN, typically named 'memberOf', but customizable: - Attr AttributeMap `yaml:"attributes"` -} - -// AttributeMap is a struct representation for LDAP "attributes" setting -type AttributeMap struct { - Username string - Name string - Surname string - Email string - MemberOf string `yaml:"member-of"` -} diff --git a/irc/ldap/grafana.go b/irc/ldap/grafana.go deleted file mode 100644 index 4cd83cdb..00000000 --- a/irc/ldap/grafana.go +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2014-2018 Grafana Labs -// Released under the Apache 2.0 license - -// Modification notice: -// 1. `serverConn` was substituted for `Server` as the type of the server object -// 2. Debug loglines were altered to work with Oragono's logging system - -package ldap - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "fmt" - "io/ioutil" - "strings" - - ldap "github.com/go-ldap/ldap/v3" -) - -var ( - // ErrInvalidCredentials is returned if username and password do not match - ErrInvalidCredentials = errors.New("Invalid Username or Password") - - // ErrCouldNotFindUser is returned when username hasn't been found (not username+password) - ErrCouldNotFindUser = errors.New("Can't find user in LDAP") -) - -// shouldAdminBind checks if we should use -// admin username & password for LDAP bind -func (server *serverConn) shouldAdminBind() bool { - return server.Config.BindPassword != "" -} - -// singleBindDN combines the bind with the username -// in order to get the proper path -func (server *serverConn) singleBindDN(username string) string { - return fmt.Sprintf(server.Config.BindDN, username) -} - -// shouldSingleBind checks if we can use "single bind" approach -func (server *serverConn) shouldSingleBind() bool { - return strings.Contains(server.Config.BindDN, "%s") -} - -// Dial dials in the LDAP -// TODO: decrease cyclomatic complexity -func (server *serverConn) Dial() error { - var err error - var certPool *x509.CertPool - if server.Config.RootCACert != "" { - certPool = x509.NewCertPool() - for _, caCertFile := range strings.Split(server.Config.RootCACert, " ") { - pem, err := ioutil.ReadFile(caCertFile) - if err != nil { - return err - } - if !certPool.AppendCertsFromPEM(pem) { - return errors.New("Failed to append CA certificate " + caCertFile) - } - } - } - var clientCert tls.Certificate - if server.Config.ClientCert != "" && server.Config.ClientKey != "" { - clientCert, err = tls.LoadX509KeyPair(server.Config.ClientCert, server.Config.ClientKey) - if err != nil { - return err - } - } - for _, host := range strings.Split(server.Config.Host, " ") { - address := fmt.Sprintf("%s:%d", host, server.Config.Port) - if server.Config.UseSSL { - tlsCfg := &tls.Config{ - InsecureSkipVerify: server.Config.SkipVerifySSL, - ServerName: host, - RootCAs: certPool, - } - if len(clientCert.Certificate) > 0 { - tlsCfg.Certificates = append(tlsCfg.Certificates, clientCert) - } - if server.Config.StartTLS { - server.Connection, err = ldap.Dial("tcp", address) - if err == nil { - if err = server.Connection.StartTLS(tlsCfg); err == nil { - return nil - } - } - } else { - server.Connection, err = ldap.DialTLS("tcp", address, tlsCfg) - } - } else { - server.Connection, err = ldap.Dial("tcp", address) - } - - if err == nil { - return nil - } - } - return err -} - -// Close closes the LDAP connection -// Dial() sets the connection with the server for this Struct. Therefore, we require a -// call to Dial() before being able to execute this function. -func (server *serverConn) Close() { - server.Connection.Close() -} - -// userBind binds the user with the LDAP server -func (server *serverConn) userBind(path, password string) error { - err := server.Connection.Bind(path, password) - if err != nil { - if ldapErr, ok := err.(*ldap.Error); ok { - if ldapErr.ResultCode == 49 { - return ErrInvalidCredentials - } - } - return err - } - - return nil -} - -// users is helper method for the Users() -func (server *serverConn) users(logins []string) ( - []*ldap.Entry, - error, -) { - var result *ldap.SearchResult - var Config = server.Config - var err error - - for _, base := range Config.SearchBaseDNs { - result, err = server.Connection.Search( - server.getSearchRequest(base, logins), - ) - if err != nil { - return nil, err - } - - if len(result.Entries) > 0 { - break - } - } - - return result.Entries, nil -} - -// getSearchRequest returns LDAP search request for users -func (server *serverConn) getSearchRequest( - base string, - logins []string, -) *ldap.SearchRequest { - attributes := []string{} - - inputs := server.Config.Attr - attributes = appendIfNotEmpty( - attributes, - inputs.Username, - inputs.Surname, - inputs.Email, - inputs.Name, - inputs.MemberOf, - - // In case for the POSIX LDAP schema server - server.Config.GroupSearchFilterUserAttribute, - ) - - search := "" - for _, login := range logins { - query := strings.Replace( - server.Config.SearchFilter, - "%s", ldap.EscapeFilter(login), - -1, - ) - - search = search + query - } - - filter := fmt.Sprintf("(|%s)", search) - - return &ldap.SearchRequest{ - BaseDN: base, - Scope: ldap.ScopeWholeSubtree, - DerefAliases: ldap.NeverDerefAliases, - Attributes: attributes, - Filter: filter, - } -} - -// requestMemberOf use this function when POSIX LDAP -// schema does not support memberOf, so it manually search the groups -func (server *serverConn) requestMemberOf(entry *ldap.Entry) ([]string, error) { - var memberOf []string - var config = server.Config - - for _, groupSearchBase := range config.GroupSearchBaseDNs { - var filterReplace string - if config.GroupSearchFilterUserAttribute == "" { - filterReplace = getAttribute(config.Attr.Username, entry) - } else { - filterReplace = getAttribute( - config.GroupSearchFilterUserAttribute, - entry, - ) - } - - filter := strings.Replace( - config.GroupSearchFilter, "%s", - ldap.EscapeFilter(filterReplace), - -1, - ) - - server.logger.Debug("ldap", "Searching for groups with filter", filter) - - // support old way of reading settings - groupIDAttribute := config.Attr.MemberOf - // but prefer dn attribute if default settings are used - if groupIDAttribute == "" || groupIDAttribute == "memberOf" { - groupIDAttribute = "dn" - } - - groupSearchReq := ldap.SearchRequest{ - BaseDN: groupSearchBase, - Scope: ldap.ScopeWholeSubtree, - DerefAliases: ldap.NeverDerefAliases, - Attributes: []string{groupIDAttribute}, - Filter: filter, - } - - groupSearchResult, err := server.Connection.Search(&groupSearchReq) - if err != nil { - return nil, err - } - - if len(groupSearchResult.Entries) > 0 { - for _, group := range groupSearchResult.Entries { - - memberOf = append( - memberOf, - getAttribute(groupIDAttribute, group), - ) - } - break - } - } - - return memberOf, nil -} - -// getMemberOf finds memberOf property or request it -func (server *serverConn) getMemberOf(result *ldap.Entry) ( - []string, error, -) { - if server.Config.GroupSearchFilter == "" { - memberOf := getArrayAttribute(server.Config.Attr.MemberOf, result) - - return memberOf, nil - } - - memberOf, err := server.requestMemberOf(result) - if err != nil { - return nil, err - } - - return memberOf, nil -} diff --git a/irc/ldap/helpers.go b/irc/ldap/helpers.go deleted file mode 100644 index cadb822c..00000000 --- a/irc/ldap/helpers.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014-2018 Grafana Labs -// Released under the Apache 2.0 license - -package ldap - -import ( - "strings" - - ldap "github.com/go-ldap/ldap/v3" -) - -func isMemberOf(memberOf []string, group string) bool { - if group == "*" { - return true - } - - for _, member := range memberOf { - if strings.EqualFold(member, group) { - return true - } - } - return false -} - -func getArrayAttribute(name string, entry *ldap.Entry) []string { - if strings.ToLower(name) == "dn" { - return []string{entry.DN} - } - - for _, attr := range entry.Attributes { - if attr.Name == name && len(attr.Values) > 0 { - return attr.Values - } - } - return []string{} -} - -func getAttribute(name string, entry *ldap.Entry) string { - if strings.ToLower(name) == "dn" { - return entry.DN - } - - for _, attr := range entry.Attributes { - if attr.Name == name { - if len(attr.Values) > 0 { - return attr.Values[0] - } - } - } - return "" -} - -func appendIfNotEmpty(slice []string, values ...string) []string { - for _, v := range values { - if v != "" { - slice = append(slice, v) - } - } - return slice -} diff --git a/irc/ldap/login.go b/irc/ldap/login.go deleted file mode 100644 index fb22c992..00000000 --- a/irc/ldap/login.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2020 Matt Ouille -// Copyright (c) 2020 Shivaram Lingamneni -// released under the MIT license - -// Portions of this code copyright Grafana Labs and contributors -// and released under the Apache 2.0 license - -// Copying Grafana's original comment on the different cases for LDAP: -// There are several cases - -// 1. "admin" user -// Bind the "admin" user (defined in Grafana config file) which has the search privileges -// in LDAP server, then we search the targeted user through that bind, then the second -// perform the bind via passed login/password. -// 2. Single bind -// // If all the users meant to be used with Grafana have the ability to search in LDAP server -// then we bind with LDAP server with targeted login/password -// and then search for the said user in order to retrive all the information about them -// 3. Unauthenticated bind -// For some LDAP configurations it is allowed to search the -// user without login/password binding with LDAP server, in such case -// we will perform "unauthenticated bind", then search for the -// targeted user and then perform the bind with passed login/password. - -// Note: the only validation we do on users is to check RequiredGroups. -// If RequiredGroups is not set and we can do a single bind, we don't -// even need to search. So our case 2 is not restricted -// to setups where all the users have search privileges: we only need to -// be able to do DN resolution via pure string substitution. - -package ldap - -import ( - "errors" - "fmt" - - ldap "github.com/go-ldap/ldap/v3" - - "github.com/oragono/oragono/irc/logger" -) - -var ( - ErrUserNotInRequiredGroup = errors.New("User is not a member of any required groups") -) - -// equivalent of Grafana's `Server`, but unexported -// also, `log` was renamed to `logger`, since the APIs are slightly different -// and this way the compiler will catch any unchanged references to Grafana's `Server.log` -type serverConn struct { - Config *ServerConfig - Connection *ldap.Conn - logger *logger.Manager -} - -func CheckLDAPPassphrase(config ServerConfig, accountName, passphrase string, log *logger.Manager) (err error) { - defer func() { - if err != nil { - log.Debug("ldap", "failed passphrase check", err.Error()) - } - }() - - server := serverConn{ - Config: &config, - logger: log, - } - - err = server.Dial() - if err != nil { - return - } - defer server.Close() - - server.Connection.SetTimeout(config.Timeout) - - passphraseChecked := false - - if server.shouldSingleBind() { - log.Debug("ldap", "attempting single bind to", accountName) - err = server.userBind(server.singleBindDN(accountName), passphrase) - passphraseChecked = (err == nil) - } else if server.shouldAdminBind() { - log.Debug("ldap", "attempting admin bind to", config.BindDN) - err = server.userBind(config.BindDN, config.BindPassword) - } else { - log.Debug("ldap", "attempting unauthenticated bind") - err = server.Connection.UnauthenticatedBind(config.BindDN) - } - - if err != nil { - return - } - - if passphraseChecked && len(config.RequireGroups) == 0 { - return nil - } - - users, err := server.users([]string{accountName}) - if err != nil { - log.Debug("ldap", "failed user lookup") - return err - } - - if len(users) == 0 { - return ErrCouldNotFindUser - } - - user := users[0] - - log.Debug("ldap", "looked up user", user.DN) - - err = server.validateGroupMembership(user) - if err != nil { - return err - } - - if !passphraseChecked { - log.Debug("ldap", "rebinding", user.DN) - err = server.userBind(user.DN, passphrase) - } - - return err -} - -func (server *serverConn) validateGroupMembership(user *ldap.Entry) (err error) { - if len(server.Config.RequireGroups) == 0 { - return - } - - var memberOf []string - memberOf, err = server.getMemberOf(user) - if err != nil { - server.logger.Debug("ldap", "could not retrieve group memberships", err.Error()) - return - } - server.logger.Debug("ldap", fmt.Sprintf("found group memberships: %v", memberOf)) - foundGroup := false - for _, inGroup := range memberOf { - for _, acceptableGroup := range server.Config.RequireGroups { - if inGroup == acceptableGroup { - foundGroup = true - break - } - } - if foundGroup { - break - } - } - if foundGroup { - return nil - } else { - return ErrUserNotInRequiredGroup - } -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/.travis.yml b/vendor/github.com/go-asn1-ber/asn1-ber/.travis.yml deleted file mode 100644 index 4ad2067b..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -language: go -matrix: - include: - - go: 1.2.x - env: GOOS=linux GOARCH=amd64 - - go: 1.2.x - env: GOOS=linux GOARCH=386 - - go: 1.2.x - env: GOOS=windows GOARCH=amd64 - - go: 1.2.x - env: GOOS=windows GOARCH=386 - - go: 1.3.x - - go: 1.4.x - - go: 1.5.x - - go: 1.6.x - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: 1.11.x - - go: 1.12.x - - go: 1.13.x - env: GOOS=linux GOARCH=amd64 - - go: 1.13.x - env: GOOS=linux GOARCH=386 - - go: 1.13.x - env: GOOS=windows GOARCH=amd64 - - go: 1.13.x - env: GOOS=windows GOARCH=386 - - go: 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 ./... || go test -v ./... diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/LICENSE b/vendor/github.com/go-asn1-ber/asn1-ber/LICENSE deleted file mode 100644 index 23f94253..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -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. diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/README.md b/vendor/github.com/go-asn1-ber/asn1-ber/README.md deleted file mode 100644 index e3a9560d..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/README.md +++ /dev/null @@ -1,24 +0,0 @@ -[![GoDoc](https://godoc.org/gopkg.in/asn1-ber.v1?status.svg)](https://godoc.org/gopkg.in/asn1-ber.v1) [![Build Status](https://travis-ci.org/go-asn1-ber/asn1-ber.svg)](https://travis-ci.org/go-asn1-ber/asn1-ber) - - -ASN1 BER Encoding / Decoding Library for the GO programming language. ---------------------------------------------------------------------- - -Required libraries: - None - -Working: - Very basic encoding / decoding needed for LDAP protocol - -Tests Implemented: - A few - -TODO: - Fix all encoding / decoding to conform to ASN1 BER spec - Implement Tests / Benchmarks - ---- - -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 diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/ber.go b/vendor/github.com/go-asn1-ber/asn1-ber/ber.go deleted file mode 100644 index 6153f460..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/ber.go +++ /dev/null @@ -1,512 +0,0 @@ -package ber - -import ( - "bytes" - "errors" - "fmt" - "io" - "math" - "os" - "reflect" -) - -// 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{} - ByteValue []byte - Data *bytes.Buffer - Children []*Packet - Description string -} - -type Identifier struct { - ClassType Class - TagType Type - Tag Tag -} - -type Tag uint64 - -const ( - TagEOC Tag = 0x00 - TagBoolean Tag = 0x01 - TagInteger Tag = 0x02 - TagBitString Tag = 0x03 - TagOctetString Tag = 0x04 - TagNULL Tag = 0x05 - TagObjectIdentifier Tag = 0x06 - TagObjectDescriptor Tag = 0x07 - TagExternal Tag = 0x08 - TagRealFloat Tag = 0x09 - TagEnumerated Tag = 0x0a - TagEmbeddedPDV Tag = 0x0b - TagUTF8String Tag = 0x0c - TagRelativeOID Tag = 0x0d - TagSequence Tag = 0x10 - TagSet Tag = 0x11 - TagNumericString Tag = 0x12 - TagPrintableString Tag = 0x13 - TagT61String Tag = 0x14 - TagVideotexString Tag = 0x15 - TagIA5String Tag = 0x16 - TagUTCTime Tag = 0x17 - TagGeneralizedTime Tag = 0x18 - TagGraphicString Tag = 0x19 - TagVisibleString Tag = 0x1a - TagGeneralString Tag = 0x1b - TagUniversalString Tag = 0x1c - TagCharacterString Tag = 0x1d - TagBMPString Tag = 0x1e - TagBitmask Tag = 0x1f // xxx11111b - - // HighTag indicates the start of a high-tag byte sequence - HighTag Tag = 0x1f // xxx11111b - // HighTagContinueBitmask indicates the high-tag byte sequence should continue - HighTagContinueBitmask Tag = 0x80 // 10000000b - // HighTagValueBitmask obtains the tag value from a high-tag byte sequence byte - HighTagValueBitmask Tag = 0x7f // 01111111b -) - -const ( - // LengthLongFormBitmask is the mask to apply to the length byte to see if a long-form byte sequence is used - LengthLongFormBitmask = 0x80 - // LengthValueBitmask is the mask to apply to the length byte to get the number of bytes in the long-form byte sequence - LengthValueBitmask = 0x7f - - // LengthIndefinite is returned from readLength to indicate an indefinite length - LengthIndefinite = -1 -) - -var tagMap = map[Tag]string{ - TagEOC: "EOC (End-of-Content)", - TagBoolean: "Boolean", - TagInteger: "Integer", - TagBitString: "Bit String", - TagOctetString: "Octet String", - TagNULL: "NULL", - TagObjectIdentifier: "Object Identifier", - TagObjectDescriptor: "Object Descriptor", - TagExternal: "External", - TagRealFloat: "Real (float)", - TagEnumerated: "Enumerated", - TagEmbeddedPDV: "Embedded PDV", - TagUTF8String: "UTF8 String", - TagRelativeOID: "Relative-OID", - TagSequence: "Sequence and Sequence of", - TagSet: "Set and Set OF", - TagNumericString: "Numeric String", - TagPrintableString: "Printable String", - TagT61String: "T61 String", - TagVideotexString: "Videotex String", - TagIA5String: "IA5 String", - TagUTCTime: "UTC Time", - TagGeneralizedTime: "Generalized Time", - TagGraphicString: "Graphic String", - TagVisibleString: "Visible String", - TagGeneralString: "General String", - TagUniversalString: "Universal String", - TagCharacterString: "Character String", - TagBMPString: "BMP String", -} - -type Class uint8 - -const ( - ClassUniversal Class = 0 // 00xxxxxxb - ClassApplication Class = 64 // 01xxxxxxb - ClassContext Class = 128 // 10xxxxxxb - ClassPrivate Class = 192 // 11xxxxxxb - ClassBitmask Class = 192 // 11xxxxxxb -) - -var ClassMap = map[Class]string{ - ClassUniversal: "Universal", - ClassApplication: "Application", - ClassContext: "Context", - ClassPrivate: "Private", -} - -type Type uint8 - -const ( - TypePrimitive Type = 0 // xx0xxxxxb - TypeConstructed Type = 32 // xx1xxxxxb - TypeBitmask Type = 32 // xx1xxxxxb -) - -var TypeMap = map[Type]string{ - TypePrimitive: "Primitive", - TypeConstructed: "Constructed", -} - -var Debug bool = 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) - - for i, b := range buf { - data_lines[i/30] += fmt.Sprintf("%02x ", b) - num_lines[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")) - } -} - -func PrintPacket(p *Packet) { - printPacket(os.Stdout, p, 0, false) -} - -func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) { - indent_str := "" - - for len(indent_str) != indent { - indent_str += " " - } - - class_str := ClassMap[p.ClassType] - - tagtype_str := TypeMap[p.TagType] - - tag_str := fmt.Sprintf("0x%02X", p.Tag) - - if p.ClassType == ClassUniversal { - tag_str = tagMap[p.Tag] - } - - value := fmt.Sprint(p.Value) - description := "" - - if p.Description != "" { - 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) - - if printBytes { - PrintBytes(out, p.Bytes(), indent_str) - } - - for _, child := range p.Children { - printPacket(out, child, indent+1, printBytes) - } -} - -// ReadPacket reads a single Packet from the reader -func ReadPacket(reader io.Reader) (*Packet, error) { - p, _, err := readPacket(reader) - if err != nil { - return nil, err - } - return p, nil -} - -func DecodeString(data []byte) string { - return string(data) -} - -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") - return - } - for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { - ret <<= 8 - ret |= int64(bytes[bytesRead]) - } - - // Shift up and down in order to sign extend the result. - ret <<= 64 - uint8(len(bytes))*8 - ret >>= 64 - uint8(len(bytes))*8 - return -} - -func encodeInteger(i int64) []byte { - n := int64Length(i) - out := make([]byte, n) - - var j int - for ; n > 0; n-- { - out[j] = (byte(i >> uint((n-1)*8))) - j++ - } - - return out -} - -func int64Length(i int64) (numBytes int) { - numBytes = 1 - - for i > 127 { - numBytes++ - i >>= 8 - } - - for i < -128 { - numBytes++ - i >>= 8 - } - - return -} - -// DecodePacket decodes the given bytes into a single Packet -// If a decode error is encountered, nil is returned. -func DecodePacket(data []byte) *Packet { - p, _, _ := readPacket(bytes.NewBuffer(data)) - - return p -} - -// DecodePacketErr decodes the given bytes into a single Packet -// If a decode error is encountered, nil is returned -func DecodePacketErr(data []byte) (*Packet, error) { - p, _, err := readPacket(bytes.NewBuffer(data)) - if err != nil { - return nil, err - } - return p, nil -} - -// 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 { - return nil, read, err - } - - p := &Packet{ - Identifier: identifier, - } - - p.Data = new(bytes.Buffer) - p.Children = make([]*Packet, 0, 2) - p.Value = nil - - if p.TagType == TypeConstructed { - // TODO: if universal, ensure tag type is allowed to be constructed - - // Track how much content we've read - contentRead := 0 - for { - if length != LengthIndefinite { - // End if we've read what we've been told to - if contentRead == length { - break - } - // Detect if a packet boundary didn't fall on the expected length - if contentRead > length { - return nil, read, fmt.Errorf("expected to read %d bytes, read %d", length, contentRead) - } - } - - // Read the next packet - child, r, err := readPacket(reader) - if err != nil { - return nil, read, err - } - contentRead += r - read += r - - // Test is this is the EOC marker for our packet - if isEOCPacket(child) { - if length == LengthIndefinite { - break - } - return nil, read, errors.New("eoc child not allowed with definite length") - } - - // Append and continue - p.AppendChild(child) - } - return p, read, nil - } - - if length == LengthIndefinite { - return nil, read, errors.New("indefinite length used with primitive type") - } - - // Read definite-length content - if MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes { - return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes) - } - content := make([]byte, length, length) - if length > 0 { - _, err := io.ReadFull(reader, content) - if err != nil { - if err == io.EOF { - return nil, read, io.ErrUnexpectedEOF - } - return nil, read, err - } - read += length - } - - if p.ClassType == ClassUniversal { - p.Data.Write(content) - p.ByteValue = content - - switch p.Tag { - case TagEOC: - case TagBoolean: - val, _ := ParseInt64(content) - - p.Value = val != 0 - case TagInteger: - p.Value, _ = ParseInt64(content) - case TagBitString: - case TagOctetString: - // the actual string encoding is not known here - // (e.g. for LDAP content is already an UTF8-encoded - // string). Return the data without further processing - p.Value = DecodeString(content) - case TagNULL: - case TagObjectIdentifier: - case TagObjectDescriptor: - case TagExternal: - case TagRealFloat: - case TagEnumerated: - p.Value, _ = ParseInt64(content) - case TagEmbeddedPDV: - case TagUTF8String: - p.Value = DecodeString(content) - case TagRelativeOID: - case TagSequence: - case TagSet: - case TagNumericString: - case TagPrintableString: - p.Value = DecodeString(content) - case TagT61String: - case TagVideotexString: - case TagIA5String: - case TagUTCTime: - case TagGeneralizedTime: - case TagGraphicString: - case TagVisibleString: - case TagGeneralString: - case TagUniversalString: - case TagCharacterString: - case TagBMPString: - } - } else { - p.Data.Write(content) - } - - return p, read, nil -} - -func (p *Packet) Bytes() []byte { - var out bytes.Buffer - - out.Write(encodeIdentifier(p.Identifier)) - out.Write(encodeLength(p.Data.Len())) - out.Write(p.Data.Bytes()) - - return out.Bytes() -} - -func (p *Packet) AppendChild(child *Packet) { - p.Data.Write(child.Bytes()) - p.Children = append(p.Children, child) -} - -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.Data = new(bytes.Buffer) - - p.Children = make([]*Packet, 0, 2) - - p.Value = Value - p.Description = Description - - if Value != nil { - v := reflect.ValueOf(Value) - - if ClassType == ClassUniversal { - switch Tag { - case TagOctetString: - sv, ok := v.Interface().(string) - - if ok { - p.Data.Write([]byte(sv)) - } - } - } - } - - return p -} - -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 { - intValue := int64(0) - - if Value { - intValue = 1 - } - - 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: - p.Data.Write(encodeInteger(int64(v))) - case int64: - p.Data.Write(encodeInteger(v)) - case uint64: - // TODO : check range or add encodeUInt... - p.Data.Write(encodeInteger(int64(v))) - case int32: - p.Data.Write(encodeInteger(int64(v))) - case uint32: - p.Data.Write(encodeInteger(int64(v))) - case int16: - p.Data.Write(encodeInteger(int64(v))) - case uint16: - p.Data.Write(encodeInteger(int64(v))) - case int8: - p.Data.Write(encodeInteger(int64(v))) - case uint8: - p.Data.Write(encodeInteger(int64(v))) - default: - // TODO : add support for big.Int ? - panic(fmt.Sprintf("Invalid type %T, expected {u|}int{64|32|16|8}", v)) - } - - return p -} - -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)) - - return p -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/content_int.go b/vendor/github.com/go-asn1-ber/asn1-ber/content_int.go deleted file mode 100644 index 1858b74b..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/content_int.go +++ /dev/null @@ -1,25 +0,0 @@ -package ber - -func encodeUnsignedInteger(i uint64) []byte { - n := uint64Length(i) - out := make([]byte, n) - - var j int - for ; n > 0; n-- { - out[j] = (byte(i >> uint((n-1)*8))) - j++ - } - - return out -} - -func uint64Length(i uint64) (numBytes int) { - numBytes = 1 - - for i > 255 { - numBytes++ - i >>= 8 - } - - return -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/go.mod b/vendor/github.com/go-asn1-ber/asn1-ber/go.mod deleted file mode 100644 index ee0b4be2..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/go-asn1-ber/asn1-ber - -go 1.13 diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/header.go b/vendor/github.com/go-asn1-ber/asn1-ber/header.go deleted file mode 100644 index 71615621..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/header.go +++ /dev/null @@ -1,35 +0,0 @@ -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 - } - - if l, c, err := readLength(reader); err != nil { - return Identifier{}, 0, read, err - } else { - 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 -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/identifier.go b/vendor/github.com/go-asn1-ber/asn1-ber/identifier.go deleted file mode 100644 index e8c43574..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/identifier.go +++ /dev/null @@ -1,112 +0,0 @@ -package ber - -import ( - "errors" - "fmt" - "io" -) - -func readIdentifier(reader io.Reader) (Identifier, int, error) { - identifier := Identifier{} - read := 0 - - // identifier byte - b, err := readByte(reader) - if err != nil { - if Debug { - fmt.Printf("error reading identifier byte: %v\n", err) - } - return Identifier{}, read, err - } - read++ - - identifier.ClassType = Class(b) & ClassBitmask - identifier.TagType = Type(b) & TypeBitmask - - if tag := Tag(b) & TagBitmask; tag != HighTag { - // short-form tag - identifier.Tag = tag - return identifier, read, nil - } - - // high-tag-number tag - tagBytes := 0 - for { - b, err := readByte(reader) - if err != nil { - if Debug { - fmt.Printf("error reading high-tag-number tag byte %d: %v\n", tagBytes, err) - } - return Identifier{}, read, err - } - tagBytes++ - read++ - - // Lowest 7 bits get appended to the tag value (x.690, 8.1.2.4.2.b) - identifier.Tag <<= 7 - identifier.Tag |= Tag(b) & HighTagValueBitmask - - // First byte may not be all zeros (x.690, 8.1.2.4.2.c) - if tagBytes == 1 && identifier.Tag == 0 { - return Identifier{}, read, errors.New("invalid first high-tag-number tag byte") - } - // Overflow of int64 - // TODO: support big int tags? - if tagBytes > 9 { - return Identifier{}, read, errors.New("high-tag-number tag overflow") - } - - // Top bit of 0 means this is the last byte in the high-tag-number tag (x.690, 8.1.2.4.2.a) - if Tag(b)&HighTagContinueBitmask == 0 { - break - } - } - - return identifier, read, nil -} - -func encodeIdentifier(identifier Identifier) []byte { - b := []byte{0x0} - b[0] |= byte(identifier.ClassType) - b[0] |= byte(identifier.TagType) - - if identifier.Tag < HighTag { - // Short-form - b[0] |= byte(identifier.Tag) - } else { - // high-tag-number - b[0] |= byte(HighTag) - - tag := identifier.Tag - - 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 -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/length.go b/vendor/github.com/go-asn1-ber/asn1-ber/length.go deleted file mode 100644 index 750e8f44..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/length.go +++ /dev/null @@ -1,81 +0,0 @@ -package ber - -import ( - "errors" - "fmt" - "io" -) - -func readLength(reader io.Reader) (length int, read int, err error) { - // length byte - b, err := readByte(reader) - if err != nil { - if Debug { - fmt.Printf("error reading length byte: %v\n", err) - } - return 0, 0, err - } - read++ - - switch { - case b == 0xFF: - // Invalid 0xFF (x.600, 8.1.3.5.c) - return 0, read, errors.New("invalid length byte 0xff") - - case b == LengthLongFormBitmask: - // Indefinite form, we have to decode packets until we encounter an EOC packet (x.600, 8.1.3.6) - length = LengthIndefinite - - case b&LengthLongFormBitmask == 0: - // Short definite form, extract the length from the bottom 7 bits (x.600, 8.1.3.4) - length = int(b) & LengthValueBitmask - - case b&LengthLongFormBitmask != 0: - // Long definite form, extract the number of length bytes to follow from the bottom 7 bits (x.600, 8.1.3.5.b) - lengthBytes := int(b) & LengthValueBitmask - // Protect against overflow - // TODO: support big int length? - 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 { - if Debug { - fmt.Printf("error reading long-form length byte %d: %v\n", i, err) - } - return 0, read, err - } - read++ - - // x.600, 8.1.3.5 - 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: - return 0, read, errors.New("invalid length byte") - } - - return length, read, nil -} - -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 - } - return length_bytes -} diff --git a/vendor/github.com/go-asn1-ber/asn1-ber/util.go b/vendor/github.com/go-asn1-ber/asn1-ber/util.go deleted file mode 100644 index 3e56b66c..00000000 --- a/vendor/github.com/go-asn1-ber/asn1-ber/util.go +++ /dev/null @@ -1,24 +0,0 @@ -package ber - -import "io" - -func readByte(reader io.Reader) (byte, error) { - bytes := make([]byte, 1, 1) - _, err := io.ReadFull(reader, bytes) - if err != nil { - if err == io.EOF { - return 0, io.ErrUnexpectedEOF - } - return 0, err - } - return bytes[0], nil -} - -func isEOCPacket(p *Packet) bool { - return p != nil && - p.Tag == TagEOC && - p.ClassType == ClassUniversal && - p.TagType == TypePrimitive && - len(p.ByteValue) == 0 && - len(p.Children) == 0 -} diff --git a/vendor/github.com/go-ldap/ldap/v3/LICENSE b/vendor/github.com/go-ldap/ldap/v3/LICENSE deleted file mode 100644 index 6c0ed4b3..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com) -Portions copyright (c) 2015-2016 go-ldap 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. diff --git a/vendor/github.com/go-ldap/ldap/v3/add.go b/vendor/github.com/go-ldap/ldap/v3/add.go deleted file mode 100644 index baecd787..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/add.go +++ /dev/null @@ -1,91 +0,0 @@ -package ldap - -import ( - "log" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// Attribute represents an LDAP attribute -type Attribute struct { - // Type is the name of the LDAP attribute - Type string - // Vals are the LDAP attribute values - Vals []string -} - -func (a *Attribute) encode() *ber.Packet { - seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute") - seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.Type, "Type")) - set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue") - for _, value := range a.Vals { - set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals")) - } - seq.AppendChild(set) - return seq -} - -// AddRequest represents an LDAP AddRequest operation -type AddRequest struct { - // DN identifies the entry being added - DN string - // Attributes list the attributes of the new entry - Attributes []Attribute - // Controls hold optional controls to send with the request - Controls []Control -} - -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 req.Attributes { - attributes.AppendChild(attribute.encode()) - } - 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 (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 -func NewAddRequest(dn string, controls []Control) *AddRequest { - return &AddRequest{ - DN: dn, - Controls: controls, - } - -} - -// Add performs the given AddRequest -func (l *Conn) Add(addRequest *AddRequest) error { - msgCtx, err := l.doRequest(addRequest) - if err != nil { - return err - } - defer l.finishMessage(msgCtx) - - packet, err := l.readPacket(msgCtx) - if err != nil { - return err - } - - if packet.Children[1].Tag == ApplicationAddResponse { - err := GetLDAPError(packet) - if err != nil { - return err - } - } else { - log.Printf("Unexpected Response: %d", packet.Children[1].Tag) - } - return nil -} diff --git a/vendor/github.com/go-ldap/ldap/v3/bind.go b/vendor/github.com/go-ldap/ldap/v3/bind.go deleted file mode 100644 index 1f429369..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/bind.go +++ /dev/null @@ -1,389 +0,0 @@ -package ldap - -import ( - "bytes" - "crypto/md5" - enchex "encoding/hex" - "errors" - "fmt" - "io/ioutil" - "math/rand" - "strings" - - 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) -} diff --git a/vendor/github.com/go-ldap/ldap/v3/client.go b/vendor/github.com/go-ldap/ldap/v3/client.go deleted file mode 100644 index 619677c7..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/client.go +++ /dev/null @@ -1,30 +0,0 @@ -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) -} diff --git a/vendor/github.com/go-ldap/ldap/v3/compare.go b/vendor/github.com/go-ldap/ldap/v3/compare.go deleted file mode 100644 index cd43e4c5..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/compare.go +++ /dev/null @@ -1,61 +0,0 @@ -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) -} diff --git a/vendor/github.com/go-ldap/ldap/v3/conn.go b/vendor/github.com/go-ldap/ldap/v3/conn.go deleted file mode 100644 index 3643064f..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/conn.go +++ /dev/null @@ -1,570 +0,0 @@ -package ldap - -import ( - "crypto/tls" - "errors" - "fmt" - "log" - "net" - "net/url" - "sync" - "sync/atomic" - "time" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -const ( - // MessageQuit causes the processMessages loop to exit - MessageQuit = 0 - // MessageRequest sends a request to the server - MessageRequest = 1 - // MessageResponse receives a response from the server - MessageResponse = 2 - // MessageFinish indicates the client considers a particular message ID to be finished - MessageFinish = 3 - // MessageTimeout indicates the client-specified timeout for a particular message ID has been reached - MessageTimeout = 4 -) - -const ( - // DefaultLdapPort default ldap port for pure TCP connection - DefaultLdapPort = "389" - // DefaultLdapsPort default ldap port for SSL connection - DefaultLdapsPort = "636" -) - -// PacketResponse contains the packet or error encountered reading a response -type PacketResponse struct { - // Packet is the packet read from the server - Packet *ber.Packet - // Error is an error encountered while reading - Error error -} - -// ReadPacket returns the packet or an error -func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) { - if (pr == nil) || (pr.Packet == nil && pr.Error == nil) { - return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve response")) - } - return pr.Packet, pr.Error -} - -type messageContext struct { - id int64 - // close(done) should only be called from finishMessage() - done chan struct{} - // close(responses) should only be called from processMessages(), and only sent to from sendResponse() - responses chan *PacketResponse -} - -// sendResponse should only be called within the processMessages() loop which -// is also responsible for closing the responses channel. -func (msgCtx *messageContext) sendResponse(packet *PacketResponse) { - select { - case msgCtx.responses <- packet: - // Successfully sent packet to message handler. - case <-msgCtx.done: - // The request handler is done and will not receive more - // packets. - } -} - -type messagePacket struct { - Op int - MessageID int64 - Packet *ber.Packet - Context *messageContext -} - -type sendMessageFlags uint - -const ( - startTLS sendMessageFlags = 1 << iota -) - -// Conn represents an LDAP Connection -type Conn struct { - // requestTimeout is loaded atomically - // so we need to ensure 64-bit alignment on 32-bit platforms. - requestTimeout int64 - conn net.Conn - isTLS bool - closing uint32 - closeErr atomic.Value - isStartingTLS bool - Debug debugging - chanConfirm chan struct{} - messageContexts map[int64]*messageContext - chanMessage chan *messagePacket - chanMessageID chan int64 - wgClose sync.WaitGroup - outstandingRequests uint - messageMutex sync.Mutex -} - -var _ Client = &Conn{} - -// DefaultTimeout is a package-level variable that sets the timeout value -// used for the Dial and DialTLS methods. -// -// WARNING: since this is a package-level variable, setting this value from -// 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 asume 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 { - return nil, NewError(ErrorNetwork, err) - } - conn := NewConn(c, false) - conn.Start() - return conn, nil -} - -// 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 { - return nil, NewError(ErrorNetwork, err) - } - conn := NewConn(c, true) - conn.Start() - return conn, nil -} - -// 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) - } - - 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 { - return nil, NewError(ErrorNetwork, err) - } - - conn := NewConn(c, u.Scheme == "ldaps") - conn.Start() - return conn, nil -} - -// NewConn returns a new Conn using conn for network I/O. -func NewConn(conn net.Conn, isTLS bool) *Conn { - return &Conn{ - conn: conn, - chanConfirm: make(chan struct{}), - chanMessageID: make(chan int64), - chanMessage: make(chan *messagePacket, 10), - messageContexts: map[int64]*messageContext{}, - requestTimeout: 0, - isTLS: isTLS, - } -} - -// Start initializes goroutines to read responses and process messages -func (l *Conn) Start() { - l.wgClose.Add(1) - go l.reader() - go l.processMessages() -} - -// IsClosing returns whether or not we're currently closing. -func (l *Conn) IsClosing() bool { - return atomic.LoadUint32(&l.closing) == 1 -} - -// setClosing sets the closing value to true -func (l *Conn) setClosing() bool { - return atomic.CompareAndSwapUint32(&l.closing, 0, 1) -} - -// Close closes the connection. -func (l *Conn) Close() { - l.messageMutex.Lock() - defer l.messageMutex.Unlock() - - if l.setClosing() { - l.Debug.Printf("Sending quit message and waiting for confirmation") - l.chanMessage <- &messagePacket{Op: MessageQuit} - <-l.chanConfirm - close(l.chanMessage) - - l.Debug.Printf("Closing network connection") - if err := l.conn.Close(); err != nil { - log.Println(err) - } - - l.wgClose.Done() - } - l.wgClose.Wait() -} - -// SetTimeout sets the time after a request is sent that a MessageTimeout triggers -func (l *Conn) SetTimeout(timeout time.Duration) { - if timeout > 0 { - atomic.StoreInt64(&l.requestTimeout, int64(timeout)) - } -} - -// Returns the next available messageID -func (l *Conn) nextMessageID() int64 { - if messageID, ok := <-l.chanMessageID; ok { - return messageID - } - return 0 -} - -// StartTLS sends the command to start a TLS session and then creates a new TLS Client -func (l *Conn) StartTLS(config *tls.Config) error { - if l.isTLS { - return NewError(ErrorNetwork, errors.New("ldap: already encrypted")) - } - - 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, ApplicationExtendedRequest, nil, "Start TLS") - request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command")) - packet.AppendChild(request) - l.Debug.PrintPacket(packet) - - msgCtx, err := l.sendMessageWithFlags(packet, startTLS) - 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 { - l.Close() - return err - } - l.Debug.PrintPacket(packet) - } - - if err := GetLDAPError(packet); err == nil { - conn := tls.Client(l.conn, config) - - if connErr := conn.Handshake(); connErr != nil { - l.Close() - return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", connErr)) - } - - l.isTLS = true - l.conn = conn - } else { - return err - } - go l.reader() - - return nil -} - -// TLSConnectionState returns the client's TLS connection state. -// The return values are their zero values if StartTLS did -// not succeed. -func (l *Conn) TLSConnectionState() (state tls.ConnectionState, ok bool) { - tc, ok := l.conn.(*tls.Conn) - if !ok { - return - } - return tc.ConnectionState(), true -} - -func (l *Conn) sendMessage(packet *ber.Packet) (*messageContext, error) { - return l.sendMessageWithFlags(packet, 0) -} - -func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags) (*messageContext, error) { - if l.IsClosing() { - return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed")) - } - l.messageMutex.Lock() - l.Debug.Printf("flags&startTLS = %d", flags&startTLS) - if l.isStartingTLS { - l.messageMutex.Unlock() - return nil, NewError(ErrorNetwork, errors.New("ldap: connection is in startls phase")) - } - if flags&startTLS != 0 { - if l.outstandingRequests != 0 { - l.messageMutex.Unlock() - return nil, NewError(ErrorNetwork, errors.New("ldap: cannot StartTLS with outstanding requests")) - } - l.isStartingTLS = true - } - l.outstandingRequests++ - - l.messageMutex.Unlock() - - responses := make(chan *PacketResponse) - messageID := packet.Children[0].Value.(int64) - message := &messagePacket{ - Op: MessageRequest, - MessageID: messageID, - Packet: packet, - Context: &messageContext{ - id: messageID, - done: make(chan struct{}), - responses: responses, - }, - } - 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 -} - -func (l *Conn) finishMessage(msgCtx *messageContext) { - close(msgCtx.done) - - if l.IsClosing() { - return - } - - l.messageMutex.Lock() - l.outstandingRequests-- - if l.isStartingTLS { - l.isStartingTLS = false - } - l.messageMutex.Unlock() - - message := &messagePacket{ - Op: MessageFinish, - MessageID: msgCtx.id, - } - l.sendProcessMessage(message) -} - -func (l *Conn) sendProcessMessage(message *messagePacket) bool { - l.messageMutex.Lock() - defer l.messageMutex.Unlock() - if l.IsClosing() { - return false - } - l.chanMessage <- message - return true -} - -func (l *Conn) processMessages() { - defer func() { - if err := recover(); err != nil { - log.Printf("ldap: recovered panic in processMessages: %v", err) - } - for messageID, msgCtx := range l.messageContexts { - // If we are closing due to an error, inform anyone who - // is waiting about the error. - if l.IsClosing() && l.closeErr.Load() != nil { - msgCtx.sendResponse(&PacketResponse{Error: l.closeErr.Load().(error)}) - } - l.Debug.Printf("Closing channel for MessageID %d", messageID) - close(msgCtx.responses) - delete(l.messageContexts, messageID) - } - close(l.chanMessageID) - close(l.chanConfirm) - }() - - var messageID int64 = 1 - for { - select { - case l.chanMessageID <- messageID: - messageID++ - case message := <-l.chanMessage: - switch message.Op { - case MessageQuit: - l.Debug.Printf("Shutting down - quit message received") - return - case MessageRequest: - // Add to message list and write to network - l.Debug.Printf("Sending message %d", message.MessageID) - - buf := message.Packet.Bytes() - _, err := l.conn.Write(buf) - if err != nil { - l.Debug.Printf("Error Sending Message: %s", err.Error()) - message.Context.sendResponse(&PacketResponse{Error: fmt.Errorf("unable to send request: %s", err)}) - close(message.Context.responses) - break - } - - // Only add to messageContexts if we were able to - // successfully write the message. - l.messageContexts[message.MessageID] = message.Context - - // Add timeout if defined - requestTimeout := time.Duration(atomic.LoadInt64(&l.requestTimeout)) - if requestTimeout > 0 { - go func() { - defer func() { - if err := recover(); err != nil { - log.Printf("ldap: recovered panic in RequestTimeout: %v", err) - } - }() - time.Sleep(requestTimeout) - timeoutMessage := &messagePacket{ - Op: MessageTimeout, - MessageID: message.MessageID, - } - l.sendProcessMessage(timeoutMessage) - }() - } - case MessageResponse: - l.Debug.Printf("Receiving message %d", message.MessageID) - if msgCtx, ok := l.messageContexts[message.MessageID]; ok { - msgCtx.sendResponse(&PacketResponse{message.Packet, nil}) - } else { - log.Printf("Received unexpected message %d, %v", message.MessageID, l.IsClosing()) - l.Debug.PrintPacket(message.Packet) - } - case MessageTimeout: - // Handle the timeout by closing the channel - // All reads will return immediately - if msgCtx, ok := l.messageContexts[message.MessageID]; ok { - l.Debug.Printf("Receiving message timeout for %d", message.MessageID) - msgCtx.sendResponse(&PacketResponse{message.Packet, errors.New("ldap: connection timed out")}) - delete(l.messageContexts, message.MessageID) - close(msgCtx.responses) - } - case MessageFinish: - l.Debug.Printf("Finished message %d", message.MessageID) - if msgCtx, ok := l.messageContexts[message.MessageID]; ok { - delete(l.messageContexts, message.MessageID) - close(msgCtx.responses) - } - } - } - } -} - -func (l *Conn) reader() { - cleanstop := false - defer func() { - if err := recover(); err != nil { - log.Printf("ldap: recovered panic in reader: %v", err) - } - if !cleanstop { - l.Close() - } - }() - - for { - if cleanstop { - l.Debug.Printf("reader clean stopping (without closing the connection)") - return - } - packet, err := ber.ReadPacket(l.conn) - if err != nil { - // 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) - } - return - } - 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 - } - l.messageMutex.Lock() - if l.isStartingTLS { - cleanstop = true - } - l.messageMutex.Unlock() - message := &messagePacket{ - Op: MessageResponse, - MessageID: packet.Children[0].Value.(int64), - Packet: packet, - } - if !l.sendProcessMessage(message) { - return - } - } -} diff --git a/vendor/github.com/go-ldap/ldap/v3/control.go b/vendor/github.com/go-ldap/ldap/v3/control.go deleted file mode 100644 index 463fe3a3..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/control.go +++ /dev/null @@ -1,499 +0,0 @@ -package ldap - -import ( - "fmt" - "strconv" - - "github.com/go-asn1-ber/asn1-ber" -) - -const ( - // ControlTypePaging - https://www.ietf.org/rfc/rfc2696.txt - ControlTypePaging = "1.2.840.113556.1.4.319" - // ControlTypeBeheraPasswordPolicy - https://tools.ietf.org/html/draft-behera-ldap-password-policy-10 - ControlTypeBeheraPasswordPolicy = "1.3.6.1.4.1.42.2.27.8.5.1" - // ControlTypeVChuPasswordMustChange - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00 - ControlTypeVChuPasswordMustChange = "2.16.840.1.113730.3.4.4" - // ControlTypeVChuPasswordWarning - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00 - ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5" - // ControlTypeManageDsaIT - https://tools.ietf.org/html/rfc3296 - ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2" - - // ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx - ControlTypeMicrosoftNotification = "1.2.840.113556.1.4.528" - // ControlTypeMicrosoftShowDeleted - https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx - ControlTypeMicrosoftShowDeleted = "1.2.840.113556.1.4.417" -) - -// ControlTypeMap maps controls to text descriptions -var ControlTypeMap = map[string]string{ - ControlTypePaging: "Paging", - ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft", - ControlTypeManageDsaIT: "Manage DSA IT", - ControlTypeMicrosoftNotification: "Change Notification - Microsoft", - ControlTypeMicrosoftShowDeleted: "Show Deleted Objects - Microsoft", -} - -// Control defines an interface controls provide to encode and describe themselves -type Control interface { - // GetControlType returns the OID - GetControlType() string - // Encode returns the ber packet representation - Encode() *ber.Packet - // String returns a human-readable description - String() string -} - -// ControlString implements the Control interface for simple controls -type ControlString struct { - ControlType string - Criticality bool - ControlValue string -} - -// GetControlType returns the OID -func (c *ControlString) GetControlType() string { - return c.ControlType -} - -// Encode returns the ber packet representation -func (c *ControlString) Encode() *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlType, "Control Type ("+ControlTypeMap[c.ControlType]+")")) - if c.Criticality { - packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality")) - } - if c.ControlValue != "" { - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(c.ControlValue), "Control Value")) - } - return packet -} - -// String returns a human-readable description -func (c *ControlString) String() string { - return fmt.Sprintf("Control Type: %s (%q) Criticality: %t Control Value: %s", ControlTypeMap[c.ControlType], c.ControlType, c.Criticality, c.ControlValue) -} - -// ControlPaging implements the paging control described in https://www.ietf.org/rfc/rfc2696.txt -type ControlPaging struct { - // PagingSize indicates the page size - PagingSize uint32 - // Cookie is an opaque value returned by the server to track a paging cursor - Cookie []byte -} - -// GetControlType returns the OID -func (c *ControlPaging) GetControlType() string { - return ControlTypePaging -} - -// Encode returns the ber packet representation -func (c *ControlPaging) Encode() *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypePaging, "Control Type ("+ControlTypeMap[ControlTypePaging]+")")) - - p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)") - seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value") - seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, int64(c.PagingSize), "Paging Size")) - cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie") - cookie.Value = c.Cookie - cookie.Data.Write(c.Cookie) - seq.AppendChild(cookie) - p2.AppendChild(seq) - - packet.AppendChild(p2) - return packet -} - -// String returns a human-readable description -func (c *ControlPaging) String() string { - return fmt.Sprintf( - "Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q", - ControlTypeMap[ControlTypePaging], - ControlTypePaging, - false, - c.PagingSize, - c.Cookie) -} - -// SetCookie stores the given cookie in the paging control -func (c *ControlPaging) SetCookie(cookie []byte) { - c.Cookie = cookie -} - -// ControlBeheraPasswordPolicy implements the control described in https://tools.ietf.org/html/draft-behera-ldap-password-policy-10 -type ControlBeheraPasswordPolicy struct { - // Expire contains the number of seconds before a password will expire - Expire int64 - // Grace indicates the remaining number of times a user will be allowed to authenticate with an expired password - Grace int64 - // Error indicates the error code - Error int8 - // ErrorString is a human readable error - ErrorString string -} - -// GetControlType returns the OID -func (c *ControlBeheraPasswordPolicy) GetControlType() string { - return ControlTypeBeheraPasswordPolicy -} - -// Encode returns the ber packet representation -func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeBeheraPasswordPolicy, "Control Type ("+ControlTypeMap[ControlTypeBeheraPasswordPolicy]+")")) - - return packet -} - -// String returns a human-readable description -func (c *ControlBeheraPasswordPolicy) String() string { - return fmt.Sprintf( - "Control Type: %s (%q) Criticality: %t Expire: %d Grace: %d Error: %d, ErrorString: %s", - ControlTypeMap[ControlTypeBeheraPasswordPolicy], - ControlTypeBeheraPasswordPolicy, - false, - c.Expire, - c.Grace, - c.Error, - c.ErrorString) -} - -// ControlVChuPasswordMustChange implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00 -type ControlVChuPasswordMustChange struct { - // MustChange indicates if the password is required to be changed - MustChange bool -} - -// GetControlType returns the OID -func (c *ControlVChuPasswordMustChange) GetControlType() string { - return ControlTypeVChuPasswordMustChange -} - -// Encode returns the ber packet representation -func (c *ControlVChuPasswordMustChange) Encode() *ber.Packet { - return nil -} - -// String returns a human-readable description -func (c *ControlVChuPasswordMustChange) String() string { - return fmt.Sprintf( - "Control Type: %s (%q) Criticality: %t MustChange: %v", - ControlTypeMap[ControlTypeVChuPasswordMustChange], - ControlTypeVChuPasswordMustChange, - false, - c.MustChange) -} - -// ControlVChuPasswordWarning implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00 -type ControlVChuPasswordWarning struct { - // Expire indicates the time in seconds until the password expires - Expire int64 -} - -// GetControlType returns the OID -func (c *ControlVChuPasswordWarning) GetControlType() string { - return ControlTypeVChuPasswordWarning -} - -// Encode returns the ber packet representation -func (c *ControlVChuPasswordWarning) Encode() *ber.Packet { - return nil -} - -// String returns a human-readable description -func (c *ControlVChuPasswordWarning) String() string { - return fmt.Sprintf( - "Control Type: %s (%q) Criticality: %t Expire: %b", - ControlTypeMap[ControlTypeVChuPasswordWarning], - ControlTypeVChuPasswordWarning, - false, - c.Expire) -} - -// ControlManageDsaIT implements the control described in https://tools.ietf.org/html/rfc3296 -type ControlManageDsaIT struct { - // Criticality indicates if this control is required - Criticality bool -} - -// GetControlType returns the OID -func (c *ControlManageDsaIT) GetControlType() string { - return ControlTypeManageDsaIT -} - -// Encode returns the ber packet representation -func (c *ControlManageDsaIT) Encode() *ber.Packet { - //FIXME - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeManageDsaIT, "Control Type ("+ControlTypeMap[ControlTypeManageDsaIT]+")")) - if c.Criticality { - packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality")) - } - return packet -} - -// String returns a human-readable description -func (c *ControlManageDsaIT) String() string { - return fmt.Sprintf( - "Control Type: %s (%q) Criticality: %t", - ControlTypeMap[ControlTypeManageDsaIT], - ControlTypeManageDsaIT, - c.Criticality) -} - -// NewControlManageDsaIT returns a ControlManageDsaIT control -func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT { - return &ControlManageDsaIT{Criticality: Criticality} -} - -// ControlMicrosoftNotification implements the control described in https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx -type ControlMicrosoftNotification struct{} - -// GetControlType returns the OID -func (c *ControlMicrosoftNotification) GetControlType() string { - return ControlTypeMicrosoftNotification -} - -// Encode returns the ber packet representation -func (c *ControlMicrosoftNotification) Encode() *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftNotification, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftNotification]+")")) - - return packet -} - -// String returns a human-readable description -func (c *ControlMicrosoftNotification) String() string { - return fmt.Sprintf( - "Control Type: %s (%q)", - ControlTypeMap[ControlTypeMicrosoftNotification], - ControlTypeMicrosoftNotification) -} - -// NewControlMicrosoftNotification returns a ControlMicrosoftNotification control -func NewControlMicrosoftNotification() *ControlMicrosoftNotification { - return &ControlMicrosoftNotification{} -} - -// ControlMicrosoftShowDeleted implements the control described in https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx -type ControlMicrosoftShowDeleted struct{} - -// GetControlType returns the OID -func (c *ControlMicrosoftShowDeleted) GetControlType() string { - return ControlTypeMicrosoftShowDeleted -} - -// Encode returns the ber packet representation -func (c *ControlMicrosoftShowDeleted) Encode() *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftShowDeleted, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftShowDeleted]+")")) - - return packet -} - -// String returns a human-readable description -func (c *ControlMicrosoftShowDeleted) String() string { - return fmt.Sprintf( - "Control Type: %s (%q)", - ControlTypeMap[ControlTypeMicrosoftShowDeleted], - ControlTypeMicrosoftShowDeleted) -} - -// NewControlMicrosoftShowDeleted returns a ControlMicrosoftShowDeleted control -func NewControlMicrosoftShowDeleted() *ControlMicrosoftShowDeleted { - return &ControlMicrosoftShowDeleted{} -} - -// FindControl returns the first control of the given type in the list, or nil -func FindControl(controls []Control, controlType string) Control { - for _, c := range controls { - if c.GetControlType() == controlType { - return c - } - } - return nil -} - -// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made -func DecodeControl(packet *ber.Packet) (Control, error) { - var ( - ControlType = "" - Criticality = false - value *ber.Packet - ) - - switch len(packet.Children) { - case 0: - // at least one child is required for control type - return nil, fmt.Errorf("at least one child is required for control type") - - case 1: - // just type, no criticality or value - packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")" - ControlType = packet.Children[0].Value.(string) - - case 2: - packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")" - ControlType = packet.Children[0].Value.(string) - - // Children[1] could be criticality or value (both are optional) - // duck-type on whether this is a boolean - if _, ok := packet.Children[1].Value.(bool); ok { - packet.Children[1].Description = "Criticality" - Criticality = packet.Children[1].Value.(bool) - } else { - packet.Children[1].Description = "Control Value" - value = packet.Children[1] - } - - case 3: - packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")" - ControlType = packet.Children[0].Value.(string) - - packet.Children[1].Description = "Criticality" - Criticality = packet.Children[1].Value.(bool) - - packet.Children[2].Description = "Control Value" - value = packet.Children[2] - - default: - // more than 3 children is invalid - return nil, fmt.Errorf("more than 3 children is invalid for controls") - } - - switch ControlType { - case ControlTypeManageDsaIT: - return NewControlManageDsaIT(Criticality), nil - case ControlTypePaging: - value.Description += " (Paging)" - c := new(ControlPaging) - if value.Value != nil { - valueChildren, err := ber.DecodePacketErr(value.Data.Bytes()) - if err != nil { - return nil, fmt.Errorf("failed to decode data bytes: %s", err) - } - value.Data.Truncate(0) - value.Value = nil - value.AppendChild(valueChildren) - } - value = value.Children[0] - value.Description = "Search Control Value" - value.Children[0].Description = "Paging Size" - value.Children[1].Description = "Cookie" - c.PagingSize = uint32(value.Children[0].Value.(int64)) - c.Cookie = value.Children[1].Data.Bytes() - value.Children[1].Value = c.Cookie - return c, nil - case ControlTypeBeheraPasswordPolicy: - value.Description += " (Password Policy - Behera)" - c := NewControlBeheraPasswordPolicy() - if value.Value != nil { - valueChildren, err := ber.DecodePacketErr(value.Data.Bytes()) - if err != nil { - return nil, fmt.Errorf("failed to decode data bytes: %s", err) - } - value.Data.Truncate(0) - value.Value = nil - value.AppendChild(valueChildren) - } - - sequence := value.Children[0] - - for _, child := range sequence.Children { - if child.Tag == 0 { - //Warning - warningPacket := child.Children[0] - packet, err := ber.DecodePacketErr(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 - } - } - } 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 - } - c.Error = val - child.Value = c.Error - c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error] - } - } - return c, nil - case ControlTypeVChuPasswordMustChange: - c := &ControlVChuPasswordMustChange{MustChange: true} - return c, nil - case ControlTypeVChuPasswordWarning: - c := &ControlVChuPasswordWarning{Expire: -1} - expireStr := ber.DecodeString(value.Data.Bytes()) - - expire, err := strconv.ParseInt(expireStr, 10, 64) - if err != nil { - return nil, fmt.Errorf("failed to parse value as int: %s", err) - } - c.Expire = expire - value.Value = c.Expire - - return c, nil - case ControlTypeMicrosoftNotification: - return NewControlMicrosoftNotification(), nil - case ControlTypeMicrosoftShowDeleted: - return NewControlMicrosoftShowDeleted(), nil - default: - c := new(ControlString) - c.ControlType = ControlType - c.Criticality = Criticality - if value != nil { - c.ControlValue = value.Value.(string) - } - return c, nil - } -} - -// NewControlString returns a generic control -func NewControlString(controlType string, criticality bool, controlValue string) *ControlString { - return &ControlString{ - ControlType: controlType, - Criticality: criticality, - ControlValue: controlValue, - } -} - -// NewControlPaging returns a paging control -func NewControlPaging(pagingSize uint32) *ControlPaging { - return &ControlPaging{PagingSize: pagingSize} -} - -// NewControlBeheraPasswordPolicy returns a ControlBeheraPasswordPolicy -func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy { - return &ControlBeheraPasswordPolicy{ - Expire: -1, - Grace: -1, - Error: -1, - } -} - -func encodeControls(controls []Control) *ber.Packet { - packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls") - for _, control := range controls { - packet.AppendChild(control.Encode()) - } - return packet -} diff --git a/vendor/github.com/go-ldap/ldap/v3/debug.go b/vendor/github.com/go-ldap/ldap/v3/debug.go deleted file mode 100644 index 2c0b30c8..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/debug.go +++ /dev/null @@ -1,30 +0,0 @@ -package ldap - -import ( - "log" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// debugging type -// - has a Printf method to write the debug output -type debugging bool - -// 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) - } -} diff --git a/vendor/github.com/go-ldap/ldap/v3/del.go b/vendor/github.com/go-ldap/ldap/v3/del.go deleted file mode 100644 index 6e987267..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/del.go +++ /dev/null @@ -1,59 +0,0 @@ -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 -} diff --git a/vendor/github.com/go-ldap/ldap/v3/dn.go b/vendor/github.com/go-ldap/ldap/v3/dn.go deleted file mode 100644 index bff137cc..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/dn.go +++ /dev/null @@ -1,207 +0,0 @@ -package ldap - -import ( - "bytes" - enchex "encoding/hex" - "errors" - "fmt" - "strings" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// AttributeTypeAndValue represents an attributeTypeAndValue from https://tools.ietf.org/html/rfc4514 -type AttributeTypeAndValue struct { - // Type is the attribute type - Type string - // Value is the attribute value - Value string -} - -// RelativeDN represents a relativeDistinguishedName from https://tools.ietf.org/html/rfc4514 -type RelativeDN struct { - Attributes []*AttributeTypeAndValue -} - -// DN represents a distinguishedName from https://tools.ietf.org/html/rfc4514 -type DN struct { - RDNs []*RelativeDN -} - -// 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) - rdn := new(RelativeDN) - rdn.Attributes = make([]*AttributeTypeAndValue, 0) - buffer := bytes.Buffer{} - attribute := new(AttributeTypeAndValue) - escaping := false - - unescapedTrailingSpaces := 0 - stringFromBuffer := func() string { - s := buffer.String() - s = s[0 : len(s)-unescapedTrailingSpaces] - buffer.Reset() - unescapedTrailingSpaces = 0 - return s - } - - for i := 0; i < len(str); i++ { - char := str[i] - switch { - case escaping: - unescapedTrailingSpaces = 0 - escaping = false - switch char { - case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\': - buffer.WriteByte(char) - continue - } - // Not a special character, assume hex encoded octet - if len(str) == i+1 { - return nil, errors.New("got corrupted escaped character") - } - - dst := []byte{0} - n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2])) - if err != nil { - return nil, fmt.Errorf("failed to decode escaped character: %s", err) - } else if n != 1 { - return nil, fmt.Errorf("expected 1 byte when un-escaping, got %d", n) - } - buffer.WriteByte(dst[0]) - i++ - case char == '\\': - unescapedTrailingSpaces = 0 - escaping = true - case char == '=': - attribute.Type = stringFromBuffer() - // Special case: If the first character in the value is # the - // following data is BER encoded so we can just fast forward - // and decode. - if len(str) > i+1 && str[i+1] == '#' { - i += 2 - index := strings.IndexAny(str[i:], ",+") - data := str - if index > 0 { - data = str[i : i+index] - } else { - data = str[i:] - } - rawBER, err := enchex.DecodeString(data) - if err != nil { - return nil, fmt.Errorf("failed to decode BER encoding: %s", err) - } - packet, err := ber.DecodePacketErr(rawBER) - if err != nil { - return nil, fmt.Errorf("failed to decode BER packet: %s", err) - } - buffer.WriteString(packet.Data.String()) - i += len(data) - 1 - } - case char == ',' || char == '+': - // We're done with this RDN or value, push it - if len(attribute.Type) == 0 { - return nil, errors.New("incomplete type, value pair") - } - attribute.Value = stringFromBuffer() - rdn.Attributes = append(rdn.Attributes, attribute) - attribute = new(AttributeTypeAndValue) - if char == ',' { - dn.RDNs = append(dn.RDNs, rdn) - rdn = new(RelativeDN) - rdn.Attributes = make([]*AttributeTypeAndValue, 0) - } - case char == ' ' && buffer.Len() == 0: - // ignore unescaped leading spaces - continue - default: - if char == ' ' { - // Track unescaped spaces in case they are trailing and we need to remove them - unescapedTrailingSpaces++ - } else { - // Reset if we see a non-space char - unescapedTrailingSpaces = 0 - } - buffer.WriteByte(char) - } - } - if buffer.Len() > 0 { - if len(attribute.Type) == 0 { - return nil, errors.New("DN ended with incomplete type, value pair") - } - attribute.Value = stringFromBuffer() - rdn.Attributes = append(rdn.Attributes, attribute) - dn.RDNs = append(dn.RDNs, rdn) - } - return dn, nil -} - -// Equal returns true if the DNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch). -// Returns true if they have the same number of relative distinguished names -// and corresponding relative distinguished names (by position) are the same. -func (d *DN) Equal(other *DN) bool { - if len(d.RDNs) != len(other.RDNs) { - return false - } - for i := range d.RDNs { - if !d.RDNs[i].Equal(other.RDNs[i]) { - return false - } - } - return true -} - -// AncestorOf returns true if the other DN consists of at least one RDN followed by all the RDNs of the current DN. -// "ou=widgets,o=acme.com" is an ancestor of "ou=sprockets,ou=widgets,o=acme.com" -// "ou=widgets,o=acme.com" is not an ancestor of "ou=sprockets,ou=widgets,o=foo.com" -// "ou=widgets,o=acme.com" is not an ancestor of "ou=widgets,o=acme.com" -func (d *DN) AncestorOf(other *DN) bool { - if len(d.RDNs) >= len(other.RDNs) { - return false - } - // Take the last `len(d.RDNs)` RDNs from the other DN to compare against - otherRDNs := other.RDNs[len(other.RDNs)-len(d.RDNs):] - for i := range d.RDNs { - if !d.RDNs[i].Equal(otherRDNs[i]) { - return false - } - } - return true -} - -// Equal returns true if the RelativeDNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch). -// Relative distinguished names are the same if and only if they have the same number of AttributeTypeAndValues -// and each attribute of the first RDN is the same as the attribute of the second RDN with the same attribute type. -// The order of attributes is not significant. -// Case of attribute types is not significant. -func (r *RelativeDN) Equal(other *RelativeDN) bool { - if len(r.Attributes) != len(other.Attributes) { - return false - } - return r.hasAllAttributes(other.Attributes) && other.hasAllAttributes(r.Attributes) -} - -func (r *RelativeDN) hasAllAttributes(attrs []*AttributeTypeAndValue) bool { - for _, attr := range attrs { - found := false - for _, myattr := range r.Attributes { - if myattr.Equal(attr) { - found = true - break - } - } - if !found { - return false - } - } - return true -} - -// Equal returns true if the AttributeTypeAndValue is equivalent to the specified AttributeTypeAndValue -// Case of the attribute type is not significant -func (a *AttributeTypeAndValue) Equal(other *AttributeTypeAndValue) bool { - return strings.EqualFold(a.Type, other.Type) && a.Value == other.Value -} diff --git a/vendor/github.com/go-ldap/ldap/v3/doc.go b/vendor/github.com/go-ldap/ldap/v3/doc.go deleted file mode 100644 index f20d39bc..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -/* -Package ldap provides basic LDAP v3 functionality. -*/ -package ldap diff --git a/vendor/github.com/go-ldap/ldap/v3/error.go b/vendor/github.com/go-ldap/ldap/v3/error.go deleted file mode 100644 index b1fda2d8..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/error.go +++ /dev/null @@ -1,236 +0,0 @@ -package ldap - -import ( - "fmt" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// LDAP Result Codes -const ( - LDAPResultSuccess = 0 - LDAPResultOperationsError = 1 - LDAPResultProtocolError = 2 - LDAPResultTimeLimitExceeded = 3 - LDAPResultSizeLimitExceeded = 4 - LDAPResultCompareFalse = 5 - LDAPResultCompareTrue = 6 - LDAPResultAuthMethodNotSupported = 7 - LDAPResultStrongAuthRequired = 8 - LDAPResultReferral = 10 - LDAPResultAdminLimitExceeded = 11 - LDAPResultUnavailableCriticalExtension = 12 - LDAPResultConfidentialityRequired = 13 - LDAPResultSaslBindInProgress = 14 - LDAPResultNoSuchAttribute = 16 - LDAPResultUndefinedAttributeType = 17 - LDAPResultInappropriateMatching = 18 - LDAPResultConstraintViolation = 19 - LDAPResultAttributeOrValueExists = 20 - LDAPResultInvalidAttributeSyntax = 21 - LDAPResultNoSuchObject = 32 - LDAPResultAliasProblem = 33 - LDAPResultInvalidDNSyntax = 34 - LDAPResultIsLeaf = 35 - LDAPResultAliasDereferencingProblem = 36 - LDAPResultInappropriateAuthentication = 48 - LDAPResultInvalidCredentials = 49 - LDAPResultInsufficientAccessRights = 50 - LDAPResultBusy = 51 - LDAPResultUnavailable = 52 - LDAPResultUnwillingToPerform = 53 - LDAPResultLoopDetect = 54 - LDAPResultSortControlMissing = 60 - LDAPResultOffsetRangeError = 61 - LDAPResultNamingViolation = 64 - LDAPResultObjectClassViolation = 65 - LDAPResultNotAllowedOnNonLeaf = 66 - LDAPResultNotAllowedOnRDN = 67 - LDAPResultEntryAlreadyExists = 68 - LDAPResultObjectClassModsProhibited = 69 - LDAPResultResultsTooLarge = 70 - LDAPResultAffectsMultipleDSAs = 71 - LDAPResultVirtualListViewErrorOrControlError = 76 - LDAPResultOther = 80 - LDAPResultServerDown = 81 - LDAPResultLocalError = 82 - LDAPResultEncodingError = 83 - LDAPResultDecodingError = 84 - LDAPResultTimeout = 85 - LDAPResultAuthUnknown = 86 - LDAPResultFilterError = 87 - LDAPResultUserCanceled = 88 - LDAPResultParamError = 89 - LDAPResultNoMemory = 90 - LDAPResultConnectError = 91 - LDAPResultNotSupported = 92 - LDAPResultControlNotFound = 93 - LDAPResultNoResultsReturned = 94 - LDAPResultMoreResultsToReturn = 95 - LDAPResultClientLoop = 96 - LDAPResultReferralLimitExceeded = 97 - LDAPResultInvalidResponse = 100 - LDAPResultAmbiguousResponse = 101 - LDAPResultTLSNotSupported = 112 - LDAPResultIntermediateResponse = 113 - LDAPResultUnknownType = 114 - LDAPResultCanceled = 118 - LDAPResultNoSuchOperation = 119 - LDAPResultTooLate = 120 - LDAPResultCannotCancel = 121 - LDAPResultAssertionFailed = 122 - LDAPResultAuthorizationDenied = 123 - LDAPResultSyncRefreshRequired = 4096 - - ErrorNetwork = 200 - ErrorFilterCompile = 201 - ErrorFilterDecompile = 202 - ErrorDebugging = 203 - ErrorUnexpectedMessage = 204 - ErrorUnexpectedResponse = 205 - ErrorEmptyPassword = 206 -) - -// LDAPResultCodeMap contains string descriptions for LDAP error codes -var LDAPResultCodeMap = map[uint16]string{ - LDAPResultSuccess: "Success", - LDAPResultOperationsError: "Operations Error", - LDAPResultProtocolError: "Protocol Error", - LDAPResultTimeLimitExceeded: "Time Limit Exceeded", - LDAPResultSizeLimitExceeded: "Size Limit Exceeded", - LDAPResultCompareFalse: "Compare False", - LDAPResultCompareTrue: "Compare True", - LDAPResultAuthMethodNotSupported: "Auth Method Not Supported", - LDAPResultStrongAuthRequired: "Strong Auth Required", - LDAPResultReferral: "Referral", - LDAPResultAdminLimitExceeded: "Admin Limit Exceeded", - LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension", - LDAPResultConfidentialityRequired: "Confidentiality Required", - LDAPResultSaslBindInProgress: "Sasl Bind In Progress", - LDAPResultNoSuchAttribute: "No Such Attribute", - LDAPResultUndefinedAttributeType: "Undefined Attribute Type", - LDAPResultInappropriateMatching: "Inappropriate Matching", - LDAPResultConstraintViolation: "Constraint Violation", - LDAPResultAttributeOrValueExists: "Attribute Or Value Exists", - LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax", - LDAPResultNoSuchObject: "No Such Object", - LDAPResultAliasProblem: "Alias Problem", - LDAPResultInvalidDNSyntax: "Invalid DN Syntax", - LDAPResultIsLeaf: "Is Leaf", - LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem", - LDAPResultInappropriateAuthentication: "Inappropriate Authentication", - LDAPResultInvalidCredentials: "Invalid Credentials", - LDAPResultInsufficientAccessRights: "Insufficient Access Rights", - LDAPResultBusy: "Busy", - LDAPResultUnavailable: "Unavailable", - LDAPResultUnwillingToPerform: "Unwilling To Perform", - LDAPResultLoopDetect: "Loop Detect", - LDAPResultSortControlMissing: "Sort Control Missing", - LDAPResultOffsetRangeError: "Result Offset Range Error", - LDAPResultNamingViolation: "Naming Violation", - LDAPResultObjectClassViolation: "Object Class Violation", - LDAPResultResultsTooLarge: "Results Too Large", - LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf", - LDAPResultNotAllowedOnRDN: "Not Allowed On RDN", - LDAPResultEntryAlreadyExists: "Entry Already Exists", - LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited", - LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs", - LDAPResultVirtualListViewErrorOrControlError: "Failed because of a problem related to the virtual list view", - LDAPResultOther: "Other", - LDAPResultServerDown: "Cannot establish a connection", - LDAPResultLocalError: "An error occurred", - LDAPResultEncodingError: "LDAP encountered an error while encoding", - LDAPResultDecodingError: "LDAP encountered an error while decoding", - LDAPResultTimeout: "LDAP timeout while waiting for a response from the server", - LDAPResultAuthUnknown: "The auth method requested in a bind request is unknown", - LDAPResultFilterError: "An error occurred while encoding the given search filter", - LDAPResultUserCanceled: "The user canceled the operation", - LDAPResultParamError: "An invalid parameter was specified", - LDAPResultNoMemory: "Out of memory error", - LDAPResultConnectError: "A connection to the server could not be established", - LDAPResultNotSupported: "An attempt has been made to use a feature not supported LDAP", - LDAPResultControlNotFound: "The controls required to perform the requested operation were not found", - LDAPResultNoResultsReturned: "No results were returned from the server", - LDAPResultMoreResultsToReturn: "There are more results in the chain of results", - LDAPResultClientLoop: "A loop has been detected. For example when following referrals", - LDAPResultReferralLimitExceeded: "The referral hop limit has been exceeded", - LDAPResultCanceled: "Operation was canceled", - LDAPResultNoSuchOperation: "Server has no knowledge of the operation requested for cancellation", - LDAPResultTooLate: "Too late to cancel the outstanding operation", - LDAPResultCannotCancel: "The identified operation does not support cancellation or the cancel operation cannot be performed", - LDAPResultAssertionFailed: "An assertion control given in the LDAP operation evaluated to false causing the operation to not be performed", - LDAPResultSyncRefreshRequired: "Refresh Required", - LDAPResultInvalidResponse: "Invalid Response", - LDAPResultAmbiguousResponse: "Ambiguous Response", - LDAPResultTLSNotSupported: "Tls Not Supported", - LDAPResultIntermediateResponse: "Intermediate Response", - LDAPResultUnknownType: "Unknown Type", - LDAPResultAuthorizationDenied: "Authorization Denied", - - ErrorNetwork: "Network Error", - ErrorFilterCompile: "Filter Compile Error", - ErrorFilterDecompile: "Filter Decompile Error", - ErrorDebugging: "Debugging Error", - ErrorUnexpectedMessage: "Unexpected Message", - ErrorUnexpectedResponse: "Unexpected Response", - ErrorEmptyPassword: "Empty password not allowed by the client", -} - -// Error holds LDAP error information -type Error struct { - // Err is the underlying error - Err error - // ResultCode is the LDAP error code - ResultCode uint16 - // MatchedDN is the matchedDN returned if any - MatchedDN string -} - -func (e *Error) Error() string { - return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error()) -} - -// GetLDAPError creates an Error out of a BER packet representing a LDAPResult -// The return is an error object. It can be casted to a Error structure. -// This function returns nil if resultCode in the LDAPResult sequence is success(0). -func GetLDAPError(packet *ber.Packet) error { - if packet == nil { - return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")} - } - - if len(packet.Children) >= 2 { - response := packet.Children[1] - if response == nil { - return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in 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: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")} -} - -// NewError creates an LDAP error with the given code and underlying error -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 { - if err == nil { - return false - } - - serverError, ok := err.(*Error) - if !ok { - return false - } - - return serverError.ResultCode == desiredResultCode -} diff --git a/vendor/github.com/go-ldap/ldap/v3/filter.go b/vendor/github.com/go-ldap/ldap/v3/filter.go deleted file mode 100644 index 73505e79..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/filter.go +++ /dev/null @@ -1,487 +0,0 @@ -package ldap - -import ( - "bytes" - hexpac "encoding/hex" - "errors" - "fmt" - "io" - "strings" - "unicode" - "unicode/utf8" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// Filter choices -const ( - FilterAnd = 0 - FilterOr = 1 - FilterNot = 2 - FilterEqualityMatch = 3 - FilterSubstrings = 4 - FilterGreaterOrEqual = 5 - FilterLessOrEqual = 6 - FilterPresent = 7 - FilterApproxMatch = 8 - FilterExtensibleMatch = 9 -) - -// FilterMap contains human readable descriptions of Filter choices -var FilterMap = map[uint64]string{ - FilterAnd: "And", - FilterOr: "Or", - FilterNot: "Not", - FilterEqualityMatch: "Equality Match", - FilterSubstrings: "Substrings", - FilterGreaterOrEqual: "Greater Or Equal", - FilterLessOrEqual: "Less Or Equal", - FilterPresent: "Present", - FilterApproxMatch: "Approx Match", - FilterExtensibleMatch: "Extensible Match", -} - -// SubstringFilter options -const ( - FilterSubstringsInitial = 0 - FilterSubstringsAny = 1 - FilterSubstringsFinal = 2 -) - -// FilterSubstringsMap contains human readable descriptions of SubstringFilter choices -var FilterSubstringsMap = map[uint64]string{ - FilterSubstringsInitial: "Substrings Initial", - FilterSubstringsAny: "Substrings Any", - FilterSubstringsFinal: "Substrings Final", -} - -// MatchingRuleAssertion choices -const ( - MatchingRuleAssertionMatchingRule = 1 - MatchingRuleAssertionType = 2 - MatchingRuleAssertionMatchValue = 3 - MatchingRuleAssertionDNAttributes = 4 -) - -// MatchingRuleAssertionMap contains human readable descriptions of MatchingRuleAssertion choices -var MatchingRuleAssertionMap = map[uint64]string{ - MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule", - MatchingRuleAssertionType: "Matching Rule Assertion Type", - MatchingRuleAssertionMatchValue: "Matching Rule Assertion Match Value", - 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] != '(' { - return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('")) - } - packet, pos, err := compileFilter(filter, 1) - if err != nil { - return nil, err - } - switch { - case pos > len(filter): - return nil, NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter")) - case pos < len(filter): - return nil, NewError(ErrorFilterCompile, errors.New("ldap: finished compiling filter with extra at end: "+fmt.Sprint(filter[pos:]))) - } - return packet, nil -} - -// DecompileFilter converts a packet representation of a filter into a string representation -func DecompileFilter(packet *ber.Packet) (_ string, err error) { - defer func() { - if r := recover(); r != nil { - err = NewError(ErrorFilterDecompile, errors.New("ldap: error decompiling filter")) - } - }() - - buf := bytes.NewBuffer(nil) - buf.WriteByte('(') - childStr := "" - - switch packet.Tag { - case FilterAnd: - buf.WriteByte('&') - for _, child := range packet.Children { - childStr, err = DecompileFilter(child) - if err != nil { - return - } - buf.WriteString(childStr) - } - case FilterOr: - buf.WriteByte('|') - for _, child := range packet.Children { - childStr, err = DecompileFilter(child) - if err != nil { - return - } - buf.WriteString(childStr) - } - case FilterNot: - buf.WriteByte('!') - childStr, err = DecompileFilter(packet.Children[0]) - if err != nil { - return - } - buf.WriteString(childStr) - - case FilterSubstrings: - 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 { - buf.Write(_SymbolAny) - } - buf.WriteString(EscapeFilter(ber.DecodeString(child.Data.Bytes()))) - if child.Tag != FilterSubstringsFinal { - buf.Write(_SymbolAny) - } - } - case FilterEqualityMatch: - buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes())) - buf.WriteByte('=') - buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))) - case FilterGreaterOrEqual: - buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes())) - buf.WriteString(">=") - buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))) - case FilterLessOrEqual: - buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes())) - buf.WriteString("<=") - buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))) - case FilterPresent: - buf.WriteString(ber.DecodeString(packet.Data.Bytes())) - buf.WriteString("=*") - case FilterApproxMatch: - 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 - matchingRule := "" - value := "" - - for _, child := range packet.Children { - switch child.Tag { - case MatchingRuleAssertionMatchingRule: - matchingRule = ber.DecodeString(child.Data.Bytes()) - case MatchingRuleAssertionType: - attr = ber.DecodeString(child.Data.Bytes()) - case MatchingRuleAssertionMatchValue: - value = ber.DecodeString(child.Data.Bytes()) - case MatchingRuleAssertionDNAttributes: - dnAttributes = child.Value.(bool) - } - } - - if len(attr) > 0 { - buf.WriteString(attr) - } - if dnAttributes { - buf.WriteString(":dn") - } - if len(matchingRule) > 0 { - buf.WriteString(":") - buf.WriteString(matchingRule) - } - buf.WriteString(":=") - buf.WriteString(EscapeFilter(value)) - } - - buf.WriteByte(')') - - return buf.String(), nil -} - -func compileFilterSet(filter string, pos int, parent *ber.Packet) (int, error) { - for pos < len(filter) && filter[pos] == '(' { - child, newPos, err := compileFilter(filter, pos+1) - if err != nil { - return pos, err - } - pos = newPos - parent.AppendChild(child) - } - if pos == len(filter) { - return pos, NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter")) - } - - return pos + 1, nil -} - -func compileFilter(filter string, pos int) (*ber.Packet, int, error) { - var ( - packet *ber.Packet - err error - ) - - defer func() { - if r := recover(); r != nil { - err = NewError(ErrorFilterCompile, errors.New("ldap: error compiling filter")) - } - }() - newPos := pos - - currentRune, currentWidth := utf8.DecodeRuneInString(filter[newPos:]) - - switch currentRune { - case utf8.RuneError: - return nil, 0, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos)) - case '(': - packet, newPos, err = compileFilter(filter, pos+currentWidth) - newPos++ - return packet, newPos, err - case '&': - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterAnd, nil, FilterMap[FilterAnd]) - newPos, err = compileFilterSet(filter, pos+currentWidth, packet) - return packet, newPos, err - case '|': - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterOr, nil, FilterMap[FilterOr]) - newPos, err = compileFilterSet(filter, pos+currentWidth, packet) - return packet, newPos, err - case '!': - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterNot, nil, FilterMap[FilterNot]) - var child *ber.Packet - child, newPos, err = compileFilter(filter, pos+currentWidth) - packet.AppendChild(child) - return packet, newPos, err - default: - const ( - stateReadingAttr = 0 - stateReadingExtensibleMatchingRule = 1 - stateReadingCondition = 2 - ) - - state := stateReadingAttr - attribute := bytes.NewBuffer(nil) - extensibleDNAttributes := false - extensibleMatchingRule := bytes.NewBuffer(nil) - condition := bytes.NewBuffer(nil) - - for newPos < len(filter) { - remainingFilter := filter[newPos:] - currentRune, currentWidth = utf8.DecodeRuneInString(remainingFilter) - if currentRune == ')' { - break - } - if currentRune == utf8.RuneError { - return packet, newPos, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos)) - } - - switch state { - case stateReadingAttr: - switch { - // Extensible rule, with only DN-matching - case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch]) - extensibleDNAttributes = true - state = stateReadingCondition - newPos += 5 - - // Extensible rule, with DN-matching and a matching OID - case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch]) - extensibleDNAttributes = true - state = stateReadingExtensibleMatchingRule - newPos += 4 - - // Extensible rule, with attr only - case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch]) - state = stateReadingCondition - newPos += 2 - - // Extensible rule, with no DN attribute matching - case currentRune == ':': - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch]) - state = stateReadingExtensibleMatchingRule - newPos++ - - // Equality condition - case currentRune == '=': - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch]) - state = stateReadingCondition - newPos++ - - // Greater-than or equal - case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual]) - state = stateReadingCondition - newPos += 2 - - // Less-than or equal - case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual]) - state = stateReadingCondition - newPos += 2 - - // Approx - case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="): - packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch]) - state = stateReadingCondition - newPos += 2 - - // Still reading the attribute name - default: - attribute.WriteRune(currentRune) - newPos += currentWidth - } - - case stateReadingExtensibleMatchingRule: - switch { - - // Matching rule OID is done - case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="): - state = stateReadingCondition - newPos += 2 - - // Still reading the matching rule oid - default: - extensibleMatchingRule.WriteRune(currentRune) - newPos += currentWidth - } - - case stateReadingCondition: - // append to the condition - condition.WriteRune(currentRune) - newPos += currentWidth - } - } - - if newPos == len(filter) { - err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter")) - return packet, newPos, err - } - if packet == nil { - err = NewError(ErrorFilterCompile, errors.New("ldap: error parsing filter")) - return packet, newPos, err - } - - switch { - case packet.Tag == FilterExtensibleMatch: - // MatchingRuleAssertion ::= SEQUENCE { - // matchingRule [1] MatchingRuleID OPTIONAL, - // type [2] AttributeDescription OPTIONAL, - // matchValue [3] AssertionValue, - // dnAttributes [4] BOOLEAN DEFAULT FALSE - // } - - // Include the matching rule oid, if specified - if extensibleMatchingRule.Len() > 0 { - packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule.String(), MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule])) - } - - // Include the attribute, if specified - 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 := decodeEscapedSymbols(condition.Bytes()) - if encodeErr != nil { - return packet, newPos, encodeErr - } - packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue])) - - // Defaults to false, so only include in the sequence if true - if extensibleDNAttributes { - packet.AppendChild(ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionDNAttributes, extensibleDNAttributes, MatchingRuleAssertionMap[MatchingRuleAssertionDNAttributes])) - } - - 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 := bytes.Split(condition.Bytes(), _SymbolAny) - for i, part := range parts { - if len(part) == 0 { - continue - } - var tag ber.Tag - switch i { - case 0: - tag = FilterSubstringsInitial - case len(parts) - 1: - tag = FilterSubstringsFinal - default: - tag = FilterSubstringsAny - } - encodedString, encodeErr := decodeEscapedSymbols(part) - if encodeErr != nil { - return packet, newPos, encodeErr - } - seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)])) - } - packet.AppendChild(seq) - default: - encodedString, encodeErr := decodeEscapedSymbols(condition.Bytes()) - if encodeErr != nil { - return packet, newPos, encodeErr - } - 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")) - } - - newPos += currentWidth - return packet, newPos, err - } -} - -// Convert from "ABC\xx\xx\xx" form to literal bytes for transport -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)) - } - - 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 byteHex == nil { - byteHex = make([]byte, 2) - byteVal = make([]byte, 1) - } - - 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)) - } - - 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(runeVal) - } - - offset += runeSize - } -} diff --git a/vendor/github.com/go-ldap/ldap/v3/go.mod b/vendor/github.com/go-ldap/ldap/v3/go.mod deleted file mode 100644 index 9816ce0e..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/go-ldap/ldap/v3 - -go 1.13 - -require github.com/go-asn1-ber/asn1-ber v1.3.1 diff --git a/vendor/github.com/go-ldap/ldap/v3/go.sum b/vendor/github.com/go-ldap/ldap/v3/go.sum deleted file mode 100644 index c8b9085b..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= diff --git a/vendor/github.com/go-ldap/ldap/v3/ldap.go b/vendor/github.com/go-ldap/ldap/v3/ldap.go deleted file mode 100644 index 7dbc951a..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/ldap.go +++ /dev/null @@ -1,345 +0,0 @@ -package ldap - -import ( - "fmt" - "io/ioutil" - "os" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// LDAP Application Codes -const ( - ApplicationBindRequest = 0 - ApplicationBindResponse = 1 - ApplicationUnbindRequest = 2 - ApplicationSearchRequest = 3 - ApplicationSearchResultEntry = 4 - ApplicationSearchResultDone = 5 - ApplicationModifyRequest = 6 - ApplicationModifyResponse = 7 - ApplicationAddRequest = 8 - ApplicationAddResponse = 9 - ApplicationDelRequest = 10 - ApplicationDelResponse = 11 - ApplicationModifyDNRequest = 12 - ApplicationModifyDNResponse = 13 - ApplicationCompareRequest = 14 - ApplicationCompareResponse = 15 - ApplicationAbandonRequest = 16 - ApplicationSearchResultReference = 19 - ApplicationExtendedRequest = 23 - ApplicationExtendedResponse = 24 -) - -// ApplicationMap contains human readable descriptions of LDAP Application Codes -var ApplicationMap = map[uint8]string{ - ApplicationBindRequest: "Bind Request", - ApplicationBindResponse: "Bind Response", - ApplicationUnbindRequest: "Unbind Request", - ApplicationSearchRequest: "Search Request", - ApplicationSearchResultEntry: "Search Result Entry", - ApplicationSearchResultDone: "Search Result Done", - ApplicationModifyRequest: "Modify Request", - ApplicationModifyResponse: "Modify Response", - ApplicationAddRequest: "Add Request", - ApplicationAddResponse: "Add Response", - ApplicationDelRequest: "Del Request", - ApplicationDelResponse: "Del Response", - ApplicationModifyDNRequest: "Modify DN Request", - ApplicationModifyDNResponse: "Modify DN Response", - ApplicationCompareRequest: "Compare Request", - ApplicationCompareResponse: "Compare Response", - ApplicationAbandonRequest: "Abandon Request", - ApplicationSearchResultReference: "Search Result Reference", - ApplicationExtendedRequest: "Extended Request", - ApplicationExtendedResponse: "Extended Response", -} - -// Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10) -const ( - BeheraPasswordExpired = 0 - BeheraAccountLocked = 1 - BeheraChangeAfterReset = 2 - BeheraPasswordModNotAllowed = 3 - BeheraMustSupplyOldPassword = 4 - BeheraInsufficientPasswordQuality = 5 - BeheraPasswordTooShort = 6 - BeheraPasswordTooYoung = 7 - BeheraPasswordInHistory = 8 -) - -// BeheraPasswordPolicyErrorMap contains human readable descriptions of Behera Password Policy error codes -var BeheraPasswordPolicyErrorMap = map[int8]string{ - BeheraPasswordExpired: "Password expired", - BeheraAccountLocked: "Account locked", - BeheraChangeAfterReset: "Password must be changed", - BeheraPasswordModNotAllowed: "Policy prevents password modification", - BeheraMustSupplyOldPassword: "Policy requires old password in order to change password", - BeheraInsufficientPasswordQuality: "Password fails quality checks", - BeheraPasswordTooShort: "Password is too short for policy", - BeheraPasswordTooYoung: "Password has been changed too recently", - BeheraPasswordInHistory: "New password is in list of old passwords", -} - -// Adds descriptions to an LDAP Response packet for debugging -func addLDAPDescriptions(packet *ber.Packet) (err error) { - defer func() { - if r := recover(); r != nil { - err = NewError(ErrorDebugging, fmt.Errorf("ldap: cannot process packet to add descriptions: %s", r)) - } - }() - packet.Description = "LDAP Response" - packet.Children[0].Description = "Message ID" - - application := uint8(packet.Children[1].Tag) - packet.Children[1].Description = ApplicationMap[application] - - switch application { - case ApplicationBindRequest: - err = addRequestDescriptions(packet) - case ApplicationBindResponse: - err = addDefaultLDAPResponseDescriptions(packet) - case ApplicationUnbindRequest: - err = addRequestDescriptions(packet) - case ApplicationSearchRequest: - err = addRequestDescriptions(packet) - case ApplicationSearchResultEntry: - packet.Children[1].Children[0].Description = "Object Name" - packet.Children[1].Children[1].Description = "Attributes" - for _, child := range packet.Children[1].Children[1].Children { - child.Description = "Attribute" - child.Children[0].Description = "Attribute Name" - child.Children[1].Description = "Attribute Values" - for _, grandchild := range child.Children[1].Children { - grandchild.Description = "Attribute Value" - } - } - if len(packet.Children) == 3 { - err = addControlDescriptions(packet.Children[2]) - } - case ApplicationSearchResultDone: - err = addDefaultLDAPResponseDescriptions(packet) - case ApplicationModifyRequest: - err = addRequestDescriptions(packet) - case ApplicationModifyResponse: - case ApplicationAddRequest: - err = addRequestDescriptions(packet) - case ApplicationAddResponse: - case ApplicationDelRequest: - err = addRequestDescriptions(packet) - case ApplicationDelResponse: - case ApplicationModifyDNRequest: - err = addRequestDescriptions(packet) - case ApplicationModifyDNResponse: - case ApplicationCompareRequest: - err = addRequestDescriptions(packet) - case ApplicationCompareResponse: - case ApplicationAbandonRequest: - err = addRequestDescriptions(packet) - case ApplicationSearchResultReference: - case ApplicationExtendedRequest: - err = addRequestDescriptions(packet) - case ApplicationExtendedResponse: - } - - return err -} - -func addControlDescriptions(packet *ber.Packet) error { - packet.Description = "Controls" - for _, child := range packet.Children { - var value *ber.Packet - controlType := "" - child.Description = "Control" - switch len(child.Children) { - case 0: - // at least one child is required for control type - return fmt.Errorf("at least one child is required for control type") - - case 1: - // just type, no criticality or value - controlType = child.Children[0].Value.(string) - child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")" - - case 2: - controlType = child.Children[0].Value.(string) - child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")" - // Children[1] could be criticality or value (both are optional) - // duck-type on whether this is a boolean - if _, ok := child.Children[1].Value.(bool); ok { - child.Children[1].Description = "Criticality" - } else { - child.Children[1].Description = "Control Value" - value = child.Children[1] - } - - case 3: - // criticality and value present - controlType = child.Children[0].Value.(string) - child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")" - child.Children[1].Description = "Criticality" - child.Children[2].Description = "Control Value" - value = child.Children[2] - - default: - // more than 3 children is invalid - return fmt.Errorf("more than 3 children for control packet found") - } - - if value == nil { - continue - } - switch controlType { - case ControlTypePaging: - value.Description += " (Paging)" - if value.Value != nil { - valueChildren, err := ber.DecodePacketErr(value.Data.Bytes()) - if err != nil { - return fmt.Errorf("failed to decode data bytes: %s", err) - } - value.Data.Truncate(0) - value.Value = nil - valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes() - value.AppendChild(valueChildren) - } - value.Children[0].Description = "Real Search Control Value" - value.Children[0].Children[0].Description = "Paging Size" - value.Children[0].Children[1].Description = "Cookie" - - case ControlTypeBeheraPasswordPolicy: - value.Description += " (Password Policy - Behera Draft)" - if value.Value != nil { - valueChildren, err := ber.DecodePacketErr(value.Data.Bytes()) - if err != nil { - return fmt.Errorf("failed to decode data bytes: %s", err) - } - value.Data.Truncate(0) - value.Value = nil - value.AppendChild(valueChildren) - } - sequence := value.Children[0] - for _, child := range sequence.Children { - if child.Tag == 0 { - //Warning - warningPacket := child.Children[0] - packet, err := ber.DecodePacketErr(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 - } - } - } 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 - } - child.Description = "Error" - child.Value = val - } - } - } - } - return nil -} - -func addRequestDescriptions(packet *ber.Packet) error { - packet.Description = "LDAP Request" - packet.Children[0].Description = "Message ID" - packet.Children[1].Description = ApplicationMap[uint8(packet.Children[1].Tag)] - if len(packet.Children) == 3 { - return addControlDescriptions(packet.Children[2]) - } - return nil -} - -func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error { - 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" - } - if len(packet.Children) == 3 { - return addControlDescriptions(packet.Children[2]) - } - return nil -} - -// DebugBinaryFile reads and prints packets from the given filename -func DebugBinaryFile(fileName string) error { - file, err := ioutil.ReadFile(fileName) - if err != nil { - return NewError(ErrorDebugging, err) - } - ber.PrintBytes(os.Stdout, file, "") - packet, err := ber.DecodePacketErr(file) - if err != nil { - return fmt.Errorf("failed to decode packet: %s", err) - } - if err := addLDAPDescriptions(packet); err != nil { - return err - } - ber.PrintPacket(packet) - - return nil -} - -var hex = "0123456789abcdef" - -func mustEscape(c byte) bool { - return c > 0x7f || c == '(' || c == ')' || c == '\\' || c == '*' || c == 0 -} - -// EscapeFilter escapes from the provided LDAP filter string the special -// characters in the set `()*\` and those out of the range 0 < c < 0x80, -// as defined in RFC4515. -func EscapeFilter(filter string) string { - escape := 0 - for i := 0; i < len(filter); i++ { - if mustEscape(filter[i]) { - escape++ - } - } - if escape == 0 { - return filter - } - buf := make([]byte, len(filter)+escape*2) - for i, j := 0, 0; i < len(filter); i++ { - c := filter[i] - if mustEscape(c) { - buf[j+0] = '\\' - buf[j+1] = hex[c>>4] - buf[j+2] = hex[c&0xf] - j += 3 - } else { - buf[j] = c - j++ - } - } - return string(buf) -} diff --git a/vendor/github.com/go-ldap/ldap/v3/moddn.go b/vendor/github.com/go-ldap/ldap/v3/moddn.go deleted file mode 100644 index 380b8cf6..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/moddn.go +++ /dev/null @@ -1,75 +0,0 @@ -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")) - 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 -} diff --git a/vendor/github.com/go-ldap/ldap/v3/modify.go b/vendor/github.com/go-ldap/ldap/v3/modify.go deleted file mode 100644 index ee712890..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/modify.go +++ /dev/null @@ -1,132 +0,0 @@ -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 -} diff --git a/vendor/github.com/go-ldap/ldap/v3/passwdmodify.go b/vendor/github.com/go-ldap/ldap/v3/passwdmodify.go deleted file mode 100644 index 62a11084..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/passwdmodify.go +++ /dev/null @@ -1,126 +0,0 @@ -package ldap - -import ( - "fmt" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -const ( - passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1" -) - -// PasswordModifyRequest implements the Password Modify Extended Operation as defined in https://www.ietf.org/rfc/rfc3062.txt -type PasswordModifyRequest struct { - // UserIdentity is an optional string representation of the user associated with the request. - // This string may or may not be an LDAPDN [RFC2253]. - // If no UserIdentity field is present, the request acts up upon the password of the user currently associated with the LDAP session - UserIdentity string - // OldPassword, if present, contains the user's current password - OldPassword string - // NewPassword, if present, contains the desired password for this user - NewPassword string -} - -// PasswordModifyResult holds the server response to a PasswordModifyRequest -type PasswordModifyResult struct { - // GeneratedPassword holds a password generated by the server, if present - GeneratedPassword string - // Referral are the returned referral - Referral string -} - -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 req.UserIdentity != "" { - passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.UserIdentity, "User Identity")) - } - if req.OldPassword != "" { - passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, req.OldPassword, "Old Password")) - } - if req.NewPassword != "" { - passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, req.NewPassword, "New Password")) - } - extendedRequestValue.AppendChild(passwordModifyRequestValue) - - pkt.AppendChild(extendedRequestValue) - - envelope.AppendChild(pkt) - - return nil -} - -// NewPasswordModifyRequest creates a new PasswordModifyRequest -// -// 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 -// with the session. -// -// oldPassword is the current user's password, it can be empty or it can be -// needed depending on the session user access rights (usually an administrator -// can change a user's password without knowing the current one) and the -// password policy (see pwdSafeModify password policy's attribute) -// -// newPassword is the desired user's password. If empty the server can return -// an error or generate a new password that will be available in the -// PasswordModifyResult.GeneratedPassword -// -func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest { - return &PasswordModifyRequest{ - UserIdentity: userIdentity, - OldPassword: oldPassword, - NewPassword: newPassword, - } -} - -// PasswordModify performs the modification request -func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) { - msgCtx, err := l.doRequest(passwordModifyRequest) - if err != nil { - return nil, err - } - defer l.finishMessage(msgCtx) - - packet, err := l.readPacket(msgCtx) - if err != nil { - return nil, err - } - - result := &PasswordModifyResult{} - - if packet.Children[1].Tag == ApplicationExtendedResponse { - err := GetLDAPError(packet) - if err != nil { - if IsErrorWithCode(err, LDAPResultReferral) { - for _, child := range packet.Children[1].Children { - if child.Tag == 3 { - result.Referral = child.Children[0].Value.(string) - } - } - } - return result, err - } - } else { - return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)) - } - - extendedResponse := packet.Children[1] - for _, child := range extendedResponse.Children { - if child.Tag == 11 { - passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes()) - if len(passwordModifyResponseValue.Children) == 1 { - if passwordModifyResponseValue.Children[0].Tag == 0 { - result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes()) - } - } - } - } - - return result, nil -} diff --git a/vendor/github.com/go-ldap/ldap/v3/request.go b/vendor/github.com/go-ldap/ldap/v3/request.go deleted file mode 100644 index 8c68f34a..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/request.go +++ /dev/null @@ -1,66 +0,0 @@ -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 -} diff --git a/vendor/github.com/go-ldap/ldap/v3/search.go b/vendor/github.com/go-ldap/ldap/v3/search.go deleted file mode 100644 index 9a5c2c86..00000000 --- a/vendor/github.com/go-ldap/ldap/v3/search.go +++ /dev/null @@ -1,370 +0,0 @@ -package ldap - -import ( - "errors" - "fmt" - "sort" - "strings" - - ber "github.com/go-asn1-ber/asn1-ber" -) - -// scope choices -const ( - ScopeBaseObject = 0 - ScopeSingleLevel = 1 - ScopeWholeSubtree = 2 -) - -// ScopeMap contains human readable descriptions of scope choices -var ScopeMap = map[int]string{ - ScopeBaseObject: "Base Object", - ScopeSingleLevel: "Single Level", - ScopeWholeSubtree: "Whole Subtree", -} - -// derefAliases -const ( - NeverDerefAliases = 0 - DerefInSearching = 1 - DerefFindingBaseObj = 2 - DerefAlways = 3 -) - -// DerefMap contains human readable descriptions of derefAliases choices -var DerefMap = map[int]string{ - NeverDerefAliases: "NeverDerefAliases", - DerefInSearching: "DerefInSearching", - DerefFindingBaseObj: "DerefFindingBaseObj", - DerefAlways: "DerefAlways", -} - -// NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs. -// The map of attributes is accessed in alphabetical order of the keys in order to ensure that, for the -// same input map of attributes, the output entry will contain the same order of attributes -func NewEntry(dn string, attributes map[string][]string) *Entry { - var attributeNames []string - for attributeName := range attributes { - attributeNames = append(attributeNames, attributeName) - } - sort.Strings(attributeNames) - - var encodedAttributes []*EntryAttribute - for _, attributeName := range attributeNames { - encodedAttributes = append(encodedAttributes, NewEntryAttribute(attributeName, attributes[attributeName])) - } - return &Entry{ - DN: dn, - Attributes: encodedAttributes, - } -} - -// Entry represents a single search result entry -type Entry struct { - // DN is the distinguished name of the entry - DN string - // Attributes are the returned attributes for the entry - Attributes []*EntryAttribute -} - -// GetAttributeValues returns the values for the named attribute, or an empty list -func (e *Entry) GetAttributeValues(attribute string) []string { - for _, attr := range e.Attributes { - if attr.Name == attribute { - 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 { - if 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) - 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) - 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) - for _, attr := range e.Attributes { - attr.Print() - } -} - -// PrettyPrint outputs a human-readable description indenting -func (e *Entry) PrettyPrint(indent int) { - fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN) - for _, attr := range e.Attributes { - attr.PrettyPrint(indent + 2) - } -} - -// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair -func NewEntryAttribute(name string, values []string) *EntryAttribute { - var bytes [][]byte - for _, value := range values { - bytes = append(bytes, []byte(value)) - } - return &EntryAttribute{ - Name: name, - Values: values, - ByteValues: bytes, - } -} - -// EntryAttribute holds a single attribute -type EntryAttribute struct { - // Name is the name of the attribute - Name string - // Values contain the string values of the attribute - Values []string - // ByteValues contain the raw values of the attribute - ByteValues [][]byte -} - -// Print outputs a human-readable description -func (e *EntryAttribute) Print() { - fmt.Printf("%s: %s\n", e.Name, e.Values) -} - -// PrettyPrint outputs a human-readable description with indenting -func (e *EntryAttribute) PrettyPrint(indent int) { - fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values) -} - -// SearchResult holds the server's response to a search request -type SearchResult struct { - // Entries are the returned entries - Entries []*Entry - // Referrals are the returned referrals - Referrals []string - // Controls are the returned controls - Controls []Control -} - -// Print outputs a human-readable description -func (s *SearchResult) Print() { - for _, entry := range s.Entries { - entry.Print() - } -} - -// PrettyPrint outputs a human-readable description with indenting -func (s *SearchResult) PrettyPrint(indent int) { - for _, entry := range s.Entries { - entry.PrettyPrint(indent) - } -} - -// SearchRequest represents a search request to send to the server -type SearchRequest struct { - BaseDN string - Scope int - DerefAliases int - SizeLimit int - TimeLimit int - TypesOnly bool - Filter string - Attributes []string - Controls []Control -} - -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(req.Filter) - if err != nil { - return err - } - pkt.AppendChild(filterPacket) - // encode attributes - attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes") - for _, attribute := range req.Attributes { - attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute")) - } - pkt.AppendChild(attributesPacket) - - envelope.AppendChild(pkt) - if len(req.Controls) > 0 { - envelope.AppendChild(encodeControls(req.Controls)) - } - - return nil -} - -// NewSearchRequest creates a new search request -func NewSearchRequest( - BaseDN string, - Scope, DerefAliases, SizeLimit, TimeLimit int, - TypesOnly bool, - Filter string, - Attributes []string, - Controls []Control, -) *SearchRequest { - return &SearchRequest{ - BaseDN: BaseDN, - Scope: Scope, - DerefAliases: DerefAliases, - SizeLimit: SizeLimit, - TimeLimit: TimeLimit, - TypesOnly: TypesOnly, - Filter: Filter, - Attributes: Attributes, - Controls: Controls, - } -} - -// SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the -// search request. All paged LDAP query responses will be buffered and the final result will be returned atomically. -// The following four cases are possible given the arguments: -// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size -// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries -// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request -// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries -// A requested pagingSize of 0 is interpreted as no limit by LDAP servers. -func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) { - var pagingControl *ControlPaging - - control := FindControl(searchRequest.Controls, ControlTypePaging) - if control == nil { - pagingControl = NewControlPaging(pagingSize) - searchRequest.Controls = append(searchRequest.Controls, pagingControl) - } else { - castControl, ok := control.(*ControlPaging) - if !ok { - return nil, fmt.Errorf("expected paging control to be of type *ControlPaging, got %v", control) - } - if castControl.PagingSize != pagingSize { - return nil, fmt.Errorf("paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize) - } - pagingControl = castControl - } - - searchResult := new(SearchResult) - for { - result, err := l.Search(searchRequest) - l.Debug.Printf("Looking for Paging Control...") - if err != nil { - return searchResult, err - } - if result == nil { - return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received")) - } - - for _, entry := range result.Entries { - searchResult.Entries = append(searchResult.Entries, entry) - } - for _, referral := range result.Referrals { - searchResult.Referrals = append(searchResult.Referrals, referral) - } - for _, control := range result.Controls { - searchResult.Controls = append(searchResult.Controls, control) - } - - l.Debug.Printf("Looking for Paging Control...") - pagingResult := FindControl(result.Controls, ControlTypePaging) - if pagingResult == nil { - pagingControl = nil - l.Debug.Printf("Could not find paging control. Breaking...") - break - } - - cookie := pagingResult.(*ControlPaging).Cookie - if len(cookie) == 0 { - pagingControl = nil - l.Debug.Printf("Could not find cookie. Breaking...") - break - } - pagingControl.SetCookie(cookie) - } - - if pagingControl != nil { - l.Debug.Printf("Abandoning Paging...") - pagingControl.PagingSize = 0 - l.Search(searchRequest) - } - - return searchResult, nil -} - -// Search performs the given search request -func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) { - msgCtx, err := l.doRequest(searchRequest) - if err != nil { - return nil, err - } - defer l.finishMessage(msgCtx) - - result := &SearchResult{ - Entries: make([]*Entry, 0), - Referrals: make([]string, 0), - Controls: make([]Control, 0)} - - for { - packet, err := l.readPacket(msgCtx) - if err != nil { - return nil, err - } - - switch packet.Children[1].Tag { - case 4: - entry := new(Entry) - entry.DN = packet.Children[1].Children[0].Value.(string) - for _, child := range packet.Children[1].Children[1].Children { - attr := new(EntryAttribute) - attr.Name = child.Children[0].Value.(string) - for _, value := range child.Children[1].Children { - attr.Values = append(attr.Values, value.Value.(string)) - attr.ByteValues = append(attr.ByteValues, value.ByteValue) - } - entry.Attributes = append(entry.Attributes, attr) - } - result.Entries = append(result.Entries, entry) - case 5: - err := GetLDAPError(packet) - if err != nil { - return nil, 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) - } - result.Controls = append(result.Controls, decodedChild) - } - } - return result, nil - case 19: - result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string)) - } - } -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2ad3556c..212b3600 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,11 +7,6 @@ github.com/dgrijalva/jwt-go # github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 ## explicit github.com/docopt/docopt-go -# github.com/go-asn1-ber/asn1-ber v1.3.1 -github.com/go-asn1-ber/asn1-ber -# github.com/go-ldap/ldap/v3 v3.1.10 -## explicit -github.com/go-ldap/ldap/v3 # github.com/go-sql-driver/mysql v1.5.0 ## explicit github.com/go-sql-driver/mysql