diff --git a/build b/build index 3fd11f8..515acc9 100755 --- a/build +++ b/build @@ -3,7 +3,7 @@ set -e base='docker.io/tpimenta/nginx-ldap-auth' -version='v1.0.2' +version='v1.0.3' image="$base:$version" atexit() { diff --git a/ldap/connect.go b/ldap/connect.go index f9bfa62..8e457de 100644 --- a/ldap/connect.go +++ b/ldap/connect.go @@ -19,7 +19,7 @@ func (p *Pool) Connect() error { } if p.conn != nil { - return nil + p.conn.Close() } address := fmt.Sprintf("%s:%d", p.url, p.port) @@ -37,6 +37,11 @@ func (p *Pool) Connect() error { err = conn.StartTLS(&tls.Config{InsecureSkipVerify: true}) if err != nil { log.Printf("It was not possble to start TLS, falling back to plain: %v.\n", err) + conn.Close() + conn, err = ldap.Dial("tcp", address) + if err != nil { + return err + } } p.conn = conn } diff --git a/ldap/jail.go b/ldap/jail.go new file mode 100644 index 0000000..e18d2d9 --- /dev/null +++ b/ldap/jail.go @@ -0,0 +1,20 @@ +package ldap + +import ( + "log" + + ldap "gopkg.in/ldap.v2" +) + +func (p *Pool) networkJail(f func() error) error { + err := f() + if err != nil && ldap.IsErrorWithCode(err, ldap.ErrorNetwork) { + log.Printf("Network problem, trying to reconnect once: %v.\n", err) + err = p.Connect() + if err != nil { + return err + } + err = f() + } + return err +} diff --git a/ldap/login.go b/ldap/login.go index 61d25be..f89e2cc 100644 --- a/ldap/login.go +++ b/ldap/login.go @@ -10,7 +10,9 @@ func (p *Pool) Validate(username, password string) (bool, error) { } p.admin = false - err = p.conn.Bind(username, password) + err = p.networkJail(func() error { + return p.conn.Bind(username, password) + }) if err != nil { return true, err } @@ -28,7 +30,9 @@ func (p *Pool) auth() error { return nil } - err := p.conn.Bind(p.username, p.password) + err := p.networkJail(func() error { + return p.conn.Bind(p.username, p.password) + }) if err == nil { p.admin = true } diff --git a/ldap/search.go b/ldap/search.go index 6d998db..d468923 100644 --- a/ldap/search.go +++ b/ldap/search.go @@ -21,22 +21,27 @@ func (p *Pool) Search(base, filter string, attr string) (bool, string, []string, list = []string{attr} } - res, err := p.conn.Search(ldap.NewSearchRequest( - base, - ldap.ScopeWholeSubtree, - ldap.NeverDerefAliases, - 0, - 0, - false, - filter, - list, - nil, - )) + var res *ldap.SearchResult + err = p.networkJail(func() error { + res, err = p.conn.Search(ldap.NewSearchRequest( + base, + ldap.ScopeWholeSubtree, + ldap.NeverDerefAliases, + 0, + 0, + false, + filter, + list, + nil, + )) + return err + }) + if err != nil { return false, "", nil, err } - if len(res.Entries) == 0 { + if res == nil || len(res.Entries) == 0 { return true, "", nil, fmt.Errorf("No results for %s filter %s", base, filter) } diff --git a/rule/service.go b/rule/service.go index 15f2500..26e6f7d 100644 --- a/rule/service.go +++ b/rule/service.go @@ -33,7 +33,7 @@ func (p *Service) Validate(username, password string) bool { ok, err := p.validate(username, password) if err != nil { - log.Printf("Could not validade user %s: %v\n", username, err) + log.Printf("Could not validate user %s: %v\n", username, err) return false } diff --git a/test-server b/test-server new file mode 100755 index 0000000..c6b0ca4 --- /dev/null +++ b/test-server @@ -0,0 +1,44 @@ +#!/bin/sh + +set -e + +for name in ldap-test-server ldap-test-client; do + if docker ps -a --format '{{.Names}}' | egrep -q "^${name}\$"; then + docker rm -f "$name" || : + fi +done + +docker run \ + -p 389:389 \ + -p 636:636 \ + --name ldap-test-server \ + -d \ + osixia/openldap:1.2.2 + +# docker exec ldap-test-server ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin + +cat > /tmp/config.yaml <