|
|
@@ -137,6 +137,17 @@ func (ls *LdapService) Authenticate(username, password string) (*model.User, err
|
|
137
|
137
|
return nil, ErrLdapUserDisabled
|
|
138
|
138
|
}
|
|
139
|
139
|
cfg := &Config.Ldap
|
|
|
140
|
+
|
|
|
141
|
+ // Skip allow-group check for admins
|
|
|
142
|
+ isAdmin := ls.isUserAdmin(cfg, ldapUser)
|
|
|
143
|
+
|
|
|
144
|
+ // non-admins only check if allow-group is configured
|
|
|
145
|
+ if !isAdmin && cfg.User.AllowGroup != "" {
|
|
|
146
|
+ if !ls.isUserInGroup(cfg, ldapUser, cfg.User.AllowGroup) {
|
|
|
147
|
+ return nil, errors.New("user not in allowed group")
|
|
|
148
|
+ }
|
|
|
149
|
+ }
|
|
|
150
|
+
|
|
140
|
151
|
err = ls.verifyCredentials(cfg, ldapUser.Dn, password)
|
|
141
|
152
|
if err != nil {
|
|
142
|
153
|
return nil, err
|
|
|
@@ -148,6 +159,46 @@ func (ls *LdapService) Authenticate(username, password string) (*model.User, err
|
|
148
|
159
|
return user, nil
|
|
149
|
160
|
}
|
|
150
|
161
|
|
|
|
162
|
+// isUserInGroup checks if the user is a member of the specified group. by_sw
|
|
|
163
|
+func (ls *LdapService) isUserInGroup(cfg *config.Ldap, ldapUser *LdapUser, groupDN string) bool {
|
|
|
164
|
+ // Check "memberOf" directly
|
|
|
165
|
+ if len(ldapUser.MemberOf) > 0 {
|
|
|
166
|
+ for _, group := range ldapUser.MemberOf {
|
|
|
167
|
+ if strings.EqualFold(group, groupDN) {
|
|
|
168
|
+ return true
|
|
|
169
|
+ }
|
|
|
170
|
+ }
|
|
|
171
|
+ }
|
|
|
172
|
+
|
|
|
173
|
+ // For "member" attribute, perform a reverse search on the group
|
|
|
174
|
+ member := "member"
|
|
|
175
|
+ userDN := ldap.EscapeFilter(ldapUser.Dn)
|
|
|
176
|
+ groupDN = ldap.EscapeFilter(groupDN)
|
|
|
177
|
+ groupFilter := fmt.Sprintf("(%s=%s)", member, userDN)
|
|
|
178
|
+
|
|
|
179
|
+ // Create the LDAP search request
|
|
|
180
|
+ groupSearchRequest := ldap.NewSearchRequest(
|
|
|
181
|
+ groupDN,
|
|
|
182
|
+ ldap.ScopeWholeSubtree,
|
|
|
183
|
+ ldap.NeverDerefAliases,
|
|
|
184
|
+ 0, // Unlimited search results
|
|
|
185
|
+ 0, // No time limit
|
|
|
186
|
+ false, // Return both attributes and DN
|
|
|
187
|
+ groupFilter,
|
|
|
188
|
+ []string{"dn"},
|
|
|
189
|
+ nil,
|
|
|
190
|
+ )
|
|
|
191
|
+
|
|
|
192
|
+ // Perform the group search
|
|
|
193
|
+ groupResult, err := ls.searchResult(cfg, groupSearchRequest)
|
|
|
194
|
+ if err != nil {
|
|
|
195
|
+ return false
|
|
|
196
|
+ }
|
|
|
197
|
+
|
|
|
198
|
+ // If any results are returned, the user is part of the group
|
|
|
199
|
+ return len(groupResult.Entries) > 0
|
|
|
200
|
+}
|
|
|
201
|
+
|
|
151
|
202
|
// mapToLocalUser checks whether the user exists locally; if not, creates one.
|
|
152
|
203
|
// If the user exists and Ldap.Sync is enabled, it updates local info.
|
|
153
|
204
|
func (ls *LdapService) mapToLocalUser(cfg *config.Ldap, lu *LdapUser) (*model.User, error) {
|