Skip to content

Commit

Permalink
修改UpdatePassowrd和Authenticate函数
Browse files Browse the repository at this point in the history
    认证和更新密码失败,返回更多错误信息, 如账号锁定, 过期, 禁用导致
    方便用户识别
  • Loading branch information
LeoBest2 committed Jul 19, 2022
1 parent f496b7a commit 2e4aa67
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 97 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.swp
.env
tags
.history/
89 changes: 89 additions & 0 deletions README-ORIGIN.md
Original file line number Diff line number Diff line change
@@ -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.
95 changes: 9 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
```
20 changes: 19 additions & 1 deletion conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"errors"
"fmt"
"strings"

ldap "github.com/go-ldap/ldap/v3"
)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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
)
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
15 changes: 13 additions & 2 deletions passwd.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package auth

import (
"errors"
"fmt"
"strings"

ldap "github.com/go-ldap/ldap/v3"
"golang.org/x/text/encoding/unicode"
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 2e4aa67

Please sign in to comment.