本文整理匯總了Golang中github.com/go-ldap/ldap.EscapeFilter函數的典型用法代碼示例。如果您正苦於以下問題:Golang EscapeFilter函數的具體用法?Golang EscapeFilter怎麽用?Golang EscapeFilter使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了EscapeFilter函數的13個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: getUserDN
/*
* Returns the DN of the object representing the authenticated user.
*/
func (b *backend) getUserDN(cfg *ConfigEntry, c *ldap.Conn, bindDN string) (string, error) {
userDN := ""
if cfg.UPNDomain != "" {
// Find the distinguished name for the user if userPrincipalName used for login
filter := fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(bindDN))
if b.Logger().IsDebug() {
b.Logger().Debug("auth/ldap: Searching UPN", "userdn", cfg.UserDN, "filter", filter)
}
result, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: filter,
})
if err != nil {
return userDN, fmt.Errorf("LDAP search failed for detecting user: %v", err)
}
for _, e := range result.Entries {
userDN = e.DN
}
} else {
userDN = bindDN
}
return userDN, nil
}
示例2: getBindDN
func getBindDN(cfg *ConfigEntry, c *ldap.Conn, username string) (string, error) {
bindDN := ""
if cfg.DiscoverDN || (cfg.BindDN != "" && cfg.BindPassword != "") {
if err := c.Bind(cfg.BindDN, cfg.BindPassword); err != nil {
return bindDN, fmt.Errorf("LDAP bind (service) failed: %v", err)
}
result, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(%s=%s)", cfg.UserAttr, ldap.EscapeFilter(username)),
})
if err != nil {
return bindDN, fmt.Errorf("LDAP search for binddn failed: %v", err)
}
if len(result.Entries) != 1 {
return bindDN, fmt.Errorf("LDAP search for binddn 0 or not unique")
}
bindDN = result.Entries[0].DN
} else {
if cfg.UPNDomain != "" {
bindDN = fmt.Sprintf("%[email protected]%s", EscapeLDAPValue(username), cfg.UPNDomain)
} else {
bindDN = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, EscapeLDAPValue(username), cfg.UserDN)
}
}
return bindDN, nil
}
示例3: getUserSearchFilter
func (ad *ActiveDirectoryClient) getUserSearchFilter(samAccountName string) string {
userFilter := fmt.Sprintf("(&(%s=%s)%s)",
AD_USER_ATTRIBUTE, ldap.EscapeFilter(samAccountName), AD_USER_FILTER)
log.V(11).Infof("Filter: %s\n", userFilter)
return userFilter
}
示例4: buildAttributeQuery
// buildAttributeQuery builds the query containing a filter that conjoins the common filter given
// in the configuration with the specific attribute filter for which the attribute value is given
func (o *LDAPQueryOnAttribute) buildAttributeQuery(attributeValue string,
attributes []string) *ldap.SearchRequest {
specificFilter := fmt.Sprintf("%s=%s",
ldap.EscapeFilter(o.QueryAttribute),
ldap.EscapeFilter(attributeValue))
filter := fmt.Sprintf("(&(%s)(%s))", o.Filter, specificFilter)
return ldap.NewSearchRequest(
o.BaseDN,
int(o.Scope),
int(o.DerefAliases),
0, // allowed return size - indicates no limit
o.TimeLimit,
false, // not types only
filter,
attributes,
nil, // no controls
)
}
示例5: getUserDN
func getUserDN(cfg *ConfigEntry, c *ldap.Conn, bindDN string) (string, error) {
userDN := ""
if cfg.UPNDomain != "" {
// Find the distinguished name for the user if userPrincipalName used for login
result, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(bindDN)),
})
if err != nil {
return userDN, fmt.Errorf("LDAP search failed for detecting user: %v", err)
}
for _, e := range result.Entries {
userDN = e.DN
}
} else {
userDN = bindDN
}
return userDN, nil
}
示例6: getIdentity
// getIdentity looks up a username in an LDAP server, and attempts to bind to the user's DN using the provided password
func (a *Authenticator) getIdentity(username, password string) (authapi.UserIdentityInfo, bool, error) {
defer func() {
if e := recover(); e != nil {
util.HandleError(fmt.Errorf("Recovered panic: %v, %s", e, debug.Stack()))
}
}()
if len(username) == 0 || len(password) == 0 {
return nil, false, nil
}
// Make the connection
l, err := a.connect()
if err != nil {
return nil, false, err
}
defer l.Close()
// If specified, bind the username/password for search phase
if len(a.options.BindDN) > 0 {
if err := l.Bind(a.options.BindDN, a.options.BindPassword); err != nil {
return nil, false, err
}
}
// & together the filter specified in the LDAP options with the user-specific filter
filter := fmt.Sprintf("(&%s(%s=%s))",
a.options.URL.Filter,
ldap.EscapeFilter(a.options.URL.QueryAttribute),
ldap.EscapeFilter(username),
)
// Build list of attributes to retrieve
attrs := util.NewStringSet(a.options.URL.QueryAttribute)
attrs.Insert(a.options.AttributeEmail...)
attrs.Insert(a.options.AttributeName...)
attrs.Insert(a.options.AttributePreferredUsername...)
attrs.Insert(a.options.AttributeID...)
// Search for LDAP record
searchRequest := ldap.NewSearchRequest(
a.options.URL.BaseDN, // base dn
int(a.options.URL.Scope), // scope
ldap.NeverDerefAliases, // deref
2, // size limit, we want to know if this is not unique, but don't want the entire tree
0, // no client-specified time limit, determined by LDAP server. TODO: make configurable?
false, // not types only
filter, // filter
attrs.List(), // attributes to retrieve
nil, // controls
)
glog.V(4).Infof("searching for %s", filter)
results, err := l.Search(searchRequest)
if err != nil {
return nil, false, err
}
if len(results.Entries) == 0 {
// 0 results means a missing username, not an error
glog.V(4).Infof("no entries matching %s", filter)
return nil, false, nil
}
if len(results.Entries) > 1 {
// More than 1 result means a misconfigured server filter or query parameter
return nil, false, fmt.Errorf("multiple entries found matching %q", username)
}
entry := results.Entries[0]
glog.V(4).Infof("found dn=%q for %s", entry.DN, filter)
// Bind with given username and password to attempt to authenticate
if err := l.Bind(entry.DN, password); err != nil {
glog.V(4).Infof("error binding password for %q: %v", entry.DN, err)
if err, ok := err.(*ldap.Error); ok {
switch err.ResultCode {
case ldap.LDAPResultInappropriateAuthentication:
// inappropriateAuthentication (48)
// Indicates the server requires the client that had attempted
// to bind anonymously or without supplying credentials to
// provide some form of credentials.
fallthrough
case ldap.LDAPResultInvalidCredentials:
// invalidCredentials (49)
// Indicates that the provided credentials (e.g., the user's name
// and password) are invalid.
// Authentication failed, return false, but no error
return nil, false, nil
}
}
return nil, false, err
}
// Build the identity
uid := getAttributeValue(entry, a.options.AttributeID)
if uid == "" {
return nil, false, fmt.Errorf("Could not retrieve a non-empty value from %v attributes for dn=%q", a.options.AttributeID, entry.DN)
}
//.........這裏部分代碼省略.........
示例7: searchForUser
func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) {
var searchResult *ldap.SearchResult
var err error
for _, searchBase := range a.server.SearchBaseDNs {
searchReq := ldap.SearchRequest{
BaseDN: searchBase,
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{
a.server.Attr.Username,
a.server.Attr.Surname,
a.server.Attr.Email,
a.server.Attr.Name,
a.server.Attr.MemberOf,
},
Filter: strings.Replace(a.server.SearchFilter, "%s", ldap.EscapeFilter(username), -1),
}
searchResult, err = a.conn.Search(&searchReq)
if err != nil {
return nil, err
}
if len(searchResult.Entries) > 0 {
break
}
}
if len(searchResult.Entries) == 0 {
return nil, ErrInvalidCredentials
}
if len(searchResult.Entries) > 1 {
return nil, errors.New("Ldap search matched more than one entry, please review your filter setting")
}
var memberOf []string
if a.server.GroupSearchFilter == "" {
memberOf = getLdapAttrArray(a.server.Attr.MemberOf, searchResult)
} else {
// If we are using a POSIX LDAP schema it won't support memberOf, so we manually search the groups
var groupSearchResult *ldap.SearchResult
for _, groupSearchBase := range a.server.GroupSearchBaseDNs {
var filter_replace string
filter_replace = getLdapAttr(a.server.GroupSearchFilterUserAttribute, searchResult)
if a.server.GroupSearchFilterUserAttribute == "" {
filter_replace = getLdapAttr(a.server.Attr.Username, searchResult)
}
filter := strings.Replace(a.server.GroupSearchFilter, "%s", ldap.EscapeFilter(filter_replace), -1)
if ldapCfg.VerboseLogging {
log.Info("LDAP: Searching for user's groups: %s", filter)
}
groupSearchReq := ldap.SearchRequest{
BaseDN: groupSearchBase,
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{
// Here MemberOf would be the thing that identifies the group, which is normally 'cn'
a.server.Attr.MemberOf,
},
Filter: filter,
}
groupSearchResult, err = a.conn.Search(&groupSearchReq)
if err != nil {
return nil, err
}
if len(groupSearchResult.Entries) > 0 {
for i := range groupSearchResult.Entries {
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
}
break
}
}
}
return &ldapUserInfo{
DN: searchResult.Entries[0].DN,
LastName: getLdapAttr(a.server.Attr.Surname, searchResult),
FirstName: getLdapAttr(a.server.Attr.Name, searchResult),
Username: getLdapAttr(a.server.Attr.Username, searchResult),
Email: getLdapAttr(a.server.Attr.Email, searchResult),
MemberOf: memberOf,
}, nil
}
示例8: getLdapGroups
func getLdapGroups(cfg *ConfigEntry, c *ldap.Conn, userDN string, username string) ([]string, error) {
// retrieve the groups in a string/bool map as a structure to avoid duplicates inside
ldapMap := make(map[string]bool)
// Fetch the optional memberOf property values on the user object
// This is the most common method used in Active Directory setup to retrieve the groups
result, err := c.Search(&ldap.SearchRequest{
BaseDN: userDN,
Scope: 0, // base scope to fetch only the userDN
Filter: "(cn=*)", // bogus filter, required to fetch the CN from userDN
Attributes: []string{
"memberOf",
},
})
// this check remains in case something happens with the ldap query or connection
if err != nil {
return nil, fmt.Errorf("LDAP fetch of distinguishedName=%s failed: %v", userDN, err)
}
// if there are more than one entry, we consider the results irrelevant and ignore them
if len(result.Entries) == 1 {
for _, attr := range result.Entries[0].Attributes {
// Find the groups the user is member of from the 'memberOf' attribute extracting the CN
if attr.Name == "memberOf" {
for _, value := range attr.Values {
memberOfDN, err := ldap.ParseDN(value)
if err != nil || len(memberOfDN.RDNs) == 0 {
continue
}
for _, rdn := range memberOfDN.RDNs {
for _, rdnTypeAndValue := range rdn.Attributes {
if strings.EqualFold(rdnTypeAndValue.Type, "CN") {
ldapMap[rdnTypeAndValue.Value] = true
}
}
}
}
}
}
}
// Find groups by searching in groupDN for any of the memberUid, member or uniqueMember attributes
// and retrieving the CN in the DN result
if cfg.GroupDN != "" {
result, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.GroupDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(|(memberUid=%s)(member=%s)(uniqueMember=%s))", ldap.EscapeFilter(username), ldap.EscapeFilter(userDN), ldap.EscapeFilter(userDN)),
})
if err != nil {
return nil, fmt.Errorf("LDAP search failed: %v", err)
}
for _, e := range result.Entries {
dn, err := ldap.ParseDN(e.DN)
if err != nil || len(dn.RDNs) == 0 {
continue
}
for _, rdn := range dn.RDNs {
for _, rdnTypeAndValue := range rdn.Attributes {
if strings.EqualFold(rdnTypeAndValue.Type, "CN") {
ldapMap[rdnTypeAndValue.Value] = true
}
}
}
}
}
ldapGroups := make([]string, len(ldapMap))
for key, _ := range ldapMap {
ldapGroups = append(ldapGroups, key)
}
return ldapGroups, nil
}
示例9: getIdentity
// getIdentity looks up a username in an LDAP server, and attempts to bind to the user's DN using the provided password
func (a *Authenticator) getIdentity(username, password string) (authapi.UserIdentityInfo, bool, error) {
defer func() {
if e := recover(); e != nil {
util.HandleError(fmt.Errorf("Recovered panic: %v, %s", e, debug.Stack()))
}
}()
if len(username) == 0 || len(password) == 0 {
return nil, false, nil
}
// Make the connection and bind to it if a bind DN and password were given
l, err := a.options.ClientConfig.Connect()
if err != nil {
return nil, false, err
}
defer l.Close()
if _, err := a.options.ClientConfig.Bind(l); err != nil {
return nil, false, err
}
// & together the filter specified in the LDAP options with the user-specific filter
filter := fmt.Sprintf("(&%s(%s=%s))",
a.options.URL.Filter,
ldap.EscapeFilter(a.options.URL.QueryAttribute),
ldap.EscapeFilter(username),
)
// Build list of attributes to retrieve
attrs := sets.NewString(a.options.URL.QueryAttribute)
attrs.Insert(a.options.UserAttributeDefiner.AllAttributes().List()...)
// Search for LDAP record
searchRequest := ldap.NewSearchRequest(
a.options.URL.BaseDN, // base dn
int(a.options.URL.Scope), // scope
ldap.NeverDerefAliases, // deref
2, // size limit, we want to know if this is not unique, but don't want the entire tree
0, // no client-specified time limit, determined by LDAP server. TODO: make configurable?
false, // not types only
filter, // filter
attrs.List(), // attributes to retrieve
nil, // controls
)
glog.V(4).Infof("searching for %s", filter)
results, err := l.Search(searchRequest)
if err != nil {
return nil, false, err
}
if len(results.Entries) == 0 {
// 0 results means a missing username, not an error
glog.V(4).Infof("no entries matching %s", filter)
return nil, false, nil
}
if len(results.Entries) > 1 {
// More than 1 result means a misconfigured server filter or query parameter
return nil, false, fmt.Errorf("multiple entries found matching %q", username)
}
entry := results.Entries[0]
glog.V(4).Infof("found dn=%q for %s", entry.DN, filter)
// Bind with given username and password to attempt to authenticate
if err := l.Bind(entry.DN, password); err != nil {
glog.V(4).Infof("error binding password for %q: %v", entry.DN, err)
if err, ok := err.(*ldap.Error); ok {
switch err.ResultCode {
case ldap.LDAPResultInappropriateAuthentication:
// inappropriateAuthentication (48)
// Indicates the server requires the client that had attempted
// to bind anonymously or without supplying credentials to
// provide some form of credentials.
fallthrough
case ldap.LDAPResultInvalidCredentials:
// invalidCredentials (49)
// Indicates that the provided credentials (e.g., the user's name
// and password) are invalid.
// Authentication failed, return false, but no error
return nil, false, nil
}
}
return nil, false, err
}
// Build the identity
identity, err := a.identityFactory.IdentityFor(entry)
if err != nil {
return nil, false, err
}
return identity, true, nil
}
示例10: getLdapGroups
/*
* getLdapGroups queries LDAP and returns a slice describing the set of groups the authenticated user is a member of.
*
* The search query is constructed according to cfg.GroupFilter, and run in context of cfg.GroupDN.
* Groups will be resolved from the query results by following the attribute defined in cfg.GroupAttr.
*
* cfg.GroupFilter is a go template and is compiled with the following context: [UserDN, Username]
* UserDN - The DN of the authenticated user
* Username - The Username of the authenticated user
*
* Example:
* cfg.GroupFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))"
* cfg.GroupDN = "OU=Groups,DC=myorg,DC=com"
* cfg.GroupAttr = "cn"
*
* NOTE - If cfg.GroupFilter is empty, no query is performed and an empty result slice is returned.
*
*/
func (b *backend) getLdapGroups(cfg *ConfigEntry, c *ldap.Conn, userDN string, username string) ([]string, error) {
// retrieve the groups in a string/bool map as a structure to avoid duplicates inside
ldapMap := make(map[string]bool)
if cfg.GroupFilter == "" {
b.Logger().Warn("auth/ldap: GroupFilter is empty, will not query server")
return make([]string, 0), nil
}
if cfg.GroupDN == "" {
b.Logger().Warn("auth/ldap: GroupDN is empty, will not query server")
return make([]string, 0), nil
}
// If groupfilter was defined, resolve it as a Go template and use the query for
// returning the user's groups
if b.Logger().IsDebug() {
b.Logger().Debug("auth/ldap: Compiling group filter", "group_filter", cfg.GroupFilter)
}
// Parse the configuration as a template.
// Example template "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))"
t, err := template.New("queryTemplate").Parse(cfg.GroupFilter)
if err != nil {
return nil, fmt.Errorf("LDAP search failed due to template compilation error: %v", err)
}
// Build context to pass to template - we will be exposing UserDn and Username.
context := struct {
UserDN string
Username string
}{
ldap.EscapeFilter(userDN),
ldap.EscapeFilter(username),
}
var renderedQuery bytes.Buffer
t.Execute(&renderedQuery, context)
if b.Logger().IsDebug() {
b.Logger().Debug("auth/ldap: Searching", "groupdn", cfg.GroupDN, "rendered_query", renderedQuery.String())
}
result, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.GroupDN,
Scope: 2, // subtree
Filter: renderedQuery.String(),
Attributes: []string{
cfg.GroupAttr,
},
})
if err != nil {
return nil, fmt.Errorf("LDAP search failed: %v", err)
}
for _, e := range result.Entries {
dn, err := ldap.ParseDN(e.DN)
if err != nil || len(dn.RDNs) == 0 {
continue
}
// Enumerate attributes of each result, parse out CN and add as group
values := e.GetAttributeValues(cfg.GroupAttr)
if len(values) > 0 {
for _, val := range values {
groupCN := b.getCN(val)
ldapMap[groupCN] = true
}
} else {
// If groupattr didn't resolve, use self (enumerating group objects)
groupCN := b.getCN(e.DN)
ldapMap[groupCN] = true
}
}
ldapGroups := make([]string, 0, len(ldapMap))
for key, _ := range ldapMap {
ldapGroups = append(ldapGroups, key)
}
return ldapGroups, nil
}
示例11: getUserSearchFilter
func (lc *LDAPClient) getUserSearchFilter(samAccountName string) string {
userFilter := fmt.Sprintf("(&(%s=%s)%s)",
AD_USER_ATTRIBUTE, ldap.EscapeFilter(samAccountName), AD_USER_FILTER)
return userFilter
}
示例12: Login
func (b *backend) Login(req *logical.Request, username string, password string) ([]string, *logical.Response, error) {
cfg, err := b.Config(req)
if err != nil {
return nil, nil, err
}
if cfg == nil {
return nil, logical.ErrorResponse("ldap backend not configured"), nil
}
c, err := cfg.DialLDAP()
if err != nil {
return nil, logical.ErrorResponse(err.Error()), nil
}
binddn := ""
if cfg.DiscoverDN || (cfg.BindDN != "" && cfg.BindPassword != "") {
if err = c.Bind(cfg.BindDN, cfg.BindPassword); err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP bind (service) failed: %v", err)), nil
}
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(%s=%s)", cfg.UserAttr, ldap.EscapeFilter(username)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search for binddn failed: %v", err)), nil
}
if len(sresult.Entries) != 1 {
return nil, logical.ErrorResponse("LDAP search for binddn 0 or not uniq"), nil
}
binddn = sresult.Entries[0].DN
} else {
if cfg.UPNDomain != "" {
binddn = fmt.Sprintf("%[email protected]%s", EscapeLDAPValue(username), cfg.UPNDomain)
} else {
binddn = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, EscapeLDAPValue(username), cfg.UserDN)
}
}
if err = c.Bind(binddn, password); err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP bind failed: %v", err)), nil
}
userdn := ""
if cfg.UPNDomain != "" {
// Find the distinguished name for the user if userPrincipalName used for login
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(binddn)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search failed: %v", err)), nil
}
for _, e := range sresult.Entries {
userdn = e.DN
}
} else {
userdn = binddn
}
// Enumerate all groups the user is member of. The search filter should
// work with both openldap and MS AD standard schemas.
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.GroupDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(|(memberUid=%s)(member=%s)(uniqueMember=%s))", ldap.EscapeFilter(username), ldap.EscapeFilter(userdn), ldap.EscapeFilter(userdn)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search failed: %v", err)), nil
}
var allgroups []string
var policies []string
user, err := b.User(req.Storage, username)
if err == nil && user != nil {
allgroups = append(allgroups, user.Groups...)
}
for _, e := range sresult.Entries {
dn, err := ldap.ParseDN(e.DN)
if err != nil || len(dn.RDNs) == 0 || len(dn.RDNs[0].Attributes) == 0 {
continue
}
gname := dn.RDNs[0].Attributes[0].Value
allgroups = append(allgroups, gname)
}
for _, gname := range allgroups {
group, err := b.Group(req.Storage, gname)
if err == nil && group != nil {
policies = append(policies, group.Policies...)
}
}
if len(policies) == 0 {
return nil, logical.ErrorResponse("user is not member of any authorized group"), nil
}
return policies, nil, nil
//.........這裏部分代碼省略.........
示例13: Login
func (b *backend) Login(req *logical.Request, username string, password string) ([]string, *logical.Response, error) {
cfg, err := b.Config(req)
if err != nil {
return nil, nil, err
}
if cfg == nil {
return nil, logical.ErrorResponse("ldap backend not configured"), nil
}
c, err := cfg.DialLDAP()
if err != nil {
return nil, logical.ErrorResponse(err.Error()), nil
}
if c == nil {
return nil, logical.ErrorResponse("invalid connection returned from LDAP dial"), nil
}
binddn := ""
if cfg.DiscoverDN || (cfg.BindDN != "" && cfg.BindPassword != "") {
if err = c.Bind(cfg.BindDN, cfg.BindPassword); err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP bind (service) failed: %v", err)), nil
}
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(%s=%s)", cfg.UserAttr, ldap.EscapeFilter(username)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search for binddn failed: %v", err)), nil
}
if len(sresult.Entries) != 1 {
return nil, logical.ErrorResponse("LDAP search for binddn 0 or not uniq"), nil
}
binddn = sresult.Entries[0].DN
} else {
if cfg.UPNDomain != "" {
binddn = fmt.Sprintf("%[email protected]%s", EscapeLDAPValue(username), cfg.UPNDomain)
} else {
binddn = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, EscapeLDAPValue(username), cfg.UserDN)
}
}
if err = c.Bind(binddn, password); err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP bind failed: %v", err)), nil
}
userdn := ""
if cfg.UPNDomain != "" {
// Find the distinguished name for the user if userPrincipalName used for login
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.UserDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(binddn)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search failed: %v", err)), nil
}
for _, e := range sresult.Entries {
userdn = e.DN
}
} else {
userdn = binddn
}
var allgroups []string
var policies []string
resp := &logical.Response{
Data: map[string]interface{}{},
}
// Fetch custom (local) groups the user has been added to
user, err := b.User(req.Storage, username)
if err == nil && user != nil {
allgroups = append(allgroups, user.Groups...)
}
if cfg.GroupDN != "" {
// Enumerate all groups the user is member of. The search filter should
// work with both openldap and MS AD standard schemas.
sresult, err := c.Search(&ldap.SearchRequest{
BaseDN: cfg.GroupDN,
Scope: 2, // subtree
Filter: fmt.Sprintf("(|(memberUid=%s)(member=%s)(uniqueMember=%s))", ldap.EscapeFilter(username), ldap.EscapeFilter(userdn), ldap.EscapeFilter(userdn)),
})
if err != nil {
return nil, logical.ErrorResponse(fmt.Sprintf("LDAP search failed: %v", err)), nil
}
for _, e := range sresult.Entries {
dn, err := ldap.ParseDN(e.DN)
if err != nil || len(dn.RDNs) == 0 || len(dn.RDNs[0].Attributes) == 0 {
continue
}
gname := dn.RDNs[0].Attributes[0].Value
allgroups = append(allgroups, gname)
}
} else {
resp.AddWarning("no group DN configured; only policies from locally-defined groups available")
}
for _, gname := range allgroups {
//.........這裏部分代碼省略.........