From 262a09bb2d7989a8f120d5c3eefce78edce2cfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 14 Jul 2015 17:35:11 +0200 Subject: [PATCH] feat(ldap): added support for binding initially with an admin user searching for user and then binding again to authenticate current user, #1450 --- pkg/auth/ldap.go | 30 ++++++++++++++++++++++++++++-- pkg/auth/ldap_user.go | 1 + 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/pkg/auth/ldap.go b/pkg/auth/ldap.go index a6bf9109fec..62802012954 100644 --- a/pkg/auth/ldap.go +++ b/pkg/auth/ldap.go @@ -3,6 +3,7 @@ package auth import ( "errors" "fmt" + "strings" "github.com/go-ldap/ldap" "github.com/grafana/grafana/pkg/bus" @@ -18,7 +19,8 @@ func init() { UseSSL: false, Host: "127.0.0.1", Port: "389", - BindDN: "cn=%s,dc=grafana,dc=org", + BindDN: "cn=admin,dc=grafana,dc=org", + BindPassword: "grafana", AttrName: "givenName", AttrSurname: "sn", AttrUsername: "cn", @@ -74,6 +76,13 @@ func (a *ldapAuther) login(query *AuthenticateUserQuery) error { log.Info("email: %s", ldapUser.Email) log.Info("memberOf: %s", ldapUser.MemberOf) + // check if a second user bind is needed + if a.server.BindPassword != "" { + if err := a.secondBind(ldapUser, query.Password); err != nil { + return err + } + } + if grafanaUser, err := a.getGrafanaUserFor(ldapUser); err != nil { return err } else { @@ -190,12 +199,28 @@ func (a *ldapAuther) syncOrgRoles(user *m.User, ldapUser *ldapUserInfo) error { return nil } +func (a *ldapAuther) secondBind(ldapUser *ldapUserInfo, userPassword string) error { + if err := a.conn.Bind(ldapUser.DN, userPassword); err != nil { + if ldapErr, ok := err.(*ldap.Error); ok { + if ldapErr.ResultCode == 49 { + return ErrInvalidCredentials + } + } + return err + } + + return nil +} + func (a *ldapAuther) initialBind(username, userPassword string) error { if a.server.BindPassword != "" { userPassword = a.server.BindPassword } - bindPath := fmt.Sprintf(a.server.BindDN, username) + bindPath := a.server.BindDN + if strings.Contains(bindPath, "%s") { + bindPath = fmt.Sprintf(a.server.BindDN, username) + } if err := a.conn.Bind(bindPath, userPassword); err != nil { if ldapErr, ok := err.(*ldap.Error); ok { @@ -247,6 +272,7 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) { } return &ldapUserInfo{ + DN: searchResult.Entries[0].DN, LastName: getLdapAttr(a.server.AttrSurname, searchResult), FirstName: getLdapAttr(a.server.AttrName, searchResult), Username: getLdapAttr(a.server.AttrUsername, searchResult), diff --git a/pkg/auth/ldap_user.go b/pkg/auth/ldap_user.go index d8a885b9ac5..80ad67f063d 100644 --- a/pkg/auth/ldap_user.go +++ b/pkg/auth/ldap_user.go @@ -1,6 +1,7 @@ package auth type ldapUserInfo struct { + DN string FirstName string LastName string Username string