Research code for #14
This commit is contained in:
@@ -72,7 +72,11 @@ public abstract class LdapBackend {
|
||||
}
|
||||
|
||||
protected synchronized LdapConnection getConn() {
|
||||
return new LdapNetworkConnection(cfg.getConnection().getHost(), cfg.getConnection().getPort(), cfg.getConnection().isTls());
|
||||
return getConn(cfg.getConnection().getHost());
|
||||
}
|
||||
|
||||
protected synchronized LdapConnection getConn(String host) {
|
||||
return new LdapNetworkConnection(host, cfg.getConnection().getPort(), cfg.getConnection().isTls());
|
||||
}
|
||||
|
||||
protected void bind(LdapConnection conn) throws LdapException {
|
||||
|
@@ -28,6 +28,7 @@ import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import io.kamax.mxisd.util.GsonUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorException;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
|
||||
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
|
||||
@@ -37,8 +38,10 @@ import org.apache.directory.api.ldap.model.message.SearchScope;
|
||||
import org.apache.directory.ldap.client.api.LdapConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -91,7 +94,10 @@ public class LdapThreePidProvider extends LdapBackend implements IThreePidProvid
|
||||
return Optional.of(buildMatrixIdFromUid(data.get()));
|
||||
}
|
||||
} catch (CursorLdapReferralException e) {
|
||||
log.warn("3PID {} is only available via referral, skipping", value);
|
||||
log.info("Got referral info: {}", e.getReferralInfo());
|
||||
|
||||
return followReferral(medium, value, e.getReferralInfo());
|
||||
//log.warn("3PID {} is only available via referral, skipping", value);
|
||||
} catch (IOException | LdapException | CursorException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
@@ -104,12 +110,50 @@ public class LdapThreePidProvider extends LdapBackend implements IThreePidProvid
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
log.info("Performing LDAP lookup {} of type {}", request.getThreePid(), request.getType());
|
||||
|
||||
try (LdapConnection conn = getConn()) {
|
||||
bind(conn);
|
||||
return lookup(conn, request.getType(), request.getThreePid()).map(id -> new SingleLookupReply(request, id));
|
||||
} catch (LdapException | IOException e) {
|
||||
throw new InternalServerError(e);
|
||||
List<String> hosts = new ArrayList<>();
|
||||
|
||||
String domain = getCfg().getConnection().getDomain();
|
||||
if (StringUtils.isNotBlank(domain)) {
|
||||
try {
|
||||
Record[] records = new Lookup("_ldap._tcp.DomainDnsZones." + domain, Type.SRV).run();
|
||||
if (records == null || records.length == 0) {
|
||||
log.warn("No LDAP server found for domain {}", domain);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
for (Record record : records) {
|
||||
if (record instanceof SRVRecord) {
|
||||
SRVRecord srvRec = (SRVRecord) record;
|
||||
hosts.add(srvRec.getTarget().toString(true));
|
||||
}
|
||||
}
|
||||
|
||||
if (hosts.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (TextParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
hosts.add(getCfg().getConnection().getHost());
|
||||
}
|
||||
|
||||
for (String host : hosts) {
|
||||
log.info("Trying host {}", host);
|
||||
try (LdapConnection conn = getConn(host)) {
|
||||
bind(conn);
|
||||
Optional<SingleLookupReply> reply = lookup(conn, request.getType(), request.getThreePid()).map(id -> new SingleLookupReply(request, id));
|
||||
if (reply.isPresent()) return reply;
|
||||
} catch (LdapException | IOException e) {
|
||||
if (hosts.size() == 1) {
|
||||
throw new InternalServerError(e);
|
||||
} else {
|
||||
log.warn("Unable to query {}: {}", host, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,4 +181,51 @@ public class LdapThreePidProvider extends LdapBackend implements IThreePidProvid
|
||||
return mappingsFound;
|
||||
}
|
||||
|
||||
private Optional<String> followReferral(String medium, String value, String ref) {
|
||||
URI uri = URI.create(ref);
|
||||
|
||||
Optional<String> tPidQueryOpt = getCfg().getIdentity().getQuery(medium);
|
||||
if (!tPidQueryOpt.isPresent()) {
|
||||
log.warn("{} is not a configured 3PID type for LDAP lookup", medium);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
LdapConnection conn = getConn(uri.getHost());
|
||||
try {
|
||||
bind(conn);
|
||||
} catch (LdapException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// we merge 3PID specific query with global/specific filter, if one exists.
|
||||
String tPidQuery = tPidQueryOpt.get().replaceAll(getCfg().getIdentity().getToken(), value);
|
||||
String searchQuery = buildWithFilter(tPidQuery, getCfg().getIdentity().getFilter());
|
||||
log.debug("Query: {}", searchQuery);
|
||||
log.debug("Attributes: {}", GsonUtil.build().toJson(getUidAtt()));
|
||||
|
||||
try (EntryCursor cursor = conn.search(uri.getPath().substring(1), searchQuery, SearchScope.SUBTREE, getUidAtt())) {
|
||||
while (cursor.next()) {
|
||||
Entry entry = cursor.get();
|
||||
log.info("Found possible match, DN: {}", entry.getDn().getName());
|
||||
|
||||
Optional<String> data = getAttribute(entry, getUidAtt());
|
||||
if (!data.isPresent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
log.info("DN {} is a valid match", entry.getDn().getName());
|
||||
return Optional.of(buildMatrixIdFromUid(data.get()));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
} catch (CursorLdapReferralException e) {
|
||||
log.info("Got referral info: {}", e.getReferralInfo());
|
||||
|
||||
return followReferral(medium, value, e.getReferralInfo());
|
||||
//log.warn("3PID {} is only available via referral, skipping", value);
|
||||
} catch (IOException | LdapException | CursorException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -125,6 +125,7 @@ public abstract class LdapConfig {
|
||||
|
||||
private boolean tls = false;
|
||||
private String host;
|
||||
private String domain;
|
||||
private int port = 389;
|
||||
private String bindDn;
|
||||
private String bindPassword;
|
||||
@@ -147,6 +148,14 @@ public abstract class LdapConfig {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
Reference in New Issue
Block a user