From ae4c32bc3b654794c623f671a198516dc67e123b Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Fri, 18 Nov 2016 15:16:09 -0800 Subject: [PATCH] connector/ldap: use gopkg.in/ldap.v2's escape filter Use the escape filter method provided by the upstream LDAP package instead of rolling our own. --- connector/ldap/ldap.go | 45 ++----------------------------------- connector/ldap/ldap_test.go | 23 ------------------- 2 files changed, 2 insertions(+), 66 deletions(-) delete mode 100644 connector/ldap/ldap_test.go diff --git a/connector/ldap/ldap.go b/connector/ldap/ldap.go index 22b033ae..05588626 100644 --- a/connector/ldap/ldap.go +++ b/connector/ldap/ldap.go @@ -2,17 +2,13 @@ package ldap import ( - "bytes" "crypto/tls" "crypto/x509" - "encoding/hex" "encoding/json" "fmt" "io/ioutil" "log" "net" - "strings" - "unicode" "gopkg.in/ldap.v2" @@ -134,43 +130,6 @@ func parseScope(s string) (int, bool) { return 0, false } -// escapeRune maps a rune to a hex encoded value. For example 'é' would become '\\c3\\a9' -func escapeRune(buff *bytes.Buffer, r rune) { - // Really inefficient, but it seems correct. - for _, b := range []byte(string(r)) { - buff.WriteString("\\") - buff.WriteString(hex.EncodeToString([]byte{b})) - } -} - -// NOTE(ericchiang): There are no good documents on how to escape an LDAP string. -// This implementation is inspired by an Oracle document, and is purposefully -// extremely restrictive. -// -// See: https://docs.oracle.com/cd/E19424-01/820-4811/gdxpo/index.html -func escapeFilter(s string) string { - r := strings.NewReader(s) - buff := new(bytes.Buffer) - for { - ru, _, err := r.ReadRune() - if err != nil { - // ignore decoding issues - return buff.String() - } - - switch { - case ru > unicode.MaxASCII: // Not ASCII - escapeRune(buff, ru) - case !unicode.IsPrint(ru): // Not printable - escapeRune(buff, ru) - case strings.ContainsRune(`*\()`, ru): // Reserved characters - escapeRune(buff, ru) - default: - buff.WriteRune(ru) - } - } -} - // Open returns an authentication strategy using LDAP. func (c *Config) Open() (connector.Connector, error) { conn, err := c.OpenConnector() @@ -302,7 +261,7 @@ func (c *ldapConnector) Login(username, password string) (ident connector.Identi user ldap.Entry ) - filter := fmt.Sprintf("(%s=%s)", c.UserSearch.Username, escapeFilter(username)) + filter := fmt.Sprintf("(%s=%s)", c.UserSearch.Username, ldap.EscapeFilter(username)) if c.UserSearch.Filter != "" { filter = fmt.Sprintf("(&%s%s)", c.UserSearch.Filter, filter) } @@ -402,7 +361,7 @@ func (c *ldapConnector) Groups(ident connector.Identity) ([]string, error) { return nil, fmt.Errorf("ldap: failed to unmarshal connector data: %v", err) } - filter := fmt.Sprintf("(%s=%s)", c.GroupSearch.GroupAttr, escapeFilter(getAttr(user, c.GroupSearch.UserAttr))) + filter := fmt.Sprintf("(%s=%s)", c.GroupSearch.GroupAttr, ldap.EscapeFilter(getAttr(user, c.GroupSearch.UserAttr))) if c.GroupSearch.Filter != "" { filter = fmt.Sprintf("(&%s%s)", c.GroupSearch.Filter, filter) } diff --git a/connector/ldap/ldap_test.go b/connector/ldap/ldap_test.go deleted file mode 100644 index 2a93e316..00000000 --- a/connector/ldap/ldap_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package ldap - -import "testing" - -func TestEscapeFilter(t *testing.T) { - tests := []struct { - val string - want string - }{ - {"Five*Star", "Five\\2aStar"}, - {"c:\\File", "c:\\5cFile"}, - {"John (2nd)", "John \\282nd\\29"}, - {string([]byte{0, 0, 0, 4}), "\\00\\00\\00\\04"}, - {"Chloé", "Chlo\\c3\\a9"}, - } - - for _, tc := range tests { - got := escapeFilter(tc.val) - if tc.want != got { - t.Errorf("value %q want=%q, got=%q", tc.val, tc.want, got) - } - } -}