From 2e4aa679e36e6eceba55c7db03146a075569613b Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 14 Jul 2022 21:19:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9UpdatePassowrd=E5=92=8CAuthen?= =?UTF-8?q?ticate=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 认证和更新密码失败,返回更多错误信息, 如账号锁定, 过期, 禁用导致 方便用户识别 --- .gitignore | 1 + README-ORIGIN.md | 89 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 95 +++++------------------------------------------- conn.go | 20 +++++++++- example_test.go | 2 +- go.mod | 5 +-- go.sum | 6 +-- passwd.go | 15 +++++++- 8 files changed, 136 insertions(+), 97 deletions(-) create mode 100644 README-ORIGIN.md diff --git a/.gitignore b/.gitignore index a0bbe17..a349415 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp .env tags +.history/ diff --git a/README-ORIGIN.md b/README-ORIGIN.md new file mode 100644 index 0000000..d090398 --- /dev/null +++ b/README-ORIGIN.md @@ -0,0 +1,89 @@ +[![pkg.go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3) + +# About + +`go-ad-auth` is a simple wrapper around the great [ldap](https://github.com/go-ldap/ldap) library to help with Active Directory authentication. + +# Installing + +Using Go Modules: + +`go get github.com/korylprince/go-ad-auth/v3` + +Using gopkg.in: + +`go get gopkg.in/korylprince/go-ad-auth.v3` + +**Dependencies:** + +* [github.com/go-ldap/ldap](https://github.com/go-ldap/ldap) +* [golang.org/x/text/encoding/unicode](https://pkg.go.dev/golang.org/x/text/encoding/unicode) + +If you have any issues or questions [create an issue](https://github.com/korylprince/go-ad-auth/issues). + +# API Versions + +You should update to the `v3` API when possible. The new API is cleaner, more idiomatic, exposes a lot more functionality, and is fully testable. + +`v3` was created to support Go Modules, so it is backwards compatible with `v2`. However, updates made to `v3` are not backported to `v2`. + +The `v3` API is almost a complete rewrite of the older [`gopkg.in/korylprince/go-ad-auth.v1`](https://pkg.go.dev/gopkg.in/korylprince/go-ad-auth.v1) API. There are similarities, but `v3` is not backwards-compatible. + + +One notable difference to be careful of is that while `v1`'s `Login` will return `false` if the user is not in the specified group, `v3`'s `AuthenticateExtended` will return `true` if the user authenticated successfully, regardless if they were in any of the specified groups or not. + +# Usage + +Example: + +```go +config := &auth.Config{ + Server: "ldap.example.com", + Port: 389, + BaseDN: "OU=Users,DC=example,DC=com", + Security: auth.SecurityStartTLS, +} + +username := "user" +password := "pass" + +status, err := auth.Authenticate(config, username, password) + +if err != nil { + //handle err + return +} + +if !status { + //handle failed authentication + return +} +``` + +See more advanced examples on [go.dev](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#pkg-examples). + +# Testing + +`go test -v` + +Most tests will be skipped unless you supply the following environment variables to connect to an Active Directory server: + +| Name | Description | +| ----------------------- | ------------- | +| ADTEST_SERVER | Hostname or IP Address of an Active Directory server | +| ADTEST_PORT | Port to use - defaults to 389 | +| ADTEST_BIND_UPN | userPrincipalName (user@domain.tld) of admin user | +| ADTEST_BIND_PASS | Password of admin user | +| ADTEST_BIND_SECURITY | `NONE` \|\| `TLS` \|\| `STARTTLS` \|\| `INSECURETLS` \|\| `INSECURESTARTTLS` - defaults to `STARTTLS` | +| ADTEST_BASEDN | LDAP Base DN - for testing the root DN is recommended, e.g. `DC=example,DC=com` | +| ADTEST_PASSWORD_UPN | userPrincipalName of a test user that will be used to test password changing functions | + +# Nested Groups + +Since `v3.1.0`, [`AuthenticateExtended`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#AuthenticateExtended) and [`Conn.ObjectGroups`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#Conn.ObjectGroups) will automatically search for nested groups. For example, if `User A` is a member of `Group A`, and `Group A` is a member of `Group B`, using `Conn.ObjectGroups` on `User A` will return both `Group A` and `Group B`. + +# Security + +[SQL Injection](https://en.wikipedia.org/wiki/SQL_injection) is a well known attack vector, and most SQL libraries provide mitigations such as [prepared statements](https://en.wikipedia.org/wiki/Prepared_statement). Similarly, [LDAP Injection](https://www.owasp.org/index.php/Testing_for_LDAP_Injection_\(OTG-INPVAL-006\)), while not seen often in the wild, is something we should be concerned with. + +Since `v2.2.0`, this library sanitizes inputs (with [`ldap.EscapeFilter`](https://pkg.go.dev/github.com/go-ldap/ldap/v3?tab=doc#EscapeFilter)) that are used to create LDAP filters in library functions, namely [`GetDN`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.GetDN) and [`GetAttributes`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.GetAttributes). This means high level functions in this library are protected against malicious inputs. If you use [`Search`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.Search) or [`SearchOne`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.SearchOne), take care to sanitize any untrusted inputs you use in your LDAP filter. diff --git a/README.md b/README.md index d090398..4b7a547 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,12 @@ -[![pkg.go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3) +> 项目fork自`https://github.com/korylprince/go-ad-auth.git` +> +> 增强两个函数功能, 返回, 如账号锁定, 过期, 禁用导致等导致认证或修改密码失败的原因 -# About +- UpdatePassowrd +- Authenticate -`go-ad-auth` is a simple wrapper around the great [ldap](https://github.com/go-ldap/ldap) library to help with Active Directory authentication. +> usage: -# Installing - -Using Go Modules: - -`go get github.com/korylprince/go-ad-auth/v3` - -Using gopkg.in: - -`go get gopkg.in/korylprince/go-ad-auth.v3` - -**Dependencies:** - -* [github.com/go-ldap/ldap](https://github.com/go-ldap/ldap) -* [golang.org/x/text/encoding/unicode](https://pkg.go.dev/golang.org/x/text/encoding/unicode) - -If you have any issues or questions [create an issue](https://github.com/korylprince/go-ad-auth/issues). - -# API Versions - -You should update to the `v3` API when possible. The new API is cleaner, more idiomatic, exposes a lot more functionality, and is fully testable. - -`v3` was created to support Go Modules, so it is backwards compatible with `v2`. However, updates made to `v3` are not backported to `v2`. - -The `v3` API is almost a complete rewrite of the older [`gopkg.in/korylprince/go-ad-auth.v1`](https://pkg.go.dev/gopkg.in/korylprince/go-ad-auth.v1) API. There are similarities, but `v3` is not backwards-compatible. - - -One notable difference to be careful of is that while `v1`'s `Login` will return `false` if the user is not in the specified group, `v3`'s `AuthenticateExtended` will return `true` if the user authenticated successfully, regardless if they were in any of the specified groups or not. - -# Usage - -Example: - -```go -config := &auth.Config{ - Server: "ldap.example.com", - Port: 389, - BaseDN: "OU=Users,DC=example,DC=com", - Security: auth.SecurityStartTLS, -} - -username := "user" -password := "pass" - -status, err := auth.Authenticate(config, username, password) - -if err != nil { - //handle err - return -} - -if !status { - //handle failed authentication - return -} -``` - -See more advanced examples on [go.dev](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#pkg-examples). - -# Testing - -`go test -v` - -Most tests will be skipped unless you supply the following environment variables to connect to an Active Directory server: - -| Name | Description | -| ----------------------- | ------------- | -| ADTEST_SERVER | Hostname or IP Address of an Active Directory server | -| ADTEST_PORT | Port to use - defaults to 389 | -| ADTEST_BIND_UPN | userPrincipalName (user@domain.tld) of admin user | -| ADTEST_BIND_PASS | Password of admin user | -| ADTEST_BIND_SECURITY | `NONE` \|\| `TLS` \|\| `STARTTLS` \|\| `INSECURETLS` \|\| `INSECURESTARTTLS` - defaults to `STARTTLS` | -| ADTEST_BASEDN | LDAP Base DN - for testing the root DN is recommended, e.g. `DC=example,DC=com` | -| ADTEST_PASSWORD_UPN | userPrincipalName of a test user that will be used to test password changing functions | - -# Nested Groups - -Since `v3.1.0`, [`AuthenticateExtended`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#AuthenticateExtended) and [`Conn.ObjectGroups`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3?tab=doc#Conn.ObjectGroups) will automatically search for nested groups. For example, if `User A` is a member of `Group A`, and `Group A` is a member of `Group B`, using `Conn.ObjectGroups` on `User A` will return both `Group A` and `Group B`. - -# Security - -[SQL Injection](https://en.wikipedia.org/wiki/SQL_injection) is a well known attack vector, and most SQL libraries provide mitigations such as [prepared statements](https://en.wikipedia.org/wiki/Prepared_statement). Similarly, [LDAP Injection](https://www.owasp.org/index.php/Testing_for_LDAP_Injection_\(OTG-INPVAL-006\)), while not seen often in the wild, is something we should be concerned with. - -Since `v2.2.0`, this library sanitizes inputs (with [`ldap.EscapeFilter`](https://pkg.go.dev/github.com/go-ldap/ldap/v3?tab=doc#EscapeFilter)) that are used to create LDAP filters in library functions, namely [`GetDN`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.GetDN) and [`GetAttributes`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.GetAttributes). This means high level functions in this library are protected against malicious inputs. If you use [`Search`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.Search) or [`SearchOne`](https://pkg.go.dev/github.com/korylprince/go-ad-auth/v3#Conn.SearchOne), take care to sanitize any untrusted inputs you use in your LDAP filter. +```bash +go get github.com/LeoBest2/go-ad-auth/v3 +``` \ No newline at end of file diff --git a/conn.go b/conn.go index 5a43530..e2dbde2 100644 --- a/conn.go +++ b/conn.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "errors" "fmt" + "strings" ldap "github.com/go-ldap/ldap/v3" ) @@ -71,7 +72,24 @@ func (c *Conn) Bind(upn, password string) (bool, error) { if err != nil { if e, ok := err.(*ldap.Error); ok { if e.ResultCode == ldap.LDAPResultInvalidCredentials { - return false, nil + var msg string + s := err.Error() + if strings.Contains(s, "52e") { + msg = "账号或密码不正确" + } else if strings.Contains(s, "773") { + msg = "该账号必须修改密码后才能使用" + } else if strings.Contains(s, "775") { + msg = "该账号已锁定, 请联系管理员解锁!" + } else if strings.Contains(s, "532") { + msg = "密码已过有效期,请联系管理员重置!" + } else if strings.Contains(s, "533") { + msg = "该账号已禁用,请联系管理员!" + } else if strings.Contains(s, "701") { + msg = "该账号已过期,请联系管理员!" + } else { + msg = s + } + return false, errors.New(msg) } } return false, fmt.Errorf("Bind error (%s): %w", upn, err) diff --git a/example_test.go b/example_test.go index 8bce08f..4a6b8fb 100644 --- a/example_test.go +++ b/example_test.go @@ -3,7 +3,7 @@ package auth_test import ( "fmt" - auth "github.com/korylprince/go-ad-auth/v3" + auth "github.com/LeoBest2/go-ad-auth/v3" ) func ExampleAuthenticate() { diff --git a/go.mod b/go.mod index de974d9..6c61b6a 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,8 @@ -module github.com/korylprince/go-ad-auth/v3 +module github.com/LeoBest2/go-ad-auth/v3 go 1.13 require ( - github.com/go-asn1-ber/asn1-ber v1.4.1 // indirect github.com/go-ldap/ldap/v3 v3.1.7 - golang.org/x/text v0.3.2 + golang.org/x/text v0.3.7 ) diff --git a/go.sum b/go.sum index 3ed7a07..74bc03e 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,7 @@ 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-asn1-ber/asn1-ber v1.4.1 h1:qP/QDxOtmMoJVgXHCXNzDpA0+wkgYB2x5QoLMVOciyw= -github.com/go-asn1-ber/asn1-ber v1.4.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-ldap/ldap/v3 v3.1.7 h1:aHjuWTgZsnxjMgqzx0JHwNqz4jBYZTcNarbPFkW1Oww= github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/passwd.go b/passwd.go index 9052930..ed28601 100644 --- a/passwd.go +++ b/passwd.go @@ -1,8 +1,8 @@ package auth import ( - "errors" "fmt" + "strings" ldap "github.com/go-ldap/ldap/v3" "golang.org/x/text/encoding/unicode" @@ -59,7 +59,18 @@ func UpdatePassword(config *Config, username, oldPasswd, newPasswd string) error return err } if !status { - return errors.New("Password error: credentials not valid") + var msg string + s := err.Error() + if strings.Contains(s, "0000052D") { + msg = "新密码不符合策略要求!" + } else if strings.Contains(s, "00000056") { + msg = "用户名或密码不正确!" + } else if strings.Contains(s, "00000005") { + msg = "该账号不允许修改密码!" + } else { + msg = s + } + return fmt.Errorf(msg) } dn, err := conn.GetDN("userPrincipalName", upn)