use of org.apache.directory.api.ldap.model.entry.Attribute in project graylog2-server by Graylog2.
the class LdapConnector method search.
@Nullable
public LdapEntry search(LdapNetworkConnection connection, String searchBase, String searchPattern, String displayNameAttribute, String principal, boolean activeDirectory, String groupSearchBase, String groupIdAttribute, String groupSearchPattern) throws LdapException, CursorException {
final LdapEntry ldapEntry = new LdapEntry();
final Set<String> groupDns = Sets.newHashSet();
final String filter = new MessageFormat(searchPattern, Locale.ENGLISH).format(new Object[] { sanitizePrincipal(principal) });
if (LOG.isTraceEnabled()) {
LOG.trace("Search {} for {}, starting at {}", activeDirectory ? "ActiveDirectory" : "LDAP", filter, searchBase);
}
try (final EntryCursor entryCursor = connection.search(searchBase, filter, SearchScope.SUBTREE, groupIdAttribute, displayNameAttribute, "dn", "uid", "userPrincipalName", "mail", "rfc822Mailbox", "memberOf", "isMemberOf")) {
final Iterator<Entry> it = entryCursor.iterator();
if (it.hasNext()) {
final Entry e = it.next();
// always set the proper DN for the entry, we need it for group matching
ldapEntry.setDn(e.getDn().getName());
// for generic LDAP use the dn of the entry for the subsequent bind, active directory needs the userPrincipalName attribute (set below)
if (!activeDirectory) {
ldapEntry.setBindPrincipal(e.getDn().getName());
}
for (Attribute attribute : e.getAttributes()) {
if (activeDirectory && "userPrincipalName".equalsIgnoreCase(attribute.getId())) {
ldapEntry.setBindPrincipal(attribute.getString());
}
if (attribute.isHumanReadable()) {
ldapEntry.put(attribute.getId(), Joiner.on(", ").join(attribute.iterator()));
}
// ActiveDirectory (memberOf) and Sun Directory Server (isMemberOf)
if ("memberOf".equalsIgnoreCase(attribute.getId()) || "isMemberOf".equalsIgnoreCase(attribute.getId())) {
for (Value<?> group : attribute) {
groupDns.add(group.getString());
}
}
}
} else {
LOG.trace("No LDAP entry found for filter {}", filter);
return null;
}
if (!groupDns.isEmpty() && !isNullOrEmpty(groupSearchBase) && !isNullOrEmpty(groupIdAttribute)) {
// according to groupIdAttribute if present
try {
for (String groupDn : groupDns) {
LOG.trace("Looking up group {}", groupDn);
try {
Entry group = connection.lookup(groupDn, groupIdAttribute);
// See: https://github.com/Graylog2/graylog2-server/issues/1453
if (group != null) {
final Attribute groupId = group.get(groupIdAttribute);
LOG.trace("Resolved {} to group {}", groupDn, groupId);
if (groupId != null) {
final String string = groupId.getString();
ldapEntry.addGroups(Collections.singleton(string));
}
} else {
LOG.debug("Unable to lookup group: {}", groupDn);
}
} catch (LdapException e) {
LOG.warn("Error while looking up group " + groupDn, e);
}
}
} catch (Exception e) {
LOG.error("Unexpected error during LDAP group resolution", e);
}
}
if (ldapEntry.getGroups().isEmpty() && !isNullOrEmpty(groupSearchBase) && !isNullOrEmpty(groupIdAttribute) && !isNullOrEmpty(groupSearchPattern)) {
ldapEntry.addGroups(findGroups(connection, groupSearchBase, groupSearchPattern, groupIdAttribute, ldapEntry));
LOG.trace("LDAP search found entry for DN {} with search filter {}: {}", ldapEntry.getDn(), filter, ldapEntry);
} else {
if (groupDns.isEmpty()) {
LOG.info("LDAP group search base, id attribute or object class missing, not iterating over LDAP groups.");
}
}
return ldapEntry;
} catch (IOException e) {
LOG.debug("Error while closing cursor", e);
return null;
}
}
use of org.apache.directory.api.ldap.model.entry.Attribute in project graylog2-server by Graylog2.
the class LdapConnector method findGroups.
public Set<String> findGroups(LdapNetworkConnection connection, String groupSearchBase, String groupSearchPattern, String groupIdAttribute, @Nullable LdapEntry ldapEntry) {
final Set<String> groups = Sets.newHashSet();
try (final EntryCursor groupSearch = connection.search(groupSearchBase, groupSearchPattern, SearchScope.SUBTREE, "objectClass", ATTRIBUTE_UNIQUE_MEMBER, ATTRIBUTE_MEMBER, ATTRIBUTE_MEMBER_UID, groupIdAttribute)) {
LOG.trace("LDAP search for groups: {} starting at {}", groupSearchPattern, groupSearchBase);
for (Entry e : groupSearch) {
if (LOG.isTraceEnabled()) {
LOG.trace("Group Entry: {}", e.toString(" "));
}
if (!e.containsAttribute(groupIdAttribute)) {
LOG.warn("Unknown group id attribute {}, skipping group entry {}", groupIdAttribute, e);
continue;
}
final String groupId = e.get(groupIdAttribute).getString();
if (ldapEntry == null) {
// no membership lookup possible (we have no user), simply collect the found group names
groups.add(groupId);
} else {
// test if the given dn parameter is actually member of any of the found groups
String memberAttribute;
if (e.hasObjectClass("groupOfUniqueNames")) {
memberAttribute = ATTRIBUTE_UNIQUE_MEMBER;
} else if (e.hasObjectClass("groupOfNames") || e.hasObjectClass("group")) {
memberAttribute = ATTRIBUTE_MEMBER;
} else if (e.hasObjectClass("posixGroup")) {
memberAttribute = ATTRIBUTE_MEMBER_UID;
} else {
// Trying auto detection of the member attribute. This should be configurable!
if (e.containsAttribute(ATTRIBUTE_UNIQUE_MEMBER)) {
memberAttribute = ATTRIBUTE_UNIQUE_MEMBER;
} else if (e.containsAttribute(ATTRIBUTE_MEMBER_UID)) {
memberAttribute = ATTRIBUTE_MEMBER_UID;
} else {
memberAttribute = ATTRIBUTE_MEMBER;
}
LOG.warn("Unable to auto-detect the LDAP group object class, assuming '{}' is the correct attribute.", memberAttribute);
}
final Attribute members = e.get(memberAttribute);
if (members != null) {
final String dn = normalizedDn(ldapEntry.getDn());
final String uid = ldapEntry.get("uid");
for (Value<?> member : members) {
LOG.trace("DN {} == {} member?", dn, member.getString());
if (dn != null && dn.equalsIgnoreCase(normalizedDn(member.getString()))) {
groups.add(groupId);
} else {
// check against the uid attribute of the user.
if (!isNullOrEmpty(uid) && uid.equalsIgnoreCase(member.getString())) {
LOG.trace("UID {} == {} member?", uid, member.getString());
groups.add(groupId);
}
}
}
}
}
}
} catch (Exception e) {
LOG.warn("Unable to iterate over user's groups, unable to perform group mapping. Graylog does not support " + "LDAP referrals at the moment. Please see " + DocsHelper.PAGE_LDAP_TROUBLESHOOTING.toString() + " for more information.", ExceptionUtils.getRootCause(e));
}
return groups;
}
use of org.apache.directory.api.ldap.model.entry.Attribute in project jackrabbit-oak by apache.
the class LdapIdentityProvider method createUser.
@Nonnull
private ExternalUser createUser(@Nonnull Entry entry, @CheckForNull String id) throws LdapInvalidAttributeValueException {
ExternalIdentityRef ref = new ExternalIdentityRef(entry.getDn().getName(), this.getName());
if (id == null) {
String idAttribute = config.getUserConfig().getIdAttribute();
Attribute attr = entry.get(idAttribute);
if (attr == null) {
throw new LdapInvalidAttributeValueException(ResultCodeEnum.CONSTRAINT_VIOLATION, "no value found for attribute '" + idAttribute + "' for entry " + entry);
}
id = attr.getString();
}
String path = config.getUserConfig().makeDnPath() ? createDNPath(entry.getDn()) : null;
LdapUser user = new LdapUser(this, ref, id, path);
Map<String, Object> props = user.getProperties();
applyAttributes(props, entry);
return user;
}
use of org.apache.directory.api.ldap.model.entry.Attribute in project jackrabbit-oak by apache.
the class LdapIdentityProvider method createGroup.
@Nonnull
private ExternalGroup createGroup(@Nonnull Entry entry, @CheckForNull String name) throws LdapInvalidAttributeValueException {
ExternalIdentityRef ref = new ExternalIdentityRef(entry.getDn().getName(), this.getName());
if (name == null) {
String idAttribute = config.getGroupConfig().getIdAttribute();
Attribute attr = entry.get(idAttribute);
if (attr == null) {
throw new LdapInvalidAttributeValueException(ResultCodeEnum.CONSTRAINT_VIOLATION, "no value found for attribute '" + idAttribute + "' for entry " + entry);
}
name = attr.getString();
}
String path = config.getGroupConfig().makeDnPath() ? createDNPath(entry.getDn()) : null;
LdapGroup group = new LdapGroup(this, ref, name, path);
Map<String, Object> props = group.getProperties();
applyAttributes(props, entry);
return group;
}
use of org.apache.directory.api.ldap.model.entry.Attribute in project mxisd by kamax-io.
the class LdapAuthProvider method authenticate.
@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
log.info("Performing auth for {}", mxid);
try (LdapConnection conn = getConn()) {
bind(conn);
String uidType = getAt().getUid().getType();
String userFilterValue = StringUtils.equals(LdapBackend.UID, uidType) ? mxid.getLocalPart() : mxid.getId();
if (StringUtils.isBlank(userFilterValue)) {
log.warn("Username is empty, failing auth");
return BackendAuthResult.failure();
}
String userFilter = "(" + getUidAtt() + "=" + userFilterValue + ")";
userFilter = buildWithFilter(userFilter, getCfg().getAuth().getFilter());
Set<String> attributes = new HashSet<>();
attributes.add(getUidAtt());
attributes.add(getAt().getName());
getAt().getThreepid().forEach((k, v) -> attributes.addAll(v));
String[] attArray = new String[attributes.size()];
attributes.toArray(attArray);
log.debug("Base DN: {}", getBaseDn());
log.debug("Query: {}", userFilter);
log.debug("Attributes: {}", GsonUtil.build().toJson(attArray));
try (EntryCursor cursor = conn.search(getBaseDn(), userFilter, SearchScope.SUBTREE, attArray)) {
while (cursor.next()) {
Entry entry = cursor.get();
String dn = entry.getDn().getName();
log.info("Checking possible match, DN: {}", dn);
if (!getAttribute(entry, getUidAtt()).isPresent()) {
continue;
}
log.info("Attempting authentication on LDAP for {}", dn);
try {
conn.bind(entry.getDn(), password);
} catch (LdapException e) {
log.info("Unable to bind using {} because {}", entry.getDn().getName(), e.getMessage());
return BackendAuthResult.failure();
}
Attribute nameAttribute = entry.get(getAt().getName());
String name = nameAttribute != null ? nameAttribute.get().toString() : null;
log.info("Authentication successful for {}", entry.getDn().getName());
log.info("DN {} is a valid match", dn);
// TODO should we canonicalize the MXID?
BackendAuthResult result = BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, name);
log.info("Processing 3PIDs for profile");
getAt().getThreepid().forEach((k, v) -> {
log.info("Processing 3PID type {}", k);
v.forEach(attId -> {
List<String> values = getAttributes(entry, attId);
log.info("\tAttribute {} has {} value(s)", attId, values.size());
getAttributes(entry, attId).forEach(tpidValue -> {
if (ThreePidMedium.PhoneNumber.is(k)) {
tpidValue = getMsisdn(tpidValue).orElse(tpidValue);
}
result.withThreePid(new ThreePid(k, tpidValue));
});
});
});
log.info("Found {} 3PIDs", result.getProfile().getThreePids().size());
return result;
}
} catch (CursorLdapReferralException e) {
log.warn("Entity for {} is only available via referral, skipping", mxid);
}
log.info("No match were found for {}", mxid);
return BackendAuthResult.failure();
} catch (LdapException | IOException | CursorException e) {
throw new RuntimeException(e);
}
}
Aggregations