1
0
mirror of https://github.com/moparisthebest/davmail synced 2024-12-13 11:12:22 -05:00

LDAP: implement (as much as possible) exact match

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@340 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2009-02-09 22:40:55 +00:00
parent 6deee85651
commit d3eab09f00

View File

@ -83,6 +83,7 @@ public class LdapConnection extends AbstractConnection {
static { static {
// assume mail starts with firstname // assume mail starts with firstname
CRITERIA_MAP.put("uid", "AN");
CRITERIA_MAP.put("mail", "FN"); CRITERIA_MAP.put("mail", "FN");
CRITERIA_MAP.put("displayname", "DN"); CRITERIA_MAP.put("displayname", "DN");
CRITERIA_MAP.put("cn", "DN"); CRITERIA_MAP.put("cn", "DN");
@ -124,6 +125,7 @@ public class LdapConnection extends AbstractConnection {
static final int LDAP_FILTER_LE = 0xa6; static final int LDAP_FILTER_LE = 0xa6;
static final int LDAP_FILTER_PRESENT = 0x87; static final int LDAP_FILTER_PRESENT = 0x87;
static final int LDAP_FILTER_APPROX = 0xa8; static final int LDAP_FILTER_APPROX = 0xa8;
static final int LDAP_FILTER_EQUALITY = 0xa3;
// LDAP filter mode (only startsWith supported by galfind) // LDAP filter mode (only startsWith supported by galfind)
static final int LDAP_SUBSTRING_INITIAL = 0x80; static final int LDAP_SUBSTRING_INITIAL = 0x80;
@ -330,7 +332,7 @@ public class LdapConnection extends AbstractConnection {
int timelimit = reqBer.parseInt(); int timelimit = reqBer.parseInt();
/*boolean typesOnly =*/ /*boolean typesOnly =*/
reqBer.parseBoolean(); reqBer.parseBoolean();
Map<String, String> criteria = parseFilter(reqBer); Map<String, SimpleFilter> criteria = parseFilter(reqBer);
Set<String> returningAttributes = parseReturningAttributes(reqBer); Set<String> returningAttributes = parseReturningAttributes(reqBer);
int size = 0; int size = 0;
@ -357,7 +359,7 @@ public class LdapConnection extends AbstractConnection {
} else if (BASE_CONTEXT.equalsIgnoreCase(dn) && session != null) { } else if (BASE_CONTEXT.equalsIgnoreCase(dn) && session != null) {
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>(); Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
if ("*".equals(criteria.get("objectclass"))) { if (criteria.get("objectclass") != null && "*".equals(criteria.get("objectclass").value)) {
// full search // full search
for (char c = 'A'; c < 'Z'; c++) { for (char c = 'A'; c < 'Z'; c++) {
if (persons.size() < sizeLimit) { if (persons.size() < sizeLimit) {
@ -373,10 +375,14 @@ public class LdapConnection extends AbstractConnection {
} }
} }
} else { } else {
for (Map.Entry<String, String> entry : criteria.entrySet()) { for (Map.Entry<String, SimpleFilter> entry : criteria.entrySet()) {
if (persons.size() < sizeLimit) { if (persons.size() < sizeLimit) {
for (Map<String, String> person : session.galFind(entry.getKey(), entry.getValue()).values()) { for (Map<String, String> person : session.galFind(entry.getKey(), entry.getValue().value).values()) {
persons.put(person.get("AN"), person); if ((entry.getValue().operator == LDAP_FILTER_SUBSTRINGS)
|| (entry.getValue().operator == LDAP_FILTER_EQUALITY &&
entry.getValue().value.equalsIgnoreCase(person.get(entry.getKey())))) {
persons.put(person.get("AN"), person);
}
if (persons.size() == sizeLimit) { if (persons.size() == sizeLimit) {
break; break;
} }
@ -423,12 +429,12 @@ public class LdapConnection extends AbstractConnection {
} }
} }
protected Map<String, String> parseFilter(BerDecoder reqBer) throws IOException { protected Map<String, SimpleFilter> parseFilter(BerDecoder reqBer) throws IOException {
Map<String, String> criteria = new HashMap<String, String>(); Map<String, SimpleFilter> criteria = new HashMap<String, SimpleFilter>();
if (reqBer.peekByte() == LDAP_FILTER_PRESENT) { if (reqBer.peekByte() == LDAP_FILTER_PRESENT) {
String attributeName = reqBer.parseStringWithTag(LDAP_FILTER_PRESENT, isLdapV3(), null).toLowerCase(); String attributeName = reqBer.parseStringWithTag(LDAP_FILTER_PRESENT, isLdapV3(), null).toLowerCase();
if ("objectclass".equals(attributeName)) { if ("objectclass".equals(attributeName)) {
criteria.put(attributeName, "*"); criteria.put(attributeName, new SimpleFilter("*"));
} else { } else {
DavGatewayTray.warn("Unsupported filter"); DavGatewayTray.warn("Unsupported filter");
} }
@ -439,39 +445,41 @@ public class LdapConnection extends AbstractConnection {
if (ldapFilterType == LDAP_FILTER_OR) { if (ldapFilterType == LDAP_FILTER_OR) {
while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) { while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) {
int ldapFilterOperator = reqBer.parseSeq(null); int ldapFilterOperator = reqBer.parseSeq(null);
if (ldapFilterOperator == LDAP_FILTER_SUBSTRINGS) { parseSimpleFilter(reqBer, criteria, ldapFilterOperator);
parseSimpleFilter(reqBer, criteria);
}
} }
// simple filter // simple filter
} else if (ldapFilterType == LDAP_FILTER_SUBSTRINGS) {
parseSimpleFilter(reqBer, criteria);
} else { } else {
DavGatewayTray.warn("Unsupported filter"); parseSimpleFilter(reqBer, criteria, ldapFilterType);
} }
} }
return criteria; return criteria;
} }
protected void parseSimpleFilter(BerDecoder reqBer, Map<String, String> criteria) throws IOException { protected void parseSimpleFilter(BerDecoder reqBer, Map<String, SimpleFilter> criteria, int ldapFilterOperator) throws IOException {
String attributeName = reqBer.parseString(isLdapV3()).toLowerCase(); String attributeName = reqBer.parseString(isLdapV3()).toLowerCase();
String exchangeAttributeName = CRITERIA_MAP.get(attributeName); String exchangeAttributeName = CRITERIA_MAP.get(attributeName);
// Thunderbird sends values with space as separate strings, rebuild value
StringBuilder value = new StringBuilder(); StringBuilder value = new StringBuilder();
int[] seqSize = new int[1]; if (ldapFilterOperator == LDAP_FILTER_SUBSTRINGS) {
/*LBER_SEQUENCE*/ // Thunderbird sends values with space as separate strings, rebuild value
reqBer.parseSeq(seqSize); int[] seqSize = new int[1];
int end = reqBer.getParsePosition() + seqSize[0]; /*LBER_SEQUENCE*/
while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) { reqBer.parseSeq(seqSize);
int ldapFilterMode = reqBer.peekByte(); int end = reqBer.getParsePosition() + seqSize[0];
if (value.length() > 0) { while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) {
value.append(' '); int ldapFilterMode = reqBer.peekByte();
if (value.length() > 0) {
value.append(' ');
}
value.append(reqBer.parseStringWithTag(ldapFilterMode, isLdapV3(), null));
} }
value.append(reqBer.parseStringWithTag(ldapFilterMode, isLdapV3(), null)); } else if (ldapFilterOperator == LDAP_FILTER_EQUALITY) {
value.append(reqBer.parseString(isLdapV3()));
} else {
DavGatewayTray.warn("Unsupported filter value");
} }
if (exchangeAttributeName != null) { if (exchangeAttributeName != null) {
criteria.put(exchangeAttributeName, value.toString()); criteria.put(exchangeAttributeName, new SimpleFilter(value.toString(), ldapFilterOperator));
} else { } else {
DavGatewayTray.warn("Unsupported filter attribute: " + attributeName); DavGatewayTray.warn("Unsupported filter attribute: " + attributeName);
} }
@ -568,29 +576,29 @@ public class LdapConnection extends AbstractConnection {
protected void sendEntry(int currentMessageId, String dn, Map<String, Object> attributes) throws IOException { protected void sendEntry(int currentMessageId, String dn, Map<String, Object> attributes) throws IOException {
responseBer.reset(); responseBer.reset();
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
responseBer.encodeInt(currentMessageId); responseBer.encodeInt(currentMessageId);
responseBer.beginSeq(LDAP_REP_SEARCH); responseBer.beginSeq(LDAP_REP_SEARCH);
responseBer.encodeString(dn, isLdapV3()); responseBer.encodeString(dn, isLdapV3());
responseBer.beginSeq(LBER_SEQUENCE); responseBer.beginSeq(LBER_SEQUENCE);
for (Map.Entry<String,Object> entry:attributes.entrySet()) { for (Map.Entry<String, Object> entry : attributes.entrySet()) {
responseBer.beginSeq(LBER_SEQUENCE); responseBer.beginSeq(LBER_SEQUENCE);
responseBer.encodeString(entry.getKey(), isLdapV3()); responseBer.encodeString(entry.getKey(), isLdapV3());
responseBer.beginSeq(LBER_SET); responseBer.beginSeq(LBER_SET);
Object values = entry.getValue(); Object values = entry.getValue();
if (values instanceof String) { if (values instanceof String) {
responseBer.encodeString((String)values, isLdapV3()); responseBer.encodeString((String) values, isLdapV3());
} else if (values instanceof List) { } else if (values instanceof List) {
for (Object value: (List)values) { for (Object value : (List) values) {
responseBer.encodeString((String) value, isLdapV3()); responseBer.encodeString((String) value, isLdapV3());
} }
} else { } else {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
responseBer.endSeq();
responseBer.endSeq();
}
responseBer.endSeq();
responseBer.endSeq(); responseBer.endSeq();
responseBer.endSeq();
}
responseBer.endSeq();
responseBer.endSeq();
responseBer.endSeq(); responseBer.endSeq();
sendResponse(); sendResponse();
} }
@ -625,5 +633,20 @@ public class LdapConnection extends AbstractConnection {
os.flush(); os.flush();
} }
class SimpleFilter {
String value;
int operator;
SimpleFilter(String value) {
this.value = value;
this.operator = LDAP_FILTER_SUBSTRINGS;
}
SimpleFilter(String value, int ldapFilterOperator) {
this.value = value;
this.operator = ldapFilterOperator;
}
}
} }